Index: dll/ntdll/def/ntdll.spec =================================================================== --- dll/ntdll/def/ntdll.spec (révision 72694) +++ dll/ntdll/def/ntdll.spec (copie de travail) @@ -956,7 +956,7 @@ 948 stdcall RtlZeroMemory(ptr long) 949 stdcall RtlZombifyActivationContext(ptr) 950 stdcall RtlpApplyLengthFunction(long long ptr ptr) -951 stdcall RtlpEnsureBufferSize(ptr ptr ptr) ; CHECKME +951 stdcall RtlpEnsureBufferSize(long ptr long) # stdcall RtlpNotOwnerCriticalSection 953 stdcall RtlpNtCreateKey(ptr long ptr long ptr ptr) 954 stdcall RtlpNtEnumerateSubKey(ptr ptr long long) Index: sdk/include/ndk/rtlfuncs.h =================================================================== --- sdk/include/ndk/rtlfuncs.h (révision 72694) +++ sdk/include/ndk/rtlfuncs.h (copie de travail) @@ -2312,6 +2312,17 @@ _In_ PCUNICODE_STRING String ); +#define RTL_SKIP_BUFFER_COPY 0x00000001 + +NTSYSAPI +NTSTATUS +NTAPI +RtlpEnsureBufferSize( + _In_ ULONG Flags, + _Inout_ PRTL_BUFFER Buffer, + _In_ SIZE_T RequiredSize +); + // // Ansi String Functions // Index: sdk/lib/rtl/unicode.c =================================================================== --- sdk/lib/rtl/unicode.c (révision 72694) +++ sdk/lib/rtl/unicode.c (copie de travail) @@ -3,7 +3,7 @@ * PROJECT: ReactOS system libraries * PURPOSE: Unicode Conversion Routines * FILE: lib/rtl/unicode.c - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) * Emanuele Aliberti * Gunnar Dalsnes */ @@ -32,19 +32,76 @@ /* FUNCTIONS *****************************************************************/ +#define RtlEnsureBufferSize(Flags, Buffer, RequiredSize) \ + ((Buffer) != NULL && (RequiredSize) <= (Buffer)->Size) \ + ? STATUS_SUCCESS \ + : RtlpEnsureBufferSize((Flags), (Buffer), (RequiredSize)) + +/* + * @implemented + */ NTSTATUS NTAPI RtlMultiAppendUnicodeStringBuffer(OUT PRTL_UNICODE_STRING_BUFFER StringBuffer, - IN ULONG NumberOfAddends, - IN PCUNICODE_STRING Addends) + IN ULONG NumberOfStrings, + IN PCUNICODE_STRING StringArray) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + SIZE_T Length, TotalLength, MaximumLength; + ULONG i; + + Length = TotalLength = StringBuffer->String.Length; + + /* Determine the total length we need for the destination string buffer */ + i = 0; + while (i < NumberOfStrings) + { + TotalLength += StringArray[i++].Length; + + /* Fail if we overflow */ + if (TotalLength > UNICODE_STRING_MAX_BYTES) + return STATUS_NAME_TOO_LONG; + } + + /* Account for the terminating NULL character */ + MaximumLength = TotalLength + sizeof(UNICODE_NULL); + + /* Fail if we overflow */ + if (MaximumLength > UNICODE_STRING_MAX_BYTES) + return STATUS_NAME_TOO_LONG; + + /* + * Ensure the size of the destination string buffer is big + * enough to hold the result, and grow it if necessary. + */ + Status = RtlEnsureBufferSize(0, &StringBuffer->ByteBuffer, MaximumLength); + if (!NT_SUCCESS(Status)) return Status; + + /* Initialize the destination string */ + StringBuffer->String.Buffer = (PWSTR)StringBuffer->ByteBuffer.Buffer; + StringBuffer->String.Length = (USHORT)TotalLength; + StringBuffer->String.MaximumLength = (USHORT)MaximumLength; + + /* Append each string into the destination string */ + i = 0; + while (i < NumberOfStrings) + { + RtlMoveMemory(&StringBuffer->String.Buffer[Length / sizeof(WCHAR)], + StringArray[i].Buffer, + StringArray[i].Length); + Length += StringArray[i++].Length; + } + + /* NULL-terminate the destination string */ + StringBuffer->String.Buffer[Length / sizeof(WCHAR)] = UNICODE_NULL; + + /* Done */ + return STATUS_SUCCESS; } /* -* @implemented -*/ + * @implemented + */ WCHAR NTAPI RtlAnsiCharToUnicodeChar(IN OUT PUCHAR *AnsiChar) @@ -2544,7 +2601,7 @@ RtlValidateUnicodeString(IN ULONG Flags, IN PCUNICODE_STRING UnicodeString) { - /* currently no flags are supported! */ + /* Currently no flags are supported! */ ASSERT(Flags == 0); if ((Flags == 0) && @@ -2555,8 +2612,10 @@ ((UnicodeString->MaximumLength % sizeof(WCHAR)) == 0) && (UnicodeString->MaximumLength >= UnicodeString->Length)))) { - /* a NULL pointer as a unicode string is considered to be a valid unicode - string! */ + /* + * A NULL pointer as a unicode string is considered + * to be a valid unicode string! + */ return STATUS_SUCCESS; } else @@ -2566,14 +2625,65 @@ } /* - * @unimplemented + * @implemented */ NTSTATUS NTAPI -RtlpEnsureBufferSize(ULONG Unknown1, ULONG Unknown2, ULONG Unknown3) +RtlpEnsureBufferSize( + IN ULONG Flags, + IN OUT PRTL_BUFFER Buffer, + IN SIZE_T RequiredSize) { - DPRINT1("RtlpEnsureBufferSize: stub\n"); - return STATUS_NOT_IMPLEMENTED; + PUCHAR NewBuffer; + + /* Parameter checks */ + if (Flags & ~RTL_SKIP_BUFFER_COPY) return STATUS_INVALID_PARAMETER; + if (Buffer == NULL) return STATUS_INVALID_PARAMETER; + + /* + * We don't need to grow the buffer if its size + * is already larger than the required size. + */ + if (Buffer->Size >= RequiredSize) return STATUS_SUCCESS; + + /* + * When we are using the static buffer as our buffer, we don't need + * to grow it if its size is already larger than the required size. + * In this case, just keep it but update the current buffer size to + * the one requested. + * (But NEVER EVER modify the size of the static buffer!!) + * Otherwise, we'll need to create a new buffer and use this one instead. + */ + if ( (Buffer->Buffer == Buffer->StaticBuffer) && + (Buffer->StaticSize >= RequiredSize) ) + { + Buffer->Size = RequiredSize; + return STATUS_SUCCESS; + } + + /* The buffer we are using is not large enough, try to create a bigger one */ + NewBuffer = RtlpAllocateStringMemory(RequiredSize, TAG_USTR); + if (NewBuffer == NULL) return STATUS_NO_MEMORY; + + /* Copy the original content if needed */ + if ((Flags & RTL_SKIP_BUFFER_COPY) == 0) + { + RtlMoveMemory(NewBuffer, Buffer->Buffer, Buffer->Size); + } + + /* Free the original buffer only if it's not the static buffer */ + if (Buffer->Buffer != Buffer->StaticBuffer) + { + RtlpFreeStringMemory(Buffer->Buffer, TAG_USTR); + Buffer->Buffer = NULL; + } + + /* Update the members */ + Buffer->Buffer = NewBuffer; + Buffer->Size = RequiredSize; + + /* Done */ + return STATUS_SUCCESS; } static