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.

169 lines
4.6 KiB

  1. /*
  2. ** lzexp.c - Routines used in Lempel-Ziv (from their 1977 article) expansion.
  3. **
  4. ** Author: DavidDi
  5. */
  6. // Headers
  7. ///////////
  8. #ifndef LZA_DLL
  9. #include <io.h>
  10. #endif
  11. #include "lz_common.h"
  12. #include "lz_buffers.h"
  13. #include "lz_header.h"
  14. #include "lzcommon.h"
  15. /*
  16. ** int LZDecode(int doshSource, int doshDest, long cblExpandedLength,
  17. ** BOOL bRestartDecoding, BOOL bFirstAlg);
  18. **
  19. ** Expand input file to output file.
  20. **
  21. ** Arguments: doshSource - DOS file handle of open input file
  22. ** doshDest - DOS file handle of open output file
  23. ** cblExpandedLength - amount of output file to expand
  24. ** bRestartDecoding - flag indicating whether or not to start
  25. ** decoding from scratch
  26. ** bFirstAlg - flag indicating whether to use ALG_FIRST
  27. ** or ALG_LZ
  28. **
  29. ** Returns: int - TRUE if expansion was successful. One of the LZERROR_
  30. ** codes if the expansion failed.
  31. **
  32. ** Globals:
  33. **
  34. ** The number of bytes actually expanded will be >= cblExpandedLength. The
  35. ** number of bytes actually expanded may be calculated as
  36. ** (pbyteOutBuf - rgbyteOutBuf). The expansion will overrun the
  37. ** cblExpandedLength request by at most (cbMaxMatchLen - 1) bytes.
  38. */
  39. INT LZDecode(
  40. INT doshSource,
  41. INT doshDest,
  42. LONG cblExpandedLength,
  43. BOOL bRestartDecoding,
  44. BOOL bFirstAlg,
  45. PLZINFO pLZI)
  46. {
  47. INT i,
  48. cb, // number of bytes to unpack
  49. f; // holds ReadByte() return values
  50. INT oStart; // buffer offset for unpacking
  51. BYTE byte1, byte2; // input byte holders
  52. // !!! Assumes parm pLZI is always valid
  53. #if 0
  54. if (bFirstAlg == TRUE)
  55. pLZI->cbMaxMatchLen = FIRST_MAX_MATCH_LEN;
  56. else
  57. pLZI->cbMaxMatchLen = LZ_MAX_MATCH_LEN;
  58. #else
  59. pLZI->cbMaxMatchLen = FIRST_MAX_MATCH_LEN;
  60. #endif
  61. // Start decoding from scratch?
  62. if (bRestartDecoding == TRUE)
  63. {
  64. // Rewind the compressed input file to just after the compressed file
  65. // header.
  66. if (FSEEK(doshSource, (LONG)HEADER_LEN, SEEK_SET) != (LONG)HEADER_LEN) {
  67. return(LZERROR_BADINHANDLE);
  68. }
  69. // Rewind output file.
  70. if (doshDest != NO_DOSH &&
  71. FSEEK(doshDest, 0L, SEEK_SET) != 0L) {
  72. return(LZERROR_BADOUTHANDLE);
  73. }
  74. // Set up a fresh buffer state.
  75. ResetBuffers();
  76. // Initialize ring buffer.
  77. for (i = 0; i < RING_BUF_LEN - pLZI->cbMaxMatchLen; i++)
  78. pLZI->rgbyteRingBuf[i] = BUF_CLEAR_BYTE;
  79. // Initialize decoding globals.
  80. pLZI->uFlags = 0U;
  81. pLZI->iCurRingBufPos = RING_BUF_LEN - pLZI->cbMaxMatchLen;
  82. }
  83. if ((f = ReadByte(byte1)) != TRUE && f != END_OF_INPUT) {
  84. return(f);
  85. }
  86. // Decode one encoded unit at a time.
  87. FOREVER
  88. {
  89. if (f == END_OF_INPUT) // EOF reached
  90. break;
  91. // Have we expanded enough data yet?
  92. if (pLZI->cblOutSize > cblExpandedLength) // Might want to make this >=.
  93. {
  94. UnreadByte();
  95. return(TRUE);
  96. }
  97. // High order byte counts the number of bits used in the low order
  98. // byte.
  99. if (((pLZI->uFlags >>= 1) & 0x100) == 0)
  100. {
  101. // Set bit mask describing the next 8 bytes.
  102. pLZI->uFlags = ((DWORD)byte1) | 0xff00;
  103. if ((f = ReadByte(byte1)) != TRUE) {
  104. return(LZERROR_READ);
  105. }
  106. }
  107. if (pLZI->uFlags & 1)
  108. {
  109. // Just store the literal byte in the buffer.
  110. if ((f = WriteByte(byte1)) != TRUE) {
  111. return(f);
  112. }
  113. pLZI->rgbyteRingBuf[pLZI->iCurRingBufPos++] = byte1;
  114. pLZI->iCurRingBufPos &= RING_BUF_LEN - 1;
  115. }
  116. else
  117. {
  118. // Extract the offset and count to copy from the ring buffer.
  119. if ((f = ReadByte(byte2)) != TRUE) {
  120. return(LZERROR_READ);
  121. }
  122. cb = (INT)byte2;
  123. oStart = (cb & 0xf0) << 4 | (INT)byte1;
  124. cb = (cb & 0x0f) + MAX_LITERAL_LEN;
  125. for (i = 0; i <= cb; i++)
  126. {
  127. byte1 = pLZI->rgbyteRingBuf[(oStart + i) & (RING_BUF_LEN - 1)];
  128. if ((f = WriteByte(byte1)) != TRUE) {
  129. return( f );
  130. }
  131. pLZI->rgbyteRingBuf[pLZI->iCurRingBufPos++] = byte1;
  132. pLZI->iCurRingBufPos &= RING_BUF_LEN - 1;
  133. }
  134. }
  135. if ((f = ReadByte(byte1)) != TRUE && f != END_OF_INPUT) {
  136. return(f);
  137. }
  138. }
  139. return(TRUE);
  140. }