windows-nt/Source/XPSP1/NT/windows/winstate/cobra/utils/cablib/cablib.c
2020-09-26 16:20:57 +08:00

2197 lines
52 KiB
C

/*++
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 <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
//
// None
//
// Macros
//
// None
//
// Types
//
typedef struct {
PCSTR CabPath;
PCSTR CabFileFormat;
PCSTR CabDiskFormat;
PCABGETCABINETNAMESA CabGetCabinetNames;
PCABGETTEMPFILEA CabGetTempFile;
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;
PCABGETTEMPFILEW CabGetTempFile;
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 CabNotification;
} CAB_DATAA, *PCAB_DATAA;
typedef struct {
PCWSTR ExtractPath;
PCABNOTIFICATIONW CabNotification;
} CAB_DATAW, *PCAB_DATAW;
//
// Globals
//
HASHTABLE g_UnicodeTable = NULL;
//
// 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;
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;
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
--*/
{
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
--*/
{
if (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;
// 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) {
*Error = GetLastError ();
return -1;
}
*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;
// 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;
}
INT_PTR
DIAMONDAPI
pCabOpen1W (
IN PSTR FileName,
IN INT oFlag,
IN INT pMode
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PFDI_CAB_HANDLEW cabHandle;
HANDLE fileHandle = INVALID_HANDLE_VALUE;
PCSTR fileName = NULL;
PSTR fileNamePtr = NULL;
PCWSTR fileNameW = NULL;
PCWSTR fullFileName = NULL;
// 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);
if (g_UnicodeTable) {
fileName = DuplicatePathStringA (FileName, 0);
if (fileName) {
fileNamePtr = (PSTR)GetFileNameFromPathA (fileName);
if (fileNamePtr) {
*fileNamePtr = 0;
if ((HtFindStringAndDataA (g_UnicodeTable, fileName, &cabHandle) != NULL) &&
(cabHandle != NULL)
) {
fileNamePtr = (PSTR)GetFileNameFromPathA (FileName);
if (fileNamePtr) {
fileNameW = ConvertAtoW (fileNamePtr);
if (fileNameW) {
fullFileName = JoinPathsW (cabHandle->CabPath, fileNameW);
if (fullFileName) {
fileHandle = CreateFileW (
fullFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_ARCHIVE,
NULL
);
FreePathStringW (fullFileName);
fullFileName = NULL;
}
FreeConvertedStr (fileNameW);
fileNameW = NULL;
}
}
}
}
FreePathStringA (fileName);
fileName = NULL;
}
}
if (fileHandle == INVALID_HANDLE_VALUE) {
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;
result = ReadFile ((HANDLE)FileHandle, Buffer, Size, &bytesRead, NULL);
if (!result) {
*Error = GetLastError ();
return ((UINT)(-1));
}
*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;
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;
result = BfWriteFile ((HANDLE)FileHandle, Buffer, Size);
if (!result) {
*Error = GetLastError ();
return ((UINT)(-1));
}
*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;
result = BfWriteFile ((HANDLE)FileHandle, Buffer, Size);
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
--*/
{
CloseHandle ((HANDLE)FileHandle);
*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
--*/
{
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;
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;
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
--*/
{
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
--*/
{
PFCI_CAB_HANDLEA cabHandle;
cabHandle = (PFCI_CAB_HANDLEA) Context;
if (cabHandle && cabHandle->CabGetTempFile) {
return cabHandle->CabGetTempFile (FileName, FileNameLen);
}
return BfGetTempFileNameA (FileName, FileNameLen);
}
BOOL
DIAMONDAPI
pCabGetTempFileW (
OUT PSTR FileName,
IN INT FileNameLen,
IN PVOID Context
)
/*++
Routine Description:
Callback for cabinet compression/decompression. For more information see fci.h/fdi.h
--*/
{
PFCI_CAB_HANDLEW cabHandle;
WCHAR tempFileNameW [MAX_PATH];
PCSTR tempFileNameA = NULL;
cabHandle = (PFCI_CAB_HANDLEW) Context;
if (cabHandle && cabHandle->CabGetTempFile) {
if (cabHandle->CabGetTempFile (tempFileNameW, MAX_PATH)) {
tempFileNameA = ConvertWtoA (tempFileNameW);
if (tempFileNameA) {
StringCopyTcharCountA (FileName, tempFileNameA, FileNameLen);
FreeConvertedStr (tempFileNameA);
return TRUE;
}
}
return FALSE;
}
return BfGetTempFileNameA (FileName, FileNameLen);
}
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 [1024];
CHAR cabDisk [1024];
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) {
wsprintfA (cabFile, cabHandle->CabFileFormat, FciCabParams->iCab);
StringCopyByteCountA (FciCabParams->szCab, cabFile, CB_MAX_CABINET_NAME * sizeof (CHAR));
}
if (cabHandle->CabDiskFormat) {
wsprintfA (cabDisk, cabHandle->CabDiskFormat, FciCabParams->iDisk);
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 [1024];
WCHAR cabFile [1024];
WCHAR cabDisk [1024];
BOOL result;
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) {
KnownSizeUnicodeToDbcsN (FciCabParams->szCabPath, cabPath, min (CB_MAX_CAB_PATH, CharCountW (cabPath)));
KnownSizeUnicodeToDbcsN (FciCabParams->szCab, cabFile, min (CB_MAX_CABINET_NAME, CharCountW (cabFile)));
KnownSizeUnicodeToDbcsN (FciCabParams->szDisk, cabDisk, min (CB_MAX_DISK_NAME, CharCountW (cabDisk)));
return TRUE;
}
return FALSE;
} else {
FciCabParams->iDisk = FciCabParams->iCab;
if (cabHandle->CabFileFormat) {
wsprintfW (cabFile, cabHandle->CabFileFormat, FciCabParams->iCab);
KnownSizeUnicodeToDbcsN (FciCabParams->szCab, cabFile, min (CB_MAX_CABINET_NAME, CharCountW (cabFile)));
}
if (cabHandle->CabDiskFormat) {
wsprintfW (cabDisk, cabHandle->CabDiskFormat, FciCabParams->iDisk);
KnownSizeUnicodeToDbcsN (FciCabParams->szDisk, cabDisk, min (CB_MAX_DISK_NAME, CharCountW (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) {
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) {
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;
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;
}
}
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;
switch (FdiNotificationType) {
case fdintCABINET_INFO: // General information about cabinet
return 0;
case fdintCOPY_FILE: // File to be copied
cabData = (PCAB_DATAA)FdiNotification->pv;
destFile = JoinPathsA (cabData->ExtractPath, FdiNotification->psz1);
if (cabData->CabNotification) {
if (cabData->CabNotification (destFile)) {
destHandle = BfCreateFileA (destFile);
}
} else {
destHandle = BfCreateFileA (destFile);
}
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 = JoinPathsA (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
// sometimes, in a corrupted cabinet file, the cabinet APIs can ask
// for the next cabinet but nothing more exists. If we don't fail here
// in this case, we are going to infinite loop, so do some checking
if (!FdiNotification) {
return -1;
}
if (FdiNotification->psz1[0] == 0) {
return -1;
}
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;
PCWSTR destFileW = NULL;
HANDLE destHandle = NULL;
DWORD attributes;
FILETIME localFileTime;
FILETIME fileTime;
PCAB_DATAW cabData;
switch (FdiNotificationType) {
case fdintCABINET_INFO: // General information about cabinet
return 0;
case fdintCOPY_FILE: // File to be copied
cabData = (PCAB_DATAW)FdiNotification->pv;
destFileW = ConvertAtoW (FdiNotification->psz1);
if (destFileW) {
destFile = JoinPathsW (cabData->ExtractPath, destFileW);
if (destFile) {
if (cabData->CabNotification) {
if (cabData->CabNotification (destFile)) {
destHandle = BfCreateFileW (destFile);
}
} else {
destHandle = BfCreateFileW (destFile);
}
FreePathStringW (destFile);
}
FreeConvertedStr (destFileW);
}
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);
}
}
destFileW = ConvertAtoW (FdiNotification->psz1);
if (destFileW) {
destFile = JoinPathsW (cabData->ExtractPath, destFileW);
if (destFile) {
CloseHandle ((HANDLE)FdiNotification->hf);
attributes = (FdiNotification->attribs & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE));
SetFileAttributesW (destFile, attributes);
FreePathStringW (destFile);
}
FreeConvertedStr (destFileW);
}
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
// sometimes, in a corrupted cabinet file, the cabinet APIs can ask
// for the next cabinet but nothing more exists. If we don't fail here
// in this case, we are going to infinite loop, so do some checking
if (!FdiNotification) {
return -1;
}
if (FdiNotification->psz1[0] == 0) {
return -1;
}
return 0;
}
return 0;
}
CCABHANDLE
CabCreateCabinetByIndexA (
IN PCSTR CabPath,
IN PCSTR CabFileFormat,
IN PCSTR CabDiskFormat,
IN PCABGETTEMPFILEA CabGetTempFile, // OPTIONAL
IN LONG MaxFileSize,
IN INT InitialIndex
)
/*++
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 [1024];
CHAR cabDisk [1024];
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);
}
cabHandle->CabGetTempFile = CabGetTempFile;
// 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 = InitialIndex;
cabHandle->FciCabParams.iDisk = InitialIndex;
cabHandle->FciCabParams.setID = 0;
if (CabPath) {
StringCopyByteCountA (cabHandle->FciCabParams.szCabPath, CabPath, CB_MAX_CAB_PATH - 1);
AppendWackA (cabHandle->FciCabParams.szCabPath);
}
if (CabDiskFormat) {
wsprintfA (cabDisk, CabDiskFormat, cabHandle->FciCabParams.iDisk);
StringCopyByteCountA (cabHandle->FciCabParams.szDisk, cabDisk, CB_MAX_DISK_NAME * sizeof (CHAR));
}
wsprintfA (cabFile, CabFileFormat, cabHandle->FciCabParams.iCab);
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
CabCreateCabinetByIndexW (
IN PCWSTR CabPath,
IN PCWSTR CabFileFormat,
IN PCWSTR CabDiskFormat,
IN PCABGETTEMPFILEW CabGetTempFile, // OPTIONAL
IN LONG MaxFileSize,
IN INT InitialIndex
)
/*++
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 [1024];
WCHAR cabDisk [1024];
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);
}
cabHandle->CabGetTempFile = CabGetTempFile;
// 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 = InitialIndex;
cabHandle->FciCabParams.iDisk = InitialIndex;
cabHandle->FciCabParams.setID = 0;
if (CabPath) {
KnownSizeUnicodeToDbcsN (cabHandle->FciCabParams.szCabPath, CabPath, min (CB_MAX_CAB_PATH - 1, CharCountW (CabPath)));
AppendWackA (cabHandle->FciCabParams.szCabPath);
}
if (CabDiskFormat) {
wsprintfW (cabDisk, CabDiskFormat, cabHandle->FciCabParams.iDisk);
KnownSizeUnicodeToDbcsN (cabHandle->FciCabParams.szDisk, cabDisk, min (CB_MAX_DISK_NAME, CharCountW (cabDisk)));
}
wsprintfW (cabFile, CabFileFormat, cabHandle->FciCabParams.iCab);
KnownSizeUnicodeToDbcsN (cabHandle->FciCabParams.szCab, cabFile, min (CB_MAX_CABINET_NAME, CharCountW (cabFile)));
cabHandle->FciHandle = FCICreate (
&cabHandle->FciErrorStruct,
pCabFilePlacedW,
pCabAlloc,
pCabFree,
pCabOpenA,
pCabRead,
pCabWrite,
pCabClose,
pCabSeek,
pCabDeleteA,
pCabGetTempFileW,
&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 [1024];
WCHAR cabFile [1024];
WCHAR cabDisk [1024];
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;
}
KnownSizeUnicodeToDbcsN (cabHandle->FciCabParams.szCabPath, cabPath, min (CB_MAX_CAB_PATH, CharCountW (cabPath)));
KnownSizeUnicodeToDbcsN (cabHandle->FciCabParams.szCab, cabFile, min (CB_MAX_CABINET_NAME, CharCountW (cabFile)));
KnownSizeUnicodeToDbcsN (cabHandle->FciCabParams.szDisk, cabDisk, min (CB_MAX_DISK_NAME, CharCountW (cabDisk)));
cabHandle->FciHandle = FCICreate (
&cabHandle->FciErrorStruct,
pCabFilePlacedW,
pCabAlloc,
pCabFree,
pCabOpenA,
pCabRead,
pCabWrite,
pCabClose,
pCabSeek,
pCabDeleteA,
pCabGetTempFileW,
&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;
}
KnownSizeUnicodeToDbcsN (ansiFileName, FileName, min (CB_MAX_CABINET_NAME, CharCountW (FileName)));
KnownSizeUnicodeToDbcsN (ansiStoredName, StoredName, min (CB_MAX_CABINET_NAME, CharCountW (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;
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 = BfOpenReadFileA (fileName);
if (!fileHandle) {
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;
PCSTR filePathA = NULL;
cabHandle = (PFDI_CAB_HANDLEW) MemAlloc (g_hHeap, 0, sizeof (FDI_CAB_HANDLEW));
ZeroMemory (cabHandle, sizeof (FDI_CAB_HANDLEW));
cabHandle->FdiHandle = FDICreate (
pCabAlloc,
pCabFree,
pCabOpen1W,
pCabRead1,
pCabWrite1,
pCabClose1,
pCabSeek1,
cpuUNKNOWN,
&cabHandle->FdiErrorStruct
);
if (!cabHandle->FdiHandle) {
MemFree (g_hHeap, 0, cabHandle);
return NULL;
}
fileName = DuplicatePathStringW (FileName, 0);
fileHandle = BfOpenReadFileW (fileName);
if (!fileHandle) {
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);
if (!g_UnicodeTable) {
g_UnicodeTable = HtAllocWithDataA (sizeof (PFDI_CAB_HANDLEW));
}
if (g_UnicodeTable) {
filePathA = ConvertWtoA (cabHandle->CabPath);
if (filePathA) {
HtAddStringAndDataA (g_UnicodeTable, filePathA, &cabHandle);
FreeConvertedStr (filePathA);
filePathA = NULL;
}
}
return ((CCABHANDLE)(cabHandle));
}
BOOL
CabExtractAllFilesExA (
IN OCABHANDLE CabHandle,
IN PCSTR ExtractPath,
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.CabNotification = CabNotification;
return FDICopy (
cabHandle->FdiHandle,
(PSTR)cabHandle->CabFile,
(PSTR)cabHandle->CabPath,
0,
pCabNotificationA,
NULL,
(PVOID)(&cabData)
);
}
BOOL
CabExtractAllFilesExW (
IN OCABHANDLE CabHandle,
IN PCWSTR ExtractPath,
IN PCABNOTIFICATIONW 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_HANDLEW cabHandle;
CAB_DATAW cabData;
PCSTR cabFileA = NULL;
PCSTR cabPathA = NULL;
BOOL result = FALSE;
cabHandle = (PFDI_CAB_HANDLEW)CabHandle;
if (!cabHandle) {
return FALSE;
}
if (!cabHandle->FdiHandle) {
return FALSE;
}
cabData.ExtractPath = ExtractPath;
cabData.CabNotification = CabNotification;
cabFileA = ConvertWtoA (cabHandle->CabFile);
cabPathA = ConvertWtoA (cabHandle->CabPath);
if (cabFileA && cabPathA) {
result = FDICopy (
cabHandle->FdiHandle,
(PSTR)cabFileA,
(PSTR)cabPathA,
0,
pCabNotificationW,
NULL,
(PVOID)(&cabData)
);
}
if (cabPathA) {
FreeConvertedStr (cabPathA);
cabPathA = NULL;
}
if (cabFileA) {
FreeConvertedStr (cabFileA);
cabFileA = NULL;
}
return result;
}
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;
PCSTR filePathA = NULL;
cabHandle = (PFDI_CAB_HANDLEW) CabHandle;
if (!cabHandle) {
return FALSE;
}
if (!cabHandle->FdiHandle) {
return FALSE;
}
if (FDIDestroy (cabHandle->FdiHandle)) {
if (cabHandle->CabPath) {
if (g_UnicodeTable) {
filePathA = ConvertWtoA (cabHandle->CabPath);
if (filePathA) {
HtRemoveStringA (g_UnicodeTable, filePathA);
FreeConvertedStr (filePathA);
filePathA = NULL;
}
}
FreePathStringW (cabHandle->CabPath);
}
if (cabHandle->CabFile) {
FreePathStringW (cabHandle->CabFile);
}
MemFree (g_hHeap, 0, cabHandle);
return TRUE;
}
return FALSE;
}