ReactOS  0.4.13-dev-257-gfabbd7c
rtl.c
Go to the documentation of this file.
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 #include "in6addr.h"
29 #include "initguid.h"
30 #define COBJMACROS
31 #ifdef __REACTOS__
32 #include <objbase.h>
33 #endif
34 #include "shobjidl.h"
35 
36 #ifndef __WINE_WINTERNL_H
37 
38 typedef struct _RTL_HANDLE
39 {
40  struct _RTL_HANDLE * Next;
41 } RTL_HANDLE;
42 
43 typedef struct _RTL_HANDLE_TABLE
44 {
53 
54 #endif
55 
56 /* avoid #include <winsock2.h> */
57 #undef htons
58 #ifdef WORDS_BIGENDIAN
59 #define htons(s) ((USHORT)(s))
60 #else /* WORDS_BIGENDIAN */
62 {
63  return (s >> 8) | (s << 8);
64 }
65 #define htons(s) __my_ushort_swap(s)
66 #endif /* WORDS_BIGENDIAN */
67 
68 
69 
70 /* Function ptrs for ntdll calls */
71 static HMODULE hntdll = 0;
72 static SIZE_T (WINAPI *pRtlCompareMemory)(LPCVOID,LPCVOID,SIZE_T);
73 static SIZE_T (WINAPI *pRtlCompareMemoryUlong)(PULONG, SIZE_T, ULONG);
74 static NTSTATUS (WINAPI *pRtlDeleteTimer)(HANDLE, HANDLE, HANDLE);
75 static VOID (WINAPI *pRtlMoveMemory)(LPVOID,LPCVOID,SIZE_T);
76 static VOID (WINAPI *pRtlFillMemory)(LPVOID,SIZE_T,BYTE);
77 static VOID (WINAPI *pRtlFillMemoryUlong)(LPVOID,SIZE_T,ULONG);
78 static VOID (WINAPI *pRtlZeroMemory)(LPVOID,SIZE_T);
79 static ULONGLONG (WINAPIV *pRtlUlonglongByteSwap)(ULONGLONG source);
80 static ULONG (WINAPI *pRtlUniform)(PULONG);
81 static ULONG (WINAPI *pRtlRandom)(PULONG);
82 static BOOLEAN (WINAPI *pRtlAreAllAccessesGranted)(ACCESS_MASK, ACCESS_MASK);
83 static BOOLEAN (WINAPI *pRtlAreAnyAccessesGranted)(ACCESS_MASK, ACCESS_MASK);
84 static DWORD (WINAPI *pRtlComputeCrc32)(DWORD,const BYTE*,INT);
85 static void (WINAPI * pRtlInitializeHandleTable)(ULONG, ULONG, RTL_HANDLE_TABLE *);
86 static BOOLEAN (WINAPI * pRtlIsValidIndexHandle)(const RTL_HANDLE_TABLE *, ULONG, RTL_HANDLE **);
87 static NTSTATUS (WINAPI * pRtlDestroyHandleTable)(RTL_HANDLE_TABLE *);
89 static BOOLEAN (WINAPI * pRtlFreeHandle)(RTL_HANDLE_TABLE *, RTL_HANDLE *);
91 static NTSTATUS (WINAPI *pRtlFreeSid)(PSID);
92 static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
93 static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD);
95 static CHAR * (WINAPI *pRtlIpv4AddressToStringA)(const IN_ADDR *, LPSTR);
96 static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG);
97 static NTSTATUS (WINAPI *pRtlIpv4StringToAddressA)(PCSTR, BOOLEAN, PCSTR *, IN_ADDR *);
98 static NTSTATUS (WINAPI *pRtlIpv4StringToAddressExA)(PCSTR, BOOLEAN, IN_ADDR *, PUSHORT);
99 static CHAR * (WINAPI *pRtlIpv6AddressToStringA)(struct in6_addr *, PSTR);
100 static NTSTATUS (WINAPI *pRtlIpv6AddressToStringExA)(struct in6_addr *, ULONG, USHORT, PCHAR, PULONG);
101 static NTSTATUS (WINAPI *pRtlIpv6StringToAddressA)(PCSTR, PCSTR *, struct in6_addr *);
102 static NTSTATUS (WINAPI *pRtlIpv6StringToAddressW)(PCWSTR, PCWSTR *, struct in6_addr *);
103 static NTSTATUS (WINAPI *pRtlIpv6StringToAddressExA)(PCSTR, struct in6_addr *, PULONG, PUSHORT);
104 static NTSTATUS (WINAPI *pRtlIpv6StringToAddressExW)(PCWSTR, struct in6_addr *, PULONG, PUSHORT);
105 static NTSTATUS (WINAPI *pLdrAddRefDll)(ULONG, HMODULE);
106 static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG*, ULONG_PTR*);
107 static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR);
108 static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD);
109 static NTSTATUS (WINAPI *pRtlGetCompressionWorkSpaceSize)(USHORT, PULONG, PULONG);
110 static NTSTATUS (WINAPI *pRtlDecompressBuffer)(USHORT, PUCHAR, ULONG, const UCHAR*, ULONG, PULONG);
111 static NTSTATUS (WINAPI *pRtlDecompressFragment)(USHORT, PUCHAR, ULONG, const UCHAR*, ULONG, ULONG, PULONG, PVOID);
112 static NTSTATUS (WINAPI *pRtlCompressBuffer)(USHORT, const UCHAR*, ULONG, PUCHAR, ULONG, ULONG, PULONG, PVOID);
113 static BOOL (WINAPI *pRtlIsCriticalSectionLocked)(CRITICAL_SECTION *);
114 static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION *);
115 static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG);
116 static NTSTATUS (WINAPI *pLdrEnumerateLoadedModules)(void *, void *, void *);
117 static NTSTATUS (WINAPI *pRtlQueryPackageIdentity)(HANDLE, WCHAR*, SIZE_T*, WCHAR*, SIZE_T*, BOOLEAN*);
119 static NTSTATUS (WINAPI *pRtlAbsoluteToSelfRelativeSD)(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR,PULONG);
120 static NTSTATUS (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **);
121 static NTSTATUS (WINAPI *pLdrUnregisterDllNotification)(void *);
122 
123 static HMODULE hkernel32 = 0;
124 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
125 
126 
127 #define LEN 16
128 static const char* src_src = "This is a test!"; /* 16 bytes long, incl NUL */
129 static WCHAR ws2_32dllW[] = {'w','s','2','_','3','2','.','d','l','l',0};
130 static WCHAR wintrustdllW[] = {'w','i','n','t','r','u','s','t','.','d','l','l',0};
131 static WCHAR crypt32dllW[] = {'c','r','y','p','t','3','2','.','d','l','l',0};
134 static const char *src = (const char*)src_aligned_block;
135 static char* dest = (char*)dest_aligned_block;
136 
137 static void InitFunctionPtrs(void)
138 {
139  hntdll = LoadLibraryA("ntdll.dll");
140  ok(hntdll != 0, "LoadLibrary failed\n");
141  if (hntdll) {
142  pRtlCompareMemory = (void *)GetProcAddress(hntdll, "RtlCompareMemory");
143  pRtlCompareMemoryUlong = (void *)GetProcAddress(hntdll, "RtlCompareMemoryUlong");
144  pRtlDeleteTimer = (void *)GetProcAddress(hntdll, "RtlDeleteTimer");
145  pRtlMoveMemory = (void *)GetProcAddress(hntdll, "RtlMoveMemory");
146  pRtlFillMemory = (void *)GetProcAddress(hntdll, "RtlFillMemory");
147  pRtlFillMemoryUlong = (void *)GetProcAddress(hntdll, "RtlFillMemoryUlong");
148  pRtlZeroMemory = (void *)GetProcAddress(hntdll, "RtlZeroMemory");
149  pRtlUlonglongByteSwap = (void *)GetProcAddress(hntdll, "RtlUlonglongByteSwap");
150  pRtlUniform = (void *)GetProcAddress(hntdll, "RtlUniform");
151  pRtlRandom = (void *)GetProcAddress(hntdll, "RtlRandom");
152  pRtlAreAllAccessesGranted = (void *)GetProcAddress(hntdll, "RtlAreAllAccessesGranted");
153  pRtlAreAnyAccessesGranted = (void *)GetProcAddress(hntdll, "RtlAreAnyAccessesGranted");
154  pRtlComputeCrc32 = (void *)GetProcAddress(hntdll, "RtlComputeCrc32");
155  pRtlInitializeHandleTable = (void *)GetProcAddress(hntdll, "RtlInitializeHandleTable");
156  pRtlIsValidIndexHandle = (void *)GetProcAddress(hntdll, "RtlIsValidIndexHandle");
157  pRtlDestroyHandleTable = (void *)GetProcAddress(hntdll, "RtlDestroyHandleTable");
158  pRtlAllocateHandle = (void *)GetProcAddress(hntdll, "RtlAllocateHandle");
159  pRtlFreeHandle = (void *)GetProcAddress(hntdll, "RtlFreeHandle");
160  pRtlAllocateAndInitializeSid = (void *)GetProcAddress(hntdll, "RtlAllocateAndInitializeSid");
161  pRtlFreeSid = (void *)GetProcAddress(hntdll, "RtlFreeSid");
162  pRtlGetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlGetThreadErrorMode");
163  pRtlSetThreadErrorMode = (void *)GetProcAddress(hntdll, "RtlSetThreadErrorMode");
164  pLdrProcessRelocationBlock = (void *)GetProcAddress(hntdll, "LdrProcessRelocationBlock");
165  pRtlIpv4AddressToStringA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringA");
166  pRtlIpv4AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv4AddressToStringExA");
167  pRtlIpv4StringToAddressA = (void *)GetProcAddress(hntdll, "RtlIpv4StringToAddressA");
168  pRtlIpv4StringToAddressExA = (void *)GetProcAddress(hntdll, "RtlIpv4StringToAddressExA");
169  pRtlIpv6AddressToStringA = (void *)GetProcAddress(hntdll, "RtlIpv6AddressToStringA");
170  pRtlIpv6AddressToStringExA = (void *)GetProcAddress(hntdll, "RtlIpv6AddressToStringExA");
171  pRtlIpv6StringToAddressA = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressA");
172  pRtlIpv6StringToAddressW = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressW");
173  pRtlIpv6StringToAddressExA = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressExA");
174  pRtlIpv6StringToAddressExW = (void *)GetProcAddress(hntdll, "RtlIpv6StringToAddressExW");
175  pLdrAddRefDll = (void *)GetProcAddress(hntdll, "LdrAddRefDll");
176  pLdrLockLoaderLock = (void *)GetProcAddress(hntdll, "LdrLockLoaderLock");
177  pLdrUnlockLoaderLock = (void *)GetProcAddress(hntdll, "LdrUnlockLoaderLock");
178  pRtlMultiByteToUnicodeN = (void *)GetProcAddress(hntdll, "RtlMultiByteToUnicodeN");
179  pRtlGetCompressionWorkSpaceSize = (void *)GetProcAddress(hntdll, "RtlGetCompressionWorkSpaceSize");
180  pRtlDecompressBuffer = (void *)GetProcAddress(hntdll, "RtlDecompressBuffer");
181  pRtlDecompressFragment = (void *)GetProcAddress(hntdll, "RtlDecompressFragment");
182  pRtlCompressBuffer = (void *)GetProcAddress(hntdll, "RtlCompressBuffer");
183  pRtlIsCriticalSectionLocked = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLocked");
184  pRtlIsCriticalSectionLockedByThread = (void *)GetProcAddress(hntdll, "RtlIsCriticalSectionLockedByThread");
185  pRtlInitializeCriticalSectionEx = (void *)GetProcAddress(hntdll, "RtlInitializeCriticalSectionEx");
186  pLdrEnumerateLoadedModules = (void *)GetProcAddress(hntdll, "LdrEnumerateLoadedModules");
187  pRtlQueryPackageIdentity = (void *)GetProcAddress(hntdll, "RtlQueryPackageIdentity");
188  pRtlMakeSelfRelativeSD = (void *)GetProcAddress(hntdll, "RtlMakeSelfRelativeSD");
189  pRtlAbsoluteToSelfRelativeSD = (void *)GetProcAddress(hntdll, "RtlAbsoluteToSelfRelativeSD");
190  pLdrRegisterDllNotification = (void *)GetProcAddress(hntdll, "LdrRegisterDllNotification");
191  pLdrUnregisterDllNotification = (void *)GetProcAddress(hntdll, "LdrUnregisterDllNotification");
192  }
193  hkernel32 = LoadLibraryA("kernel32.dll");
194  ok(hkernel32 != 0, "LoadLibrary failed\n");
195  if (hkernel32) {
196  pIsWow64Process = (void *)GetProcAddress(hkernel32, "IsWow64Process");
197  }
199  ok(strlen(src) == 15, "Source must be 16 bytes long!\n");
200 }
201 
202 #define COMP(str1,str2,cmplen,len) size = pRtlCompareMemory(str1, str2, cmplen); \
203  ok(size == len, "Expected %ld, got %ld\n", size, (SIZE_T)len)
204 
205 static void test_RtlCompareMemory(void)
206 {
207  SIZE_T size;
208 
209  if (!pRtlCompareMemory)
210  {
211  win_skip("RtlCompareMemory is not available\n");
212  return;
213  }
214 
215  strcpy(dest, src);
216 
217  COMP(src,src,0,0);
218  COMP(src,src,LEN,LEN);
219  dest[0] = 'x';
220  COMP(src,dest,LEN,0);
221 }
222 
223 static void test_RtlCompareMemoryUlong(void)
224 {
225  ULONG a[10];
226  ULONG result;
227 
228  if (!pRtlCompareMemoryUlong)
229  {
230  win_skip("RtlCompareMemoryUlong is not available\n");
231  return;
232  }
233 
234  a[0]= 0x0123;
235  a[1]= 0x4567;
236  a[2]= 0x89ab;
237  a[3]= 0xcdef;
238  result = pRtlCompareMemoryUlong(a, 0, 0x0123);
239  ok(result == 0, "RtlCompareMemoryUlong(%p, 0, 0x0123) returns %u, expected 0\n", a, result);
240  result = pRtlCompareMemoryUlong(a, 3, 0x0123);
241  ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %u, expected 0\n", a, result);
242  result = pRtlCompareMemoryUlong(a, 4, 0x0123);
243  ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %u, expected 4\n", a, result);
244  result = pRtlCompareMemoryUlong(a, 5, 0x0123);
245  ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %u, expected 4\n", a, result);
246  result = pRtlCompareMemoryUlong(a, 7, 0x0123);
247  ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %u, expected 4\n", a, result);
248  result = pRtlCompareMemoryUlong(a, 8, 0x0123);
249  ok(result == 4, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %u, expected 4\n", a, result);
250  result = pRtlCompareMemoryUlong(a, 9, 0x0123);
251  ok(result == 4, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %u, expected 4\n", a, result);
252  result = pRtlCompareMemoryUlong(a, 4, 0x0127);
253  ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x0127) returns %u, expected 0\n", a, result);
254  result = pRtlCompareMemoryUlong(a, 4, 0x7123);
255  ok(result == 0, "RtlCompareMemoryUlong(%p, 4, 0x7123) returns %u, expected 0\n", a, result);
256  result = pRtlCompareMemoryUlong(a, 16, 0x4567);
257  ok(result == 0, "RtlCompareMemoryUlong(%p, 16, 0x4567) returns %u, expected 0\n", a, result);
258 
259  a[1]= 0x0123;
260  result = pRtlCompareMemoryUlong(a, 3, 0x0123);
261  ok(result == 0, "RtlCompareMemoryUlong(%p, 3, 0x0123) returns %u, expected 0\n", a, result);
262  result = pRtlCompareMemoryUlong(a, 4, 0x0123);
263  ok(result == 4, "RtlCompareMemoryUlong(%p, 4, 0x0123) returns %u, expected 4\n", a, result);
264  result = pRtlCompareMemoryUlong(a, 5, 0x0123);
265  ok(result == 4, "RtlCompareMemoryUlong(%p, 5, 0x0123) returns %u, expected 4\n", a, result);
266  result = pRtlCompareMemoryUlong(a, 7, 0x0123);
267  ok(result == 4, "RtlCompareMemoryUlong(%p, 7, 0x0123) returns %u, expected 4\n", a, result);
268  result = pRtlCompareMemoryUlong(a, 8, 0x0123);
269  ok(result == 8, "RtlCompareMemoryUlong(%p, 8, 0x0123) returns %u, expected 8\n", a, result);
270  result = pRtlCompareMemoryUlong(a, 9, 0x0123);
271  ok(result == 8, "RtlCompareMemoryUlong(%p, 9, 0x0123) returns %u, expected 8\n", a, result);
272 }
273 
274 #define COPY(len) memset(dest,0,sizeof(dest_aligned_block)); pRtlMoveMemory(dest, src, len)
275 #define CMP(str) ok(strcmp(dest,str) == 0, "Expected '%s', got '%s'\n", str, dest)
276 
277 static void test_RtlMoveMemory(void)
278 {
279  if (!pRtlMoveMemory)
280  {
281  win_skip("RtlMoveMemory is not available\n");
282  return;
283  }
284 
285  /* Length should be in bytes and not rounded. Use strcmp to ensure we
286  * didn't write past the end (it checks for the final NUL left by memset)
287  */
288  COPY(0); CMP("");
289  COPY(1); CMP("T");
290  COPY(2); CMP("Th");
291  COPY(3); CMP("Thi");
292  COPY(4); CMP("This");
293  COPY(5); CMP("This ");
294  COPY(6); CMP("This i");
295  COPY(7); CMP("This is");
296  COPY(8); CMP("This is ");
297  COPY(9); CMP("This is a");
298 
299  /* Overlapping */
300  strcpy(dest, src); pRtlMoveMemory(dest, dest + 1, strlen(src) - 1);
301  CMP("his is a test!!");
302  strcpy(dest, src); pRtlMoveMemory(dest + 1, dest, strlen(src));
303  CMP("TThis is a test!");
304 }
305 
306 #define FILL(len) memset(dest,0,sizeof(dest_aligned_block)); strcpy(dest, src); pRtlFillMemory(dest,len,'x')
307 
308 static void test_RtlFillMemory(void)
309 {
310  if (!pRtlFillMemory)
311  {
312  win_skip("RtlFillMemory is not available\n");
313  return;
314  }
315 
316  /* Length should be in bytes and not rounded. Use strcmp to ensure we
317  * didn't write past the end (the remainder of the string should match)
318  */
319  FILL(0); CMP("This is a test!");
320  FILL(1); CMP("xhis is a test!");
321  FILL(2); CMP("xxis is a test!");
322  FILL(3); CMP("xxxs is a test!");
323  FILL(4); CMP("xxxx is a test!");
324  FILL(5); CMP("xxxxxis a test!");
325  FILL(6); CMP("xxxxxxs a test!");
326  FILL(7); CMP("xxxxxxx a test!");
327  FILL(8); CMP("xxxxxxxxa test!");
328  FILL(9); CMP("xxxxxxxxx test!");
329 }
330 
331 #define LFILL(len) memset(dest,0,sizeof(dest_aligned_block)); strcpy(dest, src); pRtlFillMemoryUlong(dest,len,val)
332 
333 static void test_RtlFillMemoryUlong(void)
334 {
335  ULONG val = ('x' << 24) | ('x' << 16) | ('x' << 8) | 'x';
336  if (!pRtlFillMemoryUlong)
337  {
338  win_skip("RtlFillMemoryUlong is not available\n");
339  return;
340  }
341 
342  /* Length should be in bytes and not rounded. Use strcmp to ensure we
343  * didn't write past the end (the remainder of the string should match)
344  */
345  LFILL(0); CMP("This is a test!");
346  LFILL(1); CMP("This is a test!");
347  LFILL(2); CMP("This is a test!");
348  LFILL(3); CMP("This is a test!");
349  LFILL(4); CMP("xxxx is a test!");
350  LFILL(5); CMP("xxxx is a test!");
351  LFILL(6); CMP("xxxx is a test!");
352  LFILL(7); CMP("xxxx is a test!");
353  LFILL(8); CMP("xxxxxxxxa test!");
354  LFILL(9); CMP("xxxxxxxxa test!");
355 }
356 
357 #define ZERO(len) memset(dest,0,sizeof(dest_aligned_block)); strcpy(dest, src); pRtlZeroMemory(dest,len)
358 #define MCMP(str) ok(memcmp(dest,str,LEN) == 0, "Memcmp failed\n")
359 
360 static void test_RtlZeroMemory(void)
361 {
362  if (!pRtlZeroMemory)
363  {
364  win_skip("RtlZeroMemory is not available\n");
365  return;
366  }
367 
368  /* Length should be in bytes and not rounded. */
369  ZERO(0); MCMP("This is a test!");
370  ZERO(1); MCMP("\0his is a test!");
371  ZERO(2); MCMP("\0\0is is a test!");
372  ZERO(3); MCMP("\0\0\0s is a test!");
373  ZERO(4); MCMP("\0\0\0\0 is a test!");
374  ZERO(5); MCMP("\0\0\0\0\0is a test!");
375  ZERO(6); MCMP("\0\0\0\0\0\0s a test!");
376  ZERO(7); MCMP("\0\0\0\0\0\0\0 a test!");
377  ZERO(8); MCMP("\0\0\0\0\0\0\0\0a test!");
378  ZERO(9); MCMP("\0\0\0\0\0\0\0\0\0 test!");
379 }
380 
381 static void test_RtlUlonglongByteSwap(void)
382 {
384 
385  if ( !pRtlUlonglongByteSwap )
386  {
387  win_skip("RtlUlonglongByteSwap is not available\n");
388  return;
389  }
390 
391  if ( pRtlUlonglongByteSwap( 0 ) != 0 )
392  {
393  win_skip("Broken RtlUlonglongByteSwap in win2k\n");
394  return;
395  }
396 
397  result = pRtlUlonglongByteSwap( ((ULONGLONG)0x76543210 << 32) | 0x87654321 );
398  ok( (((ULONGLONG)0x21436587 << 32) | 0x10325476) == result,
399  "RtlUlonglongByteSwap(0x7654321087654321) returns 0x%s, expected 0x2143658710325476\n",
401 }
402 
403 
404 static void test_RtlUniform(void)
405 {
406  ULONGLONG num;
407  ULONG seed;
408  ULONG seed_bak;
409  ULONG expected;
410  ULONG result;
411 
412  if (!pRtlUniform)
413  {
414  win_skip("RtlUniform is not available\n");
415  return;
416  }
417 
418 /*
419  * According to the documentation RtlUniform is using D.H. Lehmer's 1948
420  * algorithm. This algorithm is:
421  *
422  * seed = (seed * const_1 + const_2) % const_3;
423  *
424  * According to the documentation the random number is distributed over
425  * [0..MAXLONG]. Therefore const_3 is MAXLONG + 1:
426  *
427  * seed = (seed * const_1 + const_2) % (MAXLONG + 1);
428  *
429  * Because MAXLONG is 0x7fffffff (and MAXLONG + 1 is 0x80000000) the
430  * algorithm can be expressed without division as:
431  *
432  * seed = (seed * const_1 + const_2) & MAXLONG;
433  *
434  * To find out const_2 we just call RtlUniform with seed set to 0:
435  */
436  seed = 0;
437  expected = 0x7fffffc3;
438  result = pRtlUniform(&seed);
439  ok(result == expected,
440  "RtlUniform(&seed (seed == 0)) returns %x, expected %x\n",
441  result, expected);
442 /*
443  * The algorithm is now:
444  *
445  * seed = (seed * const_1 + 0x7fffffc3) & MAXLONG;
446  *
447  * To find out const_1 we can use:
448  *
449  * const_1 = RtlUniform(1) - 0x7fffffc3;
450  *
451  * If that does not work a search loop can try all possible values of
452  * const_1 and compare to the result to RtlUniform(1).
453  * This way we find out that const_1 is 0xffffffed.
454  *
455  * For seed = 1 the const_2 is 0x7fffffc4:
456  */
457  seed = 1;
458  expected = seed * 0xffffffed + 0x7fffffc3 + 1;
459  result = pRtlUniform(&seed);
460  ok(result == expected,
461  "RtlUniform(&seed (seed == 1)) returns %x, expected %x\n",
462  result, expected);
463 /*
464  * For seed = 2 the const_2 is 0x7fffffc3:
465  */
466  seed = 2;
467  expected = seed * 0xffffffed + 0x7fffffc3;
468  result = pRtlUniform(&seed);
469 
470 /*
471  * Windows Vista uses different algorithms, so skip the rest of the tests
472  * until that is figured out. Trace output for the failures is about 10.5 MB!
473  */
474 
475  if (result == 0x7fffff9f) {
476  skip("Most likely running on Windows Vista which uses a different algorithm\n");
477  return;
478  }
479 
480  ok(result == expected,
481  "RtlUniform(&seed (seed == 2)) returns %x, expected %x\n",
482  result, expected);
483 
484 /*
485  * More tests show that if seed is odd the result must be incremented by 1:
486  */
487  seed = 3;
488  expected = seed * 0xffffffed + 0x7fffffc3 + (seed & 1);
489  result = pRtlUniform(&seed);
490  ok(result == expected,
491  "RtlUniform(&seed (seed == 3)) returns %x, expected %x\n",
492  result, expected);
493 
494  seed = 0x6bca1aa;
495  expected = seed * 0xffffffed + 0x7fffffc3;
496  result = pRtlUniform(&seed);
497  ok(result == expected,
498  "RtlUniform(&seed (seed == 0x6bca1aa)) returns %x, expected %x\n",
499  result, expected);
500 
501  seed = 0x6bca1ab;
502  expected = seed * 0xffffffed + 0x7fffffc3 + 1;
503  result = pRtlUniform(&seed);
504  ok(result == expected,
505  "RtlUniform(&seed (seed == 0x6bca1ab)) returns %x, expected %x\n",
506  result, expected);
507 /*
508  * When seed is 0x6bca1ac there is an exception:
509  */
510  seed = 0x6bca1ac;
511  expected = seed * 0xffffffed + 0x7fffffc3 + 2;
512  result = pRtlUniform(&seed);
513  ok(result == expected,
514  "RtlUniform(&seed (seed == 0x6bca1ac)) returns %x, expected %x\n",
515  result, expected);
516 /*
517  * Note that up to here const_3 is not used
518  * (the highest bit of the result is not set).
519  *
520  * Starting with 0x6bca1ad: If seed is even the result must be incremented by 1:
521  */
522  seed = 0x6bca1ad;
523  expected = (seed * 0xffffffed + 0x7fffffc3) & MAXLONG;
524  result = pRtlUniform(&seed);
525  ok(result == expected,
526  "RtlUniform(&seed (seed == 0x6bca1ad)) returns %x, expected %x\n",
527  result, expected);
528 
529  seed = 0x6bca1ae;
530  expected = (seed * 0xffffffed + 0x7fffffc3 + 1) & MAXLONG;
531  result = pRtlUniform(&seed);
532  ok(result == expected,
533  "RtlUniform(&seed (seed == 0x6bca1ae)) returns %x, expected %x\n",
534  result, expected);
535 /*
536  * There are several ranges where for odd or even seed the result must be
537  * incremented by 1. You can see this ranges in the following test.
538  *
539  * For a full test use one of the following loop heads:
540  *
541  * for (num = 0; num <= 0xffffffff; num++) {
542  * seed = num;
543  * ...
544  *
545  * seed = 0;
546  * for (num = 0; num <= 0xffffffff; num++) {
547  * ...
548  */
549  seed = 0;
550  for (num = 0; num <= 100000; num++) {
551 
552  expected = seed * 0xffffffed + 0x7fffffc3;
553  if (seed < 0x6bca1ac) {
554  expected = expected + (seed & 1);
555  } else if (seed == 0x6bca1ac) {
556  expected = (expected + 2) & MAXLONG;
557  } else if (seed < 0xd79435c) {
558  expected = (expected + (~seed & 1)) & MAXLONG;
559  } else if (seed < 0x1435e50b) {
560  expected = expected + (seed & 1);
561  } else if (seed < 0x1af286ba) {
562  expected = (expected + (~seed & 1)) & MAXLONG;
563  } else if (seed < 0x21af2869) {
564  expected = expected + (seed & 1);
565  } else if (seed < 0x286bca18) {
566  expected = (expected + (~seed & 1)) & MAXLONG;
567  } else if (seed < 0x2f286bc7) {
568  expected = expected + (seed & 1);
569  } else if (seed < 0x35e50d77) {
570  expected = (expected + (~seed & 1)) & MAXLONG;
571  } else if (seed < 0x3ca1af26) {
572  expected = expected + (seed & 1);
573  } else if (seed < 0x435e50d5) {
574  expected = (expected + (~seed & 1)) & MAXLONG;
575  } else if (seed < 0x4a1af284) {
576  expected = expected + (seed & 1);
577  } else if (seed < 0x50d79433) {
578  expected = (expected + (~seed & 1)) & MAXLONG;
579  } else if (seed < 0x579435e2) {
580  expected = expected + (seed & 1);
581  } else if (seed < 0x5e50d792) {
582  expected = (expected + (~seed & 1)) & MAXLONG;
583  } else if (seed < 0x650d7941) {
584  expected = expected + (seed & 1);
585  } else if (seed < 0x6bca1af0) {
586  expected = (expected + (~seed & 1)) & MAXLONG;
587  } else if (seed < 0x7286bc9f) {
588  expected = expected + (seed & 1);
589  } else if (seed < 0x79435e4e) {
590  expected = (expected + (~seed & 1)) & MAXLONG;
591  } else if (seed < 0x7ffffffd) {
592  expected = expected + (seed & 1);
593  } else if (seed < 0x86bca1ac) {
594  expected = (expected + (~seed & 1)) & MAXLONG;
595  } else if (seed == 0x86bca1ac) {
596  expected = (expected + 1) & MAXLONG;
597  } else if (seed < 0x8d79435c) {
598  expected = expected + (seed & 1);
599  } else if (seed < 0x9435e50b) {
600  expected = (expected + (~seed & 1)) & MAXLONG;
601  } else if (seed < 0x9af286ba) {
602  expected = expected + (seed & 1);
603  } else if (seed < 0xa1af2869) {
604  expected = (expected + (~seed & 1)) & MAXLONG;
605  } else if (seed < 0xa86bca18) {
606  expected = expected + (seed & 1);
607  } else if (seed < 0xaf286bc7) {
608  expected = (expected + (~seed & 1)) & MAXLONG;
609  } else if (seed == 0xaf286bc7) {
610  expected = (expected + 2) & MAXLONG;
611  } else if (seed < 0xb5e50d77) {
612  expected = expected + (seed & 1);
613  } else if (seed < 0xbca1af26) {
614  expected = (expected + (~seed & 1)) & MAXLONG;
615  } else if (seed < 0xc35e50d5) {
616  expected = expected + (seed & 1);
617  } else if (seed < 0xca1af284) {
618  expected = (expected + (~seed & 1)) & MAXLONG;
619  } else if (seed < 0xd0d79433) {
620  expected = expected + (seed & 1);
621  } else if (seed < 0xd79435e2) {
622  expected = (expected + (~seed & 1)) & MAXLONG;
623  } else if (seed < 0xde50d792) {
624  expected = expected + (seed & 1);
625  } else if (seed < 0xe50d7941) {
626  expected = (expected + (~seed & 1)) & MAXLONG;
627  } else if (seed < 0xebca1af0) {
628  expected = expected + (seed & 1);
629  } else if (seed < 0xf286bc9f) {
630  expected = (expected + (~seed & 1)) & MAXLONG;
631  } else if (seed < 0xf9435e4e) {
632  expected = expected + (seed & 1);
633  } else if (seed < 0xfffffffd) {
634  expected = (expected + (~seed & 1)) & MAXLONG;
635  } else {
636  expected = expected + (seed & 1);
637  } /* if */
638  seed_bak = seed;
639  result = pRtlUniform(&seed);
640  ok(result == expected,
641  "test: 0x%s RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
642  wine_dbgstr_longlong(num), seed_bak, result, expected);
643  ok(seed == expected,
644  "test: 0x%s RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
645  wine_dbgstr_longlong(num), seed_bak, result, expected);
646  } /* for */
647 /*
648  * Further investigation shows: In the different regions the highest bit
649  * is set or cleared when even or odd seeds need an increment by 1.
650  * This leads to a simplified algorithm:
651  *
652  * seed = seed * 0xffffffed + 0x7fffffc3;
653  * if (seed == 0xffffffff || seed == 0x7ffffffe) {
654  * seed = (seed + 2) & MAXLONG;
655  * } else if (seed == 0x7fffffff) {
656  * seed = 0;
657  * } else if ((seed & 0x80000000) == 0) {
658  * seed = seed + (~seed & 1);
659  * } else {
660  * seed = (seed + (seed & 1)) & MAXLONG;
661  * }
662  *
663  * This is also the algorithm used for RtlUniform of wine (see dlls/ntdll/rtl.c).
664  *
665  * Now comes the funny part:
666  * It took me one weekend, to find the complicated algorithm and one day more,
667  * to find the simplified algorithm. Several weeks later I found out: The value
668  * MAXLONG (=0x7fffffff) is never returned, neither with the native function
669  * nor with the simplified algorithm. In reality the native function and our
670  * function return a random number distributed over [0..MAXLONG-1]. Note
671  * that this is different from what native documentation states [0..MAXLONG].
672  * Expressed with D.H. Lehmer's 1948 algorithm it looks like:
673  *
674  * seed = (seed * const_1 + const_2) % MAXLONG;
675  *
676  * Further investigations show that the real algorithm is:
677  *
678  * seed = (seed * 0x7fffffed + 0x7fffffc3) % MAXLONG;
679  *
680  * This is checked with the test below:
681  */
682  seed = 0;
683  for (num = 0; num <= 100000; num++) {
684  expected = (seed * 0x7fffffed + 0x7fffffc3) % 0x7fffffff;
685  seed_bak = seed;
686  result = pRtlUniform(&seed);
687  ok(result == expected,
688  "test: 0x%s RtlUniform(&seed (seed == %x)) returns %x, expected %x\n",
689  wine_dbgstr_longlong(num), seed_bak, result, expected);
690  ok(seed == expected,
691  "test: 0x%s RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
692  wine_dbgstr_longlong(num), seed_bak, result, expected);
693  } /* for */
694 /*
695  * More tests show that RtlUniform does not return 0x7ffffffd for seed values
696  * in the range [0..MAXLONG-1]. Additionally 2 is returned twice. This shows
697  * that there is more than one cycle of generated randon numbers ...
698  */
699 }
700 
701 
702 static void test_RtlRandom(void)
703 {
704  int i, j;
705  ULONG seed;
706  ULONG res[512];
707 
708  if (!pRtlRandom)
709  {
710  win_skip("RtlRandom is not available\n");
711  return;
712  }
713 
714  seed = 0;
715  for (i = 0; i < sizeof(res) / sizeof(res[0]); i++)
716  {
717  res[i] = pRtlRandom(&seed);
718  ok(seed != res[i], "%i: seed is same as res %x\n", i, seed);
719  for (j = 0; j < i; j++)
720  ok(res[i] != res[j], "res[%i] (%x) is same as res[%i] (%x)\n", j, res[j], i, res[i]);
721  }
722 }
723 
724 
725 typedef struct {
730 
731 static const all_accesses_t all_accesses[] = {
732  {0xFEDCBA76, 0xFEDCBA76, 1},
733  {0x00000000, 0xFEDCBA76, 0},
734  {0xFEDCBA76, 0x00000000, 1},
735  {0x00000000, 0x00000000, 1},
736  {0xFEDCBA76, 0xFEDCBA70, 1},
737  {0xFEDCBA70, 0xFEDCBA76, 0},
738  {0xFEDCBA76, 0xFEDC8A76, 1},
739  {0xFEDC8A76, 0xFEDCBA76, 0},
740  {0xFEDCBA76, 0xC8C4B242, 1},
741  {0xC8C4B242, 0xFEDCBA76, 0},
742 };
743 #define NB_ALL_ACCESSES (sizeof(all_accesses)/sizeof(*all_accesses))
744 
745 
747 {
748  unsigned int test_num;
749  BOOLEAN result;
750 
751  if (!pRtlAreAllAccessesGranted)
752  {
753  win_skip("RtlAreAllAccessesGranted is not available\n");
754  return;
755  }
756 
757  for (test_num = 0; test_num < NB_ALL_ACCESSES; test_num++) {
758  result = pRtlAreAllAccessesGranted(all_accesses[test_num].GrantedAccess,
759  all_accesses[test_num].DesiredAccess);
760  ok(all_accesses[test_num].result == result,
761  "(test %d): RtlAreAllAccessesGranted(%08x, %08x) returns %d, expected %d\n",
762  test_num, all_accesses[test_num].GrantedAccess,
763  all_accesses[test_num].DesiredAccess,
764  result, all_accesses[test_num].result);
765  } /* for */
766 }
767 
768 
769 typedef struct {
774 
775 static const any_accesses_t any_accesses[] = {
776  {0xFEDCBA76, 0xFEDCBA76, 1},
777  {0x00000000, 0xFEDCBA76, 0},
778  {0xFEDCBA76, 0x00000000, 0},
779  {0x00000000, 0x00000000, 0},
780  {0xFEDCBA76, 0x01234589, 0},
781  {0x00040000, 0xFEDCBA76, 1},
782  {0x00040000, 0xFED8BA76, 0},
783  {0xFEDCBA76, 0x00040000, 1},
784  {0xFED8BA76, 0x00040000, 0},
785 };
786 #define NB_ANY_ACCESSES (sizeof(any_accesses)/sizeof(*any_accesses))
787 
788 
790 {
791  unsigned int test_num;
792  BOOLEAN result;
793 
794  if (!pRtlAreAnyAccessesGranted)
795  {
796  win_skip("RtlAreAnyAccessesGranted is not available\n");
797  return;
798  }
799 
800  for (test_num = 0; test_num < NB_ANY_ACCESSES; test_num++) {
801  result = pRtlAreAnyAccessesGranted(any_accesses[test_num].GrantedAccess,
802  any_accesses[test_num].DesiredAccess);
803  ok(any_accesses[test_num].result == result,
804  "(test %d): RtlAreAnyAccessesGranted(%08x, %08x) returns %d, expected %d\n",
805  test_num, any_accesses[test_num].GrantedAccess,
806  any_accesses[test_num].DesiredAccess,
807  result, any_accesses[test_num].result);
808  } /* for */
809 }
810 
811 static void test_RtlComputeCrc32(void)
812 {
813  DWORD crc = 0;
814 
815  if (!pRtlComputeCrc32)
816  {
817  win_skip("RtlComputeCrc32 is not available\n");
818  return;
819  }
820 
821  crc = pRtlComputeCrc32(crc, (const BYTE *)src, LEN);
822  ok(crc == 0x40861dc2,"Expected 0x40861dc2, got %8x\n", crc);
823 }
824 
825 
826 typedef struct MY_HANDLE
827 {
829  void * MyValue;
830 } MY_HANDLE;
831 
833 {
834  ULONG_PTR *AllocatedBit = (ULONG_PTR *)(&Handle->Next);
835  *AllocatedBit = *AllocatedBit | 1;
836 }
837 
838 static void test_HandleTables(void)
839 {
840  BOOLEAN result;
842  ULONG Index;
843  MY_HANDLE * MyHandle;
845 
846  if (!pRtlInitializeHandleTable)
847  {
848  win_skip("RtlInitializeHandleTable is not available\n");
849  return;
850  }
851 
852  pRtlInitializeHandleTable(0x3FFF, sizeof(MY_HANDLE), &HandleTable);
853  MyHandle = (MY_HANDLE *)pRtlAllocateHandle(&HandleTable, &Index);
854  ok(MyHandle != NULL, "RtlAllocateHandle failed\n");
856  MyHandle = NULL;
857  result = pRtlIsValidIndexHandle(&HandleTable, Index, (RTL_HANDLE **)&MyHandle);
858  ok(result, "Handle %p wasn't valid\n", MyHandle);
859  result = pRtlFreeHandle(&HandleTable, &MyHandle->RtlHandle);
860  ok(result, "Couldn't free handle %p\n", MyHandle);
861  status = pRtlDestroyHandleTable(&HandleTable);
862  ok(status == STATUS_SUCCESS, "RtlDestroyHandleTable failed with error 0x%08x\n", status);
863 }
864 
866 {
867  NTSTATUS ret;
868  SID_IDENTIFIER_AUTHORITY sia = {{ 1, 2, 3, 4, 5, 6 }};
869  PSID psid;
870 
871  if (!pRtlAllocateAndInitializeSid)
872  {
873  win_skip("RtlAllocateAndInitializeSid is not available\n");
874  return;
875  }
876 
877  ret = pRtlAllocateAndInitializeSid(&sia, 0, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
878  ok(!ret, "RtlAllocateAndInitializeSid error %08x\n", ret);
879  ret = pRtlFreeSid(psid);
880  ok(!ret, "RtlFreeSid error %08x\n", ret);
881 
882  /* these tests crash on XP */
883  if (0)
884  {
885  pRtlAllocateAndInitializeSid(NULL, 0, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
886  pRtlAllocateAndInitializeSid(&sia, 0, 1, 2, 3, 4, 5, 6, 7, 8, NULL);
887  }
888 
889  ret = pRtlAllocateAndInitializeSid(&sia, 9, 1, 2, 3, 4, 5, 6, 7, 8, &psid);
890  ok(ret == STATUS_INVALID_SID, "wrong error %08x\n", ret);
891 }
892 
893 static void test_RtlDeleteTimer(void)
894 {
895  NTSTATUS ret;
896 
897  if (!pRtlDeleteTimer)
898  {
899  win_skip("RtlDeleteTimer is not available\n");
900  return;
901  }
902 
903  ret = pRtlDeleteTimer(NULL, NULL, NULL);
905  ret == STATUS_INVALID_PARAMETER, /* W2K */
906  "expected STATUS_INVALID_PARAMETER_1 or STATUS_INVALID_PARAMETER, got %x\n", ret);
907 }
908 
909 static void test_RtlThreadErrorMode(void)
910 {
911  DWORD oldmode;
912  BOOL is_wow64;
913  DWORD mode;
915 
916  if (!pRtlGetThreadErrorMode || !pRtlSetThreadErrorMode)
917  {
918  win_skip("RtlGetThreadErrorMode and/or RtlSetThreadErrorMode not available\n");
919  return;
920  }
921 
922  if (!pIsWow64Process || !pIsWow64Process(GetCurrentProcess(), &is_wow64))
923  is_wow64 = FALSE;
924 
925  oldmode = pRtlGetThreadErrorMode();
926 
927  status = pRtlSetThreadErrorMode(0x70, &mode);
928  ok(status == STATUS_SUCCESS ||
929  status == STATUS_WAIT_1, /* Vista */
930  "RtlSetThreadErrorMode failed with error 0x%08x\n", status);
931  ok(mode == oldmode,
932  "RtlSetThreadErrorMode returned mode 0x%x, expected 0x%x\n",
933  mode, oldmode);
934  ok(pRtlGetThreadErrorMode() == 0x70,
935  "RtlGetThreadErrorMode returned 0x%x, expected 0x%x\n", mode, 0x70);
936  if (!is_wow64)
937  {
938  ok(NtCurrentTeb()->HardErrorDisabled == 0x70,
939  "The TEB contains 0x%x, expected 0x%x\n",
940  NtCurrentTeb()->HardErrorDisabled, 0x70);
941  }
942 
943  status = pRtlSetThreadErrorMode(0, &mode);
944  ok(status == STATUS_SUCCESS ||
945  status == STATUS_WAIT_1, /* Vista */
946  "RtlSetThreadErrorMode failed with error 0x%08x\n", status);
947  ok(mode == 0x70,
948  "RtlSetThreadErrorMode returned mode 0x%x, expected 0x%x\n",
949  mode, 0x70);
950  ok(pRtlGetThreadErrorMode() == 0,
951  "RtlGetThreadErrorMode returned 0x%x, expected 0x%x\n", mode, 0);
952  if (!is_wow64)
953  {
954  ok(NtCurrentTeb()->HardErrorDisabled == 0,
955  "The TEB contains 0x%x, expected 0x%x\n",
956  NtCurrentTeb()->HardErrorDisabled, 0);
957  }
958 
959  for (mode = 1; mode; mode <<= 1)
960  {
961  status = pRtlSetThreadErrorMode(mode, NULL);
962  if (mode & 0x70)
963  ok(status == STATUS_SUCCESS ||
964  status == STATUS_WAIT_1, /* Vista */
965  "RtlSetThreadErrorMode(%x,NULL) failed with error 0x%08x\n",
966  mode, status);
967  else
969  "RtlSetThreadErrorMode(%x,NULL) returns 0x%08x, "
970  "expected STATUS_INVALID_PARAMETER_1\n",
971  mode, status);
972  }
973 
974  pRtlSetThreadErrorMode(oldmode, NULL);
975 }
976 
978 {
980  USHORT reloc;
981  DWORD addr32;
982  SHORT addr16;
983 
985  win_skip("LdrProcessRelocationBlock not available\n");
986  return;
987  }
988 
989  addr32 = 0x50005;
990  reloc = IMAGE_REL_BASED_HIGHLOW<<12;
991  ret = pLdrProcessRelocationBlock(&addr32, 1, &reloc, 0x500050);
992  ok((USHORT*)ret == &reloc+1, "ret = %p, expected %p\n", ret, &reloc+1);
993  ok(addr32 == 0x550055, "addr32 = %x, expected 0x550055\n", addr32);
994 
995  addr16 = 0x505;
996  reloc = IMAGE_REL_BASED_HIGH<<12;
997  ret = pLdrProcessRelocationBlock(&addr16, 1, &reloc, 0x500060);
998  ok((USHORT*)ret == &reloc+1, "ret = %p, expected %p\n", ret, &reloc+1);
999  ok(addr16 == 0x555, "addr16 = %x, expected 0x555\n", addr16);
1000 
1001  addr16 = 0x505;
1002  reloc = IMAGE_REL_BASED_LOW<<12;
1003  ret = pLdrProcessRelocationBlock(&addr16, 1, &reloc, 0x500060);
1004  ok((USHORT*)ret == &reloc+1, "ret = %p, expected %p\n", ret, &reloc+1);
1005  ok(addr16 == 0x565, "addr16 = %x, expected 0x565\n", addr16);
1006 }
1007 
1009 {
1010  CHAR buffer[20];
1011  CHAR *res;
1012  IN_ADDR ip;
1013  DWORD_PTR len;
1014 
1016  {
1017  win_skip("RtlIpv4AddressToStringA not available\n");
1018  return;
1019  }
1020 
1021  ip.S_un.S_un_b.s_b1 = 1;
1022  ip.S_un.S_un_b.s_b2 = 2;
1023  ip.S_un.S_un_b.s_b3 = 3;
1024  ip.S_un.S_un_b.s_b4 = 4;
1025 
1026  memset(buffer, '#', sizeof(buffer) - 1);
1027  buffer[sizeof(buffer) -1] = 0;
1029  len = strlen(buffer);
1030  ok(res == (buffer + len), "got %p with '%s' (expected %p)\n", res, buffer, buffer + len);
1031 
1033  ok( (res == (char *)~0) ||
1034  broken(res == (char *)len), /* XP and w2003 */
1035  "got %p (expected ~0)\n", res);
1036 
1037  if (0) {
1038  /* this crashes in windows */
1039  memset(buffer, '#', sizeof(buffer) - 1);
1040  buffer[sizeof(buffer) -1] = 0;
1042  trace("got %p with '%s'\n", res, buffer);
1043  }
1044 
1045  if (0) {
1046  /* this crashes in windows */
1048  trace("got %p\n", res);
1049  }
1050 }
1051 
1053 {
1054  CHAR ip_1234[] = "1.2.3.4";
1055  CHAR ip_1234_80[] = "1.2.3.4:80";
1056  LPSTR expect;
1057  CHAR buffer[30];
1058  NTSTATUS res;
1059  IN_ADDR ip;
1060  ULONG size;
1061  DWORD used;
1062  USHORT port;
1063 
1064  if (!pRtlIpv4AddressToStringExA)
1065  {
1066  win_skip("RtlIpv4AddressToStringExA not available\n");
1067  return;
1068  }
1069 
1070  ip.S_un.S_un_b.s_b1 = 1;
1071  ip.S_un.S_un_b.s_b2 = 2;
1072  ip.S_un.S_un_b.s_b3 = 3;
1073  ip.S_un.S_un_b.s_b4 = 4;
1074 
1075  port = htons(80);
1076  expect = ip_1234_80;
1077 
1078  size = sizeof(buffer);
1079  memset(buffer, '#', sizeof(buffer) - 1);
1080  buffer[sizeof(buffer) -1] = 0;
1081  res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1082  used = strlen(buffer);
1083  ok( (res == STATUS_SUCCESS) &&
1084  (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1085  "got 0x%x and size %d with '%s'\n", res, size, buffer);
1086 
1087  size = used + 1;
1088  memset(buffer, '#', sizeof(buffer) - 1);
1089  buffer[sizeof(buffer) -1] = 0;
1090  res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1091  ok( (res == STATUS_SUCCESS) &&
1092  (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1093  "got 0x%x and size %d with '%s'\n", res, size, buffer);
1094 
1095  size = used;
1096  memset(buffer, '#', sizeof(buffer) - 1);
1097  buffer[sizeof(buffer) -1] = 0;
1098  res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1099  ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1100  "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1101  res, size, buffer, used + 1);
1102 
1103  size = used - 1;
1104  memset(buffer, '#', sizeof(buffer) - 1);
1105  buffer[sizeof(buffer) -1] = 0;
1106  res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1107  ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1108  "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1109  res, size, buffer, used + 1);
1110 
1111 
1112  /* to get only the ip, use 0 as port */
1113  port = 0;
1114  expect = ip_1234;
1115 
1116  size = sizeof(buffer);
1117  memset(buffer, '#', sizeof(buffer) - 1);
1118  buffer[sizeof(buffer) -1] = 0;
1119  res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1120  used = strlen(buffer);
1121  ok( (res == STATUS_SUCCESS) &&
1122  (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1123  "got 0x%x and size %d with '%s'\n", res, size, buffer);
1124 
1125  size = used + 1;
1126  memset(buffer, '#', sizeof(buffer) - 1);
1127  buffer[sizeof(buffer) -1] = 0;
1128  res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1129  ok( (res == STATUS_SUCCESS) &&
1130  (size == strlen(expect) + 1) && !strcmp(buffer, expect),
1131  "got 0x%x and size %d with '%s'\n", res, size, buffer);
1132 
1133  size = used;
1134  memset(buffer, '#', sizeof(buffer) - 1);
1135  buffer[sizeof(buffer) -1] = 0;
1136  res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1137  ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1138  "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1139  res, size, buffer, used + 1);
1140 
1141  size = used - 1;
1142  memset(buffer, '#', sizeof(buffer) - 1);
1143  buffer[sizeof(buffer) -1] = 0;
1144  res = pRtlIpv4AddressToStringExA(&ip, port, buffer, &size);
1145  ok( (res == STATUS_INVALID_PARAMETER) && (size == used + 1),
1146  "got 0x%x and %d with '%s' (expected STATUS_INVALID_PARAMETER and %d)\n",
1147  res, size, buffer, used + 1);
1148 
1149 
1150  /* parameters are checked */
1151  memset(buffer, '#', sizeof(buffer) - 1);
1152  buffer[sizeof(buffer) -1] = 0;
1153  res = pRtlIpv4AddressToStringExA(&ip, 0, buffer, NULL);
1155  "got 0x%x with '%s' (expected STATUS_INVALID_PARAMETER)\n", res, buffer);
1156 
1157  size = sizeof(buffer);
1158  res = pRtlIpv4AddressToStringExA(&ip, 0, NULL, &size);
1160  "got 0x%x and size %d (expected STATUS_INVALID_PARAMETER)\n", res, size);
1161 
1162  size = sizeof(buffer);
1163  memset(buffer, '#', sizeof(buffer) - 1);
1164  buffer[sizeof(buffer) -1] = 0;
1165  res = pRtlIpv4AddressToStringExA(NULL, 0, buffer, &size);
1167  "got 0x%x and size %d with '%s' (expected STATUS_INVALID_PARAMETER)\n",
1168  res, size, buffer);
1169 }
1170 
1171 static struct
1172 {
1176  int ip[4];
1177  enum { normal_4, strict_diff_4 = 1, ex_fail_4 = 2 } flags;
1180  int ip_strict[4];
1181 } ipv4_tests[] =
1182 {
1183  { "", STATUS_INVALID_PARAMETER, 0, { -1 } },
1184  { " ", STATUS_INVALID_PARAMETER, 0, { -1 } },
1185  { "1.1.1.1", STATUS_SUCCESS, 7, { 1, 1, 1, 1 } },
1186  { "0.0.0.0", STATUS_SUCCESS, 7, { 0, 0, 0, 0 } },
1187  { "255.255.255.255", STATUS_SUCCESS, 15, { 255, 255, 255, 255 } },
1188  { "255.255.255.255:123", STATUS_SUCCESS, 15, { 255, 255, 255, 255 } },
1189  { "255.255.255.256", STATUS_INVALID_PARAMETER, 15, { -1 } },
1190  { "255.255.255.4294967295", STATUS_INVALID_PARAMETER, 22, { -1 } },
1191  { "255.255.255.4294967296", STATUS_INVALID_PARAMETER, 21, { -1 } },
1192  { "255.255.255.4294967297", STATUS_INVALID_PARAMETER, 21, { -1 } },
1193  { "a", STATUS_INVALID_PARAMETER, 0, { -1 } },
1194  { "1.1.1.0xaA", STATUS_SUCCESS, 10, { 1, 1, 1, 170 }, strict_diff_4,
1195  STATUS_INVALID_PARAMETER, 8, { -1 } },
1196  { "1.1.1.0XaA", STATUS_SUCCESS, 10, { 1, 1, 1, 170 }, strict_diff_4,
1197  STATUS_INVALID_PARAMETER, 8, { -1 } },
1198  { "1.1.1.0x", STATUS_INVALID_PARAMETER, 8, { -1 } },
1199  { "1.1.1.0xff", STATUS_SUCCESS, 10, { 1, 1, 1, 255 }, strict_diff_4,
1200  STATUS_INVALID_PARAMETER, 8, { -1 } },
1201  { "1.1.1.0x100", STATUS_INVALID_PARAMETER, 11, { -1 }, strict_diff_4,
1202  STATUS_INVALID_PARAMETER, 8, { -1 } },
1203  { "1.1.1.0xffffffff", STATUS_INVALID_PARAMETER, 16, { -1 }, strict_diff_4,
1204  STATUS_INVALID_PARAMETER, 8, { -1 } },
1205  { "1.1.1.0x100000000", STATUS_INVALID_PARAMETER, 16, { -1, 0, 0, 0 }, strict_diff_4,
1206  STATUS_INVALID_PARAMETER, 8, { -1 } },
1207  { "1.1.1.010", STATUS_SUCCESS, 9, { 1, 1, 1, 8 }, strict_diff_4,
1208  STATUS_INVALID_PARAMETER, 7, { -1 } },
1209  { "1.1.1.00", STATUS_SUCCESS, 8, { 1, 1, 1, 0 }, strict_diff_4,
1210  STATUS_INVALID_PARAMETER, 7, { -1 } },
1211  { "1.1.1.007", STATUS_SUCCESS, 9, { 1, 1, 1, 7 }, strict_diff_4,
1212  STATUS_INVALID_PARAMETER, 7, { -1 } },
1213  { "1.1.1.08", STATUS_INVALID_PARAMETER, 7, { -1 } },
1214  { "1.1.1.008", STATUS_SUCCESS, 8, { 1, 1, 1, 0 }, strict_diff_4 | ex_fail_4,
1215  STATUS_INVALID_PARAMETER, 7, { -1 } },
1216  { "1.1.1.0a", STATUS_SUCCESS, 7, { 1, 1, 1, 0 }, ex_fail_4 },
1217  { "1.1.1.0o10", STATUS_SUCCESS, 7, { 1, 1, 1, 0 }, ex_fail_4 },
1218  { "1.1.1.0b10", STATUS_SUCCESS, 7, { 1, 1, 1, 0 }, ex_fail_4 },
1219  { "1.1.1.-2", STATUS_INVALID_PARAMETER, 6, { -1 } },
1220  { "1", STATUS_SUCCESS, 1, { 0, 0, 0, 1 }, strict_diff_4,
1221  STATUS_INVALID_PARAMETER, 1, { -1 } },
1222  { "-1", STATUS_INVALID_PARAMETER, 0, { -1 } },
1223  { "203569230", STATUS_SUCCESS, 9, { 12, 34, 56, 78 }, strict_diff_4,
1224  STATUS_INVALID_PARAMETER, 9, { -1 } },
1225  { "1.223756", STATUS_SUCCESS, 8, { 1, 3, 106, 12 }, strict_diff_4,
1226  STATUS_INVALID_PARAMETER, 8, { -1 } },
1227  { "3.4.756", STATUS_SUCCESS, 7, { 3, 4, 2, 244 }, strict_diff_4,
1228  STATUS_INVALID_PARAMETER, 7, { -1 } },
1229  { "3.4.756.1", STATUS_INVALID_PARAMETER, 9, { -1 } },
1230  { "3.4.65536", STATUS_INVALID_PARAMETER, 9, { -1 } },
1231  { "3.4.5.6.7", STATUS_INVALID_PARAMETER, 7, { -1 } },
1232  { "3.4.5.+6", STATUS_INVALID_PARAMETER, 6, { -1 } },
1233  { " 3.4.5.6", STATUS_INVALID_PARAMETER, 0, { -1 } },
1234  { "\t3.4.5.6", STATUS_INVALID_PARAMETER, 0, { -1 } },
1235  { "3.4.5.6 ", STATUS_SUCCESS, 7, { 3, 4, 5, 6 }, ex_fail_4 },
1236  { "3. 4.5.6", STATUS_INVALID_PARAMETER, 2, { -1 } },
1237  { ".", STATUS_INVALID_PARAMETER, 1, { -1 } },
1238  { "..", STATUS_INVALID_PARAMETER, 1, { -1 } },
1239  { "1.", STATUS_INVALID_PARAMETER, 2, { -1 } },
1240  { "1..", STATUS_INVALID_PARAMETER, 3, { -1 } },
1241  { ".1", STATUS_INVALID_PARAMETER, 1, { -1 } },
1242  { ".1.", STATUS_INVALID_PARAMETER, 1, { -1 } },
1243  { ".1.2.3", STATUS_INVALID_PARAMETER, 1, { -1 } },
1244  { "0.1.2.3", STATUS_SUCCESS, 7, { 0, 1, 2, 3 } },
1245  { "0.1.2.3.", STATUS_INVALID_PARAMETER, 7, { -1 } },
1246  { "[0.1.2.3]", STATUS_INVALID_PARAMETER, 0, { -1 } },
1247  { "::1", STATUS_INVALID_PARAMETER, 0, { -1 } },
1248  { ":1", STATUS_INVALID_PARAMETER, 0, { -1 } },
1249 };
1250 const unsigned int ipv4_testcount = sizeof(ipv4_tests) / sizeof(ipv4_tests[0]);
1251 
1252 static void init_ip4(IN_ADDR* addr, const int src[4])
1253 {
1254  if (!src || src[0] == -1)
1255  {
1256  addr->S_un.S_addr = 0xabababab;
1257  }
1258  else
1259  {
1260  addr->S_un.S_un_b.s_b1 = src[0];
1261  addr->S_un.S_un_b.s_b2 = src[1];
1262  addr->S_un.S_un_b.s_b3 = src[2];
1263  addr->S_un.S_un_b.s_b4 = src[3];
1264  }
1265 }
1266 
1268 {
1269  NTSTATUS res;
1270  IN_ADDR ip, expected_ip;
1271  PCSTR terminator;
1272  CHAR dummy;
1273  unsigned int i;
1274 
1275  if (!pRtlIpv4StringToAddressA)
1276  {
1277  skip("RtlIpv4StringToAddress not available\n");
1278  return;
1279  }
1280 
1281  if (0)
1282  {
1283  /* leaving either parameter NULL crashes on Windows */
1284  res = pRtlIpv4StringToAddressA(NULL, FALSE, &terminator, &ip);
1285  res = pRtlIpv4StringToAddressA("1.1.1.1", FALSE, NULL, &ip);
1286  res = pRtlIpv4StringToAddressA("1.1.1.1", FALSE, &terminator, NULL);
1287  /* same for the wide char version */
1288  /*
1289  res = pRtlIpv4StringToAddressW(NULL, FALSE, &terminatorW, &ip);
1290  res = pRtlIpv4StringToAddressW(L"1.1.1.1", FALSE, NULL, &ip);
1291  res = pRtlIpv4StringToAddressW(L"1.1.1.1", FALSE, &terminatorW, NULL);
1292  */
1293  }
1294 
1295  for (i = 0; i < ipv4_testcount; i++)
1296  {
1297  /* non-strict */
1298  terminator = &dummy;
1299  ip.S_un.S_addr = 0xabababab;
1300  res = pRtlIpv4StringToAddressA(ipv4_tests[i].address, FALSE, &terminator, &ip);
1301  ok(res == ipv4_tests[i].res,
1302  "[%s] res = 0x%08x, expected 0x%08x\n",
1304  ok(terminator == ipv4_tests[i].address + ipv4_tests[i].terminator_offset,
1305  "[%s] terminator = %p, expected %p\n",
1307 
1308  init_ip4(&expected_ip, ipv4_tests[i].ip);
1309  ok(ip.S_un.S_addr == expected_ip.S_un.S_addr,
1310  "[%s] ip = %08x, expected %08x\n",
1311  ipv4_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
1312 
1313  if (!(ipv4_tests[i].flags & strict_diff_4))
1314  {
1315  ipv4_tests[i].res_strict = ipv4_tests[i].res;
1316  ipv4_tests[i].terminator_offset_strict = ipv4_tests[i].terminator_offset;
1317  ipv4_tests[i].ip_strict[0] = ipv4_tests[i].ip[0];
1318  ipv4_tests[i].ip_strict[1] = ipv4_tests[i].ip[1];
1319  ipv4_tests[i].ip_strict[2] = ipv4_tests[i].ip[2];
1320  ipv4_tests[i].ip_strict[3] = ipv4_tests[i].ip[3];
1321  }
1322  /* strict */
1323  terminator = &dummy;
1324  ip.S_un.S_addr = 0xabababab;
1325  res = pRtlIpv4StringToAddressA(ipv4_tests[i].address, TRUE, &terminator, &ip);
1327  "[%s] res = 0x%08x, expected 0x%08x\n",
1330  "[%s] terminator = %p, expected %p\n",
1332 
1333  init_ip4(&expected_ip, ipv4_tests[i].ip_strict);
1334  ok(ip.S_un.S_addr == expected_ip.S_un.S_addr,
1335  "[%s] ip = %08x, expected %08x\n",
1336  ipv4_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
1337  }
1338 }
1339 
1341 {
1342  NTSTATUS res;
1343  IN_ADDR ip, expected_ip;
1344  USHORT port;
1345  static const struct
1346  {
1347  PCSTR address;
1348  NTSTATUS res;
1349  int ip[4];
1350  USHORT port;
1351  } ipv4_ex_tests[] =
1352  {
1353  { "", STATUS_INVALID_PARAMETER, { -1 }, 0xdead },
1354  { " ", STATUS_INVALID_PARAMETER, { -1 }, 0xdead },
1355  { "1.1.1.1:", STATUS_INVALID_PARAMETER, { 1, 1, 1, 1 }, 0xdead },
1356  { "1.1.1.1+", STATUS_INVALID_PARAMETER, { 1, 1, 1, 1 }, 0xdead },
1357  { "1.1.1.1:1", STATUS_SUCCESS, { 1, 1, 1, 1 }, 0x100 },
1358  { "256.1.1.1:1", STATUS_INVALID_PARAMETER, { -1 }, 0xdead },
1359  { "-1.1.1.1:1", STATUS_INVALID_PARAMETER, { -1 }, 0xdead },
1360  { "0.0.0.0:0", STATUS_INVALID_PARAMETER, { 0, 0, 0, 0 }, 0xdead },
1361  { "0.0.0.0:1", STATUS_SUCCESS, { 0, 0, 0, 0 }, 0x100 },
1362  { "1.2.3.4:65535", STATUS_SUCCESS, { 1, 2, 3, 4 }, 65535 },
1363  { "1.2.3.4:65536", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
1364  { "1.2.3.4:0xffff", STATUS_SUCCESS, { 1, 2, 3, 4 }, 65535 },
1365  { "1.2.3.4:0XfFfF", STATUS_SUCCESS, { 1, 2, 3, 4 }, 65535 },
1366  { "1.2.3.4:011064", STATUS_SUCCESS, { 1, 2, 3, 4 }, 0x3412 },
1367  { "1.2.3.4:1234a", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
1368  { "1.2.3.4:1234+", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
1369  { "1.2.3.4: 1234", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
1370  { "1.2.3.4:\t1234", STATUS_INVALID_PARAMETER, { 1, 2, 3, 4 }, 0xdead },
1371  };
1372  const unsigned int ipv4_ex_testcount = sizeof(ipv4_ex_tests) / sizeof(ipv4_ex_tests[0]);
1373  unsigned int i;
1374  BOOLEAN strict;
1375 
1376  if (!pRtlIpv4StringToAddressExA)
1377  {
1378  skip("RtlIpv4StringToAddressEx not available\n");
1379  return;
1380  }
1381 
1382  /* do not crash, and do not touch the ip / port. */
1383  ip.S_un.S_addr = 0xabababab;
1384  port = 0xdead;
1385  res = pRtlIpv4StringToAddressExA(NULL, FALSE, &ip, &port);
1386  ok(res == STATUS_INVALID_PARAMETER, "[null address] res = 0x%08x, expected 0x%08x\n",
1388  ok(ip.S_un.S_addr == 0xabababab, "RtlIpv4StringToAddressExA should not touch the ip!, ip == %x\n", ip.S_un.S_addr);
1389  ok(port == 0xdead, "RtlIpv4StringToAddressExA should not touch the port!, port == %x\n", port);
1390 
1391  port = 0xdead;
1392  res = pRtlIpv4StringToAddressExA("1.1.1.1", FALSE, NULL, &port);
1393  ok(res == STATUS_INVALID_PARAMETER, "[null ip] res = 0x%08x, expected 0x%08x\n",
1395  ok(port == 0xdead, "RtlIpv4StringToAddressExA should not touch the port!, port == %x\n", port);
1396 
1397  ip.S_un.S_addr = 0xabababab;
1398  port = 0xdead;
1399  res = pRtlIpv4StringToAddressExA("1.1.1.1", FALSE, &ip, NULL);
1400  ok(res == STATUS_INVALID_PARAMETER, "[null port] res = 0x%08x, expected 0x%08x\n",
1402  ok(ip.S_un.S_addr == 0xabababab, "RtlIpv4StringToAddressExA should not touch the ip!, ip == %x\n", ip.S_un.S_addr);
1403  ok(port == 0xdead, "RtlIpv4StringToAddressExA should not touch the port!, port == %x\n", port);
1404 
1405  /* first we run the non-ex testcases on the ex function */
1406  for (i = 0; i < ipv4_testcount; i++)
1407  {
1408  NTSTATUS expect_res = (ipv4_tests[i].flags & ex_fail_4) ? STATUS_INVALID_PARAMETER : ipv4_tests[i].res;
1409 
1410  /* non-strict */
1411  port = 0xdead;
1412  ip.S_un.S_addr = 0xabababab;
1413  res = pRtlIpv4StringToAddressExA(ipv4_tests[i].address, FALSE, &ip, &port);
1414  ok(res == expect_res, "[%s] res = 0x%08x, expected 0x%08x\n",
1415  ipv4_tests[i].address, res, expect_res);
1416 
1417  init_ip4(&expected_ip, ipv4_tests[i].ip);
1418  ok(ip.S_un.S_addr == expected_ip.S_un.S_addr, "[%s] ip = %08x, expected %08x\n",
1419  ipv4_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
1420 
1421  if (!(ipv4_tests[i].flags & strict_diff_4))
1422  {
1423  ipv4_tests[i].res_strict = ipv4_tests[i].res;
1424  ipv4_tests[i].terminator_offset_strict = ipv4_tests[i].terminator_offset;
1425  ipv4_tests[i].ip_strict[0] = ipv4_tests[i].ip[0];
1426  ipv4_tests[i].ip_strict[1] = ipv4_tests[i].ip[1];
1427  ipv4_tests[i].ip_strict[2] = ipv4_tests[i].ip[2];
1428  ipv4_tests[i].ip_strict[3] = ipv4_tests[i].ip[3];
1429  }
1430  /* strict */
1431  expect_res = (ipv4_tests[i].flags & ex_fail_4) ? STATUS_INVALID_PARAMETER : ipv4_tests[i].res_strict;
1432  port = 0xdead;
1433  ip.S_un.S_addr = 0xabababab;
1434  res = pRtlIpv4StringToAddressExA(ipv4_tests[i].address, TRUE, &ip, &port);
1435  ok(res == expect_res, "[%s] res = 0x%08x, expected 0x%08x\n",
1436  ipv4_tests[i].address, res, expect_res);
1437 
1438  init_ip4(&expected_ip, ipv4_tests[i].ip_strict);
1439  ok(ip.S_un.S_addr == expected_ip.S_un.S_addr, "[%s] ip = %08x, expected %08x\n",
1440  ipv4_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
1441  }
1442 
1443 
1444  for (i = 0; i < ipv4_ex_testcount; i++)
1445  {
1446  /* Strict is only relevant for the ip address, so make sure that it does not influence the port */
1447  for (strict = 0; strict < 2; strict++)
1448  {
1449  ip.S_un.S_addr = 0xabababab;
1450  port = 0xdead;
1451  res = pRtlIpv4StringToAddressExA(ipv4_ex_tests[i].address, strict, &ip, &port);
1452  ok(res == ipv4_ex_tests[i].res, "[%s] res = 0x%08x, expected 0x%08x\n",
1453  ipv4_ex_tests[i].address, res, ipv4_ex_tests[i].res);
1454 
1455  init_ip4(&expected_ip, ipv4_ex_tests[i].ip);
1456  ok(ip.S_un.S_addr == expected_ip.S_un.S_addr, "[%s] ip = %08x, expected %08x\n",
1457  ipv4_ex_tests[i].address, ip.S_un.S_addr, expected_ip.S_un.S_addr);
1458  ok(port == ipv4_ex_tests[i].port, "[%s] port = %u, expected %u\n",
1459  ipv4_ex_tests[i].address, port, ipv4_ex_tests[i].port);
1460  }
1461  }
1462 }
1463 
1464 /* ipv6 addresses based on the set from https://github.com/beaugunderson/javascript-ipv6/tree/master/test/data */
1465 static const struct
1466 {
1467  PCSTR address;
1468  NTSTATUS res;
1469  int terminator_offset;
1470  int ip[8];
1471  /* win_broken: older versions of windows do not handle this correct
1472  ex_fail: Ex function does need the string to be terminated, non-Ex does not.
1473  ex_skip: test doesnt make sense for Ex (f.e. it's invalid for non-Ex but valid for Ex) */
1474  enum { normal_6, win_broken_6 = 1, ex_fail_6 = 2, ex_skip_6 = 4 } flags;
1475 } ipv6_tests[] =
1476 {
1477  { "0000:0000:0000:0000:0000:0000:0000:0000", STATUS_SUCCESS, 39,
1478  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1479  { "0000:0000:0000:0000:0000:0000:0000:0001", STATUS_SUCCESS, 39,
1480  { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
1481  { "0:0:0:0:0:0:0:0", STATUS_SUCCESS, 15,
1482  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1483  { "0:0:0:0:0:0:0:1", STATUS_SUCCESS, 15,
1484  { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
1485  { "0:0:0:0:0:0:0::", STATUS_SUCCESS, 13,
1486  { 0, 0, 0, 0, 0, 0, 0, 0 }, win_broken_6 },
1487  { "0:0:0:0:0:0:13.1.68.3", STATUS_SUCCESS, 21,
1488  { 0, 0, 0, 0, 0, 0, 0x10d, 0x344 } },
1489  { "0:0:0:0:0:0::", STATUS_SUCCESS, 13,
1490  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1491  { "0:0:0:0:0::", STATUS_SUCCESS, 11,
1492  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1493  { "0:0:0:0:0:FFFF:129.144.52.38", STATUS_SUCCESS, 28,
1494  { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
1495  { "0::", STATUS_SUCCESS, 3,
1496  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1497  { "0:1:2:3:4:5:6:7", STATUS_SUCCESS, 15,
1498  { 0, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700 } },
1499  { "1080:0:0:0:8:800:200c:417a", STATUS_SUCCESS, 26,
1500  { 0x8010, 0, 0, 0, 0x800, 0x8, 0x0c20, 0x7a41 } },
1501  { "0:a:b:c:d:e:f::", STATUS_SUCCESS, 13,
1502  { 0, 0xa00, 0xb00, 0xc00, 0xd00, 0xe00, 0xf00, 0 }, win_broken_6 },
1503  { "1111:2222:3333:4444:5555:6666:123.123.123.123", STATUS_SUCCESS, 45,
1504  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1505  { "1111:2222:3333:4444:5555:6666:7777:8888", STATUS_SUCCESS, 39,
1506  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 } },
1507  { "1111:2222:3333:4444:0x5555:6666:7777:8888", STATUS_INVALID_PARAMETER, 21,
1508  { 0x1111, 0x2222, 0x3333, 0x4444, 0xabab, 0xabab, 0xabab, 0xabab } },
1509  { "1111:2222:3333:4444:x555:6666:7777:8888", STATUS_INVALID_PARAMETER, 20,
1510  { 0x1111, 0x2222, 0x3333, 0x4444, 0xabab, 0xabab, 0xabab, 0xabab } },
1511  { "1111:2222:3333:4444:0r5555:6666:7777:8888", STATUS_INVALID_PARAMETER, 21,
1512  { 0x1111, 0x2222, 0x3333, 0x4444, 0xabab, 0xabab, 0xabab, 0xabab } },
1513  { "1111:2222:3333:4444:r5555:6666:7777:8888", STATUS_INVALID_PARAMETER, 20,
1514  { 0x1111, 0x2222, 0x3333, 0x4444, 0xabab, 0xabab, 0xabab, 0xabab } },
1515  { "1111:2222:3333:4444:5555:6666:7777::", STATUS_SUCCESS, 34,
1516  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0 }, win_broken_6 },
1517  { "1111:2222:3333:4444:5555:6666::", STATUS_SUCCESS, 31,
1518  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0, 0 } },
1519  { "1111:2222:3333:4444:5555:6666::8888", STATUS_SUCCESS, 35,
1520  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0, 0x8888 } },
1521  { "1111:2222:3333:4444:5555::", STATUS_SUCCESS, 26,
1522  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0 } },
1523  { "1111:2222:3333:4444:5555::123.123.123.123", STATUS_SUCCESS, 41,
1524  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0x7b7b, 0x7b7b } },
1525  { "1111:2222:3333:4444:5555::0x1.123.123.123", STATUS_SUCCESS, 27,
1526  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0x100 }, ex_fail_6 },
1527  { "1111:2222:3333:4444:5555::0x88", STATUS_SUCCESS, 27,
1528  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0x8800 }, ex_fail_6 },
1529  { "1111:2222:3333:4444:5555::0X88", STATUS_SUCCESS, 27,
1530  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0x8800 }, ex_fail_6 },
1531  { "1111:2222:3333:4444:5555::0X", STATUS_SUCCESS, 27,
1532  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0 }, ex_fail_6 },
1533  { "1111:2222:3333:4444:5555::0X88:7777", STATUS_SUCCESS, 27,
1534  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0x8800 }, ex_fail_6 },
1535  { "1111:2222:3333:4444:5555::0x8888", STATUS_SUCCESS, 27,
1536  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0x8888 }, ex_fail_6 },
1537  { "1111:2222:3333:4444:5555::08888", STATUS_INVALID_PARAMETER, 31,
1538  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0xabab, 0xabab, 0xabab } },
1539  { "1111:2222:3333:4444:5555::fffff", STATUS_INVALID_PARAMETER, 31,
1540  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0xabab, 0xabab, 0xabab } },
1541  { "1111:2222:3333:4444::fffff", STATUS_INVALID_PARAMETER, 26,
1542  { 0x1111, 0x2222, 0x3333, 0x4444, 0xabab, 0xabab, 0xabab, 0xabab } },
1543  { "1111:2222:3333::fffff", STATUS_INVALID_PARAMETER, 21,
1544  { 0x1111, 0x2222, 0x3333, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1545  { "1111:2222:3333:4444:5555::7777:8888", STATUS_SUCCESS, 35,
1546  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0x7777, 0x8888 } },
1547  { "1111:2222:3333:4444:5555::8888", STATUS_SUCCESS, 30,
1548  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0x8888 } },
1549  { "1111::", STATUS_SUCCESS, 6,
1550  { 0x1111, 0, 0, 0, 0, 0, 0, 0 } },
1551  { "1111::123.123.123.123", STATUS_SUCCESS, 21,
1552  { 0x1111, 0, 0, 0, 0, 0, 0x7b7b, 0x7b7b } },
1553  { "1111::3333:4444:5555:6666:123.123.123.123", STATUS_SUCCESS, 41,
1554  { 0x1111, 0, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1555  { "1111::3333:4444:5555:6666:7777:8888", STATUS_SUCCESS, 35,
1556  { 0x1111, 0, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 } },
1557  { "1111::4444:5555:6666:123.123.123.123", STATUS_SUCCESS, 36,
1558  { 0x1111, 0, 0, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1559  { "1111::4444:5555:6666:7777:8888", STATUS_SUCCESS, 30,
1560  { 0x1111, 0, 0, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 } },
1561  { "1111::5555:6666:123.123.123.123", STATUS_SUCCESS, 31,
1562  { 0x1111, 0, 0, 0, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1563  { "1111::5555:6666:7777:8888", STATUS_SUCCESS, 25,
1564  { 0x1111, 0, 0, 0, 0x5555, 0x6666, 0x7777, 0x8888 } },
1565  { "1111::6666:123.123.123.123", STATUS_SUCCESS, 26,
1566  { 0x1111, 0, 0, 0, 0, 0x6666, 0x7b7b, 0x7b7b } },
1567  { "1111::6666:7777:8888", STATUS_SUCCESS, 20,
1568  { 0x1111, 0, 0, 0, 0, 0x6666, 0x7777, 0x8888 } },
1569  { "1111::7777:8888", STATUS_SUCCESS, 15,
1570  { 0x1111, 0, 0, 0, 0, 0, 0x7777, 0x8888 } },
1571  { "1111::8888", STATUS_SUCCESS, 10,
1572  { 0x1111, 0, 0, 0, 0, 0, 0, 0x8888 } },
1573  { "1:2:3:4:5:6:1.2.3.4", STATUS_SUCCESS, 19,
1574  { 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x201, 0x403 } },
1575  { "1:2:3:4:5:6:7:8", STATUS_SUCCESS, 15,
1576  { 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800 } },
1577  { "1:2:3:4:5:6::", STATUS_SUCCESS, 13,
1578  { 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0, 0 } },
1579  { "1:2:3:4:5:6::8", STATUS_SUCCESS, 14,
1580  { 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0, 0x800 } },
1581  { "2001:0000:1234:0000:0000:C1C0:ABCD:0876", STATUS_SUCCESS, 39,
1582  { 0x120, 0, 0x3412, 0, 0, 0xc0c1, 0xcdab, 0x7608 } },
1583  { "2001:0000:4136:e378:8000:63bf:3fff:fdd2", STATUS_SUCCESS, 39,
1584  { 0x120, 0, 0x3641, 0x78e3, 0x80, 0xbf63, 0xff3f, 0xd2fd } },
1585  { "2001:0db8:0:0:0:0:1428:57ab", STATUS_SUCCESS, 27,
1586  { 0x120, 0xb80d, 0, 0, 0, 0, 0x2814, 0xab57 } },
1587  { "2001:0db8:1234:ffff:ffff:ffff:ffff:ffff", STATUS_SUCCESS, 39,
1588  { 0x120, 0xb80d, 0x3412, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff } },
1589  { "2001::CE49:7601:2CAD:DFFF:7C94:FFFE", STATUS_SUCCESS, 35,
1590  { 0x120, 0, 0x49ce, 0x176, 0xad2c, 0xffdf, 0x947c, 0xfeff } },
1591  { "2001:db8:85a3::8a2e:370:7334", STATUS_SUCCESS, 28,
1592  { 0x120, 0xb80d, 0xa385, 0, 0, 0x2e8a, 0x7003, 0x3473 } },
1593  { "3ffe:0b00:0000:0000:0001:0000:0000:000a", STATUS_SUCCESS, 39,
1594  { 0xfe3f, 0xb, 0, 0, 0x100, 0, 0, 0xa00 } },
1595  { "::", STATUS_SUCCESS, 2,
1596  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1597  { "::%16", STATUS_SUCCESS, 2,
1598  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1599  { "::/16", STATUS_SUCCESS, 2,
1600  { 0, 0, 0, 0, 0, 0, 0, 0 }, ex_fail_6 },
1601  { "::0", STATUS_SUCCESS, 3,
1602  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1603  { "::0:0", STATUS_SUCCESS, 5,
1604  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1605  { "::0:0:0", STATUS_SUCCESS, 7,
1606  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1607  { "::0:0:0:0", STATUS_SUCCESS, 9,
1608  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1609  { "::0:0:0:0:0", STATUS_SUCCESS, 11,
1610  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1611  { "::0:0:0:0:0:0", STATUS_SUCCESS, 13,
1612  { 0, 0, 0, 0, 0, 0, 0, 0 } },
1613  /* this one and the next one are incorrectly parsed by windows,
1614  it adds one zero too many in front, cutting off the last digit. */
1615  { "::0:0:0:0:0:0:0", STATUS_SUCCESS, 13,
1616  { 0, 0, 0, 0, 0, 0, 0, 0 }, ex_fail_6 },
1617  { "::0:a:b:c:d:e:f", STATUS_SUCCESS, 13,
1618  { 0, 0, 0, 0xa00, 0xb00, 0xc00, 0xd00, 0xe00 }, ex_fail_6 },
1619  { "::123.123.123.123", STATUS_SUCCESS, 17,
1620  { 0, 0, 0, 0, 0, 0, 0x7b7b, 0x7b7b } },
1621  { "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", STATUS_SUCCESS, 39,
1622  { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff } },
1623 
1624  { "':10.0.0.1", STATUS_INVALID_PARAMETER, 0,
1625  { -1 } },
1626  { "-1", STATUS_INVALID_PARAMETER, 0,
1627  { -1 } },
1628  { "02001:0000:1234:0000:0000:C1C0:ABCD:0876", STATUS_INVALID_PARAMETER, -1,
1629  { -1 } },
1630  { "2001:00000:1234:0000:0000:C1C0:ABCD:0876", STATUS_INVALID_PARAMETER, -1,
1631  { 0x120, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1632  { "2001:0000:01234:0000:0000:C1C0:ABCD:0876", STATUS_INVALID_PARAMETER, -1,
1633  { 0x120, 0, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1634  { "1.2.3.4", STATUS_INVALID_PARAMETER, 7,
1635  { 0x201, 0xab03, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1636  { "1.2.3.4:1111::5555", STATUS_INVALID_PARAMETER, 7,
1637  { 0x201, 0xab03, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1638  { "1.2.3.4::5555", STATUS_INVALID_PARAMETER, 7,
1639  { 0x201, 0xab03, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1640  { "11112222:3333:4444:5555:6666:1.2.3.4", STATUS_INVALID_PARAMETER, -1,
1641  { -1 } },
1642  { "11112222:3333:4444:5555:6666:7777:8888", STATUS_INVALID_PARAMETER, -1,
1643  { -1 } },
1644  { "1111", STATUS_INVALID_PARAMETER, 4,
1645  { -1 } },
1646  { "1111:22223333:4444:5555:6666:1.2.3.4", STATUS_INVALID_PARAMETER, -1,
1647  { 0x1111, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1648  { "1111:22223333:4444:5555:6666:7777:8888", STATUS_INVALID_PARAMETER, -1,
1649  { 0x1111, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1650  { "1111:2222:", STATUS_INVALID_PARAMETER, 10,
1651  { 0x1111, 0x2222, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1652  { "1111:2222:1.2.3.4", STATUS_INVALID_PARAMETER, 17,
1653  { 0x1111, 0x2222, 0x201, 0xab03, 0xabab, 0xabab, 0xabab, 0xabab } },
1654  { "1111:2222:3333", STATUS_INVALID_PARAMETER, 14,
1655  { 0x1111, 0x2222, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1656  { "1111:2222:3333:4444:5555:6666:7777:1.2.3.4", STATUS_SUCCESS, 36,
1657  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x100 }, ex_fail_6 },
1658  { "1111:2222:3333:4444:5555:6666:7777:8888:", STATUS_SUCCESS, 39,
1659  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 }, ex_fail_6 },
1660  { "1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4",STATUS_SUCCESS, 39,
1661  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 }, ex_fail_6 },
1662  { "1111:2222:3333:4444:5555:6666:7777:8888:9999", STATUS_SUCCESS, 39,
1663  { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 }, ex_fail_6 },
1664  { "1111:2222:::", STATUS_SUCCESS, 11,
1665  { 0x1111, 0x2222, 0, 0, 0, 0, 0, 0 }, ex_fail_6 },
1666  { "1111::5555:", STATUS_INVALID_PARAMETER, 11,
1667  { 0x1111, 0x5555, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1668  { "1111::3333:4444:5555:6666:7777::", STATUS_SUCCESS, 30,
1669  { 0x1111, 0, 0, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777 }, ex_fail_6 },
1670  { "1111:2222:::4444:5555:6666:1.2.3.4", STATUS_SUCCESS, 11,
1671  { 0x1111, 0x2222, 0, 0, 0, 0, 0, 0 }, ex_fail_6 },
1672  { "1111::3333::5555:6666:1.2.3.4", STATUS_SUCCESS, 10,
1673  { 0x1111, 0, 0, 0, 0, 0, 0, 0x3333 }, ex_fail_6 },
1674  { "12345::6:7:8", STATUS_INVALID_PARAMETER, -1,
1675  { -1 } },
1676  { "1::1.2.256.4", STATUS_INVALID_PARAMETER, -1,
1677  { 0x100, 0x201, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1678  { "1::1.2.3.256", STATUS_INVALID_PARAMETER, 12,
1679  { 0x100, 0x201, 0xab03, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1680  { "1::1.2.3.300", STATUS_INVALID_PARAMETER, 12,
1681  { 0x100, 0x201, 0xab03, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1682  { "1::1.2::1", STATUS_INVALID_PARAMETER, 6,
1683  { 0x100, 0xab01, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1684  { "1::1.2.3.4::1", STATUS_SUCCESS, 10,
1685  { 0x100, 0, 0, 0, 0, 0, 0x201, 0x403 }, ex_fail_6 },
1686  { "1::1.", STATUS_INVALID_PARAMETER, 5,
1687  { 0x100, 0xab01, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1688  { "1::1.2", STATUS_INVALID_PARAMETER, 6,
1689  { 0x100, 0xab01, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1690  { "1::1.2.", STATUS_INVALID_PARAMETER, 7,
1691  { 0x100, 0x201, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1692  { "1::1.2.3", STATUS_INVALID_PARAMETER, 8,
1693  { 0x100, 0x201, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1694  { "1::1.2.3.", STATUS_INVALID_PARAMETER, 9,
1695  { 0x100, 0x201, 0xab03, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1696  { "1::1.2.3.4", STATUS_SUCCESS, 10,
1697  { 0x100, 0, 0, 0, 0, 0, 0x201, 0x403 } },
1698  { "1::1.2.3.900", STATUS_INVALID_PARAMETER, 12,
1699  { 0x100, 0x201, 0xab03, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1700  { "1::1.2.300.4", STATUS_INVALID_PARAMETER, -1,
1701  { 0x100, 0x201, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1702  { "1::1.256.3.4", STATUS_INVALID_PARAMETER, -1,
1703  { 0x100, 0xab01, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1704  { "1::256.2.3.4", STATUS_INVALID_PARAMETER, -1,
1705  { 0x100, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1706  { "1::2::3", STATUS_SUCCESS, 4,
1707  { 0x100, 0, 0, 0, 0, 0, 0, 0x200 }, ex_fail_6 },
1708  { "2001:0000:1234: 0000:0000:C1C0:ABCD:0876", STATUS_INVALID_PARAMETER, 15,
1709  { 0x120, 0, 0x3412, 0xabab, 0xabab, 0xabab, 0xabab, 0xabab } },
1710  { "2001:0000:1234:0000:0000:C1C0:ABCD:0876 0", STATUS_SUCCESS, 39,
1711  { 0x120, 0, 0x3412, 0, 0, 0xc0c1, 0xcdab, 0x7608 }, ex_fail_6 },
1712  { "2001:1:1:1:1:1:255Z255X255Y255", STATUS_INVALID_PARAMETER, 18,
1713  { 0x120, 0x100, 0x100, 0x100, 0x100, 0x100, 0xabab, 0xabab } },
1714  { "2001::FFD3::57ab", STATUS_SUCCESS, 10,
1715  { 0x120, 0, 0, 0, 0, 0, 0, 0xd3ff }, ex_fail_6 },
1716  { ":", STATUS_INVALID_PARAMETER, 0,
1717  { -1 } },
1718  { ":1111:2222:3333:4444:5555:6666:1.2.3.4", STATUS_INVALID_PARAMETER, 0,
1719  { -1 } },
1720  { ":1111:2222:3333:4444:5555:6666:7777:8888", STATUS_INVALID_PARAMETER, 0,
1721  { -1 } },
1722  { ":1111::", STATUS_INVALID_PARAMETER, 0,
1723  { -1 } },
1724  { "::-1", STATUS_SUCCESS, 2,
1725  { 0, 0, 0, 0, 0, 0, 0, 0 }, ex_fail_6 },
1726  { "::.", STATUS_SUCCESS, 2,
1727  { 0, 0, 0, 0, 0, 0, 0, 0 }, ex_fail_6 },
1728  { "::..", STATUS_SUCCESS, 2,
1729  { 0, 0, 0, 0, 0, 0, 0, 0 }, ex_fail_6 },
1730  { "::...", STATUS_SUCCESS, 2,
1731  { 0, 0, 0, 0, 0, 0, 0, 0 }, ex_fail_6 },
1732  { "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4", STATUS_INVALID_PARAMETER, 0,
1733  { -1 } },
1734  { "[::]", STATUS_INVALID_PARAMETER, 0,
1735  { -1 }, ex_skip_6 },
1736 };
1737 const unsigned int ipv6_testcount = sizeof(ipv6_tests) / sizeof(ipv6_tests[0]);
1738 
1739 static void init_ip6(IN6_ADDR* addr, const int src[8])
1740 {
1741  unsigned int j;
1742  if (!src || src[0] == -1)
1743  {
1744  for (j = 0; j < 8; ++j)
1745  addr->s6_words[j] = 0xabab;
1746  }
1747  else
1748  {
1749  for (j = 0; j < 8; ++j)
1750  addr->s6_words[j] = src[j];
1751  }
1752 }
1753 
1755 {
1756  CHAR buffer[50];
1757  LPCSTR result;
1758  IN6_ADDR ip;
1759  DWORD_PTR len;
1760  struct
1761  {
1762  PCSTR address;
1763  int ip[8];
1764  } tests[] =
1765  {
1766  /* ipv4 addresses & ISATAP addresses */
1767  { "::13.1.68.3", { 0, 0, 0, 0, 0, 0, 0x10d, 0x344 } },
1768  { "::ffff:13.1.68.3", { 0, 0, 0, 0, 0, 0xffff, 0x10d, 0x344 } },
1769  { "::feff:d01:4403", { 0, 0, 0, 0, 0, 0xfffe, 0x10d, 0x344 } },
1770  { "::fffe:d01:4403", { 0, 0, 0, 0, 0, 0xfeff, 0x10d, 0x344 } },
1771  { "::100:d01:4403", { 0, 0, 0, 0, 0, 1, 0x10d, 0x344 } },
1772  { "::1:d01:4403", { 0, 0, 0, 0, 0, 0x100, 0x10d, 0x344 } },
1773  { "::ffff:0:4403", { 0, 0, 0, 0, 0, 0xffff, 0, 0x344 } },
1774  { "::ffff:13.1.0.0", { 0, 0, 0, 0, 0, 0xffff, 0x10d, 0 } },
1775  { "::ffff:0:0", { 0, 0, 0, 0, 0, 0xffff, 0, 0 } },
1776  { "::ffff:0:13.1.68.3", { 0, 0, 0, 0, 0xffff, 0, 0x10d, 0x344 } },
1777  { "::ffff:ffff:d01:4403", { 0, 0, 0, 0, 0xffff, 0xffff, 0x10d, 0x344 } },
1778  { "::ffff:0:0:d01:4403", { 0, 0, 0, 0xffff, 0, 0, 0x10d, 0x344 } },
1779  { "::ffff:255.255.255.255", { 0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff } },
1780  { "::ffff:129.144.52.38", { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
1781  { "::5efe:129.144.52.38", { 0, 0, 0, 0, 0, 0xfe5e, 0x9081, 0x2634 } },
1782  { "1111:2222:3333:4444:0:5efe:129.144.52.38", { 0x1111, 0x2222, 0x3333, 0x4444, 0, 0xfe5e, 0x9081, 0x2634 } },
1783  { "1111:2222:3333::5efe:129.144.52.38", { 0x1111, 0x2222, 0x3333, 0, 0, 0xfe5e, 0x9081, 0x2634 } },
1784  { "1111:2222::5efe:129.144.52.38", { 0x1111, 0x2222, 0, 0, 0, 0xfe5e, 0x9081, 0x2634 } },
1785  { "1111::5efe:129.144.52.38", { 0x1111, 0, 0, 0, 0, 0xfe5e, 0x9081, 0x2634 } },
1786  { "::200:5efe:129.144.52.38", { 0, 0, 0, 0, 2, 0xfe5e, 0x9081, 0x2634 } },
1787  { "::100:5efe:8190:3426", { 0, 0, 0, 0, 1, 0xfe5e, 0x9081, 0x2634 } },
1788  /* 'normal' addresses */
1789  { "::1", { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
1790  { "0:1:2:3:4:5:6:7", { 0, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700 } },
1791  { "1080::8:800:200c:417a", { 0x8010, 0, 0, 0, 0x800, 0x8, 0x0c20, 0x7a41 } },
1792  { "1111:2222:3333:4444:5555:6666:7b7b:7b7b", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1793  { "1111:2222:3333:4444:5555:6666:7777:8888", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 } },
1794  { "1111:2222:3333:4444:5555:6666::", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0, 0 } },
1795  { "1111:2222:3333:4444:5555:6666:0:8888", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0, 0x8888 } },
1796  { "1111:2222:3333:4444:5555::", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0 } },
1797  { "1111:2222:3333:4444:5555:0:7b7b:7b7b", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0x7b7b, 0x7b7b } },
1798  { "1111:2222:3333:4444:5555:0:7777:8888", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0x7777, 0x8888 } },
1799  { "1111:2222:3333:4444:5555::8888", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0, 0, 0x8888 } },
1800  { "1111::", { 0x1111, 0, 0, 0, 0, 0, 0, 0 } },
1801  { "1111::7b7b:7b7b", { 0x1111, 0, 0, 0, 0, 0, 0x7b7b, 0x7b7b } },
1802  { "1111:0:3333:4444:5555:6666:7b7b:7b7b", { 0x1111, 0, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1803  { "1111:0:3333:4444:5555:6666:7777:8888", { 0x1111, 0, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 } },
1804  { "1111::4444:5555:6666:7b7b:7b7b", { 0x1111, 0, 0, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1805  { "1111::4444:5555:6666:7777:8888", { 0x1111, 0, 0, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 } },
1806  { "1111::5555:6666:7b7b:7b7b", { 0x1111, 0, 0, 0, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1807  { "1111::5555:6666:7777:8888", { 0x1111, 0, 0, 0, 0x5555, 0x6666, 0x7777, 0x8888 } },
1808  { "1111::6666:7b7b:7b7b", { 0x1111, 0, 0, 0, 0, 0x6666, 0x7b7b, 0x7b7b } },
1809  { "1111::6666:7777:8888", { 0x1111, 0, 0, 0, 0, 0x6666, 0x7777, 0x8888 } },
1810  { "1111::7777:8888", { 0x1111, 0, 0, 0, 0, 0, 0x7777, 0x8888 } },
1811  { "1111::8888", { 0x1111, 0, 0, 0, 0, 0, 0, 0x8888 } },
1812  { "1:2:3:4:5:6:102:304", { 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x201, 0x403 } },
1813  { "1:2:3:4:5:6:7:8", { 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800 } },
1814  { "1:2:3:4:5:6::", { 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0, 0 } },
1815  { "1:2:3:4:5:6:0:8", { 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0, 0x800 } },
1816  { "2001:0:1234::c1c0:abcd:876", { 0x120, 0, 0x3412, 0, 0, 0xc0c1, 0xcdab, 0x7608 } },
1817  { "2001:0:4136:e378:8000:63bf:3fff:fdd2", { 0x120, 0, 0x3641, 0x78e3, 0x80, 0xbf63, 0xff3f, 0xd2fd } },
1818  { "2001:db8::1428:57ab", { 0x120, 0xb80d, 0, 0, 0, 0, 0x2814, 0xab57 } },
1819  { "2001:db8:1234:ffff:ffff:ffff:ffff:ffff", { 0x120, 0xb80d, 0x3412, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff } },
1820  { "2001:0:ce49:7601:2cad:dfff:7c94:fffe", { 0x120, 0, 0x49ce, 0x176, 0xad2c, 0xffdf, 0x947c, 0xfeff } },
1821  { "2001:db8:85a3::8a2e:370:7334", { 0x120, 0xb80d, 0xa385, 0, 0, 0x2e8a, 0x7003, 0x3473 } },
1822  { "3ffe:b00::1:0:0:a", { 0xfe3f, 0xb, 0, 0, 0x100, 0, 0, 0xa00 } },
1823  { "::a:b:c:d:e", { 0, 0, 0, 0xa00, 0xb00, 0xc00, 0xd00, 0xe00 } },
1824  { "::123.123.123.123", { 0, 0, 0, 0, 0, 0, 0x7b7b, 0x7b7b } },
1825  { "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff } },
1826  { "1111:2222:3333:4444:5555:6666:7777:1", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x100 } },
1827  { "1111:2222:3333:4444:5555:6666:7777:8888", { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x8888 } },
1828  { "1111:2222::", { 0x1111, 0x2222, 0, 0, 0, 0, 0, 0 } },
1829  { "1111::3333:4444:5555:6666:7777", { 0x1111, 0, 0, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777 } },
1830  { "1111:2222::", { 0x1111, 0x2222, 0, 0, 0, 0, 0, 0 } },
1831  { "1111::3333", { 0x1111, 0, 0, 0, 0, 0, 0, 0x3333 } },
1832  { "2001:0:1234::c1c0:abcd:876", { 0x120, 0, 0x3412, 0, 0, 0xc0c1, 0xcdab, 0x7608 } },
1833  { "2001::ffd3", { 0x120, 0, 0, 0, 0, 0, 0, 0xd3ff } },
1834  };
1835  const size_t testcount = sizeof(tests) / sizeof(tests[0]);
1836  unsigned int i;
1837 
1839  {
1840  skip("RtlIpv6AddressToStringA not available\n");
1841  return;
1842  }
1843 
1844  memset(buffer, '#', sizeof(buffer));
1845  buffer[sizeof(buffer)-1] = 0;
1846  memset(&ip, 0, sizeof(ip));
1848 
1849  len = strlen(buffer);
1850  ok(result == (buffer + len) && !strcmp(buffer, "::"),
1851  "got %p with '%s' (expected %p with '::')\n", result, buffer, buffer + len);
1852 
1854  ok(result == (LPCSTR)~0 || broken(result == (LPCSTR)len) /* WinXP / Win2k3 */,
1855  "got %p, expected %p\n", result, (LPCSTR)~0);
1856 
1857  for (i = 0; i < testcount; i++)
1858  {
1859  init_ip6(&ip, tests[i].ip);
1860  memset(buffer, '#', sizeof(buffer));
1861  buffer[sizeof(buffer)-1] = 0;
1862 
1864  len = strlen(buffer);
1865  ok(result == (buffer + len) && !strcmp(buffer, tests[i].address),
1866  "got %p with '%s' (expected %p with '%s')\n", result, buffer, buffer + len, tests[i].address);
1867 
1868  ok(buffer[45] == 0 || broken(buffer[45] != 0) /* WinXP / Win2k3 */,
1869  "expected data at buffer[45] to always be NULL\n");
1870  ok(buffer[46] == '#', "expected data at buffer[46] not to change\n");
1871  }
1872 }
1873 
1875 {
1876  CHAR buffer[70];
1877  NTSTATUS res;
1878  IN6_ADDR ip;
1879  ULONG len;
1880  struct
1881  {
1882  PCSTR address;
1883  ULONG scopeid;
1884  USHORT port;
1885  int ip[8];
1886  } tests[] =
1887  {
1888  /* ipv4 addresses & ISATAP addresses */
1889  { "::13.1.68.3", 0, 0, { 0, 0, 0, 0, 0, 0, 0x10d, 0x344 } },
1890  { "::13.1.68.3%1", 1, 0, { 0, 0, 0, 0, 0, 0, 0x10d, 0x344 } },
1891  { "::13.1.68.3%4294949819", 0xffffbbbb, 0, { 0, 0, 0, 0, 0, 0, 0x10d, 0x344 } },
1892  { "[::13.1.68.3%4294949819]:65518", 0xffffbbbb, 0xeeff, { 0, 0, 0, 0, 0, 0, 0x10d, 0x344 } },
1893  { "[::13.1.68.3%4294949819]:256", 0xffffbbbb, 1, { 0, 0, 0, 0, 0, 0, 0x10d, 0x344 } },
1894  { "[::13.1.68.3]:256", 0, 1, { 0, 0, 0, 0, 0, 0, 0x10d, 0x344 } },
1895 
1896  { "::1:d01:4403", 0, 0, { 0, 0, 0, 0, 0, 0x100, 0x10d, 0x344 } },
1897  { "::1:d01:4403%1", 1, 0, { 0, 0, 0, 0, 0, 0x100, 0x10d, 0x344 } },
1898  { "::1:d01:4403%4294949819", 0xffffbbbb, 0, { 0, 0, 0, 0, 0, 0x100, 0x10d, 0x344 } },
1899  { "[::1:d01:4403%4294949819]:65518", 0xffffbbbb, 0xeeff, { 0, 0, 0, 0, 0, 0x100, 0x10d, 0x344 } },
1900  { "[::1:d01:4403%4294949819]:256", 0xffffbbbb, 1, { 0, 0, 0, 0, 0, 0x100, 0x10d, 0x344 } },
1901  { "[::1:d01:4403]:256", 0, 1, { 0, 0, 0, 0, 0, 0x100, 0x10d, 0x344 } },
1902 
1903  { "1111:2222:3333:4444:0:5efe:129.144.52.38", 0, 0, { 0x1111, 0x2222, 0x3333, 0x4444, 0, 0xfe5e, 0x9081, 0x2634 } },
1904  { "1111:2222:3333:4444:0:5efe:129.144.52.38%1", 1, 0, { 0x1111, 0x2222, 0x3333, 0x4444, 0, 0xfe5e, 0x9081, 0x2634 } },
1905  { "1111:2222:3333:4444:0:5efe:129.144.52.38%4294949819", 0xffffbbbb, 0, { 0x1111, 0x2222, 0x3333, 0x4444, 0, 0xfe5e, 0x9081, 0x2634 } },
1906  { "[1111:2222:3333:4444:0:5efe:129.144.52.38%4294949819]:65518",0xffffbbbb, 0xeeff, { 0x1111, 0x2222, 0x3333, 0x4444, 0, 0xfe5e, 0x9081, 0x2634 } },
1907  { "[1111:2222:3333:4444:0:5efe:129.144.52.38%4294949819]:256", 0xffffbbbb, 1, { 0x1111, 0x2222, 0x3333, 0x4444, 0, 0xfe5e, 0x9081, 0x2634 } },
1908  { "[1111:2222:3333:4444:0:5efe:129.144.52.38]:256", 0, 1, { 0x1111, 0x2222, 0x3333, 0x4444, 0, 0xfe5e, 0x9081, 0x2634 } },
1909 
1910  { "::1", 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
1911  { "::1%1", 1, 0, { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
1912  { "::1%4294949819", 0xffffbbbb, 0, { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
1913  { "[::1%4294949819]:65518", 0xffffbbbb, 0xeeff, { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
1914  { "[::1%4294949819]:256", 0xffffbbbb, 1, { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
1915  { "[::1]:256", 0, 1, { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
1916 
1917  { "1111:2222:3333:4444:5555:6666:7b7b:7b7b", 0, 0, { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1918  { "1111:2222:3333:4444:5555:6666:7b7b:7b7b%1", 1, 0, { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1919  { "1111:2222:3333:4444:5555:6666:7b7b:7b7b%4294949819", 0xffffbbbb, 0, { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1920  { "[1111:2222:3333:4444:5555:6666:7b7b:7b7b%4294949819]:65518", 0xffffbbbb, 0xeeff, { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1921  { "[1111:2222:3333:4444:5555:6666:7b7b:7b7b%4294949819]:256", 0xffffbbbb, 1, { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1922  { "[1111:2222:3333:4444:5555:6666:7b7b:7b7b]:256", 0, 1, { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7b7b, 0x7b7b } },
1923 
1924  { "1111::", 0, 0, { 0x1111, 0, 0, 0, 0, 0, 0, 0 } },
1925  { "1111::%1", 1, 0, { 0x1111, 0, 0, 0, 0, 0, 0, 0 } },
1926  { "1111::%4294949819", 0xffffbbbb, 0, { 0x1111, 0, 0, 0, 0, 0, 0, 0 } },
1927  { "[1111::%4294949819]:65518", 0xffffbbbb, 0xeeff, { 0x1111, 0, 0, 0, 0, 0, 0, 0 } },
1928  { "[1111::%4294949819]:256", 0xffffbbbb, 1, { 0x1111, 0, 0, 0, 0, 0, 0, 0 } },
1929  { "[1111::]:256", 0, 1, { 0x1111, 0, 0, 0, 0, 0, 0, 0 } },
1930 
1931  { "2001::ffd3", 0, 0, { 0x120, 0, 0, 0, 0, 0, 0, 0xd3ff } },
1932  { "2001::ffd3%1", 1, 0, { 0x120, 0, 0, 0, 0, 0, 0, 0xd3ff } },
1933  { "2001::ffd3%4294949819", 0xffffbbbb, 0, { 0x120, 0, 0, 0, 0, 0, 0, 0xd3ff } },
1934  { "[2001::ffd3%4294949819]:65518", 0xffffbbbb, 0xeeff, { 0x120, 0, 0, 0, 0, 0, 0, 0xd3ff } },
1935  { "[2001::ffd3%4294949819]:256", 0xffffbbbb, 1, { 0x120, 0, 0, 0, 0, 0, 0, 0xd3ff } },
1936  { "[2001::ffd3]:256", 0, 1, { 0x120, 0, 0, 0, 0, 0, 0, 0xd3ff } },
1937  };
1938  const size_t testcount = sizeof(tests) / sizeof(tests[0]);
1939  unsigned int i;
1940 
1941  if (!pRtlIpv6AddressToStringExA)
1942  {
1943  skip("RtlIpv6AddressToStringExA not available\n");
1944  return;
1945  }
1946 
1947  memset(buffer, '#', sizeof(buffer));
1948  buffer[sizeof(buffer)-1] = 0;
1949  memset(&ip, 0, sizeof(ip));
1950  len = sizeof(buffer);
1951  res = pRtlIpv6AddressToStringExA(&ip, 0, 0, buffer, &len);
1952 
1953  ok(res == STATUS_SUCCESS, "[validate] res = 0x%08x, expected STATUS_SUCCESS\n", res);
1954  ok(len == 3 && !strcmp(buffer, "::"),
1955  "got len %d with '%s' (expected 3 with '::')\n", len, buffer);
1956 
1957  memset(buffer, '#', sizeof(buffer));
1958  buffer[sizeof(buffer)-1] = 0;
1959 
1960  len = sizeof(buffer);
1961  res = pRtlIpv6AddressToStringExA(NULL, 0, 0, buffer, &len);
1962  ok(res == STATUS_INVALID_PARAMETER, "[null ip] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
1963 
1964  len = sizeof(buffer);
1965  res = pRtlIpv6AddressToStringExA(&ip, 0, 0, NULL, &len);
1966  ok(res == STATUS_INVALID_PARAMETER, "[null buffer] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
1967 
1968  res = pRtlIpv6AddressToStringExA(&ip, 0, 0, buffer, NULL);
1969  ok(res == STATUS_INVALID_PARAMETER, "[null length] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
1970 
1971  len = 2;
1972  memset(buffer, '#', sizeof(buffer));
1973  buffer[sizeof(buffer)-1] = 0;
1974  res = pRtlIpv6AddressToStringExA(&ip, 0, 0, buffer, &len);
1975  ok(res == STATUS_INVALID_PARAMETER, "[null length] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
1976  ok(buffer[0] == '#', "got first char %c (expected '#')\n", buffer[0]);
1977  ok(len == 3, "got len %d (expected len 3)\n", len);
1978 
1979  for (i = 0; i < testcount; i++)
1980  {
1981  init_ip6(&ip, tests[i].ip);
1982  len = sizeof(buffer);
1983  memset(buffer, '#', sizeof(buffer));
1984  buffer[sizeof(buffer)-1] = 0;
1985 
1986  res = pRtlIpv6AddressToStringExA(&ip, tests[i].scopeid, tests[i].port, buffer, &len);
1987 
1988  ok(res == STATUS_SUCCESS, "[validate] res = 0x%08x, expected STATUS_SUCCESS\n", res);
1989  ok(len == (strlen(tests[i].address) + 1) && !strcmp(buffer, tests[i].address),
1990  "got len %d with '%s' (expected %d with '%s')\n", len, buffer, (int)strlen(tests[i].address), tests[i].address);
1991  }
1992 }
1993 
1994 static void compare_RtlIpv6StringToAddressW(PCSTR name_a, int terminator_offset_a,
1995  const struct in6_addr *addr_a, NTSTATUS res_a)
1996 {
1997  WCHAR name[512];
1998  NTSTATUS res;
1999  IN6_ADDR ip;
2000  PCWSTR terminator;
2001 
2002  if (!pRtlIpv6StringToAddressW)
2003  return;
2004 
2005  pRtlMultiByteToUnicodeN(name, sizeof(name), NULL, name_a, strlen(name_a) + 1);
2006 
2007  init_ip6(&ip, NULL);
2008  terminator = (void *)0xdeadbeef;
2009  res = pRtlIpv6StringToAddressW(name, &terminator, &ip);
2010  ok(res == res_a, "[W:%s] res = 0x%08x, expected 0x%08x\n", name_a, res, res_a);
2011 
2012  if (terminator_offset_a < 0)
2013  {
2014  ok(terminator == (void *)0xdeadbeef,
2015  "[W:%s] terminator = %p, expected it not to change\n",
2016  name_a, terminator);
2017  }
2018  else
2019  {
2020  ok(terminator == name + terminator_offset_a,
2021  "[W:%s] terminator = %p, expected %p\n",
2022  name_a, terminator, name + terminator_offset_a);
2023  }
2024 
2025  ok(!memcmp(&ip, addr_a, sizeof(ip)),
2026  "[W:%s] ip = %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
2027  name_a,
2028  ip.s6_words[0], ip.s6_words[1], ip.s6_words[2], ip.s6_words[3],
2029  ip.s6_words[4], ip.s6_words[5], ip.s6_words[6], ip.s6_words[7],
2030  addr_a->s6_words[0], addr_a->s6_words[1], addr_a->s6_words[2], addr_a->s6_words[3],
2031  addr_a->s6_words[4], addr_a->s6_words[5], addr_a->s6_words[6], addr_a->s6_words[7]);
2032 }
2033 
2035 {
2036  NTSTATUS res;
2037  IN6_ADDR ip, expected_ip;
2038  PCSTR terminator;
2039  unsigned int i;
2040 
2041  if (!pRtlIpv6StringToAddressW)
2042  {
2043  skip("RtlIpv6StringToAddressW not available\n");
2044  /* we can continue, just not test W */
2045  }
2046 
2047  if (!pRtlIpv6StringToAddressA)
2048  {
2049  skip("RtlIpv6StringToAddressA not available\n");
2050  return; /* all tests are centered around A, we cannot continue */
2051  }
2052 
2053  res = pRtlIpv6StringToAddressA("::", &terminator, &ip);
2054  ok(res == STATUS_SUCCESS, "[validate] res = 0x%08x, expected STATUS_SUCCESS\n", res);
2055  if (0)
2056  {
2057  /* any of these crash */
2058  res = pRtlIpv6StringToAddressA(NULL, &terminator, &ip);
2059  ok(res == STATUS_INVALID_PARAMETER, "[null string] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
2060  res = pRtlIpv6StringToAddressA("::", NULL, &ip);
2061  ok(res == STATUS_INVALID_PARAMETER, "[null terminator] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
2062  res = pRtlIpv6StringToAddressA("::", &terminator, NULL);
2063  ok(res == STATUS_INVALID_PARAMETER, "[null result] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
2064  }
2065 
2066  /* sanity check */
2067  ok(sizeof(ip) == sizeof(USHORT)* 8, "sizeof(ip)\n");
2068 
2069  for (i = 0; i < ipv6_testcount; i++)
2070  {
2071  init_ip6(&ip, NULL);
2072  terminator = (void *)0xdeadbeef;
2073  res = pRtlIpv6StringToAddressA(ipv6_tests[i].address, &terminator, &ip);
2074  compare_RtlIpv6StringToAddressW(ipv6_tests[i].address, (terminator != (void *)0xdeadbeef) ?
2075  (terminator - ipv6_tests[i].address) : -1, &ip, res);
2076 
2077  if (ipv6_tests[i].flags & win_broken_6)
2078  {
2080  "[%s] res = 0x%08x, expected 0x%08x\n",
2082 
2084  continue;
2085  }
2086  else
2087  {
2088  ok(res == ipv6_tests[i].res,
2089  "[%s] res = 0x%08x, expected 0x%08x\n",
2091  }
2092 
2093  if (ipv6_tests[i].terminator_offset < 0)
2094  {
2095  ok(terminator == (void *)0xdeadbeef,
2096  "[%s] terminator = %p, expected it not to change\n",
2097  ipv6_tests[i].address, terminator);
2098  }
2099  else if (ipv6_tests[i].flags & win_broken_6)
2100  {
2101  PCSTR expected = ipv6_tests[i].address + ipv6_tests[i].terminator_offset;
2102  ok(terminator == expected || broken(terminator == expected + 2),
2103  "[%s] terminator = %p, expected %p\n",
2104  ipv6_tests[i].address, terminator, expected);
2105  }
2106  else
2107  {
2108  ok(terminator == ipv6_tests[i].address + ipv6_tests[i].terminator_offset,
2109  "[%s] terminator = %p, expected %p\n",
2111  }
2112 
2113  init_ip6(&expected_ip, ipv6_tests[i].ip);
2114  ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
2115  "[%s] ip = %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
2116  ipv6_tests[i].address,
2117  ip.s6_words[0], ip.s6_words[1], ip.s6_words[2], ip.s6_words[3],
2118  ip.s6_words[4], ip.s6_words[5], ip.s6_words[6], ip.s6_words[7],
2119  expected_ip.s6_words[0], expected_ip.s6_words[1], expected_ip.s6_words[2], expected_ip.s6_words[3],
2120  expected_ip.s6_words[4], expected_ip.s6_words[5], expected_ip.s6_words[6], expected_ip.s6_words[7]);
2121  }
2122 }
2123 
2124 static void compare_RtlIpv6StringToAddressExW(PCSTR name_a, const struct in6_addr *addr_a, HRESULT res_a, ULONG scope_a, USHORT port_a)
2125 {
2126  WCHAR name[512];
2127  NTSTATUS res;
2128  IN6_ADDR ip;
2129  ULONG scope = 0xbadf00d;
2130  USHORT port = 0xbeef;
2131 
2132  if (!pRtlIpv6StringToAddressExW)
2133  return;
2134 
2135  pRtlMultiByteToUnicodeN(name, sizeof(name), NULL, name_a, strlen(name_a) + 1);
2136 
2137  init_ip6(&ip, NULL);
2138  res = pRtlIpv6StringToAddressExW(name, &ip, &scope, &port);
2139 
2140  ok(res == res_a, "[W:%s] res = 0x%08x, expected 0x%08x\n", name_a, res, res_a);
2141  ok(scope == scope_a, "[W:%s] scope = 0x%08x, expected 0x%08x\n", name_a, scope, scope_a);
2142  ok(port == port_a, "[W:%s] port = 0x%08x, expected 0x%08x\n", name_a, port, port_a);
2143 
2144  ok(!memcmp(&ip, addr_a, sizeof(ip)),
2145  "[W:%s] ip = %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
2146  name_a,
2147  ip.s6_words[0], ip.s6_words[1], ip.s6_words[2], ip.s6_words[3],
2148  ip.s6_words[4], ip.s6_words[5], ip.s6_words[6], ip.s6_words[7],
2149  addr_a->s6_words[0], addr_a->s6_words[1], addr_a->s6_words[2], addr_a->s6_words[3],
2150  addr_a->s6_words[4], addr_a->s6_words[5], addr_a->s6_words[6], addr_a->s6_words[7]);
2151 }
2152 
2154 {
2155  NTSTATUS res;
2156  IN6_ADDR ip, expected_ip;
2157  ULONG scope;
2158  USHORT port;
2159  static const struct
2160  {
2161  PCSTR address;
2162  NTSTATUS res;
2163  ULONG scope;
2164  USHORT port;
2165  int ip[8];
2166  } ipv6_ex_tests[] =
2167  {
2168  { "[::]", STATUS_SUCCESS, 0, 0,
2169  { 0, 0, 0, 0, 0, 0, 0, 0 } },
2170  { "[::1]:8080", STATUS_SUCCESS, 0, 0x901f,
2171  { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
2172  { "[::1]:0x80", STATUS_SUCCESS, 0, 0x8000,
2173  { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
2174  { "[::1]:0X80", STATUS_SUCCESS, 0, 0x8000,
2175  { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
2176  { "[::1]:080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2177  { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
2178  { "[::1]:800000000080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2179  { 0, 0, 0, 0, 0, 0, 0, 0x100 } },
2180  { "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80", STATUS_SUCCESS, 0, 0x5000,
2181  { 0xdcfe, 0x98ba, 0x5476, 0x1032, 0xdcfe, 0x98ba, 0x5476, 0x1032 } },
2182  { "[1080:0:0:0:8:800:200C:417A]:1234", STATUS_SUCCESS, 0, 0xd204,
2183  { 0x8010, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2184  { "[3ffe:2a00:100:7031::1]:8080", STATUS_SUCCESS, 0, 0x901f,
2185  { 0xfe3f, 0x2a, 1, 0x3170, 0, 0, 0, 0x100 } },
2186  { "[ 3ffe:2a00:100:7031::1]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2187  { -1 } },
2188  { "[3ffe:2a00:100:7031::1 ]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2189  { 0xfe3f, 0x2a, 1, 0x3170, 0, 0, 0, 0x100 } },
2190  { "[3ffe:2a00:100:7031::1].8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2191  { 0xfe3f, 0x2a, 1, 0x3170, 0, 0, 0, 0x100 } },
2192  { "[1080::8:800:200C:417A]:8080", STATUS_SUCCESS, 0, 0x901f,
2193  { 0x8010, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2194  { "[1080::8:800:200C:417A]!8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2195  { 0x8010, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2196  { "[::FFFF:129.144.52.38]:80", STATUS_SUCCESS, 0, 0x5000,
2197  { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
2198  { "[::FFFF:129.144.52.38]:-80", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2199  { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
2200  { "[::FFFF:129.144.52.38]:999999999999", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2201  { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
2202  { "[::FFFF:129.144.52.38%-8]:80", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2203  { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
2204  { "[::FFFF:129.144.52.38]:80", STATUS_SUCCESS, 0, 0x5000,
2205  { 0, 0, 0, 0, 0, 0xffff, 0x9081, 0x2634 } },
2206  { "[12345::6:7:8]:80", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2207  { -1 } },
2208  { "[ff01::8:800:200C:417A%16]:8080", STATUS_SUCCESS, 16, 0x901f,
2209  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2210  { "[ff01::8:800:200C:417A%100]:8080", STATUS_SUCCESS, 100, 0x901f,
2211  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2212  { "[ff01::8:800:200C:417A%1000]:8080", STATUS_SUCCESS, 1000, 0x901f,
2213  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2214  { "[ff01::8:800:200C:417A%10000]:8080", STATUS_SUCCESS, 10000, 0x901f,
2215  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2216  { "[ff01::8:800:200C:417A%1000000]:8080", STATUS_SUCCESS, 1000000, 0x901f,
2217  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2218  { "[ff01::8:800:200C:417A%4294967295]:8080", STATUS_SUCCESS, 0xffffffff, 0x901f,
2219  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2220  { "[ff01::8:800:200C:417A%4294967296]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2221  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2222  { "[ff01::8:800:200C:417A%-1]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2223  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2224  { "[ff01::8:800:200C:417A%0]:8080", STATUS_SUCCESS, 0, 0x901f,
2225  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2226  { "[ff01::8:800:200C:417A%1", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2227  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2228  { "[ff01::8:800:200C:417A%0x1000]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2229  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2230  { "[ff01::8:800:200C:417A/16]:8080", STATUS_INVALID_PARAMETER, 0xbadf00d, 0xbeef,
2231  { 0x1ff, 0, 0, 0, 0x800, 8, 0xc20, 0x7a41 } },
2232  };
2233  const unsigned int ipv6_ex_testcount = sizeof(ipv6_ex_tests) / sizeof(ipv6_ex_tests[0]);
2234  const char *simple_ip = "::";
2235  unsigned int i;
2236 
2237  if (!pRtlIpv6StringToAddressExW)
2238  {
2239  skip("RtlIpv6StringToAddressExW not available\n");
2240  /* we can continue, just not test W */
2241  }
2242 
2243  if (!pRtlIpv6StringToAddressExA)
2244  {
2245  skip("RtlIpv6StringToAddressExA not available\n");
2246  return;
2247  }
2248 
2249  res = pRtlIpv6StringToAddressExA(simple_ip, &ip, &scope, &port);
2250  ok(res == STATUS_SUCCESS, "[validate] res = 0x%08x, expected STATUS_SUCCESS\n", res);
2251 
2252  init_ip6(&ip, NULL);
2253  init_ip6(&expected_ip, NULL);
2254  scope = 0xbadf00d;
2255  port = 0xbeef;
2256  res = pRtlIpv6StringToAddressExA(NULL, &ip, &scope, &port);
2258  "[null string] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
2259  ok(scope == 0xbadf00d, "[null string] scope = 0x%08x, expected 0xbadf00d\n", scope);
2260  ok(port == 0xbeef, "[null string] port = 0x%08x, expected 0xbeef\n", port);
2261  ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
2262  "[null string] ip is changed, expected it not to change\n");
2263 
2264 
2265  init_ip6(&ip, NULL);
2266  scope = 0xbadf00d;
2267  port = 0xbeef;
2268  res = pRtlIpv6StringToAddressExA(simple_ip, NULL, &scope, &port);
2270  "[null result] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
2271  ok(scope == 0xbadf00d, "[null result] scope = 0x%08x, expected 0xbadf00d\n", scope);
2272  ok(port == 0xbeef, "[null result] port = 0x%08x, expected 0xbeef\n", port);
2273  ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
2274  "[null result] ip is changed, expected it not to change\n");
2275 
2276  init_ip6(&ip, NULL);
2277  scope = 0xbadf00d;
2278  port = 0xbeef;
2279  res = pRtlIpv6StringToAddressExA(simple_ip, &ip, NULL, &port);
2281  "[null scope] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
2282  ok(scope == 0xbadf00d, "[null scope] scope = 0x%08x, expected 0xbadf00d\n", scope);
2283  ok(port == 0xbeef, "[null scope] port = 0x%08x, expected 0xbeef\n", port);
2284  ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
2285  "[null scope] ip is changed, expected it not to change\n");
2286 
2287  init_ip6(&ip, NULL);
2288  scope = 0xbadf00d;
2289  port = 0xbeef;
2290  res = pRtlIpv6StringToAddressExA(simple_ip, &ip, &scope, NULL);
2292  "[null port] res = 0x%08x, expected STATUS_INVALID_PARAMETER\n", res);
2293  ok(scope == 0xbadf00d, "[null port] scope = 0x%08x, expected 0xbadf00d\n", scope);
2294  ok(port == 0xbeef, "[null port] port = 0x%08x, expected 0xbeef\n", port);
2295  ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
2296  "[null port] ip is changed, expected it not to change\n");
2297 
2298  /* sanity check */
2299  ok(sizeof(ip) == sizeof(USHORT)* 8, "sizeof(ip)\n");
2300 
2301  /* first we run all ip related tests, to make sure someone didnt accidentally reimplement instead of re-use. */
2302  for (i = 0; i < ipv6_testcount; i++)
2303  {
2304  ULONG scope = 0xbadf00d;
2305  USHORT port = 0xbeef;
2306  NTSTATUS expect_ret = (ipv6_tests[i].flags & ex_fail_6) ? STATUS_INVALID_PARAMETER : ipv6_tests[i].res;
2307 
2308  if (ipv6_tests[i].flags & ex_skip_6)
2309  continue;
2310 
2311  init_ip6(&ip, NULL);
2312  res = pRtlIpv6StringToAddressExA(ipv6_tests[i].address, &ip, &scope, &port);
2314 
2315  /* make sure nothing was changed if this function fails. */
2317  {
2318  ok(scope == 0xbadf00d, "[%s] scope = 0x%08x, expected 0xbadf00d\n",
2319  ipv6_tests[i].address, scope);
2320  ok(port == 0xbeef, "[%s] port = 0x%08x, expected 0xbeef\n",
2321  ipv6_tests[i].address, port);
2322  }
2323  else
2324  {
2325  ok(scope != 0xbadf00d, "[%s] scope = 0x%08x, not expected 0xbadf00d\n",
2326  ipv6_tests[i].address, scope);
2327  ok(port != 0xbeef, "[%s] port = 0x%08x, not expected 0xbeef\n",
2328  ipv6_tests[i].address, port);
2329  }
2330 
2331  if (ipv6_tests[i].flags & win_broken_6)
2332  {
2333  ok(res == expect_ret || broken(res == STATUS_INVALID_PARAMETER),
2334  "[%s] res = 0x%08x, expected 0x%08x\n", ipv6_tests[i].address, res, expect_ret);
2335 
2337  continue;
2338  }
2339  else
2340  {
2341  ok(res == expect_ret, "[%s] res = 0x%08x, expected 0x%08x\n",
2342  ipv6_tests[i].address, res, expect_ret);
2343  }
2344 
2345  /* If ex fails but non-ex does not we cannot check if the part that is converted
2346  before it failed was correct, since there is no data for it in the table. */
2347  if (res == expect_ret)
2348  {
2349  init_ip6(&expected_ip, ipv6_tests[i].ip);
2350  ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
2351  "[%s] ip = %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
2352  ipv6_tests[i].address,
2353  ip.s6_words[0], ip.s6_words[1], ip.s6_words[2], ip.s6_words[3],
2354  ip.s6_words[4], ip.s6_words[5], ip.s6_words[6], ip.s6_words[7],
2355  expected_ip.s6_words[0], expected_ip.s6_words[1], expected_ip.s6_words[2], expected_ip.s6_words[3],
2356  expected_ip.s6_words[4], expected_ip.s6_words[5], expected_ip.s6_words[6], expected_ip.s6_words[7]);
2357  }
2358  }
2359 
2360  /* now we run scope / port related tests */
2361  for (i = 0; i < ipv6_ex_testcount; i++)
2362  {
2363  scope = 0xbadf00d;
2364  port = 0xbeef;
2365  init_ip6(&ip, NULL);
2366  res = pRtlIpv6StringToAddressExA(ipv6_ex_tests[i].address, &ip, &scope, &port);
2367  compare_RtlIpv6StringToAddressExW(ipv6_ex_tests[i].address, &ip, res, scope, port);
2368 
2369  ok(res == ipv6_ex_tests[i].res, "[%s] res = 0x%08x, expected 0x%08x\n",
2370  ipv6_ex_tests[i].address, res, ipv6_ex_tests[i].res);
2371  ok(scope == ipv6_ex_tests[i].scope, "[%s] scope = 0x%08x, expected 0x%08x\n",
2372  ipv6_ex_tests[i].address, scope, ipv6_ex_tests[i].scope);
2373  ok(port == ipv6_ex_tests[i].port, "[%s] port = 0x%08x, expected 0x%08x\n",
2374  ipv6_ex_tests[i].address, port, ipv6_ex_tests[i].port);
2375 
2376  init_ip6(&expected_ip, ipv6_ex_tests[i].ip);
2377  ok(!memcmp(&ip, &expected_ip, sizeof(ip)),
2378  "[%s] ip = %x:%x:%x:%x:%x:%x:%x:%x, expected %x:%x:%x:%x:%x:%x:%x:%x\n",
2379  ipv6_ex_tests[i].address,
2380  ip.s6_words[0], ip.s6_words[1], ip.s6_words[2], ip.s6_words[3],
2381  ip.s6_words[4], ip.s6_words[5], ip.s6_words[6], ip.s6_words[7],
2382  expected_ip.s6_words[0], expected_ip.s6_words[1], expected_ip.s6_words[2], expected_ip.s6_words[3],
2383  expected_ip.s6_words[4], expected_ip.s6_words[5], expected_ip.s6_words[6], expected_ip.s6_words[7]);
2384  }
2385 }
2386 
2387 static void test_LdrAddRefDll(void)
2388 {
2389  HMODULE mod, mod2;
2390  NTSTATUS status;
2391  BOOL ret;
2392 
2393  if (!pLdrAddRefDll)
2394  {
2395  win_skip( "LdrAddRefDll not supported\n" );
2396  return;
2397  }
2398 
2399  mod = LoadLibraryA("comctl32.dll");
2400  ok(mod != NULL, "got %p\n", mod);
2401  ret = FreeLibrary(mod);
2402  ok(ret, "got %d\n", ret);
2403 
2404  mod2 = GetModuleHandleA("comctl32.dll");
2405  ok(mod2 == NULL, "got %p\n", mod2);
2406 
2407  /* load, addref and release 2 times */
2408  mod = LoadLibraryA("comctl32.dll");
2409  ok(mod != NULL, "got %p\n", mod);
2410  status = pLdrAddRefDll(0, mod);
2411  ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
2412  ret = FreeLibrary(mod);
2413  ok(ret, "got %d\n", ret);
2414 
2415  mod2 = GetModuleHandleA("comctl32.dll");
2416  ok(mod2 != NULL, "got %p\n", mod2);
2417  ret = FreeLibrary(mod);
2418  ok(ret, "got %d\n", ret);
2419 
2420  mod2 = GetModuleHandleA("comctl32.dll");
2421  ok(mod2 == NULL, "got %p\n", mod2);
2422 
2423  /* pin refcount */
2424  mod = LoadLibraryA("comctl32.dll");
2425  ok(mod != NULL, "got %p\n", mod);
2426  status = pLdrAddRefDll(LDR_ADDREF_DLL_PIN, mod);
2427  ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
2428 
2429  ret = FreeLibrary(mod);
2430  ok(ret, "got %d\n", ret);
2431  ret = FreeLibrary(mod);
2432  ok(ret, "got %d\n", ret);
2433  ret = FreeLibrary(mod);
2434  ok(ret, "got %d\n", ret);
2435  ret = FreeLibrary(mod);
2436  ok(ret, "got %d\n", ret);
2437 
2438  mod2 = GetModuleHandleA("comctl32.dll");
2439  ok(mod2 != NULL, "got %p\n", mod2);
2440 }
2441 
2442 static void test_LdrLockLoaderLock(void)
2443 {
2444  ULONG_PTR magic;
2445  ULONG result;
2446  NTSTATUS status;
2447 
2448  if (!pLdrLockLoaderLock)
2449  {
2450  win_skip("LdrLockLoaderLock() is not available\n");
2451  return;
2452  }
2453 
2454  /* invalid flags */
2455  result = 10;
2456  magic = 0xdeadbeef;
2457  status = pLdrLockLoaderLock(0x10, &result, &magic);
2458  ok(status == STATUS_INVALID_PARAMETER_1, "got 0x%08x\n", status);
2459  ok(result == 0, "got %d\n", result);
2460  ok(magic == 0, "got %lx\n", magic);
2461 
2462  magic = 0xdeadbeef;
2463  status = pLdrLockLoaderLock(0x10, NULL, &magic);
2464  ok(status == STATUS_INVALID_PARAMETER_1, "got 0x%08x\n", status);
2465  ok(magic == 0, "got %lx\n", magic);
2466 
2467  result = 10;
2468  status = pLdrLockLoaderLock(0x10, &result, NULL);
2469  ok(status == STATUS_INVALID_PARAMETER_1, "got 0x%08x\n", status);
2470  ok(result == 0, "got %d\n", result);
2471 
2472  /* non-blocking mode, result is null */
2473  magic = 0xdeadbeef;
2474  status = pLdrLockLoaderLock(0x2, NULL, &magic);
2475  ok(status == STATUS_INVALID_PARAMETER_2, "got 0x%08x\n", status);
2476  ok(magic == 0, "got %lx\n", magic);
2477 
2478  /* magic pointer is null */
2479  result = 10;
2480  status = pLdrLockLoaderLock(0, &result, NULL);
2481  ok(status == STATUS_INVALID_PARAMETER_3, "got 0x%08x\n", status);
2482  ok(result == 0, "got %d\n", result);
2483 
2484  /* lock in non-blocking mode */
2485  result = 0;
2486  magic = 0;
2487  status = pLdrLockLoaderLock(0x2, &result, &magic);
2488  ok(status == STATUS_SUCCESS, "got 0x%08x\n", status);
2489  ok(result == 1, "got %d\n", result);
2490  ok(magic != 0, "got %lx\n", magic);
2491  pLdrUnlockLoaderLock(0, magic);
2492 }
2493 
2494 static void test_RtlCompressBuffer(void)
2495 {
2496  ULONG compress_workspace, decompress_workspace;
2497  static const UCHAR test_buffer[] = "WineWineWine";
2498  static UCHAR buf1[0x1000], buf2[0x1000];
2499  ULONG final_size, buf_size;
2500  UCHAR *workspace = NULL;
2501  NTSTATUS status;
2502 
2503  if (!pRtlCompressBuffer || !pRtlDecompressBuffer || !pRtlGetCompressionWorkSpaceSize)
2504  {
2505  win_skip("skipping RtlCompressBuffer tests, required functions not available\n");
2506  return;
2507  }
2508 
2509  compress_workspace = decompress_workspace = 0xdeadbeef;
2510  status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1, &compress_workspace,
2511  &decompress_workspace);
2512  ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
2513  ok(compress_workspace != 0, "got wrong compress_workspace %u\n", compress_workspace);
2514  workspace = HeapAlloc(GetProcessHeap(), 0, compress_workspace);
2515  ok(workspace != NULL, "HeapAlloc failed %d\n", GetLastError());
2516 
2517  /* test compression format / engine */
2518  final_size = 0xdeadbeef;
2519  status = pRtlCompressBuffer(COMPRESSION_FORMAT_NONE, test_buffer, sizeof(test_buffer),
2520  buf1, sizeof(buf1) - 1, 4096, &final_size, workspace);
2521  ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
2522  ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
2523 
2524  final_size = 0xdeadbeef;
2525  status = pRtlCompressBuffer(COMPRESSION_FORMAT_DEFAULT, test_buffer, sizeof(test_buffer),
2526  buf1, sizeof(buf1) - 1, 4096, &final_size, workspace);
2527  ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
2528  ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
2529 
2530  final_size = 0xdeadbeef;
2531  status = pRtlCompressBuffer(0xFF, test_buffer, sizeof(test_buffer),
2532  buf1, sizeof(buf1) - 1, 4096, &final_size, workspace);
2533  ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n", status);
2534  ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
2535 
2536  /* test compression */
2537  final_size = 0xdeadbeef;
2538  memset(buf1, 0x11, sizeof(buf1));
2539  status = pRtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, test_buffer, sizeof(test_buffer),
2540  buf1, sizeof(buf1), 4096, &final_size, workspace);
2541  ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
2542  ok((*(WORD *)buf1 & 0x7000) == 0x3000, "no chunk signature found %04x\n", *(WORD *)buf1);
2543  todo_wine
2544  ok(final_size < sizeof(test_buffer), "got wrong final_size %u\n", final_size);
2545 
2546  /* test decompression */
2547  buf_size = final_size;
2548  final_size = 0xdeadbeef;
2549  memset(buf2, 0x11, sizeof(buf2));
2550  status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf2, sizeof(buf2),
2551  buf1, buf_size, &final_size);
2552  ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
2553  ok(final_size == sizeof(test_buffer), "got wrong final_size %u\n", final_size);
2554  ok(!memcmp(buf2, test_buffer, sizeof(test_buffer)), "got wrong decoded data\n");
2555  ok(buf2[sizeof(test_buffer)] == 0x11, "too many bytes written\n");
2556 
2557  /* buffer too small */
2558  final_size = 0xdeadbeef;
2559  memset(buf1, 0x11, sizeof(buf1));
2560  status = pRtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, test_buffer, sizeof(test_buffer),
2561  buf1, 4, 4096, &final_size, workspace);
2562  ok(status == STATUS_BUFFER_TOO_SMALL, "got wrong status 0x%08x\n", status);
2563 
2564  HeapFree(GetProcessHeap(), 0, workspace);
2565 }
2566 
2568 {
2569  ULONG compress_workspace, decompress_workspace;
2570  NTSTATUS status;
2571 
2572  if (!pRtlGetCompressionWorkSpaceSize)
2573  {
2574  win_skip("RtlGetCompressionWorkSpaceSize is not available\n");
2575  return;
2576  }
2577 
2578  /* test invalid format / engine */
2579  status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_NONE, &compress_workspace,
2580  &decompress_workspace);
2581  ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
2582 
2583  status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_DEFAULT, &compress_workspace,
2584  &decompress_workspace);
2585  ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
2586 
2587  status = pRtlGetCompressionWorkSpaceSize(0xFF, &compress_workspace, &decompress_workspace);
2588  ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n", status);
2589 
2590  /* test LZNT1 with normal and maximum compression */
2591  compress_workspace = decompress_workspace = 0xdeadbeef;
2592  status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1, &compress_workspace,
2593  &decompress_workspace);
2594  ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
2595  ok(compress_workspace != 0, "got wrong compress_workspace %u\n", compress_workspace);
2596  ok(decompress_workspace == 0x1000, "got wrong decompress_workspace %u\n", decompress_workspace);
2597 
2598  compress_workspace = decompress_workspace = 0xdeadbeef;
2599  status = pRtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM,
2600  &compress_workspace, &decompress_workspace);
2601  ok(status == STATUS_SUCCESS, "got wrong status 0x%08x\n", status);
2602  ok(compress_workspace != 0, "got wrong compress_workspace %u\n", compress_workspace);
2603  ok(decompress_workspace == 0x1000, "got wrong decompress_workspace %u\n", decompress_workspace);
2604 }
2605 
2606 /* helper for test_RtlDecompressBuffer, checks if a chunk is incomplete */
2607 static BOOL is_incomplete_chunk(const UCHAR *compressed, ULONG compressed_size, BOOL check_all)
2608 {
2609  ULONG chunk_size;
2610 
2611  if (compressed_size <= sizeof(WORD))
2612  return TRUE;
2613 
2614  while (compressed_size >= sizeof(WORD))
2615  {
2616  chunk_size = (*(WORD *)compressed & 0xFFF) + 1;
2617  if (compressed_size < sizeof(WORD) + chunk_size)
2618  return TRUE;
2619  if (!check_all)
2620  break;
2621  compressed += sizeof(WORD) + chunk_size;
2622  compressed_size -= sizeof(WORD) + chunk_size;
2623  }
2624 
2625  return FALSE;
2626 }
2627 
2628 #define DECOMPRESS_BROKEN_FRAGMENT 1 /* < Win 7 */
2629 #define DECOMPRESS_BROKEN_TRUNCATED 2 /* broken on all machines */
2630 
2631 static void test_RtlDecompressBuffer(void)
2632 {
2633  static const struct
2634  {
2635  UCHAR compressed[32];
2636  ULONG compressed_size;
2637  NTSTATUS status;
2638  UCHAR uncompressed[32];
2639  ULONG uncompressed_size;
2640  DWORD broken_flags;
2641  }
2642  test_lznt[] =
2643  {
2644  /* 4 byte uncompressed chunk */
2645  {
2646  {0x03, 0x30, 'W', 'i', 'n', 'e'},
2647  6,
2649  "Wine",
2650  4,
2652  },
2653  /* 8 byte uncompressed chunk */
2654  {
2655  {0x07, 0x30, 'W', 'i', 'n', 'e', 'W', 'i', 'n', 'e'},
2656  10,
2658  "WineWine",
2659  8,
2661  },
2662  /* 4 byte compressed chunk */
2663  {
2664  {0x04, 0xB0, 0x00, 'W', 'i', 'n', 'e'},
2665  7,
2667  "Wine",
2668  4
2669  },
2670  /* 8 byte compressed chunk */
2671  {
2672  {0x08, 0xB0, 0x00, 'W', 'i', 'n', 'e', 'W', 'i', 'n', 'e'},
2673  11,
2675  "WineWine",
2676  8
2677  },
2678  /* compressed chunk using backwards reference */
2679  {
2680  {0x06, 0xB0, 0x10, 'W', 'i', 'n', 'e', 0x01, 0x30},
2681  9,
2683  "WineWine",
2684  8,
2686  },
2687  /* compressed chunk using backwards reference with length > bytes_read */
2688  {
2689  {0x06, 0xB0, 0x10, 'W', 'i', 'n', 'e', 0x05, 0x30},
2690  9,
2692  "WineWineWine",
2693  12,
2695  },
2696  /* same as above, but unused bits != 0 */
2697  {
2698  {0x06, 0xB0, 0x30, 'W', 'i', 'n', 'e', 0x01, 0x30},
2699  9,
2701  "WineWine",
2702  8,
2704  },
2705  /* compressed chunk without backwards reference and unused bits != 0 */
2706  {
2707  {0x01, 0xB0, 0x02, 'W'},
2708  4,
2710  "W",
2711  1
2712  },
2713  /* termination sequence after first chunk */
2714  {
2715  {0x03, 0x30, 'W', 'i', 'n', 'e', 0x00, 0x00, 0x03, 0x30, 'W', 'i', 'n', 'e'},
2716  14,
2718  "Wine",
2719  4,
2721  },
2722  /* compressed chunk using backwards reference with 4 bit offset, 12 bit length */
2723  {
2724  {0x14, 0xB0, 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
2725  0x00, 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
2726  0x01, 0x01, 0xF0},
2727  23,
2729  "ABCDEFGHIJKLMNOPABCD",
2730  20,
2732  },
2733  /* compressed chunk using backwards reference with 5 bit offset, 11 bit length */
2734  {
2735  {0x15, 0xB0, 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
2736  0x00, 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
2737  0x02, 'A', 0x00, 0x78},
2738  24,
2740  "ABCDEFGHIJKLMNOPABCD",
2741  20,
2743  },
2744  /* uncompressed chunk with invalid magic */
2745  {
2746  {0x03, 0x20, 'W', 'i', 'n', 'e'},
2747  6,
2749  "Wine",
2750  4,
2752  },
2753  /* compressed chunk with invalid magic */
2754  {
2755  {0x04, 0xA0, 0x00, 'W', 'i', 'n', 'e'},
2756  7,
2758  "Wine",
2759  4
2760  },
2761  /* garbage byte after end of buffer */
2762  {
2763  {0x00, 0xB0, 0x02, 0x01},
2764  4,
2766  "",
2767  0
2768  },
2769  /* empty compressed chunk */
2770  {
2771  {0x00, 0xB0, 0x00},
2772  3,
2774  "",
2775  0
2776  },
2777  /* empty compressed chunk with unused bits != 0 */
2778  {
2779  {0x00, 0xB0, 0x01},
2780  3,
2782  "",
2783  0
2784  },
2785  /* empty input buffer */
2786  {
2787  {0},
2788  0,
2790  },
2791  /* incomplete chunk header */
2792  {
2793  {0x01},
2794  1,
2796  },
2797  /* incomplete chunk header */
2798  {
2799  {0x00, 0x30},
2800  2,
2802  },
2803  /* compressed chunk with invalid backwards reference */
2804  {
2805  {0x06, 0xB0, 0x10, 'W', 'i', 'n', 'e', 0x05, 0x40},
2806  9,
2808  },
2809  /* compressed chunk with incomplete backwards reference */
2810  {
2811  {0x05, 0xB0, 0x10, 'W', 'i', 'n', 'e', 0x05},
2812  8,
2814  },
2815  /* incomplete uncompressed chunk */
2816  {
2817  {0x07, 0x30, 'W', 'i', 'n', 'e'},
2818  6,
2820  },
2821  /* incomplete compressed chunk */
2822  {
2823  {0x08, 0xB0, 0x00, 'W', 'i', 'n', 'e'},
2824  7,
2826  },
2827  /* two compressed chunks, the second one incomplete */
2828  {
2829  {0x00, 0xB0, 0x02, 0x00, 0xB0},
2830  5,
2832  }
2833  };
2834 
2835  static UCHAR buf[0x2000], workspace[0x1000];
2836  NTSTATUS status, expected_status;
2837  ULONG final_size;
2838  int i;
2839 
2840  if (!pRtlDecompressBuffer || !pRtlDecompressFragment)
2841  {
2842  win_skip("RtlDecompressBuffer or RtlDecompressFragment is not available\n");
2843  return;
2844  }
2845 
2846  /* test compression format / engine */
2847  final_size = 0xdeadbeef;
2848  status = pRtlDecompressBuffer(COMPRESSION_FORMAT_NONE, buf, sizeof(buf), test_lznt[0].compressed,
2849  test_lznt[0].compressed_size, &final_size);
2850  ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
2851  ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
2852 
2853  final_size = 0xdeadbeef;
2854  status = pRtlDecompressBuffer(COMPRESSION_FORMAT_DEFAULT, buf, sizeof(buf), test_lznt[0].compressed,
2855  test_lznt[0].compressed_size, &final_size);
2856  ok(status == STATUS_INVALID_PARAMETER, "got wrong status 0x%08x\n", status);
2857  ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
2858 
2859  final_size = 0xdeadbeef;
2860  status = pRtlDecompressBuffer(0xFF, buf, sizeof(buf), test_lznt[0].compressed,
2861  test_lznt[0].compressed_size, &final_size);
2862  ok(status == STATUS_UNSUPPORTED_COMPRESSION, "got wrong status 0x%08x\n", status);
2863  ok(final_size == 0xdeadbeef, "got wrong final_size %u\n", final_size);
2864 
2865  /* regular tests for RtlDecompressBuffer */
2866  for (i = 0; i < sizeof(test_lznt) / sizeof(test_lznt[0]); i++)
2867  {
2868  trace("Running test %d (compressed_size=%u, uncompressed_size=%u, status=0x%08x)\n",
2869  i, test_lznt[i].compressed_size, test_lznt[i].uncompressed_size, test_lznt[i].status);
2870 
2871  /* test with very big buffer */
2872  final_size = 0xdeadbeef;
2873  memset(buf, 0x11, sizeof(buf));
2874  status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_lznt[i].compressed,
2875  test_lznt[i].compressed_size, &final_size);
2877  (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)), "%d: got wrong status 0x%08x\n", i, status);
2878  if (!status)
2879  {
2880  ok(final_size == test_lznt[i].uncompressed_size,
2881  "%d: got wrong final_size %u\n", i, final_size);
2882  ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
2883  "%d: got wrong decoded data\n", i);
2884  ok(buf[test_lznt[i].uncompressed_size] == 0x11,
2885  "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size);
2886  }
2887 
2888  /* test that modifier for compression engine is ignored */
2889  final_size = 0xdeadbeef;
2890  memset(buf, 0x11, sizeof(buf));
2891  status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, buf, sizeof(buf),
2892  test_lznt[i].compressed, test_lznt[i].compressed_size, &final_size);
2894  (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)), "%d: got wrong status 0x%08x\n", i, status);
2895  if (!status)
2896  {
2897  ok(final_size == test_lznt[i].uncompressed_size,
2898  "%d: got wrong final_size %u\n", i, final_size);
2899  ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
2900  "%d: got wrong decoded data\n", i);
2901  ok(buf[test_lznt[i].uncompressed_size] == 0x11,
2902  "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size);
2903  }
2904 
2905  /* test with expected output size */
2906  if (test_lznt[i].uncompressed_size > 0)
2907  {
2908  final_size = 0xdeadbeef;
2909  memset(buf, 0x11, sizeof(buf));
2910  status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, test_lznt[i].uncompressed_size,
2911  test_lznt[i].compressed, test_lznt[i].compressed_size, &final_size);
2912  ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i, status);
2913  if (!status)
2914  {
2915  ok(final_size == test_lznt[i].uncompressed_size,
2916  "%d: got wrong final_size %u\n", i, final_size);
2917  ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
2918  "%d: got wrong decoded data\n", i);
2919  ok(buf[test_lznt[i].uncompressed_size] == 0x11,
2920  "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size);
2921  }
2922  }
2923 
2924  /* test with smaller output size */
2925  if (test_lznt[i].uncompressed_size > 1)
2926  {
2927  final_size = 0xdeadbeef;
2928  memset(buf, 0x11, sizeof(buf));
2929  status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, test_lznt[i].uncompressed_size - 1,
2930  test_lznt[i].compressed, test_lznt[i].compressed_size, &final_size);
2931  if (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_TRUNCATED)
2932  todo_wine
2933  ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
2934  else
2935  ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i, status);
2936  if (!status)
2937  {
2938  ok(final_size == test_lznt[i].uncompressed_size - 1,
2939  "%d: got wrong final_size %u\n", i, final_size);
2940  ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size - 1),
2941  "%d: got wrong decoded data\n", i);
2942  ok(buf[test_lznt[i].uncompressed_size - 1] == 0x11,
2943  "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size - 1);
2944  }
2945  }
2946 
2947  /* test with zero output size */
2948  final_size = 0xdeadbeef;
2949  memset(buf, 0x11, sizeof(buf));
2950  status = pRtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, buf, 0, test_lznt[i].compressed,
2951  test_lznt[i].compressed_size, &final_size);
2952  if (is_incomplete_chunk(test_lznt[i].compressed, test_lznt[i].compressed_size, FALSE))
2953  ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
2954  else
2955  {
2956  ok(status == STATUS_SUCCESS, "%d: got wrong status 0x%08x\n", i, status);
2957  ok(final_size == 0, "%d: got wrong final_size %u\n", i, final_size);
2958  ok(buf[0] == 0x11, "%d: buf[0] was modified\n", i);
2959  }
2960 
2961  /* test RtlDecompressFragment with offset = 0 */
2962  final_size = 0xdeadbeef;
2963  memset(buf, 0x11, sizeof(buf));
2964  status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_lznt[i].compressed,
2965  test_lznt[i].compressed_size, 0, &final_size, workspace);
2966  if (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)
2967  todo_wine
2968  ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
2969  else
2970  ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i, status);
2971  if (!status)
2972  {
2973  ok(final_size == test_lznt[i].uncompressed_size,
2974  "%d: got wrong final_size %u\n", i, final_size);
2975  ok(!memcmp(buf, test_lznt[i].uncompressed, test_lznt[i].uncompressed_size),
2976  "%d: got wrong decoded data\n", i);
2977  ok(buf[test_lznt[i].uncompressed_size] == 0x11,
2978  "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size);
2979  }
2980 
2981  /* test RtlDecompressFragment with offset = 1 */
2982  final_size = 0xdeadbeef;
2983  memset(buf, 0x11, sizeof(buf));
2984  status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_lznt[i].compressed,
2985  test_lznt[i].compressed_size, 1, &final_size, workspace);
2986  if (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)
2987  todo_wine
2988  ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
2989  else
2990  ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i, status);
2991  if (!status)
2992  {
2993  if (test_lznt[i].uncompressed_size == 0)
2994  {
2995  todo_wine
2996  ok(final_size == 4095, "%d: got wrong final_size %u\n", i, final_size);
2997  /* Buffer doesn't contain any useful value on Windows */
2998  ok(buf[4095] == 0x11, "%d: buf[4095] was modified\n", i);
2999  }
3000  else
3001  {
3002  ok(final_size == test_lznt[i].uncompressed_size - 1,
3003  "%d: got wrong final_size %u\n", i, final_size);
3004  ok(!memcmp(buf, test_lznt[i].uncompressed + 1, test_lznt[i].uncompressed_size - 1),
3005  "%d: got wrong decoded data\n", i);
3006  ok(buf[test_lznt[i].uncompressed_size - 1] == 0x11,
3007  "%d: buf[%u] was modified\n", i, test_lznt[i].uncompressed_size - 1);
3008  }
3009  }
3010 
3011  /* test RtlDecompressFragment with offset = 4095 */
3012  final_size = 0xdeadbeef;
3013  memset(buf, 0x11, sizeof(buf));
3014  status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_lznt[i].compressed,
3015  test_lznt[i].compressed_size, 4095, &final_size, workspace);
3016  if (test_lznt[i].broken_flags & DECOMPRESS_BROKEN_FRAGMENT)
3017  todo_wine
3018  ok(status == STATUS_BAD_COMPRESSION_BUFFER, "%d: got wrong status 0x%08x\n", i, status);
3019  else
3020  ok(status == test_lznt[i].status, "%d: got wrong status 0x%08x\n", i, status);
3021  if (!status)
3022  {
3023  todo_wine
3024  ok(final_size == 1, "%d: got wrong final_size %u\n", i, final_size);
3025  todo_wine
3026  ok(buf[0] == 0, "%d: padding is not zero\n", i);
3027  ok(buf[1] == 0x11, "%d: buf[1] was modified\n", i);
3028  }
3029 
3030  /* test RtlDecompressFragment with offset = 4096 */
3031  final_size = 0xdeadbeef;
3032  memset(buf, 0x11, sizeof(buf));
3033  status = pRtlDecompressFragment(COMPRESSION_FORMAT_LZNT1, buf, sizeof(buf), test_lznt[i].compressed,
3034  test_lznt[i].compressed_size, 4096, &final_size, workspace);
3035  expected_status = is_incomplete_chunk(test_lznt[i].compressed, test_lznt[i].compressed_size, TRUE) ?
3036  test_lznt[i].status : STATUS_SUCCESS;
3037  ok(status == expected_status, "%d: got wrong status 0x%08x, expected 0x%08x\n", i, status, expected_status);
3038  if (!status)
3039  {
3040  ok(final_size == 0, "%d: got wrong final_size %u\n", i, final_size);
3041  ok(buf[0] == 0x11, "%d: buf[4096] was modified\n", i);
3042  }
3043  }
3044 }
3045 
3046 #undef DECOMPRESS_BROKEN_FRAGMENT
3047 #undef DECOMPRESS_BROKEN_TRUNCATED
3048 
3050 {
3053 };
3054 
3056 {
3057  struct critsect_locked_info *info = param;
3058  DWORD ret;
3059 
3060  ret = pRtlIsCriticalSectionLocked(&info->crit);
3061  ok(ret == TRUE, "expected TRUE, got %u\n", ret);
3062  ret = pRtlIsCriticalSectionLockedByThread(&info->crit);
3063  ok(ret == FALSE, "expected FALSE, got %u\n", ret);
3064 
3065  ReleaseSemaphore(info->semaphores[0], 1, NULL);
3066  ret = WaitForSingleObject(info->semaphores[1], 1000);
3067  ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
3068 
3069  ret = pRtlIsCriticalSectionLocked(&info->crit);
3070  ok(ret == FALSE, "expected FALSE, got %u\n", ret);
3071  ret = pRtlIsCriticalSectionLockedByThread(&info->crit);
3072  ok(ret == FALSE, "expected FALSE, got %u\n", ret);
3073 
3074  EnterCriticalSection(&info->crit);
3075 
3076  ret = pRtlIsCriticalSectionLocked(&info->crit);
3077  ok(ret == TRUE, "expected TRUE, got %u\n", ret);
3078  ret = pRtlIsCriticalSectionLockedByThread(&info->crit);
3079  ok(ret == TRUE, "expected TRUE, got %u\n", ret);
3080 
3081  ReleaseSemaphore(info->semaphores[0], 1, NULL);
3082  ret = WaitForSingleObject(info->semaphores[1], 1000);
3083  ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
3084 
3085  LeaveCriticalSection(&info->crit);
3086  return 0;
3087 }
3088 
3090 {
3091  struct critsect_locked_info info;
3092  HANDLE thread;
3093  BOOL ret;
3094 
3095  if (!pRtlIsCriticalSectionLocked || !pRtlIsCriticalSectionLockedByThread)
3096  {
3097  win_skip("skipping RtlIsCriticalSectionLocked tests, required functions not available\n");
3098  return;
3099  }
3100 
3102  info.semaphores[0] = CreateSemaphoreW(NULL, 0, 1, NULL);
3103  ok(info.semaphores[0] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
3104  info.semaphores[1] = CreateSemaphoreW(NULL, 0, 1, NULL);
3105  ok(info.semaphores[1] != NULL, "CreateSemaphore failed with %u\n", GetLastError());
3106 
3107  ret = pRtlIsCriticalSectionLocked(&info.crit);
3108  ok(ret == FALSE, "expected FALSE, got %u\n", ret);
3109  ret = pRtlIsCriticalSectionLockedByThread(&info.crit);
3110  ok(ret == FALSE, "expected FALSE, got %u\n", ret);
3111 
3112  EnterCriticalSection(&info.crit);
3113 
3114  ret = pRtlIsCriticalSectionLocked(&info.crit);
3115  ok(ret == TRUE, "expected TRUE, got %u\n", ret);
3116  ret = pRtlIsCriticalSectionLockedByThread(&info.crit);
3117  ok(ret == TRUE, "expected TRUE, got %u\n", ret);
3118 
3120  ok(thread != NULL, "CreateThread failed with %u\n", GetLastError());
3121  ret = WaitForSingleObject(info.semaphores[0], 1000);
3122  ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
3123 
3124  LeaveCriticalSection(&info.crit);
3125 
3126  ReleaseSemaphore(info.semaphores[1], 1, NULL);
3127  ret = WaitForSingleObject(info.semaphores[0], 1000);
3128  ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
3129 
3130  ret = pRtlIsCriticalSectionLocked(&info.crit);
3131  ok(ret == TRUE, "expected TRUE, got %u\n", ret);
3132  ret = pRtlIsCriticalSectionLockedByThread(&info.crit);
3133  ok(ret == FALSE, "expected FALSE, got %u\n", ret);
3134 
3135  ReleaseSemaphore(info.semaphores[1], 1, NULL);
3136  ret = WaitForSingleObject(thread, 1000);
3137  ok(ret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", ret);
3138 
3140  CloseHandle(info.semaphores[0]);
3141  CloseHandle(info.semaphores[1]);
3142  DeleteCriticalSection(&info.crit);
3143 }
3144 
3146 {
3147  static const CRITICAL_SECTION_DEBUG *no_debug = (void *)~(ULONG_PTR)0;
3149 
3150  if (!pRtlInitializeCriticalSectionEx)
3151  {
3152  win_skip("RtlInitializeCriticalSectionEx is not available\n");
3153  return;
3154  }
3155 
3156  memset(&cs, 0x11, sizeof(cs));
3157  pRtlInitializeCriticalSectionEx(&cs, 0, 0);
3158  ok((cs.DebugInfo != NULL && cs.DebugInfo != no_debug) || broken(cs.DebugInfo == no_debug) /* >= Win 8 */,
3159  "expected DebugInfo != NULL and DebugInfo != ~0, got %p\n", cs.DebugInfo);
3160  ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
3161  ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount);
3162  ok(cs.LockSemaphore == NULL, "expected LockSemaphore == NULL, got %p\n", cs.LockSemaphore);
3163  ok(cs.SpinCount == 0 || broken(cs.SpinCount != 0) /* >= Win 8 */,
3164  "expected SpinCount == 0, got %ld\n", cs.SpinCount);
3166 
3167  memset(&cs, 0x11, sizeof(cs));
3168  pRtlInitializeCriticalSectionEx(&cs, 0, RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO);
3169  todo_wine
3170  ok(cs.DebugInfo == no_debug, "expected DebugInfo == ~0, got %p\n", cs.DebugInfo);
3171  ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
3172  ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount);
3173  ok(cs.LockSemaphore == NULL, "expected LockSemaphore == NULL, got %p\n", cs.LockSemaphore);
3174  ok(cs.SpinCount == 0 || broken(cs.SpinCount != 0) /* >= Win 8 */,
3175  "expected SpinCount == 0, got %ld\n", cs.SpinCount);
3177 }
3178 
3180 {
3182  NTSTATUS status;
3183 
3184  if (!pRtlInitializeCriticalSectionEx)
3185  return; /* Skip winxp */
3186 
3188  ok(!status, "RtlInitializeCriticalSection failed: %x\n", status);
3189 
3191  ok(!status, "RtlEnterCriticalSection failed: %x\n", status);
3192  todo_wine
3193  ok(cs.LockCount == -2, "expected LockCount == -2, got %d\n", cs.LockCount);
3194  ok(cs.RecursionCount == 1, "expected RecursionCount == 1, got %d\n", cs.RecursionCount);
3195  ok(cs.OwningThread == ULongToHandle(GetCurrentThreadId()), "unexpected OwningThread\n");
3196 
3198  ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
3199  ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
3200  ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount);
3201  ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
3202 
3203  /*
3204  * Trying to leave a section that wasn't acquired modifies RecursionCount to an invalid value,
3205  * but doesn't modify LockCount so that an attempt to enter the section later will work.
3206  */
3208  ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
3209  ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
3210  ok(cs.RecursionCount == -1, "expected RecursionCount == -1, got %d\n", cs.RecursionCount);
3211  ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
3212 
3213  /* and again */
3215  ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
3216  ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
3217  ok(cs.RecursionCount == -2, "expected RecursionCount == -2, got %d\n", cs.RecursionCount);
3218  ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
3219 
3220  /* entering section fixes RecursionCount */
3222  ok(!status, "RtlEnterCriticalSection failed: %x\n", status);
3223  todo_wine
3224  ok(cs.LockCount == -2, "expected LockCount == -2, got %d\n", cs.LockCount);
3225  ok(cs.RecursionCount == 1, "expected RecursionCount == 1, got %d\n", cs.RecursionCount);
3226  ok(cs.OwningThread == ULongToHandle(GetCurrentThreadId()), "unexpected OwningThread\n");
3227 
3229  ok(!status, "RtlLeaveCriticalSection failed: %x\n", status);
3230  ok(cs.LockCount == -1, "expected LockCount == -1, got %d\n", cs.LockCount);
3231  ok(cs.RecursionCount == 0, "expected RecursionCount == 0, got %d\n", cs.RecursionCount);
3232  ok(!cs.OwningThread, "unexpected OwningThread %p\n", cs.OwningThread);
3233 
3235  ok(!status, "RtlDeleteCriticalSection failed: %x\n", status);
3236 }
3237 
3239 {
3242  int count;
3243 };
3244 
3246 {
3247  static const WCHAR ntdllW[] = {'n','t','d','l','l','.','d','l','l',0};
3248  struct ldr_enum_context *ctx = context;
3249 
3250  if (!lstrcmpiW(module->BaseDllName.Buffer, ntdllW))
3251  ctx->found = TRUE;
3252 
3253  ctx->count++;
3254  *stop = ctx->abort;
3255 }
3256 
3258 {
3259  struct ldr_enum_context ctx;
3260  NTSTATUS status;
3261 
3262  if (!pLdrEnumerateLoadedModules)
3263  {
3264  win_skip("LdrEnumerateLoadedModules not available\n");
3265  return;
3266  }
3267 
3268  ctx.abort = FALSE;
3269  ctx.found = FALSE;
3270  ctx.count = 0;
3271  status = pLdrEnumerateLoadedModules(NULL, ldr_enum_callback, &ctx);
3272  ok(status == STATUS_SUCCESS, "LdrEnumerateLoadedModules failed with %08x\n", status);
3273  ok(ctx.count > 1, "Expected more than one module, got %d\n", ctx.count);
3274  ok(ctx.found, "Could not find ntdll in list of modules\n");
3275 
3276  ctx.abort = TRUE;
3277  ctx.count = 0;
3278  status = pLdrEnumerateLoadedModules(NULL, ldr_enum_callback, &ctx);
3279  ok(status == STATUS_SUCCESS, "LdrEnumerateLoadedModules failed with %08x\n", status);
3280  ok(ctx.count == 1, "Expected exactly one module, got %d\n", ctx.count);
3281 
3282  status = pLdrEnumerateLoadedModules((void *)0x1, ldr_enum_callback, (void *)0xdeadbeef);
3283  ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got 0x%08x\n", status);
3284 
3285  status = pLdrEnumerateLoadedModules((void *)0xdeadbeef, ldr_enum_callback, (void *)0xdeadbeef);
3286  ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got 0x%08x\n", status);
3287 
3288  status = pLdrEnumerateLoadedModules(NULL, NULL, (void *)0xdeadbeef);
3289  ok(status == STATUS_INVALID_PARAMETER, "expected STATUS_INVALID_PARAMETER, got 0x%08x\n", status);
3290 }
3291 
3293 {
3294  char buf[sizeof(SECURITY_DESCRIPTOR_RELATIVE) + 4];
3297  NTSTATUS status;
3298  DWORD len;
3299 
3300  if (!pRtlMakeSelfRelativeSD || !pRtlAbsoluteToSelfRelativeSD)
3301  {
3302  win_skip( "RtlMakeSelfRelativeSD/RtlAbsoluteToSelfRelativeSD not available\n" );
3303  return;
3304  }
3305 
3306  memset( &sd, 0, sizeof(sd) );
3307  sd.Revision = SECURITY_DESCRIPTOR_REVISION;
3308 
3309  len = 0;
3310  status = pRtlMakeSelfRelativeSD( &sd, NULL, &len );
3311  ok( status == STATUS_BUFFER_TOO_SMALL, "got %08x\n", status );
3312  ok( len == sizeof(*sd_rel), "got %u\n", len );
3313 
3314  len += 4;
3315  status = pRtlMakeSelfRelativeSD( &sd, sd_rel, &len );
3316  ok( status == STATUS_SUCCESS, "got %08x\n", status );
3317  ok( len == sizeof(*sd_rel) + 4, "got %u\n", len );
3318 
3319  len = 0;
3320  status = pRtlAbsoluteToSelfRelativeSD( &sd, NULL, &len );
3321  ok( status == STATUS_BUFFER_TOO_SMALL, "got %08x\n", status );
3322  ok( len == sizeof(*sd_rel), "got %u\n", len );
3323 
3324  len += 4;
3325  status = pRtlAbsoluteToSelfRelativeSD( &sd, sd_rel, &len );
3326  ok( status == STATUS_SUCCESS, "got %08x\n", status );
3327  ok( len == sizeof(*sd_rel) + 4, "got %u\n", len );
3328 
3329  sd.Control = SE_SELF_RELATIVE;
3330  status = pRtlMakeSelfRelativeSD( &sd, sd_rel, &len );
3331  ok( status == STATUS_SUCCESS, "got %08x\n", status );
3332  ok( len == sizeof(*sd_rel) + 4, "got %u\n", len );
3333 
3334  status = pRtlAbsoluteToSelfRelativeSD( &sd, sd_rel, &len );
3335  ok( status == STATUS_BAD_DESCRIPTOR_FORMAT, "got %08x\n", status );
3336 }
3337 
3339 {
3340  const WCHAR programW[] = {'M','i','c','r','o','s','o','f','t','.','W','i','n','d','o','w','s','.',
3341  'P','h','o','t','o','s','_','8','w','e','k','y','b','3','d','8','b','b','w','e','!','A','p','p',0};
3342  const WCHAR fullnameW[] = {'M','i','c','r','o','s','o','f','t','.','W','i','n','d','o','w','s','.',
3343  'P','h','o','t','o','s', 0};
3344  const WCHAR appidW[] = {'A','p','p',0};
3346  WCHAR buf1[MAX_PATH], buf2[MAX_PATH];
3347  HANDLE process, token;
3348  SIZE_T size1, size2;
3349  NTSTATUS status;
3350  DWORD processid;
3351  HRESULT hr;
3352  BOOL ret;
3353 
3354  if (!pRtlQueryPackageIdentity)
3355  {
3356  win_skip("RtlQueryPackageIdentity not available\n");
3357  return;
3358  }
3359 
3360  size1 = size2 = MAX_PATH * sizeof(WCHAR);
3361  status = pRtlQueryPackageIdentity((HANDLE)~(ULONG_PTR)3, buf1, &size1, buf2, &size2, NULL);
3362  ok(status == STATUS_NOT_FOUND, "expected STATUS_NOT_FOUND, got %08x\n", status);
3363 
3365  hr = CoCreateInstance(&CLSID_ApplicationActivationManager, NULL, CLSCTX_LOCAL_SERVER,
3366  &IID_IApplicationActivationManager, (void **)&manager);
3367  if (FAILED(hr))
3368  {
3369  todo_wine win_skip("Failed to create ApplicationActivationManager (%x)\n", hr);
3370  goto done;
3371  }
3372 
3373  hr = IApplicationActivationManager_ActivateApplication(manager, programW, NULL,
3374  AO_NOERRORUI, &processid);
3375  if (FAILED(hr))
3376  {
3377  todo_wine win_skip("Failed to start program (%x)\n", hr);
3378  IApplicationActivationManager_Release(manager);
3379  goto done;
3380  }
3381 
3383  ok(process != NULL, "OpenProcess failed with %u\n", GetLastError());
3385  ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
3386 
3387  size1 = size2 = MAX_PATH * sizeof(WCHAR);
3388  status = pRtlQueryPackageIdentity(token, buf1, &size1, buf2, &size2, NULL);
3389  ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
3390 
3391  ok(!memcmp(buf1, fullnameW, sizeof(fullnameW) - sizeof(WCHAR)),
3392  "Expected buf1 to begin with %s, got %s\n", wine_dbgstr_w(fullnameW), wine_dbgstr_w(buf1));
3393  ok(size1 >= sizeof(WCHAR) && !(size1 % sizeof(WCHAR)), "Unexpected size1 = %lu\n", size1);
3394  ok(buf1[size1 / sizeof(WCHAR) - 1] == 0, "Expected buf1[%lu] == 0\n", size1 / sizeof(WCHAR) - 1);
3395 
3396  ok(!lstrcmpW(buf2, appidW), "Expected buf2 to be %s, got %s\n", wine_dbgstr_w(appidW), wine_dbgstr_w(buf2));
3397  ok(size2 >= sizeof(WCHAR) && !(size2 % sizeof(WCHAR)), "Unexpected size2 = %lu\n", size2);
3398  ok(buf2[size2 / sizeof(WCHAR) - 1] == 0, "Expected buf2[%lu] == 0\n", size2 / sizeof(WCHAR) - 1);
3399 
3400  CloseHandle(token);
3403 
3404 done:
3405  CoUninitialize();
3406 }
3407 
3408 static DWORD (CALLBACK *orig_entry)(HMODULE,DWORD,LPVOID);
3410 
3411 static inline void *get_rva( HMODULE module, DWORD va )
3412 {
3413  return (void *)((char *)module + va);
3414 }
3415 
3417 {
3419  const IMAGE_THUNK_DATA *import_list;
3420  IMAGE_THUNK_DATA *thunk_list;
3421  DWORD *calls = context;
3422  LIST_ENTRY *mark;
3423  LDR_MODULE *mod;
3424  ULONG size;
3425  int i, j;
3426 
3427  *calls <<= 4;
3428  *calls |= reason;
3429 
3430  ok(data->Loaded.Flags == 0, "Expected flags 0, got %x\n", data->Loaded.Flags);
3431  ok(!lstrcmpiW(data->Loaded.BaseDllName->Buffer, ws2_32dllW), "Expected ws2_32.dll, got %s\n",
3432  wine_dbgstr_w(data->Loaded.BaseDllName->Buffer));
3433  ok(!!data->Loaded.DllBase, "Expected non zero base address\n");
3434  ok(data->Loaded.SizeOfImage, "Expected non zero image size\n");
3435 
3436  /* expect module to be last module listed in LdrData load order list */
3437  mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
3438  mod = CONTAINING_RECORD(mark->Blink, LDR_MODULE, InMemoryOrderModuleList);
3439  ok(mod->BaseAddress == data->Loaded.DllBase, "Expected base address %p, got %p\n",
3440  data->Loaded.DllBase, mod->BaseAddress);
3441  ok(!lstrcmpiW(mod->BaseDllName.Buffer, ws2_32dllW), "Expected ws2_32.dll, got %s\n",
3442  wine_dbgstr_w(mod->BaseDllName.Buffer));
3443 
3444  /* show that imports have already been resolved */
3446  ok(!!imports, "Expected dll to have imports\n");
3447 
3448  for (i = 0; imports[i].Name; i++)
3449  {
3450  thunk_list = get_rva(data->Loaded.DllBase, (DWORD)imports[i].FirstThunk);
3451  if (imports[i].OriginalFirstThunk)
3452  import_list = get_rva(data->Loaded.DllBase, (DWORD)imports[i].OriginalFirstThunk);
3453  else
3454  import_list = thunk_list;
3455 
3456  for (j = 0; import_list[j].u1.Ordinal; j++)
3457  {
3458  ok(thunk_list[j].u1.AddressOfData > data->Loaded.SizeOfImage,
3459  "Import has not been resolved: %p\n", (void*)thunk_list[j].u1.Function);
3460  }
3461  }
3462 }
3463 
3465 {
3466  DWORD *calls = context;
3467  *calls <<= 4;
3468  *calls |= reason + 2;
3469 }
3470 
3472 {
3473  if (reason == DLL_PROCESS_ATTACH)
3474  {
3475  *dll_main_data <<= 4;
3476  *dll_main_data |= 3;
3477  }
3478  else if (reason == DLL_PROCESS_DETACH)
3479  {
3480  *dll_main_data <<= 4;
3481  *dll_main_data |= 4;
3482  }
3483  return orig_entry(instance, reason, reserved);
3484 }
3485 
3487 {
3488  DWORD *calls = context;
3489  LIST_ENTRY *mark;
3490  LDR_MODULE *mod;
3491 
3492  *calls <<= 4;
3493  *calls |= reason;
3494 
3496  return;
3497 
3498  mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
3499  mod = CONTAINING_RECORD(mark->Blink, LDR_MODULE, InMemoryOrderModuleList);
3500  ok(mod->BaseAddress == data->Loaded.DllBase, "Expected base address %p, got %p\n",
3501  data->Loaded.DllBase, mod->BaseAddress);
3502  if (mod->BaseAddress != data->Loaded.DllBase)
3503  return;
3504 
3505  orig_entry = mod->EntryPoint;
3506  mod->EntryPoint = fake_dll_main;
3507  dll_main_data = calls;
3508 }
3509 
3511 {
3512  if (reason == DLL_PROCESS_ATTACH)
3513  {
3514  *dll_main_data <<= 4;
3515  *dll_main_data |= 3;
3516  }
3517  else if (reason == DLL_PROCESS_DETACH)
3518  {
3519  *dll_main_data <<= 4;
3520  *dll_main_data |= 4;
3521  }
3522  return FALSE;
3523 }
3524 
3526 {
3527  DWORD *calls = context;
3528  LIST_ENTRY *mark;
3529  LDR_MODULE *mod;
3530 
3531  *calls <<= 4;
3532  *calls |= reason;
3533 
3535  return;
3536 
3537  mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
3538  mod = CONTAINING_RECORD(mark->Blink, LDR_MODULE, InMemoryOrderModuleList);
3539  ok(mod->BaseAddress == data->Loaded.DllBase, "Expected base address %p, got %p\n",
3540  data->Loaded.DllBase, mod->BaseAddress);
3541  if (mod->BaseAddress != data->Loaded.DllBase)
3542  return;
3543 
3544  orig_entry = mod->EntryPoint;
3545  mod->EntryPoint = fake_dll_main_fail;
3546  dll_main_data = calls;
3547 }
3548 
3550 {
3551  DWORD *calls = context;
3552 
3554  return;
3555 
3556  if (!lstrcmpiW(data->Loaded.BaseDllName->Buffer, crypt32dllW))
3557  {
3558  *calls <<= 4;
3559  *calls |= 1;
3560  }
3561 
3562  if (!lstrcmpiW(data->Loaded.BaseDllName->Buffer, wintrustdllW))
3563  {
3564  *calls <<= 4;
3565  *calls |= 2;
3566  }
3567 }
3568 
3570 {
3571  void *cookie, *cookie2;
3572  NTSTATUS status;
3573  HMODULE mod;
3574  DWORD calls;
3575 
3576  if (!pLdrRegisterDllNotification || !pLdrUnregisterDllNotification)
3577  {
3578  win_skip("Ldr(Un)RegisterDllNotification not available\n");
3579  return;
3580  }
3581 
3582  /* generic test */
3583  status = pLdrRegisterDllNotification(0, ldr_notify_callback1, &calls, &cookie);
3584  ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
3585 
3586  calls = 0;
3588  ok(!!mod, "Failed to load library: %d\n", GetLastError());
3589  ok(calls == LDR_DLL_NOTIFICATION_REASON_LOADED, "Expected LDR_DLL_NOTIFICATION_REASON_LOADED, got %x\n", calls);
3590 
3591  calls = 0;
3592  FreeLibrary(mod);
3593  ok(calls == LDR_DLL_NOTIFICATION_REASON_UNLOADED, "Expected LDR_DLL_NOTIFICATION_REASON_UNLOADED, got %x\n", calls);
3594 
3595  /* test order of callbacks */
3596  status = pLdrRegisterDllNotification(0, ldr_notify_callback2, &calls, &cookie2);
3597  ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
3598 
3599  calls = 0;
3601  ok(!!mod, "Failed to load library: %d\n", GetLastError());
3602  ok(calls == 0x13, "Expected order 0x13, got %x\n", calls);
3603 
3604  calls = 0;
3605  FreeLibrary(mod);
3606  ok(calls == 0x24, "Expected order 0x24, got %x\n", calls);
3607 
3608  pLdrUnregisterDllNotification(cookie2);
3609  pLdrUnregisterDllNotification(cookie);
3610 
3611  /* test dll main order */
3612  status = pLdrRegisterDllNotification(0, ldr_notify_callback_dll_main, &calls, &cookie);
3613  ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
3614 
3615  calls = 0;
3617  ok(!!mod, "Failed to load library: %d\n", GetLastError());
3618  ok(calls == 0x13, "Expected order 0x13, got %x\n", calls);
3619 
3620  calls = 0;
3621  FreeLibrary(mod);
3622  ok(calls == 0x42, "Expected order 0x42, got %x\n", calls);
3623 
3624  pLdrUnregisterDllNotification(cookie);
3625 
3626  /* test dll main order */
3627  status = pLdrRegisterDllNotification(0, ldr_notify_callback_fail, &calls, &cookie);
3628  ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
3629 
3630  calls = 0;
3632  ok(!mod, "Expected library to fail loading\n");
3633  ok(calls == 0x1342, "Expected order 0x1342, got %x\n", calls);
3634 
3635  pLdrUnregisterDllNotification(cookie);
3636 
3637  /* test dll with dependencies */
3638  status = pLdrRegisterDllNotification(0, ldr_notify_callback_imports, &calls, &cookie);
3639  ok(!status, "Expected STATUS_SUCCESS, got %08x\n", status);
3640 
3641  calls = 0;
3643  ok(!!mod, "Failed to load library: %d\n", GetLastError());
3644  ok(calls == 0x12, "Expected order 0x12, got %x\n", calls);
3645 
3646  FreeLibrary(mod);
3647  pLdrUnregisterDllNotification(cookie);
3648 }
3649 
3651 {
3652  InitFunctionPtrs();
3653 
3661  test_RtlUniform();
3662  test_RtlRandom();
3691 }
#define STATUS_UNSUPPORTED_COMPRESSION
Definition: ntstatus.h:718
PVOID ReservedMemory
Definition: rtl.c:50
ULONG Unused[2]
Definition: rtl.c:47
static USHORT
Definition: rtl.c:96
int ip_strict[4]
Definition: rtl.c:1180
#define COMPRESSION_FORMAT_NONE
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define trace(...)
Definition: kmt_test.h:217
struct param_test tests[]
#define LFILL(len)
Definition: rtl.c:331
#define ULongToHandle(h)
Definition: basetsd.h:81
NTSTATUS res_strict
Definition: rtl.c:1178
#define MCMP(str)
Definition: rtl.c:358
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
static void CALLBACK ldr_notify_callback_dll_main(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
Definition: rtl.c:3486
static void test_RtlCompareMemory(void)
Definition: rtl.c:205
static WCHAR wintrustdllW[]
Definition: rtl.c:130
#define SE_SELF_RELATIVE
Definition: setypes.h:780
static void compare_RtlIpv6StringToAddressExW(PCSTR name_a, const struct in6_addr *addr_a, HRESULT res_a, ULONG scope_a, USHORT port_a)
Definition: rtl.c:2124
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static BOOL rtl
Definition: propsheet.c:36
#define COPY(len)
Definition: rtl.c:274
static const struct @1610 ipv6_tests[]
static ULONG ULONG_PTR *static ULONG_PTR
Definition: rtl.c:107
static PBOOL
Definition: rtl.c:124
ACCESS_MASK GrantedAccess
Definition: rtl.c:770
HRESULT hr
Definition: shlfolder.c:183
static const all_accesses_t all_accesses[]
Definition: rtl.c:731
static void test_RtlAreAllAccessesGranted(void)
Definition: rtl.c:746
HANDLE WINAPI DECLSPEC_HOTPATCH CreateSemaphoreW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, IN LONG lInitialCount, IN LONG lMaximumCount, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:444
static WCHAR crypt32dllW[]
Definition: rtl.c:131
#define MAXLONG
Definition: umtypes.h:116
static void test_RtlMoveMemory(void)
Definition: rtl.c:277
Definition: http.c:6587
CRITICAL_SECTION crit
Definition: rtl.c:3051
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
* PSID_IDENTIFIER_AUTHORITY
Definition: setypes.h:436
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
static void test_LdrEnumerateLoadedModules(void)
Definition: rtl.c:3257
static void test_RtlIpv4AddressToStringEx(void)
Definition: rtl.c:1052
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
PVOID MaxHandle
Definition: rtl.c:51