1 /*
2 * Unit tests for cabinet.dll extract functions
3 *
4 * Copyright (C) 2006 James Hawkins
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <stdio.h>
22 #include <windows.h>
23 #include "fci.h"
24 #include "fdi.h"
25 #include "wine/test.h"
26
27 /* make the max size large so there is only one cab file */
28 #define MEDIA_SIZE 999999999
29 #define FOLDER_THRESHOLD 900000
30
31 /* The following definitions were copied from dlls/cabinet/cabinet.h
32 * because they are undocumented in windows.
33 */
34
35 /* SESSION Operation */
36 #define EXTRACT_FILLFILELIST 0x00000001
37 #define EXTRACT_EXTRACTFILES 0x00000002
38
39 struct FILELIST{
40 LPSTR FileName;
41 struct FILELIST *next;
42 BOOL DoExtract;
43 };
44
45 typedef struct {
46 INT FileSize;
47 ERF Error;
48 struct FILELIST *FileList;
49 INT FileCount;
50 INT Operation;
51 CHAR Destination[MAX_PATH];
52 CHAR CurrentFile[MAX_PATH];
53 CHAR Reserved[MAX_PATH];
54 struct FILELIST *FilterList;
55 } SESSION;
56
57 /* function pointers */
58 static HMODULE hCabinet;
59 static HRESULT (WINAPI *pExtract)(SESSION*, LPCSTR);
60
61 static CHAR CURR_DIR[MAX_PATH];
62
init_function_pointers(void)63 static void init_function_pointers(void)
64 {
65 hCabinet = GetModuleHandleA("cabinet.dll");
66
67 pExtract = (void *)GetProcAddress(hCabinet, "Extract");
68 }
69
70 /* creates a file with the specified name for tests */
createTestFile(const CHAR * name)71 static void createTestFile(const CHAR *name)
72 {
73 HANDLE file;
74 DWORD written;
75
76 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
77 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
78 WriteFile(file, name, strlen(name), &written, NULL);
79 WriteFile(file, "\n", strlen("\n"), &written, NULL);
80 CloseHandle(file);
81 }
82
getFileSize(const CHAR * name)83 static int getFileSize(const CHAR *name)
84 {
85 HANDLE file;
86 int size;
87 file = CreateFileA(name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
88 if (file == INVALID_HANDLE_VALUE)
89 return -1;
90 size = GetFileSize(file, NULL);
91 CloseHandle(file);
92 return size;
93 }
94
create_test_files(void)95 static void create_test_files(void)
96 {
97 int len;
98
99 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
100 len = lstrlenA(CURR_DIR);
101
102 if(len && (CURR_DIR[len-1] == '\\'))
103 CURR_DIR[len-1] = 0;
104
105 createTestFile("a.txt");
106 createTestFile("b.txt");
107 CreateDirectoryA("testdir", NULL);
108 createTestFile("testdir\\c.txt");
109 createTestFile("testdir\\d.txt");
110 CreateDirectoryA("dest", NULL);
111 }
112
delete_test_files(void)113 static void delete_test_files(void)
114 {
115 DeleteFileA("a.txt");
116 DeleteFileA("b.txt");
117 DeleteFileA("testdir\\c.txt");
118 DeleteFileA("testdir\\d.txt");
119 RemoveDirectoryA("testdir");
120
121 DeleteFileA("extract.cab");
122 }
123
124 /* the FCI callbacks */
125
mem_alloc(ULONG cb)126 static void * CDECL mem_alloc(ULONG cb)
127 {
128 return HeapAlloc(GetProcessHeap(), 0, cb);
129 }
130
mem_free(void * memory)131 static void CDECL mem_free(void *memory)
132 {
133 HeapFree(GetProcessHeap(), 0, memory);
134 }
135
get_next_cabinet(PCCAB pccab,ULONG cbPrevCab,void * pv)136 static BOOL CDECL get_next_cabinet(PCCAB pccab, ULONG cbPrevCab, void *pv)
137 {
138 return TRUE;
139 }
140
progress(UINT typeStatus,ULONG cb1,ULONG cb2,void * pv)141 static LONG CDECL progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
142 {
143 return 0;
144 }
145
file_placed(PCCAB pccab,char * pszFile,LONG cbFile,BOOL fContinuation,void * pv)146 static int CDECL file_placed(PCCAB pccab, char *pszFile, LONG cbFile,
147 BOOL fContinuation, void *pv)
148 {
149 return 0;
150 }
151
fci_open(char * pszFile,int oflag,int pmode,int * err,void * pv)152 static INT_PTR CDECL fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
153 {
154 HANDLE handle;
155 DWORD dwAccess = 0;
156 DWORD dwShareMode = 0;
157 DWORD dwCreateDisposition = OPEN_EXISTING;
158
159 dwAccess = GENERIC_READ | GENERIC_WRITE;
160 /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
161 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
162
163 if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
164 dwCreateDisposition = OPEN_EXISTING;
165 else
166 dwCreateDisposition = CREATE_NEW;
167
168 handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
169 dwCreateDisposition, 0, NULL);
170
171 ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
172
173 return (INT_PTR)handle;
174 }
175
fci_read(INT_PTR hf,void * memory,UINT cb,int * err,void * pv)176 static UINT CDECL fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
177 {
178 HANDLE handle = (HANDLE)hf;
179 DWORD dwRead;
180 BOOL res;
181
182 res = ReadFile(handle, memory, cb, &dwRead, NULL);
183 ok(res, "Failed to ReadFile\n");
184
185 return dwRead;
186 }
187
fci_write(INT_PTR hf,void * memory,UINT cb,int * err,void * pv)188 static UINT CDECL fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
189 {
190 HANDLE handle = (HANDLE)hf;
191 DWORD dwWritten;
192 BOOL res;
193
194 res = WriteFile(handle, memory, cb, &dwWritten, NULL);
195 ok(res, "Failed to WriteFile\n");
196
197 return dwWritten;
198 }
199
fci_close(INT_PTR hf,int * err,void * pv)200 static int CDECL fci_close(INT_PTR hf, int *err, void *pv)
201 {
202 HANDLE handle = (HANDLE)hf;
203 ok(CloseHandle(handle), "Failed to CloseHandle\n");
204
205 return 0;
206 }
207
fci_seek(INT_PTR hf,LONG dist,int seektype,int * err,void * pv)208 static LONG CDECL fci_seek(INT_PTR hf, LONG dist, int seektype, int *err, void *pv)
209 {
210 HANDLE handle = (HANDLE)hf;
211 DWORD ret;
212
213 ret = SetFilePointer(handle, dist, NULL, seektype);
214 ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
215
216 return ret;
217 }
218
fci_delete(char * pszFile,int * err,void * pv)219 static int CDECL fci_delete(char *pszFile, int *err, void *pv)
220 {
221 BOOL ret = DeleteFileA(pszFile);
222 ok(ret, "Failed to DeleteFile %s\n", pszFile);
223
224 return 0;
225 }
226
get_temp_file(char * pszTempName,int cbTempName,void * pv)227 static BOOL CDECL get_temp_file(char *pszTempName, int cbTempName, void *pv)
228 {
229 LPSTR tempname;
230
231 tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
232 GetTempFileNameA(".", "xx", 0, tempname);
233
234 if (tempname && (strlen(tempname) < (unsigned)cbTempName))
235 {
236 lstrcpyA(pszTempName, tempname);
237 HeapFree(GetProcessHeap(), 0, tempname);
238 return TRUE;
239 }
240
241 HeapFree(GetProcessHeap(), 0, tempname);
242
243 return FALSE;
244 }
245
get_open_info(char * pszName,USHORT * pdate,USHORT * ptime,USHORT * pattribs,int * err,void * pv)246 static INT_PTR CDECL get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
247 USHORT *pattribs, int *err, void *pv)
248 {
249 BY_HANDLE_FILE_INFORMATION finfo;
250 FILETIME filetime;
251 HANDLE handle;
252 DWORD attrs;
253 BOOL res;
254
255 handle = CreateFileA(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
256 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
257
258 ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
259
260 res = GetFileInformationByHandle(handle, &finfo);
261 ok(res, "Expected GetFileInformationByHandle to succeed\n");
262
263 FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
264 FileTimeToDosDateTime(&filetime, pdate, ptime);
265
266 attrs = GetFileAttributesA(pszName);
267 ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
268
269 return (INT_PTR)handle;
270 }
271
add_file(HFCI hfci,char * file)272 static void add_file(HFCI hfci, char *file)
273 {
274 char path[MAX_PATH];
275 BOOL res;
276
277 lstrcpyA(path, CURR_DIR);
278 lstrcatA(path, "\\");
279 lstrcatA(path, file);
280
281 res = FCIAddFile(hfci, path, file, FALSE, get_next_cabinet, progress,
282 get_open_info, tcompTYPE_MSZIP);
283 ok(res, "Expected FCIAddFile to succeed\n");
284 }
285
set_cab_parameters(PCCAB pCabParams)286 static void set_cab_parameters(PCCAB pCabParams)
287 {
288 ZeroMemory(pCabParams, sizeof(CCAB));
289
290 pCabParams->cb = MEDIA_SIZE;
291 pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
292 pCabParams->setID = 0xbeef;
293 lstrcpyA(pCabParams->szCabPath, CURR_DIR);
294 lstrcatA(pCabParams->szCabPath, "\\");
295 lstrcpyA(pCabParams->szCab, "extract.cab");
296 }
297
create_cab_file(void)298 static void create_cab_file(void)
299 {
300 CCAB cabParams;
301 HFCI hfci;
302 ERF erf;
303 static CHAR a_txt[] = "a.txt",
304 b_txt[] = "b.txt",
305 testdir_c_txt[] = "testdir\\c.txt",
306 testdir_d_txt[] = "testdir\\d.txt";
307 BOOL res;
308
309 set_cab_parameters(&cabParams);
310
311 hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
312 fci_read, fci_write, fci_close, fci_seek, fci_delete,
313 get_temp_file, &cabParams, NULL);
314
315 ok(hfci != NULL, "Failed to create an FCI context\n");
316
317 add_file(hfci, a_txt);
318 add_file(hfci, b_txt);
319 add_file(hfci, testdir_c_txt);
320 add_file(hfci, testdir_d_txt);
321
322 res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
323 ok(res, "Failed to flush the cabinet\n");
324
325 res = FCIDestroy(hfci);
326 ok(res, "Failed to destroy the cabinet\n");
327 }
328
check_list(struct FILELIST ** node,const char * filename,BOOL do_extract)329 static BOOL check_list(struct FILELIST **node, const char *filename, BOOL do_extract)
330 {
331 if (!*node)
332 return FALSE;
333
334 if (lstrcmpA((*node)->FileName, filename))
335 return FALSE;
336
337 if ((*node)->DoExtract != do_extract)
338 return FALSE;
339
340 *node = (*node)->next;
341 return TRUE;
342 }
343
free_file_node(struct FILELIST * node)344 static void free_file_node(struct FILELIST *node)
345 {
346 HeapFree(GetProcessHeap(), 0, node->FileName);
347 HeapFree(GetProcessHeap(), 0, node);
348 }
349
free_file_list(SESSION * session)350 static void free_file_list(SESSION* session)
351 {
352 struct FILELIST *next, *curr = session->FileList;
353
354 while (curr)
355 {
356 next = curr->next;
357 free_file_node(curr);
358 curr = next;
359 }
360
361 session->FileList = NULL;
362 }
363
test_Extract(void)364 static void test_Extract(void)
365 {
366 SESSION session;
367 HRESULT res;
368 struct FILELIST *node;
369
370 /* native windows crashes if
371 * - invalid parameters are sent in
372 * - you call EXTRACT_EXTRACTFILES without calling
373 * EXTRACT_FILLFILELIST first or at the same time
374 */
375
376 /* try to extract all files */
377 ZeroMemory(&session, sizeof(SESSION));
378 lstrcpyA(session.Destination, "dest");
379 session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES;
380 res = pExtract(&session, "extract.cab");
381 node = session.FileList;
382 ok(res == S_OK, "Expected S_OK, got %d\n", res);
383 ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
384 ok(session.Error.erfOper == FDIERROR_NONE,
385 "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
386 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
387 ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
388 ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
389 ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES),
390 "Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
391 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
392 ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
393 "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
394 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
395 ok(!session.FilterList, "Expected empty filter list\n");
396 ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
397 ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
398 ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
399 ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
400 ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
401 ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
402 ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
403 ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
404 ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
405 free_file_list(&session);
406
407 /* try fill file list operation */
408 ZeroMemory(&session, sizeof(SESSION));
409 lstrcpyA(session.Destination, "dest");
410 session.Operation = EXTRACT_FILLFILELIST;
411 res = pExtract(&session, "extract.cab");
412 node = session.FileList;
413 ok(res == S_OK, "Expected S_OK, got %d\n", res);
414 ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
415 ok(session.Error.erfOper == FDIERROR_NONE,
416 "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
417 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
418 ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
419 ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
420 ok(session.Operation == EXTRACT_FILLFILELIST,
421 "Expected EXTRACT_FILLFILELIST, got %d\n", session.Operation);
422 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
423 ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
424 "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
425 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
426 ok(!session.FilterList, "Expected empty filter list\n");
427 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
428 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
429 ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n");
430 ok(check_list(&node, "testdir\\c.txt", TRUE), "list entry wrong\n");
431 ok(check_list(&node, "b.txt", TRUE), "list entry wrong\n");
432 ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n");
433
434 /* try extract files operation once file list is filled */
435 session.Operation = EXTRACT_EXTRACTFILES;
436 res = pExtract(&session, "extract.cab");
437 node = session.FileList;
438 ok(res == S_OK, "Expected S_OK, got %d\n", res);
439 ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
440 ok(session.Error.erfOper == FDIERROR_NONE,
441 "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
442 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
443 ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
444 ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
445 ok(session.Operation == EXTRACT_EXTRACTFILES,
446 "Expected EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
447 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
448 ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
449 "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
450 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
451 ok(!session.FilterList, "Expected empty filter list\n");
452 ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
453 ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
454 ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
455 ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
456 ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
457 ok(RemoveDirectoryA("dest"), "Expected dest to exist\n");
458 ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
459 ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
460 ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
461 ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
462
463 /* Extract does not extract files if the dest dir does not exist */
464 res = pExtract(&session, "extract.cab");
465 node = session.FileList;
466 ok(res == S_OK, "Expected S_OK, got %d\n", res);
467 ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
468 ok(session.Error.erfOper == FDIERROR_NONE,
469 "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
470 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
471 ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
472 ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
473 ok(session.Operation == EXTRACT_EXTRACTFILES,
474 "Expected EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
475 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
476 ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
477 "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
478 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
479 ok(!session.FilterList, "Expected empty filter list\n");
480 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
481 ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
482 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
483 ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
484 ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
485 ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
486 ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
487 ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
488
489 /* remove two of the files in the list */
490 node = session.FileList->next;
491 session.FileList->next = session.FileList->next->next;
492 free_file_node(node);
493 free_file_node(session.FileList->next->next);
494 session.FileList->next->next = NULL;
495 session.FilterList = NULL;
496 CreateDirectoryA("dest", NULL);
497 res = pExtract(&session, "extract.cab");
498 node = session.FileList;
499 ok(res == S_OK, "Expected S_OK, got %d\n", res);
500 ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
501 ok(session.Error.erfOper == FDIERROR_NONE,
502 "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
503 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
504 ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
505 ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount);
506 ok(session.Operation == EXTRACT_EXTRACTFILES,
507 "Expected EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
508 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
509 ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
510 "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
511 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
512 ok(!session.FilterList, "Expected empty filter list\n");
513 ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
514 ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
515 ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
516 ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
517 ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
518 ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
519 ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
520 ok(!check_list(&node, "a.txt", FALSE), "list entry wrong\n");
521 free_file_list(&session);
522
523 session.Operation = EXTRACT_FILLFILELIST;
524 session.FileList = NULL;
525 res = pExtract(&session, "extract.cab");
526 node = session.FileList;
527 ok(res == S_OK, "Expected S_OK, got %d\n", res);
528 ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
529 ok(session.Error.erfOper == FDIERROR_NONE,
530 "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
531 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
532 ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
533 ok(session.FileCount == 8, "Expected 8, got %d\n", session.FileCount);
534 ok(session.Operation == EXTRACT_FILLFILELIST,
535 "Expected EXTRACT_FILLFILELIST, got %d\n", session.Operation);
536 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
537 ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
538 "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
539 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
540 ok(!session.FilterList, "Expected empty filter list\n");
541 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
542 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
543 ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
544 ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
545 ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n");
546 ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
547 ok(!check_list(&node, "b.txt", FALSE), "list entry wrong\n");
548 ok(!check_list(&node, "a.txt", FALSE), "list entry wrong\n");
549
550 session.Operation = 0;
551 res = pExtract(&session, "extract.cab");
552 node = session.FileList;
553 ok(res == S_OK, "Expected S_OK, got %d\n", res);
554 ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
555 ok(session.Error.erfOper == FDIERROR_NONE,
556 "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
557 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
558 ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
559 ok(session.FileCount == 8, "Expected 8, got %d\n", session.FileCount);
560 ok(session.Operation == 0, "Expected 0, got %d\n", session.Operation);
561 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
562 ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
563 "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
564 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
565 ok(!session.FilterList, "Expected empty filter list\n");
566 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
567 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
568 ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
569 ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
570 ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n");
571 ok(check_list(&node, "testdir\\c.txt", TRUE), "list entry wrong\n");
572 ok(check_list(&node, "b.txt", TRUE), "list entry wrong\n");
573 ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n");
574
575 session.Operation = 0;
576 session.FilterList = session.FileList;
577 res = pExtract(&session, "extract.cab");
578 node = session.FileList;
579 ok(res == S_OK, "Expected S_OK, got %d\n", res);
580 ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize);
581 ok(session.Error.erfOper == FDIERROR_NONE,
582 "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper);
583 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
584 ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError);
585 ok(session.FileCount == 8, "Expected 8, got %d\n", session.FileCount);
586 ok(session.Operation == 0, "Expected 0, got %d\n", session.Operation);
587 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
588 ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"),
589 "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile);
590 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
591 ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
592 ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n");
593 ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
594 ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n");
595 ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
596 ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
597 ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
598 ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
599 node = session.FilterList;
600 ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n");
601 ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
602 ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n");
603 ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n");
604 free_file_list(&session);
605
606 /* cabinet does not exist */
607 ZeroMemory(&session, sizeof(SESSION));
608 lstrcpyA(session.Destination, "dest");
609 session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES;
610 res = pExtract(&session, "nonexistent.cab");
611 node = session.FileList;
612 ok(res == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND),
613 "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", res);
614 ok(session.Error.erfOper == FDIERROR_CABINET_NOT_FOUND,
615 "Expected FDIERROR_CABINET_NOT_FOUND, got %d\n", session.Error.erfOper);
616 ok(session.FileSize == 0, "Expected 0, got %d\n", session.FileSize);
617 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
618 ok(session.Error.fError == TRUE, "Expected TRUE, got %d\n", session.Error.fError);
619 ok(session.FileCount == 0, "Expected 0, got %d\n", session.FileCount);
620 ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES),
621 "Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
622 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
623 ok(!*session.CurrentFile, "Expected empty string, got %s\n", session.CurrentFile);
624 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
625 ok(!session.FilterList, "Expected empty filter list\n");
626 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n");
627 ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
628 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
629 ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
630 ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n");
631 ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry should not exist\n");
632 ok(!check_list(&node, "b.txt", FALSE), "list entry should not exist\n");
633 ok(!check_list(&node, "a.txt", FALSE), "list entry should not exist\n");
634 free_file_list(&session);
635
636 /* first file exists but is read-only */
637 createTestFile("dest\\a.txt");
638 SetFileAttributesA("dest\\a.txt", FILE_ATTRIBUTE_READONLY);
639 ok(getFileSize("dest\\a.txt") == 11, "Expected dest\\a.txt to be 11 bytes\n");
640 ZeroMemory(&session, sizeof(SESSION));
641 lstrcpyA(session.Destination, "dest");
642 session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES;
643 res = pExtract(&session, "extract.cab");
644 node = session.FileList;
645 ok(res == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) || res == E_FAIL,
646 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) or E_FAIL, got %08x\n", res);
647 ok(session.FileSize == 6, "Expected 6, got %d\n", session.FileSize);
648 ok(session.Error.erfOper == FDIERROR_USER_ABORT,
649 "Expected FDIERROR_USER_ABORT, got %d\n", session.Error.erfOper);
650 ok(session.Error.fError == TRUE, "Expected TRUE, got %d\n", session.Error.fError);
651 ok(session.FileCount == 1, "Expected 1, got %d\n", session.FileCount);
652 ok(!lstrcmpA(session.CurrentFile, "dest\\a.txt"),
653 "Expected dest\\a.txt, got %s\n", session.CurrentFile);
654 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
655 ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES),
656 "Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
657 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
658 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
659 ok(!session.FilterList, "Expected empty filter list\n");
660 ok(getFileSize("dest\\a.txt") == 11, "Expected dest\\a.txt to be 11 bytes\n");
661 ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to be read-only\n");
662 ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n");
663 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n");
664 ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
665 ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n");
666 ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry should not exist\n");
667 ok(!check_list(&node, "b.txt", FALSE), "list entry should not exist\n");
668 ok(!check_list(&node, "a.txt", FALSE), "list entry should not exist\n");
669 free_file_list(&session);
670
671 SetFileAttributesA("dest\\a.txt", FILE_ATTRIBUTE_NORMAL);
672 DeleteFileA("dest\\a.txt");
673
674 /* first file exists and is writable, third file exists but is read-only */
675 createTestFile("dest\\a.txt");
676 createTestFile("dest\\testdir\\c.txt");
677 SetFileAttributesA("dest\\testdir\\c.txt", FILE_ATTRIBUTE_READONLY);
678 ZeroMemory(&session, sizeof(SESSION));
679 lstrcpyA(session.Destination, "dest");
680 session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES;
681 res = pExtract(&session, "extract.cab");
682 node = session.FileList;
683 ok(res == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) || res == E_FAIL,
684 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) or E_FAIL, got %08x\n", res);
685 ok(session.FileSize == 26, "Expected 26, got %d\n", session.FileSize);
686 ok(session.Error.erfOper == FDIERROR_USER_ABORT,
687 "Expected FDIERROR_USER_ABORT, got %d\n", session.Error.erfOper);
688 ok(session.Error.fError == TRUE, "Expected TRUE, got %d\n", session.Error.fError);
689 ok(session.FileCount == 3, "Expected 3, got %d\n", session.FileCount);
690 ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\c.txt"),
691 "Expected dest\\c.txt, got %s\n", session.CurrentFile);
692 ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType);
693 ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES),
694 "Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation);
695 ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination);
696 ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved);
697 ok(!session.FilterList, "Expected empty filter list\n");
698 ok(getFileSize("dest\\a.txt") == 6, "Expected dest\\a.txt to be 6 bytes\n");
699 ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n");
700 ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n");
701 ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to be read-only\n");
702 ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n");
703 ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n");
704 ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n");
705 ok(!check_list(&node, "b.txt", FALSE), "list entry wrong\n");
706 ok(!check_list(&node, "a.txt", TRUE), "list entry wrong\n");
707 free_file_list(&session);
708
709 SetFileAttributesA("dest\\testdir\\c.txt", FILE_ATTRIBUTE_NORMAL);
710 DeleteFileA("dest\\testdir\\c.txt");
711
712 ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n");
713 ok(RemoveDirectoryA("dest"), "Expected dest to exist\n");
714 }
715
START_TEST(extract)716 START_TEST(extract)
717 {
718 init_function_pointers();
719 create_test_files();
720 create_cab_file();
721
722 test_Extract();
723
724 delete_test_files();
725 }
726