Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

470 lines
9.2 KiB

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