4 * This file contains the Rtl* API functions. These should be implementable.
6 * Copyright 1996-1998 Marcus Meissner
7 * Copyright 1999 Alex Korobka
8 * Copyright 2003 Thomas Mertes
9 * Crc32 code Copyright 1986 Gary S. Brown (Public domain)
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/port.h"
33 #ifdef HAVE_NETINET_IN_H
34 #include <netinet/in.h>
37 #define NONAMELESSSTRUCT
38 #define WIN32_NO_STATUS
42 #include "wine/debug.h"
43 #include "wine/exception.h"
44 #include "wine/unicode.h"
45 #include "ntdll_misc.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
50 static RTL_CRITICAL_SECTION peb_lock
;
51 static RTL_CRITICAL_SECTION_DEBUG critsect_debug
=
54 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
55 0, 0, { (DWORD_PTR
)(__FILE__
": peb_lock") }
57 static RTL_CRITICAL_SECTION peb_lock
= { &critsect_debug
, -1, 0, 0, 0, 0 };
59 /* CRC polynomial 0xedb88320 */
60 static const DWORD CRC_table
[256] =
62 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
63 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
64 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
65 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
66 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
67 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
68 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
69 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
70 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
71 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
72 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
73 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
74 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
75 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
76 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
77 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
78 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
79 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
80 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
81 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
82 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
83 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
84 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
85 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
86 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
87 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
88 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
89 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
90 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
91 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
92 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
93 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
94 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
95 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
96 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
97 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
98 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
99 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
100 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
101 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
102 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
103 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
104 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
111 /***********************************************************************
112 * RtlInitializeResource (NTDLL.@)
114 * xxxResource() functions implement multiple-reader-single-writer lock.
115 * The code is based on information published in WDJ January 1999 issue.
117 void WINAPI
RtlInitializeResource(LPRTL_RWLOCK rwl
)
121 rwl
->iNumberActive
= 0;
122 rwl
->uExclusiveWaiters
= 0;
123 rwl
->uSharedWaiters
= 0;
124 rwl
->hOwningThreadId
= 0;
125 rwl
->dwTimeoutBoost
= 0; /* no info on this one, default value is 0 */
126 RtlInitializeCriticalSection( &rwl
->rtlCS
);
127 rwl
->rtlCS
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": RTL_RWLOCK.rtlCS");
128 NtCreateSemaphore( &rwl
->hExclusiveReleaseSemaphore
, SEMAPHORE_ALL_ACCESS
, NULL
, 0, 65535 );
129 NtCreateSemaphore( &rwl
->hSharedReleaseSemaphore
, SEMAPHORE_ALL_ACCESS
, NULL
, 0, 65535 );
134 /***********************************************************************
135 * RtlDeleteResource (NTDLL.@)
137 void WINAPI
RtlDeleteResource(LPRTL_RWLOCK rwl
)
141 RtlEnterCriticalSection( &rwl
->rtlCS
);
142 if( rwl
->iNumberActive
|| rwl
->uExclusiveWaiters
|| rwl
->uSharedWaiters
)
143 ERR("Deleting active MRSW lock (%p), expect failure\n", rwl
);
144 rwl
->hOwningThreadId
= 0;
145 rwl
->uExclusiveWaiters
= rwl
->uSharedWaiters
= 0;
146 rwl
->iNumberActive
= 0;
147 NtClose( rwl
->hExclusiveReleaseSemaphore
);
148 NtClose( rwl
->hSharedReleaseSemaphore
);
149 RtlLeaveCriticalSection( &rwl
->rtlCS
);
150 rwl
->rtlCS
.DebugInfo
->Spare
[0] = 0;
151 RtlDeleteCriticalSection( &rwl
->rtlCS
);
156 /***********************************************************************
157 * RtlAcquireResourceExclusive (NTDLL.@)
159 BYTE WINAPI
RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl
, BYTE fWait
)
165 RtlEnterCriticalSection( &rwl
->rtlCS
);
166 if( rwl
->iNumberActive
== 0 ) /* lock is free */
168 rwl
->iNumberActive
= -1;
171 else if( rwl
->iNumberActive
< 0 ) /* exclusive lock in progress */
173 if( rwl
->hOwningThreadId
== ULongToHandle(GetCurrentThreadId()) )
176 rwl
->iNumberActive
--;
184 rwl
->uExclusiveWaiters
++;
186 RtlLeaveCriticalSection( &rwl
->rtlCS
);
187 status
= NtWaitForSingleObject( rwl
->hExclusiveReleaseSemaphore
, FALSE
, NULL
);
190 goto start
; /* restart the acquisition to avoid deadlocks */
193 else /* one or more shared locks are in progress */
198 rwl
->hOwningThreadId
= ULongToHandle(GetCurrentThreadId());
200 RtlLeaveCriticalSection( &rwl
->rtlCS
);
204 /***********************************************************************
205 * RtlAcquireResourceShared (NTDLL.@)
207 BYTE WINAPI
RtlAcquireResourceShared(LPRTL_RWLOCK rwl
, BYTE fWait
)
209 NTSTATUS status
= STATUS_UNSUCCESSFUL
;
214 RtlEnterCriticalSection( &rwl
->rtlCS
);
215 if( rwl
->iNumberActive
< 0 )
217 if( rwl
->hOwningThreadId
== ULongToHandle(GetCurrentThreadId()) )
219 rwl
->iNumberActive
--;
226 rwl
->uSharedWaiters
++;
227 RtlLeaveCriticalSection( &rwl
->rtlCS
);
228 status
= NtWaitForSingleObject( rwl
->hSharedReleaseSemaphore
, FALSE
, NULL
);
236 if( status
!= STATUS_WAIT_0
) /* otherwise RtlReleaseResource() has already done it */
237 rwl
->iNumberActive
++;
241 RtlLeaveCriticalSection( &rwl
->rtlCS
);
246 /***********************************************************************
247 * RtlReleaseResource (NTDLL.@)
249 void WINAPI
RtlReleaseResource(LPRTL_RWLOCK rwl
)
251 RtlEnterCriticalSection( &rwl
->rtlCS
);
253 if( rwl
->iNumberActive
> 0 ) /* have one or more readers */
255 if( --rwl
->iNumberActive
== 0 )
257 if( rwl
->uExclusiveWaiters
)
260 rwl
->uExclusiveWaiters
--;
261 NtReleaseSemaphore( rwl
->hExclusiveReleaseSemaphore
, 1, NULL
);
266 if( rwl
->iNumberActive
< 0 ) /* have a writer, possibly recursive */
268 if( ++rwl
->iNumberActive
== 0 )
270 rwl
->hOwningThreadId
= 0;
271 if( rwl
->uExclusiveWaiters
)
274 if( rwl
->uSharedWaiters
)
276 UINT n
= rwl
->uSharedWaiters
;
277 rwl
->iNumberActive
= rwl
->uSharedWaiters
; /* prevent new writers from joining until
278 * all queued readers have done their thing */
279 rwl
->uSharedWaiters
= 0;
280 NtReleaseSemaphore( rwl
->hSharedReleaseSemaphore
, n
, NULL
);
284 RtlLeaveCriticalSection( &rwl
->rtlCS
);
288 /***********************************************************************
289 * RtlDumpResource (NTDLL.@)
291 void WINAPI
RtlDumpResource(LPRTL_RWLOCK rwl
)
295 MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
296 rwl
, rwl
->iNumberActive
, rwl
->uSharedWaiters
, rwl
->uExclusiveWaiters
);
297 if( rwl
->iNumberActive
)
298 MESSAGE("\towner thread = %p\n", rwl
->hOwningThreadId
);
306 /******************************************************************************
309 NTSTATUS WINAPIV
DbgPrint(LPCSTR fmt
, ...)
314 __ms_va_start(args
, fmt
);
315 NTDLL__vsnprintf(buf
, sizeof(buf
), fmt
, args
);
318 MESSAGE("DbgPrint says: %s",buf
);
319 /* hmm, raise exception? */
320 return STATUS_SUCCESS
;
324 /******************************************************************************
325 * DbgPrintEx [NTDLL.@]
327 NTSTATUS WINAPIV
DbgPrintEx(ULONG iComponentId
, ULONG Level
, LPCSTR fmt
, ...)
332 __ms_va_start(args
, fmt
);
333 ret
= vDbgPrintEx(iComponentId
, Level
, fmt
, args
);
338 /******************************************************************************
339 * vDbgPrintEx [NTDLL.@]
341 NTSTATUS WINAPI
vDbgPrintEx( ULONG id
, ULONG level
, LPCSTR fmt
, __ms_va_list args
)
343 return vDbgPrintExWithPrefix( "", id
, level
, fmt
, args
);
346 /******************************************************************************
347 * vDbgPrintExWithPrefix [NTDLL.@]
349 NTSTATUS WINAPI
vDbgPrintExWithPrefix( LPCSTR prefix
, ULONG id
, ULONG level
, LPCSTR fmt
, __ms_va_list args
)
353 NTDLL__vsnprintf(buf
, sizeof(buf
), fmt
, args
);
355 switch (level
& DPFLTR_MASK
)
357 case DPFLTR_ERROR_LEVEL
: ERR("%s%x: %s", prefix
, id
, buf
); break;
358 case DPFLTR_WARNING_LEVEL
: WARN("%s%x: %s", prefix
, id
, buf
); break;
359 case DPFLTR_TRACE_LEVEL
:
360 case DPFLTR_INFO_LEVEL
:
361 default: TRACE("%s%x: %s", prefix
, id
, buf
); break;
363 return STATUS_SUCCESS
;
366 /******************************************************************************
367 * RtlAcquirePebLock [NTDLL.@]
369 VOID WINAPI
RtlAcquirePebLock(void)
371 RtlEnterCriticalSection( &peb_lock
);
374 /******************************************************************************
375 * RtlReleasePebLock [NTDLL.@]
377 VOID WINAPI
RtlReleasePebLock(void)
379 RtlLeaveCriticalSection( &peb_lock
);
382 /******************************************************************************
383 * RtlNewSecurityObject [NTDLL.@]
386 RtlNewSecurityObject( PSECURITY_DESCRIPTOR ParentDescriptor
,
387 PSECURITY_DESCRIPTOR CreatorDescriptor
,
388 PSECURITY_DESCRIPTOR
*NewDescriptor
,
389 BOOLEAN IsDirectoryObject
,
391 PGENERIC_MAPPING GenericMapping
)
393 FIXME("(%p %p %p %d %p %p) stub!\n", ParentDescriptor
, CreatorDescriptor
,
394 NewDescriptor
, IsDirectoryObject
, Token
, GenericMapping
);
395 return STATUS_NOT_IMPLEMENTED
;
398 /******************************************************************************
399 * RtlDeleteSecurityObject [NTDLL.@]
402 RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR
*ObjectDescriptor
)
404 FIXME("(%p) stub!\n", ObjectDescriptor
);
405 return STATUS_NOT_IMPLEMENTED
;
408 /******************************************************************************
409 * RtlInitializeGenericTable [NTDLL.@]
411 PVOID WINAPI
RtlInitializeGenericTable(PVOID pTable
, PVOID arg2
, PVOID arg3
, PVOID arg4
, PVOID arg5
)
413 FIXME("(%p,%p,%p,%p,%p) stub!\n", pTable
, arg2
, arg3
, arg4
, arg5
);
417 /******************************************************************************
418 * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
420 PVOID
RtlEnumerateGenericTableWithoutSplaying(PVOID pTable
, PVOID
*RestartKey
)
422 static int warn_once
;
425 FIXME("(%p,%p) stub!\n", pTable
, RestartKey
);
429 /******************************************************************************
430 * RtlNumberGenericTableElements [NTDLL.@]
432 ULONG
RtlNumberGenericTableElements(PVOID pTable
)
434 FIXME("(%p) stub!\n", pTable
);
438 /******************************************************************************
439 * RtlMoveMemory [NTDLL.@]
441 * Move a block of memory that may overlap.
444 * Destination [O] End destination for block
445 * Source [O] Where to start copying from
446 * Length [I] Number of bytes to copy
452 VOID WINAPI
RtlMoveMemory( VOID
*Destination
, CONST VOID
*Source
, SIZE_T Length
)
454 memmove(Destination
, Source
, Length
);
457 /******************************************************************************
458 * RtlFillMemory [NTDLL.@]
460 * Set a block of memory with a value.
463 * Destination [O] Block to fill
464 * Length [I] Number of bytes to fill
465 * Fill [I] Value to set
471 VOID WINAPI
RtlFillMemory( VOID
*Destination
, SIZE_T Length
, BYTE Fill
)
473 memset(Destination
, Fill
, Length
);
476 /******************************************************************************
477 * RtlZeroMemory [NTDLL.@]
479 * Set a block of memory with 0's.
482 * Destination [O] Block to fill
483 * Length [I] Number of bytes to fill
489 VOID WINAPI
RtlZeroMemory( VOID
*Destination
, SIZE_T Length
)
491 memset(Destination
, 0, Length
);
494 /******************************************************************************
495 * RtlCompareMemory [NTDLL.@]
497 * Compare one block of memory with another
500 * Source1 [I] Source block
501 * Source2 [I] Block to compare to Source1
502 * Length [I] Number of bytes to compare
505 * The length of the first byte at which Source1 and Source2 differ, or Length
506 * if they are the same.
508 SIZE_T WINAPI
RtlCompareMemory( const VOID
*Source1
, const VOID
*Source2
, SIZE_T Length
)
511 for(i
=0; (i
<Length
) && (((const BYTE
*)Source1
)[i
]==((const BYTE
*)Source2
)[i
]); i
++);
515 /******************************************************************************
516 * RtlCompareMemoryUlong [NTDLL.@]
518 * Compare a block of memory with a value, a ULONG at a time
521 * Source1 [I] Source block. This must be ULONG aligned
522 * Length [I] Number of bytes to compare. This should be a multiple of 4
523 * dwVal [I] Value to compare to
526 * The byte position of the first byte at which Source1 is not dwVal.
528 SIZE_T WINAPI
RtlCompareMemoryUlong(const ULONG
*Source1
, SIZE_T Length
, ULONG dwVal
)
531 for(i
= 0; i
< Length
/sizeof(ULONG
) && Source1
[i
] == dwVal
; i
++);
532 return i
* sizeof(ULONG
);
535 /******************************************************************************
536 * RtlAssert [NTDLL.@]
538 * Fail a debug assertion.
541 * Nothing. This call does not return control to its caller.
544 * Not implemented in non-debug versions.
546 void WINAPI
RtlAssert(LPVOID x1
,LPVOID x2
,DWORD x3
, DWORD x4
)
548 FIXME("(%p,%p,0x%08x,0x%08x),stub\n",x1
,x2
,x3
,x4
);
551 /*************************************************************************
552 * RtlFillMemoryUlong [NTDLL.@]
554 * Fill memory with a 32 bit (dword) value.
557 * lpDest [I] Bitmap pointer
558 * ulCount [I] Number of dwords to write
559 * ulValue [I] Value to fill with
564 VOID WINAPI
RtlFillMemoryUlong(ULONG
* lpDest
, ULONG ulCount
, ULONG ulValue
)
566 TRACE("(%p,%d,%d)\n", lpDest
, ulCount
, ulValue
);
568 ulCount
/= sizeof(ULONG
);
573 /*********************************************************************
574 * RtlComputeCrc32 [NTDLL.@]
576 * Calculate the CRC32 checksum of a block of bytes
579 * dwInitial [I] Initial CRC value
580 * pData [I] Data block
581 * iLen [I] Length of the byte block
584 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
586 DWORD WINAPI
RtlComputeCrc32(DWORD dwInitial
, const BYTE
*pData
, INT iLen
)
588 DWORD crc
= ~dwInitial
;
590 TRACE("(%d,%p,%d)\n", dwInitial
, pData
, iLen
);
594 crc
= CRC_table
[(crc
^ *pData
) & 0xff] ^ (crc
>> 8);
602 /*************************************************************************
603 * RtlUlonglongByteSwap [NTDLL.@]
605 * Swap the bytes of an unsigned long long value.
608 * i [I] Value to swap bytes of
611 * The value with its bytes swapped.
613 ULONGLONG __cdecl
RtlUlonglongByteSwap(ULONGLONG i
)
615 return ((ULONGLONG
)RtlUlongByteSwap(i
) << 32) | RtlUlongByteSwap(i
>>32);
618 /*************************************************************************
619 * RtlUlongByteSwap [NTDLL.@]
621 * Swap the bytes of an unsigned int value.
624 * ix86 version takes argument in %ecx. Other systems use the inline version.
627 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap
,
633 /*************************************************************************
634 * RtlUshortByteSwap [NTDLL.@]
636 * Swap the bytes of an unsigned short value.
639 * i386 version takes argument in %cx. Other systems use the inline version.
642 __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap
,
649 /*************************************************************************
650 * RtlUniform [NTDLL.@]
652 * Generates an uniform random number
655 * seed [O] The seed of the Random function
658 * It returns a random number uniformly distributed over [0..MAXLONG-1].
661 * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
662 * In our case the algorithm is:
664 *| result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
669 * The native documentation states that the random number is
670 * uniformly distributed over [0..MAXLONG]. In reality the native
671 * function and our function return a random number uniformly
672 * distributed over [0..MAXLONG-1].
674 ULONG WINAPI
RtlUniform (PULONG seed
)
679 * Instead of the algorithm stated above, we use the algorithm
680 * below, which is totally equivalent (see the tests), but does
681 * not use a division and therefore is faster.
683 result
= *seed
* 0xffffffed + 0x7fffffc3;
684 if (result
== 0xffffffff || result
== 0x7ffffffe) {
685 result
= (result
+ 2) & MAXLONG
;
686 } else if (result
== 0x7fffffff) {
688 } else if ((result
& 0x80000000) == 0) {
689 result
= result
+ (~result
& 1);
691 result
= (result
+ (result
& 1)) & MAXLONG
;
698 /*************************************************************************
699 * RtlRandom [NTDLL.@]
701 * Generates a random number
704 * seed [O] The seed of the Random function
707 * It returns a random number distributed over [0..MAXLONG-1].
709 ULONG WINAPI
RtlRandom (PULONG seed
)
711 static ULONG saved_value
[128] =
712 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
713 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
714 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
715 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
716 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
717 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
718 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
719 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
720 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
721 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
722 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
723 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
724 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
725 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
726 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
727 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
732 rand
= (*seed
* 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
733 *seed
= (rand
* 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
735 result
= saved_value
[pos
];
736 saved_value
[pos
] = rand
;
741 /*************************************************************************
742 * RtlAreAllAccessesGranted [NTDLL.@]
744 * Check if all desired accesses are granted
747 * TRUE: All desired accesses are granted
750 BOOLEAN WINAPI
RtlAreAllAccessesGranted(
751 ACCESS_MASK GrantedAccess
,
752 ACCESS_MASK DesiredAccess
)
754 return (GrantedAccess
& DesiredAccess
) == DesiredAccess
;
758 /*************************************************************************
759 * RtlAreAnyAccessesGranted [NTDLL.@]
761 * Check if at least one of the desired accesses is granted
764 * GrantedAccess [I] Access mask of granted accesses
765 * DesiredAccess [I] Access mask of desired accesses
768 * TRUE: At least one of the desired accesses is granted
771 BOOLEAN WINAPI
RtlAreAnyAccessesGranted(
772 ACCESS_MASK GrantedAccess
,
773 ACCESS_MASK DesiredAccess
)
775 return (GrantedAccess
& DesiredAccess
) != 0;
779 /*************************************************************************
780 * RtlMapGenericMask [NTDLL.@]
782 * Determine the nongeneric access rights specified by an access mask
787 void WINAPI
RtlMapGenericMask(
788 PACCESS_MASK AccessMask
,
789 const GENERIC_MAPPING
*GenericMapping
)
791 if (*AccessMask
& GENERIC_READ
) {
792 *AccessMask
|= GenericMapping
->GenericRead
;
795 if (*AccessMask
& GENERIC_WRITE
) {
796 *AccessMask
|= GenericMapping
->GenericWrite
;
799 if (*AccessMask
& GENERIC_EXECUTE
) {
800 *AccessMask
|= GenericMapping
->GenericExecute
;
803 if (*AccessMask
& GENERIC_ALL
) {
804 *AccessMask
|= GenericMapping
->GenericAll
;
807 *AccessMask
&= 0x0FFFFFFF;
811 /*************************************************************************
812 * RtlCopyLuid [NTDLL.@]
814 * Copy a local unique ID.
817 * LuidDest [O] Destination for the copied Luid
818 * LuidSrc [I] Source Luid to copy to LuidDest
823 void WINAPI
RtlCopyLuid (PLUID LuidDest
, const LUID
*LuidSrc
)
825 *LuidDest
= *LuidSrc
;
829 /*************************************************************************
830 * RtlEqualLuid [NTDLL.@]
832 * Compare two local unique IDs.
835 * Luid1 [I] First Luid to compare to Luid2
836 * Luid2 [I] Second Luid to compare to Luid1
839 * TRUE: The two LUIDs are equal.
842 BOOLEAN WINAPI
RtlEqualLuid (const LUID
*Luid1
, const LUID
*Luid2
)
844 return (Luid1
->LowPart
== Luid2
->LowPart
&& Luid1
->HighPart
== Luid2
->HighPart
);
848 /*************************************************************************
849 * RtlCopyLuidAndAttributesArray [NTDLL.@]
851 * Copy an array of local unique IDs and attributes.
854 * Count [I] Number of Luid/attributes in Src
855 * Src [I] Source Luid/attributes to copy
856 * Dest [O] Destination for copied Luid/attributes
862 * Dest must be large enough to hold Src.
864 void WINAPI
RtlCopyLuidAndAttributesArray(
866 const LUID_AND_ATTRIBUTES
*Src
,
867 PLUID_AND_ATTRIBUTES Dest
)
871 for (i
= 0; i
< Count
; i
++) Dest
[i
] = Src
[i
];
874 NTSTATUS WINAPI
RtlIpv4StringToAddressExW(PULONG IP
, PULONG Port
,
875 LPCWSTR Buffer
, PULONG MaxSize
)
877 FIXME("(%p,%p,%p,%p): stub\n", IP
, Port
, Buffer
, MaxSize
);
879 return STATUS_SUCCESS
;
882 /***********************************************************************
883 * RtlIpv4AddressToStringExW [NTDLL.@]
885 * Convert the given ipv4 address and optional the port to a string
888 * pin [I] PTR to the ip address to convert (network byte order)
889 * port [I] optional port to convert (network byte order)
890 * buffer [O] destination buffer for the result
891 * psize [IO] PTR to available/used size of the destination buffer
894 * Success: STATUS_SUCCESS
895 * Failure: STATUS_INVALID_PARAMETER
898 NTSTATUS WINAPI
RtlIpv4AddressToStringExW(const IN_ADDR
*pin
, USHORT port
, LPWSTR buffer
, PULONG psize
)
901 static const WCHAR fmt_ip
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
902 static const WCHAR fmt_port
[] = {':','%','u',0};
905 if (!pin
|| !buffer
|| !psize
)
906 return STATUS_INVALID_PARAMETER
;
908 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin
, pin
->S_un
.S_addr
, port
, buffer
, psize
, *psize
);
910 needed
= sprintfW(tmp_ip
, fmt_ip
,
911 pin
->S_un
.S_un_b
.s_b1
, pin
->S_un
.S_un_b
.s_b2
,
912 pin
->S_un
.S_un_b
.s_b3
, pin
->S_un
.S_un_b
.s_b4
);
914 if (port
) needed
+= sprintfW(tmp_ip
+ needed
, fmt_port
, ntohs(port
));
916 if (*psize
> needed
) {
918 strcpyW(buffer
, tmp_ip
);
919 return STATUS_SUCCESS
;
923 return STATUS_INVALID_PARAMETER
;
926 /***********************************************************************
927 * RtlIpv4AddressToStringExA [NTDLL.@]
929 * Convert the given ipv4 address and optional the port to a string
931 * See RtlIpv4AddressToStringExW
933 NTSTATUS WINAPI
RtlIpv4AddressToStringExA(const IN_ADDR
*pin
, USHORT port
, LPSTR buffer
, PULONG psize
)
938 if (!pin
|| !buffer
|| !psize
)
939 return STATUS_INVALID_PARAMETER
;
941 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin
, pin
->S_un
.S_addr
, port
, buffer
, psize
, *psize
);
943 needed
= sprintf(tmp_ip
, "%u.%u.%u.%u",
944 pin
->S_un
.S_un_b
.s_b1
, pin
->S_un
.S_un_b
.s_b2
,
945 pin
->S_un
.S_un_b
.s_b3
, pin
->S_un
.S_un_b
.s_b4
);
947 if (port
) needed
+= sprintf(tmp_ip
+ needed
, ":%u", ntohs(port
));
949 if (*psize
> needed
) {
951 strcpy(buffer
, tmp_ip
);
952 return STATUS_SUCCESS
;
956 return STATUS_INVALID_PARAMETER
;
959 /***********************************************************************
960 * RtlIpv4AddressToStringW [NTDLL.@]
962 * Convert the given ipv4 address to a string
965 * pin [I] PTR to the ip address to convert (network byte order)
966 * buffer [O] destination buffer for the result (at least 16 character)
969 * PTR to the 0 character at the end of the converted string
972 WCHAR
* WINAPI
RtlIpv4AddressToStringW(const IN_ADDR
*pin
, LPWSTR buffer
)
976 if (RtlIpv4AddressToStringExW(pin
, 0, buffer
, &size
)) size
= 0;
977 return buffer
+ size
- 1;
980 /***********************************************************************
981 * RtlIpv4AddressToStringA [NTDLL.@]
983 * Convert the given ipv4 address to a string
985 * See RtlIpv4AddressToStringW
987 CHAR
* WINAPI
RtlIpv4AddressToStringA(const IN_ADDR
*pin
, LPSTR buffer
)
991 if (RtlIpv4AddressToStringExA(pin
, 0, buffer
, &size
)) size
= 0;
992 return buffer
+ size
- 1;
995 /***********************************************************************
996 * get_pointer_obfuscator (internal)
998 static DWORD_PTR
get_pointer_obfuscator( void )
1000 static DWORD_PTR pointer_obfuscator
;
1002 if (!pointer_obfuscator
)
1004 ULONG seed
= NtGetTickCount();
1007 /* generate a random value for the obfuscator */
1008 rand
= RtlUniform( &seed
);
1010 /* handle 64bit pointers */
1011 rand
^= (ULONG_PTR
)RtlUniform( &seed
) << ((sizeof (DWORD_PTR
) - sizeof (ULONG
))*8);
1013 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1014 rand
|= (ULONG_PTR
)0xc0000000 << ((sizeof (DWORD_PTR
) - sizeof (ULONG
))*8);
1016 interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator
, (void*) rand
, NULL
);
1019 return pointer_obfuscator
;
1022 /*************************************************************************
1023 * RtlEncodePointer [NTDLL.@]
1025 PVOID WINAPI
RtlEncodePointer( PVOID ptr
)
1027 DWORD_PTR ptrval
= (DWORD_PTR
) ptr
;
1028 return (PVOID
)(ptrval
^ get_pointer_obfuscator());
1031 PVOID WINAPI
RtlDecodePointer( PVOID ptr
)
1033 DWORD_PTR ptrval
= (DWORD_PTR
) ptr
;
1034 return (PVOID
)(ptrval
^ get_pointer_obfuscator());
1037 /*************************************************************************
1038 * RtlInitializeSListHead [NTDLL.@]
1040 VOID WINAPI
RtlInitializeSListHead(PSLIST_HEADER list
)
1043 list
->s
.Alignment
= list
->s
.Region
= 0;
1044 list
->Header16
.HeaderType
= 1; /* we use the 16-byte header */
1046 list
->Alignment
= 0;
1050 /*************************************************************************
1051 * RtlQueryDepthSList [NTDLL.@]
1053 WORD WINAPI
RtlQueryDepthSList(PSLIST_HEADER list
)
1056 return list
->Header16
.Depth
;
1058 return list
->s
.Depth
;
1062 /*************************************************************************
1063 * RtlFirstEntrySList [NTDLL.@]
1065 PSLIST_ENTRY WINAPI
RtlFirstEntrySList(const SLIST_HEADER
* list
)
1068 return (SLIST_ENTRY
*)((ULONG_PTR
)list
->Header16
.NextEntry
<< 4);
1070 return list
->s
.Next
.Next
;
1074 /*************************************************************************
1075 * RtlInterlockedFlushSList [NTDLL.@]
1077 PSLIST_ENTRY WINAPI
RtlInterlockedFlushSList(PSLIST_HEADER list
)
1079 SLIST_HEADER old
, new;
1082 if (!list
->Header16
.Depth
) return NULL
;
1083 new.s
.Alignment
= new.s
.Region
= 0;
1084 new.Header16
.HeaderType
= 1; /* we use the 16-byte header */
1088 new.Header16
.Sequence
= old
.Header16
.Sequence
+ 1;
1089 } while (!interlocked_cmpxchg128((__int64
*)list
, new.s
.Region
, new.s
.Alignment
, (__int64
*)&old
));
1090 return (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1092 if (!list
->s
.Depth
) return NULL
;
1097 new.s
.Sequence
= old
.s
.Sequence
+ 1;
1098 } while (interlocked_cmpxchg64((__int64
*)&list
->Alignment
, new.Alignment
,
1099 old
.Alignment
) != old
.Alignment
);
1100 return old
.s
.Next
.Next
;
1104 /*************************************************************************
1105 * RtlInterlockedPushEntrySList [NTDLL.@]
1107 PSLIST_ENTRY WINAPI
RtlInterlockedPushEntrySList(PSLIST_HEADER list
, PSLIST_ENTRY entry
)
1109 SLIST_HEADER old
, new;
1112 new.Header16
.NextEntry
= (ULONG_PTR
)entry
>> 4;
1116 entry
->Next
= (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1117 new.Header16
.Depth
= old
.Header16
.Depth
+ 1;
1118 new.Header16
.Sequence
= old
.Header16
.Sequence
+ 1;
1119 } while (!interlocked_cmpxchg128((__int64
*)list
, new.s
.Region
, new.s
.Alignment
, (__int64
*)&old
));
1120 return (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1122 new.s
.Next
.Next
= entry
;
1126 entry
->Next
= old
.s
.Next
.Next
;
1127 new.s
.Depth
= old
.s
.Depth
+ 1;
1128 new.s
.Sequence
= old
.s
.Sequence
+ 1;
1129 } while (interlocked_cmpxchg64((__int64
*)&list
->Alignment
, new.Alignment
,
1130 old
.Alignment
) != old
.Alignment
);
1131 return old
.s
.Next
.Next
;
1135 /*************************************************************************
1136 * RtlInterlockedPopEntrySList [NTDLL.@]
1138 PSLIST_ENTRY WINAPI
RtlInterlockedPopEntrySList(PSLIST_HEADER list
)
1140 SLIST_HEADER old
, new;
1147 if (!(entry
= (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4))) return NULL
;
1148 /* entry could be deleted by another thread */
1151 new.Header16
.NextEntry
= (ULONG_PTR
)entry
->Next
>> 4;
1152 new.Header16
.Depth
= old
.Header16
.Depth
- 1;
1153 new.Header16
.Sequence
= old
.Header16
.Sequence
+ 1;
1159 } while (!interlocked_cmpxchg128((__int64
*)list
, new.s
.Region
, new.s
.Alignment
, (__int64
*)&old
));
1164 if (!(entry
= old
.s
.Next
.Next
)) return NULL
;
1165 /* entry could be deleted by another thread */
1168 new.s
.Next
.Next
= entry
->Next
;
1169 new.s
.Depth
= old
.s
.Depth
- 1;
1170 new.s
.Sequence
= old
.s
.Sequence
+ 1;
1176 } while (interlocked_cmpxchg64((__int64
*)&list
->Alignment
, new.Alignment
,
1177 old
.Alignment
) != old
.Alignment
);
1182 /*************************************************************************
1183 * RtlInterlockedPushListSList [NTDLL.@]
1185 PSLIST_ENTRY WINAPI
RtlInterlockedPushListSList(PSLIST_HEADER list
, PSLIST_ENTRY first
,
1186 PSLIST_ENTRY last
, ULONG count
)
1188 SLIST_HEADER old
, new;
1191 new.Header16
.NextEntry
= (ULONG_PTR
)first
>> 4;
1195 new.Header16
.Depth
= old
.Header16
.Depth
+ count
;
1196 new.Header16
.Sequence
= old
.Header16
.Sequence
+ 1;
1197 last
->Next
= (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1198 } while (!interlocked_cmpxchg128((__int64
*)list
, new.s
.Region
, new.s
.Alignment
, (__int64
*)&old
));
1199 return (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1201 new.s
.Next
.Next
= first
;
1205 new.s
.Depth
= old
.s
.Depth
+ count
;
1206 new.s
.Sequence
= old
.s
.Sequence
+ 1;
1207 last
->Next
= old
.s
.Next
.Next
;
1208 } while (interlocked_cmpxchg64((__int64
*)&list
->Alignment
, new.Alignment
,
1209 old
.Alignment
) != old
.Alignment
);
1210 return old
.s
.Next
.Next
;
1214 /******************************************************************************
1215 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1217 NTSTATUS WINAPI
RtlGetCompressionWorkSpaceSize(USHORT CompressionFormatAndEngine
,
1218 PULONG CompressBufferWorkSpaceSize
,
1219 PULONG CompressFragmentWorkSpaceSize
)
1221 FIXME("0x%04x, %p, %p: stub!\n", CompressionFormatAndEngine
, CompressBufferWorkSpaceSize
,
1222 CompressFragmentWorkSpaceSize
);
1224 return STATUS_NOT_IMPLEMENTED
;
1227 /******************************************************************************
1228 * RtlCompressBuffer [NTDLL.@]
1230 NTSTATUS WINAPI
RtlCompressBuffer(USHORT CompressionFormatAndEngine
, PUCHAR UncompressedBuffer
,
1231 ULONG UncompressedBufferSize
, PUCHAR CompressedBuffer
,
1232 ULONG CompressedBufferSize
, ULONG UncompressedChunkSize
,
1233 PULONG FinalCompressedSize
, PVOID WorkSpace
)
1235 FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p :stub\n", CompressionFormatAndEngine
, UncompressedBuffer
,
1236 UncompressedBufferSize
, CompressedBuffer
, CompressedBufferSize
, UncompressedChunkSize
,
1237 FinalCompressedSize
, WorkSpace
);
1239 return STATUS_NOT_IMPLEMENTED
;
1242 /******************************************************************************
1243 * RtlDecompressBuffer [NTDLL.@]
1245 NTSTATUS WINAPI
RtlDecompressBuffer(USHORT CompressionFormat
, PUCHAR UncompressedBuffer
,
1246 ULONG UncompressedBufferSize
, PUCHAR CompressedBuffer
,
1247 ULONG CompressedBufferSize
, PULONG FinalUncompressedSize
)
1249 FIXME("0x%04x, %p, %u, %p, %u, %p :stub\n", CompressionFormat
, UncompressedBuffer
, UncompressedBufferSize
,
1250 CompressedBuffer
, CompressedBufferSize
, FinalUncompressedSize
);
1252 return STATUS_NOT_IMPLEMENTED
;
1255 /***********************************************************************
1256 * RtlSetThreadErrorMode [NTDLL.@]
1258 * Set the thread local error mode.
1261 * mode [I] The new error mode
1262 * oldmode [O] Destination of the old error mode (may be NULL)
1265 * Success: STATUS_SUCCESS
1266 * Failure: STATUS_INVALID_PARAMETER_1
1268 NTSTATUS WINAPI
RtlSetThreadErrorMode( DWORD mode
, LPDWORD oldmode
)
1271 return STATUS_INVALID_PARAMETER_1
;
1274 *oldmode
= NtCurrentTeb()->HardErrorDisabled
;
1276 NtCurrentTeb()->HardErrorDisabled
= mode
;
1277 return STATUS_SUCCESS
;
1280 /***********************************************************************
1281 * RtlGetThreadErrorMode [NTDLL.@]
1283 * Get the thread local error mode.
1289 * The current thread local error mode.
1291 DWORD WINAPI
RtlGetThreadErrorMode( void )
1293 return NtCurrentTeb()->HardErrorDisabled
;
1296 /******************************************************************************
1297 * RtlGetCurrentTransaction [NTDLL.@]
1299 HANDLE WINAPI
RtlGetCurrentTransaction(void)
1301 FIXME("() :stub\n");
1305 /******************************************************************************
1306 * RtlSetCurrentTransaction [NTDLL.@]
1308 BOOL WINAPI
RtlSetCurrentTransaction(HANDLE new_transaction
)
1310 FIXME("(%p) :stub\n", new_transaction
);