cab_D_00.diff

Gregory M. Turner gmturner007 at ameritech.net
Mon Jun 23 03:46:02 CDT 2003


Basically just a WIP snapshot and more-or-less a noop, this should
nevertheless be applied as it fixes the warning about buf2.

The apparent largeness of the patch is an illusion caused by
the elimination of a large loop and subsequent indent changes.
Actual semantic changes are quite minimal.  This patch does not
implement split cabinet support as previously promised.... this is
still "coming soon to cvs repositories near you," I promise.

License: Bugroff

ChangeLog:

* dlls/cabinet: fdi.c:
  Greg Turner <gmturner007 at ameritech.net>
- remove unused loop that always iterates once
- remove warning
- preparations to use multiple fdi_decomp_state structures in a linkedlist,
  which will be used to implement split cabinets, if all goes according
  to plan -- this is somewhat analogous to struct cabinet in cabextract.

--
diff -ur --minimal --exclude-from=/home/greg/bin/winetreediff_excl ../wine.vanilla/dlls/cabinet/fdi.c ./dlls/cabinet/fdi.c
--- ../wine.vanilla/dlls/cabinet/fdi.c	2003-06-19 14:48:26.000000000 -0500
+++ ./dlls/cabinet/fdi.c	2003-06-23 03:29:46.000000000 -0500
@@ -93,6 +93,9 @@
     struct QTMstate qtm;
     struct LZXstate lzx;
   } methods;
+  struct fdi_folder *firstfol; 
+  struct fdi_file   *firstfile;
+  struct fdi_cds_fwd *next;
 } fdi_decomp_state;
 
 /*
@@ -1790,10 +1793,12 @@
   char              fullpath[MAX_PATH];
   size_t            pathlen, filenamelen;
   char              emptystring = '\0';
-  cab_UBYTE         buf[64], buf2[256] /* for modification by call back fn */ ;
+  cab_UBYTE         buf[64];
   BOOL              initialcab = TRUE;
-  struct fdi_folder *fol = NULL, *linkfol = NULL, *firstfol = NULL; 
-  struct fdi_file   *file = NULL, *linkfile = NULL, *firstfile = NULL;
+  struct fdi_folder *fol = NULL, *linkfol = NULL; 
+  struct fdi_file   *file = NULL, *linkfile = NULL;
+  fdi_decomp_state _decomp_state;
+  fdi_decomp_state *decomp_state = &_decomp_state;
 
   TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, \
         pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
@@ -1804,231 +1809,254 @@
     return FALSE;
   }
 
