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