windows-nt/Source/XPSP1/NT/base/pnp/setupapi/ntcab.c
2020-09-26 16:20:57 +08:00

437 lines
8 KiB
C

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
ntcab.c
Abstract:
NTCab compression support.
Author:
Ted Miller (tedm) 31-Jan-1995
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
BOOL
NtCabNotifyFunction(
IN PNTCAB_ENUM_DATA EnumData,
IN PVOID Cntxt
)
{
PNTCABCONTEXT Context = Cntxt;
BOOL rc;
DWORD Operation;
PSTR FileNameA;
CABINET_INFO CabInfo;
FILE_IN_CABINET_INFO FileInCab;
FILETIME FileTime, UtcTime;
TCHAR NewPath[MAX_PATH];
PTSTR p;
rc = ((PSP_NTCAB_CALLBACK)Context->MsgHandler)( EnumData, Context, &Operation );
if (rc == ERROR_REQUEST_ABORTED) {
//
// this means stop making callback
//
return(FALSE);
}
#if 0
switch(Operation) {
case FILEOP_SKIP:
//
// do nothing
//
;
break;
case FILEOP_DOIT:
;
break;
default:
//
// Abort.
//
return(FALSE);
break;
}
#endif
return(TRUE);
}
#ifdef UNICODE
DWORD
NtCabProcessCabinet(
//IN PVOID InCabHandle, OPTIONAL
IN PCTSTR CabinetFile,
IN DWORD Flags,
IN PVOID MsgHandler,
IN PVOID Context,
IN BOOL IsMsgHandlerNativeCharWidth
)
/*++
Routine Description:
Process an ntcab file, iterating through all files
contained within it and calling the callback function with
information about each file.
Arguments:
CabHandle - supplies a handle to the cab file, if it already exists,
otherwise, a new handle is created
CabinetFile - 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;
PWSTR CabCopy, FilePart,PathPart,tmp;
WCHAR c;
WCHAR fullcab[MAX_PATH];
int h;
PVOID CabHandle;
NTCABCONTEXT CabContext;
UNREFERENCED_PARAMETER(Flags);
//
// Initialize diamond for this thread if not
// already initialized.
//
//if(!InCabHandle) {
CabHandle = NtCabInitialize();
if (!CabHandle) {
rc = ERROR_INVALID_HANDLE;
goto c0;
}
//} else {
// CabHandle = InCabHandle;
//}
if (!CabinetFile) {
rc = ERROR_INVALID_PARAMETER;
goto c1;
}
MYASSERT( CabHandle != NULL );
MYASSERT( CabinetFile != NULL );
//
// make a copy because the input is const
//
CabCopy = DuplicateString(CabinetFile);
if (!CabCopy) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto c1;
}
//
// Split the cabinet name into path and name.
// Make separate copies because we want to remember the
//
if(FilePart = wcsrchr(CabCopy, L'\\')) {
FilePart++;
} else {
FilePart = CabCopy;
}
c = *FilePart;
*FilePart = 0;
PathPart = DuplicateString(CabCopy);
*FilePart = c;
if(!PathPart) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto c2;
}
FilePart = DuplicateString(FilePart);
if(!FilePart) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto c3;
}
MyFree( CabCopy );
MYASSERT( FilePart != NULL && PathPart != NULL );
rc = GetFullPathName(CabinetFile,MAX_PATH,fullcab,&tmp);
if (!rc || rc > MAX_PATH) {
rc = ERROR_BUFFER_OVERFLOW;
goto c4;
} else if (GetFileAttributes(fullcab) == 0xFFFFFFFF) {
rc = ERROR_FILE_NOT_FOUND;
goto c4;
}
if (!NtCabOpenCabFile(CabHandle,fullcab)) {
rc = ERROR_INVALID_DATA;
goto c4;
}
CabContext.hCab = CabHandle;
CabContext.UserContext = Context;
CabContext.CabFile = CabinetFile;
CabContext.FilePart = FilePart;
CabContext.PathPart = PathPart;
CabContext.IsMsgHandlerNativeCharWidth = IsMsgHandlerNativeCharWidth;
CabContext.MsgHandler = MsgHandler;
CabContext.LastError = ERROR_SUCCESS;
CabContext.CurrentTargetFile = NULL;
//CabContext.UserPath[0] = 0;
//CabContext.SwitchedCabinets = FALSE ;
//
// call cab enumeration callback
//
b = NtCabEnumerateFiles(
CabHandle,
(PNTCABFILEENUM)NtCabNotifyFunction,
(ULONG_PTR)&CabContext);
if(b && GetLastError()==ERROR_NO_MORE_FILES) {
//
// Everything succeeded so we shouldn't have any partially
// processed files.
//
SetLastError(NO_ERROR);
MYASSERT(!CabContext.CurrentTargetFile);
rc = NO_ERROR;
} else {
rc = CabContext.LastError;
#if 0
switch(CabContext.LastError) {
case :
break;
default:
//
// Cabinet is corrupt or not actually a cabinet, etc.
//
rc = ERROR_INVALID_DATA;
break;
}
#endif
if(CabContext.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(CabContext.CurrentTargetFile);
CabContext.CurrentTargetFile = NULL;
}
}
c4:
MyFree(FilePart);
c3:
MyFree(PathPart);
c2:
MyFree(CabCopy);
c1:
//if (CabHandle != InCabHandle) {
NtCabClose( CabHandle );
//}
c0:
return(rc);
}
#else
DWORD
NtCabProcessCabinet(
//IN PVOID InCabHandle, OPTIONAL
IN PCTSTR CabinetFile,
IN DWORD Flags,
IN PVOID MsgHandler,
IN PVOID Context,
IN BOOL IsMsgHandlerNativeCharWidth
)
{
//UNREFERENCED_PARAMETER(InCabHandle);
UNREFERENCED_PARAMETER(CabinetFile);
UNREFERENCED_PARAMETER(Flags);
UNREFERENCED_PARAMETER(MsgHandler);
UNREFERENCED_PARAMETER(Context);
UNREFERENCED_PARAMETER(IsMsgHandlerNativeCharWidth);
return(ERROR_CALL_NOT_IMPLEMENTED);
}
#endif
#ifdef UNICODE
BOOL
NtCabIsCabinet(
IN PCWSTR CabinetFile
)
/*++
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;
--*/
{
DWORD rc;
PVOID CabHandle;
WCHAR fullcab[MAX_PATH];
PWSTR tmp;
CabHandle = NtCabInitialize();
if (!CabHandle) {
rc = ERROR_INVALID_DATA;
goto c0;
}
rc = GetFullPathName(CabinetFile,MAX_PATH,fullcab,&tmp);
if (!rc || rc > MAX_PATH) {
rc = ERROR_BUFFER_OVERFLOW;
goto c1;
} else if (GetFileAttributes(fullcab) == 0xFFFFFFFF) {
rc = ERROR_FILE_NOT_FOUND;
goto c1;
}
if (!NtCabOpenCabFile(CabHandle,fullcab)) {
rc = ERROR_INVALID_DATA;
goto c1;
}
rc = ERROR_SUCCESS;
c1:
NtCabClose(CabHandle);
c0:
return(rc == ERROR_SUCCESS);
}
#else
BOOL
NtCabIsCabinet(
IN PCWSTR FileName
)
{
UNREFERENCED_PARAMETER(FileName);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return(FALSE);
}
#endif
PVOID
NtCabAlloc(
IN ULONG NumberOfBytes
)
/*++
Routine Description:
Callback used by cab callback 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
NtCabFree(
IN PVOID Block
)
/*++
Routine Description:
Callback used by cab callback to free a memory block.
The block must have been allocated with NtCabAlloc().
Arguments:
Block - supplies pointer to block of memory to be freed.
Return Value:
None.
--*/
{
MyFree(Block);
}