ntdll: move relocations from mapping into loader
[wine/kumbayo.git] / dlls / cabinet / tests / fdi.c
blob7c10b3d1663bb6b1d8232e8054d1b97cf1e3889c
1 /*
2 * Unit tests for the File Decompression Interface
4 * Copyright (C) 2006 James Hawkins
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdio.h>
22 #include <windows.h>
23 #include "fci.h"
24 #include "fdi.h"
25 #include "wine/test.h"
27 /* make the max size large so there is only one cab file */
28 #define MEDIA_SIZE 999999999
29 #define FOLDER_THRESHOLD 900000
31 CHAR CURR_DIR[MAX_PATH];
33 /* FDI callbacks */
35 static void *fdi_alloc(ULONG cb)
37 return HeapAlloc(GetProcessHeap(), 0, cb);
40 static void *fdi_alloc_bad(ULONG cb)
42 return NULL;
45 static void fdi_free(void *pv)
47 HeapFree(GetProcessHeap(), 0, pv);
50 static INT_PTR fdi_open(char *pszFile, int oflag, int pmode)
52 HANDLE handle;
53 handle = CreateFileA(pszFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
54 OPEN_EXISTING, 0, NULL );
55 if (handle == INVALID_HANDLE_VALUE)
56 return 0;
57 return (INT_PTR) handle;
60 static UINT fdi_read(INT_PTR hf, void *pv, UINT cb)
62 HANDLE handle = (HANDLE) hf;
63 DWORD dwRead;
64 if (ReadFile(handle, pv, cb, &dwRead, NULL))
65 return dwRead;
66 return 0;
69 static UINT fdi_write(INT_PTR hf, void *pv, UINT cb)
71 HANDLE handle = (HANDLE) hf;
72 DWORD dwWritten;
73 if (WriteFile(handle, pv, cb, &dwWritten, NULL))
74 return dwWritten;
75 return 0;
78 static int fdi_close(INT_PTR hf)
80 HANDLE handle = (HANDLE) hf;
81 return CloseHandle(handle) ? 0 : -1;
84 static long fdi_seek(INT_PTR hf, long dist, int seektype)
86 HANDLE handle = (HANDLE) hf;
87 return SetFilePointer(handle, dist, NULL, seektype);
90 static void test_FDICreate(void)
92 HFDI hfdi;
93 ERF erf;
95 erf.erfOper = 0xcafefeed;
96 erf.erfType = 0xdeadbabe;
97 erf.fError = 0xdecaface;
99 /* native crashes if pfnalloc is NULL */
101 /* FDICreate does not crash with a NULL pfnfree,
102 * but FDIDestroy will crash when it tries to access it.
104 if (0)
106 SetLastError(0xdeadbeef);
107 hfdi = FDICreate(fdi_alloc, NULL, fdi_open, fdi_read,
108 fdi_write, fdi_close, fdi_seek,
109 cpuUNKNOWN, &erf);
110 ok(hfdi != NULL, "Expected non-NULL context\n");
111 ok(GetLastError() == 0xdeadbeef,
112 "Expected 0xdeadbeef, got %d\n", GetLastError());
113 ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
114 ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
115 ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
117 FDIDestroy(hfdi);
120 SetLastError(0xdeadbeef);
121 hfdi = FDICreate(fdi_alloc, fdi_free, NULL, fdi_read,
122 fdi_write, fdi_close, fdi_seek,
123 cpuUNKNOWN, &erf);
124 ok(hfdi != NULL, "Expected non-NULL context\n");
125 ok(GetLastError() == 0xdeadbeef,
126 "Expected 0xdeadbeef, got %d\n", GetLastError());
127 ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
128 ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
129 ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
131 FDIDestroy(hfdi);
133 SetLastError(0xdeadbeef);
134 hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, NULL,
135 fdi_write, fdi_close, fdi_seek,
136 cpuUNKNOWN, &erf);
137 ok(hfdi != NULL, "Expected non-NULL context\n");
138 ok(GetLastError() == 0xdeadbeef,
139 "Expected 0xdeadbeef, got %d\n", GetLastError());
140 ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
141 ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
142 ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
144 FDIDestroy(hfdi);
146 SetLastError(0xdeadbeef);
147 hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
148 NULL, fdi_close, fdi_seek,
149 cpuUNKNOWN, &erf);
150 ok(hfdi != NULL, "Expected non-NULL context\n");
151 ok(GetLastError() == 0xdeadbeef,
152 "Expected 0xdeadbeef, got %d\n", GetLastError());
153 ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
154 ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
155 ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
157 FDIDestroy(hfdi);
159 SetLastError(0xdeadbeef);
160 hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
161 fdi_write, NULL, fdi_seek,
162 cpuUNKNOWN, &erf);
163 ok(hfdi != NULL, "Expected non-NULL context\n");
164 ok(GetLastError() == 0xdeadbeef,
165 "Expected 0xdeadbeef, got %d\n", GetLastError());
166 ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
167 ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
168 ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
170 FDIDestroy(hfdi);
172 SetLastError(0xdeadbeef);
173 hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
174 fdi_write, fdi_close, NULL,
175 cpuUNKNOWN, &erf);
176 ok(hfdi != NULL, "Expected non-NULL context\n");
177 ok(GetLastError() == 0xdeadbeef,
178 "Expected 0xdeadbeef, got %d\n", GetLastError());
179 ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
180 ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
181 ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
183 FDIDestroy(hfdi);
185 SetLastError(0xdeadbeef);
186 hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
187 fdi_write, fdi_close, fdi_seek,
188 cpuUNKNOWN, NULL);
189 ok(hfdi != NULL, "Expected non-NULL context\n");
190 ok(GetLastError() == 0xdeadbeef,
191 "Expected 0xdeadbeef, got %d\n", GetLastError());
192 ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
193 ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
194 ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
196 FDIDestroy(hfdi);
198 /* bad cpu type */
199 SetLastError(0xdeadbeef);
200 hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
201 fdi_write, fdi_close, fdi_seek,
202 0xcafebabe, &erf);
203 ok(hfdi != NULL, "Expected non-NULL context\n");
204 ok(GetLastError() == 0xdeadbeef,
205 "Expected 0xdeadbeef, got %d\n", GetLastError());
206 ok(erf.erfOper == 0xcafefeed, "Expected 0xcafefeed, got %d\n", erf.erfOper);
207 ok(erf.erfType == 0xdeadbabe, "Expected 0xdeadbabe, got %d\n", erf.erfType);
208 ok(erf.fError == 0xdecaface, "Expected 0xdecaface, got %d\n", erf.fError);
210 FDIDestroy(hfdi);
212 /* pfnalloc fails */
213 SetLastError(0xdeadbeef);
214 hfdi = FDICreate(fdi_alloc_bad, fdi_free, fdi_open, fdi_read,
215 fdi_write, fdi_close, fdi_seek,
216 cpuUNKNOWN, &erf);
217 ok(hfdi == NULL, "Expected NULL context, got %p\n", hfdi);
218 ok(erf.erfOper == FDIERROR_ALLOC_FAIL,
219 "Expected FDIERROR_ALLOC_FAIL, got %d\n", erf.erfOper);
220 ok(erf.fError == TRUE, "Expected TRUE, got %d\n", erf.fError);
221 todo_wine
223 ok(GetLastError() == 0xdeadbeef,
224 "Expected 0xdeadbeef, got %d\n", GetLastError());
225 ok(erf.erfType == 0, "Expected 0, got %d\n", erf.erfType);
229 static void test_FDIDestroy(void)
231 HFDI hfdi;
232 ERF erf;
233 BOOL ret;
235 /* native crashes if hfdi is NULL or invalid */
237 hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
238 fdi_write, fdi_close, fdi_seek,
239 cpuUNKNOWN, &erf);
240 ok(hfdi != NULL, "Expected non-NULL context\n");
242 /* successfully destroy hfdi */
243 ret = FDIDestroy(hfdi);
244 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
246 /* native crashes if you try to destroy hfdi twice */
247 if (0)
249 /* try to destroy hfdi again */
250 ret = FDIDestroy(hfdi);
251 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
255 static void createTestFile(const CHAR *name)
257 HANDLE file;
258 DWORD written;
260 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
261 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
262 WriteFile(file, name, strlen(name), &written, NULL);
263 WriteFile(file, "\n", strlen("\n"), &written, NULL);
264 CloseHandle(file);
267 static void create_test_files(void)
269 int len;
271 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
272 len = lstrlenA(CURR_DIR);
274 if(len && (CURR_DIR[len-1] == '\\'))
275 CURR_DIR[len-1] = 0;
277 createTestFile("a.txt");
278 createTestFile("b.txt");
279 CreateDirectoryA("testdir", NULL);
280 createTestFile("testdir\\c.txt");
281 createTestFile("testdir\\d.txt");
284 static void delete_test_files(void)
286 DeleteFileA("a.txt");
287 DeleteFileA("b.txt");
288 DeleteFileA("testdir\\c.txt");
289 DeleteFileA("testdir\\d.txt");
290 RemoveDirectoryA("testdir");
292 DeleteFileA("extract.cab");
295 /* FCI callbacks */
297 static void *mem_alloc(ULONG cb)
299 return HeapAlloc(GetProcessHeap(), 0, cb);
302 static void mem_free(void *memory)
304 HeapFree(GetProcessHeap(), 0, memory);
307 static BOOL get_next_cabinet(PCCAB pccab, ULONG cbPrevCab, void *pv)
309 return TRUE;
312 static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
314 return 0;
317 static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
318 BOOL fContinuation, void *pv)
320 return 0;
323 static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
325 HANDLE handle;
326 DWORD dwAccess = 0;
327 DWORD dwShareMode = 0;
328 DWORD dwCreateDisposition = OPEN_EXISTING;
330 dwAccess = GENERIC_READ | GENERIC_WRITE;
331 /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
332 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
334 if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
335 dwCreateDisposition = OPEN_EXISTING;
336 else
337 dwCreateDisposition = CREATE_NEW;
339 handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
340 dwCreateDisposition, 0, NULL);
342 ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
344 return (INT_PTR)handle;
347 static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
349 HANDLE handle = (HANDLE)hf;
350 DWORD dwRead;
351 BOOL res;
353 res = ReadFile(handle, memory, cb, &dwRead, NULL);
354 ok(res, "Failed to ReadFile\n");
356 return dwRead;
359 static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
361 HANDLE handle = (HANDLE)hf;
362 DWORD dwWritten;
363 BOOL res;
365 res = WriteFile(handle, memory, cb, &dwWritten, NULL);
366 ok(res, "Failed to WriteFile\n");
368 return dwWritten;
371 static int fci_close(INT_PTR hf, int *err, void *pv)
373 HANDLE handle = (HANDLE)hf;
374 ok(CloseHandle(handle), "Failed to CloseHandle\n");
376 return 0;
379 static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
381 HANDLE handle = (HANDLE)hf;
382 DWORD ret;
384 ret = SetFilePointer(handle, dist, NULL, seektype);
385 ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
387 return ret;
390 static int fci_delete(char *pszFile, int *err, void *pv)
392 BOOL ret = DeleteFileA(pszFile);
393 ok(ret, "Failed to DeleteFile %s\n", pszFile);
395 return 0;
398 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
400 LPSTR tempname;
402 tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
403 GetTempFileNameA(".", "xx", 0, tempname);
405 if (tempname && (strlen(tempname) < (unsigned)cbTempName))
407 lstrcpyA(pszTempName, tempname);
408 HeapFree(GetProcessHeap(), 0, tempname);
409 return TRUE;
412 HeapFree(GetProcessHeap(), 0, tempname);
414 return FALSE;
417 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
418 USHORT *pattribs, int *err, void *pv)
420 BY_HANDLE_FILE_INFORMATION finfo;
421 FILETIME filetime;
422 HANDLE handle;
423 DWORD attrs;
424 BOOL res;
426 handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
427 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
429 ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
431 res = GetFileInformationByHandle(handle, &finfo);
432 ok(res, "Expected GetFileInformationByHandle to succeed\n");
434 FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
435 FileTimeToDosDateTime(&filetime, pdate, ptime);
437 attrs = GetFileAttributes(pszName);
438 ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
439 /* fixme: should convert attrs to *pattribs, make sure
440 * have a test that catches the fact that we don't?
443 return (INT_PTR)handle;
446 static void add_file(HFCI hfci, char *file)
448 char path[MAX_PATH];
449 BOOL res;
451 lstrcpyA(path, CURR_DIR);
452 lstrcatA(path, "\\");
453 lstrcatA(path, file);
455 res = FCIAddFile(hfci, path, file, FALSE, get_next_cabinet, progress,
456 get_open_info, tcompTYPE_MSZIP);
457 ok(res, "Expected FCIAddFile to succeed\n");
460 static void set_cab_parameters(PCCAB pCabParams)
462 ZeroMemory(pCabParams, sizeof(CCAB));
464 pCabParams->cb = MEDIA_SIZE;
465 pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
466 pCabParams->setID = 0xbeef;
467 lstrcpyA(pCabParams->szCabPath, CURR_DIR);
468 lstrcatA(pCabParams->szCabPath, "\\");
469 lstrcpyA(pCabParams->szCab, "extract.cab");
472 static void create_cab_file(void)
474 CCAB cabParams;
475 HFCI hfci;
476 ERF erf;
477 static CHAR a_txt[] = "a.txt",
478 b_txt[] = "b.txt",
479 testdir_c_txt[] = "testdir\\c.txt",
480 testdir_d_txt[] = "testdir\\d.txt";
481 BOOL res;
483 set_cab_parameters(&cabParams);
485 hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
486 fci_read, fci_write, fci_close, fci_seek, fci_delete,
487 get_temp_file, &cabParams, NULL);
489 ok(hfci != NULL, "Failed to create an FCI context\n");
491 add_file(hfci, a_txt);
492 add_file(hfci, b_txt);
493 add_file(hfci, testdir_c_txt);
494 add_file(hfci, testdir_d_txt);
496 res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
497 ok(res, "Failed to flush the cabinet\n");
499 res = FCIDestroy(hfci);
500 ok(res, "Failed to destroy the cabinet\n");
503 static void test_FDIIsCabinet(void)
505 ERF erf;
506 BOOL ret;
507 HFDI hfdi;
508 INT_PTR fd;
509 FDICABINETINFO cabinfo;
510 char temp[] = "temp.txt";
511 char extract[] = "extract.cab";
513 create_test_files();
514 create_cab_file();
516 hfdi = FDICreate(fdi_alloc, fdi_free, fdi_open, fdi_read,
517 fdi_write, fdi_close, fdi_seek,
518 cpuUNKNOWN, &erf);
519 ok(hfdi != NULL, "Expected non-NULL context\n");
521 /* native crashes if hfdi or cabinfo are NULL or invalid */
523 /* invalid file handle */
524 ZeroMemory(&cabinfo, sizeof(FDICABINETINFO));
525 SetLastError(0xdeadbeef);
526 ret = FDIIsCabinet(hfdi, (int)INVALID_HANDLE_VALUE, &cabinfo);
527 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
528 ok(GetLastError() == ERROR_INVALID_HANDLE,
529 "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
530 ok(cabinfo.cbCabinet == 0, "Expected 0, got %ld\n", cabinfo.cbCabinet);
531 ok(cabinfo.cFiles == 0, "Expected 0, got %d\n", cabinfo.cFiles);
532 ok(cabinfo.cFolders == 0, "Expected 0, got %d\n", cabinfo.cFolders);
533 ok(cabinfo.iCabinet == 0, "Expected 0, got %d\n", cabinfo.iCabinet);
534 ok(cabinfo.setID == 0, "Expected 0, got %d\n", cabinfo.setID);
536 createTestFile("temp.txt");
537 fd = fdi_open(temp, 0, 0);
539 /* file handle doesn't point to a cabinet */
540 ZeroMemory(&cabinfo, sizeof(FDICABINETINFO));
541 SetLastError(0xdeadbeef);
542 ret = FDIIsCabinet(hfdi, fd, &cabinfo);
543 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
544 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
545 ok(cabinfo.cbCabinet == 0, "Expected 0, got %ld\n", cabinfo.cbCabinet);
546 ok(cabinfo.cFiles == 0, "Expected 0, got %d\n", cabinfo.cFiles);
547 ok(cabinfo.cFolders == 0, "Expected 0, got %d\n", cabinfo.cFolders);
548 ok(cabinfo.iCabinet == 0, "Expected 0, got %d\n", cabinfo.iCabinet);
549 ok(cabinfo.setID == 0, "Expected 0, got %d\n", cabinfo.setID);
551 fdi_close(fd);
552 DeleteFileA("temp.txt");
554 /* try a real cab */
555 fd = fdi_open(extract, 0, 0);
556 ZeroMemory(&cabinfo, sizeof(FDICABINETINFO));
557 SetLastError(0xdeadbeef);
558 ret = FDIIsCabinet(hfdi, fd, &cabinfo);
559 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
560 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError());
561 ok(cabinfo.cFiles == 4, "Expected 4, got %d\n", cabinfo.cFiles);
562 ok(cabinfo.cFolders == 1, "Expected 1, got %d\n", cabinfo.cFolders);
563 ok(cabinfo.setID == 0xbeef, "Expected 0xbeef, got %d\n", cabinfo.setID);
564 todo_wine
566 ok(cabinfo.cbCabinet == 182, "Expected 182, got %ld\n", cabinfo.cbCabinet);
567 ok(cabinfo.iCabinet == 0, "Expected 0, got %d\n", cabinfo.iCabinet);
570 fdi_close(fd);
571 FDIDestroy(hfdi);
572 delete_test_files();
575 START_TEST(fdi)
577 test_FDICreate();
578 test_FDIDestroy();
579 test_FDIIsCabinet();