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.

670 lines
21 KiB

  1. //************************************************************************
  2. // compress.c
  3. //
  4. // Decompression code for MPPC compression. Compression code is on the
  5. // server, \nt\private\ntos\termsrv\rdp\rdpwd\compress.c.
  6. //
  7. // Copyright(c) Microsoft Corp., 1990-1999
  8. //
  9. // Revision history:
  10. // 5/5/94 Created gurdeep
  11. // 4/20/1999 Optimized for TS jparsons, erikma
  12. // 8/24/2000 Fixed bugs nadima
  13. //************************************************************************
  14. #include <adcg.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <compress.h>
  18. #ifdef COMPR_DEBUG
  19. #ifdef DECOMPRESS_KERNEL_DEBUG
  20. #include <nturtl.h>
  21. #include <ntddkbd.h>
  22. #include <ntddmou.h>
  23. #include <windows.h>
  24. #include <winbase.h>
  25. #include <winerror.h>
  26. #include <winsta.h>
  27. #include <icadd.h>
  28. #include <icaapi.h>
  29. //Include all this stuff just to pickup icaapi.h
  30. #define DbgComprPrint(_x_) DbgPrint _x_
  31. #define DbgComprBreakOnDbg IcaBreakOnDebugger
  32. #else //DECOMPRESS_KERNEL_DEBUG
  33. _inline ULONG DbgUserPrint(TCHAR* Format, ...)
  34. {
  35. va_list arglist;
  36. TCHAR Buffer[512];
  37. ULONG retval;
  38. //
  39. // Format the output into a buffer and then print it.
  40. //
  41. va_start(arglist, Format);
  42. retval = _vsntprintf(Buffer, sizeof(Buffer)/sizeof(Buffer[0]),
  43. Format, arglist);
  44. if (retval != -1) {
  45. OutputDebugString(Buffer);
  46. OutputDebugString(_T("\n"));
  47. }
  48. return retval;
  49. }
  50. #define DbgComprPrint(_x_) DbgUserPrint _x_
  51. #define DbgComprBreakOnDbg DebugBreak
  52. #endif //DECOMPRESS_KERNEL_DEBUG
  53. #endif //COMPR_DEBUG
  54. /* Bitptrs point to the current byte. The current bit (i.e. next bit to be
  55. * stored) is masked off by the bit entry. When this reaches zero, it is
  56. * reset to 0x80 and the next byte is set up. The bytes are filled MSBit
  57. * first. */
  58. /* Starts the given bit pointer */
  59. #define inbit_start(s) pbyte = s; bit = 16; byte=(*pbyte << 8) + *(pbyte+1); pbyte++;
  60. #define inbit_end() if (bit != 16) pbyte++;
  61. //
  62. // Without the ROBUSTness fix, the code will try to prefetch
  63. // a byte or more past then end of the input buffer which can
  64. // cause problems in kernel mode.
  65. //
  66. // We fixed this by forcing kernel mode to allocate the input
  67. // buffers with enough extra padding at the end so it's ok to
  68. // read past the end. If someday this needs to be changed
  69. // enable ROBUST_FIX, this _will_ slow down the algorithm.
  70. //
  71. // TODO: if we define ROBUST_FIX_ENABLE flag we have to handle a couple
  72. // of more cases that this code does not take into account. For instance
  73. // if you are at the end of the buffer and you do an in_bit_16 you will overread.
  74. // The in_bit_next/in_bit_advance macros for the robust fix should return
  75. // FALSE so the decompression fails in case we are at the end of the buffer
  76. // and we try to decompress further. As it is now the ROBUST_FIX macros will
  77. // not go past the end of the buffer but the in_bit_X (with X>7) will do.
  78. //
  79. #ifdef ROBUST_FIX_ENABLED
  80. #define in_bit_next() if (bit < 9) { \
  81. bit=16; \
  82. byte <<=8; \
  83. ++pbyte; \
  84. if(pbyte < inend) { \
  85. byte |= *(pbyte); \
  86. } \
  87. } \
  88. #define in_bit_advance() if (bit < 9) { \
  89. bit+=8; \
  90. byte <<=8; \
  91. ++pbyte; \
  92. if(pbyte < inend) { \
  93. byte |= *(pbyte); \
  94. } \
  95. }
  96. #else //ROBUST_FIX_ENABLED
  97. #define in_bit_next() if (bit < 9) { \
  98. bit=16; \
  99. byte <<=8; \
  100. byte |= *(++pbyte); \
  101. }
  102. #define in_bit_advance() if (bit < 9) { \
  103. bit+=8; \
  104. byte <<=8; \
  105. byte |= *(++pbyte); \
  106. }
  107. #endif //ROBUST_FIX_ENABLED
  108. /* Returns non-zero in bitset if the next bit in the stream is a 1. */
  109. #define in_bit() bit--; bitset = (byte >> bit) & 1; in_bit_next()
  110. #define in_bits_2(w) bit-=2; w = (byte >> bit) & 0x03;\
  111. in_bit_advance();
  112. #define in_bits_3(w) bit-=3; w = (byte >> bit) & 0x07;\
  113. in_bit_advance();
  114. #define in_bits_4(w) bit-=4; w = (byte >> bit) & 0x0F;\
  115. in_bit_advance();
  116. #define in_bits_5(w) bit-=5; w = (byte >> bit) & 0x1F;\
  117. in_bit_advance();
  118. #define in_bits_6(w) bit-=6; w = (byte >> bit) & 0x3F;\
  119. in_bit_advance();
  120. #define in_bits_7(w) bit-=7; w = (byte >> bit) & 0x7F;\
  121. in_bit_advance();
  122. #define in_bits_8(w) bit-=8; w = (byte >> bit) & 0xFF;\
  123. bit+=8; byte <<=8; byte |= *(++pbyte);
  124. #define in_bits_9(w) bit-=9; w = (byte >> bit) & 0x1FF; \
  125. bit+=8; byte <<=8; byte |= *(++pbyte); \
  126. in_bit_advance();
  127. #define in_bits_10(w) if (bit > 10) { \
  128. bit-=10; w = (byte >> bit) & 0x3FF; \
  129. bit+=8; byte <<=8; byte |= *(++pbyte); \
  130. } else { \
  131. in_bits_2(bitset); \
  132. in_bits_8(w); \
  133. w= w + (bitset << 8); \
  134. }
  135. #define in_bits_11(w) if (bit > 11) { \
  136. bit-=11; w = (byte >> bit) & 0x7FF; \
  137. bit+=8; byte <<=8; byte |= *(++pbyte); \
  138. } else { \
  139. in_bits_3(bitset); \
  140. in_bits_8(w); \
  141. w= w + (bitset << 8); \
  142. }
  143. #define in_bits_12(w) if (bit > 12) { \
  144. bit-=12; w = (byte >> bit) & 0xFFF; \
  145. bit+=8; byte <<=8; byte |= *(++pbyte); \
  146. } else { \
  147. in_bits_4(bitset); \
  148. in_bits_8(w); \
  149. w= w + (bitset << 8); \
  150. }
  151. #define in_bits_13(w)\
  152. if (bit > 13) { \
  153. bit-=13; w = (byte >> bit) & 0x1FFF; \
  154. bit+=8; byte <<=8; byte |= *(++pbyte); \
  155. } else { \
  156. in_bits_5(bitset); \
  157. in_bits_8(w); \
  158. w=w + (bitset << 8); \
  159. }
  160. #define in_bits_14(w)\
  161. if (bit > 14) { \
  162. bit-=14; w = (byte >> bit) & 0x3FFF; \
  163. bit+=8; byte <<=8; byte |= *(++pbyte); \
  164. } else { \
  165. in_bits_6(bitset); \
  166. in_bits_8(w); \
  167. w=w + (bitset << 8); \
  168. }
  169. #define in_bits_15(w)\
  170. if (bit > 15) { \
  171. bit -= 15; w = (byte >> bit) & 0x7FFF; \
  172. bit += 8; byte <<= 8; byte |= *(++pbyte); \
  173. } else { \
  174. in_bits_7(bitset); \
  175. in_bits_8(w); \
  176. w = w + (bitset << 8); \
  177. }
  178. // initrecvcontext()
  179. //
  180. // Function: Initialize RecvContext block
  181. //
  182. // Parameters: IN context -> connection decompress context
  183. //
  184. // Callers of this API must allocate an object of the appropriate
  185. // type e.g RecvContext2_64K or RecvContext2_8K and set the
  186. // size field before casting to the generic type.
  187. //
  188. // The cleanest way to do this would be for initrecvcontext
  189. // to alloc the context itself but since the code is shared
  190. // between client and server there is no clean way to do this.
  191. // (callback allocators are _not_ clean).
  192. //
  193. // Returns status
  194. int initrecvcontext(RecvContext1 *context1,
  195. RecvContext2_Generic *context2,
  196. unsigned ComprType)
  197. {
  198. context1->CurrentPtr = context2->History;
  199. if(ComprType == PACKET_COMPR_TYPE_64K)
  200. {
  201. if(context2->cbSize > HISTORY_SIZE_64K)
  202. {
  203. context2->cbHistorySize = HISTORY_SIZE_64K-1;
  204. }
  205. else
  206. {
  207. return FALSE;
  208. }
  209. }
  210. else if(ComprType == PACKET_COMPR_TYPE_8K)
  211. {
  212. if(context2->cbSize > HISTORY_SIZE_8K)
  213. {
  214. context2->cbHistorySize = HISTORY_SIZE_8K-1;
  215. }
  216. else
  217. {
  218. return FALSE;
  219. }
  220. }
  221. else
  222. {
  223. return FALSE;
  224. }
  225. #if COMPR_DEBUG
  226. //
  227. // Setup debug fences to detect context buffer overwrites
  228. //
  229. if (context2->cbHistorySize == (HISTORY_SIZE_64K-1))
  230. {
  231. ((RecvContext2_64K*)context2)->Debug16kFence = DEBUG_FENCE_16K_VALUE;
  232. }
  233. else if (context2->cbHistorySize == (HISTORY_SIZE_8K-1))
  234. {
  235. ((RecvContext2_8K*)context2)->Debug8kFence = DEBUG_FENCE_8K_VALUE;
  236. }
  237. #endif
  238. memset(context2->History, 0, context2->cbHistorySize);
  239. return TRUE;
  240. }
  241. //* decompress()
  242. //
  243. // Function: de-compression function.
  244. //
  245. // Parameters: IN inbuf -> points to data to be uncompressed
  246. // IN inlen -> length of data
  247. // IN start -> flag indicating whether to start with a clean
  248. // history buffer
  249. // OUT output-> decompressed data
  250. // OUT outlen-> lenght of decompressed data
  251. // IN context -> connection decompress context
  252. //
  253. // Returns: TRUE if decompress was successful
  254. // FALSE if it wasnt
  255. //
  256. // WARNING: CODE IS HIGHLY OPTIMIZED FOR TIME.
  257. //
  258. int decompress(
  259. UCHAR FAR *inbuf,
  260. int inlen,
  261. int start,
  262. UCHAR FAR * FAR *output,
  263. int *outlen,
  264. RecvContext1 *context1,
  265. RecvContext2_Generic *context2,
  266. unsigned ComprType)
  267. {
  268. UCHAR FAR *inend; // When we know we're done decompressing
  269. UCHAR FAR *outstart; // Remember where in dbuf we started
  270. UCHAR FAR *current;
  271. long backptr = 0; // Back pointer for copy items
  272. long length; // Where to copy from in dbuf
  273. UCHAR FAR *s1, FAR *s2;
  274. int bitset;
  275. int bit;
  276. int byte;
  277. UCHAR FAR *pbyte;
  278. long HistorySize; // 2^N - 1 for fast modulo arithmetic below.
  279. const long HistorySizes[2] = { HISTORY_SIZE_8K - 1, HISTORY_SIZE_64K - 1 };
  280. //
  281. // Important to validate the compression type otherwise we could overread
  282. // this HistroySizes array and then use a bogus size to validate further
  283. // down below
  284. //
  285. if (ComprType > PACKET_COMPR_TYPE_MAX) {
  286. return FALSE;
  287. }
  288. inend = inbuf + inlen;
  289. HistorySize = HistorySizes[ComprType];
  290. // Start out looking at the first bit, which tells us whether to restart
  291. // the history buffer.
  292. inbit_start(inbuf);
  293. if (!start)
  294. current = context1->CurrentPtr;
  295. else
  296. context1->CurrentPtr = current = context2->History;
  297. //
  298. // Save our starting position
  299. //
  300. outstart = current;
  301. //
  302. // Decompress until we run out of input
  303. //
  304. while (pbyte < inend) {
  305. //
  306. // Jump on what to do with these three bits.
  307. //
  308. in_bits_3(length);
  309. switch (length) {
  310. case 0:
  311. in_bits_5(length);
  312. goto LITERAL;
  313. case 1:
  314. in_bits_5(length);
  315. length += 32;
  316. goto LITERAL;
  317. case 2:
  318. in_bits_5(length);
  319. length += 64;
  320. goto LITERAL;
  321. case 3:
  322. in_bits_5(length);
  323. length += 96;
  324. goto LITERAL;
  325. case 4:
  326. in_bits_6(length);
  327. length += 128;
  328. goto LITERAL;
  329. case 5:
  330. in_bits_6(length);
  331. length += 192;
  332. goto LITERAL;
  333. case 6:
  334. if (ComprType == PACKET_COMPR_TYPE_64K) {
  335. int foo;
  336. // 16-bit offset
  337. in_bits_8(foo);
  338. in_bits_8(backptr);
  339. backptr += (foo << 8) + 64 + 256 + 2048;
  340. }
  341. else {
  342. in_bits_13 (backptr); // 110 + 13 bit offset
  343. backptr += 320;
  344. }
  345. break;
  346. case 7:
  347. in_bit();
  348. if (ComprType == PACKET_COMPR_TYPE_64K) {
  349. if (!bitset) {
  350. // 11-bit offset.
  351. in_bits_11(backptr);
  352. backptr += 64 + 256;
  353. }
  354. else {
  355. in_bit();
  356. if (!bitset) {
  357. // 8-bit offset
  358. in_bits_8(backptr);
  359. backptr += 64;
  360. }
  361. else {
  362. in_bits_6(backptr) ;
  363. }
  364. }
  365. }
  366. else {
  367. if (!bitset) {
  368. in_bits_8(backptr);
  369. backptr+=64;
  370. }
  371. else {
  372. in_bits_6(backptr);
  373. }
  374. }
  375. break;
  376. }
  377. //
  378. // If we reach here, it's a copy item
  379. //
  380. in_bit() ; // 1st length bit
  381. if (!bitset) {
  382. length = 3;
  383. goto DONE;
  384. }
  385. in_bit(); // 2nd length bit
  386. if (!bitset) {
  387. in_bits_2 (length);
  388. length += 4;
  389. goto DONE;
  390. }
  391. in_bit(); // 3rd length bit
  392. if (!bitset) {
  393. in_bits_3 (length);
  394. length += 8;
  395. goto DONE;
  396. }
  397. in_bit(); // 4th length bit
  398. if (!bitset) {
  399. in_bits_4 (length);
  400. length += 16;
  401. goto DONE;
  402. }
  403. in_bit(); // 5th length bit
  404. if (!bitset) {
  405. in_bits_5 (length);
  406. length += 32;
  407. goto DONE;
  408. }
  409. in_bit(); // 6th length bit
  410. if (!bitset) {
  411. in_bits_6 (length);
  412. length += 64;
  413. goto DONE;
  414. }
  415. in_bit(); // 7th length bit
  416. if (!bitset) {
  417. in_bits_7 (length);
  418. length += 128;
  419. goto DONE;
  420. }
  421. in_bit(); // 8th length bit
  422. if (!bitset) {
  423. in_bits_8 (length);
  424. length += 256;
  425. goto DONE;
  426. }
  427. in_bit(); // 9th length bit
  428. if (!bitset) {
  429. in_bits_9 (length);
  430. length += 512;
  431. goto DONE;
  432. }
  433. in_bit(); // 10th length bit
  434. if (!bitset) {
  435. in_bits_10 (length);
  436. length += 1024;
  437. goto DONE;
  438. }
  439. in_bit(); // 11th length bit
  440. if (!bitset) {
  441. in_bits_11 (length);
  442. length += 2048;
  443. goto DONE;
  444. }
  445. in_bit(); // 12th length bit
  446. if (!bitset) {
  447. in_bits_12 (length);
  448. length += 4096;
  449. goto DONE;
  450. }
  451. in_bit(); // 13th length bit
  452. if (!bitset) {
  453. in_bits_13(length);
  454. length += 8192;
  455. goto DONE;
  456. }
  457. in_bit(); // 14th length bit
  458. if (!bitset) {
  459. in_bits_14(length);
  460. length += 16384;
  461. goto DONE;
  462. }
  463. in_bit(); // 15th length bit
  464. if (!bitset) {
  465. in_bits_15(length);
  466. length += 32768;
  467. goto DONE;
  468. }
  469. return FALSE;
  470. DONE:
  471. // Turn the backptr into an index location
  472. s2 = context2->History + (((current - context2->History) - backptr) &
  473. HistorySize);
  474. s1 = current;
  475. current += length;
  476. // If we are past the end of the history this is a bad sign:
  477. // abort decompression. Note this pointer comparison likely will not
  478. // work in Win16 since FAR pointers are not comparable. HUGE pointers
  479. // are too expensive to use here.
  480. //
  481. // We will also check the s2 pointer for overread. s2 will walk length
  482. // bytes and it could go outside the buffer.
  483. // We DON'T check current, s2 for underflow for the simle reason
  484. // that the length can't be more then 64k and the context2 buffer
  485. // can't be allocated in the last 64k of memory.
  486. if ((current < (context2->History + context2->cbHistorySize)) &&
  487. ((s2+length) < context2->History + context2->cbHistorySize)) {
  488. // loop unrolled to handle length>backptr case
  489. *s1 = *s2;
  490. *(s1 + 1) = *(s2 + 1);
  491. s1 += 2;
  492. s2 += 2;
  493. length -= 2;
  494. // copy all the bytes
  495. while (length) {
  496. *s1++ = *s2++;
  497. length--;
  498. }
  499. // We have another copy item, and no literals
  500. continue;
  501. }
  502. else {
  503. #if COMPR_DEBUG
  504. DbgComprPrint(("Decompression Error - invalid stream or overrun atack!\n"));
  505. DbgComprPrint(("context1 %p, context2 %p, current 0x%8.8x, outstart 0x%8.8x\n",
  506. context1, context2, current, outstart));
  507. DbgComprPrint(("inbuf 0x%8.8x, inlength %d, start 0x%8.8x\n",
  508. inbuf, inlen, start));
  509. DbgComprPrint(("length 0x%x, s1 0x%x, s2 0x%x, bit 0x%x, byte 0x%x\n",
  510. length, s1, s2, bit, byte));
  511. #endif
  512. return FALSE;
  513. }
  514. LITERAL:
  515. if (current < (context2->History + context2->cbHistorySize)) {
  516. // We have a literal
  517. *current++ = (UCHAR)length;
  518. }
  519. else {
  520. return FALSE;
  521. }
  522. } // while loop
  523. // End case:
  524. if ((bit == 16) && (pbyte == inend)) {
  525. if (current < (context2->History + context2->cbHistorySize)) {
  526. *current++ = *(pbyte - 1);
  527. }
  528. else {
  529. return FALSE;
  530. }
  531. }
  532. #if COMPR_DEBUG
  533. //
  534. // This code will ONLY test 64K decompression contexts
  535. //
  536. if ((context2->cbHistorySize == (HISTORY_SIZE_64K-1)))
  537. {
  538. if ((DEBUG_FENCE_16K_VALUE !=
  539. ((RecvContext2_64K*)context2)->Debug16kFence))
  540. {
  541. DbgComprPrint(("Decompression (16K) Error (mail tsstress) - (overwrote fence)!\n"));
  542. DbgComprPrint(("context1 %p, context2 %p, current 0x%8.8x, outstart 0x%8.8x\n",
  543. context1, context2, current, outstart));
  544. DbgComprPrint(("inbuf 0x%8.8x, inlength %d, start 0x%8.8x\n",
  545. inbuf, inlen, start));
  546. DbgComprPrint(("length 0x%x, s1 0x%x, s2 0x%x, bit 0x%x, byte 0x%x\n",
  547. length, s1, s2, bit, byte));
  548. DbgComprBreakOnDbg();
  549. }
  550. }
  551. else if ((context2->cbHistorySize == (HISTORY_SIZE_8K-1)))
  552. {
  553. if ((DEBUG_FENCE_8K_VALUE !=
  554. ((RecvContext2_8K*)context2)->Debug8kFence))
  555. {
  556. DbgComprPrint(("Decompression (8K) Error (mail tsstress) - (overwrote fence)!\n"));
  557. DbgComprPrint(("context1 %p, context2 %p, current 0x%8.8x, outstart 0x%8.8x\n",
  558. context1, context2, current, outstart));
  559. DbgComprPrint(("inbuf 0x%8.8x, inlength %d, start 0x%8.8x\n",
  560. inbuf, inlen, start));
  561. DbgComprPrint(("length 0x%x, s1 0x%x, s2 0x%x, bit 0x%x, byte 0x%x\n",
  562. length, s1, s2, bit, byte));
  563. DbgComprBreakOnDbg();
  564. }
  565. }
  566. #endif
  567. *outlen = (int)(current - outstart); // the length of decompressed data
  568. *output = context1->CurrentPtr;
  569. context1->CurrentPtr = current;
  570. return TRUE;
  571. }