/* returns the number of files that are in both the linked list and szFileList */ static DWORD fill_file_list(SESSION *session, LPCSTR szCabName, LPCSTR szFileList) { DWORD dwNumFound = 0; struct FILELIST *pNode; session->Operation |= EXTRACT_FILLFILELIST; if (pExtract(session, szCabName) != S_OK) { session->Operation &= ~EXTRACT_FILLFILELIST; return -1; } pNode = session->FileList; while (pNode) { if (!file_in_list(pNode->FileName, szFileList)) pNode->DoExtract = FALSE; else dwNumFound++; pNode = pNode->next; } session->Operation &= ~EXTRACT_FILLFILELIST; return dwNumFound; }
/*********************************************************************** * Extract (URLMON.@) */ HRESULT WINAPI Extract(void *dest, LPCSTR szCabName) { HRESULT (WINAPI *pExtract)(void *, LPCSTR); if (!hCabinet) hCabinet = LoadLibraryA("cabinet.dll"); if (!hCabinet) return HRESULT_FROM_WIN32(GetLastError()); pExtract = (void *)GetProcAddress(hCabinet, "Extract"); if (!pExtract) return HRESULT_FROM_WIN32(GetLastError()); return pExtract(dest, szCabName); }
/*********************************************************************** * ExtractFilesA (ADVPACK.@) * * Extracts the specified files from a cab archive into * a destination directory. * * PARAMS * CabName [I] Filename of the cab archive. * ExpandDir [I] Destination directory for the extracted files. * Flags [I] Reserved. * FileList [I] Optional list of files to extract. See NOTES. * LReserved [I] Reserved. Must be NULL. * Reserved [I] Reserved. Must be 0. * * RETURNS * Success: S_OK. * Failure: E_FAIL. * * NOTES * FileList is a colon-separated list of filenames. If FileList is * non-NULL, only the files in the list will be extracted from the * cab file, otherwise all files will be extracted. Any number of * spaces, tabs, or colons can be before or after the list, but * the list itself must only be separated by colons. */ HRESULT WINAPI ExtractFilesA(LPCSTR CabName, LPCSTR ExpandDir, DWORD Flags, LPCSTR FileList, LPVOID LReserved, DWORD Reserved) { SESSION session; HMODULE hCabinet; HRESULT res = S_OK; DWORD dwFileCount = 0; DWORD dwFilesFound = 0; LPSTR szConvertedList = NULL; TRACE("(%s, %s, %d, %s, %p, %d)\n", debugstr_a(CabName), debugstr_a(ExpandDir), Flags, debugstr_a(FileList), LReserved, Reserved); if (!CabName || !ExpandDir) return E_INVALIDARG; if (GetFileAttributesA(ExpandDir) == INVALID_FILE_ATTRIBUTES) return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); hCabinet = LoadLibraryA("cabinet.dll"); if (!hCabinet) return E_FAIL; ZeroMemory(&session, sizeof(SESSION)); pExtract = (void *)GetProcAddress(hCabinet, "Extract"); if (!pExtract) { res = E_FAIL; goto done; } lstrcpyA(session.Destination, ExpandDir); if (FileList) { szConvertedList = convert_file_list(FileList, &dwFileCount); if (!szConvertedList) { res = E_FAIL; goto done; } dwFilesFound = fill_file_list(&session, CabName, szConvertedList); if (dwFilesFound != dwFileCount) { res = E_FAIL; goto done; } } else session.Operation |= EXTRACT_FILLFILELIST; session.Operation |= EXTRACT_EXTRACTFILES; res = pExtract(&session, CabName); done: free_file_list(&session); FreeLibrary(hCabinet); HeapFree(GetProcessHeap(), 0, szConvertedList); return res; }
static void test_Extract(void) { SESSION session; HRESULT res; struct FILELIST *node; /* native windows crashes if * - invalid parameters are sent in * - you call EXTRACT_EXTRACTFILES without calling * EXTRACT_FILLFILELIST first or at the same time */ /* try to extract all files */ ZeroMemory(&session, sizeof(SESSION)); lstrcpyA(session.Destination, "dest"); session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES; res = pExtract(&session, "extract.cab"); node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError); ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount); ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES), "Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n"); ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n"); ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n"); ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n"); ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); free_file_list(&session); /* try fill file list operation */ ZeroMemory(&session, sizeof(SESSION)); lstrcpyA(session.Destination, "dest"); session.Operation = EXTRACT_FILLFILELIST; res = pExtract(&session, "extract.cab"); node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError); ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount); ok(session.Operation == EXTRACT_FILLFILELIST, "Expected EXTRACT_FILLFILELIST, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n"); ok(check_list(&node, "testdir\\c.txt", TRUE), "list entry wrong\n"); ok(check_list(&node, "b.txt", TRUE), "list entry wrong\n"); ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n"); /* try extract files operation once file list is filled */ session.Operation = EXTRACT_EXTRACTFILES; res = pExtract(&session, "extract.cab"); node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError); ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount); ok(session.Operation == EXTRACT_EXTRACTFILES, "Expected EXTRACT_EXTRACTFILES, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n"); ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n"); ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n"); ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n"); ok(RemoveDirectoryA("dest"), "Expected dest to exist\n"); ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); /* Extract does not extract files if the dest dir does not exist */ res = pExtract(&session, "extract.cab"); node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError); ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount); ok(session.Operation == EXTRACT_EXTRACTFILES, "Expected EXTRACT_EXTRACTFILES, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n"); ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); /* remove two of the files in the list */ node = session.FileList->next; session.FileList->next = session.FileList->next->next; free_file_node(node); free_file_node(session.FileList->next->next); session.FileList->next->next = NULL; session.FilterList = NULL; CreateDirectoryA("dest", NULL); res = pExtract(&session, "extract.cab"); node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError); ok(session.FileCount == 4, "Expected 4, got %d\n", session.FileCount); ok(session.Operation == EXTRACT_EXTRACTFILES, "Expected EXTRACT_EXTRACTFILES, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n"); ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); ok(!check_list(&node, "a.txt", FALSE), "list entry wrong\n"); free_file_list(&session); session.Operation = EXTRACT_FILLFILELIST; session.FileList = NULL; res = pExtract(&session, "extract.cab"); node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError); ok(session.FileCount == 8, "Expected 8, got %d\n", session.FileCount); ok(session.Operation == EXTRACT_FILLFILELIST, "Expected EXTRACT_FILLFILELIST, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n"); ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); ok(!check_list(&node, "b.txt", FALSE), "list entry wrong\n"); ok(!check_list(&node, "a.txt", FALSE), "list entry wrong\n"); session.Operation = 0; res = pExtract(&session, "extract.cab"); node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError); ok(session.FileCount == 8, "Expected 8, got %d\n", session.FileCount); ok(session.Operation == 0, "Expected 0, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n"); ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n"); ok(check_list(&node, "testdir\\c.txt", TRUE), "list entry wrong\n"); ok(check_list(&node, "b.txt", TRUE), "list entry wrong\n"); ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n"); session.Operation = 0; session.FilterList = session.FileList; res = pExtract(&session, "extract.cab"); node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Error.fError == FALSE, "Expected FALSE, got %d\n", session.Error.fError); ok(session.FileCount == 8, "Expected 8, got %d\n", session.FileCount); ok(session.Operation == 0, "Expected 0, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n"); ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n"); ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n"); ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); node = session.FilterList; ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); free_file_list(&session); /* cabinet does not exist */ ZeroMemory(&session, sizeof(SESSION)); lstrcpyA(session.Destination, "dest"); session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES; res = pExtract(&session, "nonexistent.cab"); node = session.FileList; ok(res == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got %08x\n", res); ok(session.Error.erfOper == FDIERROR_CABINET_NOT_FOUND, "Expected FDIERROR_CABINET_NOT_FOUND, got %d\n", session.Error.erfOper); ok(session.FileSize == 0, "Expected 0, got %d\n", session.FileSize); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Error.fError == TRUE, "Expected TRUE, got %d\n", session.Error.fError); ok(session.FileCount == 0, "Expected 0, got %d\n", session.FileCount); ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES), "Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!*session.CurrentFile, "Expected empty string, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n"); ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n"); ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry should not exist\n"); ok(!check_list(&node, "b.txt", FALSE), "list entry should not exist\n"); ok(!check_list(&node, "a.txt", FALSE), "list entry should not exist\n"); free_file_list(&session); /* first file exists */ createTestFile("dest\\a.txt"); SetFileAttributes("dest\\a.txt", FILE_ATTRIBUTE_READONLY); ZeroMemory(&session, sizeof(SESSION)); lstrcpyA(session.Destination, "dest"); session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES; res = pExtract(&session, "extract.cab"); node = session.FileList; todo_wine { ok(res == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) || res == E_FAIL, "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) or E_FAIL, got %08x\n", res); ok(session.FileSize == 6, "Expected 6, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_USER_ABORT, "Expected FDIERROR_USER_ABORT, got %d\n", session.Error.erfOper); ok(session.Error.fError == TRUE, "Expected TRUE, got %d\n", session.Error.fError); ok(session.FileCount == 1, "Expected 1, got %d\n", session.FileCount); ok(!lstrcmpA(session.CurrentFile, "dest\\a.txt"), "Expected dest\\a.txt, got %s\n", session.CurrentFile); } ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES), "Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n"); todo_wine { ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n"); ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry should not exist\n"); ok(!check_list(&node, "b.txt", FALSE), "list entry should not exist\n"); } ok(!check_list(&node, "a.txt", FALSE), "list entry should not exist\n"); free_file_list(&session); SetFileAttributesA("dest\\a.txt", FILE_ATTRIBUTE_NORMAL); DeleteFileA("dest\\a.txt"); /* third file exists */ createTestFile("dest\\testdir\\c.txt"); SetFileAttributes("dest\\testdir\\c.txt", FILE_ATTRIBUTE_READONLY); ZeroMemory(&session, sizeof(SESSION)); lstrcpyA(session.Destination, "dest"); session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES; res = pExtract(&session, "extract.cab"); node = session.FileList; todo_wine { ok(res == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) || res == E_FAIL, "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) or E_FAIL, got %08x\n", res); ok(session.FileSize == 26, "Expected 26, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_USER_ABORT, "Expected FDIERROR_USER_ABORT, got %d\n", session.Error.erfOper); ok(session.Error.fError == TRUE, "Expected TRUE, got %d\n", session.Error.fError); ok(session.FileCount == 3, "Expected 3, got %d\n", session.FileCount); ok(!lstrcmpA(session.CurrentFile, "dest\\testdir\\c.txt"), "Expected dest\\c.txt, got %s\n", session.CurrentFile); } ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); ok(session.Operation == (EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES), "Expected EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES, got %d\n", session.Operation); ok(!lstrcmpA(session.Destination, "dest"), "Expected dest, got %s\n", session.Destination); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n"); ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); todo_wine { ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n"); } ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); ok(!check_list(&node, "b.txt", FALSE), "list entry wrong\n"); ok(!check_list(&node, "a.txt", TRUE), "list entry wrong\n"); free_file_list(&session); SetFileAttributesA("dest\\testdir\\c.txt", FILE_ATTRIBUTE_NORMAL); DeleteFileA("dest\\testdir\\c.txt"); ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n"); ok(RemoveDirectoryA("dest"), "Expected dest to exist\n"); }