Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1355 lines
28 KiB

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
diamond.c
Abstract:
Diamond MSZIP decompression support.
Author:
Ted Miller (tedm) 31-Jan-1995
Revision History:
--*/
#include "setupntp.h"
#pragma hdrstop
//
// Tls index used by Diamond. This is set up in
// DiamondProcessAttach().
//
DWORD DiamondTlsIndex = (DWORD)(-1);
//
// Per-thread globals.
//
typedef struct _DIAMOND_THREAD_DATA {
//
// Boolean value indicating whether the current thread
// is inside diamond. Diamond doesn't really providee
// a full context environment so we declare it non-reentrant.
//
BOOL InDiamond;
//
// Diamond context data
//
HFDI FdiContext;
ERF FdiError;
//
// Last encountered error
//
DWORD LastError;
//
// Name of cabinet as passed to DiamondProcessCabinet,
// and an ANSI version.
//
PCTSTR CabinetFile;
PCSTR CabinetFileA;
//
// Notification callback and context parameter
//
PVOID MsgHandler;
PVOID Context;
BOOL IsMsgHandlerNativeCharWidth;
//
// Full path of the current target file being extracted.
//
PTSTR CurrentTargetFile;
//
// Flag indicating whether diamond asked us to switch cabinets.
// If we do switch, then we stop copying when the current file
// is done. This prevents diamond from happily doing each file
// in the new cabinet, which would ruin the queue commit routine's
// ability to allow some files to exist outside the cabinet, etc.
//
BOOL SwitchedCabinets;
//
// If the source path changes as the result of a prompt for a
// new cabinet (when a file continues across multiple cabinets),
// we remember the path the user gave us here.
//
TCHAR UserPath[MAX_PATH];
} DIAMOND_THREAD_DATA, *PDIAMOND_THREAD_DATA;
BOOL
DiamondInitialize(
VOID
);
int
DIAMONDAPI
SpdFdiOpen(
IN PSTR FileName,
IN int oflag,
IN int pmode
);
int
DIAMONDAPI
SpdFdiClose(
IN int Handle
);
UINT
pDiamondNotifyFileDone(
IN PDIAMOND_THREAD_DATA PerThread,
IN DWORD Win32Error
)
{
UINT u;
FILEPATHS FilePaths;
MYASSERT(PerThread->CurrentTargetFile);
FilePaths.Source = PerThread->CabinetFile;
FilePaths.Target = PerThread->CurrentTargetFile;
FilePaths.Win32Error = Win32Error;
u = pSetupCallMsgHandler(
PerThread->MsgHandler,
PerThread->IsMsgHandlerNativeCharWidth,
PerThread->Context,
SPFILENOTIFY_FILEEXTRACTED,
(UINT)&FilePaths,
0
);
return(u);
}
int
DIAMONDAPI
DiamondNotifyFunction(
IN FDINOTIFICATIONTYPE Operation,
IN PFDINOTIFICATION Parameters
)
{
PDIAMOND_THREAD_DATA PerThread;
int h;
PSTR FileNameA;
CABINET_INFO CabInfo;
FILE_IN_CABINET_INFO FileInCab;
FILETIME FileTime;
TCHAR NewPath[MAX_PATH];
PTSTR p;
PerThread = TlsGetValue(DiamondTlsIndex);
MYASSERT(PerThread);
switch(Operation) {
case fdintCABINET_INFO:
//
// Tell the callback function, in case it wants to do something
// with this information.
//
h = ERROR_NOT_ENOUGH_MEMORY;
CabInfo.CabinetFile = NewPortableString(Parameters->psz1);
if(CabInfo.CabinetFile) {
CabInfo.DiskName = NewPortableString(Parameters->psz2);
if(CabInfo.DiskName) {
CabInfo.CabinetPath = NewPortableString(Parameters->psz3);
if(CabInfo.CabinetPath) {
CabInfo.SetId = Parameters->setID;
CabInfo.CabinetNumber = Parameters->iCabinet;
h = pSetupCallMsgHandler(
PerThread->MsgHandler,
PerThread->IsMsgHandlerNativeCharWidth,
PerThread->Context,
SPFILENOTIFY_CABINETINFO,
(UINT)&CabInfo,
0
);
MyFree(CabInfo.CabinetPath);
}
MyFree(CabInfo.DiskName);
}
MyFree(CabInfo.CabinetFile);
}
if(h != NO_ERROR) {
PerThread->LastError = h;
}
return((h == NO_ERROR) ? 0 : -1);
case fdintCOPY_FILE:
//
// Diamond is asking us whether we want to copy the file.
// If we switched cabinets, then the answer is no.
//
if(PerThread->SwitchedCabinets) {
PerThread->LastError = NO_ERROR;
return(-1);
}
// Pass the information on to the callback function and
// let it decide.
//
FileInCab.NameInCabinet = NewPortableString(Parameters->psz1);
FileInCab.FileSize = Parameters->cb;
FileInCab.DosDate = Parameters->date;
FileInCab.DosTime = Parameters->time;
FileInCab.DosAttribs = Parameters->attribs;
FileInCab.Win32Error = NO_ERROR;
if(!FileInCab.NameInCabinet) {
PerThread->LastError = ERROR_NOT_ENOUGH_MEMORY;
return(-1);
}
//
// Call the callback function.
//
h = pSetupCallMsgHandler(
PerThread->MsgHandler,
PerThread->IsMsgHandlerNativeCharWidth,
PerThread->Context,
SPFILENOTIFY_FILEINCABINET,
(UINT)&FileInCab,
(UINT)PerThread->CabinetFile
);
switch(h) {
case FILEOP_SKIP:
h = 0;
break;
case FILEOP_DOIT:
//
// The callback wants to copy the file. In this case it has
// provided us the full target pathname to use.
//
MYASSERT(PerThread->CurrentTargetFile == NULL);
if(p = DuplicateString(FileInCab.FullTargetName)) {
if(FileNameA = NewAnsiString(FileInCab.FullTargetName)) {
h = _lcreat(FileNameA,0);
if(h == HFILE_ERROR) {
PerThread->LastError = GetLastError();
h = -1;
}
MyFree(FileNameA);
//
// If we get here, a file is being processed.
//
if(h == -1) {
MyFree(p);
} else {
PerThread->CurrentTargetFile = p;
}
} else {
PerThread->LastError = ERROR_NOT_ENOUGH_MEMORY;
MyFree(p);
h = -1;
}
} else {
PerThread->LastError = ERROR_NOT_ENOUGH_MEMORY;
h = -1;
}
break;
default:
//
// Abort.
//
h = -1;
PerThread->LastError = FileInCab.Win32Error;
break;
}
return(h);
case fdintCLOSE_FILE_INFO:
//
// Diamond is done with the target file and wants us to close it.
// (ie, this is the counterpart to fdintCOPY_FILE).
//
// We want the timestamp to be what is stored in the cabinet.
// Note that we lose the create and last access times in this case.
//
if(DosDateTimeToFileTime(Parameters->date,Parameters->time,&FileTime)) {
SetFileTime((HANDLE)Parameters->hf,NULL,NULL,&FileTime);
}
SpdFdiClose(Parameters->hf);
//
// Call the callback function to inform it that the file has been
// successfully extracted from the cabinet.
//
MYASSERT(PerThread->CurrentTargetFile);
h = pDiamondNotifyFileDone(PerThread,NO_ERROR);
if(h != NO_ERROR) {
PerThread->LastError = h;
}
MyFree(PerThread->CurrentTargetFile);
PerThread->CurrentTargetFile = NULL;
return((h == NO_ERROR) ? TRUE : -1);
case fdintPARTIAL_FILE:
//
// We don't do anything with this.
//
return(0);
case fdintNEXT_CABINET:
if((Parameters->fdie == FDIERROR_NONE) || (Parameters->fdie == FDIERROR_WRONG_CABINET)) {
//
// A file continues into another cabinet.
// Inform the callback function, who is responsible for
// making sure the cabinet is accessible when it returns.
//
h = ERROR_NOT_ENOUGH_MEMORY;
CabInfo.SetId = 0;
CabInfo.CabinetNumber = 0;
CabInfo.CabinetPath = NewPortableString(Parameters->psz3);
if(CabInfo.CabinetPath) {
CabInfo.CabinetFile = NewPortableString(Parameters->psz1);
if(CabInfo.CabinetFile) {
CabInfo.DiskName = NewPortableString(Parameters->psz2);
if(CabInfo.DiskName) {
h = pSetupCallMsgHandler(
PerThread->MsgHandler,
PerThread->IsMsgHandlerNativeCharWidth,
PerThread->Context,
SPFILENOTIFY_NEEDNEWCABINET,
(UINT)&CabInfo,
(UINT)NewPath
);
if(h == NO_ERROR) {
//
// See if a new path was specified.
//
if(NewPath[0]) {
lstrcpyn(PerThread->UserPath,NewPath,MAX_PATH);
}
//
// Remember that we switched cabinets.
//
PerThread->SwitchedCabinets = TRUE;
}
MyFree(CabInfo.DiskName);
}
MyFree(CabInfo.CabinetFile);
}
MyFree(CabInfo.CabinetPath);
}
} else {
//
// Some other error we don't understand -- this indicates
// a bad cabinet.
//
h = ERROR_INVALID_DATA;
}
if(h != NO_ERROR) {
PerThread->LastError = h;
}
return((h == NO_ERROR) ? 0 : -1);
default:
//
// Unknown notification type. Should never get here.
//
MYASSERT(0);
return(0);
}
}
PVOID
DIAMONDAPI
SpdFdiAlloc(
IN ULONG NumberOfBytes
)
/*++
Routine Description:
Callback used by FDICopy to allocate memory.
Arguments:
NumberOfBytes - supplies desired size of block.
Return Value:
Returns pointer to a block of memory or NULL
if memory cannot be allocated.
--*/
{
return(MyMalloc(NumberOfBytes));
}
VOID
DIAMONDAPI
SpdFdiFree(
IN PVOID Block
)
/*++
Routine Description:
Callback used by FDICopy to free a memory block.
The block must have been allocated with SpdFdiAlloc().
Arguments:
Block - supplies pointer to block of memory to be freed.
Return Value:
None.
--*/
{
MyFree(Block);
}
int
DIAMONDAPI
SpdFdiOpen(
IN PSTR FileName,
IN int oflag,
IN int pmode
)
/*++
Routine Description:
Callback used by FDICopy to open files.
This routine is capable only of opening existing files.
Arguments:
FileName - supplies name of file to be opened.
oflag - supplies flags for open.
pmode - supplies additional flags for open.
Return Value:
Handle to open file or -1 if error occurs.
--*/
{
HFILE h;
PDIAMOND_THREAD_DATA PerThread;
UNREFERENCED_PARAMETER(pmode);
PerThread = TlsGetValue(DiamondTlsIndex);
MYASSERT(PerThread);
if(oflag & (_O_WRONLY | _O_RDWR | _O_APPEND | _O_CREAT | _O_TRUNC | _O_EXCL)) {
PerThread->LastError = ERROR_INVALID_PARAMETER;
return(-1);
}
h = _lopen(FileName,OF_READ | OF_SHARE_DENY_WRITE);
if(h == HFILE_ERROR) {
PerThread->LastError = GetLastError();
return(-1);
}
return((int)h);
}
UINT
DIAMONDAPI
SpdFdiRead(
IN int Handle,
OUT PVOID pv,
IN UINT ByteCount
)
/*++
Routine Description:
Callback used by FDICopy to read from a file.
Arguments:
Handle - supplies handle to open file to be read from.
pv - supplies pointer to buffer to receive bytes we read.
ByteCount - supplies number of bytes to read.
Return Value:
Number of bytes read (ByteCount) or -1 if an error occurs.
--*/
{
UINT rc;
PDIAMOND_THREAD_DATA PerThread;
DWORD d;
rc = _lread((HFILE)Handle,pv,ByteCount);
if(rc == HFILE_ERROR) {
rc = (UINT)(-1);
d = GetLastError();
PerThread = TlsGetValue(DiamondTlsIndex);
MYASSERT(PerThread);
PerThread->LastError = d;
}
return(rc);
}
UINT
DIAMONDAPI
SpdFdiWrite(
IN int Handle,
IN PVOID pv,
IN UINT ByteCount
)
/*++
Routine Description:
Callback used by FDICopy to write to a file.
Arguments:
Handle - supplies handle to open file to be written to.
pv - supplies pointer to buffer containing bytes to write.
ByteCount - supplies number of bytes to write.
Return Value:
Number of bytes written (ByteCount) or -1 if an error occurs.
--*/
{
UINT rc;
PDIAMOND_THREAD_DATA PerThread;
DWORD d;
rc = _lwrite((HFILE)Handle,pv,ByteCount);
if(rc == HFILE_ERROR) {
rc = (UINT)(-1);
d = GetLastError();
PerThread = TlsGetValue(DiamondTlsIndex);
MYASSERT(PerThread);
PerThread->LastError = d;
}
return(rc);
}
int
DIAMONDAPI
SpdFdiClose(
IN int Handle
)
/*++
Routine Description:
Callback used by FDICopy to close files.
Arguments:
Handle - handle of file to close.
Return Value:
0 (success).
--*/
{
HFILE h;
h = _lclose((HFILE)Handle);
MYASSERT(h == 0);
return(0);
}
long
DIAMONDAPI
SpdFdiSeek(
IN int Handle,
IN long Distance,
IN int SeekType
)
/*++
Routine Description:
Callback used by FDICopy to seek files.
Arguments:
Handle - handle of file to close.
Distance - supplies distance to seek. Interpretation of this
parameter depends on the value of SeekType.
SeekType - supplies a value indicating how Distance is to be
interpreted; one of SEEK_SET, SEEK_CUR, SEEK_END.
Return Value:
New file offset or -1 if an error occurs.
--*/
{
LONG rc;
DWORD d;
PDIAMOND_THREAD_DATA PerThread;
rc = _llseek((HFILE)Handle,Distance,SeekType);
if(rc == HFILE_ERROR) {
d = GetLastError();
PerThread = TlsGetValue(DiamondTlsIndex);
MYASSERT(PerThread);
PerThread->LastError = d;
rc = -1L;
}
return(rc);
}
DWORD
DiamondProcessCabinet(
IN PCTSTR CabinetFile,
IN DWORD Flags,
IN PVOID MsgHandler,
IN PVOID Context,
IN BOOL IsMsgHandlerNativeCharWidth
)
/*++
Routine Description:
Process a diamond cabinet file, iterating through all files
contained within it and calling the callback function with
information about each file.
Arguments:
SourceFileName - supplies name of cabinet file.
Flags - supplies flags to control behavior of cabinet processing.
MsgHandler - Supplies a callback routine to be notified
of various significant events in cabinet processing.
Context - Supplies a value that is passed to the MsgHandler
callback function.
Return Value:
Win32 error code indicating result. If the cabinet was corrupt,
ERROR_INVALID_DATA is returned.
--*/
{
BOOL b;
DWORD rc;
PDIAMOND_THREAD_DATA PerThread;
PSTR CabinetFileA;
PSTR p,FilePartA,PathPartA;
CHAR c;
int h;
UNREFERENCED_PARAMETER(Flags);
//
// Initialize diamond for this thread if not
// already initialized.
//
if(!DiamondInitialize()) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto c0;
}
//
// Fetch pointer to per-thread data.
//
PerThread = TlsGetValue(DiamondTlsIndex);
MYASSERT(PerThread);
MYASSERT(PerThread->FdiContext);
//
// Because diamond does not really give us a truly comprehensive
// context mechanism, our diamond support is NOT reentrant.
// No synchronization is required to check this state because
// it is stored in per-thread data.
//
if(PerThread->InDiamond) {
rc = ERROR_INVALID_FUNCTION;
goto c0;
}
PerThread->InDiamond = TRUE;
//
// Get an ANSI version of the name because diamond is not unicode.
//
CabinetFileA = NewAnsiString(CabinetFile);
if(!CabinetFileA) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto c1;
}
//
// Split the cabinet name into path and name.
// Make separate copies because we want to remember the
// full ansi version of the fill cabinet filename we were passed,
// so we'll leave CabinetFileA alone.
//
if(FilePartA = strrchr(CabinetFileA,'\\')) {
FilePartA++;
} else {
FilePartA = CabinetFileA;
}
c = *FilePartA;
*FilePartA = 0;
PathPartA = _strdup(CabinetFileA);
*FilePartA = c;
if(!PathPartA) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto c2;
}
FilePartA = _strdup(FilePartA);
if(!FilePartA) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto c3;
}
//
// Initialize thread globals.
//
PerThread->LastError = NO_ERROR;
PerThread->CabinetFile = CabinetFile;
PerThread->CabinetFileA = CabinetFileA;
PerThread->MsgHandler = MsgHandler;
PerThread->IsMsgHandlerNativeCharWidth = IsMsgHandlerNativeCharWidth;
PerThread->Context = Context;
PerThread->SwitchedCabinets = FALSE;
PerThread->UserPath[0] = 0;
PerThread->CurrentTargetFile = NULL;
//
// Perform the copy.
//
b = FDICopy(
PerThread->FdiContext,
FilePartA,
PathPartA,
0, // flags
DiamondNotifyFunction,
NULL, // no decryption
NULL // don't bother with user-specified data
);
if(b) {
//
// Everything succeeded so we shouldn't have any partially
// processed files.
//
MYASSERT(!PerThread->CurrentTargetFile);
rc = NO_ERROR;
} else {
switch(PerThread->FdiError.erfOper) {
case FDIERROR_NONE:
//
// We shouldn't see this -- if there was no error
// then FDICopy should have returned TRUE.
//
MYASSERT(PerThread->FdiError.erfOper != FDIERROR_NONE);
rc = ERROR_INVALID_DATA;
break;
case FDIERROR_CABINET_NOT_FOUND:
rc = ERROR_FILE_NOT_FOUND;
break;
case FDIERROR_CORRUPT_CABINET:
//
// Read/open/seek error or corrupt cabinet
//
rc = PerThread->LastError;
if(rc == NO_ERROR) {
rc = ERROR_INVALID_DATA;
}
break;
case FDIERROR_ALLOC_FAIL:
rc = ERROR_NOT_ENOUGH_MEMORY;
break;
case FDIERROR_TARGET_FILE:
case FDIERROR_USER_ABORT:
rc = PerThread->LastError;
break;
case FDIERROR_NOT_A_CABINET:
case FDIERROR_UNKNOWN_CABINET_VERSION:
case FDIERROR_BAD_COMPR_TYPE:
case FDIERROR_MDI_FAIL:
case FDIERROR_RESERVE_MISMATCH:
case FDIERROR_WRONG_CABINET:
default:
//
// Cabinet is corrupt or not actually a cabinet, etc.
//
rc = ERROR_INVALID_DATA;
break;
}
if(PerThread->CurrentTargetFile) {
//
// Call the callback function to inform it that the last file
// was not successfully extracted from the cabinet.
// Also remove the partially copied file.
//
DeleteFile(PerThread->CurrentTargetFile);
pDiamondNotifyFileDone(PerThread,rc);
MyFree(PerThread->CurrentTargetFile);
PerThread->CurrentTargetFile = NULL;
}
}
free(FilePartA);
c3:
free(PathPartA);
c2:
MyFree(CabinetFileA);
c1:
PerThread->InDiamond = FALSE;
c0:
return(rc);
}
BOOL
DiamondIsCabinet(
IN PCTSTR FileName
)
/*++
Routine Description:
Determine if a file is a diamond cabinet.
Arguments:
FileName - supplies name of file to be checked.
Return Value:
TRUE if file is diamond file. FALSE if not;
--*/
{
FDICABINETINFO CabinetInfo;
BOOL b;
int h;
PDIAMOND_THREAD_DATA PerThread;
PSTR FileNameA;
b = FALSE;
//
// Initialize diamond for this thread if not
// already initialized.
//
if(!DiamondInitialize()) {
goto c0;
}
PerThread = TlsGetValue(DiamondTlsIndex);
MYASSERT(PerThread);
MYASSERT(PerThread->FdiContext);
//
// Because diamond does not really give us a truly comprehensive
// context mechanism, our diamond support is NOT reentrant.
// No synchronization is required to check this state because
// it is stored in per-thread data.
//
if(PerThread->InDiamond) {
goto c0;
}
PerThread->InDiamond = TRUE;
//
// Unfortunately the diamond engine is not Unicode.
// Convert the filename to ANSI.
//
FileNameA = NewAnsiString(FileName);
if(!FileNameA) {
goto c1;
}
//
// Open the file such that the handle is valid for use
// in the diamond context (ie, seek, read routines above).
//
h = SpdFdiOpen(FileNameA,_O_RDONLY,0);
if(h == -1) {
goto c2;
}
b = FDIIsCabinet(PerThread->FdiContext,h,&CabinetInfo);
SpdFdiClose(h);
c2:
MyFree(FileNameA);
c1:
PerThread->InDiamond = FALSE;
c0:
return(b);
}
BOOL
DiamondInitialize(
VOID
)
/*++
Routine Description:
Per-thread initialization routine for Diamond.
Called internally.
Arguments:
None.
Return Value:
Boolean result indicating success or failure.
Failure can be assumed to be out of memory.
--*/
{
HFDI FdiContext;
PDIAMOND_THREAD_DATA PerThread;
//
// See if this thread is already initialized.
//
if(TlsGetValue(DiamondTlsIndex)) {
return(TRUE);
}
//
// Allocate a per-thread data structure
//
if(PerThread = MyMalloc(sizeof(DIAMOND_THREAD_DATA))) {
ZeroMemory(PerThread,sizeof(DIAMOND_THREAD_DATA));
//
// Initialize a diamond context.
//
FdiContext = FDICreate(
SpdFdiAlloc,
SpdFdiFree,
SpdFdiOpen,
SpdFdiRead,
SpdFdiWrite,
SpdFdiClose,
SpdFdiSeek,
cpuUNKNOWN,
&PerThread->FdiError
);
if(FdiContext) {
if(TlsSetValue(DiamondTlsIndex,PerThread)) {
PerThread->FdiContext = FdiContext;
return(TRUE);
}
FDIDestroy(FdiContext);
}
MyFree(PerThread);
}
return(FALSE);
}
VOID
DiamondTerminate(
VOID
)
/*++
Routine Description:
Per-thread termination routine for Diamond.
Called internally.
Arguments:
None.
Return Value:
Boolean result indicating success or failure.
Failure can be assumed to be out of memory.
--*/
{
PDIAMOND_THREAD_DATA PerThread;
if(PerThread = TlsGetValue(DiamondTlsIndex)) {
FDIDestroy(PerThread->FdiContext);
MyFree(PerThread);
TlsSetValue(DiamondTlsIndex,NULL);
}
}
BOOL
DiamondProcessAttach(
IN BOOL Attach
)
/*++
Routine Description:
Process attach routine. Must be called by the DLL entry point routine
on DLL_PROCESS_ATTACH and DLL_PROCESS_DETACH notifications.
This routine allocates a Tls index on process attach for
thread-specific data used by Diamond. The Tls index is freed on
process detach.
Arguments:
Attach - TRUE if process is attaching; FALSE if not.
Return Value:
Boolean result indicating success or failure. Meaningful only if
Attach is TRUE.
--*/
{
if(Attach) {
//
// Allocate a Tls index.
//
DiamondTlsIndex = TlsAlloc();
return(DiamondTlsIndex != (DWORD)(-1));
} else {
//
// Free the Tls index
//
return(TlsFree(DiamondTlsIndex));
}
}
VOID
DiamondThreadAttach(
IN BOOL Attach
)
/*++
Routine Description:
Thread attach routine. Must be called by the DLL entry point routine
on DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications.
The routine initializes per-thread data used by diamond.
Arguments:
Attach - TRUE if thread is attaching; FALSE if not.
Return Value:
None.
--*/
{
PVOID p;
if(Attach) {
//
// There really isn't any reason to do the initialization here
// because it will get done on entry to externally exposed API.
// (We have to do that, in case someone uses LoadLibrary and then
// calls Diamond from a thread that existed before the LoadLibrary.)
//
//DiamondInitialize();
} else {
DiamondTerminate();
}
}
///////////////////////////////////////////////////////////////////////////
#if 0
HFCI
DiamondCreateCabinet(
IN PCTSTR FileName
)
{
HFCI hfci;
//
// Initialize diamond for this thread if not
// already initialized.
//
if(!DiamondInitialize()) {
goto c0;
}
PerThread = TlsGetValue(DiamondTlsIndex);
MYASSERT(PerThread);
hfci = FCICreate(
&PerThread->FdiError,
SpdFciFilePlaced,
SpdFdiAlloc,
SpdFdiFree,
SpdFciGetTempFile,
&Cabinfo
);
return(hfci);
}
#endif
///////////////////////////////////////////////////////////////////////////
BOOL
_SetupIterateCabinet(
IN PCTSTR CabinetFile,
IN DWORD Flags,
IN PVOID MsgHandler,
IN PVOID Context,
IN BOOL IsMsgHandlerNativeCharWidth
)
{
PTSTR cabinetFile;
DWORD rc;
//
// Flags param not used. Make sure it's zero.
//
if(Flags) {
rc = ERROR_INVALID_PARAMETER;
goto c0;
}
//
// Get a copy of the cabinet file name to validate
// the caller's buffer.
//
try {
cabinetFile = DuplicateString(CabinetFile);
} except(EXCEPTION_EXECUTE_HANDLER) {
rc = ERROR_INVALID_PARAMETER;
goto c0;
}
if(!cabinetFile) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto c0;
}
rc = DiamondProcessCabinet(cabinetFile,Flags,MsgHandler,Context,IsMsgHandlerNativeCharWidth);
MyFree(cabinetFile);
c0:
SetLastError(rc);
return(rc == NO_ERROR);
}
#ifdef UNICODE
//
// ANSI version
//
BOOL
SetupIterateCabinetA(
IN PCSTR CabinetFile,
IN DWORD Flags,
IN PSP_FILE_CALLBACK_A MsgHandler,
IN PVOID Context
)
{
BOOL b;
DWORD rc;
PCWSTR cabinetFile;
rc = CaptureAndConvertAnsiArg(CabinetFile,&cabinetFile);
if(rc == NO_ERROR) {
b = _SetupIterateCabinet(cabinetFile,Flags,MsgHandler,Context,FALSE);
rc = GetLastError();
MyFree(cabinetFile);
} else {
b = FALSE;
}
SetLastError(rc);
return(b);
}
#else
//
// Unicode stub
//
BOOL
SetupIterateCabinetW(
IN PCWSTR CabinetFile,
IN DWORD Flags,
IN PSP_FILE_CALLBACK_W MsgHandler,
IN PVOID Context
)
{
UNREFERENCED_PARAMETER(CabinetFile);
UNREFERENCED_PARAMETER(Flags);
UNREFERENCED_PARAMETER(MsgHandler);
UNREFERENCED_PARAMETER(Context);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return(FALSE);
}
#endif
BOOL
SetupIterateCabinet(
IN PCTSTR CabinetFile,
IN DWORD Flags,
IN PSP_FILE_CALLBACK MsgHandler,
IN PVOID Context
)
{
return(_SetupIterateCabinet(CabinetFile,Flags,MsgHandler,Context,TRUE));
}