1 rizwank 1.1 /*
2 * testfdi.c
3 *
4 * Demonstrates how to use the FDI library APIs
5 */
6 #include <windows.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <io.h>
11 #include <fcntl.h>
12 #include <dos.h>
13 #include <sys/stat.h>
14
15 #include "..\..\include\fdi.h"
16
17
18 /*
19 * Function prototypes
20 */
21 BOOL test_fdi(char *cabinet_file);
22 rizwank 1.1 int get_percentage(unsigned long a, unsigned long b);
23 char *return_fdi_error_string(FDIERROR err);
24
25
26 /*
27 * Destination directory for extracted files
28 */
29 char dest_dir[256];
30
31
32 void main(int argc, char **argv)
33 {
34 if (argc != 3)
35 {
36 printf(
37 "TESTFDI - Demonstrates how to use the FDI library API calls\n"
38 "\n"
39 "Usage: TESTFDI cabinet dest_dir\n"
40 "\n"
41 "Where <cabinet> is the name of a cabinet file, and <dest_dir>\n"
42 "is the destination for the files extracted\n"
43 rizwank 1.1 "\n"
44 " e.g. testfdi c:\\test1.cab c:\\\n"
45 "\n"
46 );
47
48 exit(0);
49 }
50
51 strcpy(dest_dir, argv[2]);
52
53 if (test_fdi(argv[1]) == TRUE)
54 printf("TESTFDI was successful\n");
55 else
56 printf("TESTFDI failed\n");
57
58 exit(0);
59 }
60
61
62 /*
63 * Memory allocation function
64 rizwank 1.1 */
65 FNALLOC(mem_alloc)
66 {
67 return malloc(cb);
68 }
69
70
71 /*
72 * Memory free function
73 */
74 FNFREE(mem_free)
75 {
76 free(pv);
77 }
78
79
80 FNOPEN(file_open)
81 {
82 return _open(pszFile, oflag, pmode);
83 }
84
85 rizwank 1.1
86 FNREAD(file_read)
87 {
88 return _read(hf, pv, cb);
89 }
90
91
92 FNWRITE(file_write)
93 {
94 return _write(hf, pv, cb);
95 }
96
97
98 FNCLOSE(file_close)
99 {
100 return _close(hf);
101 }
102
103
104 FNSEEK(file_seek)
105 {
106 rizwank 1.1 return _lseek(hf, dist, seektype);
107 }
108
109
110 FNFDINOTIFY(notification_function)
111 {
112 switch (fdint)
113 {
114 case fdintCABINET_INFO: // general information about the cabinet
115 printf(
116 "fdintCABINET_INFO\n"
117 " next cabinet = %s\n"
118 " next disk = %s\n"
119 " cabinet path = %s\n"
120 " cabinet set ID = %d\n"
121 " cabinet # in set = %d (zero based)\n"
122 "\n",
123 pfdin->psz1,
124 pfdin->psz2,
125 pfdin->psz3,
126 pfdin->setID,
127 rizwank 1.1 pfdin->iCabinet
128 );
129
130 return 0;
131
132 case fdintPARTIAL_FILE: // first file in cabinet is continuation
133 printf(
134 "fdintPARTIAL_FILE\n"
135 " name of continued file = %s\n"
136 " name of cabinet where file starts = %s\n"
137 " name of disk where file starts = %s\n",
138 pfdin->psz1,
139 pfdin->psz2,
140 pfdin->psz3
141 );
142 return 0;
143
144 case fdintCOPY_FILE: // file to be copied
145 {
146 int response;
147 int handle;
148 rizwank 1.1 char destination[256];
149
150 printf(
151 "fdintCOPY_FILE\n"
152 " file name in cabinet = %s\n"
153 " uncompressed file size = %d\n"
154 " copy this file? (y/n): ",
155 pfdin->psz1,
156 pfdin->cb
157 );
158
159 do
160 {
161 response = getc(stdin);
162 response = toupper(response);
163 } while (response != 'Y' && response != 'N');
164
165 printf("\n");
166
167 if (response == 'Y')
168 {
169 rizwank 1.1 sprintf(
170 destination,
171 "%s%s",
172 dest_dir,
173 pfdin->psz1
174 );
175
176 handle = file_open(
177 destination,
178 _O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL,
179 _S_IREAD | _S_IWRITE
180 );
181
182 return handle;
183 }
184 else
185 {
186 return 0; /* skip file */
187 }
188 }
189
190 rizwank 1.1 case fdintCLOSE_FILE_INFO: // close the file, set relevant info
191 {
192 HANDLE handle;
193 DWORD attrs;
194 char destination[256];
195
196 printf(
197 "fdintCLOSE_FILE_INFO\n"
198 " file name in cabinet = %s\n"
199 "\n",
200 pfdin->psz1
201 );
202
203 sprintf(
204 destination,
205 "%s%s",
206 dest_dir,
207 pfdin->psz1
208 );
209
210 file_close(pfdin->hf);
211 rizwank 1.1
212
213 /*
214 * Set date/time
215 *
216 * Need Win32 type handle for to set date/time
217 */
218 handle = CreateFile(
219 destination,
220 GENERIC_READ | GENERIC_WRITE,
221 FILE_SHARE_READ,
222 NULL,
223 OPEN_EXISTING,
224 FILE_ATTRIBUTE_NORMAL,
225 NULL
226 );
227
228 if (handle != INVALID_HANDLE_VALUE)
229 {
230 FILETIME datetime;
231
232 rizwank 1.1 if (TRUE == DosDateTimeToFileTime(
233 pfdin->date,
234 pfdin->time,
235 &datetime))
236 {
237 FILETIME local_filetime;
238
239 if (TRUE == LocalFileTimeToFileTime(
240 &datetime,
241 &local_filetime))
242 {
243 (void) SetFileTime(
244 handle,
245 &local_filetime,
246 NULL,
247 &local_filetime
248 );
249 }
250 }
251
252 CloseHandle(handle);
253 rizwank 1.1 }
254
255 /*
256 * Mask out attribute bits other than readonly,
257 * hidden, system, and archive, since the other
258 * attribute bits are reserved for use by
259 * the cabinet format.
260 */
261 attrs = pfdin->attribs;
262
263 attrs &= (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);
264
265 (void) SetFileAttributes(
266 destination,
267 attrs
268 );
269
270 return TRUE;
271 }
272
273 case fdintNEXT_CABINET: // file continued to next cabinet
274 rizwank 1.1 printf(
275 "fdintNEXT_CABINET\n"
276 " name of next cabinet where file continued = %s\n"
277 " name of next disk where file continued = %s\n"
278 " cabinet path name = %s\n"
279 "\n",
280 pfdin->psz1,
281 pfdin->psz2,
282 pfdin->psz3
283 );
284 return 0;
285 }
286
287 return 0;
288 }
289
290
291 BOOL test_fdi(char *cabinet_fullpath)
292 {
293 HFDI hfdi;
294 ERF erf;
295 rizwank 1.1 FDICABINETINFO fdici;
296 int hf;
297 char *p;
298 char cabinet_name[256];
299 char cabinet_path[256];
300
301 hfdi = FDICreate(
302 mem_alloc,
303 mem_free,
304 file_open,
305 file_read,
306 file_write,
307 file_close,
308 file_seek,
309 cpu80386,
310 &erf
311 );
312
313 if (hfdi == NULL)
314 {
315 printf("FDICreate() failed: code %d [%s]\n",
316 rizwank 1.1 erf.erfOper, return_fdi_error_string(erf.erfOper)
317 );
318
319 return FALSE;
320 }
321
322
323 /*
324 * Is this file really a cabinet?
325 */
326 hf = file_open(
327 cabinet_fullpath,
328 _O_BINARY | _O_RDONLY | _O_SEQUENTIAL,
329 0
330 );
331
332 if (hf == -1)
333 {
334 (void) FDIDestroy(hfdi);
335
336 printf("Unable to open '%s' for input\n", cabinet_fullpath);
337 rizwank 1.1 return FALSE;
338 }
339
340 if (FALSE == FDIIsCabinet(
341 hfdi,
342 hf,
343 &fdici))
344 {
345 /*
346 * No, it's not a cabinet!
347 */
348 _close(hf);
349
350 printf(
351 "FDIIsCabinet() failed: '%s' is not a cabinet\n",
352 cabinet_fullpath
353 );
354
355 (void) FDIDestroy(hfdi);
356 return FALSE;
357 }
358 rizwank 1.1 else
359 {
360 _close(hf);
361
362 printf(
363 "Information on cabinet file '%s'\n"
364 " Total length of cabinet file : %d\n"
365 " Number of folders in cabinet : %d\n"
366 " Number of files in cabinet : %d\n"
367 " Cabinet set ID : %d\n"
368 " Cabinet number in set : %d\n"
369 " RESERVE area in cabinet? : %s\n"
370 " Chained to prev cabinet? : %s\n"
371 " Chained to next cabinet? : %s\n"
372 "\n",
373 cabinet_fullpath,
374 fdici.cbCabinet,
375 fdici.cFolders,
376 fdici.cFiles,
377 fdici.setID,
378 fdici.iCabinet,
379 rizwank 1.1 fdici.fReserve == TRUE ? "yes" : "no",
380 fdici.hasprev == TRUE ? "yes" : "no",
381 fdici.hasnext == TRUE ? "yes" : "no"
382 );
383 }
384
385 p = strrchr(cabinet_fullpath, '\\');
386
387 if (p == NULL)
388 {
389 strcpy(cabinet_name, cabinet_fullpath);
390 strcpy(cabinet_path, "");
391 }
392 else
393 {
394 strcpy(cabinet_name, p+1);
395
396 strncpy(cabinet_path, cabinet_fullpath, (int) (p-cabinet_fullpath)+1);
397 cabinet_path[ (int) (p-cabinet_fullpath)+1 ] = 0;
398 }
399
400 rizwank 1.1 if (TRUE != FDICopy(
401 hfdi,
402 cabinet_name,
403 cabinet_path,
404 0,
405 notification_function,
406 NULL,
407 NULL))
408 {
409 printf(
410 "FDICopy() failed: code %d [%s]\n",
411 erf.erfOper, return_fdi_error_string(erf.erfOper)
412 );
413
414 (void) FDIDestroy(hfdi);
415 return FALSE;
416 }
417
418 if (FDIDestroy(hfdi) != TRUE)
419 {
420 printf(
421 rizwank 1.1 "FDIDestroy() failed: code %d [%s]\n",
422 erf.erfOper, return_fdi_error_string(erf.erfOper)
423 );
424
425 return FALSE;
426 }
427
428 return TRUE;
429 }
430
431
432 char *return_fdi_error_string(FDIERROR err)
433 {
434 switch (err)
435 {
436 case FDIERROR_NONE:
437 return "No error";
438
439 case FDIERROR_CABINET_NOT_FOUND:
440 return "Cabinet not found";
441
442 rizwank 1.1 case FDIERROR_NOT_A_CABINET:
443 return "Not a cabinet";
444
445 case FDIERROR_UNKNOWN_CABINET_VERSION:
446 return "Unknown cabinet version";
447
448 case FDIERROR_CORRUPT_CABINET:
449 return "Corrupt cabinet";
450
451 case FDIERROR_ALLOC_FAIL:
452 return "Memory allocation failed";
453
454 case FDIERROR_BAD_COMPR_TYPE:
455 return "Unknown compression type";
456
457 case FDIERROR_MDI_FAIL:
458 return "Failure decompressing data";
459
460 case FDIERROR_TARGET_FILE:
461 return "Failure writing to target file";
462
463 rizwank 1.1 case FDIERROR_RESERVE_MISMATCH:
464 return "Cabinets in set have different RESERVE sizes";
465
466 case FDIERROR_WRONG_CABINET:
467 return "Cabinet returned on fdintNEXT_CABINET is incorrect";
468
469 case FDIERROR_USER_ABORT:
470 return "User aborted";
471
472 default:
473 return "Unknown error";
474 }
475 }
|