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.

521 lines
14 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. cabbing.cpp
  5. Abstract:
  6. FDU main
  7. Revision History:
  8. created derekm 02/23/00
  9. ******************************************************************************/
  10. #include <stdafx.h>
  11. #include <stdio.h>
  12. #include <io.h>
  13. #include <fcntl.h>
  14. #include <sys/stat.h>
  15. #include <fci.h>
  16. #include <fdi.h>
  17. #include "pfarray.h"
  18. #include "pfcab.h"
  19. /////////////////////////////////////////////////////////////////////////////
  20. // tracing
  21. #ifdef THIS_FILE
  22. #undef THIS_FILE
  23. #endif
  24. static char __szTraceSourceFile[] = __FILE__;
  25. #define THIS_FILE __szTraceSourceFile
  26. /////////////////////////////////////////////////////////////////////////////
  27. // structs
  28. struct SPFFileInfo
  29. {
  30. LPSTR szCab;
  31. LPSTR szDestFile;
  32. LPSTR szFileName;
  33. BOOL fFound;
  34. };
  35. /////////////////////////////////////////////////////////////////////////////
  36. // utility
  37. // **************************************************************************
  38. static MyCabGetLastError()
  39. {
  40. DWORD dwErr;
  41. // this function assumes that it is called in an error state, so it will
  42. // never return ERROR_SUCCESS
  43. dwErr = GetLastError();
  44. if (dwErr == ERROR_SUCCESS)
  45. {
  46. dwErr = _doserrno;
  47. if (dwErr == ERROR_SUCCESS)
  48. dwErr = ERROR_TOO_MANY_OPEN_FILES;
  49. }
  50. return dwErr;
  51. }
  52. // **************************************************************************
  53. static void DeleteFromFileList(LPVOID pv)
  54. {
  55. SysFreeString((BSTR)pv);
  56. }
  57. // **************************************************************************
  58. static void SplitPath(LPCSTR szFullPath, LPSTR szPath, LPSTR szName)
  59. {
  60. LPSTR szEnd;
  61. szEnd = strrchr(szFullPath, '\\');
  62. if (szEnd == NULL)
  63. {
  64. strcpy(szPath, "");
  65. strcpy(szName, szFullPath);
  66. }
  67. else
  68. {
  69. DWORD cb;
  70. cb = (DWORD)(LONG_PTR)(szEnd - szFullPath) + 1;
  71. strcpy(szName, szEnd + 1);
  72. strncpy(szPath, szFullPath, cb);
  73. szPath[cb] = 0;
  74. }
  75. }
  76. /////////////////////////////////////////////////////////////////////////////
  77. //
  78. // **************************************************************************
  79. static LPVOID DIAMONDAPI mem_alloc(ULONG cb)
  80. {
  81. return MyAlloc(cb);
  82. }
  83. // **************************************************************************
  84. static void DIAMONDAPI mem_free(LPVOID pv)
  85. {
  86. MyFree(pv);
  87. }
  88. /////////////////////////////////////////////////////////////////////////////
  89. //
  90. // **************************************************************************
  91. static INT_PTR DIAMONDAPI fci_open(LPSTR pszFile, int oflag, int pmode,
  92. int *err, LPVOID pv)
  93. {
  94. int result;
  95. result = _open(pszFile, oflag, pmode);
  96. if (result == -1)
  97. *err = errno;
  98. return result;
  99. }
  100. // **************************************************************************
  101. static UINT DIAMONDAPI fci_read(INT_PTR hf, LPVOID memory, UINT cb, int *err,
  102. LPVOID pv)
  103. {
  104. UINT result;
  105. result = (UINT)_read((int)hf, memory, cb);
  106. if (result != cb)
  107. *err = errno;
  108. return result;
  109. }
  110. // **************************************************************************
  111. static UINT DIAMONDAPI fci_write(INT_PTR hf, LPVOID memory, UINT cb, int *err,
  112. LPVOID pv)
  113. {
  114. UINT result;
  115. result = (UINT)_write((int)hf, memory, cb);
  116. if (result != cb)
  117. *err = errno;
  118. return result;
  119. }
  120. // **************************************************************************
  121. static int DIAMONDAPI fci_close(INT_PTR hf, int *err, LPVOID pv)
  122. {
  123. int result;
  124. result = _close((int)hf);
  125. if (result != 0)
  126. *err = errno;
  127. return result;
  128. }
  129. // **************************************************************************
  130. static long DIAMONDAPI fci_seek(INT_PTR hf, long dist, int seektype, int *err,
  131. LPVOID pv)
  132. {
  133. long result;
  134. result = _lseek((int)hf, dist, seektype);
  135. if (result == -1)
  136. *err = errno;
  137. return result;
  138. }
  139. // **************************************************************************
  140. static int DIAMONDAPI fci_delete(LPSTR pszFile, int *err, LPVOID pv)
  141. {
  142. int result;
  143. result = remove(pszFile);
  144. if (result != 0)
  145. *err = errno;
  146. return result;
  147. }
  148. /////////////////////////////////////////////////////////////////////////////
  149. //
  150. // **************************************************************************
  151. static int DIAMONDAPI fci_file_placed(PCCAB pccab, LPSTR pszFile, long cbFile,
  152. BOOL fContinuation, LPVOID pv)
  153. {
  154. return 0;
  155. }
  156. // **************************************************************************
  157. static BOOL DIAMONDAPI fci_get_temp_file(LPSTR pszTempName, int cbTempName,
  158. LPVOID pv)
  159. {
  160. char *psz = _tempnam("", "PCHPF"); // Get a name
  161. BOOL res = FALSE;
  162. if (psz != NULL)
  163. {
  164. if(strlen(psz) < (size_t)cbTempName)
  165. {
  166. strcpy(pszTempName, psz); // Copy to caller's buffer
  167. res = TRUE;
  168. }
  169. free(psz);
  170. }
  171. return res;
  172. }
  173. // **************************************************************************
  174. static long DIAMONDAPI fci_progress(UINT typeStatus, ULONG cb1, ULONG cb2,
  175. LPVOID pv)
  176. {
  177. return 0;
  178. }
  179. // **************************************************************************
  180. static BOOL DIAMONDAPI fci_get_next_cabinet(PCCAB pccab, ULONG cbPrevCab,
  181. LPVOID pv)
  182. {
  183. SPFFileInfo *ppffi = (SPFFileInfo *)pv;
  184. SplitPath(ppffi->szDestFile, pccab->szCabPath, pccab->szCab);
  185. return TRUE;
  186. }
  187. // **************************************************************************
  188. static INT_PTR DIAMONDAPI fci_get_open_info(LPSTR pszName, USHORT *pdate,
  189. USHORT *ptime, USHORT *pattribs,
  190. int *err, LPVOID pv)
  191. {
  192. BY_HANDLE_FILE_INFORMATION finfo;
  193. FILETIME filetime;
  194. HANDLE handle;
  195. DWORD attrs;
  196. int hf = -1;
  197. // Need a Win32 type handle to get file date/time using the Win32 APIs,
  198. // even though the handle we will be returning is of the type compatible
  199. // with _open
  200. handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
  201. OPEN_EXISTING,
  202. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  203. NULL);
  204. if (handle != INVALID_HANDLE_VALUE)
  205. {
  206. if (GetFileInformationByHandle(handle, &finfo))
  207. {
  208. FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
  209. FileTimeToDosDateTime(&filetime, pdate, ptime);
  210. attrs = GetFileAttributes(pszName);
  211. if (attrs == (DWORD)-1)
  212. {
  213. // failure
  214. *pattribs = 0;
  215. }
  216. else
  217. {
  218. // Mask out all other bits except these four, since other
  219. // bits are used by the cabinet format to indicate a
  220. // special meaning.
  221. *pattribs = (int)(attrs & (_A_RDONLY | _A_SYSTEM | _A_HIDDEN | _A_ARCH));
  222. }
  223. }
  224. CloseHandle(handle);
  225. }
  226. // Return handle using _open
  227. hf = _open( pszName, _O_RDONLY | _O_BINARY );
  228. if(hf == -1)
  229. {
  230. return -1; // abort on error
  231. }
  232. return hf;
  233. }
  234. /////////////////////////////////////////////////////////////////////////////
  235. //
  236. // **************************************************************************
  237. static INT_PTR DIAMONDAPI fdi_open(LPSTR pszFile, int oflag, int pmode)
  238. {
  239. return _open(pszFile, oflag, pmode);
  240. }
  241. // **************************************************************************
  242. static UINT DIAMONDAPI fdi_read(INT_PTR hf, LPVOID pv, UINT cb)
  243. {
  244. return _read((int)hf, pv, cb);
  245. }
  246. // **************************************************************************
  247. static UINT DIAMONDAPI fdi_write(INT_PTR hf, LPVOID pv, UINT cb)
  248. {
  249. return _write((int)hf, pv, cb);
  250. }
  251. // **************************************************************************
  252. static int DIAMONDAPI fdi_close(INT_PTR hf)
  253. {
  254. return _close((int)hf);
  255. }
  256. // **************************************************************************
  257. static long DIAMONDAPI fdi_seek(INT_PTR hf, long dist, int seektype)
  258. {
  259. return _lseek((int)hf, dist, seektype);
  260. }
  261. // **************************************************************************
  262. static INT_PTR DIAMONDAPI fdi_notify_copy(FDINOTIFICATIONTYPE fdint,
  263. PFDINOTIFICATION pfdin)
  264. {
  265. SPFFileInfo *ppffi = (SPFFileInfo *)pfdin->pv;
  266. switch(fdint)
  267. {
  268. // file to be copied
  269. case fdintCOPY_FILE:
  270. // is it an exact match?
  271. if (_stricmp(pfdin->psz1, ppffi->szFileName) == 0)
  272. {
  273. ppffi->fFound = TRUE;
  274. return fdi_open(ppffi->szDestFile,
  275. _O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL,
  276. _S_IREAD | _S_IWRITE);
  277. }
  278. // are we looking for a wildcard?
  279. else if (ppffi->szFileName[0] == '*' &&
  280. ppffi->szFileName[1] == '.' &&
  281. ppffi->szFileName[2] != '\0' &&
  282. ppffi->szFileName[3] != '\0' &&
  283. ppffi->szFileName[4] != '\0' &&
  284. ppffi->szFileName[5] == '\0')
  285. {
  286. // compare the suffix's
  287. char *p;
  288. p = strrchr(pfdin->psz1, '.');
  289. if (p != NULL && _stricmp(p, &(ppffi->szFileName[1])) == 0)
  290. {
  291. ppffi->fFound = TRUE;
  292. return fdi_open(ppffi->szDestFile,
  293. _O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL,
  294. _S_IREAD | _S_IWRITE);
  295. }
  296. }
  297. break;
  298. // close the file, set relevant info
  299. case fdintCLOSE_FILE_INFO:
  300. fdi_close(pfdin->hf);
  301. return TRUE;
  302. }
  303. return 0;
  304. }
  305. // **************************************************************************
  306. static INT_PTR DIAMONDAPI fdi_notify_enum(FDINOTIFICATIONTYPE fdint,
  307. PFDINOTIFICATION pfdin)
  308. {
  309. if (fdint == fdintCOPY_FILE)
  310. {
  311. CPFArrayBSTR *rgFiles = (CPFArrayBSTR *)pfdin->pv;
  312. CComBSTR bstr;
  313. bstr = pfdin->psz1;
  314. if (bstr.m_str != NULL && rgFiles != NULL)
  315. {
  316. if (SUCCEEDED(rgFiles->Append(bstr.m_str)))
  317. bstr.Detach();
  318. }
  319. }
  320. return 0;
  321. }
  322. /////////////////////////////////////////////////////////////////////////////
  323. // our exposed functions
  324. // **************************************************************************
  325. HRESULT PFExtractFromCab(LPWSTR wszCab, LPWSTR wszDestFile,
  326. LPWSTR wszFileToFind)
  327. {
  328. USES_CONVERSION;
  329. USE_TRACING("PFExtractFromCabinet");
  330. SPFFileInfo pffi;
  331. HRESULT hr = NOERROR;
  332. BOOL fRes = FALSE;
  333. HFDI hfdi = NULL;
  334. char szCabName[MAX_PATH];
  335. char szCabPath[MAX_PATH];
  336. BOOL fOk;
  337. ERF erf;
  338. VALIDATEPARM(hr, (wszCab == NULL || wszDestFile == NULL ||
  339. wszFileToFind == NULL));
  340. if (FAILED(hr))
  341. goto done;
  342. // create the cab handle
  343. hfdi = FDICreate(mem_alloc, mem_free, fdi_open, fdi_read, fdi_write,
  344. fdi_close, fdi_seek, cpuUNKNOWN, &erf);
  345. VALIDATEEXPR(hr, (hfdi == NULL), Err2HR(MyCabGetLastError()));
  346. if (FAILED(hr))
  347. goto done;
  348. __try
  349. {
  350. pffi.szCab = W2A(wszCab);
  351. pffi.szDestFile = W2A(wszDestFile);
  352. pffi.szFileName = W2A(wszFileToFind);
  353. pffi.fFound = FALSE;
  354. }
  355. __except(1)
  356. {
  357. hr = E_OUTOFMEMORY;
  358. }
  359. if (FAILED(hr))
  360. goto done;
  361. SplitPath(pffi.szCab, szCabPath, szCabName);
  362. fOk = FDICopy(hfdi, szCabName, szCabPath, 0, fdi_notify_copy, NULL, &pffi);
  363. VALIDATEEXPR(hr, (fOk == FALSE), Err2HR(MyCabGetLastError()));
  364. if (FAILED(hr))
  365. goto done;
  366. hr = (pffi.fFound) ? NOERROR : S_FALSE;
  367. done:
  368. if (hfdi != NULL)
  369. FDIDestroy(hfdi);
  370. return hr;
  371. }
  372. // **************************************************************************
  373. HRESULT PFGetCabFileList(LPWSTR wszCabName, CPFArrayBSTR &rgFiles)
  374. {
  375. USES_CONVERSION;
  376. USE_TRACING("PFGetCabFiles");
  377. CComBSTR bstr;
  378. HRESULT hr = NOERROR;
  379. HFDI hfdi = NULL;
  380. char szCabName[MAX_PATH], szCabPath[MAX_PATH], *pszCab = NULL;
  381. BOOL fOk;
  382. ERF erf;
  383. rgFiles.RemoveAll();
  384. VALIDATEPARM(hr, (wszCabName == NULL));
  385. if (FAILED(hr))
  386. goto done;
  387. __try
  388. {
  389. pszCab = W2A(wszCabName);
  390. _ASSERT(pszCab != NULL);
  391. }
  392. __except(1)
  393. {
  394. hr = E_OUTOFMEMORY;
  395. }
  396. if (FAILED(hr))
  397. goto done;
  398. hfdi = FDICreate(mem_alloc, mem_free, fdi_open, fdi_read, fdi_write,
  399. fdi_close, fdi_seek, cpuUNKNOWN, &erf);
  400. VALIDATEEXPR(hr, (hfdi == NULL), Err2HR(MyCabGetLastError()));
  401. if (FAILED(hr))
  402. goto done;
  403. SplitPath(pszCab, szCabPath, szCabName);
  404. fOk = FDICopy(hfdi, szCabName, szCabPath, 0, fdi_notify_enum, NULL,
  405. &rgFiles);
  406. VALIDATEEXPR(hr, (fOk == FALSE), Err2HR(MyCabGetLastError()));
  407. if (FAILED(hr))
  408. goto done;
  409. done:
  410. if (hfdi != NULL)
  411. FDIDestroy(hfdi);
  412. return hr;
  413. }