-  while (TRUE) { /* this loop executes one per. cabinet */
-    pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
-    filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
-  
-    /* slight overestimation here to save CPU cycles in the developer's brain */
-    if ((pathlen + filenamelen + 3) > MAX_PATH) {
-      ERR("MAX_PATH exceeded.\n");
-      PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
-      PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
+  ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
+
+  pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
+  filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
+
+  /* slight overestimation here to save CPU cycles in the developer's brain */
+  if ((pathlen + filenamelen + 3) > MAX_PATH) {
+    ERR("MAX_PATH exceeded.\n");
+    PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
+    PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
+    PFDI_INT(hfdi)->perf->fError = TRUE;
+    SetLastError(ERROR_FILE_NOT_FOUND);
+    return FALSE;
+  }
+
+  /* paste the path and filename together */
+  idx = 0;
+  if (pathlen) {
+    for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
+    if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
+  }
+  if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
+  fullpath[idx] = '\0';
+
+  TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
+
+  /* get a handle to the cabfile */
+  cabhf = PFDI_OPEN(hfdi, fullpath, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
+  if (cabhf == -1) {
+    PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
+    PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
+    PFDI_INT(hfdi)->perf->fError = TRUE;
+    SetLastError(ERROR_FILE_NOT_FOUND);
+    return FALSE;
+  }
+
+  /* check if it's really a cabfile. Note that this doesn't implement the bug */
+  if (!FDI_read_entries(hfdi, cabhf, &fdici, &mii)) {
+    ERR("FDIIsCabinet failed.\n");
+    PFDI_CLOSE(hfdi, cabhf);
+    return FALSE;
+  }
+   
+  /* cabinet notification */
+  ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
+  fdin.setID = fdici.setID;
+  fdin.iCabinet = fdici.iCabinet;
+  fdin.pv = pvUser;
+  fdin.psz1 = (mii.nextname) ? mii.nextname : &emptystring;
+  fdin.psz2 = (mii.nextinfo) ? mii.nextinfo : &emptystring;
+  fdin.psz3 = pszCabPath;
+
+  if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
+    PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
+    PFDI_INT(hfdi)->perf->erfType = 0;
+    PFDI_INT(hfdi)->perf->fError = TRUE;
+    goto bail_and_fail;
+  }
+
+  /* read folders */
+  for (i = 0; i < fdici.cFolders; i++) {
+    if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
+      PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
+      PFDI_INT(hfdi)->perf->erfType = 0;
       PFDI_INT(hfdi)->perf->fError = TRUE;
-      SetLastError(ERROR_FILE_NOT_FOUND);
-      return FALSE;
+      goto bail_and_fail;
     }
-  
-    /* paste the path and filename together */
-    idx = 0;
-    if (pathlen) {
-      for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
-      if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
+
+    if (mii.folder_resv > 0)
+      PFDI_SEEK(hfdi, cabhf, mii.folder_resv, SEEK_CUR);
+
+    fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
+    if (!fol) {
+      ERR("out of memory!\n");
+      PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
+      PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
+      PFDI_INT(hfdi)->perf->fError = TRUE;
+      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      goto bail_and_fail;
     }
-    if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
-    fullpath[idx] = '\0';
-  
-    TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
-  
-    /* get a handle to the cabfile */
-    cabhf = PFDI_OPEN(hfdi, fullpath, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
-    if (cabhf == -1) {
-      PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
-      PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
+    ZeroMemory(fol, sizeof(struct fdi_folder));
+    if (!CAB(firstfol)) CAB(firstfol) = fol;
+
+    fol->offset[0]  = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
+    fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
+    fol->comp_type  = EndGetI16(buf+cffold_CompType);
+
+    if (linkfol)
+      linkfol->next = fol; 
+    linkfol = fol;
+  }
+
+  /* read files */
+  for (i = 0; i < fdici.cFiles; i++) {
+    if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
+      PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
+      PFDI_INT(hfdi)->perf->erfType = 0;
       PFDI_INT(hfdi)->perf->fError = TRUE;
-      SetLastError(ERROR_FILE_NOT_FOUND);
-      return FALSE;
+      goto bail_and_fail;
     }
-  
-    /* check if it's really a cabfile. Note that this doesn't implement the bug */
-    if (!FDI_read_entries(hfdi, cabhf, &fdici, &mii)) {
-      ERR("FDIIsCabinet failed.\n");
-      PFDI_CLOSE(hfdi, cabhf);
-      return FALSE;
+
+    file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
+    if (!file) { 
+      ERR("out of memory!\n"); 
+      PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
+      PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
+      PFDI_INT(hfdi)->perf->fError = TRUE;
+      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      goto bail_and_fail;
     }
-     
-    /* cabinet notification */
-    ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
-    fdin.setID = fdici.setID;
-    fdin.iCabinet = fdici.iCabinet;
-    fdin.pv = pvUser;
-    fdin.psz1 = (mii.nextname) ? mii.nextname : &emptystring;
-    fdin.psz2 = (mii.nextinfo) ? mii.nextinfo : &emptystring;
-    fdin.psz3 = pszCabPath;
+    ZeroMemory(file, sizeof(struct fdi_file));
+    if (!CAB(firstfile)) CAB(firstfile) = file;
+      
+    file->length   = EndGetI32(buf+cffile_UncompressedSize);
+    file->offset   = EndGetI32(buf+cffile_FolderOffset);
+    file->index    = EndGetI16(buf+cffile_FolderIndex);
+    file->time     = EndGetI16(buf+cffile_Time);
+    file->date     = EndGetI16(buf+cffile_Date);
+    file->attribs  = EndGetI16(buf+cffile_Attribs);
+    file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
 
-    if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
-      PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
+    if (!file->filename) {
+      PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
       PFDI_INT(hfdi)->perf->erfType = 0;
       PFDI_INT(hfdi)->perf->fError = TRUE;
       goto bail_and_fail;
     }
 
-    /* read folders */
-    for (i = 0; i < fdici.cFolders; i++) {
-      if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
-        PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
-        PFDI_INT(hfdi)->perf->erfType = 0;
-        PFDI_INT(hfdi)->perf->fError = TRUE;
-        goto bail_and_fail;
-      }
+    if (linkfile)
+      linkfile->next = file;
+    linkfile = file;
+  }
 
-      if (mii.folder_resv > 0)
-        PFDI_SEEK(hfdi, cabhf, mii.folder_resv, SEEK_CUR);
+  for (file = CAB(firstfile); (file); file = file->next) {
+    /* partial file notification (do it just once for the first cabinet) */
+    if (initialcab && ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV)) {
+      /* OK, more MS bugs to simulate here, I think.  I don't have a huge spanning
+       * cabinet to test this theory on ATM, but here's the deal.  The SDK says that we
+       * are supposed to notify the user of the filename and "disk name" (info) of
+       * the cabinet where the spanning file /started/.  That would certainly be convenient
+       * for the consumer, who could decide to abort everything and try to start over with
+       * that cabinet so as not to create a front-truncated output file.  Note that this
+       * task would be a horrible bitch from the implementor's (wine's) perspective: the
+       * information is associated nowhere with the file header and is not to be found in
+       * the cabinet header.  So we would have to open the previous cabinet, and check
+       * if it contains a single spanning file that's continued from yet another prior cabinet,
+       * and so-on, until we find the beginning.  Note that cabextract.c has code to do exactly
+       * this.  Luckily, MS clearly didn't implement this logic, so we don't have to either.
+       * Watching the callbacks (and debugmsg +file) clearly shows that they don't open
+       * the preceeding cabinet -- and therefore, I deduce, there is NO WAY they could
+       * have implemented what's in the spec.  Instead, they are obviously just returning
+       * the previous cabinet and it's info from the header of this cabinet.  So we shall
+       * do the same.  Of course, I could be missing something...
+       */
+      ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
+      fdin.pv = pvUser;
+      fdin.psz1 = (char *)file->filename;
+      fdin.psz2 = (mii.prevname) ? mii.prevname : &emptystring;
+      fdin.psz3 = (mii.previnfo) ? mii.previnfo : &emptystring;
 
-      fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
-      if (!fol) {
-        ERR("out of memory!\n");
-        PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
-        PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
+      if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
+        PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
+        PFDI_INT(hfdi)->perf->erfType = 0;
         PFDI_INT(hfdi)->perf->fError = TRUE;
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         goto bail_and_fail;
       }
-      ZeroMemory(fol, sizeof(struct fdi_folder));
-      if (!firstfol) firstfol = fol;
-
-      fol->offset[0]  = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
-      fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
-      fol->comp_type  = EndGetI16(buf+cffold_CompType);
-
-      if (linkfol)
-        linkfol->next = fol; 
-      linkfol = fol;
+      /* I don't think we are supposed to decompress partial files */
+      file->oppressed = TRUE;
     }
-
-    /* read files */
-    for (i = 0; i < fdici.cFiles; i++) {
-      if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
-        PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
+    if (file->oppressed) {
+      filehf = 0;
+    } else {
+      /* fdintCOPY_FILE notification (TODO: skip for spanning cab's we already should have hf) */
+      ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
+      fdin.pv = pvUser;
+      fdin.psz1 = (char *)file->filename;
+      fdin.cb = file->length;
+      fdin.date = file->date;
+      fdin.time = file->time;
+      fdin.attribs = file->attribs;
+      if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
+        PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
         PFDI_INT(hfdi)->perf->erfType = 0;
         PFDI_INT(hfdi)->perf->fError = TRUE;
         goto bail_and_fail;
       }
+    }
 
-      file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
-      if (!file) { 
-        ERR("out of memory!\n"); 
-        PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
-        PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
-        PFDI_INT(hfdi)->perf->fError = TRUE;
-        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        goto bail_and_fail;
-      }
-      ZeroMemory(file, sizeof(struct fdi_file));
-      if (!firstfile) firstfile = file;
-        
-      file->length   = EndGetI32(buf+cffile_UncompressedSize);
-      file->offset   = EndGetI32(buf+cffile_FolderOffset);
-      file->index    = EndGetI16(buf+cffile_FolderIndex);
-      file->time     = EndGetI16(buf+cffile_Time);
-      file->date     = EndGetI16(buf+cffile_Date);
-      file->attribs  = EndGetI16(buf+cffile_Attribs);
-      file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
-  
-      if (!file->filename) {
-        PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
-        PFDI_INT(hfdi)->perf->erfType = 0;
-        PFDI_INT(hfdi)->perf->fError = TRUE;
-        goto bail_and_fail;
+    if (filehf) {
+      cab_UWORD comptype = fol->comp_type;
+      int ct1 = comptype & cffoldCOMPTYPE_MASK;
+      int err = 0;
+
+      TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
+
+      /* set up decomp_state (unneccesary?); at least 
+         ignore trailing three pointers in the struct */
+      ZeroMemory(decomp_state, sizeof(fdi_decomp_state) - sizeof(void*) * 3);
+      CAB(hfdi) = hfdi;
+      CAB(filehf) = filehf;
+      CAB(cabhf) = cabhf;
+      CAB(current) = file->folder;
+      CAB(block_resv) = mii.block_resv;
+
+      /* set up the appropriate decompressor */
+      switch (ct1) {
+        case cffoldCOMPTYPE_NONE:
+          CAB(decompress) = NONEfdi_decomp;
+          break;
+        case cffoldCOMPTYPE_MSZIP:
+          CAB(decompress) = ZIPfdi_decomp;
+          break;
+        case cffoldCOMPTYPE_QUANTUM:
+          CAB(decompress) = QTMfdi_decomp;
+          err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
+          break;
+        case cffoldCOMPTYPE_LZX:
+          CAB(decompress) = LZXfdi_decomp;
+          err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
+          break;
+        default:
+          err = DECR_DATAFORMAT;
       }
-  
-      if (linkfile)
-        linkfile->next = file;
-      linkfile = file;
-    }
 
-    for (file = firstfile; (file); file = file->next) {
-      /* partial file notification (do it just once for the first cabinet) */
-      if (initialcab && ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV)) {
-        /* OK, more MS bugs to simulate here, I think.  I don't have a huge spanning
-         * cabinet to test this theory on ATM, but here's the deal.  The SDK says that we
-         * are supposed to notify the user of the filename and "disk name" (info) of
-         * the cabinet where the spanning file /started/.  That would certainly be convenient
-         * for the consumer, who could decide to abort everything and try to start over with
-         * that cabinet so as not to create a front-truncated output file.  Note that this
-         * task would be a horrible bitch from the implementor's (wine's) perspective: the
-         * information is associated nowhere with the file header and is not to be found in
-         * the cabinet header.  So we would have to open the previous cabinet, and check
-         * if it contains a single spanning file that's continued from yet another prior cabinet,
-         * and so-on, until we find the beginning.  Note that cabextract.c has code to do exactly
-         * this.  Luckily, MS clearly didn't implement this logic, so we don't have to either.
-         * Watching the callbacks (and debugmsg +file) clearly shows that they don't open
-         * the preceeding cabinet -- and therefore, I deduce, there is NO WAY they could
-         * have implemented what's in the spec.  Instead, they are obviously just returning
-         * the previous cabinet and it's info from the header of this cabinet.  So we shall
-         * do the same.  Of course, I could be missing something...
-         */
-        ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
-        fdin.pv = pvUser;
-        fdin.psz1 = (char *)file->filename;
-        fdin.psz2 = (mii.prevname) ? mii.prevname : &emptystring;
-        fdin.psz3 = (mii.previnfo) ? mii.previnfo : &emptystring;
-  
-        if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
-          PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
-          PFDI_INT(hfdi)->perf->erfType = 0;
+      switch (err) {
+        case DECR_OK:
+          break;
+        case DECR_NOMEMORY:
+          PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
+          PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
           PFDI_INT(hfdi)->perf->fError = TRUE;
+          SetLastError(ERROR_NOT_ENOUGH_MEMORY);
           goto bail_and_fail;
-        }
-        /* I don't think we are supposed to decompress partial files */
-        file->oppressed = TRUE;
-      }
-      if (file->oppressed) {
-        filehf = 0;
-      } else {
-        /* fdintCOPY_FILE notification (TODO: skip for spanning cab's we already should have hf) */
-        ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
-        fdin.pv = pvUser;
-        fdin.psz1 = (char *)file->filename;
-        fdin.cb = file->length;
-        fdin.date = file->date;
-        fdin.time = file->time;
-        fdin.attribs = file->attribs;
-        if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
-          PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
-          PFDI_INT(hfdi)->perf->erfType = 0;
+        default:
+          PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
+          PFDI_INT(hfdi)->perf->erfOper = 0;
           PFDI_INT(hfdi)->perf->fError = TRUE;
           goto bail_and_fail;
-        }
       }
 
-      if (filehf) {
-        cab_UWORD comptype = fol->comp_type;
-        int ct1 = comptype & cffoldCOMPTYPE_MASK;
-        fdi_decomp_state _decomp_state;
-        fdi_decomp_state *decomp_state = &_decomp_state;
-        int err = 0;
-
-        TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
-
-        /* set up decomp_state */
-        ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
-        CAB(hfdi) = hfdi;
-        CAB(filehf) = filehf;
-        CAB(cabhf) = cabhf;
-        CAB(current) = file->folder;
-        CAB(block_resv) = mii.block_resv;
-
-        /* set up the appropriate decompressor */
-        switch (ct1) {
-          case cffoldCOMPTYPE_NONE:
-            CAB(decompress) = NONEfdi_decomp;
-            break;
-          case cffoldCOMPTYPE_MSZIP:
-            CAB(decompress) = ZIPfdi_decomp;
-            break;
-          case cffoldCOMPTYPE_QUANTUM:
-            CAB(decompress) = QTMfdi_decomp;
-            err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
-            break;
-          case cffoldCOMPTYPE_LZX:
-            CAB(decompress) = LZXfdi_decomp;
-            err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
-            break;
-          default:
-            err = DECR_DATAFORMAT;
-        }
+      PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset[0], SEEK_SET);
+      CAB(offset) = 0;
+      CAB(outlen) = 0;
+      CAB(split)  = 0;
 
-        switch (err) {
+      if (file->offset > CAB(offset)) {
+        /* decode bytes and send them to /dev/null */
+        switch ((err = fdi_decomp(file, 0, decomp_state))) {
           case DECR_OK:
             break;
           case DECR_NOMEMORY:
@@ -2043,119 +2071,108 @@
             PFDI_INT(hfdi)->perf->fError = TRUE;
             goto bail_and_fail;
         }
+        CAB(offset) = file->offset;
+      }
 
-        PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset[0], SEEK_SET);
-        CAB(offset) = 0;
-        CAB(outlen) = 0;
-        CAB(split)  = 0;
-
-        if (file->offset > CAB(offset)) {
-          /* decode bytes and send them to /dev/null */
-          switch ((err = fdi_decomp(file, 0, decomp_state))) {
-            case DECR_OK:
-              break;
-            case DECR_NOMEMORY:
-              PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
-              PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
-              PFDI_INT(hfdi)->perf->fError = TRUE;
-              SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-              goto bail_and_fail;
-            default:
-              PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
-              PFDI_INT(hfdi)->perf->erfOper = 0;
-              PFDI_INT(hfdi)->perf->fError = TRUE;
-              goto bail_and_fail;
-          }
-          CAB(offset) = file->offset;
-        }
-  
-        /* now do the actual decompression */
-        err = fdi_decomp(file, 1, decomp_state);
-        if (err) CAB(current) = NULL; else CAB(offset) += file->length;
-
-        switch (err) {
-          case DECR_OK:
-            break;
-          case DECR_NOMEMORY:
-            PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
-            PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
-            PFDI_INT(hfdi)->perf->fError = TRUE;
-            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            goto bail_and_fail;
-          default:
-            PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
-            PFDI_INT(hfdi)->perf->erfOper = 0;
-            PFDI_INT(hfdi)->perf->fError = TRUE;
-            goto bail_and_fail;
-        }
+      /* now do the actual decompression */
+      err = fdi_decomp(file, 1, decomp_state);
+      if (err) CAB(current) = NULL; else CAB(offset) += file->length;
 
-        /* FIXME: don't do it if we are continuing the file in another cab */
-        /* fdintCLOSE_FILE_INFO notification */
-        ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
-        fdin.pv = pvUser;
-        fdin.psz1 = (char *)file->filename;
-        fdin.hf = filehf;
-        fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE;
-        fdin.date = file->date;
-        fdin.time = file->time;
-        fdin.attribs = file->attribs;
-        err = ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
-        if (err == FALSE || err == -1) {
-          /*
-           * SDK states that even though they indicated failure,
-           * we are not supposed to try and close the file, so we
-           * just treat this like all the others
-           */
-          PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
-          PFDI_INT(hfdi)->perf->erfType = 0;
+      switch (err) {
+        case DECR_OK:
+          break;
+        case DECR_NOMEMORY:
+          PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
+          PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
           PFDI_INT(hfdi)->perf->fError = TRUE;
+          SetLastError(ERROR_NOT_ENOUGH_MEMORY);
           goto bail_and_fail;
-        }
+        default:
+          PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
+          PFDI_INT(hfdi)->perf->erfOper = 0;
+          PFDI_INT(hfdi)->perf->fError = TRUE;
+          goto bail_and_fail;
+      }
+
+      /* fdintCLOSE_FILE_INFO notification */
+      ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
+      fdin.pv = pvUser;
+      fdin.psz1 = (char *)file->filename;
+      fdin.hf = filehf;
+      fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE;
+      fdin.date = file->date;
+      fdin.time = file->time;
+      fdin.attribs = file->attribs;
+      err = ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
+      if (err == FALSE || err == -1) {
+        /*
+         * SDK states that even though they indicated failure,
+         * we are not supposed to try and close the file, so we
+         * just treat this like all the others
+         */
+        PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
+        PFDI_INT(hfdi)->perf->erfType = 0;
+        PFDI_INT(hfdi)->perf->fError = TRUE;
+        goto bail_and_fail;
       }
     }
+  }
 
-    while (firstfol) {
-      fol = firstfol;
-      firstfol = firstfol->next;
+  while (decomp_state) {
+    fdi_decomp_state *prev_fds;
+    while (CAB(firstfol)) {
+      fol = CAB(firstfol);
+      CAB(firstfol) = CAB(firstfol)->next;
       PFDI_FREE(hfdi, fol);
     }
-    while (firstfile) {
-      file = firstfile;
-      firstfile = firstfile->next;
+    while (CAB(firstfile)) {
+      file = CAB(firstfile);
+      CAB(firstfile) = CAB(firstfile)->next;
       PFDI_FREE(hfdi, file);
     }
+    prev_fds = decomp_state;
+    decomp_state = CAB(next);
+    if (prev_fds != &_decomp_state)
+      PFDI_FREE(hfdi, prev_fds);
+  }
+ 
+  /* free the storage remembered by mii */
+  if (mii.nextname) PFDI_FREE(hfdi, mii.nextname);
+  if (mii.nextinfo) PFDI_FREE(hfdi, mii.nextinfo);
+  if (mii.prevname) PFDI_FREE(hfdi, mii.prevname);
+  if (mii.previnfo) PFDI_FREE(hfdi, mii.previnfo);
 
-    /* free the storage remembered by mii */
-    if (mii.nextname) PFDI_FREE(hfdi, mii.nextname);
-    if (mii.nextinfo) PFDI_FREE(hfdi, mii.nextinfo);
-    if (mii.prevname) PFDI_FREE(hfdi, mii.prevname);
-    if (mii.previnfo) PFDI_FREE(hfdi, mii.previnfo);
-  
-    PFDI_CLOSE(hfdi, cabhf);
-    /* TODO: if (:?) */ return TRUE; /* else { ...; initialcab=FALSE; continue; } */
+  PFDI_CLOSE(hfdi, cabhf);
+  return TRUE;
 
-    bail_and_fail: /* here we free ram before error returns */
+  bail_and_fail: /* here we free ram before error returns */
 
-    while (firstfol) {
-      fol = firstfol;
-      firstfol = firstfol->next;
+  while (decomp_state) {
+    fdi_decomp_state *prev_fds;
+    while (CAB(firstfol)) {
+      fol = CAB(firstfol);
+      CAB(firstfol) = CAB(firstfol)->next;
       PFDI_FREE(hfdi, fol);
     }
-    while (firstfile) {
-      file = firstfile;
-      firstfile = firstfile->next;
+    while (CAB(firstfile)) {
+      file = CAB(firstfile);
+      CAB(firstfile) = CAB(firstfile)->next;
       PFDI_FREE(hfdi, file);
     }
-
-    /* free the storage remembered by mii */
-    if (mii.nextname) PFDI_FREE(hfdi, mii.nextname);
-    if (mii.nextinfo) PFDI_FREE(hfdi, mii.nextinfo);
-    if (mii.prevname) PFDI_FREE(hfdi, mii.prevname);
-    if (mii.previnfo) PFDI_FREE(hfdi, mii.previnfo);
-  
-    PFDI_CLOSE(hfdi, cabhf);
-    return FALSE;
+    prev_fds = decomp_state;
+    decomp_state = CAB(next);
+    if (prev_fds != &_decomp_state)
+      PFDI_FREE(hfdi, prev_fds);
   }
+
+  /* free the storage remembered by mii */
+  if (mii.nextname) PFDI_FREE(hfdi, mii.nextname);
+  if (mii.nextinfo) PFDI_FREE(hfdi, mii.nextinfo);
+  if (mii.prevname) PFDI_FREE(hfdi, mii.prevname);
+  if (mii.previnfo) PFDI_FREE(hfdi, mii.previnfo);
+
+  PFDI_CLOSE(hfdi, cabhf);
+  return FALSE;
 }
 
 /***********************************************************************
-- 
"Socialism in general has a record of failure so blatant
 that only an intellectual could ignore or evade it."
 -- Thomas Sowell

gmt




More information about the wine-patches mailing list