20b39f3ea73a7da04b7de0f2cd30a9309715c59b
[reactos.git] / rostests / winetests / ntdll / rtl.c
1 /* Unit test suite for Rtl* API functions
2 *
3 * Copyright 2003 Thomas Mertes
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 *
19 * NOTES
20 * We use function pointers here as there is no import library for NTDLL on
21 * windows.
22 */
23
24 #include <stdlib.h>
25
26 #include "ntdll_test.h"
27 #include "inaddr.h"
28
29 #ifndef __WINE_WINTERNL_H
30
31 typedef struct _RTL_HANDLE
32 {
33 struct _RTL_HANDLE * Next;
34 } RTL_HANDLE;
35
36 typedef struct _RTL_HANDLE_TABLE
37 {
38 ULONG MaxHandleCount;
39 ULONG HandleSize;
40 ULONG Unused[2];
41 PVOID NextFree;
42 PVOID FirstHandle;
43 PVOID ReservedMemory;
44 PVOID MaxHandle;
45 } RTL_HANDLE_TABLE;
46
47 #endif
48
49 /* avoid #include <winsock2.h> */
50 #undef htons
51 #ifdef WORDS_BIGENDIAN
52 #define htons(s) ((USHORT)(s))
53 #else /* WORDS_BIGENDIAN */
54 static inline USHORT __my_ushort_swap(USHORT s)
55 {
56 return (s >> 8) | (s << 8);
57 }
58 #define htons(s) __my_ushort_swap(s)
59 #endif /* WORDS_BIGENDIAN */
60
61
62
63 /* Function ptrs for ntdll calls */
64 static HMODULE hntdll = 0;
65 static SIZE_T (WINAPI *pRtlCompareMemory)(LPCVOID,LPCVOID,SIZE_T);
66 static SIZE_T (WINAPI *pRtlCompareMemoryUlong)(PULONG, SIZE_T, ULONG);
67 static NTSTATUS (WINAPI *pRtlDeleteTimer)(HANDLE, HANDLE, HANDLE);
68 static VOID (WINAPI *pRtlMoveMemory)(LPVOID,LPCVOID,SIZE_T);
69 static VOID (WINAPI *pRtlFillMemory)(LPVOID,SIZE_T,BYTE);
70 static VOID (WINAPI *pRtlFillMemoryUlong)(LPVOID,SIZE_T,ULONG);
71 static VOID (WINAPI *pRtlZeroMemory)(LPVOID,SIZE_T);
72 static ULONGLONG (WINAPIV *pRtlUlonglongByteSwap)(ULONGLONG source);
73 static ULONG (WINAPI *pRtlUniform)(PULONG);
74 static ULONG (WINAPI *pRtlRandom)(PULONG);
75 static BOOLEAN (WINAPI *pRtlAreAllAccessesGranted)(ACCESS_MASK, ACCESS_MASK);
76 static BOOLEAN (WINAPI *pRtlAreAnyAccessesGranted)(ACCESS_MASK, ACCESS_MASK);
77 static DWORD (WINAPI *pRtlComputeCrc32)(DWORD,const BYTE*,INT);
78 static void (WINAPI * pRtlInitializeHandleTable)(ULONG, ULONG, RTL_HANDLE_TABLE *);
79 static BOOLEAN (WINAPI * pRtlIsValidIndexHandle)(const RTL_HANDLE_TABLE *, ULONG, RTL_HANDLE **);
80 static NTSTATUS (WINAPI * pRtlDestroyHandleTable)(RTL_HANDLE_TABLE *);
81 static RTL_HANDLE * (WINAPI * pRtlAllocateHandle)(RTL_HANDLE_TABLE *, ULONG *);
82 static BOOLEAN (WINAPI * pRtlFreeHandle)(RTL_HANDLE_TABLE *, RTL_HANDLE *);
83 static NTSTATUS (WINAPI *pRtlAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY,BYTE,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,PSID*);
84 static NTSTATUS (WINAPI *pRtlFreeSid)(PSID);
85 static struct _TEB * (WINAPI *pNtCurrentTeb)(void);
86 static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
87 static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD);
88 static IMAGE_BASE_RELOCATION *(WINAPI *pLdrProcessRelocationBlock)(void*,UINT,USHORT*,INT_PTR);
89 static CHAR * (WINAPI *pRtlIpv4AddressToStringA)(const IN_ADDR *, LPSTR);
90 static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG);
91
92 static HMODULE hkernel32 = 0;
93 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
94
95
96 #define LEN 16
97 static const char* src_src = "This is a test!"; /* 16 bytes long, incl NUL */
98 static ULONG src_aligned_block[4];
99 static ULONG dest_aligned_block[32];
100 static const char *src = (const char*)src_aligned_block;
101 static char* dest = (char*)dest_aligned_block;
102
103 static void InitFunctionPtrs(void)
104 {
105 hntdll = LoadLibraryA("ntdll.dll");
106 ok(hntdll != 0, "LoadLibrary failed\n");
107 if (hntdll) {
108 pRtlCompareMemory = (void *)GetProcAddress(hntdll, "RtlCompareMemory");
109 pRtlCompareMemoryUlong = (void *)GetProcAddress(hntdll, "RtlCompareMemoryUlong");
110 pRtlDeleteTimer = (void *)GetProcAddress(hntdll, "RtlDeleteTimer");
111 pRtlMoveMemory = (void *)GetProcAddress(hntdll, "RtlMoveMemory");
112 pRtlFillMemory = (void *)GetProcAddress(hntdll, "RtlFillMemory");
113 pRtlFillMemoryUlong = (void *)GetProcAddress(hntdll, "RtlFillMemoryUlong");
114 pRtlZeroMemory = (void *)GetProcAddress(hntdll, "RtlZeroMemory");
115 pRtlUlonglongByteSwap = (void *)GetProcAddress(hntdll, "RtlUlonglongByteSwap");
116 pRtlUniform = (void *)GetProcAddress(hntdll, "RtlUniform");
117 pRtlRandom = (void *)GetProcAddress(hntdll, "RtlRandom");
118 pRtlAreAllAccessesGranted = (void *)GetProcAddress(hntdll, "RtlAreAllAccessesGranted");
119 pRtlAreAnyAccessesGranted = (void *)GetProcAddress(hntdll, "RtlAreAnyAccessesGranted");
120 pRtlComputeCrc32 = (void *)GetProcAddress(hntdll, "RtlComputeCrc32");
121 pRtlInitializeHandleTable = (void *)GetProcAddress(hntdll, "RtlInitializeHandleTable");
122 pRtlIsValidIndexHandle = (void *)GetProcAddress(hntdll, "RtlIsValidIndexHandle");
123 pRtlDestroyHandleTable = (void *)GetProcAddress(hntdll, "RtlDestroyHandleTable");
124 pRtlAllocateHandle = (void *)GetProcAddress(hntdll, "RtlAllocateHandle");
125 pRtlFreeHandle = (void *)GetProcAddress(hntdll, "RtlFreeHandle");
126 pRtlAllocateAndInitializeSid = (void *)GetProcAddress(hntdll, "RtlAllocateAndInitializeSid");
127 pRtlFreeSid = (void *)GetProcAddress(hntdll, "RtlFreeSid");
128 pNtCurrentTeb = (void *)GetProcAddress(hntdll, "NtCurrentTeb");
129 pRtlGetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlGetThreadErrorMode");
130 pRtlSetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlSetThreadErrorMode");
131 pLdrProcessRelocationBlock = (void *)GetProcAddress(hntdll, "LdrProcessRelocationBlock");
132 pRtlIpv4AddressToStringA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringA");
133 pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringExA");
134 }
135 hkernel32 = LoadLibraryA("kernel32.dll");
136 ok(hkernel32 != 0, "LoadLibrary failed\n");
137 if (hkernel32) {
138 pIsWow64Process = (void *)GetProcAddress(hkernel32, "IsWow64Process");
139 }
140 strcpy((char*)src_aligned_block, src_src);
141 ok(strlen(src) == 15, "Source must be 16 bytes long!\n");
142 }
143
144 #define COMP(str1,str2,cmplen,len) size = pRtlCompareMemory(str1, str2, cmplen); \
145 ok(size == len, "Expected %ld, got %ld\n", size, (SIZE_T)len)
146
147 static void test_RtlCompareMemory(void)
148 {
149 SIZE_T size;
150
151 if (!pRtlCompareMemory)
152 {
153 win_skip("RtlCompareMemory is not available\n");
154 return;
155 }
156
157 strcpy(dest, src);
158
159 COMP(src,src,0,0);
160 COMP(src,src,LEN,LEN);
161 dest[0] = 'x';
162 COMP(src,dest,LEN,0);
163 }
164
165 static void test_RtlCompareMemoryUlong(void)
166 {
167 ULONG a[10];
168 ULONG result;
169
170 if (!pRtlCompareMemoryUlong)
171 {
172 win_skip("RtlCompareMemoryUlong is not available\n");
173 return;
174 }
175
176 a[0]= 0x0123;
177 a[1]= 0x4567;
178 a[2]= 0x89ab;
179 a[3]= 0xcdef;
180 result = pRtlCompareMemoryUlong(a, 0, 0x0123);
181 ok(result == 0, "RtlCompareMemoryUlong(%p, 0, 0x0123) returns %u, expected 0\n", a, result);
182 result = pRtlCompareMemoryUlong(a, 3, 0x0123);
183 ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %u, expected 0\n", a, result);
184 result = pRtlCompareMemoryUlong(a, 4, 0x0123);
185 ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %u, expected 4\n", a, result);
186 result = pRtlCompareMemoryUlong(a, 5, 0x0123);
187 ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %u, expected 4\n", a, result);
188 result = pRtlCompareMemoryUlong(a, 7, 0x0123);
189 ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %u, expected 4\n", a, result);
190 result = pRtlCompareMemoryUlong(a, 8, 0x0123);
191 ok(result == 4, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %u, expected 4\n", a, result);
192 result = pRtlCompareMemoryUlong(a, 9, 0x0123);
193 ok(result == 4, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %u, expected 4\n", a, result);
194 result = pRtlCompareMemoryUlong(a, 4, 0x0127);
195 ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x0127) returns %u, expected 0\n", a, result);
196 result = pRtlCompareMemoryUlong(a, 4, 0x7123);
197 ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x7123) returns %u, expected 0\n", a, result);
198 result = pRtlCompareMemoryUlong(a, 16, 0x4567);
199 ok(result == 0, "RtlCompareMemoryUlong(%p, 16, 0x4567) returns %u, expected 0\n", a, result);
200
201 a[1]= 0x0123;
202 result = pRtlCompareMemoryUlong(a, 3, 0x0123);
203 ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %u, expected 0\n", a, result);
204 result = pRtlCompareMemoryUlong(a, 4, 0x0123);
205 ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %u, expected 4\n", a, result);
206 result = pRtlCompareMemoryUlong(a, 5, 0x0123);
207 ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %u, expected 4\n", a, result);
208 result = pRtlCompareMemoryUlong(a, 7, 0x0123);
209 ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %u, expected 4\n", a, result);
210 result = pRtlCompareMemoryUlong(a, 8, 0x0123);
211 ok(result == 8, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %u, expected 8\n", a, result);
212 result = pRtlCompareMemoryUlong(a, 9, 0x0123);
213 ok(result == 8, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %u, expected 8\n", a, result);
214 }
215
216 #define COPY(len) memset(dest,0,sizeof(dest_aligned_block)); pRtlMoveMemory(dest, src, len)
217 #define CMP(str) ok(strcmp(dest,str) == 0, "Expected '%s', got '%s'\n", str, dest)
218
219 static void test_RtlMoveMemory(void)
220 {
221 if (!pRtlMoveMemory)
222 {
223 win_skip("RtlMoveMemory is not available\n");
224 return;
225 }
226
227 /* Length should be in bytes and not rounded. Use strcmp to ensure we
228 * didn't write past the end (it checks for the final NUL left by memset)
229 */
230 COPY(0); CMP("");
231 COPY(1); CMP("T");
232 COPY(2); CMP("Th");
233 COPY(3); CMP("Thi");
234 COPY(4); CMP("This");
235 COPY(5); CMP("This ");
236 COPY(6); CMP("This i");
237 COPY(7); CMP("This is");
238 COPY(8); CMP("This is ");
239 COPY(9); CMP("This is a");
240
241 /* Overlapping */
242 strcpy(dest, src); pRtlMoveMemory(dest, dest + 1, strlen(src) - 1);
243 CMP("his is a test!!");
244 strcpy(dest, src); pRtlMoveMemory(dest + 1, dest, strlen(src));
245 CMP("TThis is a test!");
246 }
247
248 #define FILL(len) memset(dest,0,sizeof(dest_aligned_block)); strcpy(dest, src); pRtlFillMemory(dest,len,'x')
249
250 static void test_RtlFillMemory(void)
251 {
252 if (!pRtlFillMemory)
253 {
254 win_skip("RtlFillMemory is not available\n");
255 return;
256 }
257
258 /* Length should be in bytes and not rounded. Use strcmp to ensure we
259 * didn't write past the end (the remainder of the string should match)
260 */
261 FILL(0); CMP("This is a test!");
262 FILL(1); CMP("xhis is a test!");
263 FILL(2); CMP("xxis is a test!");
264 FILL(3); CMP("xxxs is a test!");
265 FILL(4); CMP("xxxx is a test!");
266 FILL(5); CMP("xxxxxis a test!");
267 FILL(6); CMP("xxxxxxs a test!");
268 FILL(7); CMP("xxxxxxx a test!");
269 FILL(8); CMP("xxxxxxxxa test!");
270 FILL(9); CMP("xxxxxxxxx test!");
271 }
272
273 #define LFILL(len) memset(dest,0,sizeof(dest_aligned_block)); strcpy(dest, src); pRtlFillMemoryUlong(dest,len,val)
274
275 static void test_RtlFillMemoryUlong(void)
276 {
277 ULONG val = ('x' << 24) | ('x' << 16) | ('x' << 8) | 'x';
278 if (!pRtlFillMemoryUlong)
279 {
280 win_skip("RtlFillMemoryUlong is not available\n");
281 return;
282 }
283
284 /* Length should be in bytes and not rounded. Use strcmp to ensure we
285 * didn't write past the end (the remainder of the string should match)
286 */
287 LFILL(0); CMP("This is a test!");
288 LFILL(1); CMP("This is a test!");
289 LFILL(2); CMP("This is a test!");
290 LFILL(3); CMP("This is a test!");
291 LFILL(4); CMP("xxxx is a test!");
292 LFILL(5); CMP("xxxx is a test!");
293 LFILL(6); CMP("xxxx is a test!");
294 LFILL(7); CMP("xxxx is a test!");
295 LFILL(8); CMP("xxxxxxxxa test!");
296 LFILL(9); CMP("xxxxxxxxa test!");
297 }
298
299 #define ZERO(len) memset(dest,0,sizeof(dest_aligned_block)); strcpy(dest, src); pRtlZeroMemory(dest,len)
300 #define MCMP(str) ok(memcmp(dest,str,LEN) == 0, "Memcmp failed\n")
301
302 static void test_RtlZeroMemory(void)
303 {
304 if (!pRtlZeroMemory)
305 {
306 win_skip("RtlZeroMemory is not available\n");
307 return;
308 }
309
310 /* Length should be in bytes and not rounded. */
311 ZERO(0); MCMP("This is a test!");
312 ZERO(1); MCMP("\0his is a test!");
313 ZERO(2); MCMP("\0\0is is a test!");
314 ZERO(3); MCMP("\0\0\0s is a test!");
315 ZERO(4); MCMP("\0\0\0\0 is a test!");
316 ZERO(5); MCMP("\0\0\0\0\0is a test!");
317 ZERO(6); MCMP("\0\0\0\0\0\0s a test!");
318 ZERO(7); MCMP("\0\0\0\0\0\0\0 a test!");
319 ZERO(8); MCMP("\0\0\0\0\0\0\0\0a test!");
320 ZERO(9); MCMP("\0\0\0\0\0\0\0\0\0 test!");
321 }
322
323 static void test_RtlUlonglongByteSwap(void)
324 {
325 ULONGLONG result;
326
327 if ( !pRtlUlonglongByteSwap )
328 {
329 win_skip("RtlUlonglongByteSwap is not available\n");
330 return;
331 }
332
333 if ( pRtlUlonglongByteSwap( 0 ) != 0 )
334 {
335 win_skip("Broken RtlUlonglongByteSwap in win2k\n");
336 return;
337 }
338
339 result = pRtlUlonglongByteSwap( ((ULONGLONG)0x76543210 << 32) | 0x87654321 );
340 ok( (((ULONGLONG)0x21436587 << 32) | 0x10325476) == result,
341 "RtlUlonglongByteSwap(0x7654321087654321) returns 0x%x%08x, expected 0x2143658710325476\n",
342 (DWORD)(result >> 32), (DWORD)result);
343 }
344
345
346 static void test_RtlUniform(void)
347 {
348 ULONGLONG num;
349 ULONG seed;
350 ULONG seed_bak;
351 ULONG expected;
352 ULONG result;
353
354 if (!pRtlUniform)
355 {
356 win_skip("RtlUniform is not available\n");
357 return;
358 }
359
360 /*
361 * According to the documentation RtlUniform is using D.H. Lehmer's 1948
362 * algorithm. This algorithm is:
363 *
364 * seed = (seed * const_1 + const_2) % const_3;
365 *
366 * According to the documentation the random number is distributed over
367 * [0..MAXLONG]. Therefore const_3 is MAXLONG + 1:
368 *
369 * seed = (seed * const_1 + const_2) % (MAXLONG + 1);
370 *
371 * Because MAXLONG is 0x7fffffff (and MAXLONG + 1 is 0x80000000) the
372 * algorithm can be expressed without division as:
373 *
374 * seed = (seed * const_1 + const_2) & MAXLONG;
375 *
376 * To find out const_2 we just call RtlUniform with seed set to 0:
377 */
378 seed = 0;
379 expected = 0x7fffffc3;
380 result = pRtlUniform(&seed);
381 ok(result == expected,
382 "RtlUniform(&seed (seed == 0)) returns %x, expected %x\n",
383 result, expected);
384 /*
385 * The algorithm is now:
386 *
387 * seed = (seed * const_1 + 0x7fffffc3) & MAXLONG;
388 *
389 * To find out const_1 we can use:
390 *
391 * const_1 = RtlUniform(1) - 0x7fffffc3;
392 *
393 * If that does not work a search loop can try all possible values of
394 * const_1 and compare to the result to RtlUniform(1).
395 * This way we find out that const_1 is 0xffffffed.
396 *
397 * For seed = 1 the const_2 is 0x7fffffc4:
398 */
399 seed = 1;
400 expected = seed * 0xffffffed + 0x7fffffc3 + 1;
401 result = pRtlUniform(&seed);
402 ok(result == expected,
403 "RtlUniform(&seed (seed == 1)) returns %x, expected %x\n",
404 result, expected);
405 /*
406 * For seed = 2 the const_2 is 0x7fffffc3:
407 */
408 seed = 2;
409 expected = seed * 0xffffffed + 0x7fffffc3;
410 result = pRtlUniform(&seed);
411
412 /*
413 * Windows Vista uses different algorithms, so skip the rest of the tests
414 * until that is figured out. Trace output for the failures is about 10.5 MB!
415 */
416
417 if (result == 0x7fffff9f) {
418 skip("Most likely running on Windows Vista which uses a different algorithm\n");
419 return;
420 }
421
422 ok(result == expected,
423 "RtlUniform(&seed (seed == 2)) returns %x, expected %x\n",
424 result, expected);
425
426 /*
427 * More tests show that if seed is odd the result must be incremented by 1:
428 */
429 seed = 3;
430 expected = seed * 0xffffffed + 0x7fffffc3 + (seed & 1);
431 result = pRtlUniform(&seed);
432 ok(result == expected,
433 "RtlUniform(&seed (seed == 3)) returns %x, expected %x\n",
434 result, expected);
435
436 seed = 0x6bca1aa;
437 expected = seed * 0xffffffed + 0x7fffffc3;
438 result = pRtlUniform(&seed);
439 ok(result == expected,
440 "RtlUniform(&seed (seed == 0x6bca1aa)) returns %x, expected %x\n",
441 result, expected);
442
443 seed = 0x6bca1ab;
444 expected = seed * 0xffffffed + 0x7fffffc3 + 1;
445 result = pRtlUniform(&seed);
446 ok(result == expected,
447 "RtlUniform(&seed (seed == 0x6bca1ab)) returns %x, expected %x\n",
448 result, expected);
449 /*
450 * When seed is 0x6bca1ac there is an exception:
451 */
452 seed = 0x6bca1ac;
453 expected = seed * 0xffffffed + 0x7fffffc3 + 2;
454 result = pRtlUniform(&seed);
455 ok(result == expected,
456 "RtlUniform(&seed (seed == 0x6bca1ac)) returns %x, expected %x\n",
457 result, expected);
458 /*
459 * Note that up to here const_3 is not used
460 * (the highest bit of the result is not set).
461 *
462 * Starting with 0x6bca1ad: If seed is even the result must be incremented by 1:
463 */
464 seed = 0x6bca1ad;
465 expected = (seed * 0xffffffed + 0x7fffffc3) & MAXLONG;
466 result = pRtlUniform(&seed);
467 ok(result == expected,
468 "RtlUniform(&seed (seed == 0x6bca1ad)) returns %x, expected %x\n",
469 result, expected);
470
471 seed = 0x6bca1ae;
472 expected = (seed * 0xffffffed + 0x7fffffc3 + 1) & MAXLONG;
473 result = pRtlUniform(&seed);
474 ok(result == expected,
475 "RtlUniform(&seed (seed == 0x6bca1ae)) returns %x, expected %x\n",
476 result, expected);
477 /*
478 * There are several ranges where for odd or even seed the result must be
479 * incremented by 1. You can see this ranges in the following test.
480 *
481 * For a full test use one of the following loop heads:
482 *
483 * for (num = 0; num <= 0xffffffff; num++) {
484 * seed = num;
485 * ...
486 *
487 * seed = 0;
488 * for (num = 0; num <= 0xffffffff; num++) {
489 * ...
490 */
491 seed = 0;
492 for (num = 0; num <= 100000; num++) {
493
494 expected = seed * 0xffffffed + 0x7fffffc3;
495 if (seed < 0x6bca1ac) {
496 expected = expected + (seed & 1);
497 } else if (seed == 0x6bca1ac) {
498 expected = (expected + 2) & MAXLONG;
499 } else if (seed < 0xd79435c) {
500 expected = (expected + (~seed & 1)) & MAXLONG;
501 } else if (seed < 0x1435e50b) {
502 expected = expected + (seed & 1);
503 } else if (seed < 0x1af286ba) {
504 expected = (expected + (~seed & 1)) & MAXLONG;
505 } else if (seed < 0x21af2869) {
506 expected = expected + (seed & 1);
507 } else if (seed < 0x286bca18) {
508 expected = (expected + (~seed & 1)) & MAXLONG;
509 } else if (seed < 0x2f286bc7) {
510 expected = expected + (seed & 1);
511 } else if (seed < 0x35e50d77) {
512 expected = (expected + (~seed & 1)) & MAXLONG;
513 } else if (seed < 0x3ca1af26) {
514 expected = expected + (seed & 1);
515 } else if (seed < 0x435e50d5) {
516 expected = (expected + (~seed & 1)) & MAXLONG;
517 } else if (seed < 0x4a1af284) {
518 expected = expected + (seed & 1);
519 } else if (seed < 0x50d79433) {
520 expected = (expected + (~seed & 1)) & MAXLONG;
521 } else if (seed < 0x579435e2) {
522 expected = expected + (seed & 1);
523 } else if (seed < 0x5e50d792) {
524 expected = (expected + (~seed & 1)) & MAXLONG;
525 } else if (seed < 0x650d7941) {
526 expected = expected + (seed & 1);
527 } else if (seed < 0x6bca1af0) {
528 expected = (expected + (~seed & 1)) & MAXLONG;
529 } else if (seed < 0x7286bc9f) {
530 expected = expected + (seed & 1);
531 } else if (seed < 0x79435e4e) {
532 expected = (expected + (~seed & 1)) & MAXLONG;
533 } else if (seed < 0x7ffffffd) {
534 expected = expected + (seed & 1);
535 } else if (seed < 0x86bca1ac) {
536 expected = (expected + (~seed & 1)) & MAXLONG;
537 } else if (seed == 0x86bca1ac) {
538 expected = (expected + 1) & MAXLONG;
539 } else if (seed < 0x8d79435c) {
540 expected = expected + (seed & 1);
541 } else if (seed < 0x9435e50b) {
542 expected = (expected + (~seed & 1)) & MAXLONG;
543 } else if (seed < 0x9af286ba) {
544 expected = expected + (seed & 1);
545 } else if (seed < 0xa1af2869) {
546 expected = (expected + (~seed & 1)) & MAXLONG;
547 } else if (seed < 0xa86bca18) {
548 expected = expected + (seed & 1);
549 } else if (seed < 0xaf286bc7) {
550 expected = (expected + (~seed & 1)) & MAXLONG;
551 } else if (seed == 0xaf286bc7) {
552 expected = (expected + 2) & MAXLONG;
553 } else if (seed < 0xb5e50d77) {
554 expected = expected + (seed & 1);
555 } else if (seed < 0xbca1af26) {
556 expected = (expected + (~seed & 1)) & MAXLONG;
557 } else if (seed < 0xc35e50d5) {
558 expected = expected + (seed & 1);
559 } else if (seed < 0xca1af284) {
560 expected = (expected + (~seed & 1)) & MAXLONG;
561 } else if (seed < 0xd0d79433) {
562 expected = expected + (seed & 1);
563 } else if (seed < 0xd79435e2) {
564 expected = (expected + (~seed & 1)) & MAXLONG;
565 } else if (seed < 0xde50d792) {
566 expected = expected + (seed & 1);
567 } else if (seed < 0xe50d7941) {
568 expected = (expected + (~seed & 1)) & MAXLONG;
569 } else if (seed < 0xebca1af0) {
570 expected = expected + (seed & 1);
571 } else if (seed < 0xf286bc9f) {
572 expected = (expected + (~seed & 1)) & MAXLONG;
573 } else if (seed < 0xf9435e4e) {
574 expected = expected + (seed & 1);
575 } else if (seed < 0xfffffffd) {
576 expected = (expected + (~seed & 1)) & MAXLONG;
577 } else {
578 expected = expected + (seed & 1);
579 } /* if */
580 seed_bak = seed;
581 result = pRtlUniform(&seed);
582 ok(result == expected,
583 "test: 0x%x%08x RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
584 (DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
585 ok(seed == expected,
586 "test: 0x%x%08x RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
587 (DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
588 } /* for */
589 /*
590 * Further investigation shows: In the different regions the highest bit
591 * is set or cleared when even or odd seeds need an increment by 1.
592 * This leads to a simplified algorithm:
593 *
594 * seed = seed * 0xffffffed + 0x7fffffc3;
595 * if (seed == 0xffffffff || seed == 0x7ffffffe) {
596 * seed = (seed + 2) & MAXLONG;
597 * } else if (seed == 0x7fffffff) {
598 * seed = 0;
599 * } else if ((seed & 0x80000000) == 0) {
600 * seed = seed + (~seed & 1);
601 * } else {
602 * seed = (seed + (seed & 1)) & MAXLONG;
603 * }
604 *
605 * This is also the algorithm used for RtlUniform of wine (see dlls/ntdll/rtl.c).
606 *
607 * Now comes the funny part:
608 * It took me one weekend, to find the complicated algorithm and one day more,
609 * to find the simplified algorithm. Several weeks later I found out: The value
610 * MAXLONG (=0x7fffffff) is never returned, neither with the native function
611 * nor with the simplified algorithm. In reality the native function and our
612 * function return a random number distributed over [0..MAXLONG-1]. Note
613 * that this is different from what native documentation states [0..MAXLONG].
614 * Expressed with D.H. Lehmer's 1948 algorithm it looks like:
615 *
616 * seed = (seed * const_1 + const_2) % MAXLONG;
617 *
618 * Further investigations show that the real algorithm is:
619 *
620 * seed = (seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
621 *
622 * This is checked with the test below:
623 */
624 seed = 0;
625 for (num = 0; num <= 100000; num++) {
626 expected = (seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
627 seed_bak = seed;
628 result = pRtlUniform(&seed);
629 ok(result == expected,
630 "test: 0x%x%08x RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
631 (DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
632 ok(seed == expected,
633 "test: 0x%x%08x RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
634 (DWORD)(num >> 32), (DWORD)num, seed_bak, result, expected);
635 } /* for */
636 /*
637 * More tests show that RtlUniform does not return 0x7ffffffd for seed values
638 * in the range [0..MAXLONG-1]. Additionally 2 is returned twice. This shows
639 * that there is more than one cycle of generated randon numbers ...
640 */
641 }
642
643
644 static ULONG my_RtlRandom(PULONG seed)
645 {
646 static ULONG saved_value[128] =
647 { /* 0 */ 0x4c8bc0aa, 0x4c022957, 0x2232827a, 0x2f1e7626, 0x7f8bdafb, 0x5c37d02a, 0x0ab48f72, 0x2f0c4ffa,
648 /* 8 */ 0x290e1954, 0x6b635f23, 0x5d3885c0, 0x74b49ff8, 0x5155fa54, 0x6214ad3f, 0x111e9c29, 0x242a3a09,
649 /* 16 */ 0x75932ae1, 0x40ac432e, 0x54f7ba7a, 0x585ccbd5, 0x6df5c727, 0x0374dad1, 0x7112b3f1, 0x735fc311,
650 /* 24 */ 0x404331a9, 0x74d97781, 0x64495118, 0x323e04be, 0x5974b425, 0x4862e393, 0x62389c1d, 0x28a68b82,
651 /* 32 */ 0x0f95da37, 0x7a50bbc6, 0x09b0091c, 0x22cdb7b4, 0x4faaed26, 0x66417ccd, 0x189e4bfa, 0x1ce4e8dd,
652 /* 40 */ 0x5274c742, 0x3bdcf4dc, 0x2d94e907, 0x32eac016, 0x26d33ca3, 0x60415a8a, 0x31f57880, 0x68c8aa52,
653 /* 48 */ 0x23eb16da, 0x6204f4a1, 0x373927c1, 0x0d24eb7c, 0x06dd7379, 0x2b3be507, 0x0f9c55b1, 0x2c7925eb,
654 /* 56 */ 0x36d67c9a, 0x42f831d9, 0x5e3961cb, 0x65d637a8, 0x24bb3820, 0x4d08e33d, 0x2188754f, 0x147e409e,
655 /* 64 */ 0x6a9620a0, 0x62e26657, 0x7bd8ce81, 0x11da0abb, 0x5f9e7b50, 0x23e444b6, 0x25920c78, 0x5fc894f0,
656 /* 72 */ 0x5e338cbb, 0x404237fd, 0x1d60f80f, 0x320a1743, 0x76013d2b, 0x070294ee, 0x695e243b, 0x56b177fd,
657 /* 80 */ 0x752492e1, 0x6decd52f, 0x125f5219, 0x139d2e78, 0x1898d11e, 0x2f7ee785, 0x4db405d8, 0x1a028a35,
658 /* 88 */ 0x63f6f323, 0x1f6d0078, 0x307cfd67, 0x3f32a78a, 0x6980796c, 0x462b3d83, 0x34b639f2, 0x53fce379,
659 /* 96 */ 0x74ba50f4, 0x1abc2c4b, 0x5eeaeb8d, 0x335a7a0d, 0x3973dd20, 0x0462d66b, 0x159813ff, 0x1e4643fd,
660 /* 104 */ 0x06bc5c62, 0x3115e3fc, 0x09101613, 0x47af2515, 0x4f11ec54, 0x78b99911, 0x3db8dd44, 0x1ec10b9b,
661 /* 112 */ 0x5b5506ca, 0x773ce092, 0x567be81a, 0x5475b975, 0x7a2cde1a, 0x494536f5, 0x34737bb4, 0x76d9750b,
662 /* 120 */ 0x2a1f6232, 0x2e49644d, 0x7dddcbe7, 0x500cebdb, 0x619dab9e, 0x48c626fe, 0x1cda3193, 0x52dabe9d };
663 ULONG rand;
664 int pos;
665 ULONG result;
666
667 rand = (*seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
668 *seed = (rand * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
669 pos = *seed & 0x7f;
670 result = saved_value[pos];
671 saved_value[pos] = rand;
672 return(result);
673 }
674
675
676 static void test_RtlRandom(void)
677 {
678 ULONGLONG num;
679 ULONG seed;
680 ULONG seed_bak;
681 ULONG seed_expected;
682 ULONG result;
683 ULONG result_expected;
684
685 if (!pRtlRandom)
686 {
687 win_skip("RtlRandom is not available\n");
688 return;
689 }
690
691 /*
692 * Unlike RtlUniform, RtlRandom is not documented. We guess that for
693 * RtlRandom D.H. Lehmer's 1948 algorithm is used like stated in
694 * the documentation of the RtlUniform function. This algorithm is:
695 *
696 * seed = (seed * const_1 + const_2) % const_3;
697 *
698 * According to the RtlUniform documentation the random number is
699 * distributed over [0..MAXLONG], but in reality it is distributed
700 * over [0..MAXLONG-1]. Therefore const_3 might be MAXLONG + 1 or
701 * MAXLONG:
702 *
703 * seed = (seed * const_1 + const_2) % (MAXLONG + 1);
704 *
705 * or
706 *
707 * seed = (seed * const_1 + const_2) % MAXLONG;
708 *
709 * To find out const_2 we just call RtlRandom with seed set to 0:
710 */
711 seed = 0;
712 result_expected = 0x320a1743;
713 seed_expected =0x44b;
714 result = pRtlRandom(&seed);
715
716 /*
717 * Windows Vista uses different algorithms, so skip the rest of the tests
718 * until that is figured out. Trace output for the failures is about 10.5 MB!
719 */
720
721 if (seed == 0x3fc) {
722 skip("Most likely running on Windows Vista which uses a different algorithm\n");
723 return;
724 }
725
726 ok(result == result_expected,
727 "pRtlRandom(&seed (seed == 0)) returns %x, expected %x\n",
728 result, result_expected);
729 ok(seed == seed_expected,
730 "pRtlRandom(&seed (seed == 0)) sets seed to %x, expected %x\n",
731 seed, seed_expected);
732 /*
733 * Seed is not equal to result as with RtlUniform. To see more we
734 * call RtlRandom again with seed set to 0:
735 */
736 seed = 0;
737 result_expected = 0x7fffffc3;
738 seed_expected =0x44b;
739 result = pRtlRandom(&seed);
740 ok(result == result_expected,
741 "RtlRandom(&seed (seed == 0)) returns %x, expected %x\n",
742 result, result_expected);
743 ok(seed == seed_expected,
744 "RtlRandom(&seed (seed == 0)) sets seed to %x, expected %x\n",
745 seed, seed_expected);
746 /*
747 * Seed is set to the same value as before but the result is different.
748 * To see more we call RtlRandom again with seed set to 0:
749 */
750 seed = 0;
751 result_expected = 0x7fffffc3;
752 seed_expected =0x44b;
753 result = pRtlRandom(&seed);
754 ok(result == result_expected,
755 "RtlRandom(&seed (seed == 0)) returns %x, expected %x\n",
756 result, result_expected);
757 ok(seed == seed_expected,
758 "RtlRandom(&seed (seed == 0)) sets seed to %x, expected %x\n",
759 seed, seed_expected);
760 /*
761 * Seed is again set to the same value as before. This time we also
762 * have the same result as before. Interestingly the value of the
763 * result is 0x7fffffc3 which is the same value used in RtlUniform
764 * as const_2. If we do
765 *
766 * seed = 0;
767 * result = RtlUniform(&seed);
768 *
769 * we get the same result (0x7fffffc3) as with
770 *
771 * seed = 0;
772 * RtlRandom(&seed);
773 * seed = 0;
774 * result = RtlRandom(&seed);
775 *
776 * And there is another interesting thing. If we do
777 *
778 * seed = 0;
779 * RtlUniform(&seed);
780 * RtlUniform(&seed);
781 *
782 * seed is set to the value 0x44b which ist the same value that
783 *
784 * seed = 0;
785 * RtlRandom(&seed);
786 *
787 * assigns to seed. Putting these two findings together leads to
788 * the conclusion that RtlRandom saves the value in some variable,
789 * like in the following algorithm:
790 *
791 * result = saved_value;
792 * saved_value = RtlUniform(&seed);
793 * RtlUniform(&seed);
794 * return(result);
795 *
796 * Now we do further tests with seed set to 1:
797 */
798 seed = 1;
799 result_expected = 0x7a50bbc6;
800 seed_expected =0x5a1;
801 result = pRtlRandom(&seed);
802 ok(result == result_expected,
803 "RtlRandom(&seed (seed == 1)) returns %x, expected %x\n",
804 result, result_expected);
805 ok(seed == seed_expected,
806 "RtlRandom(&seed (seed == 1)) sets seed to %x, expected %x\n",
807 seed, seed_expected);
808 /*
809 * If there is just one saved_value the result now would be
810 * 0x7fffffc3. From this test we can see that there is more than
811 * one saved_value, like with this algorithm:
812 *
813 * result = saved_value[pos];
814 * saved_value[pos] = RtlUniform(&seed);
815 * RtlUniform(&seed);
816 * return(result);
817 *
818 * But how is the value of pos determined? The calls to RtlUniform
819 * create a sequence of random numbers. Every second random number
820 * is put into the saved_value array and is used in some later call
821 * of RtlRandom as result. The only reasonable source to determine
822 * pos are the random numbers generated by RtlUniform which are not
823 * put into the saved_value array. This are the values of seed
824 * between the two calls of RtlUniform as in this algorithm:
825 *
826 * rand = RtlUniform(&seed);
827 * RtlUniform(&seed);
828 * pos = position(seed);
829 * result = saved_value[pos];
830 * saved_value[pos] = rand;
831 * return(result);
832 *
833 * What remains to be determined is: The size of the saved_value array,
834 * the initial values of the saved_value array and the function
835 * position(seed). These tests are not shown here.
836 * The result of these tests is: The size of the saved_value array
837 * is 128, the initial values can be seen in the my_RtlRandom
838 * function and the position(seed) function is (seed & 0x7f).
839 *
840 * For a full test of RtlRandom use one of the following loop heads:
841 *
842 * for (num = 0; num <= 0xffffffff; num++) {
843 * seed = num;
844 * ...
845 *
846 * seed = 0;
847 * for (num = 0; num <= 0xffffffff; num++) {
848 * ...
849 */
850 seed = 0;
851 for (num = 0; num <= 100000; num++) {
852 seed_bak = seed;
853 seed_expected = seed;
854 result_expected = my_RtlRandom(&seed_expected);
855 /* The following corrections are necessary because the */
856 /* previous tests changed the saved_value array */
857 if (num == 0) {
858 result_expected = 0x7fffffc3;
859 } else if (num == 81) {
860 result_expected = 0x7fffffb1;
861 } /* if */
862 result = pRtlRandom(&seed);
863 ok(result == result_expected,
864 "test: 0x%x%08x RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
865 (DWORD)(num >> 32), (DWORD)num, seed_bak, result, result_expected);
866 ok(seed == seed_expected,
867 "test: 0x%x%08x RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
868 (DWORD)(num >> 32), (DWORD)num, seed_bak, result, seed_expected);
869 } /* for */
870 }
871
872
873 typedef struct {
874 ACCESS_MASK GrantedAccess;
875 ACCESS_MASK DesiredAccess;
876 BOOLEAN result;
877 } all_accesses_t;
878
879 static const all_accesses_t all_accesses[] = {
880 {0xFEDCBA76, 0xFEDCBA76, 1},
881 {0x00000000, 0xFEDCBA76, 0},
882 {0xFEDCBA76, 0x00000000, 1},
883 {0x00000000, 0x00000000, 1},
884 {0xFEDCBA76, 0xFEDCBA70, 1},
885 {0xFEDCBA70, 0xFEDCBA76, 0},
886 {0xFEDCBA76, 0xFEDC8A76, 1},
887 {0xFEDC8A76, 0xFEDCBA76, 0},
888 {0xFEDCBA76, 0xC8C4B242, 1},
889 {0xC8C4B242, 0xFEDCBA76, 0},
890 };
891 #define NB_ALL_ACCESSES (sizeof(all_accesses)/sizeof(*all_accesses))
892
893
894 static void test_RtlAreAllAccessesGranted(void)
895 {
896 unsigned int test_num;
897 BOOLEAN result;
898
899 if (!pRtlAreAllAccessesGranted)
900 {
901 win_skip("RtlAreAllAccessesGranted is not available\n");
902 return;
903 }
904
905 for (test_num = 0; test_num < NB_ALL_ACCESSES; test_num++) {
906 result = pRtlAreAllAccessesGranted(all_accesses[test_num].GrantedAccess,
907 all_accesses[test_num].DesiredAccess);
908 ok(all_accesses[test_num].result == result,
909 "(test %d): RtlAreAllAccessesGranted(%08x, %08x) returns %d, expected %d\n",
910 test_num, all_accesses[test_num].GrantedAccess,
911 all_accesses[test_num].DesiredAccess,
912 result, all_accesses[test_num].result);
913 } /* for */
914 }
915
916
917 typedef struct {
918 ACCESS_MASK GrantedAccess;
919 ACCESS_MASK DesiredAccess;
920 BOOLEAN result;
921 } any_accesses_t;
922
923 static const any_accesses_t any_accesses[] = {
924 {0xFEDCBA76, 0xFEDCBA76, 1},
925 {0x00000000, 0xFEDCBA76, 0},
926 {0xFEDCBA76, 0x00000000, 0},
927 {0x00000000, 0x00000000, 0},
928 {0xFEDCBA76, 0x01234589, 0},
929 {0x00040000, 0xFEDCBA76, 1},
930 {0x00040000, 0xFED8BA76, 0},
931 {0xFEDCBA76, 0x00040000, 1},
932 {0xFED8BA76, 0x00040000, 0},
933 };
934 #define NB_ANY_ACCESSES (sizeof(any_accesses)/sizeof(*any_accesses))
935
936
937 static void test_RtlAreAnyAccessesGranted(void)
938 {
939 unsigned int test_num;
940 BOOLEAN result;
941
942 if (!pRtlAreAnyAccessesGranted)
943 {
944 win_skip("RtlAreAnyAccessesGranted is not available\n");
945 return;
946 }
947
948 for (test_num = 0; test_num < NB_ANY_ACCESSES; test_num++) {
949 result = pRtlAreAnyAccessesGranted(any_accesses[test_num].GrantedAccess,
950 any_accesses[test_num].DesiredAccess);
951 ok(any_accesses[test_num].result == result,
952 "(test %d): RtlAreAnyAccessesGranted(%08x, %08x) returns %d, expected %d\n",
953 test_num, any_accesses[test_num].GrantedAccess,
954 any_accesses[test_num].DesiredAccess,
955 result, any_accesses[test_num].result);
956 } /* for */
957 }
958
959 static void test_RtlComputeCrc32(void)
960 {
961 DWORD crc = 0;
962
963 if (!pRtlComputeCrc32)
964 {
965 win_skip("RtlComputeCrc32 is not available\n");
966 return;
967 }
968
969 crc = pRtlComputeCrc32(crc, (const BYTE *)src, LEN);
970 ok(crc == 0x40861dc2,"Expected 0x40861dc2, got %8x\n", crc);
971 }
972
973
974 typedef struct MY_HANDLE
975 {
976 RTL_HANDLE RtlHandle;
977 void * MyValue;
978 } MY_HANDLE;
979
980 static inline void RtlpMakeHandleAllocated(RTL_HANDLE * Handle)
981 {
982 ULONG_PTR *AllocatedBit = (ULONG_PTR *)(&Handle->Next);
983 *AllocatedBit = *AllocatedBit | 1;
984 }
985
986 static void test_HandleTables(void)
987 {
988 BOOLEAN result;
989 NTSTATUS status;
990 ULONG Index;
991 MY_HANDLE * MyHandle;
992 RTL_HANDLE_TABLE HandleTable;
993
994 if (!pRtlInitializeHandleTable)
995 {
996 win_skip("RtlInitializeHandleTable is not available\n");
997 return;
998 }
999
1000 pRtlInitializeHandleTable(0x3FFF, sizeof(MY_HANDLE), &HandleTable);
1001 MyHandle = (MY_HANDLE *)pRtlAllocateHandle(&HandleTable, &Index);
1002 ok(MyHandle != NULL, "RtlAllocateHandle failed\n");
1003 RtlpMakeHandleAllocated(&MyHandle->RtlHandle);
1004 MyHandle = NULL;
1005 result = pRtlIsValidIndexHandle(&HandleTable, Index, (RTL_HANDLE **)&MyHandle);
1006 ok(result, "Handle %p wasn't valid\n", MyHandle);
1007 result = pRtlFreeHandle(&HandleTable, &MyHandle->RtlHandle);
1008 ok(result, "Couldn't free handle %p\n", MyHandle);
1009 status = pRtlDestroyHandleTable(&HandleTable);
1010 ok(status == STATUS_SUCCESS, "RtlDestroyHandleTable failed with error 0x%08x\n", status);
1011 }
1012
1013 static void test_RtlAllocateAndInitializeSid(void)
1014 {
1015 NTSTATUS ret;
1016 SID_IDENTIFIER_AUTHORITY sia = {{ 1, 2, 3, 4, 5, 6 }};
1017 PSID psid;
1018
1019 if (!pRtlAllocateAndInitializeSid)
1020 {
1021 win_skip("RtlAllocateAndInitializeSid is not available\n");
1022 return;
1023 }
1024
1025 ret = pRtlAllocateAndInitializeSid(&sia, 0, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
1026 ok(!ret, "RtlAllocateAndInitializeSid error %08x\n", ret);
1027 ret = pRtlFreeSid(psid);
1028 ok(!ret, "RtlFreeSid error %08x\n", ret);
1029
1030 /* these tests crash on XP */
1031 if (0)
1032 {
1033 pRtlAllocateAndInitializeSid(NULL, 0, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
1034 pRtlAllocateAndInitializeSid(&sia, 0, 1, 2, 3, 4, 5, 6, 7, 8, NULL);
1035 }
1036
1037 ret = pRtlAllocateAndInitializeSid(&sia, 9, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
1038 ok(ret == STATUS_INVALID_SID, "wrong error %08x\n", ret);
1039 }
1040
1041 static void test_RtlDeleteTimer(void)
1042 {
1043 NTSTATUS ret;
1044
1045 if (!pRtlDeleteTimer)
1046 {
1047 win_skip("RtlDeleteTimer is not available\n");
1048 return;
1049 }
1050
1051 ret = pRtlDeleteTimer(NULL, NULL, NULL);
1052 ok(ret == STATUS_INVALID_PARAMETER_1 ||
1053 ret == STATUS_INVALID_PARAMETER, /* W2K */
1054 "expected STATUS_INVALID_PARAMETER_1 or STATUS_INVALID_PARAMETER, got %x\n", ret);
1055 }
1056
1057 static void test_RtlThreadErrorMode(void)
1058 {
1059 DWORD oldmode;
1060 BOOL is_wow64;
1061 DWORD mode;
1062 NTSTATUS status;
1063
1064 if (!pRtlGetThreadErrorMode || !pRtlSetThreadErrorMode)
1065 {
1066 win_skip("RtlGetThreadErrorMode and/or RtlSetThreadErrorMode not available\n");
1067 return;
1068 }
1069
1070 if (!pIsWow64Process || !pIsWow64Process(GetCurrentProcess(), &is_wow64))
1071 is_wow64 = FALSE;
1072
1073 oldmode = pRtlGetThreadErrorMode();
1074
1075 status = pRtlSetThreadErrorMode(0x70, &mode);
1076 ok(status == STATUS_SUCCESS ||
1077 status == STATUS_WAIT_1, /* Vista */
1078 "RtlSetThreadErrorMode failed with error 0x%08x\n", status);
1079 ok(mode == oldmode,
1080 "RtlSetThreadErrorMode returned mode 0x%x, expected 0x%x\n",
1081 mode, oldmode);
1082 ok(pRtlGetThreadErrorMode() == 0x70,
1083 "RtlGetThreadErrorMode returned 0x%x, expected 0x%x\n", mode, 0x70);
1084 if (!is_wow64 && pNtCurrentTeb)
1085 ok(pNtCurrentTeb()->HardErrorDisabled == 0x70,
1086 "The TEB contains 0x%x, expected 0x%x\n",
1087 pNtCurrentTeb()->HardErrorDisabled, 0x70);
1088
1089 status = pRtlSetThreadErrorMode(0, &mode);
1090 ok(status == STATUS_SUCCESS ||
1091 status == STATUS_WAIT_1, /* Vista */
1092 "RtlSetThreadErrorMode failed with error 0x%08x\n", status);
1093 ok(mode == 0x70,
1094 "RtlSetThreadErrorMode returned mode 0x%x, expected 0x%x\n",
1095 mode, 0x70);
1096 ok(pRtlGetThreadErrorMode() == 0,
1097 "RtlGetThreadErrorMode returned 0x%x, expected 0x%x\n", mode, 0);
1098 if (!is_wow64 && pNtCurrentTeb)
1099 ok(pNtCurrentTeb()->HardErrorDisabled == 0,
1100 "The TEB contains 0x%x, expected 0x%x\n",
1101 pNtCurrentTeb()->HardErrorDisabled, 0);
1102
1103 for (mode = 1; mode; mode <<= 1)
1104 {
1105 status = pRtlSetThreadErrorMode(mode, NULL);
1106 if (mode & 0x70)
1107 ok(status == STATUS_SUCCESS ||
1108 status == STATUS_WAIT_1, /* Vista */
1109 "RtlSetThreadErrorMode(%x,NULL) failed with error 0x%08x\n",
1110 mode, status);
1111 else
1112 ok(status == STATUS_INVALID_PARAMETER_1,
1113 "RtlSetThreadErrorMode(%x,NULL) returns 0x%08x, "
1114 "expected STATUS_INVALID_PARAMETER_1\n",
1115 mode, status);
1116 }
1117
1118 pRtlSetThreadErrorMode(oldmode, NULL);
1119 }
1120
1121 static void test_LdrProcessRelocationBlock(void)
1122 {
1123 IMAGE_BASE_RELOCATION *ret;
1124 USHORT reloc;
1125 DWORD addr32;
1126 SHORT addr16;
1127
1128 if(!pLdrProcessRelocationBlock) {
1129 win_skip("LdrProcessRelocationBlock not available\n");
1130 return;
1131 }
1132
1133 addr32 = 0x50005;
1134 reloc = IMAGE_REL_BASED_HIGHLOW<<12;
1135 ret = pLdrProcessRelocationBlock(&addr32, 1, &reloc, 0x500050);
1136 ok((USHORT*)ret == &reloc+1, "ret = %p, expected %p\n", ret, &reloc+1);
1137 ok(addr32 == 0x550055, "addr32 = %x, expected 0x550055\n", addr32);
1138
1139 addr16 = 0x505;
1140 reloc = IMAGE_REL_BASED_HIGH<<12;
1141 ret = pLdrProcessRelocationBlock(&addr16, 1, &reloc, 0x500060);
1142 ok((USHORT*)ret == &reloc+1, "ret = %p, expected %p\n", ret, &reloc+1);
1143 ok(addr16 == 0x555, "addr16 = %x, expected 0x555\n", addr16);
1144
1145 addr16 = 0x505;
1146 reloc = IMAGE_REL_BASED_LOW<<12;
1147 ret = pLdrProcessRelocationBlock(&addr16, 1, &reloc, 0x500060);
1148 ok((USHORT*)ret == &reloc+1, "ret = %p, expected %p\n", ret, &reloc+1);
1149 ok(addr16 == 0x565, "addr16 = %x, expected 0x565\n", addr16);
1150 }
1151
1152 static void test_RtlIpv4AddressToString(void)
1153 {
1154 CHAR buffer[20];
1155 CHAR *res;
1156 IN_ADDR ip;
1157 DWORD len;
1158
1159 if (!pRtlIpv4AddressToStringA)
1160 {
1161 win_skip("RtlIpv4AddressToStringA not available\n");
1162 return;
1163 }
1164
1165 ip.S_un.S_un_b.s_b1 = 1;
1166 ip.S_un.S_un_b.s_b2 = 2;
1167 ip.S_un.S_un_b.s_b3 = 3;
1168 ip.S_un.S_un_b.s_b4 = 4;
1169
1170 memset(buffer, '#', sizeof(buffer) - 1);
1171 buffer[sizeof(buffer) -1] = 0;
1172 res = pRtlIpv4AddressToStringA(&ip, buffer);
1173 len = strlen(buffer);
1174 ok(res == (buffer + len), "got %p with '%s' (expected %p)\n", res, buffer, buffer + len);
1175
1176 if (0) {
1177 /* this crashes in windows */
1178 res = pRtlIpv4AddressToStringA(&ip, NULL);
1179 ok( (res == (char *)~0) ||
1180 broken(res == (char *)0 + len), /* XP and w2003 */
1181 "got %p (expected ~0)\n", res);
1182 }
1183
1184 if (0) {
1185 /* this crashes in windows */
1186 memset(buffer, '#', sizeof(buffer) - 1);
1187 buffer[sizeof(buffer) -1] = 0;
1188 res = pRtlIpv4AddressToStringA(NULL, buffer);
1189 trace("got %p with '%s'\n", res, buffer);
1190 }
1191
1192 if (0) {
1193 /* this crashes in windows */
1194 res = pRtlIpv4AddressToStringA(NULL, NULL);
1195 trace("got %p\n", res);
1196 }
1197 }
1198
1199 static void test_RtlIpv4AddressToStringEx(void)
1200 {
1201 CHAR ip_1234[] = "1.2.3.4";
1202 CHAR ip_1234_80[] = "1.2.3.4:80";
1203 LPSTR expect;
1204 CHAR buffer[30];
1205 NTSTATUS res;
1206 IN_ADDR ip;
1207 ULONG size;
1208 DWORD used;
1209 USHORT port;
1210
1211 if (!pRtlIpv4AddressToStringExA)
1212 {
1213 win_skip("RtlIpv4AddressToStringExA not available\n");
1214 return;
1215 }
1216
1217 ip.S_un.S_un_b.s_b1 = 1;
1218 ip.S_un.S_un_b.s_b2 = 2;
1219 ip.S_un.S_un_b.s_b3 = 3;
1220 ip.S_un.S_un_b.s_b4 = 4;
1221
1222 port = htons(80);
1223 expect = ip_1234_80;
1224
1225 size = sizeof(buffer);
1226 memset(buffer, '#', sizeof(buffer) - 1);
1227 buffer[sizeof(buffer) -1] = 0;
1228 res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1229 used = strlen(buffer);
1230 ok( (res == STATUS_SUCCESS) &&
1231 (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1232 "got 0x%x and size %d with '%s'\n", res, size, buffer);
1233
1234 size = used + 1;
1235 memset(buffer, '#', sizeof(buffer) - 1);
1236 buffer[sizeof(buffer) -1] = 0;
1237 res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1238 ok( (res == STATUS_SUCCESS) &&
1239 (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1240 "got 0x%x and size %d with '%s'\n", res, size, buffer);
1241
1242 size = used;
1243 memset(buffer, '#', sizeof(buffer) - 1);
1244 buffer[sizeof(buffer) -1] = 0;
1245 res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1246 ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1247 "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1248 res, size, buffer, used + 1);
1249
1250 size = used - 1;
1251 memset(buffer, '#', sizeof(buffer) - 1);
1252 buffer[sizeof(buffer) -1] = 0;
1253 res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1254 ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1255 "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1256 res, size, buffer, used + 1);
1257
1258
1259 /* to get only the ip, use 0 as port */
1260 port = 0;
1261 expect = ip_1234;
1262
1263 size = sizeof(buffer);
1264 memset(buffer, '#', sizeof(buffer) - 1);
1265 buffer[sizeof(buffer) -1] = 0;
1266 res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1267 used = strlen(buffer);
1268 ok( (res == STATUS_SUCCESS) &&
1269 (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1270 "got 0x%x and size %d with '%s'\n", res, size, buffer);
1271
1272 size = used + 1;
1273 memset(buffer, '#', sizeof(buffer) - 1);
1274 buffer[sizeof(buffer) -1] = 0;
1275 res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1276 ok( (res == STATUS_SUCCESS) &&
1277 (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1278 "got 0x%x and size %d with '%s'\n", res, size, buffer);
1279
1280 size = used;
1281 memset(buffer, '#', sizeof(buffer) - 1);
1282 buffer[sizeof(buffer) -1] = 0;
1283 res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1284 ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1285 "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1286 res, size, buffer, used + 1);
1287
1288 size = used - 1;
1289 memset(buffer, '#', sizeof(buffer) - 1);
1290 buffer[sizeof(buffer) -1] = 0;
1291 res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1292 ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1293 "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1294 res, size, buffer, used + 1);
1295
1296
1297 /* parameters are checked */
1298 memset(buffer, '#', sizeof(buffer) - 1);
1299 buffer[sizeof(buffer) -1] = 0;
1300 res = pRtlIpv4AddressToStringExA(&ip, 0, buffer, NULL);
1301 ok(res == STATUS_INVALID_PARAMETER,
1302 "got 0x%x with '%s' (expected STATUS_INVALID_PARAMETER)\n", res, buffer);
1303
1304 size = sizeof(buffer);
1305 res = pRtlIpv4AddressToStringExA(&ip, 0, NULL, &size);
1306 ok( res == STATUS_INVALID_PARAMETER,
1307 "got 0x%x and size %d (expected STATUS_INVALID_PARAMETER)\n", res, size);
1308
1309 size = sizeof(buffer);
1310 memset(buffer, '#', sizeof(buffer) - 1);
1311 buffer[sizeof(buffer) -1] = 0;
1312 res = pRtlIpv4AddressToStringExA(NULL, 0, buffer, &size);
1313 ok( res == STATUS_INVALID_PARAMETER,
1314 "got 0x%x and size %d with '%s' (expected STATUS_INVALID_PARAMETER)\n",
1315 res, size, buffer);
1316 }
1317
1318
1319 START_TEST(rtl)
1320 {
1321 InitFunctionPtrs();
1322
1323 test_RtlCompareMemory();
1324 test_RtlCompareMemoryUlong();
1325 test_RtlMoveMemory();
1326 test_RtlFillMemory();
1327 test_RtlFillMemoryUlong();
1328 test_RtlZeroMemory();
1329 test_RtlUlonglongByteSwap();
1330 test_RtlUniform();
1331 test_RtlRandom();
1332 test_RtlAreAllAccessesGranted();
1333 test_RtlAreAnyAccessesGranted();
1334 test_RtlComputeCrc32();
1335 test_HandleTables();
1336 test_RtlAllocateAndInitializeSid();
1337 test_RtlDeleteTimer();
1338 test_RtlThreadErrorMode();
1339 test_LdrProcessRelocationBlock();
1340 test_RtlIpv4AddressToString();
1341 test_RtlIpv4AddressToStringEx();
1342 }