From 50c6965c7801ad761a3bdb8b247340584a576b52 Mon Sep 17 00:00:00 2001 From: "Gregory M. Turner" <gmturner007@ameritech.net> Date: Mon, 23 Jun 2003 18:10:47 +0000 Subject: [PATCH] - 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. --- dlls/cabinet/fdi.c | 603 +++++++++++++++++++++++---------------------- 1 file changed, 310 insertions(+), 293 deletions(-) diff --git a/dlls/cabinet/fdi.c b/dlls/cabinet/fdi.c index f8f1b3c076e..f2673014fea 100644 --- a/dlls/cabinet/fdi.c +++ b/dlls/cabinet/fdi.c @@ -93,6 +93,9 @@ typedef struct fdi_cds_fwd { 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 @@ BOOL __cdecl FDICopy( 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 @@ BOOL __cdecl FDICopy( 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; - - if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) { - PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT; + 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 (!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 (mii.folder_resv > 0) - PFDI_SEEK(hfdi, cabhf, mii.folder_resv, SEEK_CUR); + if (linkfile) + linkfile->next = file; + linkfile = file; + } - 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; + 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; + + 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 @@ BOOL __cdecl FDICopy( 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; + /* 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; - } - - /* 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); + + PFDI_CLOSE(hfdi, cabhf); + return TRUE; - /* 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; } */ - - 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; } /*********************************************************************** -- GitLab