ntdll/tests: Dump entire VM_COUNTERS structure.
[wine.git] / dlls / ntdll / rtl.c
blobc309e10df6b7f28900760fe4698482499d08b393
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 "ddk/ntddk.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
52 static RTL_CRITICAL_SECTION peb_lock;
53 static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
55 0, 0, &peb_lock,
56 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
57 0, 0, { (DWORD_PTR)(__FILE__ ": peb_lock") }
59 static RTL_CRITICAL_SECTION peb_lock = { &critsect_debug, -1, 0, 0, 0, 0 };
61 #ifdef __i386__
62 #define DEFINE_FASTCALL4_ENTRYPOINT( name ) \
63 __ASM_STDCALL_FUNC( name, 16, \
64 "popl %eax\n\t" \
65 "pushl %edx\n\t" \
66 "pushl %ecx\n\t" \
67 "pushl %eax\n\t" \
68 "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(16))
69 #endif
71 /* CRC polynomial 0xedb88320 */
72 static const DWORD CRC_table[256] =
74 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
75 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
76 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
77 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
78 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
79 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
80 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
81 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
82 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
83 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
84 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
85 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
86 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
87 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
88 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
89 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
90 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
91 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
92 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
93 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
94 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
95 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
96 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
97 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
98 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
99 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
100 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
101 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
102 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
103 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
104 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
105 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
106 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
107 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
108 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
109 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
110 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
111 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
112 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
113 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
114 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
115 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
116 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
120 * resource functions
123 /***********************************************************************
124 * RtlInitializeResource (NTDLL.@)
126 * xxxResource() functions implement multiple-reader-single-writer lock.
127 * The code is based on information published in WDJ January 1999 issue.
129 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
131 if( rwl )
133 rwl->iNumberActive = 0;
134 rwl->uExclusiveWaiters = 0;
135 rwl->uSharedWaiters = 0;
136 rwl->hOwningThreadId = 0;
137 rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
138 RtlInitializeCriticalSection( &rwl->rtlCS );
139 rwl->rtlCS.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RTL_RWLOCK.rtlCS");
140 NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
141 NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
146 /***********************************************************************
147 * RtlDeleteResource (NTDLL.@)
149 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
151 if( rwl )
153 RtlEnterCriticalSection( &rwl->rtlCS );
154 if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
155 ERR("Deleting active MRSW lock (%p), expect failure\n", rwl );
156 rwl->hOwningThreadId = 0;
157 rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
158 rwl->iNumberActive = 0;
159 NtClose( rwl->hExclusiveReleaseSemaphore );
160 NtClose( rwl->hSharedReleaseSemaphore );
161 RtlLeaveCriticalSection( &rwl->rtlCS );
162 rwl->rtlCS.DebugInfo->Spare[0] = 0;
163 RtlDeleteCriticalSection( &rwl->rtlCS );
168 /***********************************************************************
169 * RtlAcquireResourceExclusive (NTDLL.@)
171 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
173 BYTE retVal = 0;
174 if( !rwl ) return 0;
176 start:
177 RtlEnterCriticalSection( &rwl->rtlCS );
178 if( rwl->iNumberActive == 0 ) /* lock is free */
180 rwl->iNumberActive = -1;
181 retVal = 1;
183 else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
185 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
187 retVal = 1;
188 rwl->iNumberActive--;
189 goto done;
191 wait:
192 if( fWait )
194 NTSTATUS status;
196 rwl->uExclusiveWaiters++;
198 RtlLeaveCriticalSection( &rwl->rtlCS );
199 status = NtWaitForSingleObject( rwl->hExclusiveReleaseSemaphore, FALSE, NULL );
200 if( HIWORD(status) )
201 goto done;
202 goto start; /* restart the acquisition to avoid deadlocks */
205 else /* one or more shared locks are in progress */
206 if( fWait )
207 goto wait;
209 if( retVal == 1 )
210 rwl->hOwningThreadId = ULongToHandle(GetCurrentThreadId());
211 done:
212 RtlLeaveCriticalSection( &rwl->rtlCS );
213 return retVal;
216 /***********************************************************************
217 * RtlAcquireResourceShared (NTDLL.@)
219 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
221 NTSTATUS status = STATUS_UNSUCCESSFUL;
222 BYTE retVal = 0;
223 if( !rwl ) return 0;
225 start:
226 RtlEnterCriticalSection( &rwl->rtlCS );
227 if( rwl->iNumberActive < 0 )
229 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
231 rwl->iNumberActive--;
232 retVal = 1;
233 goto done;
236 if( fWait )
238 rwl->uSharedWaiters++;
239 RtlLeaveCriticalSection( &rwl->rtlCS );
240 status = NtWaitForSingleObject( rwl->hSharedReleaseSemaphore, FALSE, NULL );
241 if( HIWORD(status) )
242 goto done;
243 goto start;
246 else
248 if( status != STATUS_WAIT_0 ) /* otherwise RtlReleaseResource() has already done it */
249 rwl->iNumberActive++;
250 retVal = 1;
252 done:
253 RtlLeaveCriticalSection( &rwl->rtlCS );
254 return retVal;
258 /***********************************************************************
259 * RtlReleaseResource (NTDLL.@)
261 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
263 RtlEnterCriticalSection( &rwl->rtlCS );
265 if( rwl->iNumberActive > 0 ) /* have one or more readers */
267 if( --rwl->iNumberActive == 0 )
269 if( rwl->uExclusiveWaiters )
271 wake_exclusive:
272 rwl->uExclusiveWaiters--;
273 NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
277 else
278 if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
280 if( ++rwl->iNumberActive == 0 )
282 rwl->hOwningThreadId = 0;
283 if( rwl->uExclusiveWaiters )
284 goto wake_exclusive;
285 else
286 if( rwl->uSharedWaiters )
288 UINT n = rwl->uSharedWaiters;
289 rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
290 * all queued readers have done their thing */
291 rwl->uSharedWaiters = 0;
292 NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
296 RtlLeaveCriticalSection( &rwl->rtlCS );
300 /***********************************************************************
301 * RtlDumpResource (NTDLL.@)
303 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
305 if( rwl )
307 MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
308 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
309 if( rwl->iNumberActive )
310 MESSAGE("\towner thread = %p\n", rwl->hOwningThreadId );
315 * misc functions
318 /******************************************************************************
319 * DbgPrint [NTDLL.@]
321 NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...)
323 char buf[512];
324 __ms_va_list args;
326 __ms_va_start(args, fmt);
327 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
328 __ms_va_end(args);
330 MESSAGE("DbgPrint says: %s",buf);
331 /* hmm, raise exception? */
332 return STATUS_SUCCESS;
336 /******************************************************************************
337 * DbgPrintEx [NTDLL.@]
339 NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...)
341 NTSTATUS ret;
342 __ms_va_list args;
344 __ms_va_start(args, fmt);
345 ret = vDbgPrintEx(iComponentId, Level, fmt, args);
346 __ms_va_end(args);
347 return ret;
350 /******************************************************************************
351 * vDbgPrintEx [NTDLL.@]
353 NTSTATUS WINAPI vDbgPrintEx( ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
355 return vDbgPrintExWithPrefix( "", id, level, fmt, args );
358 /******************************************************************************
359 * vDbgPrintExWithPrefix [NTDLL.@]
361 NTSTATUS WINAPI vDbgPrintExWithPrefix( LPCSTR prefix, ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
363 char buf[1024];
365 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
367 switch (level & DPFLTR_MASK)
369 case DPFLTR_ERROR_LEVEL: ERR("%s%x: %s", prefix, id, buf); break;
370 case DPFLTR_WARNING_LEVEL: WARN("%s%x: %s", prefix, id, buf); break;
371 case DPFLTR_TRACE_LEVEL:
372 case DPFLTR_INFO_LEVEL:
373 default: TRACE("%s%x: %s", prefix, id, buf); break;
375 return STATUS_SUCCESS;
378 /******************************************************************************
379 * RtlAcquirePebLock [NTDLL.@]
381 VOID WINAPI RtlAcquirePebLock(void)
383 RtlEnterCriticalSection( &peb_lock );
386 /******************************************************************************
387 * RtlReleasePebLock [NTDLL.@]
389 VOID WINAPI RtlReleasePebLock(void)
391 RtlLeaveCriticalSection( &peb_lock );
394 /******************************************************************************
395 * RtlNewSecurityObject [NTDLL.@]
397 NTSTATUS WINAPI
398 RtlNewSecurityObject( PSECURITY_DESCRIPTOR ParentDescriptor,
399 PSECURITY_DESCRIPTOR CreatorDescriptor,
400 PSECURITY_DESCRIPTOR *NewDescriptor,
401 BOOLEAN IsDirectoryObject,
402 HANDLE Token,
403 PGENERIC_MAPPING GenericMapping )
405 FIXME("(%p %p %p %d %p %p) stub!\n", ParentDescriptor, CreatorDescriptor,
406 NewDescriptor, IsDirectoryObject, Token, GenericMapping);
407 return STATUS_NOT_IMPLEMENTED;
410 /******************************************************************************
411 * RtlDeleteSecurityObject [NTDLL.@]
413 NTSTATUS WINAPI
414 RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR *ObjectDescriptor )
416 FIXME("(%p) stub!\n", ObjectDescriptor);
417 return STATUS_NOT_IMPLEMENTED;
420 /******************************************************************************
421 * RtlInitializeGenericTable [NTDLL.@]
423 PVOID WINAPI RtlInitializeGenericTable(PVOID pTable, PVOID arg2, PVOID arg3, PVOID arg4, PVOID arg5)
425 FIXME("(%p,%p,%p,%p,%p) stub!\n", pTable, arg2, arg3, arg4, arg5);
426 return NULL;
429 /******************************************************************************
430 * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
432 PVOID RtlEnumerateGenericTableWithoutSplaying(PVOID pTable, PVOID *RestartKey)
434 static int warn_once;
436 if (!warn_once++)
437 FIXME("(%p,%p) stub!\n", pTable, RestartKey);
438 return NULL;
441 /******************************************************************************
442 * RtlNumberGenericTableElements [NTDLL.@]
444 ULONG RtlNumberGenericTableElements(PVOID pTable)
446 FIXME("(%p) stub!\n", pTable);
447 return 0;
450 /******************************************************************************
451 * RtlMoveMemory [NTDLL.@]
453 * Move a block of memory that may overlap.
455 * PARAMS
456 * Destination [O] End destination for block
457 * Source [O] Where to start copying from
458 * Length [I] Number of bytes to copy
460 * RETURNS
461 * Nothing.
463 #undef RtlMoveMemory
464 VOID WINAPI RtlMoveMemory( void *Destination, const void *Source, SIZE_T Length )
466 memmove(Destination, Source, Length);
469 /******************************************************************************
470 * RtlFillMemory [NTDLL.@]
472 * Set a block of memory with a value.
474 * PARAMS
475 * Destination [O] Block to fill
476 * Length [I] Number of bytes to fill
477 * Fill [I] Value to set
479 * RETURNS
480 * Nothing.
482 #undef RtlFillMemory
483 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
485 memset(Destination, Fill, Length);
488 /******************************************************************************
489 * RtlZeroMemory [NTDLL.@]
491 * Set a block of memory with 0's.
493 * PARAMS
494 * Destination [O] Block to fill
495 * Length [I] Number of bytes to fill
497 * RETURNS
498 * Nothing.
500 #undef RtlZeroMemory
501 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
503 memset(Destination, 0, Length);
506 /******************************************************************************
507 * RtlCompareMemory [NTDLL.@]
509 * Compare one block of memory with another
511 * PARAMS
512 * Source1 [I] Source block
513 * Source2 [I] Block to compare to Source1
514 * Length [I] Number of bytes to compare
516 * RETURNS
517 * The length of the first byte at which Source1 and Source2 differ, or Length
518 * if they are the same.
520 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
522 SIZE_T i;
523 for(i=0; (i<Length) && (((const BYTE*)Source1)[i]==((const BYTE*)Source2)[i]); i++);
524 return i;
527 /******************************************************************************
528 * RtlCompareMemoryUlong [NTDLL.@]
530 * Compare a block of memory with a value, a ULONG at a time
532 * PARAMS
533 * Source1 [I] Source block. This must be ULONG aligned
534 * Length [I] Number of bytes to compare. This should be a multiple of 4
535 * dwVal [I] Value to compare to
537 * RETURNS
538 * The byte position of the first byte at which Source1 is not dwVal.
540 SIZE_T WINAPI RtlCompareMemoryUlong(const ULONG *Source1, SIZE_T Length, ULONG dwVal)
542 SIZE_T i;
543 for(i = 0; i < Length/sizeof(ULONG) && Source1[i] == dwVal; i++);
544 return i * sizeof(ULONG);
547 /******************************************************************************
548 * RtlCopyMemory [NTDLL.@]
550 #undef RtlCopyMemory
551 void WINAPI RtlCopyMemory(void *dest, const void *src, SIZE_T len)
553 memcpy(dest, src, len);
556 /******************************************************************************
557 * RtlAssert [NTDLL.@]
559 * Fail a debug assertion.
561 * RETURNS
562 * Nothing. This call does not return control to its caller.
564 * NOTES
565 * Not implemented in non-debug versions.
567 void WINAPI RtlAssert(void *assertion, void *filename, ULONG linenumber, char *message)
569 FIXME("(%s, %s, %u, %s): stub\n", debugstr_a((char*)assertion), debugstr_a((char*)filename),
570 linenumber, debugstr_a(message));
573 /*************************************************************************
574 * RtlFillMemoryUlong [NTDLL.@]
576 * Fill memory with a 32 bit (dword) value.
578 * PARAMS
579 * lpDest [I] Bitmap pointer
580 * ulCount [I] Number of dwords to write
581 * ulValue [I] Value to fill with
583 * RETURNS
584 * Nothing.
586 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
588 TRACE("(%p,%d,%d)\n", lpDest, ulCount, ulValue);
590 ulCount /= sizeof(ULONG);
591 while(ulCount--)
592 *lpDest++ = ulValue;
595 /*********************************************************************
596 * RtlComputeCrc32 [NTDLL.@]
598 * Calculate the CRC32 checksum of a block of bytes
600 * PARAMS
601 * dwInitial [I] Initial CRC value
602 * pData [I] Data block
603 * iLen [I] Length of the byte block
605 * RETURNS
606 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
608 DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
610 DWORD crc = ~dwInitial;
612 TRACE("(%d,%p,%d)\n", dwInitial, pData, iLen);
614 while (iLen > 0)
616 crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
617 pData++;
618 iLen--;
620 return ~crc;
624 /*************************************************************************
625 * RtlUlonglongByteSwap [NTDLL.@]
627 * Swap the bytes of an unsigned long long value.
629 * PARAMS
630 * i [I] Value to swap bytes of
632 * RETURNS
633 * The value with its bytes swapped.
635 ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i)
637 return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32);
640 /*************************************************************************
641 * RtlUlongByteSwap [NTDLL.@]
643 * Swap the bytes of an unsigned int value.
645 * NOTES
646 * ix86 version takes argument in %ecx. Other systems use the inline version.
648 #ifdef __i386__
649 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap,
650 "movl %ecx,%eax\n\t"
651 "bswap %eax\n\t"
652 "ret")
653 #endif
655 /*************************************************************************
656 * RtlUshortByteSwap [NTDLL.@]
658 * Swap the bytes of an unsigned short value.
660 * NOTES
661 * i386 version takes argument in %cx. Other systems use the inline version.
663 #ifdef __i386__
664 __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap,
665 "movb %ch,%al\n\t"
666 "movb %cl,%ah\n\t"
667 "ret")
668 #endif
671 /*************************************************************************
672 * RtlUniform [NTDLL.@]
674 * Generates an uniform random number
676 * PARAMS
677 * seed [O] The seed of the Random function
679 * RETURNS
680 * It returns a random number uniformly distributed over [0..MAXLONG-1].
682 * NOTES
683 * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
684 * In our case the algorithm is:
686 *| result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
688 *| *seed = result;
690 * DIFFERENCES
691 * The native documentation states that the random number is
692 * uniformly distributed over [0..MAXLONG]. In reality the native
693 * function and our function return a random number uniformly
694 * distributed over [0..MAXLONG-1].
696 ULONG WINAPI RtlUniform (PULONG seed)
698 ULONG result;
701 * Instead of the algorithm stated above, we use the algorithm
702 * below, which is totally equivalent (see the tests), but does
703 * not use a division and therefore is faster.
705 result = *seed * 0xffffffed + 0x7fffffc3;
706 if (result == 0xffffffff || result == 0x7ffffffe) {
707 result = (result + 2) & MAXLONG;
708 } else if (result == 0x7fffffff) {
709 result = 0;
710 } else if ((result & 0x80000000) == 0) {
711 result = result + (~result & 1);
712 } else {
713 result = (result + (result & 1)) & MAXLONG;
714 } /* if */
715 *seed = result;
716 return result;
720 /*************************************************************************
721 * RtlRandom [NTDLL.@]
723 * Generates a random number
725 * PARAMS
726 * seed [O] The seed of the Random function
728 * RETURNS
729 * It returns a random number distributed over [0..MAXLONG-1].
731 ULONG WINAPI RtlRandom (PULONG seed)
733 static ULONG saved_value[128] =
734 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
735 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
736 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
737 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
738 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
739 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
740 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
741 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
742 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
743 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
744 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
745 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
746 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
747 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
748 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
749 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
750 ULONG rand;
751 int pos;
752 ULONG result;
754 rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
755 *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
756 pos = *seed & 0x7f;
757 result = saved_value[pos];
758 saved_value[pos] = rand;
759 return(result);
763 /*************************************************************************
764 * RtlAreAllAccessesGranted [NTDLL.@]
766 * Check if all desired accesses are granted
768 * RETURNS
769 * TRUE: All desired accesses are granted
770 * FALSE: Otherwise
772 BOOLEAN WINAPI RtlAreAllAccessesGranted(
773 ACCESS_MASK GrantedAccess,
774 ACCESS_MASK DesiredAccess)
776 return (GrantedAccess & DesiredAccess) == DesiredAccess;
780 /*************************************************************************
781 * RtlAreAnyAccessesGranted [NTDLL.@]
783 * Check if at least one of the desired accesses is granted
785 * PARAMS
786 * GrantedAccess [I] Access mask of granted accesses
787 * DesiredAccess [I] Access mask of desired accesses
789 * RETURNS
790 * TRUE: At least one of the desired accesses is granted
791 * FALSE: Otherwise
793 BOOLEAN WINAPI RtlAreAnyAccessesGranted(
794 ACCESS_MASK GrantedAccess,
795 ACCESS_MASK DesiredAccess)
797 return (GrantedAccess & DesiredAccess) != 0;
801 /*************************************************************************
802 * RtlMapGenericMask [NTDLL.@]
804 * Determine the nongeneric access rights specified by an access mask
806 * RETURNS
807 * Nothing.
809 void WINAPI RtlMapGenericMask(
810 PACCESS_MASK AccessMask,
811 const GENERIC_MAPPING *GenericMapping)
813 if (*AccessMask & GENERIC_READ) {
814 *AccessMask |= GenericMapping->GenericRead;
815 } /* if */
817 if (*AccessMask & GENERIC_WRITE) {
818 *AccessMask |= GenericMapping->GenericWrite;
819 } /* if */
821 if (*AccessMask & GENERIC_EXECUTE) {
822 *AccessMask |= GenericMapping->GenericExecute;
823 } /* if */
825 if (*AccessMask & GENERIC_ALL) {
826 *AccessMask |= GenericMapping->GenericAll;
827 } /* if */
829 *AccessMask &= 0x0FFFFFFF;
833 /*************************************************************************
834 * RtlCopyLuid [NTDLL.@]
836 * Copy a local unique ID.
838 * PARAMS
839 * LuidDest [O] Destination for the copied Luid
840 * LuidSrc [I] Source Luid to copy to LuidDest
842 * RETURNS
843 * Nothing.
845 void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc)
847 *LuidDest = *LuidSrc;
851 /*************************************************************************
852 * RtlEqualLuid [NTDLL.@]
854 * Compare two local unique IDs.
856 * PARAMS
857 * Luid1 [I] First Luid to compare to Luid2
858 * Luid2 [I] Second Luid to compare to Luid1
860 * RETURNS
861 * TRUE: The two LUIDs are equal.
862 * FALSE: Otherwise
864 BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2)
866 return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart);
870 /*************************************************************************
871 * RtlCopyLuidAndAttributesArray [NTDLL.@]
873 * Copy an array of local unique IDs and attributes.
875 * PARAMS
876 * Count [I] Number of Luid/attributes in Src
877 * Src [I] Source Luid/attributes to copy
878 * Dest [O] Destination for copied Luid/attributes
880 * RETURNS
881 * Nothing.
883 * NOTES
884 * Dest must be large enough to hold Src.
886 void WINAPI RtlCopyLuidAndAttributesArray(
887 ULONG Count,
888 const LUID_AND_ATTRIBUTES *Src,
889 PLUID_AND_ATTRIBUTES Dest)
891 ULONG i;
893 for (i = 0; i < Count; i++) Dest[i] = Src[i];
896 NTSTATUS WINAPI RtlIpv4StringToAddressExW(PULONG IP, PULONG Port,
897 LPCWSTR Buffer, PULONG MaxSize)
899 FIXME("(%p,%p,%p,%p): stub\n", IP, Port, Buffer, MaxSize);
901 return STATUS_SUCCESS;
904 /***********************************************************************
905 * RtlIpv4AddressToStringExW [NTDLL.@]
907 * Convert the given ipv4 address and optional the port to a string
909 * PARAMS
910 * pin [I] PTR to the ip address to convert (network byte order)
911 * port [I] optional port to convert (network byte order)
912 * buffer [O] destination buffer for the result
913 * psize [IO] PTR to available/used size of the destination buffer
915 * RETURNS
916 * Success: STATUS_SUCCESS
917 * Failure: STATUS_INVALID_PARAMETER
920 NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
922 WCHAR tmp_ip[32];
923 static const WCHAR fmt_ip[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
924 static const WCHAR fmt_port[] = {':','%','u',0};
925 ULONG needed;
927 if (!pin || !buffer || !psize)
928 return STATUS_INVALID_PARAMETER;
930 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
932 needed = sprintfW(tmp_ip, fmt_ip,
933 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
934 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
936 if (port) needed += sprintfW(tmp_ip + needed, fmt_port, ntohs(port));
938 if (*psize > needed) {
939 *psize = needed + 1;
940 strcpyW(buffer, tmp_ip);
941 return STATUS_SUCCESS;
944 *psize = needed + 1;
945 return STATUS_INVALID_PARAMETER;
948 /***********************************************************************
949 * RtlIpv4AddressToStringExA [NTDLL.@]
951 * Convert the given ipv4 address and optional the port to a string
953 * See RtlIpv4AddressToStringExW
955 NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
957 CHAR tmp_ip[32];
958 ULONG needed;
960 if (!pin || !buffer || !psize)
961 return STATUS_INVALID_PARAMETER;
963 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
965 needed = sprintf(tmp_ip, "%u.%u.%u.%u",
966 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
967 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
969 if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
971 if (*psize > needed) {
972 *psize = needed + 1;
973 strcpy(buffer, tmp_ip);
974 return STATUS_SUCCESS;
977 *psize = needed + 1;
978 return STATUS_INVALID_PARAMETER;
981 /***********************************************************************
982 * RtlIpv4AddressToStringW [NTDLL.@]
984 * Convert the given ipv4 address to a string
986 * PARAMS
987 * pin [I] PTR to the ip address to convert (network byte order)
988 * buffer [O] destination buffer for the result (at least 16 character)
990 * RETURNS
991 * PTR to the 0 character at the end of the converted string
994 WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
996 ULONG size = 16;
998 if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
999 return buffer + size - 1;
1002 /***********************************************************************
1003 * RtlIpv4AddressToStringA [NTDLL.@]
1005 * Convert the given ipv4 address to a string
1007 * See RtlIpv4AddressToStringW
1009 CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
1011 ULONG size = 16;
1013 if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
1014 return buffer + size - 1;
1017 /***********************************************************************
1018 * get_pointer_obfuscator (internal)
1020 static DWORD_PTR get_pointer_obfuscator( void )
1022 static DWORD_PTR pointer_obfuscator;
1024 if (!pointer_obfuscator)
1026 ULONG seed = NtGetTickCount();
1027 ULONG_PTR rand;
1029 /* generate a random value for the obfuscator */
1030 rand = RtlUniform( &seed );
1032 /* handle 64bit pointers */
1033 rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1035 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1036 rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1038 interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator, (void*) rand, NULL );
1041 return pointer_obfuscator;
1044 /*************************************************************************
1045 * RtlEncodePointer [NTDLL.@]
1047 PVOID WINAPI RtlEncodePointer( PVOID ptr )
1049 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1050 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1053 PVOID WINAPI RtlDecodePointer( PVOID ptr )
1055 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1056 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1059 /*************************************************************************
1060 * RtlInitializeSListHead [NTDLL.@]
1062 VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
1064 #ifdef _WIN64
1065 list->s.Alignment = list->s.Region = 0;
1066 list->Header16.HeaderType = 1; /* we use the 16-byte header */
1067 #else
1068 list->Alignment = 0;
1069 #endif
1072 /*************************************************************************
1073 * RtlQueryDepthSList [NTDLL.@]
1075 WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
1077 #ifdef _WIN64
1078 return list->Header16.Depth;
1079 #else
1080 return list->s.Depth;
1081 #endif
1084 /*************************************************************************
1085 * RtlFirstEntrySList [NTDLL.@]
1087 PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
1089 #ifdef _WIN64
1090 return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
1091 #else
1092 return list->s.Next.Next;
1093 #endif
1096 /*************************************************************************
1097 * RtlInterlockedFlushSList [NTDLL.@]
1099 PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
1101 SLIST_HEADER old, new;
1103 #ifdef _WIN64
1104 if (!list->Header16.NextEntry) return NULL;
1105 new.s.Alignment = new.s.Region = 0;
1106 new.Header16.HeaderType = 1; /* we use the 16-byte header */
1109 old = *list;
1110 new.Header16.Sequence = old.Header16.Sequence + 1;
1111 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1112 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1113 #else
1114 if (!list->s.Next.Next) return NULL;
1115 new.Alignment = 0;
1118 old = *list;
1119 new.s.Sequence = old.s.Sequence + 1;
1120 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1121 old.Alignment) != old.Alignment);
1122 return old.s.Next.Next;
1123 #endif
1126 /*************************************************************************
1127 * RtlInterlockedPushEntrySList [NTDLL.@]
1129 PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
1131 SLIST_HEADER old, new;
1133 #ifdef _WIN64
1134 new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
1137 old = *list;
1138 entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1139 new.Header16.Depth = old.Header16.Depth + 1;
1140 new.Header16.Sequence = old.Header16.Sequence + 1;
1141 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1142 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1143 #else
1144 new.s.Next.Next = entry;
1147 old = *list;
1148 entry->Next = old.s.Next.Next;
1149 new.s.Depth = old.s.Depth + 1;
1150 new.s.Sequence = old.s.Sequence + 1;
1151 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1152 old.Alignment) != old.Alignment);
1153 return old.s.Next.Next;
1154 #endif
1157 /*************************************************************************
1158 * RtlInterlockedPopEntrySList [NTDLL.@]
1160 PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
1162 SLIST_HEADER old, new;
1163 PSLIST_ENTRY entry;
1165 #ifdef _WIN64
1168 old = *list;
1169 if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
1170 /* entry could be deleted by another thread */
1171 __TRY
1173 new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
1174 new.Header16.Depth = old.Header16.Depth - 1;
1175 new.Header16.Sequence = old.Header16.Sequence + 1;
1177 __EXCEPT_PAGE_FAULT
1180 __ENDTRY
1181 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1182 #else
1185 old = *list;
1186 if (!(entry = old.s.Next.Next)) return NULL;
1187 /* entry could be deleted by another thread */
1188 __TRY
1190 new.s.Next.Next = entry->Next;
1191 new.s.Depth = old.s.Depth - 1;
1192 new.s.Sequence = old.s.Sequence + 1;
1194 __EXCEPT_PAGE_FAULT
1197 __ENDTRY
1198 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1199 old.Alignment) != old.Alignment);
1200 #endif
1201 return entry;
1204 /*************************************************************************
1205 * RtlInterlockedPushListSListEx [NTDLL.@]
1207 PSLIST_ENTRY WINAPI RtlInterlockedPushListSListEx(PSLIST_HEADER list, PSLIST_ENTRY first,
1208 PSLIST_ENTRY last, ULONG count)
1210 SLIST_HEADER old, new;
1212 #ifdef _WIN64
1213 new.Header16.NextEntry = (ULONG_PTR)first >> 4;
1216 old = *list;
1217 new.Header16.Depth = old.Header16.Depth + count;
1218 new.Header16.Sequence = old.Header16.Sequence + 1;
1219 last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1220 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1221 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1222 #else
1223 new.s.Next.Next = first;
1226 old = *list;
1227 new.s.Depth = old.s.Depth + count;
1228 new.s.Sequence = old.s.Sequence + 1;
1229 last->Next = old.s.Next.Next;
1230 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1231 old.Alignment) != old.Alignment);
1232 return old.s.Next.Next;
1233 #endif
1236 /*************************************************************************
1237 * RtlInterlockedPushListSList [NTDLL.@]
1239 #ifdef DEFINE_FASTCALL4_ENTRYPOINT
1240 DEFINE_FASTCALL4_ENTRYPOINT(RtlInterlockedPushListSList)
1241 PSLIST_ENTRY WINAPI __regs_RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1242 PSLIST_ENTRY last, ULONG count)
1243 #else
1244 PSLIST_ENTRY WINAPI RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1245 PSLIST_ENTRY last, ULONG count)
1246 #endif
1248 return RtlInterlockedPushListSListEx(list, first, last, count);
1251 /******************************************************************************
1252 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1254 NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT format, PULONG compress_workspace,
1255 PULONG decompress_workspace)
1257 FIXME("0x%04x, %p, %p: semi-stub\n", format, compress_workspace, decompress_workspace);
1259 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1261 case COMPRESSION_FORMAT_LZNT1:
1262 if (compress_workspace)
1264 /* FIXME: The current implementation of RtlCompressBuffer does not use a
1265 * workspace buffer, but Windows applications might expect a nonzero value. */
1266 *compress_workspace = 16;
1268 if (decompress_workspace)
1269 *decompress_workspace = 0x1000;
1270 return STATUS_SUCCESS;
1272 case COMPRESSION_FORMAT_NONE:
1273 case COMPRESSION_FORMAT_DEFAULT:
1274 return STATUS_INVALID_PARAMETER;
1276 default:
1277 FIXME("format %u not implemented\n", format);
1278 return STATUS_UNSUPPORTED_COMPRESSION;
1282 /* compress data using LZNT1, currently only a stub */
1283 static NTSTATUS lznt1_compress(UCHAR *src, ULONG src_size, UCHAR *dst, ULONG dst_size,
1284 ULONG chunk_size, ULONG *final_size, UCHAR *workspace)
1286 UCHAR *src_cur = src, *src_end = src + src_size;
1287 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1288 ULONG block_size;
1290 while (src_cur < src_end)
1292 /* determine size of current chunk */
1293 block_size = min(0x1000, src_end - src_cur);
1294 if (dst_cur + sizeof(WORD) + block_size > dst_end)
1295 return STATUS_BUFFER_TOO_SMALL;
1297 /* write (uncompressed) chunk header */
1298 *(WORD *)dst_cur = 0x3000 | (block_size - 1);
1299 dst_cur += sizeof(WORD);
1301 /* write chunk content */
1302 memcpy(dst_cur, src_cur, block_size);
1303 dst_cur += block_size;
1304 src_cur += block_size;
1307 if (final_size)
1308 *final_size = dst_cur - dst;
1310 return STATUS_SUCCESS;
1313 /******************************************************************************
1314 * RtlCompressBuffer [NTDLL.@]
1316 NTSTATUS WINAPI RtlCompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1317 PUCHAR compressed, ULONG compressed_size, ULONG chunk_size,
1318 PULONG final_size, PVOID workspace)
1320 FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p: semi-stub\n", format, uncompressed,
1321 uncompressed_size, compressed, compressed_size, chunk_size, final_size, workspace);
1323 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1325 case COMPRESSION_FORMAT_LZNT1:
1326 return lznt1_compress(uncompressed, uncompressed_size, compressed,
1327 compressed_size, chunk_size, final_size, workspace);
1329 case COMPRESSION_FORMAT_NONE:
1330 case COMPRESSION_FORMAT_DEFAULT:
1331 return STATUS_INVALID_PARAMETER;
1333 default:
1334 FIXME("format %u not implemented\n", format);
1335 return STATUS_UNSUPPORTED_COMPRESSION;
1339 /* decompress a single LZNT1 chunk */
1340 static UCHAR *lznt1_decompress_chunk(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size)
1342 UCHAR *src_cur = src, *src_end = src + src_size;
1343 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1344 ULONG displacement_bits, length_bits;
1345 ULONG code_displacement, code_length;
1346 WORD flags, code;
1348 while (src_cur < src_end && dst_cur < dst_end)
1350 flags = 0x8000 | *src_cur++;
1351 while ((flags & 0xff00) && src_cur < src_end)
1353 if (flags & 1)
1355 /* backwards reference */
1356 if (src_cur + sizeof(WORD) > src_end)
1357 return NULL;
1359 code = *(WORD *)src_cur;
1360 src_cur += sizeof(WORD);
1362 /* find length / displacement bits */
1363 for (displacement_bits = 12; displacement_bits > 4; displacement_bits--)
1364 if ((1 << (displacement_bits - 1)) < dst_cur - dst) break;
1366 length_bits = 16 - displacement_bits;
1367 code_length = (code & ((1 << length_bits) - 1)) + 3;
1368 code_displacement = (code >> length_bits) + 1;
1370 if (dst_cur < dst + code_displacement)
1371 return NULL;
1373 /* copy bytes of chunk - we can't use memcpy() since source and dest can
1374 * be overlapping, and the same bytes can be repeated over and over again */
1375 while (code_length--)
1377 if (dst_cur >= dst_end) return dst_cur;
1378 *dst_cur = *(dst_cur - code_displacement);
1379 dst_cur++;
1382 else
1384 /* uncompressed data */
1385 if (dst_cur >= dst_end) return dst_cur;
1386 *dst_cur++ = *src_cur++;
1388 flags >>= 1;
1392 return dst_cur;
1395 /* decompress data encoded with LZNT1 */
1396 static NTSTATUS lznt1_decompress(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size,
1397 ULONG offset, ULONG *final_size, UCHAR *workspace)
1399 UCHAR *src_cur = src, *src_end = src + src_size;
1400 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1401 ULONG chunk_size, block_size;
1402 WORD chunk_header;
1403 UCHAR *ptr;
1405 if (src_cur + sizeof(WORD) > src_end)
1406 return STATUS_BAD_COMPRESSION_BUFFER;
1408 /* skip over chunks with a distance >= 0x1000 to the destination offset */
1409 while (offset >= 0x1000 && src_cur + sizeof(WORD) <= src_end)
1411 chunk_header = *(WORD *)src_cur;
1412 src_cur += sizeof(WORD);
1413 if (!chunk_header) goto out;
1414 chunk_size = (chunk_header & 0xfff) + 1;
1416 if (src_cur + chunk_size > src_end)
1417 return STATUS_BAD_COMPRESSION_BUFFER;
1419 src_cur += chunk_size;
1420 offset -= 0x1000;
1423 /* handle partially included chunk */
1424 if (offset && src_cur + sizeof(WORD) <= src_end)
1426 chunk_header = *(WORD *)src_cur;
1427 src_cur += sizeof(WORD);
1428 if (!chunk_header) goto out;
1429 chunk_size = (chunk_header & 0xfff) + 1;
1431 if (src_cur + chunk_size > src_end)
1432 return STATUS_BAD_COMPRESSION_BUFFER;
1434 if (dst_cur >= dst_end)
1435 goto out;
1437 if (chunk_header & 0x8000)
1439 /* compressed chunk */
1440 if (!workspace) return STATUS_ACCESS_VIOLATION;
1441 ptr = lznt1_decompress_chunk(workspace, 0x1000, src_cur, chunk_size);
1442 if (!ptr) return STATUS_BAD_COMPRESSION_BUFFER;
1443 if (ptr - workspace > offset)
1445 block_size = min((ptr - workspace) - offset, dst_end - dst_cur);
1446 memcpy(dst_cur, workspace + offset, block_size);
1447 dst_cur += block_size;
1450 else
1452 /* uncompressed chunk */
1453 if (chunk_size > offset)
1455 block_size = min(chunk_size - offset, dst_end - dst_cur);
1456 memcpy(dst_cur, src_cur + offset, block_size);
1457 dst_cur += block_size;
1461 src_cur += chunk_size;
1464 /* handle remaining chunks */
1465 while (src_cur + sizeof(WORD) <= src_end)
1467 chunk_header = *(WORD *)src_cur;
1468 src_cur += sizeof(WORD);
1469 if (!chunk_header) goto out;
1470 chunk_size = (chunk_header & 0xfff) + 1;
1472 if (src_cur + chunk_size > src_end)
1473 return STATUS_BAD_COMPRESSION_BUFFER;
1475 /* fill space with padding when the previous chunk was decompressed
1476 * to less than 4096 bytes. no padding is needed for the last chunk
1477 * or when the next chunk is truncated */
1478 block_size = ((dst_cur - dst) + offset) & 0xfff;
1479 if (block_size)
1481 block_size = 0x1000 - block_size;
1482 if (dst_cur + block_size >= dst_end)
1483 goto out;
1484 memset(dst_cur, 0, block_size);
1485 dst_cur += block_size;
1488 if (dst_cur >= dst_end)
1489 goto out;
1491 if (chunk_header & 0x8000)
1493 /* compressed chunk */
1494 dst_cur = lznt1_decompress_chunk(dst_cur, dst_end - dst_cur, src_cur, chunk_size);
1495 if (!dst_cur) return STATUS_BAD_COMPRESSION_BUFFER;
1497 else
1499 /* uncompressed chunk */
1500 block_size = min(chunk_size, dst_end - dst_cur);
1501 memcpy(dst_cur, src_cur, block_size);
1502 dst_cur += block_size;
1505 src_cur += chunk_size;
1508 out:
1509 if (final_size)
1510 *final_size = dst_cur - dst;
1512 return STATUS_SUCCESS;
1516 /******************************************************************************
1517 * RtlDecompressFragment [NTDLL.@]
1519 NTSTATUS WINAPI RtlDecompressFragment(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1520 PUCHAR compressed, ULONG compressed_size, ULONG offset,
1521 PULONG final_size, PVOID workspace)
1523 TRACE("0x%04x, %p, %u, %p, %u, %u, %p, %p\n", format, uncompressed,
1524 uncompressed_size, compressed, compressed_size, offset, final_size, workspace);
1526 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1528 case COMPRESSION_FORMAT_LZNT1:
1529 return lznt1_decompress(uncompressed, uncompressed_size, compressed,
1530 compressed_size, offset, final_size, workspace);
1532 case COMPRESSION_FORMAT_NONE:
1533 case COMPRESSION_FORMAT_DEFAULT:
1534 return STATUS_INVALID_PARAMETER;
1536 default:
1537 FIXME("format %u not implemented\n", format);
1538 return STATUS_UNSUPPORTED_COMPRESSION;
1543 /******************************************************************************
1544 * RtlDecompressBuffer [NTDLL.@]
1546 NTSTATUS WINAPI RtlDecompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1547 PUCHAR compressed, ULONG compressed_size, PULONG final_size)
1549 TRACE("0x%04x, %p, %u, %p, %u, %p\n", format, uncompressed,
1550 uncompressed_size, compressed, compressed_size, final_size);
1552 return RtlDecompressFragment(format, uncompressed, uncompressed_size,
1553 compressed, compressed_size, 0, final_size, NULL);
1556 /***********************************************************************
1557 * RtlSetThreadErrorMode [NTDLL.@]
1559 * Set the thread local error mode.
1561 * PARAMS
1562 * mode [I] The new error mode
1563 * oldmode [O] Destination of the old error mode (may be NULL)
1565 * RETURNS
1566 * Success: STATUS_SUCCESS
1567 * Failure: STATUS_INVALID_PARAMETER_1
1569 NTSTATUS WINAPI RtlSetThreadErrorMode( DWORD mode, LPDWORD oldmode )
1571 if (mode & ~0x70)
1572 return STATUS_INVALID_PARAMETER_1;
1574 if (oldmode)
1575 *oldmode = NtCurrentTeb()->HardErrorDisabled;
1577 NtCurrentTeb()->HardErrorDisabled = mode;
1578 return STATUS_SUCCESS;
1581 /***********************************************************************
1582 * RtlGetThreadErrorMode [NTDLL.@]
1584 * Get the thread local error mode.
1586 * PARAMS
1587 * None.
1589 * RETURNS
1590 * The current thread local error mode.
1592 DWORD WINAPI RtlGetThreadErrorMode( void )
1594 return NtCurrentTeb()->HardErrorDisabled;
1597 /******************************************************************************
1598 * RtlGetCurrentTransaction [NTDLL.@]
1600 HANDLE WINAPI RtlGetCurrentTransaction(void)
1602 FIXME("() :stub\n");
1603 return NULL;
1606 /******************************************************************************
1607 * RtlSetCurrentTransaction [NTDLL.@]
1609 BOOL WINAPI RtlSetCurrentTransaction(HANDLE new_transaction)
1611 FIXME("(%p) :stub\n", new_transaction);
1612 return FALSE;
1615 /**********************************************************************
1616 * RtlGetCurrentProcessorNumberEx [NTDLL.@]
1618 void WINAPI RtlGetCurrentProcessorNumberEx(PROCESSOR_NUMBER *processor)
1620 FIXME("(%p) :semi-stub\n", processor);
1621 processor->Group = 0;
1622 processor->Number = NtGetCurrentProcessorNumber();
1623 processor->Reserved = 0;
1626 /***********************************************************************
1627 * RtlInitializeGenericTableAvl (NTDLL.@)
1629 void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE table, PRTL_AVL_COMPARE_ROUTINE compare,
1630 PRTL_AVL_ALLOCATE_ROUTINE allocate, PRTL_AVL_FREE_ROUTINE free, void *context)
1632 FIXME("%p %p %p %p %p: stub\n", table, compare, allocate, free, context);
1635 /***********************************************************************
1636 * RtlInsertElementGenericTableAvl (NTDLL.@)
1638 void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE table, void *buffer, ULONG size, BOOL *element)
1640 FIXME("%p %p %u %p: stub\n", table, buffer, size, element);
1643 /**********************************************************************
1644 * RtlCreateUserProcess [NTDLL.@]
1646 NTSTATUS WINAPI RtlCreateUserProcess(UNICODE_STRING *path, ULONG attributes, RTL_USER_PROCESS_PARAMETERS *parameters,
1647 SECURITY_DESCRIPTOR *process_descriptor, SECURITY_DESCRIPTOR *thread_descriptor,
1648 HANDLE parent, BOOLEAN inherit, HANDLE debug, HANDLE exception,
1649 RTL_USER_PROCESS_INFORMATION *info)
1651 FIXME("(%p %u %p %p %p %p %d %p %p %p): stub\n", path, attributes, parameters, process_descriptor, thread_descriptor,
1652 parent, inherit, debug, exception, info);
1653 return STATUS_NOT_IMPLEMENTED;