1 /* Unit test suite for Rtl* Registry API functions 2 * 3 * Copyright 2003 Thomas Mertes 4 * Copyright 2005 Brad DeMorrow 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 * 20 * NOTE: I don't test every RelativeTo value because it would be redundant, all calls go through 21 * helper function RTL_GetKeyHandle().--Brad DeMorrow 22 * 23 */ 24 25 #include "ntdll_test.h" 26 #include "winternl.h" 27 #include "stdio.h" 28 #include "winnt.h" 29 #include "winnls.h" 30 #include "stdlib.h" 31 32 /* A test string */ 33 static const WCHAR stringW[] = {'s', 't', 'r', 'i', 'n', 'g', 'W', 0}; 34 /* A size, in bytes, short enough to cause truncation of the above */ 35 #define STR_TRUNC_SIZE (sizeof(stringW)-2*sizeof(*stringW)) 36 37 #ifndef __WINE_WINTERNL_H 38 39 /* RtlQueryRegistryValues structs and defines */ 40 #define RTL_REGISTRY_ABSOLUTE 0 41 #define RTL_REGISTRY_SERVICES 1 42 #define RTL_REGISTRY_CONTROL 2 43 #define RTL_REGISTRY_WINDOWS_NT 3 44 #define RTL_REGISTRY_DEVICEMAP 4 45 #define RTL_REGISTRY_USER 5 46 47 #define RTL_REGISTRY_HANDLE 0x40000000 48 #define RTL_REGISTRY_OPTIONAL 0x80000000 49 50 #define RTL_QUERY_REGISTRY_SUBKEY 0x00000001 51 #define RTL_QUERY_REGISTRY_TOPKEY 0x00000002 52 #define RTL_QUERY_REGISTRY_REQUIRED 0x00000004 53 #define RTL_QUERY_REGISTRY_NOVALUE 0x00000008 54 #define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010 55 #define RTL_QUERY_REGISTRY_DIRECT 0x00000020 56 #define RTL_QUERY_REGISTRY_DELETE 0x00000040 57 58 typedef NTSTATUS (WINAPI *PRTL_QUERY_REGISTRY_ROUTINE)( PCWSTR ValueName, 59 ULONG ValueType, 60 PVOID ValueData, 61 ULONG ValueLength, 62 PVOID Context, 63 PVOID EntryContext); 64 65 typedef struct _RTL_QUERY_REGISTRY_TABLE { 66 PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine; 67 ULONG Flags; 68 PWSTR Name; 69 PVOID EntryContext; 70 ULONG DefaultType; 71 PVOID DefaultData; 72 ULONG DefaultLength; 73 } RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE; 74 75 typedef struct _KEY_VALUE_BASIC_INFORMATION { 76 ULONG TitleIndex; 77 ULONG Type; 78 ULONG NameLength; 79 WCHAR Name[1]; 80 } KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; 81 82 typedef struct _KEY_VALUE_PARTIAL_INFORMATION { 83 ULONG TitleIndex; 84 ULONG Type; 85 ULONG DataLength; 86 UCHAR Data[1]; 87 } KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION; 88 89 typedef struct _KEY_VALUE_FULL_INFORMATION { 90 ULONG TitleIndex; 91 ULONG Type; 92 ULONG DataOffset; 93 ULONG DataLength; 94 ULONG NameLength; 95 WCHAR Name[1]; 96 } KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION; 97 98 typedef enum _KEY_VALUE_INFORMATION_CLASS { 99 KeyValueBasicInformation, 100 KeyValueFullInformation, 101 KeyValuePartialInformation, 102 KeyValueFullInformationAlign64, 103 KeyValuePartialInformationAlign64 104 } KEY_VALUE_INFORMATION_CLASS; 105 106 #define InitializeObjectAttributes(p,n,a,r,s) \ 107 do { \ 108 (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ 109 (p)->RootDirectory = r; \ 110 (p)->Attributes = a; \ 111 (p)->ObjectName = n; \ 112 (p)->SecurityDescriptor = s; \ 113 (p)->SecurityQualityOfService = NULL; \ 114 } while (0) 115 116 #endif 117 118 static BOOLEAN (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR); 119 static void (WINAPI * pRtlInitUnicodeString)(PUNICODE_STRING,PCWSTR); 120 static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING); 121 static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING); 122 static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_QUERY_REGISTRY_TABLE, IN PVOID,IN PVOID); 123 static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR); 124 static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, PHANDLE); 125 static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES); 126 static NTSTATUS (WINAPI * pNtOpenKeyEx)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG); 127 static NTSTATUS (WINAPI * pNtClose)(IN HANDLE); 128 static NTSTATUS (WINAPI * pNtFlushKey)(HANDLE); 129 static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE); 130 static NTSTATUS (WINAPI * pNtCreateKey)( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, 131 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options, 132 PULONG dispos ); 133 static NTSTATUS (WINAPI * pNtQueryKey)(HANDLE,KEY_INFORMATION_CLASS,PVOID,ULONG,PULONG); 134 static NTSTATUS (WINAPI * pNtQueryLicenseValue)(const UNICODE_STRING *,ULONG *,PVOID,ULONG,ULONG *); 135 static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *); 136 static NTSTATUS (WINAPI * pNtSetValueKey)(HANDLE, const PUNICODE_STRING, ULONG, 137 ULONG, const void*, ULONG ); 138 static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE,PROCESSINFOCLASS,PVOID,ULONG,PULONG); 139 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING); 140 static LONG (WINAPI * pRtlCompareUnicodeString)(const PUNICODE_STRING,const PUNICODE_STRING,BOOLEAN); 141 static BOOLEAN (WINAPI * pRtlCreateUnicodeString)(PUNICODE_STRING, LPCWSTR); 142 static LPVOID (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG); 143 static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR); 144 static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL); 145 static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID); 146 static LPVOID (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG); 147 static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG); 148 static NTSTATUS (WINAPI * pRtlpNtQueryValueKey)(HANDLE,ULONG*,PBYTE,DWORD*,void *); 149 static NTSTATUS (WINAPI * pNtNotifyChangeKey)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,PIO_STATUS_BLOCK,ULONG,BOOLEAN,PVOID,ULONG,BOOLEAN); 150 static NTSTATUS (WINAPI * pNtNotifyChangeMultipleKeys)(HANDLE,ULONG,OBJECT_ATTRIBUTES*,HANDLE,PIO_APC_ROUTINE, 151 void*,IO_STATUS_BLOCK*,ULONG,BOOLEAN,void*,ULONG,BOOLEAN); 152 static NTSTATUS (WINAPI * pNtWaitForSingleObject)(HANDLE,BOOLEAN,const LARGE_INTEGER*); 153 154 static HMODULE hntdll = 0; 155 static int CurrentTest = 0; 156 static UNICODE_STRING winetestpath; 157 158 #define NTDLL_GET_PROC(func) \ 159 p ## func = (void*)GetProcAddress(hntdll, #func); \ 160 if(!p ## func) { \ 161 trace("GetProcAddress(%s) failed\n", #func); \ 162 FreeLibrary(hntdll); \ 163 return FALSE; \ 164 } 165 166 static BOOL InitFunctionPtrs(void) 167 { 168 hntdll = LoadLibraryA("ntdll.dll"); 169 if(!hntdll) { 170 trace("Could not load ntdll.dll\n"); 171 return FALSE; 172 } 173 NTDLL_GET_PROC(RtlInitUnicodeString) 174 NTDLL_GET_PROC(RtlCreateUnicodeStringFromAsciiz) 175 NTDLL_GET_PROC(RtlCreateUnicodeString) 176 NTDLL_GET_PROC(RtlFreeUnicodeString) 177 NTDLL_GET_PROC(RtlQueryRegistryValues) 178 NTDLL_GET_PROC(RtlCheckRegistryKey) 179 NTDLL_GET_PROC(RtlOpenCurrentUser) 180 NTDLL_GET_PROC(NtClose) 181 NTDLL_GET_PROC(NtDeleteValueKey) 182 NTDLL_GET_PROC(NtCreateKey) 183 NTDLL_GET_PROC(NtFlushKey) 184 NTDLL_GET_PROC(NtDeleteKey) 185 NTDLL_GET_PROC(NtQueryKey) 186 NTDLL_GET_PROC(NtQueryValueKey) 187 NTDLL_GET_PROC(NtQueryInformationProcess) 188 NTDLL_GET_PROC(NtSetValueKey) 189 NTDLL_GET_PROC(NtOpenKey) 190 NTDLL_GET_PROC(NtNotifyChangeKey) 191 NTDLL_GET_PROC(RtlFormatCurrentUserKeyPath) 192 NTDLL_GET_PROC(RtlCompareUnicodeString) 193 NTDLL_GET_PROC(RtlReAllocateHeap) 194 NTDLL_GET_PROC(RtlAppendUnicodeToString) 195 NTDLL_GET_PROC(RtlUnicodeStringToAnsiString) 196 NTDLL_GET_PROC(RtlFreeHeap) 197 NTDLL_GET_PROC(RtlAllocateHeap) 198 NTDLL_GET_PROC(RtlZeroMemory) 199 NTDLL_GET_PROC(RtlpNtQueryValueKey) 200 NTDLL_GET_PROC(RtlOpenCurrentUser) 201 NTDLL_GET_PROC(NtWaitForSingleObject) 202 203 /* optional functions */ 204 pNtQueryLicenseValue = (void *)GetProcAddress(hntdll, "NtQueryLicenseValue"); 205 pNtOpenKeyEx = (void *)GetProcAddress(hntdll, "NtOpenKeyEx"); 206 pNtNotifyChangeMultipleKeys = (void *)GetProcAddress(hntdll, "NtNotifyChangeMultipleKeys"); 207 208 return TRUE; 209 } 210 #undef NTDLL_GET_PROC 211 212 static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, 213 IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext) 214 { 215 NTSTATUS ret = STATUS_SUCCESS; 216 217 trace("**Test %d**\n", CurrentTest); 218 trace("ValueName: %s\n", wine_dbgstr_w(ValueName)); 219 220 switch(ValueType) 221 { 222 case REG_NONE: 223 trace("ValueType: REG_NONE\n"); 224 trace("ValueData: %p\n", ValueData); 225 break; 226 227 case REG_BINARY: 228 trace("ValueType: REG_BINARY\n"); 229 trace("ValueData: %p\n", ValueData); 230 break; 231 232 case REG_SZ: 233 trace("ValueType: REG_SZ\n"); 234 trace("ValueData: %s\n", (char*)ValueData); 235 break; 236 237 case REG_MULTI_SZ: 238 trace("ValueType: REG_MULTI_SZ\n"); 239 trace("ValueData: %s\n", (char*)ValueData); 240 break; 241 242 case REG_EXPAND_SZ: 243 trace("ValueType: REG_EXPAND_SZ\n"); 244 trace("ValueData: %s\n", (char*)ValueData); 245 break; 246 247 case REG_DWORD: 248 trace("ValueType: REG_DWORD\n"); 249 trace("ValueData: %p\n", ValueData); 250 break; 251 }; 252 trace("ValueLength: %d\n", (int)ValueLength); 253 254 if(CurrentTest == 0) 255 ok(1, "\n"); /*checks that QueryRoutine is called*/ 256 if(CurrentTest > 7) 257 ok(!1, "Invalid Test Specified!\n"); 258 259 CurrentTest++; 260 261 return ret; 262 } 263 264 static void test_RtlQueryRegistryValues(void) 265 { 266 267 /* 268 ****************************** 269 * QueryTable Flags * 270 ****************************** 271 *RTL_QUERY_REGISTRY_SUBKEY * Name is the name of a subkey relative to Path 272 *RTL_QUERY_REGISTRY_TOPKEY * Resets location to original RelativeTo and Path 273 *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present 274 *RTL_QUERY_REGISTRY_NOVALUE * We just want a call-back 275 *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables! 276 *RTL_QUERY_REGISTRY_DIRECT * Results of query will be stored in EntryContext(QueryRoutine ignored) 277 *RTL_QUERY_REGISTRY_DELETE * Delete value key after query 278 ****************************** 279 280 281 **Test layout(numbered according to CurrentTest value)** 282 0)NOVALUE Just make sure call-back works 283 1)Null Name See if QueryRoutine is called for every value in current key 284 2)SUBKEY See if we can use SUBKEY to change the current path on the fly 285 3)REQUIRED Test for value that's not there 286 4)NOEXPAND See if it will return multiple strings(no expand should split strings up) 287 5)DIRECT Make it store data directly in EntryContext and not call QueryRoutine 288 6)DefaultType Test return values when key isn't present 289 7)DefaultValue Test Default Value returned with key isn't present(and no REQUIRED flag set) 290 8)DefaultLength Test Default Length with DefaultType = REG_SZ 291 9)DefaultLength Test Default Length with DefaultType = REG_MULTI_SZ 292 10)DefaultLength Test Default Length with DefaultType = REG_EXPAND_SZ 293 11)DefaultData Test whether DefaultData is used while DefaultType = REG_NONE(shouldn't be) 294 12)Delete Try to delete value key 295 296 */ 297 NTSTATUS status; 298 ULONG RelativeTo; 299 300 PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL; 301 RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/ 302 303 QueryTable = pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26); 304 305 pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26); 306 307 QueryTable[0].QueryRoutine = QueryRoutine; 308 QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE; 309 QueryTable[0].Name = NULL; 310 QueryTable[0].EntryContext = NULL; 311 QueryTable[0].DefaultType = REG_BINARY; 312 QueryTable[0].DefaultData = NULL; 313 QueryTable[0].DefaultLength = 100; 314 315 QueryTable[1].QueryRoutine = QueryRoutine; 316 QueryTable[1].Flags = 0; 317 QueryTable[1].Name = NULL; 318 QueryTable[1].EntryContext = 0; 319 QueryTable[1].DefaultType = REG_NONE; 320 QueryTable[1].DefaultData = NULL; 321 QueryTable[1].DefaultLength = 0; 322 323 QueryTable[2].QueryRoutine = NULL; 324 QueryTable[2].Flags = 0; 325 QueryTable[2].Name = NULL; 326 QueryTable[2].EntryContext = 0; 327 QueryTable[2].DefaultType = REG_NONE; 328 QueryTable[2].DefaultData = NULL; 329 QueryTable[2].DefaultLength = 0; 330 331 status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0); 332 ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08x\n", status); 333 334 pRtlFreeHeap(GetProcessHeap(), 0, QueryTable); 335 } 336 337 static void test_NtOpenKey(void) 338 { 339 HANDLE key; 340 NTSTATUS status; 341 OBJECT_ATTRIBUTES attr; 342 ACCESS_MASK am = KEY_READ; 343 UNICODE_STRING str; 344 345 /* All NULL */ 346 status = pNtOpenKey(NULL, 0, NULL); 347 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status); 348 349 /* NULL attributes */ 350 status = pNtOpenKey(&key, 0, NULL); 351 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */, 352 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status); 353 354 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 355 356 /* NULL key */ 357 status = pNtOpenKey(NULL, am, &attr); 358 ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION, got: 0x%08x\n", status); 359 360 /* Length > sizeof(OBJECT_ATTRIBUTES) */ 361 attr.Length *= 2; 362 status = pNtOpenKey(&key, am, &attr); 363 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status); 364 365 /* Zero accessmask */ 366 attr.Length = sizeof(attr); 367 key = (HANDLE)0xdeadbeef; 368 status = pNtOpenKey(&key, 0, &attr); 369 todo_wine 370 ok(status == STATUS_ACCESS_DENIED, "Expected STATUS_ACCESS_DENIED, got: 0x%08x\n", status); 371 todo_wine 372 ok(!key, "key = %p\n", key); 373 if (status == STATUS_SUCCESS) NtClose(key); 374 375 /* Calling without parent key requres full registry path. */ 376 pRtlCreateUnicodeStringFromAsciiz( &str, "Machine" ); 377 InitializeObjectAttributes(&attr, &str, 0, 0, 0); 378 key = (HANDLE)0xdeadbeef; 379 status = pNtOpenKey(&key, KEY_READ, &attr); 380 todo_wine ok(status == STATUS_OBJECT_PATH_SYNTAX_BAD, "NtOpenKey Failed: 0x%08x\n", status); 381 todo_wine 382 ok(!key, "key = %p\n", key); 383 pRtlFreeUnicodeString( &str ); 384 385 /* Open is case sensitive unless OBJ_CASE_INSENSITIVE is specified. */ 386 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Registry\\Machine" ); 387 status = pNtOpenKey(&key, KEY_READ, &attr); 388 todo_wine ok(status == STATUS_OBJECT_PATH_NOT_FOUND, "NtOpenKey Failed: 0x%08x\n", status); 389 390 attr.Attributes = OBJ_CASE_INSENSITIVE; 391 status = pNtOpenKey(&key, KEY_READ, &attr); 392 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status); 393 pNtClose(key); 394 pRtlFreeUnicodeString( &str ); 395 396 pRtlCreateUnicodeStringFromAsciiz( &str, "" ); 397 status = pNtOpenKey(&key, KEY_READ, &attr); 398 todo_wine 399 ok( status == STATUS_OBJECT_PATH_SYNTAX_BAD, "NtOpenKey failed: 0x%08x\n", status ); 400 pRtlFreeUnicodeString( &str ); 401 402 pRtlCreateUnicodeStringFromAsciiz( &str, "\\" ); 403 status = pNtOpenKey(&key, KEY_READ, &attr); 404 todo_wine 405 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtOpenKey failed: 0x%08x\n", status ); 406 pRtlFreeUnicodeString( &str ); 407 408 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Registry" ); 409 status = pNtOpenKey(&key, KEY_READ, &attr); 410 todo_wine 411 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 412 pNtClose( key ); 413 pRtlFreeUnicodeString( &str ); 414 415 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Registry\\" ); 416 status = pNtOpenKey(&key, KEY_READ, &attr); 417 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 418 pNtClose( key ); 419 pRtlFreeUnicodeString( &str ); 420 421 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Foobar" ); 422 status = pNtOpenKey(&key, KEY_READ, &attr); 423 todo_wine 424 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey failed: 0x%08x\n", status ); 425 pRtlFreeUnicodeString( &str ); 426 427 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Foobar\\Machine" ); 428 status = pNtOpenKey(&key, KEY_READ, &attr); 429 todo_wine 430 ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "NtOpenKey failed: 0x%08x\n", status ); 431 pRtlFreeUnicodeString( &str ); 432 433 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Machine\\Software\\Classes" ); 434 status = pNtOpenKey(&key, KEY_READ, &attr); 435 todo_wine 436 ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "NtOpenKey failed: 0x%08x\n", status ); 437 pRtlFreeUnicodeString( &str ); 438 439 pRtlCreateUnicodeStringFromAsciiz( &str, "Machine\\Software\\Classes" ); 440 status = pNtOpenKey(&key, KEY_READ, &attr); 441 todo_wine 442 ok( status == STATUS_OBJECT_PATH_SYNTAX_BAD, "NtOpenKey failed: 0x%08x\n", status ); 443 pRtlFreeUnicodeString( &str ); 444 445 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Device\\Null" ); 446 status = pNtOpenKey(&key, KEY_READ, &attr); 447 todo_wine 448 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtOpenKey failed: 0x%08x\n", status ); 449 pRtlFreeUnicodeString( &str ); 450 451 if (!pNtOpenKeyEx) 452 { 453 win_skip("NtOpenKeyEx not available\n"); 454 return; 455 } 456 457 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 458 status = pNtOpenKeyEx(&key, KEY_WRITE|KEY_READ, &attr, 0); 459 ok(status == STATUS_SUCCESS, "NtOpenKeyEx Failed: 0x%08x\n", status); 460 461 pNtClose(key); 462 } 463 464 static void test_NtCreateKey(void) 465 { 466 /*Create WineTest*/ 467 OBJECT_ATTRIBUTES attr; 468 HANDLE key, subkey; 469 ACCESS_MASK am = GENERIC_ALL; 470 NTSTATUS status; 471 UNICODE_STRING str; 472 473 /* All NULL */ 474 status = pNtCreateKey(NULL, 0, NULL, 0, 0, 0, 0); 475 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER, 476 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status); 477 478 /* Only the key */ 479 status = pNtCreateKey(&key, 0, NULL, 0, 0, 0, 0); 480 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */, 481 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status); 482 483 /* Only accessmask */ 484 status = pNtCreateKey(NULL, am, NULL, 0, 0, 0, 0); 485 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_INVALID_PARAMETER, 486 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER, got: 0x%08x\n", status); 487 488 /* Key and accessmask */ 489 status = pNtCreateKey(&key, am, NULL, 0, 0, 0, 0); 490 ok(status == STATUS_ACCESS_VIOLATION /* W2K3/XP/W2K */ || status == STATUS_INVALID_PARAMETER /* NT4 */, 491 "Expected STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER(NT4), got: 0x%08x\n", status); 492 493 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 494 495 /* Only attributes */ 496 status = pNtCreateKey(NULL, 0, &attr, 0, 0, 0, 0); 497 ok(status == STATUS_ACCESS_VIOLATION || status == STATUS_ACCESS_DENIED /* Win7 */, 498 "Expected STATUS_ACCESS_VIOLATION or STATUS_ACCESS_DENIED, got: 0x%08x\n", status); 499 500 /* Length > sizeof(OBJECT_ATTRIBUTES) */ 501 attr.Length *= 2; 502 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0); 503 ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER, got: 0x%08x\n", status); 504 505 attr.Length = sizeof(attr); 506 status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0); 507 ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08x\n", status); 508 509 attr.RootDirectory = key; 510 attr.ObjectName = &str; 511 512 pRtlCreateUnicodeStringFromAsciiz( &str, "test\\sub\\key" ); 513 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 514 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status ); 515 pRtlFreeUnicodeString( &str ); 516 517 pRtlCreateUnicodeStringFromAsciiz( &str, "test\\subkey" ); 518 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 519 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status ); 520 pRtlFreeUnicodeString( &str ); 521 522 pRtlCreateUnicodeStringFromAsciiz( &str, "test\\subkey\\" ); 523 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 524 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status ); 525 pRtlFreeUnicodeString( &str ); 526 527 pRtlCreateUnicodeStringFromAsciiz( &str, "test_subkey\\" ); 528 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 529 ok( status == STATUS_SUCCESS || broken(status == STATUS_OBJECT_NAME_NOT_FOUND), /* nt4 */ 530 "NtCreateKey failed: 0x%08x\n", status ); 531 if (status == STATUS_SUCCESS) 532 { 533 pNtDeleteKey( subkey ); 534 pNtClose( subkey ); 535 } 536 pRtlFreeUnicodeString( &str ); 537 538 pRtlCreateUnicodeStringFromAsciiz( &str, "test_subkey" ); 539 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 540 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 541 pRtlFreeUnicodeString( &str ); 542 pNtDeleteKey( subkey ); 543 pNtClose( subkey ); 544 545 attr.RootDirectory = 0; 546 attr.Attributes = OBJ_CASE_INSENSITIVE; 547 548 pRtlCreateUnicodeStringFromAsciiz( &str, "" ); 549 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 550 todo_wine 551 ok( status == STATUS_OBJECT_PATH_SYNTAX_BAD, "NtCreateKey failed: 0x%08x\n", status ); 552 pRtlFreeUnicodeString( &str ); 553 554 pRtlCreateUnicodeStringFromAsciiz( &str, "\\" ); 555 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 556 todo_wine 557 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtCreateKey failed: 0x%08x\n", status ); 558 pRtlFreeUnicodeString( &str ); 559 560 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Registry" ); 561 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 562 todo_wine 563 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED, 564 "NtCreateKey failed: 0x%08x\n", status ); 565 if (!status) pNtClose( subkey ); 566 pRtlFreeUnicodeString( &str ); 567 568 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Registry\\" ); 569 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 570 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED, 571 "NtCreateKey failed: 0x%08x\n", status ); 572 if (!status) pNtClose( subkey ); 573 pRtlFreeUnicodeString( &str ); 574 575 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Foobar" ); 576 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 577 todo_wine 578 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status ); 579 pRtlFreeUnicodeString( &str ); 580 581 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Foobar\\Machine" ); 582 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 583 todo_wine 584 ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status ); 585 pRtlFreeUnicodeString( &str ); 586 587 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Machine\\Software\\Classes" ); 588 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 589 todo_wine 590 ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status ); 591 pRtlFreeUnicodeString( &str ); 592 593 pRtlCreateUnicodeStringFromAsciiz( &str, "Machine\\Software\\Classes" ); 594 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 595 todo_wine 596 ok( status == STATUS_OBJECT_PATH_SYNTAX_BAD, "NtCreateKey failed: 0x%08x\n", status ); 597 pRtlFreeUnicodeString( &str ); 598 599 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Device\\Null" ); 600 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 601 todo_wine 602 ok( status == STATUS_OBJECT_TYPE_MISMATCH, "NtCreateKey failed: 0x%08x\n", status ); 603 pRtlFreeUnicodeString( &str ); 604 605 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Registry\\Machine\\Software\\Classes" ); 606 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 607 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED, 608 "NtCreateKey failed: 0x%08x\n", status ); 609 if (!status) pNtClose( subkey ); 610 pRtlFreeUnicodeString( &str ); 611 612 /* the REGISTRY part is case-sensitive unless OBJ_CASE_INSENSITIVE is specified */ 613 attr.Attributes = 0; 614 pRtlCreateUnicodeStringFromAsciiz( &str, "\\Registry\\Machine\\Software\\Classes" ); 615 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 616 todo_wine 617 ok( status == STATUS_OBJECT_PATH_NOT_FOUND, "NtCreateKey failed: 0x%08x\n", status ); 618 pRtlFreeUnicodeString( &str ); 619 620 pRtlCreateUnicodeStringFromAsciiz( &str, "\\REGISTRY\\Machine\\Software\\Classes" ); 621 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 622 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED, 623 "NtCreateKey failed: 0x%08x\n", status ); 624 if (!status) pNtClose( subkey ); 625 pRtlFreeUnicodeString( &str ); 626 627 pRtlCreateUnicodeStringFromAsciiz( &str, "\\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES" ); 628 status = pNtCreateKey( &subkey, am, &attr, 0, 0, 0, 0 ); 629 ok( status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED, 630 "NtCreateKey failed: 0x%08x\n", status ); 631 if (!status) pNtClose( subkey ); 632 pRtlFreeUnicodeString( &str ); 633 634 pNtClose(key); 635 } 636 637 static void test_NtSetValueKey(void) 638 { 639 HANDLE key; 640 NTSTATUS status; 641 OBJECT_ATTRIBUTES attr; 642 ACCESS_MASK am = KEY_WRITE; 643 UNICODE_STRING ValName; 644 DWORD data = 711; 645 646 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 647 status = pNtOpenKey(&key, am, &attr); 648 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status); 649 650 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest"); 651 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data)); 652 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status); 653 pRtlFreeUnicodeString(&ValName); 654 655 pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest"); 656 status = pNtSetValueKey(key, &ValName, 0, REG_SZ, (VOID*)stringW, STR_TRUNC_SIZE); 657 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status); 658 pRtlFreeUnicodeString(&ValName); 659 660 pNtClose(key); 661 } 662 663 static void test_RtlOpenCurrentUser(void) 664 { 665 NTSTATUS status; 666 HANDLE handle; 667 status=pRtlOpenCurrentUser(KEY_READ, &handle); 668 ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08x\n", status); 669 pNtClose(handle); 670 } 671 672 static void test_RtlCheckRegistryKey(void) 673 { 674 NTSTATUS status; 675 676 status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer); 677 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08x\n", status); 678 679 status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL), winetestpath.Buffer); 680 ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE and RTL_REGISTRY_OPTIONAL: 0x%08x\n", status); 681 } 682 683 static void test_NtFlushKey(void) 684 { 685 NTSTATUS status; 686 HANDLE hkey; 687 OBJECT_ATTRIBUTES attr; 688 ACCESS_MASK am = KEY_ALL_ACCESS; 689 690 status = pNtFlushKey(NULL); 691 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status); 692 693 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 694 pNtOpenKey(&hkey, am, &attr); 695 696 status = pNtFlushKey(hkey); 697 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status); 698 699 pNtClose(hkey); 700 } 701 702 static void test_NtQueryValueKey(void) 703 { 704 HANDLE key; 705 NTSTATUS status; 706 OBJECT_ATTRIBUTES attr; 707 UNICODE_STRING ValName; 708 KEY_VALUE_BASIC_INFORMATION *basic_info; 709 KEY_VALUE_PARTIAL_INFORMATION *partial_info, pi; 710 KEY_VALUE_FULL_INFORMATION *full_info; 711 DWORD len, expected; 712 713 pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest"); 714 715 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 716 status = pNtOpenKey(&key, KEY_READ|KEY_SET_VALUE, &attr); 717 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status); 718 719 len = FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[0]); 720 basic_info = HeapAlloc(GetProcessHeap(), 0, len); 721 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len); 722 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status); 723 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex); 724 ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type); 725 ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength); 726 ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len); 727 728 basic_info = HeapReAlloc(GetProcessHeap(), 0, basic_info, len); 729 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, basic_info, len, &len); 730 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status); 731 ok(basic_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", basic_info->TitleIndex); 732 ok(basic_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", basic_info->Type); 733 ok(basic_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", basic_info->NameLength); 734 ok(len == FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION, Name[basic_info->NameLength/sizeof(WCHAR)]), "NtQueryValueKey returned wrong len %d\n", len); 735 ok(!memcmp(basic_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n"); 736 HeapFree(GetProcessHeap(), 0, basic_info); 737 738 len = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]); 739 partial_info = HeapAlloc(GetProcessHeap(), 0, len); 740 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len); 741 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status); 742 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex); 743 ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type); 744 ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength); 745 ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len); 746 747 partial_info = HeapReAlloc(GetProcessHeap(), 0, partial_info, len); 748 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len); 749 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status); 750 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex); 751 ok(partial_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type); 752 ok(partial_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength); 753 ok(len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[partial_info->DataLength]), "NtQueryValueKey returned wrong len %d\n", len); 754 ok(*(DWORD *)partial_info->Data == 711, "incorrect Data returned: 0x%x\n", *(DWORD *)partial_info->Data); 755 HeapFree(GetProcessHeap(), 0, partial_info); 756 757 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]); 758 full_info = HeapAlloc(GetProcessHeap(), 0, len); 759 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len); 760 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey should have returned STATUS_BUFFER_OVERFLOW instead of 0x%08x\n", status); 761 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex); 762 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type); 763 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength); 764 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength); 765 ok(len == FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength, 766 "NtQueryValueKey returned wrong len %d\n", len); 767 len = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name[0]) + full_info->DataLength + full_info->NameLength; 768 769 full_info = HeapReAlloc(GetProcessHeap(), 0, full_info, len); 770 status = pNtQueryValueKey(key, &ValName, KeyValueFullInformation, full_info, len, &len); 771 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status); 772 ok(full_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", full_info->TitleIndex); 773 ok(full_info->Type == REG_DWORD, "NtQueryValueKey returned wrong Type %d\n", full_info->Type); 774 ok(full_info->DataLength == 4, "NtQueryValueKey returned wrong DataLength %d\n", full_info->DataLength); 775 ok(full_info->NameLength == 20, "NtQueryValueKey returned wrong NameLength %d\n", full_info->NameLength); 776 ok(!memcmp(full_info->Name, ValName.Buffer, ValName.Length), "incorrect Name returned\n"); 777 ok(*(DWORD *)((char *)full_info + full_info->DataOffset) == 711, "incorrect Data returned: 0x%x\n", 778 *(DWORD *)((char *)full_info + full_info->DataOffset)); 779 HeapFree(GetProcessHeap(), 0, full_info); 780 781 pRtlFreeUnicodeString(&ValName); 782 pRtlCreateUnicodeStringFromAsciiz(&ValName, "stringtest"); 783 784 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, NULL, 0, &len); 785 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey should have returned STATUS_BUFFER_TOO_SMALL instead of 0x%08x\n", status); 786 partial_info = HeapAlloc(GetProcessHeap(), 0, len+1); 787 memset(partial_info, 0xbd, len+1); 788 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, len, &len); 789 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status); 790 ok(partial_info->TitleIndex == 0, "NtQueryValueKey returned wrong TitleIndex %d\n", partial_info->TitleIndex); 791 ok(partial_info->Type == REG_SZ, "NtQueryValueKey returned wrong Type %d\n", partial_info->Type); 792 ok(partial_info->DataLength == STR_TRUNC_SIZE, "NtQueryValueKey returned wrong DataLength %d\n", partial_info->DataLength); 793 ok(!memcmp(partial_info->Data, stringW, STR_TRUNC_SIZE), "incorrect Data returned\n"); 794 ok(*(partial_info->Data+STR_TRUNC_SIZE) == 0xbd, "string overflowed %02x\n", *(partial_info->Data+STR_TRUNC_SIZE)); 795 796 expected = len; 797 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, 0, &len); 798 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status); 799 ok(len == expected, "NtQueryValueKey wrong len %u\n", len); 800 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, 1, &len); 801 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status); 802 ok(len == expected, "NtQueryValueKey wrong len %u\n", len); 803 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) - 1, &len); 804 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryValueKey wrong status 0x%08x\n", status); 805 ok(len == expected, "NtQueryValueKey wrong len %u\n", len); 806 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, partial_info, FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data), &len); 807 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryValueKey wrong status 0x%08x\n", status); 808 ok(len == expected, "NtQueryValueKey wrong len %u\n", len); 809 810 HeapFree(GetProcessHeap(), 0, partial_info); 811 pRtlFreeUnicodeString(&ValName); 812 813 pRtlCreateUnicodeStringFromAsciiz(&ValName, "custtest"); 814 status = pNtSetValueKey(key, &ValName, 0, 0xff00ff00, NULL, 0); 815 ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08x\n", status); 816 817 status = pNtQueryValueKey(key, &ValName, KeyValuePartialInformation, &pi, sizeof(pi), &len); 818 ok(status == STATUS_SUCCESS, "NtQueryValueKey should have returned STATUS_SUCCESS instead of 0x%08x\n", status); 819 ok(pi.Type == 0xff00ff00, "Type=%x\n", pi.Type); 820 ok(pi.DataLength == 0, "DataLength=%u\n", pi.DataLength); 821 pRtlFreeUnicodeString(&ValName); 822 823 pNtClose(key); 824 } 825 826 static void test_NtDeleteKey(void) 827 { 828 NTSTATUS status; 829 HANDLE hkey; 830 OBJECT_ATTRIBUTES attr; 831 ACCESS_MASK am = KEY_ALL_ACCESS; 832 833 status = pNtDeleteKey(NULL); 834 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status); 835 836 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 837 status = pNtOpenKey(&hkey, am, &attr); 838 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status); 839 840 status = pNtDeleteKey(hkey); 841 ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status); 842 } 843 844 static void test_NtQueryLicenseKey(void) 845 { 846 static const WCHAR emptyW[] = {'E','M','P','T','Y',0}; 847 UNICODE_STRING name; 848 WORD buffer[32]; 849 NTSTATUS status; 850 ULONG type, len; 851 DWORD value; 852 853 if (!pNtQueryLicenseValue) 854 { 855 win_skip("NtQueryLicenseValue not found, skipping tests\n"); 856 return; 857 } 858 859 type = 0xdead; 860 len = 0xbeef; 861 memset(&name, 0, sizeof(name)); 862 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len); 863 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 864 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 865 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); 866 867 /* test with empty key */ 868 pRtlCreateUnicodeStringFromAsciiz(&name, ""); 869 870 type = 0xdead; 871 len = 0xbeef; 872 status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len); 873 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 874 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 875 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); 876 877 type = 0xdead; 878 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL); 879 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 880 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 881 882 len = 0xbeef; 883 status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len); 884 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 885 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); 886 887 type = 0xdead; 888 len = 0xbeef; 889 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len); 890 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 891 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 892 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); 893 894 pRtlFreeUnicodeString(&name); 895 896 /* test with nonexistent licence key */ 897 pRtlCreateUnicodeStringFromAsciiz(&name, "Nonexistent-License-Value"); 898 899 type = 0xdead; 900 len = 0xbeef; 901 status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len); 902 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 903 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 904 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); 905 906 type = 0xdead; 907 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL); 908 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 909 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 910 911 len = 0xbeef; 912 status = pNtQueryLicenseValue(&name, NULL, buffer, sizeof(buffer), &len); 913 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue returned %08x, expected STATUS_OBJECT_NAME_NOT_FOUND\n", status); 914 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); 915 916 type = 0xdead; 917 len = 0xbeef; 918 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len); 919 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryLicenseValue unexpected succeeded\n"); 920 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 921 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); 922 923 pRtlFreeUnicodeString(&name); 924 925 /* test with REG_SZ license key */ 926 pRtlCreateUnicodeStringFromAsciiz(&name, "Kernel-MUI-Language-Allowed"); 927 928 type = 0xdead; 929 len = 0xbeef; 930 status = pNtQueryLicenseValue(NULL, &type, buffer, sizeof(buffer), &len); 931 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 932 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 933 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); 934 935 type = 0xdead; 936 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), NULL); 937 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 938 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 939 940 type = 0xdead; 941 len = 0; 942 status = pNtQueryLicenseValue(&name, &type, buffer, 0, &len); 943 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); 944 ok(type == REG_SZ, "expected type = REG_SZ, got %u\n", type); 945 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len); 946 947 len = 0; 948 status = pNtQueryLicenseValue(&name, NULL, buffer, 0, &len); 949 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); 950 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len); 951 952 type = 0xdead; 953 len = 0; 954 memset(buffer, 0x11, sizeof(buffer)); 955 status = pNtQueryLicenseValue(&name, &type, buffer, sizeof(buffer), &len); 956 ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status); 957 ok(type == REG_SZ, "expected type = REG_SZ, got %u\n", type); 958 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len); 959 ok(!memcmp(buffer, emptyW, sizeof(emptyW)), "unexpected buffer content\n"); 960 961 type = 0xdead; 962 len = 0; 963 memset(buffer, 0x11, sizeof(buffer)); 964 status = pNtQueryLicenseValue(&name, &type, buffer, 2, &len); 965 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); 966 ok(type == REG_SZ, "expected type REG_SZ, got %u\n", type); 967 ok(len == sizeof(emptyW), "expected len = %u, got %u\n", (DWORD)sizeof(emptyW), len); 968 ok(buffer[0] == 0x1111, "expected buffer[0] = 0x1111, got %u\n", buffer[0]); 969 970 pRtlFreeUnicodeString(&name); 971 972 /* test with REG_DWORD license key */ 973 pRtlCreateUnicodeStringFromAsciiz(&name, "Kernel-MUI-Number-Allowed"); 974 975 type = 0xdead; 976 len = 0xbeef; 977 status = pNtQueryLicenseValue(NULL, &type, &value, sizeof(value), &len); 978 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 979 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 980 ok(len == 0xbeef, "expected unmodified value for len, got %u\n", len); 981 982 type = 0xdead; 983 status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value), NULL); 984 ok(status == STATUS_INVALID_PARAMETER, "NtQueryLicenseValue returned %08x, expected STATUS_INVALID_PARAMETER\n", status); 985 ok(type == 0xdead, "expected unmodified value for type, got %u\n", type); 986 987 type = 0xdead; 988 len = 0; 989 status = pNtQueryLicenseValue(&name, &type, &value, 0, &len); 990 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); 991 ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type); 992 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len); 993 994 len = 0; 995 status = pNtQueryLicenseValue(&name, NULL, &value, 0, &len); 996 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); 997 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len); 998 999 type = 0xdead; 1000 len = 0; 1001 value = 0xdeadbeef; 1002 status = pNtQueryLicenseValue(&name, &type, &value, sizeof(value), &len); 1003 ok(status == STATUS_SUCCESS, "NtQueryLicenseValue returned %08x, expected STATUS_SUCCESS\n", status); 1004 ok(type == REG_DWORD, "expected type = REG_DWORD, got %u\n", type); 1005 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len); 1006 ok(value != 0xdeadbeef, "expected value != 0xdeadbeef\n"); 1007 1008 type = 0xdead; 1009 len = 0; 1010 status = pNtQueryLicenseValue(&name, &type, &value, 2, &len); 1011 ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryLicenseValue returned %08x, expected STATUS_BUFFER_TOO_SMALL\n", status); 1012 ok(type == REG_DWORD, "expected type REG_DWORD, got %u\n", type); 1013 ok(len == sizeof(value), "expected len = %u, got %u\n", (DWORD)sizeof(value), len); 1014 1015 pRtlFreeUnicodeString(&name); 1016 } 1017 1018 static void test_RtlpNtQueryValueKey(void) 1019 { 1020 NTSTATUS status; 1021 1022 status = pRtlpNtQueryValueKey(NULL, NULL, NULL, NULL, NULL); 1023 ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status); 1024 } 1025 1026 static void test_symlinks(void) 1027 { 1028 static const WCHAR linkW[] = {'l','i','n','k',0}; 1029 static const WCHAR valueW[] = {'v','a','l','u','e',0}; 1030 static const WCHAR symlinkW[] = {'S','y','m','b','o','l','i','c','L','i','n','k','V','a','l','u','e',0}; 1031 static const WCHAR targetW[] = {'\\','t','a','r','g','e','t',0}; 1032 static UNICODE_STRING null_str; 1033 char buffer[1024]; 1034 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; 1035 WCHAR *target; 1036 UNICODE_STRING symlink_str, link_str, target_str, value_str; 1037 HANDLE root, key, link; 1038 OBJECT_ATTRIBUTES attr; 1039 NTSTATUS status; 1040 DWORD target_len, len, dw; 1041 1042 pRtlInitUnicodeString( &link_str, linkW ); 1043 pRtlInitUnicodeString( &symlink_str, symlinkW ); 1044 pRtlInitUnicodeString( &target_str, targetW + 1 ); 1045 pRtlInitUnicodeString( &value_str, valueW ); 1046 1047 target_len = winetestpath.Length + sizeof(targetW); 1048 target = pRtlAllocateHeap( GetProcessHeap(), 0, target_len + sizeof(targetW) /*for loop test*/ ); 1049 memcpy( target, winetestpath.Buffer, winetestpath.Length ); 1050 memcpy( target + winetestpath.Length/sizeof(WCHAR), targetW, sizeof(targetW) ); 1051 1052 attr.Length = sizeof(attr); 1053 attr.RootDirectory = 0; 1054 attr.Attributes = 0; 1055 attr.ObjectName = &winetestpath; 1056 attr.SecurityDescriptor = NULL; 1057 attr.SecurityQualityOfService = NULL; 1058 1059 status = pNtCreateKey( &root, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1060 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1061 1062 attr.RootDirectory = root; 1063 attr.ObjectName = &link_str; 1064 status = pNtCreateKey( &link, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 ); 1065 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1066 1067 /* REG_SZ is not allowed */ 1068 status = pNtSetValueKey( link, &symlink_str, 0, REG_SZ, target, target_len ); 1069 ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status ); 1070 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) ); 1071 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1072 /* other values are not allowed */ 1073 status = pNtSetValueKey( link, &link_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) ); 1074 ok( status == STATUS_ACCESS_DENIED, "NtSetValueKey wrong status 0x%08x\n", status ); 1075 1076 /* try opening the target through the link */ 1077 1078 attr.ObjectName = &link_str; 1079 key = (HANDLE)0xdeadbeef; 1080 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1081 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status ); 1082 ok( !key, "key = %p\n", key ); 1083 1084 attr.ObjectName = &target_str; 1085 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1086 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1087 1088 dw = 0xbeef; 1089 status = pNtSetValueKey( key, &value_str, 0, REG_DWORD, &dw, sizeof(dw) ); 1090 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1091 pNtClose( key ); 1092 1093 attr.ObjectName = &link_str; 1094 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1095 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1096 1097 len = sizeof(buffer); 1098 status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len ); 1099 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1100 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len ); 1101 1102 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1103 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status ); 1104 1105 /* REG_LINK can be created in non-link keys */ 1106 status = pNtSetValueKey( key, &symlink_str, 0, REG_LINK, target, target_len - sizeof(WCHAR) ); 1107 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1108 len = sizeof(buffer); 1109 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1110 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1111 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), 1112 "wrong len %u\n", len ); 1113 status = pNtDeleteValueKey( key, &symlink_str ); 1114 ok( status == STATUS_SUCCESS, "NtDeleteValueKey failed: 0x%08x\n", status ); 1115 1116 pNtClose( key ); 1117 1118 attr.Attributes = 0; 1119 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1120 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1121 1122 len = sizeof(buffer); 1123 status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len ); 1124 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1125 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + sizeof(DWORD), "wrong len %u\n", len ); 1126 1127 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1128 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status ); 1129 pNtClose( key ); 1130 1131 /* now open the symlink itself */ 1132 1133 attr.RootDirectory = root; 1134 attr.Attributes = OBJ_OPENLINK; 1135 attr.ObjectName = &link_str; 1136 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1137 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1138 1139 len = sizeof(buffer); 1140 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1141 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1142 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), 1143 "wrong len %u\n", len ); 1144 pNtClose( key ); 1145 1146 if (pNtOpenKeyEx) 1147 { 1148 /* REG_OPTION_OPEN_LINK flag doesn't matter */ 1149 status = pNtOpenKeyEx( &key, KEY_ALL_ACCESS, &attr, REG_OPTION_OPEN_LINK ); 1150 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1151 1152 len = sizeof(buffer); 1153 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1154 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1155 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), 1156 "wrong len %u\n", len ); 1157 pNtClose( key ); 1158 1159 status = pNtOpenKeyEx( &key, KEY_ALL_ACCESS, &attr, 0 ); 1160 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1161 1162 len = sizeof(buffer); 1163 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1164 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1165 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), 1166 "wrong len %u\n", len ); 1167 pNtClose( key ); 1168 1169 attr.Attributes = 0; 1170 status = pNtOpenKeyEx( &key, KEY_ALL_ACCESS, &attr, REG_OPTION_OPEN_LINK ); 1171 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1172 1173 len = sizeof(buffer); 1174 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1175 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status ); 1176 pNtClose( key ); 1177 } 1178 1179 attr.Attributes = OBJ_OPENLINK; 1180 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1181 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1182 len = sizeof(buffer); 1183 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1184 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1185 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), 1186 "wrong len %u\n", len ); 1187 pNtClose( key ); 1188 1189 /* delete target and create by NtCreateKey on link */ 1190 attr.ObjectName = &target_str; 1191 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1192 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1193 status = pNtDeleteKey( key ); 1194 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status ); 1195 pNtClose( key ); 1196 1197 attr.ObjectName = &link_str; 1198 attr.Attributes = 0; 1199 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1200 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status ); 1201 1202 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1203 todo_wine ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1204 pNtClose( key ); 1205 if (status) /* can be removed once todo_wine above is fixed */ 1206 { 1207 attr.ObjectName = &target_str; 1208 attr.Attributes = OBJ_OPENLINK; 1209 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1210 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1211 pNtClose( key ); 1212 } 1213 1214 attr.ObjectName = &target_str; 1215 attr.Attributes = OBJ_OPENLINK; 1216 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1217 ok( status == STATUS_SUCCESS, "NtOpenKey wrong status 0x%08x\n", status ); 1218 1219 if (0) /* crashes the Windows kernel on some Vista systems */ 1220 { 1221 /* reopen the link from itself */ 1222 1223 attr.RootDirectory = link; 1224 attr.Attributes = OBJ_OPENLINK; 1225 attr.ObjectName = &null_str; 1226 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1227 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1228 len = sizeof(buffer); 1229 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1230 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1231 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), 1232 "wrong len %u\n", len ); 1233 pNtClose( key ); 1234 1235 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1236 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1237 len = sizeof(buffer); 1238 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1239 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1240 ok( len == FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,Data) + target_len - sizeof(WCHAR), 1241 "wrong len %u\n", len ); 1242 pNtClose( key ); 1243 } 1244 1245 if (0) /* crashes the Windows kernel in most versions */ 1246 { 1247 attr.RootDirectory = link; 1248 attr.Attributes = 0; 1249 attr.ObjectName = &null_str; 1250 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1251 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1252 len = sizeof(buffer); 1253 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1254 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status ); 1255 pNtClose( key ); 1256 1257 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1258 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1259 len = sizeof(buffer); 1260 status = pNtQueryValueKey( key, &symlink_str, KeyValuePartialInformation, info, len, &len ); 1261 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey failed: 0x%08x\n", status ); 1262 pNtClose( key ); 1263 } 1264 1265 /* target with terminating null doesn't work */ 1266 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, target, target_len ); 1267 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1268 attr.RootDirectory = root; 1269 attr.Attributes = 0; 1270 attr.ObjectName = &link_str; 1271 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1272 ok( status == STATUS_OBJECT_NAME_NOT_FOUND, "NtOpenKey wrong status 0x%08x\n", status ); 1273 1274 /* relative symlink, works only on win2k */ 1275 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, targetW+1, sizeof(targetW)-2*sizeof(WCHAR) ); 1276 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1277 attr.ObjectName = &link_str; 1278 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1279 ok( status == STATUS_SUCCESS || status == STATUS_OBJECT_NAME_NOT_FOUND, 1280 "NtOpenKey wrong status 0x%08x\n", status ); 1281 1282 key = (HKEY)0xdeadbeef; 1283 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, NULL ); 1284 ok( status == STATUS_OBJECT_NAME_COLLISION, "NtCreateKey failed: 0x%08x\n", status ); 1285 ok( !key, "key = %p\n", key ); 1286 1287 status = pNtDeleteKey( link ); 1288 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status ); 1289 pNtClose( link ); 1290 1291 attr.ObjectName = &target_str; 1292 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1293 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1294 status = pNtDeleteKey( key ); 1295 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status ); 1296 pNtClose( key ); 1297 1298 /* symlink loop */ 1299 1300 status = pNtCreateKey( &link, KEY_ALL_ACCESS, &attr, 0, 0, REG_OPTION_CREATE_LINK, 0 ); 1301 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1302 memcpy( target + target_len/sizeof(WCHAR) - 1, targetW, sizeof(targetW) ); 1303 status = pNtSetValueKey( link, &symlink_str, 0, REG_LINK, 1304 target, target_len + sizeof(targetW) - sizeof(WCHAR) ); 1305 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1306 1307 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1308 ok( status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_NAME_TOO_LONG, 1309 "NtOpenKey failed: 0x%08x\n", status ); 1310 1311 attr.Attributes = OBJ_OPENLINK; 1312 status = pNtOpenKey( &key, KEY_ALL_ACCESS, &attr ); 1313 ok( status == STATUS_SUCCESS, "NtOpenKey failed: 0x%08x\n", status ); 1314 pNtClose( key ); 1315 1316 status = pNtDeleteKey( link ); 1317 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status ); 1318 pNtClose( link ); 1319 1320 status = pNtDeleteKey( root ); 1321 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status ); 1322 pNtClose( root ); 1323 1324 pRtlFreeHeap(GetProcessHeap(), 0, target); 1325 } 1326 1327 static WCHAR valueW[] = {'v','a','l','u','e'}; 1328 static UNICODE_STRING value_str = { sizeof(valueW), sizeof(valueW), valueW }; 1329 static const DWORD ptr_size = 8 * sizeof(void*); 1330 1331 static DWORD get_key_value( HANDLE root, const char *name, DWORD flags ) 1332 { 1333 char tmp[32]; 1334 NTSTATUS status; 1335 OBJECT_ATTRIBUTES attr; 1336 UNICODE_STRING str; 1337 HANDLE key; 1338 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)tmp; 1339 DWORD dw, len = sizeof(tmp); 1340 1341 attr.Length = sizeof(attr); 1342 attr.RootDirectory = root; 1343 attr.Attributes = OBJ_CASE_INSENSITIVE; 1344 attr.ObjectName = &str; 1345 attr.SecurityDescriptor = NULL; 1346 attr.SecurityQualityOfService = NULL; 1347 pRtlCreateUnicodeStringFromAsciiz( &str, name ); 1348 1349 status = pNtCreateKey( &key, flags | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1350 if (status == STATUS_OBJECT_NAME_NOT_FOUND) return 0; 1351 ok( status == STATUS_SUCCESS, "%08x: NtCreateKey failed: 0x%08x\n", flags, status ); 1352 1353 status = pNtQueryValueKey( key, &value_str, KeyValuePartialInformation, info, len, &len ); 1354 if (status == STATUS_OBJECT_NAME_NOT_FOUND) 1355 dw = 0; 1356 else 1357 { 1358 ok( status == STATUS_SUCCESS, "%08x: NtQueryValueKey failed: 0x%08x\n", flags, status ); 1359 dw = *(DWORD *)info->Data; 1360 } 1361 pNtClose( key ); 1362 pRtlFreeUnicodeString( &str ); 1363 return dw; 1364 } 1365 1366 static void _check_key_value( int line, HANDLE root, const char *name, DWORD flags, DWORD expect ) 1367 { 1368 DWORD dw = get_key_value( root, name, flags ); 1369 ok_(__FILE__,line)( dw == expect, "%08x: wrong value %u/%u\n", flags, dw, expect ); 1370 } 1371 #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect ) 1372 1373 static void test_redirection(void) 1374 { 1375 static const WCHAR softwareW[] = {'\\','R','e','g','i','s','t','r','y','\\', 1376 'M','a','c','h','i','n','e','\\', 1377 'S','o','f','t','w','a','r','e',0}; 1378 static const WCHAR wownodeW[] = {'\\','R','e','g','i','s','t','r','y','\\', 1379 'M','a','c','h','i','n','e','\\', 1380 'S','o','f','t','w','a','r','e','\\', 1381 'W','o','w','6','4','3','2','N','o','d','e',0}; 1382 static const WCHAR wine64W[] = {'\\','R','e','g','i','s','t','r','y','\\', 1383 'M','a','c','h','i','n','e','\\', 1384 'S','o','f','t','w','a','r','e','\\', 1385 'W','i','n','e',0}; 1386 static const WCHAR wine32W[] = {'\\','R','e','g','i','s','t','r','y','\\', 1387 'M','a','c','h','i','n','e','\\', 1388 'S','o','f','t','w','a','r','e','\\', 1389 'W','o','w','6','4','3','2','N','o','d','e','\\', 1390 'W','i','n','e',0}; 1391 static const WCHAR key64W[] = {'\\','R','e','g','i','s','t','r','y','\\', 1392 'M','a','c','h','i','n','e','\\', 1393 'S','o','f','t','w','a','r','e','\\', 1394 'W','i','n','e','\\','W','i','n','e','t','e','s','t',0}; 1395 static const WCHAR key32W[] = {'\\','R','e','g','i','s','t','r','y','\\', 1396 'M','a','c','h','i','n','e','\\', 1397 'S','o','f','t','w','a','r','e','\\', 1398 'W','o','w','6','4','3','2','N','o','d','e','\\', 1399 'W','i','n','e','\\', 'W','i','n','e','t','e','s','t',0}; 1400 static const WCHAR classes64W[] = {'\\','R','e','g','i','s','t','r','y','\\', 1401 'M','a','c','h','i','n','e','\\', 1402 'S','o','f','t','w','a','r','e','\\', 1403 'C','l','a','s','s','e','s','\\', 1404 'W','i','n','e',0}; 1405 static const WCHAR classes32W[] = {'\\','R','e','g','i','s','t','r','y','\\', 1406 'M','a','c','h','i','n','e','\\', 1407 'S','o','f','t','w','a','r','e','\\', 1408 'C','l','a','s','s','e','s','\\', 1409 'W','o','w','6','4','3','2','N','o','d','e','\\', 1410 'W','i','n','e',0}; 1411 NTSTATUS status; 1412 OBJECT_ATTRIBUTES attr; 1413 UNICODE_STRING str; 1414 char buffer[1024]; 1415 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; 1416 DWORD dw, len; 1417 HANDLE key, root32, root64, key32, key64; 1418 BOOL is_vista = FALSE; 1419 1420 if (ptr_size != 64) 1421 { 1422 ULONG is_wow64, len; 1423 if (pNtQueryInformationProcess( GetCurrentProcess(), ProcessWow64Information, 1424 &is_wow64, sizeof(is_wow64), &len ) || 1425 !is_wow64) 1426 { 1427 trace( "Not on Wow64, no redirection\n" ); 1428 return; 1429 } 1430 } 1431 1432 attr.Length = sizeof(attr); 1433 attr.RootDirectory = 0; 1434 attr.Attributes = OBJ_CASE_INSENSITIVE; 1435 attr.ObjectName = &str; 1436 attr.SecurityDescriptor = NULL; 1437 attr.SecurityQualityOfService = NULL; 1438 1439 pRtlInitUnicodeString( &str, wine64W ); 1440 status = pNtCreateKey( &root64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1441 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1442 1443 pRtlInitUnicodeString( &str, wine32W ); 1444 status = pNtCreateKey( &root32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1445 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1446 1447 pRtlInitUnicodeString( &str, key64W ); 1448 status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1449 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1450 1451 pRtlInitUnicodeString( &str, key32W ); 1452 status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1453 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1454 1455 dw = 64; 1456 status = pNtSetValueKey( key64, &value_str, 0, REG_DWORD, &dw, sizeof(dw) ); 1457 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1458 1459 dw = 32; 1460 status = pNtSetValueKey( key32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) ); 1461 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1462 1463 len = sizeof(buffer); 1464 status = pNtQueryValueKey( key32, &value_str, KeyValuePartialInformation, info, len, &len ); 1465 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1466 dw = *(DWORD *)info->Data; 1467 ok( dw == 32, "wrong value %u\n", dw ); 1468 1469 len = sizeof(buffer); 1470 status = pNtQueryValueKey( key64, &value_str, KeyValuePartialInformation, info, len, &len ); 1471 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1472 dw = *(DWORD *)info->Data; 1473 ok( dw == 64, "wrong value %u\n", dw ); 1474 1475 pRtlInitUnicodeString( &str, softwareW ); 1476 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1477 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1478 1479 if (ptr_size == 32) 1480 { 1481 /* the Vista mechanism allows opening Wow6432Node from a 32-bit key too */ 1482 /* the new (and simpler) Win7 mechanism doesn't */ 1483 if (get_key_value( key, "Wow6432Node\\Wine\\Winetest", 0 ) == 32) 1484 { 1485 trace( "using Vista-style Wow6432Node handling\n" ); 1486 is_vista = TRUE; 1487 } 1488 check_key_value( key, "Wine\\Winetest", 0, 32 ); 1489 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 1490 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1491 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 ); 1492 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 ); 1493 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 ); 1494 } 1495 else 1496 { 1497 check_key_value( key, "Wine\\Winetest", 0, 64 ); 1498 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 ); 1499 } 1500 pNtClose( key ); 1501 1502 if (ptr_size == 32) 1503 { 1504 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1505 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1506 dw = get_key_value( key, "Wine\\Winetest", 0 ); 1507 ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw ); 1508 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 64 ); 1509 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1510 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 ); 1511 dw = get_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY ); 1512 ok( dw == 32 || broken(dw == 64) /* xp64 */, "wrong value %u\n", dw ); 1513 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1514 pNtClose( key ); 1515 1516 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1517 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1518 check_key_value( key, "Wine\\Winetest", 0, 32 ); 1519 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 1520 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1521 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 ); 1522 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 ); 1523 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 ); 1524 pNtClose( key ); 1525 } 1526 1527 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", 0, ptr_size ); 1528 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", 0, 32 ); 1529 if (ptr_size == 64) 1530 { 1531 /* KEY_WOW64 flags have no effect on 64-bit */ 1532 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 ); 1533 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY, 64 ); 1534 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, 32 ); 1535 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1536 } 1537 else 1538 { 1539 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 ); 1540 check_key_value( 0, "\\Registry\\Machine\\Software\\Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1541 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 1542 check_key_value( 0, "\\Registry\\Machine\\Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1543 } 1544 1545 pRtlInitUnicodeString( &str, wownodeW ); 1546 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1547 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1548 check_key_value( key, "Wine\\Winetest", 0, 32 ); 1549 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, (ptr_size == 64) ? 32 : (is_vista ? 64 : 32) ); 1550 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1551 pNtClose( key ); 1552 1553 if (ptr_size == 32) 1554 { 1555 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1556 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1557 dw = get_key_value( key, "Wine\\Winetest", 0 ); 1558 ok( dw == (is_vista ? 64 : 32) || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw ); 1559 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 1560 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1561 pNtClose( key ); 1562 1563 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1564 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1565 check_key_value( key, "Wine\\Winetest", 0, 32 ); 1566 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 1567 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 1568 pNtClose( key ); 1569 } 1570 1571 pRtlInitUnicodeString( &str, wine32W ); 1572 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1573 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1574 check_key_value( key, "Winetest", 0, 32 ); 1575 check_key_value( key, "Winetest", KEY_WOW64_64KEY, (ptr_size == 32 && is_vista) ? 64 : 32 ); 1576 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); 1577 pNtClose( key ); 1578 1579 if (ptr_size == 32) 1580 { 1581 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1582 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1583 dw = get_key_value( key, "Winetest", 0 ); 1584 ok( dw == 32 || (is_vista && dw == 64), "wrong value %u\n", dw ); 1585 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 1586 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); 1587 pNtClose( key ); 1588 1589 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1590 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1591 check_key_value( key, "Winetest", 0, 32 ); 1592 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 1593 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); 1594 pNtClose( key ); 1595 } 1596 1597 pRtlInitUnicodeString( &str, wine64W ); 1598 status = pNtCreateKey( &key, KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1599 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1600 check_key_value( key, "Winetest", 0, ptr_size ); 1601 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : ptr_size ); 1602 check_key_value( key, "Winetest", KEY_WOW64_32KEY, ptr_size ); 1603 pNtClose( key ); 1604 1605 if (ptr_size == 32) 1606 { 1607 status = pNtCreateKey( &key, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1608 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1609 dw = get_key_value( key, "Winetest", 0 ); 1610 ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw ); 1611 check_key_value( key, "Winetest", KEY_WOW64_64KEY, 64 ); 1612 dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY ); 1613 todo_wine ok( dw == 32, "wrong value %u\n", dw ); 1614 pNtClose( key ); 1615 1616 status = pNtCreateKey( &key, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1617 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1618 check_key_value( key, "Winetest", 0, 32 ); 1619 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 1620 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); 1621 pNtClose( key ); 1622 } 1623 1624 status = pNtDeleteKey( key32 ); 1625 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status ); 1626 pNtClose( key32 ); 1627 1628 status = pNtDeleteKey( key64 ); 1629 ok( status == STATUS_SUCCESS, "NtDeleteKey failed: 0x%08x\n", status ); 1630 pNtClose( key64 ); 1631 1632 pNtDeleteKey( root32 ); 1633 pNtClose( root32 ); 1634 pNtDeleteKey( root64 ); 1635 pNtClose( root64 ); 1636 1637 /* Software\Classes is shared/reflected so behavior is different */ 1638 1639 pRtlInitUnicodeString( &str, classes64W ); 1640 status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1641 if (status == STATUS_ACCESS_DENIED) 1642 { 1643 skip("Not authorized to modify the Classes key\n"); 1644 return; 1645 } 1646 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1647 1648 pRtlInitUnicodeString( &str, classes32W ); 1649 status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1650 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1651 1652 dw = 64; 1653 status = pNtSetValueKey( key64, &value_str, 0, REG_DWORD, &dw, sizeof(dw) ); 1654 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1655 pNtClose( key64 ); 1656 1657 dw = 32; 1658 status = pNtSetValueKey( key32, &value_str, 0, REG_DWORD, &dw, sizeof(dw) ); 1659 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1660 pNtClose( key32 ); 1661 1662 pRtlInitUnicodeString( &str, classes64W ); 1663 status = pNtCreateKey( &key64, KEY_WOW64_64KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1664 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1665 len = sizeof(buffer); 1666 status = pNtQueryValueKey( key64, &value_str, KeyValuePartialInformation, info, len, &len ); 1667 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1668 dw = *(DWORD *)info->Data; 1669 ok( dw == ptr_size, "wrong value %u\n", dw ); 1670 1671 pRtlInitUnicodeString( &str, classes32W ); 1672 status = pNtCreateKey( &key32, KEY_WOW64_32KEY | KEY_ALL_ACCESS, &attr, 0, 0, 0, 0 ); 1673 ok( status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status ); 1674 len = sizeof(buffer); 1675 status = pNtQueryValueKey( key32, &value_str, KeyValuePartialInformation, info, len, &len ); 1676 ok( status == STATUS_SUCCESS, "NtQueryValueKey failed: 0x%08x\n", status ); 1677 dw = *(DWORD *)info->Data; 1678 ok( dw == 32, "wrong value %u\n", dw ); 1679 1680 pNtDeleteKey( key32 ); 1681 pNtClose( key32 ); 1682 pNtDeleteKey( key64 ); 1683 pNtClose( key64 ); 1684 } 1685 1686 static void test_long_value_name(void) 1687 { 1688 HANDLE key; 1689 NTSTATUS status, expected; 1690 OBJECT_ATTRIBUTES attr; 1691 UNICODE_STRING ValName; 1692 DWORD i; 1693 1694 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 1695 status = pNtOpenKey(&key, KEY_WRITE|KEY_READ, &attr); 1696 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status); 1697 1698 ValName.MaximumLength = 0xfffc; 1699 ValName.Length = ValName.MaximumLength - sizeof(WCHAR); 1700 ValName.Buffer = HeapAlloc(GetProcessHeap(), 0, ValName.MaximumLength); 1701 for (i = 0; i < ValName.Length / sizeof(WCHAR); i++) 1702 ValName.Buffer[i] = 'a'; 1703 ValName.Buffer[i] = 0; 1704 1705 status = pNtDeleteValueKey(key, &ValName); 1706 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtDeleteValueKey with nonexistent long value name returned 0x%08x\n", status); 1707 status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &i, sizeof(i)); 1708 ok(status == STATUS_INVALID_PARAMETER || broken(status == STATUS_SUCCESS) /* nt4 */, 1709 "NtSetValueKey with long value name returned 0x%08x\n", status); 1710 expected = (status == STATUS_SUCCESS) ? STATUS_SUCCESS : STATUS_OBJECT_NAME_NOT_FOUND; 1711 status = pNtDeleteValueKey(key, &ValName); 1712 ok(status == expected, "NtDeleteValueKey with long value name returned 0x%08x\n", status); 1713 1714 status = pNtQueryValueKey(key, &ValName, KeyValueBasicInformation, NULL, 0, &i); 1715 ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "NtQueryValueKey with nonexistent long value name returned 0x%08x\n", status); 1716 1717 pRtlFreeUnicodeString(&ValName); 1718 pNtClose(key); 1719 } 1720 1721 static void test_NtQueryKey(void) 1722 { 1723 HANDLE key, subkey, subkey2; 1724 NTSTATUS status; 1725 OBJECT_ATTRIBUTES attr; 1726 ULONG length, len; 1727 KEY_NAME_INFORMATION *info = NULL; 1728 KEY_CACHED_INFORMATION cached_info; 1729 UNICODE_STRING str; 1730 DWORD dw; 1731 1732 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 1733 status = pNtOpenKey(&key, KEY_READ, &attr); 1734 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status); 1735 1736 status = pNtQueryKey(key, KeyNameInformation, NULL, 0, &length); 1737 if (status == STATUS_INVALID_PARAMETER) { 1738 win_skip("KeyNameInformation is not supported\n"); 1739 pNtClose(key); 1740 return; 1741 } 1742 todo_wine ok(status == STATUS_BUFFER_TOO_SMALL, "NtQueryKey Failed: 0x%08x\n", status); 1743 info = HeapAlloc(GetProcessHeap(), 0, length); 1744 1745 /* non-zero buffer size, but insufficient */ 1746 status = pNtQueryKey(key, KeyNameInformation, info, sizeof(*info), &len); 1747 ok(status == STATUS_BUFFER_OVERFLOW, "NtQueryKey Failed: 0x%08x\n", status); 1748 ok(length == len, "got %d, expected %d\n", len, length); 1749 ok(info->NameLength == winetestpath.Length, "got %d, expected %d\n", 1750 info->NameLength, winetestpath.Length); 1751 1752 /* correct buffer size */ 1753 status = pNtQueryKey(key, KeyNameInformation, info, length, &len); 1754 ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status); 1755 ok(length == len, "got %d, expected %d\n", len, length); 1756 1757 str.Buffer = info->Name; 1758 str.Length = info->NameLength; 1759 ok(pRtlCompareUnicodeString(&winetestpath, &str, TRUE) == 0, 1760 "got %s, expected %s\n", 1761 wine_dbgstr_wn(str.Buffer, str.Length/sizeof(WCHAR)), 1762 wine_dbgstr_wn(winetestpath.Buffer, winetestpath.Length/sizeof(WCHAR))); 1763 1764 HeapFree(GetProcessHeap(), 0, info); 1765 1766 attr.RootDirectory = key; 1767 attr.ObjectName = &str; 1768 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey"); 1769 status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0); 1770 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status); 1771 pRtlFreeUnicodeString(&str); 1772 1773 status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len); 1774 ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status); 1775 1776 if (status == STATUS_SUCCESS) 1777 { 1778 ok(len == sizeof(cached_info), "got unexpected length %d\n", len); 1779 ok(cached_info.SubKeys == 0, "cached_info.SubKeys = %u\n", cached_info.SubKeys); 1780 ok(cached_info.MaxNameLen == 0, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen); 1781 ok(cached_info.Values == 0, "cached_info.Values = %u\n", cached_info.Values); 1782 ok(cached_info.MaxValueNameLen == 0, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen); 1783 ok(cached_info.MaxValueDataLen == 0, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen); 1784 ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength); 1785 } 1786 1787 attr.RootDirectory = subkey; 1788 attr.ObjectName = &str; 1789 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey2"); 1790 status = pNtCreateKey(&subkey2, GENERIC_ALL, &attr, 0, 0, 0, 0); 1791 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status); 1792 pRtlFreeUnicodeString(&str); 1793 1794 pRtlCreateUnicodeStringFromAsciiz(&str, "val"); 1795 dw = 64; 1796 status = pNtSetValueKey( subkey, &str, 0, REG_DWORD, &dw, sizeof(dw) ); 1797 ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status ); 1798 pRtlFreeUnicodeString(&str); 1799 1800 if (!winetest_interactive) 1801 skip("ROSTESTS-198: Causes an assert in Cm.\n"); 1802 else 1803 { 1804 status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len); 1805 ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status); 1806 1807 if (status == STATUS_SUCCESS) 1808 { 1809 ok(len == sizeof(cached_info), "got unexpected length %d\n", len); 1810 ok(cached_info.SubKeys == 1, "cached_info.SubKeys = %u\n", cached_info.SubKeys); 1811 ok(cached_info.MaxNameLen == 24, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen); 1812 ok(cached_info.Values == 1, "cached_info.Values = %u\n", cached_info.Values); 1813 ok(cached_info.MaxValueNameLen == 6, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen); 1814 ok(cached_info.MaxValueDataLen == 4, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen); 1815 ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength); 1816 } 1817 } 1818 1819 status = pNtDeleteKey(subkey2); 1820 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status); 1821 status = pNtDeleteKey(subkey); 1822 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status); 1823 1824 pNtClose(subkey2); 1825 pNtClose(subkey); 1826 pNtClose(key); 1827 } 1828 1829 static void test_notify(void) 1830 { 1831 OBJECT_ATTRIBUTES attr; 1832 LARGE_INTEGER timeout; 1833 IO_STATUS_BLOCK iosb; 1834 UNICODE_STRING str; 1835 HANDLE key, events[2], subkey; 1836 NTSTATUS status; 1837 1838 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 1839 status = pNtOpenKey(&key, KEY_ALL_ACCESS, &attr); 1840 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status); 1841 1842 events[0] = CreateEventW(NULL, FALSE, TRUE, NULL); 1843 ok(events[0] != NULL, "CreateEvent failed: %u\n", GetLastError()); 1844 events[1] = CreateEventW(NULL, FALSE, TRUE, NULL); 1845 ok(events[1] != NULL, "CreateEvent failed: %u\n", GetLastError()); 1846 1847 status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE); 1848 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status); 1849 status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE); 1850 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status); 1851 1852 timeout.QuadPart = 0; 1853 status = pNtWaitForSingleObject(events[0], FALSE, &timeout); 1854 ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status); 1855 status = pNtWaitForSingleObject(events[1], FALSE, &timeout); 1856 ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status); 1857 1858 attr.RootDirectory = key; 1859 attr.ObjectName = &str; 1860 1861 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey"); 1862 status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0); 1863 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status); 1864 pRtlFreeUnicodeString(&str); 1865 1866 status = pNtWaitForSingleObject(events[0], FALSE, &timeout); 1867 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status); 1868 status = pNtWaitForSingleObject(events[1], FALSE, &timeout); 1869 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status); 1870 1871 status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE); 1872 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status); 1873 status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE); 1874 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status); 1875 1876 status = pNtDeleteKey(subkey); 1877 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status); 1878 1879 status = pNtWaitForSingleObject(events[0], FALSE, &timeout); 1880 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status); 1881 status = pNtWaitForSingleObject(events[1], FALSE, &timeout); 1882 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status); 1883 1884 pNtClose(subkey); 1885 1886 status = pNtNotifyChangeKey(key, events[0], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE); 1887 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status); 1888 status = pNtNotifyChangeKey(key, events[1], NULL, NULL, &iosb, 0, FALSE, NULL, 0, TRUE); 1889 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status); 1890 1891 pNtClose(key); 1892 1893 status = pNtWaitForSingleObject(events[0], FALSE, &timeout); 1894 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status); 1895 status = pNtWaitForSingleObject(events[1], FALSE, &timeout); 1896 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status); 1897 1898 if (pNtNotifyChangeMultipleKeys) 1899 { 1900 InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); 1901 status = pNtOpenKey(&key, KEY_ALL_ACCESS, &attr); 1902 ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status); 1903 1904 status = pNtNotifyChangeMultipleKeys(key, 0, NULL, events[0], NULL, NULL, &iosb, REG_NOTIFY_CHANGE_NAME, FALSE, NULL, 0, TRUE); 1905 ok(status == STATUS_PENDING, "NtNotifyChangeKey returned %x\n", status); 1906 1907 timeout.QuadPart = 0; 1908 status = pNtWaitForSingleObject(events[0], FALSE, &timeout); 1909 ok(status == STATUS_TIMEOUT, "NtWaitForSingleObject returned %x\n", status); 1910 1911 attr.RootDirectory = key; 1912 attr.ObjectName = &str; 1913 pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey"); 1914 status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0); 1915 ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status); 1916 pRtlFreeUnicodeString(&str); 1917 1918 status = pNtWaitForSingleObject(events[0], FALSE, &timeout); 1919 ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status); 1920 1921 status = pNtDeleteKey(subkey); 1922 ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status); 1923 pNtClose(subkey); 1924 pNtClose(key); 1925 } 1926 else 1927 { 1928 win_skip("NtNotifyChangeMultipleKeys not available\n"); 1929 } 1930 1931 pNtClose(events[0]); 1932 pNtClose(events[1]); 1933 } 1934 1935 START_TEST(reg) 1936 { 1937 static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t',0}; 1938 if(!InitFunctionPtrs()) 1939 return; 1940 pRtlFormatCurrentUserKeyPath(&winetestpath); 1941 winetestpath.Buffer = pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer, 1942 winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR)); 1943 winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR); 1944 1945 pRtlAppendUnicodeToString(&winetestpath, winetest); 1946 1947 test_NtCreateKey(); 1948 test_NtOpenKey(); 1949 test_NtSetValueKey(); 1950 test_RtlCheckRegistryKey(); 1951 test_RtlOpenCurrentUser(); 1952 test_RtlQueryRegistryValues(); 1953 test_RtlpNtQueryValueKey(); 1954 test_NtFlushKey(); 1955 test_NtQueryKey(); 1956 test_NtQueryLicenseKey(); 1957 test_NtQueryValueKey(); 1958 test_long_value_name(); 1959 test_notify(); 1960 test_NtDeleteKey(); 1961 test_symlinks(); 1962 test_redirection(); 1963 1964 pRtlFreeUnicodeString(&winetestpath); 1965 1966 FreeLibrary(hntdll); 1967 } 1968