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.

480 lines
11 KiB

  1. /*
  2. * FDIDLL.C -- FDI interface using CABINET.DLL
  3. *
  4. * Copyright (C) Microsoft Corporation 1997
  5. * All Rights Reserved.
  6. *
  7. * Overview:
  8. * This code is a wrapper which provides access to the actual FDI code
  9. * in CABINET.DLL. CABINET.DLL dynamically loads/unloads as needed.
  10. */
  11. #include "pch.hpp"
  12. #include <io.h>
  13. #include <fcntl.h>
  14. #include <sys/stat.h>
  15. #include <appdefs.h>
  16. #include "fdi.h"
  17. static HINSTANCE hCabinetDll = NULL; /* DLL module handle */
  18. /* pointers to the functions in the DLL */
  19. typedef HFDI (FAR DIAMONDAPI *PFNFDICREATE)(
  20. PFNALLOC pfnalloc,
  21. PFNFREE pfnfree,
  22. PFNOPEN pfnopen,
  23. PFNREAD pfnread,
  24. PFNWRITE pfnwrite,
  25. PFNCLOSE pfnclose,
  26. PFNSEEK pfnseek,
  27. int cpuType,
  28. PERF perf);
  29. static PFNFDICREATE pfnFDICreate = NULL;
  30. typedef BOOL (FAR DIAMONDAPI *PFNFDIIsCabinet)(
  31. HFDI hfdi,
  32. int hf,
  33. PFDICABINETINFO pfdici);
  34. static PFNFDIIsCabinet pfnFDIIsCabinet = NULL;
  35. typedef BOOL (FAR DIAMONDAPI *PFNFDICopy)(
  36. HFDI hfdi,
  37. CHAR *pszCabinet,
  38. CHAR *pszCabPath,
  39. int flags,
  40. PFNFDINOTIFY pfnfdin,
  41. PFNFDIDECRYPT pfnfdid,
  42. void *pvUser);
  43. static PFNFDICopy pfnFDICopy = NULL;
  44. typedef BOOL (FAR DIAMONDAPI *PFNFDIDestroy)(
  45. HFDI hfdi);
  46. static PFNFDIDestroy pfnFDIDestroy = NULL;
  47. /*
  48. * FDICreate -- Create an FDI context
  49. *
  50. * See fdi.h for entry/exit conditions.
  51. */
  52. HFDI FAR DIAMONDAPI FDICreate(PFNALLOC pfnalloc,
  53. PFNFREE pfnfree,
  54. PFNOPEN pfnopen,
  55. PFNREAD pfnread,
  56. PFNWRITE pfnwrite,
  57. PFNCLOSE pfnclose,
  58. PFNSEEK pfnseek,
  59. int cpuType,
  60. PERF perf)
  61. {
  62. HFDI hfdi;
  63. if ( hCabinetDll != NULL )
  64. {
  65. goto gotEntryPoints;
  66. }
  67. hCabinetDll = LoadLibraryA("CABINET");
  68. if (hCabinetDll == NULL)
  69. {
  70. return(NULL);
  71. }
  72. pfnFDICreate = (PFNFDICREATE) GetProcAddress(hCabinetDll, "FDICreate");
  73. pfnFDICopy = (PFNFDICopy) GetProcAddress(hCabinetDll, "FDICopy");
  74. pfnFDIIsCabinet = (PFNFDIIsCabinet) GetProcAddress(hCabinetDll, "FDIIsCabinet");
  75. pfnFDIDestroy = (PFNFDIDestroy) GetProcAddress(hCabinetDll, "FDIDestroy");
  76. if ((pfnFDICreate == NULL) ||
  77. (pfnFDICopy == NULL) ||
  78. (pfnFDIIsCabinet == NULL) ||
  79. (pfnFDIDestroy == NULL))
  80. {
  81. FreeLibrary(hCabinetDll);
  82. hCabinetDll = NULL;
  83. return(NULL);
  84. }
  85. gotEntryPoints:
  86. hfdi = pfnFDICreate(pfnalloc, pfnfree,
  87. pfnopen, pfnread,pfnwrite,pfnclose,pfnseek,cpuType,perf);
  88. if (hfdi == NULL)
  89. {
  90. FreeLibrary(hCabinetDll);
  91. hCabinetDll = NULL;
  92. }
  93. return(hfdi);
  94. }
  95. /*
  96. * FDIIsCabinet -- Determines if file is a cabinet, returns info if it is
  97. *
  98. * See fdi.h for entry/exit conditions.
  99. */
  100. BOOL FAR DIAMONDAPI FDIIsCabinet(HFDI hfdi,
  101. int hf,
  102. PFDICABINETINFO pfdici)
  103. {
  104. if (pfnFDIIsCabinet == NULL)
  105. {
  106. return(FALSE);
  107. }
  108. return(pfnFDIIsCabinet(hfdi, hf,pfdici));
  109. }
  110. /*
  111. * FDICopy -- extracts files from a cabinet
  112. *
  113. * See fdi.h for entry/exit conditions.
  114. */
  115. BOOL FAR DIAMONDAPI FDICopy(HFDI hfdi,
  116. CHAR *pszCabinet,
  117. CHAR *pszCabPath,
  118. int flags,
  119. PFNFDINOTIFY pfnfdin,
  120. PFNFDIDECRYPT pfnfdid,
  121. void *pvUser)
  122. {
  123. if (pfnFDICopy == NULL)
  124. {
  125. return(FALSE);
  126. }
  127. return(pfnFDICopy(hfdi, pszCabinet,pszCabPath,flags,pfnfdin,pfnfdid,pvUser));
  128. }
  129. /*
  130. * FDIDestroy -- Destroy an FDI context
  131. *
  132. * See fdi.h for entry/exit conditions.
  133. */
  134. BOOL FAR DIAMONDAPI FDIDestroy(HFDI hfdi)
  135. {
  136. BOOL rc;
  137. if (pfnFDIDestroy == NULL)
  138. {
  139. return(FALSE);
  140. }
  141. rc = pfnFDIDestroy(hfdi);
  142. return(rc);
  143. }
  144. /*
  145. * Memory allocation function
  146. */
  147. FNALLOC(mem_alloc)
  148. {
  149. return new BYTE[cb];
  150. }
  151. /*
  152. * Memory free function
  153. */
  154. FNFREE(mem_free)
  155. {
  156. delete pv;
  157. }
  158. FNOPEN(file_open)
  159. {
  160. return _open(pszFile, oflag, pmode);
  161. }
  162. FNREAD(file_read)
  163. {
  164. return _read(hf, pv, cb);
  165. }
  166. FNWRITE(file_write)
  167. {
  168. return _write(hf, pv, cb);
  169. }
  170. FNCLOSE(file_close)
  171. {
  172. return _close(hf);
  173. }
  174. FNSEEK(file_seek)
  175. {
  176. return _lseek(hf, dist, seektype);
  177. }
  178. FNFDINOTIFY(notification_function)
  179. {
  180. switch (fdint)
  181. {
  182. case fdintCABINET_INFO: // general information about the cabinet
  183. #if 0
  184. printf(
  185. "fdintCABINET_INFO\n"
  186. " next cabinet = %s\n"
  187. " next disk = %s\n"
  188. " cabinet path = %s\n"
  189. " cabinet set ID = %d\n"
  190. " cabinet # in set = %d (zero based)\n"
  191. "\n",
  192. pfdin->psz1,
  193. pfdin->psz2,
  194. pfdin->psz3,
  195. pfdin->setID,
  196. pfdin->iCabinet
  197. );
  198. #endif
  199. return 0;
  200. case fdintPARTIAL_FILE: // first file in cabinet is continuation
  201. #if 0
  202. printf(
  203. "fdintPARTIAL_FILE\n"
  204. " name of continued file = %s\n"
  205. " name of cabinet where file starts = %s\n"
  206. " name of disk where file starts = %s\n",
  207. pfdin->psz1,
  208. pfdin->psz2,
  209. pfdin->psz3
  210. );
  211. #endif
  212. return 0;
  213. case fdintCOPY_FILE: // file to be copied
  214. {
  215. int handle;
  216. #if 0
  217. int response;
  218. printf(
  219. "fdintCOPY_FILE\n"
  220. " file name in cabinet = %s\n"
  221. " uncompressed file size = %d\n"
  222. " copy this file? (y/n): ",
  223. pfdin->psz1,
  224. pfdin->cb
  225. );
  226. #endif
  227. handle = file_open(
  228. pfdin->psz1,
  229. _O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_TRUNC,
  230. _S_IREAD | _S_IWRITE
  231. );
  232. return handle;
  233. }
  234. case fdintCLOSE_FILE_INFO: // close the file, set relevant info
  235. {
  236. #if 0
  237. HANDLE handle;
  238. DWORD attrs;
  239. CHAR destination[256];
  240. printf(
  241. "fdintCLOSE_FILE_INFO\n"
  242. " file name in cabinet = %s\n"
  243. "\n",
  244. pfdin->psz1
  245. );
  246. #endif
  247. file_close(pfdin->hf);
  248. return TRUE;
  249. }
  250. case fdintNEXT_CABINET: // file continued to next cabinet
  251. #if 0
  252. printf(
  253. "fdintNEXT_CABINET\n"
  254. " name of next cabinet where file continued = %s\n"
  255. " name of next disk where file continued = %s\n"
  256. " cabinet path name = %s\n"
  257. "\n",
  258. pfdin->psz1,
  259. pfdin->psz2,
  260. pfdin->psz3
  261. );
  262. #endif
  263. return 0;
  264. }
  265. return 0;
  266. }
  267. HRESULT HandleCab(LPSTR cabinet_fullpath)
  268. {
  269. ERF erf;
  270. HFDI hfdi;
  271. int hf;
  272. FDICABINETINFO fdici;
  273. CHAR *p;
  274. CHAR cabinet_name[256];
  275. CHAR cabinet_path[256];
  276. CHAR szCurrentDirectory[MAX_PATH];
  277. CHAR szdrive[_MAX_DRIVE];
  278. CHAR szPathName[_MAX_PATH]; // This will be the dir we need to create
  279. CHAR szdir[_MAX_DIR];
  280. CHAR szfname[_MAX_FNAME];
  281. CHAR szext[_MAX_EXT];
  282. CHAR szcabinet_fullpath[MAX_PATH+1];
  283. HRESULT err = S_OK;
  284. lstrcpyA(szcabinet_fullpath, cabinet_fullpath);
  285. if (GetCurrentDirectoryA(sizeof(szCurrentDirectory), szCurrentDirectory))
  286. {
  287. // Split the provided path to get at the drive and path portion
  288. _splitpath( szcabinet_fullpath, szdrive, szdir, szfname, szext );
  289. wsprintfA(szPathName, "%s%s", szdrive, szdir);
  290. // Set the directory to where the cab is
  291. if (!SetCurrentDirectoryA(szPathName))
  292. {
  293. return(GetLastError());
  294. }
  295. }
  296. else
  297. {
  298. return(GetLastError());
  299. }
  300. do
  301. {
  302. hfdi = FDICreate(mem_alloc,
  303. mem_free,
  304. file_open,
  305. file_read,
  306. file_write,
  307. file_close,
  308. file_seek,
  309. cpuUNKNOWN,
  310. &erf);
  311. if (hfdi == NULL)
  312. {
  313. err = -1;
  314. break;
  315. }
  316. /*
  317. * Is this file really a cabinet?
  318. */
  319. hf = file_open(
  320. szcabinet_fullpath,
  321. _O_BINARY | _O_RDONLY | _O_SEQUENTIAL,
  322. 0
  323. );
  324. if (hf == -1)
  325. {
  326. (void) FDIDestroy(hfdi);
  327. // Error Opening the file
  328. err = -2;
  329. break;
  330. }
  331. if (FALSE == FDIIsCabinet(
  332. hfdi,
  333. hf,
  334. &fdici))
  335. {
  336. /*
  337. * No, it's not a cabinet!
  338. */
  339. _close(hf);
  340. (void) FDIDestroy(hfdi);
  341. err = -3;
  342. break;
  343. }
  344. else
  345. {
  346. _close(hf);
  347. }
  348. p = strrchr(szcabinet_fullpath, '\\');
  349. if (p == NULL)
  350. {
  351. lstrcpyA(cabinet_name, szcabinet_fullpath);
  352. lstrcpyA(cabinet_path, "");
  353. }
  354. else
  355. {
  356. lstrcpyA(cabinet_name, ++p);
  357. // Need to make space for the null-terminator that lstrcpyn adds
  358. lstrcpynA(cabinet_path, szcabinet_fullpath, (int) (p-szcabinet_fullpath)+1);
  359. }
  360. if (TRUE != FDICopy(
  361. hfdi,
  362. cabinet_name,
  363. cabinet_path,
  364. 0,
  365. notification_function,
  366. NULL,
  367. NULL))
  368. {
  369. // Extract Failed.
  370. (void) FDIDestroy(hfdi);
  371. err = -4;
  372. break;
  373. }
  374. if (FDIDestroy(hfdi) != TRUE)
  375. {
  376. // why in the world would the context destroy fail ?
  377. err = -5;
  378. break;
  379. }
  380. break;
  381. }
  382. while(1 );
  383. // Set the directory back to the original place
  384. if (!SetCurrentDirectoryA(szCurrentDirectory))
  385. return(GetLastError());
  386. return err;
  387. }
  388. void CleanupCabHandler()
  389. {
  390. if (hCabinetDll != NULL)
  391. {
  392. FreeLibrary(hCabinetDll);
  393. }
  394. }