184 lines
4.9 KiB
C++
184 lines
4.9 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
RecopyExeFromCD.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This shim waits for CloseHandle to be called on the appropriate .exe file.
|
||
|
Once this call has been made, CopyFile is called to recopy the executable
|
||
|
due to truncation of the file during install.
|
||
|
|
||
|
History:
|
||
|
|
||
|
12/08/1999 a-jamd Created
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
|
||
|
IMPLEMENT_SHIM_BEGIN(RecopyExeFromCD)
|
||
|
#include "ShimHookMacro.h"
|
||
|
|
||
|
APIHOOK_ENUM_BEGIN
|
||
|
APIHOOK_ENUM_ENTRY(CreateFileA)
|
||
|
APIHOOK_ENUM_ENTRY(CloseHandle)
|
||
|
APIHOOK_ENUM_END
|
||
|
|
||
|
// The following variables are used to keep track of the file handle,
|
||
|
// the source path and the destination path.
|
||
|
HANDLE g_hInterestingHandle = NULL;
|
||
|
CString * g_wszSourcePath = NULL;
|
||
|
CString * g_wszDestinationPath = NULL;
|
||
|
BOOL g_bInCopyFile = FALSE;
|
||
|
|
||
|
// The following array specifies what the valid names of executables to
|
||
|
// be recopied are. Add to these lists when new apps requiring this shim are
|
||
|
// found.
|
||
|
WCHAR *g_rgszExes[] = {
|
||
|
L"eaw.exe",
|
||
|
L"GK3.EXE",
|
||
|
};
|
||
|
|
||
|
#define N_RECOPY_EXE (sizeof(g_rgszExes) / sizeof(g_rgszExes[0]))
|
||
|
|
||
|
/*++
|
||
|
|
||
|
This stub function breaks into CreateFileA and checks to see if the file in
|
||
|
use is a known .exe file. If it is, APIHook_CreateFileA determines if
|
||
|
lpFileName is the source path or the destination and saves it. When the
|
||
|
file is the destination, the handle returned by CreateFile is also saved
|
||
|
for my check in CloseHandle.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
HANDLE
|
||
|
APIHOOK(CreateFileA)(
|
||
|
LPSTR lpFileName,
|
||
|
DWORD dwDesiredAccess,
|
||
|
DWORD dwShareMode,
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||
|
DWORD dwCreationDisposition,
|
||
|
DWORD dwFlagsAndAttributes,
|
||
|
HANDLE hTemplateFile
|
||
|
)
|
||
|
{
|
||
|
HANDLE hRet = ORIGINAL_API(CreateFileA)(
|
||
|
lpFileName,
|
||
|
dwDesiredAccess,
|
||
|
dwShareMode,
|
||
|
lpSecurityAttributes,
|
||
|
dwCreationDisposition,
|
||
|
dwFlagsAndAttributes,
|
||
|
hTemplateFile);
|
||
|
|
||
|
if (hRet != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
CString csFilePartOnly;
|
||
|
CString csFileName(lpFileName);
|
||
|
csFileName.GetFullPathNameW();
|
||
|
csFileName.GetLastPathComponent(csFilePartOnly);
|
||
|
|
||
|
// Should be d:\ or somesuch
|
||
|
CString csDir;
|
||
|
csFileName.Mid(0, 3, csDir);
|
||
|
UINT uiDriveType = GetDriveTypeW(csDir);
|
||
|
|
||
|
for (int i = 0; i < N_RECOPY_EXE; ++i)
|
||
|
{
|
||
|
const WCHAR * lpszRecopy = g_rgszExes[i];
|
||
|
|
||
|
// Find out if one of the known .exe files is the file in use
|
||
|
|
||
|
if (csFilePartOnly.CompareNoCase(lpszRecopy) == 0)
|
||
|
{
|
||
|
if (uiDriveType != DRIVE_CDROM)
|
||
|
{
|
||
|
// Known .exe file was found in the filename, and it wasn't on the CDRom.
|
||
|
// There is also a valid handle.
|
||
|
g_hInterestingHandle = hRet;
|
||
|
g_wszDestinationPath = new CString(csFileName);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Known .exe was found in the filename, and the drive is a CDRom.
|
||
|
// This is the path to the source and must be stored for later.
|
||
|
g_wszSourcePath = new CString(csFileName);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
This stub function breaks into CloseHandle and checks to see if the handle in
|
||
|
use is the handle to a known .exe. If it is, APIHook_CloseHandle calls
|
||
|
CopyFile and copies the known .exe from the CDRom to the destination.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL
|
||
|
APIHOOK(CloseHandle)(HANDLE hObject)
|
||
|
{
|
||
|
BOOL bRet;
|
||
|
|
||
|
bRet = ORIGINAL_API(CloseHandle)(hObject);
|
||
|
|
||
|
// Find out if g_hInterestingHandle is being closed
|
||
|
if ((hObject == g_hInterestingHandle) &&
|
||
|
g_wszSourcePath &&
|
||
|
g_wszDestinationPath &&
|
||
|
(g_bInCopyFile == FALSE) )
|
||
|
{
|
||
|
// CopyFileA calls CloseHandle, so we must maintain the recursive state
|
||
|
// to fix a recursion problem
|
||
|
g_bInCopyFile = TRUE;
|
||
|
|
||
|
// Correct Handle
|
||
|
// Call CopyFile and recopy the known .exe file from the CDRom to the
|
||
|
// destination
|
||
|
CopyFileW( g_wszSourcePath->Get(), g_wszDestinationPath->Get(), FALSE );
|
||
|
|
||
|
LOGN( eDbgLevelWarning, "[CloseHandle] Copied %S from CD to %S", g_wszSourcePath->Get(), g_wszDestinationPath->Get());
|
||
|
|
||
|
// Since copying from the CDRom, and attributes are carried over, the
|
||
|
// file attributes must be set
|
||
|
SetFileAttributesW( g_wszDestinationPath->Get(), FILE_ATTRIBUTE_NORMAL );
|
||
|
|
||
|
g_bInCopyFile = FALSE;
|
||
|
g_hInterestingHandle = NULL;
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Register hooked functions
|
||
|
|
||
|
--*/
|
||
|
|
||
|
HOOK_BEGIN
|
||
|
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CreateFileA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CloseHandle)
|
||
|
|
||
|
HOOK_END
|
||
|
|
||
|
|
||
|
IMPLEMENT_SHIM_END
|
||
|
|