|
|
/*++
Copyright (c) 1991-1999, Microsoft Corporation All rights reserved.
Module Name:
diamond.c
Abstract:
Implement File Decompression Interface -FDI- for Cabinet files.
Revision History:
04-20-1999 SamerA Created.
--*/
#include "muisetup.h"
#include <io.h>
#include <fcntl.h>
#include <dos.h>
#include <sys/stat.h>
#define STRSAFE_LIB
#include <strsafe.h>
//
// Module Global Variables
//
//
// Cabinet DLL handle
HINSTANCE hCabinetDll; HFDI ghfdi; // diamond FDI context
//
// DLL Function pointers
//
typedef HFDI (DIAMONDAPI *PFNFDICREATE)( PFNALLOC pfnalloc, PFNFREE pfnfree, PFNOPEN pfnopen, PFNREAD pfnread, PFNWRITE pfnwrite, PFNCLOSE pfnclose, PFNSEEK pfnseek, int cpuType, PERF perf);
typedef BOOL (DIAMONDAPI *PFNFDIISCABINET)( HFDI hfdi, INT_PTR hf, PFDICABINETINFO pfdici);
typedef BOOL (DIAMONDAPI *PFNFDICOPY)( HFDI hfdi, char *pszCabinet, char *pszCabPath, int flags, PFNFDINOTIFY pfnfdin, PFNFDIDECRYPT pfnfdid, void *pvUser);
typedef BOOL (DIAMONDAPI *PFNFDIDESTROY)( HFDI hfdi);
PFNFDICREATE pfnFDICreate; PFNFDICOPY pfnFDICopy; PFNFDIISCABINET pfnFDIIsCabinet; PFNFDIDESTROY pfnFDIDestroy;
//-------------------------------------------------------------------------//
// FDI EXTERNAL ROUTINES //
//-------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////
//
// FDICreate
//
// Tries to create an FDI context. Will load cabinet.dll and hook necessary
// function pointers.
//
// 04-20-99 SamerA Created.
////////////////////////////////////////////////////////////////////////////
HFDI DIAMONDAPI FDICreate( PFNALLOC pfnalloc, PFNFREE pfnfree, PFNOPEN pfnopen, PFNREAD pfnread, PFNWRITE pfnwrite, PFNCLOSE pfnclose, PFNSEEK pfnseek, int cpuType, PERF perf) { HFDI hfdi;
//
// Load cabinet DLL
//
hCabinetDll = LoadLibrary(TEXT("CABINET.DLL")); if (hCabinetDll == NULL) { return NULL; }
//
// Hook function pointers
//
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 ); return NULL; }
//
// Try to create an FDI context
//
hfdi = pfnFDICreate( pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek, cpuType, perf); if (hfdi == NULL) { FreeLibrary(hCabinetDll); }
return hfdi; }
////////////////////////////////////////////////////////////////////////////
//
// FDIIsCabinet
//
// Determines if file is a cabinet, returns info if it is
//
// 04-20-99 SamerA Created.
////////////////////////////////////////////////////////////////////////////
BOOL 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
//
// 04-20-99 SamerA Created.
////////////////////////////////////////////////////////////////////////////
BOOL 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. Should be called when you're done with the HFDI.
//
// 04-20-99 SamerA Created.
////////////////////////////////////////////////////////////////////////////
BOOL DIAMONDAPI FDIDestroy( HFDI hfdi) { BOOL bRet;
if (pfnFDIDestroy == NULL) { return FALSE; }
bRet = pfnFDIDestroy( hfdi ); if (bRet == TRUE) { FreeLibrary(hCabinetDll); }
return bRet; }
//-------------------------------------------------------------------------//
// FDI SUPPORT ROUTINES //
//-------------------------------------------------------------------------//
PVOID DIAMONDAPI DiamondMemAlloc( IN ULONG NumberOfBytes ) { return ((PVOID)LocalAlloc(LMEM_FIXED, NumberOfBytes)); }
VOID DIAMONDAPI DiamondMemFree( IN PVOID Block ) { if (Block) { LocalFree( (HLOCAL)Block ); } }
INT_PTR DIAMONDAPI DiamondFileOpen( IN PSTR FileName, IN int oflag, IN int pmode ) { HFILE h; int OpenMode;
if (oflag & _O_WRONLY) { OpenMode = OF_WRITE; } else { if (oflag & _O_RDWR) { OpenMode = OF_READWRITE; } else { OpenMode = OF_READ; } }
h = _lopen(FileName, OpenMode | OF_SHARE_DENY_WRITE);
if (h == HFILE_ERROR) { return -1; }
return ((INT_PTR) h); }
UINT DIAMONDAPI DiamondFileRead( IN INT_PTR Handle, OUT PVOID pv, IN UINT ByteCount ) { UINT rc;
rc = _lread((HFILE)Handle, pv, ByteCount);
if (rc == HFILE_ERROR) { rc = (UINT)(-1); }
return rc; }
UINT DIAMONDAPI DiamondFileWrite( IN INT_PTR Handle, IN PVOID pv, IN UINT ByteCount ) { UINT rc;
rc = _lwrite((HFILE)Handle, (LPCSTR)pv, ByteCount);
return rc; }
int DIAMONDAPI DiamondFileClose( IN INT_PTR Handle ) { _lclose( (HFILE)Handle ); return 0; }
LONG DIAMONDAPI DiamondFileSeek( IN INT_PTR Handle, IN long Distance, IN int SeekType ) { LONG rc;
rc = _llseek((HFILE)Handle, Distance, SeekType);
if (rc == HFILE_ERROR) { rc = -1L; }
return rc; }
INT_PTR DIAMONDAPI DiamondNotifyFunction( IN FDINOTIFICATIONTYPE Operation, IN PFDINOTIFICATION Parameters ) { HRESULT hresult; switch (Operation) { case fdintCABINET_INFO: // general information about the cabinet
return 0; break;
case fdintPARTIAL_FILE: // first file in cabinet is continuation
return 0; break;
case fdintCOPY_FILE: // file to be copied
{ HFILE handle; char destination[256]; PDIAMOND_PACKET pDiamond = (PDIAMOND_PACKET) Parameters->pv;
//
// Check to see if we just want the original file name
//
if (pDiamond->flags & DIAMOND_GET_DEST_FILE_NAME) { //*STRSAFE* strcpy( pDiamond->szDestFilePath, Parameters->psz1 );
hresult = StringCchCopyA(pDiamond->szDestFilePath , ARRAYSIZE(pDiamond->szDestFilePath), Parameters->psz1 ); if (!SUCCEEDED(hresult)) { return -1; } return 0; }
//*STRSAFE* sprintf( destination, "%s%s", pDiamond->szDestFilePath, Parameters->psz1 );
hresult = StringCchPrintfA(destination , ARRAYSIZE(destination), "%s%s", pDiamond->szDestFilePath, Parameters->psz1 ); if (!SUCCEEDED(hresult)) { return -1; }
handle = _lcreat(destination, 0);
if (handle == HFILE_ERROR) { return -1; }
return handle; } break;
case fdintCLOSE_FILE_INFO: // close the file, set relevant info
{ HANDLE handle; DWORD attrs; char destination[256]; PDIAMOND_PACKET pDiamond = (PDIAMOND_PACKET) Parameters->pv;
if (pDiamond->flags & DIAMOND_GET_DEST_FILE_NAME) { return 0; }
//*STRSAFE* sprintf( destination, "%s%s", pDiamond->szDestFilePath, Parameters->psz1);
hresult = StringCchPrintfA(destination , ARRAYSIZE(destination), "%s%s", pDiamond->szDestFilePath, Parameters->psz1); if (!SUCCEEDED(hresult)) { return -1; }
_lclose( (HFILE)Parameters->hf );
//
// Set date/time
//
// Need Win32 type handle for to set date/time
//
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( Parameters->date, Parameters->time, &datetime)) { FILETIME local_filetime;
if (TRUE == LocalFileTimeToFileTime( &datetime, &local_filetime)) { SetFileTime( handle, &local_filetime, NULL, &local_filetime ); } }
CloseHandle(handle); }
//
// Mask out attribute bits other than readonly,
// hidden, system, and archive, since the other
// attribute bits are reserved for use by
// the cabinet format.
//
attrs = Parameters->attribs;
attrs &= (_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH);
SetFileAttributesA( destination, attrs );
return TRUE; } break;
case fdintNEXT_CABINET: // file continued to next cabinet
return 0; break; }
return 0; }
//-------------------------------------------------------------------------//
// MUISETUP-SUPPORT ROUTINES //
//-------------------------------------------------------------------------//
////////////////////////////////////////////////////////////////////////////
//
// Muisetup_InitDiamond
//
// Initialize diamond DLL.
//
// 04-23-99 SamerA Created.
////////////////////////////////////////////////////////////////////////////
HFDI Muisetup_InitDiamond() { ERF erf;
if (!ghfdi) { ghfdi = FDICreate( DiamondMemAlloc, DiamondMemFree, DiamondFileOpen, DiamondFileRead, DiamondFileWrite, DiamondFileClose, DiamondFileSeek, cpuUNKNOWN, &erf ); }
return ghfdi; }
////////////////////////////////////////////////////////////////////////////
//
// Muisetup_FreeDiamond
//
// Free diamond dll. Should be called at application shutdown.
//
// 04-23-99 SamerA Created.
////////////////////////////////////////////////////////////////////////////
BOOL Muisetup_FreeDiamond() { BOOL bRet = TRUE;
if (ghfdi) { bRet = FDIDestroy(ghfdi); }
return bRet; }
////////////////////////////////////////////////////////////////////////////
//
// Muisetup_DiamondReset
//
// Should be called at the start of processing a file to copy.
//
// 04-23-99 SamerA Created.
////////////////////////////////////////////////////////////////////////////
void Muisetup_DiamondReset( PDIAMOND_PACKET pDiamond) { pDiamond->flags = DIAMOND_NONE;
return; }
////////////////////////////////////////////////////////////////////////////
//
// Muisetup_IsDiamondFile
//
// Determines if a file is a diamond file, and if so, returns its original
// name.
//
// 04-23-99 SamerA Created.
////////////////////////////////////////////////////////////////////////////
BOOL Muisetup_IsDiamondFile( PWSTR pwszFileName, PWSTR pwszOriginalName, INT nSize, PDIAMOND_PACKET pDiamond) { INT_PTR hf; BOOL bRet; int nCount; char *p; FDICABINETINFO fdici; HFDI hfdi = ghfdi; HRESULT hresult;
if (!hfdi) { #if SAMER_DBG
OutputDebugStringA("Muisetup_IsDiamondFile : No HFDI context\n"); #endif
return FALSE; }
//
// Init the diamond packet
//
pDiamond->flags = DIAMOND_NONE;
if ((nCount = WideCharToMultiByte( CP_ACP, 0, pwszFileName, -1, pDiamond->szSrcFilePath, sizeof( pDiamond->szSrcFilePath ), NULL, NULL )) == 0) { #if SAMER_DBG
OutputDebugStringA("Muisetup_IsDiamondFile : WideCharToMultiByte failed\n"); #endif
return FALSE; } pDiamond->szSrcFilePath[ nCount ] = '\0';
hf = DiamondFileOpen( pDiamond->szSrcFilePath, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0 );
if (hf == -1) { #if SAMER_DBG
OutputDebugStringA("Muisetup_IsDiamondFile : file_open failed\n"); #endif
return FALSE; }
bRet = FDIIsCabinet( hfdi, hf, &fdici );
DiamondFileClose( hf );
//
// If succeeded, then let's setup everything else
// to get the correct original file name
//
if (bRet) { pDiamond->flags |= DIAMOND_GET_DEST_FILE_NAME;
p = strrchr(pDiamond->szSrcFilePath, '\\');
if (p == NULL) { //*STRSAFE* strcpy(pDiamond->szSrcFileName, pDiamond->szSrcFilePath);
hresult = StringCchCopyA(pDiamond->szSrcFileName , ARRAYSIZE(pDiamond->szSrcFileName), pDiamond->szSrcFilePath); if (!SUCCEEDED(hresult)) { return FALSE; } //*STRSAFE* strcpy(pDiamond->szSrcFilePath, "");
hresult = StringCchCopyA(pDiamond->szSrcFilePath , ARRAYSIZE(pDiamond->szSrcFilePath), ""); if (!SUCCEEDED(hresult)) { return FALSE; } } else { //*STRSAFE* strcpy(pDiamond->szSrcFileName, p+1);
hresult = StringCchCopyA(pDiamond->szSrcFileName , ARRAYSIZE(pDiamond->szSrcFileName), p+1); if (!SUCCEEDED(hresult)) { return FALSE; } p[ 1 ] = '\0'; }
//*STRSAFE* strcpy( pDiamond->szDestFilePath, "c:\\samer\\" );
hresult = StringCchCopyA(pDiamond->szDestFilePath , ARRAYSIZE(pDiamond->szDestFilePath), "c:\\samer\\" ); if (!SUCCEEDED(hresult)) { return FALSE; }
if (Muisetup_CopyDiamondFile( pDiamond, NULL)) { //
// Convert the original file name back to Unicode
//
nCount = MultiByteToWideChar( CP_ACP, 0, pDiamond->szDestFilePath, -1, pwszOriginalName, nSize );
if (!nCount) { return FALSE; }
pwszOriginalName[ nCount ] = UNICODE_NULL; pDiamond->flags = DIAMOND_FILE; #if SAMER_DBG
{ BYTE byBuf[200];
//*STRSAFE* wsprintfA(byBuf, "SrcFile = %s%s, OriginalFileName=%s\n", pDiamond->szSrcFilePath, pDiamond->szSrcFileName,pDiamond->szDestFilePath);
hresult = StringCchPrintfA(byBuf , ARRAYSIZE(byBuf), "SrcFile = %s%s, OriginalFileName=%s\n", pDiamond->szSrcFilePath, pDiamond->szSrcFileName,pDiamond->szDestFilePath); if (!SUCCEEDED(hresult)) { return FALSE; } OutputDebugStringA(byBuf); } #endif
}
pDiamond->flags &= ~DIAMOND_GET_DEST_FILE_NAME; }
return bRet; }
////////////////////////////////////////////////////////////////////////////
//
// Muisetup_CopyDiamondFile
//
// Copies and expands a diamond file.
//
// 04-23-99 SamerA Created.
////////////////////////////////////////////////////////////////////////////
BOOL Muisetup_CopyDiamondFile( PDIAMOND_PACKET pDiamond, PWSTR pwszCopyTo) { char szDestPath[ MAX_PATH + 1]; char *p; int nCount; BOOL bRet; HFDI hfdi = ghfdi; HRESULT hresult;
//
// Validate that this is a diamond file
//
if ((!hfdi) || (pDiamond->flags == DIAMOND_NONE)) { return FALSE; }
//
// Validate flags
//
if (!(pDiamond->flags & (DIAMOND_FILE | DIAMOND_GET_DEST_FILE_NAME))) { return FALSE; }
#if SAMER_DBG
{ BYTE byBuf[100]; //*STRSAFE* wsprintfA(byBuf, "DiamondCopy called for %s, flags = %lx\n", pDiamond->szSrcFileName, pDiamond->flags);
hresult = StringCchPrintfA(byBuf , ARRAYSIZE(byBuf), "DiamondCopy called for %s, flags = %lx\n", pDiamond->szSrcFileName, pDiamond->flags); if (!SUCCEEDED(hresult)) { return FALSE; } OutputDebugStringA(byBuf); } #endif
if (!(pDiamond->flags & DIAMOND_GET_DEST_FILE_NAME)) { if ((nCount = WideCharToMultiByte( CP_ACP, 0, pwszCopyTo, -1, szDestPath, sizeof( szDestPath ), NULL, NULL )) == 0) { return FALSE; }
p = strrchr(szDestPath, '\\'); if (p) { p[1] = '\0'; } else { szDestPath[ nCount ] = '\\'; szDestPath[ nCount + 1 ] = '\0'; }
//*STRSAFE* strcpy( pDiamond->szDestFilePath, szDestPath );
hresult = StringCchCopyA(pDiamond->szDestFilePath , ARRAYSIZE(pDiamond->szDestFilePath), szDestPath ); if (!SUCCEEDED(hresult)) { return FALSE; } }
bRet = FDICopy( hfdi, pDiamond->szSrcFileName, pDiamond->szSrcFilePath, 0, DiamondNotifyFunction, NULL, pDiamond);
#if SAMER_DBG
{ BYTE byBuf[200];
//*STRSAFE* wsprintfA(byBuf, "SrcFile = %s%s, DestPath=%s, Status=%lx\n", pDiamond->szSrcFilePath,pDiamond->szSrcFileName,pDiamond->szDestFilePath, bRet);
hresult = StringCchPrintfA(byBuf , ARRAYSIZE(byBuf), "SrcFile = %s%s, DestPath=%s, Status=%lx\n", pDiamond->szSrcFilePath,pDiamond->szSrcFileName,pDiamond->szDestFilePath, bRet); if (!SUCCEEDED(hresult)) { return FALSE; } OutputDebugStringA(byBuf); } #endif
return bRet; }
|