2621 lines
80 KiB
C++
2621 lines
80 KiB
C++
|
|
||
|
/*++
|
||
|
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
CorrectFilePaths.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This APIHooks CreateProcess and attempts to convert paths from Win9x locations to Win2000
|
||
|
locations. For example "C:\WINNT\WRITE.EXE" will be converted to C:\WINNT\SYSTEM32\WRITE.EXE"
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
This APIHook emulates Windows 9x.
|
||
|
|
||
|
Created:
|
||
|
|
||
|
12/15/1999 robkenny
|
||
|
|
||
|
Modified:
|
||
|
|
||
|
03/14/2000 robkenny Now uses ClassCFP instead of global routines.
|
||
|
03/31/2000 robkenny ShellExecuteEx now handle lpDirectory path as well.
|
||
|
05/18/2000 a-sesk GetCommandLineA and GetCommandLineW convert cmd line args to short path.
|
||
|
06/20/2000 robkenny Added SetFileAttributes()
|
||
|
06/22/2000 robkenny Reordered enum list and DECLARE_APIHOOK list to match each other.
|
||
|
--SERIOUS CHANGE--
|
||
|
10/30/2000 robkenny Added path specific fixes.
|
||
|
Command lines now have the EXE path removed and corrected
|
||
|
separately from the remainder of the command line.
|
||
|
11/13/2000 a-alexsm Added SetArguments & SetIconLocation hooks
|
||
|
11/13/2000 robkenny Changed CorrectPath to always return a valid string
|
||
|
by returning the original string. Must call CorrectFree
|
||
|
to properly release the memory.
|
||
|
12/14/2000 prashkud Added hooks for _lopen and _lcreat
|
||
|
03/10/2001 robkenny Do not convert any paths until *after* all shims have been loaded.
|
||
|
03/15/2001 robkenny Converted to CString
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#include "ClassCFP.h"
|
||
|
|
||
|
IMPLEMENT_SHIM_BEGIN(CorrectFilePaths)
|
||
|
#include "ShimHookMacro.h"
|
||
|
|
||
|
|
||
|
APIHOOK_ENUM_BEGIN
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(CreateProcessA)
|
||
|
APIHOOK_ENUM_ENTRY(CreateProcessW)
|
||
|
APIHOOK_ENUM_ENTRY(WinExec)
|
||
|
APIHOOK_ENUM_ENTRY(ShellExecuteA)
|
||
|
APIHOOK_ENUM_ENTRY(ShellExecuteW)
|
||
|
APIHOOK_ENUM_ENTRY(ShellExecuteExA)
|
||
|
APIHOOK_ENUM_ENTRY(ShellExecuteExW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(GetCommandLineA)
|
||
|
APIHOOK_ENUM_ENTRY(GetCommandLineW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileIntA)
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileIntW)
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileSectionA)
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileSectionW)
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileSectionNamesA)
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileSectionNamesW)
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileStringA)
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileStringW)
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileStructA)
|
||
|
APIHOOK_ENUM_ENTRY(GetPrivateProfileStructW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(WritePrivateProfileSectionA)
|
||
|
APIHOOK_ENUM_ENTRY(WritePrivateProfileSectionW)
|
||
|
APIHOOK_ENUM_ENTRY(WritePrivateProfileStringA)
|
||
|
APIHOOK_ENUM_ENTRY(WritePrivateProfileStringW)
|
||
|
APIHOOK_ENUM_ENTRY(WritePrivateProfileStructA)
|
||
|
APIHOOK_ENUM_ENTRY(WritePrivateProfileStructW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(CopyFileA)
|
||
|
APIHOOK_ENUM_ENTRY(CopyFileW)
|
||
|
APIHOOK_ENUM_ENTRY(CopyFileExA)
|
||
|
APIHOOK_ENUM_ENTRY(CopyFileExW)
|
||
|
APIHOOK_ENUM_ENTRY(CreateDirectoryA)
|
||
|
APIHOOK_ENUM_ENTRY(CreateDirectoryW)
|
||
|
APIHOOK_ENUM_ENTRY(CreateDirectoryExA)
|
||
|
APIHOOK_ENUM_ENTRY(CreateDirectoryExW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(CreateFileA)
|
||
|
APIHOOK_ENUM_ENTRY(CreateFileW)
|
||
|
APIHOOK_ENUM_ENTRY(DeleteFileA)
|
||
|
APIHOOK_ENUM_ENTRY(DeleteFileW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(FindFirstFileA)
|
||
|
APIHOOK_ENUM_ENTRY(FindFirstFileW)
|
||
|
APIHOOK_ENUM_ENTRY(FindFirstFileExA)
|
||
|
APIHOOK_ENUM_ENTRY(FindFirstFileExW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(GetBinaryTypeA)
|
||
|
APIHOOK_ENUM_ENTRY(GetBinaryTypeW)
|
||
|
APIHOOK_ENUM_ENTRY(GetFileAttributesA)
|
||
|
APIHOOK_ENUM_ENTRY(GetFileAttributesW)
|
||
|
APIHOOK_ENUM_ENTRY(GetFileAttributesExA)
|
||
|
APIHOOK_ENUM_ENTRY(GetFileAttributesExW)
|
||
|
APIHOOK_ENUM_ENTRY(SetFileAttributesA)
|
||
|
APIHOOK_ENUM_ENTRY(SetFileAttributesW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(MoveFileA)
|
||
|
APIHOOK_ENUM_ENTRY(MoveFileW)
|
||
|
APIHOOK_ENUM_ENTRY(MoveFileExA)
|
||
|
APIHOOK_ENUM_ENTRY(MoveFileExW)
|
||
|
APIHOOK_ENUM_ENTRY(MoveFileWithProgressA)
|
||
|
APIHOOK_ENUM_ENTRY(MoveFileWithProgressW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(RemoveDirectoryA)
|
||
|
APIHOOK_ENUM_ENTRY(RemoveDirectoryW)
|
||
|
APIHOOK_ENUM_ENTRY(SetCurrentDirectoryA)
|
||
|
APIHOOK_ENUM_ENTRY(SetCurrentDirectoryW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(OpenFile)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(RegSetValueA)
|
||
|
APIHOOK_ENUM_ENTRY(RegSetValueW)
|
||
|
APIHOOK_ENUM_ENTRY(RegSetValueExA)
|
||
|
APIHOOK_ENUM_ENTRY(RegSetValueExW)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(_lopen)
|
||
|
APIHOOK_ENUM_ENTRY(_lcreat)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY_COMSERVER(SHELL32)
|
||
|
|
||
|
APIHOOK_ENUM_ENTRY(LoadImageA)
|
||
|
APIHOOK_ENUM_END
|
||
|
|
||
|
|
||
|
// This is a private define (shlapip.h) that can mess up ShellExecuteEx
|
||
|
#ifndef SEE_MASK_FILEANDURL
|
||
|
#define SEE_MASK_FILEANDURL 0x00400000
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
CorrectFree: free lpMalloc if it is different from lpOrig
|
||
|
|
||
|
--*/
|
||
|
inline void CorrectFree(char * lpMalloc, const char * lpOrig)
|
||
|
{
|
||
|
if (lpMalloc != lpOrig)
|
||
|
{
|
||
|
free(lpMalloc);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void CorrectFree(WCHAR * lpMalloc, const WCHAR * lpOrig)
|
||
|
{
|
||
|
if (lpMalloc != lpOrig)
|
||
|
{
|
||
|
free(lpMalloc);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Our path changing class.
|
||
|
Note: This is a pointer to the base class.
|
||
|
Note: g_PathCorrector *MUST* remain NULL until after SHIM_STATIC_DLLS_INITIALIZED
|
||
|
|
||
|
--*/
|
||
|
CorrectPathChangesBase * g_PathCorrector = NULL;
|
||
|
CorrectPathChangesBase * g_AllocatedPathCorrector = NULL;
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Values that can be modified by the command line
|
||
|
|
||
|
--*/
|
||
|
enum PathCorrectorEnum
|
||
|
{
|
||
|
ePathCorrectorBase,
|
||
|
ePathCorrectorUser,
|
||
|
ePathCorrectorAllUser,
|
||
|
};
|
||
|
|
||
|
BOOL g_bCreateProcessRoutines = TRUE;
|
||
|
BOOL g_bGetCommandLineRoutines = FALSE;
|
||
|
BOOL g_bRegSetValueRoutines = FALSE;
|
||
|
BOOL g_bFileRoutines = TRUE;
|
||
|
BOOL g_bProfileRoutines = TRUE;
|
||
|
BOOL g_bShellLinkRoutines = TRUE;
|
||
|
BOOL g_bW9xPath = FALSE;
|
||
|
BOOL g_bLoadImage = FALSE;
|
||
|
|
||
|
|
||
|
PathCorrectorEnum g_pathcorrectorType = ePathCorrectorAllUser;
|
||
|
|
||
|
int g_nExtraPathCorrections = 0;
|
||
|
CString * g_ExtraPathCorrections;
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Parse the command line.
|
||
|
|
||
|
--*/
|
||
|
BOOL ParseCommandLine(const char * commandLine)
|
||
|
{
|
||
|
// Force the default values
|
||
|
g_bCreateProcessRoutines = TRUE;
|
||
|
g_bGetCommandLineRoutines = FALSE;
|
||
|
g_bRegSetValueRoutines = FALSE;
|
||
|
g_bFileRoutines = TRUE;
|
||
|
g_bProfileRoutines = TRUE;
|
||
|
g_bShellLinkRoutines = TRUE;
|
||
|
g_bW9xPath = FALSE;
|
||
|
g_bLoadImage = FALSE;
|
||
|
|
||
|
g_pathcorrectorType = ePathCorrectorAllUser;
|
||
|
g_nExtraPathCorrections = 0;
|
||
|
g_ExtraPathCorrections = NULL;
|
||
|
|
||
|
// Search the beginning of the command line for these switches
|
||
|
//
|
||
|
// Switch Default Meaning
|
||
|
//================ ======= =========================================================
|
||
|
// -a Y Force shortcuts to All Users
|
||
|
// -c N Do not shim Create process routines
|
||
|
// -f N Do not shim File routines
|
||
|
// -p N Do not shim GetPrivateProfile routines
|
||
|
// -s N Do not shim IShellLink routines
|
||
|
// -b N Bare: Use the base corrector (has no built-in path changes)
|
||
|
// -u N User: Built-in paths correct to <username>/Start Menu and <username>/Desktop
|
||
|
// +GetCommandLine N shim GetCommandLine routines
|
||
|
// +RegSetValue N shim the RegSetValue and RegSetValueEx routines
|
||
|
// +Win9xPath N Apply Win9x *path* specific fixes (does not apply to command lines)
|
||
|
// -Profiles N Do not force shortcuts to All Users
|
||
|
// +LoadBitmap N shim the LoadBitmapA routine
|
||
|
//
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csCl(commandLine);
|
||
|
CStringParser csParser(csCl, L" ");
|
||
|
|
||
|
int argc = csParser.GetCount();
|
||
|
if (csParser.GetCount() == 0)
|
||
|
{
|
||
|
return TRUE; // Not an error
|
||
|
}
|
||
|
|
||
|
// allocate for worst case
|
||
|
g_ExtraPathCorrections = new CString[argc];
|
||
|
if (!g_ExtraPathCorrections)
|
||
|
{
|
||
|
return FALSE; // Failure
|
||
|
}
|
||
|
g_nExtraPathCorrections = 0;
|
||
|
|
||
|
for (int i = 0; i < argc; ++i)
|
||
|
{
|
||
|
CString & csArg = csParser[i];
|
||
|
|
||
|
DPFN( eDbgLevelSpew, "Argv[%d] == (%S)\n", i, csArg.Get());
|
||
|
|
||
|
if (csArg == L"-a")
|
||
|
{
|
||
|
g_pathcorrectorType = ePathCorrectorAllUser;
|
||
|
}
|
||
|
else if (csArg == L"-b")
|
||
|
{
|
||
|
g_pathcorrectorType = ePathCorrectorBase;
|
||
|
}
|
||
|
else if (csArg == L"-u" || csArg == L"-Profiles")
|
||
|
{
|
||
|
g_pathcorrectorType = ePathCorrectorUser;
|
||
|
}
|
||
|
else if (csArg == L"-c")
|
||
|
{
|
||
|
g_bCreateProcessRoutines = FALSE;
|
||
|
}
|
||
|
else if (csArg == L"-f")
|
||
|
{
|
||
|
g_bFileRoutines = FALSE;
|
||
|
}
|
||
|
else if (csArg == L"-p")
|
||
|
{
|
||
|
g_bProfileRoutines = FALSE;
|
||
|
}
|
||
|
else if (csArg == L"-s")
|
||
|
{
|
||
|
g_bShellLinkRoutines = FALSE;
|
||
|
}
|
||
|
else if (csArg == L"+GetCommandLine")
|
||
|
{
|
||
|
DPFN( eDbgLevelInfo, "Command line routines will be shimmed\n");
|
||
|
g_bGetCommandLineRoutines = TRUE;
|
||
|
}
|
||
|
else if (csArg == L"+RegSetValue")
|
||
|
{
|
||
|
DPFN( eDbgLevelInfo, "RegSetValue routines will be shimmed\n");
|
||
|
g_bRegSetValueRoutines = TRUE;
|
||
|
}
|
||
|
else if (csArg == L"+Win9xPath")
|
||
|
{
|
||
|
DPFN( eDbgLevelInfo, "Win9x Path corrections will be applied\n");
|
||
|
g_bW9xPath = TRUE;
|
||
|
}
|
||
|
else if (csArg == L"+LoadImage")
|
||
|
{
|
||
|
DPFN( eDbgLevelInfo, "LoadImageA will be shimmed\n");
|
||
|
g_bLoadImage = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
g_ExtraPathCorrections[g_nExtraPathCorrections] = csArg;
|
||
|
g_nExtraPathCorrections += 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
// Dump out the new path correction values.
|
||
|
{
|
||
|
const char *lpszPathCorrectorType = "Unknown";
|
||
|
if (g_pathcorrectorType == ePathCorrectorBase)
|
||
|
{
|
||
|
lpszPathCorrectorType = "ePathCorrectorBase";
|
||
|
}
|
||
|
else if (g_pathcorrectorType == ePathCorrectorUser)
|
||
|
{
|
||
|
lpszPathCorrectorType = "ePathCorrectorUser";
|
||
|
}
|
||
|
else if (g_pathcorrectorType == ePathCorrectorAllUser)
|
||
|
{
|
||
|
lpszPathCorrectorType = "ePathCorrectorAllUser";
|
||
|
}
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Shim CreateProcessRoutines = %d\n", g_bCreateProcessRoutines);
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Shim GetCommandLineRoutines = %d\n", g_bGetCommandLineRoutines);
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Shim RegSetValueRoutines = %d\n", g_bRegSetValueRoutines);
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Shim FileRoutines = %d\n", g_bFileRoutines);
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Shim ProfileRoutines = %d\n", g_bProfileRoutines);
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Shim ShellLinkRoutines = %d\n", g_bShellLinkRoutines);
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Shim LoadImageA = %d\n", g_bLoadImage);
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Shim W9xPath = %d\n", g_bW9xPath);
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Shim Path Corrector Type = %s\n", lpszPathCorrectorType);
|
||
|
|
||
|
for (int i = 0; i < g_nExtraPathCorrections; ++i)
|
||
|
{
|
||
|
DPFN( eDbgLevelInfo, "[ParseCommandLine] Extra Path Change(%S)\n", g_ExtraPathCorrections[i].Get());
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Create the appropriate g_PathCorrector
|
||
|
Return TRUE if we were successful in creating and initializing.
|
||
|
|
||
|
Note: We create g_AllocatedPathCorrector because g_PathCorrector must remain NULL until SHIM_STATIC_DLLS_INITIALIZED
|
||
|
|
||
|
--*/
|
||
|
BOOL InitPathcorrectorClass()
|
||
|
{
|
||
|
switch (g_pathcorrectorType)
|
||
|
{
|
||
|
case ePathCorrectorBase:
|
||
|
g_AllocatedPathCorrector = new CorrectPathChangesBase;
|
||
|
break;
|
||
|
|
||
|
case ePathCorrectorUser:
|
||
|
g_AllocatedPathCorrector = new CorrectPathChangesUser;
|
||
|
break;
|
||
|
|
||
|
case ePathCorrectorAllUser:
|
||
|
default:
|
||
|
g_AllocatedPathCorrector = new CorrectPathChangesAllUser;
|
||
|
break;
|
||
|
|
||
|
};
|
||
|
|
||
|
if (g_AllocatedPathCorrector)
|
||
|
{
|
||
|
return g_AllocatedPathCorrector->ClassInit();
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Add all the path corrections to the path corrector.
|
||
|
Call after SHIM_STATIC_DLLS_INITIALIZED
|
||
|
|
||
|
--*/
|
||
|
void InitializePathCorrections()
|
||
|
{
|
||
|
if (g_PathCorrector)
|
||
|
{
|
||
|
g_PathCorrector->InitializeCorrectPathChanges();
|
||
|
|
||
|
if (g_ExtraPathCorrections && g_nExtraPathCorrections)
|
||
|
{
|
||
|
// Add the command line to this Path Corrector
|
||
|
for (int i = 0; i < g_nExtraPathCorrections; ++i)
|
||
|
{
|
||
|
g_PathCorrector->AddFromToPairW(g_ExtraPathCorrections[i]);
|
||
|
}
|
||
|
|
||
|
delete [] g_ExtraPathCorrections;
|
||
|
g_ExtraPathCorrections = NULL;
|
||
|
g_nExtraPathCorrections = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Return a pointer to the PathCorrecting object
|
||
|
|
||
|
--*/
|
||
|
inline CorrectPathChangesBase * GetPathcorrecter()
|
||
|
{
|
||
|
return g_PathCorrector;
|
||
|
}
|
||
|
|
||
|
inline void DebugSpew(const WCHAR * uncorrect, const WCHAR * correct, const char * debugMsg)
|
||
|
{
|
||
|
if (correct && uncorrect && _wcsicmp(correct, uncorrect) != 0)
|
||
|
{
|
||
|
LOGN( eDbgLevelError, "%s corrected path:\n %S\n %S\n",
|
||
|
debugMsg, uncorrect, correct);
|
||
|
}
|
||
|
else // Massive Spew:
|
||
|
{
|
||
|
DPFN( eDbgLevelSpew, "%s unchanged %S\n", debugMsg, uncorrect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void DebugSpew(const char * uncorrect, const char * correct, const char * debugMsg)
|
||
|
{
|
||
|
if (correct && uncorrect && _stricmp(correct, uncorrect) != 0)
|
||
|
{
|
||
|
LOGN( eDbgLevelError, "%s corrected path:\n %s\n %s\n",
|
||
|
debugMsg, uncorrect, correct);
|
||
|
}
|
||
|
else // Massive Spew:
|
||
|
{
|
||
|
DPFN( eDbgLevelSpew, "%s unchanged %s\n", debugMsg, uncorrect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Given a string, correct the path.
|
||
|
bMassagePath determines of path specific fixes are applied
|
||
|
(should be FALSE for command lines)
|
||
|
|
||
|
--*/
|
||
|
WCHAR * CorrectorCorrectPath(CorrectPathChangesBase * pathCorrector, const WCHAR * uncorrect, const char * debugMsg, BOOL bMassagePath)
|
||
|
{
|
||
|
if (uncorrect == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
if (!pathCorrector)
|
||
|
return (WCHAR *)uncorrect;
|
||
|
|
||
|
const WCHAR * W9xCorrectedPath = uncorrect;
|
||
|
|
||
|
// Check and see if we need to perform the special Win9x path massaging
|
||
|
if (bMassagePath)
|
||
|
{
|
||
|
W9xCorrectedPath = W9xPathMassageW(uncorrect);
|
||
|
}
|
||
|
|
||
|
WCHAR * strCorrectFile = pathCorrector->CorrectPathAllocW(W9xCorrectedPath);
|
||
|
|
||
|
// If the allocation failed, return the original string.
|
||
|
// This should allow the shim routines to pass along the orignal
|
||
|
// values to the hooked APIs, which if they fail, will have the
|
||
|
// proper error codes.
|
||
|
if (!strCorrectFile)
|
||
|
{
|
||
|
strCorrectFile = (WCHAR *)uncorrect;
|
||
|
}
|
||
|
else if (debugMsg)
|
||
|
{
|
||
|
DebugSpew(uncorrect, strCorrectFile, debugMsg);
|
||
|
}
|
||
|
|
||
|
if (W9xCorrectedPath != uncorrect)
|
||
|
free((WCHAR *)W9xCorrectedPath);
|
||
|
|
||
|
return strCorrectFile;
|
||
|
}
|
||
|
|
||
|
WCHAR * CorrectPath(const WCHAR * uncorrect, const char * debugMsg, BOOL bMassagePath = g_bW9xPath)
|
||
|
{
|
||
|
WCHAR * wstrCorrectFile = const_cast<WCHAR *>(uncorrect);
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CorrectPathChangesBase * pathCorrector = GetPathcorrecter();
|
||
|
|
||
|
wstrCorrectFile = CorrectorCorrectPath(pathCorrector, uncorrect, debugMsg, bMassagePath);
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Fall through
|
||
|
}
|
||
|
|
||
|
return wstrCorrectFile;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Given a string, correct the path.
|
||
|
bMassagePath determines of path specific fixes are applied
|
||
|
(should be FALSE for command lines)
|
||
|
|
||
|
--*/
|
||
|
char * CorrectPath(const char * uncorrect, const char * debugMsg, BOOL bMassagePath = g_bW9xPath)
|
||
|
{
|
||
|
char * strCorrectFile = const_cast<char *>(uncorrect);
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csUncorrect(uncorrect);
|
||
|
|
||
|
WCHAR * wstrCorrectFile = CorrectPath(csUncorrect, NULL, bMassagePath);
|
||
|
|
||
|
// Don't assign to strCorrectFile unless we successfully allocate the memory.
|
||
|
char * lpszChar = ToAnsi(wstrCorrectFile);
|
||
|
if (lpszChar)
|
||
|
{
|
||
|
strCorrectFile = lpszChar;
|
||
|
}
|
||
|
|
||
|
CorrectFree(wstrCorrectFile, csUncorrect);
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Fall through
|
||
|
}
|
||
|
|
||
|
if (debugMsg)
|
||
|
{
|
||
|
DebugSpew(uncorrect, strCorrectFile, debugMsg);
|
||
|
}
|
||
|
|
||
|
return strCorrectFile;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD APIHOOK(GetFileAttributesA)(
|
||
|
LPCSTR lpFileName // name of file or directory
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpFileName, "GetFileAttributesA");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(GetFileAttributesA)(strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
DWORD APIHOOK(GetFileAttributesW)(
|
||
|
LPCWSTR lpFileName // name of file or directory
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpFileName, "GetFileAttributesW");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(GetFileAttributesW)(strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(SetFileAttributesA)(
|
||
|
LPCSTR lpFileName, // file name
|
||
|
DWORD dwFileAttributes // attributes
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpFileName, "SetFileAttributesA");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(SetFileAttributesA)(strCorrect, dwFileAttributes);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
DWORD APIHOOK(SetFileAttributesW)(
|
||
|
LPCWSTR lpFileName, // file name
|
||
|
DWORD dwFileAttributes // attributes
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpFileName, "SetFileAttributesW");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(SetFileAttributesW)(strCorrect, dwFileAttributes);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(GetFileAttributesExA)(
|
||
|
LPCSTR lpFileName, // file or directory name
|
||
|
GET_FILEEX_INFO_LEVELS fInfoLevelId, // attribute
|
||
|
LPVOID lpFileInformation // attribute information
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpFileName, "GetFileAttributesExA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(GetFileAttributesExA)(strCorrect, fInfoLevelId, lpFileInformation);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(GetFileAttributesExW)(
|
||
|
LPCWSTR lpFileName, // file or directory name
|
||
|
GET_FILEEX_INFO_LEVELS fInfoLevelId, // attribute
|
||
|
LPVOID lpFileInformation // attribute information
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpFileName, "GetFileAttributesExW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(GetFileAttributesExW)(strCorrect, fInfoLevelId, lpFileInformation);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for CreateProcessA
|
||
|
|
||
|
--*/
|
||
|
BOOL APIHOOK(CreateProcessA)(
|
||
|
LPCSTR lpApplicationName,
|
||
|
LPSTR lpCommandLine,
|
||
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||
|
BOOL bInheritHandles,
|
||
|
DWORD dwCreationFlags,
|
||
|
LPVOID lpEnvironment,
|
||
|
LPCSTR lpCurrentDirectory,
|
||
|
LPSTARTUPINFOA lpStartupInfo,
|
||
|
LPPROCESS_INFORMATION lpProcessInformation)
|
||
|
{
|
||
|
// Application name and command line that is passed to CreateProcess
|
||
|
// Will either point to lpApplicationName or strCorrectApplicationName
|
||
|
// Will either point to lpCommandLine or strCorrectCommandLine
|
||
|
const char * pstrCorrectApplicationName = lpApplicationName;
|
||
|
char * pstrCorrectCommandLine = lpCommandLine;
|
||
|
|
||
|
if (lpApplicationName != NULL)
|
||
|
{
|
||
|
// Get a buffer containing the application name with the corrected path
|
||
|
pstrCorrectApplicationName = CorrectPath(lpApplicationName, "CreateProcessA ApplicationName:");
|
||
|
}
|
||
|
|
||
|
if (lpCommandLine != NULL)
|
||
|
{
|
||
|
// Get a buffer containing the command line with the corrected path
|
||
|
pstrCorrectCommandLine = CorrectPath(lpCommandLine, "CreateProcessA CommandLine:", FALSE);
|
||
|
}
|
||
|
|
||
|
DPFN( eDbgLevelInfo, "CreateProcessA Application(%s) CommandLine(%s)\n", pstrCorrectApplicationName, pstrCorrectCommandLine);
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CreateProcessA)(pstrCorrectApplicationName,
|
||
|
pstrCorrectCommandLine,
|
||
|
lpProcessAttributes,
|
||
|
lpThreadAttributes,
|
||
|
bInheritHandles,
|
||
|
dwCreationFlags,
|
||
|
lpEnvironment,
|
||
|
lpCurrentDirectory,
|
||
|
lpStartupInfo,
|
||
|
lpProcessInformation);
|
||
|
|
||
|
CorrectFree(const_cast<char*>(pstrCorrectApplicationName), lpApplicationName);
|
||
|
CorrectFree(pstrCorrectCommandLine, lpCommandLine);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for CreateProcessW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL APIHOOK(CreateProcessW)(
|
||
|
LPCWSTR lpApplicationName,
|
||
|
LPWSTR lpCommandLine,
|
||
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||
|
BOOL bInheritHandles,
|
||
|
DWORD dwCreationFlags,
|
||
|
LPVOID lpEnvironment,
|
||
|
LPCWSTR lpCurrentDirectory,
|
||
|
LPSTARTUPINFOW lpStartupInfo,
|
||
|
LPPROCESS_INFORMATION lpProcessInformation)
|
||
|
{
|
||
|
// Application name and command line that is passed to CreateProcess
|
||
|
// Will either point to lpApplicationName or strCorrectApplicationName
|
||
|
// Will either point to lpCommandLine or strCorrectCommandLine
|
||
|
const WCHAR * pstrCorrectApplicationName = lpApplicationName;
|
||
|
WCHAR * pstrCorrectCommandLine = lpCommandLine;
|
||
|
|
||
|
if (lpApplicationName != NULL)
|
||
|
{
|
||
|
// Get a buffer containing the application name with the corrected path
|
||
|
pstrCorrectApplicationName = CorrectPath(lpApplicationName, "CreateProcessW ApplicationName:");
|
||
|
}
|
||
|
|
||
|
if (lpCommandLine != NULL)
|
||
|
{
|
||
|
// Get a buffer containing the command line with the corrected path
|
||
|
pstrCorrectCommandLine = CorrectPath(lpCommandLine, "CreateProcessW CommandLine:", FALSE);
|
||
|
}
|
||
|
|
||
|
DPFN( eDbgLevelInfo, "CreateProcessW Application(%S) CommandLine(%S)\n", pstrCorrectApplicationName, pstrCorrectCommandLine);
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CreateProcessW)(pstrCorrectApplicationName,
|
||
|
pstrCorrectCommandLine,
|
||
|
lpProcessAttributes,
|
||
|
lpThreadAttributes,
|
||
|
bInheritHandles,
|
||
|
dwCreationFlags,
|
||
|
lpEnvironment,
|
||
|
lpCurrentDirectory,
|
||
|
lpStartupInfo,
|
||
|
lpProcessInformation);
|
||
|
|
||
|
CorrectFree(const_cast<WCHAR *>(pstrCorrectApplicationName), lpApplicationName);
|
||
|
CorrectFree(pstrCorrectCommandLine, lpCommandLine);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for WinExec
|
||
|
|
||
|
--*/
|
||
|
|
||
|
UINT APIHOOK(WinExec)(LPCSTR lpCmdLine, UINT uCmdShow)
|
||
|
{
|
||
|
// Get a buffer containing the command line with the corrected path
|
||
|
char * strCorrect = CorrectPath(lpCmdLine, "WinExec", FALSE);
|
||
|
|
||
|
UINT returnValue = ORIGINAL_API(WinExec)(strCorrect, uCmdShow);
|
||
|
|
||
|
CorrectFree(strCorrect, lpCmdLine);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for ShellExecuteA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
HINSTANCE APIHOOK(ShellExecuteA)(
|
||
|
HWND hwnd,
|
||
|
LPCSTR lpVerb,
|
||
|
LPCSTR lpFile,
|
||
|
LPCSTR lpParameters,
|
||
|
LPCSTR lpDirectory,
|
||
|
INT nShowCmd
|
||
|
)
|
||
|
{
|
||
|
HINSTANCE returnValue = (HINSTANCE)SE_ERR_OOM;
|
||
|
// Since this command is executed by the shell, it may contain %env% variables,
|
||
|
// expand them before calling correctpath.
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csExpandFile(lpFile);
|
||
|
csExpandFile.ExpandEnvironmentStringsW();
|
||
|
|
||
|
returnValue = ORIGINAL_API(ShellExecuteA)(hwnd, lpVerb, csExpandFile.GetAnsi(), lpParameters, lpDirectory, nShowCmd);
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Error expanding the string, just pass the value thru.
|
||
|
|
||
|
returnValue = ORIGINAL_API(ShellExecuteA)(hwnd, lpVerb, lpFile, lpParameters, lpDirectory, nShowCmd);
|
||
|
}
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for ShellExecuteW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
HINSTANCE APIHOOK(ShellExecuteW)(
|
||
|
HWND hwnd,
|
||
|
LPCWSTR lpVerb,
|
||
|
LPCWSTR lpFile,
|
||
|
LPCWSTR lpParameters,
|
||
|
LPCWSTR lpDirectory,
|
||
|
INT nShowCmd
|
||
|
)
|
||
|
{
|
||
|
HINSTANCE returnValue = (HINSTANCE)SE_ERR_OOM;
|
||
|
// Since this command is executed by the shell, it may contain %env% variables,
|
||
|
// expand them before calling correctpath.
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csExpandFile(lpFile);
|
||
|
csExpandFile.ExpandEnvironmentStringsW();
|
||
|
|
||
|
returnValue = ORIGINAL_API(ShellExecuteW)(hwnd, lpVerb, csExpandFile, lpParameters, lpDirectory, nShowCmd);
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Error expanding the string, just pass the value thru.
|
||
|
|
||
|
returnValue = ORIGINAL_API(ShellExecuteW)(hwnd, lpVerb, lpFile, lpParameters, lpDirectory, nShowCmd);
|
||
|
}
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for ShellExecuteExA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL APIHOOK(ShellExecuteExA)(
|
||
|
LPSHELLEXECUTEINFOA lpExecInfo
|
||
|
)
|
||
|
{
|
||
|
// Check for this magical internal flag that tells the system
|
||
|
// that lpExecInfo->lpFile is actually a file and URL combined with
|
||
|
// a 0 byte seperator, (file\0url\0)
|
||
|
// Since this is internal only, we should not be receiving bad paths.
|
||
|
if (lpExecInfo->fMask & SEE_MASK_FILEANDURL)
|
||
|
{
|
||
|
return ORIGINAL_API(ShellExecuteExA)(lpExecInfo);
|
||
|
}
|
||
|
|
||
|
const char * lpFile = lpExecInfo->lpFile;
|
||
|
const char * lpDirectory = lpExecInfo->lpDirectory;
|
||
|
|
||
|
char * strFileCorrect;
|
||
|
char * strDirCorrect;
|
||
|
|
||
|
// Check to see if app is expecting %env% substitution
|
||
|
if (lpExecInfo->fMask & SEE_MASK_DOENVSUBST )
|
||
|
{
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csExpandedFile(lpFile);
|
||
|
CString csExpandedDir(lpDirectory);
|
||
|
|
||
|
csExpandedFile.ExpandEnvironmentStringsW();
|
||
|
csExpandedDir.ExpandEnvironmentStringsW();
|
||
|
|
||
|
strFileCorrect = CorrectPath(csExpandedFile.GetAnsi(), "ShellExecuteExA");
|
||
|
strDirCorrect = CorrectPath(csExpandedDir.GetAnsi(), "ShellExecuteExA");
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Failed to expand the env values, pass all values untouched.
|
||
|
return ORIGINAL_API(ShellExecuteExA)(lpExecInfo);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
strFileCorrect = CorrectPath(lpFile, "ShellExecuteExA");
|
||
|
strDirCorrect = CorrectPath(lpDirectory, "ShellExecuteExA");
|
||
|
}
|
||
|
|
||
|
// Save the original fileName
|
||
|
lpExecInfo->lpFile = strFileCorrect;
|
||
|
lpExecInfo->lpDirectory = strDirCorrect;
|
||
|
BOOL returnValue = ORIGINAL_API(ShellExecuteExA)(lpExecInfo);
|
||
|
lpExecInfo->lpFile = lpFile;
|
||
|
lpExecInfo->lpDirectory = lpDirectory;
|
||
|
|
||
|
CorrectFree(strFileCorrect, lpFile);
|
||
|
CorrectFree(strDirCorrect, lpDirectory);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for ShellExecuteExW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL APIHOOK(ShellExecuteExW)(
|
||
|
LPSHELLEXECUTEINFOW lpExecInfo
|
||
|
)
|
||
|
{
|
||
|
// Check for this magical *internal* flag that tells the system
|
||
|
// that lpExecInfo->lpFile is actually a file and URL combined with
|
||
|
// a 0 byte seperator, (file\0url\0)
|
||
|
// Since this is internal only, we should not be receiving bad paths.
|
||
|
if (lpExecInfo->fMask & SEE_MASK_FILEANDURL)
|
||
|
{
|
||
|
return ORIGINAL_API(ShellExecuteExW)(lpExecInfo);
|
||
|
}
|
||
|
|
||
|
|
||
|
const WCHAR * lpFile = lpExecInfo->lpFile;
|
||
|
const WCHAR * lpDirectory = lpExecInfo->lpDirectory;
|
||
|
|
||
|
WCHAR * strFileCorrect;
|
||
|
WCHAR * strDirCorrect;
|
||
|
|
||
|
// Check to see if app is expecting %env% substitution
|
||
|
if (lpExecInfo->fMask & SEE_MASK_DOENVSUBST )
|
||
|
{
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csExpandedFile(lpFile);
|
||
|
CString csExpandedDir(lpDirectory);
|
||
|
|
||
|
csExpandedFile.ExpandEnvironmentStringsW();
|
||
|
csExpandedDir.ExpandEnvironmentStringsW();
|
||
|
|
||
|
strFileCorrect = CorrectPath(csExpandedFile, "ShellExecuteExW");
|
||
|
strDirCorrect = CorrectPath(csExpandedDir, "ShellExecuteExW");
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Failed to expand the env values, pass all values untouched.
|
||
|
return ORIGINAL_API(ShellExecuteExW)(lpExecInfo);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
strFileCorrect = CorrectPath(lpFile, "ShellExecuteExW");
|
||
|
strDirCorrect = CorrectPath(lpDirectory, "ShellExecuteExW");
|
||
|
}
|
||
|
|
||
|
// Save the original fileName
|
||
|
lpExecInfo->lpFile = strFileCorrect;
|
||
|
lpExecInfo->lpDirectory = strDirCorrect;
|
||
|
BOOL returnValue = ORIGINAL_API(ShellExecuteExW)(lpExecInfo);
|
||
|
lpExecInfo->lpFile = lpFile;
|
||
|
lpExecInfo->lpDirectory = lpDirectory;
|
||
|
|
||
|
CorrectFree(strFileCorrect, lpFile);
|
||
|
CorrectFree(strDirCorrect, lpDirectory);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*++
|
||
|
Convert long command line paths to short paths for GetCommandLineW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
LPCWSTR APIHOOK(GetCommandLineW)()
|
||
|
{
|
||
|
static LPCWSTR wstrCorrectCommandLine = NULL;
|
||
|
|
||
|
if (wstrCorrectCommandLine == NULL)
|
||
|
{
|
||
|
LPCWSTR wstrCommandLine = ORIGINAL_API(GetCommandLineW)();
|
||
|
|
||
|
wstrCorrectCommandLine = CorrectPath(wstrCommandLine, "GetCommandLineW", FALSE);
|
||
|
}
|
||
|
return wstrCorrectCommandLine;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
Convert long command line paths to short paths for GetCommandLineA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
LPCSTR APIHOOK(GetCommandLineA)()
|
||
|
{
|
||
|
static LPCSTR strCorrectCommandLine = NULL;
|
||
|
|
||
|
if (strCorrectCommandLine == NULL)
|
||
|
{
|
||
|
LPCSTR strCommandLine = ORIGINAL_API(GetCommandLineA)();
|
||
|
|
||
|
strCorrectCommandLine = CorrectPath(strCommandLine, "GetCommandLineA", FALSE);
|
||
|
}
|
||
|
return strCorrectCommandLine;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
The PrivateProfile routines treat filenames differently than pathnames.
|
||
|
If we have Win9xPath corrections enabled, it is possible to "fix" a path
|
||
|
from .\example.ini to example.ini. Unfortunately the PrivateProfile routines
|
||
|
look for example.ini in %windir%
|
||
|
|
||
|
If we have a path that contains path seperators, we must ensure that
|
||
|
the resulting string also contains path separators.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
char * ProfileCorrectPath(const char * uncorrect, const char * debugMsg, BOOL bMassagePath = g_bW9xPath)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(uncorrect, NULL, bMassagePath);
|
||
|
|
||
|
if (bMassagePath && uncorrect != strCorrect)
|
||
|
{
|
||
|
char * returnString = NULL;
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csUncorrect(uncorrect);
|
||
|
if (csUncorrect.FindOneOf(L"\\/") >= 0)
|
||
|
{
|
||
|
// Found some path separators in the original string, check the corrected string.
|
||
|
// If the corrected string does not have any path separators,
|
||
|
// then the path was corrected from .\example.ini to example.ini
|
||
|
|
||
|
CString csCorrect(strCorrect);
|
||
|
if (csCorrect.FindOneOf(L"\\/") < 0)
|
||
|
{
|
||
|
// No path seperators, make this a CWD relative path
|
||
|
|
||
|
csCorrect.Insert(0, L".\\");
|
||
|
|
||
|
returnString = csCorrect.ReleaseAnsi();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Some CString error occured, make sure returnString is NULL
|
||
|
if (returnString != NULL)
|
||
|
{
|
||
|
free(returnString);
|
||
|
}
|
||
|
returnString = NULL;
|
||
|
}
|
||
|
|
||
|
if (returnString)
|
||
|
{
|
||
|
CorrectFree(strCorrect, uncorrect);
|
||
|
strCorrect = returnString;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (debugMsg)
|
||
|
{
|
||
|
DebugSpew(uncorrect, strCorrect, debugMsg);
|
||
|
}
|
||
|
|
||
|
return strCorrect;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
The PrivateProfile routines treat filenames differently than pathnames.
|
||
|
If we have Win9xPath corrections enabled, it is possible to "fix" a path
|
||
|
from .\example.ini to example.ini. Unfortunately the PrivateProfile routines
|
||
|
look for example.ini in %windir%
|
||
|
|
||
|
If we have a path that contains path seperators, we must ensure that
|
||
|
the resulting string also contains path separators.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
WCHAR * ProfileCorrectPath(const WCHAR * uncorrect, const char * debugMsg, BOOL bMassagePath = g_bW9xPath)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(uncorrect, NULL, bMassagePath);
|
||
|
|
||
|
if (bMassagePath && uncorrect != strCorrect)
|
||
|
{
|
||
|
WCHAR * returnString = NULL;
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csUncorrect(uncorrect);
|
||
|
if (csUncorrect.FindOneOf(L"\\/") >= 0)
|
||
|
{
|
||
|
// Found some path separators in the original string, check the corrected string.
|
||
|
// If the corrected string does not have any path separators,
|
||
|
// then the path was corrected from .\example.ini to example.ini
|
||
|
|
||
|
CString csCorrect(strCorrect);
|
||
|
if (csCorrect.FindOneOf(L"\\/") < 0)
|
||
|
{
|
||
|
// No path seperators, make this a CWD relative path
|
||
|
|
||
|
csCorrect.Insert(0, L".\\");
|
||
|
|
||
|
// Manually copy the buffer
|
||
|
size_t nBytes = (csCorrect.GetLength() + 1) * sizeof(WCHAR);
|
||
|
returnString = (WCHAR*) malloc(nBytes);
|
||
|
if (returnString)
|
||
|
{
|
||
|
memcpy(returnString, csCorrect.Get(), nBytes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Some CString error occured, make sure returnString is NULL
|
||
|
if (returnString != NULL)
|
||
|
{
|
||
|
free(returnString);
|
||
|
}
|
||
|
returnString = NULL;
|
||
|
}
|
||
|
|
||
|
if (returnString)
|
||
|
{
|
||
|
CorrectFree(strCorrect, uncorrect);
|
||
|
strCorrect = returnString;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (debugMsg)
|
||
|
{
|
||
|
DebugSpew(uncorrect, strCorrect, debugMsg);
|
||
|
}
|
||
|
|
||
|
return strCorrect;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileIntA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
UINT APIHOOK(GetPrivateProfileIntA)(
|
||
|
LPCSTR lpAppName, // section name
|
||
|
LPCSTR lpKeyName, // key name
|
||
|
INT nDefault, // return value if key name not found
|
||
|
LPCSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileIntA");
|
||
|
|
||
|
UINT returnValue = ORIGINAL_API(GetPrivateProfileIntA)(lpAppName, lpKeyName, nDefault, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileIntW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
UINT APIHOOK(GetPrivateProfileIntW)(
|
||
|
LPCWSTR lpAppName, // section name
|
||
|
LPCWSTR lpKeyName, // key name
|
||
|
INT nDefault, // return value if key name not found
|
||
|
LPCWSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileIntW");
|
||
|
|
||
|
UINT returnValue = ORIGINAL_API(GetPrivateProfileIntW)(lpAppName, lpKeyName, nDefault, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileSectionA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD APIHOOK(GetPrivateProfileSectionA)(
|
||
|
LPCSTR lpAppName, // section name
|
||
|
LPSTR lpReturnedString, // return buffer
|
||
|
DWORD nSize, // size of return buffer
|
||
|
LPCSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileSectionA");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileSectionA)(lpAppName, lpReturnedString, nSize, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileSectionW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD APIHOOK(GetPrivateProfileSectionW)(
|
||
|
LPCWSTR lpAppName, // section name
|
||
|
LPWSTR lpReturnedString, // return buffer
|
||
|
DWORD nSize, // size of return buffer
|
||
|
LPCWSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileSectionW");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileSectionW)(lpAppName, lpReturnedString, nSize, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileSectionNamesA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD APIHOOK(GetPrivateProfileSectionNamesA)(
|
||
|
LPSTR lpszReturnBuffer, // return buffer
|
||
|
DWORD nSize, // size of return buffer
|
||
|
LPCSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileSectionNamesA");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileSectionNamesA)(lpszReturnBuffer, nSize, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileSectionNamesW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD APIHOOK(GetPrivateProfileSectionNamesW)(
|
||
|
LPWSTR lpszReturnBuffer, // return buffer
|
||
|
DWORD nSize, // size of return buffer
|
||
|
LPCWSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileSectionNamesW");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileSectionNamesW)(lpszReturnBuffer, nSize, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileSectionNamesA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD APIHOOK(GetPrivateProfileStringA)(
|
||
|
LPCSTR lpAppName, // section name
|
||
|
LPCSTR lpKeyName, // key name
|
||
|
LPCSTR lpDefault, // default string
|
||
|
LPSTR lpReturnedString, // destination buffer
|
||
|
DWORD nSize, // size of destination buffer
|
||
|
LPCSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileStringA");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileStringA)(lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileSectionNamesA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
DWORD APIHOOK(GetPrivateProfileStringW)(
|
||
|
LPCWSTR lpAppName, // section name
|
||
|
LPCWSTR lpKeyName, // key name
|
||
|
LPCWSTR lpDefault, // default string
|
||
|
LPWSTR lpReturnedString, // destination buffer
|
||
|
DWORD nSize, // size of destination buffer
|
||
|
LPCWSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileStringW");
|
||
|
|
||
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileStringW)(lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileStructA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL APIHOOK(GetPrivateProfileStructA)(
|
||
|
LPCSTR lpszSection, // section name
|
||
|
LPCSTR lpszKey, // key name
|
||
|
LPVOID lpStruct, // return buffer
|
||
|
UINT uSizeStruct, // size of return buffer
|
||
|
LPCSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileStructA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(GetPrivateProfileStructA)(lpszSection, lpszKey, lpStruct, uSizeStruct, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileStructW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL APIHOOK(GetPrivateProfileStructW)(
|
||
|
LPCWSTR lpszSection, // section name
|
||
|
LPCWSTR lpszKey, // key name
|
||
|
LPVOID lpStruct, // return buffer
|
||
|
UINT uSizeStruct, // size of return buffer
|
||
|
LPCWSTR lpFileName // initialization file name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = ProfileCorrectPath(lpFileName, "GetPrivateProfileStructW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(GetPrivateProfileStructW)(lpszSection, lpszKey, lpStruct, uSizeStruct, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for GetPrivateProfileStructA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL APIHOOK(WritePrivateProfileSectionA)(
|
||
|
LPCSTR lpAppName, // section name
|
||
|
LPCSTR lpString, // data
|
||
|
LPCSTR lpFileName // file name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = ProfileCorrectPath(lpFileName, "WritePrivateProfileSectionA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileSectionA)(lpAppName, lpString, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for WritePrivateProfileSectionW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL APIHOOK(WritePrivateProfileSectionW)(
|
||
|
LPCWSTR lpAppName, // section name
|
||
|
LPCWSTR lpString, // data
|
||
|
LPCWSTR lpFileName // file name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = ProfileCorrectPath(lpFileName, "WritePrivateProfileSectionW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileSectionW)(lpAppName, lpString, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for WritePrivateProfileStringA
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL APIHOOK(WritePrivateProfileStringA)(
|
||
|
LPCSTR lpAppName, // section name
|
||
|
LPCSTR lpKeyName, // key name
|
||
|
LPCSTR lpString, // string to add
|
||
|
LPCSTR lpFileName // initialization file
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = ProfileCorrectPath(lpFileName, "WritePrivateProfileStringA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileStringA)(lpAppName, lpKeyName, lpString, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for WritePrivateProfileStringW
|
||
|
|
||
|
--*/
|
||
|
|
||
|
BOOL APIHOOK(WritePrivateProfileStringW)(
|
||
|
LPCWSTR lpAppName, // section name
|
||
|
LPCWSTR lpKeyName, // key name
|
||
|
LPCWSTR lpString, // string to add
|
||
|
LPCWSTR lpFileName // initialization file
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = ProfileCorrectPath(lpFileName, "WritePrivateProfileStringW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileStringW)(lpAppName, lpKeyName, lpString, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for WritePrivateProfileStructA
|
||
|
|
||
|
--*/
|
||
|
BOOL APIHOOK(WritePrivateProfileStructA)(
|
||
|
LPCSTR lpszSection, // section name
|
||
|
LPCSTR lpszKey, // key name
|
||
|
LPVOID lpStruct, // data buffer
|
||
|
UINT uSizeStruct, // size of data buffer
|
||
|
LPCSTR lpFileName // initialization file
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = ProfileCorrectPath(lpFileName, "WritePrivateProfileStructA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileStructA)(lpszSection, lpszKey, lpStruct, uSizeStruct, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for WritePrivateProfileStructW
|
||
|
|
||
|
--*/
|
||
|
BOOL APIHOOK(WritePrivateProfileStructW)(
|
||
|
LPCWSTR lpszSection, // section name
|
||
|
LPCWSTR lpszKey, // key name
|
||
|
LPVOID lpStruct, // data buffer
|
||
|
UINT uSizeStruct, // size of data buffer
|
||
|
LPCWSTR lpFileName // initialization file
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = ProfileCorrectPath(lpFileName, "WritePrivateProfileStructW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileStructW)(lpszSection, lpszKey, lpStruct, uSizeStruct, strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for IShellLinkA::SetArguments
|
||
|
|
||
|
--*/
|
||
|
HRESULT COMHOOK(IShellLinkA, SetArguments)( PVOID pThis, LPCSTR pszArgs )
|
||
|
{
|
||
|
HRESULT hrReturn = E_FAIL;
|
||
|
|
||
|
char * strCorrect = CorrectPath(pszArgs, "IShellLinkA::SetArguments", FALSE);
|
||
|
|
||
|
_pfn_IShellLinkA_SetArguments pfnOld = ORIGINAL_COM(IShellLinkA, SetArguments, pThis);
|
||
|
if (pfnOld)
|
||
|
hrReturn = (*pfnOld)( pThis, strCorrect );
|
||
|
|
||
|
CorrectFree(strCorrect, pszArgs);
|
||
|
|
||
|
return hrReturn;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for IShellLinkW::SetArguments
|
||
|
|
||
|
--*/
|
||
|
HRESULT COMHOOK(IShellLinkW, SetArguments)( PVOID pThis, LPCWSTR pszArgs )
|
||
|
{
|
||
|
HRESULT hrReturn = E_FAIL;
|
||
|
|
||
|
WCHAR * strCorrect = CorrectPath(pszArgs, "IShellLinkA::SetArguments", FALSE);
|
||
|
|
||
|
_pfn_IShellLinkW_SetArguments pfnOld = ORIGINAL_COM(IShellLinkW, SetArguments, pThis);
|
||
|
if(pfnOld)
|
||
|
hrReturn = (*pfnOld)( pThis, strCorrect );
|
||
|
|
||
|
CorrectFree(strCorrect, pszArgs);
|
||
|
|
||
|
return hrReturn;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for IShellLinkA::SetIconLocation
|
||
|
|
||
|
--*/
|
||
|
HRESULT COMHOOK(IShellLinkA, SetIconLocation)(PVOID pThis, LPCSTR pszIconLocation, int nIcon )
|
||
|
{
|
||
|
HRESULT hrReturn = E_FAIL;
|
||
|
|
||
|
char * strCorrect = CorrectPath(pszIconLocation, "IShellLinkA::SetIconLocation");
|
||
|
|
||
|
_pfn_IShellLinkA_SetIconLocation pfnOld = ORIGINAL_COM(IShellLinkA, SetIconLocation, pThis);
|
||
|
if (pfnOld)
|
||
|
hrReturn = (*pfnOld)( pThis, strCorrect, nIcon );
|
||
|
|
||
|
CorrectFree(strCorrect, pszIconLocation);
|
||
|
|
||
|
return hrReturn;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for IShellLinkW::SetIconLocation
|
||
|
|
||
|
--*/
|
||
|
HRESULT COMHOOK(IShellLinkW, SetIconLocation)(PVOID pThis, LPCWSTR pszIconLocation, int nIcon )
|
||
|
{
|
||
|
HRESULT hrReturn = E_FAIL;
|
||
|
|
||
|
WCHAR * strCorrect = CorrectPath(pszIconLocation, "IShellLinkW::SetIconLocation");
|
||
|
|
||
|
_pfn_IShellLinkW_SetIconLocation pfnOld = ORIGINAL_COM(IShellLinkW, SetIconLocation, pThis);
|
||
|
if(pfnOld)
|
||
|
hrReturn = (*pfnOld)( pThis, strCorrect, nIcon );
|
||
|
|
||
|
CorrectFree(strCorrect, pszIconLocation);
|
||
|
|
||
|
return hrReturn;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for IShellLinkA::SetPath
|
||
|
|
||
|
--*/
|
||
|
HRESULT COMHOOK(IShellLinkA, SetPath)(PVOID pThis,
|
||
|
LPCSTR pszFile )
|
||
|
{
|
||
|
HRESULT hrReturn = E_FAIL;
|
||
|
|
||
|
char * strCorrect = CorrectPath(pszFile, "IShellLinkA::SetPath");
|
||
|
|
||
|
_pfn_IShellLinkA_SetPath pfnOld = ORIGINAL_COM(IShellLinkA, SetPath, pThis);
|
||
|
if (pfnOld)
|
||
|
hrReturn = (*pfnOld)( pThis, strCorrect );
|
||
|
|
||
|
CorrectFree(strCorrect, pszFile);
|
||
|
|
||
|
return hrReturn;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for IShellLinkW::SetPath
|
||
|
|
||
|
--*/
|
||
|
HRESULT COMHOOK(IShellLinkW, SetPath)(PVOID pThis,
|
||
|
LPCWSTR pszFile )
|
||
|
{
|
||
|
HRESULT hrReturn = E_FAIL;
|
||
|
|
||
|
WCHAR * strCorrect = CorrectPath(pszFile, "IShellLinkW::SetPath");
|
||
|
|
||
|
_pfn_IShellLinkW_SetPath pfnOld = ORIGINAL_COM(IShellLinkW, SetPath, pThis);
|
||
|
if (pfnOld)
|
||
|
hrReturn = (*pfnOld)( pThis, strCorrect );
|
||
|
|
||
|
CorrectFree(strCorrect, pszFile);
|
||
|
|
||
|
return hrReturn;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Convert Win9x paths to WinNT paths for IPersistFile::Save
|
||
|
|
||
|
--*/
|
||
|
HRESULT COMHOOK(IPersistFile, Save)(PVOID pThis,
|
||
|
LPCOLESTR pszFileName,
|
||
|
BOOL fRemember)
|
||
|
{
|
||
|
HRESULT hrReturn = E_FAIL;
|
||
|
|
||
|
WCHAR * strCorrect = CorrectPath(pszFileName, "IPersistFile_Save");
|
||
|
|
||
|
_pfn_IPersistFile_Save pfnOld = ORIGINAL_COM(IPersistFile, Save, pThis);
|
||
|
if (pfnOld)
|
||
|
hrReturn = (*pfnOld)( pThis, strCorrect, fRemember );
|
||
|
|
||
|
CorrectFree(strCorrect, pszFileName);
|
||
|
|
||
|
return hrReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL APIHOOK(CopyFileA)(
|
||
|
LPCSTR lpExistingFileName, // name of an existing file
|
||
|
LPCSTR lpNewFileName, // name of new file
|
||
|
BOOL bFailIfExists // operation if file exists
|
||
|
)
|
||
|
{
|
||
|
char * strExistingCorrect = CorrectPath(lpExistingFileName, "CopyFileA");
|
||
|
char * strNewCorrect = CorrectPath(lpNewFileName, "CopyFileA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CopyFileA)(strExistingCorrect, strNewCorrect, bFailIfExists);
|
||
|
|
||
|
CorrectFree(strExistingCorrect, lpExistingFileName);
|
||
|
CorrectFree(strNewCorrect, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(CopyFileW)(
|
||
|
LPCWSTR lpExistingFileName, // name of an existing file
|
||
|
LPCWSTR lpNewFileName, // name of new file
|
||
|
BOOL bFailIfExists // operation if file exists
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strExistingCorrect = CorrectPath(lpExistingFileName, "CopyFileW");
|
||
|
WCHAR * strNewCorrect = CorrectPath(lpNewFileName, "CopyFileW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CopyFileW)(strExistingCorrect, strNewCorrect, bFailIfExists);
|
||
|
|
||
|
CorrectFree(strExistingCorrect, lpExistingFileName);
|
||
|
CorrectFree(strNewCorrect, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL APIHOOK(CopyFileExA)(
|
||
|
LPCSTR lpExistingFileName, // name of existing file
|
||
|
LPCSTR lpNewFileName, // name of new file
|
||
|
LPPROGRESS_ROUTINE lpProgressRoutine, // callback function
|
||
|
LPVOID lpData, // callback parameter
|
||
|
LPBOOL pbCancel, // cancel status
|
||
|
DWORD dwCopyFlags // copy options
|
||
|
)
|
||
|
{
|
||
|
char * strExistingCorrect = CorrectPath(lpExistingFileName, "CopyFileExA");
|
||
|
char * strNewCorrect = CorrectPath(lpNewFileName, "CopyFileExA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CopyFileExA)(strExistingCorrect, strNewCorrect, lpProgressRoutine, lpData, pbCancel, dwCopyFlags);
|
||
|
|
||
|
CorrectFree(strExistingCorrect, lpExistingFileName);
|
||
|
CorrectFree(strNewCorrect, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(CopyFileExW)(
|
||
|
LPCWSTR lpExistingFileName, // name of existing file
|
||
|
LPCWSTR lpNewFileName, // name of new file
|
||
|
LPPROGRESS_ROUTINE lpProgressRoutine, // callback function
|
||
|
LPVOID lpData, // callback parameter
|
||
|
LPBOOL pbCancel, // cancel status
|
||
|
DWORD dwCopyFlags // copy options
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strExistingCorrect = CorrectPath(lpExistingFileName, "CopyFileExW");
|
||
|
WCHAR * strNewCorrect = CorrectPath(lpNewFileName, "CopyFileExW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CopyFileExW)(strExistingCorrect, strNewCorrect, lpProgressRoutine, lpData, pbCancel, dwCopyFlags);
|
||
|
|
||
|
CorrectFree(strExistingCorrect, lpExistingFileName);
|
||
|
CorrectFree(strNewCorrect, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(CreateDirectoryA)(
|
||
|
LPCSTR lpPathName, // directory name
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpPathName, "CreateDirectoryA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CreateDirectoryA)(strCorrect, lpSecurityAttributes);
|
||
|
|
||
|
CorrectFree(strCorrect, lpPathName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(CreateDirectoryW)(
|
||
|
LPCWSTR lpPathName, // directory name
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpPathName, "CreateDirectoryW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CreateDirectoryW)(strCorrect, lpSecurityAttributes);
|
||
|
|
||
|
CorrectFree(strCorrect, lpPathName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(CreateDirectoryExA)(
|
||
|
LPCSTR lpTemplateDirectory, // template directory
|
||
|
LPCSTR lpNewDirectory, // directory name
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD
|
||
|
)
|
||
|
{
|
||
|
char * strTemplateCorrect = CorrectPath(lpTemplateDirectory, "CreateDirectoryExA");
|
||
|
char * strNewCorrect = CorrectPath(lpNewDirectory, "CreateDirectoryExA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CreateDirectoryExA)(strTemplateCorrect, strNewCorrect, lpSecurityAttributes);
|
||
|
|
||
|
CorrectFree(strTemplateCorrect, lpTemplateDirectory);
|
||
|
CorrectFree(strNewCorrect, lpNewDirectory);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(CreateDirectoryExW)(
|
||
|
LPCWSTR lpTemplateDirectory, // template directory
|
||
|
LPCWSTR lpNewDirectory, // directory name
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strTemplateCorrect = CorrectPath(lpTemplateDirectory, "CreateDirectoryExW");
|
||
|
WCHAR * strNewCorrect = CorrectPath(lpNewDirectory, "CreateDirectoryExW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(CreateDirectoryExW)(strTemplateCorrect, strNewCorrect, lpSecurityAttributes);
|
||
|
|
||
|
CorrectFree(strTemplateCorrect, lpTemplateDirectory);
|
||
|
CorrectFree(strNewCorrect, lpNewDirectory);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
HANDLE APIHOOK(CreateFileA)(
|
||
|
LPCSTR lpFileName, // file name
|
||
|
DWORD dwDesiredAccess, // access mode
|
||
|
DWORD dwShareMode, // share mode
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
|
||
|
DWORD dwCreationDisposition, // how to create
|
||
|
DWORD dwFlagsAndAttributes, // file attributes
|
||
|
HANDLE hTemplateFile // handle to template file
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpFileName, "CreateFileA");
|
||
|
|
||
|
HANDLE returnValue = ORIGINAL_API(CreateFileA)(strCorrect,
|
||
|
dwDesiredAccess,
|
||
|
dwShareMode,
|
||
|
lpSecurityAttributes,
|
||
|
dwCreationDisposition,
|
||
|
dwFlagsAndAttributes,
|
||
|
hTemplateFile);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
HANDLE APIHOOK(CreateFileW)(
|
||
|
LPCWSTR lpFileName, // file name
|
||
|
DWORD dwDesiredAccess, // access mode
|
||
|
DWORD dwShareMode, // share mode
|
||
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
|
||
|
DWORD dwCreationDisposition, // how to create
|
||
|
DWORD dwFlagsAndAttributes, // file attributes
|
||
|
HANDLE hTemplateFile // handle to template file
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpFileName, "CreateFileW");
|
||
|
|
||
|
HANDLE returnValue = ORIGINAL_API(CreateFileW)(
|
||
|
strCorrect,
|
||
|
dwDesiredAccess,
|
||
|
dwShareMode,
|
||
|
lpSecurityAttributes,
|
||
|
dwCreationDisposition,
|
||
|
dwFlagsAndAttributes,
|
||
|
hTemplateFile);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(DeleteFileA)(
|
||
|
LPCSTR lpFileName // file name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpFileName, "DeleteFileA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(DeleteFileA)(strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(DeleteFileW)(
|
||
|
|
||
|
LPCWSTR lpFileName // file name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpFileName, "DeleteFileW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(DeleteFileW)(strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Win9xPath corrections will strip a trailing . from the end of a search string.
|
||
|
As a path, the . is not significant, but as a wildcard it is important--the
|
||
|
difference between finding files without an extension and finding all files
|
||
|
in the directory.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
char * FindFirstFileCorrectPath(const char * uncorrect, const char * debugMsg, BOOL bMassagePath = g_bW9xPath)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(uncorrect, NULL, bMassagePath);
|
||
|
|
||
|
if (bMassagePath && uncorrect != strCorrect)
|
||
|
{
|
||
|
char * returnString = NULL;
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csUncorrect(uncorrect);
|
||
|
CString csCorrect(strCorrect);
|
||
|
|
||
|
CString csUncorrectLast;
|
||
|
CString csCorrectLast;
|
||
|
|
||
|
csUncorrect.GetLastPathComponent(csUncorrectLast);
|
||
|
csCorrect.GetLastPathComponent(csCorrectLast);
|
||
|
|
||
|
if (csUncorrectLast.Compare(L"*.") == 0 && csCorrectLast.Compare(L"*") == 0)
|
||
|
{
|
||
|
csCorrectLast += L".";
|
||
|
returnString = csCorrectLast.ReleaseAnsi();
|
||
|
}
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Some CString error occured, make sure returnString is NULL
|
||
|
if (returnString != NULL)
|
||
|
{
|
||
|
free(returnString);
|
||
|
}
|
||
|
returnString = NULL;
|
||
|
}
|
||
|
|
||
|
if (returnString)
|
||
|
{
|
||
|
CorrectFree(strCorrect, uncorrect);
|
||
|
strCorrect = returnString;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (debugMsg)
|
||
|
{
|
||
|
DebugSpew(uncorrect, strCorrect, debugMsg);
|
||
|
}
|
||
|
|
||
|
return strCorrect;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Win9xPath corrections will strip a trailing . from the end of a search string.
|
||
|
As a path, the . is not significant, but as a wildcard it is important--the
|
||
|
difference between finding files without an extension and finding all files
|
||
|
in the directory.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
WCHAR * FindFirstFileCorrectPath(const WCHAR * uncorrect, const char * debugMsg, BOOL bMassagePath = g_bW9xPath)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(uncorrect, NULL, bMassagePath);
|
||
|
|
||
|
if (bMassagePath && uncorrect != strCorrect)
|
||
|
{
|
||
|
WCHAR * returnString = NULL;
|
||
|
|
||
|
CSTRING_TRY
|
||
|
{
|
||
|
CString csUncorrect(uncorrect);
|
||
|
CString csCorrect(strCorrect);
|
||
|
|
||
|
CString csUncorrectLast;
|
||
|
CString csCorrectLast;
|
||
|
|
||
|
csUncorrect.GetLastPathComponent(csUncorrectLast);
|
||
|
csCorrect.GetLastPathComponent(csCorrectLast);
|
||
|
|
||
|
if (csUncorrectLast.Compare(L"*.") == 0 && csCorrectLast.Compare(L"*") == 0)
|
||
|
{
|
||
|
csCorrectLast += L".";
|
||
|
|
||
|
// Manually copy the buffer
|
||
|
size_t nBytes = (csCorrectLast.GetLength() + 1) * sizeof(WCHAR);
|
||
|
returnString = (WCHAR*) malloc(nBytes);
|
||
|
if (returnString)
|
||
|
{
|
||
|
memcpy(returnString, csCorrectLast.Get(), nBytes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
CSTRING_CATCH
|
||
|
{
|
||
|
// Some CString error occured, make sure returnString is NULL
|
||
|
if (returnString != NULL)
|
||
|
{
|
||
|
free(returnString);
|
||
|
}
|
||
|
returnString = NULL;
|
||
|
}
|
||
|
|
||
|
if (returnString)
|
||
|
{
|
||
|
CorrectFree(strCorrect, uncorrect);
|
||
|
strCorrect = returnString;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (debugMsg)
|
||
|
{
|
||
|
DebugSpew(uncorrect, strCorrect, debugMsg);
|
||
|
}
|
||
|
|
||
|
return strCorrect;
|
||
|
}
|
||
|
|
||
|
HANDLE APIHOOK(FindFirstFileA)(
|
||
|
LPCSTR lpFileName, // file name
|
||
|
LPWIN32_FIND_DATAA lpFindFileData // data buffer
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = FindFirstFileCorrectPath(lpFileName, "FindFirstFileA");
|
||
|
|
||
|
HANDLE returnValue = ORIGINAL_API(FindFirstFileA)(strCorrect, lpFindFileData);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
HANDLE APIHOOK(FindFirstFileW)(
|
||
|
LPCWSTR lpFileName, // file name
|
||
|
LPWIN32_FIND_DATAW lpFindFileData // data buffer
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = FindFirstFileCorrectPath(lpFileName, "FindFirstFileW");
|
||
|
|
||
|
HANDLE returnValue = ORIGINAL_API(FindFirstFileW)(strCorrect, lpFindFileData);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
HANDLE APIHOOK(FindFirstFileExA)(
|
||
|
LPCSTR lpFileName, // file name
|
||
|
FINDEX_INFO_LEVELS fInfoLevelId, // information level
|
||
|
LPVOID lpFindFileData, // information buffer
|
||
|
FINDEX_SEARCH_OPS fSearchOp, // filtering type
|
||
|
LPVOID lpSearchFilter, // search criteria
|
||
|
DWORD dwAdditionalFlags // additional search control
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = FindFirstFileCorrectPath(lpFileName, "FindFirstFileExA");
|
||
|
|
||
|
HANDLE returnValue = ORIGINAL_API(FindFirstFileExA)(
|
||
|
strCorrect,
|
||
|
fInfoLevelId,
|
||
|
lpFindFileData,
|
||
|
fSearchOp,
|
||
|
lpSearchFilter,
|
||
|
dwAdditionalFlags);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
HANDLE APIHOOK(FindFirstFileExW)(
|
||
|
LPCWSTR lpFileName, // file name
|
||
|
FINDEX_INFO_LEVELS fInfoLevelId, // information level
|
||
|
LPVOID lpFindFileData, // information buffer
|
||
|
FINDEX_SEARCH_OPS fSearchOp, // filtering type
|
||
|
LPVOID lpSearchFilter, // search criteria
|
||
|
DWORD dwAdditionalFlags // additional search control
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = FindFirstFileCorrectPath(lpFileName, "FindFirstFileExW");
|
||
|
|
||
|
HANDLE returnValue = ORIGINAL_API(FindFirstFileExW)(
|
||
|
strCorrect,
|
||
|
fInfoLevelId,
|
||
|
lpFindFileData,
|
||
|
fSearchOp,
|
||
|
lpSearchFilter,
|
||
|
dwAdditionalFlags);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(GetBinaryTypeA)(
|
||
|
LPCSTR lpApplicationName, // full file path
|
||
|
LPDWORD lpBinaryType // binary type information
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpApplicationName, "GetBinaryTypeA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(GetBinaryTypeA)(strCorrect, lpBinaryType);
|
||
|
|
||
|
CorrectFree(strCorrect, lpApplicationName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(GetBinaryTypeW)(
|
||
|
LPCWSTR lpApplicationName, // full file path
|
||
|
LPDWORD lpBinaryType // binary type information
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpApplicationName, "GetBinaryTypeW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(GetBinaryTypeW)(strCorrect, lpBinaryType);
|
||
|
|
||
|
CorrectFree(strCorrect, lpApplicationName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(MoveFileA)(
|
||
|
LPCSTR lpExistingFileName, // file name
|
||
|
LPCSTR lpNewFileName // new file name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrectExisting = CorrectPath(lpExistingFileName, "MoveFileA");
|
||
|
char * strCorrectNew = CorrectPath(lpNewFileName, "MoveFileA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(MoveFileA)(strCorrectExisting, strCorrectNew);
|
||
|
|
||
|
CorrectFree(strCorrectExisting, lpExistingFileName);
|
||
|
CorrectFree(strCorrectNew, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(MoveFileW)(
|
||
|
LPCWSTR lpExistingFileName, // file name
|
||
|
LPCWSTR lpNewFileName // new file name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrectExisting = CorrectPath(lpExistingFileName, "MoveFileW");
|
||
|
WCHAR * strCorrectNew = CorrectPath(lpNewFileName, "MoveFileW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(MoveFileW)(strCorrectExisting, strCorrectNew);
|
||
|
|
||
|
CorrectFree(strCorrectExisting, lpExistingFileName);
|
||
|
CorrectFree(strCorrectNew, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(MoveFileExA)(
|
||
|
LPCSTR lpExistingFileName, // file name
|
||
|
LPCSTR lpNewFileName, // new file name
|
||
|
DWORD dwFlags // move options
|
||
|
)
|
||
|
{
|
||
|
char * strCorrectExisting = CorrectPath(lpExistingFileName, "MoveFileExA");
|
||
|
char * strCorrectNew = CorrectPath(lpNewFileName, "MoveFileExA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(MoveFileExA)(strCorrectExisting, strCorrectNew, dwFlags);
|
||
|
|
||
|
CorrectFree(strCorrectExisting, lpExistingFileName);
|
||
|
CorrectFree(strCorrectNew, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(MoveFileExW)(
|
||
|
LPCWSTR lpExistingFileName, // file name
|
||
|
LPCWSTR lpNewFileName, // new file name
|
||
|
DWORD dwFlags // move options
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrectExisting = CorrectPath(lpExistingFileName, "MoveFileExW");
|
||
|
WCHAR * strCorrectNew = CorrectPath(lpNewFileName, "MoveFileExW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(MoveFileExW)(strCorrectExisting, strCorrectNew, dwFlags);
|
||
|
|
||
|
CorrectFree(strCorrectExisting, lpExistingFileName);
|
||
|
CorrectFree(strCorrectNew, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(MoveFileWithProgressA)(
|
||
|
LPCSTR lpExistingFileName, // file name
|
||
|
LPCSTR lpNewFileName, // new file name
|
||
|
LPPROGRESS_ROUTINE lpProgressRoutine, // callback function
|
||
|
LPVOID lpData, // parameter for callback
|
||
|
DWORD dwFlags // move options
|
||
|
)
|
||
|
{
|
||
|
char * strCorrectExisting = CorrectPath(lpExistingFileName, "MoveFileWithProgressA");
|
||
|
char * strCorrectNew = CorrectPath(lpNewFileName, "MoveFileWithProgressA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(MoveFileWithProgressA)(strCorrectExisting, strCorrectNew, lpProgressRoutine, lpData, dwFlags);
|
||
|
|
||
|
CorrectFree(strCorrectExisting, lpExistingFileName);
|
||
|
CorrectFree(strCorrectNew, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(MoveFileWithProgressW)(
|
||
|
LPCWSTR lpExistingFileName, // file name
|
||
|
LPCWSTR lpNewFileName, // new file name
|
||
|
LPPROGRESS_ROUTINE lpProgressRoutine, // callback function
|
||
|
LPVOID lpData, // parameter for callback
|
||
|
DWORD dwFlags // move options
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrectExisting = CorrectPath(lpExistingFileName, "MoveFileW");
|
||
|
WCHAR * strCorrectNew = CorrectPath(lpNewFileName, "MoveFileW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(MoveFileWithProgressW)(strCorrectExisting, strCorrectNew, lpProgressRoutine, lpData, dwFlags);
|
||
|
|
||
|
CorrectFree(strCorrectExisting, lpExistingFileName);
|
||
|
CorrectFree(strCorrectNew, lpNewFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(RemoveDirectoryA)(
|
||
|
LPCSTR lpPathName // directory name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpPathName, "RemoveDirectoryA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(RemoveDirectoryA)(strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpPathName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(RemoveDirectoryW)(
|
||
|
LPCWSTR lpPathName // directory name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpPathName, "RemoveDirectoryW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(RemoveDirectoryW)(strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpPathName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(SetCurrentDirectoryA)(
|
||
|
LPCSTR lpPathName // new directory name
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpPathName, "SetCurrentDirectoryA");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(SetCurrentDirectoryA)(strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpPathName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
BOOL APIHOOK(SetCurrentDirectoryW)(
|
||
|
LPCWSTR lpPathName // new directory name
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpPathName, "SetCurrentDirectoryW");
|
||
|
|
||
|
BOOL returnValue = ORIGINAL_API(SetCurrentDirectoryW)(strCorrect);
|
||
|
|
||
|
CorrectFree(strCorrect, lpPathName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
HFILE APIHOOK(OpenFile)(
|
||
|
LPCSTR lpFileName, // file name
|
||
|
LPOFSTRUCT lpReOpenBuff, // file information
|
||
|
UINT uStyle // action and attributes
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpFileName, "OpenFile");
|
||
|
|
||
|
HFILE returnValue = ORIGINAL_API(OpenFile)(strCorrect, lpReOpenBuff, uStyle);
|
||
|
|
||
|
CorrectFree(strCorrect, lpFileName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
LONG APIHOOK(RegSetValueA)(
|
||
|
HKEY hKey, // handle to key
|
||
|
LPCSTR lpSubKey, // subkey name
|
||
|
DWORD dwType, // information type
|
||
|
LPCSTR lpData, // value data
|
||
|
DWORD cbData // size of value data
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpData, "RegSetValueA", FALSE);
|
||
|
|
||
|
// Data key is length of string *not* including null byte.
|
||
|
if (strCorrect)
|
||
|
{
|
||
|
cbData = strlen(strCorrect);
|
||
|
}
|
||
|
|
||
|
LONG returnValue = ORIGINAL_API(RegSetValueA)(hKey, lpSubKey, dwType, strCorrect, cbData);
|
||
|
|
||
|
CorrectFree(strCorrect, lpData);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
LONG APIHOOK(RegSetValueW)(
|
||
|
HKEY hKey, // handle to key
|
||
|
LPCWSTR lpSubKey, // subkey name
|
||
|
DWORD dwType, // information type
|
||
|
LPCWSTR lpData, // value data
|
||
|
DWORD cbData // size of value data
|
||
|
)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath(lpData, "RegSetValueW", FALSE);
|
||
|
|
||
|
// Data key is length of string *not* including null byte.
|
||
|
if (strCorrect)
|
||
|
cbData = wcslen(strCorrect);
|
||
|
|
||
|
LONG returnValue = ORIGINAL_API(RegSetValueW)(hKey, lpSubKey, dwType, strCorrect, cbData);
|
||
|
|
||
|
CorrectFree(strCorrect, lpData);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
LONG APIHOOK(RegSetValueExA)(
|
||
|
HKEY hKey, // handle to key
|
||
|
LPCSTR lpValueName, // value name
|
||
|
DWORD Reserved, // reserved
|
||
|
DWORD dwType, // value type
|
||
|
CONST BYTE *lpData, // value data
|
||
|
DWORD cbData // size of value data
|
||
|
)
|
||
|
{
|
||
|
if (dwType == REG_SZ)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath((const char *)lpData, "RegSetValueExA", FALSE);
|
||
|
|
||
|
// Data key is length of string *including* null byte.
|
||
|
if (strCorrect)
|
||
|
{
|
||
|
cbData = strlen(strCorrect) + 1;
|
||
|
}
|
||
|
|
||
|
LONG returnValue = ORIGINAL_API(RegSetValueExA)(
|
||
|
hKey, // handle to key
|
||
|
lpValueName, // value name
|
||
|
Reserved, // reserved
|
||
|
dwType, // value type
|
||
|
(CONST BYTE *)strCorrect, // value data
|
||
|
cbData);
|
||
|
CorrectFree(strCorrect, (const char *)lpData);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Pass data on through
|
||
|
LONG returnValue = ORIGINAL_API(RegSetValueExA)(
|
||
|
hKey, // handle to key
|
||
|
lpValueName, // value name
|
||
|
Reserved, // reserved
|
||
|
dwType, // value type
|
||
|
lpData, // value data
|
||
|
cbData);
|
||
|
return returnValue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LONG APIHOOK(RegSetValueExW)(
|
||
|
HKEY hKey, // handle to key
|
||
|
LPCWSTR lpValueName, // value name
|
||
|
DWORD Reserved, // reserved
|
||
|
DWORD dwType, // value type
|
||
|
CONST BYTE *lpData, // value data
|
||
|
DWORD cbData // size of value data
|
||
|
)
|
||
|
{
|
||
|
if (dwType == REG_SZ)
|
||
|
{
|
||
|
WCHAR * strCorrect = CorrectPath((const WCHAR*)lpData, "RegSetValueExW", FALSE);
|
||
|
|
||
|
// Data key is length of string *including* null byte.
|
||
|
if (strCorrect)
|
||
|
{
|
||
|
cbData = wcslen(strCorrect) + 1;
|
||
|
}
|
||
|
|
||
|
LONG returnValue = ORIGINAL_API(RegSetValueExW)(
|
||
|
hKey, // handle to key
|
||
|
lpValueName, // value name
|
||
|
Reserved, // reserved
|
||
|
dwType, // value type
|
||
|
(CONST BYTE *)strCorrect, // value data
|
||
|
cbData);
|
||
|
CorrectFree(strCorrect, (const WCHAR *)lpData);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Pass data on through
|
||
|
LONG returnValue = ORIGINAL_API(RegSetValueExW)(
|
||
|
hKey, // handle to key
|
||
|
lpValueName, // value name
|
||
|
Reserved, // reserved
|
||
|
dwType, // value type
|
||
|
lpData, // value data
|
||
|
cbData);
|
||
|
return returnValue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HFILE APIHOOK(_lopen)(
|
||
|
LPCSTR lpPathName,
|
||
|
int iReadWrite
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpPathName, "lopen");
|
||
|
|
||
|
HFILE returnValue = ORIGINAL_API(_lopen)(strCorrect, iReadWrite);
|
||
|
|
||
|
CorrectFree(strCorrect, lpPathName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
HFILE APIHOOK(_lcreat)(
|
||
|
LPCSTR lpPathName,
|
||
|
int iAttribute
|
||
|
)
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpPathName, "lcreat");
|
||
|
|
||
|
HFILE returnValue = ORIGINAL_API(_lcreat)(strCorrect, iAttribute);
|
||
|
|
||
|
CorrectFree(strCorrect, lpPathName);
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
HANDLE
|
||
|
APIHOOK(LoadImageA)(
|
||
|
HINSTANCE hinst, // handle to instance
|
||
|
LPCSTR lpszName, // name or identifier of the image
|
||
|
UINT uType, // image type
|
||
|
int cxDesired, // desired width
|
||
|
int cyDesired, // desired height
|
||
|
UINT fuLoad // load options
|
||
|
)
|
||
|
{
|
||
|
HANDLE returnValue = NULL;
|
||
|
|
||
|
// Another one of those incredibly overloaded API's:
|
||
|
// lpszName is not always a path
|
||
|
if ((uType == IMAGE_BITMAP) &&
|
||
|
(fuLoad & LR_LOADFROMFILE) &&
|
||
|
!IsBadStringPtrA(lpszName, 1))
|
||
|
{
|
||
|
char * strCorrect = CorrectPath(lpszName, "LoadImageA");
|
||
|
|
||
|
returnValue = ORIGINAL_API(LoadImageA)(hinst, strCorrect, uType, cxDesired, cyDesired, fuLoad);
|
||
|
|
||
|
CorrectFree(strCorrect, lpszName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
returnValue = ORIGINAL_API(LoadImageA)(hinst, lpszName, uType, cxDesired, cyDesired, fuLoad);
|
||
|
}
|
||
|
|
||
|
return returnValue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
IMPLEMENT_COMSERVER_HOOK(SHELL32)
|
||
|
|
||
|
BOOL
|
||
|
NOTIFY_FUNCTION(
|
||
|
DWORD fdwReason
|
||
|
)
|
||
|
{
|
||
|
BOOL bSuccess = TRUE;
|
||
|
|
||
|
if (fdwReason == DLL_PROCESS_ATTACH)
|
||
|
{
|
||
|
bSuccess = ParseCommandLine(COMMAND_LINE);
|
||
|
if (bSuccess)
|
||
|
{
|
||
|
// Create g_AllocatedPathCorrector
|
||
|
return InitPathcorrectorClass();
|
||
|
}
|
||
|
}
|
||
|
else if (fdwReason == SHIM_STATIC_DLLS_INITIALIZED)
|
||
|
{
|
||
|
// It is now safe for us to do our work
|
||
|
g_PathCorrector = g_AllocatedPathCorrector;
|
||
|
InitializePathCorrections();
|
||
|
}
|
||
|
return bSuccess;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Register hooked functions
|
||
|
|
||
|
--*/
|
||
|
|
||
|
HOOK_BEGIN
|
||
|
|
||
|
CALL_NOTIFY_FUNCTION
|
||
|
|
||
|
if (g_bCreateProcessRoutines)
|
||
|
{
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CreateProcessA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CreateProcessW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, WinExec)
|
||
|
|
||
|
APIHOOK_ENTRY(SHELL32.DLL, ShellExecuteA)
|
||
|
APIHOOK_ENTRY(SHELL32.DLL, ShellExecuteW)
|
||
|
APIHOOK_ENTRY(SHELL32.DLL, ShellExecuteExA)
|
||
|
APIHOOK_ENTRY(SHELL32.DLL, ShellExecuteExW)
|
||
|
}
|
||
|
|
||
|
if (g_bGetCommandLineRoutines)
|
||
|
{
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetCommandLineA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetCommandLineW)
|
||
|
}
|
||
|
|
||
|
if (g_bProfileRoutines)
|
||
|
{
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileIntA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileIntW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileSectionA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileSectionW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileSectionNamesA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileSectionNamesW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileStringA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileStringW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileStructA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetPrivateProfileStructW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, WritePrivateProfileSectionA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, WritePrivateProfileSectionW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, WritePrivateProfileStringA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, WritePrivateProfileStringW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, WritePrivateProfileStructA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, WritePrivateProfileStructW)
|
||
|
}
|
||
|
|
||
|
if (g_bFileRoutines)
|
||
|
{
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CopyFileA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CopyFileW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CopyFileExA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CopyFileExW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CreateDirectoryA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CreateDirectoryW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CreateDirectoryExA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CreateDirectoryExW)
|
||
|
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CreateFileA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, CreateFileW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, DeleteFileA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, DeleteFileW)
|
||
|
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, FindFirstFileA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, FindFirstFileW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, FindFirstFileExA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, FindFirstFileExW)
|
||
|
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetBinaryTypeA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetBinaryTypeW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesExA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesExW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, SetFileAttributesA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, SetFileAttributesW)
|
||
|
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, MoveFileA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, MoveFileW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, MoveFileExA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, MoveFileExW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, MoveFileWithProgressA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, MoveFileWithProgressW)
|
||
|
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, RemoveDirectoryA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, RemoveDirectoryW)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, SetCurrentDirectoryA)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, SetCurrentDirectoryW)
|
||
|
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, OpenFile)
|
||
|
|
||
|
// 16 bit compatibility file routines
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, _lopen)
|
||
|
APIHOOK_ENTRY(KERNEL32.DLL, _lcreat)
|
||
|
}
|
||
|
|
||
|
if (g_bRegSetValueRoutines)
|
||
|
{
|
||
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegSetValueA)
|
||
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegSetValueW)
|
||
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegSetValueExA)
|
||
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegSetValueExW)
|
||
|
}
|
||
|
|
||
|
if (g_bShellLinkRoutines)
|
||
|
{
|
||
|
APIHOOK_ENTRY_COMSERVER(SHELL32)
|
||
|
|
||
|
COMHOOK_ENTRY(ShellLink, IShellLinkA, SetPath, 20)
|
||
|
COMHOOK_ENTRY(ShellLink, IShellLinkW, SetPath, 20)
|
||
|
COMHOOK_ENTRY(ShellLink, IShellLinkA, SetArguments, 11)
|
||
|
COMHOOK_ENTRY(ShellLink, IShellLinkW, SetArguments, 11)
|
||
|
COMHOOK_ENTRY(ShellLink, IShellLinkA, SetIconLocation, 17)
|
||
|
COMHOOK_ENTRY(ShellLink, IShellLinkW, SetIconLocation, 17)
|
||
|
|
||
|
COMHOOK_ENTRY(ShellLink, IPersistFile, Save, 6)
|
||
|
}
|
||
|
|
||
|
if (g_bLoadImage)
|
||
|
{
|
||
|
APIHOOK_ENTRY(USER32.DLL, LoadImageA)
|
||
|
}
|
||
|
|
||
|
HOOK_END
|
||
|
|
||
|
IMPLEMENT_SHIM_END
|
||
|
|