Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2398 lines
57 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
cablib.c
Abstract:
Implements wrappers for cabinet APIs
Author:
Calin Negreanu (calinn) 27-Apr-2000
Revision History:
<alias> <date> <comments>
--*/
#include "pch.h"
#include "migutilp.h"
#include <cablib.h>
#include <fci.h>
#include <fdi.h>
#include <fcntl.h>
#include <crt\sys\stat.h>
//
// Includes
//
// None
#define DBG_CABLIB "CabLib"
//
// Strings
//
// None
//
// Constants
//
#define VERIFY_HANDLE ((HANDLE) (-2))
//
// Macros
//
// None
//
// Types
//
typedef struct {
PCSTR CabPath;
PCSTR CabFileFormat;
PCSTR CabDiskFormat;
PCABGETCABINETNAMESA CabGetCabinetNames;
HFCI FciHandle;
ERF FciErrorStruct;
CCAB FciCabParams;
UINT FileCount;
UINT CabCount;
LONGLONG FileSize;
LONGLONG CompressedSize;
} FCI_CAB_HANDLEA, *PFCI_CAB_HANDLEA;
typedef struct {
PCWSTR CabPath;
PCWSTR CabFileFormat;
PCWSTR CabDiskFormat;
PCABGETCABINETNAMESW CabGetCabinetNames;
HFCI FciHandle;
ERF FciErrorStruct;
CCAB FciCabParams;
UINT FileCount;
UINT CabCount;
LONGLONG FileSize;
LONGLONG CompressedSize;
} FCI_CAB_HANDLEW, *PFCI_CAB_HANDLEW;
typedef struct {
PCSTR CabPath;
PCSTR CabFile;
HFDI FdiHandle;
ERF FdiErrorStruct;
FDICABINETINFO FdiCabinetInfo;
} FDI_CAB_HANDLEA, *PFDI_CAB_HANDLEA;
typedef struct {
PCWSTR CabPath;
PCWSTR CabFile;
HFDI FdiHandle;
ERF FdiErrorStruct;
FDICABINETINFO FdiCabinetInfo;
} FDI_CAB_HANDLEW, *PFDI_CAB_HANDLEW;
typedef struct {
PCSTR ExtractPath;
PCABNOTIFICATIONA CabNotificationA;
} CAB_DATAA, *PCAB_DATAA;
typedef struct {
PCWSTR ExtractPath;
PCABNOTIFICATIONW CabNotificationW;
BOOL VerifyMode;
} CAB_DATAW, *PCAB_DATAW;
//
// Globals
//
// None
//
// Macro expansion list
//
// None
//
// Private function prototypes
//
// None
//
// Macro expansion definition
//
// None
//
// Code
//
INT
DIAMONDAPI
pCabFilePlacedA (
IN PCCAB FciCabParams,
IN PSTR FileName,
IN LONG FileSize,
IN BOOL Continuation,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PFCI_CAB_HANDLEA cabHandle;
MYASSERT(Context);
cabHandle = (PFCI_CAB_HANDLEA) Context;
if (!cabHandle) {
return 0;
}
cabHandle->FileCount++;
cabHandle->FileSize += FileSize;
return 0;
}
INT
DIAMONDAPI
pCabFilePlacedW (
IN PCCAB FciCabParams,
IN PSTR FileName,
IN LONG FileSize,
IN BOOL Continuation,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PFCI_CAB_HANDLEW cabHandle;
MYASSERT(Context);
cabHandle = (PFCI_CAB_HANDLEW) Context;
if (!cabHandle) {
return 0;
}
cabHandle->FileCount++;
cabHandle->FileSize += FileSize;
return 0;
}
PVOID
DIAMONDAPI
pCabAlloc (
IN ULONG Size
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
MYASSERT(Size);
return MemAlloc (g_hHeap, 0, Size);
}
VOID
DIAMONDAPI
pCabFree (
IN PVOID Memory
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
MYASSERT(Memory);
MemFree (g_hHeap, 0, Memory);
}
INT_PTR
DIAMONDAPI
pCabOpenA (
IN PSTR FileName,
IN INT oFlag,
IN INT pMode,
OUT PINT Error,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
HANDLE fileHandle;
if(!FileName){
MYASSERT(FileName);
if(Error){
*Error = ERROR_FILE_NOT_FOUND;
}
return -1;
}
// oFlag and pMode are prepared for using _open. We won't do that
// and it's a terrible waste of time to check each individual flags
// We'll just assert these values.
MYASSERT ((oFlag == (_O_CREAT | _O_TRUNC | _O_BINARY | _O_RDWR)) || (oFlag == (_O_CREAT | _O_EXCL | _O_BINARY | _O_RDWR)));
MYASSERT (pMode == (_S_IREAD | _S_IWRITE));
fileHandle = CreateFileA (
FileName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_ARCHIVE,
NULL
);
if (fileHandle == INVALID_HANDLE_VALUE) {
if(Error){
*Error = GetLastError ();
}
return -1;
}
if(Error){
*Error = 0;
}
return (INT_PTR)fileHandle;
}
INT_PTR
DIAMONDAPI
pCabOpen1A (
IN PSTR FileName,
IN INT oFlag,
IN INT pMode
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
HANDLE fileHandle;
if(!FileName){
MYASSERT(FileName);
return -1;
}
// oFlag and pMode are prepared for using _open. We won't do that
// and it's a terrible waste of time to check each individual flags
// We'll just assert these values.
MYASSERT (oFlag == _O_BINARY);
fileHandle = CreateFileA (
FileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_ARCHIVE,
NULL
);
if (fileHandle == INVALID_HANDLE_VALUE) {
return -1;
}
return (INT_PTR)fileHandle;
}
UINT
DIAMONDAPI
pCabRead (
IN INT_PTR FileHandle,
IN PVOID Buffer,
IN UINT Size,
OUT PINT Error,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
BOOL result;
UINT bytesRead;
MYASSERT(((HANDLE)FileHandle) != INVALID_HANDLE_VALUE);
MYASSERT(Buffer);
MYASSERT(Size);
result = ReadFile ((HANDLE)FileHandle, Buffer, Size, &bytesRead, NULL);
if (!result) {
if(Error){
*Error = GetLastError ();
}
return ((UINT)(-1));
}
if(Error){
*Error = 0;
}
return bytesRead;
}
UINT
DIAMONDAPI
pCabRead1 (
IN INT_PTR FileHandle,
IN PVOID Buffer,
IN UINT Size
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
BOOL result;
UINT bytesRead;
MYASSERT(((HANDLE)FileHandle) != INVALID_HANDLE_VALUE);
MYASSERT(Buffer);
MYASSERT(Size);
result = ReadFile ((HANDLE)FileHandle, Buffer, Size, &bytesRead, NULL);
if (!result) {
return ((UINT)(-1));
}
return bytesRead;
}
UINT
DIAMONDAPI
pCabWrite (
IN INT_PTR FileHandle,
IN PVOID Buffer,
IN UINT Size,
OUT PINT Error,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
BOOL result;
DWORD dontCare;
MYASSERT(((HANDLE)FileHandle) != INVALID_HANDLE_VALUE);
MYASSERT(Buffer);
MYASSERT(Size);
if (FileHandle == (INT_PTR) VERIFY_HANDLE) {
return Size;
}
result = WriteFile ((HANDLE)FileHandle, Buffer, Size, &dontCare, NULL);
if (!result) {
if(Error){
*Error = GetLastError ();
}
return ((UINT)(-1));
}
if(Error){
*Error = 0;
}
return Size;
}
UINT
DIAMONDAPI
pCabWrite1 (
IN INT_PTR FileHandle,
IN PVOID Buffer,
IN UINT Size
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
BOOL result;
DWORD dontCare;
MYASSERT(((HANDLE)FileHandle) != INVALID_HANDLE_VALUE);
MYASSERT(Buffer);
MYASSERT(Size);
if (FileHandle == (INT_PTR) VERIFY_HANDLE) {
return Size;
}
result = WriteFile ((HANDLE)FileHandle, Buffer, Size, &dontCare, NULL);
if (!result) {
return ((UINT)(-1));
}
return Size;
}
INT
DIAMONDAPI
pCabClose (
IN INT_PTR FileHandle,
OUT PINT Error,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
MYASSERT(((HANDLE)FileHandle) != INVALID_HANDLE_VALUE);
CloseHandle ((HANDLE)FileHandle);
if(Error){
*Error = 0;
}
return 0;
}
INT
DIAMONDAPI
pCabClose1 (
IN INT_PTR FileHandle
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
MYASSERT(((HANDLE)FileHandle) != INVALID_HANDLE_VALUE);
CloseHandle ((HANDLE)FileHandle);
return 0;
}
LONG
DIAMONDAPI
pCabSeek (
IN INT_PTR FileHandle,
IN LONG Distance,
IN INT SeekType,
OUT PINT Error,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
DWORD result;
DWORD seekType = FILE_BEGIN;
MYASSERT(((HANDLE)FileHandle) != INVALID_HANDLE_VALUE);
switch (SeekType) {
case SEEK_SET:
seekType = FILE_BEGIN;
break;
case SEEK_CUR:
seekType = FILE_CURRENT;
break;
case SEEK_END:
seekType = FILE_END;
break;
}
result = SetFilePointer ((HANDLE)FileHandle, Distance, NULL, seekType);
if (result == INVALID_SET_FILE_POINTER) {
*Error = GetLastError ();
return -1;
}
*Error = 0;
return ((LONG)(result));
}
LONG
DIAMONDAPI
pCabSeek1 (
IN INT_PTR FileHandle,
IN LONG Distance,
IN INT SeekType
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
DWORD result;
DWORD seekType = FILE_BEGIN;
MYASSERT(((HANDLE)FileHandle) != INVALID_HANDLE_VALUE);
switch (SeekType) {
case SEEK_SET:
seekType = FILE_BEGIN;
break;
case SEEK_CUR:
seekType = FILE_CURRENT;
break;
case SEEK_END:
seekType = FILE_END;
break;
}
result = SetFilePointer ((HANDLE)FileHandle, Distance, NULL, seekType);
if (result == INVALID_SET_FILE_POINTER) {
return -1;
}
return ((LONG)(result));
}
INT
DIAMONDAPI
pCabDeleteA (
IN PSTR FileName,
OUT PINT Error,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
MYASSERT(FileName);
MYASSERT(Error);
if (!DeleteFileA (FileName)) {
*Error = GetLastError ();
return -1;
}
*Error = 0;
return 0;
}
BOOL
DIAMONDAPI
pCabGetTempFileA (
OUT PSTR FileName,
IN INT FileNameLen,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
CHAR tempPath[MAX_PATH];
PSTR p;
MYASSERT(FileName);
if (!GetTempPathA (ARRAYSIZE(tempPath), tempPath)) {
return FALSE;
}
p = _mbsrchr (tempPath, '\\');
if (p && !p[1]) {
*p = 0;
}
if (!DoesFileExistA (tempPath)) {
CreateDirectoryA (tempPath, NULL);
}
if (!GetTempFileNameA (tempPath, "cab", 0, FileName)) {
return FALSE;
}
return TRUE;
}
BOOL
DIAMONDAPI
pCabGetNextCabinetA (
IN PCCAB FciCabParams,
IN ULONG PrevCabinetSize,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PFCI_CAB_HANDLEA cabHandle;
CHAR cabFile [CB_MAX_CABINET_NAME];
CHAR cabDisk [CB_MAX_DISK_NAME];
MYASSERT(Context);
cabHandle = (PFCI_CAB_HANDLEA) Context;
if (!cabHandle) {
return FALSE;
}
if (cabHandle->CabGetCabinetNames) {
return cabHandle->CabGetCabinetNames (
FciCabParams->szCabPath,
CB_MAX_CAB_PATH,
FciCabParams->szCab,
CB_MAX_CABINET_NAME,
FciCabParams->szDisk,
CB_MAX_DISK_NAME,
FciCabParams->iCab,
&FciCabParams->iDisk
);
} else {
FciCabParams->iDisk = FciCabParams->iCab;
if (cabHandle->CabFileFormat) {
if(_snprintf(cabFile, CB_MAX_CABINET_NAME, cabHandle->CabFileFormat, FciCabParams->iCab) < 0){
cabFile[CB_MAX_CABINET_NAME - 1] = '\0';
DEBUGMSG((DBG_ERROR, "pCabGetNextCabinetW: _snprintf truncated cabfile %s", cabFile));
//BUGBUG: we have truncated path, what to do?
//return TRUE;
}
StringCopyByteCountA (FciCabParams->szCab, cabFile, CB_MAX_CABINET_NAME * sizeof (CHAR));
}
if (cabHandle->CabDiskFormat) {
if(_snprintf(cabDisk, CB_MAX_DISK_NAME, cabHandle->CabDiskFormat, FciCabParams->iDisk) < 0){
cabDisk[CB_MAX_DISK_NAME - 1] = '\0';
DEBUGMSG((DBG_ERROR, "pCabGetNextCabinetW: _snprintf truncated cabdisk %s", cabDisk));
//BUGBUG: we have truncated path, what to do?
//return TRUE;
}
StringCopyByteCountA (FciCabParams->szDisk, cabDisk, CB_MAX_DISK_NAME * sizeof (CHAR));
}
}
return TRUE;
}
BOOL
DIAMONDAPI
pCabGetNextCabinetW (
IN PCCAB FciCabParams,
IN ULONG PrevCabinetSize,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PFCI_CAB_HANDLEW cabHandle;
WCHAR cabPath [CB_MAX_CAB_PATH];
WCHAR cabFile [CB_MAX_CABINET_NAME];
WCHAR cabDisk [CB_MAX_DISK_NAME];
BOOL result;
MYASSERT(Context);
MYASSERT(FciCabParams);
cabHandle = (PFCI_CAB_HANDLEW) Context;
if (!cabHandle) {
return FALSE;
}
if (cabHandle->CabGetCabinetNames) {
result = cabHandle->CabGetCabinetNames (
cabPath,
CB_MAX_CAB_PATH,
cabFile,
CB_MAX_CABINET_NAME,
cabDisk,
CB_MAX_DISK_NAME,
FciCabParams->iCab,
&FciCabParams->iDisk
);
if (result) {
KnownSizeUnicodeToDbcs (FciCabParams->szCabPath, cabPath);
KnownSizeUnicodeToDbcs (FciCabParams->szCab, cabFile);
KnownSizeUnicodeToDbcs (FciCabParams->szDisk, cabDisk);
return TRUE;
}
return FALSE;
} else {
FciCabParams->iDisk = FciCabParams->iCab;
if (cabHandle->CabFileFormat) {
if(_snwprintf(cabFile, CB_MAX_CABINET_NAME, cabHandle->CabFileFormat, FciCabParams->iCab) < 0){
cabFile[CB_MAX_CABINET_NAME - 1] = '\0';
DEBUGMSG((DBG_ERROR, "pCabGetNextCabinetW: _snwprintf truncated cabfile %s", cabFile));
//BUGBUG: we have truncated path, what to do?
//return TRUE;
}
KnownSizeUnicodeToDbcs (FciCabParams->szCab, cabFile);
}
if (cabHandle->CabDiskFormat) {
if(_snwprintf(cabDisk, CB_MAX_DISK_NAME, cabHandle->CabDiskFormat, FciCabParams->iDisk) < 0){
cabDisk[CB_MAX_DISK_NAME - 1] = '\0';
DEBUGMSG((DBG_ERROR, "pCabGetNextCabinetW: _snwprintf truncated cabdisk %s", cabDisk));
//BUGBUG: we have truncated path, what to do?
//return TRUE;
}
KnownSizeUnicodeToDbcs (FciCabParams->szDisk, cabDisk);
}
}
return TRUE;
}
LONG
DIAMONDAPI
pCabStatusA (
IN UINT StatusType,
IN ULONG Size1,
IN ULONG Size2,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PFCI_CAB_HANDLEA cabHandle;
if (StatusType == statusCabinet) {
MYASSERT(Context);
cabHandle = (PFCI_CAB_HANDLEA) Context;
if (!cabHandle) {
return 0;
}
cabHandle->CabCount++;
cabHandle->CompressedSize += (LONGLONG) Size2;
}
return 0;
}
LONG
DIAMONDAPI
pCabStatusW (
IN UINT StatusType,
IN ULONG Size1,
IN ULONG Size2,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PFCI_CAB_HANDLEW cabHandle;
if (StatusType == statusCabinet) {
MYASSERT(Context);
cabHandle = (PFCI_CAB_HANDLEW) Context;
if (!cabHandle) {
return 0;
}
cabHandle->CabCount++;
cabHandle->CompressedSize += (LONGLONG) Size2;
}
return 0;
}
INT_PTR
DIAMONDAPI
pCabGetOpenInfoA (
IN PSTR FileName,
OUT USHORT *Date,
OUT USHORT *Time,
OUT USHORT *Attributes,
OUT PINT Error,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
WIN32_FIND_DATAA findData;
FILETIME fileTime;
HANDLE fileHandle;
MYASSERT(FileName);
MYASSERT(Error);
if (DoesFileExistExA (FileName, &findData)) {
FileTimeToLocalFileTime (&findData.ftLastWriteTime, &fileTime);
FileTimeToDosDateTime (&fileTime, Date, Time);
/*
* Mask out all other bits except these four, since other
* bits are used by the cabinet format to indicate a
* special meaning.
*/
*Attributes = (USHORT) (findData.dwFileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE));
fileHandle = CreateFileA (
FileName,
GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (fileHandle == INVALID_HANDLE_VALUE) {
*Error = GetLastError ();
return -1;
}
*Error = 0;
return (INT_PTR)fileHandle;
} else {
*Error = GetLastError ();
return -1;
}
}
BOOL
pIsFullPathA (
IN PCSTR PathToTest
)
{
MBCHAR ch1;
MBCHAR ch2;
MYASSERT(PathToTest);
ch1 = _mbsnextc (PathToTest);
_mbsinc (PathToTest);
ch2 = _mbsnextc (PathToTest);
if ((ch1 == '\\' && ch2 == '\\') ||
(isalpha (ch1) && ch2 == '\\')
) {
return TRUE;
}
return FALSE;
}
BOOL
pIsFullPathW (
IN PCWSTR PathToTest
)
{
WCHAR ch1;
WCHAR ch2;
MYASSERT(PathToTest);
ch1 = *PathToTest++;
ch2 = *PathToTest;
if ((ch1 == '\\' && ch2 == '\\') ||
(isalpha (ch1) && ch2 == '\\')
) {
return TRUE;
}
return FALSE;
}
PCSTR
pComputeDestPathA (
IN PCSTR ExtractPath, OPTIONAL
IN PCSTR PathStoredInCab
)
{
PCSTR destFile;
MYASSERT(PathStoredInCab);
//
// If ExtractPath is NULL, then use the path stored in the cab.
// If the path stored in the cab is a full path, use only the file name.
// Otherwise join ExtractPath with PathStoredInCab.
//
if (!ExtractPath) {
destFile = DuplicatePathStringA (PathStoredInCab, 0);
} else if (pIsFullPathA (PathStoredInCab)) {
destFile = JoinPathsA (ExtractPath, GetFileNameFromPathA (PathStoredInCab));
} else {
destFile = JoinPathsA (ExtractPath, PathStoredInCab);
}
return destFile;
}
PCWSTR
pComputeDestPathW (
IN PCWSTR ExtractPath, OPTIONAL
IN PCWSTR PathStoredInCab
)
{
PCWSTR destFile;
MYASSERT(PathStoredInCab);
//
// If ExtractPath is NULL, then use the path stored in the cab.
// If the path stored in the cab is a full path, use only the file name.
// Otherwise join ExtractPath with PathStoredInCab.
//
if (!ExtractPath) {
destFile = DuplicatePathStringW (PathStoredInCab, 0);
} else if (pIsFullPathW (PathStoredInCab)) {
destFile = JoinPathsW (ExtractPath, GetFileNameFromPathW (PathStoredInCab));
} else {
destFile = JoinPathsW (ExtractPath, PathStoredInCab);
}
return destFile;
}
INT_PTR
DIAMONDAPI
pCabNotificationA (
IN FDINOTIFICATIONTYPE FdiNotificationType,
IN OUT PFDINOTIFICATION FdiNotification
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PCSTR destFile = NULL;
HANDLE destHandle = NULL;
DWORD attributes;
FILETIME localFileTime;
FILETIME fileTime;
PCAB_DATAA cabData;
INT createFlag;
switch (FdiNotificationType) {
case fdintCABINET_INFO: // General information about cabinet
return 0;
case fdintCOPY_FILE: // File to be copied
cabData = (PCAB_DATAA)FdiNotification->pv;
destFile = pComputeDestPathA (cabData->ExtractPath, FdiNotification->psz1);
MYASSERT(destFile);
createFlag = TRUE;
if (cabData->CabNotificationA) {
createFlag = cabData->CabNotificationA (destFile);
}
if(-1 == createFlag){
FreePathStringA (destFile);
return -1;
}
if (createFlag) {
MakeSurePathExistsA (FdiNotification->psz1, FALSE);
SetFileAttributesA (destFile, FILE_ATTRIBUTE_NORMAL);
destHandle = CreateFileA (
destFile,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
}
FreePathStringA (destFile);
return (INT_PTR)destHandle;
case fdintCLOSE_FILE_INFO: // close the file, set relevant info
cabData = (PCAB_DATAA)FdiNotification->pv;
if (DosDateTimeToFileTime (FdiNotification->date, FdiNotification->time, &localFileTime)) {
if (LocalFileTimeToFileTime (&localFileTime, &fileTime)) {
SetFileTime ((HANDLE)FdiNotification->hf, &fileTime, &fileTime, &fileTime);
}
}
destFile = pComputeDestPathA (cabData->ExtractPath, FdiNotification->psz1);
CloseHandle ((HANDLE)FdiNotification->hf);
attributes = (FdiNotification->attribs & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE));
SetFileAttributesA (destFile, attributes);
FreePathStringA (destFile);
return TRUE;
case fdintPARTIAL_FILE: // First file in cabinet is continuation
return 0;
case fdintENUMERATE: // Enumeration status
return 0;
case fdintNEXT_CABINET: // File continued to next cabinet
return 0;
}
return 0;
}
INT_PTR
DIAMONDAPI
pCabNotificationW (
IN FDINOTIFICATIONTYPE FdiNotificationType,
IN OUT PFDINOTIFICATION FdiNotification
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PCWSTR destFile = NULL;
HANDLE destHandle = NULL;
DWORD attributes;
FILETIME localFileTime;
FILETIME fileTime;
PCAB_DATAW cabData;
INT createFlag;
PCWSTR cabFileSpecW;
switch (FdiNotificationType) {
case fdintCABINET_INFO: // General information about cabinet
return 0;
case fdintCOPY_FILE: // File to be copied
cabFileSpecW = ConvertAtoW (FdiNotification->psz1);
cabData = (PCAB_DATAW)FdiNotification->pv;
destFile = pComputeDestPathW (cabData->ExtractPath, cabFileSpecW);
MYASSERT(destFile);
FreeConvertedStr (cabFileSpecW);
createFlag = TRUE;
if (cabData->CabNotificationW) {
createFlag = cabData->CabNotificationW (destFile);
}
if(-1 == createFlag){
FreePathStringW (destFile);
return -1;
}
if (createFlag) {
if (!cabData->VerifyMode) {
MakeSurePathExistsW (cabFileSpecW, FALSE);
SetFileAttributesW (destFile, FILE_ATTRIBUTE_NORMAL);
destHandle = CreateFileW (
destFile,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
} else {
destHandle = VERIFY_HANDLE;
}
}
FreePathStringW (destFile);
return (INT_PTR)destHandle;
case fdintCLOSE_FILE_INFO: // close the file, set relevant info
cabData = (PCAB_DATAW)FdiNotification->pv;
if (DosDateTimeToFileTime (FdiNotification->date, FdiNotification->time, &localFileTime)) {
if (LocalFileTimeToFileTime (&localFileTime, &fileTime)) {
SetFileTime ((HANDLE)FdiNotification->hf, &fileTime, &fileTime, &fileTime);
}
}
cabFileSpecW = ConvertAtoW (FdiNotification->psz1);
destFile = pComputeDestPathW (cabData->ExtractPath, cabFileSpecW);
MYASSERT(destFile);
FreeConvertedStr (cabFileSpecW);
CloseHandle ((HANDLE)FdiNotification->hf);
attributes = (FdiNotification->attribs & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE));
SetFileAttributesW (destFile, attributes);
FreePathStringW (destFile);
return TRUE;
case fdintPARTIAL_FILE: // First file in cabinet is continuation
return 0;
case fdintENUMERATE: // Enumeration status
return 0;
case fdintNEXT_CABINET: // File continued to next cabinet
return 0;
}
return 0;
}
CCABHANDLE
CabCreateCabinetA (
IN PCSTR CabPath,
IN PCSTR CabFileFormat,
IN PCSTR CabDiskFormat,
IN LONG MaxFileSize
)
/*++
Routine Description:
Creates a cabinet context. Caller may use this context for subsequent calls to
CabAddFile.
Arguments:
CabPath - Specifies the path where the new cabinet file will be.
CabFileFormat - Specifies (as for wsprintf) the format of the cabinet file name.
CabDiskFormat - Specifies (as for wsprintf) the format of the cabinet disk name.
MaxFileSize - Specifies maximum size of the cabinet file (limited to 2GB). if 0 => 2GB
Return Value:
a valid CCABHANDLE if successful, NULL otherwise.
--*/
{
PFCI_CAB_HANDLEA cabHandle;
CHAR cabFile [CB_MAX_CABINET_NAME];
CHAR cabDisk [CB_MAX_DISK_NAME];
if(!CabPath){
MYASSERT(CabPath);
return NULL;
}
if (!CabFileFormat) {
return NULL;
}
if (MaxFileSize < 0) {
return NULL;
}
if (MaxFileSize == 0) {
MaxFileSize = 0x7FFFFFFF;
}
cabHandle = (PFCI_CAB_HANDLEA) MemAlloc (g_hHeap, 0, sizeof (FCI_CAB_HANDLEA));
ZeroMemory (cabHandle, sizeof (FCI_CAB_HANDLEA));
if (CabPath) {
cabHandle->CabPath = DuplicatePathStringA (CabPath, 0);
}
cabHandle->CabFileFormat = DuplicatePathStringA (CabFileFormat, 0);
if (CabDiskFormat) {
cabHandle->CabDiskFormat = DuplicatePathStringA (CabDiskFormat, 0);
}
// fill out the CCAB structure
cabHandle->FciCabParams.cb = MaxFileSize;
cabHandle->FciCabParams.cbFolderThresh = MaxFileSize;
cabHandle->FciCabParams.cbReserveCFHeader = 0;
cabHandle->FciCabParams.cbReserveCFFolder = 0;
cabHandle->FciCabParams.cbReserveCFData = 0;
cabHandle->FciCabParams.iCab = 1;
cabHandle->FciCabParams.iDisk = 1;
cabHandle->FciCabParams.setID = 0;
if (CabPath) {
StringCopyByteCountA (cabHandle->FciCabParams.szCabPath, CabPath, CB_MAX_CAB_PATH - 1);
AppendWackA (cabHandle->FciCabParams.szCabPath);
}
if (CabDiskFormat) {
if(_snprintf(cabDisk, CB_MAX_DISK_NAME, CabDiskFormat, cabHandle->FciCabParams.iDisk) < 0){
cabDisk[CB_MAX_DISK_NAME - 1] = '\0';
DEBUGMSG((DBG_ERROR, "CabCreateCabinetA: _snwprintf truncated cabdisk %s", cabDisk));
//BUGBUG: we have truncated path, what to do?
//return NULL;
}
StringCopyByteCountA (cabHandle->FciCabParams.szDisk, cabDisk, CB_MAX_DISK_NAME * sizeof (CHAR));
}
if(_snprintf(cabFile, CB_MAX_CABINET_NAME, CabFileFormat, cabHandle->FciCabParams.iCab) < 0){
cabFile[CB_MAX_CABINET_NAME - 1] = '\0';
DEBUGMSG((DBG_ERROR, "CabCreateCabinetA: _snwprintf truncated cabfile %s", cabFile));
//BUGBUG: we have truncated path, what to do?
//return NULL;
}
StringCopyByteCountA (cabHandle->FciCabParams.szCab, cabFile, CB_MAX_CABINET_NAME * sizeof (CHAR));
cabHandle->FciHandle = FCICreate (
&cabHandle->FciErrorStruct,
pCabFilePlacedA,
pCabAlloc,
pCabFree,
pCabOpenA,
pCabRead,
pCabWrite,
pCabClose,
pCabSeek,
pCabDeleteA,
pCabGetTempFileA,
&cabHandle->FciCabParams,
cabHandle
);
if (!cabHandle->FciHandle) {
if (cabHandle->CabPath) {
FreePathStringA (cabHandle->CabPath);
}
if (cabHandle->CabFileFormat) {
FreePathStringA (cabHandle->CabFileFormat);
}
if (cabHandle->CabDiskFormat) {
FreePathStringA (cabHandle->CabDiskFormat);
}
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
return ((CCABHANDLE)(cabHandle));
}
CCABHANDLE
CabCreateCabinetW (
IN PCWSTR CabPath,
IN PCWSTR CabFileFormat,
IN PCWSTR CabDiskFormat,
IN LONG MaxFileSize
)
/*++
Routine Description:
Creates a cabinet context. Caller may use this context for subsequent calls to
CabAddFile.
Arguments:
CabPath - Specifies the path where the new cabinet file will be.
CabFileFormat - Specifies (as for wsprintf) the format of the cabinet file name.
CabDiskFormat - Specifies (as for wsprintf) the format of the cabinet disk name.
MaxFileSize - Specifies maximum size of the cabinet file (limited to 2GB). if 0 => 2GB
Return Value:
a valid CCABHANDLE if successful, NULL otherwise.
--*/
{
PFCI_CAB_HANDLEW cabHandle;
WCHAR cabFile [CB_MAX_CABINET_NAME];
WCHAR cabDisk [CB_MAX_DISK_NAME];
if(!CabPath){
MYASSERT(CabPath);
return NULL;
}
if (!CabFileFormat) {
return NULL;
}
if (MaxFileSize < 0) {
return NULL;
}
if (MaxFileSize == 0) {
MaxFileSize = 0x7FFFFFFF;
}
cabHandle = (PFCI_CAB_HANDLEW) MemAlloc (g_hHeap, 0, sizeof (FCI_CAB_HANDLEW));
ZeroMemory (cabHandle, sizeof (FCI_CAB_HANDLEW));
if (CabPath) {
cabHandle->CabPath = DuplicatePathStringW (CabPath, 0);
}
cabHandle->CabFileFormat = DuplicatePathStringW (CabFileFormat, 0);
if (CabDiskFormat) {
cabHandle->CabDiskFormat = DuplicatePathStringW (CabDiskFormat, 0);
}
// fill out the CCAB structure
cabHandle->FciCabParams.cb = MaxFileSize;
cabHandle->FciCabParams.cbFolderThresh = MaxFileSize;
cabHandle->FciCabParams.cbReserveCFHeader = 0;
cabHandle->FciCabParams.cbReserveCFFolder = 0;
cabHandle->FciCabParams.cbReserveCFData = 0;
cabHandle->FciCabParams.iCab = 1;
cabHandle->FciCabParams.iDisk = 1;
cabHandle->FciCabParams.setID = 0;
if (CabPath) {
KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szCabPath, CabPath);
AppendWackA (cabHandle->FciCabParams.szCabPath);
}
if (CabDiskFormat) {
if(_snwprintf(cabDisk, CB_MAX_DISK_NAME, CabDiskFormat, cabHandle->FciCabParams.iDisk) < 0){
cabDisk[CB_MAX_DISK_NAME - 1] = '\0';
DEBUGMSG((DBG_ERROR, "CabCreateCabinetW: _snwprintf truncated cabdisk %s", cabDisk));
//BUGBUG: we have truncated path, what to do?
//return NULL;
}
KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szDisk, cabDisk);
}
if(_snwprintf(cabFile, CB_MAX_CABINET_NAME, CabFileFormat, cabHandle->FciCabParams.iCab) < 0){
cabFile[CB_MAX_CABINET_NAME - 1] = '\0';
DEBUGMSG((DBG_ERROR, "CabCreateCabinetW: _snwprintf truncated cabfile %s", cabFile));
//BUGBUG: we have truncated path, what to do?
//return NULL;
}
KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szCab, cabFile);
cabHandle->FciHandle = FCICreate (
&cabHandle->FciErrorStruct,
pCabFilePlacedW,
pCabAlloc,
pCabFree,
pCabOpenA,
pCabRead,
pCabWrite,
pCabClose,
pCabSeek,
pCabDeleteA,
pCabGetTempFileA,
&cabHandle->FciCabParams,
cabHandle
);
if (!cabHandle->FciHandle) {
if (cabHandle->CabPath) {
FreePathStringW (cabHandle->CabPath);
}
if (cabHandle->CabFileFormat) {
FreePathStringW (cabHandle->CabFileFormat);
}
if (cabHandle->CabDiskFormat) {
FreePathStringW (cabHandle->CabDiskFormat);
}
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
return ((CCABHANDLE)(cabHandle));
}
CCABHANDLE
CabCreateCabinetExA (
IN PCABGETCABINETNAMESA CabGetCabinetNames,
IN LONG MaxFileSize
)
/*++
Routine Description:
Creates a cabinet context. Caller may use this context for subsequent calls to
CabAddFile.
Arguments:
CabGetCabinetNames - Specifies a callback used to decide cabinet path, cabinet name and disk name.
MaxFileSize - Specifies maximum size of the cabinet file (limited to 2GB). if 0 => 2GB
Return Value:
a valid CCABHANDLE if successful, NULL otherwise.
--*/
{
PFCI_CAB_HANDLEA cabHandle;
if (!CabGetCabinetNames) {
return NULL;
}
if (MaxFileSize < 0) {
return NULL;
}
if (MaxFileSize == 0) {
MaxFileSize = 0x80000000;
}
cabHandle = MemAlloc (g_hHeap, 0, sizeof (FCI_CAB_HANDLEA));
ZeroMemory (cabHandle, sizeof (FCI_CAB_HANDLEA));
cabHandle->CabGetCabinetNames = CabGetCabinetNames;
// fill out the CCAB structure
cabHandle->FciCabParams.cb = MaxFileSize;
cabHandle->FciCabParams.cbFolderThresh = MaxFileSize;
cabHandle->FciCabParams.cbReserveCFHeader = 0;
cabHandle->FciCabParams.cbReserveCFFolder = 0;
cabHandle->FciCabParams.cbReserveCFData = 0;
cabHandle->FciCabParams.iCab = 1;
cabHandle->FciCabParams.iDisk = 1;
cabHandle->FciCabParams.setID = 0;
if (!CabGetCabinetNames (
cabHandle->FciCabParams.szCabPath,
CB_MAX_CAB_PATH,
cabHandle->FciCabParams.szCab,
CB_MAX_CABINET_NAME,
cabHandle->FciCabParams.szDisk,
CB_MAX_DISK_NAME,
cabHandle->FciCabParams.iCab,
&cabHandle->FciCabParams.iDisk
)) {
return NULL;
}
cabHandle->FciHandle = FCICreate (
&cabHandle->FciErrorStruct,
pCabFilePlacedA,
pCabAlloc,
pCabFree,
pCabOpenA,
pCabRead,
pCabWrite,
pCabClose,
pCabSeek,
pCabDeleteA,
pCabGetTempFileA,
&cabHandle->FciCabParams,
cabHandle
);
if (!cabHandle->FciHandle) {
if (cabHandle->CabPath) {
FreePathStringA (cabHandle->CabPath);
}
if (cabHandle->CabFileFormat) {
FreePathStringA (cabHandle->CabFileFormat);
}
if (cabHandle->CabDiskFormat) {
FreePathStringA (cabHandle->CabDiskFormat);
}
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
return ((CCABHANDLE)(cabHandle));
}
CCABHANDLE
CabCreateCabinetExW (
IN PCABGETCABINETNAMESW CabGetCabinetNames,
IN LONG MaxFileSize
)
/*++
Routine Description:
Creates a cabinet context. Caller may use this context for subsequent calls to
CabAddFile.
Arguments:
CabGetCabinetNames - Specifies a callback used to decide cabinet path, cabinet name and disk name.
MaxFileSize - Specifies maximum size of the cabinet file (limited to 2GB). if 0 => 2GB
Return Value:
a valid CCABHANDLE if successful, NULL otherwise.
--*/
{
PFCI_CAB_HANDLEW cabHandle;
WCHAR cabPath [CB_MAX_CAB_PATH];
WCHAR cabFile [CB_MAX_CABINET_NAME];
WCHAR cabDisk [CB_MAX_DISK_NAME];
if (!CabGetCabinetNames) {
return NULL;
}
if (MaxFileSize < 0) {
return NULL;
}
if (MaxFileSize == 0) {
MaxFileSize = 0x80000000;
}
cabHandle = MemAlloc (g_hHeap, 0, sizeof (FCI_CAB_HANDLEW));
ZeroMemory (cabHandle, sizeof (FCI_CAB_HANDLEW));
cabHandle->CabGetCabinetNames = CabGetCabinetNames;
// fill out the CCAB structure
cabHandle->FciCabParams.cb = MaxFileSize;
cabHandle->FciCabParams.cbFolderThresh = MaxFileSize;
cabHandle->FciCabParams.cbReserveCFHeader = 0;
cabHandle->FciCabParams.cbReserveCFFolder = 0;
cabHandle->FciCabParams.cbReserveCFData = 0;
cabHandle->FciCabParams.iCab = 1;
cabHandle->FciCabParams.iDisk = 1;
cabHandle->FciCabParams.setID = 0;
if (!CabGetCabinetNames (
cabPath,
CB_MAX_CAB_PATH,
cabFile,
CB_MAX_CABINET_NAME,
cabDisk,
CB_MAX_DISK_NAME,
cabHandle->FciCabParams.iCab,
&cabHandle->FciCabParams.iDisk
)) {
return NULL;
}
KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szCabPath, cabPath);
KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szCab, cabFile);
KnownSizeUnicodeToDbcs (cabHandle->FciCabParams.szDisk, cabDisk);
cabHandle->FciHandle = FCICreate (
&cabHandle->FciErrorStruct,
pCabFilePlacedW,
pCabAlloc,
pCabFree,
pCabOpenA,
pCabRead,
pCabWrite,
pCabClose,
pCabSeek,
pCabDeleteA,
pCabGetTempFileA,
&cabHandle->FciCabParams,
cabHandle
);
if (!cabHandle->FciHandle) {
if (cabHandle->CabPath) {
FreePathStringW (cabHandle->CabPath);
}
if (cabHandle->CabFileFormat) {
FreePathStringW (cabHandle->CabFileFormat);
}
if (cabHandle->CabDiskFormat) {
FreePathStringW (cabHandle->CabDiskFormat);
}
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
return ((CCABHANDLE)(cabHandle));
}
BOOL
CabAddFileToCabinetA (
IN CCABHANDLE CabHandle,
IN PCSTR FileName,
IN PCSTR StoredName
)
/*++
Routine Description:
Compresses and adds a file to a cabinet context.
Arguments:
CabHandle - Specifies cabinet context.
FileName - Specifies the file to be added.
StoredName - Specifies the name to be stored in the cabinet file.
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
PFCI_CAB_HANDLEA cabHandle;
cabHandle = (PFCI_CAB_HANDLEA) CabHandle;
if (cabHandle == NULL) {
return FALSE;
}
if (cabHandle->FciHandle == NULL) {
return FALSE;
}
return FCIAddFile (
cabHandle->FciHandle,
(PSTR)FileName,
(PSTR)StoredName,
FALSE,
pCabGetNextCabinetA,
pCabStatusA,
pCabGetOpenInfoA,
tcompTYPE_MSZIP
);
}
BOOL
CabAddFileToCabinetW (
IN CCABHANDLE CabHandle,
IN PCWSTR FileName,
IN PCWSTR StoredName
)
/*++
Routine Description:
Compresses and adds a file to a cabinet context.
Arguments:
CabHandle - Specifies cabinet context.
FileName - Specifies the file to be added.
StoredName - Specifies the name to be stored in the cabinet file.
FileCount - Specifies a count of files, receives the updated count
when cabinet files are created
FileSize - Specifies the number of bytes used by the file, receives
the updated size
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
PFCI_CAB_HANDLEW cabHandle;
CHAR ansiFileName [1024];
CHAR ansiStoredName [1024];
cabHandle = (PFCI_CAB_HANDLEW) CabHandle;
if (cabHandle == NULL) {
return FALSE;
}
if (cabHandle->FciHandle == NULL) {
return FALSE;
}
if(!StoredName || !FileName){
MYASSERT(FileName);
MYASSERT(StoredName);
return FALSE;
}
KnownSizeUnicodeToDbcs (ansiFileName, FileName);
KnownSizeUnicodeToDbcs (ansiStoredName, StoredName);
return FCIAddFile (
cabHandle->FciHandle,
ansiFileName,
ansiStoredName,
FALSE,
pCabGetNextCabinetW,
pCabStatusW,
pCabGetOpenInfoA,
tcompTYPE_MSZIP
);
}
BOOL
CabFlushAndCloseCabinetExA (
IN CCABHANDLE CabHandle,
OUT PUINT FileCount, OPTIONAL
OUT PLONGLONG FileSize, OPTIONAL
OUT PUINT CabFileCount, OPTIONAL
OUT PLONGLONG CabFileSize OPTIONAL
)
/*++
Routine Description:
Completes a cabinet file and closes its context.
Arguments:
CabHandle - Specifies cabinet context.
FileCount - Receives the number of files added to the cab
FileSize - Receives the size of all files before compression
CabFileCount - Receives the number of cabinet files created
CabFileSize - Receives the size of all cabinet files
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
PFCI_CAB_HANDLEA cabHandle;
BOOL result = FALSE;
cabHandle = (PFCI_CAB_HANDLEA) CabHandle;
if (cabHandle == NULL) {
return FALSE;
}
if (cabHandle->FciHandle == NULL) {
return FALSE;
}
if (FCIFlushCabinet (
cabHandle->FciHandle,
FALSE,
pCabGetNextCabinetA,
pCabStatusA
)) {
if (cabHandle->CabPath) {
FreePathStringA (cabHandle->CabPath);
}
if (cabHandle->CabFileFormat) {
FreePathStringA (cabHandle->CabFileFormat);
}
if (cabHandle->CabDiskFormat) {
FreePathStringA (cabHandle->CabDiskFormat);
}
result = FCIDestroy (cabHandle->FciHandle);
if (FileCount) {
*FileCount = cabHandle->FileCount;
}
if (FileSize) {
*FileSize = cabHandle->FileSize;
}
if (CabFileCount) {
*CabFileCount = cabHandle->CabCount;
}
if (CabFileSize) {
*CabFileSize = cabHandle->CompressedSize;
}
MemFree (g_hHeap, 0, cabHandle);
}
return result;
}
BOOL
CabFlushAndCloseCabinetExW (
IN CCABHANDLE CabHandle,
OUT PUINT FileCount, OPTIONAL
OUT PLONGLONG FileSize, OPTIONAL
OUT PUINT CabFileCount, OPTIONAL
OUT PLONGLONG CabFileSize OPTIONAL
)
/*++
Routine Description:
Completes a cabinet file and closes its context.
Arguments:
CabHandle - Specifies cabinet context.
FileCount - Receives the number of files added to the cab
FileSize - Receives the size of all files before compression
CabFileCount - Receives the number of cabinet files created
CabFileSize - Receives the size of all cabinet files
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
PFCI_CAB_HANDLEW cabHandle;
BOOL result = FALSE;
cabHandle = (PFCI_CAB_HANDLEW) CabHandle;
if (cabHandle == NULL) {
return FALSE;
}
if (cabHandle->FciHandle == NULL) {
return FALSE;
}
if (FCIFlushCabinet (
cabHandle->FciHandle,
FALSE,
pCabGetNextCabinetW,
pCabStatusW
)) {
if (cabHandle->CabPath) {
FreePathStringW (cabHandle->CabPath);
}
if (cabHandle->CabFileFormat) {
FreePathStringW (cabHandle->CabFileFormat);
}
if (cabHandle->CabDiskFormat) {
FreePathStringW (cabHandle->CabDiskFormat);
}
result = FCIDestroy (cabHandle->FciHandle);
if (FileCount) {
*FileCount = cabHandle->FileCount;
}
if (FileSize) {
*FileSize = cabHandle->FileSize;
}
if (CabFileCount) {
*CabFileCount = cabHandle->CabCount;
}
if (CabFileSize) {
*CabFileSize = cabHandle->CompressedSize;
}
MemFree (g_hHeap, 0, cabHandle);
}
return result;
}
OCABHANDLE
CabOpenCabinetA (
IN PCSTR FileName
)
/*++
Routine Description:
Creates a cabinet context for an existent cabinet file.
Arguments:
FileName - Specifies cabinet file name.
Return Value:
a valid OCABHANDLE if successful, NULL otherwise.
--*/
{
PFDI_CAB_HANDLEA cabHandle;
PSTR filePtr;
HANDLE fileHandle;
PCSTR fileName;
if(!FileName){
MYASSERT(FileName);
return NULL;
}
cabHandle = (PFDI_CAB_HANDLEA) MemAlloc (g_hHeap, 0, sizeof (FDI_CAB_HANDLEA));
ZeroMemory (cabHandle, sizeof (FDI_CAB_HANDLEA));
cabHandle->FdiHandle = FDICreate (
pCabAlloc,
pCabFree,
pCabOpen1A,
pCabRead1,
pCabWrite1,
pCabClose1,
pCabSeek1,
cpuUNKNOWN,
&cabHandle->FdiErrorStruct
);
if (!cabHandle->FdiHandle) {
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
fileName = DuplicatePathStringA (FileName, 0);
fileHandle = CreateFileA (
fileName,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (fileHandle == INVALID_HANDLE_VALUE) {
FreePathStringA (fileName);
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
if (!FDIIsCabinet (cabHandle->FdiHandle, (INT_PTR)fileHandle, &cabHandle->FdiCabinetInfo)) {
FreePathStringA (fileName);
CloseHandle (fileHandle);
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
CloseHandle (fileHandle);
filePtr = (PSTR)GetFileNameFromPathA (fileName);
if (!filePtr) {
FreePathStringA (fileName);
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
cabHandle->CabFile = DuplicatePathStringA (filePtr, 0);
*filePtr = 0;
cabHandle->CabPath = DuplicatePathStringA (fileName, 0);
FreePathStringA (fileName);
return ((CCABHANDLE)(cabHandle));
}
OCABHANDLE
CabOpenCabinetW (
IN PCWSTR FileName
)
/*++
Routine Description:
Creates a cabinet context for an existent cabinet file.
Arguments:
FileName - Specifies cabinet file name.
Return Value:
a valid OCABHANDLE if successful, NULL otherwise.
--*/
{
PFDI_CAB_HANDLEW cabHandle;
PWSTR filePtr;
HANDLE fileHandle;
PCWSTR fileName;
if(!FileName){
MYASSERT(FileName);
return NULL;
}
cabHandle = (PFDI_CAB_HANDLEW) MemAlloc (g_hHeap, 0, sizeof (FDI_CAB_HANDLEW));
ZeroMemory (cabHandle, sizeof (FDI_CAB_HANDLEW));
cabHandle->FdiHandle = FDICreate (
pCabAlloc,
pCabFree,
pCabOpen1A,
pCabRead1,
pCabWrite1,
pCabClose1,
pCabSeek1,
cpuUNKNOWN,
&cabHandle->FdiErrorStruct
);
if (!cabHandle->FdiHandle) {
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
fileName = DuplicatePathStringW (FileName, 0);
fileHandle = CreateFileW (
fileName,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (fileHandle == INVALID_HANDLE_VALUE) {
FreePathStringW (fileName);
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
if (!FDIIsCabinet (cabHandle->FdiHandle, (INT_PTR)fileHandle, &cabHandle->FdiCabinetInfo)) {
FreePathStringW (fileName);
CloseHandle (fileHandle);
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
CloseHandle (fileHandle);
filePtr = (PWSTR)GetFileNameFromPathW (fileName);
if (!filePtr) {
FreePathStringW (fileName);
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
cabHandle->CabFile = DuplicatePathStringW (filePtr, 0);
*filePtr = 0;
cabHandle->CabPath = DuplicatePathStringW (fileName, 0);
FreePathStringW (fileName);
return ((CCABHANDLE)(cabHandle));
}
BOOL
CabExtractAllFilesExA (
IN OCABHANDLE CabHandle,
IN PCSTR ExtractPath, OPTIONAL
IN PCABNOTIFICATIONA CabNotification OPTIONAL
)
/*++
Routine Description:
Extracts all files from a cabinet file.
Arguments:
CabHandle - Specifies cabinet context.
ExtractPath - Specifies the path to extract the files to.
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
PFDI_CAB_HANDLEA cabHandle;
CAB_DATAA cabData;
cabHandle = (PFDI_CAB_HANDLEA)CabHandle;
if (!cabHandle) {
return FALSE;
}
if (!cabHandle->FdiHandle) {
return FALSE;
}
cabData.ExtractPath = ExtractPath;
cabData.CabNotificationA = CabNotification;
return FDICopy (
cabHandle->FdiHandle,
(PSTR)cabHandle->CabFile,
(PSTR)cabHandle->CabPath,
0,
pCabNotificationA,
NULL,
(PVOID)(&cabData)
);
}
BOOL
pCabExtractAllFilesExWorkerW (
IN OCABHANDLE CabHandle,
IN PCWSTR ExtractPath, OPTIONAL
IN PCABNOTIFICATIONW CabNotificationW, OPTIONAL
IN BOOL VerifyMode
)
/*++
Routine Description:
Extracts all files from a cabinet file.
Arguments:
CabHandle - Specifies cabinet context.
ExtractPath - Specifies the path to extract the files to.
CabNotification - Specifies the notification callback function that is
called for every file in the cab
VerifyMode - Specifies TRUE if the cab should be verified, FALSE if it
should be extracted
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
PFDI_CAB_HANDLEW cabHandle;
CAB_DATAW cabData;
BOOL result;
PCSTR cabFileAnsi;
PCSTR cabPathAnsi;
cabHandle = (PFDI_CAB_HANDLEW)CabHandle;
if (!cabHandle) {
return FALSE;
}
if (!cabHandle->FdiHandle) {
return FALSE;
}
cabData.ExtractPath = ExtractPath;
cabData.CabNotificationW = CabNotificationW;
cabData.VerifyMode = VerifyMode;
cabFileAnsi = ConvertWtoA (cabHandle->CabFile);
cabPathAnsi = ConvertWtoA (cabHandle->CabPath);
result = FDICopy (
cabHandle->FdiHandle,
(PSTR) cabFileAnsi,
(PSTR) cabPathAnsi,
0,
pCabNotificationW,
NULL,
(PVOID)(&cabData)
);
FreeConvertedStr (cabFileAnsi);
FreeConvertedStr (cabPathAnsi);
return result;
}
BOOL
CabExtractAllFilesExW (
IN OCABHANDLE CabHandle,
IN PCWSTR ExtractPath, OPTIONAL
IN PCABNOTIFICATIONW CabNotificationW OPTIONAL
)
{
return pCabExtractAllFilesExWorkerW (CabHandle, ExtractPath, CabNotificationW, FALSE);
}
BOOL
CabVerifyCabinet (
IN OCABHANDLE CabHandle
)
{
return pCabExtractAllFilesExWorkerW (CabHandle, NULL, NULL, TRUE);
}
BOOL
CabCloseCabinetA (
IN OCABHANDLE CabHandle
)
/*++
Routine Description:
Closes a cabinet file context.
Arguments:
CabHandle - Specifies cabinet context.
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
PFDI_CAB_HANDLEA cabHandle;
cabHandle = (PFDI_CAB_HANDLEA) CabHandle;
if (!cabHandle) {
return FALSE;
}
if (!cabHandle->FdiHandle) {
return FALSE;
}
if (FDIDestroy (cabHandle->FdiHandle)) {
if (cabHandle->CabPath) {
FreePathStringA (cabHandle->CabPath);
}
if (cabHandle->CabFile) {
FreePathStringA (cabHandle->CabFile);
}
MemFree (g_hHeap, 0, cabHandle);
return TRUE;
}
return FALSE;
}
BOOL
CabCloseCabinetW (
IN OCABHANDLE CabHandle
)
/*++
Routine Description:
Closes a cabinet file context.
Arguments:
CabHandle - Specifies cabinet context.
Return Value:
TRUE if successful, FALSE otherwise.
--*/
{
PFDI_CAB_HANDLEW cabHandle;
cabHandle = (PFDI_CAB_HANDLEW) CabHandle;
if (!cabHandle) {
return FALSE;
}
if (!cabHandle->FdiHandle) {
return FALSE;
}
if (FDIDestroy (cabHandle->FdiHandle)) {
if (cabHandle->CabPath) {
FreePathStringW (cabHandle->CabPath);
}
if (cabHandle->CabFile) {
FreePathStringW (cabHandle->CabFile);
}
MemFree (g_hHeap, 0, cabHandle);
return TRUE;
}
return FALSE;
}