some ntdll functions (4) - part 1: functions

thomas.mertes at gmx.at thomas.mertes at gmx.at
Mon Apr 7 02:22:15 CDT 2003


Hello

Here are implementations and documentation updates of
some ntdll functions.I have tested some of the functions
a lot on w2k (see part 2: tests).

Changelog:

	* include/winnt.h, include/winternl.h,
	  dlls/ntdll/ntdll.spec, dlls/ntdll/rtl.c,
	  dlls/ntdll/rtlstr.c, dlls/ntdll/large_int.c:
	Thomas Mertes <thomas.mertes at gmx.at>
	Implement RtlRandom, RtlAreAllAccessesGranted,
	  RtlAreAnyAccessesGranted, RtlCopyLuid, RtlEqualLuid,
	  RtlMapGenericMasc and RtlCopyLuidAndAttributesArray.
	Documentation updates for RtlExtendedMagicDivide,
	  RtlUniform, RtlUnicodeStringToAnsiString,
	  RtlAppendAsciizToString, RtlAppendStringToString,
	  RtlAppendUnicodeToString and
	  RtlAppendUnicodeStringToString.


-- 
+++ GMX - Mail, Messaging & more  http://www.gmx.net +++
Bitte lächeln! Fotogalerie online mit GMX ohne eigene Homepage!
-------------- next part --------------
diff -urN wine_cvs_from_20030404/dlls/ntdll/large_int.c new_wine-20030318/dlls/ntdll/large_int.c
--- wine_cvs_from_20030404/dlls/ntdll/large_int.c	Thu Apr  3 21:18:27 2003
+++ new_wine-20030318/dlls/ntdll/large_int.c	Sun Apr  6 22:56:30 2003
@@ -183,56 +183,57 @@
 /******************************************************************************
  *        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 -urN wine_cvs_from_20030404/dlls/ntdll/ntdll.spec new_wine-20030318/dlls/ntdll/ntdll.spec
--- wine_cvs_from_20030404/dlls/ntdll/ntdll.spec	Fri Apr  4 00:54:01 2003
+++ new_wine-20030318/dlls/ntdll/ntdll.spec	Sun Apr  6 22:56:02 2003
@@ -283,8 +283,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)
@@ -295,7 +295,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
@@ -307,8 +307,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
@@ -360,7 +360,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)
@@ -458,7 +458,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)
@@ -490,7 +490,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 -urN wine_cvs_from_20030404/dlls/ntdll/rtl.c new_wine-20030318/dlls/ntdll/rtl.c
--- wine_cvs_from_20030404/dlls/ntdll/rtl.c	Thu Apr  3 21:18:56 2003
+++ new_wine-20030318/dlls/ntdll/rtl.c	Sun Apr  6 22:56:11 2003
@@ -741,24 +741,36 @@
  *  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 {
@@ -766,4 +778,166 @@
     } /* if */
     *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,
+    PGENERIC_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, PLUID LuidSrc)
+{
+    LuidDest->HighPart = LuidSrc->HighPart;
+    LuidDest->LowPart =  LuidSrc->LowPart;
+}
+
+
+/*************************************************************************
+ * RtlEqualLuid   [NTDLL.@]
+ *
+ * Compares two local unique ID's.
+ *
+ * RETURNS
+ *  TRUE: The two LUID's are equal.
+ *  FALSE: Otherwise
+ */
+BOOLEAN WINAPI RtlEqualLuid (PLUID Luid1, PLUID Luid2)
+{
+  return (Luid1->LowPart ==  Luid2->LowPart &&
+	  Luid1->HighPart == Luid2->HighPart) ? TRUE : FALSE;
+}
+
+
+/*************************************************************************
+ * RtlCopyLuidAndAttributesArray   [NTDLL.@]
+ *
+ * Copies an array of LUID's and attributes.
+ *
+ * RETURNS
+ *  Nothing.
+ */
+void WINAPI RtlCopyLuidAndAttributesArray(
+    ULONG Count,
+    PLUID_AND_ATTRIBUTES Src,
+    PLUID_AND_ATTRIBUTES Dest)
+{
+    ULONG i;
+
+    for (i = 0; i < Count; i++) {
+	RtlCopyMemory(&Dest[i], &Src[i],
+		      sizeof(LUID_AND_ATTRIBUTES));
+    } /* for */
 }
