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.

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