[SETUPAPI_WINETEST] Sync with Wine Staging 4.0. CORE-15682
[reactos.git] / modules / rostests / winetests / setupapi / install.c
1 /*
2 * Unit test for setupapi.dll install functions
3 *
4 * Copyright 2007 Misha Koshelev
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
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnls.h"
29 #include "winuser.h"
30 #include "winreg.h"
31 #include "winsvc.h"
32 #include "setupapi.h"
33 #include "shlobj.h"
34
35 #include "wine/test.h"
36
37 static const char inffile[] = "test.inf";
38 static const WCHAR inffileW[] = {'t','e','s','t','.','i','n','f',0};
39 static char CURR_DIR[MAX_PATH];
40
41 /* Notes on InstallHinfSectionA/W:
42 * - InstallHinfSectionA on WinXP seems to be a stub - it does not do anything
43 * and simply returns without displaying any error message or setting last
44 * error.
45 * - These functions do not return a value and do not always set last error to
46 * ERROR_SUCCESS when installation still occurs (e.g., unquoted inf file with
47 * spaces, registry keys are written but last error is 6).
48 * - On installation problems, a MessageBox() is displayed and a Beep() is
49 * issued. The MessageBox() is disabled with a CBT hook.
50 */
51
52 /*
53 * Helpers
54 */
55
56 static void create_inf_file(LPCSTR filename, const char *data)
57 {
58 DWORD res;
59 BOOL ret;
60 HANDLE handle = CreateFileA(filename, GENERIC_WRITE, 0, NULL,
61 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
62 assert(handle != INVALID_HANDLE_VALUE);
63 ret = WriteFile(handle, data, strlen(data), &res, NULL);
64 assert(ret != 0);
65 CloseHandle(handle);
66 }
67
68 /* CBT hook to ensure a window (e.g., MessageBox) cannot be created */
69 static HHOOK hhook;
70 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
71 {
72 return nCode == HCBT_CREATEWND ? 1: CallNextHookEx(hhook, nCode, wParam, lParam);
73 }
74
75 /*
76 * Tests
77 */
78
79 static const char *cmdline_inf = "[Version]\n"
80 "Signature=\"$Chicago$\"\n"
81 "[DefaultInstall]\n"
82 "AddReg=Add.Settings\n"
83 "[Add.Settings]\n"
84 "HKCU,Software\\Wine\\setupapitest,,\n";
85
86 static void run_cmdline(LPCSTR section, int mode, LPCSTR path)
87 {
88 CHAR cmdline[MAX_PATH * 2];
89 WCHAR cmdlinew[MAX_PATH * 2];
90
91 sprintf(cmdline, "%s %d %s", section, mode, path);
92 MultiByteToWideChar(CP_ACP, 0, cmdline, -1, cmdlinew, MAX_PATH*2);
93 InstallHinfSectionW(NULL, NULL, cmdlinew, 0);
94 }
95
96 static void ok_registry(BOOL expectsuccess)
97 {
98 LONG ret;
99
100 /* Functional tests for success of install and clean up */
101 ret = RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest");
102 ok((expectsuccess && ret == ERROR_SUCCESS) ||
103 (!expectsuccess && ret == ERROR_FILE_NOT_FOUND),
104 "Expected registry key Software\\Wine\\setupapitest to %s, RegDeleteKey returned %d\n",
105 expectsuccess ? "exist" : "not exist",
106 ret);
107 }
108
109 /* Test command line processing */
110 static void test_cmdline(void)
111 {
112 static const char infwithspaces[] = "test file.inf";
113 char path[MAX_PATH];
114 BOOL ret;
115
116 create_inf_file(inffile, cmdline_inf);
117 sprintf(path, "%s\\%s", CURR_DIR, inffile);
118 run_cmdline("DefaultInstall", 128, path);
119 ok_registry(TRUE);
120 ret = DeleteFileA(inffile);
121 ok(ret, "Expected source inf to exist, last error was %d\n", GetLastError());
122
123 /* Test handling of spaces in path, unquoted and quoted */
124 create_inf_file(infwithspaces, cmdline_inf);
125
126 sprintf(path, "%s\\%s", CURR_DIR, infwithspaces);
127 run_cmdline("DefaultInstall", 128, path);
128 ok_registry(TRUE);
129
130 sprintf(path, "\"%s\\%s\"", CURR_DIR, infwithspaces);
131 run_cmdline("DefaultInstall", 128, path);
132 ok_registry(FALSE);
133
134 ret = DeleteFileA(infwithspaces);
135 ok(ret, "Expected source inf to exist, last error was %d\n", GetLastError());
136 }
137
138 static const char *cmdline_inf_reg = "[Version]\n"
139 "Signature=\"$Chicago$\"\n"
140 "[DefaultInstall]\n"
141 "DelReg=Del.Settings\n"
142 "[Del.Settings]\n"
143 "HKCU,Software\\Wine\\setupapitest\n";
144
145 static void test_registry(void)
146 {
147 HKEY key;
148 LONG res;
149 char path[MAX_PATH];
150 BOOL ret;
151
152 /* First create a registry structure we would like to be deleted */
153 ok(!RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest", &key),
154 "Expected RegCreateKeyA to succeed\n");
155
156 /* Doublecheck if the registry key is present */
157 ok(!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest", &key),
158 "Expected registry key to exist\n");
159
160 create_inf_file(inffile, cmdline_inf_reg);
161 sprintf(path, "%s\\%s", CURR_DIR, inffile);
162 run_cmdline("DefaultInstall", 128, path);
163
164 /* Check if the registry key is recursively deleted */
165 res = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest", &key);
166 ok(res == ERROR_FILE_NOT_FOUND, "Didn't expect the registry key to exist\n");
167 /* Just in case */
168 if (res == ERROR_SUCCESS)
169 {
170 RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest");
171 RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest");
172 }
173 ret = DeleteFileA(inffile);
174 ok(ret, "Expected source inf to exist, last error was %d\n", GetLastError());
175 }
176
177 static void test_install_from(void)
178 {
179 char path[MAX_PATH];
180 HINF infhandle;
181 HKEY key;
182 LONG res;
183 BOOL ret;
184
185 /* First create a registry structure we would like to be deleted */
186 ok(!RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest", &key),
187 "Expected RegCreateKeyA to succeed\n");
188
189 /* Doublecheck if the registry key is present */
190 ok(!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest", &key),
191 "Expected registry key to exist\n");
192
193 create_inf_file(inffile, cmdline_inf_reg);
194 sprintf(path, "%s\\%s", CURR_DIR, inffile);
195 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
196 SetLastError(0xdeadbeef);
197 ret = SetupInstallFromInfSectionA(NULL, infhandle, "DefaultInstall", SPINST_REGISTRY, key,
198 "A:\\", 0, NULL, NULL, NULL, NULL);
199 ok(ret, "Unexpected failure\n");
200 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
201
202 /* Check if the registry key is recursively deleted */
203 res = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest", &key);
204 ok(res == ERROR_FILE_NOT_FOUND, "Didn't expect the registry key to exist\n");
205 /* Just in case */
206 if (res == ERROR_SUCCESS)
207 {
208 RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest\\setupapitest");
209 RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest");
210 }
211
212 SetupCloseInfFile(infhandle);
213 DeleteFileA(inffile);
214 }
215
216 static void test_install_svc_from(void)
217 {
218 char inf[2048];
219 char path[MAX_PATH];
220 HINF infhandle;
221 BOOL ret;
222 SC_HANDLE scm_handle, svc_handle;
223
224 /* Basic inf file to satisfy SetupOpenInfFileA */
225 strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n");
226 create_inf_file(inffile, inf);
227 sprintf(path, "%s\\%s", CURR_DIR, inffile);
228 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
229
230 /* Nothing but the Version section */
231 SetLastError(0xdeadbeef);
232 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
233 ok(!ret, "Expected failure\n");
234 ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
235 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
236 SetupCloseInfFile(infhandle);
237 DeleteFileA(inffile);
238
239 /* Add the section */
240 strcat(inf, "[Winetest.Services]\n");
241 create_inf_file(inffile, inf);
242 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
243 SetLastError(0xdeadbeef);
244 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
245 ok(!ret, "Expected failure\n");
246 ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
247 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
248 SetupCloseInfFile(infhandle);
249 DeleteFileA(inffile);
250
251 /* Add a reference */
252 strcat(inf, "AddService=Winetest,,Winetest.Service\n");
253 create_inf_file(inffile, inf);
254 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
255 SetLastError(0xdeadbeef);
256 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
257 ok(!ret, "Expected failure\n");
258 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
259 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
260 SetupCloseInfFile(infhandle);
261 DeleteFileA(inffile);
262
263 /* Add the section */
264 strcat(inf, "[Winetest.Service]\n");
265 create_inf_file(inffile, inf);
266 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
267 SetLastError(0xdeadbeef);
268 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
269 ok(!ret, "Expected failure\n");
270 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
271 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
272 SetupCloseInfFile(infhandle);
273 DeleteFileA(inffile);
274
275 /* Just the ServiceBinary */
276 strcat(inf, "ServiceBinary=%12%\\winetest.sys\n");
277 create_inf_file(inffile, inf);
278 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
279 SetLastError(0xdeadbeef);
280 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
281 ok(!ret, "Expected failure\n");
282 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
283 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
284 SetupCloseInfFile(infhandle);
285 DeleteFileA(inffile);
286
287 /* Add the ServiceType */
288 strcat(inf, "ServiceType=1\n");
289 create_inf_file(inffile, inf);
290 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
291 SetLastError(0xdeadbeef);
292 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
293 ok(!ret, "Expected failure\n");
294 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
295 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
296 SetupCloseInfFile(infhandle);
297 DeleteFileA(inffile);
298
299 /* Add the StartType */
300 strcat(inf, "StartType=4\n");
301 create_inf_file(inffile, inf);
302 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
303 SetLastError(0xdeadbeef);
304 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
305 ok(!ret, "Expected failure\n");
306 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
307 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
308 SetupCloseInfFile(infhandle);
309 DeleteFileA(inffile);
310
311 /* This should be it, the minimal entries to install a service */
312 strcat(inf, "ErrorControl=1");
313 create_inf_file(inffile, inf);
314 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
315 SetLastError(0xdeadbeef);
316 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
317 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
318 {
319 skip("Not enough rights to install the service\n");
320 SetupCloseInfFile(infhandle);
321 DeleteFileA(inffile);
322 return;
323 }
324 ok(ret, "Expected success\n");
325 ok(GetLastError() == ERROR_SUCCESS,
326 "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
327 SetupCloseInfFile(infhandle);
328 DeleteFileA(inffile);
329
330 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
331
332 /* Open the service to see if it's really there */
333 svc_handle = OpenServiceA(scm_handle, "Winetest", DELETE);
334 ok(svc_handle != NULL, "Service was not created\n");
335
336 SetLastError(0xdeadbeef);
337 ret = DeleteService(svc_handle);
338 ok(ret, "Service could not be deleted : %d\n", GetLastError());
339
340 CloseServiceHandle(svc_handle);
341 CloseServiceHandle(scm_handle);
342
343 strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n");
344 strcat(inf, "[XSP.InstallPerVer]\n");
345 strcat(inf, "AddReg=AspEventlogMsg.Reg,Perf.Reg,AspVersions.Reg,FreeADO.Reg,IndexServer.Reg\n");
346 create_inf_file(inffile, inf);
347 sprintf(path, "%s\\%s", CURR_DIR, inffile);
348 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
349
350 SetLastError(0xdeadbeef);
351 ret = SetupInstallServicesFromInfSectionA(infhandle, "XSP.InstallPerVer", 0);
352 ok(ret, "Expected success\n");
353 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
354 SetupCloseInfFile(infhandle);
355 DeleteFileA(inffile);
356
357 /* TODO: Test the Flags */
358 }
359
360 static void test_driver_install(void)
361 {
362 HANDLE handle;
363 SC_HANDLE scm_handle, svc_handle;
364 BOOL ret;
365 char path[MAX_PATH], windir[MAX_PATH], driver[MAX_PATH];
366 DWORD attrs;
367 /* Minimal stuff needed */
368 static const char *inf =
369 "[Version]\n"
370 "Signature=\"$Chicago$\"\n"
371 "[DestinationDirs]\n"
372 "Winetest.DriverFiles=12\n"
373 "[DefaultInstall]\n"
374 "CopyFiles=Winetest.DriverFiles\n"
375 "[DefaultInstall.Services]\n"
376 "AddService=Winetest,,Winetest.Service\n"
377 "[Winetest.Service]\n"
378 "ServiceBinary=%12%\\winetest.sys\n"
379 "ServiceType=1\n"
380 "StartType=4\n"
381 "ErrorControl=1\n"
382 "[Winetest.DriverFiles]\n"
383 "winetest.sys";
384
385 /* Bail out if we don't have enough rights */
386 SetLastError(0xdeadbeef);
387 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
388 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
389 {
390 skip("Not enough rights to install the service\n");
391 return;
392 }
393 CloseServiceHandle(scm_handle);
394
395 /* Place where we expect the driver to be installed */
396 GetWindowsDirectoryA(windir, MAX_PATH);
397 lstrcpyA(driver, windir);
398 lstrcatA(driver, "\\system32\\drivers\\winetest.sys");
399
400 /* Create a dummy driver file */
401 handle = CreateFileA("winetest.sys", GENERIC_WRITE, 0, NULL,
402 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
403 CloseHandle(handle);
404
405 create_inf_file(inffile, inf);
406 sprintf(path, "%s\\%s", CURR_DIR, inffile);
407 run_cmdline("DefaultInstall", 128, path);
408
409 /* Driver should have been installed */
410 attrs = GetFileAttributesA(driver);
411 ok(attrs != INVALID_FILE_ATTRIBUTES, "Expected driver to exist\n");
412
413 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
414
415 /* Open the service to see if it's really there */
416 svc_handle = OpenServiceA(scm_handle, "Winetest", DELETE);
417 ok(svc_handle != NULL, "Service was not created\n");
418
419 SetLastError(0xdeadbeef);
420 ret = DeleteService(svc_handle);
421 ok(ret, "Service could not be deleted : %d\n", GetLastError());
422
423 CloseServiceHandle(svc_handle);
424 CloseServiceHandle(scm_handle);
425
426 /* File cleanup */
427 DeleteFileA(inffile);
428 DeleteFileA("winetest.sys");
429 DeleteFileA(driver);
430 }
431
432 static void test_profile_items(void)
433 {
434 char path[MAX_PATH], commonprogs[MAX_PATH];
435
436 static const char *inf =
437 "[Version]\n"
438 "Signature=\"$Chicago$\"\n"
439 "[DefaultInstall]\n"
440 "ProfileItems=TestItem,TestItem2,TestGroup\n"
441 "[TestItem]\n"
442 "Name=TestItem\n"
443 "CmdLine=11,,notepad.exe\n"
444 "[TestItem2]\n"
445 "Name=TestItem2\n"
446 "CmdLine=11,,notepad.exe\n"
447 "SubDir=TestDir\n"
448 "[TestGroup]\n"
449 "Name=TestGroup,4\n"
450 ;
451
452 if (S_OK != SHGetFolderPathA(NULL, CSIDL_COMMON_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, commonprogs))
453 {
454 skip("No common program files directory exists\n");
455 goto cleanup;
456 }
457
458 snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs);
459 if (!CreateDirectoryA(path, NULL) && GetLastError() == ERROR_ACCESS_DENIED)
460 {
461 skip("need admin rights\n");
462 return;
463 }
464 RemoveDirectoryA(path);
465
466 create_inf_file(inffile, inf);
467 sprintf(path, "%s\\%s", CURR_DIR, inffile);
468 run_cmdline("DefaultInstall", 128, path);
469
470 snprintf(path, MAX_PATH, "%s\\TestItem.lnk", commonprogs);
471 snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs);
472 ok(INVALID_FILE_ATTRIBUTES != GetFileAttributesA(path), "directory not created\n");
473 snprintf(path, MAX_PATH, "%s\\TestDir\\TestItem2.lnk", commonprogs);
474 ok(INVALID_FILE_ATTRIBUTES != GetFileAttributesA(path), "link not created\n");
475 snprintf(path, MAX_PATH, "%s\\TestGroup", commonprogs);
476 ok(INVALID_FILE_ATTRIBUTES != GetFileAttributesA(path), "group not created\n");
477
478 snprintf(path, MAX_PATH, "%s\\TestItem.lnk", commonprogs);
479 DeleteFileA(path);
480 snprintf(path, MAX_PATH, "%s\\TestDir\\TestItem2.lnk", commonprogs);
481 DeleteFileA(path);
482 snprintf(path, MAX_PATH, "%s\\TestItem2.lnk", commonprogs);
483 DeleteFileA(path);
484 snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs);
485 RemoveDirectoryA(path);
486 snprintf(path, MAX_PATH, "%s\\TestGroup", commonprogs);
487 RemoveDirectoryA(path);
488
489 cleanup:
490 DeleteFileA(inffile);
491 }
492
493 static void test_inffilelistA(void)
494 {
495 static const char inffile2[] = "test2.inf";
496 static const char *inf =
497 "[Version]\n"
498 "Signature=\"$Chicago$\"";
499
500 char buffer[MAX_PATH] = { 0 };
501 char dir[MAX_PATH], *p;
502 DWORD expected, outsize;
503 BOOL ret;
504
505 /* create a private directory, the temp directory may contain some
506 * inf files left over from old installations
507 */
508 if (!GetTempFileNameA(CURR_DIR, "inftest", 1, dir))
509 {
510 win_skip("GetTempFileNameA failed with error %d\n", GetLastError());
511 return;
512 }
513 if (!CreateDirectoryA(dir, NULL ))
514 {
515 win_skip("CreateDirectoryA(%s) failed with error %d\n", dir, GetLastError());
516 return;
517 }
518 if (!SetCurrentDirectoryA(dir))
519 {
520 win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError());
521 RemoveDirectoryA(dir);
522 return;
523 }
524
525 create_inf_file(inffile, inf);
526 create_inf_file(inffile2, inf);
527
528 /* mixed style
529 */
530 expected = 3 + strlen(inffile) + strlen(inffile2);
531 ret = SetupGetInfFileListA(dir, INF_STYLE_OLDNT | INF_STYLE_WIN4, buffer,
532 MAX_PATH, &outsize);
533 ok(ret, "expected SetupGetInfFileListA to succeed!\n");
534 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
535 expected, outsize);
536 for(p = buffer; lstrlenA(p) && (outsize > (p - buffer)); p+=lstrlenA(p) + 1)
537 ok(!lstrcmpA(p,inffile2) || !lstrcmpA(p,inffile),
538 "unexpected filename %s\n",p);
539
540 DeleteFileA(inffile);
541 DeleteFileA(inffile2);
542 SetCurrentDirectoryA(CURR_DIR);
543 RemoveDirectoryA(dir);
544 }
545
546 static void test_inffilelist(void)
547 {
548 static const char inffile2[] = "test2.inf";
549 static const WCHAR inffile2W[] = {'t','e','s','t','2','.','i','n','f',0};
550 static const char invalid_inf[] = "invalid.inf";
551 static const WCHAR invalid_infW[] = {'i','n','v','a','l','i','d','.','i','n','f',0};
552 static const char *inf =
553 "[Version]\n"
554 "Signature=\"$Chicago$\"";
555 static const char *inf2 =
556 "[Version]\n"
557 "Signature=\"$CHICAGO$\"";
558 static const char *infNT =
559 "[Version]\n"
560 "Signature=\"$WINDOWS NT$\"";
561
562 WCHAR *p, *ptr;
563 char dirA[MAX_PATH];
564 WCHAR dir[MAX_PATH] = { 0 };
565 WCHAR buffer[MAX_PATH] = { 0 };
566 DWORD expected, outsize;
567 BOOL ret;
568
569 /* NULL means %windir%\\inf
570 * get the value as reference
571 */
572 expected = 0;
573 SetLastError(0xdeadbeef);
574 ret = SetupGetInfFileListW(NULL, INF_STYLE_WIN4, NULL, 0, &expected);
575 ok(ret, "expected SetupGetInfFileListW to succeed! Error: %d\n", GetLastError());
576 ok(expected > 0, "expected required buffersize to be at least 1\n");
577
578 /* check if an empty string doesn't behaves like NULL */
579 outsize = 0;
580 SetLastError(0xdeadbeef);
581 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
582 ok(!ret, "expected SetupGetInfFileListW to fail!\n");
583
584 /* create a private directory, the temp directory may contain some
585 * inf files left over from old installations
586 */
587 if (!GetTempFileNameA(CURR_DIR, "inftest", 1, dirA))
588 {
589 win_skip("GetTempFileNameA failed with error %d\n", GetLastError());
590 return;
591 }
592 if (!CreateDirectoryA(dirA, NULL ))
593 {
594 win_skip("CreateDirectoryA(%s) failed with error %d\n", dirA, GetLastError());
595 return;
596 }
597 if (!SetCurrentDirectoryA(dirA))
598 {
599 win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError());
600 RemoveDirectoryA(dirA);
601 return;
602 }
603
604 MultiByteToWideChar(CP_ACP, 0, dirA, -1, dir, MAX_PATH);
605 /* check a not existing directory
606 */
607 ptr = dir + lstrlenW(dir);
608 MultiByteToWideChar(CP_ACP, 0, "\\not_existent", -1, ptr, MAX_PATH - lstrlenW(dir));
609 outsize = 0xffffffff;
610 SetLastError(0xdeadbeef);
611 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
612 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
613 ok(outsize == 1, "expected required buffersize to be 1, got %d\n", outsize);
614 ok(ERROR_PATH_NOT_FOUND == GetLastError(),
615 "expected error ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
616
617 create_inf_file(inffile, inf);
618 create_inf_file(inffile2, inf);
619 create_inf_file(invalid_inf, "This content does not match the inf file format");
620
621 /* pass a filename instead of a directory
622 */
623 *ptr = '\\';
624 MultiByteToWideChar(CP_ACP, 0, invalid_inf, -1, ptr+1, MAX_PATH - lstrlenW(dir));
625 outsize = 0xffffffff;
626 SetLastError(0xdeadbeef);
627 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
628 ok(!ret, "expected SetupGetInfFileListW to fail!\n");
629 ok(ERROR_DIRECTORY == GetLastError(),
630 "expected error ERROR_DIRECTORY, got %d\n", GetLastError());
631
632 /* make the filename look like directory
633 */
634 dir[1 + lstrlenW(dir)] = 0;
635 dir[lstrlenW(dir)] = '\\';
636 SetLastError(0xdeadbeef);
637 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
638 ok(!ret, "expected SetupGetInfFileListW to fail!\n");
639 ok(ERROR_DIRECTORY == GetLastError(),
640 "expected error ERROR_DIRECTORY, got %d\n", GetLastError());
641
642 /* now check the buffer contents of a valid call
643 */
644 *ptr = 0;
645 expected = 3 + strlen(inffile) + strlen(inffile2);
646 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize);
647 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
648 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
649 expected, outsize);
650 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
651 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW),
652 "unexpected filename %s\n",wine_dbgstr_w(p));
653
654 /* upper case value
655 */
656 create_inf_file(inffile2, inf2);
657 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize);
658 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
659 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
660 expected, outsize);
661 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
662 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW),
663 "unexpected filename %s\n",wine_dbgstr_w(p));
664
665 /* signature Windows NT is also inf style win4
666 */
667 create_inf_file(inffile2, infNT);
668 expected = 3 + strlen(inffile) + strlen(inffile2);
669 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize);
670 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
671 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
672 expected, outsize);
673 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
674 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW),
675 "unexpected filename %s\n",wine_dbgstr_w(p));
676
677 /* old style
678 */
679 expected = 2 + strlen(invalid_inf);
680 ret = SetupGetInfFileListW(dir, INF_STYLE_OLDNT, buffer, MAX_PATH, &outsize);
681 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
682 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
683 expected, outsize);
684 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
685 ok(!lstrcmpW(p,invalid_infW), "unexpected filename %s\n",wine_dbgstr_w(p));
686
687 /* mixed style
688 */
689 expected = 4 + strlen(inffile) + strlen(inffile2) + strlen(invalid_inf);
690 ret = SetupGetInfFileListW(dir, INF_STYLE_OLDNT | INF_STYLE_WIN4, buffer,
691 MAX_PATH, &outsize);
692 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
693 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
694 expected, outsize);
695 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
696 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW) || !lstrcmpW(p,invalid_infW),
697 "unexpected filename %s\n",wine_dbgstr_w(p));
698
699 DeleteFileA(inffile);
700 DeleteFileA(inffile2);
701 DeleteFileA(invalid_inf);
702 SetCurrentDirectoryA(CURR_DIR);
703 RemoveDirectoryA(dirA);
704 }
705
706 static const char dirid_inf[] = "[Version]\n"
707 "Signature=\"$Chicago$\"\n"
708 "[DefaultInstall]\n"
709 "AddReg=Add.Settings\n"
710 "[Add.Settings]\n"
711 "HKCU,Software\\Wine\\setupapitest,dirid,,%%%i%%\n";
712
713 static void check_dirid(int dirid, LPCSTR expected)
714 {
715 char buffer[sizeof(dirid_inf)+11];
716 char path[MAX_PATH], actual[MAX_PATH];
717 LONG ret;
718 DWORD size, type;
719 HKEY key;
720
721 sprintf(buffer, dirid_inf, dirid);
722
723 create_inf_file(inffile, buffer);
724
725 sprintf(path, "%s\\%s", CURR_DIR, inffile);
726 run_cmdline("DefaultInstall", 128, path);
727
728 size = sizeof(actual);
729 actual[0] = '\0';
730 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest", &key);
731 if (ret == ERROR_SUCCESS)
732 {
733 ret = RegQueryValueExA(key, "dirid", NULL, &type, (BYTE*)&actual, &size);
734 RegCloseKey(key);
735 if (type != REG_SZ)
736 ret = ERROR_FILE_NOT_FOUND;
737 }
738
739 ok(ret == ERROR_SUCCESS, "Failed getting value for dirid %i, err=%d\n", dirid, ret);
740 ok(!strcmp(actual, expected), "Expected path for dirid %i was \"%s\", got \"%s\"\n", dirid, expected, actual);
741
742 ok_registry(TRUE);
743 ret = DeleteFileA(inffile);
744 ok(ret, "Expected source inf to exist, last error was %d\n", GetLastError());
745 }
746
747 /* Test dirid values */
748 static void test_dirid(void)
749 {
750 char expected[MAX_PATH];
751
752 check_dirid(DIRID_NULL, "");
753
754 GetWindowsDirectoryA(expected, MAX_PATH);
755 check_dirid(DIRID_WINDOWS, expected);
756
757 GetSystemDirectoryA(expected, MAX_PATH);
758 check_dirid(DIRID_SYSTEM, expected);
759
760 strcat(expected, "\\unknown");
761 check_dirid(40, expected);
762 }
763
764 START_TEST(install)
765 {
766 char temp_path[MAX_PATH], prev_path[MAX_PATH];
767 DWORD len;
768
769 GetCurrentDirectoryA(MAX_PATH, prev_path);
770 GetTempPathA(MAX_PATH, temp_path);
771 SetCurrentDirectoryA(temp_path);
772
773 strcpy(CURR_DIR, temp_path);
774 len = strlen(CURR_DIR);
775 if(len && (CURR_DIR[len - 1] == '\\'))
776 CURR_DIR[len - 1] = 0;
777
778 /* Set CBT hook to disallow MessageBox creation in current thread */
779 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
780 assert(hhook != 0);
781
782 test_cmdline();
783 test_registry();
784 test_install_from();
785 test_install_svc_from();
786 test_driver_install();
787 test_dirid();
788
789 UnhookWindowsHookEx(hhook);
790
791 /* We have to run this test after the CBT hook is disabled because
792 ProfileItems needs to create a window on Windows XP. */
793 test_profile_items();
794
795 test_inffilelist();
796 test_inffilelistA();
797
798 SetCurrentDirectoryA(prev_path);
799 }