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.

418 lines
14 KiB

  1. /*
  2. * Microsoft Confidential
  3. * Copyright (C) Microsoft Corporation 1993,1994
  4. * All Rights Reserved.
  5. *
  6. * LDI.H - Diamond Memory Decompression Interface (LDI)
  7. *
  8. * History:
  9. * 03-Jul-1994 jforbes Initial version.
  10. *
  11. * Functions:
  12. * LDICreateDecompression - Create and reset an LDI decompression context
  13. * LDIDecompress - Decompress a block of data
  14. * LDIResetDecompression - Reset LDI decompression context
  15. * LDIDestroyDecompression - Destroy LDI Decompression context
  16. *
  17. * Types:
  18. * LDI_CONTEXT_HANDLE - Handle to an LDI decompression context
  19. * PFNALLOC - Memory allocation function for LDI
  20. * PFNFREE - Free memory function for LDI
  21. */
  22. /* --- types -------------------------------------------------------------- */
  23. #include <basetsd.h>
  24. extern "C"
  25. {
  26. #ifndef DIAMONDAPI
  27. #define DIAMONDAPI __cdecl
  28. #endif
  29. #ifndef _BYTE_DEFINED
  30. #define _BYTE_DEFINED
  31. typedef unsigned char BYTE;
  32. #endif
  33. #ifndef _UINT_DEFINED
  34. #define _UINT_DEFINED
  35. typedef unsigned int UINT;
  36. #endif
  37. #ifndef _ULONG_DEFINED
  38. #define _ULONG_DEFINED
  39. typedef unsigned long ULONG;
  40. #endif
  41. #ifndef NEAR
  42. # ifdef BIT16
  43. # define NEAR __near
  44. # else
  45. # define NEAR
  46. # endif
  47. #endif
  48. #ifndef FAR
  49. #ifdef BIT16
  50. #define FAR __far
  51. #else
  52. #define FAR
  53. #endif
  54. #endif
  55. #ifndef HUGE
  56. #ifdef BIT16
  57. #define HUGE __huge
  58. #else
  59. #define HUGE
  60. #endif
  61. #endif
  62. #ifndef _MI_MEMORY_DEFINED
  63. #define _MI_MEMORY_DEFINED
  64. typedef void HUGE * MI_MEMORY;
  65. #endif
  66. #ifndef _MHANDLE_DEFINED
  67. #define _MHANDLE_DEFINED
  68. #ifdef IA64
  69. typedef ULONG_PTR MHANDLE;
  70. #else
  71. typedef unsigned long MHANDLE;
  72. #endif
  73. #endif
  74. #ifndef UNALIGNED
  75. #ifndef NEEDS_ALIGNMENT
  76. #define UNALIGNED
  77. #else
  78. #define UNALIGNED __unaligned
  79. #endif
  80. #endif
  81. /*
  82. * LDI will try to create a virtual ring buffer on disk if the pfnalloc call
  83. * to create the buffer fails. These functions provide LDI the disk access
  84. * features needed.
  85. *
  86. * These are modeled after the C run-time routines _open, _read,
  87. * _write, _close, and _lseek. The values for the PFNOPEN oflag
  88. * and pmode calls are those defined for _open. LDI expects error
  89. * handling to be identical to these C run-time routines.
  90. *
  91. * As long as you faithfully copy these aspects, you can supply
  92. * any functions you like!
  93. *
  94. * For PFNOPEN, the pszFile parameter will take on a special form for LDI's
  95. * temporary file. The special form appears as a file named "*". Such a
  96. * name field should be cast into the struct below, which contains the
  97. * required file's size as shown in the RINGNAME structure below.
  98. *
  99. * Example open and close callbacks are provided. It is assumed that the
  100. * client will provide more adaptive code for determining the temporary
  101. * file's name and drive location, based on environment variables and the
  102. * amount of free disk space. This sample code has hard-coded the actual
  103. * path and fails if there is not enough free space. This code creates the
  104. * file, then attempts to expand it to the requested size by writing a byte
  105. * (any byte) at the requested size - 1. (This approach is not suitable for
  106. * a file system which can support sparse files.)
  107. *
  108. * The callback routine may create this file on any path, and with any name,
  109. * as appropriate. If the file cannot be created with the requested size,
  110. * the PFNOPEN should fail. The file really should be placed on a local
  111. * fixed disk. It would not be appropriate for the file to be placed on a
  112. * compressed drive or a floppy disk. If the client has access to alternate
  113. * memory, such as XMS or EMS, these operations could be emuluated.
  114. *
  115. * static int tempHandle = -1;
  116. *
  117. * int FAR DIAMONDAPI MyOpen(char FAR *pszFile,int oflag,int pmode)
  118. * {
  119. * if (*pszFile == '*')
  120. * {
  121. * PRINGNAME pringDescriptor;
  122. *
  123. * pringDescriptor = (PRINGNAME) pszFile;
  124. *
  125. * tempHandle = _open("C:\\ldi_temp.$$$",oflag,pmode);
  126. *
  127. * if (tempHandle != -1)
  128. * {
  129. * _lseek(tempHandle,(pringDescriptor->fileSize - 1),SEEK_SET);
  130. *
  131. * if (_write(tempHandle,&tempHandle,1) != 1)
  132. * {
  133. * _close(tempHandle);
  134. * remove("C:\\ldi_temp.$$$");
  135. * tempHandle = -1;
  136. * }
  137. * }
  138. *
  139. * return(tempHandle);
  140. * }
  141. * else
  142. * {
  143. * * LDI only will call with *pszFile == '*' *
  144. * }
  145. * }
  146. *
  147. * The callback provider must watch for the corresponding PFNCLOSE call on
  148. * the returned handle, and delete the created file after closing. (The
  149. * file handle and file name assigned to the temporary file must be tracked;
  150. * a close operation on that handle must be trapped, so the temporary file
  151. * can be deleted as well.)
  152. *
  153. * The client does not need to worry about multiple concurrent opens of the
  154. * temporary file, or more than a single temporary file (from LDI).
  155. *
  156. * int FAR DIAMONDAPI MyClose(int handle)
  157. * {
  158. * int result;
  159. *
  160. * result = _close(handle);
  161. *
  162. * if (handle == tempHandle)
  163. * {
  164. * remove("C:\\ldi_temp.$$$");
  165. * tempHandle = -1;
  166. * }
  167. *
  168. * return(result);
  169. * }
  170. */
  171. typedef int (FAR DIAMONDAPI *PFNOPEN) (char FAR *pszFile,int oflag,int pmode);
  172. typedef UINT (FAR DIAMONDAPI *PFNREAD) (int hf, void FAR *pv, UINT cb);
  173. typedef UINT (FAR DIAMONDAPI *PFNWRITE)(int hf, void FAR *pv, UINT cb);
  174. typedef int (FAR DIAMONDAPI *PFNCLOSE)(int hf);
  175. typedef long (FAR DIAMONDAPI *PFNSEEK) (int hf, long dist, int seektype);
  176. /* --- LDI-defined types -------------------------------------------------- */
  177. /* LDI_CONTEXT_HANDLE - Handle to a LDI decompression context */
  178. typedef MHANDLE LDI_CONTEXT_HANDLE; /* hmd */
  179. /*** PFNALLOC - Memory allocation function for LDI
  180. *
  181. * Entry:
  182. * cb - Size in bytes of memory block to allocate
  183. *
  184. * Exit-Success:
  185. * Returns !NULL pointer to memory block
  186. *
  187. * Exit-Failure:
  188. * Returns NULL; insufficient memory
  189. */
  190. #ifndef _PFNALLOC_DEFINED
  191. #define _PFNALLOC_DEFINED
  192. typedef MI_MEMORY (FAR DIAMONDAPI *PFNALLOC)(ULONG cb); /* pfnma */
  193. #endif
  194. /*** PFNFREE - Free memory function for LDI
  195. *
  196. * Entry:
  197. * pv - Memory block allocated by matching PFNALLOC function
  198. *
  199. * Exit:
  200. * Memory block freed.
  201. */
  202. #ifndef _PFNFREE_DEFINED
  203. #define _PFNFREE_DEFINED
  204. typedef void (FAR DIAMONDAPI *PFNFREE)(MI_MEMORY pv); /* pfnmf */
  205. #endif
  206. /* --- prototypes --------------------------------------------------------- */
  207. /*** LDICreateDecompression - Create LDI decompression context
  208. *
  209. * Entry:
  210. * pcbDataBlockMax *largest uncompressed data block size expected,
  211. * gets largest uncompressed data block allowed
  212. * pvConfiguration passes implementation-specific info to decompressor.
  213. * pfnma memory allocation function pointer
  214. * pfnmf memory free function pointer
  215. * pcbSrcBufferMin gets max compressed buffer size
  216. * pmdhHandle gets newly-created context's handle
  217. * pfnopen file open function pointer (or NULL)
  218. * pfnread file read function pointer (or don't care)
  219. * pfnwrite file write function pointer (or don't care)
  220. * pfnclose file close function pointer (or don't care)
  221. * pfnseek file seek function pointer (or don't care)
  222. *
  223. * If NULL is provided for pfnopen, and the ring buffer cannot be
  224. * created via pfnma, LDICreateDecompression will fail.
  225. *
  226. * If pmdhHandle==NULL, *pcbDataBlockMax and *pcbSrcBufferMin will be
  227. * filled in, but no context will be created. This query will allow
  228. * the caller to determine required buffer sizes before creating a
  229. * context.
  230. *
  231. * Exit-Success:
  232. * Returns MDI_ERROR_NO_ERROR;
  233. * *pcbDataBlockMax, *pcbSrcBufferMin, *pmdhHandle filled in.
  234. *
  235. * Exit-Failure:
  236. * MDI_ERROR_NOT_ENOUGH_MEMORY, could not allocate enough memory.
  237. * MDI_ERROR_BAD_PARAMETERS, something wrong with parameters.
  238. * *pcbDataBlockMax, *pcbSrcBufferMin, *pmdhHandle undefined.
  239. */
  240. int FAR DIAMONDAPI LDICreateDecompression(
  241. UINT FAR * pcbDataBlockMax, /* max uncompressed data block size */
  242. void FAR * pvConfiguration, /* implementation-defined */
  243. PFNALLOC pfnma, /* Memory allocation function ptr */
  244. PFNFREE pfnmf, /* Memory free function ptr */
  245. UINT FAR * pcbSrcBufferMin, /* gets max. comp. buffer size */
  246. LDI_CONTEXT_HANDLE FAR * pmdhHandle, /* gets newly-created handle */
  247. PFNOPEN pfnopen, /* open a file callback */
  248. PFNREAD pfnread, /* read a file callback */
  249. PFNWRITE pfnwrite, /* write a file callback */
  250. PFNCLOSE pfnclose, /* close a file callback */
  251. PFNSEEK pfnseek); /* seek in file callback */
  252. /*** LDIDecompress - Decompress a block of data
  253. *
  254. * Entry:
  255. * hmd handle to decompression context
  256. * pbSrc source buffer (compressed data)
  257. * cbSrc compressed size of data to be decompressed
  258. * pbDst destination buffer (for decompressed data)
  259. * *pcbDecompressed (ptr to UINT) the expected de-compressed size
  260. * of this data block. (same as cbSrc from the
  261. * LCICompress() call.).
  262. *
  263. * Exit-Success:
  264. * Returns MDI_ERROR_NO_ERROR;
  265. * *pcbDecompressed has size of decompressed data in pbDst.
  266. * Decompression context updated.
  267. *
  268. * Exit-Failure:
  269. * MDI_ERROR_BAD_PARAMETERS, something wrong with parameters.
  270. * MDI_ERROR_BUFFER_OVERFLOW, cbSrc is too small to yield the
  271. * requested *pcbDecompressed count. cbSrc before LDIDecompressed
  272. * should always equal *pcbResult after QCICompress(), and
  273. * *pcbDecompressed before LDIDecompress should always equal the
  274. * cbSrc before QCICompress().
  275. * MDI_ERROR_FAILED, either cbSrc is too small, *pcbDecompressed is too
  276. * large, or *pbSrc is corrupt.
  277. *
  278. * Note:
  279. * Set your cbDecompressed to the expected de-compressed size of this
  280. * data block, then call LDIDecompress() with the address of your
  281. * cbDecompressed.
  282. */
  283. int FAR DIAMONDAPI LDIDecompress(
  284. LDI_CONTEXT_HANDLE hmd, /* decompression context */
  285. void FAR * pbSrc, /* source buffer */
  286. UINT cbSrc, /* source data size */
  287. void FAR * pbDst, /* target buffer */
  288. UINT FAR * pcbDecompressed); /* target data size */
  289. /*** LDIResetDecompression - Reset decompression history (if any)
  290. *
  291. * De-compression can only be started on a block which was compressed
  292. * immediately following a MCICreateCompression() or MCIResetCompression()
  293. * call. This function provides notification to the decompressor that the
  294. * next compressed block begins on a compression boundary.
  295. *
  296. * Entry:
  297. * hmd - handle to decompression context
  298. *
  299. * Exit-Success:
  300. * Returns MDI_ERROR_NO_ERROR;
  301. * Decompression context reset.
  302. *
  303. * Exit-Failure:
  304. * Returns MDI_ERROR_BAD_PARAMETERS, invalid context handle.
  305. */
  306. int FAR DIAMONDAPI LDIResetDecompression(LDI_CONTEXT_HANDLE hmd);
  307. /*** LDIDestroyDecompression - Destroy LDI decompression context
  308. *
  309. * Entry:
  310. * hmd - handle to decompression context
  311. *
  312. * Exit-Success:
  313. * Returns MDI_ERROR_NO_ERROR;
  314. * Decompression context destroyed.
  315. *
  316. * Exit-Failure:
  317. * Returns MDI_ERROR_BAD_PARAMETERS, invalid context handle.
  318. */
  319. int FAR DIAMONDAPI LDIDestroyDecompression(LDI_CONTEXT_HANDLE hmd);
  320. #ifndef BIT16
  321. int FAR DIAMONDAPI LDIGetWindow(
  322. LDI_CONTEXT_HANDLE hmd, /* decompression context */
  323. BYTE FAR ** ppWindow, /* pointer to window start */
  324. long * pFileOffset, /* offset in folder */
  325. long * pWindowOffset, /* offset in window */
  326. long * pcbBytesAvail); /* bytes avail from window start */
  327. #endif
  328. /* --- constants ---------------------------------------------------------- */
  329. /* return codes */
  330. #define MDI_ERROR_NO_ERROR 0
  331. #define MDI_ERROR_NOT_ENOUGH_MEMORY 1
  332. #define MDI_ERROR_BAD_PARAMETERS 2
  333. #define MDI_ERROR_BUFFER_OVERFLOW 3
  334. #define MDI_ERROR_FAILED 4
  335. #define MDI_ERROR_CONFIGURATION 5
  336. /* --- LZX configuration details ------------------------------------- */
  337. /*** LZX pvConfiguration structure
  338. *
  339. * For the LZX decompressor, two parameters are configurable, the
  340. * "window bits", which defines the size of the buffer needed by the
  341. * the decompressor (must match the value used to compress), and the CPU
  342. * type, which controls whether 386 opcodes will be used or not. If
  343. * "unknown" is provided for the fCPUtype, LDI will attempt to determine
  344. * the CPU type itself, which could fail or produce system faults on
  345. * non-DOS platforms (like Windows.) Windows apps should use GetWinFlags()
  346. * or a similiar method, and never pass "unknown".
  347. *
  348. * pvConfiguration points to this structure.
  349. */
  350. #pragma pack (1)
  351. typedef struct {
  352. long WindowSize; /* buffersize */
  353. long fCPUtype; /* controls internal code selection */
  354. } LZXDECOMPRESS; /* qdec */
  355. #pragma pack ()
  356. typedef LZXDECOMPRESS *PLZXDECOMPRESS; /* pldec */
  357. typedef LZXDECOMPRESS FAR *PFLZXDECOMPRESS; /* pfldec */
  358. /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
  359. *
  360. * LDI_CPU_UNKNOWN detection does *not* work when running under Windows
  361. * in 286 protected mode! Call GetWinFlags() to determine
  362. * the CPU type and pass it explicitly!
  363. */
  364. #define LDI_CPU_UNKNOWN (-1) /* internally determined */
  365. /*
  366. * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
  367. */
  368. #define LDI_CPU_80286 (0) /* '286 opcodes only */
  369. #define LDI_CPU_80386 (1) /* '386 opcodes used */
  370. #define LDI_CPU_CONSERVATIVE (LDI_CPU_80286)
  371. /* ----------------------------------------------------------------------- */
  372. }