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
27 #include "wine/port.h"
33 #ifdef HAVE_NETINET_IN_H
34 #include <netinet/in.h>
37 #define NONAMELESSUNION
38 #define NONAMELESSSTRUCT
39 #define WIN32_NO_STATUS
43 #include "wine/debug.h"
44 #include "wine/exception.h"
45 #include "wine/unicode.h"
46 #include "ntdll_misc.h"
49 #include "ddk/ntddk.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
54 #define DEFINE_FASTCALL4_ENTRYPOINT( name ) \
55 __ASM_STDCALL_FUNC( name, 16, \
60 "jmp " __ASM_NAME("__regs_") #name __ASM_STDCALL(16))
63 /* CRC polynomial 0xedb88320 */
64 static const DWORD CRC_table
[256] =
66 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
67 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
68 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
69 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
70 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
71 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
72 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
73 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
74 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
75 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
76 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
77 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
78 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
79 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
80 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
81 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
82 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
83 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
84 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
85 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
86 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
87 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
88 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
89 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
90 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
91 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
92 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
93 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
94 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
95 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
96 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
97 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
98 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
99 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
100 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
101 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
102 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
103 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
104 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
105 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
106 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
107 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
108 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
115 /***********************************************************************
116 * RtlInitializeResource (NTDLL.@)
118 * xxxResource() functions implement multiple-reader-single-writer lock.
119 * The code is based on information published in WDJ January 1999 issue.
121 void WINAPI
RtlInitializeResource(LPRTL_RWLOCK rwl
)
125 rwl
->iNumberActive
= 0;
126 rwl
->uExclusiveWaiters
= 0;
127 rwl
->uSharedWaiters
= 0;
128 rwl
->hOwningThreadId
= 0;
129 rwl
->dwTimeoutBoost
= 0; /* no info on this one, default value is 0 */
130 RtlInitializeCriticalSection( &rwl
->rtlCS
);
131 rwl
->rtlCS
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": RTL_RWLOCK.rtlCS");
132 NtCreateSemaphore( &rwl
->hExclusiveReleaseSemaphore
, SEMAPHORE_ALL_ACCESS
, NULL
, 0, 65535 );
133 NtCreateSemaphore( &rwl
->hSharedReleaseSemaphore
, SEMAPHORE_ALL_ACCESS
, NULL
, 0, 65535 );
138 /***********************************************************************
139 * RtlDeleteResource (NTDLL.@)
141 void WINAPI
RtlDeleteResource(LPRTL_RWLOCK rwl
)
145 RtlEnterCriticalSection( &rwl
->rtlCS
);
146 if( rwl
->iNumberActive
|| rwl
->uExclusiveWaiters
|| rwl
->uSharedWaiters
)
147 ERR("Deleting active MRSW lock (%p), expect failure\n", rwl
);
148 rwl
->hOwningThreadId
= 0;
149 rwl
->uExclusiveWaiters
= rwl
->uSharedWaiters
= 0;
150 rwl
->iNumberActive
= 0;
151 NtClose( rwl
->hExclusiveReleaseSemaphore
);
152 NtClose( rwl
->hSharedReleaseSemaphore
);
153 RtlLeaveCriticalSection( &rwl
->rtlCS
);
154 rwl
->rtlCS
.DebugInfo
->Spare
[0] = 0;
155 RtlDeleteCriticalSection( &rwl
->rtlCS
);
160 /***********************************************************************
161 * RtlAcquireResourceExclusive (NTDLL.@)
163 BYTE WINAPI
RtlAcquireResourceExclusive(LPRTL_RWLOCK rwl
, BYTE fWait
)
169 RtlEnterCriticalSection( &rwl
->rtlCS
);
170 if( rwl
->iNumberActive
== 0 ) /* lock is free */
172 rwl
->iNumberActive
= -1;
175 else if( rwl
->iNumberActive
< 0 ) /* exclusive lock in progress */
177 if( rwl
->hOwningThreadId
== ULongToHandle(GetCurrentThreadId()) )
180 rwl
->iNumberActive
--;
188 rwl
->uExclusiveWaiters
++;
190 RtlLeaveCriticalSection( &rwl
->rtlCS
);
191 status
= NtWaitForSingleObject( rwl
->hExclusiveReleaseSemaphore
, FALSE
, NULL
);
194 goto start
; /* restart the acquisition to avoid deadlocks */
197 else /* one or more shared locks are in progress */
202 rwl
->hOwningThreadId
= ULongToHandle(GetCurrentThreadId());
204 RtlLeaveCriticalSection( &rwl
->rtlCS
);
208 /***********************************************************************
209 * RtlAcquireResourceShared (NTDLL.@)
211 BYTE WINAPI
RtlAcquireResourceShared(LPRTL_RWLOCK rwl
, BYTE fWait
)
213 NTSTATUS status
= STATUS_UNSUCCESSFUL
;
218 RtlEnterCriticalSection( &rwl
->rtlCS
);
219 if( rwl
->iNumberActive
< 0 )
221 if( rwl
->hOwningThreadId
== ULongToHandle(GetCurrentThreadId()) )
223 rwl
->iNumberActive
--;
230 rwl
->uSharedWaiters
++;
231 RtlLeaveCriticalSection( &rwl
->rtlCS
);
232 status
= NtWaitForSingleObject( rwl
->hSharedReleaseSemaphore
, FALSE
, NULL
);
240 if( status
!= STATUS_WAIT_0
) /* otherwise RtlReleaseResource() has already done it */
241 rwl
->iNumberActive
++;
245 RtlLeaveCriticalSection( &rwl
->rtlCS
);
250 /***********************************************************************
251 * RtlReleaseResource (NTDLL.@)
253 void WINAPI
RtlReleaseResource(LPRTL_RWLOCK rwl
)
255 RtlEnterCriticalSection( &rwl
->rtlCS
);
257 if( rwl
->iNumberActive
> 0 ) /* have one or more readers */
259 if( --rwl
->iNumberActive
== 0 )
261 if( rwl
->uExclusiveWaiters
)
264 rwl
->uExclusiveWaiters
--;
265 NtReleaseSemaphore( rwl
->hExclusiveReleaseSemaphore
, 1, NULL
);
270 if( rwl
->iNumberActive
< 0 ) /* have a writer, possibly recursive */
272 if( ++rwl
->iNumberActive
== 0 )
274 rwl
->hOwningThreadId
= 0;
275 if( rwl
->uExclusiveWaiters
)
278 if( rwl
->uSharedWaiters
)
280 UINT n
= rwl
->uSharedWaiters
;
281 rwl
->iNumberActive
= rwl
->uSharedWaiters
; /* prevent new writers from joining until
282 * all queued readers have done their thing */
283 rwl
->uSharedWaiters
= 0;
284 NtReleaseSemaphore( rwl
->hSharedReleaseSemaphore
, n
, NULL
);
288 RtlLeaveCriticalSection( &rwl
->rtlCS
);
292 /***********************************************************************
293 * RtlDumpResource (NTDLL.@)
295 void WINAPI
RtlDumpResource(LPRTL_RWLOCK rwl
)
299 MESSAGE("RtlDumpResource(%p):\n\tactive count = %i\n\twaiting readers = %i\n\twaiting writers = %i\n",
300 rwl
, rwl
->iNumberActive
, rwl
->uSharedWaiters
, rwl
->uExclusiveWaiters
);
301 if( rwl
->iNumberActive
)
302 MESSAGE("\towner thread = %p\n", rwl
->hOwningThreadId
);
310 /******************************************************************************
313 NTSTATUS WINAPIV
DbgPrint(LPCSTR fmt
, ...)
318 __ms_va_start(args
, fmt
);
319 NTDLL__vsnprintf(buf
, sizeof(buf
), fmt
, args
);
322 MESSAGE("DbgPrint says: %s",buf
);
323 /* hmm, raise exception? */
324 return STATUS_SUCCESS
;
328 /******************************************************************************
329 * DbgPrintEx [NTDLL.@]
331 NTSTATUS WINAPIV
DbgPrintEx(ULONG iComponentId
, ULONG Level
, LPCSTR fmt
, ...)
336 __ms_va_start(args
, fmt
);
337 ret
= vDbgPrintEx(iComponentId
, Level
, fmt
, args
);
342 /******************************************************************************
343 * vDbgPrintEx [NTDLL.@]
345 NTSTATUS WINAPI
vDbgPrintEx( ULONG id
, ULONG level
, LPCSTR fmt
, __ms_va_list args
)
347 return vDbgPrintExWithPrefix( "", id
, level
, fmt
, args
);
350 /******************************************************************************
351 * vDbgPrintExWithPrefix [NTDLL.@]
353 NTSTATUS WINAPI
vDbgPrintExWithPrefix( LPCSTR prefix
, ULONG id
, ULONG level
, LPCSTR fmt
, __ms_va_list args
)
357 NTDLL__vsnprintf(buf
, sizeof(buf
), fmt
, args
);
359 switch (level
& DPFLTR_MASK
)
361 case DPFLTR_ERROR_LEVEL
: ERR("%s%x: %s", prefix
, id
, buf
); break;
362 case DPFLTR_WARNING_LEVEL
: WARN("%s%x: %s", prefix
, id
, buf
); break;
363 case DPFLTR_TRACE_LEVEL
:
364 case DPFLTR_INFO_LEVEL
:
365 default: TRACE("%s%x: %s", prefix
, id
, buf
); break;
367 return STATUS_SUCCESS
;
370 /******************************************************************************
371 * RtlAcquirePebLock [NTDLL.@]
373 VOID WINAPI
RtlAcquirePebLock(void)
375 RtlEnterCriticalSection( NtCurrentTeb()->Peb
->FastPebLock
);
378 /******************************************************************************
379 * RtlReleasePebLock [NTDLL.@]
381 VOID WINAPI
RtlReleasePebLock(void)
383 RtlLeaveCriticalSection( NtCurrentTeb()->Peb
->FastPebLock
);
386 /******************************************************************************
387 * RtlNewSecurityObject [NTDLL.@]
390 RtlNewSecurityObject( PSECURITY_DESCRIPTOR ParentDescriptor
,
391 PSECURITY_DESCRIPTOR CreatorDescriptor
,
392 PSECURITY_DESCRIPTOR
*NewDescriptor
,
393 BOOLEAN IsDirectoryObject
,
395 PGENERIC_MAPPING GenericMapping
)
397 FIXME("(%p %p %p %d %p %p) stub!\n", ParentDescriptor
, CreatorDescriptor
,
398 NewDescriptor
, IsDirectoryObject
, Token
, GenericMapping
);
399 return STATUS_NOT_IMPLEMENTED
;
402 /******************************************************************************
403 * RtlDeleteSecurityObject [NTDLL.@]
406 RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR
*ObjectDescriptor
)
408 FIXME("(%p) stub!\n", ObjectDescriptor
);
409 return STATUS_NOT_IMPLEMENTED
;
412 /******************************************************************************
413 * RtlInitializeGenericTable [NTDLL.@]
415 PVOID WINAPI
RtlInitializeGenericTable(PVOID pTable
, PVOID arg2
, PVOID arg3
, PVOID arg4
, PVOID arg5
)
417 FIXME("(%p,%p,%p,%p,%p) stub!\n", pTable
, arg2
, arg3
, arg4
, arg5
);
421 /******************************************************************************
422 * RtlEnumerateGenericTableWithoutSplaying [NTDLL.@]
424 PVOID
RtlEnumerateGenericTableWithoutSplaying(PVOID pTable
, PVOID
*RestartKey
)
426 static int warn_once
;
429 FIXME("(%p,%p) stub!\n", pTable
, RestartKey
);
433 /******************************************************************************
434 * RtlNumberGenericTableElements [NTDLL.@]
436 ULONG
RtlNumberGenericTableElements(PVOID pTable
)
438 FIXME("(%p) stub!\n", pTable
);
442 /******************************************************************************
443 * RtlMoveMemory [NTDLL.@]
445 * Move a block of memory that may overlap.
448 * Destination [O] End destination for block
449 * Source [O] Where to start copying from
450 * Length [I] Number of bytes to copy
456 VOID WINAPI
RtlMoveMemory( void *Destination
, const void *Source
, SIZE_T Length
)
458 memmove(Destination
, Source
, Length
);
461 /******************************************************************************
462 * RtlFillMemory [NTDLL.@]
464 * Set a block of memory with a value.
467 * Destination [O] Block to fill
468 * Length [I] Number of bytes to fill
469 * Fill [I] Value to set
475 VOID WINAPI
RtlFillMemory( VOID
*Destination
, SIZE_T Length
, BYTE Fill
)
477 memset(Destination
, Fill
, Length
);
480 /******************************************************************************
481 * RtlZeroMemory [NTDLL.@]
483 * Set a block of memory with 0's.
486 * Destination [O] Block to fill
487 * Length [I] Number of bytes to fill
493 VOID WINAPI
RtlZeroMemory( VOID
*Destination
, SIZE_T Length
)
495 memset(Destination
, 0, Length
);
498 /******************************************************************************
499 * RtlCompareMemory [NTDLL.@]
501 * Compare one block of memory with another
504 * Source1 [I] Source block
505 * Source2 [I] Block to compare to Source1
506 * Length [I] Number of bytes to compare
509 * The length of the first byte at which Source1 and Source2 differ, or Length
510 * if they are the same.
512 SIZE_T WINAPI
RtlCompareMemory( const VOID
*Source1
, const VOID
*Source2
, SIZE_T Length
)
515 for(i
=0; (i
<Length
) && (((const BYTE
*)Source1
)[i
]==((const BYTE
*)Source2
)[i
]); i
++);
519 /******************************************************************************
520 * RtlCompareMemoryUlong [NTDLL.@]
522 * Compare a block of memory with a value, a ULONG at a time
525 * Source1 [I] Source block. This must be ULONG aligned
526 * Length [I] Number of bytes to compare. This should be a multiple of 4
527 * dwVal [I] Value to compare to
530 * The byte position of the first byte at which Source1 is not dwVal.
532 SIZE_T WINAPI
RtlCompareMemoryUlong(const ULONG
*Source1
, SIZE_T Length
, ULONG dwVal
)
535 for(i
= 0; i
< Length
/sizeof(ULONG
) && Source1
[i
] == dwVal
; i
++);
536 return i
* sizeof(ULONG
);
539 /******************************************************************************
540 * RtlCopyMemory [NTDLL.@]
543 void WINAPI
RtlCopyMemory(void *dest
, const void *src
, SIZE_T len
)
545 memcpy(dest
, src
, len
);
548 /******************************************************************************
549 * RtlAssert [NTDLL.@]
551 * Fail a debug assertion.
554 * Nothing. This call does not return control to its caller.
557 * Not implemented in non-debug versions.
559 void WINAPI
RtlAssert(void *assertion
, void *filename
, ULONG linenumber
, char *message
)
561 FIXME("(%s, %s, %u, %s): stub\n", debugstr_a((char*)assertion
), debugstr_a((char*)filename
),
562 linenumber
, debugstr_a(message
));
565 /*************************************************************************
566 * RtlFillMemoryUlong [NTDLL.@]
568 * Fill memory with a 32 bit (dword) value.
571 * lpDest [I] Bitmap pointer
572 * ulCount [I] Number of dwords to write
573 * ulValue [I] Value to fill with
578 VOID WINAPI
RtlFillMemoryUlong(ULONG
* lpDest
, ULONG ulCount
, ULONG ulValue
)
580 TRACE("(%p,%d,%d)\n", lpDest
, ulCount
, ulValue
);
582 ulCount
/= sizeof(ULONG
);
587 /*********************************************************************
588 * RtlComputeCrc32 [NTDLL.@]
590 * Calculate the CRC32 checksum of a block of bytes
593 * dwInitial [I] Initial CRC value
594 * pData [I] Data block
595 * iLen [I] Length of the byte block
598 * The cumulative CRC32 of dwInitial and iLen bytes of the pData block.
600 DWORD WINAPI
RtlComputeCrc32(DWORD dwInitial
, const BYTE
*pData
, INT iLen
)
602 DWORD crc
= ~dwInitial
;
604 TRACE("(%d,%p,%d)\n", dwInitial
, pData
, iLen
);
608 crc
= CRC_table
[(crc
^ *pData
) & 0xff] ^ (crc
>> 8);
616 /*************************************************************************
617 * RtlUlonglongByteSwap [NTDLL.@]
619 * Swap the bytes of an unsigned long long value.
622 * i [I] Value to swap bytes of
625 * The value with its bytes swapped.
627 ULONGLONG __cdecl
RtlUlonglongByteSwap(ULONGLONG i
)
629 return ((ULONGLONG
)RtlUlongByteSwap(i
) << 32) | RtlUlongByteSwap(i
>>32);
632 /*************************************************************************
633 * RtlUlongByteSwap [NTDLL.@]
635 * Swap the bytes of an unsigned int value.
638 * ix86 version takes argument in %ecx. Other systems use the inline version.
641 __ASM_GLOBAL_FUNC(NTDLL_RtlUlongByteSwap
,
647 /*************************************************************************
648 * RtlUshortByteSwap [NTDLL.@]
650 * Swap the bytes of an unsigned short value.
653 * i386 version takes argument in %cx. Other systems use the inline version.
656 __ASM_GLOBAL_FUNC(NTDLL_RtlUshortByteSwap
,
663 /*************************************************************************
664 * RtlUniform [NTDLL.@]
666 * Generates an uniform random number
669 * seed [O] The seed of the Random function
672 * It returns a random number uniformly distributed over [0..MAXLONG-1].
675 * Generates an uniform random number using D.H. Lehmer's 1948 algorithm.
676 * In our case the algorithm is:
678 *| result = (*seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
683 * The native documentation states that the random number is
684 * uniformly distributed over [0..MAXLONG]. In reality the native
685 * function and our function return a random number uniformly
686 * distributed over [0..MAXLONG-1].
688 ULONG WINAPI
RtlUniform (PULONG seed
)
693 * Instead of the algorithm stated above, we use the algorithm
694 * below, which is totally equivalent (see the tests), but does
695 * not use a division and therefore is faster.
697 result
= *seed
* 0xffffffed + 0x7fffffc3;
698 if (result
== 0xffffffff || result
== 0x7ffffffe) {
699 result
= (result
+ 2) & MAXLONG
;
700 } else if (result
== 0x7fffffff) {
702 } else if ((result
& 0x80000000) == 0) {
703 result
= result
+ (~result
& 1);
705 result
= (result
+ (result
& 1)) & MAXLONG
;
712 /*************************************************************************
713 * RtlRandom [NTDLL.@]
715 * Generates a random number
718 * seed [O] The seed of the Random function
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 };
746 rand
= (*seed
* 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
747 *seed
= (rand
* 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
749 result
= saved_value
[pos
];
750 saved_value
[pos
] = rand
;
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
770 * TRUE: All desired accesses are granted
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
787 * GrantedAccess [I] Access mask of granted accesses
788 * DesiredAccess [I] Access mask of desired accesses
791 * TRUE: At least one of the desired accesses is granted
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
810 void WINAPI
RtlMapGenericMask(
811 PACCESS_MASK AccessMask
,
812 const GENERIC_MAPPING
*GenericMapping
)
814 if (*AccessMask
& GENERIC_READ
) {
815 *AccessMask
|= GenericMapping
->GenericRead
;
818 if (*AccessMask
& GENERIC_WRITE
) {
819 *AccessMask
|= GenericMapping
->GenericWrite
;
822 if (*AccessMask
& GENERIC_EXECUTE
) {
823 *AccessMask
|= GenericMapping
->GenericExecute
;
826 if (*AccessMask
& GENERIC_ALL
) {
827 *AccessMask
|= GenericMapping
->GenericAll
;
830 *AccessMask
&= 0x0FFFFFFF;
834 /*************************************************************************
835 * RtlCopyLuid [NTDLL.@]
837 * Copy a local unique ID.
840 * LuidDest [O] Destination for the copied Luid
841 * LuidSrc [I] Source Luid to copy to LuidDest
846 void WINAPI
RtlCopyLuid (PLUID LuidDest
, const LUID
*LuidSrc
)
848 *LuidDest
= *LuidSrc
;
852 /*************************************************************************
853 * RtlEqualLuid [NTDLL.@]
855 * Compare two local unique IDs.
858 * Luid1 [I] First Luid to compare to Luid2
859 * Luid2 [I] Second Luid to compare to Luid1
862 * TRUE: The two LUIDs are equal.
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.
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
885 * Dest must be large enough to hold Src.
887 void WINAPI
RtlCopyLuidAndAttributesArray(
889 const LUID_AND_ATTRIBUTES
*Src
,
890 PLUID_AND_ATTRIBUTES Dest
)
894 for (i
= 0; i
< Count
; i
++) Dest
[i
] = Src
[i
];
897 /***********************************************************************
898 * RtlIpv4StringToAddressExW [NTDLL.@]
900 NTSTATUS WINAPI
RtlIpv4StringToAddressExW(const WCHAR
*str
, BOOLEAN strict
, IN_ADDR
*address
, USHORT
*port
)
902 FIXME("(%s, %u, %p, %p): stub\n", debugstr_w(str
), strict
, address
, port
);
903 return STATUS_NOT_IMPLEMENTED
;
906 /***********************************************************************
907 * RtlIpv4StringToAddressW [NTDLL.@]
909 NTSTATUS WINAPI
RtlIpv4StringToAddressW(const WCHAR
*str
, BOOLEAN strict
, const WCHAR
**terminator
, IN_ADDR
*address
)
911 FIXME("(%s, %u, %p, %p): stub\n", debugstr_w(str
), strict
, terminator
, address
);
912 return STATUS_NOT_IMPLEMENTED
;
915 /***********************************************************************
916 * RtlIpv6StringToAddressExW [NTDLL.@]
918 NTSTATUS NTAPI
RtlIpv6StringToAddressExW(const WCHAR
*str
, IN6_ADDR
*address
, ULONG
*scope
, USHORT
*port
)
920 FIXME("(%s, %p, %p, %p): stub\n", debugstr_w(str
), address
, scope
, port
);
921 return STATUS_NOT_IMPLEMENTED
;
924 /***********************************************************************
925 * RtlIpv4AddressToStringExW [NTDLL.@]
927 * Convert the given ipv4 address and optional the port to a string
930 * pin [I] PTR to the ip address to convert (network byte order)
931 * port [I] optional port to convert (network byte order)
932 * buffer [O] destination buffer for the result
933 * psize [IO] PTR to available/used size of the destination buffer
936 * Success: STATUS_SUCCESS
937 * Failure: STATUS_INVALID_PARAMETER
940 NTSTATUS WINAPI
RtlIpv4AddressToStringExW(const IN_ADDR
*pin
, USHORT port
, LPWSTR buffer
, PULONG psize
)
943 static const WCHAR fmt_ip
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
944 static const WCHAR fmt_port
[] = {':','%','u',0};
947 if (!pin
|| !buffer
|| !psize
)
948 return STATUS_INVALID_PARAMETER
;
950 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin
, pin
->S_un
.S_addr
, port
, buffer
, psize
, *psize
);
952 needed
= sprintfW(tmp_ip
, fmt_ip
,
953 pin
->S_un
.S_un_b
.s_b1
, pin
->S_un
.S_un_b
.s_b2
,
954 pin
->S_un
.S_un_b
.s_b3
, pin
->S_un
.S_un_b
.s_b4
);
956 if (port
) needed
+= sprintfW(tmp_ip
+ needed
, fmt_port
, ntohs(port
));
958 if (*psize
> needed
) {
960 strcpyW(buffer
, tmp_ip
);
961 return STATUS_SUCCESS
;
965 return STATUS_INVALID_PARAMETER
;
968 /***********************************************************************
969 * RtlIpv4AddressToStringExA [NTDLL.@]
971 * Convert the given ipv4 address and optional the port to a string
973 * See RtlIpv4AddressToStringExW
975 NTSTATUS WINAPI
RtlIpv4AddressToStringExA(const IN_ADDR
*pin
, USHORT port
, LPSTR buffer
, PULONG psize
)
980 if (!pin
|| !buffer
|| !psize
)
981 return STATUS_INVALID_PARAMETER
;
983 TRACE("(%p:0x%x, %d, %p, %p:%d)\n", pin
, pin
->S_un
.S_addr
, port
, buffer
, psize
, *psize
);
985 needed
= sprintf(tmp_ip
, "%u.%u.%u.%u",
986 pin
->S_un
.S_un_b
.s_b1
, pin
->S_un
.S_un_b
.s_b2
,
987 pin
->S_un
.S_un_b
.s_b3
, pin
->S_un
.S_un_b
.s_b4
);
989 if (port
) needed
+= sprintf(tmp_ip
+ needed
, ":%u", ntohs(port
));
991 if (*psize
> needed
) {
993 strcpy(buffer
, tmp_ip
);
994 return STATUS_SUCCESS
;
998 return STATUS_INVALID_PARAMETER
;
1001 /***********************************************************************
1002 * RtlIpv4AddressToStringW [NTDLL.@]
1004 * Convert the given ipv4 address to a string
1007 * pin [I] PTR to the ip address to convert (network byte order)
1008 * buffer [O] destination buffer for the result (at least 16 character)
1011 * PTR to the 0 character at the end of the converted string
1014 WCHAR
* WINAPI
RtlIpv4AddressToStringW(const IN_ADDR
*pin
, LPWSTR buffer
)
1018 if (RtlIpv4AddressToStringExW(pin
, 0, buffer
, &size
)) size
= 0;
1019 return buffer
+ size
- 1;
1022 /***********************************************************************
1023 * RtlIpv4AddressToStringA [NTDLL.@]
1025 * Convert the given ipv4 address to a string
1027 * See RtlIpv4AddressToStringW
1029 CHAR
* WINAPI
RtlIpv4AddressToStringA(const IN_ADDR
*pin
, LPSTR buffer
)
1033 if (RtlIpv4AddressToStringExA(pin
, 0, buffer
, &size
)) size
= 0;
1034 return buffer
+ size
- 1;
1037 /***********************************************************************
1038 * get_pointer_obfuscator (internal)
1040 static DWORD_PTR
get_pointer_obfuscator( void )
1042 static DWORD_PTR pointer_obfuscator
;
1044 if (!pointer_obfuscator
)
1046 ULONG seed
= NtGetTickCount();
1049 /* generate a random value for the obfuscator */
1050 rand
= RtlUniform( &seed
);
1052 /* handle 64bit pointers */
1053 rand
^= (ULONG_PTR
)RtlUniform( &seed
) << ((sizeof (DWORD_PTR
) - sizeof (ULONG
))*8);
1055 /* set the high bits so dereferencing obfuscated pointers will (usually) crash */
1056 rand
|= (ULONG_PTR
)0xc0000000 << ((sizeof (DWORD_PTR
) - sizeof (ULONG
))*8);
1058 interlocked_cmpxchg_ptr( (void**) &pointer_obfuscator
, (void*) rand
, NULL
);
1061 return pointer_obfuscator
;
1064 /*************************************************************************
1065 * RtlEncodePointer [NTDLL.@]
1067 PVOID WINAPI
RtlEncodePointer( PVOID ptr
)
1069 DWORD_PTR ptrval
= (DWORD_PTR
) ptr
;
1070 return (PVOID
)(ptrval
^ get_pointer_obfuscator());
1073 PVOID WINAPI
RtlDecodePointer( PVOID ptr
)
1075 DWORD_PTR ptrval
= (DWORD_PTR
) ptr
;
1076 return (PVOID
)(ptrval
^ get_pointer_obfuscator());
1079 /*************************************************************************
1080 * RtlInitializeSListHead [NTDLL.@]
1082 VOID WINAPI
RtlInitializeSListHead(PSLIST_HEADER list
)
1085 list
->s
.Alignment
= list
->s
.Region
= 0;
1086 list
->Header16
.HeaderType
= 1; /* we use the 16-byte header */
1088 list
->Alignment
= 0;
1092 /*************************************************************************
1093 * RtlQueryDepthSList [NTDLL.@]
1095 WORD WINAPI
RtlQueryDepthSList(PSLIST_HEADER list
)
1098 return list
->Header16
.Depth
;
1100 return list
->s
.Depth
;
1104 /*************************************************************************
1105 * RtlFirstEntrySList [NTDLL.@]
1107 PSLIST_ENTRY WINAPI
RtlFirstEntrySList(const SLIST_HEADER
* list
)
1110 return (SLIST_ENTRY
*)((ULONG_PTR
)list
->Header16
.NextEntry
<< 4);
1112 return list
->s
.Next
.Next
;
1116 /*************************************************************************
1117 * RtlInterlockedFlushSList [NTDLL.@]
1119 PSLIST_ENTRY WINAPI
RtlInterlockedFlushSList(PSLIST_HEADER list
)
1121 SLIST_HEADER old
, new;
1124 if (!list
->Header16
.NextEntry
) return NULL
;
1125 new.s
.Alignment
= new.s
.Region
= 0;
1126 new.Header16
.HeaderType
= 1; /* we use the 16-byte header */
1130 new.Header16
.Sequence
= old
.Header16
.Sequence
+ 1;
1131 } while (!interlocked_cmpxchg128((__int64
*)list
, new.s
.Region
, new.s
.Alignment
, (__int64
*)&old
));
1132 return (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1134 if (!list
->s
.Next
.Next
) return NULL
;
1139 new.s
.Sequence
= old
.s
.Sequence
+ 1;
1140 } while (interlocked_cmpxchg64((__int64
*)&list
->Alignment
, new.Alignment
,
1141 old
.Alignment
) != old
.Alignment
);
1142 return old
.s
.Next
.Next
;
1146 /*************************************************************************
1147 * RtlInterlockedPushEntrySList [NTDLL.@]
1149 PSLIST_ENTRY WINAPI
RtlInterlockedPushEntrySList(PSLIST_HEADER list
, PSLIST_ENTRY entry
)
1151 SLIST_HEADER old
, new;
1154 new.Header16
.NextEntry
= (ULONG_PTR
)entry
>> 4;
1158 entry
->Next
= (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1159 new.Header16
.Depth
= old
.Header16
.Depth
+ 1;
1160 new.Header16
.Sequence
= old
.Header16
.Sequence
+ 1;
1161 } while (!interlocked_cmpxchg128((__int64
*)list
, new.s
.Region
, new.s
.Alignment
, (__int64
*)&old
));
1162 return (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1164 new.s
.Next
.Next
= entry
;
1168 entry
->Next
= old
.s
.Next
.Next
;
1169 new.s
.Depth
= old
.s
.Depth
+ 1;
1170 new.s
.Sequence
= old
.s
.Sequence
+ 1;
1171 } while (interlocked_cmpxchg64((__int64
*)&list
->Alignment
, new.Alignment
,
1172 old
.Alignment
) != old
.Alignment
);
1173 return old
.s
.Next
.Next
;
1177 /*************************************************************************
1178 * RtlInterlockedPopEntrySList [NTDLL.@]
1180 PSLIST_ENTRY WINAPI
RtlInterlockedPopEntrySList(PSLIST_HEADER list
)
1182 SLIST_HEADER old
, new;
1189 if (!(entry
= (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4))) return NULL
;
1190 /* entry could be deleted by another thread */
1193 new.Header16
.NextEntry
= (ULONG_PTR
)entry
->Next
>> 4;
1194 new.Header16
.Depth
= old
.Header16
.Depth
- 1;
1195 new.Header16
.Sequence
= old
.Header16
.Sequence
+ 1;
1201 } while (!interlocked_cmpxchg128((__int64
*)list
, new.s
.Region
, new.s
.Alignment
, (__int64
*)&old
));
1206 if (!(entry
= old
.s
.Next
.Next
)) return NULL
;
1207 /* entry could be deleted by another thread */
1210 new.s
.Next
.Next
= entry
->Next
;
1211 new.s
.Depth
= old
.s
.Depth
- 1;
1212 new.s
.Sequence
= old
.s
.Sequence
+ 1;
1218 } while (interlocked_cmpxchg64((__int64
*)&list
->Alignment
, new.Alignment
,
1219 old
.Alignment
) != old
.Alignment
);
1224 /*************************************************************************
1225 * RtlInterlockedPushListSListEx [NTDLL.@]
1227 PSLIST_ENTRY WINAPI
RtlInterlockedPushListSListEx(PSLIST_HEADER list
, PSLIST_ENTRY first
,
1228 PSLIST_ENTRY last
, ULONG count
)
1230 SLIST_HEADER old
, new;
1233 new.Header16
.NextEntry
= (ULONG_PTR
)first
>> 4;
1237 new.Header16
.Depth
= old
.Header16
.Depth
+ count
;
1238 new.Header16
.Sequence
= old
.Header16
.Sequence
+ 1;
1239 last
->Next
= (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1240 } while (!interlocked_cmpxchg128((__int64
*)list
, new.s
.Region
, new.s
.Alignment
, (__int64
*)&old
));
1241 return (SLIST_ENTRY
*)((ULONG_PTR
)old
.Header16
.NextEntry
<< 4);
1243 new.s
.Next
.Next
= first
;
1247 new.s
.Depth
= old
.s
.Depth
+ count
;
1248 new.s
.Sequence
= old
.s
.Sequence
+ 1;
1249 last
->Next
= old
.s
.Next
.Next
;
1250 } while (interlocked_cmpxchg64((__int64
*)&list
->Alignment
, new.Alignment
,
1251 old
.Alignment
) != old
.Alignment
);
1252 return old
.s
.Next
.Next
;
1256 /*************************************************************************
1257 * RtlInterlockedPushListSList [NTDLL.@]
1259 #ifdef DEFINE_FASTCALL4_ENTRYPOINT
1260 DEFINE_FASTCALL4_ENTRYPOINT(RtlInterlockedPushListSList
)
1261 PSLIST_ENTRY WINAPI DECLSPEC_HIDDEN
__regs_RtlInterlockedPushListSList(PSLIST_HEADER list
, PSLIST_ENTRY first
,
1262 PSLIST_ENTRY last
, ULONG count
)
1264 PSLIST_ENTRY WINAPI
RtlInterlockedPushListSList(PSLIST_HEADER list
, PSLIST_ENTRY first
,
1265 PSLIST_ENTRY last
, ULONG count
)
1268 return RtlInterlockedPushListSListEx(list
, first
, last
, count
);
1271 /******************************************************************************
1272 * RtlGetCompressionWorkSpaceSize [NTDLL.@]
1274 NTSTATUS WINAPI
RtlGetCompressionWorkSpaceSize(USHORT format
, PULONG compress_workspace
,
1275 PULONG decompress_workspace
)
1277 FIXME("0x%04x, %p, %p: semi-stub\n", format
, compress_workspace
, decompress_workspace
);
1279 switch (format
& ~COMPRESSION_ENGINE_MAXIMUM
)
1281 case COMPRESSION_FORMAT_LZNT1
:
1282 if (compress_workspace
)
1284 /* FIXME: The current implementation of RtlCompressBuffer does not use a
1285 * workspace buffer, but Windows applications might expect a nonzero value. */
1286 *compress_workspace
= 16;
1288 if (decompress_workspace
)
1289 *decompress_workspace
= 0x1000;
1290 return STATUS_SUCCESS
;
1292 case COMPRESSION_FORMAT_NONE
:
1293 case COMPRESSION_FORMAT_DEFAULT
:
1294 return STATUS_INVALID_PARAMETER
;
1297 FIXME("format %u not implemented\n", format
);
1298 return STATUS_UNSUPPORTED_COMPRESSION
;
1302 /* compress data using LZNT1, currently only a stub */
1303 static NTSTATUS
lznt1_compress(UCHAR
*src
, ULONG src_size
, UCHAR
*dst
, ULONG dst_size
,
1304 ULONG chunk_size
, ULONG
*final_size
, UCHAR
*workspace
)
1306 UCHAR
*src_cur
= src
, *src_end
= src
+ src_size
;
1307 UCHAR
*dst_cur
= dst
, *dst_end
= dst
+ dst_size
;
1310 while (src_cur
< src_end
)
1312 /* determine size of current chunk */
1313 block_size
= min(0x1000, src_end
- src_cur
);
1314 if (dst_cur
+ sizeof(WORD
) + block_size
> dst_end
)
1315 return STATUS_BUFFER_TOO_SMALL
;
1317 /* write (uncompressed) chunk header */
1318 *(WORD
*)dst_cur
= 0x3000 | (block_size
- 1);
1319 dst_cur
+= sizeof(WORD
);
1321 /* write chunk content */
1322 memcpy(dst_cur
, src_cur
, block_size
);
1323 dst_cur
+= block_size
;
1324 src_cur
+= block_size
;
1328 *final_size
= dst_cur
- dst
;
1330 return STATUS_SUCCESS
;
1333 /******************************************************************************
1334 * RtlCompressBuffer [NTDLL.@]
1336 NTSTATUS WINAPI
RtlCompressBuffer(USHORT format
, PUCHAR uncompressed
, ULONG uncompressed_size
,
1337 PUCHAR compressed
, ULONG compressed_size
, ULONG chunk_size
,
1338 PULONG final_size
, PVOID workspace
)
1340 FIXME("0x%04x, %p, %u, %p, %u, %u, %p, %p: semi-stub\n", format
, uncompressed
,
1341 uncompressed_size
, compressed
, compressed_size
, chunk_size
, final_size
, workspace
);
1343 switch (format
& ~COMPRESSION_ENGINE_MAXIMUM
)
1345 case COMPRESSION_FORMAT_LZNT1
:
1346 return lznt1_compress(uncompressed
, uncompressed_size
, compressed
,
1347 compressed_size
, chunk_size
, final_size
, workspace
);
1349 case COMPRESSION_FORMAT_NONE
:
1350 case COMPRESSION_FORMAT_DEFAULT
:
1351 return STATUS_INVALID_PARAMETER
;
1354 FIXME("format %u not implemented\n", format
);
1355 return STATUS_UNSUPPORTED_COMPRESSION
;
1359 /* decompress a single LZNT1 chunk */
1360 static UCHAR
*lznt1_decompress_chunk(UCHAR
*dst
, ULONG dst_size
, UCHAR
*src
, ULONG src_size
)
1362 UCHAR
*src_cur
= src
, *src_end
= src
+ src_size
;
1363 UCHAR
*dst_cur
= dst
, *dst_end
= dst
+ dst_size
;
1364 ULONG displacement_bits
, length_bits
;
1365 ULONG code_displacement
, code_length
;
1368 while (src_cur
< src_end
&& dst_cur
< dst_end
)
1370 flags
= 0x8000 | *src_cur
++;
1371 while ((flags
& 0xff00) && src_cur
< src_end
)
1375 /* backwards reference */
1376 if (src_cur
+ sizeof(WORD
) > src_end
)
1379 code
= *(WORD
*)src_cur
;
1380 src_cur
+= sizeof(WORD
);
1382 /* find length / displacement bits */
1383 for (displacement_bits
= 12; displacement_bits
> 4; displacement_bits
--)
1384 if ((1 << (displacement_bits
- 1)) < dst_cur
- dst
) break;
1386 length_bits
= 16 - displacement_bits
;
1387 code_length
= (code
& ((1 << length_bits
) - 1)) + 3;
1388 code_displacement
= (code
>> length_bits
) + 1;
1390 if (dst_cur
< dst
+ code_displacement
)
1393 /* copy bytes of chunk - we can't use memcpy() since source and dest can
1394 * be overlapping, and the same bytes can be repeated over and over again */
1395 while (code_length
--)
1397 if (dst_cur
>= dst_end
) return dst_cur
;
1398 *dst_cur
= *(dst_cur
- code_displacement
);
1404 /* uncompressed data */
1405 if (dst_cur
>= dst_end
) return dst_cur
;
1406 *dst_cur
++ = *src_cur
++;
1415 /* decompress data encoded with LZNT1 */
1416 static NTSTATUS
lznt1_decompress(UCHAR
*dst
, ULONG dst_size
, UCHAR
*src
, ULONG src_size
,
1417 ULONG offset
, ULONG
*final_size
, UCHAR
*workspace
)
1419 UCHAR
*src_cur
= src
, *src_end
= src
+ src_size
;
1420 UCHAR
*dst_cur
= dst
, *dst_end
= dst
+ dst_size
;
1421 ULONG chunk_size
, block_size
;
1425 if (src_cur
+ sizeof(WORD
) > src_end
)
1426 return STATUS_BAD_COMPRESSION_BUFFER
;
1428 /* skip over chunks with a distance >= 0x1000 to the destination offset */
1429 while (offset
>= 0x1000 && src_cur
+ sizeof(WORD
) <= src_end
)
1431 chunk_header
= *(WORD
*)src_cur
;
1432 src_cur
+= sizeof(WORD
);
1433 if (!chunk_header
) goto out
;
1434 chunk_size
= (chunk_header
& 0xfff) + 1;
1436 if (src_cur
+ chunk_size
> src_end
)
1437 return STATUS_BAD_COMPRESSION_BUFFER
;
1439 src_cur
+= chunk_size
;
1443 /* handle partially included chunk */
1444 if (offset
&& src_cur
+ sizeof(WORD
) <= src_end
)
1446 chunk_header
= *(WORD
*)src_cur
;
1447 src_cur
+= sizeof(WORD
);
1448 if (!chunk_header
) goto out
;
1449 chunk_size
= (chunk_header
& 0xfff) + 1;
1451 if (src_cur
+ chunk_size
> src_end
)
1452 return STATUS_BAD_COMPRESSION_BUFFER
;
1454 if (dst_cur
>= dst_end
)
1457 if (chunk_header
& 0x8000)
1459 /* compressed chunk */
1460 if (!workspace
) return STATUS_ACCESS_VIOLATION
;
1461 ptr
= lznt1_decompress_chunk(workspace
, 0x1000, src_cur
, chunk_size
);
1462 if (!ptr
) return STATUS_BAD_COMPRESSION_BUFFER
;
1463 if (ptr
- workspace
> offset
)
1465 block_size
= min((ptr
- workspace
) - offset
, dst_end
- dst_cur
);
1466 memcpy(dst_cur
, workspace
+ offset
, block_size
);
1467 dst_cur
+= block_size
;
1472 /* uncompressed chunk */
1473 if (chunk_size
> offset
)
1475 block_size
= min(chunk_size
- offset
, dst_end
- dst_cur
);
1476 memcpy(dst_cur
, src_cur
+ offset
, block_size
);
1477 dst_cur
+= block_size
;
1481 src_cur
+= chunk_size
;
1484 /* handle remaining chunks */
1485 while (src_cur
+ sizeof(WORD
) <= src_end
)
1487 chunk_header
= *(WORD
*)src_cur
;
1488 src_cur
+= sizeof(WORD
);
1489 if (!chunk_header
) goto out
;
1490 chunk_size
= (chunk_header
& 0xfff) + 1;
1492 if (src_cur
+ chunk_size
> src_end
)
1493 return STATUS_BAD_COMPRESSION_BUFFER
;
1495 /* fill space with padding when the previous chunk was decompressed
1496 * to less than 4096 bytes. no padding is needed for the last chunk
1497 * or when the next chunk is truncated */
1498 block_size
= ((dst_cur
- dst
) + offset
) & 0xfff;
1501 block_size
= 0x1000 - block_size
;
1502 if (dst_cur
+ block_size
>= dst_end
)
1504 memset(dst_cur
, 0, block_size
);
1505 dst_cur
+= block_size
;
1508 if (dst_cur
>= dst_end
)
1511 if (chunk_header
& 0x8000)
1513 /* compressed chunk */
1514 dst_cur
= lznt1_decompress_chunk(dst_cur
, dst_end
- dst_cur
, src_cur
, chunk_size
);
1515 if (!dst_cur
) return STATUS_BAD_COMPRESSION_BUFFER
;
1519 /* uncompressed chunk */
1520 block_size
= min(chunk_size
, dst_end
- dst_cur
);
1521 memcpy(dst_cur
, src_cur
, block_size
);
1522 dst_cur
+= block_size
;
1525 src_cur
+= chunk_size
;
1530 *final_size
= dst_cur
- dst
;
1532 return STATUS_SUCCESS
;
1536 /******************************************************************************
1537 * RtlDecompressFragment [NTDLL.@]
1539 NTSTATUS WINAPI
RtlDecompressFragment(USHORT format
, PUCHAR uncompressed
, ULONG uncompressed_size
,
1540 PUCHAR compressed
, ULONG compressed_size
, ULONG offset
,
1541 PULONG final_size
, PVOID workspace
)
1543 TRACE("0x%04x, %p, %u, %p, %u, %u, %p, %p\n", format
, uncompressed
,
1544 uncompressed_size
, compressed
, compressed_size
, offset
, final_size
, workspace
);
1546 switch (format
& ~COMPRESSION_ENGINE_MAXIMUM
)
1548 case COMPRESSION_FORMAT_LZNT1
:
1549 return lznt1_decompress(uncompressed
, uncompressed_size
, compressed
,
1550 compressed_size
, offset
, final_size
, workspace
);
1552 case COMPRESSION_FORMAT_NONE
:
1553 case COMPRESSION_FORMAT_DEFAULT
:
1554 return STATUS_INVALID_PARAMETER
;
1557 FIXME("format %u not implemented\n", format
);
1558 return STATUS_UNSUPPORTED_COMPRESSION
;
1563 /******************************************************************************
1564 * RtlDecompressBuffer [NTDLL.@]
1566 NTSTATUS WINAPI
RtlDecompressBuffer(USHORT format
, PUCHAR uncompressed
, ULONG uncompressed_size
,
1567 PUCHAR compressed
, ULONG compressed_size
, PULONG final_size
)
1569 TRACE("0x%04x, %p, %u, %p, %u, %p\n", format
, uncompressed
,
1570 uncompressed_size
, compressed
, compressed_size
, final_size
);
1572 return RtlDecompressFragment(format
, uncompressed
, uncompressed_size
,
1573 compressed
, compressed_size
, 0, final_size
, NULL
);
1576 /***********************************************************************
1577 * RtlSetThreadErrorMode [NTDLL.@]
1579 * Set the thread local error mode.
1582 * mode [I] The new error mode
1583 * oldmode [O] Destination of the old error mode (may be NULL)
1586 * Success: STATUS_SUCCESS
1587 * Failure: STATUS_INVALID_PARAMETER_1
1589 NTSTATUS WINAPI
RtlSetThreadErrorMode( DWORD mode
, LPDWORD oldmode
)
1592 return STATUS_INVALID_PARAMETER_1
;
1595 *oldmode
= NtCurrentTeb()->HardErrorDisabled
;
1597 NtCurrentTeb()->HardErrorDisabled
= mode
;
1598 return STATUS_SUCCESS
;
1601 /***********************************************************************
1602 * RtlGetThreadErrorMode [NTDLL.@]
1604 * Get the thread local error mode.
1610 * The current thread local error mode.
1612 DWORD WINAPI
RtlGetThreadErrorMode( void )
1614 return NtCurrentTeb()->HardErrorDisabled
;
1617 /******************************************************************************
1618 * RtlGetCurrentTransaction [NTDLL.@]
1620 HANDLE WINAPI
RtlGetCurrentTransaction(void)
1622 FIXME("() :stub\n");
1626 /******************************************************************************
1627 * RtlSetCurrentTransaction [NTDLL.@]
1629 BOOL WINAPI
RtlSetCurrentTransaction(HANDLE new_transaction
)
1631 FIXME("(%p) :stub\n", new_transaction
);
1635 /**********************************************************************
1636 * RtlGetCurrentProcessorNumberEx [NTDLL.@]
1638 void WINAPI
RtlGetCurrentProcessorNumberEx(PROCESSOR_NUMBER
*processor
)
1640 FIXME("(%p) :semi-stub\n", processor
);
1641 processor
->Group
= 0;
1642 processor
->Number
= NtGetCurrentProcessorNumber();
1643 processor
->Reserved
= 0;
1646 /***********************************************************************
1647 * RtlInitializeGenericTableAvl (NTDLL.@)
1649 void WINAPI
RtlInitializeGenericTableAvl(PRTL_AVL_TABLE table
, PRTL_AVL_COMPARE_ROUTINE compare
,
1650 PRTL_AVL_ALLOCATE_ROUTINE allocate
, PRTL_AVL_FREE_ROUTINE free
, void *context
)
1652 FIXME("%p %p %p %p %p: stub\n", table
, compare
, allocate
, free
, context
);
1655 /***********************************************************************
1656 * RtlInsertElementGenericTableAvl (NTDLL.@)
1658 void WINAPI
RtlInsertElementGenericTableAvl(PRTL_AVL_TABLE table
, void *buffer
, ULONG size
, BOOL
*element
)
1660 FIXME("%p %p %u %p: stub\n", table
, buffer
, size
, element
);
1663 typedef struct _RTL_UNLOAD_EVENT_TRACE
1668 ULONG TimeDateStamp
;
1670 WCHAR ImageName
[32];
1671 } RTL_UNLOAD_EVENT_TRACE
, *PRTL_UNLOAD_EVENT_TRACE
;
1673 /*********************************************************************
1674 * RtlGetUnloadEventTrace [NTDLL.@]
1676 RTL_UNLOAD_EVENT_TRACE
* WINAPI
RtlGetUnloadEventTrace(void)
1682 /*********************************************************************
1683 * RtlGetUnloadEventTraceEx [NTDLL.@]
1685 void WINAPI
RtlGetUnloadEventTraceEx(ULONG
**size
, ULONG
**count
, void **trace
)
1687 static ULONG dummy_size
, dummy_count
;
1689 FIXME("(%p, %p, %p): stub!\n", size
, count
, trace
);
1691 if (size
) *size
= &dummy_size
;
1692 if (count
) *count
= &dummy_count
;
1693 if (trace
) *trace
= NULL
;
1696 /*********************************************************************
1697 * RtlQueryPackageIdentity [NTDLL.@]
1699 NTSTATUS WINAPI
RtlQueryPackageIdentity(HANDLE token
, WCHAR
*fullname
, SIZE_T
*fullname_size
,
1700 WCHAR
*appid
, SIZE_T
*appid_size
, BOOLEAN
*packaged
)
1702 FIXME("(%p, %p, %p, %p, %p, %p): stub\n", token
, fullname
, fullname_size
, appid
, appid_size
, packaged
);
1703 return STATUS_NOT_FOUND
;