/*++ Copyright (c) 1999 Microsoft Corporation Module Name: cablib.c Abstract: Implements wrappers for cabinet APIs Author: Calin Negreanu (calinn) 27-Apr-2000 Revision History: --*/ #include "pch.h" #include #include #include #include #include // // 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; }