ReactOS 0.4.15-dev-7958-gcd0bb1a
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
38typedef struct _RTL_HANDLE
39{
40 struct _RTL_HANDLE * Next;
42
43typedef 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 */
71static HMODULE hntdll = 0;
72static SIZE_T (WINAPI *pRtlCompareMemory)(LPCVOID,LPCVOID,SIZE_T);
73static SIZE_T (WINAPI *pRtlCompareMemoryUlong)(PULONG, SIZE_T, ULONG);
74static NTSTATUS (WINAPI *pRtlDeleteTimer)(HANDLE, HANDLE, HANDLE);
75static VOID (WINAPI *pRtlMoveMemory)(LPVOID,LPCVOID,SIZE_T);
76static VOID (WINAPI *pRtlFillMemory)(LPVOID,SIZE_T,BYTE);
77static VOID (WINAPI *pRtlFillMemoryUlong)(LPVOID,SIZE_T,ULONG);
78static VOID (WINAPI *pRtlZeroMemory)(LPVOID,SIZE_T);
79static ULONGLONG (WINAPIV *pRtlUlonglongByteSwap)(ULONGLONG source);
80static ULONG (WINAPI *pRtlUniform)(PULONG);
81static ULONG (WINAPI *pRtlRandom)(PULONG);
82static BOOLEAN (WINAPI *pRtlAreAllAccessesGranted)(ACCESS_MASK, ACCESS_MASK);
83static BOOLEAN (WINAPI *pRtlAreAnyAccessesGranted)(ACCESS_MASK, ACCESS_MASK);
84static DWORD (WINAPI *pRtlComputeCrc32)(DWORD,const BYTE*,INT);
85static void (WINAPI * pRtlInitializeHandleTable)(ULONG, ULONG, RTL_HANDLE_TABLE *);
86static BOOLEAN (WINAPI * pRtlIsValidIndexHandle)(const RTL_HANDLE_TABLE *, ULONG, RTL_HANDLE **);
87static NTSTATUS (WINAPI * pRtlDestroyHandleTable)(RTL_HANDLE_TABLE *);
89static BOOLEAN (WINAPI * pRtlFreeHandle)(RTL_HANDLE_TABLE *, RTL_HANDLE *);
91static NTSTATUS (WINAPI *pRtlFreeSid)(PSID);
92static DWORD (WINAPI *pRtlGetThreadErrorMode)(void);
93static NTSTATUS (WINAPI *pRtlSetThreadErrorMode)(DWORD, LPDWORD);
96static NTSTATUS (WINAPI *pRtlIpv4AddressToStringExA)(const IN_ADDR *, USHORT, LPSTR, PULONG);
97static NTSTATUS (WINAPI *pRtlIpv4StringToAddressA)(PCSTR, BOOLEAN, PCSTR *, IN_ADDR *);
98static NTSTATUS (WINAPI *pRtlIpv4StringToAddressExA)(PCSTR, BOOLEAN, IN_ADDR *, PUSHORT);
100static NTSTATUS (WINAPI *pRtlIpv6AddressToStringExA)(struct in6_addr *, ULONG, USHORT, PCHAR, PULONG);
101static NTSTATUS (WINAPI *pRtlIpv6StringToAddressA)(PCSTR, PCSTR *, struct in6_addr *);
102static NTSTATUS (WINAPI *pRtlIpv6StringToAddressW)(PCWSTR, PCWSTR *, struct in6_addr *);
103static NTSTATUS (WINAPI *pRtlIpv6StringToAddressExA)(PCSTR, struct in6_addr *, PULONG, PUSHORT);
104static NTSTATUS (WINAPI *pRtlIpv6StringToAddressExW)(PCWSTR, struct in6_addr *, PULONG, PUSHORT);
105static NTSTATUS (WINAPI *pLdrAddRefDll)(ULONG, HMODULE);
106static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG*, ULONG_PTR*);
107static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR);
108static NTSTATUS (WINAPI *pRtlMultiByteToUnicodeN)(LPWSTR, DWORD, LPDWORD, LPCSTR, DWORD);
109static NTSTATUS (WINAPI *pRtlGetCompressionWorkSpaceSize)(USHORT, PULONG, PULONG);
110static NTSTATUS (WINAPI *pRtlDecompressBuffer)(USHORT, PUCHAR, ULONG, const UCHAR*, ULONG, PULONG);
111static NTSTATUS (WINAPI *pRtlDecompressFragment)(USHORT, PUCHAR, ULONG, const UCHAR*, ULONG, ULONG, PULONG, PVOID);
112static NTSTATUS (WINAPI *pRtlCompressBuffer)(USHORT, const UCHAR*, ULONG, PUCHAR, ULONG, ULONG, PULONG, PVOID);
113static BOOL (WINAPI *pRtlIsCriticalSectionLocked)(CRITICAL_SECTION *);
114static BOOL (WINAPI *pRtlIsCriticalSectionLockedByThread)(CRITICAL_SECTION *);
115static NTSTATUS (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, ULONG, ULONG);
116static NTSTATUS (WINAPI *pLdrEnumerateLoadedModules)(void *, void *, void *);
117static NTSTATUS (WINAPI *pRtlQueryPackageIdentity)(HANDLE, WCHAR*, SIZE_T*, WCHAR*, SIZE_T*, BOOLEAN*);
119static NTSTATUS (WINAPI *pRtlAbsoluteToSelfRelativeSD)(PSECURITY_DESCRIPTOR,PSECURITY_DESCRIPTOR,PULONG);
120static NTSTATUS (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **);
121static NTSTATUS (WINAPI *pLdrUnregisterDllNotification)(void *);
122
124static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
125
126
127#define LEN 16
128static const char* src_src = "This is a test!"; /* 16 bytes long, incl NUL */
129static WCHAR ws2_32dllW[] = {'w','s','2','_','3','2','.','d','l','l',0};
130static WCHAR wintrustdllW[] = {'w','i','n','t','r','u','s','t','.','d','l','l',0};
131static WCHAR crypt32dllW[] = {'c','r','y','p','t','3','2','.','d','l','l',0};
134static const char *src = (const char*)src_aligned_block;
135static char* dest = (char*)dest_aligned_block;
136
137static 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
205static 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
224{
225 ULONG a[10];
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
277static 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
308static 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
333static 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
360static 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
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
404static void test_RtlUniform(void)
405{
407 ULONG seed;
408 ULONG seed_bak;
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",
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",
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",
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",
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",
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",
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",
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",
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",
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",
643 ok(seed == expected,
644 "test: 0x%s RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
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",
690 ok(seed == expected,
691 "test: 0x%s RtlUniform(&seed (seed == %x)) sets seed to %x, expected %x\n",
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
702static 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
725typedef struct {
730
731static 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;
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
769typedef struct {
774
775static 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;
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
811static 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
826typedef struct MY_HANDLE
827{
829 void * MyValue;
831
833{
834 ULONG_PTR *AllocatedBit = (ULONG_PTR *)(&Handle->Next);
835 *AllocatedBit = *AllocatedBit | 1;
836}
837
838static void test_HandleTables(void)
839{
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);
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{
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
893static void test_RtlDeleteTimer(void)
894{
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
909static void test_RtlThreadErrorMode(void)
910{
911 DWORD oldmode;
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);
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);
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)
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
1171static struct
1172{
1176 int ip[4];
1177 enum { normal_4, strict_diff_4 = 1, ex_fail_4 = 2 } flags;
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 } },
1250const unsigned int ipv4_testcount = sizeof(ipv4_tests) / sizeof(ipv4_tests[0]);
1251
1252static 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",
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;
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 */
1465static const struct
1466{
1467 PCSTR address;
1468 NTSTATUS res;
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 },
1737const unsigned int ipv6_testcount = sizeof(ipv6_tests) / sizeof(ipv6_tests[0]);
1738
1739static 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
1994static 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
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 {
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",
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
2124static 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",
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",
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",
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
2387static void test_LdrAddRefDll(void)
2388{
2389 HMODULE mod, mod2;
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
2442static void test_LdrLockLoaderLock(void)
2443{
2445 ULONG result;
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
2494static 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;
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;
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 */
2607static 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
2632{
2633 static const struct
2634 {
2635 UCHAR compressed[32];
2636 ULONG compressed_size;
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{
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{
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
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
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);
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]);
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{
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{
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;
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];
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) );
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];
3348 SIZE_T size1, size2;
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
3403
3404done:
3406}
3407
3408static DWORD (CALLBACK *orig_entry)(HMODULE,DWORD,LPVOID);
3410
3411static inline void *get_rva( HMODULE module, DWORD va )
3412{
3413 return (void *)((char *)module + va);
3414}
3415
3417{
3418 const IMAGE_IMPORT_DESCRIPTOR *imports;
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{
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{
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;
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;
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;
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;
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
3647 pLdrUnregisterDllNotification(cookie);
3648}
3649
3651{
3653
3691}
unsigned char BOOLEAN
#define expect(EXPECTED, GOT)
Definition: SystemMenu.c:483
#define broken(x)
Definition: _sntprintf.h:21
static TCHAR test_buffer[TEST_BUFFER_SIZE]
Definition: _tfileio.c:53
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define VOID
Definition: acefi.h:82
static int used
Definition: adh-main.c:39
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
static HANDLE thread
Definition: service.c:33
#define ULongToHandle(h)
Definition: basetsd.h:81
#define mod2(n)
Definition: vgavideo.h:71
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static HINSTANCE instance
Definition: main.c:40
#define NTSTATUS
Definition: precomp.h:21
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:294
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define DLL_PROCESS_ATTACH
Definition: compat.h:131
#define DLL_PROCESS_DETACH
Definition: compat.h:130
#define GetProcAddress(x, y)
Definition: compat.h:753
#define HeapAlloc
Definition: compat.h:733
#define FreeLibrary(x)
Definition: compat.h:748
static __inline const char * wine_dbgstr_longlong(ULONGLONG ll)
Definition: compat.h:49
#define GetCurrentProcess()
Definition: compat.h:759
#define RtlImageDirectoryEntryToData
Definition: compat.h:809
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
#define LoadLibraryW(x)
Definition: compat.h:747
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
BOOL WINAPI TerminateProcess(IN HANDLE hProcess, IN UINT uExitCode)
Definition: proc.c:1532
HANDLE WINAPI OpenProcess(IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId)
Definition: proc.c:1227
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL is_wow64
Definition: msi.c:54
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(LPVOID lpReserved, DWORD dwCoInit)
Definition: compobj.c:2002
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: compobj.c:2067
USHORT port
Definition: uri.c:228
r reserved
Definition: btrfs.c:3006
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
ULONG Handle
Definition: gdb_input.c:15
GLdouble s
Definition: gl.h:2039
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLuint address
Definition: glext.h:9393
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
GLuint GLfloat * val
Definition: glext.h:7180
GLuint GLuint num
Definition: glext.h:9618
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
GLdouble u1
Definition: glext.h:8308
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static XMS_HANDLE HandleTable[XMS_MAX_HANDLES]
Definition: himem.c:83
static int mod
Definition: i386-dis.c:1288
#define cs
Definition: i386-dis.c:442
#define PROCESS_TERMINATE
Definition: pstypes.h:157
#define LDR_DLL_NOTIFICATION_REASON_UNLOADED
Definition: winternl.h:2304
#define LDR_DLL_NOTIFICATION_REASON_LOADED
Definition: winternl.h:2303
#define FAILED(hr)
Definition: intsafe.h:51
#define NtCurrentTeb
#define wine_dbgstr_w
Definition: kernel32.h:34
#define LDR_ADDREF_DLL_PIN
Definition: ldrtypes.h:71
int WINAPI lstrcmpiW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:194
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
static struct test_info tests[]
#define PROCESS_QUERY_LIMITED_INFORMATION
Definition: security.c:45
static BOOL rtl
Definition: propsheet.c:36
BOOL expected
Definition: store.c:2063
#define todo_wine
Definition: custom.c:79
static const WCHAR sd[]
Definition: suminfo.c:286
static int strict
Definition: error.c:51
static ACCESS_MASK
Definition: rtl.c:82
const unsigned int ipv6_testcount
Definition: rtl.c:1737
static void test_RtlFillMemoryUlong(void)
Definition: rtl.c:333
static HMODULE hntdll
Definition: rtl.c:71
#define LEN
Definition: rtl.c:127
#define DECOMPRESS_BROKEN_TRUNCATED
Definition: rtl.c:2629
static HMODULE
Definition: rtl.c:105
static void test_RtlIpv4StringToAddress(void)
Definition: rtl.c:1267
static BOOL WINAPI fake_dll_main_fail(HINSTANCE instance, DWORD reason, void *reserved)
Definition: rtl.c:3510
enum @1682::@1684 flags
static void CALLBACK ldr_notify_callback_imports(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
Definition: rtl.c:3549
static void test_RtlDeleteTimer(void)
Definition: rtl.c:893
static USHORT
Definition: rtl.c:96
NTSTATUS res
Definition: rtl.c:1174
static RTL_HANDLE *WINAPI * pRtlAllocateHandle(RTL_HANDLE_TABLE *, ULONG *)
#define DECOMPRESS_BROKEN_FRAGMENT
Definition: rtl.c:2628
static void test_RtlIsCriticalSectionLocked(void)
Definition: rtl.c:3089
static LPSTR
Definition: rtl.c:96
static WCHAR wintrustdllW[]
Definition: rtl.c:130
static DWORD WINAPI critsect_locked_thread(void *param)
Definition: rtl.c:3055
static void test_RtlComputeCrc32(void)
Definition: rtl.c:811
static char * dest
Definition: rtl.c:135
PCSTR address
Definition: rtl.c:1173
static void init_ip4(IN_ADDR *addr, const int src[4])
Definition: rtl.c:1252
static void compare_RtlIpv6StringToAddressW(PCSTR name_a, int terminator_offset_a, const struct in6_addr *addr_a, NTSTATUS res_a)
Definition: rtl.c:1994
#define NB_ALL_ACCESSES
Definition: rtl.c:743
int ip[4]
Definition: rtl.c:1176
static void CALLBACK ldr_notify_callback_dll_main(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
Definition: rtl.c:3486
static void * get_rva(HMODULE module, DWORD va)
Definition: rtl.c:3411
static PLDR_DLL_NOTIFICATION_FUNCTION
Definition: rtl.c:120
static IMAGE_BASE_RELOCATION *WINAPI * pLdrProcessRelocationBlock(void *, UINT, USHORT *, INT_PTR)
static const all_accesses_t all_accesses[]
Definition: rtl.c:731
static void void *static WCHAR SIZE_T WCHAR SIZE_T BOOLEAN *static PSECURITY_DESCRIPTOR
Definition: rtl.c:118
static WCHAR crypt32dllW[]
Definition: rtl.c:131
static BOOLEAN
Definition: rtl.c:97
static void test_RtlUniform(void)
Definition: rtl.c:404
static CHAR *WINAPI * pRtlIpv4AddressToStringA(const IN_ADDR *, LPSTR)
struct _RTL_HANDLE_TABLE RTL_HANDLE_TABLE
static ULONG ULONG_PTR *static ULONG_PTR
Definition: rtl.c:107
static void test_RtlIpv6AddressToString(void)
Definition: rtl.c:1754
static void test_RtlMakeSelfRelativeSD(void)
Definition: rtl.c:3292
#define LFILL(len)
Definition: rtl.c:331
static HANDLE
Definition: rtl.c:74
#define CMP(str)
Definition: rtl.c:275
static void test_RtlInitializeCriticalSectionEx(void)
Definition: rtl.c:3145
static void RtlpMakeHandleAllocated(RTL_HANDLE *Handle)
Definition: rtl.c:832
static void test_RtlAreAnyAccessesGranted(void)
Definition: rtl.c:789
static void test_RtlThreadErrorMode(void)
Definition: rtl.c:909
static void test_RtlRandom(void)
Definition: rtl.c:702
int terminator_offset
Definition: rtl.c:1175
static ULONG dest_aligned_block[32]
Definition: rtl.c:133
static const char * src_src
Definition: rtl.c:128
static const struct @1683 ipv6_tests[]
static WCHAR ws2_32dllW[]
Definition: rtl.c:129
#define COPY(len)
Definition: rtl.c:274
static LPDWORD
Definition: rtl.c:93
static void test_RtlIpv4AddressToStringEx(void)
Definition: rtl.c:1052
static void WINAPI ldr_enum_callback(LDR_MODULE *module, void *context, BOOLEAN *stop)
Definition: rtl.c:3245
struct _RTL_HANDLE RTL_HANDLE
static PUCHAR
Definition: rtl.c:110
const unsigned int ipv4_testcount
Definition: rtl.c:1250
static void test_RtlQueryPackageIdentity(void)
Definition: rtl.c:3338
static ULONG
Definition: rtl.c:73
static void CALLBACK ldr_notify_callback2(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
Definition: rtl.c:3464
static const any_accesses_t any_accesses[]
Definition: rtl.c:775
static void test_RtlZeroMemory(void)
Definition: rtl.c:360
static void test_RtlIpv4StringToAddressEx(void)
Definition: rtl.c:1340
static void test_LdrAddRefDll(void)
Definition: rtl.c:2387
static void test_RtlIpv6StringToAddressEx(void)
Definition: rtl.c:2153
static void test_RtlLeaveCriticalSection(void)
Definition: rtl.c:3179
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
#define COMP(str1, str2, cmplen, len)
Definition: rtl.c:202
static RTL_HANDLE *static DWORD
Definition: rtl.c:90
int terminator_offset_strict
Definition: rtl.c:1179
static CHAR *WINAPI * pRtlIpv6AddressToStringA(struct in6_addr *, PSTR)
static void test_RtlMoveMemory(void)
Definition: rtl.c:277
static void InitFunctionPtrs(void)
Definition: rtl.c:137
static PBOOL
Definition: rtl.c:124
static void test_RtlCompareMemory(void)
Definition: rtl.c:205
static PCSTR IN_ADDR *static IN_ADDR PUSHORT
Definition: rtl.c:98
static ULONG src_aligned_block[4]
Definition: rtl.c:132
static void test_RtlDecompressBuffer(void)
Definition: rtl.c:2631
#define MCMP(str)
Definition: rtl.c:358
static void test_HandleTables(void)
Definition: rtl.c:838
static LPCVOID
Definition: rtl.c:72
static const BYTE INT
Definition: rtl.c:84
static PCHAR
Definition: rtl.c:100
static BYTE
Definition: rtl.c:76
static void test_LdrRegisterDllNotification(void)
Definition: rtl.c:3569
static void test_RtlCompressBuffer(void)
Definition: rtl.c:2494
static BOOL is_incomplete_chunk(const UCHAR *compressed, ULONG compressed_size, BOOL check_all)
Definition: rtl.c:2607
static HMODULE hkernel32
Definition: rtl.c:123
#define htons(s)
Definition: rtl.c:65
static void init_ip6(IN6_ADDR *addr, const int src[8])
Definition: rtl.c:1739
static void test_RtlFillMemory(void)
Definition: rtl.c:308
static LPVOID
Definition: rtl.c:3408
static const UCHAR PVOID
Definition: rtl.c:111
static SIZE_T
Definition: rtl.c:72
static void test_LdrEnumerateLoadedModules(void)
Definition: rtl.c:3257
static void test_RtlGetCompressionWorkSpaceSize(void)
Definition: rtl.c:2567
static void CALLBACK ldr_notify_callback1(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
Definition: rtl.c:3416
static DWORD * dll_main_data
Definition: rtl.c:3409
static void test_RtlIpv6StringToAddress(void)
Definition: rtl.c:2034
static void test_RtlAllocateAndInitializeSid(void)
Definition: rtl.c:865
static void test_RtlAreAllAccessesGranted(void)
Definition: rtl.c:746
#define FILL(len)
Definition: rtl.c:306
static BOOL WINAPI fake_dll_main(HINSTANCE instance, DWORD reason, void *reserved)
Definition: rtl.c:3471
static LPCSTR
Definition: rtl.c:108
int ip_strict[4]
Definition: rtl.c:1180
static void test_LdrLockLoaderLock(void)
Definition: rtl.c:2442
static void test_RtlCompareMemoryUlong(void)
Definition: rtl.c:223
static void test_RtlUlonglongByteSwap(void)
Definition: rtl.c:381
#define ZERO(len)
Definition: rtl.c:357
static void test_RtlIpv6AddressToStringEx(void)
Definition: rtl.c:1874
#define NB_ANY_ACCESSES
Definition: rtl.c:786
NTSTATUS res_strict
Definition: rtl.c:1178
static void test_LdrProcessRelocationBlock(void)
Definition: rtl.c:977
static PULONG
Definition: rtl.c:96
static void CALLBACK ldr_notify_callback_fail(ULONG reason, LDR_DLL_NOTIFICATION_DATA *data, void *context)
Definition: rtl.c:3525
static USHORT __my_ushort_swap(USHORT s)
Definition: rtl.c:61
static struct @1682 ipv4_tests[]
static void test_RtlIpv4AddressToString(void)
Definition: rtl.c:1008
static const BYTE uncompressed[]
Definition: misc.c:392
struct _SID * PSID
Definition: eventlog.c:35
unsigned int UINT
Definition: ndis.h:50
NTSYSAPI NTSTATUS NTAPI RtlDeleteCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
NTSYSAPI NTSTATUS NTAPI RtlInitializeCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
u32_t magic(void)
#define BOOL
Definition: nt_native.h:43
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define COMPRESSION_FORMAT_DEFAULT
#define COMPRESSION_FORMAT_NONE
#define COMPRESSION_ENGINE_MAXIMUM
#define COMPRESSION_FORMAT_LZNT1
#define STATUS_UNSUPPORTED_COMPRESSION
Definition: ntstatus.h:732
#define STATUS_WAIT_1
Definition: ntstatus.h:71
#define STATUS_BAD_DESCRIPTOR_FORMAT
Definition: ntstatus.h:467
#define STATUS_BAD_COMPRESSION_BUFFER
Definition: ntstatus.h:710
#define STATUS_INVALID_SID
Definition: ntstatus.h:356
#define STATUS_INVALID_PARAMETER_2
Definition: ntstatus.h:476
#define STATUS_INVALID_PARAMETER_1
Definition: ntstatus.h:475
#define STATUS_INVALID_PARAMETER_3
Definition: ntstatus.h:477
@ COINIT_APARTMENTTHREADED
Definition: objbase.h:278
#define IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: pedump.c:260
short SHORT
Definition: pedump.c:59
unsigned short USHORT
Definition: pedump.c:61
#define WINAPIV
Definition: sdbpapi.h:64
#define win_skip
Definition: test.h:160
#define memset(x, y, z)
Definition: compat.h:39
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
HRESULT hr
Definition: shlfolder.c:183
@ AO_NOERRORUI
Definition: shobjidl.idl:4353
Definition: rtl.c:827
void * MyValue
Definition: rtl.c:829
RTL_HANDLE RtlHandle
Definition: rtl.c:828
union _IMAGE_THUNK_DATA32::@2134 u1
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
ULONG Unused[2]
Definition: rtl.c:47
PVOID ReservedMemory
Definition: rtl.c:50
PVOID FirstHandle
Definition: rtl.c:49
PVOID MaxHandle
Definition: rtl.c:51
PVOID NextFree
Definition: rtl.c:48
ULONG MaxHandleCount
Definition: rtl.c:45
ULONG HandleSize
Definition: rtl.c:46
struct _RTL_HANDLE * Next
Definition: rtl.c:40
ACCESS_MASK GrantedAccess
Definition: rtl.c:726
BOOLEAN result
Definition: rtl.c:728
ACCESS_MASK DesiredAccess
Definition: rtl.c:727
ACCESS_MASK GrantedAccess
Definition: rtl.c:770
BOOLEAN result
Definition: rtl.c:772
ACCESS_MASK DesiredAccess
Definition: rtl.c:771
Definition: http.c:7252
Definition: cookie.c:34
CRITICAL_SECTION crit
Definition: rtl.c:3051
HANDLE semaphores[2]
Definition: rtl.c:3052
Definition: tcpip.h:126
u_long S_addr
Definition: tcpip.h:131
union in_addr::@1020 S_un
Definition: dhcpd.h:62
BOOL abort
Definition: rtl.c:3240
BOOL found
Definition: rtl.c:3241
Definition: name.c:39
Definition: ps.c:97
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:751
HANDLE WINAPI DECLSPEC_HOTPATCH CreateSemaphoreW(IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes OPTIONAL, IN LONG lInitialCount, IN LONG lMaximumCount, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:444
BOOL WINAPI DECLSPEC_HOTPATCH ReleaseSemaphore(IN HANDLE hSemaphore, IN LONG lReleaseCount, IN LPLONG lpPreviousCount)
Definition: synch.c:542
int32_t INT_PTR
Definition: typedefs.h:64
char * PSTR
Definition: typedefs.h:51
const uint16_t * PCWSTR
Definition: typedefs.h:57
uint32_t DWORD_PTR
Definition: typedefs.h:65
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define MAXLONG
Definition: umtypes.h:116
int ret
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
#define WAIT_OBJECT_0
Definition: winbase.h:406
#define WINAPI
Definition: msvc.h:6
#define IMAGE_REL_BASED_HIGHLOW
Definition: winnt_old.h:852
#define IMAGE_REL_BASED_HIGH
Definition: winnt_old.h:850
#define RTL_CRITICAL_SECTION_FLAG_NO_DEBUG_INFO
Definition: winnt_old.h:1085
#define IMAGE_REL_BASED_LOW
Definition: winnt_old.h:851
_In_ PSECURITY_SUBJECT_CONTEXT _In_ BOOLEAN _In_ ACCESS_MASK _In_ ACCESS_MASK _Outptr_opt_ PPRIVILEGE_SET _In_ PGENERIC_MAPPING _In_ KPROCESSOR_MODE _Out_ PACCESS_MASK GrantedAccess
Definition: sefuncs.h:20
#define TOKEN_QUERY
Definition: setypes.h:928
#define SE_SELF_RELATIVE
Definition: setypes.h:834
struct _SECURITY_DESCRIPTOR_RELATIVE SECURITY_DESCRIPTOR_RELATIVE
#define SECURITY_DESCRIPTOR_REVISION
Definition: setypes.h:58
* PSID_IDENTIFIER_AUTHORITY
Definition: setypes.h:464
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193