winebus.sys: Add stub driver.
[wine.git] / dlls / ntdll / rtl.c
blob3e985d5d2665e58be9c579d1d2dffe3123f73289
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(LPVOID x1,LPVOID x2,DWORD x3, DWORD x4)
569 FIXME("(%p,%p,0x%08x,0x%08x),stub\n",x1,x2,x3,x4);
572 /*************************************************************************
573 * RtlFillMemoryUlong [NTDLL.@]
575 * Fill memory with a 32 bit (dword) value.
577 * PARAMS
578 * lpDest [I] Bitmap pointer
579 * ulCount [I] Number of dwords to write
580 * ulValue [I] Value to fill with
582 * RETURNS
583 * Nothing.
585 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
587 TRACE("(%p,%d,%d)\n", lpDest, ulCount, ulValue);
589 ulCount /= sizeof(ULONG);
590 while(ulCount--)
591 *lpDest++ = ulValue;
594 /*********************************************************************
595 * RtlComputeCrc32 [NTDLL.@]
597 * Calculate the CRC32 checksum of a block of bytes
599 * PARAMS
600 * dwInitial [I] Initial CRC value
601 * pData [I] Data block
602 * iLen [I] Length of the byte block
604 * RETURNS
605 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
607 DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
609 DWORD crc = ~dwInitial;
611 TRACE("(%d,%p,%d)\n", dwInitial, pData, iLen);
613 while (iLen > 0)
615 crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
616 pData++;
617 iLen--;
619 return ~crc;
623 /*************************************************************************
624 * RtlUlonglongByteSwap [NTDLL.@]
626 * Swap the bytes of an unsigned long long value.
628 * PARAMS
629 * i [I] Value to swap bytes of
631 * RETURNS
632 * The value with its bytes swapped.
634 ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i)
636 return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32);
639 /*************************************************************************
640 * RtlUlongByteSwap [NTDLL.@]
642 * Swap the bytes of an unsigned int value.
644 * NOTES
645 * ix86 version takes argument in %ecx. Other systems use the inline version.
647 #ifdef __i386__
648 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap,
649 "movl %ecx,%eax\n\t"
650 "bswap %eax\n\t"
651 "ret")
652 #endif
654 /*************************************************************************
655 * RtlUshortByteSwap [NTDLL.@]
657 * Swap the bytes of an unsigned short value.
659 * NOTES
660 * i386 version takes argument in %cx. Other systems use the inline version.
662 #ifdef __i386__
663 __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap,
664 "movb %ch,%al\n\t"
665 "movb %cl,%ah\n\t"
666 "ret")
667 #endif
670 /*************************************************************************
671 * RtlUniform [NTDLL.@]
673 * Generates an uniform random number
675 * PARAMS
676 * seed [O] The seed of the Random function
678 * RETURNS
679 * It returns a random number uniformly distributed over [0..MAXLONG-1].
681 * NOTES
682 * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
683 * In our case the algorithm is:
685 *| result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
687 *| *seed = result;
689 * DIFFERENCES
690 * The native documentation states that the random number is
691 * uniformly distributed over [0..MAXLONG]. In reality the native
692 * function and our function return a random number uniformly
693 * distributed over [0..MAXLONG-1].
695 ULONG WINAPI RtlUniform (PULONG seed)
697 ULONG result;
700 * Instead of the algorithm stated above, we use the algorithm
701 * below, which is totally equivalent (see the tests), but does
702 * not use a division and therefore is faster.
704 result = *seed * 0xffffffed + 0x7fffffc3;
705 if (result == 0xffffffff || result == 0x7ffffffe) {
706 result = (result + 2) & MAXLONG;
707 } else if (result == 0x7fffffff) {
708 result = 0;
709 } else if ((result & 0x80000000) == 0) {
710 result = result + (~result & 1);
711 } else {
712 result = (result + (result & 1)) & MAXLONG;
713 } /* if */
714 *seed = result;
715 return result;
719 /*************************************************************************
720 * RtlRandom [NTDLL.@]
722 * Generates a random number
724 * PARAMS
725 * seed [O] The seed of the Random function
727 * RETURNS
728 * It returns a random number distributed over [0..MAXLONG-1].
730 ULONG WINAPI RtlRandom (PULONG seed)
732 static ULONG saved_value[128] =
733 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
734 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
735 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
736 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
737 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
738 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
739 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
740 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
741 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
742 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
743 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
744 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
745 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
746 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
747 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
748 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
749 ULONG rand;
750 int pos;
751 ULONG result;
753 rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
754 *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
755 pos = *seed & 0x7f;
756 result = saved_value[pos];
757 saved_value[pos] = rand;
758 return(result);
762 /*************************************************************************
763 * RtlAreAllAccessesGranted [NTDLL.@]
765 * Check if all desired accesses are granted
767 * RETURNS
768 * TRUE: All desired accesses are granted
769 * FALSE: Otherwise
771 BOOLEAN WINAPI RtlAreAllAccessesGranted(
772 ACCESS_MASK GrantedAccess,
773 ACCESS_MASK DesiredAccess)
775 return (GrantedAccess & DesiredAccess) == DesiredAccess;
779 /*************************************************************************
780 * RtlAreAnyAccessesGranted [NTDLL.@]
782 * Check if at least one of the desired accesses is granted
784 * PARAMS
785 * GrantedAccess [I] Access mask of granted accesses
786 * DesiredAccess [I] Access mask of desired accesses
788 * RETURNS
789 * TRUE: At least one of the desired accesses is granted
790 * FALSE: Otherwise
792 BOOLEAN WINAPI RtlAreAnyAccessesGranted(
793 ACCESS_MASK GrantedAccess,
794 ACCESS_MASK DesiredAccess)
796 return (GrantedAccess & DesiredAccess) != 0;
800 /*************************************************************************
801 * RtlMapGenericMask [NTDLL.@]
803 * Determine the nongeneric access rights specified by an access mask
805 * RETURNS
806 * Nothing.
808 void WINAPI RtlMapGenericMask(
809 PACCESS_MASK AccessMask,
810 const GENERIC_MAPPING *GenericMapping)
812 if (*AccessMask & GENERIC_READ) {
813 *AccessMask |= GenericMapping->GenericRead;
814 } /* if */
816 if (*AccessMask & GENERIC_WRITE) {
817 *AccessMask |= GenericMapping->GenericWrite;
818 } /* if */
820 if (*AccessMask & GENERIC_EXECUTE) {
821 *AccessMask |= GenericMapping->GenericExecute;
822 } /* if */
824 if (*AccessMask & GENERIC_ALL) {
825 *AccessMask |= GenericMapping->GenericAll;
826 } /* if */
828 *AccessMask &= 0x0FFFFFFF;
832 /*************************************************************************
833 * RtlCopyLuid [NTDLL.@]
835 * Copy a local unique ID.
837 * PARAMS
838 * LuidDest [O] Destination for the copied Luid
839 * LuidSrc [I] Source Luid to copy to LuidDest
841 * RETURNS
842 * Nothing.
844 void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc)
846 *LuidDest = *LuidSrc;
850 /*************************************************************************
851 * RtlEqualLuid [NTDLL.@]
853 * Compare two local unique IDs.
855 * PARAMS
856 * Luid1 [I] First Luid to compare to Luid2
857 * Luid2 [I] Second Luid to compare to Luid1
859 * RETURNS
860 * TRUE: The two LUIDs are equal.
861 * FALSE: Otherwise
863 BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2)
865 return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart);
869 /*************************************************************************
870 * RtlCopyLuidAndAttributesArray [NTDLL.@]
872 * Copy an array of local unique IDs and attributes.
874 * PARAMS
875 * Count [I] Number of Luid/attributes in Src
876 * Src [I] Source Luid/attributes to copy
877 * Dest [O] Destination for copied Luid/attributes
879 * RETURNS
880 * Nothing.
882 * NOTES
883 * Dest must be large enough to hold Src.
885 void WINAPI RtlCopyLuidAndAttributesArray(
886 ULONG Count,
887 const LUID_AND_ATTRIBUTES *Src,
888 PLUID_AND_ATTRIBUTES Dest)
890 ULONG i;
892 for (i = 0; i < Count; i++) Dest[i] = Src[i];
895 NTSTATUS WINAPI RtlIpv4StringToAddressExW(PULONG IP, PULONG Port,
896 LPCWSTR Buffer, PULONG MaxSize)
898 FIXME("(%p,%p,%p,%p): stub\n", IP, Port, Buffer, MaxSize);
900 return STATUS_SUCCESS;
903 /***********************************************************************
904 * RtlIpv4AddressToStringExW [NTDLL.@]
906 * Convert the given ipv4 address and optional the port to a string
908 * PARAMS
909 * pin [I] PTR to the ip address to convert (network byte order)
910 * port [I] optional port to convert (network byte order)
911 * buffer [O] destination buffer for the result
912 * psize [IO] PTR to available/used size of the destination buffer
914 * RETURNS
915 * Success: STATUS_SUCCESS
916 * Failure: STATUS_INVALID_PARAMETER
919 NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
921 WCHAR tmp_ip[32];
922 static const WCHAR fmt_ip[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
923 static const WCHAR fmt_port[] = {':','%','u',0};
924 ULONG needed;
926 if (!pin || !buffer || !psize)
927 return STATUS_INVALID_PARAMETER;
929 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
931 needed = sprintfW(tmp_ip, fmt_ip,
932 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
933 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
935 if (port) needed += sprintfW(tmp_ip + needed, fmt_port, ntohs(port));
937 if (*psize > needed) {
938 *psize = needed + 1;
939 strcpyW(buffer, tmp_ip);
940 return STATUS_SUCCESS;
943 *psize = needed + 1;
944 return STATUS_INVALID_PARAMETER;
947 /***********************************************************************
948 * RtlIpv4AddressToStringExA [NTDLL.@]
950 * Convert the given ipv4 address and optional the port to a string
952 * See RtlIpv4AddressToStringExW
954 NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
956 CHAR tmp_ip[32];
957 ULONG needed;
959 if (!pin || !buffer || !psize)
960 return STATUS_INVALID_PARAMETER;
962 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
964 needed = sprintf(tmp_ip, "%u.%u.%u.%u",
965 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
966 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
968 if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
970 if (*psize > needed) {
971 *psize = needed + 1;
972 strcpy(buffer, tmp_ip);
973 return STATUS_SUCCESS;
976 *psize = needed + 1;
977 return STATUS_INVALID_PARAMETER;
980 /***********************************************************************
981 * RtlIpv4AddressToStringW [NTDLL.@]
983 * Convert the given ipv4 address to a string
985 * PARAMS
986 * pin [I] PTR to the ip address to convert (network byte order)
987 * buffer [O] destination buffer for the result (at least 16 character)
989 * RETURNS
990 * PTR to the 0 character at the end of the converted string
993 WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
995 ULONG size = 16;
997 if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
998 return buffer + size - 1;
1001 /***********************************************************************
1002 * RtlIpv4AddressToStringA [NTDLL.@]
1004 * Convert the given ipv4 address to a string
1006 * See RtlIpv4AddressToStringW
1008 CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
1010 ULONG size = 16;
1012 if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
1013 return buffer + size - 1;
1016 /***********************************************************************
1017 * get_pointer_obfuscator (internal)
1019 static DWORD_PTR get_pointer_obfuscator( void )
1021 static DWORD_PTR pointer_obfuscator;
1023 if (!pointer_obfuscator)
1025 ULONG seed = NtGetTickCount();
1026 ULONG_PTR rand;
1028 /* generate a random value for the obfuscator */
1029 rand = RtlUniform( &seed );
1031 /* handle 64bit pointers */
1032 rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1034 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1035 rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1037 interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator, (void*) rand, NULL );
1040 return pointer_obfuscator;
1043 /*************************************************************************
1044 * RtlEncodePointer [NTDLL.@]
1046 PVOID WINAPI RtlEncodePointer( PVOID ptr )
1048 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1049 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1052 PVOID WINAPI RtlDecodePointer( PVOID ptr )
1054 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1055 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1058 /*************************************************************************
1059 * RtlInitializeSListHead [NTDLL.@]
1061 VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
1063 #ifdef _WIN64
1064 list->s.Alignment = list->s.Region = 0;
1065 list->Header16.HeaderType = 1; /* we use the 16-byte header */
1066 #else
1067 list->Alignment = 0;
1068 #endif
1071 /*************************************************************************
1072 * RtlQueryDepthSList [NTDLL.@]
1074 WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
1076 #ifdef _WIN64
1077 return list->Header16.Depth;
1078 #else
1079 return list->s.Depth;
1080 #endif
1083 /*************************************************************************
1084 * RtlFirstEntrySList [NTDLL.@]
1086 PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
1088 #ifdef _WIN64
1089 return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
1090 #else
1091 return list->s.Next.Next;
1092 #endif
1095 /*************************************************************************
1096 * RtlInterlockedFlushSList [NTDLL.@]
1098 PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
1100 SLIST_HEADER old, new;
1102 #ifdef _WIN64
1103 if (!list->Header16.NextEntry) return NULL;
1104 new.s.Alignment = new.s.Region = 0;
1105 new.Header16.HeaderType = 1; /* we use the 16-byte header */
1108 old = *list;
1109 new.Header16.Sequence = old.Header16.Sequence + 1;
1110 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1111 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1112 #else
1113 if (!list->s.Next.Next) return NULL;
1114 new.Alignment = 0;
1117 old = *list;
1118 new.s.Sequence = old.s.Sequence + 1;
1119 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1120 old.Alignment) != old.Alignment);
1121 return old.s.Next.Next;
1122 #endif
1125 /*************************************************************************
1126 * RtlInterlockedPushEntrySList [NTDLL.@]
1128 PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
1130 SLIST_HEADER old, new;
1132 #ifdef _WIN64
1133 new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
1136 old = *list;
1137 entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1138 new.Header16.Depth = old.Header16.Depth + 1;
1139 new.Header16.Sequence = old.Header16.Sequence + 1;
1140 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1141 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1142 #else
1143 new.s.Next.Next = entry;
1146 old = *list;
1147 entry->Next = old.s.Next.Next;
1148 new.s.Depth = old.s.Depth + 1;
1149 new.s.Sequence = old.s.Sequence + 1;
1150 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1151 old.Alignment) != old.Alignment);
1152 return old.s.Next.Next;
1153 #endif
1156 /*************************************************************************
1157 * RtlInterlockedPopEntrySList [NTDLL.@]
1159 PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
1161 SLIST_HEADER old, new;
1162 PSLIST_ENTRY entry;
1164 #ifdef _WIN64
1167 old = *list;
1168 if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
1169 /* entry could be deleted by another thread */
1170 __TRY
1172 new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
1173 new.Header16.Depth = old.Header16.Depth - 1;
1174 new.Header16.Sequence = old.Header16.Sequence + 1;
1176 __EXCEPT_PAGE_FAULT
1179 __ENDTRY
1180 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1181 #else
1184 old = *list;
1185 if (!(entry = old.s.Next.Next)) return NULL;
1186 /* entry could be deleted by another thread */
1187 __TRY
1189 new.s.Next.Next = entry->Next;
1190 new.s.Depth = old.s.Depth - 1;
1191 new.s.Sequence = old.s.Sequence + 1;
1193 __EXCEPT_PAGE_FAULT
1196 __ENDTRY
1197 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1198 old.Alignment) != old.Alignment);
1199 #endif
1200 return entry;
1203 /*************************************************************************
1204 * RtlInterlockedPushListSListEx [NTDLL.@]
1206 PSLIST_ENTRY WINAPI RtlInterlockedPushListSListEx(PSLIST_HEADER list, PSLIST_ENTRY first,
1207 PSLIST_ENTRY last, ULONG count)
1209 SLIST_HEADER old, new;
1211 #ifdef _WIN64
1212 new.Header16.NextEntry = (ULONG_PTR)first >> 4;
1215 old = *list;
1216 new.Header16.Depth = old.Header16.Depth + count;
1217 new.Header16.Sequence = old.Header16.Sequence + 1;
1218 last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1219 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1220 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1221 #else
1222 new.s.Next.Next = first;
1225 old = *list;
1226 new.s.Depth = old.s.Depth + count;
1227 new.s.Sequence = old.s.Sequence + 1;
1228 last->Next = old.s.Next.Next;
1229 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1230 old.Alignment) != old.Alignment);
1231 return old.s.Next.Next;
1232 #endif
1235 /*************************************************************************
1236 * RtlInterlockedPushListSList [NTDLL.@]
1238 #ifdef DEFINE_FASTCALL4_ENTRYPOINT
1239 DEFINE_FASTCALL4_ENTRYPOINT(RtlInterlockedPushListSList)
1240 PSLIST_ENTRY WINAPI __regs_RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1241 PSLIST_ENTRY last, ULONG count)
1242 #else
1243 PSLIST_ENTRY WINAPI RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1244 PSLIST_ENTRY last, ULONG count)
1245 #endif
1247 return RtlInterlockedPushListSListEx(list, first, last, count);
1250 /******************************************************************************
1251 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1253 NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT format, PULONG compress_workspace,
1254 PULONG decompress_workspace)
1256 FIXME("0x%04x, %p, %p: semi-stub\n", format, compress_workspace, decompress_workspace);
1258 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1260 case COMPRESSION_FORMAT_LZNT1:
1261 if (compress_workspace)
1263 /* FIXME: The current implementation of RtlCompressBuffer does not use a
1264 * workspace buffer, but Windows applications might expect a nonzero value. */
1265 *compress_workspace = 16;
1267 if (decompress_workspace)
1268 *decompress_workspace = 0x1000;
1269 return STATUS_SUCCESS;
1271 case COMPRESSION_FORMAT_NONE:
1272 case COMPRESSION_FORMAT_DEFAULT:
1273 return STATUS_INVALID_PARAMETER;
1275 default:
1276 FIXME("format %u not implemented\n", format);
1277 return STATUS_UNSUPPORTED_COMPRESSION;
1281 /* compress data using LZNT1, currently only a stub */
1282 static NTSTATUS lznt1_compress(UCHAR *src, ULONG src_size, UCHAR *dst, ULONG dst_size,
1283 ULONG chunk_size, ULONG *final_size, UCHAR *workspace)
1285 UCHAR *src_cur = src, *src_end = src + src_size;
1286 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1287 ULONG block_size;
1289 while (src_cur < src_end)
1291 /* determine size of current chunk */
1292 block_size = min(0x1000, src_end - src_cur);
1293 if (dst_cur + sizeof(WORD) + block_size > dst_end)
1294 return STATUS_BUFFER_TOO_SMALL;
1296 /* write (uncompressed) chunk header */
1297 *(WORD *)dst_cur = 0x3000 | (block_size - 1);
1298 dst_cur += sizeof(WORD);
1300 /* write chunk content */
1301 memcpy(dst_cur, src_cur, block_size);
1302 dst_cur += block_size;
1303 src_cur += block_size;
1306 if (final_size)
1307 *final_size = dst_cur - dst;
1309 return STATUS_SUCCESS;
1312 /******************************************************************************
1313 * RtlCompressBuffer [NTDLL.@]
1315 NTSTATUS WINAPI RtlCompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1316 PUCHAR compressed, ULONG compressed_size, ULONG chunk_size,
1317 PULONG final_size, PVOID workspace)
1319 FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p: semi-stub\n", format, uncompressed,
1320 uncompressed_size, compressed, compressed_size, chunk_size, final_size, workspace);
1322 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1324 case COMPRESSION_FORMAT_LZNT1:
1325 return lznt1_compress(uncompressed, uncompressed_size, compressed,
1326 compressed_size, chunk_size, final_size, workspace);
1328 case COMPRESSION_FORMAT_NONE:
1329 case COMPRESSION_FORMAT_DEFAULT:
1330 return STATUS_INVALID_PARAMETER;
1332 default:
1333 FIXME("format %u not implemented\n", format);
1334 return STATUS_UNSUPPORTED_COMPRESSION;
1338 /* decompress a single LZNT1 chunk */
1339 static UCHAR *lznt1_decompress_chunk(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size)
1341 UCHAR *src_cur = src, *src_end = src + src_size;
1342 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1343 ULONG displacement_bits, length_bits;
1344 ULONG code_displacement, code_length;
1345 WORD flags, code;
1347 while (src_cur < src_end && dst_cur < dst_end)
1349 flags = 0x8000 | *src_cur++;
1350 while ((flags & 0xff00) && src_cur < src_end)
1352 if (flags & 1)
1354 /* backwards reference */
1355 if (src_cur + sizeof(WORD) > src_end)
1356 return NULL;
1358 code = *(WORD *)src_cur;
1359 src_cur += sizeof(WORD);
1361 /* find length / displacement bits */
1362 for (displacement_bits = 12; displacement_bits > 4; displacement_bits--)
1363 if ((1 << (displacement_bits - 1)) < dst_cur - dst) break;
1365 length_bits = 16 - displacement_bits;
1366 code_length = (code & ((1 << length_bits) - 1)) + 3;
1367 code_displacement = (code >> length_bits) + 1;
1369 if (dst_cur < dst + code_displacement)
1370 return NULL;
1372 /* copy bytes of chunk - we can't use memcpy() since source and dest can
1373 * be overlapping, and the same bytes can be repeated over and over again */
1374 while (code_length--)
1376 if (dst_cur >= dst_end) return dst_cur;
1377 *dst_cur = *(dst_cur - code_displacement);
1378 dst_cur++;
1381 else
1383 /* uncompressed data */
1384 if (dst_cur >= dst_end) return dst_cur;
1385 *dst_cur++ = *src_cur++;
1387 flags >>= 1;
1391 return dst_cur;
1394 /* decompress data encoded with LZNT1 */
1395 static NTSTATUS lznt1_decompress(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size,
1396 ULONG offset, ULONG *final_size, UCHAR *workspace)
1398 UCHAR *src_cur = src, *src_end = src + src_size;
1399 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1400 ULONG chunk_size, block_size;
1401 WORD chunk_header;
1402 UCHAR *ptr;
1404 if (src_cur + sizeof(WORD) > src_end)
1405 return STATUS_BAD_COMPRESSION_BUFFER;
1407 /* skip over chunks with a distance >= 0x1000 to the destination offset */
1408 while (offset >= 0x1000 && src_cur + sizeof(WORD) <= src_end)
1410 chunk_header = *(WORD *)src_cur;
1411 src_cur += sizeof(WORD);
1412 if (!chunk_header) goto out;
1413 chunk_size = (chunk_header & 0xfff) + 1;
1415 if (src_cur + chunk_size > src_end)
1416 return STATUS_BAD_COMPRESSION_BUFFER;
1418 src_cur += chunk_size;
1419 offset -= 0x1000;
1422 /* handle partially included chunk */
1423 if (offset && src_cur + sizeof(WORD) <= src_end)
1425 chunk_header = *(WORD *)src_cur;
1426 src_cur += sizeof(WORD);
1427 if (!chunk_header) goto out;
1428 chunk_size = (chunk_header & 0xfff) + 1;
1430 if (src_cur + chunk_size > src_end)
1431 return STATUS_BAD_COMPRESSION_BUFFER;
1433 if (dst_cur >= dst_end)
1434 goto out;
1436 if (chunk_header & 0x8000)
1438 /* compressed chunk */
1439 if (!workspace) return STATUS_ACCESS_VIOLATION;
1440 ptr = lznt1_decompress_chunk(workspace, 0x1000, src_cur, chunk_size);
1441 if (!ptr) return STATUS_BAD_COMPRESSION_BUFFER;
1442 if (ptr - workspace > offset)
1444 block_size = min((ptr - workspace) - offset, dst_end - dst_cur);
1445 memcpy(dst_cur, workspace + offset, block_size);
1446 dst_cur += block_size;
1449 else
1451 /* uncompressed chunk */
1452 if (chunk_size > offset)
1454 block_size = min(chunk_size - offset, dst_end - dst_cur);
1455 memcpy(dst_cur, src_cur + offset, block_size);
1456 dst_cur += block_size;
1460 src_cur += chunk_size;
1463 /* handle remaining chunks */
1464 while (src_cur + sizeof(WORD) <= src_end)
1466 chunk_header = *(WORD *)src_cur;
1467 src_cur += sizeof(WORD);
1468 if (!chunk_header) goto out;
1469 chunk_size = (chunk_header & 0xfff) + 1;
1471 if (src_cur + chunk_size > src_end)
1472 return STATUS_BAD_COMPRESSION_BUFFER;
1474 /* fill space with padding when the previous chunk was decompressed
1475 * to less than 4096 bytes. no padding is needed for the last chunk
1476 * or when the next chunk is truncated */
1477 block_size = ((dst_cur - dst) + offset) & 0xfff;
1478 if (block_size)
1480 block_size = 0x1000 - block_size;
1481 if (dst_cur + block_size >= dst_end)
1482 goto out;
1483 memset(dst_cur, 0, block_size);
1484 dst_cur += block_size;
1487 if (dst_cur >= dst_end)
1488 goto out;
1490 if (chunk_header & 0x8000)
1492 /* compressed chunk */
1493 dst_cur = lznt1_decompress_chunk(dst_cur, dst_end - dst_cur, src_cur, chunk_size);
1494 if (!dst_cur) return STATUS_BAD_COMPRESSION_BUFFER;
1496 else
1498 /* uncompressed chunk */
1499 block_size = min(chunk_size, dst_end - dst_cur);
1500 memcpy(dst_cur, src_cur, block_size);
1501 dst_cur += block_size;
1504 src_cur += chunk_size;
1507 out:
1508 if (final_size)
1509 *final_size = dst_cur - dst;
1511 return STATUS_SUCCESS;
1515 /******************************************************************************
1516 * RtlDecompressFragment [NTDLL.@]
1518 NTSTATUS WINAPI RtlDecompressFragment(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1519 PUCHAR compressed, ULONG compressed_size, ULONG offset,
1520 PULONG final_size, PVOID workspace)
1522 TRACE("0x%04x, %p, %u, %p, %u, %u, %p, %p\n", format, uncompressed,
1523 uncompressed_size, compressed, compressed_size, offset, final_size, workspace);
1525 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1527 case COMPRESSION_FORMAT_LZNT1:
1528 return lznt1_decompress(uncompressed, uncompressed_size, compressed,
1529 compressed_size, offset, final_size, workspace);
1531 case COMPRESSION_FORMAT_NONE:
1532 case COMPRESSION_FORMAT_DEFAULT:
1533 return STATUS_INVALID_PARAMETER;
1535 default:
1536 FIXME("format %u not implemented\n", format);
1537 return STATUS_UNSUPPORTED_COMPRESSION;
1542 /******************************************************************************
1543 * RtlDecompressBuffer [NTDLL.@]
1545 NTSTATUS WINAPI RtlDecompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1546 PUCHAR compressed, ULONG compressed_size, PULONG final_size)
1548 TRACE("0x%04x, %p, %u, %p, %u, %p\n", format, uncompressed,
1549 uncompressed_size, compressed, compressed_size, final_size);
1551 return RtlDecompressFragment(format, uncompressed, uncompressed_size,
1552 compressed, compressed_size, 0, final_size, NULL);
1555 /***********************************************************************
1556 * RtlSetThreadErrorMode [NTDLL.@]
1558 * Set the thread local error mode.
1560 * PARAMS
1561 * mode [I] The new error mode
1562 * oldmode [O] Destination of the old error mode (may be NULL)
1564 * RETURNS
1565 * Success: STATUS_SUCCESS
1566 * Failure: STATUS_INVALID_PARAMETER_1
1568 NTSTATUS WINAPI RtlSetThreadErrorMode( DWORD mode, LPDWORD oldmode )
1570 if (mode & ~0x70)
1571 return STATUS_INVALID_PARAMETER_1;
1573 if (oldmode)
1574 *oldmode = NtCurrentTeb()->HardErrorDisabled;
1576 NtCurrentTeb()->HardErrorDisabled = mode;
1577 return STATUS_SUCCESS;
1580 /***********************************************************************
1581 * RtlGetThreadErrorMode [NTDLL.@]
1583 * Get the thread local error mode.
1585 * PARAMS
1586 * None.
1588 * RETURNS
1589 * The current thread local error mode.
1591 DWORD WINAPI RtlGetThreadErrorMode( void )
1593 return NtCurrentTeb()->HardErrorDisabled;
1596 /******************************************************************************
1597 * RtlGetCurrentTransaction [NTDLL.@]
1599 HANDLE WINAPI RtlGetCurrentTransaction(void)
1601 FIXME("() :stub\n");
1602 return NULL;
1605 /******************************************************************************
1606 * RtlSetCurrentTransaction [NTDLL.@]
1608 BOOL WINAPI RtlSetCurrentTransaction(HANDLE new_transaction)
1610 FIXME("(%p) :stub\n", new_transaction);
1611 return FALSE;
1614 /**********************************************************************
1615 * RtlGetCurrentProcessorNumberEx [NTDLL.@]
1617 void WINAPI RtlGetCurrentProcessorNumberEx(PROCESSOR_NUMBER *processor)
1619 FIXME("(%p) :semi-stub\n", processor);
1620 processor->Group = 0;
1621 processor->Number = NtGetCurrentProcessorNumber();
1622 processor->Reserved = 0;
1625 /***********************************************************************
1626 * RtlInitializeGenericTableAvl (NTDLL.@)
1628 void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE table, PRTL_AVL_COMPARE_ROUTINE compare,
1629 PRTL_AVL_ALLOCATE_ROUTINE allocate, PRTL_AVL_FREE_ROUTINE free, void *context)
1631 FIXME("%p %p %p %p %p: stub\n", table, compare, allocate, free, context);
1634 /***********************************************************************
1635 * RtlInsertElementGenericTableAvl (NTDLL.@)
1637 void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE table, void *buffer, ULONG size, BOOL *element)
1639 FIXME("%p %p %u %p: stub\n", table, buffer, size, element);
1642 /**********************************************************************
1643 * RtlCreateUserProcess [NTDLL.@]
1645 NTSTATUS WINAPI RtlCreateUserProcess(UNICODE_STRING *path, ULONG attributes, RTL_USER_PROCESS_PARAMETERS *parameters,
1646 SECURITY_DESCRIPTOR *process_descriptor, SECURITY_DESCRIPTOR *thread_descriptor,
1647 HANDLE parent, BOOLEAN inherit, HANDLE debug, HANDLE exception,
1648 RTL_USER_PROCESS_INFORMATION *info)
1650 FIXME("(%p %u %p %p %p %p %d %p %p %p): stub\n", path, attributes, parameters, process_descriptor, thread_descriptor,
1651 parent, inherit, debug, exception, info);
1652 return STATUS_NOT_IMPLEMENTED;