ntdll: Omit unused typedef in test_query_process_basic.
[wine] / dlls / ntdll / tests / 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_PTR 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     res = pRtlIpv4AddressToStringA(&ip, NULL);
1177     ok( (res == (char *)~0) ||
1178         broken(res == (char *)len),        /* XP and w2003 */
1179         "got %p (expected ~0)\n", res);
1180
1181     if (0) {
1182         /* this crashes in windows */
1183         memset(buffer, '#', sizeof(buffer) - 1);
1184         buffer[sizeof(buffer) -1] = 0;
1185         res = pRtlIpv4AddressToStringA(NULL, buffer);
1186         trace("got %p with '%s'\n", res, buffer);
1187     }
1188
1189     if (0) {
1190         /* this crashes in windows */
1191         res = pRtlIpv4AddressToStringA(NULL, NULL);
1192         trace("got %p\n", res);
1193     }
1194 }
1195
1196 static void test_RtlIpv4AddressToStringEx(void)
1197 {
1198     CHAR ip_1234[] = "1.2.3.4";
1199     CHAR ip_1234_80[] = "1.2.3.4:80";
1200     LPSTR expect;
1201     CHAR buffer[30];
1202     NTSTATUS res;
1203     IN_ADDR ip;
1204     ULONG size;
1205     DWORD used;
1206     USHORT port;
1207
1208     if (!pRtlIpv4AddressToStringExA)
1209     {
1210         win_skip("RtlIpv4AddressToStringExA not available\n");
1211         return;
1212     }
1213
1214     ip.S_un.S_un_b.s_b1 = 1;
1215     ip.S_un.S_un_b.s_b2 = 2;
1216     ip.S_un.S_un_b.s_b3 = 3;
1217     ip.S_un.S_un_b.s_b4 = 4;
1218
1219     port = htons(80);
1220     expect = ip_1234_80;
1221
1222     size = sizeof(buffer);
1223     memset(buffer, '#', sizeof(buffer) - 1);
1224     buffer[sizeof(buffer) -1] = 0;
1225     res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1226     used = strlen(buffer);
1227     ok( (res == STATUS_SUCCESS) &&
1228         (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1229         "got 0x%x and size %d with '%s'\n", res, size, buffer);
1230
1231     size = used + 1;
1232     memset(buffer, '#', sizeof(buffer) - 1);
1233     buffer[sizeof(buffer) -1] = 0;
1234     res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1235     ok( (res == STATUS_SUCCESS) &&
1236         (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1237         "got 0x%x and size %d with '%s'\n", res, size, buffer);
1238
1239     size = used;
1240     memset(buffer, '#', sizeof(buffer) - 1);
1241     buffer[sizeof(buffer) -1] = 0;
1242     res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1243     ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1244         "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1245         res, size, buffer, used + 1);
1246
1247     size = used - 1;
1248     memset(buffer, '#', sizeof(buffer) - 1);
1249     buffer[sizeof(buffer) -1] = 0;
1250     res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1251     ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1252         "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1253         res, size, buffer, used + 1);
1254
1255
1256     /* to get only the ip, use 0 as port */
1257     port = 0;
1258     expect = ip_1234;
1259
1260     size = sizeof(buffer);
1261     memset(buffer, '#', sizeof(buffer) - 1);
1262     buffer[sizeof(buffer) -1] = 0;
1263     res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1264     used = strlen(buffer);
1265     ok( (res == STATUS_SUCCESS) &&
1266         (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1267         "got 0x%x and size %d with '%s'\n", res, size, buffer);
1268
1269     size = used + 1;
1270     memset(buffer, '#', sizeof(buffer) - 1);
1271     buffer[sizeof(buffer) -1] = 0;
1272     res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1273     ok( (res == STATUS_SUCCESS) &&
1274         (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1275         "got 0x%x and size %d with '%s'\n", res, size, buffer);
1276
1277     size = used;
1278     memset(buffer, '#', sizeof(buffer) - 1);
1279     buffer[sizeof(buffer) -1] = 0;
1280     res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1281     ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1282         "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1283         res, size, buffer, used + 1);
1284
1285     size = used - 1;
1286     memset(buffer, '#', sizeof(buffer) - 1);
1287     buffer[sizeof(buffer) -1] = 0;
1288     res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1289     ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1290         "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1291         res, size, buffer, used + 1);
1292
1293
1294     /* parameters are checked */
1295     memset(buffer, '#', sizeof(buffer) - 1);
1296     buffer[sizeof(buffer) -1] = 0;
1297     res = pRtlIpv4AddressToStringExA(&ip, 0, buffer, NULL);
1298     ok(res == STATUS_INVALID_PARAMETER,
1299         "got 0x%x with '%s' (expected STATUS_INVALID_PARAMETER)\n", res, buffer);
1300
1301     size = sizeof(buffer);
1302     res = pRtlIpv4AddressToStringExA(&ip, 0, NULL, &size);
1303     ok( res == STATUS_INVALID_PARAMETER,
1304         "got 0x%x and size %d (expected STATUS_INVALID_PARAMETER)\n", res, size);
1305
1306     size = sizeof(buffer);
1307     memset(buffer, '#', sizeof(buffer) - 1);
1308     buffer[sizeof(buffer) -1] = 0;
1309     res = pRtlIpv4AddressToStringExA(NULL, 0, buffer, &size);
1310     ok( res == STATUS_INVALID_PARAMETER,
1311         "got 0x%x and size %d with '%s' (expected STATUS_INVALID_PARAMETER)\n",
1312         res, size, buffer);
1313 }
1314
1315
1316 START_TEST(rtl)
1317 {
1318     InitFunctionPtrs();
1319
1320     test_RtlCompareMemory();
1321     test_RtlCompareMemoryUlong();
1322     test_RtlMoveMemory();
1323     test_RtlFillMemory();
1324     test_RtlFillMemoryUlong();
1325     test_RtlZeroMemory();
1326     test_RtlUlonglongByteSwap();
1327     test_RtlUniform();
1328     test_RtlRandom();
1329     test_RtlAreAllAccessesGranted();
1330     test_RtlAreAnyAccessesGranted();
1331     test_RtlComputeCrc32();
1332     test_HandleTables();
1333     test_RtlAllocateAndInitializeSid();
1334     test_RtlDeleteTimer();
1335     test_RtlThreadErrorMode();
1336     test_LdrProcessRelocationBlock();
1337     test_RtlIpv4AddressToString();
1338     test_RtlIpv4AddressToStringEx();
1339 }