/*++ 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); }