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.

597 lines
12 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. mrcf.c
  5. Abstract:
  6. This module implements the Mrcf compression engine.
  7. Author:
  8. Gary Kimura [GaryKi] 21-Jan-1994
  9. Revision History:
  10. --*/
  11. #include "ntrtlp.h"
  12. #include <stdio.h>
  13. //
  14. // To decompress/compress a block of data the user needs to
  15. // provide a work space as an extra parameter to all the exported
  16. // procedures. That way the routines will not need to use excessive
  17. // stack space and will still be multithread safe
  18. //
  19. //
  20. // Variables for reading and writing bits
  21. //
  22. typedef struct _MRCF_BIT_IO {
  23. USHORT abitsBB; // 16-bit buffer being read
  24. LONG cbitsBB; // Number of bits left in abitsBB
  25. PUCHAR pbBB; // Pointer to byte stream being read
  26. ULONG cbBB; // Number of bytes left in pbBB
  27. ULONG cbBBInitial; // Initial size of pbBB
  28. } MRCF_BIT_IO;
  29. typedef MRCF_BIT_IO *PMRCF_BIT_IO;
  30. //
  31. // Maximum back-pointer value, also used to indicate end of compressed stream!
  32. //
  33. #define wBACKPOINTERMAX (4415)
  34. //
  35. // MDSIGNATURE - Signature at start of each compressed block
  36. //
  37. // This 4-byte signature is used as a check to ensure that we
  38. // are decompressing data we compressed, and also to indicate
  39. // which compression method was used.
  40. //
  41. // NOTE: A compressed block consists of one or more "chunks", separated
  42. // by the bitsEND_OF_STREAM pattern.
  43. //
  44. // Byte Word
  45. // ----------- ---------
  46. // 0 1 2 3 0 1 Meaning
  47. // -- -- -- -- ---- ---- ----------------
  48. // 44 53 00 01 5344 0100 MaxCompression
  49. // 44 53 00 02 5344 0200 StandardCompression
  50. //
  51. // NOTE: The *WORD* values are listed to be clear about the
  52. // byte ordering!
  53. //
  54. typedef struct _MDSIGNATURE {
  55. //
  56. // Must be MD_STAMP
  57. //
  58. USHORT sigStamp;
  59. //
  60. // mdsSTANDARD or mdsMAX
  61. //
  62. USHORT sigType;
  63. } MDSIGNATURE;
  64. typedef MDSIGNATURE *PMDSIGNATURE;
  65. #define MD_STAMP 0x5344 // Signature stamp at start of compressed blk
  66. #define MASK_VALID_mds 0x0300 // All other bits must be zero
  67. //
  68. // Local procedure declarations and macros
  69. //
  70. #define minimum(a,b) (a < b ? a : b)
  71. //
  72. // Local procedure prototypes
  73. //
  74. VOID
  75. MrcfSetBitBuffer (
  76. PUCHAR pb,
  77. ULONG cb,
  78. PMRCF_BIT_IO BitIo
  79. );
  80. VOID
  81. MrcfFillBitBuffer (
  82. PMRCF_BIT_IO BitIo
  83. );
  84. USHORT
  85. MrcfReadBit (
  86. PMRCF_BIT_IO BitIo
  87. );
  88. USHORT
  89. MrcfReadNBits (
  90. LONG cbits,
  91. PMRCF_BIT_IO BitIo
  92. );
  93. NTSTATUS
  94. RtlDecompressBufferMrcf (
  95. OUT PUCHAR UncompressedBuffer,
  96. IN ULONG UncompressedBufferSize,
  97. IN PUCHAR CompressedBuffer,
  98. IN ULONG CompressedBufferSize,
  99. OUT PULONG FinalUncompressedSize
  100. )
  101. /*++
  102. Routine Description:
  103. This routine decompresses a buffer of StandardCompressed or MaxCompressed
  104. data.
  105. Arguments:
  106. UncompressedBuffer - buffer to receive uncompressed data
  107. UncompressedBufferSize - length of UncompressedBuffer
  108. NOTE: UncompressedBufferSize must be the EXACT length of the uncompressed
  109. data, as Decompress uses this information to detect
  110. when decompression is complete. If this value is
  111. incorrect, Decompress may crash!
  112. CompressedBuffer - buffer containing compressed data
  113. CompressedBufferSize - length of CompressedBuffer
  114. WorkSpace - pointer to a private work area for use by this operation
  115. Return Value:
  116. ULONG - Returns the size of the decompressed data in bytes. Returns 0 if
  117. there was an error in the decompress.
  118. --*/
  119. {
  120. MRCF_BIT_IO WorkSpace;
  121. ULONG cbMatch; // Length of match string
  122. ULONG i; // Index in UncompressedBuffer to receive decoded data
  123. ULONG iMatch; // Index in UncompressedBuffer of matched string
  124. ULONG k; // Number of bits in length string
  125. ULONG off; // Offset from i in UncompressedBuffer of match string
  126. USHORT x; // Current bit being examined
  127. ULONG y;
  128. //
  129. // verify that compressed data starts with proper signature
  130. //
  131. if (CompressedBufferSize < sizeof(MDSIGNATURE) || // Must have signature
  132. ((PMDSIGNATURE)CompressedBuffer)->sigStamp != MD_STAMP || // Stamp must be OK
  133. ((PMDSIGNATURE)CompressedBuffer)->sigType & (~MASK_VALID_mds)) { // Type must be OK
  134. *FinalUncompressedSize = 0;
  135. return STATUS_BAD_COMPRESSION_BUFFER;
  136. }
  137. //
  138. // Skip over the valid signature
  139. //
  140. CompressedBufferSize -= sizeof(MDSIGNATURE);
  141. CompressedBuffer += sizeof(MDSIGNATURE);
  142. //
  143. // Set up for decompress, start filling UncompressedBuffer at front
  144. //
  145. i = 0;
  146. //
  147. // Set statics to save parm passing
  148. //
  149. MrcfSetBitBuffer(CompressedBuffer,CompressedBufferSize,&WorkSpace);
  150. while (TRUE) {
  151. y = MrcfReadNBits(2,&WorkSpace);
  152. //
  153. // Check if next 7 bits are a byte
  154. // 1 if 128..255 (0x80..0xff), 2 if 0..127 (0x00..0x7f)
  155. //
  156. if (y == 1 || y == 2) {
  157. ASSERTMSG("Don't exceed expected length ", i<UncompressedBufferSize);
  158. UncompressedBuffer[i] = (UCHAR)((y == 1 ? 0x80 : 0) | MrcfReadNBits(7,&WorkSpace));
  159. i++;
  160. } else {
  161. //
  162. // Have match sequence
  163. //
  164. //
  165. // Get the offset
  166. //
  167. if (y == 0) {
  168. //
  169. // next 6 bits are offset
  170. //
  171. off = MrcfReadNBits(6,&WorkSpace);
  172. ASSERTMSG("offset 0 is invalid ", off != 0);
  173. } else {
  174. x = MrcfReadBit(&WorkSpace);
  175. if (x == 0) {
  176. //
  177. // next 8 bits are offset-64 (0x40)
  178. //
  179. off = MrcfReadNBits(8, &WorkSpace) + 64;
  180. } else {
  181. //
  182. // next 12 bits are offset-320 (0x140)
  183. //
  184. off = MrcfReadNBits(12, &WorkSpace) + 320;
  185. if (off == wBACKPOINTERMAX) {
  186. //
  187. // EOS marker
  188. //
  189. if (i >= UncompressedBufferSize) {
  190. //
  191. // Done with entire buffer
  192. //
  193. *FinalUncompressedSize = i;
  194. return STATUS_SUCCESS;
  195. } else {
  196. //
  197. // More to do
  198. // Done with a 512-byte chunk
  199. //
  200. continue;
  201. }
  202. }
  203. }
  204. }
  205. ASSERTMSG("Don't exceed expected length ", i<UncompressedBufferSize);
  206. ASSERTMSG("Cannot match before start of uncoded buffer! ", off <= i);
  207. //
  208. // Get the length - logarithmically encoded
  209. //
  210. for (k=0; (x=MrcfReadBit(&WorkSpace)) == 0; k++) { NOTHING; }
  211. ASSERT(k <= 8);
  212. if (k == 0) {
  213. //
  214. // All matches at least 2 chars long
  215. //
  216. cbMatch = 2;
  217. } else {
  218. cbMatch = (1 << k) + 1 + MrcfReadNBits(k, &WorkSpace);
  219. }
  220. ASSERTMSG("Don't exceed buffer size ", (i - off + cbMatch - 1) <= UncompressedBufferSize);
  221. //
  222. // Copy the matched string
  223. //
  224. iMatch = i - off;
  225. while ( (cbMatch > 0) && (i<UncompressedBufferSize) ) {
  226. UncompressedBuffer[i++] = UncompressedBuffer[iMatch++];
  227. cbMatch--;
  228. }
  229. ASSERTMSG("Should have copied it all ", cbMatch == 0);
  230. }
  231. }
  232. }
  233. //
  234. // Internal Support Routine
  235. //
  236. VOID
  237. MrcfSetBitBuffer (
  238. PUCHAR pb,
  239. ULONG cb,
  240. PMRCF_BIT_IO BitIo
  241. )
  242. /*++
  243. Routine Description:
  244. Set statics with coded buffer pointer and length
  245. Arguments:
  246. pb - pointer to compressed data buffer
  247. cb - length of compressed data buffer
  248. BitIo - Supplies a pointer to the bit buffer statics
  249. Return Value:
  250. None.
  251. --*/
  252. {
  253. BitIo->pbBB = pb;
  254. BitIo->cbBB = cb;
  255. BitIo->cbBBInitial = cb;
  256. BitIo->cbitsBB = 0;
  257. BitIo->abitsBB = 0;
  258. }
  259. //
  260. // Internal Support Routine
  261. //
  262. USHORT
  263. MrcfReadBit (
  264. PMRCF_BIT_IO BitIo
  265. )
  266. /*++
  267. Routine Description:
  268. Get next bit from bit buffer
  269. Arguments:
  270. BitIo - Supplies a pointer to the bit buffer statics
  271. Return Value:
  272. USHORT - Returns next bit (0 or 1)
  273. --*/
  274. {
  275. USHORT bit;
  276. //
  277. // Check if no bits available
  278. //
  279. if ((BitIo->cbitsBB) == 0) {
  280. MrcfFillBitBuffer(BitIo);
  281. }
  282. //
  283. // Decrement the bit count
  284. // get the bit, remove it, and return the bit
  285. //
  286. (BitIo->cbitsBB)--;
  287. bit = (BitIo->abitsBB) & 1;
  288. (BitIo->abitsBB) >>= 1;
  289. return bit;
  290. }
  291. //
  292. // Internal Support Routine
  293. //
  294. USHORT
  295. MrcfReadNBits (
  296. LONG cbits,
  297. PMRCF_BIT_IO BitIo
  298. )
  299. /*++
  300. Routine Description:
  301. Get next N bits from bit buffer
  302. Arguments:
  303. cbits - count of bits to get
  304. BitIo - Supplies a pointer to the bit buffer statics
  305. Return Value:
  306. USHORT - Returns next cbits bits.
  307. --*/
  308. {
  309. ULONG abits; // Bits to return
  310. LONG cbitsPart; // Partial count of bits
  311. ULONG cshift; // Shift count
  312. ULONG mask; // Mask
  313. //
  314. // Largest number of bits we should read at one time is 12 bits for
  315. // a 12-bit offset. The largest length field component that we
  316. // read is 8 bits. If this routine were used for some other purpose,
  317. // it can support up to 15 (NOT 16) bit reads, due to how the masking
  318. // code works.
  319. //
  320. ASSERT(cbits <= 12);
  321. //
  322. // No shift and no bits yet
  323. //
  324. cshift = 0;
  325. abits = 0;
  326. while (cbits > 0) {
  327. //
  328. // If not bits available get some bits
  329. //
  330. if ((BitIo->cbitsBB) == 0) {
  331. MrcfFillBitBuffer(BitIo);
  332. }
  333. //
  334. // Number of bits we can read
  335. //
  336. cbitsPart = minimum((BitIo->cbitsBB), cbits);
  337. //
  338. // Mask for bits we want, extract and store them
  339. //
  340. mask = (1 << cbitsPart) - 1;
  341. abits |= ((BitIo->abitsBB) & mask) << cshift;
  342. //
  343. // Remember the next chunk of bits
  344. //
  345. cshift = cbitsPart;
  346. //
  347. // Update bit buffer, move remaining bits down and
  348. // update count of bits left
  349. //
  350. (BitIo->abitsBB) >>= cbitsPart;
  351. (BitIo->cbitsBB) -= cbitsPart;
  352. //
  353. // Update count of bits left to read
  354. //
  355. cbits -= cbitsPart;
  356. }
  357. //
  358. // Return requested bits
  359. //
  360. return (USHORT)abits;
  361. }
  362. //
  363. // Internal Support Routine
  364. //
  365. VOID
  366. MrcfFillBitBuffer (
  367. PMRCF_BIT_IO BitIo
  368. )
  369. /*++
  370. Routine Description:
  371. Fill abitsBB from static bit buffer
  372. Arguments:
  373. BitIo - Supplies a pointer to the bit buffer statics
  374. Return Value:
  375. None.
  376. --*/
  377. {
  378. ASSERT((BitIo->cbitsBB) == 0);
  379. switch (BitIo->cbBB) {
  380. case 0:
  381. ASSERTMSG("no bits left in coded buffer!", FALSE);
  382. break;
  383. case 1:
  384. //
  385. // Get last byte and adjust count
  386. //
  387. BitIo->cbitsBB = 8;
  388. BitIo->abitsBB = *(BitIo->pbBB)++;
  389. BitIo->cbBB--;
  390. break;
  391. default:
  392. //
  393. // Get word and adjust count
  394. //
  395. BitIo->cbitsBB = 16;
  396. BitIo->abitsBB = *((USHORT *)(BitIo->pbBB))++;
  397. BitIo->cbBB -= 2;
  398. break;
  399. }
  400. }
  401.