dmime/tests: Check more notification / dirty messages fields.
[wine.git] / dlls / ntdll / rtl.c
blob0d0b2d370f3301bcb4310a165438612fface61ea
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 <stdarg.h>
28 #include "ntstatus.h"
29 #define WIN32_NO_STATUS
30 #include "winsock2.h"
31 #include "windef.h"
32 #include "winternl.h"
33 #include "wine/debug.h"
34 #include "wine/exception.h"
35 #include "ntdll_misc.h"
36 #include "in6addr.h"
37 #include "ddk/ntddk.h"
38 #include "ddk/ntifs.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
41 WINE_DECLARE_DEBUG_CHANNEL(debugstr);
43 #define htons(x) RtlUshortByteSwap(x)
44 #define ntohs(x) RtlUshortByteSwap(x)
46 /* CRC polynomial 0xedb88320 */
47 static const DWORD CRC_table[256] =
49 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
50 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
51 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
52 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
53 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
54 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
55 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
56 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
57 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
58 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
59 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
60 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
61 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
62 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
63 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
64 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
65 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
66 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
67 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
68 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
69 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
70 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
71 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
72 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
73 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
74 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
75 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
76 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
77 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
78 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
79 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
80 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
81 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
82 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
83 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
84 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
85 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
86 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
87 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
88 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
89 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
90 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
91 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
94 static const int hex_table[] = {
95 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00-0x0F */
96 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10-0x1F */
97 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x20-0x2F */
98 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /* 0x30-0x3F */
99 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x40-0x4F */
100 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x50-0x5F */
101 -1, 10, 11, 12, 13, 14, 15 /* 0x60-0x66 */
105 * resource functions
108 /***********************************************************************
109 * RtlInitializeResource (NTDLL.@)
111 * xxxResource() functions implement multiple-reader-single-writer lock.
112 * The code is based on information published in WDJ January 1999 issue.
114 void WINAPI RtlInitializeResource(LPRTL_RWLOCK rwl)
116 if( rwl )
118 rwl->iNumberActive = 0;
119 rwl->uExclusiveWaiters = 0;
120 rwl->uSharedWaiters = 0;
121 rwl->hOwningThreadId = 0;
122 rwl->dwTimeoutBoost = 0; /* no info on this one, default value is 0 */
123 RtlInitializeCriticalSection( &rwl->rtlCS );
124 rwl->rtlCS.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RTL_RWLOCK.rtlCS");
125 NtCreateSemaphore( &rwl->hExclusiveReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
126 NtCreateSemaphore( &rwl->hSharedReleaseSemaphore, SEMAPHORE_ALL_ACCESS, NULL, 0, 65535 );
131 /***********************************************************************
132 * RtlDeleteResource (NTDLL.@)
134 void WINAPI RtlDeleteResource(LPRTL_RWLOCK rwl)
136 if( rwl )
138 RtlEnterCriticalSection( &rwl->rtlCS );
139 if( rwl->iNumberActive || rwl->uExclusiveWaiters || rwl->uSharedWaiters )
140 ERR("Deleting active MRSW lock (%p), expect failure\n", rwl );
141 rwl->hOwningThreadId = 0;
142 rwl->uExclusiveWaiters = rwl->uSharedWaiters = 0;
143 rwl->iNumberActive = 0;
144 NtClose( rwl->hExclusiveReleaseSemaphore );
145 NtClose( rwl->hSharedReleaseSemaphore );
146 RtlLeaveCriticalSection( &rwl->rtlCS );
147 rwl->rtlCS.DebugInfo->Spare[0] = 0;
148 RtlDeleteCriticalSection( &rwl->rtlCS );
153 /***********************************************************************
154 * RtlAcquireResourceExclusive (NTDLL.@)
156 BYTE WINAPI RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl, BYTE fWait)
158 BYTE retVal = 0;
159 if( !rwl ) return 0;
161 start:
162 RtlEnterCriticalSection( &rwl->rtlCS );
163 if( rwl->iNumberActive == 0 ) /* lock is free */
165 rwl->iNumberActive = -1;
166 retVal = 1;
168 else if( rwl->iNumberActive < 0 ) /* exclusive lock in progress */
170 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
172 retVal = 1;
173 rwl->iNumberActive--;
174 goto done;
176 wait:
177 if( fWait )
179 NTSTATUS status;
181 rwl->uExclusiveWaiters++;
183 RtlLeaveCriticalSection( &rwl->rtlCS );
184 status = NtWaitForSingleObject( rwl->hExclusiveReleaseSemaphore, FALSE, NULL );
185 if( HIWORD(status) )
186 goto done;
187 goto start; /* restart the acquisition to avoid deadlocks */
190 else /* one or more shared locks are in progress */
191 if( fWait )
192 goto wait;
194 if( retVal == 1 )
195 rwl->hOwningThreadId = ULongToHandle(GetCurrentThreadId());
196 done:
197 RtlLeaveCriticalSection( &rwl->rtlCS );
198 return retVal;
201 /***********************************************************************
202 * RtlAcquireResourceShared (NTDLL.@)
204 BYTE WINAPI RtlAcquireResourceShared(LPRTL_RWLOCK rwl, BYTE fWait)
206 NTSTATUS status = STATUS_UNSUCCESSFUL;
207 BYTE retVal = 0;
208 if( !rwl ) return 0;
210 start:
211 RtlEnterCriticalSection( &rwl->rtlCS );
212 if( rwl->iNumberActive < 0 )
214 if( rwl->hOwningThreadId == ULongToHandle(GetCurrentThreadId()) )
216 rwl->iNumberActive--;
217 retVal = 1;
218 goto done;
221 if( fWait )
223 rwl->uSharedWaiters++;
224 RtlLeaveCriticalSection( &rwl->rtlCS );
225 status = NtWaitForSingleObject( rwl->hSharedReleaseSemaphore, FALSE, NULL );
226 if( HIWORD(status) )
227 goto done;
228 goto start;
231 else
233 if( status != STATUS_WAIT_0 ) /* otherwise RtlReleaseResource() has already done it */
234 rwl->iNumberActive++;
235 retVal = 1;
237 done:
238 RtlLeaveCriticalSection( &rwl->rtlCS );
239 return retVal;
243 /***********************************************************************
244 * RtlReleaseResource (NTDLL.@)
246 void WINAPI RtlReleaseResource(LPRTL_RWLOCK rwl)
248 RtlEnterCriticalSection( &rwl->rtlCS );
250 if( rwl->iNumberActive > 0 ) /* have one or more readers */
252 if( --rwl->iNumberActive == 0 )
254 if( rwl->uExclusiveWaiters )
256 wake_exclusive:
257 rwl->uExclusiveWaiters--;
258 NtReleaseSemaphore( rwl->hExclusiveReleaseSemaphore, 1, NULL );
262 else
263 if( rwl->iNumberActive < 0 ) /* have a writer, possibly recursive */
265 if( ++rwl->iNumberActive == 0 )
267 rwl->hOwningThreadId = 0;
268 if( rwl->uExclusiveWaiters )
269 goto wake_exclusive;
270 else
271 if( rwl->uSharedWaiters )
273 UINT n = rwl->uSharedWaiters;
274 rwl->iNumberActive = rwl->uSharedWaiters; /* prevent new writers from joining until
275 * all queued readers have done their thing */
276 rwl->uSharedWaiters = 0;
277 NtReleaseSemaphore( rwl->hSharedReleaseSemaphore, n, NULL );
281 RtlLeaveCriticalSection( &rwl->rtlCS );
285 /***********************************************************************
286 * RtlDumpResource (NTDLL.@)
288 void WINAPI RtlDumpResource(LPRTL_RWLOCK rwl)
290 if( rwl )
292 MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
293 rwl, rwl->iNumberActive, rwl->uSharedWaiters, rwl->uExclusiveWaiters );
294 if( rwl->iNumberActive )
295 MESSAGE("\towner thread = %p\n", rwl->hOwningThreadId );
300 * misc functions
303 static LONG WINAPI debug_exception_handler( EXCEPTION_POINTERS *eptr )
305 EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
306 return (rec->ExceptionCode == DBG_PRINTEXCEPTION_C) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
309 /******************************************************************************
310 * DbgPrint [NTDLL.@]
312 NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...)
314 NTSTATUS ret;
315 va_list args;
317 va_start(args, fmt);
318 ret = vDbgPrintEx(0, DPFLTR_ERROR_LEVEL, fmt, args);
319 va_end(args);
320 return ret;
324 /******************************************************************************
325 * DbgPrintEx [NTDLL.@]
327 NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...)
329 NTSTATUS ret;
330 va_list args;
332 va_start(args, fmt);
333 ret = vDbgPrintEx(iComponentId, Level, fmt, args);
334 va_end(args);
335 return ret;
338 /******************************************************************************
339 * vDbgPrintEx [NTDLL.@]
341 NTSTATUS WINAPI vDbgPrintEx( ULONG id, ULONG level, LPCSTR fmt, 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, va_list args )
351 ULONG level_mask = level <= 31 ? (1 << level) : level;
352 SIZE_T len = strlen( prefix );
353 char buf[1024], *end;
355 strcpy( buf, prefix );
356 len += _vsnprintf( buf + len, sizeof(buf) - len, fmt, args );
357 end = buf + len - 1;
359 WARN_(debugstr)(*end == '\n' ? "%08lx:%08lx: %s" : "%08lx:%08lx: %s\n", id, level_mask, buf);
361 if (level_mask & (1 << DPFLTR_ERROR_LEVEL) && NtCurrentTeb()->Peb->BeingDebugged)
363 __TRY
365 EXCEPTION_RECORD record;
366 record.ExceptionCode = DBG_PRINTEXCEPTION_C;
367 record.ExceptionFlags = 0;
368 record.ExceptionRecord = NULL;
369 record.ExceptionAddress = RtlRaiseException;
370 record.NumberParameters = 2;
371 record.ExceptionInformation[1] = (ULONG_PTR)buf;
372 record.ExceptionInformation[0] = strlen( buf ) + 1;
373 RtlRaiseException( &record );
375 __EXCEPT(debug_exception_handler)
378 __ENDTRY
381 return STATUS_SUCCESS;
384 /******************************************************************************
385 * RtlAcquirePebLock [NTDLL.@]
387 VOID WINAPI RtlAcquirePebLock(void)
389 RtlEnterCriticalSection( NtCurrentTeb()->Peb->FastPebLock );
392 /******************************************************************************
393 * RtlReleasePebLock [NTDLL.@]
395 VOID WINAPI RtlReleasePebLock(void)
397 RtlLeaveCriticalSection( NtCurrentTeb()->Peb->FastPebLock );
400 /******************************************************************************
401 * RtlInitializeGenericTable [NTDLL.@]
403 void WINAPI RtlInitializeGenericTable(RTL_GENERIC_TABLE *table, PRTL_GENERIC_COMPARE_ROUTINE compare,
404 PRTL_GENERIC_ALLOCATE_ROUTINE allocate, PRTL_GENERIC_FREE_ROUTINE free,
405 void *context)
407 TRACE("(%p, %p, %p, %p, %p)\n", table, compare, allocate, free, context);
409 table->TableRoot = NULL;
410 table->InsertOrderList.Flink = &table->InsertOrderList;
411 table->InsertOrderList.Blink = &table->InsertOrderList;
412 table->OrderedPointer = &table->InsertOrderList;
413 table->NumberGenericTableElements = 0;
414 table->WhichOrderedElement = 0;
415 table->CompareRoutine = compare;
416 table->AllocateRoutine = allocate;
417 table->FreeRoutine = free;
418 table->TableContext = context;
421 /******************************************************************************
422 * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
424 void * WINAPI RtlEnumerateGenericTableWithoutSplaying(RTL_GENERIC_TABLE *table, void *previous)
426 static int warn_once;
428 if (!warn_once++)
429 FIXME("(%p, %p) stub!\n", table, previous);
430 return NULL;
433 /******************************************************************************
434 * RtlNumberGenericTableElements [NTDLL.@]
436 ULONG WINAPI RtlNumberGenericTableElements(RTL_GENERIC_TABLE *table)
438 TRACE("(%p)\n", table);
439 return table->NumberGenericTableElements;
442 /******************************************************************************
443 * RtlGetElementGenericTable [NTDLL.@]
445 void * WINAPI RtlGetElementGenericTable(RTL_GENERIC_TABLE *table, ULONG index)
447 FIXME("(%p, %lu) stub!\n", table, index);
448 return NULL;
451 /******************************************************************************
452 * RtlLookupElementGenericTable [NTDLL.@]
454 void * WINAPI RtlLookupElementGenericTable(RTL_GENERIC_TABLE *table, void *buffer)
456 FIXME("(%p, %p) stub!\n", table, buffer);
457 return NULL;
460 /******************************************************************************
461 * RtlMoveMemory [NTDLL.@]
463 * Move a block of memory that may overlap.
465 * PARAMS
466 * Destination [O] End destination for block
467 * Source [O] Where to start copying from
468 * Length [I] Number of bytes to copy
470 * RETURNS
471 * Nothing.
473 #undef RtlMoveMemory
474 VOID WINAPI RtlMoveMemory( void *Destination, const void *Source, SIZE_T Length )
476 memmove(Destination, Source, Length);
479 /******************************************************************************
480 * RtlFillMemory [NTDLL.@]
482 * Set a block of memory with a value.
484 * PARAMS
485 * Destination [O] Block to fill
486 * Length [I] Number of bytes to fill
487 * Fill [I] Value to set
489 * RETURNS
490 * Nothing.
492 #undef RtlFillMemory
493 VOID WINAPI RtlFillMemory( VOID *Destination, SIZE_T Length, BYTE Fill )
495 memset(Destination, Fill, Length);
498 /******************************************************************************
499 * RtlZeroMemory [NTDLL.@]
501 * Set a block of memory with 0's.
503 * PARAMS
504 * Destination [O] Block to fill
505 * Length [I] Number of bytes to fill
507 * RETURNS
508 * Nothing.
510 #undef RtlZeroMemory
511 VOID WINAPI RtlZeroMemory( VOID *Destination, SIZE_T Length )
513 memset(Destination, 0, Length);
516 /******************************************************************************
517 * RtlCompareMemory [NTDLL.@]
519 * Compare one block of memory with another
521 * PARAMS
522 * Source1 [I] Source block
523 * Source2 [I] Block to compare to Source1
524 * Length [I] Number of bytes to compare
526 * RETURNS
527 * The length of the first byte at which Source1 and Source2 differ, or Length
528 * if they are the same.
530 SIZE_T WINAPI RtlCompareMemory( const VOID *Source1, const VOID *Source2, SIZE_T Length)
532 SIZE_T i;
533 for(i=0; (i<Length) && (((const BYTE*)Source1)[i]==((const BYTE*)Source2)[i]); i++);
534 return i;
537 /******************************************************************************
538 * RtlCompareMemoryUlong [NTDLL.@]
540 * Compare a block of memory with a value, a ULONG at a time
542 * PARAMS
543 * Source1 [I] Source block. This must be ULONG aligned
544 * Length [I] Number of bytes to compare. This should be a multiple of 4
545 * dwVal [I] Value to compare to
547 * RETURNS
548 * The byte position of the first byte at which Source1 is not dwVal.
550 SIZE_T WINAPI RtlCompareMemoryUlong(VOID *Source1, SIZE_T Length, ULONG dwVal)
552 SIZE_T i;
553 for(i = 0; i < Length/sizeof(ULONG) && ((ULONG *)Source1)[i] == dwVal; i++);
554 return i * sizeof(ULONG);
557 /******************************************************************************
558 * RtlCopyMemory [NTDLL.@]
560 #undef RtlCopyMemory
561 void WINAPI RtlCopyMemory(void *dest, const void *src, SIZE_T len)
563 memcpy(dest, src, len);
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(void *assertion, void *filename, ULONG linenumber, char *message)
579 FIXME("(%s, %s, %lu, %s): stub\n", debugstr_a((char*)assertion), debugstr_a((char*)filename),
580 linenumber, debugstr_a(message));
583 /*************************************************************************
584 * RtlFillMemoryUlong [NTDLL.@]
586 * Fill memory with a 32 bit (dword) value.
588 * PARAMS
589 * lpDest [I] Bitmap pointer
590 * ulCount [I] Number of dwords to write
591 * ulValue [I] Value to fill with
593 * RETURNS
594 * Nothing.
596 VOID WINAPI RtlFillMemoryUlong(ULONG* lpDest, ULONG ulCount, ULONG ulValue)
598 TRACE("(%p,%lu,%lu)\n", lpDest, ulCount, ulValue);
600 ulCount /= sizeof(ULONG);
601 while(ulCount--)
602 *lpDest++ = ulValue;
605 /*********************************************************************
606 * RtlComputeCrc32 [NTDLL.@]
608 * Calculate the CRC32 checksum of a block of bytes
610 * PARAMS
611 * dwInitial [I] Initial CRC value
612 * pData [I] Data block
613 * iLen [I] Length of the byte block
615 * RETURNS
616 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
618 DWORD WINAPI RtlComputeCrc32(DWORD dwInitial, const BYTE *pData, INT iLen)
620 DWORD crc = ~dwInitial;
622 TRACE("(%lu,%p,%d)\n", dwInitial, pData, iLen);
624 while (iLen > 0)
626 crc = CRC_table[(crc ^ *pData) & 0xff] ^ (crc >> 8);
627 pData++;
628 iLen--;
630 return ~crc;
634 /*************************************************************************
635 * RtlUlonglongByteSwap [NTDLL.@]
637 * Swap the bytes of an unsigned long long value.
639 * PARAMS
640 * i [I] Value to swap bytes of
642 * RETURNS
643 * The value with its bytes swapped.
645 #ifdef __i386__
646 __ASM_FASTCALL_FUNC(RtlUlonglongByteSwap, 8,
647 "movl 4(%esp),%edx\n\t"
648 "bswap %edx\n\t"
649 "movl 8(%esp),%eax\n\t"
650 "bswap %eax\n\t"
651 "ret $8")
652 #endif
654 /*************************************************************************
655 * RtlUlongByteSwap [NTDLL.@]
657 * Swap the bytes of an unsigned int value.
659 * NOTES
660 * ix86 version takes argument in %ecx. Other systems use the inline version.
662 #ifdef __i386__
663 __ASM_FASTCALL_FUNC(RtlUlongByteSwap, 4,
664 "movl %ecx,%eax\n\t"
665 "bswap %eax\n\t"
666 "ret")
667 #endif
669 /*************************************************************************
670 * RtlUshortByteSwap [NTDLL.@]
672 * Swap the bytes of an unsigned short value.
674 * NOTES
675 * i386 version takes argument in %cx. Other systems use the inline version.
677 #ifdef __i386__
678 __ASM_FASTCALL_FUNC(RtlUshortByteSwap, 4,
679 "movb %ch,%al\n\t"
680 "movb %cl,%ah\n\t"
681 "ret")
682 #endif
685 /*************************************************************************
686 * RtlUniform [NTDLL.@]
688 * Generates a uniform random number
690 * PARAMS
691 * seed [O] The seed of the Random function
693 * RETURNS
694 * It returns a random number uniformly distributed over [0..MAXLONG-1].
696 * NOTES
697 * Generates a uniform random number using a linear congruential generator.
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( ULONG *seed )
707 /* See the tests for details. */
708 return (*seed = ((ULONGLONG)*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff);
712 /*************************************************************************
713 * RtlRandom [NTDLL.@]
715 * Generates a random number
717 * PARAMS
718 * seed [O] The seed of the Random function
720 * RETURNS
721 * It returns a random number distributed over [0..MAXLONG-1].
723 ULONG WINAPI RtlRandom (PULONG seed)
725 static ULONG saved_value[128] =
726 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
727 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
728 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
729 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
730 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
731 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
732 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
733 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
734 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
735 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
736 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
737 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
738 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
739 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
740 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
741 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
742 ULONG rand;
743 int pos;
744 ULONG result;
746 rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
747 *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
748 pos = *seed & 0x7f;
749 result = saved_value[pos];
750 saved_value[pos] = rand;
751 return(result);
755 /*************************************************************************
756 * RtlRandomEx [NTDLL.@]
758 ULONG WINAPI RtlRandomEx( ULONG *seed )
760 WARN( "semi-stub: should use a different algorithm\n" );
761 return RtlRandom( seed );
764 /*************************************************************************
765 * RtlAreAllAccessesGranted [NTDLL.@]
767 * Check if all desired accesses are granted
769 * RETURNS
770 * TRUE: All desired accesses are granted
771 * FALSE: Otherwise
773 BOOLEAN WINAPI RtlAreAllAccessesGranted(
774 ACCESS_MASK GrantedAccess,
775 ACCESS_MASK DesiredAccess)
777 return (GrantedAccess & DesiredAccess) == DesiredAccess;
781 /*************************************************************************
782 * RtlAreAnyAccessesGranted [NTDLL.@]
784 * Check if at least one of the desired accesses is granted
786 * PARAMS
787 * GrantedAccess [I] Access mask of granted accesses
788 * DesiredAccess [I] Access mask of desired accesses
790 * RETURNS
791 * TRUE: At least one of the desired accesses is granted
792 * FALSE: Otherwise
794 BOOLEAN WINAPI RtlAreAnyAccessesGranted(
795 ACCESS_MASK GrantedAccess,
796 ACCESS_MASK DesiredAccess)
798 return (GrantedAccess & DesiredAccess) != 0;
802 /*************************************************************************
803 * RtlMapGenericMask [NTDLL.@]
805 * Determine the nongeneric access rights specified by an access mask
807 * RETURNS
808 * Nothing.
810 void WINAPI RtlMapGenericMask(
811 PACCESS_MASK AccessMask,
812 const GENERIC_MAPPING *GenericMapping)
814 if (*AccessMask & GENERIC_READ) {
815 *AccessMask |= GenericMapping->GenericRead;
816 } /* if */
818 if (*AccessMask & GENERIC_WRITE) {
819 *AccessMask |= GenericMapping->GenericWrite;
820 } /* if */
822 if (*AccessMask & GENERIC_EXECUTE) {
823 *AccessMask |= GenericMapping->GenericExecute;
824 } /* if */
826 if (*AccessMask & GENERIC_ALL) {
827 *AccessMask |= GenericMapping->GenericAll;
828 } /* if */
830 *AccessMask &= 0x0FFFFFFF;
834 /*************************************************************************
835 * RtlCopyLuid [NTDLL.@]
837 * Copy a local unique ID.
839 * PARAMS
840 * LuidDest [O] Destination for the copied Luid
841 * LuidSrc [I] Source Luid to copy to LuidDest
843 * RETURNS
844 * Nothing.
846 void WINAPI RtlCopyLuid (PLUID LuidDest, const LUID *LuidSrc)
848 *LuidDest = *LuidSrc;
852 /*************************************************************************
853 * RtlEqualLuid [NTDLL.@]
855 * Compare two local unique IDs.
857 * PARAMS
858 * Luid1 [I] First Luid to compare to Luid2
859 * Luid2 [I] Second Luid to compare to Luid1
861 * RETURNS
862 * TRUE: The two LUIDs are equal.
863 * FALSE: Otherwise
865 BOOLEAN WINAPI RtlEqualLuid (const LUID *Luid1, const LUID *Luid2)
867 return (Luid1->LowPart == Luid2->LowPart && Luid1->HighPart == Luid2->HighPart);
871 /*************************************************************************
872 * RtlCopyLuidAndAttributesArray [NTDLL.@]
874 * Copy an array of local unique IDs and attributes.
876 * PARAMS
877 * Count [I] Number of Luid/attributes in Src
878 * Src [I] Source Luid/attributes to copy
879 * Dest [O] Destination for copied Luid/attributes
881 * RETURNS
882 * Nothing.
884 * NOTES
885 * Dest must be large enough to hold Src.
887 void WINAPI RtlCopyLuidAndAttributesArray(
888 ULONG Count,
889 const LUID_AND_ATTRIBUTES *Src,
890 PLUID_AND_ATTRIBUTES Dest)
892 ULONG i;
894 for (i = 0; i < Count; i++) Dest[i] = Src[i];
897 static BOOL parse_ipv4_component(const WCHAR **str, BOOL strict, ULONG *value)
899 int base = 10, d;
900 WCHAR c;
901 ULONG cur_value, prev_value = 0;
902 BOOL success = FALSE;
904 if (**str == '.')
906 *str += 1;
907 return FALSE;
910 if ((*str)[0] == '0')
912 if ((*str)[1] == 'x' || (*str)[1] == 'X')
914 *str += 2;
915 if (strict) return FALSE;
916 base = 16;
918 else if ((*str)[1] >= '0' && (*str)[1] <= '9')
920 *str += 1;
921 if (strict) return FALSE;
922 base = 8;
926 for (cur_value = 0; **str; *str += 1)
928 c = **str;
929 if (c >= ARRAY_SIZE(hex_table)) break;
930 d = hex_table[c];
931 if (d == -1 || d >= base) break;
932 cur_value = cur_value * base + d;
933 success = TRUE;
934 if (cur_value < prev_value) return FALSE; /* overflow */
935 prev_value = cur_value;
938 if (success) *value = cur_value;
939 return success;
942 static NTSTATUS ipv4_string_to_address(const WCHAR *str, BOOL strict,
943 const WCHAR **terminator, IN_ADDR *address, USHORT *port)
945 ULONG fields[4];
946 int n = 0;
948 for (;;)
950 if (!parse_ipv4_component(&str, strict, &fields[n]))
951 goto error;
952 n++;
953 if (*str != '.')
954 break;
955 if (n == 4)
956 goto error;
957 str++;
960 if (strict && n < 4)
961 goto error;
963 switch (n)
965 case 4:
966 if (fields[0] > 0xFF || fields[1] > 0xFF || fields[2] > 0xFF || fields[3] > 0xFF)
967 goto error;
968 address->S_un.S_un_b.s_b1 = fields[0];
969 address->S_un.S_un_b.s_b2 = fields[1];
970 address->S_un.S_un_b.s_b3 = fields[2];
971 address->S_un.S_un_b.s_b4 = fields[3];
972 break;
973 case 3:
974 if (fields[0] > 0xFF || fields[1] > 0xFF || fields[2] > 0xFFFF)
975 goto error;
976 address->S_un.S_un_b.s_b1 = fields[0];
977 address->S_un.S_un_b.s_b2 = fields[1];
978 address->S_un.S_un_b.s_b3 = (fields[2] & 0xFF00) >> 8;
979 address->S_un.S_un_b.s_b4 = (fields[2] & 0x00FF);
980 break;
981 case 2:
982 if (fields[0] > 0xFF || fields[1] > 0xFFFFFF)
983 goto error;
984 address->S_un.S_un_b.s_b1 = fields[0];
985 address->S_un.S_un_b.s_b2 = (fields[1] & 0xFF0000) >> 16;
986 address->S_un.S_un_b.s_b3 = (fields[1] & 0x00FF00) >> 8;
987 address->S_un.S_un_b.s_b4 = (fields[1] & 0x0000FF);
988 break;
989 case 1:
990 address->S_un.S_un_b.s_b1 = (fields[0] & 0xFF000000) >> 24;
991 address->S_un.S_un_b.s_b2 = (fields[0] & 0x00FF0000) >> 16;
992 address->S_un.S_un_b.s_b3 = (fields[0] & 0x0000FF00) >> 8;
993 address->S_un.S_un_b.s_b4 = (fields[0] & 0x000000FF);
994 break;
995 default:
996 goto error;
999 if (terminator) *terminator = str;
1001 if (*str == ':')
1003 str++;
1004 if (!parse_ipv4_component(&str, FALSE, &fields[0]))
1005 goto error;
1006 if (!fields[0] || fields[0] > 0xFFFF || *str)
1007 goto error;
1008 if (port)
1010 *port = htons(fields[0]);
1011 if (terminator) *terminator = str;
1015 if (!terminator && *str)
1016 return STATUS_INVALID_PARAMETER;
1017 return STATUS_SUCCESS;
1019 error:
1020 if (terminator) *terminator = str;
1021 return STATUS_INVALID_PARAMETER;
1024 /***********************************************************************
1025 * RtlIpv4StringToAddressExW [NTDLL.@]
1027 NTSTATUS WINAPI RtlIpv4StringToAddressExW(const WCHAR *str, BOOLEAN strict, IN_ADDR *address, USHORT *port)
1029 TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, address, port);
1030 if (!str || !address || !port) return STATUS_INVALID_PARAMETER;
1031 return ipv4_string_to_address(str, strict, NULL, address, port);
1034 /***********************************************************************
1035 * RtlIpv4StringToAddressW [NTDLL.@]
1037 NTSTATUS WINAPI RtlIpv4StringToAddressW(const WCHAR *str, BOOLEAN strict, const WCHAR **terminator, IN_ADDR *address)
1039 TRACE("(%s, %u, %p, %p)\n", debugstr_w(str), strict, terminator, address);
1040 return ipv4_string_to_address(str, strict, terminator, address, NULL);
1043 /***********************************************************************
1044 * RtlIpv4StringToAddressExA [NTDLL.@]
1046 NTSTATUS WINAPI RtlIpv4StringToAddressExA(const char *str, BOOLEAN strict, IN_ADDR *address, USHORT *port)
1048 WCHAR wstr[32];
1050 TRACE("(%s, %u, %p, %p)\n", debugstr_a(str), strict, address, port);
1052 if (!str || !address || !port)
1053 return STATUS_INVALID_PARAMETER;
1055 RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
1056 wstr[ARRAY_SIZE(wstr) - 1] = 0;
1057 return ipv4_string_to_address(wstr, strict, NULL, address, port);
1060 /***********************************************************************
1061 * RtlIpv4StringToAddressA [NTDLL.@]
1063 NTSTATUS WINAPI RtlIpv4StringToAddressA(const char *str, BOOLEAN strict, const char **terminator, IN_ADDR *address)
1065 WCHAR wstr[32];
1066 const WCHAR *wterminator;
1067 NTSTATUS ret;
1069 TRACE("(%s, %u, %p, %p)\n", debugstr_a(str), strict, terminator, address);
1071 RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
1072 wstr[ARRAY_SIZE(wstr) - 1] = 0;
1073 ret = ipv4_string_to_address(wstr, strict, &wterminator, address, NULL);
1074 if (terminator) *terminator = str + (wterminator - wstr);
1075 return ret;
1078 static BOOL parse_ipv6_component(const WCHAR **str, int base, ULONG *value)
1080 WCHAR *terminator;
1081 if (**str >= ARRAY_SIZE(hex_table) || hex_table[**str] == -1) return FALSE;
1082 *value = min(wcstoul(*str, &terminator, base), 0x7FFFFFFF);
1083 if (*terminator == '0') terminator++; /* "0x" but nothing valid after */
1084 else if (terminator == *str) return FALSE;
1085 *str = terminator;
1086 return TRUE;
1089 static NTSTATUS ipv6_string_to_address(const WCHAR *str, BOOL ex,
1090 const WCHAR **terminator, IN6_ADDR *address, ULONG *scope, USHORT *port)
1092 BOOL expecting_port = FALSE, has_0x = FALSE, too_big = FALSE;
1093 int n_bytes = 0, n_ipv4_bytes = 0, gap = -1;
1094 ULONG ip_component, scope_component = 0, port_component = 0;
1095 const WCHAR *prev_str;
1097 if (str[0] == '[')
1099 if (!ex) goto error;
1100 expecting_port = TRUE;
1101 str++;
1104 if (str[0] == ':')
1106 if (str[1] != ':') goto error;
1107 str++;
1108 address->u.Word[0] = 0;
1111 for (;;)
1113 if (!n_ipv4_bytes && *str == ':')
1115 /* double colon */
1116 if (gap != -1) goto error;
1117 str++;
1118 prev_str = str;
1119 gap = n_bytes;
1120 if (n_bytes == 14 || !parse_ipv6_component(&str, 16, &ip_component)) break;
1121 str = prev_str;
1123 else
1125 prev_str = str;
1128 if (!n_ipv4_bytes && n_bytes <= (gap != -1 ? 10 : 12))
1130 if (parse_ipv6_component(&str, 10, &ip_component) && *str == '.')
1131 n_ipv4_bytes = 1;
1132 str = prev_str;
1135 if (n_ipv4_bytes)
1137 /* IPv4 component */
1138 if (!parse_ipv6_component(&str, 10, &ip_component)) goto error;
1139 if (str - prev_str > 3 || ip_component > 255)
1141 too_big = TRUE;
1143 else
1145 if (*str != '.' && (n_ipv4_bytes < 4 || (n_bytes < 15 && gap == -1))) goto error;
1146 address->u.Byte[n_bytes] = ip_component;
1147 n_bytes++;
1149 if (n_ipv4_bytes == 4 || *str != '.') break;
1150 n_ipv4_bytes++;
1152 else
1154 /* IPv6 component */
1155 if (!parse_ipv6_component(&str, 16, &ip_component)) goto error;
1156 if (prev_str[0] == '0' && (prev_str[1] == 'x' || prev_str[1] == 'X'))
1158 /* Windows "feature": the last IPv6 component can start with "0x" and be longer than 4 digits */
1159 if (terminator) *terminator = prev_str + 1; /* Windows says that the "x" is the terminator */
1160 if (n_bytes < 14 && gap == -1) return STATUS_INVALID_PARAMETER;
1161 address->u.Word[n_bytes/2] = htons(ip_component);
1162 n_bytes += 2;
1163 has_0x = TRUE;
1164 goto fill_gap;
1166 if (*str != ':' && n_bytes < 14 && gap == -1) goto error;
1167 if (str - prev_str > 4)
1168 too_big = TRUE;
1169 else
1170 address->u.Word[n_bytes/2] = htons(ip_component);
1171 n_bytes += 2;
1172 if (*str != ':' || (gap != -1 && str[1] == ':')) break;
1174 if (n_bytes == (gap != -1 ? 14 : 16)) break;
1175 if (too_big) return STATUS_INVALID_PARAMETER;
1176 str++;
1179 if (terminator) *terminator = str;
1180 if (too_big) return STATUS_INVALID_PARAMETER;
1182 fill_gap:
1183 if (gap == -1)
1185 if (n_bytes < 16) goto error;
1187 else
1189 memmove(address->u.Byte + 16 - (n_bytes - gap), address->u.Byte + gap, n_bytes - gap);
1190 memset(address->u.Byte + gap, 0, 16 - n_bytes);
1193 if (ex)
1195 if (has_0x) goto error;
1197 if (*str == '%')
1199 str++;
1200 if (!parse_ipv4_component(&str, TRUE, &scope_component)) goto error;
1203 if (expecting_port)
1205 if (*str != ']') goto error;
1206 str++;
1207 if (*str == ':')
1209 str++;
1210 if (!parse_ipv4_component(&str, FALSE, &port_component)) goto error;
1211 if (!port_component || port_component > 0xFFFF || *str) goto error;
1212 port_component = htons(port_component);
1217 if (!terminator && *str) return STATUS_INVALID_PARAMETER;
1219 if (scope) *scope = scope_component;
1220 if (port) *port = port_component;
1222 return STATUS_SUCCESS;
1224 error:
1225 if (terminator) *terminator = str;
1226 return STATUS_INVALID_PARAMETER;
1229 /***********************************************************************
1230 * RtlIpv6StringToAddressExW [NTDLL.@]
1232 NTSTATUS NTAPI RtlIpv6StringToAddressExW(const WCHAR *str, IN6_ADDR *address, ULONG *scope, USHORT *port)
1234 TRACE("(%s, %p, %p, %p)\n", debugstr_w(str), address, scope, port);
1235 if (!str || !address || !scope || !port) return STATUS_INVALID_PARAMETER;
1236 return ipv6_string_to_address(str, TRUE, NULL, address, scope, port);
1239 /***********************************************************************
1240 * RtlIpv6StringToAddressW [NTDLL.@]
1242 NTSTATUS WINAPI RtlIpv6StringToAddressW(const WCHAR *str, const WCHAR **terminator, IN6_ADDR *address)
1244 TRACE("(%s, %p, %p)\n", debugstr_w(str), terminator, address);
1245 return ipv6_string_to_address(str, FALSE, terminator, address, NULL, NULL);
1248 /***********************************************************************
1249 * RtlIpv6StringToAddressExA [NTDLL.@]
1251 NTSTATUS WINAPI RtlIpv6StringToAddressExA(const char *str, IN6_ADDR *address, ULONG *scope, USHORT *port)
1253 WCHAR wstr[128];
1255 TRACE("(%s, %p, %p, %p)\n", debugstr_a(str), address, scope, port);
1257 if (!str || !address || !scope || !port)
1258 return STATUS_INVALID_PARAMETER;
1260 RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
1261 wstr[ARRAY_SIZE(wstr) - 1] = 0;
1262 return ipv6_string_to_address(wstr, TRUE, NULL, address, scope, port);
1265 /***********************************************************************
1266 * RtlIpv6StringToAddressA [NTDLL.@]
1268 NTSTATUS WINAPI RtlIpv6StringToAddressA(const char *str, const char **terminator, IN6_ADDR *address)
1270 WCHAR wstr[128];
1271 const WCHAR *wterminator = NULL;
1272 NTSTATUS ret;
1274 TRACE("(%s, %p, %p)\n", debugstr_a(str), terminator, address);
1276 RtlMultiByteToUnicodeN(wstr, sizeof(wstr), NULL, str, strlen(str) + 1);
1277 wstr[ARRAY_SIZE(wstr) - 1] = 0;
1278 ret = ipv6_string_to_address(wstr, FALSE, &wterminator, address, NULL, NULL);
1279 if (terminator && wterminator) *terminator = str + (wterminator - wstr);
1280 return ret;
1283 /***********************************************************************
1284 * RtlIpv4AddressToStringExW [NTDLL.@]
1286 * Convert the given ipv4 address and optional the port to a string
1288 * PARAMS
1289 * pin [I] PTR to the ip address to convert (network byte order)
1290 * port [I] optional port to convert (network byte order)
1291 * buffer [O] destination buffer for the result
1292 * psize [IO] PTR to available/used size of the destination buffer
1294 * RETURNS
1295 * Success: STATUS_SUCCESS
1296 * Failure: STATUS_INVALID_PARAMETER
1299 NTSTATUS WINAPI RtlIpv4AddressToStringExW(const IN_ADDR *pin, USHORT port, LPWSTR buffer, PULONG psize)
1301 WCHAR tmp_ip[32];
1302 ULONG needed;
1304 if (!pin || !buffer || !psize)
1305 return STATUS_INVALID_PARAMETER;
1307 TRACE("(%p:0x%lx, %d, %p, %p:%ld)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
1309 needed = swprintf(tmp_ip, ARRAY_SIZE(tmp_ip), L"%u.%u.%u.%u",
1310 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
1311 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
1313 if (port) needed += swprintf(tmp_ip + needed, ARRAY_SIZE(tmp_ip) - needed, L":%u", ntohs(port));
1315 if (*psize > needed) {
1316 *psize = needed + 1;
1317 wcscpy(buffer, tmp_ip);
1318 return STATUS_SUCCESS;
1321 *psize = needed + 1;
1322 return STATUS_INVALID_PARAMETER;
1325 /***********************************************************************
1326 * RtlIpv4AddressToStringExA [NTDLL.@]
1328 * Convert the given ipv4 address and optional the port to a string
1330 * See RtlIpv4AddressToStringExW
1332 NTSTATUS WINAPI RtlIpv4AddressToStringExA(const IN_ADDR *pin, USHORT port, LPSTR buffer, PULONG psize)
1334 CHAR tmp_ip[32];
1335 ULONG needed;
1337 if (!pin || !buffer || !psize)
1338 return STATUS_INVALID_PARAMETER;
1340 TRACE("(%p:0x%lx, %d, %p, %p:%ld)\n", pin, pin->S_un.S_addr, port, buffer, psize, *psize);
1342 needed = sprintf(tmp_ip, "%u.%u.%u.%u",
1343 pin->S_un.S_un_b.s_b1, pin->S_un.S_un_b.s_b2,
1344 pin->S_un.S_un_b.s_b3, pin->S_un.S_un_b.s_b4);
1346 if (port) needed += sprintf(tmp_ip + needed, ":%u", ntohs(port));
1348 if (*psize > needed) {
1349 *psize = needed + 1;
1350 strcpy(buffer, tmp_ip);
1351 return STATUS_SUCCESS;
1354 *psize = needed + 1;
1355 return STATUS_INVALID_PARAMETER;
1358 /***********************************************************************
1359 * RtlIpv4AddressToStringW [NTDLL.@]
1361 * Convert the given ipv4 address to a string
1363 * PARAMS
1364 * pin [I] PTR to the ip address to convert (network byte order)
1365 * buffer [O] destination buffer for the result (at least 16 character)
1367 * RETURNS
1368 * PTR to the 0 character at the end of the converted string
1371 WCHAR * WINAPI RtlIpv4AddressToStringW(const IN_ADDR *pin, LPWSTR buffer)
1373 ULONG size = 16;
1375 if (RtlIpv4AddressToStringExW(pin, 0, buffer, &size)) size = 0;
1376 return buffer + size - 1;
1379 /***********************************************************************
1380 * RtlIpv4AddressToStringA [NTDLL.@]
1382 * Convert the given ipv4 address to a string
1384 * See RtlIpv4AddressToStringW
1386 CHAR * WINAPI RtlIpv4AddressToStringA(const IN_ADDR *pin, LPSTR buffer)
1388 ULONG size = 16;
1390 if (RtlIpv4AddressToStringExA(pin, 0, buffer, &size)) size = 0;
1391 return buffer + size - 1;
1394 static BOOL is_ipv4_in_ipv6(const IN6_ADDR *address)
1396 if (address->s6_words[5] == htons(0x5efe) && (address->s6_words[4] & ~htons(0x200)) == 0)
1397 return TRUE;
1398 if (*(UINT64 *)address != 0)
1399 return FALSE;
1400 if (address->s6_words[4] != 0 && address->s6_words[4] != 0xffff)
1401 return FALSE;
1402 if (address->s6_words[4] == 0 && address->s6_words[5] != 0 && address->s6_words[5] != 0xffff)
1403 return FALSE;
1404 if (address->s6_words[4] == 0xffff && address->s6_words[5] != 0)
1405 return FALSE;
1406 if (address->s6_words[6] == 0)
1407 return FALSE;
1408 return TRUE;
1411 /***********************************************************************
1412 * RtlIpv6AddressToStringExA [NTDLL.@]
1414 NTSTATUS WINAPI RtlIpv6AddressToStringExA(const IN6_ADDR *address, ULONG scope, USHORT port, char *str, ULONG *size)
1416 char buffer[64], *p = buffer;
1417 int i, len, gap = -1, gap_len = 1, ipv6_end = 8;
1418 ULONG needed;
1419 NTSTATUS ret;
1421 TRACE("(%p %lu %u %p %p)\n", address, scope, port, str, size);
1423 if (!address || !str || !size)
1424 return STATUS_INVALID_PARAMETER;
1426 if (is_ipv4_in_ipv6(address))
1427 ipv6_end = 6;
1429 for (i = 0; i < ipv6_end; i++)
1431 len = 0;
1432 while (!address->s6_words[i] && i < ipv6_end)
1434 i++;
1435 len++;
1437 if (len > gap_len)
1439 gap = i - len;
1440 gap_len = len;
1444 if (port) p += sprintf(p, "[");
1446 i = 0;
1447 while (i < ipv6_end)
1449 if (i == gap)
1451 p += sprintf(p, ":");
1452 i += gap_len;
1453 if (i == ipv6_end) p += sprintf(p, ":");
1454 continue;
1456 if (i > 0) p += sprintf(p, ":");
1457 p += sprintf(p, "%x", ntohs(address->s6_words[i]));
1458 i++;
1461 if (ipv6_end == 6)
1463 if (p[-1] != ':') p += sprintf(p, ":");
1464 p = RtlIpv4AddressToStringA((IN_ADDR *)(address->s6_words + 6), p);
1467 if (scope) p += sprintf(p, "%%%lu", scope);
1469 if (port) p += sprintf(p, "]:%u", ntohs(port));
1471 needed = p - buffer + 1;
1473 if (*size >= needed)
1475 strcpy(str, buffer);
1476 ret = STATUS_SUCCESS;
1478 else
1480 ret = STATUS_INVALID_PARAMETER;
1483 *size = needed;
1484 return ret;
1487 /***********************************************************************
1488 * RtlIpv6AddressToStringA [NTDLL.@]
1490 char * WINAPI RtlIpv6AddressToStringA(const IN6_ADDR *address, char *str)
1492 ULONG size = 46;
1493 if (!address || !str) return str - 1;
1494 str[45] = 0; /* this byte is set even though the string is always shorter */
1495 RtlIpv6AddressToStringExA(address, 0, 0, str, &size);
1496 return str + size - 1;
1499 /***********************************************************************
1500 * RtlIpv6AddressToStringExW [NTDLL.@]
1502 NTSTATUS WINAPI RtlIpv6AddressToStringExW(const IN6_ADDR *address, ULONG scope, USHORT port, WCHAR *str, ULONG *size)
1504 char cstr[64];
1505 NTSTATUS ret = RtlIpv6AddressToStringExA(address, scope, port, cstr, size);
1506 if (ret == STATUS_SUCCESS) RtlMultiByteToUnicodeN(str, *size * sizeof(WCHAR), NULL, cstr, *size);
1507 return ret;
1510 /***********************************************************************
1511 * RtlIpv6AddressToStringW [NTDLL.@]
1513 WCHAR * WINAPI RtlIpv6AddressToStringW(const IN6_ADDR *address, WCHAR *str)
1515 ULONG size = 46;
1516 if (!address || !str) return str;
1517 str[45] = 0; /* this word is set even though the string is always shorter */
1518 if (RtlIpv6AddressToStringExW(address, 0, 0, str, &size) != STATUS_SUCCESS)
1519 return str;
1520 return str + size - 1;
1523 /***********************************************************************
1524 * get_pointer_obfuscator (internal)
1526 static DWORD_PTR get_pointer_obfuscator( void )
1528 static DWORD_PTR pointer_obfuscator;
1530 if (!pointer_obfuscator)
1532 ULONG seed = NtGetTickCount();
1533 ULONG_PTR rand;
1535 /* generate a random value for the obfuscator */
1536 rand = RtlUniform( &seed );
1538 /* handle 64bit pointers */
1539 rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1541 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1542 rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
1544 InterlockedCompareExchangePointer( (void**) &pointer_obfuscator, (void*) rand, NULL );
1547 return pointer_obfuscator;
1550 /*************************************************************************
1551 * RtlEncodePointer [NTDLL.@]
1553 PVOID WINAPI RtlEncodePointer( PVOID ptr )
1555 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1556 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1559 PVOID WINAPI RtlDecodePointer( PVOID ptr )
1561 DWORD_PTR ptrval = (DWORD_PTR) ptr;
1562 return (PVOID)(ptrval ^ get_pointer_obfuscator());
1565 /*************************************************************************
1566 * RtlInitializeSListHead [NTDLL.@]
1568 VOID WINAPI RtlInitializeSListHead(PSLIST_HEADER list)
1570 #ifdef _WIN64
1571 list->Alignment = list->Region = 0;
1572 list->Header16.HeaderType = 1; /* we use the 16-byte header */
1573 #else
1574 list->Alignment = 0;
1575 #endif
1578 /*************************************************************************
1579 * RtlQueryDepthSList [NTDLL.@]
1581 WORD WINAPI RtlQueryDepthSList(PSLIST_HEADER list)
1583 #ifdef _WIN64
1584 return list->Header16.Depth;
1585 #else
1586 return list->Depth;
1587 #endif
1590 /*************************************************************************
1591 * RtlFirstEntrySList [NTDLL.@]
1593 PSLIST_ENTRY WINAPI RtlFirstEntrySList(const SLIST_HEADER* list)
1595 #ifdef _WIN64
1596 return (SLIST_ENTRY *)((ULONG_PTR)list->Header16.NextEntry << 4);
1597 #else
1598 return list->Next.Next;
1599 #endif
1602 /*************************************************************************
1603 * RtlInterlockedFlushSList [NTDLL.@]
1605 PSLIST_ENTRY WINAPI RtlInterlockedFlushSList(PSLIST_HEADER list)
1607 SLIST_HEADER old, new;
1609 #ifdef _WIN64
1610 if (!list->Header16.NextEntry) return NULL;
1611 new.Alignment = new.Region = 0;
1612 new.Header16.HeaderType = 1; /* we use the 16-byte header */
1615 old = *list;
1616 new.Header16.Sequence = old.Header16.Sequence + 1;
1617 } while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
1618 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1619 #else
1620 if (!list->Next.Next) return NULL;
1621 new.Alignment = 0;
1624 old = *list;
1625 new.Sequence = old.Sequence + 1;
1626 } while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
1627 old.Alignment) != old.Alignment);
1628 return old.Next.Next;
1629 #endif
1632 /*************************************************************************
1633 * RtlInterlockedPushEntrySList [NTDLL.@]
1635 PSLIST_ENTRY WINAPI RtlInterlockedPushEntrySList(PSLIST_HEADER list, PSLIST_ENTRY entry)
1637 SLIST_HEADER old, new;
1639 #ifdef _WIN64
1640 new.Header16.NextEntry = (ULONG_PTR)entry >> 4;
1643 old = *list;
1644 entry->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1645 new.Header16.Depth = old.Header16.Depth + 1;
1646 new.Header16.Sequence = old.Header16.Sequence + 1;
1647 } while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
1648 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1649 #else
1650 new.Next.Next = entry;
1653 old = *list;
1654 entry->Next = old.Next.Next;
1655 new.Depth = old.Depth + 1;
1656 new.Sequence = old.Sequence + 1;
1657 } while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
1658 old.Alignment) != old.Alignment);
1659 return old.Next.Next;
1660 #endif
1663 /*************************************************************************
1664 * RtlInterlockedPopEntrySList [NTDLL.@]
1666 PSLIST_ENTRY WINAPI RtlInterlockedPopEntrySList(PSLIST_HEADER list)
1668 SLIST_HEADER old, new;
1669 PSLIST_ENTRY entry;
1671 #ifdef _WIN64
1674 old = *list;
1675 if (!(entry = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4))) return NULL;
1676 /* entry could be deleted by another thread */
1677 __TRY
1679 new.Header16.NextEntry = (ULONG_PTR)entry->Next >> 4;
1680 new.Header16.Depth = old.Header16.Depth - 1;
1681 new.Header16.Sequence = old.Header16.Sequence + 1;
1683 __EXCEPT_PAGE_FAULT
1686 __ENDTRY
1687 } while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
1688 #else
1691 old = *list;
1692 if (!(entry = old.Next.Next)) return NULL;
1693 /* entry could be deleted by another thread */
1694 __TRY
1696 new.Next.Next = entry->Next;
1697 new.Depth = old.Depth - 1;
1698 new.Sequence = old.Sequence + 1;
1700 __EXCEPT_PAGE_FAULT
1703 __ENDTRY
1704 } while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
1705 old.Alignment) != old.Alignment);
1706 #endif
1707 return entry;
1710 /*************************************************************************
1711 * RtlInterlockedPushListSListEx [NTDLL.@]
1713 PSLIST_ENTRY WINAPI RtlInterlockedPushListSListEx(PSLIST_HEADER list, PSLIST_ENTRY first,
1714 PSLIST_ENTRY last, ULONG count)
1716 SLIST_HEADER old, new;
1718 #ifdef _WIN64
1719 new.Header16.NextEntry = (ULONG_PTR)first >> 4;
1722 old = *list;
1723 new.Header16.Depth = old.Header16.Depth + count;
1724 new.Header16.Sequence = old.Header16.Sequence + 1;
1725 last->Next = (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1726 } while (!InterlockedCompareExchange128((__int64 *)list, new.Region, new.Alignment, (__int64 *)&old));
1727 return (SLIST_ENTRY *)((ULONG_PTR)old.Header16.NextEntry << 4);
1728 #else
1729 new.Next.Next = first;
1732 old = *list;
1733 new.Depth = old.Depth + count;
1734 new.Sequence = old.Sequence + 1;
1735 last->Next = old.Next.Next;
1736 } while (InterlockedCompareExchange64((__int64 *)&list->Alignment, new.Alignment,
1737 old.Alignment) != old.Alignment);
1738 return old.Next.Next;
1739 #endif
1742 /*************************************************************************
1743 * RtlInterlockedPushListSList [NTDLL.@]
1745 DEFINE_FASTCALL_WRAPPER(RtlInterlockedPushListSList, 16)
1746 PSLIST_ENTRY FASTCALL RtlInterlockedPushListSList(PSLIST_HEADER list, PSLIST_ENTRY first,
1747 PSLIST_ENTRY last, ULONG count)
1749 return RtlInterlockedPushListSListEx(list, first, last, count);
1752 /******************************************************************************
1753 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1755 NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT format, PULONG compress_workspace,
1756 PULONG decompress_workspace)
1758 FIXME("0x%04x, %p, %p: semi-stub\n", format, compress_workspace, decompress_workspace);
1760 switch (format & COMPRESSION_FORMAT_MASK)
1762 case COMPRESSION_FORMAT_LZNT1:
1763 if (compress_workspace)
1765 /* FIXME: The current implementation of RtlCompressBuffer does not use a
1766 * workspace buffer, but Windows applications might expect a nonzero value. */
1767 *compress_workspace = 16;
1769 if (decompress_workspace)
1770 *decompress_workspace = 0x1000;
1771 return STATUS_SUCCESS;
1773 case COMPRESSION_FORMAT_NONE:
1774 case COMPRESSION_FORMAT_DEFAULT:
1775 return STATUS_INVALID_PARAMETER;
1777 default:
1778 FIXME("format %u not implemented\n", format);
1779 return STATUS_UNSUPPORTED_COMPRESSION;
1783 /* compress data using LZNT1, currently only a stub */
1784 static NTSTATUS lznt1_compress(UCHAR *src, ULONG src_size, UCHAR *dst, ULONG dst_size,
1785 ULONG chunk_size, ULONG *final_size, UCHAR *workspace)
1787 UCHAR *src_cur = src, *src_end = src + src_size;
1788 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1789 ULONG block_size;
1791 while (src_cur < src_end)
1793 /* determine size of current chunk */
1794 block_size = min(0x1000, src_end - src_cur);
1795 if (dst_cur + sizeof(WORD) + block_size > dst_end)
1796 return STATUS_BUFFER_TOO_SMALL;
1798 /* write (uncompressed) chunk header */
1799 *(WORD *)dst_cur = 0x3000 | (block_size - 1);
1800 dst_cur += sizeof(WORD);
1802 /* write chunk content */
1803 memcpy(dst_cur, src_cur, block_size);
1804 dst_cur += block_size;
1805 src_cur += block_size;
1808 if (final_size)
1809 *final_size = dst_cur - dst;
1811 return STATUS_SUCCESS;
1814 /******************************************************************************
1815 * RtlCompressBuffer [NTDLL.@]
1817 NTSTATUS WINAPI RtlCompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
1818 PUCHAR compressed, ULONG compressed_size, ULONG chunk_size,
1819 PULONG final_size, PVOID workspace)
1821 FIXME("0x%04x, %p, %lu, %p, %lu, %lu, %p, %p: semi-stub\n", format, uncompressed,
1822 uncompressed_size, compressed, compressed_size, chunk_size, final_size, workspace);
1824 switch (format & COMPRESSION_FORMAT_MASK)
1826 case COMPRESSION_FORMAT_LZNT1:
1827 return lznt1_compress(uncompressed, uncompressed_size, compressed,
1828 compressed_size, chunk_size, final_size, workspace);
1830 case COMPRESSION_FORMAT_NONE:
1831 case COMPRESSION_FORMAT_DEFAULT:
1832 return STATUS_INVALID_PARAMETER;
1834 default:
1835 FIXME("format %u not implemented\n", format);
1836 return STATUS_UNSUPPORTED_COMPRESSION;
1840 /* decompress a single LZNT1 chunk */
1841 static UCHAR *lznt1_decompress_chunk(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size)
1843 UCHAR *src_cur = src, *src_end = src + src_size;
1844 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1845 ULONG displacement_bits, length_bits;
1846 ULONG code_displacement, code_length;
1847 WORD flags, code;
1849 while (src_cur < src_end && dst_cur < dst_end)
1851 flags = 0x8000 | *src_cur++;
1852 while ((flags & 0xff00) && src_cur < src_end)
1854 if (flags & 1)
1856 /* backwards reference */
1857 if (src_cur + sizeof(WORD) > src_end)
1858 return NULL;
1860 code = *(WORD *)src_cur;
1861 src_cur += sizeof(WORD);
1863 /* find length / displacement bits */
1864 for (displacement_bits = 12; displacement_bits > 4; displacement_bits--)
1865 if ((1 << (displacement_bits - 1)) < dst_cur - dst) break;
1867 length_bits = 16 - displacement_bits;
1868 code_length = (code & ((1 << length_bits) - 1)) + 3;
1869 code_displacement = (code >> length_bits) + 1;
1871 if (dst_cur < dst + code_displacement)
1872 return NULL;
1874 /* copy bytes of chunk - we can't use memcpy() since source and dest can
1875 * be overlapping, and the same bytes can be repeated over and over again */
1876 while (code_length--)
1878 if (dst_cur >= dst_end) return dst_cur;
1879 *dst_cur = *(dst_cur - code_displacement);
1880 dst_cur++;
1883 else
1885 /* uncompressed data */
1886 if (dst_cur >= dst_end) return dst_cur;
1887 *dst_cur++ = *src_cur++;
1889 flags >>= 1;
1893 return dst_cur;
1896 /* decompress data encoded with LZNT1 */
1897 static NTSTATUS lznt1_decompress(UCHAR *dst, ULONG dst_size, UCHAR *src, ULONG src_size,
1898 ULONG offset, ULONG *final_size, UCHAR *workspace)
1900 UCHAR *src_cur = src, *src_end = src + src_size;
1901 UCHAR *dst_cur = dst, *dst_end = dst + dst_size;
1902 ULONG chunk_size, block_size;
1903 WORD chunk_header;
1904 UCHAR *ptr;
1906 if (src_cur + sizeof(WORD) > src_end)
1907 return STATUS_BAD_COMPRESSION_BUFFER;
1909 /* skip over chunks with a distance >= 0x1000 to the destination offset */
1910 while (offset >= 0x1000 && src_cur + sizeof(WORD) <= src_end)
1912 chunk_header = *(WORD *)src_cur;
1913 src_cur += sizeof(WORD);
1914 if (!chunk_header) goto out;
1915 chunk_size = (chunk_header & 0xfff) + 1;
1917 if (src_cur + chunk_size > src_end)
1918 return STATUS_BAD_COMPRESSION_BUFFER;
1920 src_cur += chunk_size;
1921 offset -= 0x1000;
1924 /* handle partially included chunk */
1925 if (offset && src_cur + sizeof(WORD) <= src_end)
1927 chunk_header = *(WORD *)src_cur;
1928 src_cur += sizeof(WORD);
1929 if (!chunk_header) goto out;
1930 chunk_size = (chunk_header & 0xfff) + 1;
1932 if (src_cur + chunk_size > src_end)
1933 return STATUS_BAD_COMPRESSION_BUFFER;
1935 if (dst_cur >= dst_end)
1936 goto out;
1938 if (chunk_header & 0x8000)
1940 /* compressed chunk */
1941 if (!workspace) return STATUS_ACCESS_VIOLATION;
1942 ptr = lznt1_decompress_chunk(workspace, 0x1000, src_cur, chunk_size);
1943 if (!ptr) return STATUS_BAD_COMPRESSION_BUFFER;
1944 if (ptr - workspace > offset)
1946 block_size = min((ptr - workspace) - offset, dst_end - dst_cur);
1947 memcpy(dst_cur, workspace + offset, block_size);
1948 dst_cur += block_size;
1951 else
1953 /* uncompressed chunk */
1954 if (chunk_size > offset)
1956 block_size = min(chunk_size - offset, dst_end - dst_cur);
1957 memcpy(dst_cur, src_cur + offset, block_size);
1958 dst_cur += block_size;
1962 src_cur += chunk_size;
1965 /* handle remaining chunks */
1966 while (src_cur + sizeof(WORD) <= src_end)
1968 chunk_header = *(WORD *)src_cur;
1969 src_cur += sizeof(WORD);
1970 if (!chunk_header) goto out;
1971 chunk_size = (chunk_header & 0xfff) + 1;
1973 if (src_cur + chunk_size > src_end)
1974 return STATUS_BAD_COMPRESSION_BUFFER;
1976 /* fill space with padding when the previous chunk was decompressed
1977 * to less than 4096 bytes. no padding is needed for the last chunk
1978 * or when the next chunk is truncated */
1979 block_size = ((dst_cur - dst) + offset) & 0xfff;
1980 if (block_size)
1982 block_size = 0x1000 - block_size;
1983 if (dst_cur + block_size >= dst_end)
1984 goto out;
1985 memset(dst_cur, 0, block_size);
1986 dst_cur += block_size;
1989 if (dst_cur >= dst_end)
1990 goto out;
1992 if (chunk_header & 0x8000)
1994 /* compressed chunk */
1995 dst_cur = lznt1_decompress_chunk(dst_cur, dst_end - dst_cur, src_cur, chunk_size);
1996 if (!dst_cur) return STATUS_BAD_COMPRESSION_BUFFER;
1998 else
2000 /* uncompressed chunk */
2001 block_size = min(chunk_size, dst_end - dst_cur);
2002 memcpy(dst_cur, src_cur, block_size);
2003 dst_cur += block_size;
2006 src_cur += chunk_size;
2009 out:
2010 if (final_size)
2011 *final_size = dst_cur - dst;
2013 return STATUS_SUCCESS;
2017 /******************************************************************************
2018 * RtlDecompressFragment [NTDLL.@]
2020 NTSTATUS WINAPI RtlDecompressFragment(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
2021 PUCHAR compressed, ULONG compressed_size, ULONG offset,
2022 PULONG final_size, PVOID workspace)
2024 TRACE("0x%04x, %p, %lu, %p, %lu, %lu, %p, %p\n", format, uncompressed,
2025 uncompressed_size, compressed, compressed_size, offset, final_size, workspace);
2027 switch (format & COMPRESSION_FORMAT_MASK)
2029 case COMPRESSION_FORMAT_LZNT1:
2030 return lznt1_decompress(uncompressed, uncompressed_size, compressed,
2031 compressed_size, offset, final_size, workspace);
2033 case COMPRESSION_FORMAT_NONE:
2034 case COMPRESSION_FORMAT_DEFAULT:
2035 return STATUS_INVALID_PARAMETER;
2037 default:
2038 FIXME("format %u not implemented\n", format);
2039 return STATUS_UNSUPPORTED_COMPRESSION;
2044 /******************************************************************************
2045 * RtlDecompressBuffer [NTDLL.@]
2047 NTSTATUS WINAPI RtlDecompressBuffer(USHORT format, PUCHAR uncompressed, ULONG uncompressed_size,
2048 PUCHAR compressed, ULONG compressed_size, PULONG final_size)
2050 TRACE("0x%04x, %p, %lu, %p, %lu, %p\n", format, uncompressed,
2051 uncompressed_size, compressed, compressed_size, final_size);
2053 return RtlDecompressFragment(format, uncompressed, uncompressed_size,
2054 compressed, compressed_size, 0, final_size, NULL);
2057 /***********************************************************************
2058 * RtlSetThreadErrorMode [NTDLL.@]
2060 * Set the thread local error mode.
2062 * PARAMS
2063 * mode [I] The new error mode
2064 * oldmode [O] Destination of the old error mode (may be NULL)
2066 * RETURNS
2067 * Success: STATUS_SUCCESS
2068 * Failure: STATUS_INVALID_PARAMETER_1
2070 NTSTATUS WINAPI RtlSetThreadErrorMode( DWORD mode, LPDWORD oldmode )
2072 if (mode & ~0x70)
2073 return STATUS_INVALID_PARAMETER_1;
2075 if (oldmode)
2076 *oldmode = NtCurrentTeb()->HardErrorMode;
2078 NtCurrentTeb()->HardErrorMode = mode;
2079 return STATUS_SUCCESS;
2082 /***********************************************************************
2083 * RtlGetThreadErrorMode [NTDLL.@]
2085 * Get the thread local error mode.
2087 * PARAMS
2088 * None.
2090 * RETURNS
2091 * The current thread local error mode.
2093 DWORD WINAPI RtlGetThreadErrorMode( void )
2095 return NtCurrentTeb()->HardErrorMode;
2098 /******************************************************************************
2099 * RtlGetCurrentTransaction [NTDLL.@]
2101 HANDLE WINAPI RtlGetCurrentTransaction(void)
2103 FIXME("() :stub\n");
2104 return NULL;
2107 /******************************************************************************
2108 * RtlSetCurrentTransaction [NTDLL.@]
2110 BOOL WINAPI RtlSetCurrentTransaction(HANDLE new_transaction)
2112 FIXME("(%p) :stub\n", new_transaction);
2113 return FALSE;
2116 /**********************************************************************
2117 * RtlGetCurrentProcessorNumberEx [NTDLL.@]
2119 void WINAPI RtlGetCurrentProcessorNumberEx(PROCESSOR_NUMBER *processor)
2121 FIXME("(%p) :semi-stub\n", processor);
2122 processor->Group = 0;
2123 processor->Number = NtGetCurrentProcessorNumber();
2124 processor->Reserved = 0;
2127 /***********************************************************************
2128 * RtlIsProcessorFeaturePresent [NTDLL.@]
2130 BOOLEAN WINAPI RtlIsProcessorFeaturePresent( UINT feature )
2132 #ifdef __aarch64__
2133 static const ULONGLONG arm64_features =
2134 (1ull << PF_COMPARE_EXCHANGE_DOUBLE) |
2135 (1ull << PF_NX_ENABLED) |
2136 (1ull << PF_ARM_VFP_32_REGISTERS_AVAILABLE) |
2137 (1ull << PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) |
2138 (1ull << PF_SECOND_LEVEL_ADDRESS_TRANSLATION) |
2139 (1ull << PF_FASTFAIL_AVAILABLE) |
2140 (1ull << PF_ARM_DIVIDE_INSTRUCTION_AVAILABLE) |
2141 (1ull << PF_ARM_64BIT_LOADSTORE_ATOMIC) |
2142 (1ull << PF_ARM_EXTERNAL_CACHE_AVAILABLE) |
2143 (1ull << PF_ARM_FMAC_INSTRUCTIONS_AVAILABLE) |
2144 (1ull << PF_ARM_V8_INSTRUCTIONS_AVAILABLE) |
2145 (1ull << PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) |
2146 (1ull << PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) |
2147 (1ull << PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE) |
2148 (1ull << PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) |
2149 (1ull << PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE) |
2150 (1ull << PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE);
2152 return (feature < PROCESSOR_FEATURE_MAX && (arm64_features & (1ull << feature)) &&
2153 user_shared_data->ProcessorFeatures[feature]);
2154 #elif defined _WIN64
2155 return feature < PROCESSOR_FEATURE_MAX && user_shared_data->ProcessorFeatures[feature];
2156 #else
2157 return NtWow64IsProcessorFeaturePresent( feature );
2158 #endif
2161 /***********************************************************************
2162 * RtlInitializeGenericTableAvl (NTDLL.@)
2164 void WINAPI RtlInitializeGenericTableAvl(PRTL_AVL_TABLE table, PRTL_AVL_COMPARE_ROUTINE compare,
2165 PRTL_AVL_ALLOCATE_ROUTINE allocate, PRTL_AVL_FREE_ROUTINE free, void *context)
2167 FIXME("%p %p %p %p %p: stub\n", table, compare, allocate, free, context);
2170 /***********************************************************************
2171 * RtlInsertElementGenericTableAvl (NTDLL.@)
2173 void WINAPI RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE table, void *buffer, ULONG size, BOOL *element)
2175 FIXME("%p %p %lu %p: stub\n", table, buffer, size, element);
2178 /*********************************************************************
2179 * RtlQueryPackageIdentity [NTDLL.@]
2181 NTSTATUS WINAPI RtlQueryPackageIdentity(HANDLE token, WCHAR *fullname, SIZE_T *fullname_size,
2182 WCHAR *appid, SIZE_T *appid_size, BOOLEAN *packaged)
2184 FIXME("(%p, %p, %p, %p, %p, %p): stub\n", token, fullname, fullname_size, appid, appid_size, packaged);
2185 return STATUS_NOT_FOUND;
2188 /*********************************************************************
2189 * RtlQueryProcessPlaceholderCompatibilityMode [NTDLL.@]
2191 char WINAPI RtlQueryProcessPlaceholderCompatibilityMode(void)
2193 FIXME("stub\n");
2194 return PHCM_APPLICATION_DEFAULT;