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