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 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 */ 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 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 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 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 126 static void * CDECL mem_alloc(ULONG cb) 127 { 128 return HeapAlloc(GetProcessHeap(), 0, cb); 129 } 130 131 static void CDECL mem_free(void *memory) 132 { 133 HeapFree(GetProcessHeap(), 0, memory); 134 } 135 136 static BOOL CDECL get_next_cabinet(PCCAB pccab, ULONG cbPrevCab, void *pv) 137 { 138 return TRUE; 139 } 140 141 static LONG CDECL progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv) 142 { 143 return 0; 144 } 145 146 static int CDECL file_placed(PCCAB pccab, char *pszFile, LONG cbFile, 147 BOOL fContinuation, void *pv) 148 { 149 return 0; 150 } 151 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 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 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 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 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 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 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 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 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 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 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 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 344 static void free_file_node(struct FILELIST *node) 345 { 346 HeapFree(GetProcessHeap(), 0, node->FileName); 347 HeapFree(GetProcessHeap(), 0, node); 348 } 349 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 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 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