diff --git a/dlls/ntdll/large_int.c b/dlls/ntdll/large_int.c index 7912111cae0..cbd4d776910 100644 --- a/dlls/ntdll/large_int.c +++ b/dlls/ntdll/large_int.c @@ -183,56 +183,57 @@ LONGLONG WINAPI RtlExtendedIntegerMultiply( LONGLONG a, INT b ) /****************************************************************************** * RtlExtendedMagicDivide (NTDLL.@) * - * This function computes (a * b) >> (64 + shift) + * Allows replacing a division by a longlong constant with a multiplication by + * the inverse constant. * * RETURNS - * (a * b) >> (64 + shift) + * (dividend * inverse_divisor) >> (64 + shift) * * NOTES - * This allows replacing a division by a longlong constant - * by a multiplication by the inverse constant. + * If the divisor of a division is constant, the constants inverse_divisor and + * shift must be chosen such that inverse_divisor = 2^(64 + shift) / divisor. + * Then we have RtlExtendedMagicDivide(dividend,inverse_divisor,shift) == + * dividend * inverse_divisor / 2^(64 + shift) == dividend / divisor. * - * If 'c' is the constant divisor, the constants 'b' and 'shift' - * must be chosen such that b = 2^(64+shift) / c. - * Then we have RtlExtendedMagicDivide(a,b,shift) == a * b / 2^(64+shift) == a / c. - * - * The Parameter b although defined as LONGLONG is used as ULONGLONG. + * The Parameter inverse_divisor although defined as LONGLONG is used as + * ULONGLONG. */ #define LOWER_32(A) ((A) & 0xffffffff) #define UPPER_32(A) ((A) >> 32) LONGLONG WINAPI RtlExtendedMagicDivide( - LONGLONG a, /* [I] Dividend to be divided by the constant divisor */ - LONGLONG b, /* [I] Constant computed manually as 2^(64+shift) / divisor */ - INT shift) /* [I] Constant shift chosen to make b as big as possible for 64 bits */ + LONGLONG dividend, /* [I] Dividend to be divided by the constant divisor */ + LONGLONG inverse_divisor, /* [I] Constant computed manually as 2^(64+shift) / divisor */ + INT shift) /* [I] Constant shift chosen to make inverse_divisor as big as possible for 64 bits */ { - ULONGLONG a_high; - ULONGLONG a_low; - ULONGLONG b_high; - ULONGLONG b_low; + ULONGLONG dividend_high; + ULONGLONG dividend_low; + ULONGLONG inverse_divisor_high; + ULONGLONG inverse_divisor_low; ULONGLONG ah_bl; ULONGLONG al_bh; LONGLONG result; int positive; - if (a < 0) { - a_high = UPPER_32((ULONGLONG) -a); - a_low = LOWER_32((ULONGLONG) -a); + if (dividend < 0) { + dividend_high = UPPER_32((ULONGLONG) -dividend); + dividend_low = LOWER_32((ULONGLONG) -dividend); positive = 0; } else { - a_high = UPPER_32((ULONGLONG) a); - a_low = LOWER_32((ULONGLONG) a); + dividend_high = UPPER_32((ULONGLONG) dividend); + dividend_low = LOWER_32((ULONGLONG) dividend); positive = 1; } /* if */ - b_high = UPPER_32((ULONGLONG) b); - b_low = LOWER_32((ULONGLONG) b); + inverse_divisor_high = UPPER_32((ULONGLONG) inverse_divisor); + inverse_divisor_low = LOWER_32((ULONGLONG) inverse_divisor); - ah_bl = a_high * b_low; - al_bh = a_low * b_high; + ah_bl = dividend_high * inverse_divisor_low; + al_bh = dividend_low * inverse_divisor_high; - result = (LONGLONG) ((a_high * b_high + + result = (LONGLONG) ((dividend_high * inverse_divisor_high + UPPER_32(ah_bl) + UPPER_32(al_bh) + - UPPER_32(LOWER_32(ah_bl) + LOWER_32(al_bh) + UPPER_32(a_low * b_low))) >> shift); + UPPER_32(LOWER_32(ah_bl) + LOWER_32(al_bh) + + UPPER_32(dividend_low * inverse_divisor_low))) >> shift); if (positive) { return result; diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 71532927ee1..36f301eb886 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -286,8 +286,8 @@ @ stdcall RtlAppendUnicodeToString(ptr wstr) @ stub RtlApplyRXact @ stub RtlApplyRXactNoFlush -@ stub RtlAreAllAccessesGranted -@ stub RtlAreAnyAccessesGranted +@ stdcall RtlAreAllAccessesGranted(long long) +@ stdcall RtlAreAnyAccessesGranted(long long) @ stdcall RtlAreBitsClear(ptr long long) @ stdcall RtlAreBitsSet(ptr long long) @ stdcall RtlAssert(ptr ptr long long) @@ -298,7 +298,7 @@ @ stdcall RtlClearBits(ptr long long) @ stdcall RtlCompactHeap(long long) @ stdcall RtlCompareMemory(ptr ptr long) -@ stdcall RtlCompareMemoryUlong(ptr ptr long) +@ stdcall RtlCompareMemoryUlong(ptr long long) @ stdcall RtlCompareString(ptr ptr long) @ stdcall RtlCompareUnicodeString (ptr ptr long) @ stub RtlCompressBuffer @@ -310,8 +310,8 @@ @ stdcall RtlConvertSidToUnicodeString(ptr ptr long) @ stub RtlConvertUiListToApiList @ stdcall -ret64 RtlConvertUlongToLargeInteger(long) -@ stub RtlCopyLuid -@ stub RtlCopyLuidAndAttributesArray +@ stdcall RtlCopyLuid(ptr ptr) +@ stdcall RtlCopyLuidAndAttributesArray(long ptr ptr) @ stub RtlCopySecurityDescriptor @ stdcall RtlCopySid(long ptr ptr) @ stub RtlCopySidAndAttributesArray @@ -363,7 +363,7 @@ @ stub RtlEnumerateGenericTableWithoutSplaying @ stdcall RtlEqualComputerName(ptr ptr) @ stdcall RtlEqualDomainName(ptr ptr) -@ stub RtlEqualLuid +@ stdcall RtlEqualLuid(ptr ptr) @ stdcall RtlEqualPrefixSid(ptr ptr) @ stdcall RtlEqualSid (long long) @ stdcall RtlEqualString(ptr ptr long) @@ -461,7 +461,7 @@ @ stdcall RtlLockHeap(long) @ stub RtlLookupElementGenericTable @ stdcall RtlMakeSelfRelativeSD(ptr ptr ptr) -@ stub RtlMapGenericMask +@ stdcall RtlMapGenericMask(long ptr) @ stdcall RtlMoveMemory(ptr ptr long) @ stdcall RtlMultiByteToUnicodeN(ptr long ptr ptr long) @ stdcall RtlMultiByteToUnicodeSize(ptr str long) @@ -493,7 +493,7 @@ @ stdcall RtlQueryTimeZoneInformation(ptr) @ stdcall RtlRaiseException(ptr) @ stdcall RtlRaiseStatus(long) -@ stub RtlRandom +@ stdcall RtlRandom(ptr) @ stdcall RtlReAllocateHeap(long long ptr long) @ stub RtlRealPredecessor @ stub RtlRealSuccessor diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c index 3f92dc9b2cc..77ad84c810a 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -741,24 +741,36 @@ __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap, * seed [O] The seed of the Random function * * RETURNS - * It returns a random number uniformly distributed over [0..MAXLONG]. + * It returns a random number uniformly distributed over [0..MAXLONG-1]. * * NOTES - * Generates an uniform random number using a modified version of - * D.H. Lehmer's 1948 algorithm. The original algorithm would be: + * Generates an uniform random number using D.H. Lehmer's 1948 algorithm. + * In our case the algorithm is: + * + * result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG; * - * result = *seed * 0xffffffed + 0x7fffffc3; * *seed = result; + * + * DIFFERENCES + * The native documentation states that the random number is + * uniformly distributed over [0..MAXLONG]. In reality the native + * function and our function return a random number uniformly + * distributed over [0..MAXLONG-1]. */ ULONG WINAPI RtlUniform (PULONG seed) { ULONG result; + /* + * Instead of the algorithm stated above, we use the algorithm + * below, which is totally equivalent (see the tests), but does + * not use a division and therefore is faster. + */ result = *seed * 0xffffffed + 0x7fffffc3; if (result == 0xffffffff || result == 0x7ffffffe) { result = (result + 2) & MAXLONG; } else if (result == 0x7fffffff) { - result = (result + 1) & MAXLONG; + result = 0; } else if ((result & 0x80000000) == 0) { result = result + (~result & 1); } else { @@ -767,3 +779,160 @@ ULONG WINAPI RtlUniform (PULONG seed) *seed = result; return result; } + + +/************************************************************************* + * RtlRandom [NTDLL.@] + * + * Generates a random number + * + * PARAMS + * seed [O] The seed of the Random function + * + * RETURNS + * It returns a random number distributed over [0..MAXLONG-1]. + */ +ULONG WINAPI RtlRandom (PULONG seed) +{ + static ULONG saved_value[128] = + { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa, + /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09, + /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311, + /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82, + /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd, + /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52, + /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb, + /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e, + /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0, + /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd, + /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35, + /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379, + /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd, + /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b, + /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b, + /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d }; + ULONG rand; + int pos; + ULONG result; + + rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff; + *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff; + pos = *seed & 0x7f; + result = saved_value[pos]; + saved_value[pos] = rand; + return(result); +} + + +/************************************************************************* + * RtlAreAllAccessesGranted [NTDLL.@] + * + * Check if all desired accesses are granted + * + * RETURNS + * TRUE: All desired accesses are granted + * FALSE: Otherwise + */ +BOOLEAN WINAPI RtlAreAllAccessesGranted( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess) +{ + return (GrantedAccess & DesiredAccess) == DesiredAccess; +} + + +/************************************************************************* + * RtlAreAnyAccessesGranted [NTDLL.@] + * + * Check if at least one of the desired accesses is granted + * + * RETURNS + * TRUE: At least one of the desired accesses is granted + * FALSE: Otherwise + */ +BOOLEAN WINAPI RtlAreAnyAccessesGranted( + ACCESS_MASK GrantedAccess, + ACCESS_MASK DesiredAccess) +{ + return (GrantedAccess & DesiredAccess) != 0; +} + + +/************************************************************************* + * RtlMapGenericMask [NTDLL.@] + * + * Determine the nongeneric access rights specified by an access mask + * + * RETURNS + * Nothing. + */ +void WINAPI RtlMapGenericMask( + PACCESS_MASK AccessMask, + const GENERIC_MAPPING *GenericMapping) +{ + if (*AccessMask & GENERIC_READ) { + *AccessMask |= GenericMapping->GenericRead; + } /* if */ + + if (*AccessMask & GENERIC_WRITE) { + *AccessMask |= GenericMapping->GenericWrite; + } /* if */ + + if (*AccessMask & GENERIC_EXECUTE) { + *AccessMask |= GenericMapping->GenericExecute; + } /* if */ + + if (*AccessMask & GENERIC_ALL) { + *AccessMask |= GenericMapping->GenericAll; + } /* if */ + + *AccessMask &= 0x0FFFFFFF; +} + + +/************************************************************************* + * RtlCopyLuid [NTDLL.@] + * + * Copies the LuidSrc to LuidDest. + * + * RETURNS + * Nothing. + */ +void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc) +{ + *LuidDest = *LuidSrc; +} + + +/************************************************************************* + * RtlEqualLuid [NTDLL.@] + * + * Compares two local unique ID's. + * + * RETURNS + * TRUE: The two LUID's are equal. + * FALSE: Otherwise + */ +BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2) +{ + return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart); +} + + +/************************************************************************* + * RtlCopyLuidAndAttributesArray [NTDLL.@] + * + * Copies an array of LUID's and attributes. + * + * RETURNS + * Nothing. + */ +void WINAPI RtlCopyLuidAndAttributesArray( + ULONG Count, + const LUID_AND_ATTRIBUTES *Src, + PLUID_AND_ATTRIBUTES Dest) +{ + ULONG i; + + for (i = 0; i < Count; i++) Dest[i] = Src[i]; +} diff --git a/dlls/ntdll/rtlstr.c b/dlls/ntdll/rtlstr.c index b805c6d51b5..88d7e042625 100644 --- a/dlls/ntdll/rtlstr.c +++ b/dlls/ntdll/rtlstr.c @@ -472,13 +472,21 @@ NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni, /************************************************************************** * RtlUnicodeStringToAnsiString (NTDLL.@) * + * Converts an Unicode string to an Ansi string. + * + * RETURNS + * Success: STATUS_SUCCESS. ansi contains the converted string + * Failure: STATUS_BUFFER_OVERFLOW if doalloc is FALSE and ansi is too small. + * STATUS_NO_MEMORY if doalloc is TRUE and the allocation fails. + * * NOTES - * This function always writes a terminating NUL. - * Performs a partial copy if ansi is too small. + * This function always writes a terminating '\0'. + * It performs a partial copy if ansi is too small. */ -NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi, - const UNICODE_STRING *uni, - BOOLEAN doalloc ) +NTSTATUS WINAPI RtlUnicodeStringToAnsiString( + STRING *ansi, /* [I/O] Destination for the Ansi string */ + const UNICODE_STRING *uni, /* [I] Unicode string to be converted */ + BOOLEAN doalloc) /* [I] TRUE=Allocate new buffer for ansi, FALSE=Use existing buffer */ { NTSTATUS ret = STATUS_SUCCESS; DWORD len = RtlUnicodeStringToAnsiSize( uni ); @@ -515,8 +523,8 @@ NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi, * * RETURNS * Success: STATUS_SUCCESS. oem contains the converted string - * Failure: STATUS_BUFFER_OVERFLOW if doalloc is FALSE and oem is too small. - * STATUS_NO_MEMORY if doalloc is TRUE and allocation fails. + * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and oem is too small. + * STATUS_NO_MEMORY, if doalloc is TRUE and allocation fails. * * NOTES * If doalloc is TRUE, the length allocated is uni->Length + 1. @@ -993,66 +1001,139 @@ DWORD WINAPI RtlUnicodeStringToOemSize( const UNICODE_STRING *str ) /************************************************************************** - * RtlAppendStringToString (NTDLL.@) + * RtlAppendAsciizToString (NTDLL.@) + * + * Concatenates a buffered character string and a '\0' terminated character + * string + * + * RETURNS + * Success: STATUS_SUCCESS. src is appended to dest. + * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is to small + * to hold the concatenated string. + * + * NOTES + * if src is NULL dest is unchanged. + * dest is never '\0' terminated. */ -NTSTATUS WINAPI RtlAppendStringToString( STRING *dst, const STRING *src ) +NTSTATUS WINAPI RtlAppendAsciizToString( + STRING *dest, /* [I/O] Buffered character string to which src is concatenated */ + LPCSTR src) /* [I] '\0' terminated character string to be concatenated */ { - unsigned int len = src->Length + dst->Length; - if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL; - memcpy( dst->Buffer + dst->Length, src->Buffer, src->Length ); - dst->Length = len; + if (src != NULL) { + unsigned int src_len = strlen(src); + unsigned int dest_len = src_len + dest->Length; + + if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL; + memcpy(dest->Buffer + dest->Length, src, src_len); + dest->Length = dest_len; + } /* if */ return STATUS_SUCCESS; } /************************************************************************** - * RtlAppendAsciizToString (NTDLL.@) + * RtlAppendStringToString (NTDLL.@) + * + * Concatenates two buffered character strings + * + * RETURNS + * Success: STATUS_SUCCESS. src is appended to dest. + * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is to small + * to hold the concatenated string. + * + * NOTES + * if src->length is zero dest is unchanged. + * dest is never '\0' terminated. */ -NTSTATUS WINAPI RtlAppendAsciizToString( STRING *dst, LPCSTR src ) +NTSTATUS WINAPI RtlAppendStringToString( + STRING *dest, /* [I/O] Buffered character string to which src is concatenated */ + const STRING *src) /* [I] Buffered character string to be concatenated */ { - if (src) - { - unsigned int srclen = strlen(src); - unsigned int total = srclen + dst->Length; - if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL; - memcpy( dst->Buffer + dst->Length, src, srclen ); - dst->Length = total; - } + if (src->Length != 0) { + unsigned int dest_len = src->Length + dest->Length; + + if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL; + memcpy(dest->Buffer + dest->Length, src->Buffer, src->Length); + dest->Length = dest_len; + } /* if */ return STATUS_SUCCESS; } /************************************************************************** * RtlAppendUnicodeToString (NTDLL.@) + * + * Concatenates an buffered unicode string and a '\0' terminated unicode + * string + * + * RETURNS + * Success: STATUS_SUCCESS. src is appended to dest. + * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is to small + * to hold the concatenated string. + * + * NOTES + * if src is NULL dest is unchanged. + * dest is '\0' terminated when the MaximumLength allowes it. + * When dest fits exactly in MaximumLength characters the '\0' is ommitted. + * + * DIFFERENCES + * Does not write in the src->Buffer beyond MaximumLength when + * MaximumLength is odd as the native function does. */ -NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src ) +NTSTATUS WINAPI RtlAppendUnicodeToString( + UNICODE_STRING *dest, /* [I/O] Buffered unicode string to which src is concatenated */ + LPCWSTR src) /* [I] '\0' terminated unicode string to be concatenated */ { - if (src) - { - unsigned int srclen = strlenW(src) * sizeof(WCHAR); - unsigned int total = srclen + dst->Length; - if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL; - memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src, srclen ); - dst->Length = total; + if (src != NULL) { + unsigned int src_len = strlenW(src) * sizeof(WCHAR); + unsigned int dest_len = src_len + dest->Length; + + if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL; + memcpy(dest->Buffer + dest->Length/sizeof(WCHAR), src, src_len); + dest->Length = dest_len; /* append terminating NULL if enough space */ - if (total < dst->MaximumLength) dst->Buffer[total / sizeof(WCHAR)] = 0; - } + if (dest_len + sizeof(WCHAR) <= dest->MaximumLength) { + dest->Buffer[dest_len / sizeof(WCHAR)] = 0; + } /* if */ + } /* if */ return STATUS_SUCCESS; } /************************************************************************** * RtlAppendUnicodeStringToString (NTDLL.@) + * + * Concatenates two buffered unicode strings + * + * RETURNS + * Success: STATUS_SUCCESS. src is appended to dest. + * Failure: STATUS_BUFFER_TOO_SMALL, if the buffer of dest is to small + * to hold the concatenated string. + * + * NOTES + * if src->length is zero dest is unchanged. + * dest is '\0' terminated when the MaximumLength allowes it. + * When dest fits exactly in MaximumLength characters the '\0' is ommitted. + * + * DIFFERENCES + * Does not write in the src->Buffer beyond MaximumLength when + * MaximumLength is odd as the native function does. */ -NTSTATUS WINAPI RtlAppendUnicodeStringToString( UNICODE_STRING *dst, const UNICODE_STRING *src ) +NTSTATUS WINAPI RtlAppendUnicodeStringToString( + UNICODE_STRING *dest, /* [I/O] Buffered unicode string to which src is concatenated */ + const UNICODE_STRING *src) /* [I] Buffered unicode string to be concatenated */ { - unsigned int len = src->Length + dst->Length; - if (src->Length == 0) return STATUS_SUCCESS; - if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL; - memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src->Buffer, src->Length ); - dst->Length = len; - /* append terminating NULL if enough space */ - if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0; + if (src->Length != 0) { + unsigned int dest_len = src->Length + dest->Length; + + if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL; + memcpy(dest->Buffer + dest->Length/sizeof(WCHAR), src->Buffer, src->Length); + dest->Length = dest_len; + /* append terminating NULL if enough space */ + if (dest_len + sizeof(WCHAR) <= dest->MaximumLength) { + dest->Buffer[dest_len / sizeof(WCHAR)] = 0; + } /* if */ + } /* if */ return STATUS_SUCCESS; } diff --git a/include/winnt.h b/include/winnt.h index e9a26e63c46..0634690ddc6 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -2968,7 +2968,7 @@ typedef struct _LUID { typedef struct _LUID_AND_ATTRIBUTES { LUID Luid; DWORD Attributes; -} LUID_AND_ATTRIBUTES; +} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES; #include "poppack.h" /* diff --git a/include/winternl.h b/include/winternl.h index e0ae837359f..5a3ddb42a59 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -903,6 +903,8 @@ NTSTATUS WINAPI RtlAppendAsciizToString(STRING *,LPCSTR); NTSTATUS WINAPI RtlAppendStringToString(STRING *,const STRING *); NTSTATUS WINAPI RtlAppendUnicodeStringToString(UNICODE_STRING *,const UNICODE_STRING *); NTSTATUS WINAPI RtlAppendUnicodeToString(UNICODE_STRING *,LPCWSTR); +BOOLEAN WINAPI RtlAreAllAccessesGranted(ACCESS_MASK,ACCESS_MASK); +BOOLEAN WINAPI RtlAreAnyAccessesGranted(ACCESS_MASK,ACCESS_MASK); BOOLEAN WINAPI RtlAreBitsSet(PCRTL_BITMAP,ULONG,ULONG); BOOLEAN WINAPI RtlAreBitsClear(PCRTL_BITMAP,ULONG,ULONG); @@ -916,6 +918,8 @@ DWORD WINAPI RtlComputeCrc32(DWORD,PBYTE,INT); NTSTATUS WINAPI RtlConvertSidToUnicodeString(PUNICODE_STRING,PSID,BOOLEAN); LONGLONG WINAPI RtlConvertLongToLargeInteger(LONG); ULONGLONG WINAPI RtlConvertUlongToLargeInteger(ULONG); +void WINAPI RtlCopyLuid(PLUID,const LUID*); +void WINAPI RtlCopyLuidAndAttributesArray(ULONG,const LUID_AND_ATTRIBUTES*,PLUID_AND_ATTRIBUTES); DWORD WINAPI RtlCopySid(DWORD,PSID,PSID); void WINAPI RtlCopyString(STRING*,const STRING*); void WINAPI RtlCopyUnicodeString(UNICODE_STRING*,const UNICODE_STRING*); @@ -943,6 +947,7 @@ NTSTATUS WINAPI RtlEnterCriticalSection(RTL_CRITICAL_SECTION *); void WINAPI RtlEraseUnicodeString(UNICODE_STRING*); NTSTATUS WINAPI RtlEqualComputerName(const UNICODE_STRING*,const UNICODE_STRING*); NTSTATUS WINAPI RtlEqualDomainName(const UNICODE_STRING*,const UNICODE_STRING*); +BOOLEAN WINAPI RtlEqualLuid(const LUID*,const LUID*); BOOL WINAPI RtlEqualPrefixSid(PSID,PSID); BOOL WINAPI RtlEqualSid(PSID,PSID); BOOLEAN WINAPI RtlEqualString(const STRING*,const STRING*,BOOLEAN); @@ -1019,6 +1024,7 @@ NTSTATUS WINAPI RtlLocalTimeToSystemTime(const LARGE_INTEGER*,PLARGE_INTEGER); BOOLEAN WINAPI RtlLockHeap(HANDLE); NTSTATUS WINAPI RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR,LPDWORD); +void WINAPI RtlMapGenericMask(PACCESS_MASK,const GENERIC_MAPPING*); NTSTATUS WINAPI RtlMultiByteToUnicodeN(LPWSTR,DWORD,LPDWORD,LPCSTR,DWORD); NTSTATUS WINAPI RtlMultiByteToUnicodeSize(DWORD*,LPCSTR,UINT); @@ -1038,8 +1044,10 @@ BOOLEAN WINAPI RtlPrefixUnicodeString(const UNICODE_STRING*,const UNICODE_STRI DWORD WINAPI RtlQueryEnvironmentVariable_U(DWORD,PUNICODE_STRING,PUNICODE_STRING) ; NTSTATUS WINAPI RtlQueryTimeZoneInformation(LPTIME_ZONE_INFORMATION); + void WINAPI RtlRaiseException(PEXCEPTION_RECORD); void WINAPI RtlRaiseStatus(NTSTATUS); +ULONG WINAPI RtlRandom(PULONG); PVOID WINAPI RtlReAllocateHeap(HANDLE,ULONG,PVOID,ULONG); void WINAPI RtlReleasePebLock(void); void WINAPI RtlReleaseResource(LPRTL_RWLOCK);