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.

466 lines
14 KiB

  1. /*++
  2. Copyright (C) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. MRCICLASS.CPP
  5. Abstract:
  6. Implements the Wrapper class for MRCI 1 & MRCI 2 maxcompress
  7. and decompress functions
  8. History:
  9. paulall 1-Jul-97 Created
  10. --*/
  11. #include "precomp.h"
  12. #include <io.h>
  13. #include <stdio.h>
  14. #include <fcntl.h>
  15. #include <sys\stat.h>
  16. #include "MRCIclass.h"
  17. class CMRCICompressionHeaderV1
  18. {
  19. public:
  20. char cVersion; //Compression file format
  21. char compressionLevel; //Is this a level 1 or level 2 compression
  22. DWORD dwReadBufferSize; //Buffer size used to read original file
  23. FILETIME ftCreateTime; //Time and date file created
  24. __int64 dwOriginalSize; //Original file length
  25. // ... for each buffer
  26. // CMRCICompressionBlockV1 block;
  27. // ... until dwNextBufferSize is 0
  28. };
  29. class CMRCICompressionBlockV1
  30. {
  31. public:
  32. char bCompressed; //Was this block compressed
  33. DWORD dwNextBufferSize; //Size of the proceeding buffer
  34. DWORD dwUncompressedBufferSize; //Size needed for uncompress buffer
  35. //char[dwNextBufferSize]; //next block is the compression part
  36. };
  37. CMRCICompression::CMRCICompression()
  38. {
  39. }
  40. CMRCICompression::~CMRCICompression()
  41. {
  42. }
  43. BOOL CMRCICompression::GetCompressedFileInfo(const wchar_t *pchFile,
  44. CompressionLevel &compressionLevel,
  45. DWORD &dwReadBufferSize,
  46. FILETIME &ftCreateTime,
  47. __int64 &dwOriginalSize)
  48. {
  49. BOOL bStatus = FALSE;
  50. int hFile = _wopen(pchFile,_O_BINARY | _O_RDONLY, 0);
  51. if (hFile != -1)
  52. {
  53. CMRCICompressionHeaderV1 header;
  54. if (_read(hFile, &header, sizeof(CMRCICompressionHeaderV1)) ==
  55. sizeof(CMRCICompressionHeaderV1))
  56. {
  57. compressionLevel = (CompressionLevel)header.cVersion;
  58. dwReadBufferSize = header.dwReadBufferSize;
  59. ftCreateTime = header.ftCreateTime;
  60. dwOriginalSize = header.dwOriginalSize;
  61. //If the version is 0xFF, the file is not valid!
  62. if (header.cVersion != 0xFF)
  63. bStatus = TRUE;
  64. }
  65. _close(hFile);
  66. }
  67. return bStatus;
  68. }
  69. BOOL CMRCICompression::CompressFile(const wchar_t *pchFileFrom,
  70. const TCHAR *pchFileTo,
  71. DWORD dwBufferSize,
  72. CompressionLevel compressionLevel,
  73. CMRCIControl *pControlObject)
  74. {
  75. BOOL bStatus = FALSE;
  76. int fileFrom;
  77. int fileTo;
  78. //Open the files for processing
  79. //=============================
  80. fileFrom = _wopen(pchFileFrom,_O_BINARY | _O_RDONLY, 0);
  81. fileTo = _wopen(pchFileTo, _O_BINARY | _O_TRUNC | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE);
  82. //If open sucessful
  83. //=================
  84. if ((fileFrom != -1) && (fileTo != -1))
  85. {
  86. //DO the compression using the latest and greatest version
  87. //========================================================
  88. bStatus = CompressFileV1(fileFrom, fileTo, dwBufferSize, compressionLevel, pControlObject);
  89. }
  90. //Close the files
  91. //===============
  92. if (fileFrom != -1)
  93. _close(fileFrom);
  94. if (fileTo != -1)
  95. _close(fileTo);
  96. if (pControlObject && pControlObject->AbortRequested())
  97. {
  98. //User requested an abort, so we need to delete the compressed file...
  99. _wunlink(pchFileTo);
  100. bStatus = FALSE;
  101. }
  102. return bStatus;
  103. }
  104. BOOL CMRCICompression::CompressFileV1(int hFileFrom,
  105. int hFileTo,
  106. DWORD dwBufferSize,
  107. CompressionLevel compressionLevel,
  108. CMRCIControl *pControlObject)
  109. {
  110. BOOL bStatus = FALSE;
  111. unsigned char *pBufferFrom = new unsigned char[dwBufferSize + 4];
  112. unsigned char *pBufferTo = new unsigned char[dwBufferSize + 4];
  113. if (pBufferFrom && pBufferTo)
  114. {
  115. //Write the header to the new file
  116. //================================
  117. CMRCICompressionHeaderV1 header;
  118. header.cVersion = char(0xFF); //INVALID. We write the header back when we have
  119. //finished! When we read this, we check to see
  120. //if this is invalid. We do not uncompress if it is
  121. //this value....
  122. header.compressionLevel = compressionLevel;
  123. header.dwReadBufferSize = dwBufferSize;
  124. SYSTEMTIME sysTime;
  125. GetSystemTime(&sysTime);
  126. SystemTimeToFileTime(&sysTime, &header.ftCreateTime);
  127. header.dwOriginalSize = _filelengthi64(hFileFrom);
  128. if (_write(hFileTo, &header, sizeof(CMRCICompressionHeaderV1)) != sizeof(CMRCICompressionHeaderV1))
  129. {
  130. delete [] pBufferFrom;
  131. delete [] pBufferTo;
  132. bStatus = FALSE;
  133. return bStatus;
  134. }
  135. __int64 remainingFileSize = header.dwOriginalSize;
  136. unsigned cbChunk;
  137. unsigned cbCompressed;
  138. bStatus = TRUE;
  139. //While we have some file to write...
  140. //===================================
  141. while (remainingFileSize)
  142. {
  143. //See if we need to abort the compression...
  144. if (pControlObject && pControlObject->AbortRequested())
  145. {
  146. break;
  147. }
  148. //Calculate the size of this buffer to compress
  149. //=============================================
  150. if (remainingFileSize > dwBufferSize)
  151. {
  152. cbChunk = dwBufferSize;
  153. }
  154. else
  155. {
  156. cbChunk = (unsigned) remainingFileSize;
  157. }
  158. //Read from the source file
  159. //=========================
  160. if (_read(hFileFrom, pBufferFrom, cbChunk) != (int) cbChunk)
  161. {
  162. bStatus = FALSE;
  163. break;
  164. }
  165. //Calculate what is left to read
  166. //==============================
  167. remainingFileSize -= cbChunk;
  168. //Compress the buffer
  169. //===================
  170. cbCompressed = CompressBuffer(pBufferFrom, cbChunk, pBufferTo, dwBufferSize, compressionLevel);
  171. //Create the compression block header
  172. CMRCICompressionBlockV1 block;
  173. unsigned char *pWriteBuffer;
  174. unsigned thisBufferSize;
  175. if ((cbCompressed == (unsigned) -1) || (cbCompressed >= cbChunk))
  176. {
  177. //This means compression failed or there was no compression...
  178. block.bCompressed = FALSE;
  179. pWriteBuffer = pBufferFrom;
  180. thisBufferSize = cbChunk;
  181. }
  182. else
  183. {
  184. block.bCompressed = TRUE;
  185. pWriteBuffer = pBufferTo;
  186. thisBufferSize = cbCompressed;
  187. }
  188. block.dwNextBufferSize = thisBufferSize;
  189. block.dwUncompressedBufferSize = cbChunk;
  190. //Write the block header
  191. //======================
  192. if (_write(hFileTo, &block, sizeof(CMRCICompressionBlockV1)) != sizeof(CMRCICompressionBlockV1))
  193. {
  194. bStatus = FALSE;
  195. break;
  196. }
  197. //Write the compressed block
  198. //==========================
  199. if (_write(hFileTo, pWriteBuffer, thisBufferSize) != (int)thisBufferSize)
  200. {
  201. bStatus = FALSE;
  202. break;
  203. }
  204. }
  205. if (pControlObject && pControlObject->AbortRequested())
  206. {
  207. //User requested an abort...
  208. }
  209. else
  210. {
  211. //Write final block header with zero length buffer marker
  212. CMRCICompressionBlockV1 block;
  213. block.dwNextBufferSize = 0;
  214. block.bCompressed = FALSE;
  215. if (_write(hFileTo, &block, sizeof(CMRCICompressionBlockV1)) != -1 &&
  216. _lseek(hFileTo, 0, SEEK_SET) != -1)
  217. {
  218. //Write a valid block header to the start with a correct version number
  219. header.cVersion = 1; //Set this to the correct version
  220. bStatus =
  221. _write(hFileTo, &header, sizeof(CMRCICompressionHeaderV1)) != -1;
  222. }
  223. else
  224. bStatus = FALSE;
  225. }
  226. }
  227. //Tidy up
  228. delete [] pBufferFrom;
  229. delete [] pBufferTo;
  230. return bStatus;
  231. }
  232. unsigned CMRCICompression::CompressBuffer(unsigned char *pFromBuffer,
  233. DWORD dwFromBufferSize,
  234. unsigned char *pToBuffer,
  235. DWORD dwToBufferSize,
  236. CompressionLevel compressionLevel)
  237. {
  238. unsigned cbCompressed;
  239. if (compressionLevel == level1)
  240. {
  241. cbCompressed = Mrci1MaxCompress(pFromBuffer, dwFromBufferSize, pToBuffer, dwToBufferSize);
  242. }
  243. else
  244. {
  245. cbCompressed = Mrci2MaxCompress(pFromBuffer, dwFromBufferSize, pToBuffer, dwToBufferSize);
  246. }
  247. return cbCompressed;
  248. }
  249. BOOL CMRCICompression::UncompressFile(const wchar_t *pchFromFile, const wchar_t *pchToFile)
  250. {
  251. BOOL bStatus = FALSE;
  252. int fileFrom;
  253. int fileTo;
  254. //Open the files
  255. //==============
  256. fileFrom = _wopen(pchFromFile,_O_BINARY | _O_RDONLY, 0);
  257. fileTo = _wopen(pchToFile, _O_BINARY | _O_TRUNC | _O_CREAT | _O_WRONLY, _S_IREAD | _S_IWRITE);
  258. if ((fileFrom != -1) && (fileTo != -1))
  259. {
  260. //Read the version...
  261. //===================
  262. char cVer;
  263. if (_read(fileFrom, &cVer, sizeof(char)) == sizeof(char))
  264. {
  265. //Reset the file position to the start
  266. //====================================
  267. if (_lseek(fileFrom, 0, SEEK_SET) != -1)
  268. {
  269. //Call the uncompress with the equivelant method which created
  270. //the compression
  271. //============================================================
  272. switch(cVer)
  273. {
  274. case 1:
  275. bStatus = UncompressFileV1(fileFrom, fileTo);
  276. break;
  277. case 0xFF:
  278. //INVALID FILE!
  279. default:
  280. //Unsupported version
  281. break;
  282. }
  283. }
  284. }
  285. }
  286. //CLose the files
  287. //===============
  288. if (fileFrom != -1)
  289. _close(fileFrom);
  290. if (fileTo != -1)
  291. _close(fileTo);
  292. return bStatus;
  293. }
  294. BOOL CMRCICompression::UncompressFileV1(int hFileFrom, int hFileTo)
  295. {
  296. BOOL bStatus = FALSE;
  297. unsigned char *pBufferFrom = NULL;
  298. unsigned char *pBufferTo = NULL;
  299. //Read the header
  300. //===============
  301. CMRCICompressionHeaderV1 header;
  302. if (_read(hFileFrom, &header, sizeof(CMRCICompressionHeaderV1)) !=
  303. sizeof(CMRCICompressionHeaderV1))
  304. return FALSE;
  305. //Allocate buffers. The read buffer is never buffer than the write buffer
  306. //cos if it would have been we saved the uncompressed version!
  307. pBufferFrom = new unsigned char[header.dwReadBufferSize + 4];
  308. if (pBufferFrom == 0)
  309. return FALSE;
  310. pBufferTo = new unsigned char[header.dwReadBufferSize + 4];
  311. if (pBufferTo == 0)
  312. {
  313. delete [] pBufferFrom;
  314. return FALSE;
  315. }
  316. bStatus = TRUE;
  317. while (1)
  318. {
  319. //Read the block header
  320. //=====================
  321. CMRCICompressionBlockV1 block;
  322. if (_read(hFileFrom, &block, sizeof(CMRCICompressionBlockV1)) !=
  323. sizeof(CMRCICompressionBlockV1))
  324. {
  325. bStatus = FALSE;
  326. break;
  327. }
  328. if (block.dwNextBufferSize == 0)
  329. {
  330. bStatus = TRUE;
  331. break;
  332. }
  333. //Read the block data
  334. //===================
  335. if (_read(hFileFrom, pBufferFrom, block.dwNextBufferSize) != (int)block.dwNextBufferSize)
  336. {
  337. bStatus = FALSE;
  338. break;
  339. }
  340. unsigned char *pWriteBuffer;
  341. unsigned cbChunk, cbUncompressed;
  342. //If this block was compressed
  343. //============================
  344. if (block.bCompressed)
  345. {
  346. //Uncompress the block
  347. //====================
  348. if ((cbUncompressed = UncompressBuffer(pBufferFrom, block.dwNextBufferSize, pBufferTo, block.dwUncompressedBufferSize, (CompressionLevel)header.compressionLevel)) == (unsigned) -1)
  349. {
  350. bStatus = FALSE;
  351. break;
  352. }
  353. pWriteBuffer = pBufferTo;
  354. cbChunk = cbUncompressed;
  355. }
  356. else
  357. {
  358. //Otherwise we use the existing block
  359. pWriteBuffer = pBufferFrom;
  360. cbChunk = block.dwNextBufferSize;
  361. }
  362. //Write the file data
  363. _write(hFileTo, pWriteBuffer, cbChunk);
  364. }
  365. //Sanity check the file. It should be the same size as the original
  366. //compressed file
  367. if (_filelengthi64(hFileTo) != header.dwOriginalSize)
  368. {
  369. bStatus = FALSE;
  370. }
  371. //Tidy up
  372. delete [] pBufferFrom;
  373. delete [] pBufferTo;
  374. return bStatus;
  375. }
  376. unsigned CMRCICompression::UncompressBuffer(unsigned char *pFromBuffer,
  377. DWORD dwFromBufferSize,
  378. unsigned char *pToBuffer,
  379. DWORD dwToBufferSize,
  380. CompressionLevel compressionLevel)
  381. {
  382. unsigned cbCompressed;
  383. if (compressionLevel == level1)
  384. {
  385. cbCompressed = Mrci1Decompress(pFromBuffer, dwFromBufferSize, pToBuffer, dwToBufferSize);
  386. }
  387. else
  388. {
  389. cbCompressed = Mrci2Decompress(pFromBuffer, dwFromBufferSize, pToBuffer, dwToBufferSize);
  390. }
  391. return cbCompressed;
  392. }