471 lines
9.2 KiB
C++
471 lines
9.2 KiB
C++
|
//#include <stdio.h>
|
||
|
//
|
||
|
//#include <string.h>
|
||
|
|
||
|
#include "pre.h"
|
||
|
|
||
|
#include "fdi.h"
|
||
|
#include <io.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <sys/stat.h>
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Function prototypes
|
||
|
*/
|
||
|
BOOL fdi(char *cabinet_file, char *dir);
|
||
|
int get_percentage(unsigned long a, unsigned long b);
|
||
|
char *return_fdi_error_string(int err);
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Destination directory for extracted files
|
||
|
*/
|
||
|
char dest_dir[256];
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Memory allocation function
|
||
|
*/
|
||
|
FNALLOC(mem_alloc)
|
||
|
{
|
||
|
return malloc(cb);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Memory free function
|
||
|
*/
|
||
|
FNFREE(mem_free)
|
||
|
{
|
||
|
free(pv);
|
||
|
}
|
||
|
|
||
|
|
||
|
FNOPEN(file_open)
|
||
|
{
|
||
|
return _open(pszFile, oflag, pmode);
|
||
|
}
|
||
|
|
||
|
|
||
|
FNREAD(file_read)
|
||
|
{
|
||
|
return _read((int)hf, pv, cb);
|
||
|
}
|
||
|
|
||
|
|
||
|
FNWRITE(file_write)
|
||
|
{
|
||
|
return _write((int)hf, pv, cb);
|
||
|
}
|
||
|
|
||
|
|
||
|
FNCLOSE(file_close)
|
||
|
{
|
||
|
return _close((int)hf);
|
||
|
}
|
||
|
|
||
|
|
||
|
FNSEEK(file_seek)
|
||
|
{
|
||
|
return _lseek((int)hf, dist, seektype);
|
||
|
}
|
||
|
|
||
|
|
||
|
FNFDINOTIFY(notification_function)
|
||
|
{
|
||
|
switch (fdint)
|
||
|
{
|
||
|
case fdintCABINET_INFO: // general information about the cabinet
|
||
|
/*
|
||
|
printf(
|
||
|
"fdintCABINET_INFO\n"
|
||
|
" next cabinet = %s\n"
|
||
|
" next disk = %s\n"
|
||
|
" cabinet path = %s\n"
|
||
|
" cabinet set ID = %d\n"
|
||
|
" cabinet # in set = %d (zero based)\n"
|
||
|
"\n",
|
||
|
pfdin->psz1,
|
||
|
pfdin->psz2,
|
||
|
pfdin->psz3,
|
||
|
pfdin->setID,
|
||
|
pfdin->iCabinet
|
||
|
);
|
||
|
*/
|
||
|
return 0;
|
||
|
|
||
|
case fdintPARTIAL_FILE: // first file in cabinet is continuation
|
||
|
/*
|
||
|
printf(
|
||
|
"fdintPARTIAL_FILE\n"
|
||
|
" name of continued file = %s\n"
|
||
|
" name of cabinet where file starts = %s\n"
|
||
|
" name of disk where file starts = %s\n",
|
||
|
pfdin->psz1,
|
||
|
pfdin->psz2,
|
||
|
pfdin->psz3
|
||
|
);
|
||
|
*/
|
||
|
return 0;
|
||
|
|
||
|
case fdintCOPY_FILE: // file to be copied
|
||
|
{
|
||
|
INT_PTR handle;
|
||
|
//int response;
|
||
|
char destination[256];
|
||
|
/*
|
||
|
printf(
|
||
|
"fdintCOPY_FILE\n"
|
||
|
" file name in cabinet = %s\n"
|
||
|
" uncompressed file size = %d\n"
|
||
|
" copy this file? (y/n): ",
|
||
|
pfdin->psz1,
|
||
|
pfdin->cb
|
||
|
);
|
||
|
|
||
|
do
|
||
|
{
|
||
|
response = getc(stdin);
|
||
|
response = toupper(response);
|
||
|
} while (response != 'Y' && response != 'N');
|
||
|
|
||
|
printf("\n");
|
||
|
|
||
|
if (response == 'Y')
|
||
|
{
|
||
|
sprintf(
|
||
|
destination,
|
||
|
"%s%s",
|
||
|
dest_dir,
|
||
|
pfdin->psz1
|
||
|
);
|
||
|
|
||
|
handle = file_open(
|
||
|
destination,
|
||
|
_O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL,
|
||
|
_S_IREAD | _S_IWRITE
|
||
|
);
|
||
|
|
||
|
return handle;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
*/
|
||
|
sprintf(
|
||
|
destination,
|
||
|
"%s%s",
|
||
|
dest_dir,
|
||
|
pfdin->psz1
|
||
|
);
|
||
|
|
||
|
handle = file_open(
|
||
|
destination,
|
||
|
_O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL,
|
||
|
_S_IREAD | _S_IWRITE
|
||
|
);
|
||
|
|
||
|
return handle;
|
||
|
}
|
||
|
|
||
|
case fdintCLOSE_FILE_INFO: // close the file, set relevant info
|
||
|
{
|
||
|
HANDLE handle;
|
||
|
DWORD attrs;
|
||
|
char destination[256];
|
||
|
/*
|
||
|
printf(
|
||
|
"fdintCLOSE_FILE_INFO\n"
|
||
|
" file name in cabinet = %s\n"
|
||
|
"\n",
|
||
|
pfdin->psz1
|
||
|
);
|
||
|
|
||
|
sprintf(
|
||
|
destination,
|
||
|
"%s%s",
|
||
|
dest_dir,
|
||
|
pfdin->psz1
|
||
|
);
|
||
|
*/
|
||
|
sprintf(
|
||
|
destination,
|
||
|
"%s%s",
|
||
|
dest_dir,
|
||
|
pfdin->psz1
|
||
|
);
|
||
|
file_close(pfdin->hf);
|
||
|
|
||
|
|
||
|
handle = CreateFileA(
|
||
|
destination,
|
||
|
GENERIC_READ | GENERIC_WRITE,
|
||
|
FILE_SHARE_READ,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (handle != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
FILETIME datetime;
|
||
|
|
||
|
if (TRUE == DosDateTimeToFileTime(
|
||
|
pfdin->date,
|
||
|
pfdin->time,
|
||
|
&datetime))
|
||
|
{
|
||
|
FILETIME local_filetime;
|
||
|
|
||
|
if (TRUE == LocalFileTimeToFileTime(
|
||
|
&datetime,
|
||
|
&local_filetime))
|
||
|
{
|
||
|
(void) SetFileTime(
|
||
|
handle,
|
||
|
&local_filetime,
|
||
|
NULL,
|
||
|
&local_filetime
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CloseHandle(handle);
|
||
|
}
|
||
|
|
||
|
attrs = pfdin->attribs;
|
||
|
|
||
|
attrs &= (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);
|
||
|
|
||
|
(void) SetFileAttributesA(
|
||
|
destination,
|
||
|
attrs
|
||
|
);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
case fdintNEXT_CABINET: // file continued to next cabinet
|
||
|
/*
|
||
|
printf(
|
||
|
"fdintNEXT_CABINET\n"
|
||
|
" name of next cabinet where file continued = %s\n"
|
||
|
" name of next disk where file continued = %s\n"
|
||
|
" cabinet path name = %s\n"
|
||
|
"\n",
|
||
|
pfdin->psz1,
|
||
|
pfdin->psz2,
|
||
|
pfdin->psz3
|
||
|
);
|
||
|
*/
|
||
|
return 0;
|
||
|
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL fdi(char *cabinet_fullpath, char * directory)
|
||
|
{
|
||
|
HFDI hfdi;
|
||
|
ERF erf;
|
||
|
FDICABINETINFO fdici;
|
||
|
INT_PTR hf;
|
||
|
char *p;
|
||
|
char cabinet_name[256];
|
||
|
char cabinet_path[256];
|
||
|
|
||
|
strcpy(dest_dir, directory);
|
||
|
|
||
|
hfdi = FDICreate(
|
||
|
mem_alloc,
|
||
|
mem_free,
|
||
|
file_open,
|
||
|
file_read,
|
||
|
file_write,
|
||
|
file_close,
|
||
|
file_seek,
|
||
|
cpu80386,
|
||
|
&erf
|
||
|
);
|
||
|
|
||
|
if (hfdi == NULL)
|
||
|
{
|
||
|
char szErr[255];
|
||
|
sprintf(szErr, "FDICreate() failed: code %d [%s]\n",
|
||
|
erf.erfOper, return_fdi_error_string(erf.erfOper)
|
||
|
);
|
||
|
MessageBoxA(NULL, szErr, "", MB_OK);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Is this file really a cabinet?
|
||
|
*/
|
||
|
hf = file_open(
|
||
|
cabinet_fullpath,
|
||
|
_O_BINARY | _O_RDONLY | _O_SEQUENTIAL,
|
||
|
0
|
||
|
);
|
||
|
|
||
|
if (hf == -1)
|
||
|
{
|
||
|
(void) FDIDestroy(hfdi);
|
||
|
|
||
|
char szErr[255];
|
||
|
sprintf(szErr, "Unable to open '%s' for input\n", cabinet_fullpath);
|
||
|
MessageBoxA(NULL, szErr, "", MB_OK);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (FALSE == FDIIsCabinet(
|
||
|
hfdi,
|
||
|
hf,
|
||
|
&fdici))
|
||
|
{
|
||
|
/*
|
||
|
* No, it's not a cabinet!
|
||
|
*/
|
||
|
_close((int)hf);
|
||
|
|
||
|
char szErr[255];
|
||
|
sprintf(szErr, "FDIIsCabinet() failed: '%s' is not a cabinet\n",
|
||
|
cabinet_fullpath
|
||
|
);
|
||
|
MessageBoxA(NULL, szErr, "", MB_OK);
|
||
|
|
||
|
(void) FDIDestroy(hfdi);
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_close((int)hf);
|
||
|
|
||
|
/*
|
||
|
char szErr[255];
|
||
|
sprintf(szErr, "Information on cabinet file '%s'\n"
|
||
|
" Total length of cabinet file : %d\n"
|
||
|
" Number of folders in cabinet : %d\n"
|
||
|
" Number of files in cabinet : %d\n"
|
||
|
" Cabinet set ID : %d\n"
|
||
|
" Cabinet number in set : %d\n"
|
||
|
" RESERVE area in cabinet? : %s\n"
|
||
|
" Chained to prev cabinet? : %s\n"
|
||
|
" Chained to next cabinet? : %s\n"
|
||
|
"\n",
|
||
|
cabinet_fullpath,
|
||
|
fdici.cbCabinet,
|
||
|
fdici.cFolders,
|
||
|
fdici.cFiles,
|
||
|
fdici.setID,
|
||
|
fdici.iCabinet,
|
||
|
fdici.fReserve == TRUE ? "yes" : "no",
|
||
|
fdici.hasprev == TRUE ? "yes" : "no",
|
||
|
fdici.hasnext == TRUE ? "yes" : "no"
|
||
|
);
|
||
|
MessageBox(NULL, szErr, "", MB_OK);
|
||
|
*/
|
||
|
}
|
||
|
|
||
|
p = strrchr(cabinet_fullpath, '\\');
|
||
|
|
||
|
if (p == NULL)
|
||
|
{
|
||
|
strcpy(cabinet_name, cabinet_fullpath);
|
||
|
strcpy(cabinet_path, "");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
strcpy(cabinet_name, p+1);
|
||
|
|
||
|
strncpy(cabinet_path, cabinet_fullpath, (int) (p-cabinet_fullpath)+1);
|
||
|
cabinet_path[ (int) (p-cabinet_fullpath)+1 ] = 0;
|
||
|
}
|
||
|
|
||
|
if (TRUE != FDICopy(
|
||
|
hfdi,
|
||
|
cabinet_name,
|
||
|
cabinet_path,
|
||
|
0,
|
||
|
notification_function,
|
||
|
NULL,
|
||
|
NULL))
|
||
|
{
|
||
|
char szErr[255];
|
||
|
sprintf(szErr, "FDICopy() failed: code %d [%s]\n",
|
||
|
erf.erfOper, return_fdi_error_string(erf.erfOper)
|
||
|
);
|
||
|
MessageBoxA(NULL, szErr, "", MB_OK);
|
||
|
|
||
|
(void) FDIDestroy(hfdi);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (FDIDestroy(hfdi) != TRUE)
|
||
|
{
|
||
|
char szErr[255];
|
||
|
sprintf(szErr, "FDIDestroy() failed: code %d [%s]\n",
|
||
|
erf.erfOper, return_fdi_error_string(erf.erfOper)
|
||
|
);
|
||
|
MessageBoxA(NULL, szErr, "", MB_OK);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
char *return_fdi_error_string(int err)
|
||
|
{
|
||
|
switch (err)
|
||
|
{
|
||
|
case FDIERROR_NONE:
|
||
|
return "No error";
|
||
|
|
||
|
case FDIERROR_CABINET_NOT_FOUND:
|
||
|
return "Cabinet not found";
|
||
|
|
||
|
case FDIERROR_NOT_A_CABINET:
|
||
|
return "Not a cabinet";
|
||
|
|
||
|
case FDIERROR_UNKNOWN_CABINET_VERSION:
|
||
|
return "Unknown cabinet version";
|
||
|
|
||
|
case FDIERROR_CORRUPT_CABINET:
|
||
|
return "Corrupt cabinet";
|
||
|
|
||
|
case FDIERROR_ALLOC_FAIL:
|
||
|
return "Memory allocation failed";
|
||
|
|
||
|
case FDIERROR_BAD_COMPR_TYPE:
|
||
|
return "Unknown compression type";
|
||
|
|
||
|
case FDIERROR_MDI_FAIL:
|
||
|
return "Failure decompressing data";
|
||
|
|
||
|
case FDIERROR_TARGET_FILE:
|
||
|
return "Failure writing to target file";
|
||
|
|
||
|
case FDIERROR_RESERVE_MISMATCH:
|
||
|
return "Cabinets in set have different RESERVE sizes";
|
||
|
|
||
|
case FDIERROR_WRONG_CABINET:
|
||
|
return "Cabinet returned on fdintNEXT_CABINET is incorrect";
|
||
|
|
||
|
case FDIERROR_USER_ABORT:
|
||
|
return "User aborted";
|
||
|
|
||
|
default:
|
||
|
return "Unknown error";
|
||
|
}
|
||
|
}
|