Source code of Windows XP (NT5)
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.

323 lines
5.8 KiB

  1. #include "wsdueng.h"
  2. #include <io.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. /*
  6. * Function prototypes
  7. */
  8. BOOL fdi(char *cabinet_file, char *dir);
  9. int get_percentage(unsigned long a, unsigned long b);
  10. char *return_fdi_error_string(int err);
  11. /*
  12. * Destination directory for extracted files
  13. */
  14. char dest_dir[256];
  15. /*
  16. * Memory allocation function
  17. */
  18. FNALLOC(mem_alloc)
  19. {
  20. return malloc(cb);
  21. }
  22. /*
  23. * Memory free function
  24. */
  25. FNFREE(mem_free)
  26. {
  27. free(pv);
  28. }
  29. FNOPEN(file_open)
  30. {
  31. return _open(pszFile, oflag, pmode);
  32. }
  33. FNREAD(file_read)
  34. {
  35. return _read((int)hf, pv, cb);
  36. }
  37. FNWRITE(file_write)
  38. {
  39. return _write((int)hf, pv, cb);
  40. }
  41. FNCLOSE(file_close)
  42. {
  43. return _close((int)hf);
  44. }
  45. FNSEEK(file_seek)
  46. {
  47. return _lseek((int)hf, dist, seektype);
  48. }
  49. FNFDINOTIFY(notification_function)
  50. {
  51. switch (fdint)
  52. {
  53. case fdintCABINET_INFO: // general information about the cabinet
  54. return 0;
  55. case fdintPARTIAL_FILE: // first file in cabinet is continuation
  56. return 0;
  57. case fdintCOPY_FILE: // file to be copied
  58. {
  59. INT_PTR handle;
  60. int response;
  61. char destination[256];
  62. wsprintf(
  63. destination,
  64. "%s%s",
  65. dest_dir,
  66. pfdin->psz1
  67. );
  68. handle = file_open(
  69. destination,
  70. _O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL,
  71. _S_IREAD | _S_IWRITE
  72. );
  73. return handle;
  74. }
  75. case fdintCLOSE_FILE_INFO: // close the file, set relevant info
  76. {
  77. HANDLE handle;
  78. DWORD attrs;
  79. char destination[256];
  80. wsprintf(
  81. destination,
  82. "%s%s",
  83. dest_dir,
  84. pfdin->psz1
  85. );
  86. file_close(pfdin->hf);
  87. handle = CreateFile(
  88. destination,
  89. GENERIC_READ | GENERIC_WRITE,
  90. FILE_SHARE_READ,
  91. NULL,
  92. OPEN_EXISTING,
  93. FILE_ATTRIBUTE_NORMAL,
  94. NULL
  95. );
  96. if (handle != INVALID_HANDLE_VALUE)
  97. {
  98. FILETIME datetime;
  99. if (TRUE == DosDateTimeToFileTime(
  100. pfdin->date,
  101. pfdin->time,
  102. &datetime))
  103. {
  104. FILETIME local_filetime;
  105. if (TRUE == LocalFileTimeToFileTime(
  106. &datetime,
  107. &local_filetime))
  108. {
  109. (void) SetFileTime(
  110. handle,
  111. &local_filetime,
  112. NULL,
  113. &local_filetime
  114. );
  115. }
  116. }
  117. CloseHandle(handle);
  118. }
  119. attrs = pfdin->attribs;
  120. attrs &= (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);
  121. (void) SetFileAttributes(
  122. destination,
  123. attrs
  124. );
  125. return TRUE;
  126. }
  127. case fdintNEXT_CABINET: // file continued to next cabinet
  128. return 0;
  129. }
  130. return 0;
  131. }
  132. BOOL fdi(char *cabinet_fullpath, char * directory)
  133. {
  134. LOG_block("fdi()");
  135. HFDI hfdi;
  136. ERF erf;
  137. FDICABINETINFO fdici;
  138. INT_PTR hf;
  139. char *p;
  140. char cabinet_name[256];
  141. char cabinet_path[256];
  142. strcpy(dest_dir, directory);
  143. if (dest_dir[strlen(dest_dir)] != '\\')
  144. {
  145. strcat(dest_dir, "\\");
  146. }
  147. hfdi = FDICreate(
  148. mem_alloc,
  149. mem_free,
  150. file_open,
  151. file_read,
  152. file_write,
  153. file_close,
  154. file_seek,
  155. cpu80386,
  156. &erf
  157. );
  158. if (hfdi == NULL)
  159. {
  160. LOG_error("FDICreate() failed: code %d [%s]\n", erf.erfOper, return_fdi_error_string(erf.erfOper));
  161. return FALSE;
  162. }
  163. /*
  164. * Is this file really a cabinet?
  165. */
  166. hf = file_open(
  167. cabinet_fullpath,
  168. _O_BINARY | _O_RDONLY | _O_SEQUENTIAL,
  169. 0
  170. );
  171. if (hf == -1)
  172. {
  173. (void) FDIDestroy(hfdi);
  174. LOG_error("Unable to open '%s' for input\n", cabinet_fullpath);
  175. return FALSE;
  176. }
  177. if (FALSE == FDIIsCabinet(
  178. hfdi,
  179. hf,
  180. &fdici))
  181. {
  182. // The file is not compressed, nothing to do. This is not an error, A lot of files on the V3 server use
  183. // conditional compression depending on whether it benefits the file size.
  184. _close((int)hf);
  185. (void) FDIDestroy(hfdi);
  186. return FALSE;
  187. }
  188. else
  189. {
  190. _close((int)hf);
  191. }
  192. p = strrchr(cabinet_fullpath, '\\');
  193. if (p == NULL)
  194. {
  195. strcpy(cabinet_name, cabinet_fullpath);
  196. strcpy(cabinet_path, "");
  197. }
  198. else
  199. {
  200. strcpy(cabinet_name, p+1);
  201. strncpy(cabinet_path, cabinet_fullpath, (int) (p-cabinet_fullpath)+1);
  202. cabinet_path[ (int) (p-cabinet_fullpath)+1 ] = 0;
  203. }
  204. if (TRUE != FDICopy(
  205. hfdi,
  206. cabinet_name,
  207. cabinet_path,
  208. 0,
  209. notification_function,
  210. NULL,
  211. NULL))
  212. {
  213. LOG_error("FDICopy() failed: code %d [%s]\n", erf.erfOper, return_fdi_error_string(erf.erfOper));
  214. (void) FDIDestroy(hfdi);
  215. return FALSE;
  216. }
  217. if (FDIDestroy(hfdi) != TRUE)
  218. {
  219. LOG_error("FDIDestroy() failed: code %d [%s]\n", erf.erfOper, return_fdi_error_string(erf.erfOper));
  220. return FALSE;
  221. }
  222. return TRUE;
  223. }
  224. char *return_fdi_error_string(int err)
  225. {
  226. switch (err)
  227. {
  228. case FDIERROR_NONE:
  229. return "No error";
  230. case FDIERROR_CABINET_NOT_FOUND:
  231. return "Cabinet not found";
  232. case FDIERROR_NOT_A_CABINET:
  233. return "Not a cabinet";
  234. case FDIERROR_UNKNOWN_CABINET_VERSION:
  235. return "Unknown cabinet version";
  236. case FDIERROR_CORRUPT_CABINET:
  237. return "Corrupt cabinet";
  238. case FDIERROR_ALLOC_FAIL:
  239. return "Memory allocation failed";
  240. case FDIERROR_BAD_COMPR_TYPE:
  241. return "Unknown compression type";
  242. case FDIERROR_MDI_FAIL:
  243. return "Failure decompressing data";
  244. case FDIERROR_TARGET_FILE:
  245. return "Failure writing to target file";
  246. case FDIERROR_RESERVE_MISMATCH:
  247. return "Cabinets in set have different RESERVE sizes";
  248. case FDIERROR_WRONG_CABINET:
  249. return "Cabinet returned on fdintNEXT_CABINET is incorrect";
  250. case FDIERROR_USER_ABORT:
  251. return "User aborted";
  252. default:
  253. return "Unknown error";
  254. }
  255. }