msi: Use MsgWaitForMultipleObjectsEx to do waits.
[wine/multimedia.git] / dlls / ntdll / rtl.c
blobc430e2d9e3b4e1662932394402cda98900c0bac3
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 NONAMELESSSTRUCT
38 #define WIN32_NO_STATUS
39 #define USE_WS_PREFIX
40 #include "windef.h"
41 #include "winternl.h"
42 #include "wine/debug.h"
43 #include "wine/exception.h"
44 #include "wine/unicode.h"
45 #include "ntdll_misc.h"
46 #include "inaddr.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
50 static RTL_CRITICAL_SECTION peb_lock;
51 static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
53 0, 0, &peb_lock,
54 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
55 0, 0, { (DWORD_PTR)(__FILE__ ": peb_lock") }
57 static RTL_CRITICAL_SECTION peb_lock = { &critsect_debug, -1, 0, 0, 0, 0 };
59 /* CRC polynomial 0xedb88320 */
60 static const DWORD CRC_table[256] =
62 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
63 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
64 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
65 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
66 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
67 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
68 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
69 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
70 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
71 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
72 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
73 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
74 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
75 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
76 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
77 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
78 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
79 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
80 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
81 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
82 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
83 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
84 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
85 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
86 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
87 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
88 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
89 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
90 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
91 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
92 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
93 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
94 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
95 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
96 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
97 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
98 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
99 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
100 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
101 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
102 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
103 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
104 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
108 * resource functions
111 /***********************************************************************
112 * RtlInitializeResource (NTDLL.@)
114 * xxxResource() functions implement multiple-reader-single-writer lock.
115 * The code is based on information published in WDJ January 1999 issue.
117 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
119 if( rwl )
121 rwl->iNumberActive = 0;
122 rwl->uExclusiveWaiters = 0;
123 rwl->uSharedWaiters = 0;
124 rwl->hOwningThreadId = 0;
125 rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
126 RtlInitializeCriticalSection( &rwl->rtlCS );
127 rwl->rtlCS.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RTL_RWLOCK.rtlCS");
128 NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
129 NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
134 /***********************************************************************
135 * RtlDeleteResource (NTDLL.@)
137 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
139 if( rwl )
141 RtlEnterCriticalSection( &rwl->rtlCS );
142 if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
143 MESSAGE("Deleting active MRSW lock (%p), expect failure\n", rwl );
144 rwl->hOwningThreadId = 0;
145 rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
146 rwl->iNumberActive = 0;
147 NtClose( rwl->hExclusiveReleaseSemaphore );
148 NtClose( rwl->hSharedReleaseSemaphore );
149 RtlLeaveCriticalSection( &rwl->rtlCS );
150 rwl->rtlCS.DebugInfo->Spare[0] = 0;
151 RtlDeleteCriticalSection( &rwl->rtlCS );
156 /***********************************************************************
157 * RtlAcquireResourceExclusive (NTDLL.@)
159 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
161 BYTE retVal = 0;
162 if( !rwl ) return 0;
164 start:
165 RtlEnterCriticalSection( &rwl->rtlCS );
166 if( rwl->iNumberActive == 0 ) /* lock is free */
168 rwl->iNumberActive = -1;
169 retVal = 1;
171 else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
173 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
175 retVal = 1;
176 rwl->iNumberActive--;
177 goto done;
179 wait:
180 if( fWait )
182 NTSTATUS status;
184 rwl->uExclusiveWaiters++;
186 RtlLeaveCriticalSection( &rwl->rtlCS );
187 status = NtWaitForSingleObject( rwl->hExclusiveReleaseSemaphore, FALSE, NULL );
188 if( HIWORD(status) )
189 goto done;
190 goto start; /* restart the acquisition to avoid deadlocks */
193 else /* one or more shared locks are in progress */
194 if( fWait )
195 goto wait;
197 if( retVal == 1 )
198 rwl->hOwningThreadId = ULongToHandle(GetCurrentThreadId());
199 done:
200 RtlLeaveCriticalSection( &rwl->rtlCS );
201 return retVal;
204 /***********************************************************************
205 * RtlAcquireResourceShared (NTDLL.@)
207 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
209 NTSTATUS status = STATUS_UNSUCCESSFUL;
210 BYTE retVal = 0;
211 if( !rwl ) return 0;
213 start:
214 RtlEnterCriticalSection( &rwl->rtlCS );
215 if( rwl->iNumberActive < 0 )
217 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
219 rwl->iNumberActive--;
220 retVal = 1;
221 goto done;
224 if( fWait )
226 rwl->uSharedWaiters++;
227 RtlLeaveCriticalSection( &rwl->rtlCS );
228 status = NtWaitForSingleObject( rwl->hSharedReleaseSemaphore, FALSE, NULL );
229 if( HIWORD(status) )
230 goto done;
231 goto start;
234 else
236 if( status != STATUS_WAIT_0 ) /* otherwise RtlReleaseResource() has already done it */
237 rwl->iNumberActive++;
238 retVal = 1;
240 done:
241 RtlLeaveCriticalSection( &rwl->rtlCS );
242 return retVal;
246 /***********************************************************************
247 * RtlReleaseResource (NTDLL.@)
249 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
251 RtlEnterCriticalSection( &rwl->rtlCS );
253 if( rwl->iNumberActive > 0 ) /* have one or more readers */
255 if( --rwl->iNumberActive == 0 )
257 if( rwl->uExclusiveWaiters )
259 wake_exclusive:
260 rwl->uExclusiveWaiters--;
261 NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
265 else
266 if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
268 if( ++rwl->iNumberActive == 0 )
270 rwl->hOwningThreadId = 0;
271 if( rwl->uExclusiveWaiters )
272 goto wake_exclusive;
273 else
274 if( rwl->uSharedWaiters )
276 UINT n = rwl->uSharedWaiters;
277 rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
278 * all queued readers have done their thing */
279 rwl->uSharedWaiters = 0;
280 NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
284 RtlLeaveCriticalSection( &rwl->rtlCS );
288 /***********************************************************************
289 * RtlDumpResource (NTDLL.@)
291 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
293 if( rwl )
295 MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
296 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
297 if( rwl->iNumberActive )
298 MESSAGE("\towner thread = %p\n", rwl->hOwningThreadId );
303 * misc functions
306 /******************************************************************************
307 * DbgPrint [NTDLL.@]
309 NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...)
311 char buf[512];
312 __ms_va_list args;
314 __ms_va_start(args, fmt);
315 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
316 __ms_va_end(args);
318 MESSAGE("DbgPrint says: %s",buf);
319 /* hmm, raise exception? */
320 return STATUS_SUCCESS;
324 /******************************************************************************
325 * DbgPrintEx [NTDLL.@]
327 NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...)
329 NTSTATUS ret;
330 __ms_va_list args;
332 __ms_va_start(args, fmt);
333 ret = vDbgPrintEx(iComponentId, Level, fmt, args);
334 __ms_va_end(args);
335 return ret;
338 /******************************************************************************
339 * vDbgPrintEx [NTDLL.@]
341 NTSTATUS WINAPI vDbgPrintEx( ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
343 return vDbgPrintExWithPrefix( "", id, level, fmt, args );
346 /******************************************************************************
347 * vDbgPrintExWithPrefix [NTDLL.@]
349 NTSTATUS WINAPI vDbgPrintExWithPrefix( LPCSTR prefix, ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
351 char buf[1024];
353 NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
355 switch (level & DPFLTR_MASK)
357 case DPFLTR_ERROR_LEVEL: ERR("%s%x: %s", prefix, id, buf); break;
358 case DPFLTR_WARNING_LEVEL: WARN("%s%x: %s", prefix, id, buf); break;
359 case DPFLTR_TRACE_LEVEL:
360 case DPFLTR_INFO_LEVEL:
361 default: TRACE("%s%x: %s", prefix, id, buf); break;
363 return STATUS_SUCCESS;
366 /******************************************************************************
367 * RtlAcquirePebLock [NTDLL.@]
369 VOID WINAPI RtlAcquirePebLock(void)
371 RtlEnterCriticalSection( &peb_lock );
374 /******************************************************************************
375 * RtlReleasePebLock [NTDLL.@]
377 VOID WINAPI RtlReleasePebLock(void)
379 RtlLeaveCriticalSection( &peb_lock );
382 /******************************************************************************
383 * RtlNewSecurityObject [NTDLL.@]
385 NTSTATUS WINAPI
386 RtlNewSecurityObject( PSECURITY_DESCRIPTOR ParentDescriptor,
387 PSECURITY_DESCRIPTOR CreatorDescriptor,
388 PSECURITY_DESCRIPTOR *NewDescriptor,
389 BOOLEAN IsDirectoryObject,
390 HANDLE Token,
391 PGENERIC_MAPPING GenericMapping )
393 FIXME("(%p %p %p %d %p %p) stub!\n", ParentDescriptor, CreatorDescriptor,
394 NewDescriptor, IsDirectoryObject, Token, GenericMapping);
395 return STATUS_NOT_IMPLEMENTED;
398 /******************************************************************************
399 * RtlDeleteSecurityObject [NTDLL.@]
401 NTSTATUS WINAPI
402 RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR *ObjectDescriptor )
404 FIXME("(%p) stub!\n", ObjectDescriptor);
405 return STATUS_NOT_IMPLEMENTED;
408 /**************************************************************************
409 * _chkstk [NTDLL.@]
411 * Glorified "enter xxxx".
413 #ifdef __i386__
414 __ASM_STDCALL_FUNC( _chkstk, 0,
415 "negl %eax\n\t"
416 "addl %esp,%eax\n\t"
417 "xchgl %esp,%eax\n\t"
418 "movl 0(%eax),%eax\n\t" /* copy return address from old location */
419 "movl %eax,0(%esp)\n\t"
420 "ret" )
421 #endif
423 /**************************************************************************
424 * _alloca_probe [NTDLL.@]
426 * Glorified "enter xxxx".
428 #ifdef __i386__
429 __ASM_STDCALL_FUNC( _alloca_probe, 0,
430 "negl %eax\n\t"
431 "addl %esp,%eax\n\t"
432 "xchgl %esp,%eax\n\t"
433 "movl 0(%eax),%eax\n\t" /* copy return address from old location */
434 "movl %eax,0(%esp)\n\t"
435 "ret" )
436 #endif
439 /******************************************************************************
440 * RtlInitializeGenericTable [NTDLL.@]
442 PVOID WINAPI RtlInitializeGenericTable(PVOID pTable, PVOID arg2, PVOID arg3, PVOID arg4, PVOID arg5)
444 FIXME("(%p,%p,%p,%p,%p) stub!\n", pTable, arg2, arg3, arg4, arg5);
445 return NULL;
448 /******************************************************************************
449 * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
451 PVOID RtlEnumerateGenericTableWithoutSplaying(PVOID pTable, PVOID *RestartKey)
453 static int warn_once;
455 if (!warn_once++)
456 FIXME("(%p,%p) stub!\n", pTable, RestartKey);
457 return NULL;
460 /******************************************************************************
461 * RtlNumberGenericTableElements [NTDLL.@]
463 ULONG RtlNumberGenericTableElements(PVOID pTable)
465 FIXME("(%p) stub!\n", pTable);
466 return 0;
469 /******************************************************************************
470 * RtlMoveMemory [NTDLL.@]
472 * Move a block of memory that may overlap.
474 * PARAMS
475 * Destination [O] End destination for block
476 * Source [O] Where to start copying from
477 * Length [I] Number of bytes to copy
479 * RETURNS
480 * Nothing.
482 #undef RtlMoveMemory
483 VOID WINAPI RtlMoveMemory( VOID *Destination, CONST VOID *Source, SIZE_T Length )
485 memmove(Destination, Source, Length);
488 /******************************************************************************
489 * RtlFillMemory [NTDLL.@]
491 * Set a block of memory with a value.
493 * PARAMS
494 * Destination [O] Block to fill
495 * Length [I] Number of bytes to fill
496 * Fill [I] Value to set
498 * RETURNS
499 * Nothing.
501 #undef RtlFillMemory
502 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
504 memset(Destination, Fill, Length);
507 /******************************************************************************
508 * RtlZeroMemory [NTDLL.@]
510 * Set a block of memory with 0's.
512 * PARAMS
513 * Destination [O] Block to fill
514 * Length [I] Number of bytes to fill
516 * RETURNS
517 * Nothing.
519 #undef RtlZeroMemory
520 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
522 memset(Destination, 0, Length);
525 /******************************************************************************
526 * RtlCompareMemory [NTDLL.@]
528 * Compare one block of memory with another
530 * PARAMS
531 * Source1 [I] Source block
532 * Source2 [I] Block to compare to Source1
533 * Length [I] Number of bytes to compare
535 * RETURNS
536 * The length of the first byte at which Source1 and Source2 differ, or Length
537 * if they are the same.
539 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
541 SIZE_T i;
542 for(i=0; (i<Length) && (((const BYTE*)Source1)[i]==((const BYTE*)Source2)[i]); i++);
543 return i;
546 /******************************************************************************
547 * RtlCompareMemoryUlong [NTDLL.@]
549 * Compare a block of memory with a value, a ULONG at a time
551 * PARAMS
552 * Source1 [I] Source block. This must be ULONG aligned
553 * Length [I] Number of bytes to compare. This should be a multiple of 4
554 * dwVal [I] Value to compare to
556 * RETURNS
557 * The byte position of the first byte at which Source1 is not dwVal.
559 SIZE_T WINAPI RtlCompareMemoryUlong(const ULONG *Source1, SIZE_T Length, ULONG dwVal)
561 SIZE_T i;
562 for(i = 0; i < Length/sizeof(ULONG) && Source1[i] == dwVal; i++);
563 return i * sizeof(ULONG);
566 /******************************************************************************
567 * RtlAssert [NTDLL.@]
569 * Fail a debug assertion.
571 * RETURNS
572 * Nothing. This call does not return control to its caller.
574 * NOTES
575 * Not implemented in non-debug versions.
577 void WINAPI RtlAssert(LPVOID x1,LPVOID x2,DWORD x3, DWORD x4)
579 FIXME("(%p,%p,0x%08x,0x%08x),stub\n",x1,x2,x3,x4);
582 /*************************************************************************
583 * RtlFillMemoryUlong [NTDLL.@]
585 * Fill memory with a 32 bit (dword) value.
587 * PARAMS
588 * lpDest [I] Bitmap pointer
589 * ulCount [I] Number of dwords to write
590 * ulValue [I] Value to fill with
592 * RETURNS
593 * Nothing.
595 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
597 TRACE("(%p,%d,%d)\n", lpDest, ulCount, ulValue);
599 ulCount /= sizeof(ULONG);
600 while(ulCount--)
601 *lpDest++ = ulValue;
604 /*********************************************************************
605 * RtlComputeCrc32 [NTDLL.@]
607 * Calculate the CRC32 checksum of a block of bytes
609 * PARAMS
610 * dwInitial [I] Initial CRC value
611 * pData [I] Data block
612 * iLen [I] Length of the byte block
614 * RETURNS
615 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
617 DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
619 DWORD crc = ~dwInitial;
621 TRACE("(%d,%p,%d)\n", dwInitial, pData, iLen);
623 while (iLen > 0)
625 crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
626 pData++;
627 iLen--;
629 return ~crc;
633 /*************************************************************************
634 * RtlUlonglongByteSwap [NTDLL.@]
636 * Swap the bytes of an unsigned long long value.
638 * PARAMS
639 * i [I] Value to swap bytes of
641 * RETURNS
642 * The value with its bytes swapped.
644 ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i)
646 return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32);
649 /*************************************************************************
650 * RtlUlongByteSwap [NTDLL.@]
652 * Swap the bytes of an unsigned int value.
654 * NOTES
655 * ix86 version takes argument in %ecx. Other systems use the inline version.
657 #ifdef __i386__
658 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap,
659 "movl %ecx,%eax\n\t"
660 "bswap %eax\n\t"
661 "ret")
662 #endif
664 /*************************************************************************
665 * RtlUshortByteSwap [NTDLL.@]
667 * Swap the bytes of an unsigned short value.
669 * NOTES
670 * i386 version takes argument in %cx. Other systems use the inline version.
672 #ifdef __i386__
673 __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap,
674 "movb %ch,%al\n\t"
675 "movb %cl,%ah\n\t"
676 "ret")
677 #endif
680 /*************************************************************************
681 * RtlUniform [NTDLL.@]
683 * Generates an uniform random number
685 * PARAMS
686 * seed [O] The seed of the Random function
688 * RETURNS
689 * It returns a random number uniformly distributed over [0..MAXLONG-1].
691 * NOTES
692 * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
693 * In our case the algorithm is:
695 *| result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
697 *| *seed = result;
699 * DIFFERENCES
700 * The native documentation states that the random number is
701 * uniformly distributed over [0..MAXLONG]. In reality the native
702 * function and our function return a random number uniformly
703 * distributed over [0..MAXLONG-1].
705 ULONG WINAPI RtlUniform (PULONG seed)
707 ULONG result;
710 * Instead of the algorithm stated above, we use the algorithm
711 * below, which is totally equivalent (see the tests), but does
712 * not use a division and therefore is faster.
714 result = *seed * 0xffffffed + 0x7fffffc3;
715 if (result == 0xffffffff || result == 0x7ffffffe) {
716 result = (result + 2) & MAXLONG;
717 } else if (result == 0x7fffffff) {
718 result = 0;
719 } else if ((result & 0x80000000) == 0) {
720 result = result + (~result & 1);
721 } else {
722 result = (result + (result & 1)) & MAXLONG;
723 } /* if */
724 *seed = result;
725 return result;
729 /*************************************************************************
730 * RtlRandom [NTDLL.@]
732 * Generates a random number
734 * PARAMS
735 * seed [O] The seed of the Random function
737 * RETURNS
738 * It returns a random number distributed over [0..MAXLONG-1].
740 ULONG WINAPI RtlRandom (PULONG seed)
742 static ULONG saved_value[128] =
743 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
744 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
745 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
746 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
747 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
748 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
749 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
750 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
751 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
752 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
753 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
754 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
755 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
756 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
757 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
758 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
759 ULONG rand;
760 int pos;
761 ULONG result;
763 rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
764 *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
765 pos = *seed & 0x7f;
766 result = saved_value[pos];
767 saved_value[pos] = rand;
768 return(result);
772 /*************************************************************************
773 * RtlAreAllAccessesGranted [NTDLL.@]
775 * Check if all desired accesses are granted
777 * RETURNS
778 * TRUE: All desired accesses are granted
779 * FALSE: Otherwise
781 BOOLEAN WINAPI RtlAreAllAccessesGranted(
782 ACCESS_MASK GrantedAccess,
783 ACCESS_MASK DesiredAccess)
785 return (GrantedAccess & DesiredAccess) == DesiredAccess;
789 /*************************************************************************
790 * RtlAreAnyAccessesGranted [NTDLL.@]
792 * Check if at least one of the desired accesses is granted
794 * PARAMS
795 * GrantedAccess [I] Access mask of granted accesses
796 * DesiredAccess [I] Access mask of desired accesses
798 * RETURNS
799 * TRUE: At least one of the desired accesses is granted
800 * FALSE: Otherwise
802 BOOLEAN WINAPI RtlAreAnyAccessesGranted(
803 ACCESS_MASK GrantedAccess,
804 ACCESS_MASK DesiredAccess)
806 return (GrantedAccess & DesiredAccess) != 0;
810 /*************************************************************************
811 * RtlMapGenericMask [NTDLL.@]
813 * Determine the nongeneric access rights specified by an access mask
815 * RETURNS
816 * Nothing.
818 void WINAPI RtlMapGenericMask(
819 PACCESS_MASK AccessMask,
820 const GENERIC_MAPPING *GenericMapping)
822 if (*AccessMask & GENERIC_READ) {
823 *AccessMask |= GenericMapping->GenericRead;
824 } /* if */
826 if (*AccessMask & GENERIC_WRITE) {
827 *AccessMask |= GenericMapping->GenericWrite;
828 } /* if */
830 if (*AccessMask & GENERIC_EXECUTE) {
831 *AccessMask |= GenericMapping->GenericExecute;
832 } /* if */
834 if (*AccessMask & GENERIC_ALL) {
835 *AccessMask |= GenericMapping->GenericAll;
836 } /* if */
838 *AccessMask &= 0x0FFFFFFF;
842 /*************************************************************************
843 * RtlCopyLuid [NTDLL.@]
845 * Copy a local unique ID.
847 * PARAMS
848 * LuidDest [O] Destination for the copied Luid
849 * LuidSrc [I] Source Luid to copy to LuidDest
851 * RETURNS
852 * Nothing.
854 void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc)
856 *LuidDest = *LuidSrc;
860 /*************************************************************************
861 * RtlEqualLuid [NTDLL.@]
863 * Compare two local unique IDs.
865 * PARAMS
866 * Luid1 [I] First Luid to compare to Luid2
867 * Luid2 [I] Second Luid to compare to Luid1
869 * RETURNS
870 * TRUE: The two LUIDs are equal.
871 * FALSE: Otherwise
873 BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2)
875 return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart);
879 /*************************************************************************
880 * RtlCopyLuidAndAttributesArray [NTDLL.@]
882 * Copy an array of local unique IDs and attributes.
884 * PARAMS
885 * Count [I] Number of Luid/attributes in Src
886 * Src [I] Source Luid/attributes to copy
887 * Dest [O] Destination for copied Luid/attributes
889 * RETURNS
890 * Nothing.
892 * NOTES
893 * Dest must be large enough to hold Src.
895 void WINAPI RtlCopyLuidAndAttributesArray(
896 ULONG Count,
897 const LUID_AND_ATTRIBUTES *Src,
898 PLUID_AND_ATTRIBUTES Dest)
900 ULONG i;
902 for (i = 0; i < Count; i++) Dest[i] = Src[i];
905 NTSTATUS WINAPI RtlIpv4StringToAddressExW(PULONG IP, PULONG Port,
906 LPCWSTR Buffer, PULONG MaxSize)
908 FIXME("(%p,%p,%p,%p): stub\n", IP, Port, Buffer, MaxSize);
910 return STATUS_SUCCESS;
913 /***********************************************************************
914 * RtlIpv4AddressToStringExW [NTDLL.@]
916 * Convert the given ipv4 address and optional the port to a string
918 * PARAMS
919 * pin [I] PTR to the ip address to convert (network byte order)
920 * port [I] optional port to convert (network byte order)
921 * buffer [O] destination buffer for the result
922 * psize [IO] PTR to available/used size of the destination buffer
924 * RETURNS
925 * Success: STATUS_SUCCESS
926 * Failure: STATUS_INVALID_PARAMETER
929 NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
931 WCHAR tmp_ip[32];
932 static const WCHAR fmt_ip[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
933 static const WCHAR fmt_port[] = {':','%','u',0};
934 ULONG needed;
936 if (!pin || !buffer || !psize)
937 return STATUS_INVALID_PARAMETER;
939 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
941 needed = sprintfW(tmp_ip, fmt_ip,
942 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
943 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
945 if (port) needed += sprintfW(tmp_ip + needed, fmt_port, ntohs(port));
947 if (*psize > needed) {
948 *psize = needed + 1;
949 strcpyW(buffer, tmp_ip);
950 return STATUS_SUCCESS;
953 *psize = needed + 1;
954 return STATUS_INVALID_PARAMETER;
957 /***********************************************************************
958 * RtlIpv4AddressToStringExA [NTDLL.@]
960 * Convert the given ipv4 address and optional the port to a string
962 * See RtlIpv4AddressToStringExW
964 NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
966 CHAR tmp_ip[32];
967 ULONG needed;
969 if (!pin || !buffer || !psize)
970 return STATUS_INVALID_PARAMETER;
972 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
974 needed = sprintf(tmp_ip, "%u.%u.%u.%u",
975 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
976 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
978 if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
980 if (*psize > needed) {
981 *psize = needed + 1;
982 strcpy(buffer, tmp_ip);
983 return STATUS_SUCCESS;
986 *psize = needed + 1;
987 return STATUS_INVALID_PARAMETER;
990 /***********************************************************************
991 * RtlIpv4AddressToStringW [NTDLL.@]
993 * Convert the given ipv4 address to a string
995 * PARAMS
996 * pin [I] PTR to the ip address to convert (network byte order)
997 * buffer [O] destination buffer for the result (at least 16 character)
999 * RETURNS
1000 * PTR to the 0 character at the end of the converted string
1003 WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
1005 ULONG size = 16;
1007 if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
1008 return buffer + size - 1;
1011 /***********************************************************************
1012 * RtlIpv4AddressToStringA [NTDLL.@]
1014 * Convert the given ipv4 address to a string
1016 * See RtlIpv4AddressToStringW
1018 CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
1020 ULONG size = 16;
1022 if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
1023 return buffer + size - 1;
1026 /***********************************************************************
1027 * get_pointer_obfuscator (internal)
1029 static DWORD_PTR get_pointer_obfuscator( void )
1031 static DWORD_PTR pointer_obfuscator;
1033 if (!pointer_obfuscator)
1035 ULONG seed = NtGetTickCount();
1036 ULONG_PTR rand;
1038 /* generate a random value for the obfuscator */
1039 rand = RtlUniform( &seed );
1041 /* handle 64bit pointers */
1042 rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1044 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1045 rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1047 interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator, (void*) rand, NULL );
1050 return pointer_obfuscator;
1053 /*************************************************************************
1054 * RtlEncodePointer [NTDLL.@]
1056 PVOID WINAPI RtlEncodePointer( PVOID ptr )
1058 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1059 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1062 PVOID WINAPI RtlDecodePointer( PVOID ptr )
1064 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1065 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1068 /*************************************************************************
1069 * RtlInitializeSListHead [NTDLL.@]
1071 VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
1073 #ifdef _WIN64
1074 list->s.Alignment = list->s.Region = 0;
1075 list->Header16.HeaderType = 1; /* we use the 16-byte header */
1076 #else
1077 list->Alignment = 0;
1078 #endif
1081 /*************************************************************************
1082 * RtlQueryDepthSList [NTDLL.@]
1084 WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
1086 #ifdef _WIN64
1087 return list->Header16.Depth;
1088 #else
1089 return list->s.Depth;
1090 #endif
1093 /*************************************************************************
1094 * RtlFirstEntrySList [NTDLL.@]
1096 PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
1098 #ifdef _WIN64
1099 return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
1100 #else
1101 return list->s.Next.Next;
1102 #endif
1105 /*************************************************************************
1106 * RtlInterlockedFlushSList [NTDLL.@]
1108 PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
1110 SLIST_HEADER old, new;
1112 #ifdef _WIN64
1113 if (!list->Header16.Depth) return NULL;
1114 new.s.Alignment = new.s.Region = 0;
1115 new.Header16.HeaderType = 1; /* we use the 16-byte header */
1118 old = *list;
1119 new.Header16.Sequence = old.Header16.Sequence + 1;
1120 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1121 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1122 #else
1123 if (!list->s.Depth) return NULL;
1124 new.Alignment = 0;
1127 old = *list;
1128 new.s.Sequence = old.s.Sequence + 1;
1129 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1130 old.Alignment) != old.Alignment);
1131 return old.s.Next.Next;
1132 #endif
1135 /*************************************************************************
1136 * RtlInterlockedPushEntrySList [NTDLL.@]
1138 PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
1140 SLIST_HEADER old, new;
1142 #ifdef _WIN64
1143 new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
1146 old = *list;
1147 entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1148 new.Header16.Depth = old.Header16.Depth + 1;
1149 new.Header16.Sequence = old.Header16.Sequence + 1;
1150 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1151 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1152 #else
1153 new.s.Next.Next = entry;
1156 old = *list;
1157 entry->Next = old.s.Next.Next;
1158 new.s.Depth = old.s.Depth + 1;
1159 new.s.Sequence = old.s.Sequence + 1;
1160 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1161 old.Alignment) != old.Alignment);
1162 return old.s.Next.Next;
1163 #endif
1166 /*************************************************************************
1167 * RtlInterlockedPopEntrySList [NTDLL.@]
1169 PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
1171 SLIST_HEADER old, new;
1172 PSLIST_ENTRY entry;
1174 #ifdef _WIN64
1177 old = *list;
1178 if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
1179 /* entry could be deleted by another thread */
1180 __TRY
1182 new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
1183 new.Header16.Depth = old.Header16.Depth - 1;
1184 new.Header16.Sequence = old.Header16.Sequence + 1;
1186 __EXCEPT_PAGE_FAULT
1189 __ENDTRY
1190 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1191 #else
1194 old = *list;
1195 if (!(entry = old.s.Next.Next)) return NULL;
1196 /* entry could be deleted by another thread */
1197 __TRY
1199 new.s.Next.Next = entry->Next;
1200 new.s.Depth = old.s.Depth - 1;
1201 new.s.Sequence = old.s.Sequence + 1;
1203 __EXCEPT_PAGE_FAULT
1206 __ENDTRY
1207 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1208 old.Alignment) != old.Alignment);
1209 #endif
1210 return entry;
1213 /*************************************************************************
1214 * RtlInterlockedPushListSList [NTDLL.@]
1216 PSLIST_ENTRY WINAPI RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1217 PSLIST_ENTRY last, ULONG count)
1219 SLIST_HEADER old, new;
1221 #ifdef _WIN64
1222 new.Header16.NextEntry = (ULONG_PTR)first >> 4;
1225 old = *list;
1226 new.Header16.Depth = old.Header16.Depth + count;
1227 new.Header16.Sequence = old.Header16.Sequence + 1;
1228 last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1229 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1230 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1231 #else
1232 new.s.Next.Next = first;
1235 old = *list;
1236 new.s.Depth = old.s.Depth + count;
1237 new.s.Sequence = old.s.Sequence + 1;
1238 last->Next = old.s.Next.Next;
1239 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1240 old.Alignment) != old.Alignment);
1241 return old.s.Next.Next;
1242 #endif
1245 /******************************************************************************
1246 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1248 NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT CompressionFormatAndEngine,
1249 PULONG CompressBufferWorkSpaceSize,
1250 PULONG CompressFragmentWorkSpaceSize)
1252 FIXME("0x%04x, %p, %p: stub!\n", CompressionFormatAndEngine, CompressBufferWorkSpaceSize,
1253 CompressFragmentWorkSpaceSize);
1255 return STATUS_NOT_IMPLEMENTED;
1258 /******************************************************************************
1259 * RtlCompressBuffer [NTDLL.@]
1261 NTSTATUS WINAPI RtlCompressBuffer(USHORT CompressionFormatAndEngine, PUCHAR UncompressedBuffer,
1262 ULONG UncompressedBufferSize, PUCHAR CompressedBuffer,
1263 ULONG CompressedBufferSize, ULONG UncompressedChunkSize,
1264 PULONG FinalCompressedSize, PVOID WorkSpace)
1266 FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p :stub\n", CompressionFormatAndEngine, UncompressedBuffer,
1267 UncompressedBufferSize, CompressedBuffer, CompressedBufferSize, UncompressedChunkSize,
1268 FinalCompressedSize, WorkSpace);
1270 return STATUS_NOT_IMPLEMENTED;
1273 /******************************************************************************
1274 * RtlDecompressBuffer [NTDLL.@]
1276 NTSTATUS WINAPI RtlDecompressBuffer(USHORT CompressionFormat, PUCHAR UncompressedBuffer,
1277 ULONG UncompressedBufferSize, PUCHAR CompressedBuffer,
1278 ULONG CompressedBufferSize, PULONG FinalUncompressedSize)
1280 FIXME("0x%04x, %p, %u, %p, %u, %p :stub\n", CompressionFormat, UncompressedBuffer, UncompressedBufferSize,
1281 CompressedBuffer, CompressedBufferSize, FinalUncompressedSize);
1283 return STATUS_NOT_IMPLEMENTED;
1286 /***********************************************************************
1287 * RtlSetThreadErrorMode [NTDLL.@]
1289 * Set the thread local error mode.
1291 * PARAMS
1292 * mode [I] The new error mode
1293 * oldmode [O] Destination of the old error mode (may be NULL)
1295 * RETURNS
1296 * Success: STATUS_SUCCESS
1297 * Failure: STATUS_INVALID_PARAMETER_1
1299 NTSTATUS WINAPI RtlSetThreadErrorMode( DWORD mode, LPDWORD oldmode )
1301 if (mode & ~0x70)
1302 return STATUS_INVALID_PARAMETER_1;
1304 if (oldmode)
1305 *oldmode = NtCurrentTeb()->HardErrorDisabled;
1307 NtCurrentTeb()->HardErrorDisabled = mode;
1308 return STATUS_SUCCESS;
1311 /***********************************************************************
1312 * RtlGetThreadErrorMode [NTDLL.@]
1314 * Get the thread local error mode.
1316 * PARAMS
1317 * None.
1319 * RETURNS
1320 * The current thread local error mode.
1322 DWORD WINAPI RtlGetThreadErrorMode( void )
1324 return NtCurrentTeb()->HardErrorDisabled;
1327 /******************************************************************************
1328 * RtlGetCurrentTransaction [NTDLL.@]
1330 HANDLE WINAPI RtlGetCurrentTransaction(void)
1332 FIXME("() :stub\n");
1333 return NULL;
1336 /******************************************************************************
1337 * RtlSetCurrentTransaction [NTDLL.@]
1339 BOOL WINAPI RtlSetCurrentTransaction(HANDLE new_transaction)
1341 FIXME("(%p) :stub\n", new_transaction);
1342 return FALSE;