krnl386.exe: Fix size calculation in GetSystemDirectory16.
[wine] / dlls / ntdll / rtl.c
1 /*
2  * NT basis DLL
3  *
4  * This file contains the Rtl* API functions. These should be implementable.
5  *
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)
10  *
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.
15  *
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.
20  *
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
24  */
25
26 #include "config.h"
27 #include "wine/port.h"
28
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"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
49
50 static RTL_CRITICAL_SECTION peb_lock;
51 static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
52 {
53     0, 0, &peb_lock,
54     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
55       0, 0, { (DWORD_PTR)(__FILE__ ": peb_lock") }
56 };
57 static RTL_CRITICAL_SECTION peb_lock = { &critsect_debug, -1, 0, 0, 0, 0 };
58
59 /* CRC polynomial 0xedb88320 */
60 static const DWORD CRC_table[256] =
61 {
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
105 };
106
107 /*
108  *      resource functions
109  */
110
111 /***********************************************************************
112  *           RtlInitializeResource      (NTDLL.@)
113  *
114  * xxxResource() functions implement multiple-reader-single-writer lock.
115  * The code is based on information published in WDJ January 1999 issue.
116  */
117 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
118 {
119     if( rwl )
120     {
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 );
130     }
131 }
132
133
134 /***********************************************************************
135  *           RtlDeleteResource          (NTDLL.@)
136  */
137 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
138 {
139     if( rwl )
140     {
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 );
152     }
153 }
154
155
156 /***********************************************************************
157  *          RtlAcquireResourceExclusive (NTDLL.@)
158  */
159 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
160 {
161     BYTE retVal = 0;
162     if( !rwl ) return 0;
163
164 start:
165     RtlEnterCriticalSection( &rwl->rtlCS );
166     if( rwl->iNumberActive == 0 ) /* lock is free */
167     {
168         rwl->iNumberActive = -1;
169         retVal = 1;
170     }
171     else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
172     {
173          if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
174          {
175              retVal = 1;
176              rwl->iNumberActive--;
177              goto done;
178          }
179 wait:
180          if( fWait )
181          {
182              NTSTATUS status;
183
184              rwl->uExclusiveWaiters++;
185
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 */
191          }
192     }
193     else  /* one or more shared locks are in progress */
194          if( fWait )
195              goto wait;
196
197     if( retVal == 1 )
198         rwl->hOwningThreadId = ULongToHandle(GetCurrentThreadId());
199 done:
200     RtlLeaveCriticalSection( &rwl->rtlCS );
201     return retVal;
202 }
203
204 /***********************************************************************
205  *          RtlAcquireResourceShared    (NTDLL.@)
206  */
207 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
208 {
209     NTSTATUS status = STATUS_UNSUCCESSFUL;
210     BYTE retVal = 0;
211     if( !rwl ) return 0;
212
213 start:
214     RtlEnterCriticalSection( &rwl->rtlCS );
215     if( rwl->iNumberActive < 0 )
216     {
217         if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
218         {
219             rwl->iNumberActive--;
220             retVal = 1;
221             goto done;
222         }
223
224         if( fWait )
225         {
226             rwl->uSharedWaiters++;
227             RtlLeaveCriticalSection( &rwl->rtlCS );
228             status = NtWaitForSingleObject( rwl->hSharedReleaseSemaphore, FALSE, NULL );
229             if( HIWORD(status) )
230                 goto done;
231             goto start;
232         }
233     }
234     else
235     {
236         if( status != STATUS_WAIT_0 ) /* otherwise RtlReleaseResource() has already done it */
237             rwl->iNumberActive++;
238         retVal = 1;
239     }
240 done:
241     RtlLeaveCriticalSection( &rwl->rtlCS );
242     return retVal;
243 }
244
245
246 /***********************************************************************
247  *           RtlReleaseResource         (NTDLL.@)
248  */
249 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
250 {
251     RtlEnterCriticalSection( &rwl->rtlCS );
252
253     if( rwl->iNumberActive > 0 ) /* have one or more readers */
254     {
255         if( --rwl->iNumberActive == 0 )
256         {
257             if( rwl->uExclusiveWaiters )
258             {
259 wake_exclusive:
260                 rwl->uExclusiveWaiters--;
261                 NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
262             }
263         }
264     }
265     else
266     if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
267     {
268         if( ++rwl->iNumberActive == 0 )
269         {
270             rwl->hOwningThreadId = 0;
271             if( rwl->uExclusiveWaiters )
272                 goto wake_exclusive;
273             else
274                 if( rwl->uSharedWaiters )
275                 {
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 );
281                 }
282         }
283     }
284     RtlLeaveCriticalSection( &rwl->rtlCS );
285 }
286
287
288 /***********************************************************************
289  *           RtlDumpResource            (NTDLL.@)
290  */
291 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
292 {
293     if( rwl )
294     {
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 );
299     }
300 }
301
302 /*
303  *      misc functions
304  */
305
306 /******************************************************************************
307  *      DbgPrint        [NTDLL.@]
308  */
309 NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...)
310 {
311   char buf[512];
312   __ms_va_list args;
313
314   __ms_va_start(args, fmt);
315   NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
316   __ms_va_end(args);
317
318   MESSAGE("DbgPrint says: %s",buf);
319   /* hmm, raise exception? */
320   return STATUS_SUCCESS;
321 }
322
323
324 /******************************************************************************
325  *      DbgPrintEx      [NTDLL.@]
326  */
327 NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...)
328 {
329     NTSTATUS ret;
330     __ms_va_list args;
331
332     __ms_va_start(args, fmt);
333     ret = vDbgPrintEx(iComponentId, Level, fmt, args);
334     __ms_va_end(args);
335     return ret;
336 }
337
338 /******************************************************************************
339  *      vDbgPrintEx     [NTDLL.@]
340  */
341 NTSTATUS WINAPI vDbgPrintEx( ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
342 {
343     return vDbgPrintExWithPrefix( "", id, level, fmt, args );
344 }
345
346 /******************************************************************************
347  *      vDbgPrintExWithPrefix  [NTDLL.@]
348  */
349 NTSTATUS WINAPI vDbgPrintExWithPrefix( LPCSTR prefix, ULONG id, ULONG level, LPCSTR fmt, __ms_va_list args )
350 {
351     char buf[1024];
352
353     NTDLL__vsnprintf(buf, sizeof(buf), fmt, args);
354
355     switch (level & DPFLTR_MASK)
356     {
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;
362     }
363     return STATUS_SUCCESS;
364 }
365
366 /******************************************************************************
367  *  RtlAcquirePebLock           [NTDLL.@]
368  */
369 VOID WINAPI RtlAcquirePebLock(void)
370 {
371     RtlEnterCriticalSection( &peb_lock );
372 }
373
374 /******************************************************************************
375  *  RtlReleasePebLock           [NTDLL.@]
376  */
377 VOID WINAPI RtlReleasePebLock(void)
378 {
379     RtlLeaveCriticalSection( &peb_lock );
380 }
381
382 /******************************************************************************
383  *  RtlNewSecurityObject                [NTDLL.@]
384  */
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 )
392 {
393     FIXME("(%p %p %p %d %p %p) stub!\n", ParentDescriptor, CreatorDescriptor,
394           NewDescriptor, IsDirectoryObject, Token, GenericMapping);
395     return STATUS_NOT_IMPLEMENTED;
396 }
397
398 /******************************************************************************
399  *  RtlDeleteSecurityObject             [NTDLL.@]
400  */
401 NTSTATUS WINAPI
402 RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR *ObjectDescriptor )
403 {
404     FIXME("(%p) stub!\n", ObjectDescriptor);
405     return STATUS_NOT_IMPLEMENTED;
406 }
407
408 /**************************************************************************
409  *                 _chkstk                              [NTDLL.@]
410  *
411  * Glorified "enter xxxx".
412  */
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
422
423 /**************************************************************************
424  *                 _alloca_probe                        [NTDLL.@]
425  *
426  * Glorified "enter xxxx".
427  */
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
437
438
439 /******************************************************************************
440  *  RtlInitializeGenericTable           [NTDLL.@]
441  */
442 PVOID WINAPI RtlInitializeGenericTable(PVOID pTable, PVOID arg2, PVOID arg3, PVOID arg4, PVOID arg5)
443 {
444   FIXME("(%p,%p,%p,%p,%p) stub!\n", pTable, arg2, arg3, arg4, arg5);
445   return NULL;
446 }
447
448 /******************************************************************************
449  *  RtlEnumerateGenericTableWithoutSplaying           [NTDLL.@]
450  */
451 PVOID RtlEnumerateGenericTableWithoutSplaying(PVOID pTable, PVOID *RestartKey)
452 {
453     static int warn_once;
454
455     if (!warn_once++)
456         FIXME("(%p,%p) stub!\n", pTable, RestartKey);
457     return NULL;
458 }
459
460 /******************************************************************************
461  *  RtlNumberGenericTableElements           [NTDLL.@]
462  */
463 ULONG RtlNumberGenericTableElements(PVOID pTable)
464 {
465     FIXME("(%p) stub!\n", pTable);
466     return 0;
467 }
468
469 /******************************************************************************
470  *  RtlMoveMemory   [NTDLL.@]
471  *
472  * Move a block of memory that may overlap.
473  *
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
478  *
479  * RETURNS
480  *  Nothing.
481  */
482 #undef RtlMoveMemory
483 VOID WINAPI RtlMoveMemory( VOID *Destination, CONST VOID *Source, SIZE_T Length )
484 {
485     memmove(Destination, Source, Length);
486 }
487
488 /******************************************************************************
489  *  RtlFillMemory   [NTDLL.@]
490  *
491  * Set a block of memory with a value.
492  *
493  * PARAMS
494  *  Destination [O] Block to fill
495  *  Length      [I] Number of bytes to fill
496  *  Fill        [I] Value to set
497  *
498  * RETURNS
499  *  Nothing.
500  */
501 #undef RtlFillMemory
502 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
503 {
504     memset(Destination, Fill, Length);
505 }
506
507 /******************************************************************************
508  *  RtlZeroMemory   [NTDLL.@]
509  *
510  * Set a block of memory with 0's.
511  *
512  * PARAMS
513  *  Destination [O] Block to fill
514  *  Length      [I] Number of bytes to fill
515  *
516  * RETURNS
517  *  Nothing.
518  */
519 #undef RtlZeroMemory
520 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
521 {
522     memset(Destination, 0, Length);
523 }
524
525 /******************************************************************************
526  *  RtlCompareMemory   [NTDLL.@]
527  *
528  * Compare one block of memory with another
529  *
530  * PARAMS
531  *  Source1 [I] Source block
532  *  Source2 [I] Block to compare to Source1
533  *  Length  [I] Number of bytes to compare
534  *
535  * RETURNS
536  *  The length of the first byte at which Source1 and Source2 differ, or Length
537  *  if they are the same.
538  */
539 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
540 {
541     SIZE_T i;
542     for(i=0; (i<Length) && (((const BYTE*)Source1)[i]==((const BYTE*)Source2)[i]); i++);
543     return i;
544 }
545
546 /******************************************************************************
547  *  RtlCompareMemoryUlong   [NTDLL.@]
548  *
549  * Compare a block of memory with a value, a ULONG at a time
550  *
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
555  *
556  * RETURNS
557  *  The byte position of the first byte at which Source1 is not dwVal.
558  */
559 SIZE_T WINAPI RtlCompareMemoryUlong(const ULONG *Source1, SIZE_T Length, ULONG dwVal)
560 {
561     SIZE_T i;
562     for(i = 0; i < Length/sizeof(ULONG) && Source1[i] == dwVal; i++);
563     return i * sizeof(ULONG);
564 }
565
566 /******************************************************************************
567  *  RtlAssert                           [NTDLL.@]
568  *
569  * Fail a debug assertion.
570  *
571  * RETURNS
572  *  Nothing. This call does not return control to its caller.
573  *
574  * NOTES
575  * Not implemented in non-debug versions.
576  */
577 void WINAPI RtlAssert(LPVOID x1,LPVOID x2,DWORD x3, DWORD x4)
578 {
579         FIXME("(%p,%p,0x%08x,0x%08x),stub\n",x1,x2,x3,x4);
580 }
581
582 /*************************************************************************
583  * RtlFillMemoryUlong   [NTDLL.@]
584  *
585  * Fill memory with a 32 bit (dword) value.
586  *
587  * PARAMS
588  *  lpDest  [I] Bitmap pointer
589  *  ulCount [I] Number of dwords to write
590  *  ulValue [I] Value to fill with
591  *
592  * RETURNS
593  *  Nothing.
594  */
595 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
596 {
597   TRACE("(%p,%d,%d)\n", lpDest, ulCount, ulValue);
598
599   ulCount /= sizeof(ULONG);
600   while(ulCount--)
601     *lpDest++ = ulValue;
602 }
603
604 /*********************************************************************
605  *                  RtlComputeCrc32   [NTDLL.@]
606  *
607  * Calculate the CRC32 checksum of a block of bytes
608  *
609  * PARAMS
610  *  dwInitial [I] Initial CRC value
611  *  pData     [I] Data block
612  *  iLen      [I] Length of the byte block
613  *
614  * RETURNS
615  *  The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
616  */
617 DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
618 {
619   DWORD crc = ~dwInitial;
620
621   TRACE("(%d,%p,%d)\n", dwInitial, pData, iLen);
622
623   while (iLen > 0)
624   {
625     crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
626     pData++;
627     iLen--;
628   }
629   return ~crc;
630 }
631
632
633 /*************************************************************************
634  * RtlUlonglongByteSwap    [NTDLL.@]
635  *
636  * Swap the bytes of an unsigned long long value.
637  *
638  * PARAMS
639  *  i [I] Value to swap bytes of
640  *
641  * RETURNS
642  *  The value with its bytes swapped.
643  */
644 ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i)
645 {
646   return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32);
647 }
648
649 /*************************************************************************
650  * RtlUlongByteSwap    [NTDLL.@]
651  *
652  * Swap the bytes of an unsigned int value.
653  *
654  * NOTES
655  *  ix86 version takes argument in %ecx. Other systems use the inline version.
656  */
657 #ifdef __i386__
658 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap,
659                   "movl %ecx,%eax\n\t"
660                   "bswap %eax\n\t"
661                   "ret")
662 #endif
663
664 /*************************************************************************
665  * RtlUshortByteSwap    [NTDLL.@]
666  *
667  * Swap the bytes of an unsigned short value.
668  *
669  * NOTES
670  *  i386 version takes argument in %cx. Other systems use the inline version.
671  */
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
678
679
680 /*************************************************************************
681  * RtlUniform   [NTDLL.@]
682  *
683  * Generates an uniform random number
684  *
685  * PARAMS
686  *  seed [O] The seed of the Random function
687  *
688  * RETURNS
689  *  It returns a random number uniformly distributed over [0..MAXLONG-1].
690  *
691  * NOTES
692  *  Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
693  *  In our case the algorithm is:
694  *
695  *|  result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
696  *|
697  *|  *seed = result;
698  *
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].
704  */
705 ULONG WINAPI RtlUniform (PULONG seed)
706 {
707     ULONG result;
708
709    /*
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.
713     */
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;
726 }
727
728
729 /*************************************************************************
730  * RtlRandom   [NTDLL.@]
731  *
732  * Generates a random number
733  *
734  * PARAMS
735  *  seed [O] The seed of the Random function
736  *
737  * RETURNS
738  *  It returns a random number distributed over [0..MAXLONG-1].
739  */
740 ULONG WINAPI RtlRandom (PULONG seed)
741 {
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;
762
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);
769 }
770
771
772 /*************************************************************************
773  * RtlAreAllAccessesGranted   [NTDLL.@]
774  *
775  * Check if all desired accesses are granted
776  *
777  * RETURNS
778  *  TRUE: All desired accesses are granted
779  *  FALSE: Otherwise
780  */
781 BOOLEAN WINAPI RtlAreAllAccessesGranted(
782     ACCESS_MASK GrantedAccess,
783     ACCESS_MASK DesiredAccess)
784 {
785     return (GrantedAccess & DesiredAccess) == DesiredAccess;
786 }
787
788
789 /*************************************************************************
790  * RtlAreAnyAccessesGranted   [NTDLL.@]
791  *
792  * Check if at least one of the desired accesses is granted
793  *
794  * PARAMS
795  *  GrantedAccess [I] Access mask of granted accesses
796  *  DesiredAccess [I] Access mask of desired accesses
797  *
798  * RETURNS
799  *  TRUE: At least one of the desired accesses is granted
800  *  FALSE: Otherwise
801  */
802 BOOLEAN WINAPI RtlAreAnyAccessesGranted(
803     ACCESS_MASK GrantedAccess,
804     ACCESS_MASK DesiredAccess)
805 {
806     return (GrantedAccess & DesiredAccess) != 0;
807 }
808
809
810 /*************************************************************************
811  * RtlMapGenericMask   [NTDLL.@]
812  *
813  * Determine the nongeneric access rights specified by an access mask
814  *
815  * RETURNS
816  *  Nothing.
817  */
818 void WINAPI RtlMapGenericMask(
819     PACCESS_MASK AccessMask,
820     const GENERIC_MAPPING *GenericMapping)
821 {
822     if (*AccessMask & GENERIC_READ) {
823         *AccessMask |= GenericMapping->GenericRead;
824     } /* if */
825
826     if (*AccessMask & GENERIC_WRITE) {
827         *AccessMask |= GenericMapping->GenericWrite;
828     } /* if */
829
830     if (*AccessMask & GENERIC_EXECUTE) {
831         *AccessMask |= GenericMapping->GenericExecute;
832     } /* if */
833
834     if (*AccessMask & GENERIC_ALL) {
835         *AccessMask |= GenericMapping->GenericAll;
836     } /* if */
837
838     *AccessMask &= 0x0FFFFFFF;
839 }
840
841
842 /*************************************************************************
843  * RtlCopyLuid   [NTDLL.@]
844  *
845  * Copy a local unique ID.
846  *
847  * PARAMS
848  *  LuidDest [O] Destination for the copied Luid
849  *  LuidSrc  [I] Source Luid to copy to LuidDest
850  *
851  * RETURNS
852  *  Nothing.
853  */
854 void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc)
855 {
856     *LuidDest = *LuidSrc;
857 }
858
859
860 /*************************************************************************
861  * RtlEqualLuid   [NTDLL.@]
862  *
863  * Compare two local unique ID's.
864  *
865  * PARAMS
866  *  Luid1 [I] First Luid to compare to Luid2
867  *  Luid2 [I] Second Luid to compare to Luid1
868  *
869  * RETURNS
870  *  TRUE: The two LUID's are equal.
871  *  FALSE: Otherwise
872  */
873 BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2)
874 {
875   return (Luid1->LowPart ==  Luid2->LowPart && Luid1->HighPart == Luid2->HighPart);
876 }
877
878
879 /*************************************************************************
880  * RtlCopyLuidAndAttributesArray   [NTDLL.@]
881  *
882  * Copy an array of local unique ID's and attributes.
883  *
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
888  *
889  * RETURNS
890  *  Nothing.
891  *
892  * NOTES
893  *  Dest must be large enough to hold Src.
894  */
895 void WINAPI RtlCopyLuidAndAttributesArray(
896     ULONG Count,
897     const LUID_AND_ATTRIBUTES *Src,
898     PLUID_AND_ATTRIBUTES Dest)
899 {
900     ULONG i;
901
902     for (i = 0; i < Count; i++) Dest[i] = Src[i];
903 }
904
905 NTSTATUS WINAPI RtlIpv4StringToAddressExW(PULONG IP, PULONG Port,
906                                           LPCWSTR Buffer, PULONG MaxSize)
907 {
908     FIXME("(%p,%p,%p,%p): stub\n", IP, Port, Buffer, MaxSize);
909
910     return STATUS_SUCCESS;
911 }
912
913 /***********************************************************************
914  * RtlIpv4AddressToStringExW [NTDLL.@]
915  *
916  * Convert the given ipv4 address and optional the port to a string
917  *
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
923  *
924  * RETURNS
925  *  Success: STATUS_SUCCESS
926  *  Failure: STATUS_INVALID_PARAMETER
927  *
928  */
929 NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
930 {
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;
935
936     if (!pin || !buffer || !psize)
937         return STATUS_INVALID_PARAMETER;
938
939     TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
940
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);
944
945     if (port) needed += sprintfW(tmp_ip + needed, fmt_port, ntohs(port));
946
947     if (*psize > needed) {
948         *psize = needed + 1;
949         strcpyW(buffer, tmp_ip);
950         return STATUS_SUCCESS;
951     }
952
953     *psize = needed + 1;
954     return STATUS_INVALID_PARAMETER;
955 }
956
957 /***********************************************************************
958  * RtlIpv4AddressToStringExA [NTDLL.@]
959  *
960  * Convert the given ipv4 address and optional the port to a string
961  *
962  * See RtlIpv4AddressToStringExW
963  */
964 NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
965 {
966     CHAR tmp_ip[32];
967     ULONG needed;
968
969     if (!pin || !buffer || !psize)
970         return STATUS_INVALID_PARAMETER;
971
972     TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
973
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);
977
978     if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
979
980     if (*psize > needed) {
981         *psize = needed + 1;
982         strcpy(buffer, tmp_ip);
983         return STATUS_SUCCESS;
984     }
985
986     *psize = needed + 1;
987     return STATUS_INVALID_PARAMETER;
988 }
989
990 /***********************************************************************
991  * RtlIpv4AddressToStringW [NTDLL.@]
992  *
993  * Convert the given ipv4 address to a string
994  *
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)
998  *
999  * RETURNS
1000  *  PTR to the 0 character at the end of the converted string
1001  *
1002  */
1003 WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
1004 {
1005     ULONG size = 16;
1006
1007     if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
1008     return buffer + size - 1;
1009 }
1010
1011 /***********************************************************************
1012  * RtlIpv4AddressToStringA [NTDLL.@]
1013  *
1014  * Convert the given ipv4 address to a string
1015  *
1016  * See RtlIpv4AddressToStringW
1017  */
1018 CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
1019 {
1020     ULONG size = 16;
1021
1022     if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
1023     return buffer + size - 1;
1024 }
1025
1026 /***********************************************************************
1027  * get_pointer_obfuscator (internal)
1028  */
1029 static DWORD_PTR get_pointer_obfuscator( void )
1030 {
1031     static DWORD_PTR pointer_obfuscator;
1032
1033     if (!pointer_obfuscator)
1034     {
1035         ULONG seed = NtGetTickCount();
1036         ULONG_PTR rand;
1037
1038         /* generate a random value for the obfuscator */
1039         rand = RtlUniform( &seed );
1040
1041         /* handle 64bit pointers */
1042         rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1043
1044         /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1045         rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1046
1047         interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator, (void*) rand, NULL );
1048     }
1049
1050     return pointer_obfuscator;
1051 }
1052
1053 /*************************************************************************
1054  * RtlEncodePointer   [NTDLL.@]
1055  */
1056 PVOID WINAPI RtlEncodePointer( PVOID ptr )
1057 {
1058     DWORD_PTR ptrval = (DWORD_PTR) ptr;
1059     return (PVOID)(ptrval ^ get_pointer_obfuscator());
1060 }
1061
1062 PVOID WINAPI RtlDecodePointer( PVOID ptr )
1063 {
1064     DWORD_PTR ptrval = (DWORD_PTR) ptr;
1065     return (PVOID)(ptrval ^ get_pointer_obfuscator());
1066 }
1067
1068 /*************************************************************************
1069  * RtlInitializeSListHead   [NTDLL.@]
1070  */
1071 VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
1072 {
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
1079 }
1080
1081 /*************************************************************************
1082  * RtlQueryDepthSList   [NTDLL.@]
1083  */
1084 WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
1085 {
1086 #ifdef _WIN64
1087     return list->Header16.Depth;
1088 #else
1089     return list->s.Depth;
1090 #endif
1091 }
1092
1093 /*************************************************************************
1094  * RtlFirstEntrySList   [NTDLL.@]
1095  */
1096 PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
1097 {
1098 #ifdef _WIN64
1099     return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
1100 #else
1101     return list->s.Next.Next;
1102 #endif
1103 }
1104
1105 /*************************************************************************
1106  * RtlInterlockedFlushSList   [NTDLL.@]
1107  */
1108 PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
1109 {
1110     SLIST_HEADER old, new;
1111
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 */
1116     do
1117     {
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;
1125     do
1126     {
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
1133 }
1134
1135 /*************************************************************************
1136  * RtlInterlockedPushEntrySList   [NTDLL.@]
1137  */
1138 PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
1139 {
1140     SLIST_HEADER old, new;
1141
1142 #ifdef _WIN64
1143     new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
1144     do
1145     {
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;
1154     do
1155     {
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
1164 }
1165
1166 /*************************************************************************
1167  * RtlInterlockedPopEntrySList   [NTDLL.@]
1168  */
1169 PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
1170 {
1171     SLIST_HEADER old, new;
1172     PSLIST_ENTRY entry;
1173
1174 #ifdef _WIN64
1175     do
1176     {
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
1181         {
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;
1185         }
1186         __EXCEPT_PAGE_FAULT
1187         {
1188         }
1189         __ENDTRY
1190     } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1191 #else
1192     do
1193     {
1194         old = *list;
1195         if (!(entry = old.s.Next.Next)) return NULL;
1196         /* entry could be deleted by another thread */
1197         __TRY
1198         {
1199             new.s.Next.Next = entry->Next;
1200             new.s.Depth = old.s.Depth - 1;
1201             new.s.Sequence = old.s.Sequence + 1;
1202         }
1203         __EXCEPT_PAGE_FAULT
1204         {
1205         }
1206         __ENDTRY
1207     } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1208                                    old.Alignment) != old.Alignment);
1209 #endif
1210     return entry;
1211 }
1212
1213 /*************************************************************************
1214  * RtlInterlockedPushListSList   [NTDLL.@]
1215  */
1216 PSLIST_ENTRY WINAPI RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1217                                                 PSLIST_ENTRY last, ULONG count)
1218 {
1219     SLIST_HEADER old, new;
1220
1221 #ifdef _WIN64
1222     new.Header16.NextEntry = (ULONG_PTR)first >> 4;
1223     do
1224     {
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;
1233     do
1234     {
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
1243 }
1244
1245 /******************************************************************************
1246  *  RtlGetCompressionWorkSpaceSize              [NTDLL.@]
1247  */
1248 NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT CompressionFormatAndEngine,
1249                                                PULONG CompressBufferWorkSpaceSize,
1250                                                PULONG CompressFragmentWorkSpaceSize)
1251 {
1252     FIXME("0x%04x, %p, %p: stub!\n", CompressionFormatAndEngine, CompressBufferWorkSpaceSize,
1253          CompressFragmentWorkSpaceSize);
1254
1255     return STATUS_NOT_IMPLEMENTED;
1256 }
1257
1258 /******************************************************************************
1259  *  RtlCompressBuffer           [NTDLL.@]
1260  */
1261 NTSTATUS WINAPI RtlCompressBuffer(USHORT CompressionFormatAndEngine, PUCHAR UncompressedBuffer,
1262                                   ULONG UncompressedBufferSize, PUCHAR CompressedBuffer,
1263                                   ULONG CompressedBufferSize, ULONG UncompressedChunkSize,
1264                                   PULONG FinalCompressedSize, PVOID WorkSpace)
1265 {
1266     FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p :stub\n", CompressionFormatAndEngine, UncompressedBuffer,
1267          UncompressedBufferSize, CompressedBuffer, CompressedBufferSize, UncompressedChunkSize,
1268          FinalCompressedSize, WorkSpace);
1269
1270     return STATUS_NOT_IMPLEMENTED;
1271 }
1272
1273 /******************************************************************************
1274  *  RtlDecompressBuffer         [NTDLL.@]
1275  */
1276 NTSTATUS WINAPI RtlDecompressBuffer(USHORT CompressionFormat, PUCHAR UncompressedBuffer,
1277                                     ULONG UncompressedBufferSize, PUCHAR CompressedBuffer,
1278                                     ULONG CompressedBufferSize, PULONG FinalUncompressedSize)
1279 {
1280     FIXME("0x%04x, %p, %u, %p, %u, %p :stub\n", CompressionFormat, UncompressedBuffer, UncompressedBufferSize,
1281          CompressedBuffer, CompressedBufferSize, FinalUncompressedSize);
1282
1283     return STATUS_NOT_IMPLEMENTED;
1284 }
1285
1286 /***********************************************************************
1287  *  RtlSetThreadErrorMode       [NTDLL.@]
1288  *
1289  * Set the thread local error mode.
1290  *
1291  * PARAMS
1292  *  mode    [I] The new error mode
1293  *  oldmode [O] Destination of the old error mode (may be NULL)
1294  *
1295  * RETURNS
1296  *  Success: STATUS_SUCCESS
1297  *  Failure: STATUS_INVALID_PARAMETER_1
1298  */
1299 NTSTATUS WINAPI RtlSetThreadErrorMode( DWORD mode, LPDWORD oldmode )
1300 {
1301     if (mode & ~0x70)
1302         return STATUS_INVALID_PARAMETER_1;
1303
1304     if (oldmode)
1305         *oldmode = NtCurrentTeb()->HardErrorDisabled;
1306
1307     NtCurrentTeb()->HardErrorDisabled = mode;
1308     return STATUS_SUCCESS;
1309 }
1310
1311 /***********************************************************************
1312  *  RtlGetThreadErrorMode       [NTDLL.@]
1313  *
1314  * Get the thread local error mode.
1315  *
1316  * PARAMS
1317  *  None.
1318  *
1319  * RETURNS
1320  *  The current thread local error mode.
1321  */
1322 DWORD WINAPI RtlGetThreadErrorMode( void )
1323 {
1324     return NtCurrentTeb()->HardErrorDisabled;
1325 }
1326
1327 /******************************************************************************
1328  * RtlGetCurrentTransaction [NTDLL.@]
1329  */
1330 HANDLE WINAPI RtlGetCurrentTransaction(void)
1331 {
1332     FIXME("() :stub\n");
1333     return NULL;
1334 }
1335
1336 /******************************************************************************
1337  * RtlSetCurrentTransaction [NTDLL.@]
1338  */
1339 BOOL WINAPI RtlSetCurrentTransaction(HANDLE new_transaction)
1340 {
1341     FIXME("(%p) :stub\n", new_transaction);
1342     return FALSE;
1343 }