[CABINET] Sync with Wine Staging 3.3. CORE-14434
[reactos.git] / dll / win32 / cabinet / fdi.c
index e4959e6..01a0c4d 100644 (file)
  *   -gmt
  */
 
-#include <config.h>
+#include "config.h"
 
-//#include <stdarg.h>
+#include <stdarg.h>
 #include <stdio.h>
 
-//#include "windef.h"
-//#include "winbase.h"
-//#include "winerror.h"
-//#include "fdi.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "fdi.h"
 #include "cabinet.h"
 
-#include <wine/debug.h>
+#include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
 
@@ -500,7 +500,7 @@ static char *FDI_read_string(FDI_Int *fdi, INT_PTR hf, long cabsize)
         break;
       }
       /* The buffer is too small for the string. Reset the file to the point
-       * were we started, free the buffer and increase the size for the next try
+       * where we started, free the buffer and increase the size for the next try
        */
       fdi->seek(hf, base, SEEK_SET);
       fdi->free(buf);
@@ -536,71 +536,28 @@ static BOOL FDI_read_entries(
         PMORE_ISCAB_INFO pmii)
 {
   int num_folders, num_files, header_resv, folder_resv = 0;
-  LONG base_offset, cabsize;
+  LONG cabsize;
   USHORT setid, cabidx, flags;
   cab_UBYTE buf[64], block_resv;
   char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
 
   TRACE("(fdi == ^%p, hf == %ld, pfdici == ^%p)\n", fdi, hf, pfdici);
 
-  /* 
-   * FIXME: I just noticed that I am memorizing the initial file pointer
-   * offset and restoring it before reading in the rest of the header
-   * information in the cabinet.  Perhaps that's correct -- that is, perhaps
-   * this API is supposed to support "streaming" cabinets which are embedded
-   * in other files, or cabinets which begin at file offsets other than zero.
-   * Otherwise, I should instead go to the absolute beginning of the file.
-   * (Either way, the semantics of wine's FDICopy require me to leave the
-   * file pointer where it is afterwards -- If Windows does not do so, we
-   * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
-   * 
-   * So, the answer lies in Windows; will native cabinet.dll recognize a
-   * cabinet "file" embedded in another file?  Note that cabextract.c does
-   * support this, which implies that Microsoft's might.  I haven't tried it
-   * yet so I don't know.  ATM, most of wine's FDI cabinet routines (except
-   * this one) would not work in this way.  To fix it, we could just make the
-   * various references to absolute file positions in the code relative to an
-   * initial "beginning" offset.  Because the FDICopy API doesn't take a
-   * file-handle like this one, we would therein need to search through the
-   * file for the beginning of the cabinet (as we also do in cabextract.c).
-   * Note that this limits us to a maximum of one cabinet per. file: the first.
-   *
-   * So, in summary: either the code below is wrong, or the rest of fdi.c is
-   * wrong... I cannot imagine that both are correct ;)  One of these flaws
-   * should be fixed after determining the behavior on Windows.   We ought
-   * to check both FDIIsCabinet and FDICopy for the right behavior.
-   *
-   * -gmt
-   */
-
-  /* get basic offset & size info */
-  base_offset = FDI_getoffset(fdi, hf);
-
-  if (fdi->seek(hf, 0, SEEK_END) == -1) {
-    if (pmii) set_error( fdi, FDIERROR_NOT_A_CABINET, 0 );
-    return FALSE;
-  }
-
-  cabsize = FDI_getoffset(fdi, hf);
-
-  if ((cabsize == -1) || (base_offset == -1) || 
-      ( fdi->seek(hf, base_offset, SEEK_SET) == -1 )) {
-    if (pmii) set_error( fdi, FDIERROR_NOT_A_CABINET, 0 );
-    return FALSE;
-  }
-
   /* read in the CFHEADER */
   if (fdi->read(hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
     if (pmii) set_error( fdi, FDIERROR_NOT_A_CABINET, 0 );
     return FALSE;
   }
-  
+
   /* check basic MSCF signature */
   if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
     if (pmii) set_error( fdi, FDIERROR_NOT_A_CABINET, 0 );
     return FALSE;
   }
 
+  /* get the cabinet size */
+  cabsize = EndGetI32(buf+cfhead_CabinetSize);
+
   /* get the number of folders */
   num_folders = EndGetI16(buf+cfhead_NumFolders);
 
@@ -745,11 +702,6 @@ BOOL __cdecl FDIIsCabinet(HFDI hfdi, INT_PTR hf, PFDICABINETINFO pfdici)
 
   if (!fdi) return FALSE;
 
-  if (!hf) {
-    SetLastError(ERROR_INVALID_HANDLE);
-    return FALSE;
-  }
-
   if (!pfdici) {
     SetLastError(ERROR_BAD_ARGUMENTS);
     return FALSE;
@@ -2041,14 +1993,14 @@ static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state
       /* outlen=0 means this block was the last contiguous part
          of a split block, continued in the next cabinet */
       if (outlen == 0) {
-        int pathlen, filenamelen, i;
+        int pathlen, filenamelen;
         INT_PTR cabhf;
         char fullpath[MAX_PATH], userpath[256];
         FDINOTIFICATION fdin;
         FDICABINETINFO fdici;
         char emptystring = '\0';
         cab_UBYTE buf2[64];
-        int success = FALSE;
+        BOOL success = FALSE;
         struct fdi_folder *fol = NULL, *linkfol = NULL; 
         struct fdi_file   *file = NULL, *linkfile = NULL;
 
@@ -2056,6 +2008,8 @@ static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state
 
         /* set up the next decomp_state... */
         if (!(cab->next)) {
+          unsigned int i;
+
           if (!cab->mii.hasnext) return DECR_INPUT;
 
           if (!((cab->next = CAB(fdi)->alloc(sizeof(fdi_decomp_state)))))
@@ -2096,11 +2050,24 @@ static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state
             fullpath[0] = '\0';
             if (pathlen) {
               strcpy(fullpath, userpath);
+#ifdef __REACTOS__
+              if (fullpath[pathlen - 1] == '\\')
+                fullpath[pathlen - 1] = '\0';
+#else
               if (fullpath[pathlen - 1] != '\\')
                 strcat(fullpath, "\\");
+#endif
             }
+#ifdef __REACTOS__
+            if (filenamelen) {
+              strcat(fullpath, "\\");
+#else
             if (filenamelen)
+#endif
               strcat(fullpath, cab->mii.nextname);
+#ifdef __REACTOS__
+            }
+#endif
 
             TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
 
@@ -2542,7 +2509,7 @@ BOOL __cdecl FDICopy(
   fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
   fdin.psz3 = pszCabPath;
 
-  if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
+  if (pfnfdin(fdintCABINET_INFO, &fdin) == -1) {
     set_error( fdi, FDIERROR_USER_ABORT, 0 );
     goto bail_and_fail;
   }
@@ -2628,7 +2595,7 @@ BOOL __cdecl FDICopy(
      * where all the cabinet files needed for decryption are simultaneously
      * available.  But presumably, the API is supposed to support cabinets which
      * are split across multiple CDROMS; we may need to change our implementation
-     * to strictly serialize it's file usage so that it opens only one cabinet
+     * to strictly serialize its file usage so that it opens only one cabinet
      * at a time.  Some experimentation with Windows is needed to figure out the
      * precise semantics required.  The relevant code is here and in fdi_decomp().
      */
@@ -2659,8 +2626,8 @@ BOOL __cdecl FDICopy(
        * if we imagine parallelized access to the FDICopy API.
        *
        * The current implementation punts -- it just returns the previous cabinet and
-       * it's info from the header of this cabinet.  This provides the right answer in
-       * 95% of the cases; its worth checking if Microsoft cuts the same corner before
+       * its info from the header of this cabinet.  This provides the right answer in
+       * 95% of the cases; it's worth checking if Microsoft cuts the same corner before
        * we "fix" it.
        */
       ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
@@ -2669,7 +2636,7 @@ BOOL __cdecl FDICopy(
       fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
       fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
 
-      if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
+      if (pfnfdin(fdintPARTIAL_FILE, &fdin) == -1) {
         set_error( fdi, FDIERROR_USER_ABORT, 0 );
         goto bail_and_fail;
       }
@@ -2686,6 +2653,7 @@ BOOL __cdecl FDICopy(
       fdin.date = file->date;
       fdin.time = file->time;
       fdin.attribs = file->attribs;
+      fdin.iFolder = file->index;
       if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
         set_error( fdi, FDIERROR_USER_ABORT, 0 );
         filehf = 0;
@@ -2695,13 +2663,13 @@ BOOL __cdecl FDICopy(
 
     /* find the folder for this file if necc. */
     if (filehf) {
-      int i2;
-
       fol = CAB(firstfol);
       if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
         /* pick the last folder */
         while (fol->next) fol = fol->next;
       } else {
+        unsigned int i2;
+
         for (i2 = 0; (i2 < file->index); i2++)
           if (fol->next) /* bug resistance, should always be true */
             fol = fol->next;
@@ -2811,6 +2779,7 @@ BOOL __cdecl FDICopy(
       fdin.date = file->date;
       fdin.time = file->time;
       fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
+      fdin.iFolder = file->index;
       ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
       filehf = 0;