|
|
/*
* 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 "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_PTR 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 = LoadLibrary(TEXT("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_PTR 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((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
#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 response; INT_PTR handle;
#if 0
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
{ HANDLE handle; DWORD attrs; char destination[256];
#if 0
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(LPTSTR cabinet_fullpath) { ERF erf; HFDI hfdi; INT_PTR hf; FDICABINETINFO fdici; char *p; char cabinet_name[256]; 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;
#ifdef UNICODE
wcstombs(szcabinet_fullpath, cabinet_fullpath, MAX_PATH+1); #else
lstrcpy(szcabinet_fullpath, cabinet_fullpath); #endif
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((int)hf);
(void) FDIDestroy(hfdi); err = -3; break; } else { _close((int)hf); }
p = strrchr(szcabinet_fullpath, '\\');
if (p == NULL) { lstrcpynA(cabinet_name, szcabinet_fullpath, ARRAYSIZE(cabinet_name)); lstrcpyA(cabinet_path, ""); } else { lstrcpyA(cabinet_name, p+1);
strncpy(cabinet_path, szcabinet_fullpath, (int) (p-szcabinet_fullpath)+1); cabinet_path[ (int) (p-szcabinet_fullpath)+1 ] = 0; }
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); } }
|