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 ERR("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 * RtlInitializeGenericTable [NTDLL.@]
410 */
411 PVOID WINAPI RtlInitializeGenericTable(PVOID pTable, PVOID arg2, PVOID arg3, PVOID arg4, PVOID arg5)
412 {
413 FIXME("(%p,%p,%p,%p,%p) stub!\n", pTable, arg2, arg3, arg4, arg5);
414 return NULL;
415 }
416
417 /******************************************************************************
418 * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
419 */
420 PVOID RtlEnumerateGenericTableWithoutSplaying(PVOID pTable, PVOID *RestartKey)
421 {
422 static int warn_once;
423
424 if (!warn_once++)
425 FIXME("(%p,%p) stub!\n", pTable, RestartKey);
426 return NULL;
427 }
428
429 /******************************************************************************
430 * RtlNumberGenericTableElements [NTDLL.@]
431 */
432 ULONG RtlNumberGenericTableElements(PVOID pTable)
433 {
434 FIXME("(%p) stub!\n", pTable);
435 return 0;
436 }
437
438 /******************************************************************************
439 * RtlMoveMemory [NTDLL.@]
440 *
441 * Move a block of memory that may overlap.
442 *
443 * PARAMS
444 * Destination [O] End destination for block
445 * Source [O] Where to start copying from
446 * Length [I] Number of bytes to copy
447 *
448 * RETURNS
449 * Nothing.
450 */
451 #undef RtlMoveMemory
452 VOID WINAPI RtlMoveMemory( VOID *Destination, CONST VOID *Source, SIZE_T Length )
453 {
454 memmove(Destination, Source, Length);
455 }
456
457 /******************************************************************************
458 * RtlFillMemory [NTDLL.@]
459 *
460 * Set a block of memory with a value.
461 *
462 * PARAMS
463 * Destination [O] Block to fill
464 * Length [I] Number of bytes to fill
465 * Fill [I] Value to set
466 *
467 * RETURNS
468 * Nothing.
469 */
470 #undef RtlFillMemory
471 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
472 {
473 memset(Destination, Fill, Length);
474 }
475
476 /******************************************************************************
477 * RtlZeroMemory [NTDLL.@]
478 *
479 * Set a block of memory with 0's.
480 *
481 * PARAMS
482 * Destination [O] Block to fill
483 * Length [I] Number of bytes to fill
484 *
485 * RETURNS
486 * Nothing.
487 */
488 #undef RtlZeroMemory
489 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
490 {
491 memset(Destination, 0, Length);
492 }
493
494 /******************************************************************************
495 * RtlCompareMemory [NTDLL.@]
496 *
497 * Compare one block of memory with another
498 *
499 * PARAMS
500 * Source1 [I] Source block
501 * Source2 [I] Block to compare to Source1
502 * Length [I] Number of bytes to compare
503 *
504 * RETURNS
505 * The length of the first byte at which Source1 and Source2 differ, or Length
506 * if they are the same.
507 */
508 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
509 {
510 SIZE_T i;
511 for(i=0; (i<Length) && (((const BYTE*)Source1)[i]==((const BYTE*)Source2)[i]); i++);
512 return i;
513 }
514
515 /******************************************************************************
516 * RtlCompareMemoryUlong [NTDLL.@]
517 *
518 * Compare a block of memory with a value, a ULONG at a time
519 *
520 * PARAMS
521 * Source1 [I] Source block. This must be ULONG aligned
522 * Length [I] Number of bytes to compare. This should be a multiple of 4
523 * dwVal [I] Value to compare to
524 *
525 * RETURNS
526 * The byte position of the first byte at which Source1 is not dwVal.
527 */
528 SIZE_T WINAPI RtlCompareMemoryUlong(const ULONG *Source1, SIZE_T Length, ULONG dwVal)
529 {
530 SIZE_T i;
531 for(i = 0; i < Length/sizeof(ULONG) && Source1[i] == dwVal; i++);
532 return i * sizeof(ULONG);
533 }
534
535 /******************************************************************************
536 * RtlAssert [NTDLL.@]
537 *
538 * Fail a debug assertion.
539 *
540 * RETURNS
541 * Nothing. This call does not return control to its caller.
542 *
543 * NOTES
544 * Not implemented in non-debug versions.
545 */
546 void WINAPI RtlAssert(LPVOID x1,LPVOID x2,DWORD x3, DWORD x4)
547 {
548 FIXME("(%p,%p,0x%08x,0x%08x),stub\n",x1,x2,x3,x4);
549 }
550
551 /*************************************************************************
552 * RtlFillMemoryUlong [NTDLL.@]
553 *
554 * Fill memory with a 32 bit (dword) value.
555 *
556 * PARAMS
557 * lpDest [I] Bitmap pointer
558 * ulCount [I] Number of dwords to write
559 * ulValue [I] Value to fill with
560 *
561 * RETURNS
562 * Nothing.
563 */
564 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
565 {
566 TRACE("(%p,%d,%d)\n", lpDest, ulCount, ulValue);
567
568 ulCount /= sizeof(ULONG);
569 while(ulCount--)
570 *lpDest++ = ulValue;
571 }
572
573 /*********************************************************************
574 * RtlComputeCrc32 [NTDLL.@]
575 *
576 * Calculate the CRC32 checksum of a block of bytes
577 *
578 * PARAMS
579 * dwInitial [I] Initial CRC value
580 * pData [I] Data block
581 * iLen [I] Length of the byte block
582 *
583 * RETURNS
584 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
585 */
586 DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
587 {
588 DWORD crc = ~dwInitial;
589
590 TRACE("(%d,%p,%d)\n", dwInitial, pData, iLen);
591
592 while (iLen > 0)
593 {
594 crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
595 pData++;
596 iLen--;
597 }
598 return ~crc;
599 }
600
601
602 /*************************************************************************
603 * RtlUlonglongByteSwap [NTDLL.@]
604 *
605 * Swap the bytes of an unsigned long long value.
606 *
607 * PARAMS
608 * i [I] Value to swap bytes of
609 *
610 * RETURNS
611 * The value with its bytes swapped.
612 */
613 ULONGLONG __cdecl RtlUlonglongByteSwap(ULONGLONG i)
614 {
615 return ((ULONGLONG)RtlUlongByteSwap(i) << 32) | RtlUlongByteSwap(i>>32);
616 }
617
618 /*************************************************************************
619 * RtlUlongByteSwap [NTDLL.@]
620 *
621 * Swap the bytes of an unsigned int value.
622 *
623 * NOTES
624 * ix86 version takes argument in %ecx. Other systems use the inline version.
625 */
626 #ifdef __i386__
627 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap,
628 "movl %ecx,%eax\n\t"
629 "bswap %eax\n\t"
630 "ret")
631 #endif
632
633 /*************************************************************************
634 * RtlUshortByteSwap [NTDLL.@]
635 *
636 * Swap the bytes of an unsigned short value.
637 *
638 * NOTES
639 * i386 version takes argument in %cx. Other systems use the inline version.
640 */
641 #ifdef __i386__
642 __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap,
643 "movb %ch,%al\n\t"
644 "movb %cl,%ah\n\t"
645 "ret")
646 #endif
647
648
649 /*************************************************************************
650 * RtlUniform [NTDLL.@]
651 *
652 * Generates an uniform random number
653 *
654 * PARAMS
655 * seed [O] The seed of the Random function
656 *
657 * RETURNS
658 * It returns a random number uniformly distributed over [0..MAXLONG-1].
659 *
660 * NOTES
661 * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
662 * In our case the algorithm is:
663 *
664 *| result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
665 *|
666 *| *seed = result;
667 *
668 * DIFFERENCES
669 * The native documentation states that the random number is
670 * uniformly distributed over [0..MAXLONG]. In reality the native
671 * function and our function return a random number uniformly
672 * distributed over [0..MAXLONG-1].
673 */
674 ULONG WINAPI RtlUniform (PULONG seed)
675 {
676 ULONG result;
677
678 /*
679 * Instead of the algorithm stated above, we use the algorithm
680 * below, which is totally equivalent (see the tests), but does
681 * not use a division and therefore is faster.
682 */
683 result = *seed * 0xffffffed + 0x7fffffc3;
684 if (result == 0xffffffff || result == 0x7ffffffe) {
685 result = (result + 2) & MAXLONG;
686 } else if (result == 0x7fffffff) {
687 result = 0;
688 } else if ((result & 0x80000000) == 0) {
689 result = result + (~result & 1);
690 } else {
691 result = (result + (result & 1)) & MAXLONG;
692 } /* if */
693 *seed = result;
694 return result;
695 }
696
697
698 /*************************************************************************
699 * RtlRandom [NTDLL.@]
700 *
701 * Generates a random number
702 *
703 * PARAMS
704 * seed [O] The seed of the Random function
705 *
706 * RETURNS
707 * It returns a random number distributed over [0..MAXLONG-1].
708 */
709 ULONG WINAPI RtlRandom (PULONG seed)
710 {
711 static ULONG saved_value[128] =
712 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
713 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
714 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
715 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
716 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
717 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
718 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
719 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
720 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
721 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
722 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
723 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
724 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
725 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
726 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
727 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
728 ULONG rand;
729 int pos;
730 ULONG result;
731
732 rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
733 *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
734 pos = *seed & 0x7f;
735 result = saved_value[pos];
736 saved_value[pos] = rand;
737 return(result);
738 }
739
740
741 /*************************************************************************
742 * RtlAreAllAccessesGranted [NTDLL.@]
743 *
744 * Check if all desired accesses are granted
745 *
746 * RETURNS
747 * TRUE: All desired accesses are granted
748 * FALSE: Otherwise
749 */
750 BOOLEAN WINAPI RtlAreAllAccessesGranted(
751 ACCESS_MASK GrantedAccess,
752 ACCESS_MASK DesiredAccess)
753 {
754 return (GrantedAccess & DesiredAccess) == DesiredAccess;
755 }
756
757
758 /*************************************************************************
759 * RtlAreAnyAccessesGranted [NTDLL.@]
760 *
761 * Check if at least one of the desired accesses is granted
762 *
763 * PARAMS
764 * GrantedAccess [I] Access mask of granted accesses
765 * DesiredAccess [I] Access mask of desired accesses
766 *
767 * RETURNS
768 * TRUE: At least one of the desired accesses is granted
769 * FALSE: Otherwise
770 */
771 BOOLEAN WINAPI RtlAreAnyAccessesGranted(
772 ACCESS_MASK GrantedAccess,
773 ACCESS_MASK DesiredAccess)
774 {
775 return (GrantedAccess & DesiredAccess) != 0;
776 }
777
778
779 /*************************************************************************
780 * RtlMapGenericMask [NTDLL.@]
781 *
782 * Determine the nongeneric access rights specified by an access mask
783 *
784 * RETURNS
785 * Nothing.
786 */
787 void WINAPI RtlMapGenericMask(
788 PACCESS_MASK AccessMask,
789 const GENERIC_MAPPING *GenericMapping)
790 {
791 if (*AccessMask & GENERIC_READ) {
792 *AccessMask |= GenericMapping->GenericRead;
793 } /* if */
794
795 if (*AccessMask & GENERIC_WRITE) {
796 *AccessMask |= GenericMapping->GenericWrite;
797 } /* if */
798
799 if (*AccessMask & GENERIC_EXECUTE) {
800 *AccessMask |= GenericMapping->GenericExecute;
801 } /* if */
802
803 if (*AccessMask & GENERIC_ALL) {
804 *AccessMask |= GenericMapping->GenericAll;
805 } /* if */
806
807 *AccessMask &= 0x0FFFFFFF;
808 }
809
810
811 /*************************************************************************
812 * RtlCopyLuid [NTDLL.@]
813 *
814 * Copy a local unique ID.
815 *
816 * PARAMS
817 * LuidDest [O] Destination for the copied Luid
818 * LuidSrc [I] Source Luid to copy to LuidDest
819 *
820 * RETURNS
821 * Nothing.
822 */
823 void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc)
824 {
825 *LuidDest = *LuidSrc;
826 }
827
828
829 /*************************************************************************
830 * RtlEqualLuid [NTDLL.@]
831 *
832 * Compare two local unique IDs.
833 *
834 * PARAMS
835 * Luid1 [I] First Luid to compare to Luid2
836 * Luid2 [I] Second Luid to compare to Luid1
837 *
838 * RETURNS
839 * TRUE: The two LUIDs are equal.
840 * FALSE: Otherwise
841 */
842 BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2)
843 {
844 return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart);
845 }
846
847
848 /*************************************************************************
849 * RtlCopyLuidAndAttributesArray [NTDLL.@]
850 *
851 * Copy an array of local unique IDs and attributes.
852 *
853 * PARAMS
854 * Count [I] Number of Luid/attributes in Src
855 * Src [I] Source Luid/attributes to copy
856 * Dest [O] Destination for copied Luid/attributes
857 *
858 * RETURNS
859 * Nothing.
860 *
861 * NOTES
862 * Dest must be large enough to hold Src.
863 */
864 void WINAPI RtlCopyLuidAndAttributesArray(
865 ULONG Count,
866 const LUID_AND_ATTRIBUTES *Src,
867 PLUID_AND_ATTRIBUTES Dest)
868 {
869 ULONG i;
870
871 for (i = 0; i < Count; i++) Dest[i] = Src[i];
872 }
873
874 NTSTATUS WINAPI RtlIpv4StringToAddressExW(PULONG IP, PULONG Port,
875 LPCWSTR Buffer, PULONG MaxSize)
876 {
877 FIXME("(%p,%p,%p,%p): stub\n", IP, Port, Buffer, MaxSize);
878
879 return STATUS_SUCCESS;
880 }
881
882 /***********************************************************************
883 * RtlIpv4AddressToStringExW [NTDLL.@]
884 *
885 * Convert the given ipv4 address and optional the port to a string
886 *
887 * PARAMS
888 * pin [I] PTR to the ip address to convert (network byte order)
889 * port [I] optional port to convert (network byte order)
890 * buffer [O] destination buffer for the result
891 * psize [IO] PTR to available/used size of the destination buffer
892 *
893 * RETURNS
894 * Success: STATUS_SUCCESS
895 * Failure: STATUS_INVALID_PARAMETER
896 *
897 */
898 NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
899 {
900 WCHAR tmp_ip[32];
901 static const WCHAR fmt_ip[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
902 static const WCHAR fmt_port[] = {':','%','u',0};
903 ULONG needed;
904
905 if (!pin || !buffer || !psize)
906 return STATUS_INVALID_PARAMETER;
907
908 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
909
910 needed = sprintfW(tmp_ip, fmt_ip,
911 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
912 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
913
914 if (port) needed += sprintfW(tmp_ip + needed, fmt_port, ntohs(port));
915
916 if (*psize > needed) {
917 *psize = needed + 1;
918 strcpyW(buffer, tmp_ip);
919 return STATUS_SUCCESS;
920 }
921
922 *psize = needed + 1;
923 return STATUS_INVALID_PARAMETER;
924 }
925
926 /***********************************************************************
927 * RtlIpv4AddressToStringExA [NTDLL.@]
928 *
929 * Convert the given ipv4 address and optional the port to a string
930 *
931 * See RtlIpv4AddressToStringExW
932 */
933 NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
934 {
935 CHAR tmp_ip[32];
936 ULONG needed;
937
938 if (!pin || !buffer || !psize)
939 return STATUS_INVALID_PARAMETER;
940
941 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
942
943 needed = sprintf(tmp_ip, "%u.%u.%u.%u",
944 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
945 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
946
947 if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
948
949 if (*psize > needed) {
950 *psize = needed + 1;
951 strcpy(buffer, tmp_ip);
952 return STATUS_SUCCESS;
953 }
954
955 *psize = needed + 1;
956 return STATUS_INVALID_PARAMETER;
957 }
958
959 /***********************************************************************
960 * RtlIpv4AddressToStringW [NTDLL.@]
961 *
962 * Convert the given ipv4 address to a string
963 *
964 * PARAMS
965 * pin [I] PTR to the ip address to convert (network byte order)
966 * buffer [O] destination buffer for the result (at least 16 character)
967 *
968 * RETURNS
969 * PTR to the 0 character at the end of the converted string
970 *
971 */
972 WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
973 {
974 ULONG size = 16;
975
976 if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
977 return buffer + size - 1;
978 }
979
980 /***********************************************************************
981 * RtlIpv4AddressToStringA [NTDLL.@]
982 *
983 * Convert the given ipv4 address to a string
984 *
985 * See RtlIpv4AddressToStringW
986 */
987 CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
988 {
989 ULONG size = 16;
990
991 if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
992 return buffer + size - 1;
993 }
994
995 /***********************************************************************
996 * get_pointer_obfuscator (internal)
997 */
998 static DWORD_PTR get_pointer_obfuscator( void )
999 {
1000 static DWORD_PTR pointer_obfuscator;
1001
1002 if (!pointer_obfuscator)
1003 {
1004 ULONG seed = NtGetTickCount();
1005 ULONG_PTR rand;
1006
1007 /* generate a random value for the obfuscator */
1008 rand = RtlUniform( &seed );
1009
1010 /* handle 64bit pointers */
1011 rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1012
1013 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1014 rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1015
1016 interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator, (void*) rand, NULL );
1017 }
1018
1019 return pointer_obfuscator;
1020 }
1021
1022 /*************************************************************************
1023 * RtlEncodePointer [NTDLL.@]
1024 */
1025 PVOID WINAPI RtlEncodePointer( PVOID ptr )
1026 {
1027 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1028 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1029 }
1030
1031 PVOID WINAPI RtlDecodePointer( PVOID ptr )
1032 {
1033 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1034 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1035 }
1036
1037 /*************************************************************************
1038 * RtlInitializeSListHead [NTDLL.@]
1039 */
1040 VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
1041 {
1042 #ifdef _WIN64
1043 list->s.Alignment = list->s.Region = 0;
1044 list->Header16.HeaderType = 1; /* we use the 16-byte header */
1045 #else
1046 list->Alignment = 0;
1047 #endif
1048 }
1049
1050 /*************************************************************************
1051 * RtlQueryDepthSList [NTDLL.@]
1052 */
1053 WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
1054 {
1055 #ifdef _WIN64
1056 return list->Header16.Depth;
1057 #else
1058 return list->s.Depth;
1059 #endif
1060 }
1061
1062 /*************************************************************************
1063 * RtlFirstEntrySList [NTDLL.@]
1064 */
1065 PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
1066 {
1067 #ifdef _WIN64
1068 return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
1069 #else
1070 return list->s.Next.Next;
1071 #endif
1072 }
1073
1074 /*************************************************************************
1075 * RtlInterlockedFlushSList [NTDLL.@]
1076 */
1077 PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
1078 {
1079 SLIST_HEADER old, new;
1080
1081 #ifdef _WIN64
1082 if (!list->Header16.Depth) return NULL;
1083 new.s.Alignment = new.s.Region = 0;
1084 new.Header16.HeaderType = 1; /* we use the 16-byte header */
1085 do
1086 {
1087 old = *list;
1088 new.Header16.Sequence = old.Header16.Sequence + 1;
1089 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1090 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1091 #else
1092 if (!list->s.Depth) return NULL;
1093 new.Alignment = 0;
1094 do
1095 {
1096 old = *list;
1097 new.s.Sequence = old.s.Sequence + 1;
1098 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1099 old.Alignment) != old.Alignment);
1100 return old.s.Next.Next;
1101 #endif
1102 }
1103
1104 /*************************************************************************
1105 * RtlInterlockedPushEntrySList [NTDLL.@]
1106 */
1107 PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
1108 {
1109 SLIST_HEADER old, new;
1110
1111 #ifdef _WIN64
1112 new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
1113 do
1114 {
1115 old = *list;
1116 entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1117 new.Header16.Depth = old.Header16.Depth + 1;
1118 new.Header16.Sequence = old.Header16.Sequence + 1;
1119 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1120 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1121 #else
1122 new.s.Next.Next = entry;
1123 do
1124 {
1125 old = *list;
1126 entry->Next = old.s.Next.Next;
1127 new.s.Depth = old.s.Depth + 1;
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 * RtlInterlockedPopEntrySList [NTDLL.@]
1137 */
1138 PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
1139 {
1140 SLIST_HEADER old, new;
1141 PSLIST_ENTRY entry;
1142
1143 #ifdef _WIN64
1144 do
1145 {
1146 old = *list;
1147 if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
1148 /* entry could be deleted by another thread */
1149 __TRY
1150 {
1151 new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
1152 new.Header16.Depth = old.Header16.Depth - 1;
1153 new.Header16.Sequence = old.Header16.Sequence + 1;
1154 }
1155 __EXCEPT_PAGE_FAULT
1156 {
1157 }
1158 __ENDTRY
1159 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1160 #else
1161 do
1162 {
1163 old = *list;
1164 if (!(entry = old.s.Next.Next)) return NULL;
1165 /* entry could be deleted by another thread */
1166 __TRY
1167 {
1168 new.s.Next.Next = entry->Next;
1169 new.s.Depth = old.s.Depth - 1;
1170 new.s.Sequence = old.s.Sequence + 1;
1171 }
1172 __EXCEPT_PAGE_FAULT
1173 {
1174 }
1175 __ENDTRY
1176 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1177 old.Alignment) != old.Alignment);
1178 #endif
1179 return entry;
1180 }
1181
1182 /*************************************************************************
1183 * RtlInterlockedPushListSList [NTDLL.@]
1184 */
1185 PSLIST_ENTRY WINAPI RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1186 PSLIST_ENTRY last, ULONG count)
1187 {
1188 SLIST_HEADER old, new;
1189
1190 #ifdef _WIN64
1191 new.Header16.NextEntry = (ULONG_PTR)first >> 4;
1192 do
1193 {
1194 old = *list;
1195 new.Header16.Depth = old.Header16.Depth + count;
1196 new.Header16.Sequence = old.Header16.Sequence + 1;
1197 last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1198 } while (!interlocked_cmpxchg128((__int64 *)list, new.s.Region, new.s.Alignment, (__int64 *)&old));
1199 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1200 #else
1201 new.s.Next.Next = first;
1202 do
1203 {
1204 old = *list;
1205 new.s.Depth = old.s.Depth + count;
1206 new.s.Sequence = old.s.Sequence + 1;
1207 last->Next = old.s.Next.Next;
1208 } while (interlocked_cmpxchg64((__int64 *)&list->Alignment, new.Alignment,
1209 old.Alignment) != old.Alignment);
1210 return old.s.Next.Next;
1211 #endif
1212 }
1213
1214 /******************************************************************************
1215 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1216 */
1217 NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT CompressionFormatAndEngine,
1218 PULONG CompressBufferWorkSpaceSize,
1219 PULONG CompressFragmentWorkSpaceSize)
1220 {
1221 FIXME("0x%04x, %p, %p: stub!\n", CompressionFormatAndEngine, CompressBufferWorkSpaceSize,
1222 CompressFragmentWorkSpaceSize);
1223
1224 return STATUS_NOT_IMPLEMENTED;
1225 }
1226
1227 /******************************************************************************
1228 * RtlCompressBuffer [NTDLL.@]
1229 */
1230 NTSTATUS WINAPI RtlCompressBuffer(USHORT CompressionFormatAndEngine, PUCHAR UncompressedBuffer,
1231 ULONG UncompressedBufferSize, PUCHAR CompressedBuffer,
1232 ULONG CompressedBufferSize, ULONG UncompressedChunkSize,
1233 PULONG FinalCompressedSize, PVOID WorkSpace)
1234 {
1235 FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p :stub\n", CompressionFormatAndEngine, UncompressedBuffer,
1236 UncompressedBufferSize, CompressedBuffer, CompressedBufferSize, UncompressedChunkSize,
1237 FinalCompressedSize, WorkSpace);
1238
1239 return STATUS_NOT_IMPLEMENTED;
1240 }
1241
1242 /******************************************************************************
1243 * RtlDecompressBuffer [NTDLL.@]
1244 */
1245 NTSTATUS WINAPI RtlDecompressBuffer(USHORT CompressionFormat, PUCHAR UncompressedBuffer,
1246 ULONG UncompressedBufferSize, PUCHAR CompressedBuffer,
1247 ULONG CompressedBufferSize, PULONG FinalUncompressedSize)
1248 {
1249 FIXME("0x%04x, %p, %u, %p, %u, %p :stub\n", CompressionFormat, UncompressedBuffer, UncompressedBufferSize,
1250 CompressedBuffer, CompressedBufferSize, FinalUncompressedSize);
1251
1252 return STATUS_NOT_IMPLEMENTED;
1253 }
1254
1255 /***********************************************************************
1256 * RtlSetThreadErrorMode [NTDLL.@]
1257 *
1258 * Set the thread local error mode.
1259 *
1260 * PARAMS
1261 * mode [I] The new error mode
1262 * oldmode [O] Destination of the old error mode (may be NULL)
1263 *
1264 * RETURNS
1265 * Success: STATUS_SUCCESS
1266 * Failure: STATUS_INVALID_PARAMETER_1
1267 */
1268 NTSTATUS WINAPI RtlSetThreadErrorMode( DWORD mode, LPDWORD oldmode )
1269 {
1270 if (mode & ~0x70)
1271 return STATUS_INVALID_PARAMETER_1;
1272
1273 if (oldmode)
1274 *oldmode = NtCurrentTeb()->HardErrorDisabled;
1275
1276 NtCurrentTeb()->HardErrorDisabled = mode;
1277 return STATUS_SUCCESS;
1278 }
1279
1280 /***********************************************************************
1281 * RtlGetThreadErrorMode [NTDLL.@]
1282 *
1283 * Get the thread local error mode.
1284 *
1285 * PARAMS
1286 * None.
1287 *
1288 * RETURNS
1289 * The current thread local error mode.
1290 */
1291 DWORD WINAPI RtlGetThreadErrorMode( void )
1292 {
1293 return NtCurrentTeb()->HardErrorDisabled;
1294 }
1295
1296 /******************************************************************************
1297 * RtlGetCurrentTransaction [NTDLL.@]
1298 */
1299 HANDLE WINAPI RtlGetCurrentTransaction(void)
1300 {
1301 FIXME("() :stub\n");
1302 return NULL;
1303 }
1304
1305 /******************************************************************************
1306 * RtlSetCurrentTransaction [NTDLL.@]
1307 */
1308 BOOL WINAPI RtlSetCurrentTransaction(HANDLE new_transaction)
1309 {
1310 FIXME("(%p) :stub\n", new_transaction);
1311 return FALSE;
1312 }
1313
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.