CompositeFile.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:9k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "globals.h"
  3. #include "CompositeFile.h"
  4. #include "ZLib/zlib.h"
  5. #define CPC_PKFILE_MAGIC 0x04034B50
  6. #define CPC_PKFILE_DIRMAGIC 0x02014B50
  7. #define CPC_PKFILE_BITS_ENCRYPTED 0x1
  8. #define CPC_PKFILE_BITS_STREAMED 0x8
  9. //
  10. #define CPC_PKFILE_METHOD_STORED 0x0
  11. #define CPC_PKFILE_METHOD_DEFLATED 0x8
  12. //
  13. #pragma pack(push, 1)
  14. typedef struct _CPs_PKFILE_HEADER
  15. {
  16.     DWORD m_dwSig;
  17.     WORD m_wVersion;
  18.     WORD m_wBITs;
  19.     WORD m_wMethod;
  20.     WORD m_wModifyTime;
  21.     WORD m_wModifyDate;
  22.     DWORD m_dwCRC32;
  23.     DWORD m_dwCompressedSize;
  24.     DWORD m_dwDecompressedSize;
  25.     WORD m_wFilenameLen;
  26.     WORD m_wExtraFieldLen;
  27. } CPs_PKFILE_HEADER;
  28. //
  29. typedef struct _CPs_PKFILE_DESCRIPTOR
  30. {
  31.     DWORD m_dwCRC32;
  32.     DWORD m_dwCompressedSize;
  33.     DWORD m_dwDecompressedSize;
  34. } CPs_PKFILE_DESCRIPTOR;
  35. #pragma pack(pop)
  36. //
  37. typedef struct _CPs_SubFile
  38. {
  39.     char* m_pcName;
  40.     DWORD m_dwCRC32;
  41.     unsigned int m_iFileOffset;
  42.     unsigned int m_iCompressedSize;
  43.     unsigned int m_iUncompressedSize;
  44.     WORD m_wMethod;
  45.     void* m_pNext;
  46. } CPs_SubFile;
  47. //
  48. typedef struct _CPs_CompositeContext
  49. {
  50.     HANDLE m_hFileMapping;
  51.     BYTE* m_pFileBase;
  52.     DWORD m_dwFileSize;
  53.     BOOL m_bMemMappedFile;
  54.     CPs_SubFile* m_pFirstSubFile;
  55. } CPs_CompositeContext;
  56. //
  57. #define CPM_GET_BYTE(offset) (*(BYTE*)(pContext->m_pFileBase + (offset++) ))
  58. #define CPM_GET_WORD(offset) (*(WORD*)(pContext->m_pFileBase + (offset+=2) - 2))
  59. #define CPM_GET_DWORD(offset) (*(DWORD*)(pContext->m_pFileBase + (offset+=4) - 4))
  60. BOOL CP_BuildDirectory(CP_COMPOSITEFILE hComposite);
  61. const CPs_SubFile* CP_FindFile(CP_COMPOSITEFILE hComposite, const char* pcFilename);
  62. CP_COMPOSITEFILE CF_Create_FromFile(const char* pcPath)
  63. {
  64.     CPs_CompositeContext* pContext;
  65.     HANDLE hFile;
  66.     DWORD dwFileSize;
  67.     hFile = CreateFile(pcPath,
  68.                        GENERIC_READ,
  69.                        FILE_SHARE_READ,
  70.                        NULL,
  71.                        OPEN_EXISTING,
  72.                        FILE_ATTRIBUTE_NORMAL,
  73.                        NULL);
  74.     if(hFile == INVALID_HANDLE_VALUE)
  75.         return NULL;
  76.     dwFileSize = GetFileSize(hFile, NULL);
  77.     if(dwFileSize > 0x00800000 )
  78.     {
  79.         CloseHandle(hFile);
  80.         return NULL;
  81.     }
  82.     pContext = (CPs_CompositeContext*)malloc(sizeof(CPs_CompositeContext));
  83.     pContext->m_dwFileSize = dwFileSize;
  84.     pContext->m_hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  85.     CloseHandle(hFile);
  86.     if(pContext->m_hFileMapping == INVALID_HANDLE_VALUE)
  87.     {
  88.         free(pContext);
  89.         return NULL;
  90.     }
  91.     pContext->m_pFileBase = (BYTE*)MapViewOfFile(pContext->m_hFileMapping, FILE_MAP_READ, 0, 0, 0);
  92.     if(!pContext->m_pFileBase)
  93.     {
  94.         CloseHandle(pContext->m_hFileMapping);
  95.         free(pContext);
  96.         return NULL;
  97.     }
  98.     if(CP_BuildDirectory(pContext) == FALSE)
  99.     {
  100.         CF_Destroy(pContext);
  101.         return NULL;
  102.     }
  103.     return pContext;
  104. }
  105. //
  106. CP_COMPOSITEFILE CF_Create_FromResource(HMODULE hModule, UINT uiResourceID, const char* pcResourceType)
  107. {
  108.     CPs_CompositeContext* pContext;
  109.     HRSRC hResource;
  110.     HGLOBAL hResourceData;
  111.     hResource = FindResource(hModule, MAKEINTRESOURCE(uiResourceID), pcResourceType);
  112.     CP_ASSERT(hResource);
  113.     hResourceData = LoadResource(hModule, hResource);
  114.     CP_ASSERT(hResourceData);
  115.     pContext = (CPs_CompositeContext*)malloc(sizeof(CPs_CompositeContext));
  116.     pContext->m_dwFileSize = SizeofResource(hModule, hResource);
  117.     pContext->m_hFileMapping = NULL;
  118.     pContext->m_pFileBase = LockResource(hResourceData);
  119.     if(CP_BuildDirectory(pContext) == FALSE)
  120.     {
  121.         CF_Destroy(pContext);
  122.         return NULL;
  123.     }
  124.     // Success
  125.     return pContext;
  126. }
  127. //
  128. void CF_Destroy(CP_COMPOSITEFILE hComposite)
  129. {
  130.     CPs_CompositeContext* pContext = (CPs_CompositeContext*)hComposite;
  131.     CPs_SubFile* pSubFile_Cursor;
  132.     CPs_SubFile* pSubFile_Next;
  133.     CP_CHECKOBJECT(pContext);
  134.     if(pContext->m_hFileMapping)
  135.     {
  136.         UnmapViewOfFile(pContext->m_pFileBase);
  137.         CloseHandle(pContext->m_hFileMapping);
  138.     }
  139.     for(pSubFile_Cursor = pContext->m_pFirstSubFile; pSubFile_Cursor; pSubFile_Cursor = pSubFile_Next)
  140.     {
  141.         pSubFile_Next = (CPs_SubFile*)pSubFile_Cursor->m_pNext;
  142.         free(pSubFile_Cursor->m_pcName);
  143.         free(pSubFile_Cursor);
  144.     }
  145.     free(pContext);
  146. }
  147. //
  148. BOOL CF_GetSubFile(CP_COMPOSITEFILE hComposite, const char* pcSubfilename, void** ppSubFile_Uncompressed, unsigned int* piSubFile_Length)
  149. {
  150.     CPs_CompositeContext* pContext = (CPs_CompositeContext*)hComposite;
  151.     const CPs_SubFile* pSubFile;
  152.     DWORD dwCRC32;
  153.     CP_CHECKOBJECT(pContext);
  154.     pSubFile = CP_FindFile(hComposite, pcSubfilename);
  155.     if(!pSubFile)
  156.     {
  157.         *ppSubFile_Uncompressed = NULL;
  158.         *piSubFile_Length = 0;
  159.         return FALSE;
  160.     }
  161.     *ppSubFile_Uncompressed = malloc(pSubFile->m_iUncompressedSize);
  162.     *piSubFile_Length = pSubFile->m_iUncompressedSize;
  163.     if(pSubFile->m_wMethod == CPC_PKFILE_METHOD_STORED)
  164.     {
  165.         memcpy(*ppSubFile_Uncompressed, pContext->m_pFileBase + pSubFile->m_iFileOffset, *piSubFile_Length);
  166.     }
  167.     else if(pSubFile->m_wMethod == CPC_PKFILE_METHOD_DEFLATED)
  168.     {
  169.         z_stream zStream;
  170.         zStream.zalloc = Z_NULL;
  171.         zStream.zfree = Z_NULL;
  172.         zStream.opaque = Z_NULL;
  173.         zStream.data_type = Z_BINARY;
  174.         inflateInit2(&zStream, -15);
  175.         zStream.next_out = (BYTE*)*ppSubFile_Uncompressed;
  176.         zStream.avail_out = *piSubFile_Length;
  177.         zStream.next_in = pContext->m_pFileBase + pSubFile->m_iFileOffset;
  178.         zStream.avail_in = pSubFile->m_iCompressedSize;
  179.         inflate(&zStream, Z_FINISH);
  180.         inflateEnd(&zStream);
  181.     }
  182.     dwCRC32 = crc32(0, *ppSubFile_Uncompressed, *piSubFile_Length);
  183.     if(dwCRC32 != pSubFile->m_dwCRC32)
  184.     {
  185.         free(*ppSubFile_Uncompressed);
  186.         *ppSubFile_Uncompressed = NULL;
  187.         *piSubFile_Length = 0;
  188.         return FALSE;
  189.     }
  190.     return TRUE;
  191. }
  192. BOOL CP_BuildDirectory(CP_COMPOSITEFILE hComposite)
  193. {
  194.     CPs_CompositeContext* pContext = (CPs_CompositeContext*)hComposite;
  195.     unsigned int iOffset;
  196.     CP_CHECKOBJECT(pContext);
  197.     pContext->m_pFirstSubFile = NULL;
  198.     iOffset = 0;
  199.     while( ((iOffset + sizeof(CPs_PKFILE_HEADER)) < pContext->m_dwFileSize)
  200.             && *(DWORD*)(pContext->m_pFileBase + iOffset) != CPC_PKFILE_DIRMAGIC)
  201.     {
  202.         CPs_PKFILE_HEADER* pHeader = (CPs_PKFILE_HEADER*)(pContext->m_pFileBase + iOffset);
  203.         CPs_SubFile* pNewSubFile;
  204.         if(pHeader->m_dwSig != CPC_PKFILE_MAGIC
  205.                 || (pHeader->m_wBITs & CPC_PKFILE_BITS_ENCRYPTED)
  206.                 || (pHeader->m_wBITs & CPC_PKFILE_BITS_STREAMED)
  207.                 || (pHeader->m_wMethod != CPC_PKFILE_METHOD_STORED && pHeader->m_wMethod != CPC_PKFILE_METHOD_DEFLATED) )
  208.         {
  209.             CP_TRACE0("ZIP format not understood");
  210.             return FALSE;
  211.         }
  212.         pNewSubFile = (CPs_SubFile*)malloc(sizeof(*pNewSubFile));
  213.         pNewSubFile->m_pNext = pContext->m_pFirstSubFile;
  214.         pContext->m_pFirstSubFile = pNewSubFile;
  215.         pNewSubFile->m_pcName = (char*)malloc(pHeader->m_wFilenameLen + 1);
  216.         memcpy(pNewSubFile->m_pcName, pContext->m_pFileBase + iOffset + sizeof(*pHeader), pHeader->m_wFilenameLen);
  217.         pNewSubFile->m_pcName[pHeader->m_wFilenameLen] = '';
  218.         pNewSubFile->m_wMethod = pHeader->m_wMethod;
  219.         pNewSubFile->m_dwCRC32 = pHeader->m_dwCRC32;
  220.         pNewSubFile->m_iCompressedSize = pHeader->m_dwCompressedSize;
  221.         pNewSubFile->m_iUncompressedSize = pHeader->m_dwDecompressedSize;
  222.         pNewSubFile->m_iFileOffset = iOffset + sizeof(*pHeader) + pHeader->m_wFilenameLen + pHeader->m_wExtraFieldLen;
  223.         CP_TRACE1("SubFile:"%s"", pNewSubFile->m_pcName);
  224.         iOffset += sizeof(*pHeader)
  225.                    + pHeader->m_dwCompressedSize
  226.                    + pHeader->m_wFilenameLen
  227.                    + pHeader->m_wExtraFieldLen;
  228.     }
  229.     return TRUE;
  230. }
  231. const CPs_SubFile* CP_FindFile(CP_COMPOSITEFILE hComposite, const char* pcFilename)
  232. {
  233.     CPs_CompositeContext* pContext = (CPs_CompositeContext*)hComposite;
  234.     const CPs_SubFile* pSubFile_Cursor;
  235.     CP_CHECKOBJECT(pContext);
  236.     for(pSubFile_Cursor = pContext->m_pFirstSubFile; pSubFile_Cursor; pSubFile_Cursor = (const CPs_SubFile*)pSubFile_Cursor->m_pNext)
  237.     {
  238.         if(stricmp(pSubFile_Cursor->m_pcName, pcFilename) == 0)
  239.             return pSubFile_Cursor;
  240.     }
  241.     return NULL;
  242. }