|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
expandit.c
Abstract:
Expandit provides routines to expand a given file as much as possible. It is useful for expanding cabinet files and executable files that may themselves contain cabinet files.
Author:
Marc R. Whitten (marcw) 30-Jul-1998
Revision History:
--*/
#include "pch.h"
#include "migutilp.h"
UINT g_DirSequencer = 0;
BOOL ExpandAllFilesW ( IN PCWSTR FileDir, IN PCWSTR TempDir );
BOOL ExpandFileW ( IN PCWSTR FullPath, IN PCWSTR TempDir );
PWSTR pGetExpandName ( VOID ) { static WCHAR rName[MAX_WCHAR_PATH];
g_DirSequencer++; swprintf (rName, L"EXP%04x", g_DirSequencer);
return rName; }
BOOL pIsFileType ( IN PCWSTR FullPath, IN PCWSTR TypePattern ) { PCWSTR p;
p = GetFileExtensionFromPathW (FullPath);
return p && IsPatternMatchW (TypePattern, p); }
BOOL CALLBACK pResNameCallback ( IN HANDLE hModule, // module handle
IN LPCWSTR lpszType, // pointer to resource type
IN LPWSTR lpszName, // pointer to resource name
IN LONG lParam // application-defined parameter
) { HRSRC hResource; DWORD size; HGLOBAL hGlobal; HANDLE hFile; PWSTR fileName; PWSTR dirName; PVOID srcBytes; UINT dontCare; BOOL rSuccess=TRUE;
hResource = FindResourceW (hModule, lpszName, lpszType);
if (hResource) {
size = SizeofResource (hModule, hResource);
if (size) {
hGlobal = LoadResource (hModule, hResource);
if (hGlobal) {
srcBytes = LockResource (hGlobal); if (srcBytes) {
//
// Ok, lets see if this is a cabinet file..
//
if (size < 4 || *((PDWORD)srcBytes) != 0x4643534D) { //
// Not a cabinet file.
//
return TRUE; }
dirName = JoinPathsW ((PWSTR) lParam, pGetExpandName ()); fileName = JoinPathsW (dirName, L"temp.cab");
hFile = CreateFileW ( fileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile == INVALID_HANDLE_VALUE) { DEBUGMSGW ((DBG_ERROR, "Unable to create file %s.", fileName)); return FALSE; }
if (!WriteFile (hFile, srcBytes, size, &dontCare, NULL)) { DEBUGMSGW ((DBG_ERROR, "Cannot write to file %s", fileName)); return FALSE; }
CloseHandle (hFile);
//
// Expand this file.
//
rSuccess = ExpandFileW (fileName, dirName); FreePathStringW (dirName); FreePathStringW (fileName);
} } } }
return rSuccess; }
BOOL CALLBACK pResTypeCallback ( IN HANDLE hModule, // resource-module handle
IN PWSTR lpszType, // pointer to resource type
IN LONG lParam // application-defined parameter
) {
//
// Oh what a pain. All of the RT types are #defined without A/Ws.
// We need to converte the string to ansi, just to do this comparison.
//
PCSTR aString = ConvertWtoA (lpszType);
if ((aString != RT_ACCELERATOR ) && (aString != RT_ANICURSOR ) && (aString != RT_ANIICON ) && (aString != RT_BITMAP ) && (aString != RT_CURSOR ) && (aString != RT_DIALOG ) && (aString != RT_FONT ) && (aString != RT_FONTDIR ) && (aString != RT_GROUP_CURSOR ) && (aString != RT_GROUP_ICON ) && (aString != RT_HTML ) && (aString != RT_ICON ) && (aString != RT_MENU ) && (aString != RT_MESSAGETABLE ) && (aString != RT_PLUGPLAY ) && (aString != RT_STRING ) && (aString != RT_VERSION ) && (aString != RT_VXD ) && (aString != RT_HTML ) ) {
//
// Unknown type. We assume it is a cabinet file and try to extract it.
// Since it may not be a cabinet file, we eat the error.
//
if (!EnumResourceNamesW (hModule, lpszType, pResNameCallback, lParam)) { DEBUGMSGW ((DBG_ERROR, "Error enumerating resource names.")); } }
FreeConvertedStr (aString);
return TRUE; }
UINT CALLBACK pCabFileCallback ( IN PVOID Context, //context used by the callback routine
IN UINT Notification, //notification sent to callback routine
IN UINT Param1, //additional notification information
IN UINT Param2 //additional notification information
) { PCWSTR tempDir = Context; PCWSTR fileName = (PCWSTR)Param2 ; PFILE_IN_CABINET_INFO_W fileInfo = (PFILE_IN_CABINET_INFO_W)Param1; PCWSTR fromPtr, toPtr; WCHAR tempStr [MEMDB_MAX];
if (Notification == SPFILENOTIFY_FILEINCABINET) {
if (toPtr = wcschr (fileInfo->NameInCabinet, L'\\')) {
StringCopyW (fileInfo->FullTargetName, tempDir); fromPtr = fileInfo->NameInCabinet;
while (toPtr) {
StringCopyABW (tempStr, fromPtr, toPtr); StringCatW (fileInfo->FullTargetName, L"\\"); StringCatW (fileInfo->FullTargetName, tempStr); CreateDirectoryW (fileInfo->FullTargetName, NULL); toPtr++; fromPtr = toPtr; toPtr = wcschr (toPtr, L'\\'); } }
swprintf (fileInfo->FullTargetName, L"%ws\\%ws", tempDir, fileInfo->NameInCabinet); return FILEOP_DOIT; }
return NO_ERROR; }
BOOL ExpandFileW ( IN PCWSTR FullPath, IN PCWSTR TempDir ) { BOOL rSuccess = TRUE; PWSTR dirName = NULL; PWSTR fileName = NULL; HANDLE exeModule = NULL; HANDLE hFile = INVALID_HANDLE_VALUE; CHAR aName[MAX_MBCHAR_PATH]; PCWSTR uName = NULL; UINT bytesRead = 0;
if (pIsFileType (FullPath, L"CAB")) { //
// Expand this cabinet file and recursively handle all of its files.
//
dirName = JoinPathsW (TempDir, pGetExpandName()); __try {
if (!CreateDirectoryW (dirName, NULL)) { DEBUGMSGW ((DBG_ERROR, "ExpandFile: Cannot create directory %s", dirName)); rSuccess = FALSE; __leave; }
//
// Expand the cabinet file into the temporary directory.
//
SetLastError (ERROR_SUCCESS); if (!SetupIterateCabinetW (FullPath, 0, pCabFileCallback, dirName)) { DEBUGMSGW ((DBG_ERROR, "ExpandFile: SetupIterateCabinet failed for file %s.", FullPath)); rSuccess = FALSE; __leave; }
//
// Now, make sure all of the files in this SubDirectory are expanded.
//
rSuccess = ExpandAllFilesW (dirName, dirName); } __finally {
FreePathStringW (dirName); }
} else if (pIsFileType (FullPath, L"EXE")) {
//
// This is an executable file. Check to make sure that they aren't any cabinet files hanging out
// inside of it.
//
exeModule = LoadLibraryExW (FullPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (!exeModule) { DEBUGMSGW ((DBG_ERROR, "ExpandFile: LoadLibraryEx failed for %s.", FullPath)); return FALSE; }
if (!EnumResourceTypesW (exeModule, pResTypeCallback, (LONG) TempDir)) { DEBUGMSGW ((DBG_ERROR, "ExpandFile: EnumResourceTypes failed for %s.", FullPath)); FreeLibrary (exeModule); return FALSE; }
} else if (pIsFileType (FullPath, L"*_")) {
//
// Compressed file. Decompress it.
//
hFile = CreateFileW ( FullPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hFile == INVALID_HANDLE_VALUE) { DEBUGMSGW ((DBG_ERROR, "ExpandFile: Unable to open file %s.", FullPath)); return FALSE; }
__try {
//
// The real file name is stored at 0x3c.
//
if (0xffffffff == SetFilePointer (hFile, 0x3c, NULL, FILE_BEGIN)) { DEBUGMSGW ((DBG_ERROR, "ExpandFile: Cannot get real file name for compressed file %s.", FullPath)); rSuccess = FALSE; __leave; }
if (!ReadFile (hFile, aName, sizeof(aName), &bytesRead, NULL)) { DEBUGMSG ((DBG_ERROR, "ExpandFile: Cannot read real file name for compressed file %s.", FullPath)); rSuccess = FALSE; __leave; }
if (bytesRead >= ByteCountW (FullPath)) {
uName = ConvertAtoW (aName);
if (StringIMatchTcharCountW (FullPath, uName, TcharCountW (FullPath) - 1)) {
dirName = JoinPathsW (TempDir, pGetExpandName()); fileName = JoinPathsW (dirName, uName);
//
// Create directory for this file and decompress it.
//
if (!CreateDirectoryW (dirName, NULL)) { DEBUGMSGW ((DBG_ERROR, "ExpandFile: Cannot create directory %s", dirName)); rSuccess = FALSE; __leave; }
if (SetupDecompressOrCopyFileW (FullPath, fileName, NULL) != ERROR_SUCCESS) { DEBUGMSGW ((DBG_ERROR, "ExpandFile: Cannot decompreses %s => %s.", FullPath, fileName)); rSuccess = FALSE; __leave; }
//
// Now, run expand recursively on the decompressed file. Could be a CAB or an EXE.
//
rSuccess = ExpandFileW (fileName, dirName); }
}
} __finally {
CloseHandle (hFile); FreePathStringW (dirName); FreePathStringW (fileName);
}
}
return rSuccess; }
BOOL ExpandAllFilesW ( IN PCWSTR FileDir, IN PCWSTR TempDir ) { BOOL rSuccess = TRUE; TREE_ENUMW e;
if (EnumFirstFileInTreeW (&e, FileDir, L"*", FALSE)) { do {
if (!e.Directory) { rSuccess &= ExpandFileW (e.FullPath, TempDir); }
} while (EnumNextFileInTreeW (&e)); }
DEBUGMSGW_IF ((!rSuccess,DBG_ERROR, "ExpandAllFilesW: One or more errors occurred while expanding all files in %s.", FileDir));
return rSuccess; }
BOOL ExpandFileA ( IN PCSTR FullPath, IN PCSTR TempDir ) {
PCWSTR wFullPath = NULL; PCWSTR wTempDir = NULL; BOOL rSuccess = TRUE;
MYASSERT(FullPath && TempDir);
//
// Convert args and call W version.
//
wFullPath = ConvertAtoW (FullPath); wTempDir = ConvertAtoW (TempDir);
MYASSERT (wFullPath && wTempDir);
rSuccess = ExpandFileW (wFullPath, wTempDir);
FreeConvertedStr (wFullPath); FreeConvertedStr (wTempDir);
return rSuccess; }
BOOL ExpandAllFilesA ( IN PCSTR FileDir, IN PCSTR TempDir ) {
PCWSTR wFileDir = NULL; PCWSTR wTempDir = NULL; BOOL rSuccess = TRUE;
MYASSERT(FileDir && TempDir);
//
// Convert args and call W version.
//
wFileDir = ConvertAtoW (FileDir); wTempDir = ConvertAtoW (TempDir);
MYASSERT (wFileDir && wTempDir);
rSuccess = ExpandAllFilesW (wFileDir, wTempDir);
FreeConvertedStr (wFileDir); FreeConvertedStr (wTempDir);
return rSuccess; }
|