Implemented RtlRandom, RtlAreAllAccessesGranted,

RtlAreAnyAccessesGranted, RtlCopyLuid, RtlEqualLuid, RtlMapGenericMask
and RtlCopyLuidAndAttributesArray.
Documentation updates for RtlExtendedMagicDivide, RtlUniform,
RtlUnicodeStringToAnsiString, RtlAppendAsciizToString,
RtlAppendStringToString, RtlAppendUnicodeToString and
RtlAppendUnicodeStringToString.
oldstable
Thomas Mertes 2003-04-08 00:55:36 +00:00 committed by Alexandre Julliard
parent e434d89bc9
commit 0ce4826eee
6 changed files with 341 additions and 82 deletions

View File

@ -183,56 +183,57 @@ LONGLONG WINAPI RtlExtendedIntegerMultiply( LONGLONG a, INT b )
/****************************************************************************** /******************************************************************************
* RtlExtendedMagicDivide (NTDLL.@) * 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 * RETURNS
* (a * b) >> (64 + shift) * (dividend * inverse_divisor) >> (64 + shift)
* *
* NOTES * NOTES
* This allows replacing a division by a longlong constant * If the divisor of a division is constant, the constants inverse_divisor and
* by a multiplication by the inverse constant. * 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' * The Parameter inverse_divisor although defined as LONGLONG is used as
* must be chosen such that b = 2^(64+shift) / c. * ULONGLONG.
* 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.
*/ */
#define LOWER_32(A) ((A) & 0xffffffff) #define LOWER_32(A) ((A) & 0xffffffff)
#define UPPER_32(A) ((A) >> 32) #define UPPER_32(A) ((A) >> 32)
LONGLONG WINAPI RtlExtendedMagicDivide( LONGLONG WINAPI RtlExtendedMagicDivide(
LONGLONG a, /* [I] Dividend to be divided by the constant divisor */ LONGLONG dividend, /* [I] Dividend to be divided by the constant divisor */
LONGLONG b, /* [I] Constant computed manually as 2^(64+shift) / divisor */ LONGLONG inverse_divisor, /* [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 */ INT shift) /* [I] Constant shift chosen to make inverse_divisor as big as possible for 64 bits */
{ {
ULONGLONG a_high; ULONGLONG dividend_high;
ULONGLONG a_low; ULONGLONG dividend_low;
ULONGLONG b_high; ULONGLONG inverse_divisor_high;
ULONGLONG b_low; ULONGLONG inverse_divisor_low;
ULONGLONG ah_bl; ULONGLONG ah_bl;
ULONGLONG al_bh; ULONGLONG al_bh;
LONGLONG result; LONGLONG result;
int positive; int positive;
if (a < 0) { if (dividend < 0) {
a_high = UPPER_32((ULONGLONG) -a); dividend_high = UPPER_32((ULONGLONG) -dividend);
a_low = LOWER_32((ULONGLONG) -a); dividend_low = LOWER_32((ULONGLONG) -dividend);
positive = 0; positive = 0;
} else { } else {
a_high = UPPER_32((ULONGLONG) a); dividend_high = UPPER_32((ULONGLONG) dividend);
a_low = LOWER_32((ULONGLONG) a); dividend_low = LOWER_32((ULONGLONG) dividend);
positive = 1; positive = 1;
} /* if */ } /* if */
b_high = UPPER_32((ULONGLONG) b); inverse_divisor_high = UPPER_32((ULONGLONG) inverse_divisor);
b_low = LOWER_32((ULONGLONG) b); inverse_divisor_low = LOWER_32((ULONGLONG) inverse_divisor);
ah_bl = a_high * b_low; ah_bl = dividend_high * inverse_divisor_low;
al_bh = a_low * b_high; 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(ah_bl) +
UPPER_32(al_bh) + 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) { if (positive) {
return result; return result;

View File

@ -286,8 +286,8 @@
@ stdcall RtlAppendUnicodeToString(ptr wstr) @ stdcall RtlAppendUnicodeToString(ptr wstr)
@ stub RtlApplyRXact @ stub RtlApplyRXact
@ stub RtlApplyRXactNoFlush @ stub RtlApplyRXactNoFlush
@ stub RtlAreAllAccessesGranted @ stdcall RtlAreAllAccessesGranted(long long)
@ stub RtlAreAnyAccessesGranted @ stdcall RtlAreAnyAccessesGranted(long long)
@ stdcall RtlAreBitsClear(ptr long long) @ stdcall RtlAreBitsClear(ptr long long)
@ stdcall RtlAreBitsSet(ptr long long) @ stdcall RtlAreBitsSet(ptr long long)
@ stdcall RtlAssert(ptr ptr long long) @ stdcall RtlAssert(ptr ptr long long)
@ -298,7 +298,7 @@
@ stdcall RtlClearBits(ptr long long) @ stdcall RtlClearBits(ptr long long)
@ stdcall RtlCompactHeap(long long) @ stdcall RtlCompactHeap(long long)
@ stdcall RtlCompareMemory(ptr ptr long) @ stdcall RtlCompareMemory(ptr ptr long)
@ stdcall RtlCompareMemoryUlong(ptr ptr long) @ stdcall RtlCompareMemoryUlong(ptr long long)
@ stdcall RtlCompareString(ptr ptr long) @ stdcall RtlCompareString(ptr ptr long)
@ stdcall RtlCompareUnicodeString (ptr ptr long) @ stdcall RtlCompareUnicodeString (ptr ptr long)
@ stub RtlCompressBuffer @ stub RtlCompressBuffer
@ -310,8 +310,8 @@
@ stdcall RtlConvertSidToUnicodeString(ptr ptr long) @ stdcall RtlConvertSidToUnicodeString(ptr ptr long)
@ stub RtlConvertUiListToApiList @ stub RtlConvertUiListToApiList
@ stdcall -ret64 RtlConvertUlongToLargeInteger(long) @ stdcall -ret64 RtlConvertUlongToLargeInteger(long)
@ stub RtlCopyLuid @ stdcall RtlCopyLuid(ptr ptr)
@ stub RtlCopyLuidAndAttributesArray @ stdcall RtlCopyLuidAndAttributesArray(long ptr ptr)
@ stub RtlCopySecurityDescriptor @ stub RtlCopySecurityDescriptor
@ stdcall RtlCopySid(long ptr ptr) @ stdcall RtlCopySid(long ptr ptr)
@ stub RtlCopySidAndAttributesArray @ stub RtlCopySidAndAttributesArray
@ -363,7 +363,7 @@
@ stub RtlEnumerateGenericTableWithoutSplaying @ stub RtlEnumerateGenericTableWithoutSplaying
@ stdcall RtlEqualComputerName(ptr ptr) @ stdcall RtlEqualComputerName(ptr ptr)
@ stdcall RtlEqualDomainName(ptr ptr) @ stdcall RtlEqualDomainName(ptr ptr)
@ stub RtlEqualLuid @ stdcall RtlEqualLuid(ptr ptr)
@ stdcall RtlEqualPrefixSid(ptr ptr) @ stdcall RtlEqualPrefixSid(ptr ptr)
@ stdcall RtlEqualSid (long long) @ stdcall RtlEqualSid (long long)
@ stdcall RtlEqualString(ptr ptr long) @ stdcall RtlEqualString(ptr ptr long)
@ -461,7 +461,7 @@
@ stdcall RtlLockHeap(long) @ stdcall RtlLockHeap(long)
@ stub RtlLookupElementGenericTable @ stub RtlLookupElementGenericTable
@ stdcall RtlMakeSelfRelativeSD(ptr ptr ptr) @ stdcall RtlMakeSelfRelativeSD(ptr ptr ptr)
@ stub RtlMapGenericMask @ stdcall RtlMapGenericMask(long ptr)
@ stdcall RtlMoveMemory(ptr ptr long) @ stdcall RtlMoveMemory(ptr ptr long)
@ stdcall RtlMultiByteToUnicodeN(ptr long ptr ptr long) @ stdcall RtlMultiByteToUnicodeN(ptr long ptr ptr long)
@ stdcall RtlMultiByteToUnicodeSize(ptr str long) @ stdcall RtlMultiByteToUnicodeSize(ptr str long)
@ -493,7 +493,7 @@
@ stdcall RtlQueryTimeZoneInformation(ptr) @ stdcall RtlQueryTimeZoneInformation(ptr)
@ stdcall RtlRaiseException(ptr) @ stdcall RtlRaiseException(ptr)
@ stdcall RtlRaiseStatus(long) @ stdcall RtlRaiseStatus(long)
@ stub RtlRandom @ stdcall RtlRandom(ptr)
@ stdcall RtlReAllocateHeap(long long ptr long) @ stdcall RtlReAllocateHeap(long long ptr long)
@ stub RtlRealPredecessor @ stub RtlRealPredecessor
@ stub RtlRealSuccessor @ stub RtlRealSuccessor

View File

@ -741,24 +741,36 @@ __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap,
* seed [O] The seed of the Random function * seed [O] The seed of the Random function
* *
* RETURNS * RETURNS
* It returns a random number uniformly distributed over [0..MAXLONG]. * It returns a random number uniformly distributed over [0..MAXLONG-1].
* *
* NOTES * NOTES
* Generates an uniform random number using a modified version of * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
* D.H. Lehmer's 1948 algorithm. The original algorithm would be: * In our case the algorithm is:
*
* result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
* *
* result = *seed * 0xffffffed + 0x7fffffc3;
* *seed = result; * *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 WINAPI RtlUniform (PULONG seed)
{ {
ULONG result; 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; result = *seed * 0xffffffed + 0x7fffffc3;
if (result == 0xffffffff || result == 0x7ffffffe) { if (result == 0xffffffff || result == 0x7ffffffe) {
result = (result + 2) & MAXLONG; result = (result + 2) & MAXLONG;
} else if (result == 0x7fffffff) { } else if (result == 0x7fffffff) {
result = (result + 1) & MAXLONG; result = 0;
} else if ((result & 0x80000000) == 0) { } else if ((result & 0x80000000) == 0) {
result = result + (~result & 1); result = result + (~result & 1);
} else { } else {
@ -767,3 +779,160 @@ ULONG WINAPI RtlUniform (PULONG seed)
*seed = result; *seed = result;
return 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];
}

View File

@ -472,13 +472,21 @@ NTSTATUS WINAPI RtlOemStringToUnicodeString( UNICODE_STRING *uni,
/************************************************************************** /**************************************************************************
* RtlUnicodeStringToAnsiString (NTDLL.@) * 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 * NOTES
* This function always writes a terminating NUL. * This function always writes a terminating '\0'.
* Performs a partial copy if ansi is too small. * It performs a partial copy if ansi is too small.
*/ */
NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi, NTSTATUS WINAPI RtlUnicodeStringToAnsiString(
const UNICODE_STRING *uni, STRING *ansi, /* [I/O] Destination for the Ansi string */
BOOLEAN doalloc ) 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; NTSTATUS ret = STATUS_SUCCESS;
DWORD len = RtlUnicodeStringToAnsiSize( uni ); DWORD len = RtlUnicodeStringToAnsiSize( uni );
@ -515,8 +523,8 @@ NTSTATUS WINAPI RtlUnicodeStringToAnsiString( STRING *ansi,
* *
* RETURNS * RETURNS
* Success: STATUS_SUCCESS. oem contains the converted string * Success: STATUS_SUCCESS. oem contains the converted string
* Failure: STATUS_BUFFER_OVERFLOW if doalloc is FALSE and oem is too small. * Failure: STATUS_BUFFER_OVERFLOW, if doalloc is FALSE and oem is too small.
* STATUS_NO_MEMORY if doalloc is TRUE and allocation fails. * STATUS_NO_MEMORY, if doalloc is TRUE and allocation fails.
* *
* NOTES * NOTES
* If doalloc is TRUE, the length allocated is uni->Length + 1. * 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 (src != NULL) {
if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL; unsigned int src_len = strlen(src);
memcpy( dst->Buffer + dst->Length, src->Buffer, src->Length ); unsigned int dest_len = src_len + dest->Length;
dst->Length = len;
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; 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) if (src->Length != 0) {
{ unsigned int dest_len = src->Length + dest->Length;
unsigned int srclen = strlen(src);
unsigned int total = srclen + dst->Length; if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL; memcpy(dest->Buffer + dest->Length, src->Buffer, src->Length);
memcpy( dst->Buffer + dst->Length, src, srclen ); dest->Length = dest_len;
dst->Length = total; } /* if */
}
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/************************************************************************** /**************************************************************************
* RtlAppendUnicodeToString (NTDLL.@) * 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) if (src != NULL) {
{ unsigned int src_len = strlenW(src) * sizeof(WCHAR);
unsigned int srclen = strlenW(src) * sizeof(WCHAR); unsigned int dest_len = src_len + dest->Length;
unsigned int total = srclen + dst->Length;
if (total > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL; if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src, srclen ); memcpy(dest->Buffer + dest->Length/sizeof(WCHAR), src, src_len);
dst->Length = total; dest->Length = dest_len;
/* append terminating NULL if enough space */ /* 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; return STATUS_SUCCESS;
} }
/************************************************************************** /**************************************************************************
* RtlAppendUnicodeStringToString (NTDLL.@) * 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) {
if (src->Length == 0) return STATUS_SUCCESS; unsigned int dest_len = src->Length + dest->Length;
if (len > dst->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
memcpy( dst->Buffer + dst->Length/sizeof(WCHAR), src->Buffer, src->Length ); if (dest_len > dest->MaximumLength) return STATUS_BUFFER_TOO_SMALL;
dst->Length = len; memcpy(dest->Buffer + dest->Length/sizeof(WCHAR), src->Buffer, src->Length);
/* append terminating NULL if enough space */ dest->Length = dest_len;
if (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0; /* 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; return STATUS_SUCCESS;
} }

View File

@ -2968,7 +2968,7 @@ typedef struct _LUID {
typedef struct _LUID_AND_ATTRIBUTES { typedef struct _LUID_AND_ATTRIBUTES {
LUID Luid; LUID Luid;
DWORD Attributes; DWORD Attributes;
} LUID_AND_ATTRIBUTES; } LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;
#include "poppack.h" #include "poppack.h"
/* /*

View File

@ -903,6 +903,8 @@ NTSTATUS WINAPI RtlAppendAsciizToString(STRING *,LPCSTR);
NTSTATUS WINAPI RtlAppendStringToString(STRING *,const STRING *); NTSTATUS WINAPI RtlAppendStringToString(STRING *,const STRING *);
NTSTATUS WINAPI RtlAppendUnicodeStringToString(UNICODE_STRING *,const UNICODE_STRING *); NTSTATUS WINAPI RtlAppendUnicodeStringToString(UNICODE_STRING *,const UNICODE_STRING *);
NTSTATUS WINAPI RtlAppendUnicodeToString(UNICODE_STRING *,LPCWSTR); 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 RtlAreBitsSet(PCRTL_BITMAP,ULONG,ULONG);
BOOLEAN WINAPI RtlAreBitsClear(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); NTSTATUS WINAPI RtlConvertSidToUnicodeString(PUNICODE_STRING,PSID,BOOLEAN);
LONGLONG WINAPI RtlConvertLongToLargeInteger(LONG); LONGLONG WINAPI RtlConvertLongToLargeInteger(LONG);
ULONGLONG WINAPI RtlConvertUlongToLargeInteger(ULONG); 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); DWORD WINAPI RtlCopySid(DWORD,PSID,PSID);
void WINAPI RtlCopyString(STRING*,const STRING*); void WINAPI RtlCopyString(STRING*,const STRING*);
void WINAPI RtlCopyUnicodeString(UNICODE_STRING*,const UNICODE_STRING*); void WINAPI RtlCopyUnicodeString(UNICODE_STRING*,const UNICODE_STRING*);
@ -943,6 +947,7 @@ NTSTATUS WINAPI RtlEnterCriticalSection(RTL_CRITICAL_SECTION *);
void WINAPI RtlEraseUnicodeString(UNICODE_STRING*); void WINAPI RtlEraseUnicodeString(UNICODE_STRING*);
NTSTATUS WINAPI RtlEqualComputerName(const UNICODE_STRING*,const UNICODE_STRING*); NTSTATUS WINAPI RtlEqualComputerName(const UNICODE_STRING*,const UNICODE_STRING*);
NTSTATUS WINAPI RtlEqualDomainName(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 RtlEqualPrefixSid(PSID,PSID);
BOOL WINAPI RtlEqualSid(PSID,PSID); BOOL WINAPI RtlEqualSid(PSID,PSID);
BOOLEAN WINAPI RtlEqualString(const STRING*,const STRING*,BOOLEAN); BOOLEAN WINAPI RtlEqualString(const STRING*,const STRING*,BOOLEAN);
@ -1019,6 +1024,7 @@ NTSTATUS WINAPI RtlLocalTimeToSystemTime(const LARGE_INTEGER*,PLARGE_INTEGER);
BOOLEAN WINAPI RtlLockHeap(HANDLE); BOOLEAN WINAPI RtlLockHeap(HANDLE);
NTSTATUS WINAPI RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR,LPDWORD); 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 RtlMultiByteToUnicodeN(LPWSTR,DWORD,LPDWORD,LPCSTR,DWORD);
NTSTATUS WINAPI RtlMultiByteToUnicodeSize(DWORD*,LPCSTR,UINT); 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) ; DWORD WINAPI RtlQueryEnvironmentVariable_U(DWORD,PUNICODE_STRING,PUNICODE_STRING) ;
NTSTATUS WINAPI RtlQueryTimeZoneInformation(LPTIME_ZONE_INFORMATION); NTSTATUS WINAPI RtlQueryTimeZoneInformation(LPTIME_ZONE_INFORMATION);
void WINAPI RtlRaiseException(PEXCEPTION_RECORD); void WINAPI RtlRaiseException(PEXCEPTION_RECORD);
void WINAPI RtlRaiseStatus(NTSTATUS); void WINAPI RtlRaiseStatus(NTSTATUS);
ULONG WINAPI RtlRandom(PULONG);
PVOID WINAPI RtlReAllocateHeap(HANDLE,ULONG,PVOID,ULONG); PVOID WINAPI RtlReAllocateHeap(HANDLE,ULONG,PVOID,ULONG);
void WINAPI RtlReleasePebLock(void); void WINAPI RtlReleasePebLock(void);
void WINAPI RtlReleaseResource(LPRTL_RWLOCK); void WINAPI RtlReleaseResource(LPRTL_RWLOCK);