diff -urN wine_cvs_from_20030404/dlls/ntdll/rtlstr.c new_wine-20030318/dlls/ntdll/rtlstr.c
--- wine_cvs_from_20030404/dlls/ntdll/rtlstr.c	Fri Apr  4 00:36:36 2003
+++ new_wine-20030318/dlls/ntdll/rtlstr.c	Sun Apr  6 22:56:19 2003
@@ -472,13 +472,21 @@
 /**************************************************************************
  *	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 @@
  *
  * 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 @@
 
 
 /**************************************************************************
- *      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 )
-{
-    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;
+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 */
+{
+    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 )
-{
-    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;
-    }
+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->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.@)
- */
-NTSTATUS WINAPI RtlAppendUnicodeToString( UNICODE_STRING *dst, LPCWSTR src )
-{
-    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;
+ *
+ * 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 *dest, /* [I/O] Buffered unicode string to which src is concatenated */
+    LPCWSTR src)          /* [I]   '\0' terminated unicode string to be concatenated */
+{
+    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.@)
- */
-NTSTATUS WINAPI RtlAppendUnicodeStringToString( UNICODE_STRING *dst, const UNICODE_STRING *src )
-{
-    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;
+ *
+ * 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 *dest,      /* [I/O] Buffered unicode string to which src is concatenated */
+    const UNICODE_STRING *src) /* [I]   Buffered unicode string to be concatenated */
+{
+    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 -urN wine_cvs_from_20030404/include/winnt.h new_wine-20030318/include/winnt.h
--- wine_cvs_from_20030404/include/winnt.h	Wed Mar 12 21:14:35 2003
+++ new_wine-20030318/include/winnt.h	Sun Apr  6 22:57:16 2003
@@ -2968,7 +2968,7 @@
 typedef struct _LUID_AND_ATTRIBUTES {
   LUID   Luid;
   DWORD  Attributes;
-} LUID_AND_ATTRIBUTES;
+} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;
 #include "poppack.h"
 
 /*
diff -urN wine_cvs_from_20030404/include/winternl.h new_wine-20030318/include/winternl.h
--- wine_cvs_from_20030404/include/winternl.h	Wed Mar 19 01:09:57 2003
+++ new_wine-20030318/include/winternl.h	Sun Apr  6 22:57:24 2003
@@ -888,6 +888,8 @@
 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);
 
@@ -901,6 +903,8 @@
 NTSTATUS  WINAPI RtlConvertSidToUnicodeString(PUNICODE_STRING,PSID,BOOLEAN);
 LONGLONG  WINAPI RtlConvertLongToLargeInteger(LONG);
 ULONGLONG WINAPI RtlConvertUlongToLargeInteger(ULONG);
+void      WINAPI RtlCopyLuid(PLUID,PLUID);
+void      WINAPI RtlCopyLuidAndAttributesArray(ULONG,PLUID_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*);
@@ -918,6 +922,7 @@
 HANDLE    WINAPI RtlDestroyHeap(HANDLE);
 BOOLEAN   WINAPI RtlDosPathNameToNtPathName_U(LPWSTR,PUNICODE_STRING,DWORD,DWORD);
 WCHAR     WINAPI RtlDowncaseUnicodeChar(WCHAR);
+NTSTATUS  WINAPI RtlDowncaseUnicodeString(UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN);
 void      WINAPI RtlDumpResource(LPRTL_RWLOCK);
 
 LONGLONG  WINAPI RtlEnlargedIntegerMultiply(INT,INT);
@@ -927,6 +932,7 @@
 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(PLUID, PLUID);
 BOOL      WINAPI RtlEqualPrefixSid(PSID,PSID);
 BOOL      WINAPI RtlEqualSid(PSID,PSID);
 BOOLEAN   WINAPI RtlEqualString(const STRING*,const STRING*,BOOLEAN);
@@ -1003,6 +1009,7 @@
 BOOLEAN   WINAPI RtlLockHeap(HANDLE);
 
 NTSTATUS  WINAPI RtlMakeSelfRelativeSD(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR,LPDWORD);
+void      WINAPI RtlMapGenericMask(PACCESS_MASK,PGENERIC_MAPPING);
 NTSTATUS  WINAPI RtlMultiByteToUnicodeN(LPWSTR,DWORD,LPDWORD,LPCSTR,DWORD);
 NTSTATUS  WINAPI RtlMultiByteToUnicodeSize(DWORD*,LPCSTR,UINT);
 
@@ -1022,8 +1029,10 @@
 
 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);


More information about the wine-patches mailing list