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.

468 lines
9.6 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // CAB file manipulation for dump files and dump CABs.
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "pch.hpp"
  9. #pragma hdrstop
  10. #ifndef _WIN32_WCE
  11. #include <io.h>
  12. #include <fcntl.h>
  13. #include <sys\stat.h>
  14. #include <share.h>
  15. #include <errno.h>
  16. #include <fci.h>
  17. #include <fdi.h>
  18. #include "cmnutil.hpp"
  19. #define CAB_HR(Code) MAKE_HRESULT(SEVERITY_ERROR, 0xfd1, ((Code) & 0xffff))
  20. HFCI g_AddCab;
  21. ERF g_AddCabErr;
  22. ULONG g_CabTmpSequence;
  23. FNALLOC(CabAlloc)
  24. {
  25. return malloc(cb);
  26. }
  27. FNFREE(CabFree)
  28. {
  29. free(pv);
  30. }
  31. PSTR
  32. CabPathTail(PSTR Path)
  33. {
  34. PSTR Tail = strrchr(Path, '\\');
  35. if (Tail == NULL)
  36. {
  37. Tail = strrchr(Path, '/');
  38. if (Tail == NULL)
  39. {
  40. Tail = strrchr(Path, ':');
  41. }
  42. }
  43. return Tail ? Tail + 1 : Path;
  44. }
  45. //----------------------------------------------------------------------------
  46. //
  47. // Expanding dump files from CAB files.
  48. //
  49. //----------------------------------------------------------------------------
  50. struct FDI_CB_STATE
  51. {
  52. PSTR DmpFile;
  53. ULONG DmpFileLen;
  54. PSTR DstDir;
  55. ULONG FileFlags;
  56. INT_PTR DmpFh;
  57. PCSTR MatchFile;
  58. };
  59. FNOPEN(FdiOpen)
  60. {
  61. return _open(pszFile, oflag, pmode);
  62. }
  63. FNREAD(FdiRead)
  64. {
  65. return _read((int)hf, pv, cb);
  66. }
  67. FNWRITE(FdiWrite)
  68. {
  69. return _write((int)hf, pv, cb);
  70. }
  71. FNCLOSE(FdiClose)
  72. {
  73. return _close((int)hf);
  74. }
  75. FNSEEK(FdiSeek)
  76. {
  77. return _lseek((int)hf, dist, seektype);
  78. }
  79. INT_PTR
  80. FdiCommonNotify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin, BOOL bMatchExt)
  81. {
  82. FDI_CB_STATE* CbState = (FDI_CB_STATE*)pfdin->pv;
  83. PSTR Scan;
  84. switch(fdint)
  85. {
  86. case fdintCOPY_FILE:
  87. if (CbState->DmpFh >= 0)
  88. {
  89. return 0;
  90. }
  91. // Match the file extension if needed
  92. Scan = strrchr(pfdin->psz1, '.');
  93. if (Scan == NULL ||
  94. (bMatchExt && (_stricmp(Scan, CbState->MatchFile) != 0)) )
  95. {
  96. return 0;
  97. }
  98. // Match the file name if if needed
  99. Scan = CabPathTail(pfdin->psz1);
  100. if (!bMatchExt && (_stricmp(Scan, CbState->MatchFile) != 0))
  101. {
  102. return 0;
  103. }
  104. // Add in the process ID to the filename to
  105. // make it possible to expand the same CAB from
  106. // multiple processes at once.
  107. if (*CbState->DstDir)
  108. {
  109. if (_snprintf(CbState->DmpFile, CbState->DmpFileLen,
  110. "%s\\%08x%x_%s",
  111. CbState->DstDir, GetCurrentProcessId(),
  112. g_CabTmpSequence++, Scan) < 0)
  113. {
  114. return 0;
  115. }
  116. }
  117. else
  118. {
  119. if (_snprintf(CbState->DmpFile, CbState->DmpFileLen,
  120. "%08x%x_%s",
  121. GetCurrentProcessId(), g_CabTmpSequence++,
  122. Scan) < 0)
  123. {
  124. return 0;
  125. }
  126. }
  127. CbState->DmpFh = FdiOpen(CbState->DmpFile,
  128. _O_BINARY | _O_WRONLY | CbState->FileFlags,
  129. _S_IREAD | _S_IWRITE);
  130. return CbState->DmpFh;
  131. case fdintCLOSE_FILE_INFO:
  132. // Leave the file open.
  133. return TRUE;
  134. }
  135. return 0;
  136. }
  137. FNFDINOTIFY(FdiNotifyFileExt)
  138. {
  139. return FdiCommonNotify(fdint, pfdin, 1);
  140. }
  141. FNFDINOTIFY(FdiNotifyFileName)
  142. {
  143. return FdiCommonNotify(fdint, pfdin, 0);
  144. }
  145. HRESULT
  146. ExpandDumpCab(PCSTR CabFile, ULONG FileFlags, PCSTR FileToOpen,
  147. PSTR DmpFile, ULONG DmpFileLen, INT_PTR* DmpFh)
  148. {
  149. FDI_CB_STATE CbState;
  150. HFDI Context;
  151. ERF Err;
  152. BOOL Status;
  153. PSTR Env;
  154. Env = getenv("TMP");
  155. if (Env == NULL)
  156. {
  157. Env = getenv("TEMP");
  158. if (Env == NULL)
  159. {
  160. Env = "";
  161. }
  162. }
  163. CbState.DmpFile = DmpFile;
  164. CbState.DmpFileLen = DmpFileLen;
  165. CbState.DstDir = Env;
  166. CbState.FileFlags = FileFlags;
  167. CbState.DmpFh = -1;
  168. CbState.MatchFile = FileToOpen;
  169. Context = FDICreate(CabAlloc, CabFree,
  170. FdiOpen, FdiRead, FdiWrite, FdiClose, FdiSeek,
  171. cpuUNKNOWN, &Err);
  172. if (Context == NULL)
  173. {
  174. return CAB_HR(Err.erfOper);
  175. }
  176. if (FileToOpen == NULL)
  177. {
  178. // try to open .mdmp or .dmp extension files
  179. CbState.MatchFile = ".mdmp";
  180. Status = FDICopy(Context, "", (PSTR)CabFile, 0,
  181. FdiNotifyFileExt, NULL, &CbState);
  182. if (!Status || (CbState.DmpFh < 0))
  183. {
  184. CbState.MatchFile = ".dmp";
  185. Status = FDICopy(Context, "", (PSTR)CabFile, 0,
  186. FdiNotifyFileExt, NULL, &CbState);
  187. }
  188. } else
  189. {
  190. Status = FDICopy(Context, "", (PSTR)CabFile, 0,
  191. FdiNotifyFileName, NULL, &CbState);
  192. }
  193. if (!Status)
  194. {
  195. return CAB_HR(Err.erfOper);
  196. }
  197. *DmpFh = CbState.DmpFh;
  198. return (CbState.DmpFh >= 0) ? S_OK : E_NOINTERFACE;
  199. }
  200. //----------------------------------------------------------------------------
  201. //
  202. // Placing files into a CAB.
  203. //
  204. //----------------------------------------------------------------------------
  205. // We don't really care about specific error codes.
  206. #define CrtErr() EBADF
  207. FNFCIFILEPLACED(FciFilePlaced)
  208. {
  209. // Not watching for anything.
  210. return 0;
  211. }
  212. FNFCIGETTEMPFILE(FciGetTempFile)
  213. {
  214. CHAR TempPath[MAX_PATH];
  215. DWORD Len;
  216. Len = GetTempPathA(sizeof(TempPath), TempPath);
  217. if (Len == 0 || Len >= sizeof(TempPath))
  218. {
  219. TempPath[0] = '.';
  220. TempPath[1] = '\0';
  221. }
  222. if (GetTempFileNameA(TempPath, "dbg", 0, pszTempName))
  223. {
  224. DeleteFileA(pszTempName);
  225. }
  226. return TRUE;
  227. }
  228. FNFCIGETNEXTCABINET(FciGetNextCabinet)
  229. {
  230. // No multi-cabinet activity expected, just fail.
  231. return FALSE;
  232. }
  233. FNFCISTATUS(FciStatus)
  234. {
  235. // No status tracking.
  236. return TRUE;
  237. }
  238. FNFCIGETOPENINFO(FciGetOpenInfo)
  239. {
  240. WIN32_FIND_DATAA FindData;
  241. HANDLE FindHandle;
  242. FILETIME Local;
  243. FindHandle = FindFirstFileA(pszName, &FindData);
  244. if (FindHandle == INVALID_HANDLE_VALUE)
  245. {
  246. return -1;
  247. }
  248. FindClose(FindHandle);
  249. FileTimeToLocalFileTime(&FindData.ftLastWriteTime, &Local);
  250. FileTimeToDosDateTime(&Local, pdate, ptime);
  251. *pattribs = (WORD)(FindData.dwFileAttributes &
  252. (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN |
  253. FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE));
  254. return _open(pszName, _O_RDONLY | _O_BINARY);
  255. }
  256. FNFCIOPEN(FciOpen)
  257. {
  258. int Result;
  259. Result = _open(pszFile, oflag, pmode);
  260. if (Result == -1)
  261. {
  262. *err = CrtErr();
  263. }
  264. return Result;
  265. }
  266. FNFCIREAD(FciRead)
  267. {
  268. UINT Result;
  269. Result = (UINT)_read((int)hf, memory, cb);
  270. if (Result != cb)
  271. {
  272. *err = CrtErr();
  273. }
  274. return Result;
  275. }
  276. FNFCIWRITE(FciWrite)
  277. {
  278. UINT Result;
  279. Result = (UINT)_write((int)hf, memory, cb);
  280. if (Result != cb)
  281. {
  282. *err = CrtErr();
  283. }
  284. return Result;
  285. }
  286. FNFCICLOSE(FciClose)
  287. {
  288. int Result;
  289. Result = _close((int)hf);
  290. if (Result == -1)
  291. {
  292. *err = CrtErr();
  293. }
  294. return Result;
  295. }
  296. FNFCISEEK(FciSeek)
  297. {
  298. long Result;
  299. Result = _lseek((int)hf, dist, seektype);
  300. if (Result == -1)
  301. {
  302. *err = CrtErr();
  303. }
  304. return Result;
  305. }
  306. FNFCIDELETE(FciDelete)
  307. {
  308. int Result;
  309. Result = _unlink(pszFile);
  310. if (Result == -1)
  311. {
  312. *err = CrtErr();
  313. }
  314. return Result;
  315. }
  316. HRESULT
  317. CreateDumpCab(PCSTR FileName)
  318. {
  319. CCAB Cab;
  320. PSTR Tail;
  321. if (g_AddCab)
  322. {
  323. return E_UNEXPECTED;
  324. }
  325. ZeroMemory(&Cab, sizeof(Cab));
  326. //
  327. // Split filename into path and tail components
  328. // for szCabPath and szCab.
  329. //
  330. if (!CopyString(Cab.szCabPath, FileName, DIMA(Cab.szCabPath)))
  331. {
  332. return E_INVALIDARG;
  333. }
  334. Tail = CabPathTail(Cab.szCabPath);
  335. if (Tail > Cab.szCabPath)
  336. {
  337. if (!CopyString(Cab.szCab, Tail, DIMA(Cab.szCab)))
  338. {
  339. return E_INVALIDARG;
  340. }
  341. *Tail = 0;
  342. }
  343. else
  344. {
  345. if (!CopyString(Cab.szCab, FileName, DIMA(Cab.szCab)))
  346. {
  347. return E_INVALIDARG;
  348. }
  349. Cab.szCabPath[0] = 0;
  350. }
  351. g_AddCab = FCICreate(&g_AddCabErr, FciFilePlaced, CabAlloc, CabFree,
  352. FciOpen, FciRead, FciWrite, FciClose,
  353. FciSeek, FciDelete, FciGetTempFile,
  354. &Cab, NULL);
  355. if (!g_AddCab)
  356. {
  357. return CAB_HR(g_AddCabErr.erfOper);
  358. }
  359. return S_OK;
  360. }
  361. HRESULT
  362. AddToDumpCab(PCSTR FileName)
  363. {
  364. if (!g_AddCab)
  365. {
  366. return E_UNEXPECTED;
  367. }
  368. if (!FCIAddFile(g_AddCab, (PSTR)FileName, CabPathTail((PSTR)FileName),
  369. FALSE, FciGetNextCabinet, FciStatus,
  370. FciGetOpenInfo, tcompTYPE_LZX | tcompLZX_WINDOW_HI))
  371. {
  372. return CAB_HR(g_AddCabErr.erfOper);
  373. }
  374. return S_OK;
  375. }
  376. void
  377. CloseDumpCab(void)
  378. {
  379. if (!g_AddCab)
  380. {
  381. return;
  382. }
  383. FCIFlushCabinet(g_AddCab, FALSE, FciGetNextCabinet, FciStatus);
  384. FCIDestroy(g_AddCab);
  385. g_AddCab = NULL;
  386. }
  387. #endif // #ifndef _WIN32_WCE