TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / ntdll / rtl.c
blob8eb3e9f017d73a388e8ac20d0982e426e9ee44d9
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"
49 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
51 static RTL_CRITICAL_SECTION peb_lock;
52 static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
54 0, 0, &peb_lock,
55 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
56 0, 0, { (DWORD_PTR)(__FILE__ ": peb_lock") }
58 static RTL_CRITICAL_SECTION peb_lock = { &critsect_debug, -1, 0, 0, 0, 0 };
60 /* CRC polynomial 0xedb88320 */
61 static const DWORD CRC_table[256] =
63 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
64 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
65 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
66 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
67 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
68 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
69 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
70 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
71 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
72 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
73 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
74 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
75 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
76 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
77 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
78 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
79 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
80 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
81 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
82 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
83 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
84 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
85 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
86 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
87 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
88 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
89 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
90 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
91 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
92 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
93 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
94 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
95 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
96 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
97 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
98 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
99 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
100 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
101 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
102 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
103 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
104 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
105 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
109 * resource functions
112 /***********************************************************************
113 * RtlInitializeResource (NTDLL.@)
115 * xxxResource() functions implement multiple-reader-single-writer lock.
116 * The code is based on information published in WDJ January 1999 issue.
118 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
120 if( rwl )
122 rwl->iNumberActive = 0;
123 rwl->uExclusiveWaiters = 0;
124 rwl->uSharedWaiters = 0;
125 rwl->hOwningThreadId = 0;
126 rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
127 RtlInitializeCriticalSection( &rwl->rtlCS );
128 rwl->rtlCS.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RTL_RWLOCK.rtlCS");
129 NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
130 NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
135 /***********************************************************************
136 * RtlDeleteResource (NTDLL.@)
138 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
140 if( rwl )
142 RtlEnterCriticalSection( &rwl->rtlCS );
143 if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
144 ERR("Deleting active MRSW lock (%p), expect failure\n", rwl );
145 rwl->hOwningThreadId = 0;
146 rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
147 rwl->iNumberActive = 0;
148 NtClose( rwl->hExclusiveReleaseSemaphore );
149 NtClose( rwl->hSharedReleaseSemaphore );
150 RtlLeaveCriticalSection( &rwl->rtlCS );
151 rwl->rtlCS.DebugInfo->Spare[0] = 0;
152 RtlDeleteCriticalSection( &rwl->rtlCS );
157 /***********************************************************************
158 * RtlAcquireResourceExclusive (NTDLL.@)
160 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
162 BYTE retVal = 0;
163 if( !rwl ) return 0;
165 start:
166 RtlEnterCriticalSection( &rwl->rtlCS );
167 if( rwl->iNumberActive == 0 ) /* lock is free */
169 rwl->iNumberActive = -1;
170 retVal = 1;
172 else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
174 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
176 retVal = 1;
177 rwl->iNumberActive--;
178 goto done;
180 wait:
181 if( fWait )
183 NTSTATUS status;
185 rwl->uExclusiveWaiters++;
187 RtlLeaveCriticalSection( &rwl->rtlCS );
188 status = NtWaitForSingleObject( rwl->hExclusiveReleaseSemaphore, FALSE, NULL );
189 if( HIWORD(status) )
190 goto done;
191 goto start; /* restart the acquisition to avoid deadlocks */
194 else /* one or more shared locks are in progress */
195 if( fWait )
196 goto wait;
198 if( retVal == 1 )
199 rwl->hOwningThreadId = ULongToHandle(GetCurrentThreadId());
200 done:
201 RtlLeaveCriticalSection( &rwl->rtlCS );
202 return retVal;
205 /***********************************************************************
206 * RtlAcquireResourceShared (NTDLL.@)
208 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
210 NTSTATUS status = STATUS_UNSUCCESSFUL;
211 BYTE retVal = 0;
212 if( !rwl ) return 0;
214 start:
215 RtlEnterCriticalSection( &rwl->rtlCS );
216 if( rwl->iNumberActive < 0 )
218 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
220 rwl->iNumberActive--;
221 retVal = 1;
222 goto done;
225 if( fWait )
227 rwl->uSharedWaiters++;
228 RtlLeaveCriticalSection( &rwl->rtlCS );
229 status = NtWaitForSingleObject( rwl->hSharedReleaseSemaphore, FALSE, NULL );
230 if( HIWORD(status) )
231 goto done;
232 goto start;
235 else
237 if( status != STATUS_WAIT_0 ) /* otherwise RtlReleaseResource() has already done it */
238 rwl->iNumberActive++;
239 retVal = 1;
241 done:
242 RtlLeaveCriticalSection( &rwl->rtlCS );
243 return retVal;
247 /***********************************************************************
248 * RtlReleaseResource (NTDLL.@)
250 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
252 RtlEnterCriticalSection( &rwl->rtlCS );
254 if( rwl->iNumberActive > 0 ) /* have one or more readers */
256 if( --rwl->iNumberActive == 0 )
258 if( rwl->uExclusiveWaiters )
260 wake_exclusive:
261 rwl->uExclusiveWaiters--;
262 NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
266 else
267 if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
269 if( ++rwl->iNumberActive == 0 )
271 rwl->hOwningThreadId = 0;
272 if( rwl->uExclusiveWaiters )
273 goto wake_exclusive;
274 else
275 if( rwl->uSharedWaiters )
277 UINT n = rwl->uSharedWaiters;
278 rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
279 * all queued readers have done their thing */
280 rwl->uSharedWaiters = 0;
281 NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
285 RtlLeaveCriticalSection( &rwl->rtlCS );
289 /***********************************************************************
290 * RtlDumpResource (NTDLL.@)
292 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
294 if( rwl )
296 MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
297 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
298 if( rwl->iNumberActive )
299 MESSAGE("\towner thread = %p\n", rwl->hOwningThreadId );
304 * misc functions
307 /******************************************************************************
308 * DbgPrint [NTDLL.@]
310 NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...)
312 char buf[512];
313 __ms_va_list args;
315 __ms_va_start(args, fmt);
316 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
317 __ms_va_end(args);
319 MESSAGE("DbgPrint says: %s",buf);
320 /* hmm, raise exception? */
321 return STATUS_SUCCESS;
325 /******************************************************************************
326 * DbgPrintEx [NTDLL.@]
328 NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...)
330 NTSTATUS ret;
331 __ms_va_list args;
333 __ms_va_start(args, fmt);
334 ret = vDbgPrintEx(iComponentId, Level, fmt, args);
335 __ms_va_end(args);
336 return ret;
339 /******************************************************************************
340 * vDbgPrintEx [NTDLL.@]
342 NTSTATUS WINAPI vDbgPrintEx( ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
344 return vDbgPrintExWithPrefix( "", id, level, fmt, args );
347 /******************************************************************************
348 * vDbgPrintExWithPrefix [NTDLL.@]
350 NTSTATUS WINAPI vDbgPrintExWithPrefix( LPCSTR prefix, ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
352 char buf[1024];
354 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
356 switch (level & DPFLTR_MASK)
358 case DPFLTR_ERROR_LEVEL: ERR("%s%x: %s", prefix, id, buf); break;
359 case DPFLTR_WARNING_LEVEL: WARN("%s%x: %s", prefix, id, buf); break;
360 case DPFLTR_TRACE_LEVEL:
361 case DPFLTR_INFO_LEVEL:
362 default: TRACE("%s%x: %s", prefix, id, buf); break;
364 return STATUS_SUCCESS;
367 /******************************************************************************
368 * RtlAcquirePebLock [NTDLL.@]
370 VOID WINAPI RtlAcquirePebLock(void)
372 RtlEnterCriticalSection( &peb_lock );
375 /******************************************************************************
376 * RtlReleasePebLock [NTDLL.@]
378 VOID WINAPI RtlReleasePebLock(void)
380 RtlLeaveCriticalSection( &peb_lock );
383 /******************************************************************************
384 * RtlNewSecurityObject [NTDLL.@]
386 NTSTATUS WINAPI
387 RtlNewSecurityObject( PSECURITY_DESCRIPTOR ParentDescriptor,
388 PSECURITY_DESCRIPTOR CreatorDescriptor,
389 PSECURITY_DESCRIPTOR *NewDescriptor,
390 BOOLEAN IsDirectoryObject,
391 HANDLE Token,
392 PGENERIC_MAPPING GenericMapping )
394 FIXME("(%p %p %p %d %p %p) stub!\n", ParentDescriptor, CreatorDescriptor,
395 NewDescriptor, IsDirectoryObject, Token, GenericMapping);
396 return STATUS_NOT_IMPLEMENTED;
399 /******************************************************************************
400 * RtlDeleteSecurityObject [NTDLL.@]
402 NTSTATUS WINAPI
403 RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR *ObjectDescriptor )
405 FIXME("(%p) stub!\n", ObjectDescriptor);
406 return STATUS_NOT_IMPLEMENTED;
409 /******************************************************************************
410 * RtlInitializeGenericTable [NTDLL.@]
412 PVOID WINAPI RtlInitializeGenericTable(PVOID pTable, PVOID arg2, PVOID arg3, PVOID arg4, PVOID arg5)
414 FIXME("(%p,%p,%p,%p,%p) stub!\n", pTable, arg2, arg3, arg4, arg5);
415 return NULL;
418 /******************************************************************************
419 * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
421 PVOID RtlEnumerateGenericTableWithoutSplaying(PVOID pTable, PVOID *RestartKey)
423 static int warn_once;
425 if (!warn_once++)
426 FIXME("(%p,%p) stub!\n", pTable, RestartKey);
427 return NULL;
430 /******************************************************************************
431 * RtlNumberGenericTableElements [NTDLL.@]
433 ULONG RtlNumberGenericTableElements(PVOID pTable)
435 FIXME("(%p) stub!\n", pTable);
436 return 0;
439 /******************************************************************************
440 * RtlMoveMemory [NTDLL.@]
442 * Move a block of memory that may overlap.
444 * PARAMS
445 * Destination [O] End destination for block
446 * Source [O] Where to start copying from
447 * Length [I] Number of bytes to copy
449 * RETURNS
450 * Nothing.
452 #undef RtlMoveMemory
453 VOID WINAPI RtlMoveMemory( void *Destination, const void *Source, SIZE_T Length )
455 memmove(Destination, Source, Length);
458 /******************************************************************************
459 * RtlFillMemory [NTDLL.@]
461 * Set a block of memory with a value.
463 * PARAMS
464 * Destination [O] Block to fill
465 * Length [I] Number of bytes to fill
466 * Fill [I] Value to set
468 * RETURNS
469 * Nothing.
471 #undef RtlFillMemory
472 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
474 memset(Destination, Fill, Length);
477 /******************************************************************************
478 * RtlZeroMemory [NTDLL.@]
480 * Set a block of memory with 0's.
482 * PARAMS
483 * Destination [O] Block to fill
484 * Length [I] Number of bytes to fill
486 * RETURNS
487 * Nothing.
489 #undef RtlZeroMemory
490 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
492 memset(Destination, 0, Length);
495 /******************************************************************************
496 * RtlCompareMemory [NTDLL.@]
498 * Compare one block of memory with another
500 * PARAMS
501 * Source1 [I] Source block
502 * Source2 [I] Block to compare to Source1
503 * Length [I] Number of bytes to compare
505 * RETURNS
506 * The length of the first byte at which Source1 and Source2 differ, or Length
507 * if they are the same.
509 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
511 SIZE_T i;
512 for(i=0; (i<Length) && (((const BYTE*)Source1)[i]==((const BYTE*)Source2)[i]); i++);
513 return i;
516 /******************************************************************************
517 * RtlCompareMemoryUlong [NTDLL.@]
519 * Compare a block of memory with a value, a ULONG at a time
521 * PARAMS
522 * Source1 [I] Source block. This must be ULONG aligned
523 * Length [I] Number of bytes to compare. This should be a multiple of 4
524 * dwVal [I] Value to compare to
526 * RETURNS
527 * The byte position of the first byte at which Source1 is not dwVal.
529 SIZE_T WINAPI RtlCompareMemoryUlong(const ULONG *Source1, SIZE_T Length, ULONG dwVal)
531 SIZE_T i;
532 for(i = 0; i < Length/sizeof(ULONG) && Source1[i] == dwVal; i++);
533 return i * sizeof(ULONG);
536 /******************************************************************************
537 * RtlCopyMemory [NTDLL.@]
539 #undef RtlCopyMemory
540 void WINAPI RtlCopyMemory(void *dest, const void *src, SIZE_T len)
542 memcpy(dest, src, len);
545 /******************************************************************************
546 * RtlAssert [NTDLL.@]
548 * Fail a debug assertion.
550 * RETURNS
551 * Nothing. This call does not return control to its caller.
553 * NOTES
554 * Not implemented in non-debug versions.
556 void WINAPI RtlAssert(LPVOID x1,LPVOID x2,DWORD x3, DWORD x4)
558 FIXME("(%p,%p,0x%08x,0x%08x),stub\n",x1,x2,x3,x4);
561 /*************************************************************************
562 * RtlFillMemoryUlong [NTDLL.@]
564 * Fill memory with a 32 bit (dword) value.
566 * PARAMS
567 * lpDest [I] Bitmap pointer
568 * ulCount [I] Number of dwords to write
569 * ulValue [I] Value to fill with
571 * RETURNS
572 * Nothing.
574 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
576 TRACE("(%p,%d,%d)\n", lpDest, ulCount, ulValue);
578 ulCount /= sizeof(ULONG);
579 while(ulCount--)
580 *lpDest++ = ulValue;
583 /*********************************************************************
584 * RtlComputeCrc32 [NTDLL.@]
586 * Calculate the CRC32 checksum of a block of bytes
588 * PARAMS
589 * dwInitial [I] Initial CRC value
590 * pData [I] Data block
591 * iLen [I] Length of the byte block
593 * RETURNS
594 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
596 DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
598 DWORD crc = ~dwInitial;
600 TRACE("(%d,%p,%d)\n", dwInitial, pData, iLen);
602 while (iLen > 0)
604 crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
605 pData++;
606 iLen--;
608 return ~crc;
612 /*************************************************************************
613 * RtlUlonglongByteSwap [NTDLL.@]
615 * Swap the bytes of an unsigned long long value.
617 * PARAMS
618 * i [I] Value to swap bytes of
620 * RETURNS
621 * The value with its bytes swapped.
623 ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i)
625 return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32);
628 /*************************************************************************
629 * RtlUlongByteSwap [NTDLL.@]
631 * Swap the bytes of an unsigned int value.
633 * NOTES
634 * ix86 version takes argument in %ecx. Other systems use the inline version.
636 #ifdef __i386__
637 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap,
638 "movl %ecx,%eax\n\t"
639 "bswap %eax\n\t"
640 "ret")
641 #endif
643 /*************************************************************************
644 * RtlUshortByteSwap [NTDLL.@]
646 * Swap the bytes of an unsigned short value.
648 * NOTES
649 * i386 version takes argument in %cx. Other systems use the inline version.
651 #ifdef __i386__
652 __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap,
653 "movb %ch,%al\n\t"
654 "movb %cl,%ah\n\t"
655 "ret")
656 #endif
659 /*************************************************************************
660 * RtlUniform [NTDLL.@]
662 * Generates an uniform random number
664 * PARAMS
665 * seed [O] The seed of the Random function
667 * RETURNS
668 * It returns a random number uniformly distributed over [0..MAXLONG-1].
670 * NOTES
671 * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
672 * In our case the algorithm is:
674 *| result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
676 *| *seed = result;
678 * DIFFERENCES
679 * The native documentation states that the random number is
680 * uniformly distributed over [0..MAXLONG]. In reality the native
681 * function and our function return a random number uniformly
682 * distributed over [0..MAXLONG-1].
684 ULONG WINAPI RtlUniform (PULONG seed)
686 ULONG result;
689 * Instead of the algorithm stated above, we use the algorithm
690 * below, which is totally equivalent (see the tests), but does
691 * not use a division and therefore is faster.
693 result = *seed * 0xffffffed + 0x7fffffc3;
694 if (result == 0xffffffff || result == 0x7ffffffe) {
695 result = (result + 2) & MAXLONG;
696 } else if (result == 0x7fffffff) {
697 result = 0;
698 } else if ((result & 0x80000000) == 0) {
699 result = result + (~result & 1);
700 } else {
701 result = (result + (result & 1)) & MAXLONG;
702 } /* if */
703 *seed = result;
704 return result;
708 /*************************************************************************
709 * RtlRandom [NTDLL.@]
711 * Generates a random number
713 * PARAMS
714 * seed [O] The seed of the Random function
716 * RETURNS
717 * It returns a random number distributed over [0..MAXLONG-1].
719 ULONG WINAPI RtlRandom (PULONG seed)
721 static ULONG saved_value[128] =
722 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
723 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
724 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
725 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
726 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
727 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
728 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
729 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
730 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
731 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
732 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
733 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
734 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
735 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
736 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
737 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
738 ULONG rand;
739 int pos;
740 ULONG result;
742 rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
743 *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
744 pos = *seed & 0x7f;
745 result = saved_value[pos];
746 saved_value[pos] = rand;
747 return(result);
751 /*************************************************************************
752 * RtlAreAllAccessesGranted [NTDLL.@]
754 * Check if all desired accesses are granted
756 * RETURNS
757 * TRUE: All desired accesses are granted
758 * FALSE: Otherwise
760 BOOLEAN WINAPI RtlAreAllAccessesGranted(
761 ACCESS_MASK GrantedAccess,
762 ACCESS_MASK DesiredAccess)
764 return (GrantedAccess & DesiredAccess) == DesiredAccess;
768 /*************************************************************************
769 * RtlAreAnyAccessesGranted [NTDLL.@]
771 * Check if at least one of the desired accesses is granted
773 * PARAMS
774 * GrantedAccess [I] Access mask of granted accesses
775 * DesiredAccess [I] Access mask of desired accesses
777 * RETURNS
778 * TRUE: At least one of the desired accesses is granted
779 * FALSE: Otherwise
781 BOOLEAN WINAPI RtlAreAnyAccessesGranted(
782 ACCESS_MASK GrantedAccess,
783 ACCESS_MASK DesiredAccess)
785 return (GrantedAccess & DesiredAccess) != 0;
789 /*************************************************************************
790 * RtlMapGenericMask [NTDLL.@]
792 * Determine the nongeneric access rights specified by an access mask
794 * RETURNS
795 * Nothing.
797 void WINAPI RtlMapGenericMask(
798 PACCESS_MASK AccessMask,
799 const GENERIC_MAPPING *GenericMapping)
801 if (*AccessMask & GENERIC_READ) {
802 *AccessMask |= GenericMapping->GenericRead;
803 } /* if */
805 if (*AccessMask & GENERIC_WRITE) {
806 *AccessMask |= GenericMapping->GenericWrite;
807 } /* if */
809 if (*AccessMask & GENERIC_EXECUTE) {
810 *AccessMask |= GenericMapping->GenericExecute;
811 } /* if */
813 if (*AccessMask & GENERIC_ALL) {
814 *AccessMask |= GenericMapping->GenericAll;
815 } /* if */
817 *AccessMask &= 0x0FFFFFFF;
821 /*************************************************************************
822 * RtlCopyLuid [NTDLL.@]
824 * Copy a local unique ID.
826 * PARAMS
827 * LuidDest [O] Destination for the copied Luid
828 * LuidSrc [I] Source Luid to copy to LuidDest
830 * RETURNS
831 * Nothing.
833 void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc)
835 *LuidDest = *LuidSrc;
839 /*************************************************************************
840 * RtlEqualLuid [NTDLL.@]
842 * Compare two local unique IDs.
844 * PARAMS
845 * Luid1 [I] First Luid to compare to Luid2
846 * Luid2 [I] Second Luid to compare to Luid1
848 * RETURNS
849 * TRUE: The two LUIDs are equal.
850 * FALSE: Otherwise
852 BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2)
854 return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart);
858 /*************************************************************************
859 * RtlCopyLuidAndAttributesArray [NTDLL.@]
861 * Copy an array of local unique IDs and attributes.
863 * PARAMS
864 * Count [I] Number of Luid/attributes in Src
865 * Src [I] Source Luid/attributes to copy
866 * Dest [O] Destination for copied Luid/attributes
868 * RETURNS
869 * Nothing.
871 * NOTES
872 * Dest must be large enough to hold Src.
874 void WINAPI RtlCopyLuidAndAttributesArray(
875 ULONG Count,
876 const LUID_AND_ATTRIBUTES *Src,
877 PLUID_AND_ATTRIBUTES Dest)
879 ULONG i;
881 for (i = 0; i < Count; i++) Dest[i] = Src[i];
884 NTSTATUS WINAPI RtlIpv4StringToAddressExW(PULONG IP, PULONG Port,
885 LPCWSTR Buffer, PULONG MaxSize)
887 FIXME("(%p,%p,%p,%p): stub\n", IP, Port, Buffer, MaxSize);
889 return STATUS_SUCCESS;
892 /***********************************************************************
893 * RtlIpv4AddressToStringExW [NTDLL.@]
895 * Convert the given ipv4 address and optional the port to a string
897 * PARAMS
898 * pin [I] PTR to the ip address to convert (network byte order)
899 * port [I] optional port to convert (network byte order)
900 * buffer [O] destination buffer for the result
901 * psize [IO] PTR to available/used size of the destination buffer
903 * RETURNS
904 * Success: STATUS_SUCCESS
905 * Failure: STATUS_INVALID_PARAMETER
908 NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
910 WCHAR tmp_ip[32];
911 static const WCHAR fmt_ip[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
912 static const WCHAR fmt_port[] = {':','%','u',0};
913 ULONG needed;
915 if (!pin || !buffer || !psize)
916 return STATUS_INVALID_PARAMETER;
918 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
920 needed = sprintfW(tmp_ip, fmt_ip,
921 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
922 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
924 if (port) needed += sprintfW(tmp_ip + needed, fmt_port, ntohs(port));
926 if (*psize > needed) {
927 *psize = needed + 1;
928 strcpyW(buffer, tmp_ip);
929 return STATUS_SUCCESS;
932 *psize = needed + 1;
933 return STATUS_INVALID_PARAMETER;
936 /***********************************************************************
937 * RtlIpv4AddressToStringExA [NTDLL.@]
939 * Convert the given ipv4 address and optional the port to a string
941 * See RtlIpv4AddressToStringExW
943 NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
945 CHAR tmp_ip[32];
946 ULONG needed;
948 if (!pin || !buffer || !psize)
949 return STATUS_INVALID_PARAMETER;
951 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
953 needed = sprintf(tmp_ip, "%u.%u.%u.%u",
954 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
955 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
957 if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
959 if (*psize > needed) {
960 *psize = needed + 1;
961 strcpy(buffer, tmp_ip);
962 return STATUS_SUCCESS;
965 *psize = needed + 1;
966 return STATUS_INVALID_PARAMETER;
969 /***********************************************************************
970 * RtlIpv4AddressToStringW [NTDLL.@]
972 * Convert the given ipv4 address to a string
974 * PARAMS
975 * pin [I] PTR to the ip address to convert (network byte order)
976 * buffer [O] destination buffer for the result (at least 16 character)
978 * RETURNS
979 * PTR to the 0 character at the end of the converted string
982 WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
984 ULONG size = 16;
986 if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
987 return buffer + size - 1;
990 /***********************************************************************
991 * RtlIpv4AddressToStringA [NTDLL.@]
993 * Convert the given ipv4 address to a string
995 * See RtlIpv4AddressToStringW
997 CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
999 ULONG size = 16;
1001 if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
1002 return buffer + size - 1;
1005 /***********************************************************************
1006 * get_pointer_obfuscator (internal)
1008 static DWORD_PTR get_pointer_obfuscator( void )
1010 static DWORD_PTR pointer_obfuscator;
1012 if (!pointer_obfuscator)
1014 ULONG seed = NtGetTickCount();
1015 ULONG_PTR rand;
1017 /* generate a random value for the obfuscator */
1018 rand = RtlUniform( &seed );
1020 /* handle 64bit pointers */
1021 rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1023 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1024 rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1026 interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator, (void*) rand, NULL );
1029 return pointer_obfuscator;
1032 /*************************************************************************
1033 * RtlEncodePointer [NTDLL.@]
1035 PVOID WINAPI RtlEncodePointer( PVOID ptr )
1037 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1038 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1041 PVOID WINAPI RtlDecodePointer( PVOID ptr )
1043 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1044 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1047 /*************************************************************************
1048 * RtlInitializeSListHead [NTDLL.@]
1050 VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
1052 #ifdef _WIN64
1053 list->s.Alignment = list->s.Region = 0;
1054 list->Header16.HeaderType = 1; /* we use the 16-byte header */
1055 #else
1056 list->Alignment = 0;
1057 #endif
1060 /*************************************************************************
1061 * RtlQueryDepthSList [NTDLL.@]
1063 WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
1065 #ifdef _WIN64
1066 return list->Header16.Depth;
1067 #else
1068 return list->s.Depth;
1069 #endif
1072 /*************************************************************************
1073 * RtlFirstEntrySList [NTDLL.@]
1075 PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
1077 #ifdef _WIN64
1078 return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
1079 #else
1080 return list->s.Next.Next;
1081 #endif
1084 /*************************************************************************
1085 * RtlInterlockedFlushSList [NTDLL.@]
1087 PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
1089 SLIST_HEADER old, new;
1091 #ifdef _WIN64
1092 if (!list->Header16.NextEntry) return NULL;
1093 new.s.Alignment = new.s.Region = 0;
1094 new.Header16.HeaderType = 1; /* we use the 16-byte header */
1097 old = *list;
1098 new.Header16.Sequence = old.Header16.Sequence + 1;
1099 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1100 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1101 #else
1102 if (!list->s.Next.Next) return NULL;
1103 new.Alignment = 0;
1106 old = *list;
1107 new.s.Sequence = old.s.Sequence + 1;
1108 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1109 old.Alignment) != old.Alignment);
1110 return old.s.Next.Next;
1111 #endif
1114 /*************************************************************************
1115 * RtlInterlockedPushEntrySList [NTDLL.@]
1117 PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
1119 SLIST_HEADER old, new;
1121 #ifdef _WIN64
1122 new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
1125 old = *list;
1126 entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1127 new.Header16.Depth = old.Header16.Depth + 1;
1128 new.Header16.Sequence = old.Header16.Sequence + 1;
1129 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1130 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1131 #else
1132 new.s.Next.Next = entry;
1135 old = *list;
1136 entry->Next = old.s.Next.Next;
1137 new.s.Depth = old.s.Depth + 1;
1138 new.s.Sequence = old.s.Sequence + 1;
1139 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1140 old.Alignment) != old.Alignment);
1141 return old.s.Next.Next;
1142 #endif
1145 /*************************************************************************
1146 * RtlInterlockedPopEntrySList [NTDLL.@]
1148 PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
1150 SLIST_HEADER old, new;
1151 PSLIST_ENTRY entry;
1153 #ifdef _WIN64
1156 old = *list;
1157 if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
1158 /* entry could be deleted by another thread */
1159 __TRY
1161 new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
1162 new.Header16.Depth = old.Header16.Depth - 1;
1163 new.Header16.Sequence = old.Header16.Sequence + 1;
1165 __EXCEPT_PAGE_FAULT
1168 __ENDTRY
1169 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1170 #else
1173 old = *list;
1174 if (!(entry = old.s.Next.Next)) return NULL;
1175 /* entry could be deleted by another thread */
1176 __TRY
1178 new.s.Next.Next = entry->Next;
1179 new.s.Depth = old.s.Depth - 1;
1180 new.s.Sequence = old.s.Sequence + 1;
1182 __EXCEPT_PAGE_FAULT
1185 __ENDTRY
1186 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1187 old.Alignment) != old.Alignment);
1188 #endif
1189 return entry;
1192 /*************************************************************************
1193 * RtlInterlockedPushListSList [NTDLL.@]
1195 PSLIST_ENTRY WINAPI RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1196 PSLIST_ENTRY last, ULONG count)
1198 SLIST_HEADER old, new;
1200 #ifdef _WIN64
1201 new.Header16.NextEntry = (ULONG_PTR)first >> 4;
1204 old = *list;
1205 new.Header16.Depth = old.Header16.Depth + count;
1206 new.Header16.Sequence = old.Header16.Sequence + 1;
1207 last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1208 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1209 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1210 #else
1211 new.s.Next.Next = first;
1214 old = *list;
1215 new.s.Depth = old.s.Depth + count;
1216 new.s.Sequence = old.s.Sequence + 1;
1217 last->Next = old.s.Next.Next;
1218 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1219 old.Alignment) != old.Alignment);
1220 return old.s.Next.Next;
1221 #endif
1224 /******************************************************************************
1225 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1227 NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT format, PULONG compress_workspace,
1228 PULONG decompress_workspace)
1230 FIXME("0x%04x, %p, %p: semi-stub\n", format, compress_workspace, decompress_workspace);
1232 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1234 case COMPRESSION_FORMAT_LZNT1:
1235 if (compress_workspace)
1237 /* FIXME: The current implementation of RtlCompressBuffer does not use a
1238 * workspace buffer, but Windows applications might expect a nonzero value. */
1239 *compress_workspace = 16;
1241 if (decompress_workspace)
1242 *decompress_workspace = 0x1000;
1243 return STATUS_SUCCESS;
1245 case COMPRESSION_FORMAT_NONE:
1246 case COMPRESSION_FORMAT_DEFAULT:
1247 return STATUS_INVALID_PARAMETER;
1249 default:
1250 FIXME("format %u not implemented\n", format);
1251 return STATUS_UNSUPPORTED_COMPRESSION;
1255 /* compress data using LZNT1, currently only a stub */
1256 static NTSTATUS lznt1_compress(UCHAR *src, ULONG src_size, UCHAR *dst, ULONG dst_size,
1257 ULONG chunk_size, ULONG *final_size, UCHAR *workspace)
1259 UCHAR *src_cur = src, *src_end = src + src_size;
1260 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1261 ULONG block_size;
1263 while (src_cur < src_end)
1265 /* determine size of current chunk */
1266 block_size = min(0x1000, src_end - src_cur);
1267 if (dst_cur + sizeof(WORD) + block_size > dst_end)
1268 return STATUS_BUFFER_TOO_SMALL;
1270 /* write (uncompressed) chunk header */
1271 *(WORD *)dst_cur = 0x3000 | (block_size - 1);
1272 dst_cur += sizeof(WORD);
1274 /* write chunk content */
1275 memcpy(dst_cur, src_cur, block_size);
1276 dst_cur += block_size;
1277 src_cur += block_size;
1280 if (final_size)
1281 *final_size = dst_cur - dst;
1283 return STATUS_SUCCESS;
1286 /******************************************************************************
1287 * RtlCompressBuffer [NTDLL.@]
1289 NTSTATUS WINAPI RtlCompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1290 PUCHAR compressed, ULONG compressed_size, ULONG chunk_size,
1291 PULONG final_size, PVOID workspace)
1293 FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p: semi-stub\n", format, uncompressed,
1294 uncompressed_size, compressed, compressed_size, chunk_size, final_size, workspace);
1296 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1298 case COMPRESSION_FORMAT_LZNT1:
1299 return lznt1_compress(uncompressed, uncompressed_size, compressed,
1300 compressed_size, chunk_size, final_size, workspace);
1302 case COMPRESSION_FORMAT_NONE:
1303 case COMPRESSION_FORMAT_DEFAULT:
1304 return STATUS_INVALID_PARAMETER;
1306 default:
1307 FIXME("format %u not implemented\n", format);
1308 return STATUS_UNSUPPORTED_COMPRESSION;
1312 /* decompress a single LZNT1 chunk */
1313 static UCHAR *lznt1_decompress_chunk(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size)
1315 UCHAR *src_cur = src, *src_end = src + src_size;
1316 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1317 ULONG displacement_bits, length_bits;
1318 ULONG code_displacement, code_length;
1319 WORD flags, code;
1321 while (src_cur < src_end && dst_cur < dst_end)
1323 flags = 0x8000 | *src_cur++;
1324 while ((flags & 0xff00) && src_cur < src_end)
1326 if (flags & 1)
1328 /* backwards reference */
1329 if (src_cur + sizeof(WORD) > src_end)
1330 return NULL;
1332 code = *(WORD *)src_cur;
1333 src_cur += sizeof(WORD);
1335 /* find length / displacement bits */
1336 for (displacement_bits = 12; displacement_bits > 4; displacement_bits--)
1337 if ((1 << (displacement_bits - 1)) < dst_cur - dst) break;
1339 length_bits = 16 - displacement_bits;
1340 code_length = (code & ((1 << length_bits) - 1)) + 3;
1341 code_displacement = (code >> length_bits) + 1;
1343 if (dst_cur < dst + code_displacement)
1344 return NULL;
1346 /* copy bytes of chunk - we can't use memcpy() since source and dest can
1347 * be overlapping, and the same bytes can be repeated over and over again */
1348 while (code_length--)
1350 if (dst_cur >= dst_end) return dst_cur;
1351 *dst_cur = *(dst_cur - code_displacement);
1352 dst_cur++;
1355 else
1357 /* uncompressed data */
1358 if (dst_cur >= dst_end) return dst_cur;
1359 *dst_cur++ = *src_cur++;
1361 flags >>= 1;
1365 return dst_cur;
1368 /* decompress data encoded with LZNT1 */
1369 static NTSTATUS lznt1_decompress(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size,
1370 ULONG offset, ULONG *final_size, UCHAR *workspace)
1372 UCHAR *src_cur = src, *src_end = src + src_size;
1373 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1374 ULONG chunk_size, block_size;
1375 WORD chunk_header;
1376 UCHAR *ptr;
1378 if (src_cur + sizeof(WORD) > src_end)
1379 return STATUS_BAD_COMPRESSION_BUFFER;
1381 /* skip over chunks with a distance >= 0x1000 to the destination offset */
1382 while (offset >= 0x1000 && src_cur + sizeof(WORD) <= src_end)
1384 chunk_header = *(WORD *)src_cur;
1385 src_cur += sizeof(WORD);
1386 if (!chunk_header) goto out;
1387 chunk_size = (chunk_header & 0xfff) + 1;
1389 if (src_cur + chunk_size > src_end)
1390 return STATUS_BAD_COMPRESSION_BUFFER;
1392 src_cur += chunk_size;
1393 offset -= 0x1000;
1396 /* handle partially included chunk */
1397 if (offset && src_cur + sizeof(WORD) <= src_end)
1399 chunk_header = *(WORD *)src_cur;
1400 src_cur += sizeof(WORD);
1401 if (!chunk_header) goto out;
1402 chunk_size = (chunk_header & 0xfff) + 1;
1404 if (src_cur + chunk_size > src_end)
1405 return STATUS_BAD_COMPRESSION_BUFFER;
1407 if (dst_cur >= dst_end)
1408 goto out;
1410 if (chunk_header & 0x8000)
1412 /* compressed chunk */
1413 if (!workspace) return STATUS_ACCESS_VIOLATION;
1414 ptr = lznt1_decompress_chunk(workspace, 0x1000, src_cur, chunk_size);
1415 if (!ptr) return STATUS_BAD_COMPRESSION_BUFFER;
1416 if (ptr - workspace > offset)
1418 block_size = min((ptr - workspace) - offset, dst_end - dst_cur);
1419 memcpy(dst_cur, workspace + offset, block_size);
1420 dst_cur += block_size;
1423 else
1425 /* uncompressed chunk */
1426 if (chunk_size > offset)
1428 block_size = min(chunk_size - offset, dst_end - dst_cur);
1429 memcpy(dst_cur, src_cur + offset, block_size);
1430 dst_cur += block_size;
1434 src_cur += chunk_size;
1437 /* handle remaining chunks */
1438 while (src_cur + sizeof(WORD) <= src_end)
1440 chunk_header = *(WORD *)src_cur;
1441 src_cur += sizeof(WORD);
1442 if (!chunk_header) goto out;
1443 chunk_size = (chunk_header & 0xfff) + 1;
1445 if (src_cur + chunk_size > src_end)
1446 return STATUS_BAD_COMPRESSION_BUFFER;
1448 /* fill space with padding when the previous chunk was decompressed
1449 * to less than 4096 bytes. no padding is needed for the last chunk
1450 * or when the next chunk is truncated */
1451 block_size = ((dst_cur - dst) + offset) & 0xfff;
1452 if (block_size)
1454 block_size = 0x1000 - block_size;
1455 if (dst_cur + block_size >= dst_end)
1456 goto out;
1457 memset(dst_cur, 0, block_size);
1458 dst_cur += block_size;
1461 if (dst_cur >= dst_end)
1462 goto out;
1464 if (chunk_header & 0x8000)
1466 /* compressed chunk */
1467 dst_cur = lznt1_decompress_chunk(dst_cur, dst_end - dst_cur, src_cur, chunk_size);
1468 if (!dst_cur) return STATUS_BAD_COMPRESSION_BUFFER;
1470 else
1472 /* uncompressed chunk */
1473 block_size = min(chunk_size, dst_end - dst_cur);
1474 memcpy(dst_cur, src_cur, block_size);
1475 dst_cur += block_size;
1478 src_cur += chunk_size;
1481 out:
1482 if (final_size)
1483 *final_size = dst_cur - dst;
1485 return STATUS_SUCCESS;
1489 /******************************************************************************
1490 * RtlDecompressFragment [NTDLL.@]
1492 NTSTATUS WINAPI RtlDecompressFragment(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1493 PUCHAR compressed, ULONG compressed_size, ULONG offset,
1494 PULONG final_size, PVOID workspace)
1496 TRACE("0x%04x, %p, %u, %p, %u, %u, %p, %p\n", format, uncompressed,
1497 uncompressed_size, compressed, compressed_size, offset, final_size, workspace);
1499 switch (format & ~COMPRESSION_ENGINE_MAXIMUM)
1501 case COMPRESSION_FORMAT_LZNT1:
1502 return lznt1_decompress(uncompressed, uncompressed_size, compressed,
1503 compressed_size, offset, final_size, workspace);
1505 case COMPRESSION_FORMAT_NONE:
1506 case COMPRESSION_FORMAT_DEFAULT:
1507 return STATUS_INVALID_PARAMETER;
1509 default:
1510 FIXME("format %u not implemented\n", format);
1511 return STATUS_UNSUPPORTED_COMPRESSION;
1516 /******************************************************************************
1517 * RtlDecompressBuffer [NTDLL.@]
1519 NTSTATUS WINAPI RtlDecompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1520 PUCHAR compressed, ULONG compressed_size, PULONG final_size)
1522 TRACE("0x%04x, %p, %u, %p, %u, %p\n", format, uncompressed,
1523 uncompressed_size, compressed, compressed_size, final_size);
1525 return RtlDecompressFragment(format, uncompressed, uncompressed_size,
1526 compressed, compressed_size, 0, final_size, NULL);
1529 /***********************************************************************
1530 * RtlSetThreadErrorMode [NTDLL.@]
1532 * Set the thread local error mode.
1534 * PARAMS
1535 * mode [I] The new error mode
1536 * oldmode [O] Destination of the old error mode (may be NULL)
1538 * RETURNS
1539 * Success: STATUS_SUCCESS
1540 * Failure: STATUS_INVALID_PARAMETER_1
1542 NTSTATUS WINAPI RtlSetThreadErrorMode( DWORD mode, LPDWORD oldmode )
1544 if (mode & ~0x70)
1545 return STATUS_INVALID_PARAMETER_1;
1547 if (oldmode)
1548 *oldmode = NtCurrentTeb()->HardErrorDisabled;
1550 NtCurrentTeb()->HardErrorDisabled = mode;
1551 return STATUS_SUCCESS;
1554 /***********************************************************************
1555 * RtlGetThreadErrorMode [NTDLL.@]
1557 * Get the thread local error mode.
1559 * PARAMS
1560 * None.
1562 * RETURNS
1563 * The current thread local error mode.
1565 DWORD WINAPI RtlGetThreadErrorMode( void )
1567 return NtCurrentTeb()->HardErrorDisabled;
1570 /******************************************************************************
1571 * RtlGetCurrentTransaction [NTDLL.@]
1573 HANDLE WINAPI RtlGetCurrentTransaction(void)
1575 FIXME("() :stub\n");
1576 return NULL;
1579 /******************************************************************************
1580 * RtlSetCurrentTransaction [NTDLL.@]
1582 BOOL WINAPI RtlSetCurrentTransaction(HANDLE new_transaction)
1584 FIXME("(%p) :stub\n", new_transaction);
1585 return FALSE;
1588 /**********************************************************************
1589 * RtlGetCurrentProcessorNumberEx [NTDLL.@]
1591 void WINAPI RtlGetCurrentProcessorNumberEx(PROCESSOR_NUMBER *processor)
1593 FIXME("(%p) :semi-stub\n", processor);
1594 processor->Group = 0;
1595 processor->Number = NtGetCurrentProcessorNumber();
1596 processor->Reserved = 0;