PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/publish/zlib/zlibimp.cpp

https://bitbucket.org/knoss/pcmanager/
C++ | 502 lines | 410 code | 78 blank | 14 comment | 74 complexity | d79c3494d87f308f2ddd603b12337000 MD5 | raw file
Possible License(s): LGPL-2.0
  1. /**
  2. * @file ksupdecode.cpp
  3. * @brief ...
  4. * @author bbcallen
  5. * @date 2010-01-19 15:23
  6. */
  7. #include "stdafx.h"
  8. #include "zlibimp.h"
  9. #include <atlfile.h>
  10. #include <common\utility.h>
  11. #include "winmod/winpath.h"
  12. #define ZLIB_SINGLE_FILE_MAX_SIZE (1000 * 1000 * 1000) ///< 单个文件的最大体积
  13. #define ZLIB_DECOMPRESS_INIT_BUFF_SIZE (1000 * 1000) ///< 解压缩输出的初始体积
  14. typedef int (*PFN_uncompress)(
  15. Bytef *dest,
  16. uLongf *destLen,
  17. const Bytef *source,
  18. uLong sourceLen
  19. );
  20. #define FN_uncompress "uncompress"
  21. typedef int (*PFN_compress2)(
  22. Bytef *dest,
  23. uLongf *destLen,
  24. const Bytef *source,
  25. uLong sourceLen,
  26. int level
  27. );
  28. #define FN_compress2 "compress2"
  29. typedef int (*PFN_compress)(
  30. Bytef *dest,
  31. uLongf *destLen,
  32. const Bytef *source,
  33. uLong sourceLen
  34. );
  35. #define FN_compress "compress"
  36. typedef int (*PFN_inflate)(
  37. z_streamp strm,
  38. int flush
  39. );
  40. #define FN_inflate "inflate"
  41. typedef int (*PFN_inflateEnd)(
  42. z_streamp strm
  43. );
  44. #define FN_inflateEnd "inflateEnd"
  45. typedef int (*PFN_inflateInit_)(
  46. z_streamp strm,
  47. const char *version,
  48. int stream_size
  49. );
  50. #define FN_inflateInit_ "inflateInit_"
  51. typedef int (*PFN_inflateInit2_)(
  52. z_streamp strm,
  53. int windowBits,
  54. const char *version,
  55. int stream_size
  56. );
  57. #define FN_inflateInit2_ "inflateInit2_"
  58. #define zlib_inflateInit(strm) \
  59. zlib_inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
  60. #define zlib_inflateInit2(strm, windowBits) \
  61. zlib_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
  62. PFN_compress zlib_compress = NULL;
  63. PFN_compress2 zlib_compress2 = NULL;
  64. PFN_uncompress zlib_uncompress = NULL;
  65. PFN_inflate zlib_inflate = NULL;
  66. PFN_inflateEnd zlib_inflateEnd = NULL;
  67. PFN_inflateInit_ zlib_inflateInit_ = NULL;
  68. PFN_inflateInit2_ zlib_inflateInit2_ = NULL;
  69. #if defined(USE_STATIC_ZLIB)
  70. #include "zlib123/zlib.h"
  71. #ifdef _DEBUG
  72. #pragma comment(lib, "zlibd.lib")
  73. #else
  74. #pragma comment(lib, "zlib.lib")
  75. #endif
  76. #else
  77. #ifdef _DEBUG
  78. #define ZLIB_FILE_NAME L"zlib1d.dll"
  79. #else
  80. #define ZLIB_FILE_NAME L"zlib1.dll"
  81. #endif
  82. HMODULE g_hZlib = NULL;
  83. #endif
  84. HRESULT CZlib::InitZlib()
  85. {
  86. #if defined(USE_STATIC_ZLIB)
  87. zlib_compress = compress;
  88. zlib_compress2 = compress2;
  89. zlib_uncompress = uncompress;
  90. zlib_inflate = inflate;
  91. zlib_inflateEnd = inflateEnd;
  92. zlib_inflateInit_ = inflateInit_;
  93. zlib_inflateInit2_ = inflateInit2_;
  94. return S_OK;
  95. #else
  96. HRESULT hr = S_OK;
  97. WinMod::CWinPath modpath;
  98. hr = CAppPath::Instance().GetLeidianAppPath( modpath.m_strPath );
  99. if ( FAILED( hr ) )
  100. {
  101. return hr;
  102. }
  103. modpath.Append( ZLIB_FILE_NAME );
  104. m_lock.Lock();
  105. if ( NULL == g_hZlib )
  106. {
  107. g_hZlib = LoadLibrary( modpath );
  108. if ( NULL == g_hZlib )
  109. {
  110. hr = HRESULT_FROM_WIN32( GetLastError() );
  111. goto Exit0;
  112. }
  113. zlib_compress = ( PFN_compress )GetProcAddress( g_hZlib, FN_compress );
  114. if ( NULL == zlib_compress )
  115. {
  116. hr = HRESULT_FROM_WIN32( GetLastError() );
  117. goto Exit0;
  118. }
  119. zlib_compress2 = ( PFN_compress2 )GetProcAddress( g_hZlib, FN_compress2 );
  120. if ( NULL == zlib_compress )
  121. {
  122. hr = HRESULT_FROM_WIN32( GetLastError() );
  123. goto Exit0;
  124. }
  125. zlib_uncompress = ( PFN_uncompress )GetProcAddress( g_hZlib, FN_uncompress );
  126. if ( NULL == zlib_uncompress )
  127. {
  128. hr = HRESULT_FROM_WIN32( GetLastError() );
  129. goto Exit0;
  130. }
  131. zlib_inflate = ( PFN_inflate )GetProcAddress( g_hZlib, FN_inflate );
  132. if ( NULL == zlib_inflate )
  133. {
  134. hr = HRESULT_FROM_WIN32( GetLastError() );
  135. goto Exit0;
  136. }
  137. zlib_inflateEnd = ( PFN_inflateEnd )GetProcAddress( g_hZlib, FN_inflateEnd );
  138. if ( NULL == zlib_inflateEnd )
  139. {
  140. hr = HRESULT_FROM_WIN32( GetLastError() );
  141. goto Exit0;
  142. }
  143. zlib_inflateInit_ = ( PFN_inflateInit_ )GetProcAddress( g_hZlib, FN_inflateInit_ );
  144. if ( NULL == zlib_inflateInit_ )
  145. {
  146. hr = HRESULT_FROM_WIN32( GetLastError() );
  147. goto Exit0;
  148. }
  149. zlib_inflateInit2_ = ( PFN_inflateInit2_ )GetProcAddress( g_hZlib, FN_inflateInit2_ );
  150. if ( NULL == zlib_inflateInit2_ )
  151. {
  152. hr = HRESULT_FROM_WIN32( GetLastError() );
  153. goto Exit0;
  154. }
  155. }
  156. Exit0:
  157. if ( FAILED( hr ) )
  158. {
  159. zlib_compress = NULL;
  160. zlib_uncompress = NULL;
  161. FreeLibrary( g_hZlib );
  162. g_hZlib = NULL;
  163. }
  164. m_lock.Unlock();
  165. return hr;
  166. #endif
  167. }
  168. void CZlib::UninitZlib()
  169. {
  170. #if defined(USE_STATIC_ZLIB)
  171. #else
  172. m_lock.Lock();
  173. if ( g_hZlib )
  174. {
  175. FreeLibrary( g_hZlib );
  176. g_hZlib = NULL;
  177. }
  178. m_lock.Unlock();
  179. #endif
  180. }
  181. HRESULT CZlib::DecodeFile(
  182. LPCWSTR lpwszSrcFile,
  183. LPCWSTR lpwszDstFile,
  184. DWORD dwDstSize
  185. )
  186. {
  187. if ( zlib_uncompress )
  188. {
  189. CAtlFile hInFile;
  190. HRESULT hr = hInFile.Create(
  191. lpwszSrcFile,
  192. GENERIC_READ,
  193. FILE_SHARE_READ | FILE_SHARE_DELETE,
  194. OPEN_EXISTING);
  195. if (FAILED(hr))
  196. return hr;
  197. CAtlFile hOutFile;
  198. hr = hOutFile.Create(
  199. lpwszDstFile,
  200. GENERIC_WRITE,
  201. FILE_SHARE_READ | FILE_SHARE_DELETE,
  202. CREATE_ALWAYS);
  203. if (FAILED(hr))
  204. return hr;
  205. ULONGLONG uInFileSize = 0;
  206. hr = hInFile.GetSize(uInFileSize);
  207. if (FAILED(hr))
  208. return hr;
  209. // 0长度文件不需要解压
  210. if (0 == uInFileSize)
  211. return S_OK;
  212. // 太大的文件不解压
  213. if (uInFileSize > ZLIB_SINGLE_FILE_MAX_SIZE)
  214. return E_FAIL;
  215. // 读取输入
  216. CAtlArray<BYTE> bufRead;
  217. bufRead.SetCount((size_t)uInFileSize);
  218. if (uInFileSize != bufRead.GetCount())
  219. return E_OUTOFMEMORY;
  220. hr = hInFile.Read(bufRead.GetData(), (DWORD)bufRead.GetCount());
  221. if (FAILED(hr))
  222. return hr;
  223. // 准备解压
  224. ULONGLONG uOutFileSize = 0;
  225. if ( 0 == dwDstSize )
  226. {
  227. uOutFileSize = max(uInFileSize, ZLIB_DECOMPRESS_INIT_BUFF_SIZE);
  228. }
  229. else
  230. {
  231. uOutFileSize = ( ULONGLONG )dwDstSize;
  232. }
  233. CAtlArray<BYTE> bufWrite;
  234. try
  235. {
  236. while (uOutFileSize <= ZLIB_SINGLE_FILE_MAX_SIZE)
  237. {
  238. bufWrite.SetCount(0);
  239. bufWrite.SetCount((DWORD)uOutFileSize);
  240. if (uOutFileSize != bufWrite.GetCount())
  241. return E_OUTOFMEMORY;
  242. DWORD dwDecompressSize = DWORD(uOutFileSize);
  243. int nRet = zlib_uncompress(
  244. bufWrite.GetData(),
  245. &dwDecompressSize,
  246. bufRead.GetData(),
  247. (int)bufRead.GetCount());
  248. if (nRet == Z_OK && dwDecompressSize <= uOutFileSize)
  249. {
  250. bufWrite.SetCount(dwDecompressSize);
  251. break;
  252. }
  253. if (nRet != Z_BUF_ERROR)
  254. return E_FAIL;
  255. uOutFileSize *= 2;
  256. }
  257. }
  258. catch (...)
  259. {
  260. return E_FAIL;
  261. }
  262. hr = hOutFile.Write(bufWrite.GetData(), (DWORD)bufWrite.GetCount());
  263. if (FAILED(hr))
  264. return hr;
  265. return S_OK;
  266. }
  267. else
  268. {
  269. return E_NOINTERFACE;
  270. }
  271. }
  272. HRESULT CZlib::EncodeFile( LPCWSTR lpwszSrcFile, LPCWSTR lpwszDstFile, int level )
  273. {
  274. if ( zlib_compress )
  275. {
  276. CAtlFile hInFile;
  277. HRESULT hr = hInFile.Create(
  278. lpwszSrcFile,
  279. GENERIC_READ,
  280. FILE_SHARE_READ | FILE_SHARE_DELETE,
  281. OPEN_EXISTING);
  282. if (FAILED(hr))
  283. return hr;
  284. CAtlFile hOutFile;
  285. hr = hOutFile.Create(
  286. lpwszDstFile,
  287. GENERIC_WRITE,
  288. FILE_SHARE_READ | FILE_SHARE_DELETE,
  289. CREATE_ALWAYS);
  290. if (FAILED(hr))
  291. return hr;
  292. ULONGLONG uInFileSize = 0;
  293. hr = hInFile.GetSize(uInFileSize);
  294. if (FAILED(hr))
  295. return hr;
  296. // 0长度文件不需要压缩
  297. if (0 == uInFileSize)
  298. return S_OK;
  299. // 太大的文件不压缩
  300. if (uInFileSize > ZLIB_SINGLE_FILE_MAX_SIZE ) //假定压缩比为4:1
  301. return E_FAIL;
  302. // 读取输入
  303. CAtlArray<BYTE> bufRead;
  304. bufRead.SetCount((size_t)uInFileSize);
  305. if (uInFileSize != bufRead.GetCount())
  306. return E_OUTOFMEMORY;
  307. hr = hInFile.Read(bufRead.GetData(), (DWORD)bufRead.GetCount());
  308. if (FAILED(hr))
  309. return hr;
  310. // 准备压缩
  311. ULONGLONG uOutFileSize = max(uInFileSize, ZLIB_DECOMPRESS_INIT_BUFF_SIZE);
  312. CAtlArray<BYTE> bufWrite;
  313. try
  314. {
  315. while (uOutFileSize <= ZLIB_SINGLE_FILE_MAX_SIZE )
  316. {
  317. bufWrite.SetCount(0);
  318. bufWrite.SetCount((DWORD)uOutFileSize);
  319. if (uOutFileSize != bufWrite.GetCount())
  320. return E_OUTOFMEMORY;
  321. DWORD dwcompressSize = DWORD(uOutFileSize);
  322. int nRet = zlib_compress2(
  323. bufWrite.GetData(),
  324. &dwcompressSize,
  325. bufRead.GetData(),
  326. (int)bufRead.GetCount(),
  327. level
  328. );
  329. if (nRet == Z_OK && dwcompressSize <= uOutFileSize)
  330. {
  331. bufWrite.SetCount(dwcompressSize);
  332. break;
  333. }
  334. if (nRet != Z_BUF_ERROR)
  335. return E_FAIL;
  336. uOutFileSize *= 2;
  337. }
  338. }
  339. catch (...)
  340. {
  341. return E_FAIL;
  342. }
  343. hr = hOutFile.Write(bufWrite.GetData(), (DWORD)bufWrite.GetCount());
  344. if (FAILED(hr))
  345. return hr;
  346. return S_OK;
  347. }
  348. else
  349. {
  350. return E_NOINTERFACE;
  351. }
  352. }
  353. int inflate_read(LPBYTE pbySrcBuffer, LONG lSrcBuffSize, LPBYTE *ppbyDstBuffer, LONG *plDstBuffSize, BOOL bGZip)
  354. {
  355. # define CHUNK 4096
  356. int nRet = Z_DATA_ERROR;
  357. LONG lReadSize = 0;
  358. BYTE pbyBufferTmp[CHUNK];
  359. LONG lTotalSize = 0;
  360. LPBYTE pbyDstBuffer = NULL;
  361. z_stream strm;
  362. strm.zalloc = Z_NULL;
  363. strm.zfree = Z_NULL;
  364. strm.opaque = Z_NULL;
  365. strm.avail_in = 0;
  366. strm.next_in = Z_NULL;
  367. if (bGZip)
  368. nRet = zlib_inflateInit2(&strm, 47);
  369. else
  370. nRet = zlib_inflateInit(&strm);
  371. if (nRet != Z_OK)
  372. return nRet;
  373. strm.avail_in = lSrcBuffSize;
  374. strm.next_in = pbySrcBuffer;
  375. do
  376. {
  377. strm.avail_out = CHUNK;
  378. strm.next_out = pbyBufferTmp;
  379. nRet = zlib_inflate(&strm, Z_NO_FLUSH);
  380. switch (nRet)
  381. {
  382. case Z_NEED_DICT:
  383. nRet = Z_DATA_ERROR;
  384. case Z_DATA_ERROR:
  385. case Z_MEM_ERROR:
  386. goto Exit0;
  387. }
  388. lReadSize = CHUNK - strm.avail_out;
  389. lTotalSize += lReadSize;
  390. pbyDstBuffer = (LPBYTE)realloc(pbyDstBuffer, lTotalSize);
  391. memcpy(pbyDstBuffer + lTotalSize - lReadSize, pbyBufferTmp, lReadSize);
  392. }
  393. while (strm.avail_out == 0);
  394. Exit0:
  395. zlib_inflateEnd(&strm);
  396. if (Z_STREAM_END == nRet)
  397. {
  398. *ppbyDstBuffer = pbyDstBuffer;
  399. *plDstBuffSize = lTotalSize;
  400. }
  401. else
  402. {
  403. if (pbyDstBuffer)
  404. {
  405. free(pbyDstBuffer);
  406. pbyDstBuffer = NULL;
  407. }
  408. *ppbyDstBuffer = NULL;
  409. *plDstBuffSize = 0;
  410. }
  411. return (Z_STREAM_END == nRet) ? Z_OK : Z_DATA_ERROR;
  412. }
  413. HRESULT CZlib::DecodeGZipBuffer(
  414. LPBYTE pbySrcBuffer,
  415. LONG lSrcBuffSize,
  416. LPBYTE *ppbyDstBuffer,
  417. LONG *plDstBuffSize
  418. )
  419. {
  420. if (NULL == zlib_inflate)
  421. return E_FAIL;
  422. int nRet = inflate_read(pbySrcBuffer, lSrcBuffSize, ppbyDstBuffer, plDstBuffSize, TRUE);
  423. return (Z_OK == nRet) ? S_OK : E_FAIL;
  424. }