ntdll: Add stub for RtlGetUnloadEventTraceEx.
[wine.git] / dlls / ntdll / rtl.c
blob393bd27b1aef63f0fa4f4e4227e1d2bc858394c8
1 /*
2 * NT basis DLL
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
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdlib.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <string.h>
33 #ifdef HAVE_NETINET_IN_H
34 #include <netinet/in.h>
35 #endif
36 #include "ntstatus.h"
37 #define NONAMELESSUNION
38 #define NONAMELESSSTRUCT
39 #define WIN32_NO_STATUS
40 #define USE_WS_PREFIX
41 #include "windef.h"
42 #include "winternl.h"
43 #include "wine/debug.h"
44 #include "wine/exception.h"
45 #include "wine/unicode.h"
46 #include "ntdll_misc.h"
47 #include "inaddr.h"
48 #include "in6addr.h"
49 #include "ddk/ntddk.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
53 #ifdef __i386__
54 #define DEFINE_FASTCALL4_ENTRYPOINT( name ) \
55 __ASM_STDCALL_FUNC( name, 16, \
56 "popl %eax\n\t" \
57 "pushl %edx\n\t" \
58 "pushl %ecx\n\t" \
59 "pushl %eax\n\t" \
60 "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(16))
61 #endif
63 /* CRC polynomial 0xedb88320 */
64 static const DWORD CRC_table[256] =
66 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
67 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
68 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
69 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
70 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
71 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
72 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
73 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
74 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
75 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
76 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
77 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
78 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
79 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
80 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
81 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
82 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
83 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
84 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
85 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
86 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
87 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
88 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
89 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
90 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
91 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
92 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
93 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
94 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
95 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
96 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
97 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
98 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
99 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
100 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
101 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
102 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
103 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
104 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
105 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
106 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
107 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
108 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
112 * resource functions
115 /***********************************************************************
116 * RtlInitializeResource (NTDLL.@)
118 * xxxResource() functions implement multiple-reader-single-writer lock.
119 * The code is based on information published in WDJ January 1999 issue.
121 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
123 if( rwl )
125 rwl->iNumberActive = 0;
126 rwl->uExclusiveWaiters = 0;
127 rwl->uSharedWaiters = 0;
128 rwl->hOwningThreadId = 0;
129 rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
130 RtlInitializeCriticalSection( &rwl->rtlCS );
131 rwl->rtlCS.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RTL_RWLOCK.rtlCS");
132 NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
133 NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
138 /***********************************************************************
139 * RtlDeleteResource (NTDLL.@)
141 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
143 if( rwl )
145 RtlEnterCriticalSection( &rwl->rtlCS );
146 if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
147 ERR("Deleting active MRSW lock (%p), expect failure\n", rwl );
148 rwl->hOwningThreadId = 0;
149 rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
150 rwl->iNumberActive = 0;
151 NtClose( rwl->hExclusiveReleaseSemaphore );
152 NtClose( rwl->hSharedReleaseSemaphore );
153 RtlLeaveCriticalSection( &rwl->rtlCS );
154 rwl->rtlCS.DebugInfo->Spare[0] = 0;
155 RtlDeleteCriticalSection( &rwl->rtlCS );
160 /***********************************************************************
161 * RtlAcquireResourceExclusive (NTDLL.@)
163 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
165 BYTE retVal = 0;
166 if( !rwl ) return 0;
168 start:
169 RtlEnterCriticalSection( &rwl->rtlCS );
170 if( rwl->iNumberActive == 0 ) /* lock is free */
172 rwl->iNumberActive = -1;
173 retVal = 1;
175 else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
177 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
179 retVal = 1;
180 rwl->iNumberActive--;
181 goto done;
183 wait:
184 if( fWait )
186 NTSTATUS status;
188 rwl->uExclusiveWaiters++;
190 RtlLeaveCriticalSection( &rwl->rtlCS );
191 status = NtWaitForSingleObject( rwl->hExclusiveReleaseSemaphore, FALSE, NULL );
192 if( HIWORD(status) )
193 goto done;
194 goto start; /* restart the acquisition to avoid deadlocks */
197 else /* one or more shared locks are in progress */
198 if( fWait )
199 goto wait;
201 if( retVal == 1 )
202 rwl->hOwningThreadId = ULongToHandle(GetCurrentThreadId());
203 done:
204 RtlLeaveCriticalSection( &rwl->rtlCS );
205 return retVal;
208 /***********************************************************************
209 * RtlAcquireResourceShared (NTDLL.@)
211 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
213 NTSTATUS status = STATUS_UNSUCCESSFUL;
214 BYTE retVal = 0;
215 if( !rwl ) return 0;
217 start:
218 RtlEnterCriticalSection( &rwl->rtlCS );
219 if( rwl->iNumberActive < 0 )
221 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
223 rwl->iNumberActive--;
224 retVal = 1;
225 goto done;
228 if( fWait )
230 rwl->uSharedWaiters++;
231 RtlLeaveCriticalSection( &rwl->rtlCS );
232 status = NtWaitForSingleObject( rwl->hSharedReleaseSemaphore, FALSE, NULL );
233 if( HIWORD(status) )
234 goto done;
235 goto start;
238 else
240 if( status != STATUS_WAIT_0 ) /* otherwise RtlReleaseResource() has already done it */
241 rwl->iNumberActive++;
242 retVal = 1;
244 done:
245 RtlLeaveCriticalSection( &rwl->rtlCS );
246 return retVal;
250 /***********************************************************************
251 * RtlReleaseResource (NTDLL.@)
253 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
255 RtlEnterCriticalSection( &rwl->rtlCS );
257 if( rwl->iNumberActive > 0 ) /* have one or more readers */
259 if( --rwl->iNumberActive == 0 )
261 if( rwl->uExclusiveWaiters )
263 wake_exclusive:
264 rwl->uExclusiveWaiters--;
265 NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
269 else
270 if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
272 if( ++rwl->iNumberActive == 0 )
274 rwl->hOwningThreadId = 0;
275 if( rwl->uExclusiveWaiters )
276 goto wake_exclusive;
277 else
278 if( rwl->uSharedWaiters )
280 UINT n = rwl->uSharedWaiters;
281 rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
282 * all queued readers have done their thing */
283 rwl->uSharedWaiters = 0;
284 NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
288 RtlLeaveCriticalSection( &rwl->rtlCS );
292 /***********************************************************************
293 * RtlDumpResource (NTDLL.@)
295 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
297 if( rwl )
299 MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
300 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
301 if( rwl->iNumberActive )
302 MESSAGE("\towner thread = %p\n", rwl->hOwningThreadId );
307 * misc functions
310 /******************************************************************************
311 * DbgPrint [NTDLL.@]
313 NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...)
315 char buf[512];
316 __ms_va_list args;
318 __ms_va_start(args, fmt);
319 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
320 __ms_va_end(args);
322 MESSAGE("DbgPrint says: %s",buf);
323 /* hmm, raise exception? */
324 return STATUS_SUCCESS;
328 /******************************************************************************
329 * DbgPrintEx [NTDLL.@]
331 NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...)
333 NTSTATUS ret;
334 __ms_va_list args;
336 __ms_va_start(args, fmt);
337 ret = vDbgPrintEx(iComponentId, Level, fmt, args);
338 __ms_va_end(args);
339 return ret;
342 /******************************************************************************
343 * vDbgPrintEx [NTDLL.@]
345 NTSTATUS WINAPI vDbgPrintEx( ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
347 return vDbgPrintExWithPrefix( "", id, level, fmt, args );
350 /******************************************************************************
351 * vDbgPrintExWithPrefix [NTDLL.@]
353 NTSTATUS WINAPI vDbgPrintExWithPrefix( LPCSTR prefix, ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
355 char buf[1024];
357 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
359 switch (level & DPFLTR_MASK)
361 case DPFLTR_ERROR_LEVEL: ERR("%s%x: %s", prefix, id, buf); break;
362 case DPFLTR_WARNING_LEVEL: WARN("%s%x: %s", prefix, id, buf); break;
363 case DPFLTR_TRACE_LEVEL:
364 case DPFLTR_INFO_LEVEL:
365 default: TRACE("%s%x: %s", prefix, id, buf); break;
367 return STATUS_SUCCESS;
370 /******************************************************************************
371 * RtlAcquirePebLock [NTDLL.@]
373 VOID WINAPI RtlAcquirePebLock(void)
375 RtlEnterCriticalSection( NtCurrentTeb()->Peb->FastPebLock );
378 /******************************************************************************
379 * RtlReleasePebLock [NTDLL.@]
381 VOID WINAPI RtlReleasePebLock(void)
383 RtlLeaveCriticalSection( NtCurrentTeb()->Peb->FastPebLock );
386 /******************************************************************************
387 * RtlNewSecurityObject [NTDLL.@]
389 NTSTATUS WINAPI
390 RtlNewSecurityObject( PSECURITY_DESCRIPTOR ParentDescriptor,
391 PSECURITY_DESCRIPTOR CreatorDescriptor,
392 PSECURITY_DESCRIPTOR *NewDescriptor,
393 BOOLEAN IsDirectoryObject,
394 HANDLE Token,
395 PGENERIC_MAPPING GenericMapping )
397 FIXME("(%p %p %p %d %p %p) stub!\n", ParentDescriptor, CreatorDescriptor,
398 NewDescriptor, IsDirectoryObject, Token, GenericMapping);
399 return STATUS_NOT_IMPLEMENTED;
402 /******************************************************************************
403 * RtlDeleteSecurityObject [NTDLL.@]
405 NTSTATUS WINAPI
406 RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR *ObjectDescriptor )
408 FIXME("(%p) stub!\n", ObjectDescriptor);
409 return STATUS_NOT_IMPLEMENTED;
412 /******************************************************************************
413 * RtlInitializeGenericTable [NTDLL.@]
415 PVOID WINAPI RtlInitializeGenericTable(PVOID pTable, PVOID arg2, PVOID arg3, PVOID arg4, PVOID arg5)
417 FIXME("(%p,%p,%p,%p,%p) stub!\n", pTable, arg2, arg3, arg4, arg5);
418 return NULL;
421 /******************************************************************************
422 * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
424 PVOID RtlEnumerateGenericTableWithoutSplaying(PVOID pTable, PVOID *RestartKey)
426 static int warn_once;
428 if (!warn_once++)
429 FIXME("(%p,%p) stub!\n", pTable, RestartKey);
430 return NULL;
433 /******************************************************************************
434 * RtlNumberGenericTableElements [NTDLL.@]
436 ULONG RtlNumberGenericTableElements(PVOID pTable)
438 FIXME("(%p) stub!\n", pTable);
439 return 0;
442 /******************************************************************************
443 * RtlMoveMemory [NTDLL.@]
445 * Move a block of memory that may overlap.
447 * PARAMS
448 * Destination [O] End destination for block
449 * Source [O] Where to start copying from
450 * Length [I] Number of bytes to copy
452 * RETURNS
453 * Nothing.
455 #undef RtlMoveMemory
456 VOID WINAPI RtlMoveMemory( void *Destination, const void *Source, SIZE_T Length )
458 memmove(Destination, Source, Length);
461 /******************************************************************************
462 * RtlFillMemory [NTDLL.@]
464 * Set a block of memory with a value.
466 * PARAMS
467 * Destination [O] Block to fill
468 * Length [I] Number of bytes to fill
469 * Fill [I] Value to set
471 * RETURNS
472 * Nothing.
474 #undef RtlFillMemory
475 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
477 memset(Destination, Fill, Length);
480 /******************************************************************************
481 * RtlZeroMemory [NTDLL.@]
483 * Set a block of memory with 0's.
485 * PARAMS
486 * Destination [O] Block to fill
487 * Length [I] Number of bytes to fill
489 * RETURNS
490 * Nothing.
492 #undef RtlZeroMemory
493 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
495 memset(Destination, 0, Length);
498 /******************************************************************************
499 * RtlCompareMemory [NTDLL.@]
501 * Compare one block of memory with another
503 * PARAMS
504 * Source1 [I] Source block
505 * Source2 [I] Block to compare to Source1
506 * Length [I] Number of bytes to compare
508 * RETURNS
509 * The length of the first byte at which Source1 and Source2 differ, or Length
510 * if they are the same.
512 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
514 SIZE_T i;
515 for(i=0; (i<Length) && (((const BYTE*)Source1)[i]==((const BYTE*)Source2)[i]); i++);
516 return i;
519 /******************************************************************************
520 * RtlCompareMemoryUlong [NTDLL.@]
522 * Compare a block of memory with a value, a ULONG at a time
524 * PARAMS
525 * Source1 [I] Source block. This must be ULONG aligned
526 * Length [I] Number of bytes to compare. This should be a multiple of 4
527 * dwVal [I] Value to compare to
529 * RETURNS
530 * The byte position of the first byte at which Source1 is not dwVal.
532 SIZE_T WINAPI RtlCompareMemoryUlong(const ULONG *Source1, SIZE_T Length, ULONG dwVal)
534 SIZE_T i;
535 for(i = 0; i < Length/sizeof(ULONG) && Source1[i] == dwVal; i++);
536 return i * sizeof(ULONG);
539 /******************************************************************************
540 * RtlCopyMemory [NTDLL.@]
542 #undef RtlCopyMemory
543 void WINAPI RtlCopyMemory(void *dest, const void *src, SIZE_T len)
545 memcpy(dest, src, len);
548 /******************************************************************************
549 * RtlAssert [NTDLL.@]
551 * Fail a debug assertion.
553 * RETURNS
554 * Nothing. This call does not return control to its caller.
556 * NOTES
557 * Not implemented in non-debug versions.
559 void WINAPI RtlAssert(void *assertion, void *filename, ULONG linenumber, char *message)
561 FIXME("(%s, %s, %u, %s): stub\n", debugstr_a((char*)assertion), debugstr_a((char*)filename),
562 linenumber, debugstr_a(message));
565 /*************************************************************************
566 * RtlFillMemoryUlong [NTDLL.@]
568 * Fill memory with a 32 bit (dword) value.
570 * PARAMS
571 * lpDest [I] Bitmap pointer
572 * ulCount [I] Number of dwords to write
573 * ulValue [I] Value to fill with
575 * RETURNS
576 * Nothing.
578 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
580 TRACE("(%p,%d,%d)\n", lpDest, ulCount, ulValue);
582 ulCount /= sizeof(ULONG);
583 while(ulCount--)
584 *lpDest++ = ulValue;
587 /*********************************************************************
588 * RtlComputeCrc32 [NTDLL.@]
590 * Calculate the CRC32 checksum of a block of bytes
592 * PARAMS
593 * dwInitial [I] Initial CRC value
594 * pData [I] Data block
595 * iLen [I] Length of the byte block
597 * RETURNS
598 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
600 DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
602 DWORD crc = ~dwInitial;
604 TRACE("(%d,%p,%d)\n", dwInitial, pData, iLen);
606 while (iLen > 0)
608 crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
609 pData++;
610 iLen--;
612 return ~crc;
616 /*************************************************************************
617 * RtlUlonglongByteSwap [NTDLL.@]
619 * Swap the bytes of an unsigned long long value.
621 * PARAMS
622 * i [I] Value to swap bytes of
624 * RETURNS
625 * The value with its bytes swapped.
627 ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i)
629 return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32);
632 /*************************************************************************
633 * RtlUlongByteSwap [NTDLL.@]
635 * Swap the bytes of an unsigned int value.
637 * NOTES
638 * ix86 version takes argument in %ecx. Other systems use the inline version.
640 #ifdef __i386__
641 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap,
642 "movl %ecx,%eax\n\t"
643 "bswap %eax\n\t"
644 "ret")
645 #endif
647 /*************************************************************************
648 * RtlUshortByteSwap [NTDLL.@]
650 * Swap the bytes of an unsigned short value.
652 * NOTES
653 * i386 version takes argument in %cx. Other systems use the inline version.
655 #ifdef __i386__
656 __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap,
657 "movb %ch,%al\n\t"
658 "movb %cl,%ah\n\t"
659 "ret")
660 #endif
663 /*************************************************************************
664 * RtlUniform [NTDLL.@]
666 * Generates an uniform random number
668 * PARAMS
669 * seed [O] The seed of the Random function
671 * RETURNS
672 * It returns a random number uniformly distributed over [0..MAXLONG-1].
674 * NOTES
675 * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
676 * In our case the algorithm is:
678 *| result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
680 *| *seed = result;
682 * DIFFERENCES
683 * The native documentation states that the random number is
684 * uniformly distributed over [0..MAXLONG]. In reality the native
685 * function and our function return a random number uniformly
686 * distributed over [0..MAXLONG-1].
688 ULONG WINAPI RtlUniform (PULONG seed)
690 ULONG result;
693 * Instead of the algorithm stated above, we use the algorithm
694 * below, which is totally equivalent (see the tests), but does
695 * not use a division and therefore is faster.
697 result = *seed * 0xffffffed + 0x7fffffc3;
698 if (result == 0xffffffff || result == 0x7ffffffe) {
699 result = (result + 2) & MAXLONG;
700 } else if (result == 0x7fffffff) {
701 result = 0;
702 } else if ((result & 0x80000000) == 0) {
703 result = result + (~result & 1);
704 } else {
705 result = (result + (result & 1)) & MAXLONG;
706 } /* if */
707 *seed = result;
708 return result;
712 /*************************************************************************
713 * RtlRandom [NTDLL.@]
715 * Generates a random number
717 * PARAMS
718 * seed [O] The seed of the Random function
720 * RETURNS
721 * It returns a random number distributed over [0..MAXLONG-1].
723 ULONG WINAPI RtlRandom (PULONG seed)
725 static ULONG saved_value[128] =
726 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
727 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
728 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
729 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
730 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
731 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
732 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
733 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
734 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
735 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
736 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
737 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
738 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
739 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
740 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
741 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
742 ULONG rand;
743 int pos;
744 ULONG result;
746 rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
747 *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
748 pos = *seed & 0x7f;
749 result = saved_value[pos];
750 saved_value[pos] = rand;
751 return(result);
755 /*************************************************************************
756 * RtlRandomEx [NTDLL.@]
758 ULONG WINAPI RtlRandomEx( ULONG *seed )
760 WARN( "semi-stub: should use a different algorithm\n" );
761 return RtlRandom( seed );
764 /*************************************************************************
765 * RtlAreAllAccessesGranted [NTDLL.@]
767 * Check if all desired accesses are granted
769 * RETURNS
770 * TRUE: All desired accesses are granted
771 * FALSE: Otherwise
773 BOOLEAN WINAPI RtlAreAllAccessesGranted(
774 ACCESS_MASK GrantedAccess,
775 ACCESS_MASK DesiredAccess)
777 return (GrantedAccess & DesiredAccess) == DesiredAccess;
781 /*************************************************************************
782 * RtlAreAnyAccessesGranted [NTDLL.@]
784 * Check if at least one of the desired accesses is granted
786 * PARAMS
787 * GrantedAccess [I] Access mask of granted accesses
788 * DesiredAccess [I] Access mask of desired accesses
790 * RETURNS
791 * TRUE: At least one of the desired accesses is granted
792 * FALSE: Otherwise
794 BOOLEAN WINAPI RtlAreAnyAccessesGranted(
795 ACCESS_MASK GrantedAccess,
796 ACCESS_MASK DesiredAccess)
798 return (GrantedAccess & DesiredAccess) != 0;
802 /*************************************************************************
803 * RtlMapGenericMask [NTDLL.@]
805 * Determine the nongeneric access rights specified by an access mask
807 * RETURNS
808 * Nothing.
810 void WINAPI RtlMapGenericMask(
811 PACCESS_MASK AccessMask,
812 const GENERIC_MAPPING *GenericMapping)
814 if (*AccessMask & GENERIC_READ) {
815 *AccessMask |= GenericMapping->GenericRead;
816 } /* if */
818 if (*AccessMask & GENERIC_WRITE) {
819 *AccessMask |= GenericMapping->GenericWrite;
820 } /* if */
822 if (*AccessMask & GENERIC_EXECUTE) {
823 *AccessMask |= GenericMapping->GenericExecute;
824 } /* if */
826 if (*AccessMask & GENERIC_ALL) {
827 *AccessMask |= GenericMapping->GenericAll;
828 } /* if */
830 *AccessMask &= 0x0FFFFFFF;
834 /*************************************************************************
835 * RtlCopyLuid [NTDLL.@]
837 * Copy a local unique ID.
839 * PARAMS
840 * LuidDest [O] Destination for the copied Luid
841 * LuidSrc [I] Source Luid to copy to LuidDest
843 * RETURNS
844 * Nothing.
846 void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc)
848 *LuidDest = *LuidSrc;
852 /*************************************************************************
853 * RtlEqualLuid [NTDLL.@]
855 * Compare two local unique IDs.
857 * PARAMS
858 * Luid1 [I] First Luid to compare to Luid2
859 * Luid2 [I] Second Luid to compare to Luid1
861 * RETURNS
862 * TRUE: The two LUIDs are equal.
863 * FALSE: Otherwise
865 BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2)
867 return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart);
871 /*************************************************************************
872 * RtlCopyLuidAndAttributesArray [NTDLL.@]
874 * Copy an array of local unique IDs and attributes.
876 * PARAMS
877 * Count [I] Number of Luid/attributes in Src
878 * Src [I] Source Luid/attributes to copy
879 * Dest [O] Destination for copied Luid/attributes
881 * RETURNS
882 * Nothing.
884 * NOTES
885 * Dest must be large enough to hold Src.
887 void WINAPI RtlCopyLuidAndAttributesArray(
888 ULONG Count,
889 const LUID_AND_ATTRIBUTES *Src,
890 PLUID_AND_ATTRIBUTES Dest)
892 ULONG i;
894 for (i = 0; i < Count; i++) Dest[i] = Src[i];
897 /***********************************************************************
898 * RtlIpv4StringToAddressExW [NTDLL.@]
900 NTSTATUS WINAPI RtlIpv4StringToAddressExW(const WCHAR *str, BOOLEAN strict, IN_ADDR *address, USHORT *port)
902 FIXME("(%s, %u, %p, %p): stub\n", debugstr_w(str), strict, address, port);
903 return STATUS_NOT_IMPLEMENTED;
906 /***********************************************************************
907 * RtlIpv4StringToAddressW [NTDLL.@]
909 NTSTATUS WINAPI RtlIpv4StringToAddressW(const WCHAR *str, BOOLEAN strict, const WCHAR **terminator, IN_ADDR *address)
911 FIXME("(%s, %u, %p, %p): stub\n", debugstr_w(str), strict, terminator, address);
912 return STATUS_NOT_IMPLEMENTED;
915 /***********************************************************************
916 * RtlIpv6StringToAddressExW [NTDLL.@]
918 NTSTATUS NTAPI RtlIpv6StringToAddressExW(const WCHAR *str, IN6_ADDR *address, ULONG *scope, USHORT *port)
920 FIXME("(%s, %p, %p, %p): stub\n", debugstr_w(str), address, scope, port);
921 return STATUS_NOT_IMPLEMENTED;
924 /***********************************************************************
925 * RtlIpv4AddressToStringExW [NTDLL.@]
927 * Convert the given ipv4 address and optional the port to a string
929 * PARAMS
930 * pin [I] PTR to the ip address to convert (network byte order)
931 * port [I] optional port to convert (network byte order)
932 * buffer [O] destination buffer for the result
933 * psize [IO] PTR to available/used size of the destination buffer
935 * RETURNS
936 * Success: STATUS_SUCCESS
937 * Failure: STATUS_INVALID_PARAMETER
940 NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
942 WCHAR tmp_ip[32];
943 static const WCHAR fmt_ip[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
944 static const WCHAR fmt_port[] = {':','%','u',0};
945 ULONG needed;
947 if (!pin || !buffer || !psize)
948 return STATUS_INVALID_PARAMETER;
950 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
952 needed = sprintfW(tmp_ip, fmt_ip,
953 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
954 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
956 if (port) needed += sprintfW(tmp_ip + needed, fmt_port, ntohs(port));
958 if (*psize > needed) {
959 *psize = needed + 1;
960 strcpyW(buffer, tmp_ip);
961 return STATUS_SUCCESS;
964 *psize = needed + 1;
965 return STATUS_INVALID_PARAMETER;
968 /***********************************************************************
969 * RtlIpv4AddressToStringExA [NTDLL.@]
971 * Convert the given ipv4 address and optional the port to a string
973 * See RtlIpv4AddressToStringExW
975 NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
977 CHAR tmp_ip[32];
978 ULONG needed;
980 if (!pin || !buffer || !psize)
981 return STATUS_INVALID_PARAMETER;
983 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
985 needed = sprintf(tmp_ip, "%u.%u.%u.%u",
986 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
987 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
989 if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
991 if (*psize > needed) {
992 *psize = needed + 1;
993 strcpy(buffer, tmp_ip);
994 return STATUS_SUCCESS;
997 *psize = needed + 1;
998 return STATUS_INVALID_PARAMETER;
1001 /***********************************************************************
1002 * RtlIpv4AddressToStringW [NTDLL.@]
1004 * Convert the given ipv4 address to a string
1006 * PARAMS
1007 * pin [I] PTR to the ip address to convert (network byte order)
1008 * buffer [O] destination buffer for the result (at least 16 character)
1010 * RETURNS
1011 * PTR to the 0 character at the end of the converted string
1014 WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
1016 ULONG size = 16;
1018 if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
1019 return buffer + size - 1;
1022 /***********************************************************************
1023 * RtlIpv4AddressToStringA [NTDLL.@]
1025 * Convert the given ipv4 address to a string
1027 * See RtlIpv4AddressToStringW
1029 CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
1031 ULONG size = 16;
1033 if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
1034 return buffer + size - 1;
1037 /***********************************************************************
1038 * get_pointer_obfuscator (internal)
1040 static DWORD_PTR get_pointer_obfuscator( void )
1042 static DWORD_PTR pointer_obfuscator;
1044 if (!pointer_obfuscator)
1046 ULONG seed = NtGetTickCount();
1047 ULONG_PTR rand;
1049 /* generate a random value for the obfuscator */
1050 rand = RtlUniform( &seed );
1052 /* handle 64bit pointers */
1053 rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1055 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1056 rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1058 interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator, (void*) rand, NULL );
1061 return pointer_obfuscator;
1064 /*************************************************************************
1065 * RtlEncodePointer [NTDLL.@]
1067 PVOID WINAPI RtlEncodePointer( PVOID ptr )
1069 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1070 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1073 PVOID WINAPI RtlDecodePointer( PVOID ptr )
1075 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1076 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1079 /*************************************************************************
1080 * RtlInitializeSListHead [NTDLL.@]
1082 VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
1084 #ifdef _WIN64
1085 list->s.Alignment = list->s.Region = 0;
1086 list->Header16.HeaderType = 1; /* we use the 16-byte header */
1087 #else
1088 list->Alignment = 0;
1089 #endif
1092 /*************************************************************************
1093 * RtlQueryDepthSList [NTDLL.@]
1095 WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
1097 #ifdef _WIN64
1098 return list->Header16.Depth;
1099 #else
1100 return list->s.Depth;
1101 #endif
1104 /*************************************************************************
1105 * RtlFirstEntrySList [NTDLL.@]
1107 PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
1109 #ifdef _WIN64
1110 return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
1111 #else
1112 return list->s.Next.Next;
1113 #endif
1116 /*************************************************************************
1117 * RtlInterlockedFlushSList [NTDLL.@]
1119 PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
1121 SLIST_HEADER old, new;
1123 #ifdef _WIN64
1124 if (!list->Header16.NextEntry) return NULL;
1125 new.s.Alignment = new.s.Region = 0;
1126 new.Header16.HeaderType = 1; /* we use the 16-byte header */
1129 old = *list;
1130 new.Header16.Sequence = old.Header16.Sequence + 1;
1131 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1132 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1133 #else
1134 if (!list->s.Next.Next) return NULL;
1135 new.Alignment = 0;
1138 old = *list;
1139 new.s.Sequence = old.s.Sequence + 1;
1140 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1141 old.Alignment) != old.Alignment);
1142 return old.s.Next.Next;
1143 #endif
1146 /*************************************************************************
1147 * RtlInterlockedPushEntrySList [NTDLL.@]
1149 PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
1151 SLIST_HEADER old, new;
1153 #ifdef _WIN64
1154 new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
1157 old = *list;
1158 entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1159 new.Header16.Depth = old.Header16.Depth + 1;
1160 new.Header16.Sequence = old.Header16.Sequence + 1;
1161 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1162 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1163 #else
1164 new.s.Next.Next = entry;
1167 old = *list;
1168 entry->Next = old.s.Next.Next;
1169 new.s.Depth = old.s.Depth + 1;
1170 new.s.Sequence = old.s.Sequence + 1;
1171 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1172 old.Alignment) != old.Alignment);
1173 return old.s.Next.Next;
1174 #endif
1177 /*************************************************************************
1178 * RtlInterlockedPopEntrySList [NTDLL.@]
1180 PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
1182 SLIST_HEADER old, new;
1183 PSLIST_ENTRY entry;
1185 #ifdef _WIN64
1188 old = *list;
1189 if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
1190 /* entry could be deleted by another thread */
1191 __TRY
1193 new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
1194 new.Header16.Depth = old.Header16.Depth - 1;
1195 new.Header16.Sequence = old.Header16.Sequence + 1;
1197 __EXCEPT_PAGE_FAULT
1200 __ENDTRY
1201 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1202 #else
1205 old = *list;
1206 if (!(entry = old.s.Next.Next)) return NULL;
1207 /* entry could be deleted by another thread */
1208 __TRY
1210 new.s.Next.Next = entry->Next;
1211 new.s.Depth = old.s.Depth - 1;
1212 new.s.Sequence = old.s.Sequence + 1;
1214 __EXCEPT_PAGE_FAULT
1217 __ENDTRY
1218 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1219 old.Alignment) != old.Alignment);
1220 #endif
1221 return entry;
1224 /*************************************************************************
1225 * RtlInterlockedPushListSListEx [NTDLL.@]
1227 PSLIST_ENTRY WINAPI RtlInterlockedPushListSListEx(PSLIST_HEADER list, PSLIST_ENTRY first,
1228 PSLIST_ENTRY last, ULONG count)
1230 SLIST_HEADER old, new;
1232 #ifdef _WIN64
1233 new.Header16.NextEntry = (ULONG_PTR)first >> 4;
1236 old = *list;
1237 new.Header16.Depth = old.Header16.Depth + count;
1238 new.Header16.Sequence = old.Header16.Sequence + 1;
1239 last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1240 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1241 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1242 #else
1243 new.s.Next.Next = first;
1246 old = *list;
1247 new.s.Depth = old.s.Depth + count;
1248 new.s.Sequence = old.s.Sequence + 1;
1249 last->Next = old.s.Next.Next;
1250 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1251 old.Alignment) != old.Alignment);
1252 return old.s.Next.Next;
1253 #endif
1256 /*************************************************************************
1257 * RtlInterlockedPushListSList [NTDLL.@]
1259 #ifdef DEFINE_FASTCALL4_ENTRYPOINT
1260 DEFINE_FASTCALL4_ENTRYPOINT(RtlInterlockedPushListSList)
1261 PSLIST_ENTRY WINAPI DECLSPEC_HIDDEN __regs_RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1262 PSLIST_ENTRY last, ULONG count)
1263 #else
1264 PSLIST_ENTRY WINAPI RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1265 PSLIST_ENTRY last, ULONG count)
1266 #endif
1268 return RtlInterlockedPushListSListEx(list, first, last, count);
1271 /******************************************************************************
1272 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1274 NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT format, PULONG compress_workspace,
1275 PULONG decompress_workspace)
1277 FIXME("0x%04x, %p, %p: semi-stub\n", format, compress_workspace, decompress_workspace);
1279 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1281 case COMPRESSION_FORMAT_LZNT1:
1282 if (compress_workspace)
1284 /* FIXME: The current implementation of RtlCompressBuffer does not use a
1285 * workspace buffer, but Windows applications might expect a nonzero value. */
1286 *compress_workspace = 16;
1288 if (decompress_workspace)
1289 *decompress_workspace = 0x1000;
1290 return STATUS_SUCCESS;
1292 case COMPRESSION_FORMAT_NONE:
1293 case COMPRESSION_FORMAT_DEFAULT:
1294 return STATUS_INVALID_PARAMETER;
1296 default:
1297 FIXME("format %u not implemented\n", format);
1298 return STATUS_UNSUPPORTED_COMPRESSION;
1302 /* compress data using LZNT1, currently only a stub */
1303 static NTSTATUS lznt1_compress(UCHAR *src, ULONG src_size, UCHAR *dst, ULONG dst_size,
1304 ULONG chunk_size, ULONG *final_size, UCHAR *workspace)
1306 UCHAR *src_cur = src, *src_end = src + src_size;
1307 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1308 ULONG block_size;
1310 while (src_cur < src_end)
1312 /* determine size of current chunk */
1313 block_size = min(0x1000, src_end - src_cur);
1314 if (dst_cur + sizeof(WORD) + block_size > dst_end)
1315 return STATUS_BUFFER_TOO_SMALL;
1317 /* write (uncompressed) chunk header */
1318 *(WORD *)dst_cur = 0x3000 | (block_size - 1);
1319 dst_cur += sizeof(WORD);
1321 /* write chunk content */
1322 memcpy(dst_cur, src_cur, block_size);
1323 dst_cur += block_size;
1324 src_cur += block_size;
1327 if (final_size)
1328 *final_size = dst_cur - dst;
1330 return STATUS_SUCCESS;
1333 /******************************************************************************
1334 * RtlCompressBuffer [NTDLL.@]
1336 NTSTATUS WINAPI RtlCompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1337 PUCHAR compressed, ULONG compressed_size, ULONG chunk_size,
1338 PULONG final_size, PVOID workspace)
1340 FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p: semi-stub\n", format, uncompressed,
1341 uncompressed_size, compressed, compressed_size, chunk_size, final_size, workspace);
1343 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1345 case COMPRESSION_FORMAT_LZNT1:
1346 return lznt1_compress(uncompressed, uncompressed_size, compressed,
1347 compressed_size, chunk_size, final_size, workspace);
1349 case COMPRESSION_FORMAT_NONE:
1350 case COMPRESSION_FORMAT_DEFAULT:
1351 return STATUS_INVALID_PARAMETER;
1353 default:
1354 FIXME("format %u not implemented\n", format);
1355 return STATUS_UNSUPPORTED_COMPRESSION;
1359 /* decompress a single LZNT1 chunk */
1360 static UCHAR *lznt1_decompress_chunk(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size)
1362 UCHAR *src_cur = src, *src_end = src + src_size;
1363 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1364 ULONG displacement_bits, length_bits;
1365 ULONG code_displacement, code_length;
1366 WORD flags, code;
1368 while (src_cur < src_end && dst_cur < dst_end)
1370 flags = 0x8000 | *src_cur++;
1371 while ((flags & 0xff00) && src_cur < src_end)
1373 if (flags & 1)
1375 /* backwards reference */
1376 if (src_cur + sizeof(WORD) > src_end)
1377 return NULL;
1379 code = *(WORD *)src_cur;
1380 src_cur += sizeof(WORD);
1382 /* find length / displacement bits */
1383 for (displacement_bits = 12; displacement_bits > 4; displacement_bits--)
1384 if ((1 << (displacement_bits - 1)) < dst_cur - dst) break;
1386 length_bits = 16 - displacement_bits;
1387 code_length = (code & ((1 << length_bits) - 1)) + 3;
1388 code_displacement = (code >> length_bits) + 1;
1390 if (dst_cur < dst + code_displacement)
1391 return NULL;
1393 /* copy bytes of chunk - we can't use memcpy() since source and dest can
1394 * be overlapping, and the same bytes can be repeated over and over again */
1395 while (code_length--)
1397 if (dst_cur >= dst_end) return dst_cur;
1398 *dst_cur = *(dst_cur - code_displacement);
1399 dst_cur++;
1402 else
1404 /* uncompressed data */
1405 if (dst_cur >= dst_end) return dst_cur;
1406 *dst_cur++ = *src_cur++;
1408 flags >>= 1;
1412 return dst_cur;
1415 /* decompress data encoded with LZNT1 */
1416 static NTSTATUS lznt1_decompress(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size,
1417 ULONG offset, ULONG *final_size, UCHAR *workspace)
1419 UCHAR *src_cur = src, *src_end = src + src_size;
1420 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1421 ULONG chunk_size, block_size;
1422 WORD chunk_header;
1423 UCHAR *ptr;
1425 if (src_cur + sizeof(WORD) > src_end)
1426 return STATUS_BAD_COMPRESSION_BUFFER;
1428 /* skip over chunks with a distance >= 0x1000 to the destination offset */
1429 while (offset >= 0x1000 && src_cur + sizeof(WORD) <= src_end)
1431 chunk_header = *(WORD *)src_cur;
1432 src_cur += sizeof(WORD);
1433 if (!chunk_header) goto out;
1434 chunk_size = (chunk_header & 0xfff) + 1;
1436 if (src_cur + chunk_size > src_end)
1437 return STATUS_BAD_COMPRESSION_BUFFER;
1439 src_cur += chunk_size;
1440 offset -= 0x1000;
1443 /* handle partially included chunk */
1444 if (offset && src_cur + sizeof(WORD) <= src_end)
1446 chunk_header = *(WORD *)src_cur;
1447 src_cur += sizeof(WORD);
1448 if (!chunk_header) goto out;
1449 chunk_size = (chunk_header & 0xfff) + 1;
1451 if (src_cur + chunk_size > src_end)
1452 return STATUS_BAD_COMPRESSION_BUFFER;
1454 if (dst_cur >= dst_end)
1455 goto out;
1457 if (chunk_header & 0x8000)
1459 /* compressed chunk */
1460 if (!workspace) return STATUS_ACCESS_VIOLATION;
1461 ptr = lznt1_decompress_chunk(workspace, 0x1000, src_cur, chunk_size);
1462 if (!ptr) return STATUS_BAD_COMPRESSION_BUFFER;
1463 if (ptr - workspace > offset)
1465 block_size = min((ptr - workspace) - offset, dst_end - dst_cur);
1466 memcpy(dst_cur, workspace + offset, block_size);
1467 dst_cur += block_size;
1470 else
1472 /* uncompressed chunk */
1473 if (chunk_size > offset)
1475 block_size = min(chunk_size - offset, dst_end - dst_cur);
1476 memcpy(dst_cur, src_cur + offset, block_size);
1477 dst_cur += block_size;
1481 src_cur += chunk_size;
1484 /* handle remaining chunks */
1485 while (src_cur + sizeof(WORD) <= src_end)
1487 chunk_header = *(WORD *)src_cur;
1488 src_cur += sizeof(WORD);
1489 if (!chunk_header) goto out;
1490 chunk_size = (chunk_header & 0xfff) + 1;
1492 if (src_cur + chunk_size > src_end)
1493 return STATUS_BAD_COMPRESSION_BUFFER;
1495 /* fill space with padding when the previous chunk was decompressed
1496 * to less than 4096 bytes. no padding is needed for the last chunk
1497 * or when the next chunk is truncated */
1498 block_size = ((dst_cur - dst) + offset) & 0xfff;
1499 if (block_size)
1501 block_size = 0x1000 - block_size;
1502 if (dst_cur + block_size >= dst_end)
1503 goto out;
1504 memset(dst_cur, 0, block_size);
1505 dst_cur += block_size;
1508 if (dst_cur >= dst_end)
1509 goto out;
1511 if (chunk_header & 0x8000)
1513 /* compressed chunk */
1514 dst_cur = lznt1_decompress_chunk(dst_cur, dst_end - dst_cur, src_cur, chunk_size);
1515 if (!dst_cur) return STATUS_BAD_COMPRESSION_BUFFER;
1517 else
1519 /* uncompressed chunk */
1520 block_size = min(chunk_size, dst_end - dst_cur);
1521 memcpy(dst_cur, src_cur, block_size);
1522 dst_cur += block_size;
1525 src_cur += chunk_size;
1528 out:
1529 if (final_size)
1530 *final_size = dst_cur - dst;
1532 return STATUS_SUCCESS;
1536 /******************************************************************************
1537 * RtlDecompressFragment [NTDLL.@]
1539 NTSTATUS WINAPI RtlDecompressFragment(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1540 PUCHAR compressed, ULONG compressed_size, ULONG offset,
1541 PULONG final_size, PVOID workspace)
1543 TRACE("0x%04x, %p, %u, %p, %u, %u, %p, %p\n", format, uncompressed,
1544 uncompressed_size, compressed, compressed_size, offset, final_size, workspace);
1546 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1548 case COMPRESSION_FORMAT_LZNT1:
1549 return lznt1_decompress(uncompressed, uncompressed_size, compressed,
1550 compressed_size, offset, final_size, workspace);
1552 case COMPRESSION_FORMAT_NONE:
1553 case COMPRESSION_FORMAT_DEFAULT:
1554 return STATUS_INVALID_PARAMETER;
1556 default:
1557 FIXME("format %u not implemented\n", format);
1558 return STATUS_UNSUPPORTED_COMPRESSION;
1563 /******************************************************************************
1564 * RtlDecompressBuffer [NTDLL.@]
1566 NTSTATUS WINAPI RtlDecompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1567 PUCHAR compressed, ULONG compressed_size, PULONG final_size)
1569 TRACE("0x%04x, %p, %u, %p, %u, %p\n", format, uncompressed,
1570 uncompressed_size, compressed, compressed_size, final_size);
1572 return RtlDecompressFragment(format, uncompressed, uncompressed_size,
1573 compressed, compressed_size, 0, final_size, NULL);
1576 /***********************************************************************
1577 * RtlSetThreadErrorMode [NTDLL.@]
1579 * Set the thread local error mode.
1581 * PARAMS
1582 * mode [I] The new error mode
1583 * oldmode [O] Destination of the old error mode (may be NULL)
1585 * RETURNS
1586 * Success: STATUS_SUCCESS
1587 * Failure: STATUS_INVALID_PARAMETER_1
1589 NTSTATUS WINAPI RtlSetThreadErrorMode( DWORD mode, LPDWORD oldmode )
1591 if (mode & ~0x70)
1592 return STATUS_INVALID_PARAMETER_1;
1594 if (oldmode)
1595 *oldmode = NtCurrentTeb()->HardErrorDisabled;
1597 NtCurrentTeb()->HardErrorDisabled = mode;
1598 return STATUS_SUCCESS;
1601 /***********************************************************************
1602 * RtlGetThreadErrorMode [NTDLL.@]
1604 * Get the thread local error mode.
1606 * PARAMS
1607 * None.
1609 * RETURNS
1610 * The current thread local error mode.
1612 DWORD WINAPI RtlGetThreadErrorMode( void )
1614 return NtCurrentTeb()->HardErrorDisabled;
1617 /******************************************************************************
1618 * RtlGetCurrentTransaction [NTDLL.@]
1620 HANDLE WINAPI RtlGetCurrentTransaction(void)
1622 FIXME("() :stub\n");
1623 return NULL;
1626 /******************************************************************************
1627 * RtlSetCurrentTransaction [NTDLL.@]
1629 BOOL WINAPI RtlSetCurrentTransaction(HANDLE new_transaction)
1631 FIXME("(%p) :stub\n", new_transaction);
1632 return FALSE;
1635 /**********************************************************************
1636 * RtlGetCurrentProcessorNumberEx [NTDLL.@]
1638 void WINAPI RtlGetCurrentProcessorNumberEx(PROCESSOR_NUMBER *processor)
1640 FIXME("(%p) :semi-stub\n", processor);
1641 processor->Group = 0;
1642 processor->Number = NtGetCurrentProcessorNumber();
1643 processor->Reserved = 0;
1646 /***********************************************************************
1647 * RtlInitializeGenericTableAvl (NTDLL.@)
1649 void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE table, PRTL_AVL_COMPARE_ROUTINE compare,
1650 PRTL_AVL_ALLOCATE_ROUTINE allocate, PRTL_AVL_FREE_ROUTINE free, void *context)
1652 FIXME("%p %p %p %p %p: stub\n", table, compare, allocate, free, context);
1655 /***********************************************************************
1656 * RtlInsertElementGenericTableAvl (NTDLL.@)
1658 void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE table, void *buffer, ULONG size, BOOL *element)
1660 FIXME("%p %p %u %p: stub\n", table, buffer, size, element);
1663 typedef struct _RTL_UNLOAD_EVENT_TRACE
1665 PVOID BaseAddress;
1666 SIZE_T SizeOfImage;
1667 ULONG Sequence;
1668 ULONG TimeDateStamp;
1669 ULONG CheckSum;
1670 WCHAR ImageName[32];
1671 } RTL_UNLOAD_EVENT_TRACE, *PRTL_UNLOAD_EVENT_TRACE;
1673 /*********************************************************************
1674 * RtlGetUnloadEventTrace [NTDLL.@]
1676 RTL_UNLOAD_EVENT_TRACE * WINAPI RtlGetUnloadEventTrace(void)
1678 FIXME("stub!\n");
1679 return NULL;
1682 /*********************************************************************
1683 * RtlGetUnloadEventTraceEx [NTDLL.@]
1685 void WINAPI RtlGetUnloadEventTraceEx(ULONG **size, ULONG **count, void **trace)
1687 static ULONG dummy_size, dummy_count;
1689 FIXME("(%p, %p, %p): stub!\n", size, count, trace);
1691 if (size) *size = &dummy_size;
1692 if (count) *count = &dummy_count;
1693 if (trace) *trace = NULL;
1696 /*********************************************************************
1697 * RtlQueryPackageIdentity [NTDLL.@]
1699 NTSTATUS WINAPI RtlQueryPackageIdentity(HANDLE token, WCHAR *fullname, SIZE_T *fullname_size,
1700 WCHAR *appid, SIZE_T *appid_size, BOOLEAN *packaged)
1702 FIXME("(%p, %p, %p, %p, %p, %p): stub\n", token, fullname, fullname_size, appid, appid_size, packaged);
1703 return STATUS_NOT_FOUND;