|
|
/*
* FDIDLL.C -- FDI interface using CABINET.DLL * * Copyright (C) Microsoft Corporation 1997 * All Rights Reserved. * * Overview: * This code is a wrapper which provides access to the actual FDI code * in CABINET.DLL. CABINET.DLL dynamically loads/unloads as needed. */
#include "pch.hpp"
#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <appdefs.h>
#include "fdi.h"
static HINSTANCE hCabinetDll = NULL; /* DLL module handle */
/* pointers to the functions in the DLL */ typedef HFDI (FAR DIAMONDAPI *PFNFDICREATE)( PFNALLOC pfnalloc, PFNFREE pfnfree, PFNOPEN pfnopen, PFNREAD pfnread, PFNWRITE pfnwrite, PFNCLOSE pfnclose, PFNSEEK pfnseek, int cpuType, PERF perf);
static PFNFDICREATE pfnFDICreate = NULL;
typedef BOOL (FAR DIAMONDAPI *PFNFDIIsCabinet)( HFDI hfdi, int hf, PFDICABINETINFO pfdici);
static PFNFDIIsCabinet pfnFDIIsCabinet = NULL;
typedef BOOL (FAR DIAMONDAPI *PFNFDICopy)( HFDI hfdi, CHAR *pszCabinet, CHAR *pszCabPath, int flags, PFNFDINOTIFY pfnfdin, PFNFDIDECRYPT pfnfdid, void *pvUser);
static PFNFDICopy pfnFDICopy = NULL;
typedef BOOL (FAR DIAMONDAPI *PFNFDIDestroy)( HFDI hfdi);
static PFNFDIDestroy pfnFDIDestroy = NULL;
/*
* FDICreate -- Create an FDI context * * See fdi.h for entry/exit conditions. */
HFDI FAR DIAMONDAPI FDICreate(PFNALLOC pfnalloc, PFNFREE pfnfree, PFNOPEN pfnopen, PFNREAD pfnread, PFNWRITE pfnwrite, PFNCLOSE pfnclose, PFNSEEK pfnseek, int cpuType, PERF perf) { HFDI hfdi;
if ( hCabinetDll != NULL ) { goto gotEntryPoints; }
hCabinetDll = LoadLibraryA("CABINET"); if (hCabinetDll == NULL) { return(NULL); }
pfnFDICreate = (PFNFDICREATE) GetProcAddress(hCabinetDll, "FDICreate"); pfnFDICopy = (PFNFDICopy) GetProcAddress(hCabinetDll, "FDICopy"); pfnFDIIsCabinet = (PFNFDIIsCabinet) GetProcAddress(hCabinetDll, "FDIIsCabinet"); pfnFDIDestroy = (PFNFDIDestroy) GetProcAddress(hCabinetDll, "FDIDestroy");
if ((pfnFDICreate == NULL) || (pfnFDICopy == NULL) || (pfnFDIIsCabinet == NULL) || (pfnFDIDestroy == NULL)) { FreeLibrary(hCabinetDll); hCabinetDll = NULL; return(NULL); }
gotEntryPoints: hfdi = pfnFDICreate(pfnalloc, pfnfree, pfnopen, pfnread,pfnwrite,pfnclose,pfnseek,cpuType,perf); if (hfdi == NULL) { FreeLibrary(hCabinetDll); hCabinetDll = NULL; }
return(hfdi); }
/*
* FDIIsCabinet -- Determines if file is a cabinet, returns info if it is * * See fdi.h for entry/exit conditions. */
BOOL FAR DIAMONDAPI FDIIsCabinet(HFDI hfdi, int hf, PFDICABINETINFO pfdici) { if (pfnFDIIsCabinet == NULL) { return(FALSE); }
return(pfnFDIIsCabinet(hfdi, hf,pfdici)); }
/*
* FDICopy -- extracts files from a cabinet * * See fdi.h for entry/exit conditions. */
BOOL FAR DIAMONDAPI FDICopy(HFDI hfdi, CHAR *pszCabinet, CHAR *pszCabPath, int flags, PFNFDINOTIFY pfnfdin, PFNFDIDECRYPT pfnfdid, void *pvUser) { if (pfnFDICopy == NULL) { return(FALSE); }
return(pfnFDICopy(hfdi, pszCabinet,pszCabPath,flags,pfnfdin,pfnfdid,pvUser)); }
/*
* FDIDestroy -- Destroy an FDI context * * See fdi.h for entry/exit conditions. */
BOOL FAR DIAMONDAPI FDIDestroy(HFDI hfdi) { BOOL rc;
if (pfnFDIDestroy == NULL) { return(FALSE); }
rc = pfnFDIDestroy(hfdi);
return(rc); }
/*
* Memory allocation function */ FNALLOC(mem_alloc) { return new BYTE[cb]; }
/*
* Memory free function */ FNFREE(mem_free) { delete pv; }
FNOPEN(file_open) { return _open(pszFile, oflag, pmode); }
FNREAD(file_read) { return _read(hf, pv, cb); }
FNWRITE(file_write) { return _write(hf, pv, cb); }
FNCLOSE(file_close) { return _close(hf); }
FNSEEK(file_seek) { return _lseek(hf, dist, seektype); }
FNFDINOTIFY(notification_function) { switch (fdint) { case fdintCABINET_INFO: // general information about the cabinet
#if 0
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 ); #endif
return 0;
case fdintPARTIAL_FILE: // first file in cabinet is continuation
#if 0
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 ); #endif
return 0;
case fdintCOPY_FILE: // file to be copied
{ int handle; #if 0
int response;
printf( "fdintCOPY_FILE\n" " file name in cabinet = %s\n" " uncompressed file size = %d\n" " copy this file? (y/n): ", pfdin->psz1, pfdin->cb ); #endif
handle = file_open( pfdin->psz1, _O_BINARY | _O_CREAT | _O_WRONLY | _O_SEQUENTIAL | _O_TRUNC, _S_IREAD | _S_IWRITE );
return handle; }
case fdintCLOSE_FILE_INFO: // close the file, set relevant info
{ #if 0
HANDLE handle; DWORD attrs; CHAR destination[256];
printf( "fdintCLOSE_FILE_INFO\n" " file name in cabinet = %s\n" "\n", pfdin->psz1 ); #endif
file_close(pfdin->hf);
return TRUE; }
case fdintNEXT_CABINET: // file continued to next cabinet
#if 0
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 ); #endif
return 0; }
return 0; }
HRESULT HandleCab(LPSTR cabinet_fullpath) { ERF erf; HFDI hfdi; int hf; FDICABINETINFO fdici; CHAR *p; CHAR cabinet_name[MAX_PATH+1]; CHAR cabinet_path[256]; CHAR szCurrentDirectory[MAX_PATH]; CHAR szdrive[_MAX_DRIVE]; CHAR szPathName[_MAX_PATH]; // This will be the dir we need to create
CHAR szdir[_MAX_DIR]; CHAR szfname[_MAX_FNAME]; CHAR szext[_MAX_EXT]; CHAR szcabinet_fullpath[MAX_PATH+1]; HRESULT err = S_OK;
lstrcpyA(szcabinet_fullpath, cabinet_fullpath);
if (GetCurrentDirectoryA(sizeof(szCurrentDirectory), szCurrentDirectory)) { // Split the provided path to get at the drive and path portion
_splitpath( szcabinet_fullpath, szdrive, szdir, szfname, szext ); wsprintfA(szPathName, "%s%s", szdrive, szdir);
// Set the directory to where the cab is
if (!SetCurrentDirectoryA(szPathName)) { return(GetLastError()); } } else { return(GetLastError()); }
do { hfdi = FDICreate(mem_alloc, mem_free, file_open, file_read, file_write, file_close, file_seek, cpuUNKNOWN, &erf);
if (hfdi == NULL) { err = -1; break; }
/*
* Is this file really a cabinet? */ hf = file_open( szcabinet_fullpath, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0 );
if (hf == -1) { (void) FDIDestroy(hfdi);
// Error Opening the file
err = -2; break;
}
if (FALSE == FDIIsCabinet( hfdi, hf, &fdici)) { /*
* No, it's not a cabinet! */ _close(hf);
(void) FDIDestroy(hfdi); err = -3; break;
} else { _close(hf); }
p = strrchr(szcabinet_fullpath, '\\');
if (p == NULL) { lstrcpyA(cabinet_name, szcabinet_fullpath); lstrcpyA(cabinet_path, ""); } else { lstrcpyA(cabinet_name, ++p); // Need to make space for the null-terminator that lstrcpyn adds
lstrcpynA(cabinet_path, szcabinet_fullpath, (int) (p-szcabinet_fullpath)+1); }
if (TRUE != FDICopy( hfdi, cabinet_name, cabinet_path, 0, notification_function, NULL, NULL)) { // Extract Failed.
(void) FDIDestroy(hfdi); err = -4; break; }
if (FDIDestroy(hfdi) != TRUE) {
// why in the world would the context destroy fail ?
err = -5; break;
}
break; } while(1 );
// Set the directory back to the original place
if (!SetCurrentDirectoryA(szCurrentDirectory)) return(GetLastError());
return err; }
void CleanupCabHandler() { if (hCabinetDll != NULL) { FreeLibrary(hCabinetDll); } }
|