Leaked source code of windows server 2003
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.

139 lines
3.1 KiB

  1. #include <windows.h>
  2. #include "compress.h"
  3. #include <zlib.h>
  4. #include <limits.h>
  5. #define CURRENT_COMPRESSED_DATA_VERSION 1
  6. typedef struct _COMPRESSED_DATA_HEADER
  7. {
  8. BYTE bVersion;
  9. UNALIGNED WORD wLength;
  10. } COMPRESSED_DATA_HEADER, *PCOMPRESSED_DATA_HEADER;
  11. //
  12. // Return value is the maximum length in bytes of the compressed data. The
  13. // input is the length in bytes of the uncompressed data.
  14. //
  15. DWORD GetCompressedDataLength(
  16. IN DWORD cbUncompressed)
  17. {
  18. //
  19. // Length computation:
  20. // zlib requires input length plus .01%, plus 12 bytes
  21. // Add one additional byte for loss of precision in above computation
  22. // Add length of data header
  23. //
  24. return (13 + sizeof(COMPRESSED_DATA_HEADER) +
  25. (DWORD) ((float) cbUncompressed * (float) 1.001));
  26. }
  27. //
  28. // Compresses the input data using zlib, optimizing for compression ratio at
  29. // the expense of speed. If pbOut is NULL, pcbOut will be set to the maximum
  30. // length required to store the compressed data.
  31. //
  32. DWORD
  33. WINAPI
  34. CompressData(
  35. IN DWORD cbIn,
  36. IN PBYTE pbIn,
  37. OUT PDWORD pcbOut,
  38. OUT PBYTE pbOut)
  39. {
  40. DWORD dwSts = ERROR_SUCCESS;
  41. DWORD cbOut = GetCompressedDataLength(cbIn);
  42. PCOMPRESSED_DATA_HEADER pHeader = NULL;
  43. if (NULL == pbOut)
  44. {
  45. *pcbOut = cbOut;
  46. goto Ret;
  47. }
  48. if (*pcbOut < cbOut)
  49. {
  50. *pcbOut = cbOut;
  51. dwSts = ERROR_MORE_DATA;
  52. goto Ret;
  53. }
  54. if (USHRT_MAX < cbIn)
  55. {
  56. dwSts = ERROR_INTERNAL_ERROR;
  57. goto Ret;
  58. }
  59. if (Z_OK != compress2(
  60. pbOut + sizeof(COMPRESSED_DATA_HEADER),
  61. &cbOut,
  62. pbIn,
  63. cbIn,
  64. Z_BEST_COMPRESSION))
  65. {
  66. dwSts = ERROR_INTERNAL_ERROR;
  67. goto Ret;
  68. }
  69. pHeader = (PCOMPRESSED_DATA_HEADER) pbOut;
  70. pHeader->bVersion = CURRENT_COMPRESSED_DATA_VERSION;
  71. pHeader->wLength = (WORD) cbIn;
  72. *pcbOut = cbOut + sizeof(COMPRESSED_DATA_HEADER);
  73. Ret:
  74. return dwSts;
  75. }
  76. //
  77. // Uncompresses the data using zlib. If pbOut is NULL, pcbOut is set to the
  78. // exact length of the uncompressed data - this will equal the cbIn value
  79. // originally passed to CompressData, above.
  80. //
  81. DWORD
  82. WINAPI
  83. UncompressData(
  84. IN DWORD cbIn,
  85. IN PBYTE pbIn,
  86. OUT PDWORD pcbOut,
  87. OUT PBYTE pbOut)
  88. {
  89. DWORD dwSts = ERROR_SUCCESS;
  90. PCOMPRESSED_DATA_HEADER pHeader = NULL;
  91. pHeader = (PCOMPRESSED_DATA_HEADER) pbIn;
  92. if (NULL == pbOut)
  93. {
  94. *pcbOut = pHeader->wLength;
  95. goto Ret;
  96. }
  97. if (*pcbOut < pHeader->wLength)
  98. {
  99. *pcbOut = pHeader->wLength;
  100. dwSts = ERROR_MORE_DATA;
  101. goto Ret;
  102. }
  103. *pcbOut = pHeader->wLength;
  104. if (Z_OK != uncompress(
  105. pbOut,
  106. pcbOut,
  107. pbIn + sizeof(COMPRESSED_DATA_HEADER),
  108. cbIn - sizeof(COMPRESSED_DATA_HEADER)))
  109. {
  110. dwSts = ERROR_INTERNAL_ERROR;
  111. goto Ret;
  112. }
  113. if (pHeader->wLength != *pcbOut)
  114. dwSts = ERROR_INTERNAL_ERROR;
  115. Ret:
  116. return dwSts;
  117. }