Implemented RtlRandom, RtlAreAllAccessesGranted,

RtlAreAnyAccessesGranted, RtlCopyLuid, RtlEqualLuid, RtlMapGenericMask
and RtlCopyLuidAndAttributesArray.
Documentation updates for RtlExtendedMagicDivide, RtlUniform,
RtlUnicodeStringToAnsiString, RtlAppendAsciizToString,
RtlAppendStringToString, RtlAppendUnicodeToString and
RtlAppendUnicodeStringToString.
This commit is contained in:
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.@)
*
* 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;

View File

@ -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

View File

@ -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];
}

View File

@ -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;
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 (len < dst->MaximumLength) dst->Buffer[len / sizeof(WCHAR)] = 0;
if (dest_len + sizeof(WCHAR) <= dest->MaximumLength) {
dest->Buffer[dest_len / sizeof(WCHAR)] = 0;
} /* if */
} /* if */
return STATUS_SUCCESS;
}

View File

@ -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"
/*

View File

@ -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);