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.

271 lines
8.8 KiB

  1. /*
  2. * Microsoft Confidential
  3. * Copyright (C) Microsoft Corporation 1996
  4. * All Rights Reserved.
  5. *
  6. * LDI.C: LZX Decompression Interface
  7. *
  8. * History:
  9. * 03-Jul-1996 jforbes Initial version.
  10. */
  11. /* --- preprocessor ------------------------------------------------------- */
  12. #include <stdio.h> /* for NULL */
  13. #include "decoder.h"
  14. #include "decapi.h"
  15. #include "ldi.h" /* types, prototype verification, error codes */
  16. #define MAX_GROWTH 6144 /* see encoder.h */
  17. typedef ULONG SIGNATURE; /* structure signature */
  18. struct LDI_CONTEXT /* private structure */
  19. {
  20. SIGNATURE signature; /* for validation */
  21. PFNALLOC pfnAlloc; /* where the alloc() is */
  22. PFNFREE pfnFree; /* where the free() is */
  23. PFNOPEN pfnOpen; /* open a file callback or NULL */
  24. PFNREAD pfnRead; /* read a file callback */
  25. PFNWRITE pfnWrite; /* write a file callback */
  26. PFNCLOSE pfnClose; /* close a file callback */
  27. PFNSEEK pfnSeek; /* seek in file callback */
  28. UINT cbDataBlockMax; /* promised max data size */
  29. UINT fCPUtype; /* CPU we're running on, QDI_CPU_xxx */
  30. t_decoder_context *decoder_context;
  31. };
  32. typedef struct LDI_CONTEXT FAR *PMDC_CONTEXT; /* a pointer to one */
  33. /* MAKE_SIGNATURE - Construct a structure signature
  34. *
  35. * Entry:
  36. * a,b,c,d - four characters
  37. *
  38. * Exit:
  39. * Returns constructed SIGNATURE
  40. *
  41. * Example:
  42. * strct->signature = MAKE_SIGNATURE('b','e','n','s')
  43. */
  44. #define MAKE_SIGNATURE(a,b,c,d) (a + (b<<8) + (c<<16) + (d<<24))
  45. #define BAD_SIGNATURE (0L)
  46. #define LDI_SIGNATURE MAKE_SIGNATURE('L','D','I','C')
  47. /* --- LDI context structure ---------------------------------------------- */
  48. #define PMDCfromHMD(h) ((PMDC_CONTEXT)(h)) /* handle to pointer */
  49. #define HMDfromPMDC(p) ((LDI_CONTEXT_HANDLE)(p)) /* pointer to handle */
  50. /* --- LDICreateDecompression() ------------------------------------------- */
  51. #include <stdio.h>
  52. int FAR DIAMONDAPI LDICreateDecompression(
  53. UINT FAR * pcbDataBlockMax, /* max uncompressed data block */
  54. void FAR * pvConfiguration, /* implementation-defined */
  55. PFNALLOC pfnma, /* Memory allocation function */
  56. PFNFREE pfnmf, /* Memory free function */
  57. UINT FAR * pcbSrcBufferMin, /* gets required input buffer */
  58. LDI_CONTEXT_HANDLE FAR * pmdhHandle, /* gets newly-created handle */
  59. PFNOPEN pfnopen, /* open a file callback */
  60. PFNREAD pfnread, /* read a file callback */
  61. PFNWRITE pfnwrite, /* write a file callback */
  62. PFNCLOSE pfnclose, /* close a file callback */
  63. PFNSEEK pfnseek) /* seek in file callback */
  64. {
  65. PMDC_CONTEXT context; /* new context */
  66. PFLZXDECOMPRESS pConfig; /* to get configuration details */
  67. pConfig = pvConfiguration; /* get a pointer we can use */
  68. *pcbSrcBufferMin = /* we'll expand sometimes */
  69. *pcbDataBlockMax + MAX_GROWTH;
  70. if (pmdhHandle == NULL) /* if no context requested, */
  71. {
  72. return(MDI_ERROR_NO_ERROR); /* return from query mode */
  73. }
  74. *pmdhHandle = (LDI_CONTEXT_HANDLE) 0; /* wait until it's valid */
  75. context = pfnma(sizeof(struct LDI_CONTEXT));
  76. if (context == NULL)
  77. {
  78. return(MDI_ERROR_NOT_ENOUGH_MEMORY); /* if can't allocate */
  79. }
  80. context->decoder_context = pfnma(sizeof(t_decoder_context));
  81. if (context->decoder_context == NULL)
  82. {
  83. pfnmf(context);
  84. return MDI_ERROR_NOT_ENOUGH_MEMORY;
  85. }
  86. context->pfnAlloc = pfnma; /* remember where alloc() is */
  87. context->pfnFree = pfnmf; /* remember where free() is */
  88. context->pfnOpen = pfnopen; /* remember where pfnopen() is */
  89. context->pfnRead = pfnread; /* remember where pfnread() is */
  90. context->pfnWrite = pfnwrite; /* remember where pfnwrite() is */
  91. context->pfnClose = pfnclose; /* remember where pfnclose() is */
  92. context->pfnSeek = pfnseek; /* remember where pfnseek() is */
  93. context->cbDataBlockMax = *pcbDataBlockMax; /* remember agreement */
  94. context->fCPUtype = (UINT) pConfig->fCPUtype; /* remember CPU type */
  95. context->signature = LDI_SIGNATURE; /* install signature */
  96. if (LZX_DecodeInit(
  97. context->decoder_context,
  98. pConfig->WindowSize,
  99. pfnma,
  100. pfnmf,
  101. pfnopen,
  102. pfnread,
  103. pfnwrite,
  104. pfnclose,
  105. pfnseek) == false)
  106. {
  107. pfnmf(context);
  108. return (MDI_ERROR_NOT_ENOUGH_MEMORY);
  109. }
  110. /* pass context back to caller */
  111. *pmdhHandle = HMDfromPMDC(context);
  112. return(MDI_ERROR_NO_ERROR); /* tell caller all is well */
  113. }
  114. /* --- LDIDecompress() ---------------------------------------------------- */
  115. int FAR DIAMONDAPI LDIDecompress(
  116. LDI_CONTEXT_HANDLE hmd, /* decompression context */
  117. void FAR * pbSrc, /* source buffer */
  118. UINT cbSrc, /* source actual size */
  119. void FAR * pbDst, /* target buffer */
  120. UINT FAR * pcbResult) /* gets actual target size */
  121. {
  122. PMDC_CONTEXT context; /* pointer to the context */
  123. int result; /* return code */
  124. long bytes_to_decode;
  125. long total_bytes_written = 0;
  126. context = PMDCfromHMD(hmd); /* get pointer from handle */
  127. if (context->signature != LDI_SIGNATURE)
  128. {
  129. return(MDI_ERROR_BAD_PARAMETERS); /* missing signature */
  130. }
  131. if (*pcbResult > context->cbDataBlockMax)
  132. {
  133. return(MDI_ERROR_BUFFER_OVERFLOW); /* violated max block promise */
  134. }
  135. #if 0
  136. if (cbSrc == 0)
  137. return MDI_ERROR_NO_ERROR;
  138. #endif
  139. bytes_to_decode = (long) *pcbResult;
  140. result = LZX_Decode(
  141. context->decoder_context,
  142. bytes_to_decode,
  143. pbSrc,
  144. cbSrc,
  145. pbDst,
  146. bytes_to_decode,
  147. &total_bytes_written
  148. );
  149. *pcbResult = (UINT) total_bytes_written;
  150. if (result)
  151. return MDI_ERROR_FAILED;
  152. else
  153. return MDI_ERROR_NO_ERROR;
  154. }
  155. /* --- LDIResetDecompression() -------------------------------------------- */
  156. int FAR DIAMONDAPI LDIResetDecompression(LDI_CONTEXT_HANDLE hmd)
  157. {
  158. PMDC_CONTEXT context; /* pointer to the context */
  159. context = PMDCfromHMD(hmd); /* get pointer from handle */
  160. if (context->signature != LDI_SIGNATURE)
  161. {
  162. return(MDI_ERROR_BAD_PARAMETERS); /* missing signature */
  163. }
  164. LZX_DecodeNewGroup(context->decoder_context);
  165. return(MDI_ERROR_NO_ERROR); /* if tag is OK */
  166. }
  167. /* --- LDIDestroyDecompression() ------------------------------------------ */
  168. int FAR DIAMONDAPI LDIDestroyDecompression(LDI_CONTEXT_HANDLE hmd)
  169. {
  170. PMDC_CONTEXT context; /* pointer to the context */
  171. context = PMDCfromHMD(hmd); /* get pointer from handle */
  172. if (context->signature != LDI_SIGNATURE)
  173. {
  174. return(MDI_ERROR_BAD_PARAMETERS); /* missing signature */
  175. }
  176. LZX_DecodeFree(context->decoder_context);
  177. context->signature = BAD_SIGNATURE; /* destroy signature */
  178. context->pfnFree(context->decoder_context);
  179. context->pfnFree(context); /* self-destruct */
  180. return(MDI_ERROR_NO_ERROR); /* success */
  181. }
  182. /* --- LDIGetWindow() ---------------------------------------------------- */
  183. #ifndef BIT16
  184. int FAR DIAMONDAPI LDIGetWindow(
  185. LDI_CONTEXT_HANDLE hmd, /* decompression context */
  186. BYTE FAR ** ppWindow, /* pointer to window start */
  187. long * pFileOffset, /* offset in folder */
  188. long * pWindowOffset, /* offset in window */
  189. long * pcbBytesAvail) /* bytes avail from window start */
  190. {
  191. PMDC_CONTEXT context;
  192. t_decoder_context *dec_context;
  193. context = PMDCfromHMD(hmd); /* get pointer from handle */
  194. dec_context = context->decoder_context;
  195. *ppWindow = dec_context->dec_mem_window;
  196. // window is a circular buffer
  197. if ((ulong) dec_context->dec_position_at_start < dec_context->dec_window_size)
  198. {
  199. *pWindowOffset = 0;
  200. *pFileOffset = 0;
  201. *pcbBytesAvail = dec_context->dec_position_at_start;
  202. }
  203. else
  204. {
  205. *pWindowOffset = dec_context->dec_position_at_start & (dec_context->dec_window_size - 1);
  206. *pcbBytesAvail = dec_context->dec_window_size;
  207. *pFileOffset = dec_context->dec_position_at_start - dec_context->dec_window_size;
  208. }
  209. return MDI_ERROR_NO_ERROR;
  210. }
  211. #endif
  212. /* ------------------------------------------------------------------------ */