[PATCH] d3dxof: Decompress all MSZIP chunks of the compressed file and update file format description

Christian Costa titan.costa at gmail.com
Thu Feb 16 17:19:12 CST 2012


Fix first problem of bug 24751
---
 dlls/d3dxof/parsing.c      |   60 +++++++++++++++++++++++++++++++-------------
 dlls/d3dxof/tests/d3dxof.c |    9 ++++---
 2 files changed, 47 insertions(+), 22 deletions(-)

diff --git a/dlls/d3dxof/parsing.c b/dlls/d3dxof/parsing.c
index 4b9b12f..f177e0a 100644
--- a/dlls/d3dxof/parsing.c
+++ b/dlls/d3dxof/parsing.c
@@ -220,40 +220,64 @@ HRESULT parse_header(parse_buffer * buf, BYTE ** decomp_buffer_ptr)
   if (header[2] == XOFFILE_FORMAT_BINARY_MSZIP || header[2] == XOFFILE_FORMAT_TEXT_MSZIP)
   {
     /* Extended header for compressed data:
-     * 16-17 -> decompressed size w/ header,  18-19 -> null,
-     * 20-21 -> decompressed size w/o header, 22-23 -> size of MSZIP compressed data,
-     * 24-xx -> compressed MSZIP data */
+     * 16-19 -> size of decompressed file including xof header,
+     * 20-21 -> size of first decompressed MSZIP chunk, 22-23 -> size of first compressed MSZIP chunk
+     * 24-xx -> compressed MSZIP data chunk 
+     * xx-xx -> size of next decompressed MSZIP chunk, xx-xx -> size of next compressed MSZIP chunk
+     * xx-xx -> compressed MSZIP data chunk
+     * .............................................................................................. */
     int err;
-    WORD decomp_size;
-    WORD comp_size;
+    DWORD decomp_file_size;
+    WORD decomp_chunk_size;
+    WORD comp_chunk_size;
     LPBYTE decomp_buffer;
 
-    buf->rem_bytes -= sizeof(WORD) * 2;
-    buf->buffer += sizeof(WORD) * 2;
-    if (!read_bytes(buf, &decomp_size, sizeof(decomp_size)))
-      return DXFILEERR_BADFILETYPE;
-    if (!read_bytes(buf, &comp_size, sizeof(comp_size)))
+    if (!read_bytes(buf, &decomp_file_size, sizeof(decomp_file_size)))
       return DXFILEERR_BADFILETYPE;
 
-    TRACE("Compressed format %s detected: compressed_size = %x, decompressed_size = %x\n",
-        debugstr_fourcc(header[2]), comp_size, decomp_size);
+    TRACE("Compressed format %s detected: decompressed file size with xof header = %d\n",
+          debugstr_fourcc(header[2]), decomp_file_size);
+
+    /* Does not take xof header into account */
+    decomp_file_size -= 16;
 
-    decomp_buffer = HeapAlloc(GetProcessHeap(), 0, decomp_size);
+    decomp_buffer = HeapAlloc(GetProcessHeap(), 0, decomp_file_size);
     if (!decomp_buffer)
     {
         ERR("Out of memory\n");
         return DXFILEERR_BADALLOC;
     }
-    err = mszip_decompress(comp_size, decomp_size, (char*)buf->buffer, (char*)decomp_buffer);
-    if (err)
+    *decomp_buffer_ptr = decomp_buffer;
+
+    while (buf->rem_bytes)
     {
-        WARN("Error while decompressing mszip archive %d\n", err);
+      if (!read_bytes(buf, &decomp_chunk_size, sizeof(decomp_chunk_size)))
+        return DXFILEERR_BADFILETYPE;
+      if (!read_bytes(buf, &comp_chunk_size, sizeof(comp_chunk_size)))
+        return DXFILEERR_BADFILETYPE;
+
+      TRACE("Process chunk: compressed_size = %d, decompressed_size = %d\n",
+            comp_chunk_size, decomp_chunk_size);
+
+      err = mszip_decompress(comp_chunk_size, decomp_chunk_size, (char*)buf->buffer, (char*)decomp_buffer);
+      if (err)
+      {
+        WARN("Error while decompressing MSZIP chunk %d\n", err);
         HeapFree(GetProcessHeap(), 0, decomp_buffer);
         return DXFILEERR_BADALLOC;
+      }
+      buf->rem_bytes -= comp_chunk_size;
+      buf->buffer += comp_chunk_size;
+      decomp_buffer += decomp_chunk_size;
     }
+
+    if ((decomp_buffer - *decomp_buffer_ptr) != decomp_file_size)
+      ERR("Size of all decompressed chunks (%d) does not match decompressed file size (%d)\n",
+          decomp_buffer - *decomp_buffer_ptr, decomp_file_size);
+
     /* Use decompressed data */
-    buf->buffer = *decomp_buffer_ptr = decomp_buffer;
-    buf->rem_bytes = decomp_size;
+    buf->buffer = *decomp_buffer_ptr;
+    buf->rem_bytes = decomp_file_size;
   }
 
   TRACE("Header is correct\n");
diff --git a/dlls/d3dxof/tests/d3dxof.c b/dlls/d3dxof/tests/d3dxof.c
index 8ce22b7..5c6315a 100644
--- a/dlls/d3dxof/tests/d3dxof.c
+++ b/dlls/d3dxof/tests/d3dxof.c
@@ -74,11 +74,12 @@ static char empty_bin_file[]  = "xof 0302bin 0064";
 /* MSZip data is generated with the command "MAKECAB.EXE /D Compress=ON /D CompressionType=MSZip file packed"
  * Data in cab is after the filename (null terminated) and the 32-bit checksum:
  * size (16-bit), packed_size (16-bit) and compressed data (with leading 16-bit CK signature)
- * Data in x files is preceding by 2 16-bit words: size with xof header (16 bytes) and a 0 value
- * It does not seem possible to generate a MSZip data with no byte, so put just 1 byte here */
-/* "\n" packed with MSZip => not text */
+ * for each MSZIP chunk whose decompressed size can not exceed 32768 bytes
+ * Data in x files is preceeding by the size (32-bit) of the decompressed file including the xof header (16 bytes)
+ * It does not seem possible to generate a MSZip data chunk with no byte, so put just 1 byte here */
+/* "\n" packed with MSZip => no text */
 static char empty_tzip_file[] = "xof 0302tzip0064\x11\x00\x00\x00\x01\x00\x05\x00\x43\x4b\xe3\x02\x00";
-/* "\n" packed with MSZip => not token (token are 16-bit and there is only 1 byte) */
+/* "\n" packed with MSZip => no token (token are 16-bit and there is only 1 byte) */
 static char empty_bzip_file[] = "xof 0302bzip0064\x11\x00\x00\x00\x01\x00\x05\x00\x43\x4b\xe3\x02\x00";
 static char empty_cmp_file[]  = "xof 0302cmp 0064";
 static char empty_xxxx_file[] = "xof 0302xxxx0064";




More information about the wine-patches mailing list