mirror of
https://github.com/reactos/reactos.git
synced 2025-04-20 20:36:35 +00:00
Sync to Wine-0_9_9:
Gerold J. Wucherpfennig <gjwucherpfennig@gmx.net> - cabinet: Set proper error information on failures. Sync to Wine-0_9_6: James Hawkins <truiken@gmail.com> - cabinet: Implement Extract on top of FDI. - cabinet: Clean up the documentation for Extract. - cabinet: Fix the second parameter name of Extract. - cabinet: Add documentation for FDITruncateCabinet. - cabinet: Store the cab file handle before extracting files so we can close the cab file even if no files are extracted. - cabinet: Move the remaining cabextract.c functions to fdi.c. - cabinet: Add initial tests for Extract. - cabinet: Add the two flags used by Extract to cabinet.h. - cabinet: Define the flags member of the EXTRACTdest structure. svn path=/trunk/; revision=21610
This commit is contained in:
parent
1888104b32
commit
2122478f7b
7 changed files with 774 additions and 2938 deletions
File diff suppressed because it is too large
Load diff
|
@ -340,6 +340,7 @@ typedef struct {
|
|||
cab_ULONG sizeFileCFFILE2;
|
||||
cab_ULONG sizeFileCFFOLDER;
|
||||
BOOL fNewPrevious;
|
||||
cab_ULONG estimatedCabinetSize;
|
||||
} FCI_Int, *PFCI_Int;
|
||||
|
||||
typedef struct {
|
||||
|
@ -613,6 +614,10 @@ static const cab_UWORD Zipmask[17] = {
|
|||
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff \
|
||||
}
|
||||
|
||||
/* EXTRACTdest flags */
|
||||
#define EXTRACT_FILLFILELIST 0x00000001
|
||||
#define EXTRACT_EXTRACTFILES 0x00000002
|
||||
|
||||
struct ExtractFileList {
|
||||
LPSTR filename;
|
||||
struct ExtractFileList *next;
|
||||
|
@ -625,14 +630,13 @@ typedef struct {
|
|||
long unknown1[3]; /* 0x004 */
|
||||
struct ExtractFileList *filelist; /* 0x010 */
|
||||
long filecount; /* 0x014 */
|
||||
long unknown2; /* 0x018 */
|
||||
DWORD flags; /* 0x018 */
|
||||
char directory[0x104]; /* 0x01c */
|
||||
char lastfile[0x20c]; /* 0x120 */
|
||||
} EXTRACTdest;
|
||||
|
||||
|
||||
/* from cabextract.c */
|
||||
BOOL process_cabinet(LPCSTR cabname, LPCSTR dir, BOOL fix, BOOL lower, EXTRACTdest *dest);
|
||||
/* from fdi.c */
|
||||
void QTMupdatemodel(struct QTMmodel *model, int sym);
|
||||
int make_decode_table(cab_ULONG nsyms, cab_ULONG nbits, cab_UBYTE *length, cab_UWORD *table);
|
||||
cab_ULONG checksum(cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum);
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
<library>kernel32</library>
|
||||
<library>advapi32</library>
|
||||
<library>iphlpapi</library>
|
||||
<file>cabextract.c</file>
|
||||
<file>cabinet_main.c</file>
|
||||
<file>fci.c</file>
|
||||
<file>fdi.c</file>
|
||||
|
|
|
@ -37,6 +37,14 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
|
||||
|
||||
/* the following defintions are copied from msvcrt/fcntl.h */
|
||||
|
||||
#define _O_RDONLY 0
|
||||
#define _O_WRONLY 1
|
||||
#define _O_RDWR 2
|
||||
#define _O_ACCMODE (_O_RDONLY|_O_WRONLY|_O_RDWR)
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* DllGetVersion (CABINET.2)
|
||||
*
|
||||
|
@ -66,70 +74,259 @@ HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
/* FDI callback functions */
|
||||
|
||||
static void *mem_alloc(ULONG cb)
|
||||
{
|
||||
return HeapAlloc(GetProcessHeap(), 0, cb);
|
||||
}
|
||||
|
||||
static void mem_free(void *memory)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, memory);
|
||||
}
|
||||
|
||||
static INT_PTR fdi_open(char *pszFile, int oflag, int pmode)
|
||||
{
|
||||
HANDLE handle;
|
||||
DWORD dwAccess = 0;
|
||||
DWORD dwShareMode = 0;
|
||||
DWORD dwCreateDisposition = OPEN_EXISTING;
|
||||
|
||||
switch (oflag & _O_ACCMODE)
|
||||
{
|
||||
case _O_RDONLY:
|
||||
dwAccess = GENERIC_READ;
|
||||
dwShareMode = FILE_SHARE_READ | FILE_SHARE_DELETE;
|
||||
break;
|
||||
case _O_WRONLY:
|
||||
dwAccess = GENERIC_WRITE;
|
||||
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||
break;
|
||||
case _O_RDWR:
|
||||
dwAccess = GENERIC_READ | GENERIC_WRITE;
|
||||
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
|
||||
dwCreateDisposition = OPEN_EXISTING;
|
||||
else
|
||||
dwCreateDisposition = CREATE_NEW;
|
||||
|
||||
handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
|
||||
dwCreateDisposition, 0, NULL);
|
||||
|
||||
return (INT_PTR) handle;
|
||||
}
|
||||
|
||||
static UINT fdi_read(INT_PTR hf, void *pv, UINT cb)
|
||||
{
|
||||
HANDLE handle = (HANDLE) hf;
|
||||
DWORD dwRead;
|
||||
|
||||
if (ReadFile(handle, pv, cb, &dwRead, NULL))
|
||||
return dwRead;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT fdi_write(INT_PTR hf, void *pv, UINT cb)
|
||||
{
|
||||
HANDLE handle = (HANDLE) hf;
|
||||
DWORD dwWritten;
|
||||
|
||||
if (WriteFile(handle, pv, cb, &dwWritten, NULL))
|
||||
return dwWritten;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fdi_close(INT_PTR hf)
|
||||
{
|
||||
HANDLE handle = (HANDLE) hf;
|
||||
return CloseHandle(handle) ? 0 : -1;
|
||||
}
|
||||
|
||||
static long fdi_seek(INT_PTR hf, long dist, int seektype)
|
||||
{
|
||||
HANDLE handle = (HANDLE) hf;
|
||||
return SetFilePointer(handle, dist, NULL, seektype);
|
||||
}
|
||||
|
||||
static void fill_file_node(struct ExtractFileList *pNode, LPSTR szFilename)
|
||||
{
|
||||
pNode->next = NULL;
|
||||
pNode->unknown = TRUE;
|
||||
|
||||
pNode->filename = HeapAlloc(GetProcessHeap(), 0, strlen(szFilename) + 1);
|
||||
lstrcpyA(pNode->filename, szFilename);
|
||||
}
|
||||
|
||||
static BOOL file_in_list(struct ExtractFileList *pNode, LPSTR szFilename)
|
||||
{
|
||||
while (pNode)
|
||||
{
|
||||
if (!lstrcmpiA(pNode->filename, szFilename))
|
||||
return TRUE;
|
||||
|
||||
pNode = pNode->next;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static INT_PTR fdi_notify_extract(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
|
||||
{
|
||||
switch (fdint)
|
||||
{
|
||||
case fdintCOPY_FILE:
|
||||
{
|
||||
struct ExtractFileList **fileList;
|
||||
EXTRACTdest *pDestination = pfdin->pv;
|
||||
LPSTR szFullPath, szDirectory;
|
||||
HANDLE hFile = 0;
|
||||
DWORD dwSize;
|
||||
|
||||
dwSize = lstrlenA(pDestination->directory) +
|
||||
lstrlenA("\\") + lstrlenA(pfdin->psz1) + 1;
|
||||
szFullPath = HeapAlloc(GetProcessHeap(), 0, dwSize);
|
||||
|
||||
lstrcpyA(szFullPath, pDestination->directory);
|
||||
lstrcatA(szFullPath, "\\");
|
||||
lstrcatA(szFullPath, pfdin->psz1);
|
||||
|
||||
/* pull out the destination directory string from the full path */
|
||||
dwSize = strrchr(szFullPath, '\\') - szFullPath + 1;
|
||||
szDirectory = HeapAlloc(GetProcessHeap(), 0, dwSize);
|
||||
lstrcpynA(szDirectory, szFullPath, dwSize);
|
||||
|
||||
if (pDestination->flags & EXTRACT_FILLFILELIST)
|
||||
{
|
||||
fileList = &pDestination->filelist;
|
||||
|
||||
while (*fileList)
|
||||
fileList = &((*fileList)->next);
|
||||
|
||||
*fileList = HeapAlloc(GetProcessHeap(), 0,
|
||||
sizeof(struct ExtractFileList));
|
||||
|
||||
fill_file_node(*fileList, pfdin->psz1);
|
||||
lstrcpyA(pDestination->lastfile, szFullPath);
|
||||
pDestination->filecount++;
|
||||
}
|
||||
|
||||
if (pDestination->flags & EXTRACT_EXTRACTFILES)
|
||||
{
|
||||
/* skip this file it it's not in the file list */
|
||||
if (!file_in_list(pDestination->filelist, pfdin->psz1))
|
||||
return 0;
|
||||
|
||||
/* create the destination directory if it doesn't exist */
|
||||
if (GetFileAttributesA(szDirectory) == INVALID_FILE_ATTRIBUTES)
|
||||
CreateDirectoryA(szDirectory, NULL);
|
||||
|
||||
hFile = CreateFileA(szFullPath, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
hFile = 0;
|
||||
}
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, szFullPath);
|
||||
HeapFree(GetProcessHeap(), 0, szDirectory);
|
||||
|
||||
return (INT_PTR) hFile;
|
||||
}
|
||||
|
||||
case fdintCLOSE_FILE_INFO:
|
||||
{
|
||||
FILETIME ft;
|
||||
FILETIME ftLocal;
|
||||
HANDLE handle = (HANDLE) pfdin->hf;
|
||||
|
||||
if (!DosDateTimeToFileTime(pfdin->date, pfdin->time, &ft))
|
||||
return FALSE;
|
||||
|
||||
if (!LocalFileTimeToFileTime(&ft, &ftLocal))
|
||||
return FALSE;
|
||||
|
||||
if (!SetFileTime(handle, &ftLocal, 0, &ftLocal))
|
||||
return FALSE;
|
||||
|
||||
CloseHandle(handle);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Extract (CABINET.3)
|
||||
*
|
||||
* Apparently an undocumented function, presumably to extract a CAB file
|
||||
* to somewhere...
|
||||
* Extracts the contents of the cabinet file to the specified
|
||||
* destination.
|
||||
*
|
||||
* PARAMS
|
||||
* dest pointer to a buffer of 0x32c bytes containing
|
||||
* [I] - number with value 1 at index 0x18
|
||||
* - the dest path starting at index 0x1c
|
||||
* [O] - a linked list with the filename existing inside the
|
||||
* CAB file at idx 0x10
|
||||
* - the number of files inside the CAB file at index 0x14
|
||||
* - the name of the last file with dest path at idx 0x120
|
||||
* what [I] char* describing what to uncompress, I guess.
|
||||
* dest [I/O] Controls the operation of Extract. See NOTES.
|
||||
* szCabName [I] Filename of the cabinet to extract.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: S_OK
|
||||
* Failure: E_OUTOFMEMORY (?)
|
||||
* Success: S_OK.
|
||||
* Failure: E_FAIL.
|
||||
*
|
||||
* NOTES
|
||||
* The following members of the dest struct control the operation
|
||||
* of Extract:
|
||||
* filelist [I] A linked list of filenames. Extract only extracts
|
||||
* files from the cabinet that are in this list.
|
||||
* filecount [O] Contains the number of files in filelist on
|
||||
* completion.
|
||||
* flags [I] See Operation.
|
||||
* directory [I] The destination directory.
|
||||
* lastfile [O] The last file extracted.
|
||||
*
|
||||
* Operation
|
||||
* If flags contains EXTRACT_FILLFILELIST, then filelist will be
|
||||
* filled with all the files in the cabinet. If flags contains
|
||||
* EXTRACT_EXTRACTFILES, then only the files in the filelist will
|
||||
* be extracted from the cabinet. EXTRACT_FILLFILELIST can be called
|
||||
* by itself, but EXTRACT_EXTRACTFILES must have a valid filelist
|
||||
* in order to succeed. If flags contains both EXTRACT_FILLFILELIST
|
||||
* and EXTRACT_EXTRACTFILES, then all the files in the cabinet
|
||||
* will be extracted.
|
||||
*/
|
||||
HRESULT WINAPI Extract(EXTRACTdest *dest, LPCSTR what)
|
||||
HRESULT WINAPI Extract(EXTRACTdest *dest, LPCSTR szCabName)
|
||||
{
|
||||
#define DUMPC(idx) idx >= sizeof(EXTRACTdest) ? ' ' : \
|
||||
((unsigned char*) dest)[idx] >= 0x20 ? \
|
||||
((unsigned char*) dest)[idx] : '.'
|
||||
HRESULT res = S_OK;
|
||||
HFDI hfdi;
|
||||
ERF erf;
|
||||
|
||||
#define DUMPH(idx) idx >= sizeof(EXTRACTdest) ? 0x55 : ((unsigned char*) dest)[idx]
|
||||
TRACE("(%p, %s)\n", dest, szCabName);
|
||||
|
||||
LPSTR dir;
|
||||
unsigned int i;
|
||||
hfdi = FDICreate(mem_alloc,
|
||||
mem_free,
|
||||
fdi_open,
|
||||
fdi_read,
|
||||
fdi_write,
|
||||
fdi_close,
|
||||
fdi_seek,
|
||||
cpuUNKNOWN,
|
||||
&erf);
|
||||
|
||||
TRACE("(dest == %0lx, what == %s)\n", (long) dest, debugstr_a(what));
|
||||
|
||||
if (!dest) {
|
||||
/* win2k will crash here */
|
||||
FIXME("called without valid parameter dest!\n");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
for (i=0; i < sizeof(EXTRACTdest); i+=8)
|
||||
TRACE( "dest[%04x]:%02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c\n",
|
||||
i,
|
||||
DUMPH(i+0), DUMPH(i+1), DUMPH(i+2), DUMPH(i+3),
|
||||
DUMPH(i+4), DUMPH(i+5), DUMPH(i+6), DUMPH(i+7),
|
||||
DUMPC(i+0), DUMPC(i+1), DUMPC(i+2), DUMPC(i+3),
|
||||
DUMPC(i+4), DUMPC(i+5), DUMPC(i+6), DUMPC(i+7));
|
||||
|
||||
dir = LocalAlloc(LPTR, strlen(dest->directory)+1);
|
||||
if (!dir) return E_OUTOFMEMORY;
|
||||
lstrcpyA(dir, dest->directory);
|
||||
dest->filecount=0;
|
||||
dest->filelist = NULL;
|
||||
|
||||
TRACE("extracting to dir: %s\n", debugstr_a(dir));
|
||||
|
||||
/* FIXME: what to do on failure? */
|
||||
if (!process_cabinet(what, dir, FALSE, FALSE, dest)) {
|
||||
LocalFree(dir);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
LocalFree(dir);
|
||||
|
||||
TRACE("filecount %08lx,lastfile %s\n",
|
||||
dest->filecount, debugstr_a(dest->lastfile));
|
||||
if (!hfdi)
|
||||
return E_FAIL;
|
||||
|
||||
if (GetFileAttributesA(dest->directory) == INVALID_FILE_ATTRIBUTES)
|
||||
return S_OK;
|
||||
|
||||
if (!FDICopy(hfdi, (LPSTR)szCabName, "", 0,
|
||||
fdi_notify_extract, NULL, dest))
|
||||
res = E_FAIL;
|
||||
|
||||
FDIDestroy(hfdi);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -148,6 +148,169 @@ typedef struct fdi_cds_fwd {
|
|||
struct fdi_cds_fwd *next;
|
||||
} fdi_decomp_state;
|
||||
|
||||
/****************************************************************
|
||||
* QTMupdatemodel (internal)
|
||||
*/
|
||||
void QTMupdatemodel(struct QTMmodel *model, int sym) {
|
||||
struct QTMmodelsym temp;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < sym; i++) model->syms[i].cumfreq += 8;
|
||||
|
||||
if (model->syms[0].cumfreq > 3800) {
|
||||
if (--model->shiftsleft) {
|
||||
for (i = model->entries - 1; i >= 0; i--) {
|
||||
/* -1, not -2; the 0 entry saves this */
|
||||
model->syms[i].cumfreq >>= 1;
|
||||
if (model->syms[i].cumfreq <= model->syms[i+1].cumfreq) {
|
||||
model->syms[i].cumfreq = model->syms[i+1].cumfreq + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
model->shiftsleft = 50;
|
||||
for (i = 0; i < model->entries ; i++) {
|
||||
/* no -1, want to include the 0 entry */
|
||||
/* this converts cumfreqs into frequencies, then shifts right */
|
||||
model->syms[i].cumfreq -= model->syms[i+1].cumfreq;
|
||||
model->syms[i].cumfreq++; /* avoid losing things entirely */
|
||||
model->syms[i].cumfreq >>= 1;
|
||||
}
|
||||
|
||||
/* now sort by frequencies, decreasing order -- this must be an
|
||||
* inplace selection sort, or a sort with the same (in)stability
|
||||
* characteristics
|
||||
*/
|
||||
for (i = 0; i < model->entries - 1; i++) {
|
||||
for (j = i + 1; j < model->entries; j++) {
|
||||
if (model->syms[i].cumfreq < model->syms[j].cumfreq) {
|
||||
temp = model->syms[i];
|
||||
model->syms[i] = model->syms[j];
|
||||
model->syms[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* then convert frequencies back to cumfreq */
|
||||
for (i = model->entries - 1; i >= 0; i--) {
|
||||
model->syms[i].cumfreq += model->syms[i+1].cumfreq;
|
||||
}
|
||||
/* then update the other part of the table */
|
||||
for (i = 0; i < model->entries; i++) {
|
||||
model->tabloc[model->syms[i].sym] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* make_decode_table (internal)
|
||||
*
|
||||
* This function was coded by David Tritscher. It builds a fast huffman
|
||||
* decoding table out of just a canonical huffman code lengths table.
|
||||
*
|
||||
* PARAMS
|
||||
* nsyms: total number of symbols in this huffman tree.
|
||||
* nbits: any symbols with a code length of nbits or less can be decoded
|
||||
* in one lookup of the table.
|
||||
* length: A table to get code lengths from [0 to syms-1]
|
||||
* table: The table to fill up with decoded symbols and pointers.
|
||||
*
|
||||
* RETURNS
|
||||
* OK: 0
|
||||
* error: 1
|
||||
*/
|
||||
int make_decode_table(cab_ULONG nsyms, cab_ULONG nbits, cab_UBYTE *length, cab_UWORD *table) {
|
||||
register cab_UWORD sym;
|
||||
register cab_ULONG leaf;
|
||||
register cab_UBYTE bit_num = 1;
|
||||
cab_ULONG fill;
|
||||
cab_ULONG pos = 0; /* the current position in the decode table */
|
||||
cab_ULONG table_mask = 1 << nbits;
|
||||
cab_ULONG bit_mask = table_mask >> 1; /* don't do 0 length codes */
|
||||
cab_ULONG next_symbol = bit_mask; /* base of allocation for long codes */
|
||||
|
||||
/* fill entries for codes short enough for a direct mapping */
|
||||
while (bit_num <= nbits) {
|
||||
for (sym = 0; sym < nsyms; sym++) {
|
||||
if (length[sym] == bit_num) {
|
||||
leaf = pos;
|
||||
|
||||
if((pos += bit_mask) > table_mask) return 1; /* table overrun */
|
||||
|
||||
/* fill all possible lookups of this symbol with the symbol itself */
|
||||
fill = bit_mask;
|
||||
while (fill-- > 0) table[leaf++] = sym;
|
||||
}
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
bit_num++;
|
||||
}
|
||||
|
||||
/* if there are any codes longer than nbits */
|
||||
if (pos != table_mask) {
|
||||
/* clear the remainder of the table */
|
||||
for (sym = pos; sym < table_mask; sym++) table[sym] = 0;
|
||||
|
||||
/* give ourselves room for codes to grow by up to 16 more bits */
|
||||
pos <<= 16;
|
||||
table_mask <<= 16;
|
||||
bit_mask = 1 << 15;
|
||||
|
||||
while (bit_num <= 16) {
|
||||
for (sym = 0; sym < nsyms; sym++) {
|
||||
if (length[sym] == bit_num) {
|
||||
leaf = pos >> 16;
|
||||
for (fill = 0; fill < bit_num - nbits; fill++) {
|
||||
/* if this path hasn't been taken yet, 'allocate' two entries */
|
||||
if (table[leaf] == 0) {
|
||||
table[(next_symbol << 1)] = 0;
|
||||
table[(next_symbol << 1) + 1] = 0;
|
||||
table[leaf] = next_symbol++;
|
||||
}
|
||||
/* follow the path and select either left or right for next bit */
|
||||
leaf = table[leaf] << 1;
|
||||
if ((pos >> (15-fill)) & 1) leaf++;
|
||||
}
|
||||
table[leaf] = sym;
|
||||
|
||||
if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
|
||||
}
|
||||
}
|
||||
bit_mask >>= 1;
|
||||
bit_num++;
|
||||
}
|
||||
}
|
||||
|
||||
/* full table? */
|
||||
if (pos == table_mask) return 0;
|
||||
|
||||
/* either erroneous table, or all elements are 0 - let's find out. */
|
||||
for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* checksum (internal)
|
||||
*/
|
||||
cab_ULONG checksum(cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum) {
|
||||
int len;
|
||||
cab_ULONG ul = 0;
|
||||
|
||||
for (len = bytes >> 2; len--; data += 4) {
|
||||
csum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
|
||||
}
|
||||
|
||||
switch (bytes & 3) {
|
||||
case 3: ul |= *data++ << 16;
|
||||
case 2: ul |= *data++ << 8;
|
||||
case 1: ul |= *data;
|
||||
}
|
||||
csum ^= ul;
|
||||
|
||||
return csum;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* FDICreate (CABINET.20)
|
||||
*
|
||||
|
@ -2370,6 +2533,7 @@ BOOL __cdecl FDICopy(
|
|||
|
||||
CAB(setID) = fdici.setID;
|
||||
CAB(iCabinet) = fdici.iCabinet;
|
||||
CAB(cabhf) = cabhf;
|
||||
|
||||
/* read folders */
|
||||
for (i = 0; i < fdici.cFolders; i++) {
|
||||
|
@ -2554,7 +2718,6 @@ BOOL __cdecl FDICopy(
|
|||
/* set up decomp_state */
|
||||
CAB(hfdi) = hfdi;
|
||||
CAB(filehf) = filehf;
|
||||
CAB(cabhf) = cabhf;
|
||||
|
||||
/* Was there a change of folder? Compression type? Did we somehow go backwards? */
|
||||
if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
|
||||
|
@ -2819,7 +2982,21 @@ BOOL __cdecl FDIDestroy(HFDI hfdi)
|
|||
/***********************************************************************
|
||||
* FDITruncateCabinet (CABINET.24)
|
||||
*
|
||||
* Undocumented and unimplemented.
|
||||
* Removes all folders of a cabinet file after and including the
|
||||
* specified folder number.
|
||||
*
|
||||
* PARAMS
|
||||
* hfdi [I] Handle to the FDI context.
|
||||
* pszCabinetName [I] Filename of the cabinet.
|
||||
* iFolderToDelete [I] Index of the first folder to delete.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: TRUE.
|
||||
* Failure: FALSE.
|
||||
*
|
||||
* NOTES
|
||||
* The PFNWRITE function supplied to FDICreate must truncate the
|
||||
* file at the current position if the number of bytes to write is 0.
|
||||
*/
|
||||
BOOL __cdecl FDITruncateCabinet(
|
||||
HFDI hfdi,
|
||||
|
|
|
@ -38,7 +38,7 @@ reactos/tools/widl # Forked at Wine-20050930
|
|||
The following libraries are shared with Wine.
|
||||
|
||||
reactos/dll/win32/avifil32 # Synced to Wine-0_9_5
|
||||
reactos/dll/win32/cabinet # Synced to Wine-0_9_5
|
||||
reactos/dll/win32/cabinet # Synced to Wine-0_9_10
|
||||
reactos/dll/win32/comctl32 # Synced to Wine-20060328
|
||||
reactos/dll/win32/comdlg32 # Synced to Wine-0_9_5
|
||||
reactos/dll/win32/crypt32 # Synced to Wine-0_9_5
|
||||
|
|
Loading…
Reference in a new issue