1 /* 2 * Unit tests for advpack.dll 3 * 4 * Copyright (C) 2005 Robert Reif 5 * Copyright (C) 2005 Sami Aario 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define WIN32_NO_STATUS 23 #define _INC_WINDOWS 24 #define COM_NO_WINDOWS_H 25 26 #include <stdio.h> 27 #include <windef.h> 28 #include <winbase.h> 29 #include <winreg.h> 30 #include <objbase.h> 31 #include <advpub.h> 32 #include <assert.h> 33 #include <wine/test.h> 34 35 /* defines for the TranslateInfString/Ex tests */ 36 #define TEST_STRING1 "\\Application Name" 37 #define TEST_STRING2 "%49001%\\Application Name" 38 39 /* defines for the SetPerUserSecValues tests */ 40 #define GUID_KEY "SOFTWARE\\Microsoft\\Active Setup\\Installed Components\\guid" 41 #define REG_VAL_EXISTS(key, value) !RegQueryValueExA(key, value, NULL, NULL, NULL, NULL) 42 #define OPEN_GUID_KEY() !RegOpenKeyA(HKEY_LOCAL_MACHINE, GUID_KEY, &guid) 43 44 static HMODULE hAdvPack; 45 static HRESULT (WINAPI *pCloseINFEngine)(HINF); 46 static HRESULT (WINAPI *pDelNode)(LPCSTR,DWORD); 47 static HRESULT (WINAPI *pGetVersionFromFile)(LPCSTR,LPDWORD,LPDWORD,BOOL); 48 static HRESULT (WINAPI *pOpenINFEngine)(PCSTR,PCSTR,DWORD,HINF*,PVOID); 49 static HRESULT (WINAPI *pSetPerUserSecValues)(PPERUSERSECTIONA pPerUser); 50 static HRESULT (WINAPI *pTranslateInfString)(LPCSTR,LPCSTR,LPCSTR,LPCSTR,LPSTR,DWORD,LPDWORD,LPVOID); 51 static HRESULT (WINAPI *pTranslateInfStringEx)(HINF,PCSTR,PCSTR,PCSTR,PSTR,DWORD,PDWORD,PVOID); 52 53 static CHAR inf_file[MAX_PATH]; 54 static CHAR PROG_FILES_ROOT[MAX_PATH]; 55 static CHAR PROG_FILES[MAX_PATH]; 56 static CHAR APP_PATH[MAX_PATH]; 57 static DWORD APP_PATH_LEN; 58 59 static void get_progfiles_dir(void) 60 { 61 HKEY hkey; 62 DWORD size = MAX_PATH; 63 64 RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey); 65 RegQueryValueExA(hkey, "ProgramFilesDir", NULL, NULL, (LPBYTE)PROG_FILES_ROOT, &size); 66 RegCloseKey(hkey); 67 68 lstrcpyA(PROG_FILES, PROG_FILES_ROOT + 3); /* skip C:\ */ 69 lstrcpyA(APP_PATH, PROG_FILES_ROOT); 70 lstrcatA(APP_PATH, TEST_STRING1); 71 APP_PATH_LEN = lstrlenA(APP_PATH) + 1; 72 } 73 74 static BOOL init_function_pointers(void) 75 { 76 hAdvPack = LoadLibraryA("advpack.dll"); 77 78 if (!hAdvPack) 79 return FALSE; 80 81 pCloseINFEngine = (void*)GetProcAddress(hAdvPack, "CloseINFEngine"); 82 pDelNode = (void *)GetProcAddress(hAdvPack, "DelNode"); 83 pGetVersionFromFile = (void *)GetProcAddress(hAdvPack, "GetVersionFromFile"); 84 pOpenINFEngine = (void*)GetProcAddress(hAdvPack, "OpenINFEngine"); 85 pSetPerUserSecValues = (void*)GetProcAddress(hAdvPack, "SetPerUserSecValues"); 86 pTranslateInfString = (void *)GetProcAddress(hAdvPack, "TranslateInfString"); 87 pTranslateInfStringEx = (void*)GetProcAddress(hAdvPack, "TranslateInfStringEx"); 88 89 if (!pCloseINFEngine || !pDelNode || !pGetVersionFromFile || 90 !pOpenINFEngine || !pSetPerUserSecValues || !pTranslateInfString) 91 { 92 win_skip("Needed functions are not available\n"); 93 FreeLibrary(hAdvPack); 94 return FALSE; 95 } 96 97 return TRUE; 98 } 99 100 static void version_test(void) 101 { 102 HRESULT hr; 103 DWORD major, minor; 104 105 major = minor = 0; 106 hr = pGetVersionFromFile("kernel32.dll", &major, &minor, FALSE); 107 ok (hr == S_OK, "GetVersionFromFileEx(kernel32.dll) failed, returned " 108 "0x%08x\n", hr); 109 trace("kernel32.dll Language ID: 0x%08x, Codepage ID: 0x%08x\n", 110 major, minor); 111 112 major = minor = 0; 113 hr = pGetVersionFromFile("kernel32.dll", &major, &minor, TRUE); 114 ok (hr == S_OK, "GetVersionFromFileEx(kernel32.dll) failed, returned " 115 "0x%08x\n", hr); 116 trace("kernel32.dll version: %d.%d.%d.%d\n", HIWORD(major), LOWORD(major), 117 HIWORD(minor), LOWORD(minor)); 118 119 major = minor = 0; 120 hr = pGetVersionFromFile("advpack.dll", &major, &minor, FALSE); 121 ok (hr == S_OK, "GetVersionFromFileEx(advpack.dll) failed, returned " 122 "0x%08x\n", hr); 123 trace("advpack.dll Language ID: 0x%08x, Codepage ID: 0x%08x\n", 124 major, minor); 125 126 major = minor = 0; 127 hr = pGetVersionFromFile("advpack.dll", &major, &minor, TRUE); 128 ok (hr == S_OK, "GetVersionFromFileEx(advpack.dll) failed, returned " 129 "0x%08x\n", hr); 130 trace("advpack.dll version: %d.%d.%d.%d\n", HIWORD(major), LOWORD(major), 131 HIWORD(minor), LOWORD(minor)); 132 } 133 134 static void delnode_test(void) 135 { 136 HRESULT hr; 137 HANDLE hn; 138 CHAR currDir[MAX_PATH]; 139 UINT currDirLen; 140 141 /* Native DelNode apparently does not support relative paths, so we use 142 absolute paths for testing */ 143 currDirLen = GetCurrentDirectoryA(sizeof(currDir) / sizeof(CHAR), currDir); 144 assert(currDirLen > 0 && currDirLen < sizeof(currDir) / sizeof(CHAR)); 145 146 if(currDir[currDirLen - 1] == '\\') 147 currDir[--currDirLen] = 0; 148 149 /* Simple tests; these should fail. */ 150 hr = pDelNode(NULL, 0); 151 ok (hr == E_FAIL, "DelNode called with NULL pathname should return E_FAIL\n"); 152 hr = pDelNode("", 0); 153 ok (hr == E_FAIL, "DelNode called with empty pathname should return E_FAIL\n"); 154 155 /* Test deletion of a file. */ 156 hn = CreateFileA("DelNodeTestFile1", GENERIC_WRITE, 0, NULL, 157 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 158 assert(hn != INVALID_HANDLE_VALUE); 159 CloseHandle(hn); 160 hr = pDelNode(lstrcatA(currDir, "\\DelNodeTestFile1"), 0); 161 ok (hr == S_OK, "DelNode failed deleting a single file\n"); 162 currDir[currDirLen] = '\0'; 163 164 /* Test deletion of an empty directory. */ 165 CreateDirectoryA("DelNodeTestDir", NULL); 166 hr = pDelNode(lstrcatA(currDir, "\\DelNodeTestDir"), 0); 167 ok (hr == S_OK, "DelNode failed deleting an empty directory\n"); 168 currDir[currDirLen] = '\0'; 169 170 /* Test deletion of a directory containing one file. */ 171 CreateDirectoryA("DelNodeTestDir", NULL); 172 hn = CreateFileA("DelNodeTestDir\\DelNodeTestFile1", GENERIC_WRITE, 0, NULL, 173 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 174 assert(hn != INVALID_HANDLE_VALUE); 175 CloseHandle(hn); 176 hr = pDelNode(lstrcatA(currDir, "\\DelNodeTestDir"), 0); 177 ok (hr == S_OK, "DelNode failed deleting a directory containing one file\n"); 178 currDir[currDirLen] = '\0'; 179 180 /* Test deletion of a directory containing multiple files. */ 181 CreateDirectoryA("DelNodeTestDir", NULL); 182 hn = CreateFileA("DelNodeTestDir\\DelNodeTestFile1", GENERIC_WRITE, 0, NULL, 183 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 184 assert(hn != INVALID_HANDLE_VALUE); 185 CloseHandle(hn); 186 hn = CreateFileA("DelNodeTestDir\\DelNodeTestFile2", GENERIC_WRITE, 0, NULL, 187 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 188 assert(hn != INVALID_HANDLE_VALUE); 189 CloseHandle(hn); 190 hn = CreateFileA("DelNodeTestDir\\DelNodeTestFile3", GENERIC_WRITE, 0, NULL, 191 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 192 assert(hn != INVALID_HANDLE_VALUE); 193 CloseHandle(hn); 194 hr = pDelNode(lstrcatA(currDir, "\\DelNodeTestDir"), 0); 195 ok (hr == S_OK, "DelNode failed deleting a directory containing multiple files\n"); 196 } 197 198 static void append_str(char **str, const char *data, ...) 199 { 200 va_list valist; 201 202 va_start(valist, data); 203 vsprintf(*str, data, valist); 204 *str += strlen(*str); 205 va_end(valist); 206 } 207 208 static void create_inf_file(void) 209 { 210 char data[1024]; 211 char *ptr = data; 212 DWORD dwNumberOfBytesWritten; 213 HANDLE hf = CreateFileA(inf_file, GENERIC_WRITE, 0, NULL, 214 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 215 216 append_str(&ptr, "[Version]\n"); 217 append_str(&ptr, "Signature=\"$Chicago$\"\n"); 218 append_str(&ptr, "[CustInstDestSection]\n"); 219 append_str(&ptr, "49001=ProgramFilesDir\n"); 220 append_str(&ptr, "49010=DestA,1\n"); 221 append_str(&ptr, "49020=DestB\n"); 222 append_str(&ptr, "49030=DestC\n"); 223 append_str(&ptr, "[ProgramFilesDir]\n"); 224 append_str(&ptr, "HKLM,\"Software\\Microsoft\\Windows\\CurrentVersion\","); 225 append_str(&ptr, "\"ProgramFilesDir\",,\"%%24%%\\%%LProgramF%%\"\n"); 226 append_str(&ptr, "[section]\n"); 227 append_str(&ptr, "NotACustomDestination=Version\n"); 228 append_str(&ptr, "CustomDestination=CustInstDestSection\n"); 229 append_str(&ptr, "[Options.NTx86]\n"); 230 append_str(&ptr, "49001=ProgramFilesDir\n"); 231 append_str(&ptr, "InstallDir=%%49001%%\\%%DefaultAppPath%%\n"); 232 append_str(&ptr, "Result1=%%49010%%\n"); 233 append_str(&ptr, "Result2=%%49020%%\n"); 234 append_str(&ptr, "Result3=%%49030%%\n"); 235 append_str(&ptr, "CustomHDestination=CustInstDestSection\n"); 236 append_str(&ptr, "[Strings]\n"); 237 append_str(&ptr, "DefaultAppPath=\"Application Name\"\n"); 238 append_str(&ptr, "LProgramF=\"%s\"\n", PROG_FILES); 239 append_str(&ptr, "[DestA]\n"); 240 append_str(&ptr, "HKLM,\"Software\\Garbage\",\"ProgramFilesDir\",,'%%24%%\\%%LProgramF%%'\n"); 241 append_str(&ptr, "[DestB]\n"); 242 append_str(&ptr, "'HKLM','Software\\Microsoft\\Windows\\CurrentVersion',"); 243 append_str(&ptr, "'ProgramFilesDir',,\"%%24%%\"\n"); 244 append_str(&ptr, "[DestC]\n"); 245 append_str(&ptr, "HKLM,\"Software\\Garbage\",\"ProgramFilesDir\",,'%%24%%'\n"); 246 247 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL); 248 CloseHandle(hf); 249 } 250 251 static void translateinfstring_test(void) 252 { 253 HRESULT hr; 254 char buffer[MAX_PATH]; 255 DWORD dwSize; 256 257 create_inf_file(); 258 259 /* pass in a couple invalid parameters */ 260 hr = pTranslateInfString(NULL, NULL, NULL, NULL, buffer, MAX_PATH, &dwSize, NULL); 261 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got 0x%08x\n", (UINT)hr); 262 263 /* try to open an inf file that doesn't exist */ 264 hr = pTranslateInfString("c:\\a.inf", "Options.NTx86", "Options.NTx86", 265 "InstallDir", buffer, MAX_PATH, &dwSize, NULL); 266 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || hr == E_INVALIDARG || 267 hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND), 268 "Expected E_INVALIDARG, 0x80070002 or 0x8007007e, got 0x%08x\n", (UINT)hr); 269 270 if(hr == HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND)) 271 { 272 win_skip("WinNT 3.51 detected. Skipping tests for TranslateInfString()\n"); 273 return; 274 } 275 276 /* try a nonexistent section */ 277 buffer[0] = 0; 278 hr = pTranslateInfString(inf_file, "idontexist", "Options.NTx86", 279 "InstallDir", buffer, MAX_PATH, &dwSize, NULL); 280 if (hr == E_ACCESSDENIED) 281 { 282 skip("TranslateInfString is broken\n"); 283 return; 284 } 285 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", (UINT)hr); 286 ok(!strcmp(buffer, TEST_STRING2), "Expected %s, got %s\n", TEST_STRING2, buffer); 287 ok(dwSize == 25, "Expected size 25, got %d\n", dwSize); 288 289 buffer[0] = 0; 290 /* try other nonexistent section */ 291 hr = pTranslateInfString(inf_file, "Options.NTx86", "idontexist", 292 "InstallDir", buffer, MAX_PATH, &dwSize, NULL); 293 ok(hr == SPAPI_E_LINE_NOT_FOUND || hr == E_INVALIDARG, 294 "Expected SPAPI_E_LINE_NOT_FOUND or E_INVALIDARG, got 0x%08x\n", (UINT)hr); 295 296 buffer[0] = 0; 297 /* try nonexistent key */ 298 hr = pTranslateInfString(inf_file, "Options.NTx86", "Options.NTx86", 299 "notvalid", buffer, MAX_PATH, &dwSize, NULL); 300 ok(hr == SPAPI_E_LINE_NOT_FOUND || hr == E_INVALIDARG, 301 "Expected SPAPI_E_LINE_NOT_FOUND or E_INVALIDARG, got 0x%08x\n", (UINT)hr); 302 303 buffer[0] = 0; 304 /* test the behavior of pszInstallSection */ 305 hr = pTranslateInfString(inf_file, "section", "Options.NTx86", 306 "InstallDir", buffer, MAX_PATH, &dwSize, NULL); 307 ok(hr == ERROR_SUCCESS || hr == E_FAIL, 308 "Expected ERROR_SUCCESS or E_FAIL, got 0x%08x\n", (UINT)hr); 309 310 if(hr == ERROR_SUCCESS) 311 { 312 ok(!strcmp(buffer, APP_PATH), "Expected '%s', got '%s'\n", APP_PATH, buffer); 313 ok(dwSize == APP_PATH_LEN, "Expected size %d, got %d\n", APP_PATH_LEN, dwSize); 314 } 315 316 buffer[0] = 0; 317 /* try without a pszInstallSection */ 318 hr = pTranslateInfString(inf_file, NULL, "Options.NTx86", 319 "InstallDir", buffer, MAX_PATH, &dwSize, NULL); 320 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", (UINT)hr); 321 todo_wine 322 { 323 ok(!strcmp(buffer, TEST_STRING2), "Expected %s, got %s\n", TEST_STRING2, buffer); 324 ok(dwSize == 25, "Expected size 25, got %d\n", dwSize); 325 } 326 327 DeleteFileA("c:\\a.inf"); 328 DeleteFileA(inf_file); 329 } 330 331 static void translateinfstringex_test(void) 332 { 333 HINF hinf; 334 HRESULT hr; 335 char buffer[MAX_PATH]; 336 DWORD size = MAX_PATH; 337 338 hr = pOpenINFEngine(inf_file, NULL, 0, &hinf, NULL); 339 if (hr == E_UNEXPECTED) 340 { 341 win_skip("Skipping tests on win9x because of brokenness\n"); 342 return; 343 } 344 345 create_inf_file(); 346 347 /* need to see if there are any flags */ 348 349 /* try a NULL filename */ 350 hr = pOpenINFEngine(NULL, "Options.NTx86", 0, &hinf, NULL); 351 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); 352 353 /* try an empty filename */ 354 hr = pOpenINFEngine("", "Options.NTx86", 0, &hinf, NULL); 355 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) /* NT+ */ || 356 hr == HRESULT_FROM_WIN32(E_UNEXPECTED) /* 9x */, 357 "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND or E_UNEXPECTED), got %08x\n", hr); 358 359 /* try a NULL hinf */ 360 hr = pOpenINFEngine(inf_file, "Options.NTx86", 0, NULL, NULL); 361 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); 362 363 /* open the INF without the Install section specified */ 364 hr = pOpenINFEngine(inf_file, NULL, 0, &hinf, NULL); 365 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 366 367 /* try a NULL hinf */ 368 hr = pTranslateInfStringEx(NULL, inf_file, "Options.NTx86", "InstallDir", 369 buffer, size, &size, NULL); 370 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); 371 372 /* try a NULL filename */ 373 hr = pTranslateInfStringEx(hinf, NULL, "Options.NTx86", "InstallDir", 374 buffer, size, &size, NULL); 375 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); 376 377 /* try an empty filename */ 378 memset(buffer, 'a', 25); 379 buffer[24] = '\0'; 380 size = MAX_PATH; 381 hr = pTranslateInfStringEx(hinf, "", "Options.NTx86", "InstallDir", 382 buffer, size, &size, NULL); 383 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 384 todo_wine 385 { 386 ok(!strcmp(buffer, TEST_STRING2), "Expected %s, got %s\n", TEST_STRING2, buffer); 387 ok(size == 25, "Expected size 25, got %d\n", size); 388 } 389 390 /* try a NULL translate section */ 391 hr = pTranslateInfStringEx(hinf, inf_file, NULL, "InstallDir", 392 buffer, size, &size, NULL); 393 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); 394 395 /* try an empty translate section */ 396 hr = pTranslateInfStringEx(hinf, inf_file, "", "InstallDir", 397 buffer, size, &size, NULL); 398 ok(hr == SPAPI_E_LINE_NOT_FOUND, "Expected SPAPI_E_LINE_NOT_FOUND, got %08x\n", hr); 399 400 /* try a NULL translate key */ 401 hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", NULL, 402 buffer, size, &size, NULL); 403 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); 404 405 /* try an empty translate key */ 406 hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "", 407 buffer, size, &size, NULL); 408 ok(hr == SPAPI_E_LINE_NOT_FOUND, "Expected SPAPI_E_LINE_NOT_FOUND, got %08x\n", hr); 409 410 /* successfully translate the string */ 411 memset(buffer, 'a', 25); 412 buffer[24] = '\0'; 413 size = MAX_PATH; 414 hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "InstallDir", 415 buffer, size, &size, NULL); 416 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 417 todo_wine 418 { 419 ok(!strcmp(buffer, TEST_STRING2), "Expected %s, got %s\n", TEST_STRING2, buffer); 420 ok(size == 25, "Expected size 25, got %d\n", size); 421 } 422 423 /* try a NULL hinf */ 424 hr = pCloseINFEngine(NULL); 425 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr); 426 427 /* successfully close the hinf */ 428 hr = pCloseINFEngine(hinf); 429 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 430 431 /* open the inf with the install section */ 432 hr = pOpenINFEngine(inf_file, "section", 0, &hinf, NULL); 433 if (hr == E_FAIL) 434 { 435 skip("can't open engine with install section (needs admin rights)\n"); 436 DeleteFileA(inf_file); 437 return; 438 } 439 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 440 441 /* translate the string with the install section specified */ 442 memset(buffer, 'a', APP_PATH_LEN); 443 buffer[APP_PATH_LEN - 1] = '\0'; 444 size = MAX_PATH; 445 hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "InstallDir", 446 buffer, size, &size, NULL); 447 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 448 ok(!strcmp(buffer, APP_PATH), "Expected %s, got %s\n", APP_PATH, buffer); 449 ok(size == APP_PATH_LEN, "Expected size %d, got %d\n", APP_PATH_LEN, size); 450 451 /* Single quote test (Note size includes null on return from call) */ 452 memset(buffer, 'a', APP_PATH_LEN); 453 buffer[APP_PATH_LEN - 1] = '\0'; 454 size = MAX_PATH; 455 hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "Result1", 456 buffer, size, &size, NULL); 457 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 458 ok(!lstrcmpiA(buffer, PROG_FILES_ROOT), 459 "Expected %s, got %s\n", PROG_FILES_ROOT, buffer); 460 ok(size == strlen(PROG_FILES_ROOT)+1, "Expected size %d, got %d\n", 461 lstrlenA(PROG_FILES_ROOT)+1, size); 462 463 memset(buffer, 'a', APP_PATH_LEN); 464 buffer[APP_PATH_LEN - 1] = '\0'; 465 size = MAX_PATH; 466 hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "Result2", 467 buffer, size, &size, NULL); 468 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 469 ok(!lstrcmpiA(buffer, PROG_FILES_ROOT), 470 "Expected %s, got %s\n", PROG_FILES_ROOT, buffer); 471 ok(size == strlen(PROG_FILES_ROOT)+1, "Expected size %d, got %d\n", 472 lstrlenA(PROG_FILES_ROOT)+1, size); 473 474 { 475 char drive[MAX_PATH]; 476 lstrcpyA(drive, PROG_FILES_ROOT); 477 drive[3] = 0x00; /* Just keep the system drive plus '\' */ 478 479 memset(buffer, 'a', APP_PATH_LEN); 480 buffer[APP_PATH_LEN - 1] = '\0'; 481 size = MAX_PATH; 482 hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "Result3", 483 buffer, size, &size, NULL); 484 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 485 ok(!lstrcmpiA(buffer, drive), 486 "Expected %s, got %s\n", drive, buffer); 487 ok(size == strlen(drive)+1, "Expected size %d, got %d\n", 488 lstrlenA(drive)+1, size); 489 } 490 491 /* close the INF again */ 492 hr = pCloseINFEngine(hinf); 493 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 494 495 DeleteFileA(inf_file); 496 497 /* Create another .inf file which is just here to trigger a wine bug */ 498 { 499 char data[1024]; 500 char *ptr = data; 501 DWORD dwNumberOfBytesWritten; 502 HANDLE hf = CreateFileA(inf_file, GENERIC_WRITE, 0, NULL, 503 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 504 505 append_str(&ptr, "[Version]\n"); 506 append_str(&ptr, "Signature=\"$Chicago$\"\n"); 507 append_str(&ptr, "[section]\n"); 508 append_str(&ptr, "NotACustomDestination=Version\n"); 509 append_str(&ptr, "CustomDestination=CustInstDestSection\n"); 510 append_str(&ptr, "[CustInstDestSection]\n"); 511 append_str(&ptr, "49010=DestA,1\n"); 512 append_str(&ptr, "49020=DestB\n"); 513 append_str(&ptr, "49030=DestC\n"); 514 append_str(&ptr, "49040=DestD\n"); 515 append_str(&ptr, "[Options.NTx86]\n"); 516 append_str(&ptr, "Result2=%%49030%%\n"); 517 append_str(&ptr, "[DestA]\n"); 518 append_str(&ptr, "HKLM,\"Software\\Garbage\",\"ProgramFilesDir\",,'%%24%%'\n"); 519 /* The point of this test is to have HKCU just before the quoted HKLM */ 520 append_str(&ptr, "[DestB]\n"); 521 append_str(&ptr, "HKCU,\"Software\\Garbage\",\"ProgramFilesDir\",,'%%24%%'\n"); 522 append_str(&ptr, "[DestC]\n"); 523 append_str(&ptr, "'HKLM','Software\\Microsoft\\Windows\\CurrentVersion',"); 524 append_str(&ptr, "'ProgramFilesDir',,\"%%24%%\"\n"); 525 append_str(&ptr, "[DestD]\n"); 526 append_str(&ptr, "HKLM,\"Software\\Garbage\",\"ProgramFilesDir\",,'%%24%%'\n"); 527 528 WriteFile(hf, data, ptr - data, &dwNumberOfBytesWritten, NULL); 529 CloseHandle(hf); 530 } 531 532 /* open the inf with the install section */ 533 hr = pOpenINFEngine(inf_file, "section", 0, &hinf, NULL); 534 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 535 536 /* Single quote test (Note size includes null on return from call) */ 537 memset(buffer, 'a', APP_PATH_LEN); 538 buffer[APP_PATH_LEN - 1] = '\0'; 539 size = MAX_PATH; 540 hr = pTranslateInfStringEx(hinf, inf_file, "Options.NTx86", "Result2", 541 buffer, size, &size, NULL); 542 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 543 ok(!lstrcmpiA(buffer, PROG_FILES_ROOT), 544 "Expected %s, got %s\n", PROG_FILES_ROOT, buffer); 545 ok(size == strlen(PROG_FILES_ROOT)+1, "Expected size %d, got %d\n", 546 lstrlenA(PROG_FILES_ROOT)+1, size); 547 548 /* close the INF again */ 549 hr = pCloseINFEngine(hinf); 550 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 551 552 DeleteFileA(inf_file); 553 } 554 555 static BOOL check_reg_str(HKEY hkey, LPCSTR name, LPCSTR value) 556 { 557 DWORD size = MAX_PATH; 558 char check[MAX_PATH]; 559 560 if (RegQueryValueExA(hkey, name, NULL, NULL, (LPBYTE)check, &size)) 561 return FALSE; 562 563 return !lstrcmpA(check, value); 564 } 565 566 static BOOL check_reg_dword(HKEY hkey, LPCSTR name, DWORD value) 567 { 568 DWORD size = sizeof(DWORD); 569 DWORD check; 570 571 if (RegQueryValueExA(hkey, name, NULL, NULL, (LPBYTE)&check, &size)) 572 return FALSE; 573 574 return (check == value); 575 } 576 577 static void setperusersecvalues_test(void) 578 { 579 PERUSERSECTIONA peruser; 580 HRESULT hr; 581 HKEY guid; 582 583 lstrcpyA(peruser.szDispName, "displayname"); 584 lstrcpyA(peruser.szLocale, "locale"); 585 lstrcpyA(peruser.szStub, "stub"); 586 lstrcpyA(peruser.szVersion, "1,1,1,1"); 587 lstrcpyA(peruser.szCompID, "compid"); 588 peruser.dwIsInstalled = 1; 589 peruser.bRollback = FALSE; 590 591 /* try a NULL pPerUser */ 592 if (0) 593 { 594 /* This crashes on systems with IE7 */ 595 hr = pSetPerUserSecValues(NULL); 596 todo_wine 597 ok(hr == S_OK, "Expected S_OK, got %d\n", hr); 598 ok(!OPEN_GUID_KEY(), "Expected guid key to not exist\n"); 599 } 600 601 /* at the very least, szGUID must be valid */ 602 peruser.szGUID[0] = '\0'; 603 hr = pSetPerUserSecValues(&peruser); 604 ok(hr == S_OK, "Expected S_OK, got %d\n", hr); 605 ok(!OPEN_GUID_KEY(), "Expected guid key to not exist\n"); 606 607 /* set initial values */ 608 lstrcpyA(peruser.szGUID, "guid"); 609 hr = pSetPerUserSecValues(&peruser); 610 if (hr == E_FAIL) 611 { 612 skip("SetPerUserSecValues is broken\n"); 613 return; 614 } 615 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 616 ok(OPEN_GUID_KEY(), "Expected guid key to exist\n"); 617 ok(check_reg_str(guid, NULL, "displayname"), "Expected displayname\n"); 618 ok(check_reg_str(guid, "ComponentID", "compid"), "Expected compid\n"); 619 ok(check_reg_str(guid, "Locale", "locale"), "Expected locale\n"); 620 ok(check_reg_str(guid, "StubPath", "stub"), "Expected stub\n"); 621 ok(check_reg_str(guid, "Version", "1,1,1,1"), "Expected 1,1,1,1\n"); 622 ok(check_reg_dword(guid, "IsInstalled", 1), "Expected 1\n"); 623 ok(!REG_VAL_EXISTS(guid, "OldDisplayName"), "Expected OldDisplayName to not exist\n"); 624 ok(!REG_VAL_EXISTS(guid, "OldLocale"), "Expected OldLocale to not exist\n"); 625 ok(!REG_VAL_EXISTS(guid, "OldStubPath"), "Expected OldStubPath to not exist\n"); 626 ok(!REG_VAL_EXISTS(guid, "OldVersion"), "Expected OldVersion to not exist\n"); 627 ok(!REG_VAL_EXISTS(guid, "RealStubPath"), "Expected RealStubPath to not exist\n"); 628 629 /* raise the version, but bRollback is FALSE, so vals not saved */ 630 lstrcpyA(peruser.szVersion, "2,1,1,1"); 631 hr = pSetPerUserSecValues(&peruser); 632 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 633 ok(check_reg_str(guid, NULL, "displayname"), "Expected displayname\n"); 634 ok(check_reg_str(guid, "ComponentID", "compid"), "Expected compid\n"); 635 ok(check_reg_str(guid, "Locale", "locale"), "Expected locale\n"); 636 ok(check_reg_str(guid, "StubPath", "stub"), "Expected stub\n"); 637 ok(check_reg_str(guid, "Version", "2,1,1,1"), "Expected 2,1,1,1\n"); 638 ok(check_reg_dword(guid, "IsInstalled", 1), "Expected 1\n"); 639 ok(!REG_VAL_EXISTS(guid, "OldDisplayName"), "Expected OldDisplayName to not exist\n"); 640 ok(!REG_VAL_EXISTS(guid, "OldLocale"), "Expected OldLocale to not exist\n"); 641 ok(!REG_VAL_EXISTS(guid, "OldStubPath"), "Expected OldStubPath to not exist\n"); 642 ok(!REG_VAL_EXISTS(guid, "OldVersion"), "Expected OldVersion to not exist\n"); 643 ok(!REG_VAL_EXISTS(guid, "RealStubPath"), "Expected RealStubPath to not exist\n"); 644 645 /* raise the version again, bRollback is TRUE so vals are saved */ 646 peruser.bRollback = TRUE; 647 lstrcpyA(peruser.szVersion, "3,1,1,1"); 648 hr = pSetPerUserSecValues(&peruser); 649 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); 650 ok(check_reg_str(guid, NULL, "displayname"), "Expected displayname\n"); 651 ok(check_reg_str(guid, "ComponentID", "compid"), "Expected compid\n"); 652 ok(check_reg_str(guid, "Locale", "locale"), "Expected locale\n"); 653 ok(check_reg_dword(guid, "IsInstalled", 1), "Expected 1\n"); 654 ok(check_reg_str(guid, "Version", "3,1,1,1"), "Expected 3,1,1,1\n"); 655 todo_wine 656 { 657 ok(check_reg_str(guid, "OldDisplayName", "displayname"), "Expected displayname\n"); 658 ok(check_reg_str(guid, "OldLocale", "locale"), "Expected locale\n"); 659 ok(check_reg_str(guid, "RealStubPath", "stub"), "Expected stub\n"); 660 ok(check_reg_str(guid, "OldStubPath", "stub"), "Expected stub\n"); 661 ok(check_reg_str(guid, "OldVersion", "2,1,1,1"), "Expected 2,1,1,1\n"); 662 ok(check_reg_str(guid, "StubPath", 663 "rundll32.exe advpack.dll,UserInstStubWrapper guid"), 664 "Expected real stub\n"); 665 } 666 667 RegDeleteKeyA(HKEY_LOCAL_MACHINE, GUID_KEY); 668 } 669 670 START_TEST(advpack) 671 { 672 if (!init_function_pointers()) 673 return; 674 675 /* Make sure we create the temporary file in a directory 676 * where we have adequate rights 677 */ 678 GetTempPathA(MAX_PATH, inf_file); 679 lstrcatA(inf_file,"test.inf"); 680 681 get_progfiles_dir(); 682 683 version_test(); 684 delnode_test(); 685 setperusersecvalues_test(); 686 translateinfstring_test(); 687 translateinfstringex_test(); 688 689 FreeLibrary(hAdvPack); 690 } 691