2 * Unit test for setupapi.dll install functions
4 * Copyright 2007 Misha Koshelev
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.
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.
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
36 #include "wine/test.h"
38 static const char inffile
[] = "test.inf";
39 static const WCHAR inffileW
[] = {'t','e','s','t','.','i','n','f',0};
40 static char CURR_DIR
[MAX_PATH
];
42 /* Notes on InstallHinfSectionA/W:
43 * - InstallHinfSectionA on WinXP seems to be a stub - it does not do anything
44 * and simply returns without displaying any error message or setting last
46 * - These functions do not return a value and do not always set last error to
47 * ERROR_SUCCESS when installation still occurs (e.g., unquoted inf file with
48 * spaces, registry keys are written but last error is 6).
49 * - On installation problems, a MessageBox() is displayed and a Beep() is
50 * issued. The MessageBox() is disabled with a CBT hook.
57 static void load_resource(const char *name
, const char *filename
)
64 file
= CreateFileA(filename
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
65 ok(file
!= INVALID_HANDLE_VALUE
, "file creation failed, at %s, error %d\n", filename
, GetLastError());
67 res
= FindResourceA(NULL
, name
, "TESTDLL");
68 ok( res
!= 0, "couldn't find resource\n" );
69 ptr
= LockResource( LoadResource( GetModuleHandleA(NULL
), res
));
70 WriteFile( file
, ptr
, SizeofResource( GetModuleHandleA(NULL
), res
), &written
, NULL
);
71 ok( written
== SizeofResource( GetModuleHandleA(NULL
), res
), "couldn't write resource\n" );
75 static void create_inf_file(LPCSTR filename
, const char *data
)
79 HANDLE handle
= CreateFileA(filename
, GENERIC_WRITE
, 0, NULL
,
80 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
81 ok(handle
!= INVALID_HANDLE_VALUE
, "Failed to create %s, error %u.\n", filename
, GetLastError());
82 ret
= WriteFile(handle
, data
, strlen(data
), &res
, NULL
);
83 ok(ret
, "Failed to write file, error %u.\n", GetLastError());
87 static void create_file(const char *filename
)
89 create_inf_file(filename
, "dummy");
92 static BOOL
delete_file(const char *filename
)
94 if (GetFileAttributesA(filename
) & FILE_ATTRIBUTE_DIRECTORY
)
95 return RemoveDirectoryA(filename
);
97 return DeleteFileA(filename
);
100 static BOOL
file_exists(const char *path
)
102 return GetFileAttributesA(path
) != INVALID_FILE_ATTRIBUTES
;
105 static void * CDECL
mem_alloc(ULONG cb
)
107 return HeapAlloc(GetProcessHeap(), 0, cb
);
110 static void CDECL
mem_free(void *memory
)
112 HeapFree(GetProcessHeap(), 0, memory
);
115 static BOOL CDECL
get_next_cabinet(PCCAB pccab
, ULONG cbPrevCab
, void *pv
)
117 sprintf(pccab
->szCab
, pv
, pccab
->iCab
);
121 static LONG CDECL
progress(UINT typeStatus
, ULONG cb1
, ULONG cb2
, void *pv
)
126 static int CDECL
file_placed(PCCAB pccab
, char *pszFile
, LONG cbFile
,
127 BOOL fContinuation
, void *pv
)
132 static INT_PTR CDECL
fci_open(char *pszFile
, int oflag
, int pmode
, int *err
, void *pv
)
136 DWORD dwShareMode
= 0;
137 DWORD dwCreateDisposition
= OPEN_EXISTING
;
139 dwAccess
= GENERIC_READ
| GENERIC_WRITE
;
140 dwShareMode
= FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
142 if (GetFileAttributesA(pszFile
) != INVALID_FILE_ATTRIBUTES
)
143 dwCreateDisposition
= OPEN_EXISTING
;
145 dwCreateDisposition
= CREATE_NEW
;
147 handle
= CreateFileA(pszFile
, dwAccess
, dwShareMode
, NULL
,
148 dwCreateDisposition
, 0, NULL
);
150 ok(handle
!= INVALID_HANDLE_VALUE
, "Failed to CreateFile %s\n", pszFile
);
152 return (INT_PTR
)handle
;
155 static UINT CDECL
fci_read(INT_PTR hf
, void *memory
, UINT cb
, int *err
, void *pv
)
157 HANDLE handle
= (HANDLE
)hf
;
161 res
= ReadFile(handle
, memory
, cb
, &dwRead
, NULL
);
162 ok(res
, "Failed to ReadFile\n");
167 static UINT CDECL
fci_write(INT_PTR hf
, void *memory
, UINT cb
, int *err
, void *pv
)
169 HANDLE handle
= (HANDLE
)hf
;
173 res
= WriteFile(handle
, memory
, cb
, &dwWritten
, NULL
);
174 ok(res
, "Failed to WriteFile\n");
179 static int CDECL
fci_close(INT_PTR hf
, int *err
, void *pv
)
181 HANDLE handle
= (HANDLE
)hf
;
182 ok(CloseHandle(handle
), "Failed to CloseHandle\n");
187 static LONG CDECL
fci_seek(INT_PTR hf
, LONG dist
, int seektype
, int *err
, void *pv
)
189 HANDLE handle
= (HANDLE
)hf
;
192 ret
= SetFilePointer(handle
, dist
, NULL
, seektype
);
193 ok(ret
!= INVALID_SET_FILE_POINTER
, "Failed to SetFilePointer\n");
198 static int CDECL
fci_delete(char *pszFile
, int *err
, void *pv
)
200 BOOL ret
= DeleteFileA(pszFile
);
201 ok(ret
, "Failed to DeleteFile %s\n", pszFile
);
206 static BOOL CDECL
get_temp_file(char *pszTempName
, int cbTempName
, void *pv
)
210 tempname
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
211 GetTempFileNameA(".", "xx", 0, tempname
);
213 if (tempname
&& (strlen(tempname
) < (unsigned)cbTempName
))
215 lstrcpyA(pszTempName
, tempname
);
216 HeapFree(GetProcessHeap(), 0, tempname
);
220 HeapFree(GetProcessHeap(), 0, tempname
);
225 static INT_PTR CDECL
get_open_info(char *pszName
, USHORT
*pdate
, USHORT
*ptime
,
226 USHORT
*pattribs
, int *err
, void *pv
)
228 BY_HANDLE_FILE_INFORMATION finfo
;
234 handle
= CreateFileA(pszName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
235 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_SEQUENTIAL_SCAN
, NULL
);
237 ok(handle
!= INVALID_HANDLE_VALUE
, "Failed to CreateFile %s\n", pszName
);
239 res
= GetFileInformationByHandle(handle
, &finfo
);
240 ok(res
, "Expected GetFileInformationByHandle to succeed\n");
242 FileTimeToLocalFileTime(&finfo
.ftLastWriteTime
, &filetime
);
243 FileTimeToDosDateTime(&filetime
, pdate
, ptime
);
245 attrs
= GetFileAttributesA(pszName
);
246 ok(attrs
!= INVALID_FILE_ATTRIBUTES
, "Failed to GetFileAttributes\n");
248 return (INT_PTR
)handle
;
251 static BOOL
add_file(HFCI hfci
, const char *file
, TCOMP compress
)
254 char filename
[MAX_PATH
];
256 lstrcpyA(path
, CURR_DIR
);
257 lstrcatA(path
, "\\");
258 lstrcatA(path
, file
);
260 lstrcpyA(filename
, file
);
262 return FCIAddFile(hfci
, path
, filename
, FALSE
, get_next_cabinet
,
263 progress
, get_open_info
, compress
);
266 static void create_cab_file(const CHAR
*name
, const CHAR
*files
)
268 CCAB cabParams
= {0};
274 cabParams
.cb
= INT_MAX
;
275 cabParams
.cbFolderThresh
= 900000;
276 cabParams
.setID
= 0xbeef;
278 lstrcpyA(cabParams
.szCabPath
, CURR_DIR
);
279 lstrcatA(cabParams
.szCabPath
, "\\");
280 lstrcpyA(cabParams
.szCab
, name
);
282 hfci
= FCICreate(&erf
, file_placed
, mem_alloc
, mem_free
, fci_open
,
283 fci_read
, fci_write
, fci_close
, fci_seek
, fci_delete
,
284 get_temp_file
, &cabParams
, NULL
);
286 ok(hfci
!= NULL
, "Failed to create an FCI context\n");
292 res
= add_file(hfci
, ptr
, tcompTYPE_MSZIP
);
293 ok(res
, "Failed to add file: %s\n", ptr
);
294 res
= DeleteFileA(ptr
);
295 ok(res
, "Failed to delete file %s, error %u\n", ptr
, GetLastError());
296 ptr
+= lstrlenA(ptr
) + 1;
299 res
= FCIFlushCabinet(hfci
, FALSE
, get_next_cabinet
, progress
);
300 ok(res
, "Failed to flush the cabinet\n");
302 res
= FCIDestroy(hfci
);
303 ok(res
, "Failed to destroy the cabinet\n");
306 /* CBT hook to ensure a window (e.g., MessageBox) cannot be created */
308 static LRESULT CALLBACK
cbt_hook_proc(int nCode
, WPARAM wParam
, LPARAM lParam
)
310 return nCode
== HCBT_CREATEWND
? 1: CallNextHookEx(hhook
, nCode
, wParam
, lParam
);
317 static const char *cmdline_inf
= "[Version]\n"
318 "Signature=\"$Chicago$\"\n"
320 "AddReg=Add.Settings\n"
322 "HKCU,Software\\Wine\\setupapitest,,\n";
324 static void run_cmdline(LPCSTR section
, int mode
, LPCSTR path
)
326 CHAR cmdline
[MAX_PATH
* 2];
327 WCHAR cmdlinew
[MAX_PATH
* 2];
329 sprintf(cmdline
, "%s %d %s", section
, mode
, path
);
330 MultiByteToWideChar(CP_ACP
, 0, cmdline
, -1, cmdlinew
, MAX_PATH
*2);
331 InstallHinfSectionW(NULL
, NULL
, cmdlinew
, 0);
334 static void ok_registry(BOOL expectsuccess
)
338 /* Functional tests for success of install and clean up */
339 ret
= RegDeleteKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest");
340 ok((expectsuccess
&& ret
== ERROR_SUCCESS
) ||
341 (!expectsuccess
&& ret
== ERROR_FILE_NOT_FOUND
),
342 "Expected registry key Software\\Wine\\setupapitest to %s, RegDeleteKey returned %d\n",
343 expectsuccess
? "exist" : "not exist",
347 /* Test command line processing */
348 static void test_cmdline(void)
350 static const char infwithspaces
[] = "test file.inf";
351 char path
[MAX_PATH
+ 16];
354 create_inf_file(inffile
, cmdline_inf
);
355 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
356 run_cmdline("DefaultInstall", 128, path
);
358 ret
= DeleteFileA(inffile
);
359 ok(ret
, "Expected source inf to exist, last error was %d\n", GetLastError());
361 /* Test handling of spaces in path, unquoted and quoted */
362 create_inf_file(infwithspaces
, cmdline_inf
);
364 sprintf(path
, "%s\\%s", CURR_DIR
, infwithspaces
);
365 run_cmdline("DefaultInstall", 128, path
);
368 sprintf(path
, "\"%s\\%s\"", CURR_DIR
, infwithspaces
);
369 run_cmdline("DefaultInstall", 128, path
);
372 ret
= DeleteFileA(infwithspaces
);
373 ok(ret
, "Expected source inf to exist, last error was %d\n", GetLastError());
376 static const char *cmdline_inf_reg
= "[Version]\n"
377 "Signature=\"$Chicago$\"\n"
379 "DelReg=Del.Settings\n"
381 "HKCU,Software\\Wine\\setupapitest\n";
383 static void test_registry(void)
387 char path
[MAX_PATH
+ 9];
390 /* First create a registry structure we would like to be deleted */
391 ok(!RegCreateKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest\\setupapitest", &key
),
392 "Expected RegCreateKeyA to succeed\n");
394 /* Doublecheck if the registry key is present */
395 ok(!RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest\\setupapitest", &key
),
396 "Expected registry key to exist\n");
398 create_inf_file(inffile
, cmdline_inf_reg
);
399 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
400 run_cmdline("DefaultInstall", 128, path
);
402 /* Check if the registry key is recursively deleted */
403 res
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest", &key
);
404 ok(res
== ERROR_FILE_NOT_FOUND
, "Didn't expect the registry key to exist\n");
406 if (res
== ERROR_SUCCESS
)
408 RegDeleteKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest\\setupapitest");
409 RegDeleteKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest");
411 ret
= DeleteFileA(inffile
);
412 ok(ret
, "Expected source inf to exist, last error was %d\n", GetLastError());
415 static void test_install_from(void)
417 char path
[MAX_PATH
+ 9];
423 /* First create a registry structure we would like to be deleted */
424 ok(!RegCreateKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest\\setupapitest", &key
),
425 "Expected RegCreateKeyA to succeed\n");
427 /* Doublecheck if the registry key is present */
428 ok(!RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest\\setupapitest", &key
),
429 "Expected registry key to exist\n");
431 create_inf_file(inffile
, cmdline_inf_reg
);
432 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
433 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
434 SetLastError(0xdeadbeef);
435 ret
= SetupInstallFromInfSectionA(NULL
, infhandle
, "DefaultInstall", SPINST_REGISTRY
, key
,
436 "A:\\", 0, NULL
, NULL
, NULL
, NULL
);
437 ok(ret
, "Unexpected failure\n");
438 ok(GetLastError() == ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
440 /* Check if the registry key is recursively deleted */
441 res
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest", &key
);
442 ok(res
== ERROR_FILE_NOT_FOUND
, "Didn't expect the registry key to exist\n");
444 if (res
== ERROR_SUCCESS
)
446 RegDeleteKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest\\setupapitest");
447 RegDeleteKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest");
450 SetupCloseInfFile(infhandle
);
451 DeleteFileA(inffile
);
454 static void test_install_svc_from(void)
457 char path
[MAX_PATH
+ 9];
460 SC_HANDLE scm_handle
, svc_handle
;
462 /* Basic inf file to satisfy SetupOpenInfFileA */
463 strcpy(inf
, "[Version]\nSignature=\"$Chicago$\"\n");
464 create_inf_file(inffile
, inf
);
465 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
466 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
468 /* Nothing but the Version section */
469 SetLastError(0xdeadbeef);
470 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "Winetest.Services", 0);
471 ok(!ret
, "Expected failure\n");
472 ok(GetLastError() == ERROR_SECTION_NOT_FOUND
,
473 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
474 SetupCloseInfFile(infhandle
);
475 DeleteFileA(inffile
);
477 /* Add the section */
478 strcat(inf
, "[Winetest.Services]\n");
479 create_inf_file(inffile
, inf
);
480 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
481 SetLastError(0xdeadbeef);
482 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "Winetest.Services", 0);
483 ok(!ret
, "Expected failure\n");
484 ok(GetLastError() == ERROR_SECTION_NOT_FOUND
,
485 "Expected ERROR_SECTION_NOT_FOUND, got %08x\n", GetLastError());
486 SetupCloseInfFile(infhandle
);
487 DeleteFileA(inffile
);
489 /* Add a reference */
490 strcat(inf
, "AddService=Winetest,,Winetest.Service\n");
491 create_inf_file(inffile
, inf
);
492 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
493 SetLastError(0xdeadbeef);
494 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "Winetest.Services", 0);
495 ok(!ret
, "Expected failure\n");
496 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT
,
497 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
498 SetupCloseInfFile(infhandle
);
499 DeleteFileA(inffile
);
501 /* Add the section */
502 strcat(inf
, "[Winetest.Service]\n");
503 create_inf_file(inffile
, inf
);
504 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
505 SetLastError(0xdeadbeef);
506 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "Winetest.Services", 0);
507 ok(!ret
, "Expected failure\n");
508 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT
,
509 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
510 SetupCloseInfFile(infhandle
);
511 DeleteFileA(inffile
);
513 /* Just the ServiceBinary */
514 strcat(inf
, "ServiceBinary=%12%\\winetest.sys\n");
515 create_inf_file(inffile
, inf
);
516 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
517 SetLastError(0xdeadbeef);
518 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "Winetest.Services", 0);
519 ok(!ret
, "Expected failure\n");
520 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT
,
521 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
522 SetupCloseInfFile(infhandle
);
523 DeleteFileA(inffile
);
525 /* Add the ServiceType */
526 strcat(inf
, "ServiceType=1\n");
527 create_inf_file(inffile
, inf
);
528 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
529 SetLastError(0xdeadbeef);
530 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "Winetest.Services", 0);
531 ok(!ret
, "Expected failure\n");
532 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT
,
533 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
534 SetupCloseInfFile(infhandle
);
535 DeleteFileA(inffile
);
537 /* Add the StartType */
538 strcat(inf
, "StartType=4\n");
539 create_inf_file(inffile
, inf
);
540 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
541 SetLastError(0xdeadbeef);
542 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "Winetest.Services", 0);
543 ok(!ret
, "Expected failure\n");
544 ok(GetLastError() == ERROR_BAD_SERVICE_INSTALLSECT
,
545 "Expected ERROR_BAD_SERVICE_INSTALLSECT, got %08x\n", GetLastError());
546 SetupCloseInfFile(infhandle
);
547 DeleteFileA(inffile
);
549 /* This should be it, the minimal entries to install a service */
550 strcat(inf
, "ErrorControl=1");
551 create_inf_file(inffile
, inf
);
552 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
553 SetLastError(0xdeadbeef);
554 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "Winetest.Services", 0);
555 if (!ret
&& GetLastError() == ERROR_ACCESS_DENIED
)
557 skip("Not enough rights to install the service\n");
558 SetupCloseInfFile(infhandle
);
559 DeleteFileA(inffile
);
562 ok(ret
, "Expected success\n");
563 ok(GetLastError() == ERROR_SUCCESS
,
564 "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
565 SetupCloseInfFile(infhandle
);
566 DeleteFileA(inffile
);
568 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
570 /* Open the service to see if it's really there */
571 svc_handle
= OpenServiceA(scm_handle
, "Winetest", DELETE
);
572 ok(svc_handle
!= NULL
, "Service was not created\n");
574 SetLastError(0xdeadbeef);
575 ret
= DeleteService(svc_handle
);
576 ok(ret
, "Service could not be deleted : %d\n", GetLastError());
578 CloseServiceHandle(svc_handle
);
579 CloseServiceHandle(scm_handle
);
581 strcpy(inf
, "[Version]\nSignature=\"$Chicago$\"\n");
582 strcat(inf
, "[XSP.InstallPerVer]\n");
583 strcat(inf
, "AddReg=AspEventlogMsg.Reg,Perf.Reg,AspVersions.Reg,FreeADO.Reg,IndexServer.Reg\n");
584 create_inf_file(inffile
, inf
);
585 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
586 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
588 SetLastError(0xdeadbeef);
589 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "XSP.InstallPerVer", 0);
590 ok(ret
, "Expected success\n");
591 ok(GetLastError() == ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
592 SetupCloseInfFile(infhandle
);
593 DeleteFileA(inffile
);
595 strcpy(inf
, "[Version]\nSignature=\"$Chicago$\"\n");
596 strcat(inf
, "[Winetest.Services]\n");
597 strcat(inf
, "AddService=,2\n");
598 create_inf_file(inffile
, inf
);
599 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
600 infhandle
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
602 SetLastError(0xdeadbeef);
603 ret
= SetupInstallServicesFromInfSectionA(infhandle
, "Winetest.Services", 0);
604 ok(ret
, "Expected success\n");
605 ok(GetLastError() == ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %08x\n", GetLastError());
606 SetupCloseInfFile(infhandle
);
607 DeleteFileA(inffile
);
609 /* TODO: Test the Flags */
612 static void test_driver_install(void)
615 SC_HANDLE scm_handle
, svc_handle
;
617 char path
[MAX_PATH
+ 9], windir
[MAX_PATH
], driver
[MAX_PATH
];
619 /* Minimal stuff needed */
620 static const char *inf
=
622 "Signature=\"$Chicago$\"\n"
623 "[DestinationDirs]\n"
624 "Winetest.DriverFiles=12\n"
626 "CopyFiles=Winetest.DriverFiles\n"
627 "[DefaultInstall.Services]\n"
628 "AddService=Winetest,,Winetest.Service\n"
629 "[Winetest.Service]\n"
630 "ServiceBinary=%12%\\winetest.sys\n"
634 "[Winetest.DriverFiles]\n"
637 /* Bail out if we don't have enough rights */
638 SetLastError(0xdeadbeef);
639 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
640 if (!scm_handle
&& (GetLastError() == ERROR_ACCESS_DENIED
))
642 skip("Not enough rights to install the service\n");
645 CloseServiceHandle(scm_handle
);
647 /* Place where we expect the driver to be installed */
648 GetWindowsDirectoryA(windir
, MAX_PATH
);
649 lstrcpyA(driver
, windir
);
650 lstrcatA(driver
, "\\system32\\drivers\\winetest.sys");
652 /* Create a dummy driver file */
653 handle
= CreateFileA("winetest.sys", GENERIC_WRITE
, 0, NULL
,
654 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
657 create_inf_file(inffile
, inf
);
658 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
659 run_cmdline("DefaultInstall", 128, path
);
661 /* Driver should have been installed */
662 attrs
= GetFileAttributesA(driver
);
663 ok(attrs
!= INVALID_FILE_ATTRIBUTES
, "Expected driver to exist\n");
665 scm_handle
= OpenSCManagerA(NULL
, NULL
, GENERIC_ALL
);
667 /* Open the service to see if it's really there */
668 svc_handle
= OpenServiceA(scm_handle
, "Winetest", DELETE
);
669 ok(svc_handle
!= NULL
, "Service was not created\n");
671 SetLastError(0xdeadbeef);
672 ret
= DeleteService(svc_handle
);
673 ok(ret
, "Service could not be deleted : %d\n", GetLastError());
675 CloseServiceHandle(svc_handle
);
676 CloseServiceHandle(scm_handle
);
679 DeleteFileA(inffile
);
680 DeleteFileA("winetest.sys");
684 static void test_profile_items(void)
686 char path
[MAX_PATH
+ 22], commonprogs
[MAX_PATH
];
688 static const char *inf
=
690 "Signature=\"$Chicago$\"\n"
692 "ProfileItems=TestItem,TestItem2,TestGroup\n"
695 "CmdLine=11,,notepad.exe\n"
698 "CmdLine=11,,notepad.exe\n"
704 if (S_OK
!= SHGetFolderPathA(NULL
, CSIDL_COMMON_PROGRAMS
, NULL
, SHGFP_TYPE_CURRENT
, commonprogs
))
706 skip("No common program files directory exists\n");
710 sprintf(path
, "%s\\TestDir", commonprogs
);
711 if (!CreateDirectoryA(path
, NULL
) && GetLastError() == ERROR_ACCESS_DENIED
)
713 skip("need admin rights\n");
716 RemoveDirectoryA(path
);
718 create_inf_file(inffile
, inf
);
719 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
720 run_cmdline("DefaultInstall", 128, path
);
722 sprintf(path
, "%s\\TestItem.lnk", commonprogs
);
723 sprintf(path
, "%s\\TestDir", commonprogs
);
724 ok(INVALID_FILE_ATTRIBUTES
!= GetFileAttributesA(path
), "directory not created\n");
725 sprintf(path
, "%s\\TestDir\\TestItem2.lnk", commonprogs
);
726 ok(INVALID_FILE_ATTRIBUTES
!= GetFileAttributesA(path
), "link not created\n");
727 sprintf(path
, "%s\\TestGroup", commonprogs
);
728 ok(INVALID_FILE_ATTRIBUTES
!= GetFileAttributesA(path
), "group not created\n");
730 sprintf(path
, "%s\\TestItem.lnk", commonprogs
);
732 sprintf(path
, "%s\\TestDir\\TestItem2.lnk", commonprogs
);
734 sprintf(path
, "%s\\TestItem2.lnk", commonprogs
);
736 sprintf(path
, "%s\\TestDir", commonprogs
);
737 RemoveDirectoryA(path
);
738 sprintf(path
, "%s\\TestGroup", commonprogs
);
739 RemoveDirectoryA(path
);
742 DeleteFileA(inffile
);
745 static void test_inffilelistA(void)
747 static const char inffile2
[] = "test2.inf";
748 static const char *inf
=
750 "Signature=\"$Chicago$\"";
752 char buffer
[MAX_PATH
] = { 0 };
753 char dir
[MAX_PATH
], *p
;
754 DWORD expected
, outsize
;
757 /* create a private directory, the temp directory may contain some
758 * inf files left over from old installations
760 if (!GetTempFileNameA(CURR_DIR
, "inftest", 1, dir
))
762 win_skip("GetTempFileNameA failed with error %d\n", GetLastError());
765 if (!CreateDirectoryA(dir
, NULL
))
767 win_skip("CreateDirectoryA(%s) failed with error %d\n", dir
, GetLastError());
770 if (!SetCurrentDirectoryA(dir
))
772 win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError());
773 RemoveDirectoryA(dir
);
777 create_inf_file(inffile
, inf
);
778 create_inf_file(inffile2
, inf
);
782 expected
= 3 + strlen(inffile
) + strlen(inffile2
);
783 ret
= SetupGetInfFileListA(dir
, INF_STYLE_OLDNT
| INF_STYLE_WIN4
, buffer
,
785 ok(ret
, "expected SetupGetInfFileListA to succeed!\n");
786 ok(expected
== outsize
, "expected required buffersize to be %d, got %d\n",
788 for(p
= buffer
; lstrlenA(p
) && (outsize
> (p
- buffer
)); p
+=lstrlenA(p
) + 1)
789 ok(!lstrcmpA(p
,inffile2
) || !lstrcmpA(p
,inffile
),
790 "unexpected filename %s\n",p
);
792 DeleteFileA(inffile
);
793 DeleteFileA(inffile2
);
794 SetCurrentDirectoryA(CURR_DIR
);
795 RemoveDirectoryA(dir
);
798 static void test_inffilelist(void)
800 static const char inffile2
[] = "test2.inf";
801 static const WCHAR inffile2W
[] = {'t','e','s','t','2','.','i','n','f',0};
802 static const char invalid_inf
[] = "invalid.inf";
803 static const WCHAR invalid_infW
[] = {'i','n','v','a','l','i','d','.','i','n','f',0};
804 static const char *inf
=
806 "Signature=\"$Chicago$\"";
807 static const char *inf2
=
809 "Signature=\"$CHICAGO$\"";
810 static const char *infNT
=
812 "Signature=\"$WINDOWS NT$\"";
816 WCHAR dir
[MAX_PATH
] = { 0 };
817 WCHAR buffer
[MAX_PATH
] = { 0 };
818 DWORD expected
, outsize
;
821 /* NULL means %windir%\\inf
822 * get the value as reference
825 SetLastError(0xdeadbeef);
826 ret
= SetupGetInfFileListW(NULL
, INF_STYLE_WIN4
, NULL
, 0, &expected
);
827 ok(ret
, "expected SetupGetInfFileListW to succeed! Error: %d\n", GetLastError());
828 ok(expected
> 0, "expected required buffersize to be at least 1\n");
830 /* check if an empty string doesn't behaves like NULL */
832 SetLastError(0xdeadbeef);
833 ret
= SetupGetInfFileListW(dir
, INF_STYLE_WIN4
, NULL
, 0, &outsize
);
834 ok(!ret
, "expected SetupGetInfFileListW to fail!\n");
836 /* create a private directory, the temp directory may contain some
837 * inf files left over from old installations
839 if (!GetTempFileNameA(CURR_DIR
, "inftest", 1, dirA
))
841 win_skip("GetTempFileNameA failed with error %d\n", GetLastError());
844 if (!CreateDirectoryA(dirA
, NULL
))
846 win_skip("CreateDirectoryA(%s) failed with error %d\n", dirA
, GetLastError());
849 if (!SetCurrentDirectoryA(dirA
))
851 win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError());
852 RemoveDirectoryA(dirA
);
856 MultiByteToWideChar(CP_ACP
, 0, dirA
, -1, dir
, MAX_PATH
);
857 /* check a not existing directory
859 ptr
= dir
+ lstrlenW(dir
);
860 MultiByteToWideChar(CP_ACP
, 0, "\\not_existent", -1, ptr
, MAX_PATH
- lstrlenW(dir
));
861 outsize
= 0xffffffff;
862 SetLastError(0xdeadbeef);
863 ret
= SetupGetInfFileListW(dir
, INF_STYLE_WIN4
, NULL
, 0, &outsize
);
864 ok(ret
, "expected SetupGetInfFileListW to succeed!\n");
865 ok(outsize
== 1, "expected required buffersize to be 1, got %d\n", outsize
);
866 ok(ERROR_PATH_NOT_FOUND
== GetLastError(),
867 "expected error ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
869 create_inf_file(inffile
, inf
);
870 create_inf_file(inffile2
, inf
);
871 create_inf_file(invalid_inf
, "This content does not match the inf file format");
873 /* pass a filename instead of a directory
876 MultiByteToWideChar(CP_ACP
, 0, invalid_inf
, -1, ptr
+1, MAX_PATH
- lstrlenW(dir
));
877 outsize
= 0xffffffff;
878 SetLastError(0xdeadbeef);
879 ret
= SetupGetInfFileListW(dir
, INF_STYLE_WIN4
, NULL
, 0, &outsize
);
880 ok(!ret
, "expected SetupGetInfFileListW to fail!\n");
881 ok(ERROR_DIRECTORY
== GetLastError(),
882 "expected error ERROR_DIRECTORY, got %d\n", GetLastError());
884 /* make the filename look like directory
886 dir
[1 + lstrlenW(dir
)] = 0;
887 dir
[lstrlenW(dir
)] = '\\';
888 SetLastError(0xdeadbeef);
889 ret
= SetupGetInfFileListW(dir
, INF_STYLE_WIN4
, NULL
, 0, &outsize
);
890 ok(!ret
, "expected SetupGetInfFileListW to fail!\n");
891 ok(ERROR_DIRECTORY
== GetLastError(),
892 "expected error ERROR_DIRECTORY, got %d\n", GetLastError());
894 /* now check the buffer contents of a valid call
897 expected
= 3 + strlen(inffile
) + strlen(inffile2
);
898 ret
= SetupGetInfFileListW(dir
, INF_STYLE_WIN4
, buffer
, MAX_PATH
, &outsize
);
899 ok(ret
, "expected SetupGetInfFileListW to succeed!\n");
900 ok(expected
== outsize
, "expected required buffersize to be %d, got %d\n",
902 for(p
= buffer
; lstrlenW(p
) && (outsize
> (p
- buffer
)); p
+=lstrlenW(p
) + 1)
903 ok(!lstrcmpW(p
,inffile2W
) || !lstrcmpW(p
,inffileW
),
904 "unexpected filename %s\n",wine_dbgstr_w(p
));
908 create_inf_file(inffile2
, inf2
);
909 ret
= SetupGetInfFileListW(dir
, INF_STYLE_WIN4
, buffer
, MAX_PATH
, &outsize
);
910 ok(ret
, "expected SetupGetInfFileListW to succeed!\n");
911 ok(expected
== outsize
, "expected required buffersize to be %d, got %d\n",
913 for(p
= buffer
; lstrlenW(p
) && (outsize
> (p
- buffer
)); p
+=lstrlenW(p
) + 1)
914 ok(!lstrcmpW(p
,inffile2W
) || !lstrcmpW(p
,inffileW
),
915 "unexpected filename %s\n",wine_dbgstr_w(p
));
917 /* signature Windows NT is also inf style win4
919 create_inf_file(inffile2
, infNT
);
920 expected
= 3 + strlen(inffile
) + strlen(inffile2
);
921 ret
= SetupGetInfFileListW(dir
, INF_STYLE_WIN4
, buffer
, MAX_PATH
, &outsize
);
922 ok(ret
, "expected SetupGetInfFileListW to succeed!\n");
923 ok(expected
== outsize
, "expected required buffersize to be %d, got %d\n",
925 for(p
= buffer
; lstrlenW(p
) && (outsize
> (p
- buffer
)); p
+=lstrlenW(p
) + 1)
926 ok(!lstrcmpW(p
,inffile2W
) || !lstrcmpW(p
,inffileW
),
927 "unexpected filename %s\n",wine_dbgstr_w(p
));
931 expected
= 2 + strlen(invalid_inf
);
932 ret
= SetupGetInfFileListW(dir
, INF_STYLE_OLDNT
, buffer
, MAX_PATH
, &outsize
);
933 ok(ret
, "expected SetupGetInfFileListW to succeed!\n");
934 ok(expected
== outsize
, "expected required buffersize to be %d, got %d\n",
936 for(p
= buffer
; lstrlenW(p
) && (outsize
> (p
- buffer
)); p
+=lstrlenW(p
) + 1)
937 ok(!lstrcmpW(p
,invalid_infW
), "unexpected filename %s\n",wine_dbgstr_w(p
));
941 expected
= 4 + strlen(inffile
) + strlen(inffile2
) + strlen(invalid_inf
);
942 ret
= SetupGetInfFileListW(dir
, INF_STYLE_OLDNT
| INF_STYLE_WIN4
, buffer
,
944 ok(ret
, "expected SetupGetInfFileListW to succeed!\n");
945 ok(expected
== outsize
, "expected required buffersize to be %d, got %d\n",
947 for(p
= buffer
; lstrlenW(p
) && (outsize
> (p
- buffer
)); p
+=lstrlenW(p
) + 1)
948 ok(!lstrcmpW(p
,inffile2W
) || !lstrcmpW(p
,inffileW
) || !lstrcmpW(p
,invalid_infW
),
949 "unexpected filename %s\n",wine_dbgstr_w(p
));
951 DeleteFileA(inffile
);
952 DeleteFileA(inffile2
);
953 DeleteFileA(invalid_inf
);
954 SetCurrentDirectoryA(CURR_DIR
);
955 RemoveDirectoryA(dirA
);
958 static const char dirid_inf
[] = "[Version]\n"
959 "Signature=\"$Chicago$\"\n"
961 "AddReg=Add.Settings\n"
963 "HKCU,Software\\Wine\\setupapitest,dirid,,%%%i%%\n";
965 static void check_dirid(int dirid
, LPCSTR expected
)
967 char buffer
[sizeof(dirid_inf
)+11];
968 char path
[MAX_PATH
+ 9], actual
[MAX_PATH
];
973 sprintf(buffer
, dirid_inf
, dirid
);
975 create_inf_file(inffile
, buffer
);
977 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
978 run_cmdline("DefaultInstall", 128, path
);
980 size
= sizeof(actual
);
982 ret
= RegOpenKeyA(HKEY_CURRENT_USER
, "Software\\Wine\\setupapitest", &key
);
983 if (ret
== ERROR_SUCCESS
)
985 ret
= RegQueryValueExA(key
, "dirid", NULL
, &type
, (BYTE
*)&actual
, &size
);
988 ret
= ERROR_FILE_NOT_FOUND
;
991 ok(ret
== ERROR_SUCCESS
, "Failed getting value for dirid %i, err=%d\n", dirid
, ret
);
992 ok(!strcmp(actual
, expected
), "Expected path for dirid %i was \"%s\", got \"%s\"\n", dirid
, expected
, actual
);
995 ret
= DeleteFileA(inffile
);
996 ok(ret
, "Expected source inf to exist, last error was %d\n", GetLastError());
999 /* Test dirid values */
1000 static void test_dirid(void)
1002 char expected
[MAX_PATH
];
1004 check_dirid(DIRID_NULL
, "");
1006 GetWindowsDirectoryA(expected
, MAX_PATH
);
1007 check_dirid(DIRID_WINDOWS
, expected
);
1009 GetSystemDirectoryA(expected
, MAX_PATH
);
1010 check_dirid(DIRID_SYSTEM
, expected
);
1012 strcat(expected
, "\\unknown");
1013 check_dirid(40, expected
);
1016 static void test_install_files_queue(void)
1018 static const char inf_data
[] = "[Version]\n"
1019 "Signature=\"$Chicago$\"\n"
1020 "[DefaultInstall]\n"
1021 "CopyFiles=files_section\n"
1031 "[SourceDisksNames]\n"
1034 "3=treis,treis.cab\n"
1035 "4=tessares,tessares.cab,,alpha\n"
1036 "[SourceDisksFiles]\n"
1044 "eight.txt=4,beta\n"
1045 "[DestinationDirs]\n"
1046 "files_section=40000,dst\n";
1048 char path
[MAX_PATH
+ 9];
1054 create_inf_file(inffile
, inf_data
);
1056 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
1057 hinf
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
1058 ok(hinf
!= INVALID_HANDLE_VALUE
, "Failed to open INF file, error %#x.\n", GetLastError());
1060 ret
= CreateDirectoryA("src", NULL
);
1061 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1062 ret
= CreateDirectoryA("src/alpha", NULL
);
1063 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1064 ret
= CreateDirectoryA("src/alpha/beta", NULL
);
1065 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1066 ret
= CreateDirectoryA("src/beta", NULL
);
1067 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1068 ret
= SetupSetDirectoryIdA(hinf
, 40000, CURR_DIR
);
1069 ok(ret
, "Failed to set directory ID, error %u.\n", GetLastError());
1071 create_file("src/one.txt");
1072 create_file("src/beta/two.txt");
1073 create_file("src/alpha/three.txt");
1074 create_file("src/alpha/beta/four.txt");
1075 create_cab_file("src/treis.cab", "src\\beta\\five.txt\0six.txt\0");
1076 create_cab_file("src/alpha/tessares.cab", "seven.txt\0eight.txt\0");
1078 queue
= SetupOpenFileQueue();
1079 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1081 context
= SetupInitDefaultQueueCallbackEx(NULL
, INVALID_HANDLE_VALUE
, 0, 0, 0);
1082 ok(!!context
, "Failed to create callback context, error %#x.\n", GetLastError());
1084 ret
= SetupInstallFilesFromInfSectionA(hinf
, NULL
, queue
, "DefaultInstall", "src", 0);
1085 ok(ret
, "Failed to install files, error %#x.\n", GetLastError());
1087 ok(file_exists("src/one.txt"), "Source file should exist.\n");
1088 ok(!file_exists("dst/one.txt"), "Destination file should not exist.\n");
1090 ret
= SetupCommitFileQueueA(NULL
, queue
, SetupDefaultQueueCallbackA
, context
);
1091 ok(ret
, "Failed to commit queue, error %#x.\n", GetLastError());
1093 ok(file_exists("src/one.txt"), "Source file should exist.\n");
1094 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1095 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1096 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1097 ok(delete_file("dst/four.txt"), "Destination file should exist.\n");
1098 ok(delete_file("dst/five.txt"), "Destination file should exist.\n");
1099 ok(delete_file("dst/six.txt"), "Destination file should exist.\n");
1100 ok(delete_file("dst/seven.txt"), "Destination file should exist.\n");
1101 ok(delete_file("dst/eight.txt"), "Destination file should exist.\n");
1103 SetupTermDefaultQueueCallback(context
);
1104 ret
= SetupCloseFileQueue(queue
);
1105 ok(ret
, "Failed to close queue, error %#x.\n", GetLastError());
1107 SetupCloseInfFile(hinf
);
1108 delete_file("src/one.txt");
1109 delete_file("src/beta/two.txt");
1110 delete_file("src/alpha/three.txt");
1111 delete_file("src/alpha/beta/four.txt");
1112 delete_file("src/treis.cab");
1113 delete_file("src/alpha/tessares.cab");
1114 delete_file("src/alpha/beta/");
1115 delete_file("src/alpha/");
1116 delete_file("src/beta/");
1117 delete_file("src/");
1118 delete_file("dst/");
1119 ret
= DeleteFileA(inffile
);
1120 ok(ret
, "Failed to delete INF file, error %u.\n", GetLastError());
1123 static unsigned int got_need_media
, got_copy_error
;
1124 static unsigned int testmode
;
1126 static UINT WINAPI
need_media_cb(void *context
, UINT message
, UINT_PTR param1
, UINT_PTR param2
)
1128 if (winetest_debug
> 1) trace("%p, %#x, %#lx, %#lx\n", context
, message
, param1
, param2
);
1130 if (message
== SPFILENOTIFY_NEEDMEDIA
)
1132 const SOURCE_MEDIA_A
*media
= (const SOURCE_MEDIA_A
*)param1
;
1133 char *path
= (char *)param2
;
1136 /* The default callback will fill out SourcePath, but as long as DOIT
1137 * is returned, it's ignored. */
1138 ok(!path
[0], "Test %u: got path '%s'.\n", testmode
, path
);
1139 ret
= SetupDefaultQueueCallbackA(context
, message
, param1
, param2
);
1140 ok(!strcmp(path
, media
->SourcePath
), "Test %u: got path '%s'.\n", testmode
, path
);
1141 ok(ret
== FILEOP_DOIT
, "Got unexpected return value %u.\n", ret
);
1145 ok(media
->Flags
== SP_COPY_WARNIFSKIP
, "Got Flags %#x.\n", media
->Flags
);
1147 ok(!media
->Flags
, "Got Flags %#x for test %u.\n", media
->Flags
, testmode
);
1152 ok(!media
->Tagfile
, "Got Tagfile '%s'.\n", media
->Tagfile
);
1153 ok(!strcmp(media
->Description
, "File One"), "Got Description '%s'.\n", media
->Description
);
1154 ok(!strcmp(media
->SourcePath
, "src"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1155 ok(!strcmp(media
->SourceFile
, "one.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1158 ok(!media
->Tagfile
, "Got Tagfile '%s'.\n", media
->Tagfile
);
1159 ok(!media
->Description
, "Got Description '%s'.\n", media
->Description
);
1160 ok(!strcmp(media
->SourcePath
, "src\\beta"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1161 ok(!strcmp(media
->SourceFile
, "two.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1164 ok(!strcmp(media
->Tagfile
, "faketag"), "Got Tagfile '%s'.\n", media
->Tagfile
);
1165 ok(!strcmp(media
->Description
, "desc"), "Got Description '%s'.\n", media
->Description
);
1166 ok(!strcmp(media
->SourcePath
, "src\\beta"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1167 ok(!strcmp(media
->SourceFile
, "two.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1170 ok(!media
->Tagfile
, "Got Tagfile '%s'.\n", media
->Tagfile
);
1171 ok(!strcmp(media
->Description
, "heis"), "Got Description '%s'.\n", media
->Description
);
1172 ok(!strcmp(media
->SourcePath
, "src"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1173 ok(!strcmp(media
->SourceFile
, "one.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1176 ok(!media
->Tagfile
, "Got Tagfile '%s'.\n", media
->Tagfile
);
1177 ok(!strcmp(media
->Description
, "heis"), "Got Description '%s'.\n", media
->Description
);
1178 ok(!strcmp(media
->SourcePath
, "src\\beta"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1179 ok(!strcmp(media
->SourceFile
, "two.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1182 ok(!media
->Tagfile
, "Got Tagfile '%s'.\n", media
->Tagfile
);
1183 ok(!strcmp(media
->Description
, "duo"), "Got Description '%s'.\n", media
->Description
);
1184 ok(!strcmp(media
->SourcePath
, "src\\alpha"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1185 ok(!strcmp(media
->SourceFile
, "three.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1188 ok(!strcmp(media
->SourcePath
, "src"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1189 ok(!strcmp(media
->SourceFile
, "one.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1193 ok(!strcmp(media
->SourcePath
, "src/alpha"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1194 ok(!strcmp(media
->SourceFile
, "three.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1197 ok(!strcmp(media
->SourcePath
, "src"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1198 ok(!strcmp(media
->SourceFile
, "one.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1202 ok(!strcmp(media
->SourcePath
, "src\\alpha"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1203 ok(!strcmp(media
->SourceFile
, "three.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1206 ok(!strcmp(media
->Description
, "desc1"), "Got description '%s'.\n", media
->Description
);
1207 ok(!strcmp(media
->SourcePath
, "src"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1208 ok(!strcmp(media
->SourceFile
, "one.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1212 ok(!media
->Description
, "Got description '%s'.\n", media
->Description
);
1213 ok(!strcmp(media
->SourcePath
, "src\\beta"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1214 ok(!strcmp(media
->SourceFile
, "two.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1217 ok(!strcmp(media
->Description
, "desc1"), "Got description '%s'.\n", media
->Description
);
1218 ok(!strcmp(media
->Tagfile
, "faketag"), "Got Tagfile '%s'.\n", media
->Tagfile
);
1219 ok(!strcmp(media
->SourcePath
, "src"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1220 ok(!strcmp(media
->SourceFile
, "one.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1224 ok(!strcmp(media
->Description
, "desc1"), "Got description '%s'.\n", media
->Description
);
1225 ok(!strcmp(media
->Tagfile
, "faketag2"), "Got Tagfile '%s'.\n", media
->Tagfile
);
1226 ok(!strcmp(media
->SourcePath
, "src\\beta"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1227 ok(!strcmp(media
->SourceFile
, "two.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1230 ok(!strcmp(media
->Description
, "desc"), "Got description '%s'.\n", media
->Description
);
1231 ok(!strcmp(media
->Tagfile
, "treis.cab"), "Got Tagfile '%s'.\n", media
->Tagfile
);
1232 ok(!strcmp(media
->SourcePath
, "src"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1233 ok(!strcmp(media
->SourceFile
, "four.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1236 ok(!strcmp(media
->Description
, "desc"), "Got description '%s'.\n", media
->Description
);
1237 ok(!strcmp(media
->Tagfile
, "tessares.cab"), "Got Tagfile '%s'.\n", media
->Tagfile
);
1238 ok(!strcmp(media
->SourcePath
, "src\\alpha"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1239 ok(!strcmp(media
->SourceFile
, "seven.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1242 ok(!media
->Description
, "Got description '%s'.\n", media
->Description
);
1243 ok(!strcmp(media
->SourcePath
, "src/alpha"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1244 ok(!strcmp(media
->SourceFile
, "six.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1252 else if (message
== SPFILENOTIFY_COPYERROR
)
1254 const FILEPATHS_A
*paths
= (const FILEPATHS_A
*)param1
;
1255 ok(0, "Got unexpected copy error %s -> %s.\n", paths
->Source
, paths
->Target
);
1258 return SetupDefaultQueueCallbackA(context
, message
, param1
, param2
);
1261 static UINT WINAPI
need_media_newpath_cb(void *context
, UINT message
, UINT_PTR param1
, UINT_PTR param2
)
1263 if (winetest_debug
> 1) trace("%p, %#x, %#lx, %#lx\n", context
, message
, param1
, param2
);
1265 if (message
== SPFILENOTIFY_NEEDMEDIA
)
1267 const SOURCE_MEDIA_A
*media
= (const SOURCE_MEDIA_A
*)param1
;
1268 char *path
= (char *)param2
;
1273 strcpy(path
, "src\\alpha");
1274 else if (testmode
== 2)
1276 if (got_need_media
== 1)
1277 strcpy(path
, "src\\alpha");
1280 ok(!strcmp(media
->SourcePath
, "src\\alpha"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1281 strcpy(path
, "src");
1284 else if (testmode
== 5)
1286 if (got_need_media
== 1)
1288 ok(!strcmp(media
->SourcePath
, "fake"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1289 ok(!strcmp(media
->SourceFile
, "one.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1294 ok(!strcmp(media
->SourcePath
, "fake\\alpha"), "Got SourcePath '%s'.\n", media
->SourcePath
);
1295 ok(!strcmp(media
->SourceFile
, "three.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1296 strcpy(path
, "src\\alpha");
1299 else if (testmode
== 6)
1301 /* SourcePath is not really consistent here, but it's not supplied
1302 * from the INF file. Usually it's a drive root, but not always. */
1303 ok(!strcmp(media
->SourceFile
, "one.txt"), "Got SourceFile '%s'.\n", media
->SourceFile
);
1304 ok(!media
->Description
, "Got Description '%s'.\n", media
->Description
);
1305 ok(!media
->Tagfile
, "Got Tagfile '%s'.\n", media
->Tagfile
);
1306 strcpy(path
, "src");
1309 strcpy(path
, "src");
1311 return FILEOP_NEWPATH
;
1313 else if (message
== SPFILENOTIFY_COPYERROR
)
1315 char *path
= (char *)param2
;
1321 strcpy(path
, "src\\alpha");
1322 return FILEOP_NEWPATH
;
1324 else if (testmode
== 4)
1326 if (got_copy_error
== 1)
1327 strcpy(path
, "fake2");
1329 strcpy(path
, "src\\alpha");
1330 return FILEOP_NEWPATH
;
1336 return SetupDefaultQueueCallbackA(context
, message
, param1
, param2
);
1339 #define run_queue(a,b) run_queue_(__LINE__,a,b)
1340 static void run_queue_(unsigned int line
, HSPFILEQ queue
, PSP_FILE_CALLBACK_A cb
)
1342 void *context
= SetupInitDefaultQueueCallbackEx(NULL
, INVALID_HANDLE_VALUE
, 0, 0, 0);
1344 ok_(__FILE__
,line
)(!!context
, "Failed to create callback context, error %#x.\n", GetLastError());
1345 ret
= SetupCommitFileQueueA(NULL
, queue
, cb
, context
);
1346 ok_(__FILE__
,line
)(ret
, "Failed to commit queue, error %#x.\n", GetLastError());
1347 SetupTermDefaultQueueCallback(context
);
1348 ret
= SetupCloseFileQueue(queue
);
1349 ok_(__FILE__
,line
)(ret
, "Failed to close queue, error %#x.\n", GetLastError());
1352 static void test_install_file(void)
1354 static const char inf_data
[] = "[Version]\n"
1355 "Signature=\"$Chicago$\"\n"
1360 "[SourceDisksNames]\n"
1363 "[SourceDisksFiles]\n"
1367 "[DestinationDirs]\n"
1368 "DefaultDestDir=40000,dst\n";
1370 char path
[MAX_PATH
+ 9];
1375 create_inf_file(inffile
, inf_data
);
1377 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
1378 hinf
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
1379 ok(hinf
!= INVALID_HANDLE_VALUE
, "Failed to open INF file, error %#x.\n", GetLastError());
1381 ret
= CreateDirectoryA("src", NULL
);
1382 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1383 ret
= CreateDirectoryA("src/alpha", NULL
);
1384 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1385 ret
= CreateDirectoryA("src/beta", NULL
);
1386 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1387 ret
= CreateDirectoryA("dst", NULL
);
1388 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1389 create_file("src/one.txt");
1390 create_file("src/beta/two.txt");
1391 create_file("src/alpha/three.txt");
1393 ret
= SetupFindFirstLineA(hinf
, "section1", "one.txt", &infctx
);
1394 ok(ret
, "Failed to find line.\n");
1395 SetLastError(0xdeadbeef);
1396 ret
= SetupInstallFileA(hinf
, &infctx
, "one.txt", "src", "one.txt", 0, NULL
, NULL
);
1397 ok(ret
, "Expected success.\n");
1398 ok(GetLastError() == ERROR_SUCCESS
, "Got unexpected error %#x.\n", GetLastError());
1399 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1401 SetLastError(0xdeadbeef);
1402 ret
= SetupInstallFileA(hinf
, &infctx
, "one.txt", "src", "one.txt", SP_COPY_REPLACEONLY
, NULL
, NULL
);
1403 ok(!ret
, "Expected failure.\n");
1404 ok(GetLastError() == ERROR_SUCCESS
, "Got unexpected error %#x.\n", GetLastError());
1405 ok(!file_exists("dst/one.txt"), "Destination file should not exist.\n");
1407 ret
= SetupFindFirstLineA(hinf
, "section1", "two.txt", &infctx
);
1408 ok(ret
, "Failed to find line.\n");
1409 SetLastError(0xdeadbeef);
1410 ret
= SetupInstallFileA(hinf
, &infctx
, "two.txt", "src", "two.txt", 0, NULL
, NULL
);
1411 todo_wine
ok(ret
, "Expected success.\n");
1412 todo_wine
ok(GetLastError() == ERROR_SUCCESS
, "Got unexpected error %#x.\n", GetLastError());
1413 todo_wine
ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1415 ret
= SetupFindFirstLineA(hinf
, "section1", "three.txt", &infctx
);
1416 ok(ret
, "Failed to find line.\n");
1417 SetLastError(0xdeadbeef);
1418 ret
= SetupInstallFileA(hinf
, &infctx
, "three.txt", "src", "three.txt", 0, NULL
, NULL
);
1419 ok(!ret
, "Expected failure.\n");
1420 ok(GetLastError() == ERROR_FILE_NOT_FOUND
, "Got unexpected error %#x.\n", GetLastError());
1421 ok(!file_exists("dst/three.txt"), "Destination file should not exist.\n");
1423 ret
= SetupFindFirstLineA(hinf
, "section1", "three.txt", &infctx
);
1424 ok(ret
, "Failed to find line.\n");
1425 SetLastError(0xdeadbeef);
1426 ret
= SetupInstallFileA(hinf
, &infctx
, "three.txt", "src/alpha", "three.txt", 0, NULL
, NULL
);
1427 ok(ret
, "Expected success.\n");
1428 ok(GetLastError() == ERROR_SUCCESS
, "Got unexpected error %#x.\n", GetLastError());
1429 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1431 SetupCloseInfFile(hinf
);
1432 delete_file("src/one.txt");
1433 delete_file("src/beta/two.txt");
1434 delete_file("src/beta/");
1435 delete_file("src/alpha/three.txt");
1436 delete_file("src/alpha/");
1437 delete_file("src/");
1438 delete_file("dst/");
1439 ok(delete_file(inffile
), "Failed to delete INF file.\n");
1442 static void test_need_media(void)
1444 static const char inf_data
[] = "[Version]\n"
1445 "Signature=\"$Chicago$\"\n"
1456 "[install_section]\n"
1457 "CopyFiles=section1\n"
1458 "[SourceDisksNames]\n"
1461 "[SourceDisksFiles]\n"
1465 "[DestinationDirs]\n"
1466 "DefaultDestDir=40000,dst\n";
1468 SP_FILE_COPY_PARAMS_A copy_params
= {sizeof(copy_params
)};
1469 char path
[MAX_PATH
+ 9];
1474 create_inf_file(inffile
, inf_data
);
1476 sprintf(path
, "%s\\%s", CURR_DIR
, inffile
);
1477 hinf
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
1478 ok(hinf
!= INVALID_HANDLE_VALUE
, "Failed to open INF file, error %#x.\n", GetLastError());
1480 ret
= CreateDirectoryA("src", NULL
);
1481 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1482 ret
= CreateDirectoryA("src/alpha", NULL
);
1483 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1484 ret
= CreateDirectoryA("src/beta", NULL
);
1485 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1486 ret
= CreateDirectoryA("dst", NULL
);
1487 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1488 create_file("src/one.txt");
1489 create_file("src/beta/two.txt");
1490 create_file("src/alpha/three.txt");
1491 create_file("src/alpha/six.txt");
1492 create_cab_file("src/treis.cab", "four.txt\0five.txt\0");
1493 create_cab_file("src/alpha/tessares.cab", "seven.txt\0eight.txt\0");
1495 queue
= SetupOpenFileQueue();
1496 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1497 ret
= SetupQueueCopyA(queue
, "src", NULL
, "one.txt", "File One", NULL
, "dst", NULL
, SP_COPY_WARNIFSKIP
);
1498 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1499 run_queue(queue
, need_media_cb
);
1500 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1501 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1504 queue
= SetupOpenFileQueue();
1505 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1506 ret
= SetupQueueCopyA(queue
, "src", NULL
, "one.txt", "File One", NULL
,
1507 "dst", NULL
, SP_COPY_WARNIFSKIP
| SP_COPY_REPLACEONLY
);
1508 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1509 run_queue(queue
, need_media_cb
);
1510 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1511 ok(!file_exists("dst/one.txt"), "Destination file should exist.\n");
1513 /* Test with a subdirectory. */
1517 queue
= SetupOpenFileQueue();
1518 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1519 ret
= SetupQueueCopyA(queue
, "src", "beta", "two.txt", NULL
, NULL
, "dst", NULL
, 0);
1520 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1521 run_queue(queue
, need_media_cb
);
1522 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1523 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1525 /* Test with a tag file. */
1529 queue
= SetupOpenFileQueue();
1530 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1531 ret
= SetupQueueCopyA(queue
, "src", "beta", "two.txt", "desc", "faketag", "dst", NULL
, 0);
1532 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1533 run_queue(queue
, need_media_cb
);
1534 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1535 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1537 /* Test from INF file. */
1541 queue
= SetupOpenFileQueue();
1542 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1543 ret
= SetupQueueCopySectionA(queue
, "src", hinf
, NULL
, "section1", 0);
1544 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1545 run_queue(queue
, need_media_cb
);
1546 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1547 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1550 queue
= SetupOpenFileQueue();
1551 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1552 ret
= SetupInstallFilesFromInfSectionA(hinf
, NULL
, queue
, "install_section", "src", 0);
1553 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1554 run_queue(queue
, need_media_cb
);
1555 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1556 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1559 queue
= SetupOpenFileQueue();
1560 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1562 ret
= SetupQueueDefaultCopyA(queue
, hinf
, "src", NULL
, "one.txt", 0);
1563 ok(!ret
, "Expected failure.\n");
1564 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "Got error %#x.\n", GetLastError());
1566 ret
= SetupQueueDefaultCopyA(queue
, hinf
, "src", "one.txt", "one.txt", 0);
1567 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1568 run_queue(queue
, need_media_cb
);
1569 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1570 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1574 queue
= SetupOpenFileQueue();
1575 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1576 ret
= SetupQueueCopySectionA(queue
, "src", hinf
, NULL
, "section2", 0);
1577 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1578 run_queue(queue
, need_media_cb
);
1579 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1580 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1583 queue
= SetupOpenFileQueue();
1584 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1585 ret
= SetupQueueDefaultCopyA(queue
, hinf
, "src", "two.txt", "two.txt", 0);
1586 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1587 run_queue(queue
, need_media_cb
);
1588 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1589 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1593 queue
= SetupOpenFileQueue();
1594 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1595 ret
= SetupQueueCopySectionA(queue
, "src", hinf
, NULL
, "section3", 0);
1596 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1597 run_queue(queue
, need_media_cb
);
1598 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1599 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1602 queue
= SetupOpenFileQueue();
1603 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1604 ret
= SetupQueueDefaultCopyA(queue
, hinf
, "src", "three.txt", "three.txt", 0);
1605 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1606 run_queue(queue
, need_media_cb
);
1607 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1608 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1610 /* One callback is sent per source directory. */
1614 queue
= SetupOpenFileQueue();
1615 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1616 ret
= SetupQueueCopyA(queue
, "src", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
1617 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1618 ret
= SetupQueueCopyA(queue
, "src", "beta", "two.txt", NULL
, NULL
, "dst", NULL
, 0);
1619 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1620 ret
= SetupQueueCopyA(queue
, "src/alpha", NULL
, "three.txt", NULL
, NULL
, "dst", NULL
, 0);
1621 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1622 run_queue(queue
, need_media_cb
);
1623 ok(got_need_media
== 2, "Got %u callbacks.\n", got_need_media
);
1624 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1625 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1626 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1628 /* The same rules apply to INF files. Here the subdir specified in the
1629 * SourceDisksNames counts as part of the root directory, but the subdir in
1630 * SourceDisksFiles does not. */
1634 queue
= SetupOpenFileQueue();
1635 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1636 ret
= SetupQueueCopySectionA(queue
, "src", hinf
, NULL
, "section4", 0);
1637 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());\
1638 run_queue(queue
, need_media_cb
);
1639 ok(got_need_media
== 2, "Got %u callbacks.\n", got_need_media
);
1640 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1641 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1642 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1644 /* Descriptions and tag files also distinguish source paths. */
1648 queue
= SetupOpenFileQueue();
1649 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1650 ret
= SetupQueueCopyA(queue
, "src", NULL
, "one.txt", "desc1", NULL
, "dst", NULL
, 0);
1651 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1652 ret
= SetupQueueCopyA(queue
, "src", "beta", "two.txt", NULL
, NULL
, "dst", NULL
, 0);
1653 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1654 run_queue(queue
, need_media_cb
);
1655 ok(got_need_media
== 2, "Got %u callbacks.\n", got_need_media
);
1656 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1657 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1661 queue
= SetupOpenFileQueue();
1662 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1663 ret
= SetupQueueCopyA(queue
, "src", NULL
, "one.txt", "desc1", "faketag", "dst", NULL
, 0);
1664 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1665 ret
= SetupQueueCopyA(queue
, "src", "beta", "two.txt", "desc1", "faketag2", "dst", NULL
, 0);
1666 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1667 run_queue(queue
, need_media_cb
);
1668 ok(got_need_media
== 2, "Got %u callbacks.\n", got_need_media
);
1669 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1670 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1672 /* Test from cabinets. Subdir is only relevant for the first argument. */
1676 queue
= SetupOpenFileQueue();
1677 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1678 ret
= SetupQueueCopyA(queue
, "src", NULL
, "four.txt", "desc", "treis.cab", "dst", NULL
, 0);
1679 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1680 ret
= SetupQueueCopyA(queue
, "src", "alpha", "five.txt", "desc", "treis.cab", "dst", NULL
, 0);
1681 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1682 run_queue(queue
, need_media_cb
);
1683 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1684 ok(delete_file("dst/four.txt"), "Destination file should exist.\n");
1685 ok(delete_file("dst/five.txt"), "Destination file should exist.\n");
1689 queue
= SetupOpenFileQueue();
1690 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1691 ret
= SetupQueueCopyA(queue
, "src", "alpha", "seven.txt", "desc", "tessares.cab", "dst", NULL
, 0);
1692 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1693 ret
= SetupQueueCopyA(queue
, "src", NULL
, "eight.txt", "desc", "tessares.cab", "dst", NULL
, 0);
1694 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1695 run_queue(queue
, need_media_cb
);
1696 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1697 ok(delete_file("dst/seven.txt"), "Destination file should exist.\n");
1698 ok(delete_file("dst/eight.txt"), "Destination file should exist.\n");
1702 queue
= SetupOpenFileQueue();
1703 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1704 ret
= SetupQueueDefaultCopyA(queue
, hinf
, "src/alpha", "six.txt", "six.txt", 0);
1705 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1706 run_queue(queue
, need_media_cb
);
1707 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1708 ok(delete_file("dst/six.txt"), "Destination file should exist.\n");
1710 /* Test absolute paths. */
1714 queue
= SetupOpenFileQueue();
1715 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1716 ret
= SetupQueueCopyA(queue
, "src", "beta", "two.txt", NULL
, NULL
, "dst", NULL
, SP_COPY_SOURCE_ABSOLUTE
);
1717 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1718 run_queue(queue
, need_media_cb
);
1719 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1720 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1724 queue
= SetupOpenFileQueue();
1725 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1726 ret
= SetupQueueCopyA(queue
, "src", "beta", "two.txt", NULL
, NULL
, "dst", NULL
, SP_COPY_SOURCEPATH_ABSOLUTE
);
1727 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1728 run_queue(queue
, need_media_cb
);
1729 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1730 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1734 queue
= SetupOpenFileQueue();
1735 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1736 ret
= SetupQueueCopySectionA(queue
, "src", hinf
, NULL
, "section3", SP_COPY_SOURCE_ABSOLUTE
);
1737 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1738 run_queue(queue
, need_media_cb
);
1739 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1740 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1744 queue
= SetupOpenFileQueue();
1745 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1746 ret
= SetupQueueCopySectionA(queue
, "src", hinf
, NULL
, "section3", SP_COPY_SOURCEPATH_ABSOLUTE
);
1747 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1748 run_queue(queue
, need_media_cb
);
1749 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1750 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1752 /* Test returning a new path from the NEEDMEDIA callback. */
1755 got_need_media
= got_copy_error
= 0;
1756 queue
= SetupOpenFileQueue();
1757 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1758 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
1759 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1760 ret
= SetupQueueCopyA(queue
, "fake", "alpha", "three.txt", NULL
, NULL
, "dst", NULL
, 0);
1761 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1762 run_queue(queue
, need_media_newpath_cb
);
1763 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1764 ok(!got_copy_error
, "Got %u copy errors.\n", got_copy_error
);
1765 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1766 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1768 /* setupapi expects the callback to return the path including the subdir
1769 * for the first file. It then strips off the final element. If the final
1770 * element doesn't match the given subdir exactly, then it's not stripped.
1771 * To make matters even stranger, the first file copied effectively has its
1772 * subdir removed. */
1775 got_need_media
= got_copy_error
= 0;
1776 queue
= SetupOpenFileQueue();
1777 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1778 ret
= SetupQueueCopyA(queue
, "fake", "alpha", "three.txt", NULL
, NULL
, "dst", NULL
, 0);
1779 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1780 ret
= SetupQueueCopyA(queue
, "fake", "beta", "two.txt", NULL
, NULL
, "dst", NULL
, 0);
1781 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1782 run_queue(queue
, need_media_newpath_cb
);
1783 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1784 ok(!got_copy_error
, "Got %u copy errors.\n", got_copy_error
);
1785 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1786 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
1788 got_need_media
= got_copy_error
= 0;
1789 queue
= SetupOpenFileQueue();
1790 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1791 ret
= SetupQueueCopyA(queue
, "fake", "alpha\\", "three.txt", NULL
, NULL
, "dst", NULL
, 0);
1792 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1793 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "six.txt", NULL
, NULL
, "dst", NULL
, 0);
1794 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1795 run_queue(queue
, need_media_newpath_cb
);
1796 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1797 ok(!got_copy_error
, "Got %u copy errors.\n", got_copy_error
);
1798 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1799 ok(delete_file("dst/six.txt"), "Destination file should exist.\n");
1801 /* If the source file does not exist (even if the path is valid),
1802 * SPFILENOTIFY_NEEDMEDIA is resent until it does. */
1805 got_need_media
= got_copy_error
= 0;
1806 queue
= SetupOpenFileQueue();
1807 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1808 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
1809 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1810 ret
= SetupQueueCopyA(queue
, "fake", "alpha", "three.txt", NULL
, NULL
, "dst", NULL
, 0);
1811 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1812 run_queue(queue
, need_media_newpath_cb
);
1813 ok(got_need_media
== 2, "Got %u callbacks.\n", got_need_media
);
1814 ok(!got_copy_error
, "Got %u copy errors.\n", got_copy_error
);
1815 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1816 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1818 /* If a following file doesn't exist, it results in a copy error instead. */
1821 got_need_media
= got_copy_error
= 0;
1822 queue
= SetupOpenFileQueue();
1823 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1824 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
1825 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1826 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "fake.txt", NULL
, NULL
, "dst", NULL
, 0);
1827 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1828 run_queue(queue
, need_media_newpath_cb
);
1829 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1830 ok(got_copy_error
== 1, "Got %u copy errors.\n", got_copy_error
);
1831 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1833 /* Test providing a new path from SPFILENOTIFY_COPYERROR. */
1836 got_need_media
= got_copy_error
= 0;
1837 queue
= SetupOpenFileQueue();
1838 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1839 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
1840 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1841 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "three.txt", NULL
, NULL
, "dst", NULL
, 0);
1842 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1843 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "six.txt", NULL
, NULL
, "dst", NULL
, 0);
1844 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1845 run_queue(queue
, need_media_newpath_cb
);
1846 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1847 ok(got_copy_error
== 1, "Got %u copy errors.\n", got_copy_error
);
1848 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1849 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1850 ok(delete_file("dst/six.txt"), "Destination file should exist.\n");
1852 /* SPFILENOTIFY_COPYERROR will also be resent until the copy is successful. */
1855 got_need_media
= got_copy_error
= 0;
1856 queue
= SetupOpenFileQueue();
1857 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1858 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
1859 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1860 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "three.txt", NULL
, NULL
, "dst", NULL
, 0);
1861 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1862 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "six.txt", NULL
, NULL
, "dst", NULL
, 0);
1863 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1864 run_queue(queue
, need_media_newpath_cb
);
1865 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1866 ok(got_copy_error
== 2, "Got %u copy errors.\n", got_copy_error
);
1867 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1868 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1869 ok(delete_file("dst/six.txt"), "Destination file should exist.\n");
1871 /* Test with cabinet. As above, subdir only matters for the first file. */
1874 got_need_media
= got_copy_error
= 0;
1875 queue
= SetupOpenFileQueue();
1876 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1877 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "four.txt", "desc", "treis.cab", "dst", NULL
, 0);
1878 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1879 ret
= SetupQueueCopyA(queue
, "fake", "alpha", "five.txt", "desc", "treis.cab", "dst", NULL
, 0);
1880 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1881 run_queue(queue
, need_media_newpath_cb
);
1882 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1883 ok(!got_copy_error
, "Got %u copy errors.\n", got_copy_error
);
1884 ok(delete_file("dst/four.txt"), "Destination file should exist.\n");
1885 ok(delete_file("dst/five.txt"), "Destination file should exist.\n");
1887 /* Test returning FILEOP_SKIP from the NEEDMEDIA handler. */
1890 got_need_media
= got_copy_error
= 0;
1891 queue
= SetupOpenFileQueue();
1892 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1893 ret
= SetupQueueCopyA(queue
, "fake", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
1894 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1895 ret
= SetupQueueCopyA(queue
, "fake", "alpha", "three.txt", NULL
, NULL
, "dst", NULL
, 0);
1896 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1897 run_queue(queue
, need_media_newpath_cb
);
1898 ok(got_need_media
== 2, "Got %u callbacks.\n", got_need_media
);
1899 ok(!got_copy_error
, "Got %u copy errors.\n", got_copy_error
);
1900 ok(!file_exists("dst/one.txt"), "Destination file should not exist.\n");
1901 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
1904 got_need_media
= got_copy_error
= 0;
1905 queue
= SetupOpenFileQueue();
1906 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1907 copy_params
.QueueHandle
= queue
;
1908 copy_params
.SourceFilename
= "one.txt";
1909 /* Leaving TargetDirectory NULL causes it to be filled with garbage on
1910 * Windows, so the copy may succeed or fail. In any case it's not supplied
1911 * from LayoutInf. */
1912 copy_params
.TargetDirectory
= "dst";
1913 ret
= SetupQueueCopyIndirectA(©_params
);
1914 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
1915 run_queue(queue
, need_media_newpath_cb
);
1916 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1917 ok(!got_copy_error
, "Got %u copy errors.\n", got_copy_error
);
1918 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1920 got_need_media
= got_copy_error
= 0;
1921 queue
= SetupOpenFileQueue();
1922 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
1923 copy_params
.LayoutInf
= hinf
;
1924 copy_params
.QueueHandle
= queue
;
1925 /* In fact this fails with ERROR_INVALID_PARAMETER on 8+. */
1926 if (SetupQueueCopyIndirectA(©_params
))
1928 run_queue(queue
, need_media_newpath_cb
);
1929 ok(got_need_media
== 1, "Got %u callbacks.\n", got_need_media
);
1930 ok(!got_copy_error
, "Got %u copy errors.\n", got_copy_error
);
1931 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
1934 SetupCloseFileQueue(queue
);
1936 SetupCloseInfFile(hinf
);
1937 delete_file("src/one.txt");
1938 delete_file("src/beta/two.txt");
1939 delete_file("src/beta/");
1940 delete_file("src/alpha/six.txt");
1941 delete_file("src/alpha/three.txt");
1942 delete_file("src/alpha/tessares.cab");
1943 delete_file("src/alpha/");
1944 delete_file("src/treis.cab");
1945 delete_file("src/");
1946 delete_file("dst/");
1947 ret
= DeleteFileA(inffile
);
1948 ok(ret
, "Failed to delete INF file, error %u.\n", GetLastError());
1951 static void test_close_queue(void)
1956 context
= SetupInitDefaultQueueCallback(NULL
);
1957 ok(!!context
, "Failed to create callback context, error %#x.\n", GetLastError());
1959 ret
= SetupCloseFileQueue(context
);
1960 ok(!ret
, "Expected failure.\n");
1961 ok(GetLastError() == ERROR_INVALID_HANDLE
, "Got unexpected error %u.\n", GetLastError());
1963 SetupTermDefaultQueueCallback(context
);
1966 static unsigned int got_start_copy
, start_copy_ret
;
1968 static UINT WINAPI
start_copy_cb(void *context
, UINT message
, UINT_PTR param1
, UINT_PTR param2
)
1970 if (winetest_debug
> 1) trace("%p, %#x, %#lx, %#lx\n", context
, message
, param1
, param2
);
1972 if (message
== SPFILENOTIFY_STARTCOPY
)
1974 const FILEPATHS_A
*paths
= (const FILEPATHS_A
*)param1
;
1978 if (strstr(paths
->Source
, "two.txt"))
1980 SetLastError(0xdeadf00d);
1981 return start_copy_ret
;
1985 return SetupDefaultQueueCallbackA(context
, message
, param1
, param2
);
1988 static void test_start_copy(void)
1994 ret
= CreateDirectoryA("src", NULL
);
1995 ok(ret
, "Failed to create test directory, error %u.\n", GetLastError());
1996 create_file("src/one.txt");
1997 create_file("src/two.txt");
1998 create_file("src/three.txt");
2000 start_copy_ret
= FILEOP_DOIT
;
2002 queue
= SetupOpenFileQueue();
2003 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
2004 ret
= SetupQueueCopyA(queue
, "src", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
2005 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
2006 ret
= SetupQueueCopyA(queue
, "src", NULL
, "two.txt", NULL
, NULL
, "dst", NULL
, 0);
2007 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
2008 ret
= SetupQueueCopyA(queue
, "src", NULL
, "three.txt", NULL
, NULL
, "dst", NULL
, 0);
2009 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
2010 run_queue(queue
, start_copy_cb
);
2011 ok(got_start_copy
== 3, "Got %u callbacks.\n", got_start_copy
);
2012 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
2013 ok(delete_file("dst/two.txt"), "Destination file should exist.\n");
2014 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
2016 start_copy_ret
= FILEOP_SKIP
;
2018 queue
= SetupOpenFileQueue();
2019 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
2020 ret
= SetupQueueCopyA(queue
, "src", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
2021 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
2022 ret
= SetupQueueCopyA(queue
, "src", NULL
, "two.txt", NULL
, NULL
, "dst", NULL
, 0);
2023 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
2024 ret
= SetupQueueCopyA(queue
, "src", NULL
, "three.txt", NULL
, NULL
, "dst", NULL
, 0);
2025 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
2026 run_queue(queue
, start_copy_cb
);
2027 ok(got_start_copy
== 3, "Got %u callbacks.\n", got_start_copy
);
2028 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
2029 ok(!file_exists("dst/two.txt"), "Destination file should not exist.\n");
2030 ok(delete_file("dst/three.txt"), "Destination file should exist.\n");
2032 start_copy_ret
= FILEOP_ABORT
;
2034 queue
= SetupOpenFileQueue();
2035 ok(queue
!= INVALID_HANDLE_VALUE
, "Failed to open queue, error %#x.\n", GetLastError());
2036 ret
= SetupQueueCopyA(queue
, "src", NULL
, "one.txt", NULL
, NULL
, "dst", NULL
, 0);
2037 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
2038 ret
= SetupQueueCopyA(queue
, "src", NULL
, "two.txt", NULL
, NULL
, "dst", NULL
, 0);
2039 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
2040 ret
= SetupQueueCopyA(queue
, "src", NULL
, "three.txt", NULL
, NULL
, "dst", NULL
, 0);
2041 ok(ret
, "Failed to queue copy, error %#x.\n", GetLastError());
2042 context
= SetupInitDefaultQueueCallbackEx(NULL
, INVALID_HANDLE_VALUE
, 0, 0, 0);
2043 SetLastError(0xdeadbeef);
2044 ret
= SetupCommitFileQueueA(NULL
, queue
, start_copy_cb
, context
);
2045 ok(!ret
, "Expected failure.\n");
2046 ok(GetLastError() == 0xdeadf00d, "Got unexpected error %u.\n", GetLastError());
2047 SetupTermDefaultQueueCallback(context
);
2048 SetupCloseFileQueue(queue
);
2049 ok(got_start_copy
== 2, "Got %u callbacks.\n", got_start_copy
);
2050 ok(delete_file("dst/one.txt"), "Destination file should exist.\n");
2051 ok(!file_exists("dst/two.txt"), "Destination file should not exist.\n");
2052 ok(!file_exists("dst/three.txt"), "Destination file should not exist.\n");
2054 delete_file("src/one.txt");
2055 delete_file("src/two.txt");
2056 delete_file("src/three.txt");
2057 delete_file("src/");
2058 delete_file("dst/");
2061 static void test_register_dlls(void)
2063 static const char inf_data
[] = "[Version]\n"
2064 "Signature=\"$Chicago$\"\n"
2065 "[DefaultInstall]\n"
2066 "RegisterDlls=register_section\n"
2067 "UnregisterDlls=register_section\n"
2068 "[register_section]\n"
2069 "40000,,winetest_selfreg.dll,1\n";
2071 void *context
= SetupInitDefaultQueueCallbackEx(NULL
, INVALID_HANDLE_VALUE
, 0, 0, 0);
2072 char path
[MAX_PATH
];
2079 create_inf_file("test.inf", inf_data
);
2080 sprintf(path
, "%s\\test.inf", CURR_DIR
);
2081 hinf
= SetupOpenInfFileA(path
, NULL
, INF_STYLE_WIN4
, NULL
);
2082 ok(hinf
!= INVALID_HANDLE_VALUE
, "Failed to open INF file, error %#x.\n", GetLastError());
2084 load_resource("selfreg.dll", "winetest_selfreg.dll");
2085 ret
= SetupSetDirectoryIdA(hinf
, 40000, CURR_DIR
);
2086 ok(ret
, "Failed to set directory ID, error %u.\n", GetLastError());
2088 RegDeleteKeyA(HKEY_CURRENT_USER
, "winetest_setupapi_selfreg");
2090 ret
= SetupInstallFromInfSectionA(NULL
, hinf
, "DefaultInstall", SPINST_REGSVR
,
2091 NULL
, "C:\\", 0, SetupDefaultQueueCallbackA
, context
, NULL
, NULL
);
2092 ok(ret
, "Failed to install, error %#x.\n", GetLastError());
2094 l
= RegOpenKeyA(HKEY_CURRENT_USER
, "winetest_setupapi_selfreg", &key
);
2095 ok(!l
, "Got error %u.\n", l
);
2098 ret
= SetupInstallFromInfSectionA(NULL
, hinf
, "DefaultInstall", SPINST_UNREGSVR
,
2099 NULL
, "C:\\", 0, SetupDefaultQueueCallbackA
, context
, NULL
, NULL
);
2100 ok(ret
, "Failed to install, error %#x.\n", GetLastError());
2102 l
= RegOpenKeyA(HKEY_CURRENT_USER
, "winetest_setupapi_selfreg", &key
);
2103 ok(l
== ERROR_FILE_NOT_FOUND
, "Got error %u.\n", l
);
2105 hr
= CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2106 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2108 ret
= SetupInstallFromInfSectionA(NULL
, hinf
, "DefaultInstall", SPINST_REGSVR
,
2109 NULL
, "C:\\", 0, SetupDefaultQueueCallbackA
, context
, NULL
, NULL
);
2110 ok(ret
, "Failed to install, error %#x.\n", GetLastError());
2112 l
= RegOpenKeyA(HKEY_CURRENT_USER
, "winetest_setupapi_selfreg", &key
);
2113 ok(!l
, "Got error %u.\n", l
);
2116 ret
= SetupInstallFromInfSectionA(NULL
, hinf
, "DefaultInstall", SPINST_UNREGSVR
,
2117 NULL
, "C:\\", 0, SetupDefaultQueueCallbackA
, context
, NULL
, NULL
);
2118 ok(ret
, "Failed to install, error %#x.\n", GetLastError());
2120 l
= RegOpenKeyA(HKEY_CURRENT_USER
, "winetest_setupapi_selfreg", &key
);
2121 ok(l
== ERROR_FILE_NOT_FOUND
, "Got error %u.\n", l
);
2125 SetupCloseInfFile(hinf
);
2126 ret
= DeleteFileA("test.inf");
2127 ok(ret
, "Failed to delete INF file, error %u.\n", GetLastError());
2128 ret
= DeleteFileA("winetest_selfreg.dll");
2129 ok(ret
, "Failed to delete test DLL, error %u.\n", GetLastError());
2134 char temp_path
[MAX_PATH
], prev_path
[MAX_PATH
];
2137 GetCurrentDirectoryA(MAX_PATH
, prev_path
);
2138 GetTempPathA(MAX_PATH
, temp_path
);
2139 SetCurrentDirectoryA(temp_path
);
2141 strcpy(CURR_DIR
, temp_path
);
2142 len
= strlen(CURR_DIR
);
2143 if(len
&& (CURR_DIR
[len
- 1] == '\\'))
2144 CURR_DIR
[len
- 1] = 0;
2146 /* Set CBT hook to disallow MessageBox creation in current thread */
2147 hhook
= SetWindowsHookExA(WH_CBT
, cbt_hook_proc
, 0, GetCurrentThreadId());
2148 ok(!!hhook
, "Failed to set hook, error %u.\n", GetLastError());
2152 test_install_from();
2153 test_install_svc_from();
2154 test_driver_install();
2156 test_install_files_queue();
2159 test_install_file();
2161 test_register_dlls();
2163 UnhookWindowsHookEx(hhook
);
2165 /* We have to run this test after the CBT hook is disabled because
2166 ProfileItems needs to create a window on Windows XP. */
2167 test_profile_items();
2170 test_inffilelistA();
2172 SetCurrentDirectoryA(prev_path
);