ntdll: Add RtlCreateUserProcess stub.
[wine.git] / dlls / ntdll / rtl.c
blobf699cff9a10617b95303876cd832e3ff14f74971
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 /* CRC polynomial 0xedb88320 */
62 static const DWORD CRC_table[256] =
64 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
65 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
66 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
67 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
68 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
69 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
70 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
71 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
72 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
73 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
74 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
75 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
76 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
77 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
78 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
79 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
80 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
81 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
82 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
83 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
84 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
85 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
86 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
87 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
88 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
89 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
90 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
91 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
92 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
93 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
94 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
95 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
96 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
97 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
98 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
99 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
100 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
101 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
102 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
103 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
104 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
105 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
106 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
110 * resource functions
113 /***********************************************************************
114 * RtlInitializeResource (NTDLL.@)
116 * xxxResource() functions implement multiple-reader-single-writer lock.
117 * The code is based on information published in WDJ January 1999 issue.
119 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
121 if( rwl )
123 rwl->iNumberActive = 0;
124 rwl->uExclusiveWaiters = 0;
125 rwl->uSharedWaiters = 0;
126 rwl->hOwningThreadId = 0;
127 rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
128 RtlInitializeCriticalSection( &rwl->rtlCS );
129 rwl->rtlCS.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RTL_RWLOCK.rtlCS");
130 NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
131 NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
136 /***********************************************************************
137 * RtlDeleteResource (NTDLL.@)
139 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
141 if( rwl )
143 RtlEnterCriticalSection( &rwl->rtlCS );
144 if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
145 ERR("Deleting active MRSW lock (%p), expect failure\n", rwl );
146 rwl->hOwningThreadId = 0;
147 rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
148 rwl->iNumberActive = 0;
149 NtClose( rwl->hExclusiveReleaseSemaphore );
150 NtClose( rwl->hSharedReleaseSemaphore );
151 RtlLeaveCriticalSection( &rwl->rtlCS );
152 rwl->rtlCS.DebugInfo->Spare[0] = 0;
153 RtlDeleteCriticalSection( &rwl->rtlCS );
158 /***********************************************************************
159 * RtlAcquireResourceExclusive (NTDLL.@)
161 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
163 BYTE retVal = 0;
164 if( !rwl ) return 0;
166 start:
167 RtlEnterCriticalSection( &rwl->rtlCS );
168 if( rwl->iNumberActive == 0 ) /* lock is free */
170 rwl->iNumberActive = -1;
171 retVal = 1;
173 else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
175 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
177 retVal = 1;
178 rwl->iNumberActive--;
179 goto done;
181 wait:
182 if( fWait )
184 NTSTATUS status;
186 rwl->uExclusiveWaiters++;
188 RtlLeaveCriticalSection( &rwl->rtlCS );
189 status = NtWaitForSingleObject( rwl->hExclusiveReleaseSemaphore, FALSE, NULL );
190 if( HIWORD(status) )
191 goto done;
192 goto start; /* restart the acquisition to avoid deadlocks */
195 else /* one or more shared locks are in progress */
196 if( fWait )
197 goto wait;
199 if( retVal == 1 )
200 rwl->hOwningThreadId = ULongToHandle(GetCurrentThreadId());
201 done:
202 RtlLeaveCriticalSection( &rwl->rtlCS );
203 return retVal;
206 /***********************************************************************
207 * RtlAcquireResourceShared (NTDLL.@)
209 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
211 NTSTATUS status = STATUS_UNSUCCESSFUL;
212 BYTE retVal = 0;
213 if( !rwl ) return 0;
215 start:
216 RtlEnterCriticalSection( &rwl->rtlCS );
217 if( rwl->iNumberActive < 0 )
219 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
221 rwl->iNumberActive--;
222 retVal = 1;
223 goto done;
226 if( fWait )
228 rwl->uSharedWaiters++;
229 RtlLeaveCriticalSection( &rwl->rtlCS );
230 status = NtWaitForSingleObject( rwl->hSharedReleaseSemaphore, FALSE, NULL );
231 if( HIWORD(status) )
232 goto done;
233 goto start;
236 else
238 if( status != STATUS_WAIT_0 ) /* otherwise RtlReleaseResource() has already done it */
239 rwl->iNumberActive++;
240 retVal = 1;
242 done:
243 RtlLeaveCriticalSection( &rwl->rtlCS );
244 return retVal;
248 /***********************************************************************
249 * RtlReleaseResource (NTDLL.@)
251 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
253 RtlEnterCriticalSection( &rwl->rtlCS );
255 if( rwl->iNumberActive > 0 ) /* have one or more readers */
257 if( --rwl->iNumberActive == 0 )
259 if( rwl->uExclusiveWaiters )
261 wake_exclusive:
262 rwl->uExclusiveWaiters--;
263 NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
267 else
268 if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
270 if( ++rwl->iNumberActive == 0 )
272 rwl->hOwningThreadId = 0;
273 if( rwl->uExclusiveWaiters )
274 goto wake_exclusive;
275 else
276 if( rwl->uSharedWaiters )
278 UINT n = rwl->uSharedWaiters;
279 rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
280 * all queued readers have done their thing */
281 rwl->uSharedWaiters = 0;
282 NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
286 RtlLeaveCriticalSection( &rwl->rtlCS );
290 /***********************************************************************
291 * RtlDumpResource (NTDLL.@)
293 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
295 if( rwl )
297 MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
298 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
299 if( rwl->iNumberActive )
300 MESSAGE("\towner thread = %p\n", rwl->hOwningThreadId );
305 * misc functions
308 /******************************************************************************
309 * DbgPrint [NTDLL.@]
311 NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...)
313 char buf[512];
314 __ms_va_list args;
316 __ms_va_start(args, fmt);
317 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
318 __ms_va_end(args);
320 MESSAGE("DbgPrint says: %s",buf);
321 /* hmm, raise exception? */
322 return STATUS_SUCCESS;
326 /******************************************************************************
327 * DbgPrintEx [NTDLL.@]
329 NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...)
331 NTSTATUS ret;
332 __ms_va_list args;
334 __ms_va_start(args, fmt);
335 ret = vDbgPrintEx(iComponentId, Level, fmt, args);
336 __ms_va_end(args);
337 return ret;
340 /******************************************************************************
341 * vDbgPrintEx [NTDLL.@]
343 NTSTATUS WINAPI vDbgPrintEx( ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
345 return vDbgPrintExWithPrefix( "", id, level, fmt, args );
348 /******************************************************************************
349 * vDbgPrintExWithPrefix [NTDLL.@]
351 NTSTATUS WINAPI vDbgPrintExWithPrefix( LPCSTR prefix, ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
353 char buf[1024];
355 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
357 switch (level & DPFLTR_MASK)
359 case DPFLTR_ERROR_LEVEL: ERR("%s%x: %s", prefix, id, buf); break;
360 case DPFLTR_WARNING_LEVEL: WARN("%s%x: %s", prefix, id, buf); break;
361 case DPFLTR_TRACE_LEVEL:
362 case DPFLTR_INFO_LEVEL:
363 default: TRACE("%s%x: %s", prefix, id, buf); break;
365 return STATUS_SUCCESS;
368 /******************************************************************************
369 * RtlAcquirePebLock [NTDLL.@]
371 VOID WINAPI RtlAcquirePebLock(void)
373 RtlEnterCriticalSection( &peb_lock );
376 /******************************************************************************
377 * RtlReleasePebLock [NTDLL.@]
379 VOID WINAPI RtlReleasePebLock(void)
381 RtlLeaveCriticalSection( &peb_lock );
384 /******************************************************************************
385 * RtlNewSecurityObject [NTDLL.@]
387 NTSTATUS WINAPI
388 RtlNewSecurityObject( PSECURITY_DESCRIPTOR ParentDescriptor,
389 PSECURITY_DESCRIPTOR CreatorDescriptor,
390 PSECURITY_DESCRIPTOR *NewDescriptor,
391 BOOLEAN IsDirectoryObject,
392 HANDLE Token,
393 PGENERIC_MAPPING GenericMapping )
395 FIXME("(%p %p %p %d %p %p) stub!\n", ParentDescriptor, CreatorDescriptor,
396 NewDescriptor, IsDirectoryObject, Token, GenericMapping);
397 return STATUS_NOT_IMPLEMENTED;
400 /******************************************************************************
401 * RtlDeleteSecurityObject [NTDLL.@]
403 NTSTATUS WINAPI
404 RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR *ObjectDescriptor )
406 FIXME("(%p) stub!\n", ObjectDescriptor);
407 return STATUS_NOT_IMPLEMENTED;
410 /******************************************************************************
411 * RtlInitializeGenericTable [NTDLL.@]
413 PVOID WINAPI RtlInitializeGenericTable(PVOID pTable, PVOID arg2, PVOID arg3, PVOID arg4, PVOID arg5)
415 FIXME("(%p,%p,%p,%p,%p) stub!\n", pTable, arg2, arg3, arg4, arg5);
416 return NULL;
419 /******************************************************************************
420 * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
422 PVOID RtlEnumerateGenericTableWithoutSplaying(PVOID pTable, PVOID *RestartKey)
424 static int warn_once;
426 if (!warn_once++)
427 FIXME("(%p,%p) stub!\n", pTable, RestartKey);
428 return NULL;
431 /******************************************************************************
432 * RtlNumberGenericTableElements [NTDLL.@]
434 ULONG RtlNumberGenericTableElements(PVOID pTable)
436 FIXME("(%p) stub!\n", pTable);
437 return 0;
440 /******************************************************************************
441 * RtlMoveMemory [NTDLL.@]
443 * Move a block of memory that may overlap.
445 * PARAMS
446 * Destination [O] End destination for block
447 * Source [O] Where to start copying from
448 * Length [I] Number of bytes to copy
450 * RETURNS
451 * Nothing.
453 #undef RtlMoveMemory
454 VOID WINAPI RtlMoveMemory( void *Destination, const void *Source, SIZE_T Length )
456 memmove(Destination, Source, Length);
459 /******************************************************************************
460 * RtlFillMemory [NTDLL.@]
462 * Set a block of memory with a value.
464 * PARAMS
465 * Destination [O] Block to fill
466 * Length [I] Number of bytes to fill
467 * Fill [I] Value to set
469 * RETURNS
470 * Nothing.
472 #undef RtlFillMemory
473 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
475 memset(Destination, Fill, Length);
478 /******************************************************************************
479 * RtlZeroMemory [NTDLL.@]
481 * Set a block of memory with 0's.
483 * PARAMS
484 * Destination [O] Block to fill
485 * Length [I] Number of bytes to fill
487 * RETURNS
488 * Nothing.
490 #undef RtlZeroMemory
491 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
493 memset(Destination, 0, Length);
496 /******************************************************************************
497 * RtlCompareMemory [NTDLL.@]
499 * Compare one block of memory with another
501 * PARAMS
502 * Source1 [I] Source block
503 * Source2 [I] Block to compare to Source1
504 * Length [I] Number of bytes to compare
506 * RETURNS
507 * The length of the first byte at which Source1 and Source2 differ, or Length
508 * if they are the same.
510 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
512 SIZE_T i;
513 for(i=0; (i<Length) && (((const BYTE*)Source1)[i]==((const BYTE*)Source2)[i]); i++);
514 return i;
517 /******************************************************************************
518 * RtlCompareMemoryUlong [NTDLL.@]
520 * Compare a block of memory with a value, a ULONG at a time
522 * PARAMS
523 * Source1 [I] Source block. This must be ULONG aligned
524 * Length [I] Number of bytes to compare. This should be a multiple of 4
525 * dwVal [I] Value to compare to
527 * RETURNS
528 * The byte position of the first byte at which Source1 is not dwVal.
530 SIZE_T WINAPI RtlCompareMemoryUlong(const ULONG *Source1, SIZE_T Length, ULONG dwVal)
532 SIZE_T i;
533 for(i = 0; i < Length/sizeof(ULONG) && Source1[i] == dwVal; i++);
534 return i * sizeof(ULONG);
537 /******************************************************************************
538 * RtlCopyMemory [NTDLL.@]
540 #undef RtlCopyMemory
541 void WINAPI RtlCopyMemory(void *dest, const void *src, SIZE_T len)
543 memcpy(dest, src, len);
546 /******************************************************************************
547 * RtlAssert [NTDLL.@]
549 * Fail a debug assertion.
551 * RETURNS
552 * Nothing. This call does not return control to its caller.
554 * NOTES
555 * Not implemented in non-debug versions.
557 void WINAPI RtlAssert(LPVOID x1,LPVOID x2,DWORD x3, DWORD x4)
559 FIXME("(%p,%p,0x%08x,0x%08x),stub\n",x1,x2,x3,x4);
562 /*************************************************************************
563 * RtlFillMemoryUlong [NTDLL.@]
565 * Fill memory with a 32 bit (dword) value.
567 * PARAMS
568 * lpDest [I] Bitmap pointer
569 * ulCount [I] Number of dwords to write
570 * ulValue [I] Value to fill with
572 * RETURNS
573 * Nothing.
575 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
577 TRACE("(%p,%d,%d)\n", lpDest, ulCount, ulValue);
579 ulCount /= sizeof(ULONG);
580 while(ulCount--)
581 *lpDest++ = ulValue;
584 /*********************************************************************
585 * RtlComputeCrc32 [NTDLL.@]
587 * Calculate the CRC32 checksum of a block of bytes
589 * PARAMS
590 * dwInitial [I] Initial CRC value
591 * pData [I] Data block
592 * iLen [I] Length of the byte block
594 * RETURNS
595 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
597 DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
599 DWORD crc = ~dwInitial;
601 TRACE("(%d,%p,%d)\n", dwInitial, pData, iLen);
603 while (iLen > 0)
605 crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
606 pData++;
607 iLen--;
609 return ~crc;
613 /*************************************************************************
614 * RtlUlonglongByteSwap [NTDLL.@]
616 * Swap the bytes of an unsigned long long value.
618 * PARAMS
619 * i [I] Value to swap bytes of
621 * RETURNS
622 * The value with its bytes swapped.
624 ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i)
626 return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32);
629 /*************************************************************************
630 * RtlUlongByteSwap [NTDLL.@]
632 * Swap the bytes of an unsigned int value.
634 * NOTES
635 * ix86 version takes argument in %ecx. Other systems use the inline version.
637 #ifdef __i386__
638 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap,
639 "movl %ecx,%eax\n\t"
640 "bswap %eax\n\t"
641 "ret")
642 #endif
644 /*************************************************************************
645 * RtlUshortByteSwap [NTDLL.@]
647 * Swap the bytes of an unsigned short value.
649 * NOTES
650 * i386 version takes argument in %cx. Other systems use the inline version.
652 #ifdef __i386__
653 __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap,
654 "movb %ch,%al\n\t"
655 "movb %cl,%ah\n\t"
656 "ret")
657 #endif
660 /*************************************************************************
661 * RtlUniform [NTDLL.@]
663 * Generates an uniform random number
665 * PARAMS
666 * seed [O] The seed of the Random function
668 * RETURNS
669 * It returns a random number uniformly distributed over [0..MAXLONG-1].
671 * NOTES
672 * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
673 * In our case the algorithm is:
675 *| result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
677 *| *seed = result;
679 * DIFFERENCES
680 * The native documentation states that the random number is
681 * uniformly distributed over [0..MAXLONG]. In reality the native
682 * function and our function return a random number uniformly
683 * distributed over [0..MAXLONG-1].
685 ULONG WINAPI RtlUniform (PULONG seed)
687 ULONG result;
690 * Instead of the algorithm stated above, we use the algorithm
691 * below, which is totally equivalent (see the tests), but does
692 * not use a division and therefore is faster.
694 result = *seed * 0xffffffed + 0x7fffffc3;
695 if (result == 0xffffffff || result == 0x7ffffffe) {
696 result = (result + 2) & MAXLONG;
697 } else if (result == 0x7fffffff) {
698 result = 0;
699 } else if ((result & 0x80000000) == 0) {
700 result = result + (~result & 1);
701 } else {
702 result = (result + (result & 1)) & MAXLONG;
703 } /* if */
704 *seed = result;
705 return result;
709 /*************************************************************************
710 * RtlRandom [NTDLL.@]
712 * Generates a random number
714 * PARAMS
715 * seed [O] The seed of the Random function
717 * RETURNS
718 * It returns a random number distributed over [0..MAXLONG-1].
720 ULONG WINAPI RtlRandom (PULONG seed)
722 static ULONG saved_value[128] =
723 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
724 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
725 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
726 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
727 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
728 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
729 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
730 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
731 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
732 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
733 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
734 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
735 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
736 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
737 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
738 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
739 ULONG rand;
740 int pos;
741 ULONG result;
743 rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
744 *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
745 pos = *seed & 0x7f;
746 result = saved_value[pos];
747 saved_value[pos] = rand;
748 return(result);
752 /*************************************************************************
753 * RtlAreAllAccessesGranted [NTDLL.@]
755 * Check if all desired accesses are granted
757 * RETURNS
758 * TRUE: All desired accesses are granted
759 * FALSE: Otherwise
761 BOOLEAN WINAPI RtlAreAllAccessesGranted(
762 ACCESS_MASK GrantedAccess,
763 ACCESS_MASK DesiredAccess)
765 return (GrantedAccess & DesiredAccess) == DesiredAccess;
769 /*************************************************************************
770 * RtlAreAnyAccessesGranted [NTDLL.@]
772 * Check if at least one of the desired accesses is granted
774 * PARAMS
775 * GrantedAccess [I] Access mask of granted accesses
776 * DesiredAccess [I] Access mask of desired accesses
778 * RETURNS
779 * TRUE: At least one of the desired accesses is granted
780 * FALSE: Otherwise
782 BOOLEAN WINAPI RtlAreAnyAccessesGranted(
783 ACCESS_MASK GrantedAccess,
784 ACCESS_MASK DesiredAccess)
786 return (GrantedAccess & DesiredAccess) != 0;
790 /*************************************************************************
791 * RtlMapGenericMask [NTDLL.@]
793 * Determine the nongeneric access rights specified by an access mask
795 * RETURNS
796 * Nothing.
798 void WINAPI RtlMapGenericMask(
799 PACCESS_MASK AccessMask,
800 const GENERIC_MAPPING *GenericMapping)
802 if (*AccessMask & GENERIC_READ) {
803 *AccessMask |= GenericMapping->GenericRead;
804 } /* if */
806 if (*AccessMask & GENERIC_WRITE) {
807 *AccessMask |= GenericMapping->GenericWrite;
808 } /* if */
810 if (*AccessMask & GENERIC_EXECUTE) {
811 *AccessMask |= GenericMapping->GenericExecute;
812 } /* if */
814 if (*AccessMask & GENERIC_ALL) {
815 *AccessMask |= GenericMapping->GenericAll;
816 } /* if */
818 *AccessMask &= 0x0FFFFFFF;
822 /*************************************************************************
823 * RtlCopyLuid [NTDLL.@]
825 * Copy a local unique ID.
827 * PARAMS
828 * LuidDest [O] Destination for the copied Luid
829 * LuidSrc [I] Source Luid to copy to LuidDest
831 * RETURNS
832 * Nothing.
834 void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc)
836 *LuidDest = *LuidSrc;
840 /*************************************************************************
841 * RtlEqualLuid [NTDLL.@]
843 * Compare two local unique IDs.
845 * PARAMS
846 * Luid1 [I] First Luid to compare to Luid2
847 * Luid2 [I] Second Luid to compare to Luid1
849 * RETURNS
850 * TRUE: The two LUIDs are equal.
851 * FALSE: Otherwise
853 BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2)
855 return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart);
859 /*************************************************************************
860 * RtlCopyLuidAndAttributesArray [NTDLL.@]
862 * Copy an array of local unique IDs and attributes.
864 * PARAMS
865 * Count [I] Number of Luid/attributes in Src
866 * Src [I] Source Luid/attributes to copy
867 * Dest [O] Destination for copied Luid/attributes
869 * RETURNS
870 * Nothing.
872 * NOTES
873 * Dest must be large enough to hold Src.
875 void WINAPI RtlCopyLuidAndAttributesArray(
876 ULONG Count,
877 const LUID_AND_ATTRIBUTES *Src,
878 PLUID_AND_ATTRIBUTES Dest)
880 ULONG i;
882 for (i = 0; i < Count; i++) Dest[i] = Src[i];
885 NTSTATUS WINAPI RtlIpv4StringToAddressExW(PULONG IP, PULONG Port,
886 LPCWSTR Buffer, PULONG MaxSize)
888 FIXME("(%p,%p,%p,%p): stub\n", IP, Port, Buffer, MaxSize);
890 return STATUS_SUCCESS;
893 /***********************************************************************
894 * RtlIpv4AddressToStringExW [NTDLL.@]
896 * Convert the given ipv4 address and optional the port to a string
898 * PARAMS
899 * pin [I] PTR to the ip address to convert (network byte order)
900 * port [I] optional port to convert (network byte order)
901 * buffer [O] destination buffer for the result
902 * psize [IO] PTR to available/used size of the destination buffer
904 * RETURNS
905 * Success: STATUS_SUCCESS
906 * Failure: STATUS_INVALID_PARAMETER
909 NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
911 WCHAR tmp_ip[32];
912 static const WCHAR fmt_ip[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
913 static const WCHAR fmt_port[] = {':','%','u',0};
914 ULONG needed;
916 if (!pin || !buffer || !psize)
917 return STATUS_INVALID_PARAMETER;
919 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
921 needed = sprintfW(tmp_ip, fmt_ip,
922 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
923 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
925 if (port) needed += sprintfW(tmp_ip + needed, fmt_port, ntohs(port));
927 if (*psize > needed) {
928 *psize = needed + 1;
929 strcpyW(buffer, tmp_ip);
930 return STATUS_SUCCESS;
933 *psize = needed + 1;
934 return STATUS_INVALID_PARAMETER;
937 /***********************************************************************
938 * RtlIpv4AddressToStringExA [NTDLL.@]
940 * Convert the given ipv4 address and optional the port to a string
942 * See RtlIpv4AddressToStringExW
944 NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
946 CHAR tmp_ip[32];
947 ULONG needed;
949 if (!pin || !buffer || !psize)
950 return STATUS_INVALID_PARAMETER;
952 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
954 needed = sprintf(tmp_ip, "%u.%u.%u.%u",
955 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
956 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
958 if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
960 if (*psize > needed) {
961 *psize = needed + 1;
962 strcpy(buffer, tmp_ip);
963 return STATUS_SUCCESS;
966 *psize = needed + 1;
967 return STATUS_INVALID_PARAMETER;
970 /***********************************************************************
971 * RtlIpv4AddressToStringW [NTDLL.@]
973 * Convert the given ipv4 address to a string
975 * PARAMS
976 * pin [I] PTR to the ip address to convert (network byte order)
977 * buffer [O] destination buffer for the result (at least 16 character)
979 * RETURNS
980 * PTR to the 0 character at the end of the converted string
983 WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
985 ULONG size = 16;
987 if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
988 return buffer + size - 1;
991 /***********************************************************************
992 * RtlIpv4AddressToStringA [NTDLL.@]
994 * Convert the given ipv4 address to a string
996 * See RtlIpv4AddressToStringW
998 CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
1000 ULONG size = 16;
1002 if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
1003 return buffer + size - 1;
1006 /***********************************************************************
1007 * get_pointer_obfuscator (internal)
1009 static DWORD_PTR get_pointer_obfuscator( void )
1011 static DWORD_PTR pointer_obfuscator;
1013 if (!pointer_obfuscator)
1015 ULONG seed = NtGetTickCount();
1016 ULONG_PTR rand;
1018 /* generate a random value for the obfuscator */
1019 rand = RtlUniform( &seed );
1021 /* handle 64bit pointers */
1022 rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1024 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1025 rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1027 interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator, (void*) rand, NULL );
1030 return pointer_obfuscator;
1033 /*************************************************************************
1034 * RtlEncodePointer [NTDLL.@]
1036 PVOID WINAPI RtlEncodePointer( PVOID ptr )
1038 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1039 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1042 PVOID WINAPI RtlDecodePointer( PVOID ptr )
1044 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1045 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1048 /*************************************************************************
1049 * RtlInitializeSListHead [NTDLL.@]
1051 VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
1053 #ifdef _WIN64
1054 list->s.Alignment = list->s.Region = 0;
1055 list->Header16.HeaderType = 1; /* we use the 16-byte header */
1056 #else
1057 list->Alignment = 0;
1058 #endif
1061 /*************************************************************************
1062 * RtlQueryDepthSList [NTDLL.@]
1064 WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
1066 #ifdef _WIN64
1067 return list->Header16.Depth;
1068 #else
1069 return list->s.Depth;
1070 #endif
1073 /*************************************************************************
1074 * RtlFirstEntrySList [NTDLL.@]
1076 PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
1078 #ifdef _WIN64
1079 return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
1080 #else
1081 return list->s.Next.Next;
1082 #endif
1085 /*************************************************************************
1086 * RtlInterlockedFlushSList [NTDLL.@]
1088 PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
1090 SLIST_HEADER old, new;
1092 #ifdef _WIN64
1093 if (!list->Header16.NextEntry) return NULL;
1094 new.s.Alignment = new.s.Region = 0;
1095 new.Header16.HeaderType = 1; /* we use the 16-byte header */
1098 old = *list;
1099 new.Header16.Sequence = old.Header16.Sequence + 1;
1100 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1101 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1102 #else
1103 if (!list->s.Next.Next) return NULL;
1104 new.Alignment = 0;
1107 old = *list;
1108 new.s.Sequence = old.s.Sequence + 1;
1109 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1110 old.Alignment) != old.Alignment);
1111 return old.s.Next.Next;
1112 #endif
1115 /*************************************************************************
1116 * RtlInterlockedPushEntrySList [NTDLL.@]
1118 PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
1120 SLIST_HEADER old, new;
1122 #ifdef _WIN64
1123 new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
1126 old = *list;
1127 entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1128 new.Header16.Depth = old.Header16.Depth + 1;
1129 new.Header16.Sequence = old.Header16.Sequence + 1;
1130 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1131 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1132 #else
1133 new.s.Next.Next = entry;
1136 old = *list;
1137 entry->Next = old.s.Next.Next;
1138 new.s.Depth = old.s.Depth + 1;
1139 new.s.Sequence = old.s.Sequence + 1;
1140 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1141 old.Alignment) != old.Alignment);
1142 return old.s.Next.Next;
1143 #endif
1146 /*************************************************************************
1147 * RtlInterlockedPopEntrySList [NTDLL.@]
1149 PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
1151 SLIST_HEADER old, new;
1152 PSLIST_ENTRY entry;
1154 #ifdef _WIN64
1157 old = *list;
1158 if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
1159 /* entry could be deleted by another thread */
1160 __TRY
1162 new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
1163 new.Header16.Depth = old.Header16.Depth - 1;
1164 new.Header16.Sequence = old.Header16.Sequence + 1;
1166 __EXCEPT_PAGE_FAULT
1169 __ENDTRY
1170 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1171 #else
1174 old = *list;
1175 if (!(entry = old.s.Next.Next)) return NULL;
1176 /* entry could be deleted by another thread */
1177 __TRY
1179 new.s.Next.Next = entry->Next;
1180 new.s.Depth = old.s.Depth - 1;
1181 new.s.Sequence = old.s.Sequence + 1;
1183 __EXCEPT_PAGE_FAULT
1186 __ENDTRY
1187 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1188 old.Alignment) != old.Alignment);
1189 #endif
1190 return entry;
1193 /*************************************************************************
1194 * RtlInterlockedPushListSList [NTDLL.@]
1196 PSLIST_ENTRY WINAPI RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1197 PSLIST_ENTRY last, ULONG count)
1199 SLIST_HEADER old, new;
1201 #ifdef _WIN64
1202 new.Header16.NextEntry = (ULONG_PTR)first >> 4;
1205 old = *list;
1206 new.Header16.Depth = old.Header16.Depth + count;
1207 new.Header16.Sequence = old.Header16.Sequence + 1;
1208 last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1209 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1210 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1211 #else
1212 new.s.Next.Next = first;
1215 old = *list;
1216 new.s.Depth = old.s.Depth + count;
1217 new.s.Sequence = old.s.Sequence + 1;
1218 last->Next = old.s.Next.Next;
1219 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1220 old.Alignment) != old.Alignment);
1221 return old.s.Next.Next;
1222 #endif
1225 /******************************************************************************
1226 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1228 NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT format, PULONG compress_workspace,
1229 PULONG decompress_workspace)
1231 FIXME("0x%04x, %p, %p: semi-stub\n", format, compress_workspace, decompress_workspace);
1233 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1235 case COMPRESSION_FORMAT_LZNT1:
1236 if (compress_workspace)
1238 /* FIXME: The current implementation of RtlCompressBuffer does not use a
1239 * workspace buffer, but Windows applications might expect a nonzero value. */
1240 *compress_workspace = 16;
1242 if (decompress_workspace)
1243 *decompress_workspace = 0x1000;
1244 return STATUS_SUCCESS;
1246 case COMPRESSION_FORMAT_NONE:
1247 case COMPRESSION_FORMAT_DEFAULT:
1248 return STATUS_INVALID_PARAMETER;
1250 default:
1251 FIXME("format %u not implemented\n", format);
1252 return STATUS_UNSUPPORTED_COMPRESSION;
1256 /* compress data using LZNT1, currently only a stub */
1257 static NTSTATUS lznt1_compress(UCHAR *src, ULONG src_size, UCHAR *dst, ULONG dst_size,
1258 ULONG chunk_size, ULONG *final_size, UCHAR *workspace)
1260 UCHAR *src_cur = src, *src_end = src + src_size;
1261 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1262 ULONG block_size;
1264 while (src_cur < src_end)
1266 /* determine size of current chunk */
1267 block_size = min(0x1000, src_end - src_cur);
1268 if (dst_cur + sizeof(WORD) + block_size > dst_end)
1269 return STATUS_BUFFER_TOO_SMALL;
1271 /* write (uncompressed) chunk header */
1272 *(WORD *)dst_cur = 0x3000 | (block_size - 1);
1273 dst_cur += sizeof(WORD);
1275 /* write chunk content */
1276 memcpy(dst_cur, src_cur, block_size);
1277 dst_cur += block_size;
1278 src_cur += block_size;
1281 if (final_size)
1282 *final_size = dst_cur - dst;
1284 return STATUS_SUCCESS;
1287 /******************************************************************************
1288 * RtlCompressBuffer [NTDLL.@]
1290 NTSTATUS WINAPI RtlCompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1291 PUCHAR compressed, ULONG compressed_size, ULONG chunk_size,
1292 PULONG final_size, PVOID workspace)
1294 FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p: semi-stub\n", format, uncompressed,
1295 uncompressed_size, compressed, compressed_size, chunk_size, final_size, workspace);
1297 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1299 case COMPRESSION_FORMAT_LZNT1:
1300 return lznt1_compress(uncompressed, uncompressed_size, compressed,
1301 compressed_size, chunk_size, final_size, workspace);
1303 case COMPRESSION_FORMAT_NONE:
1304 case COMPRESSION_FORMAT_DEFAULT:
1305 return STATUS_INVALID_PARAMETER;
1307 default:
1308 FIXME("format %u not implemented\n", format);
1309 return STATUS_UNSUPPORTED_COMPRESSION;
1313 /* decompress a single LZNT1 chunk */
1314 static UCHAR *lznt1_decompress_chunk(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size)
1316 UCHAR *src_cur = src, *src_end = src + src_size;
1317 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1318 ULONG displacement_bits, length_bits;
1319 ULONG code_displacement, code_length;
1320 WORD flags, code;
1322 while (src_cur < src_end && dst_cur < dst_end)
1324 flags = 0x8000 | *src_cur++;
1325 while ((flags & 0xff00) && src_cur < src_end)
1327 if (flags & 1)
1329 /* backwards reference */
1330 if (src_cur + sizeof(WORD) > src_end)
1331 return NULL;
1333 code = *(WORD *)src_cur;
1334 src_cur += sizeof(WORD);
1336 /* find length / displacement bits */
1337 for (displacement_bits = 12; displacement_bits > 4; displacement_bits--)
1338 if ((1 << (displacement_bits - 1)) < dst_cur - dst) break;
1340 length_bits = 16 - displacement_bits;
1341 code_length = (code & ((1 << length_bits) - 1)) + 3;
1342 code_displacement = (code >> length_bits) + 1;
1344 if (dst_cur < dst + code_displacement)
1345 return NULL;
1347 /* copy bytes of chunk - we can't use memcpy() since source and dest can
1348 * be overlapping, and the same bytes can be repeated over and over again */
1349 while (code_length--)
1351 if (dst_cur >= dst_end) return dst_cur;
1352 *dst_cur = *(dst_cur - code_displacement);
1353 dst_cur++;
1356 else
1358 /* uncompressed data */
1359 if (dst_cur >= dst_end) return dst_cur;
1360 *dst_cur++ = *src_cur++;
1362 flags >>= 1;
1366 return dst_cur;
1369 /* decompress data encoded with LZNT1 */
1370 static NTSTATUS lznt1_decompress(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size,
1371 ULONG offset, ULONG *final_size, UCHAR *workspace)
1373 UCHAR *src_cur = src, *src_end = src + src_size;
1374 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1375 ULONG chunk_size, block_size;
1376 WORD chunk_header;
1377 UCHAR *ptr;
1379 if (src_cur + sizeof(WORD) > src_end)
1380 return STATUS_BAD_COMPRESSION_BUFFER;
1382 /* skip over chunks with a distance >= 0x1000 to the destination offset */
1383 while (offset >= 0x1000 && src_cur + sizeof(WORD) <= src_end)
1385 chunk_header = *(WORD *)src_cur;
1386 src_cur += sizeof(WORD);
1387 if (!chunk_header) goto out;
1388 chunk_size = (chunk_header & 0xfff) + 1;
1390 if (src_cur + chunk_size > src_end)
1391 return STATUS_BAD_COMPRESSION_BUFFER;
1393 src_cur += chunk_size;
1394 offset -= 0x1000;
1397 /* handle partially included chunk */
1398 if (offset && src_cur + sizeof(WORD) <= src_end)
1400 chunk_header = *(WORD *)src_cur;
1401 src_cur += sizeof(WORD);
1402 if (!chunk_header) goto out;
1403 chunk_size = (chunk_header & 0xfff) + 1;
1405 if (src_cur + chunk_size > src_end)
1406 return STATUS_BAD_COMPRESSION_BUFFER;
1408 if (dst_cur >= dst_end)
1409 goto out;
1411 if (chunk_header & 0x8000)
1413 /* compressed chunk */
1414 if (!workspace) return STATUS_ACCESS_VIOLATION;
1415 ptr = lznt1_decompress_chunk(workspace, 0x1000, src_cur, chunk_size);
1416 if (!ptr) return STATUS_BAD_COMPRESSION_BUFFER;
1417 if (ptr - workspace > offset)
1419 block_size = min((ptr - workspace) - offset, dst_end - dst_cur);
1420 memcpy(dst_cur, workspace + offset, block_size);
1421 dst_cur += block_size;
1424 else
1426 /* uncompressed chunk */
1427 if (chunk_size > offset)
1429 block_size = min(chunk_size - offset, dst_end - dst_cur);
1430 memcpy(dst_cur, src_cur + offset, block_size);
1431 dst_cur += block_size;
1435 src_cur += chunk_size;
1438 /* handle remaining chunks */
1439 while (src_cur + sizeof(WORD) <= src_end)
1441 chunk_header = *(WORD *)src_cur;
1442 src_cur += sizeof(WORD);
1443 if (!chunk_header) goto out;
1444 chunk_size = (chunk_header & 0xfff) + 1;
1446 if (src_cur + chunk_size > src_end)
1447 return STATUS_BAD_COMPRESSION_BUFFER;
1449 /* fill space with padding when the previous chunk was decompressed
1450 * to less than 4096 bytes. no padding is needed for the last chunk
1451 * or when the next chunk is truncated */
1452 block_size = ((dst_cur - dst) + offset) & 0xfff;
1453 if (block_size)
1455 block_size = 0x1000 - block_size;
1456 if (dst_cur + block_size >= dst_end)
1457 goto out;
1458 memset(dst_cur, 0, block_size);
1459 dst_cur += block_size;
1462 if (dst_cur >= dst_end)
1463 goto out;
1465 if (chunk_header & 0x8000)
1467 /* compressed chunk */
1468 dst_cur = lznt1_decompress_chunk(dst_cur, dst_end - dst_cur, src_cur, chunk_size);
1469 if (!dst_cur) return STATUS_BAD_COMPRESSION_BUFFER;
1471 else
1473 /* uncompressed chunk */
1474 block_size = min(chunk_size, dst_end - dst_cur);
1475 memcpy(dst_cur, src_cur, block_size);
1476 dst_cur += block_size;
1479 src_cur += chunk_size;
1482 out:
1483 if (final_size)
1484 *final_size = dst_cur - dst;
1486 return STATUS_SUCCESS;
1490 /******************************************************************************
1491 * RtlDecompressFragment [NTDLL.@]
1493 NTSTATUS WINAPI RtlDecompressFragment(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1494 PUCHAR compressed, ULONG compressed_size, ULONG offset,
1495 PULONG final_size, PVOID workspace)
1497 TRACE("0x%04x, %p, %u, %p, %u, %u, %p, %p\n", format, uncompressed,
1498 uncompressed_size, compressed, compressed_size, offset, final_size, workspace);
1500 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1502 case COMPRESSION_FORMAT_LZNT1:
1503 return lznt1_decompress(uncompressed, uncompressed_size, compressed,
1504 compressed_size, offset, final_size, workspace);
1506 case COMPRESSION_FORMAT_NONE:
1507 case COMPRESSION_FORMAT_DEFAULT:
1508 return STATUS_INVALID_PARAMETER;
1510 default:
1511 FIXME("format %u not implemented\n", format);
1512 return STATUS_UNSUPPORTED_COMPRESSION;
1517 /******************************************************************************
1518 * RtlDecompressBuffer [NTDLL.@]
1520 NTSTATUS WINAPI RtlDecompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1521 PUCHAR compressed, ULONG compressed_size, PULONG final_size)
1523 TRACE("0x%04x, %p, %u, %p, %u, %p\n", format, uncompressed,
1524 uncompressed_size, compressed, compressed_size, final_size);
1526 return RtlDecompressFragment(format, uncompressed, uncompressed_size,
1527 compressed, compressed_size, 0, final_size, NULL);
1530 /***********************************************************************
1531 * RtlSetThreadErrorMode [NTDLL.@]
1533 * Set the thread local error mode.
1535 * PARAMS
1536 * mode [I] The new error mode
1537 * oldmode [O] Destination of the old error mode (may be NULL)
1539 * RETURNS
1540 * Success: STATUS_SUCCESS
1541 * Failure: STATUS_INVALID_PARAMETER_1
1543 NTSTATUS WINAPI RtlSetThreadErrorMode( DWORD mode, LPDWORD oldmode )
1545 if (mode & ~0x70)
1546 return STATUS_INVALID_PARAMETER_1;
1548 if (oldmode)
1549 *oldmode = NtCurrentTeb()->HardErrorDisabled;
1551 NtCurrentTeb()->HardErrorDisabled = mode;
1552 return STATUS_SUCCESS;
1555 /***********************************************************************
1556 * RtlGetThreadErrorMode [NTDLL.@]
1558 * Get the thread local error mode.
1560 * PARAMS
1561 * None.
1563 * RETURNS
1564 * The current thread local error mode.
1566 DWORD WINAPI RtlGetThreadErrorMode( void )
1568 return NtCurrentTeb()->HardErrorDisabled;
1571 /******************************************************************************
1572 * RtlGetCurrentTransaction [NTDLL.@]
1574 HANDLE WINAPI RtlGetCurrentTransaction(void)
1576 FIXME("() :stub\n");
1577 return NULL;
1580 /******************************************************************************
1581 * RtlSetCurrentTransaction [NTDLL.@]
1583 BOOL WINAPI RtlSetCurrentTransaction(HANDLE new_transaction)
1585 FIXME("(%p) :stub\n", new_transaction);
1586 return FALSE;
1589 /**********************************************************************
1590 * RtlGetCurrentProcessorNumberEx [NTDLL.@]
1592 void WINAPI RtlGetCurrentProcessorNumberEx(PROCESSOR_NUMBER *processor)
1594 FIXME("(%p) :semi-stub\n", processor);
1595 processor->Group = 0;
1596 processor->Number = NtGetCurrentProcessorNumber();
1597 processor->Reserved = 0;
1600 /***********************************************************************
1601 * RtlInitializeGenericTableAvl (NTDLL.@)
1603 void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE table, PRTL_AVL_COMPARE_ROUTINE compare,
1604 PRTL_AVL_ALLOCATE_ROUTINE allocate, PRTL_AVL_FREE_ROUTINE free, void *context)
1606 FIXME("%p %p %p %p %p: stub\n", table, compare, allocate, free, context);
1609 /***********************************************************************
1610 * RtlInsertElementGenericTableAvl (NTDLL.@)
1612 void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE table, void *buffer, ULONG size, BOOL *element)
1614 FIXME("%p %p %u %p: stub\n", table, buffer, size, element);
1617 /**********************************************************************
1618 * RtlCreateUserProcess [NTDLL.@]
1620 NTSTATUS WINAPI RtlCreateUserProcess(UNICODE_STRING *path, ULONG attributes, RTL_USER_PROCESS_PARAMETERS *parameters,
1621 SECURITY_DESCRIPTOR *process_descriptor, SECURITY_DESCRIPTOR *thread_descriptor,
1622 HANDLE parent, BOOLEAN inherit, HANDLE debug, HANDLE exception,
1623 RTL_USER_PROCESS_INFORMATION *info)
1625 FIXME("(%p %u %p %p %p %p %d %p %p %p): stub\n", path, attributes, parameters, process_descriptor, thread_descriptor,
1626 parent, inherit, debug, exception, info);
1627 return STATUS_NOT_IMPLEMENTED;