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.

596 lines
11 KiB

  1. /*++
  2. Module Name:
  3. diamond.c
  4. Abstract:
  5. Diamond compression routines.
  6. This module contains functions to create a cabinet with
  7. files compressed using the mszip compression library.
  8. Author:
  9. Ovidiu Temereanca (ovidiut) 26-Oct-2000
  10. --*/
  11. #include "precomp.h"
  12. #include <fci.h>
  13. #include <io.h>
  14. #include <fcntl.h>
  15. static DWORD g_DiamondLastError;
  16. static PCSTR g_TempDir = NULL;
  17. HFCI
  18. (DIAMONDAPI* g_FCICreate) (
  19. PERF perf,
  20. PFNFCIFILEPLACED pfnfcifp,
  21. PFNFCIALLOC pfna,
  22. PFNFCIFREE pfnf,
  23. PFNFCIOPEN pfnopen,
  24. PFNFCIREAD pfnread,
  25. PFNFCIWRITE pfnwrite,
  26. PFNFCICLOSE pfnclose,
  27. PFNFCISEEK pfnseek,
  28. PFNFCIDELETE pfndelete,
  29. PFNFCIGETTEMPFILE pfnfcigtf,
  30. PCCAB pccab,
  31. void FAR * pv
  32. );
  33. BOOL
  34. (DIAMONDAPI* g_FCIAddFile) (
  35. HFCI hfci,
  36. char *pszSourceFile,
  37. char *pszFileName,
  38. BOOL fExecute,
  39. PFNFCIGETNEXTCABINET pfnfcignc,
  40. PFNFCISTATUS pfnfcis,
  41. PFNFCIGETOPENINFO pfnfcigoi,
  42. TCOMP typeCompress
  43. );
  44. /*
  45. BOOL
  46. (DIAMONDAPI* g_FCIFlushFolder) (
  47. HFCI hfci,
  48. PFNFCIGETNEXTCABINET pfnfcignc,
  49. PFNFCISTATUS pfnfcis
  50. );
  51. */
  52. BOOL
  53. (DIAMONDAPI* g_FCIFlushCabinet) (
  54. HFCI hfci,
  55. BOOL fGetNextCab,
  56. PFNFCIGETNEXTCABINET pfnfcignc,
  57. PFNFCISTATUS pfnfcis
  58. );
  59. BOOL
  60. (DIAMONDAPI* g_FCIDestroy) (
  61. HFCI hfci
  62. );
  63. //
  64. // Callback functions to perform memory allocation, io, etc.
  65. // We pass addresses of these functions to diamond.
  66. //
  67. int
  68. DIAMONDAPI
  69. fciFilePlacedCB(
  70. OUT PCCAB Cabinet,
  71. IN PSTR FileName,
  72. IN LONG FileSize,
  73. IN BOOL Continuation,
  74. IN PVOID Context
  75. )
  76. /*++
  77. Routine Description:
  78. Callback used by diamond to indicate that a file has been
  79. comitted to a cabinet.
  80. No action is taken and success is returned.
  81. Arguments:
  82. Cabinet - cabinet structure to fill in.
  83. FileName - name of file in cabinet
  84. FileSize - size of file in cabinet
  85. Continuation - TRUE if this is a partial file, continuation
  86. of compression begun in a different cabinet.
  87. Context - supplies context information.
  88. Return Value:
  89. 0 (success).
  90. --*/
  91. {
  92. return(0);
  93. }
  94. PVOID
  95. DIAMONDAPI
  96. fciAllocCB(
  97. IN ULONG NumberOfBytes
  98. )
  99. /*++
  100. Routine Description:
  101. Callback used by diamond to allocate memory.
  102. Arguments:
  103. NumberOfBytes - supplies desired size of block.
  104. Return Value:
  105. Returns pointer to a block of memory or NULL
  106. if memory cannot be allocated.
  107. --*/
  108. {
  109. return((PVOID)LocalAlloc(LMEM_FIXED,NumberOfBytes));
  110. }
  111. VOID
  112. DIAMONDAPI
  113. fciFreeCB(
  114. IN PVOID Block
  115. )
  116. /*++
  117. Routine Description:
  118. Callback used by diamond to free a memory block.
  119. The block must have been allocated with fciAlloc().
  120. Arguments:
  121. Block - supplies pointer to block of memory to be freed.
  122. Return Value:
  123. None.
  124. --*/
  125. {
  126. LocalFree((HLOCAL)Block);
  127. }
  128. FNFCIGETTEMPFILE(fciTempFileCB)
  129. {
  130. if (!GetTempFileNameA (g_TempDir ? g_TempDir : ".", "dc" ,0 , pszTempName)) {
  131. return FALSE;
  132. }
  133. DeleteFileA(pszTempName);
  134. return(TRUE);
  135. }
  136. BOOL
  137. DIAMONDAPI
  138. fciNextCabinetCB(
  139. OUT PCCAB Cabinet,
  140. IN DWORD CabinetSizeEstimate,
  141. IN PVOID Context
  142. )
  143. /*++
  144. Routine Description:
  145. Callback used by diamond to request a new cabinet file.
  146. This functionality is not used in our implementation.
  147. Arguments:
  148. Cabinet - cabinet structure to be filled in.
  149. CabinetSizeEstimate - estimated size of cabinet.
  150. Context - supplies context information.
  151. Return Value:
  152. FALSE (failure).
  153. --*/
  154. {
  155. return(FALSE);
  156. }
  157. BOOL
  158. DIAMONDAPI
  159. fciStatusCB(
  160. IN UINT StatusType,
  161. IN DWORD Count1,
  162. IN DWORD Count2,
  163. IN PVOID Context
  164. )
  165. /*++
  166. Routine Description:
  167. Callback used by diamond to give status on file compression
  168. and cabinet operations, etc.
  169. This routine has no effect.
  170. Arguments:
  171. Status Type - supplies status type.
  172. 0 = statusFile - compressing block into a folder.
  173. Count1 = compressed size
  174. Count2 = uncompressed size
  175. 1 = statusFolder - performing AddFilder.
  176. Count1 = bytes done
  177. Count2 = total bytes
  178. Context - supplies context info.
  179. Return Value:
  180. TRUE (success).
  181. --*/
  182. {
  183. return(TRUE);
  184. }
  185. FNFCIGETOPENINFO(fciOpenInfoCB)
  186. /*++
  187. Routine Description:
  188. Callback used by diamond to open a file and retreive information
  189. about it.
  190. Arguments:
  191. pszName - supplies filename of file about which information
  192. is desired.
  193. pdate - receives last write date of the file if the file exists.
  194. ptime - receives last write time of the file if the file exists.
  195. pattribs - receives file attributes if the file exists.
  196. pv - supplies context information.
  197. Return Value:
  198. C runtime handle to open file if success; -1 if file could
  199. not be located or opened.
  200. --*/
  201. {
  202. int h;
  203. WIN32_FIND_DATAA FindData;
  204. HANDLE FindHandle;
  205. FindHandle = FindFirstFileA(pszName,&FindData);
  206. if(FindHandle == INVALID_HANDLE_VALUE) {
  207. g_DiamondLastError = GetLastError();
  208. return(-1);
  209. }
  210. FindClose(FindHandle);
  211. FileTimeToDosDateTime(&FindData.ftLastWriteTime,pdate,ptime);
  212. *pattribs = (WORD)FindData.dwFileAttributes;
  213. h = _open(pszName,_O_RDONLY | _O_BINARY);
  214. if(h == -1) {
  215. g_DiamondLastError = GetLastError();
  216. return(-1);
  217. }
  218. return(h);
  219. }
  220. FNFCIOPEN(fciOpen)
  221. {
  222. int result;
  223. result = _open(pszFile, oflag, pmode);
  224. if (result == -1) {
  225. *err = errno;
  226. }
  227. return(result);
  228. }
  229. FNFCIREAD(fciRead)
  230. {
  231. UINT result;
  232. result = (UINT) _read((int)hf, memory, cb);
  233. if (result != cb) {
  234. *err = errno;
  235. }
  236. return(result);
  237. }
  238. FNFCIWRITE(fciWrite)
  239. {
  240. UINT result;
  241. result = (UINT) _write((int)hf, memory, cb);
  242. if (result != cb) {
  243. *err = errno;
  244. }
  245. return(result);
  246. }
  247. FNFCICLOSE(fciClose)
  248. {
  249. int result;
  250. result = _close((int)hf);
  251. if (result == -1) {
  252. *err = errno;
  253. }
  254. return(result);
  255. }
  256. FNFCISEEK(fciSeek)
  257. {
  258. long result;
  259. result = _lseek((int)hf, dist, seektype);
  260. if (result == -1) {
  261. *err = errno;
  262. }
  263. return(result);
  264. }
  265. FNFCIDELETE(fciDelete)
  266. {
  267. int result;
  268. result = _unlink(pszFile);
  269. if (result == -1) {
  270. *err = errno;
  271. }
  272. return(result);
  273. }
  274. HANDLE
  275. DiamondInitialize (
  276. IN PCTSTR TempDir
  277. )
  278. {
  279. HMODULE hCabinetDll;
  280. hCabinetDll = LoadLibrary (TEXT("cabinet.dll"));
  281. if (!hCabinetDll) {
  282. return FALSE;
  283. }
  284. (FARPROC)g_FCICreate = GetProcAddress (hCabinetDll, "FCICreate");
  285. (FARPROC)g_FCIAddFile = GetProcAddress (hCabinetDll, "FCIAddFile");
  286. (FARPROC)g_FCIFlushCabinet = GetProcAddress (hCabinetDll, "FCIFlushCabinet");
  287. (FARPROC)g_FCIDestroy = GetProcAddress (hCabinetDll, "FCIDestroy");
  288. if (!g_FCICreate || !g_FCIAddFile || !g_FCIFlushCabinet || !g_FCIDestroy) {
  289. DiamondTerminate (hCabinetDll);
  290. return NULL;
  291. }
  292. if (TempDir && !g_TempDir) {
  293. #ifdef UNICODE
  294. g_TempDir = UnicodeToAnsi (TempDir);
  295. #else
  296. g_TempDir = DupString (TempDir);
  297. #endif
  298. }
  299. return hCabinetDll;
  300. }
  301. VOID
  302. DiamondTerminate (
  303. IN HANDLE Handle
  304. )
  305. {
  306. FreeLibrary (Handle);
  307. g_FCICreate = NULL;
  308. g_FCIAddFile = NULL;
  309. g_FCIFlushCabinet = NULL;
  310. g_FCIDestroy = NULL;
  311. if (g_TempDir) {
  312. FREE ((PVOID)g_TempDir);
  313. g_TempDir = NULL;
  314. }
  315. }
  316. HANDLE
  317. DiamondStartNewCabinet (
  318. IN PCTSTR CabinetFilePath
  319. )
  320. {
  321. CCAB ccab;
  322. ERF FciError;
  323. HFCI FciContext;
  324. PSTR p;
  325. //
  326. // Fill in the cabinet structure.
  327. //
  328. ZeroMemory (&ccab, sizeof(ccab));
  329. #ifdef UNICODE
  330. if (!WideCharToMultiByte (
  331. CP_ACP,
  332. 0,
  333. CabinetFilePath,
  334. -1,
  335. ccab.szCabPath,
  336. sizeof (ccab.szCabPath) / sizeof (ccab.szCabPath[0]),
  337. NULL,
  338. NULL
  339. )) {
  340. return NULL;
  341. }
  342. #else
  343. lstrcpyA (ccab.szCabPath, CabinetFilePath);
  344. #endif
  345. p = strrchr (ccab.szCabPath, '\\');
  346. if(!p) {
  347. SetLastError (ERROR_INVALID_PARAMETER);
  348. return NULL;
  349. }
  350. lstrcpyA (ccab.szCab, ++p);
  351. *p = 0;
  352. g_DiamondLastError = NO_ERROR;
  353. FciContext = g_FCICreate(
  354. &FciError,
  355. fciFilePlacedCB,
  356. fciAllocCB,
  357. fciFreeCB,
  358. fciOpen,
  359. fciRead,
  360. fciWrite,
  361. fciClose,
  362. fciSeek,
  363. fciDelete,
  364. fciTempFileCB,
  365. &ccab,
  366. NULL
  367. );
  368. return (HANDLE)FciContext;
  369. }
  370. BOOL
  371. DiamondAddFileToCabinet (
  372. IN HANDLE CabinetContext,
  373. IN PCTSTR SourceFile,
  374. IN PCTSTR NameInCabinet
  375. )
  376. {
  377. HFCI FciContext = (HFCI)CabinetContext;
  378. BOOL b;
  379. CHAR AnsiSourceFile[MAX_PATH];
  380. CHAR AnsiNameInCabinet[MAX_PATH];
  381. #ifdef UNICODE
  382. if (!WideCharToMultiByte (
  383. CP_ACP,
  384. 0,
  385. SourceFile,
  386. -1,
  387. AnsiSourceFile,
  388. sizeof (AnsiSourceFile) / sizeof (AnsiSourceFile[0]),
  389. NULL,
  390. NULL
  391. ) ||
  392. !WideCharToMultiByte (
  393. CP_ACP,
  394. 0,
  395. NameInCabinet,
  396. -1,
  397. AnsiNameInCabinet,
  398. sizeof (AnsiNameInCabinet) / sizeof (AnsiNameInCabinet[0]),
  399. NULL,
  400. NULL
  401. )) {
  402. return FALSE;
  403. }
  404. #else
  405. lstrcpyA (AnsiSourceFile, SourceFile);
  406. lstrcpyA (AnsiNameInCabinet, NameInCabinet);
  407. #endif
  408. b = g_FCIAddFile (
  409. FciContext,
  410. AnsiSourceFile, // file to add to cabinet.
  411. AnsiNameInCabinet, // filename part, name to store in cabinet.
  412. FALSE, // fExecute on extract
  413. fciNextCabinetCB, // routine for next cabinet (always fails)
  414. fciStatusCB,
  415. fciOpenInfoCB,
  416. tcompTYPE_MSZIP
  417. );
  418. if (!b) {
  419. SetLastError (g_DiamondLastError == NO_ERROR ? ERROR_INVALID_FUNCTION : g_DiamondLastError);
  420. }
  421. return b;
  422. }
  423. BOOL
  424. DiamondTerminateCabinet (
  425. IN HANDLE CabinetContext
  426. )
  427. {
  428. HFCI FciContext = (HFCI)CabinetContext;
  429. BOOL b;
  430. b = g_FCIFlushCabinet (
  431. FciContext,
  432. FALSE,
  433. fciNextCabinetCB,
  434. fciStatusCB
  435. );
  436. g_FCIDestroy (FciContext);
  437. if (!b) {
  438. SetLastError (g_DiamondLastError == NO_ERROR ? ERROR_INVALID_FUNCTION : g_DiamondLastError);
  439. }
  440. return b;
  441. }