/* * Microsoft Confidential * Copyright (C) Microsoft Corporation 1996 * All Rights Reserved. * * LDI.C: LZX Decompression Interface * * History: * 03-Jul-1996 jforbes Initial version. */ /* --- preprocessor ------------------------------------------------------- */ #include /* for NULL */ #include "decoder.h" #include "decapi.h" #include "ldi.h" /* types, prototype verification, error codes */ #define MAX_GROWTH 6144 /* see encoder.h */ typedef ULONG SIGNATURE; /* structure signature */ struct LDI_CONTEXT /* private structure */ { SIGNATURE signature; /* for validation */ PFNALLOC pfnAlloc; /* where the alloc() is */ PFNFREE pfnFree; /* where the free() is */ PFNOPEN pfnOpen; /* open a file callback or NULL */ PFNREAD pfnRead; /* read a file callback */ PFNWRITE pfnWrite; /* write a file callback */ PFNCLOSE pfnClose; /* close a file callback */ PFNSEEK pfnSeek; /* seek in file callback */ UINT cbDataBlockMax; /* promised max data size */ UINT fCPUtype; /* CPU we're running on, QDI_CPU_xxx */ t_decoder_context *decoder_context; }; typedef struct LDI_CONTEXT FAR *PMDC_CONTEXT; /* a pointer to one */ /* MAKE_SIGNATURE - Construct a structure signature * * Entry: * a,b,c,d - four characters * * Exit: * Returns constructed SIGNATURE * * Example: * strct->signature = MAKE_SIGNATURE('b','e','n','s') */ #define MAKE_SIGNATURE(a,b,c,d) (a + (b<<8) + (c<<16) + (d<<24)) #define BAD_SIGNATURE (0L) #define LDI_SIGNATURE MAKE_SIGNATURE('L','D','I','C') /* --- LDI context structure ---------------------------------------------- */ #define PMDCfromHMD(h) ((PMDC_CONTEXT)(h)) /* handle to pointer */ #define HMDfromPMDC(p) ((LDI_CONTEXT_HANDLE)(p)) /* pointer to handle */ /* --- LDICreateDecompression() ------------------------------------------- */ #include int FAR DIAMONDAPI LDICreateDecompression( UINT FAR * pcbDataBlockMax, /* max uncompressed data block */ void FAR * pvConfiguration, /* implementation-defined */ PFNALLOC pfnma, /* Memory allocation function */ PFNFREE pfnmf, /* Memory free function */ UINT FAR * pcbSrcBufferMin, /* gets required input buffer */ LDI_CONTEXT_HANDLE FAR * pmdhHandle, /* gets newly-created handle */ PFNOPEN pfnopen, /* open a file callback */ PFNREAD pfnread, /* read a file callback */ PFNWRITE pfnwrite, /* write a file callback */ PFNCLOSE pfnclose, /* close a file callback */ PFNSEEK pfnseek) /* seek in file callback */ { PMDC_CONTEXT context; /* new context */ PFLZXDECOMPRESS pConfig; /* to get configuration details */ pConfig = pvConfiguration; /* get a pointer we can use */ *pcbSrcBufferMin = /* we'll expand sometimes */ *pcbDataBlockMax + MAX_GROWTH; if (pmdhHandle == NULL) /* if no context requested, */ { return(MDI_ERROR_NO_ERROR); /* return from query mode */ } *pmdhHandle = (LDI_CONTEXT_HANDLE) 0; /* wait until it's valid */ context = pfnma(sizeof(struct LDI_CONTEXT)); if (context == NULL) { return(MDI_ERROR_NOT_ENOUGH_MEMORY); /* if can't allocate */ } context->decoder_context = pfnma(sizeof(t_decoder_context)); if (context->decoder_context == NULL) { pfnmf(context); return MDI_ERROR_NOT_ENOUGH_MEMORY; } context->pfnAlloc = pfnma; /* remember where alloc() is */ context->pfnFree = pfnmf; /* remember where free() is */ context->pfnOpen = pfnopen; /* remember where pfnopen() is */ context->pfnRead = pfnread; /* remember where pfnread() is */ context->pfnWrite = pfnwrite; /* remember where pfnwrite() is */ context->pfnClose = pfnclose; /* remember where pfnclose() is */ context->pfnSeek = pfnseek; /* remember where pfnseek() is */ context->cbDataBlockMax = *pcbDataBlockMax; /* remember agreement */ context->fCPUtype = (UINT) pConfig->fCPUtype; /* remember CPU type */ context->signature = LDI_SIGNATURE; /* install signature */ if (LZX_DecodeInit( context->decoder_context, pConfig->WindowSize, pfnma, pfnmf, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek) == false) { pfnmf(context); return (MDI_ERROR_NOT_ENOUGH_MEMORY); } /* pass context back to caller */ *pmdhHandle = HMDfromPMDC(context); return(MDI_ERROR_NO_ERROR); /* tell caller all is well */ } /* --- LDIDecompress() ---------------------------------------------------- */ int FAR DIAMONDAPI LDIDecompress( LDI_CONTEXT_HANDLE hmd, /* decompression context */ void FAR * pbSrc, /* source buffer */ UINT cbSrc, /* source actual size */ void FAR * pbDst, /* target buffer */ UINT FAR * pcbResult) /* gets actual target size */ { PMDC_CONTEXT context; /* pointer to the context */ int result; /* return code */ long bytes_to_decode; long total_bytes_written = 0; context = PMDCfromHMD(hmd); /* get pointer from handle */ if (context->signature != LDI_SIGNATURE) { return(MDI_ERROR_BAD_PARAMETERS); /* missing signature */ } if (*pcbResult > context->cbDataBlockMax) { return(MDI_ERROR_BUFFER_OVERFLOW); /* violated max block promise */ } #if 0 if (cbSrc == 0) return MDI_ERROR_NO_ERROR; #endif bytes_to_decode = (long) *pcbResult; result = LZX_Decode( context->decoder_context, bytes_to_decode, pbSrc, cbSrc, pbDst, bytes_to_decode, &total_bytes_written ); *pcbResult = (UINT) total_bytes_written; if (result) return MDI_ERROR_FAILED; else return MDI_ERROR_NO_ERROR; } /* --- LDIResetDecompression() -------------------------------------------- */ int FAR DIAMONDAPI LDIResetDecompression(LDI_CONTEXT_HANDLE hmd) { PMDC_CONTEXT context; /* pointer to the context */ context = PMDCfromHMD(hmd); /* get pointer from handle */ if (context->signature != LDI_SIGNATURE) { return(MDI_ERROR_BAD_PARAMETERS); /* missing signature */ } LZX_DecodeNewGroup(context->decoder_context); return(MDI_ERROR_NO_ERROR); /* if tag is OK */ } /* --- LDIDestroyDecompression() ------------------------------------------ */ int FAR DIAMONDAPI LDIDestroyDecompression(LDI_CONTEXT_HANDLE hmd) { PMDC_CONTEXT context; /* pointer to the context */ context = PMDCfromHMD(hmd); /* get pointer from handle */ if (context->signature != LDI_SIGNATURE) { return(MDI_ERROR_BAD_PARAMETERS); /* missing signature */ } LZX_DecodeFree(context->decoder_context); context->signature = BAD_SIGNATURE; /* destroy signature */ context->pfnFree(context->decoder_context); context->pfnFree(context); /* self-destruct */ return(MDI_ERROR_NO_ERROR); /* success */ } /* --- LDIGetWindow() ---------------------------------------------------- */ #ifndef BIT16 int FAR DIAMONDAPI LDIGetWindow( LDI_CONTEXT_HANDLE hmd, /* decompression context */ BYTE FAR ** ppWindow, /* pointer to window start */ long * pFileOffset, /* offset in folder */ long * pWindowOffset, /* offset in window */ long * pcbBytesAvail) /* bytes avail from window start */ { PMDC_CONTEXT context; t_decoder_context *dec_context; context = PMDCfromHMD(hmd); /* get pointer from handle */ dec_context = context->decoder_context; *ppWindow = dec_context->dec_mem_window; // window is a circular buffer if ((ulong) dec_context->dec_position_at_start < dec_context->dec_window_size) { *pWindowOffset = 0; *pFileOffset = 0; *pcbBytesAvail = dec_context->dec_position_at_start; } else { *pWindowOffset = dec_context->dec_position_at_start & (dec_context->dec_window_size - 1); *pcbBytesAvail = dec_context->dec_window_size; *pFileOffset = dec_context->dec_position_at_start - dec_context->dec_window_size; } return MDI_ERROR_NO_ERROR; } #endif /* ------------------------------------------------------------------------ */