-/*\r
- * PROJECT: ReactOS Kernel\r
- * LICENSE: GPL - See COPYING in the top level directory\r
- * FILE: include/ddk/ntstrsafe.h\r
- * PURPOSE: Safe String Library for NT Code (Native/Kernel)\r
- * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#ifndef _NTSTRSAFE_H_INCLUDED_\r
-#define _NTSTRSAFE_H_INCLUDED_\r
-\r
-//\r
-// Dependencies\r
-//\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <stdarg.h>\r
-\r
-//\r
-// Maximum limits: allow overriding the maximum\r
-//\r
-#ifndef NTSTRSAFE_MAX_CCH\r
-#define NTSTRSAFE_MAX_CCH 2147483647\r
-#endif\r
-#define NTSTRSAFE_MAX_LENGTH (NTSTRSAFE_MAX_CCH - 1)\r
-\r
-//\r
-// Typedefs\r
-//\r
-typedef unsigned long DWORD;\r
-\r
-/* PRIVATE FUNCTIONS *********************************************************/\r
-\r
-FORCEINLINE\r
-NTSTATUS\r
-NTAPI\r
-RtlStringLengthWorkerA(IN PCHAR String,\r
- IN SIZE_T MaxLength,\r
- OUT PSIZE_T ReturnLength OPTIONAL)\r
-{\r
- NTSTATUS Status = STATUS_SUCCESS;\r
- SIZE_T LocalMax = MaxLength;\r
-\r
- while (MaxLength && (*String != ANSI_NULL))\r
- {\r
- String++;\r
- MaxLength--;\r
- }\r
-\r
- if (!MaxLength) Status = STATUS_INVALID_PARAMETER;\r
-\r
- if (ReturnLength)\r
- {\r
- if (NT_SUCCESS(Status))\r
- {\r
- *ReturnLength = LocalMax - MaxLength;\r
- }\r
- else\r
- {\r
- *ReturnLength = 0;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-FORCEINLINE\r
-NTSTATUS\r
-NTAPI\r
-RtlStringValidateDestA(IN PCHAR Destination,\r
- IN SIZE_T Length,\r
- OUT PSIZE_T ReturnLength OPTIONAL,\r
- IN SIZE_T MaxLength)\r
-{\r
- NTSTATUS Status = STATUS_SUCCESS;\r
-\r
- if (!(Length) || (Length > MaxLength)) Status = STATUS_INVALID_PARAMETER;\r
-\r
- if (ReturnLength)\r
- {\r
- if (NT_SUCCESS(Status))\r
- {\r
- Status = RtlStringLengthWorkerA(Destination,\r
- Length,\r
- ReturnLength);\r
- }\r
- else\r
- {\r
- *ReturnLength = 0;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-FORCEINLINE\r
-NTSTATUS\r
-NTAPI\r
-RtlStringExValidateDestA(IN OUT PCHAR *Destination,\r
- IN OUT PSIZE_T DestinationLength,\r
- OUT PSIZE_T ReturnLength OPTIONAL,\r
- IN SIZE_T MaxLength,\r
- IN DWORD Flags)\r
-{\r
- ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);\r
- return RtlStringValidateDestA(*Destination,\r
- *DestinationLength,\r
- ReturnLength,\r
- MaxLength);\r
-}\r
-\r
-FORCEINLINE\r
-NTSTATUS\r
-NTAPI\r
-RtlStringExValidateSrcA(IN OUT PCCHAR *Source OPTIONAL,\r
- IN OUT PSIZE_T ReturnLength OPTIONAL,\r
- IN SIZE_T MaxLength,\r
- IN DWORD Flags)\r
-{\r
- NTSTATUS Status = STATUS_SUCCESS;\r
- ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);\r
-\r
- if ((ReturnLength) && (*ReturnLength >= MaxLength))\r
- {\r
- Status = STATUS_INVALID_PARAMETER;\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-FORCEINLINE\r
-NTSTATUS\r
-NTAPI\r
-RtlStringVPrintfWorkerA(OUT PCHAR Destination,\r
- IN SIZE_T Length,\r
- OUT PSIZE_T NewLength OPTIONAL,\r
- IN PCCHAR Format,\r
- IN va_list argList)\r
-{\r
- NTSTATUS Status = STATUS_SUCCESS;\r
- LONG Return;\r
- SIZE_T MaxLength, LocalNewLength = 0;\r
-\r
- MaxLength = Length - 1;\r
-\r
- Return = _vsnprintf(Destination, MaxLength, Format, argList);\r
- if ((Return < 0) || ((SIZE_T)Return > MaxLength))\r
- {\r
- Destination += MaxLength;\r
- *Destination = ANSI_NULL;\r
-\r
- LocalNewLength = MaxLength;\r
-\r
- Status = STATUS_BUFFER_OVERFLOW;\r
- }\r
- else if ((SIZE_T)Return == MaxLength)\r
- {\r
- Destination += MaxLength;\r
- *Destination = ANSI_NULL;\r
-\r
- LocalNewLength = MaxLength;\r
- }\r
- else\r
- {\r
- LocalNewLength = Return;\r
- }\r
-\r
- if (NewLength) *NewLength = LocalNewLength;\r
- return Status;\r
-}\r
-\r
-FORCEINLINE\r
-NTSTATUS\r
-NTAPI\r
-RtlStringCopyWorkerA(OUT PCHAR Destination,\r
- IN SIZE_T Length,\r
- OUT PSIZE_T NewLength OPTIONAL,\r
- IN PCCHAR Source,\r
- IN SIZE_T CopyLength)\r
-{\r
- NTSTATUS Status = STATUS_SUCCESS;\r
- SIZE_T LocalNewLength = 0;\r
-\r
- while ((Length) && (CopyLength) && (*Source != ANSI_NULL))\r
- {\r
- *Destination++ = *Source++;\r
- Length--;\r
- CopyLength--;\r
-\r
- LocalNewLength++;\r
- }\r
-\r
- if (!Length)\r
- {\r
- Destination--;\r
- LocalNewLength--;\r
-\r
- Status = STATUS_BUFFER_OVERFLOW;\r
- }\r
-\r
- *Destination = ANSI_NULL;\r
-\r
- if (NewLength) *NewLength = LocalNewLength;\r
- return Status;\r
-}\r
-\r
-/* PUBLIC FUNCTIONS **********************************************************/\r
-\r
-NTSTATUS\r
-NTAPI\r
-RtlStringCbPrintfA(OUT PCHAR Destination,\r
- IN SIZE_T Length,\r
- IN PCHAR Format,\r
- ...)\r
-{\r
- NTSTATUS Status;\r
- SIZE_T CharLength = Length / sizeof(CHAR);\r
- va_list argList;\r
-\r
- Status = RtlStringValidateDestA(Destination,\r
- CharLength,\r
- NULL,\r
- NTSTRSAFE_MAX_CCH);\r
- if (NT_SUCCESS(Status))\r
- {\r
- va_start(argList, Format);\r
- Status = RtlStringVPrintfWorkerA(Destination,\r
- CharLength,\r
- NULL,\r
- Format,\r
- argList);\r
- va_end(argList);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-NTSTATUS\r
-NTAPI\r
-RtlStringCbPrintfExA(OUT PCHAR Destination,\r
- IN SIZE_T Length,\r
- OUT PCHAR *DestinationEnd OPTIONAL,\r
- OUT PSIZE_T RemainingSize OPTIONAL,\r
- IN DWORD Flags,\r
- IN PCCHAR Format,\r
- ...)\r
-{\r
- NTSTATUS Status;\r
- SIZE_T CharLength = Length / sizeof(CHAR), Remaining, LocalNewLength = 0;\r
- PCHAR LocalDestinationEnd;\r
- va_list argList;\r
- ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);\r
-\r
- Status = RtlStringExValidateDestA(&Destination,\r
- &CharLength,\r
- NULL,\r
- NTSTRSAFE_MAX_CCH,\r
- Flags);\r
- if (NT_SUCCESS(Status))\r
- {\r
- LocalDestinationEnd = Destination;\r
- Remaining = CharLength;\r
-\r
- Status = RtlStringExValidateSrcA(&Format,\r
- NULL,\r
- NTSTRSAFE_MAX_CCH,\r
- Flags);\r
- if (NT_SUCCESS(Status))\r
- {\r
- if (!Length)\r
- {\r
- if (*Format != ANSI_NULL)\r
- {\r
- if (!Destination)\r
- {\r
- Status = STATUS_INVALID_PARAMETER;\r
- }\r
- else\r
- {\r
- Status = STATUS_BUFFER_OVERFLOW;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- va_start(argList, Format);\r
- Status = RtlStringVPrintfWorkerA(Destination,\r
- CharLength,\r
- &LocalNewLength,\r
- Format,\r
- argList);\r
- va_end(argList);\r
-\r
- LocalDestinationEnd = Destination + LocalNewLength;\r
- Remaining = CharLength - LocalNewLength;\r
- }\r
- }\r
- else\r
- {\r
- if (Length) *Destination = ANSI_NULL;\r
- }\r
-\r
- if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))\r
- {\r
- if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;\r
-\r
- if (RemainingSize)\r
- {\r
- *RemainingSize = (Remaining * sizeof(CHAR)) +\r
- (Length % sizeof(CHAR));\r
- }\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-FORCEINLINE\r
-NTSTATUS\r
-NTAPI\r
-RtlStringCbCopyExA(OUT PCHAR Destination,\r
- IN SIZE_T Length,\r
- IN PCCHAR Source,\r
- OUT PCHAR *DestinationEnd OPTIONAL,\r
- OUT PSIZE_T RemainingSize OPTIONAL,\r
- IN DWORD Flags)\r
-{\r
- NTSTATUS Status;\r
- SIZE_T CharLength = Length / sizeof(CHAR), Copied = 0, Remaining;\r
- PCHAR LocalDestinationEnd;\r
- ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);\r
-\r
- Status = RtlStringExValidateDestA(&Destination,\r
- &Length,\r
- NULL,\r
- NTSTRSAFE_MAX_CCH,\r
- Flags);\r
- if (NT_SUCCESS(Status))\r
- {\r
- LocalDestinationEnd = Destination;\r
- Remaining = CharLength;\r
-\r
- Status = RtlStringExValidateSrcA(&Source,\r
- NULL,\r
- NTSTRSAFE_MAX_CCH,\r
- Flags);\r
- if (NT_SUCCESS(Status))\r
- {\r
- if (!CharLength)\r
- {\r
- if (*Source != ANSI_NULL)\r
- {\r
- if (!Destination)\r
- {\r
- Status = STATUS_INVALID_PARAMETER;\r
- }\r
- else\r
- {\r
- Status = STATUS_BUFFER_OVERFLOW;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- Status = RtlStringCopyWorkerA(Destination,\r
- CharLength,\r
- &Copied,\r
- Source,\r
- NTSTRSAFE_MAX_LENGTH);\r
-\r
- LocalDestinationEnd = Destination + Copied;\r
- Remaining = CharLength - Copied;\r
- }\r
- }\r
- else\r
- {\r
- if (CharLength) *Destination = ANSI_NULL;\r
- }\r
-\r
- if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))\r
- {\r
- if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;\r
-\r
- if (RemainingSize)\r
- {\r
- *RemainingSize = (Remaining * sizeof(CHAR)) +\r
- (Length % sizeof(CHAR));\r
- }\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-FORCEINLINE\r
-NTSTATUS\r
-NTAPI\r
-RtlStringCbCatExA(IN OUT PCHAR Destination,\r
- IN SIZE_T Length,\r
- IN PCCHAR Source,\r
- OUT PCHAR *DestinationEnd OPTIONAL,\r
- OUT PSIZE_T RemainingSize OPTIONAL,\r
- IN DWORD Flags)\r
-{\r
- NTSTATUS Status;\r
- SIZE_T CharLength = Length / sizeof(CHAR);\r
- SIZE_T DestinationLength, Remaining, Copied = 0;\r
- PCHAR LocalDestinationEnd;\r
- ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);\r
-\r
- Status = RtlStringExValidateDestA(&Destination,\r
- &CharLength,\r
- &DestinationLength,\r
- NTSTRSAFE_MAX_CCH,\r
- Flags);\r
- if (NT_SUCCESS(Status))\r
- {\r
- LocalDestinationEnd = Destination + DestinationLength;\r
- Remaining = CharLength - DestinationLength;\r
-\r
- Status = RtlStringExValidateSrcA(&Source,\r
- NULL,\r
- NTSTRSAFE_MAX_CCH,\r
- Flags);\r
- if (NT_SUCCESS(Status))\r
- {\r
- if (Remaining <= 1)\r
- {\r
- if (*Source != ANSI_NULL)\r
- {\r
- if (!Destination)\r
- {\r
- Status = STATUS_INVALID_PARAMETER;\r
- }\r
- else\r
- {\r
- Status = STATUS_BUFFER_OVERFLOW;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- Status = RtlStringCopyWorkerA(LocalDestinationEnd,\r
- Remaining,\r
- &Copied,\r
- Source,\r
- NTSTRSAFE_MAX_LENGTH);\r
-\r
- LocalDestinationEnd = LocalDestinationEnd + Copied;\r
- Remaining = Remaining - Copied;\r
- }\r
- }\r
-\r
- if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))\r
- {\r
- if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;\r
-\r
- if (RemainingSize)\r
- {\r
- *RemainingSize = (Remaining * sizeof(CHAR)) +\r
- (Length % sizeof(CHAR));\r
- }\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-FORCEINLINE\r
-NTSTATUS\r
-NTAPI\r
-RtlStringCbCopyA(OUT PCHAR Destination,\r
- IN SIZE_T Length,\r
- IN PCCHAR Source)\r
-{\r
- NTSTATUS Status;\r
- SIZE_T CharLength = Length / sizeof(CHAR);\r
-\r
- Status = RtlStringValidateDestA(Destination,\r
- CharLength,\r
- NULL,\r
- NTSTRSAFE_MAX_CCH);\r
- if (NT_SUCCESS(Status))\r
- {\r
- Status = RtlStringCopyWorkerA(Destination,\r
- CharLength,\r
- NULL,\r
- Source,\r
- NTSTRSAFE_MAX_LENGTH);\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-#endif\r
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: include/ddk/ntstrsafe.h
+ * PURPOSE: Safe String Library for NT Code (Native/Kernel)
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#ifndef _NTSTRSAFE_H_INCLUDED_
+#define _NTSTRSAFE_H_INCLUDED_
+
+//
+// Dependencies
+//
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+//
+// Maximum limits: allow overriding the maximum
+//
+#ifndef NTSTRSAFE_MAX_CCH
+#define NTSTRSAFE_MAX_CCH 2147483647
+#endif
+#define NTSTRSAFE_MAX_LENGTH (NTSTRSAFE_MAX_CCH - 1)
+
+//
+// Typedefs
+//
+typedef unsigned long DWORD;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+FORCEINLINE
+NTSTATUS
+NTAPI
+RtlStringLengthWorkerA(IN PCHAR String,
+ IN SIZE_T MaxLength,
+ OUT PSIZE_T ReturnLength OPTIONAL)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ SIZE_T LocalMax = MaxLength;
+
+ while (MaxLength && (*String != ANSI_NULL))
+ {
+ String++;
+ MaxLength--;
+ }
+
+ if (!MaxLength) Status = STATUS_INVALID_PARAMETER;
+
+ if (ReturnLength)
+ {
+ if (NT_SUCCESS(Status))
+ {
+ *ReturnLength = LocalMax - MaxLength;
+ }
+ else
+ {
+ *ReturnLength = 0;
+ }
+ }
+
+ return Status;
+}
+
+FORCEINLINE
+NTSTATUS
+NTAPI
+RtlStringValidateDestA(IN PCHAR Destination,
+ IN SIZE_T Length,
+ OUT PSIZE_T ReturnLength OPTIONAL,
+ IN SIZE_T MaxLength)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ if (!(Length) || (Length > MaxLength)) Status = STATUS_INVALID_PARAMETER;
+
+ if (ReturnLength)
+ {
+ if (NT_SUCCESS(Status))
+ {
+ Status = RtlStringLengthWorkerA(Destination,
+ Length,
+ ReturnLength);
+ }
+ else
+ {
+ *ReturnLength = 0;
+ }
+ }
+
+ return Status;
+}
+
+FORCEINLINE
+NTSTATUS
+NTAPI
+RtlStringExValidateDestA(IN OUT PCHAR *Destination,
+ IN OUT PSIZE_T DestinationLength,
+ OUT PSIZE_T ReturnLength OPTIONAL,
+ IN SIZE_T MaxLength,
+ IN DWORD Flags)
+{
+ ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
+ return RtlStringValidateDestA(*Destination,
+ *DestinationLength,
+ ReturnLength,
+ MaxLength);
+}
+
+FORCEINLINE
+NTSTATUS
+NTAPI
+RtlStringExValidateSrcA(IN OUT PCCHAR *Source OPTIONAL,
+ IN OUT PSIZE_T ReturnLength OPTIONAL,
+ IN SIZE_T MaxLength,
+ IN DWORD Flags)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
+
+ if ((ReturnLength) && (*ReturnLength >= MaxLength))
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+FORCEINLINE
+NTSTATUS
+NTAPI
+RtlStringVPrintfWorkerA(OUT PCHAR Destination,
+ IN SIZE_T Length,
+ OUT PSIZE_T NewLength OPTIONAL,
+ IN PCCHAR Format,
+ IN va_list argList)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ LONG Return;
+ SIZE_T MaxLength, LocalNewLength = 0;
+
+ MaxLength = Length - 1;
+
+ Return = _vsnprintf(Destination, MaxLength, Format, argList);
+ if ((Return < 0) || ((SIZE_T)Return > MaxLength))
+ {
+ Destination += MaxLength;
+ *Destination = ANSI_NULL;
+
+ LocalNewLength = MaxLength;
+
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ else if ((SIZE_T)Return == MaxLength)
+ {
+ Destination += MaxLength;
+ *Destination = ANSI_NULL;
+
+ LocalNewLength = MaxLength;
+ }
+ else
+ {
+ LocalNewLength = Return;
+ }
+
+ if (NewLength) *NewLength = LocalNewLength;
+ return Status;
+}
+
+FORCEINLINE
+NTSTATUS
+NTAPI
+RtlStringCopyWorkerA(OUT PCHAR Destination,
+ IN SIZE_T Length,
+ OUT PSIZE_T NewLength OPTIONAL,
+ IN PCCHAR Source,
+ IN SIZE_T CopyLength)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+ SIZE_T LocalNewLength = 0;
+
+ while ((Length) && (CopyLength) && (*Source != ANSI_NULL))
+ {
+ *Destination++ = *Source++;
+ Length--;
+ CopyLength--;
+
+ LocalNewLength++;
+ }
+
+ if (!Length)
+ {
+ Destination--;
+ LocalNewLength--;
+
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+
+ *Destination = ANSI_NULL;
+
+ if (NewLength) *NewLength = LocalNewLength;
+ return Status;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+NTSTATUS
+NTAPI
+RtlStringCbPrintfA(OUT PCHAR Destination,
+ IN SIZE_T Length,
+ IN PCHAR Format,
+ ...)
+{
+ NTSTATUS Status;
+ SIZE_T CharLength = Length / sizeof(CHAR);
+ va_list argList;
+
+ Status = RtlStringValidateDestA(Destination,
+ CharLength,
+ NULL,
+ NTSTRSAFE_MAX_CCH);
+ if (NT_SUCCESS(Status))
+ {
+ va_start(argList, Format);
+ Status = RtlStringVPrintfWorkerA(Destination,
+ CharLength,
+ NULL,
+ Format,
+ argList);
+ va_end(argList);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+RtlStringCbPrintfExA(OUT PCHAR Destination,
+ IN SIZE_T Length,
+ OUT PCHAR *DestinationEnd OPTIONAL,
+ OUT PSIZE_T RemainingSize OPTIONAL,
+ IN DWORD Flags,
+ IN PCCHAR Format,
+ ...)
+{
+ NTSTATUS Status;
+ SIZE_T CharLength = Length / sizeof(CHAR), Remaining, LocalNewLength = 0;
+ PCHAR LocalDestinationEnd;
+ va_list argList;
+ ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
+
+ Status = RtlStringExValidateDestA(&Destination,
+ &CharLength,
+ NULL,
+ NTSTRSAFE_MAX_CCH,
+ Flags);
+ if (NT_SUCCESS(Status))
+ {
+ LocalDestinationEnd = Destination;
+ Remaining = CharLength;
+
+ Status = RtlStringExValidateSrcA(&Format,
+ NULL,
+ NTSTRSAFE_MAX_CCH,
+ Flags);
+ if (NT_SUCCESS(Status))
+ {
+ if (!Length)
+ {
+ if (*Format != ANSI_NULL)
+ {
+ if (!Destination)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ }
+ }
+ else
+ {
+ va_start(argList, Format);
+ Status = RtlStringVPrintfWorkerA(Destination,
+ CharLength,
+ &LocalNewLength,
+ Format,
+ argList);
+ va_end(argList);
+
+ LocalDestinationEnd = Destination + LocalNewLength;
+ Remaining = CharLength - LocalNewLength;
+ }
+ }
+ else
+ {
+ if (Length) *Destination = ANSI_NULL;
+ }
+
+ if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
+ {
+ if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
+
+ if (RemainingSize)
+ {
+ *RemainingSize = (Remaining * sizeof(CHAR)) +
+ (Length % sizeof(CHAR));
+ }
+ }
+ }
+
+ return Status;
+}
+
+FORCEINLINE
+NTSTATUS
+NTAPI
+RtlStringCbCopyExA(OUT PCHAR Destination,
+ IN SIZE_T Length,
+ IN PCCHAR Source,
+ OUT PCHAR *DestinationEnd OPTIONAL,
+ OUT PSIZE_T RemainingSize OPTIONAL,
+ IN DWORD Flags)
+{
+ NTSTATUS Status;
+ SIZE_T CharLength = Length / sizeof(CHAR), Copied = 0, Remaining;
+ PCHAR LocalDestinationEnd;
+ ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
+
+ Status = RtlStringExValidateDestA(&Destination,
+ &Length,
+ NULL,
+ NTSTRSAFE_MAX_CCH,
+ Flags);
+ if (NT_SUCCESS(Status))
+ {
+ LocalDestinationEnd = Destination;
+ Remaining = CharLength;
+
+ Status = RtlStringExValidateSrcA(&Source,
+ NULL,
+ NTSTRSAFE_MAX_CCH,
+ Flags);
+ if (NT_SUCCESS(Status))
+ {
+ if (!CharLength)
+ {
+ if (*Source != ANSI_NULL)
+ {
+ if (!Destination)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ }
+ }
+ else
+ {
+ Status = RtlStringCopyWorkerA(Destination,
+ CharLength,
+ &Copied,
+ Source,
+ NTSTRSAFE_MAX_LENGTH);
+
+ LocalDestinationEnd = Destination + Copied;
+ Remaining = CharLength - Copied;
+ }
+ }
+ else
+ {
+ if (CharLength) *Destination = ANSI_NULL;
+ }
+
+ if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
+ {
+ if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
+
+ if (RemainingSize)
+ {
+ *RemainingSize = (Remaining * sizeof(CHAR)) +
+ (Length % sizeof(CHAR));
+ }
+ }
+ }
+
+ return Status;
+}
+
+FORCEINLINE
+NTSTATUS
+NTAPI
+RtlStringCbCatExA(IN OUT PCHAR Destination,
+ IN SIZE_T Length,
+ IN PCCHAR Source,
+ OUT PCHAR *DestinationEnd OPTIONAL,
+ OUT PSIZE_T RemainingSize OPTIONAL,
+ IN DWORD Flags)
+{
+ NTSTATUS Status;
+ SIZE_T CharLength = Length / sizeof(CHAR);
+ SIZE_T DestinationLength, Remaining, Copied = 0;
+ PCHAR LocalDestinationEnd;
+ ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
+
+ Status = RtlStringExValidateDestA(&Destination,
+ &CharLength,
+ &DestinationLength,
+ NTSTRSAFE_MAX_CCH,
+ Flags);
+ if (NT_SUCCESS(Status))
+ {
+ LocalDestinationEnd = Destination + DestinationLength;
+ Remaining = CharLength - DestinationLength;
+
+ Status = RtlStringExValidateSrcA(&Source,
+ NULL,
+ NTSTRSAFE_MAX_CCH,
+ Flags);
+ if (NT_SUCCESS(Status))
+ {
+ if (Remaining <= 1)
+ {
+ if (*Source != ANSI_NULL)
+ {
+ if (!Destination)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ else
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+ }
+ }
+ else
+ {
+ Status = RtlStringCopyWorkerA(LocalDestinationEnd,
+ Remaining,
+ &Copied,
+ Source,
+ NTSTRSAFE_MAX_LENGTH);
+
+ LocalDestinationEnd = LocalDestinationEnd + Copied;
+ Remaining = Remaining - Copied;
+ }
+ }
+
+ if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
+ {
+ if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
+
+ if (RemainingSize)
+ {
+ *RemainingSize = (Remaining * sizeof(CHAR)) +
+ (Length % sizeof(CHAR));
+ }
+ }
+ }
+
+ return Status;
+}
+
+FORCEINLINE
+NTSTATUS
+NTAPI
+RtlStringCbCopyA(OUT PCHAR Destination,
+ IN SIZE_T Length,
+ IN PCCHAR Source)
+{
+ NTSTATUS Status;
+ SIZE_T CharLength = Length / sizeof(CHAR);
+
+ Status = RtlStringValidateDestA(Destination,
+ CharLength,
+ NULL,
+ NTSTRSAFE_MAX_CCH);
+ if (NT_SUCCESS(Status))
+ {
+ Status = RtlStringCopyWorkerA(Destination,
+ CharLength,
+ NULL,
+ Source,
+ NTSTRSAFE_MAX_LENGTH);
+ }
+
+ return Status;
+}
+
+#endif