2 * Unit tests for advpack.dll file functions
4 * Copyright (C) 2006 James Hawkins
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/test.h"
27 /* make the max size large so there is only one cab file */
28 #define MEDIA_SIZE 999999999
29 #define FOLDER_THRESHOLD 900000
31 /* function pointers */
33 static HRESULT (WINAPI *pExtractFiles)(LPCSTR, LPCSTR, DWORD, LPCSTR, LPVOID, DWORD);
34 static HRESULT (WINAPI *pAdvInstallFile)(HWND,LPCSTR,LPCSTR,LPCSTR,LPCSTR,DWORD,DWORD);
36 CHAR CURR_DIR[MAX_PATH];
38 static void init_function_pointers()
40 hAdvPack = LoadLibraryA("advpack.dll");
44 pExtractFiles = (void *)GetProcAddress(hAdvPack, "ExtractFiles");
45 pAdvInstallFile = (void*)GetProcAddress(hAdvPack, "AdvInstallFile");
49 /* creates a file with the specified name for tests */
50 static void createTestFile(const CHAR *name)
55 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
56 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
57 WriteFile(file, name, strlen(name), &written, NULL);
58 WriteFile(file, "\n", strlen("\n"), &written, NULL);
62 static void create_test_files()
66 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
67 len = lstrlenA(CURR_DIR);
69 if(len && (CURR_DIR[len-1] == '\\'))
72 createTestFile("a.txt");
73 createTestFile("b.txt");
74 CreateDirectoryA("testdir", NULL);
75 createTestFile("testdir\\c.txt");
76 createTestFile("testdir\\d.txt");
77 CreateDirectoryA("dest", NULL);
80 static void delete_test_files()
84 DeleteFileA("testdir\\c.txt");
85 DeleteFileA("testdir\\d.txt");
86 RemoveDirectoryA("testdir");
87 RemoveDirectoryA("dest");
89 DeleteFileA("extract.cab");
92 /* the FCI callbacks */
94 static void *mem_alloc(ULONG cb)
96 return HeapAlloc(GetProcessHeap(), 0, cb);
99 static void mem_free(void *memory)
101 HeapFree(GetProcessHeap(), 0, memory);
104 static BOOL get_next_cabinet(PCCAB pccab, ULONG cbPrevCab, void *pv)
109 static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
114 static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
115 BOOL fContinuation, void *pv)
120 static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
124 DWORD dwShareMode = 0;
125 DWORD dwCreateDisposition = OPEN_EXISTING;
127 dwAccess = GENERIC_READ | GENERIC_WRITE;
128 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
130 if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
131 dwCreateDisposition = OPEN_EXISTING;
133 dwCreateDisposition = CREATE_NEW;
135 handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
136 dwCreateDisposition, 0, NULL);
138 ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
140 return (INT_PTR)handle;
143 static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
145 HANDLE handle = (HANDLE)hf;
149 res = ReadFile(handle, memory, cb, &dwRead, NULL);
150 ok(res, "Failed to ReadFile\n");
155 static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
157 HANDLE handle = (HANDLE)hf;
161 res = WriteFile(handle, memory, cb, &dwWritten, NULL);
162 ok(res, "Failed to WriteFile\n");
167 static int fci_close(INT_PTR hf, int *err, void *pv)
169 HANDLE handle = (HANDLE)hf;
170 ok(CloseHandle(handle), "Failed to CloseHandle\n");
175 static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
177 HANDLE handle = (HANDLE)hf;
180 ret = SetFilePointer(handle, dist, NULL, seektype);
181 ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
186 static int fci_delete(char *pszFile, int *err, void *pv)
188 BOOL ret = DeleteFileA(pszFile);
189 ok(ret, "Failed to DeleteFile %s\n", pszFile);
194 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
198 tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
199 GetTempFileNameA(".", "xx", 0, tempname);
201 if (tempname && (strlen(tempname) < (unsigned)cbTempName))
203 lstrcpyA(pszTempName, tempname);
204 HeapFree(GetProcessHeap(), 0, tempname);
208 HeapFree(GetProcessHeap(), 0, tempname);
213 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
214 USHORT *pattribs, int *err, void *pv)
216 BY_HANDLE_FILE_INFORMATION finfo;
222 handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
223 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
225 ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
227 res = GetFileInformationByHandle(handle, &finfo);
228 ok(res, "Expected GetFileInformationByHandle to succeed\n");
230 FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
231 FileTimeToDosDateTime(&filetime, pdate, ptime);
233 attrs = GetFileAttributes(pszName);
234 ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
236 return (INT_PTR)handle;
239 static void add_file(HFCI hfci, char *file)
244 lstrcpyA(path, CURR_DIR);
245 lstrcatA(path, "\\");
246 lstrcatA(path, file);
248 res = FCIAddFile(hfci, path, file, FALSE, get_next_cabinet, progress,
249 get_open_info, tcompTYPE_MSZIP);
250 ok(res, "Expected FCIAddFile to succeed\n");
253 static void set_cab_parameters(PCCAB pCabParams)
255 ZeroMemory(pCabParams, sizeof(CCAB));
257 pCabParams->cb = MEDIA_SIZE;
258 pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
259 pCabParams->setID = 0xbeef;
260 lstrcpyA(pCabParams->szCabPath, CURR_DIR);
261 lstrcatA(pCabParams->szCabPath, "\\");
262 lstrcpyA(pCabParams->szCab, "extract.cab");
265 static void create_cab_file()
272 set_cab_parameters(&cabParams);
274 hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
275 fci_read, fci_write, fci_close, fci_seek, fci_delete,
276 get_temp_file, &cabParams, NULL);
278 ok(hfci != NULL, "Failed to create an FCI context\n");
280 add_file(hfci, "a.txt");
281 add_file(hfci, "b.txt");
282 add_file(hfci, "testdir\\c.txt");
283 add_file(hfci, "testdir\\d.txt");
285 res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
286 ok(res, "Failed to flush the cabinet\n");
288 res = FCIDestroy(hfci);
289 ok(res, "Failed to destroy the cabinet\n");
292 static void test_ExtractFiles()
295 char destFolder[MAX_PATH];
297 lstrcpyA(destFolder, CURR_DIR);
298 lstrcatA(destFolder, "\\");
299 lstrcatA(destFolder, "dest");
301 /* try NULL cab file */
302 hr = pExtractFiles(NULL, destFolder, 0, NULL, NULL, 0);
303 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %ld\n", hr);
304 ok(RemoveDirectoryA("dest"), "Expected dest to exist\n");
306 /* try NULL destination */
307 hr = pExtractFiles("extract.cab", NULL, 0, NULL, NULL, 0);
308 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %ld\n", hr);
309 ok(!RemoveDirectoryA("dest"), "Expected dest to not exist\n");
311 /* extract all files in the cab to nonexistent destination directory */
312 hr = pExtractFiles("extract.cab", destFolder, 0, NULL, NULL, 0);
313 ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND),
314 "Expected %ld, got %ld\n", HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), hr);
315 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
316 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
317 ok(!RemoveDirectoryA("dest\\testdir"), "Exepected dest\\testdir to not exist\n");
318 ok(!RemoveDirectoryA("dest"), "Expected dest to not exist\n");
320 /* extract all files in the cab to the destination directory */
321 CreateDirectoryA("dest", NULL);
322 hr = pExtractFiles("extract.cab", destFolder, 0, NULL, NULL, 0);
323 ok(hr == S_OK, "Expected S_OK, got %ld\n", hr);
324 ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
325 ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
326 ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
327 ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
328 ok(RemoveDirectoryA("dest\\testdir"), "Exepected dest\\testdir to exist\n");
330 /* extract all files to a relative destination directory */
331 hr = pExtractFiles("extract.cab", "dest", 0, NULL, NULL, 0);
332 ok(hr == S_OK, "Expected S_OK, got %ld\n", hr);
333 ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
334 ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
335 ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
336 ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
337 ok(RemoveDirectoryA("dest\\testdir"), "Exepected dest\\testdir to exist\n");
339 /* only extract two of the files from the cab */
340 hr = pExtractFiles("extract.cab", "dest", 0, "a.txt:testdir\\c.txt", NULL, 0);
341 ok(hr == S_OK, "Expected S_OK, got %ld\n", hr);
342 ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
343 ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
344 ok(RemoveDirectoryA("dest\\testdir"), "Exepected dest\\testdir to exist\n");
345 ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
346 ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
348 /* use valid chars before and after file list */
349 hr = pExtractFiles("extract.cab", "dest", 0, " :\t: a.txt:testdir\\c.txt \t:", NULL, 0);
350 ok(hr == S_OK, "Expected S_OK, got %ld\n", hr);
351 ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
352 ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
353 ok(RemoveDirectoryA("dest\\testdir"), "Exepected dest\\testdir to exist\n");
354 ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
355 ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
357 /* use invalid chars before and after file list */
358 hr = pExtractFiles("extract.cab", "dest", 0, " +-\\ a.txt:testdir\\c.txt a_:", NULL, 0);
359 ok(hr == E_FAIL, "Expected E_FAIL, got %ld\n", hr);
360 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
361 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
362 ok(!RemoveDirectoryA("dest\\testdir"), "Exepected dest\\testdir to not exist\n");
364 /* try an empty file list */
365 hr = pExtractFiles("extract.cab", "dest", 0, "", NULL, 0);
366 ok(hr == E_FAIL, "Expected E_FAIL, got %ld\n", hr);
367 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
368 ok(!RemoveDirectoryA("dest\\testdir"), "Exepected dest\\testdir to not exist\n");
370 /* try a nonexistent file in the file list */
371 hr = pExtractFiles("extract.cab", "dest", 0, "a.txt:idontexist:testdir\\c.txt", NULL, 0);
372 ok(hr == E_FAIL, "Expected E_FAIL, got %ld\n", hr);
373 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
374 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
375 ok(!RemoveDirectoryA("dest\\testdir"), "Exepected dest\\testdir to not exist\n");
378 static void test_AdvInstallFile(void)
381 char CURR_DIR[MAX_PATH];
382 char destFolder[MAX_PATH];
384 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
386 lstrcpyA(destFolder, CURR_DIR);
387 lstrcatA(destFolder, "\\");
388 lstrcatA(destFolder, "dest");
390 createTestFile("source.txt");
392 /* try invalid source directory */
393 hr = pAdvInstallFile(NULL, NULL, "source.txt", destFolder, "destination.txt", 0, 0);
394 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %ld\n", hr);
395 ok(!DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to not exist\n");
397 /* try invalid source file */
398 hr = pAdvInstallFile(NULL, CURR_DIR, NULL, destFolder, "destination.txt", 0, 0);
399 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %ld\n", hr);
400 ok(!DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to not exist\n");
402 /* try invalid destination directory */
403 hr = pAdvInstallFile(NULL, CURR_DIR, "source.txt", NULL, "destination.txt", 0, 0);
404 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %ld\n", hr);
405 ok(!DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to not exist\n");
407 /* try copying to nonexistent destination directory */
408 hr = pAdvInstallFile(NULL, CURR_DIR, "source.txt", destFolder, "destination.txt", 0, 0);
409 ok(hr == S_OK, "Expected S_OK, got %ld\n", hr);
410 ok(DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to exist\n");
412 /* native windows screws up if the source file doesn't exist */
414 /* test AIF_NOOVERWRITE behavior, asks the user to overwrite if AIF_QUIET is not specified */
415 createTestFile("dest\\destination.txt");
416 hr = pAdvInstallFile(NULL, CURR_DIR, "source.txt", destFolder,
417 "destination.txt", AIF_NOOVERWRITE | AIF_QUIET, 0);
418 ok(hr == S_OK, "Expected S_OK, got %ld\n", hr);
419 ok(DeleteFileA("dest\\destination.txt"), "Expected dest\\destination.txt to exist\n");
420 ok(RemoveDirectoryA("dest"), "Expected dest to exist\n");
422 DeleteFileA("source.txt");
427 init_function_pointers();
432 test_AdvInstallFile();