[SERVICES_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_svc_from(void)
178 {
179 char inf[2048];
180 char path[MAX_PATH];
181 HINF infhandle;
182 BOOL ret;
183 SC_HANDLE scm_handle, svc_handle;
184
185 /* Basic inf file to satisfy SetupOpenInfFileA */
186 strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n");
187 create_inf_file(inffile, inf);
188 sprintf(path, "%s\\%s", CURR_DIR, inffile);
189 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
190
191 /* Nothing but the Version section */
192 SetLastError(0xdeadbeef);
193 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
194 ok(!ret, "Expected failure\n");
195 ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
196 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
197 SetupCloseInfFile(infhandle);
198 DeleteFileA(inffile);
199
200 /* Add the section */
201 strcat(inf, "[Winetest.Services]\n");
202 create_inf_file(inffile, inf);
203 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
204 SetLastError(0xdeadbeef);
205 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
206 ok(!ret, "Expected failure\n");
207 ok(GetLastError() == ERROR_SECTION_NOT_FOUND,
208 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
209 SetupCloseInfFile(infhandle);
210 DeleteFileA(inffile);
211
212 /* Add a reference */
213 strcat(inf, "AddService=Winetest,,Winetest.Service\n");
214 create_inf_file(inffile, inf);
215 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
216 SetLastError(0xdeadbeef);
217 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
218 ok(!ret, "Expected failure\n");
219 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
220 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
221 SetupCloseInfFile(infhandle);
222 DeleteFileA(inffile);
223
224 /* Add the section */
225 strcat(inf, "[Winetest.Service]\n");
226 create_inf_file(inffile, inf);
227 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
228 SetLastError(0xdeadbeef);
229 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
230 ok(!ret, "Expected failure\n");
231 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
232 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
233 SetupCloseInfFile(infhandle);
234 DeleteFileA(inffile);
235
236 /* Just the ServiceBinary */
237 strcat(inf, "ServiceBinary=%12%\\winetest.sys\n");
238 create_inf_file(inffile, inf);
239 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
240 SetLastError(0xdeadbeef);
241 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
242 ok(!ret, "Expected failure\n");
243 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
244 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
245 SetupCloseInfFile(infhandle);
246 DeleteFileA(inffile);
247
248 /* Add the ServiceType */
249 strcat(inf, "ServiceType=1\n");
250 create_inf_file(inffile, inf);
251 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
252 SetLastError(0xdeadbeef);
253 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
254 ok(!ret, "Expected failure\n");
255 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
256 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
257 SetupCloseInfFile(infhandle);
258 DeleteFileA(inffile);
259
260 /* Add the StartType */
261 strcat(inf, "StartType=4\n");
262 create_inf_file(inffile, inf);
263 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
264 SetLastError(0xdeadbeef);
265 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
266 ok(!ret, "Expected failure\n");
267 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT,
268 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
269 SetupCloseInfFile(infhandle);
270 DeleteFileA(inffile);
271
272 /* This should be it, the minimal entries to install a service */
273 strcat(inf, "ErrorControl=1");
274 create_inf_file(inffile, inf);
275 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
276 SetLastError(0xdeadbeef);
277 ret = SetupInstallServicesFromInfSectionA(infhandle, "Winetest.Services", 0);
278 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
279 {
280 skip("Not enough rights to install the service\n");
281 SetupCloseInfFile(infhandle);
282 DeleteFileA(inffile);
283 return;
284 }
285 ok(ret, "Expected success\n");
286 ok(GetLastError() == ERROR_SUCCESS,
287 "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
288 SetupCloseInfFile(infhandle);
289 DeleteFileA(inffile);
290
291 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
292
293 /* Open the service to see if it's really there */
294 svc_handle = OpenServiceA(scm_handle, "Winetest", DELETE);
295 ok(svc_handle != NULL, "Service was not created\n");
296
297 SetLastError(0xdeadbeef);
298 ret = DeleteService(svc_handle);
299 ok(ret, "Service could not be deleted : %d\n", GetLastError());
300
301 CloseServiceHandle(svc_handle);
302 CloseServiceHandle(scm_handle);
303
304 strcpy(inf, "[Version]\nSignature=\"$Chicago$\"\n");
305 strcat(inf, "[XSP.InstallPerVer]\n");
306 strcat(inf, "AddReg=AspEventlogMsg.Reg,Perf.Reg,AspVersions.Reg,FreeADO.Reg,IndexServer.Reg\n");
307 create_inf_file(inffile, inf);
308 sprintf(path, "%s\\%s", CURR_DIR, inffile);
309 infhandle = SetupOpenInfFileA(path, NULL, INF_STYLE_WIN4, NULL);
310
311 SetLastError(0xdeadbeef);
312 ret = SetupInstallServicesFromInfSectionA(infhandle, "XSP.InstallPerVer", 0);
313 ok(ret, "Expected success\n");
314 ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
315 SetupCloseInfFile(infhandle);
316 DeleteFileA(inffile);
317
318 /* TODO: Test the Flags */
319 }
320
321 static void test_driver_install(void)
322 {
323 HANDLE handle;
324 SC_HANDLE scm_handle, svc_handle;
325 BOOL ret;
326 char path[MAX_PATH], windir[MAX_PATH], driver[MAX_PATH];
327 DWORD attrs;
328 /* Minimal stuff needed */
329 static const char *inf =
330 "[Version]\n"
331 "Signature=\"$Chicago$\"\n"
332 "[DestinationDirs]\n"
333 "Winetest.DriverFiles=12\n"
334 "[DefaultInstall]\n"
335 "CopyFiles=Winetest.DriverFiles\n"
336 "[DefaultInstall.Services]\n"
337 "AddService=Winetest,,Winetest.Service\n"
338 "[Winetest.Service]\n"
339 "ServiceBinary=%12%\\winetest.sys\n"
340 "ServiceType=1\n"
341 "StartType=4\n"
342 "ErrorControl=1\n"
343 "[Winetest.DriverFiles]\n"
344 "winetest.sys";
345
346 /* Bail out if we don't have enough rights */
347 SetLastError(0xdeadbeef);
348 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
349 if (!scm_handle && (GetLastError() == ERROR_ACCESS_DENIED))
350 {
351 skip("Not enough rights to install the service\n");
352 return;
353 }
354 CloseServiceHandle(scm_handle);
355
356 /* Place where we expect the driver to be installed */
357 GetWindowsDirectoryA(windir, MAX_PATH);
358 lstrcpyA(driver, windir);
359 lstrcatA(driver, "\\system32\\drivers\\winetest.sys");
360
361 /* Create a dummy driver file */
362 handle = CreateFileA("winetest.sys", GENERIC_WRITE, 0, NULL,
363 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
364 CloseHandle(handle);
365
366 create_inf_file(inffile, inf);
367 sprintf(path, "%s\\%s", CURR_DIR, inffile);
368 run_cmdline("DefaultInstall", 128, path);
369
370 /* Driver should have been installed */
371 attrs = GetFileAttributesA(driver);
372 ok(attrs != INVALID_FILE_ATTRIBUTES, "Expected driver to exist\n");
373
374 scm_handle = OpenSCManagerA(NULL, NULL, GENERIC_ALL);
375
376 /* Open the service to see if it's really there */
377 svc_handle = OpenServiceA(scm_handle, "Winetest", DELETE);
378 ok(svc_handle != NULL, "Service was not created\n");
379
380 SetLastError(0xdeadbeef);
381 ret = DeleteService(svc_handle);
382 ok(ret, "Service could not be deleted : %d\n", GetLastError());
383
384 CloseServiceHandle(svc_handle);
385 CloseServiceHandle(scm_handle);
386
387 /* File cleanup */
388 DeleteFileA(inffile);
389 DeleteFileA("winetest.sys");
390 DeleteFileA(driver);
391 }
392
393 static void test_profile_items(void)
394 {
395 char path[MAX_PATH], commonprogs[MAX_PATH];
396
397 static const char *inf =
398 "[Version]\n"
399 "Signature=\"$Chicago$\"\n"
400 "[DefaultInstall]\n"
401 "ProfileItems=TestItem,TestItem2,TestGroup\n"
402 "[TestItem]\n"
403 "Name=TestItem\n"
404 "CmdLine=11,,notepad.exe\n"
405 "[TestItem2]\n"
406 "Name=TestItem2\n"
407 "CmdLine=11,,notepad.exe\n"
408 "SubDir=TestDir\n"
409 "[TestGroup]\n"
410 "Name=TestGroup,4\n"
411 ;
412
413 if (S_OK != SHGetFolderPathA(NULL, CSIDL_COMMON_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, commonprogs))
414 {
415 skip("No common program files directory exists\n");
416 goto cleanup;
417 }
418
419 snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs);
420 if (!CreateDirectoryA(path, NULL) && GetLastError() == ERROR_ACCESS_DENIED)
421 {
422 skip("need admin rights\n");
423 return;
424 }
425 RemoveDirectoryA(path);
426
427 create_inf_file(inffile, inf);
428 sprintf(path, "%s\\%s", CURR_DIR, inffile);
429 run_cmdline("DefaultInstall", 128, path);
430
431 snprintf(path, MAX_PATH, "%s\\TestItem.lnk", commonprogs);
432 snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs);
433 ok(INVALID_FILE_ATTRIBUTES != GetFileAttributesA(path), "directory not created\n");
434 snprintf(path, MAX_PATH, "%s\\TestDir\\TestItem2.lnk", commonprogs);
435 ok(INVALID_FILE_ATTRIBUTES != GetFileAttributesA(path), "link not created\n");
436 snprintf(path, MAX_PATH, "%s\\TestGroup", commonprogs);
437 ok(INVALID_FILE_ATTRIBUTES != GetFileAttributesA(path), "group not created\n");
438
439 snprintf(path, MAX_PATH, "%s\\TestItem.lnk", commonprogs);
440 DeleteFileA(path);
441 snprintf(path, MAX_PATH, "%s\\TestDir\\TestItem2.lnk", commonprogs);
442 DeleteFileA(path);
443 snprintf(path, MAX_PATH, "%s\\TestItem2.lnk", commonprogs);
444 DeleteFileA(path);
445 snprintf(path, MAX_PATH, "%s\\TestDir", commonprogs);
446 RemoveDirectoryA(path);
447 snprintf(path, MAX_PATH, "%s\\TestGroup", commonprogs);
448 RemoveDirectoryA(path);
449
450 cleanup:
451 DeleteFileA(inffile);
452 }
453
454 static void test_inffilelistA(void)
455 {
456 static const char inffile2[] = "test2.inf";
457 static const char *inf =
458 "[Version]\n"
459 "Signature=\"$Chicago$\"";
460
461 char buffer[MAX_PATH] = { 0 };
462 char dir[MAX_PATH], *p;
463 DWORD expected, outsize;
464 BOOL ret;
465
466 /* create a private directory, the temp directory may contain some
467 * inf files left over from old installations
468 */
469 if (!GetTempFileNameA(CURR_DIR, "inftest", 1, dir))
470 {
471 win_skip("GetTempFileNameA failed with error %d\n", GetLastError());
472 return;
473 }
474 if (!CreateDirectoryA(dir, NULL ))
475 {
476 win_skip("CreateDirectoryA(%s) failed with error %d\n", dir, GetLastError());
477 return;
478 }
479 if (!SetCurrentDirectoryA(dir))
480 {
481 win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError());
482 RemoveDirectoryA(dir);
483 return;
484 }
485
486 create_inf_file(inffile, inf);
487 create_inf_file(inffile2, inf);
488
489 /* mixed style
490 */
491 expected = 3 + strlen(inffile) + strlen(inffile2);
492 ret = SetupGetInfFileListA(dir, INF_STYLE_OLDNT | INF_STYLE_WIN4, buffer,
493 MAX_PATH, &outsize);
494 ok(ret, "expected SetupGetInfFileListA to succeed!\n");
495 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
496 expected, outsize);
497 for(p = buffer; lstrlenA(p) && (outsize > (p - buffer)); p+=lstrlenA(p) + 1)
498 ok(!lstrcmpA(p,inffile2) || !lstrcmpA(p,inffile),
499 "unexpected filename %s\n",p);
500
501 DeleteFileA(inffile);
502 DeleteFileA(inffile2);
503 SetCurrentDirectoryA(CURR_DIR);
504 RemoveDirectoryA(dir);
505 }
506
507 static void test_inffilelist(void)
508 {
509 static const char inffile2[] = "test2.inf";
510 static const WCHAR inffile2W[] = {'t','e','s','t','2','.','i','n','f',0};
511 static const char invalid_inf[] = "invalid.inf";
512 static const WCHAR invalid_infW[] = {'i','n','v','a','l','i','d','.','i','n','f',0};
513 static const char *inf =
514 "[Version]\n"
515 "Signature=\"$Chicago$\"";
516 static const char *inf2 =
517 "[Version]\n"
518 "Signature=\"$CHICAGO$\"";
519 static const char *infNT =
520 "[Version]\n"
521 "Signature=\"$WINDOWS NT$\"";
522
523 WCHAR *p, *ptr;
524 char dirA[MAX_PATH];
525 WCHAR dir[MAX_PATH] = { 0 };
526 WCHAR buffer[MAX_PATH] = { 0 };
527 DWORD expected, outsize;
528 BOOL ret;
529
530 /* NULL means %windir%\\inf
531 * get the value as reference
532 */
533 expected = 0;
534 SetLastError(0xdeadbeef);
535 ret = SetupGetInfFileListW(NULL, INF_STYLE_WIN4, NULL, 0, &expected);
536 ok(ret, "expected SetupGetInfFileListW to succeed! Error: %d\n", GetLastError());
537 ok(expected > 0, "expected required buffersize to be at least 1\n");
538
539 /* check if an empty string doesn't behaves like NULL */
540 outsize = 0;
541 SetLastError(0xdeadbeef);
542 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
543 ok(!ret, "expected SetupGetInfFileListW to fail!\n");
544
545 /* create a private directory, the temp directory may contain some
546 * inf files left over from old installations
547 */
548 if (!GetTempFileNameA(CURR_DIR, "inftest", 1, dirA))
549 {
550 win_skip("GetTempFileNameA failed with error %d\n", GetLastError());
551 return;
552 }
553 if (!CreateDirectoryA(dirA, NULL ))
554 {
555 win_skip("CreateDirectoryA(%s) failed with error %d\n", dirA, GetLastError());
556 return;
557 }
558 if (!SetCurrentDirectoryA(dirA))
559 {
560 win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError());
561 RemoveDirectoryA(dirA);
562 return;
563 }
564
565 MultiByteToWideChar(CP_ACP, 0, dirA, -1, dir, MAX_PATH);
566 /* check a not existing directory
567 */
568 ptr = dir + lstrlenW(dir);
569 MultiByteToWideChar(CP_ACP, 0, "\\not_existent", -1, ptr, MAX_PATH - lstrlenW(dir));
570 outsize = 0xffffffff;
571 SetLastError(0xdeadbeef);
572 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
573 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
574 ok(outsize == 1, "expected required buffersize to be 1, got %d\n", outsize);
575 ok(ERROR_PATH_NOT_FOUND == GetLastError(),
576 "expected error ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
577
578 create_inf_file(inffile, inf);
579 create_inf_file(inffile2, inf);
580 create_inf_file(invalid_inf, "This content does not match the inf file format");
581
582 /* pass a filename instead of a directory
583 */
584 *ptr = '\\';
585 MultiByteToWideChar(CP_ACP, 0, invalid_inf, -1, ptr+1, MAX_PATH - lstrlenW(dir));
586 outsize = 0xffffffff;
587 SetLastError(0xdeadbeef);
588 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
589 ok(!ret, "expected SetupGetInfFileListW to fail!\n");
590 ok(ERROR_DIRECTORY == GetLastError(),
591 "expected error ERROR_DIRECTORY, got %d\n", GetLastError());
592
593 /* make the filename look like directory
594 */
595 dir[1 + lstrlenW(dir)] = 0;
596 dir[lstrlenW(dir)] = '\\';
597 SetLastError(0xdeadbeef);
598 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
599 ok(!ret, "expected SetupGetInfFileListW to fail!\n");
600 ok(ERROR_DIRECTORY == GetLastError(),
601 "expected error ERROR_DIRECTORY, got %d\n", GetLastError());
602
603 /* now check the buffer contents of a valid call
604 */
605 *ptr = 0;
606 expected = 3 + strlen(inffile) + strlen(inffile2);
607 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize);
608 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
609 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
610 expected, outsize);
611 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
612 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW),
613 "unexpected filename %s\n",wine_dbgstr_w(p));
614
615 /* upper case value
616 */
617 create_inf_file(inffile2, inf2);
618 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize);
619 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
620 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
621 expected, outsize);
622 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
623 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW),
624 "unexpected filename %s\n",wine_dbgstr_w(p));
625
626 /* signature Windows NT is also inf style win4
627 */
628 create_inf_file(inffile2, infNT);
629 expected = 3 + strlen(inffile) + strlen(inffile2);
630 ret = SetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize);
631 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
632 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
633 expected, outsize);
634 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
635 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW),
636 "unexpected filename %s\n",wine_dbgstr_w(p));
637
638 /* old style
639 */
640 expected = 2 + strlen(invalid_inf);
641 ret = SetupGetInfFileListW(dir, INF_STYLE_OLDNT, buffer, MAX_PATH, &outsize);
642 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
643 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
644 expected, outsize);
645 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
646 ok(!lstrcmpW(p,invalid_infW), "unexpected filename %s\n",wine_dbgstr_w(p));
647
648 /* mixed style
649 */
650 expected = 4 + strlen(inffile) + strlen(inffile2) + strlen(invalid_inf);
651 ret = SetupGetInfFileListW(dir, INF_STYLE_OLDNT | INF_STYLE_WIN4, buffer,
652 MAX_PATH, &outsize);
653 ok(ret, "expected SetupGetInfFileListW to succeed!\n");
654 ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
655 expected, outsize);
656 for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
657 ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW) || !lstrcmpW(p,invalid_infW),
658 "unexpected filename %s\n",wine_dbgstr_w(p));
659
660 DeleteFileA(inffile);
661 DeleteFileA(inffile2);
662 DeleteFileA(invalid_inf);
663 SetCurrentDirectoryA(CURR_DIR);
664 RemoveDirectoryA(dirA);
665 }
666
667 static const char dirid_inf[] = "[Version]\n"
668 "Signature=\"$Chicago$\"\n"
669 "[DefaultInstall]\n"
670 "AddReg=Add.Settings\n"
671 "[Add.Settings]\n"
672 "HKCU,Software\\Wine\\setupapitest,dirid,,%%%i%%\n";
673
674 static void check_dirid(int dirid, LPCSTR expected)
675 {
676 char buffer[sizeof(dirid_inf)+11];
677 char path[MAX_PATH], actual[MAX_PATH];
678 LONG ret;
679 DWORD size, type;
680 HKEY key;
681
682 sprintf(buffer, dirid_inf, dirid);
683
684 create_inf_file(inffile, buffer);
685
686 sprintf(path, "%s\\%s", CURR_DIR, inffile);
687 run_cmdline("DefaultInstall", 128, path);
688
689 size = sizeof(actual);
690 actual[0] = '\0';
691 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\setupapitest", &key);
692 if (ret == ERROR_SUCCESS)
693 {
694 ret = RegQueryValueExA(key, "dirid", NULL, &type, (BYTE*)&actual, &size);
695 RegCloseKey(key);
696 if (type != REG_SZ)
697 ret = ERROR_FILE_NOT_FOUND;
698 }
699
700 ok(ret == ERROR_SUCCESS, "Failed getting value for dirid %i, err=%d\n", dirid, ret);
701 ok(!strcmp(actual, expected), "Expected path for dirid %i was \"%s\", got \"%s\"\n", dirid, expected, actual);
702
703 ok_registry(TRUE);
704 ret = DeleteFileA(inffile);
705 ok(ret, "Expected source inf to exist, last error was %d\n", GetLastError());
706 }
707
708 /* Test dirid values */
709 static void test_dirid(void)
710 {
711 char expected[MAX_PATH];
712
713 check_dirid(DIRID_NULL, "");
714
715 GetWindowsDirectoryA(expected, MAX_PATH);
716 check_dirid(DIRID_WINDOWS, expected);
717
718 GetSystemDirectoryA(expected, MAX_PATH);
719 check_dirid(DIRID_SYSTEM, expected);
720
721 strcat(expected, "\\unknown");
722 check_dirid(40, expected);
723 }
724
725 START_TEST(install)
726 {
727 char temp_path[MAX_PATH], prev_path[MAX_PATH];
728 DWORD len;
729
730 GetCurrentDirectoryA(MAX_PATH, prev_path);
731 GetTempPathA(MAX_PATH, temp_path);
732 SetCurrentDirectoryA(temp_path);
733
734 strcpy(CURR_DIR, temp_path);
735 len = strlen(CURR_DIR);
736 if(len && (CURR_DIR[len - 1] == '\\'))
737 CURR_DIR[len - 1] = 0;
738
739 /* Set CBT hook to disallow MessageBox creation in current thread */
740 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
741 assert(hhook != 0);
742
743 test_cmdline();
744 test_registry();
745 test_install_svc_from();
746 test_driver_install();
747 test_dirid();
748
749 UnhookWindowsHookEx(hhook);
750
751 /* We have to run this test after the CBT hook is disabled because
752 ProfileItems needs to create a window on Windows XP. */
753 test_profile_items();
754
755 test_inffilelist();
756 test_inffilelistA();
757
758 SetCurrentDirectoryA(prev_path);
759 }