2197 lines
52 KiB
C
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;
|
||
|
}
|
||
|
|