You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4234 lines
123 KiB
4234 lines
123 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
FilePaths.cpp
|
|
|
|
Abstract:
|
|
|
|
This AppVerifier shim hooks the APIs that require
|
|
the caller to provide a path to a file or directory
|
|
and attempts to ensure that the path is not a hardcoded
|
|
one.
|
|
|
|
Notes:
|
|
|
|
This is a general purpose shim.
|
|
|
|
Created:
|
|
|
|
02/26/2001 clupu
|
|
|
|
Modified:
|
|
|
|
07/24/2001 rparsons Added hooks for Nt* calls
|
|
Added checks for apps that use environment variables
|
|
|
|
09/04/2001 rparsons Fixed a bug in the Massage functions where we would
|
|
stop processing a fake path as soon as we found a hardcode
|
|
path. Also, we now fix multiple fake paths in the same string.
|
|
|
|
10/17/2001 rparsons Fixed bug where we wouldn't always report a bad path.
|
|
This was because the CString Find method is case sensitive,
|
|
but the paths we were comparing were mixed in case. Now all
|
|
paths are in lower case form prior to the comparison.
|
|
|
|
11/21/2001 rparsons Fixed Raid bug # 492674. FilePaths did not contain an implementation
|
|
for SHFileOperation - apps that used this API would not get their
|
|
paths corrected, thus failing.
|
|
|
|
11/29/2001 rparsons Fixed Raid bug # 497853. Removed the hooks for GetTempFileName as they
|
|
were causing a false positive to be generated. Also added code that
|
|
would handle cases where the user provides a path via a common dialog
|
|
and we provide a fake path to be massaged later.
|
|
|
|
12/11/2001 rparsons Fixed Raid bug # 505599. Added hooks for all RegQueryValue* calls
|
|
and NtQueryValueKey. The Nt hook allows us to catch paths for
|
|
system components.
|
|
|
|
02/20/2002 rparsons Implemented strsafe functions.
|
|
--*/
|
|
#include "precomp.h"
|
|
#include "rtlutils.h"
|
|
|
|
IMPLEMENT_SHIM_BEGIN(FilePaths)
|
|
#include "ShimHookMacro.h"
|
|
#include "ShimCString.h"
|
|
#include "veriflog.h"
|
|
#include "ids.h"
|
|
|
|
APIHOOK_ENUM_BEGIN
|
|
|
|
APIHOOK_ENUM_ENTRY(GetCommandLineA)
|
|
APIHOOK_ENUM_ENTRY(GetCommandLineW)
|
|
|
|
APIHOOK_ENUM_ENTRY(GetTempPathA)
|
|
APIHOOK_ENUM_ENTRY(GetTempPathW)
|
|
|
|
APIHOOK_ENUM_ENTRY(GetOpenFileNameA)
|
|
APIHOOK_ENUM_ENTRY(GetOpenFileNameW)
|
|
|
|
APIHOOK_ENUM_ENTRY(GetSaveFileNameA)
|
|
APIHOOK_ENUM_ENTRY(GetSaveFileNameW)
|
|
|
|
APIHOOK_ENUM_ENTRY(GetModuleFileNameA)
|
|
APIHOOK_ENUM_ENTRY(GetModuleFileNameW)
|
|
APIHOOK_ENUM_ENTRY(GetModuleFileNameExA)
|
|
APIHOOK_ENUM_ENTRY(GetModuleFileNameExW)
|
|
|
|
APIHOOK_ENUM_ENTRY(GetCurrentDirectoryA)
|
|
APIHOOK_ENUM_ENTRY(GetCurrentDirectoryW)
|
|
|
|
APIHOOK_ENUM_ENTRY(GetSystemDirectoryA)
|
|
APIHOOK_ENUM_ENTRY(GetSystemDirectoryW)
|
|
APIHOOK_ENUM_ENTRY(GetSystemWindowsDirectoryA)
|
|
APIHOOK_ENUM_ENTRY(GetSystemWindowsDirectoryW)
|
|
APIHOOK_ENUM_ENTRY(GetWindowsDirectoryA)
|
|
APIHOOK_ENUM_ENTRY(GetWindowsDirectoryW)
|
|
|
|
APIHOOK_ENUM_ENTRY(SHGetFolderPathA)
|
|
APIHOOK_ENUM_ENTRY(SHGetFolderPathW)
|
|
|
|
APIHOOK_ENUM_ENTRY(SHGetSpecialFolderPathA)
|
|
APIHOOK_ENUM_ENTRY(SHGetSpecialFolderPathW)
|
|
|
|
APIHOOK_ENUM_ENTRY(SHGetPathFromIDListA)
|
|
APIHOOK_ENUM_ENTRY(SHGetPathFromIDListW)
|
|
|
|
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(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(LoadLibraryA)
|
|
APIHOOK_ENUM_ENTRY(LoadLibraryW)
|
|
APIHOOK_ENUM_ENTRY(LoadLibraryExA)
|
|
APIHOOK_ENUM_ENTRY(LoadLibraryExW)
|
|
|
|
APIHOOK_ENUM_ENTRY(SearchPathA)
|
|
APIHOOK_ENUM_ENTRY(SearchPathW)
|
|
|
|
APIHOOK_ENUM_ENTRY(SHFileOperationA)
|
|
APIHOOK_ENUM_ENTRY(SHFileOperationW)
|
|
|
|
APIHOOK_ENUM_ENTRY(ExpandEnvironmentStringsA)
|
|
APIHOOK_ENUM_ENTRY(ExpandEnvironmentStringsW)
|
|
|
|
APIHOOK_ENUM_ENTRY(GetFileVersionInfoSizeA)
|
|
APIHOOK_ENUM_ENTRY(GetFileVersionInfoSizeW)
|
|
APIHOOK_ENUM_ENTRY(GetFileVersionInfoA)
|
|
APIHOOK_ENUM_ENTRY(GetFileVersionInfoW)
|
|
|
|
APIHOOK_ENUM_ENTRY(OpenFile)
|
|
|
|
APIHOOK_ENUM_ENTRY(RegQueryValueA)
|
|
APIHOOK_ENUM_ENTRY(RegQueryValueW)
|
|
APIHOOK_ENUM_ENTRY(RegQueryValueExA)
|
|
APIHOOK_ENUM_ENTRY(RegQueryValueExW)
|
|
|
|
APIHOOK_ENUM_ENTRY(RegSetValueA)
|
|
APIHOOK_ENUM_ENTRY(RegSetValueW)
|
|
APIHOOK_ENUM_ENTRY(RegSetValueExA)
|
|
APIHOOK_ENUM_ENTRY(RegSetValueExW)
|
|
|
|
APIHOOK_ENUM_ENTRY(NtCreateFile)
|
|
APIHOOK_ENUM_ENTRY(NtOpenFile)
|
|
APIHOOK_ENUM_ENTRY(NtQueryAttributesFile)
|
|
APIHOOK_ENUM_ENTRY(NtQueryFullAttributesFile)
|
|
APIHOOK_ENUM_ENTRY(NtCreateProcessEx)
|
|
|
|
APIHOOK_ENUM_ENTRY(_lopen)
|
|
APIHOOK_ENUM_ENTRY(_lcreat)
|
|
|
|
APIHOOK_ENUM_END
|
|
|
|
//
|
|
// verifier log entries
|
|
//
|
|
BEGIN_DEFINE_VERIFIER_LOG(FilePaths)
|
|
VERIFIER_LOG_ENTRY(VLOG_HARDCODED_GETTEMPPATH)
|
|
VERIFIER_LOG_ENTRY(VLOG_HARDCODED_WINDOWSPATH)
|
|
VERIFIER_LOG_ENTRY(VLOG_HARDCODED_SYSWINDOWSPATH)
|
|
VERIFIER_LOG_ENTRY(VLOG_HARDCODED_SYSTEMPATH)
|
|
VERIFIER_LOG_ENTRY(VLOG_HARDCODED_PERSONALPATH)
|
|
VERIFIER_LOG_ENTRY(VLOG_HARDCODED_COMMONPROGRAMS)
|
|
VERIFIER_LOG_ENTRY(VLOG_HARDCODED_COMMONSTARTMENU)
|
|
VERIFIER_LOG_ENTRY(VLOG_HARDCODED_PROGRAMS)
|
|
VERIFIER_LOG_ENTRY(VLOG_HARDCODED_STARTMENU)
|
|
END_DEFINE_VERIFIER_LOG(FilePaths)
|
|
|
|
INIT_VERIFIER_LOG(FilePaths);
|
|
|
|
|
|
// This is a private define (shlapip.h) that can mess up ShellExecuteEx
|
|
#ifndef SEE_MASK_FILEANDURL
|
|
#define SEE_MASK_FILEANDURL 0x00400000
|
|
#endif
|
|
|
|
#define MAX_HARDCODED_PATHS 4
|
|
|
|
//
|
|
// Linked-list for SHFileOperation
|
|
//
|
|
typedef struct FILELIST {
|
|
struct FILELIST* pNext;
|
|
UINT cchSize;
|
|
LPWSTR pwszFilePath;
|
|
} FILELIST, *PFILELIST;
|
|
|
|
enum ListType {
|
|
eFrom = 0,
|
|
eTo
|
|
};
|
|
|
|
//
|
|
// Head of the linked-lists for SHFileOperation
|
|
//
|
|
PFILELIST g_pFileListFromHead = NULL;
|
|
PFILELIST g_pFileListToHead = NULL;
|
|
|
|
//
|
|
// Critical section to keep our linked list safe.
|
|
//
|
|
RTL_CRITICAL_SECTION g_csLinkedList;
|
|
|
|
//
|
|
// Fake command-line for GetCommandLine calls.
|
|
//
|
|
LPSTR g_pszCommandLineA;
|
|
LPWSTR g_pwszCommandLineW;
|
|
|
|
typedef struct _PATH_INFO {
|
|
char szSimulatedPathA[256];
|
|
WCHAR szSimulatedPathW[256];
|
|
|
|
char szCorrectPathA[MAX_PATH];
|
|
WCHAR szCorrectPathW[MAX_PATH];
|
|
|
|
int nSimulatedPathLen;
|
|
int nCorrectPathLen;
|
|
|
|
char szHardCodedPathsA[MAX_HARDCODED_PATHS][MAX_PATH];
|
|
WCHAR szHardCodedPathsW[MAX_HARDCODED_PATHS][MAX_PATH];
|
|
|
|
DWORD dwIssueCode;
|
|
} PATH_INFO, *PPATH_INFO;
|
|
|
|
|
|
//
|
|
// the following enum and the g_Paths initializers must be kept in parallel
|
|
// Note: The paths must be in lower case for the comparison to work properly.
|
|
//
|
|
enum _PATH_NUM {
|
|
PATH_TEMP = 0,
|
|
PATH_WINDOWS,
|
|
PATH_SYSTEM_WINDOWS,
|
|
PATH_SYSTEM,
|
|
PATH_PERSONAL,
|
|
PATH_COMMON_PROGRAMS,
|
|
PATH_COMMON_STARTMENU,
|
|
PATH_PROGRAMS,
|
|
PATH_STARTMENU
|
|
};
|
|
|
|
PATH_INFO g_Paths[] = {
|
|
{
|
|
"c:\\abc\\temppath\\123\\",
|
|
L"c:\\abc\\temppath\\123\\",
|
|
"",
|
|
L"",
|
|
0,
|
|
0,
|
|
{
|
|
"\\temp\\",
|
|
"",
|
|
"",
|
|
""
|
|
},
|
|
{
|
|
L"\\temp\\",
|
|
L"",
|
|
L"",
|
|
L""
|
|
},
|
|
VLOG_HARDCODED_GETTEMPPATH
|
|
},
|
|
{
|
|
"c:\\abc\\windowsdir\\123",
|
|
L"c:\\abc\\windowsdir\\123",
|
|
"",
|
|
L"",
|
|
0,
|
|
0,
|
|
{
|
|
":\\windows\\",
|
|
":\\winnt\\",
|
|
"",
|
|
""
|
|
},
|
|
{
|
|
L":\\windows\\",
|
|
L":\\winnt\\",
|
|
L"",
|
|
L""
|
|
},
|
|
VLOG_HARDCODED_WINDOWSPATH
|
|
},
|
|
{
|
|
"c:\\abc\\systemwindowsdir\\123",
|
|
L"c:\\abc\\systemwindowsdir\\123",
|
|
"",
|
|
L"",
|
|
0,
|
|
0,
|
|
{
|
|
":\\windows\\",
|
|
":\\winnt\\",
|
|
"",
|
|
""
|
|
},
|
|
{
|
|
L":\\windows\\",
|
|
L":\\winnt\\",
|
|
L"",
|
|
L""
|
|
},
|
|
VLOG_HARDCODED_SYSWINDOWSPATH
|
|
},
|
|
{
|
|
"c:\\abc\\systemdir\\123",
|
|
L"c:\\abc\\systemdir\\123",
|
|
"",
|
|
L"",
|
|
0,
|
|
0,
|
|
{
|
|
"\\system\\",
|
|
"\\system32\\",
|
|
"",
|
|
""
|
|
},
|
|
{
|
|
L"\\system\\",
|
|
L"\\system32\\",
|
|
L"",
|
|
L""
|
|
},
|
|
VLOG_HARDCODED_SYSTEMPATH
|
|
},
|
|
{
|
|
"c:\\abc\\personal\\123",
|
|
L"c:\\abc\\personal\\123",
|
|
"",
|
|
L"",
|
|
0,
|
|
0,
|
|
{
|
|
"\\my documents\\",
|
|
"",
|
|
"",
|
|
""
|
|
},
|
|
{
|
|
L"\\my documents\\",
|
|
L"",
|
|
L"",
|
|
L""
|
|
},
|
|
VLOG_HARDCODED_PERSONALPATH
|
|
},
|
|
{
|
|
"c:\\abc\\commonprograms\\123",
|
|
L"c:\\abc\\commonprograms\\123",
|
|
"",
|
|
L"",
|
|
0,
|
|
0,
|
|
{
|
|
"\\all users\\start menu\\programs\\",
|
|
"",
|
|
"",
|
|
""
|
|
},
|
|
{
|
|
L"\\all users\\start menu\\programs\\",
|
|
L"",
|
|
L"",
|
|
L""
|
|
},
|
|
VLOG_HARDCODED_COMMONPROGRAMS
|
|
},
|
|
{
|
|
"c:\\abc\\commonstartmenu\\123",
|
|
L"c:\\abc\\commonstartmenu\\123",
|
|
"",
|
|
L"",
|
|
0,
|
|
0,
|
|
{
|
|
"\\all users\\start menu\\",
|
|
"",
|
|
"",
|
|
""
|
|
},
|
|
{
|
|
L"\\all users\\start menu\\",
|
|
L"",
|
|
L"",
|
|
L""
|
|
},
|
|
VLOG_HARDCODED_COMMONSTARTMENU
|
|
},
|
|
{
|
|
"c:\\abc\\programs\\123",
|
|
L"c:\\abc\\programs\\123",
|
|
"",
|
|
L"",
|
|
0,
|
|
0,
|
|
{
|
|
"\\start menu\\programs\\",
|
|
"",
|
|
"",
|
|
""
|
|
},
|
|
{
|
|
L"\\start menu\\programs\\",
|
|
L"",
|
|
L"",
|
|
L""
|
|
},
|
|
VLOG_HARDCODED_PROGRAMS
|
|
},
|
|
{
|
|
"c:\\abc\\startmenu\\123",
|
|
L"c:\\abc\\startmenu\\123",
|
|
"",
|
|
L"",
|
|
0,
|
|
0,
|
|
{
|
|
"\\start menu\\",
|
|
"",
|
|
"",
|
|
""
|
|
},
|
|
{
|
|
L"\\start menu\\",
|
|
L"",
|
|
L"",
|
|
L""
|
|
},
|
|
VLOG_HARDCODED_STARTMENU
|
|
}
|
|
|
|
};
|
|
|
|
const int g_nPaths = sizeof(g_Paths)/sizeof(g_Paths[0]);
|
|
|
|
static BOOL g_bPathsInited = FALSE;
|
|
|
|
void
|
|
InitFakeCommandLine(
|
|
void
|
|
)
|
|
{
|
|
int cchSize;
|
|
int nPathIndex;
|
|
BOOL fReplaced = FALSE;
|
|
|
|
CString csCommandLine(GetCommandLineW());
|
|
|
|
csCommandLine.MakeLower();
|
|
|
|
//
|
|
// Point them to the normal command-line at first.
|
|
//
|
|
g_pwszCommandLineW = GetCommandLineW();
|
|
g_pszCommandLineA = GetCommandLineA();
|
|
|
|
//
|
|
// Replace real paths with simulated paths.
|
|
//
|
|
for (nPathIndex = 0; nPathIndex < g_nPaths; ++nPathIndex) {
|
|
if (csCommandLine.Replace(g_Paths[nPathIndex].szCorrectPathW,
|
|
g_Paths[nPathIndex].szSimulatedPathW)) {
|
|
fReplaced = TRUE;
|
|
}
|
|
}
|
|
|
|
if (fReplaced) {
|
|
//
|
|
// Allocate room on the heap and save the command line away.
|
|
//
|
|
cchSize = csCommandLine.GetLength();
|
|
|
|
g_pwszCommandLineW = (LPWSTR)malloc(cchSize * sizeof(WCHAR));
|
|
|
|
if (!g_pwszCommandLineW) {
|
|
DPFN(eDbgLevelError, "[InitFakeCommandLine] No memory available");
|
|
return;
|
|
}
|
|
|
|
g_pszCommandLineA = (LPSTR)malloc(cchSize);
|
|
|
|
if (!g_pszCommandLineA) {
|
|
DPFN(eDbgLevelError, "[InitFakeCommandLine] No memory available");
|
|
free(g_pwszCommandLineW);
|
|
return;
|
|
}
|
|
|
|
StringCchCopy(g_pwszCommandLineW, cchSize, csCommandLine.Get());
|
|
StringCchCopyA(g_pszCommandLineA, cchSize, csCommandLine.GetAnsi());
|
|
}
|
|
}
|
|
|
|
void
|
|
InitPaths(
|
|
void
|
|
)
|
|
{
|
|
g_bPathsInited = TRUE;
|
|
|
|
//
|
|
// Convert paths to lower case as this is necessary when performing
|
|
// the comparison.
|
|
//
|
|
CharLowerA(g_Paths[PATH_TEMP].szCorrectPathA);
|
|
CharLowerW(g_Paths[PATH_TEMP].szCorrectPathW);
|
|
|
|
CharLowerA(g_Paths[PATH_WINDOWS].szCorrectPathA);
|
|
CharLowerW(g_Paths[PATH_WINDOWS].szCorrectPathW);
|
|
|
|
CharLowerA(g_Paths[PATH_SYSTEM_WINDOWS].szCorrectPathA);
|
|
CharLowerW(g_Paths[PATH_SYSTEM_WINDOWS].szCorrectPathW);
|
|
|
|
CharLowerA(g_Paths[PATH_SYSTEM].szCorrectPathA);
|
|
CharLowerW(g_Paths[PATH_SYSTEM].szCorrectPathW);
|
|
|
|
SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_PERSONAL].szCorrectPathA);
|
|
SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_PERSONAL].szCorrectPathW);
|
|
g_Paths[PATH_PERSONAL].nCorrectPathLen = strlen(g_Paths[PATH_PERSONAL].szCorrectPathA);
|
|
g_Paths[PATH_PERSONAL].nSimulatedPathLen = strlen(g_Paths[PATH_PERSONAL].szSimulatedPathA);
|
|
CharLowerA(g_Paths[PATH_PERSONAL].szCorrectPathA);
|
|
CharLowerW(g_Paths[PATH_PERSONAL].szCorrectPathW);
|
|
|
|
SHGetFolderPathA(NULL, CSIDL_STARTMENU, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_STARTMENU].szCorrectPathA);
|
|
SHGetFolderPathW(NULL, CSIDL_STARTMENU, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_STARTMENU].szCorrectPathW);
|
|
g_Paths[PATH_STARTMENU].nCorrectPathLen = strlen(g_Paths[PATH_STARTMENU].szCorrectPathA);
|
|
g_Paths[PATH_STARTMENU].nSimulatedPathLen = strlen(g_Paths[PATH_STARTMENU].szSimulatedPathA);
|
|
CharLowerA(g_Paths[PATH_STARTMENU].szCorrectPathA);
|
|
CharLowerW(g_Paths[PATH_STARTMENU].szCorrectPathW);
|
|
|
|
SHGetFolderPathA(NULL, CSIDL_COMMON_STARTMENU, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_COMMON_STARTMENU].szCorrectPathA);
|
|
SHGetFolderPathW(NULL, CSIDL_COMMON_STARTMENU, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_COMMON_STARTMENU].szCorrectPathW);
|
|
g_Paths[PATH_COMMON_STARTMENU].nCorrectPathLen = strlen(g_Paths[PATH_COMMON_STARTMENU].szCorrectPathA);
|
|
g_Paths[PATH_COMMON_STARTMENU].nSimulatedPathLen = strlen(g_Paths[PATH_COMMON_STARTMENU].szSimulatedPathA);
|
|
CharLowerA(g_Paths[PATH_COMMON_STARTMENU].szCorrectPathA);
|
|
CharLowerW(g_Paths[PATH_COMMON_STARTMENU].szCorrectPathW);
|
|
|
|
SHGetFolderPathA(NULL, CSIDL_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_PROGRAMS].szCorrectPathA);
|
|
SHGetFolderPathW(NULL, CSIDL_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_PROGRAMS].szCorrectPathW);
|
|
g_Paths[PATH_PROGRAMS].nCorrectPathLen = strlen(g_Paths[PATH_PROGRAMS].szCorrectPathA);
|
|
g_Paths[PATH_PROGRAMS].nSimulatedPathLen = strlen(g_Paths[PATH_PROGRAMS].szSimulatedPathA);
|
|
CharLowerA(g_Paths[PATH_PROGRAMS].szCorrectPathA);
|
|
CharLowerW(g_Paths[PATH_PROGRAMS].szCorrectPathW);
|
|
|
|
SHGetFolderPathA(NULL, CSIDL_COMMON_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_COMMON_PROGRAMS].szCorrectPathA);
|
|
SHGetFolderPathW(NULL, CSIDL_COMMON_PROGRAMS, NULL, SHGFP_TYPE_CURRENT, g_Paths[PATH_COMMON_PROGRAMS].szCorrectPathW);
|
|
g_Paths[PATH_COMMON_PROGRAMS].nCorrectPathLen = strlen(g_Paths[PATH_COMMON_PROGRAMS].szCorrectPathA);
|
|
g_Paths[PATH_COMMON_PROGRAMS].nSimulatedPathLen = strlen(g_Paths[PATH_COMMON_PROGRAMS].szSimulatedPathA);
|
|
CharLowerA(g_Paths[PATH_COMMON_PROGRAMS].szCorrectPathA);
|
|
CharLowerW(g_Paths[PATH_COMMON_PROGRAMS].szCorrectPathW);
|
|
|
|
InitFakeCommandLine();
|
|
}
|
|
|
|
inline void
|
|
FPFreeA(
|
|
LPSTR lpMalloc,
|
|
LPCSTR lpOrig
|
|
)
|
|
{
|
|
if (lpMalloc != lpOrig) {
|
|
free((LPVOID)lpMalloc);
|
|
}
|
|
}
|
|
|
|
inline void
|
|
FPFreeW(
|
|
LPWSTR lpMalloc,
|
|
LPCWSTR lpOrig
|
|
)
|
|
{
|
|
if (lpMalloc != lpOrig) {
|
|
free((LPVOID)lpMalloc);
|
|
}
|
|
}
|
|
|
|
void
|
|
MassageRealPathToFakePathW(
|
|
LPWSTR pwszPath,
|
|
DWORD cchBufferSize
|
|
)
|
|
{
|
|
int nPathIndex;
|
|
BOOL fReplaced = FALSE;
|
|
|
|
if (!pwszPath || 0 == cchBufferSize) {
|
|
return;
|
|
}
|
|
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
DPFN(eDbgLevelInfo, "[MassageRealPathToFakePath] '%ls'", pwszPath);
|
|
|
|
CString csString(pwszPath);
|
|
|
|
csString.MakeLower();
|
|
|
|
//
|
|
// Replace real paths with simulated paths.
|
|
//
|
|
for (nPathIndex = 0; nPathIndex < g_nPaths; ++nPathIndex) {
|
|
if (csString.Replace(g_Paths[nPathIndex].szCorrectPathW,
|
|
g_Paths[nPathIndex].szSimulatedPathW)) {
|
|
fReplaced = TRUE;
|
|
}
|
|
}
|
|
|
|
if (fReplaced) {
|
|
//
|
|
// Ensure that the buffer is large enough to contain the new path.
|
|
//
|
|
if (cchBufferSize < (DWORD)csString.GetLength()) {
|
|
DPFN(eDbgLevelError,
|
|
"[MassageRealPathToFakePath] Buffer is not large enough. Need %d have %lu",
|
|
csString.GetLength(),
|
|
cchBufferSize);
|
|
return;
|
|
} else {
|
|
StringCchCopy(pwszPath, cchBufferSize, csString);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
MassageRealPathToFakePathA(
|
|
LPSTR pszPath,
|
|
DWORD cchBufferSize
|
|
)
|
|
{
|
|
int nPathIndex;
|
|
BOOL fReplaced = FALSE;
|
|
|
|
if (!pszPath || 0 == cchBufferSize) {
|
|
return;
|
|
}
|
|
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
DPFN(eDbgLevelInfo, "[MassageRealPathToFakePath] '%s'", pszPath);
|
|
|
|
CString csString(pszPath);
|
|
|
|
csString.MakeLower();
|
|
|
|
//
|
|
// Replace real paths with simulated paths.
|
|
//
|
|
for (nPathIndex = 0; nPathIndex < g_nPaths; ++nPathIndex) {
|
|
if (csString.Replace(g_Paths[nPathIndex].szCorrectPathW,
|
|
g_Paths[nPathIndex].szSimulatedPathW)) {
|
|
fReplaced = TRUE;
|
|
}
|
|
}
|
|
|
|
if (fReplaced) {
|
|
//
|
|
// Ensure that the buffer is large enough to contain the new path.
|
|
//
|
|
if (cchBufferSize < (DWORD)csString.GetLength()) {
|
|
DPFN(eDbgLevelError,
|
|
"[MassageRealPathToFakePath] Buffer is not large enough. Need %d have %lu",
|
|
csString.GetLength(),
|
|
cchBufferSize);
|
|
return;
|
|
} else {
|
|
StringCchCopyA(pszPath, cchBufferSize, csString.GetAnsi());
|
|
}
|
|
}
|
|
}
|
|
|
|
LPWSTR
|
|
MassageStringForPathW(
|
|
LPCWSTR pwszString
|
|
)
|
|
{
|
|
int nPosition;
|
|
int nPathIndex, nHardcodedIndex;
|
|
UINT nLen = 0;
|
|
UINT cFakePaths = 0;
|
|
LPWSTR pwszPath;
|
|
LPWSTR pwszNew = NULL;
|
|
CString csToken(L"");
|
|
|
|
if (pwszString == NULL || *pwszString == 0) {
|
|
return (LPWSTR)pwszString;
|
|
}
|
|
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
DPFN(eDbgLevelInfo, "[MassageStringForPathW] '%ls'", pwszString);
|
|
|
|
//
|
|
// Search the string for hardcoded paths first.
|
|
//
|
|
CString csString(pwszString);
|
|
|
|
csString.MakeLower();
|
|
|
|
for (nPathIndex = 0; nPathIndex < g_nPaths; ++nPathIndex) {
|
|
|
|
for (nHardcodedIndex = 0; nHardcodedIndex < MAX_HARDCODED_PATHS; ++nHardcodedIndex) {
|
|
pwszPath = g_Paths[nPathIndex].szHardCodedPathsW[nHardcodedIndex];
|
|
|
|
if (!pwszPath[0]) {
|
|
break;
|
|
}
|
|
|
|
nPosition = csString.Find(pwszPath);
|
|
|
|
if (nPosition != -1) {
|
|
VLOG(VLOG_LEVEL_ERROR,
|
|
g_Paths[nPathIndex].dwIssueCode,
|
|
"Hardcoded path found in path '%ls'.",
|
|
pwszString);
|
|
break;
|
|
}
|
|
nPosition = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now search for the fake paths that we substituted ourselves.
|
|
//
|
|
CStringToken csTokenList(csString, L" ");
|
|
|
|
while (csTokenList.GetToken(csToken)) {
|
|
|
|
csToken.MakeLower();
|
|
for (nPathIndex = 0, nPosition = 0; nPathIndex < g_nPaths; ++nPathIndex) {
|
|
|
|
nPosition = csToken.Find(g_Paths[nPathIndex].szSimulatedPathW);
|
|
|
|
if (nPosition != -1) {
|
|
cFakePaths++;
|
|
break;
|
|
}
|
|
nPosition = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// See if the string contained any fake paths. If not, we're done here.
|
|
//
|
|
if (!cFakePaths) {
|
|
return (LPWSTR)pwszString;
|
|
}
|
|
|
|
//
|
|
// Our string has simulated paths; replace them.
|
|
//
|
|
for (nPathIndex = 0; nPathIndex < g_nPaths; ++nPathIndex) {
|
|
csString.Replace(g_Paths[nPathIndex].szSimulatedPathW,
|
|
g_Paths[nPathIndex].szCorrectPathW);
|
|
}
|
|
|
|
//
|
|
// Allocate a string large enough to hold the corrected path and
|
|
// give it back to the caller. They'll free it later.
|
|
//
|
|
nLen = MAX_PATH * cFakePaths;
|
|
nLen += csString.GetLength();
|
|
|
|
pwszNew = (LPWSTR)malloc((nLen + 1) * sizeof(WCHAR));
|
|
|
|
if (!pwszNew) {
|
|
DPFN(eDbgLevelError,
|
|
"[MassageStringForPathW] Failed to allocate memory");
|
|
return (LPWSTR)pwszString;
|
|
}
|
|
|
|
StringCchCopy(pwszNew, nLen + 1, csString);
|
|
|
|
DPFN(eDbgLevelInfo,
|
|
"[MassageStringForPathW] Replaced '%ls' with '%ls'",
|
|
pwszString,
|
|
pwszNew);
|
|
|
|
return pwszNew;
|
|
}
|
|
|
|
LPSTR
|
|
MassageStringForPathA(
|
|
LPCSTR pszString
|
|
)
|
|
{
|
|
int cchSize, nRetLen = 0;
|
|
WCHAR wszTmp[MAX_PATH];
|
|
LPWSTR pwszReturn = NULL;
|
|
LPSTR pszNew = NULL;
|
|
|
|
if (pszString == NULL || *pszString == 0) {
|
|
return (LPSTR)pszString;
|
|
}
|
|
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
//
|
|
// Convert from ANSI to Unicode so we can pass this on
|
|
// to the Unicode version of the function.
|
|
//
|
|
cchSize = MultiByteToWideChar(CP_ACP,
|
|
0,
|
|
pszString,
|
|
-1,
|
|
wszTmp,
|
|
ARRAYSIZE(wszTmp));
|
|
|
|
if (cchSize == 0) {
|
|
DPFN(eDbgLevelError, "[MassageStringForPathA] Ansi -> Unicode failed");
|
|
return (LPSTR)pszString;
|
|
}
|
|
|
|
pwszReturn = MassageStringForPathW(wszTmp);
|
|
|
|
//
|
|
// If the return is the same as the source, we're done.
|
|
//
|
|
if (!_wcsicmp(pwszReturn, wszTmp)) {
|
|
return (LPSTR)pszString;
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer large enough to hold the return
|
|
// and give it back to the caller as ANSI.
|
|
//
|
|
nRetLen = wcslen(pwszReturn) + 1;
|
|
|
|
pszNew = (LPSTR)malloc(nRetLen);
|
|
|
|
if (!pszNew) {
|
|
DPFN(eDbgLevelError, "[MassageStringForPathA] No memory available");
|
|
return (LPSTR)pszString;
|
|
}
|
|
|
|
cchSize = WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
pwszReturn,
|
|
-1,
|
|
pszNew,
|
|
nRetLen,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (cchSize == 0) {
|
|
DPFN(eDbgLevelError, "[MassageStringForPathA] Unicode -> Ansi failed");
|
|
free(pszNew);
|
|
return (LPSTR)pszString;
|
|
}
|
|
|
|
free(pwszReturn);
|
|
|
|
return pszNew;
|
|
}
|
|
|
|
void
|
|
MassageNtPath(
|
|
IN POBJECT_ATTRIBUTES pObjectAttributes,
|
|
OUT POBJECT_ATTRIBUTES pRetObjectAttributes
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
PUNICODE_STRING pstrObjectName = NULL;
|
|
LPWSTR pwszString = NULL;
|
|
RTL_UNICODE_STRING_BUFFER DosPathBuffer;
|
|
UCHAR PathBuffer[MAX_PATH * 2];
|
|
BOOL TranslationStatus = FALSE;
|
|
|
|
//
|
|
// Preserve the existing attributes.
|
|
//
|
|
InitializeObjectAttributes(pRetObjectAttributes,
|
|
pObjectAttributes->ObjectName,
|
|
pObjectAttributes->Attributes,
|
|
pObjectAttributes->RootDirectory,
|
|
pObjectAttributes->SecurityDescriptor);
|
|
|
|
//
|
|
// Ensure that we have a valid source path to work with.
|
|
//
|
|
if (!pObjectAttributes->ObjectName->Buffer) {
|
|
return;
|
|
}
|
|
|
|
DPFN(eDbgLevelInfo,
|
|
"[MassageNtPath] '%ls'",
|
|
pObjectAttributes->ObjectName->Buffer);
|
|
|
|
//
|
|
// Convert from an NT path to a DOS path.
|
|
//
|
|
RtlInitUnicodeStringBuffer(&DosPathBuffer,
|
|
PathBuffer,
|
|
sizeof(PathBuffer));
|
|
|
|
status = ShimAssignUnicodeStringBuffer(&DosPathBuffer,
|
|
pObjectAttributes->ObjectName);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DPFN(eDbgLevelError,
|
|
"[MassageNtPath] Failed to initialize DOS path buffer");
|
|
return;
|
|
}
|
|
|
|
status = ShimNtPathNameToDosPathName(0, &DosPathBuffer, NULL, NULL);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DPFN(eDbgLevelError,
|
|
"[MassageNtPath] Failed to convert NT '%ls' to DOS path",
|
|
pObjectAttributes->ObjectName->Buffer);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Now check for a hardcoded path.
|
|
//
|
|
pwszString = MassageStringForPathW(DosPathBuffer.String.Buffer);
|
|
|
|
//
|
|
// Convert from a DOS path to an NT path name.
|
|
//
|
|
pstrObjectName = (PUNICODE_STRING)RtlAllocateHeap(RtlProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(UNICODE_STRING));
|
|
|
|
if (!pstrObjectName) {
|
|
DPFN(eDbgLevelError, "[MassageNtPath] Failed to allocate memory");
|
|
goto cleanup;
|
|
}
|
|
|
|
TranslationStatus = RtlDosPathNameToNtPathName_U(pwszString,
|
|
pstrObjectName,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (!TranslationStatus) {
|
|
DPFN(eDbgLevelError,
|
|
"[MassageNtPath] Failed to convert DOS '%ls' to NT path",
|
|
pwszString);
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Everything worked, so now we update the ObjectName and return it through
|
|
// the structure.
|
|
//
|
|
pRetObjectAttributes->ObjectName = pstrObjectName;
|
|
|
|
cleanup:
|
|
|
|
FPFreeW(pwszString, DosPathBuffer.String.Buffer);
|
|
|
|
RtlFreeUnicodeStringBuffer(&DosPathBuffer);
|
|
}
|
|
|
|
inline
|
|
void
|
|
FPNtFree(
|
|
IN POBJECT_ATTRIBUTES pOriginal,
|
|
IN POBJECT_ATTRIBUTES pAllocated
|
|
)
|
|
{
|
|
RtlFreeUnicodeString(pAllocated->ObjectName);
|
|
|
|
if (pOriginal->ObjectName != pAllocated->ObjectName) {
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pAllocated->ObjectName);
|
|
}
|
|
}
|
|
|
|
LPSTR
|
|
APIHOOK(GetCommandLineA)(
|
|
void
|
|
)
|
|
{
|
|
if (g_bPathsInited) {
|
|
return g_pszCommandLineA;
|
|
} else {
|
|
return ORIGINAL_API(GetCommandLineA)();
|
|
}
|
|
}
|
|
|
|
LPWSTR
|
|
APIHOOK(GetCommandLineW)(
|
|
void
|
|
)
|
|
{
|
|
if (g_bPathsInited) {
|
|
return g_pwszCommandLineW;
|
|
} else {
|
|
return ORIGINAL_API(GetCommandLineW)();
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetFileAttributesA)(
|
|
LPCSTR lpFileName // name of file or directory
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetFileAttributesA)(lpszString);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetFileAttributesW)(
|
|
LPCWSTR lpFileName // name of file or directory
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetFileAttributesW)(lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(SetFileAttributesA)(
|
|
LPCSTR lpFileName, // file name
|
|
DWORD dwFileAttributes // attributes
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(SetFileAttributesA)(lpszString, dwFileAttributes);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(SetFileAttributesW)(
|
|
LPCWSTR lpFileName, // file name
|
|
DWORD dwFileAttributes // attributes
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(SetFileAttributesW)(lpszString, dwFileAttributes);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(GetFileAttributesExA)(
|
|
LPCSTR lpFileName, // file or directory name
|
|
GET_FILEEX_INFO_LEVELS fInfoLevelId, // attribute
|
|
LPVOID lpFileInformation // attribute information
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(GetFileAttributesExA)(lpszString,
|
|
fInfoLevelId,
|
|
lpFileInformation);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(GetFileAttributesExW)(
|
|
LPCWSTR lpFileName, // file or directory name
|
|
GET_FILEEX_INFO_LEVELS fInfoLevelId, // attribute
|
|
LPVOID lpFileInformation // attribute information
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(GetFileAttributesExW)(lpszString,
|
|
fInfoLevelId,
|
|
lpFileInformation);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
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
|
|
)
|
|
{
|
|
LPSTR lpszStringAppName = MassageStringForPathA(lpApplicationName);
|
|
LPSTR lpszStringCmdLine = MassageStringForPathA(lpCommandLine);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CreateProcessA)(lpszStringAppName,
|
|
lpszStringCmdLine,
|
|
lpProcessAttributes,
|
|
lpThreadAttributes,
|
|
bInheritHandles,
|
|
dwCreationFlags,
|
|
lpEnvironment,
|
|
lpCurrentDirectory,
|
|
lpStartupInfo,
|
|
lpProcessInformation);
|
|
|
|
FPFreeA(lpszStringAppName, lpApplicationName);
|
|
FPFreeA(lpszStringCmdLine, lpCommandLine);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
LPWSTR lpszStringAppName = MassageStringForPathW(lpApplicationName);
|
|
LPWSTR lpszStringCmdLine = MassageStringForPathW(lpCommandLine);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CreateProcessW)(lpszStringAppName,
|
|
lpszStringCmdLine,
|
|
lpProcessAttributes,
|
|
lpThreadAttributes,
|
|
bInheritHandles,
|
|
dwCreationFlags,
|
|
lpEnvironment,
|
|
lpCurrentDirectory,
|
|
lpStartupInfo,
|
|
lpProcessInformation);
|
|
|
|
FPFreeW(lpszStringAppName, lpApplicationName);
|
|
FPFreeW(lpszStringCmdLine, lpCommandLine);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
UINT
|
|
APIHOOK(WinExec)(
|
|
LPCSTR lpCmdLine,
|
|
UINT uCmdShow
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpCmdLine);
|
|
|
|
UINT returnValue = ORIGINAL_API(WinExec)(lpszString, uCmdShow);
|
|
|
|
FPFreeA(lpszString, lpCmdLine);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
HINSTANCE
|
|
APIHOOK(ShellExecuteA)(
|
|
HWND hwnd,
|
|
LPCSTR lpVerb,
|
|
LPCSTR lpFile,
|
|
LPCSTR lpParameters,
|
|
LPCSTR lpDirectory,
|
|
INT nShowCmd
|
|
)
|
|
{
|
|
LPSTR lpszStringFile = MassageStringForPathA(lpFile);
|
|
LPSTR lpszStringDir = MassageStringForPathA(lpDirectory);
|
|
|
|
HINSTANCE returnValue = ORIGINAL_API(ShellExecuteA)(hwnd,
|
|
lpVerb,
|
|
lpszStringFile,
|
|
lpParameters,
|
|
lpszStringDir,
|
|
nShowCmd);
|
|
|
|
FPFreeA(lpszStringFile, lpFile);
|
|
FPFreeA(lpszStringDir, lpDirectory);
|
|
|
|
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
|
|
)
|
|
{
|
|
LPWSTR lpszStringFile = MassageStringForPathW(lpFile);
|
|
LPWSTR lpszStringDir = MassageStringForPathW(lpDirectory);
|
|
|
|
HINSTANCE returnValue = ORIGINAL_API(ShellExecuteW)(hwnd,
|
|
lpVerb,
|
|
lpszStringFile,
|
|
lpParameters,
|
|
lpszStringDir,
|
|
nShowCmd);
|
|
|
|
FPFreeW(lpszStringFile, lpFile);
|
|
FPFreeW(lpszStringDir, lpDirectory);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
LPSTR lpszStringFile = MassageStringForPathA(lpExecInfo->lpFile);
|
|
LPSTR lpszStringDir = MassageStringForPathA(lpExecInfo->lpDirectory);
|
|
|
|
LPCSTR lpFileSave = lpExecInfo->lpFile;
|
|
LPCSTR lpDirSave = lpExecInfo->lpDirectory;
|
|
|
|
lpExecInfo->lpFile = lpszStringFile;
|
|
lpExecInfo->lpDirectory = lpszStringDir;
|
|
|
|
BOOL returnValue = ORIGINAL_API(ShellExecuteExA)(lpExecInfo);
|
|
|
|
lpExecInfo->lpFile = lpFileSave;
|
|
lpExecInfo->lpDirectory = lpDirSave;
|
|
|
|
FPFreeA(lpszStringFile, lpFileSave);
|
|
FPFreeA(lpszStringDir, lpDirSave);
|
|
|
|
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);
|
|
}
|
|
|
|
LPWSTR lpszStringFile = MassageStringForPathW(lpExecInfo->lpFile);
|
|
LPWSTR lpszStringDir = MassageStringForPathW(lpExecInfo->lpDirectory);
|
|
|
|
LPCWSTR lpFileSave = lpExecInfo->lpFile;
|
|
LPCWSTR lpDirSave = lpExecInfo->lpDirectory;
|
|
|
|
lpExecInfo->lpFile = lpszStringFile;
|
|
lpExecInfo->lpDirectory = lpszStringDir;
|
|
|
|
BOOL returnValue = ORIGINAL_API(ShellExecuteExW)(lpExecInfo);
|
|
|
|
lpExecInfo->lpFile = lpFileSave;
|
|
lpExecInfo->lpDirectory = lpDirSave;
|
|
|
|
FPFreeW(lpszStringFile, lpFileSave);
|
|
FPFreeW(lpszStringDir, lpDirSave);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
UINT returnValue = ORIGINAL_API(GetPrivateProfileIntA)(lpAppName,
|
|
lpKeyName,
|
|
nDefault,
|
|
lpszString);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
UINT returnValue = ORIGINAL_API(GetPrivateProfileIntW)(lpAppName,
|
|
lpKeyName,
|
|
nDefault,
|
|
lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
DWORD
|
|
APIHOOK(GetPrivateProfileSectionA)(
|
|
LPCSTR lpAppName, // section name
|
|
LPSTR lpReturnedString, // return buffer
|
|
DWORD nSize, // size of return buffer
|
|
LPCSTR lpFileName // initialization file name
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileSectionA)(lpAppName,
|
|
lpReturnedString,
|
|
nSize,
|
|
lpszString);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
DWORD
|
|
APIHOOK(GetPrivateProfileSectionW)(
|
|
LPCWSTR lpAppName, // section name
|
|
LPWSTR lpReturnedString, // return buffer
|
|
DWORD nSize, // size of return buffer
|
|
LPCWSTR lpFileName // initialization file name
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileSectionW)(lpAppName,
|
|
lpReturnedString,
|
|
nSize,
|
|
lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
DWORD
|
|
APIHOOK(GetPrivateProfileSectionNamesA)(
|
|
LPSTR lpszReturnBuffer, // return buffer
|
|
DWORD nSize, // size of return buffer
|
|
LPCSTR lpFileName // initialization file name
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileSectionNamesA)(lpszReturnBuffer,
|
|
nSize,
|
|
lpszString);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
DWORD
|
|
APIHOOK(GetPrivateProfileSectionNamesW)(
|
|
LPWSTR lpszReturnBuffer, // return buffer
|
|
DWORD nSize, // size of return buffer
|
|
LPCWSTR lpFileName // initialization file name
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileSectionNamesW)(lpszReturnBuffer,
|
|
nSize,
|
|
lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileStringA)(lpAppName,
|
|
lpKeyName,
|
|
lpDefault,
|
|
lpReturnedString,
|
|
nSize,
|
|
lpszString);
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetPrivateProfileStringW)(lpAppName,
|
|
lpKeyName,
|
|
lpDefault,
|
|
lpReturnedString,
|
|
nSize,
|
|
lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(GetPrivateProfileStructA)(lpszSection,
|
|
lpszKey,
|
|
lpStruct,
|
|
uSizeStruct,
|
|
lpszString);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(GetPrivateProfileStructW)(lpszSection,
|
|
lpszKey,
|
|
lpStruct,
|
|
uSizeStruct,
|
|
lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(WritePrivateProfileSectionA)(
|
|
LPCSTR lpAppName, // section name
|
|
LPCSTR lpString, // data
|
|
LPCSTR lpFileName // file name
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileSectionA)(lpAppName,
|
|
lpString,
|
|
lpszString);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(WritePrivateProfileSectionW)(
|
|
LPCWSTR lpAppName, // section name
|
|
LPCWSTR lpString, // data
|
|
LPCWSTR lpFileName // file name
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileSectionW)(lpAppName,
|
|
lpString,
|
|
lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(WritePrivateProfileStringA)(
|
|
LPCSTR lpAppName, // section name
|
|
LPCSTR lpKeyName, // key name
|
|
LPCSTR lpString, // string to add
|
|
LPCSTR lpFileName // initialization file
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileStringA)(lpAppName,
|
|
lpKeyName,
|
|
lpString,
|
|
lpszString);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(WritePrivateProfileStringW)(
|
|
LPCWSTR lpAppName, // section name
|
|
LPCWSTR lpKeyName, // key name
|
|
LPCWSTR lpString, // string to add
|
|
LPCWSTR lpFileName // initialization file
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileStringW)(lpAppName,
|
|
lpKeyName,
|
|
lpString,
|
|
lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileStructA)(lpszSection,
|
|
lpszKey,
|
|
lpStruct,
|
|
uSizeStruct,
|
|
lpszString);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(WritePrivateProfileStructW)(lpszSection,
|
|
lpszKey,
|
|
lpStruct,
|
|
uSizeStruct,
|
|
lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(CopyFileA)(
|
|
LPCSTR lpExistingFileName, // name of an existing file
|
|
LPCSTR lpNewFileName, // name of new file
|
|
BOOL bFailIfExists // operation if file exists
|
|
)
|
|
{
|
|
LPSTR lpszStringExisting = MassageStringForPathA(lpExistingFileName);
|
|
LPSTR lpszStringNew = MassageStringForPathA(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CopyFileA)(lpszStringExisting,
|
|
lpszStringNew,
|
|
bFailIfExists);
|
|
|
|
FPFreeA(lpszStringExisting, lpExistingFileName);
|
|
FPFreeA(lpszStringNew, 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
|
|
)
|
|
{
|
|
LPWSTR lpszStringExisting = MassageStringForPathW(lpExistingFileName);
|
|
LPWSTR lpszStringNew = MassageStringForPathW(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CopyFileW)(lpszStringExisting,
|
|
lpszStringNew,
|
|
bFailIfExists);
|
|
|
|
FPFreeW(lpszStringExisting, lpExistingFileName);
|
|
FPFreeW(lpszStringNew, 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
|
|
)
|
|
{
|
|
LPSTR lpszStringExisting = MassageStringForPathA(lpExistingFileName);
|
|
LPSTR lpszStringNew = MassageStringForPathA(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CopyFileExA)(lpszStringExisting,
|
|
lpszStringNew,
|
|
lpProgressRoutine,
|
|
lpData,
|
|
pbCancel,
|
|
dwCopyFlags);
|
|
|
|
FPFreeA(lpszStringExisting, lpExistingFileName);
|
|
FPFreeA(lpszStringNew, 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
|
|
)
|
|
{
|
|
LPWSTR lpszStringExisting = MassageStringForPathW(lpExistingFileName);
|
|
LPWSTR lpszStringNew = MassageStringForPathW(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CopyFileExW)(lpszStringExisting,
|
|
lpszStringNew,
|
|
lpProgressRoutine,
|
|
lpData,
|
|
pbCancel,
|
|
dwCopyFlags);
|
|
|
|
FPFreeW(lpszStringExisting, lpExistingFileName);
|
|
FPFreeW(lpszStringNew, lpNewFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(CreateDirectoryA)(
|
|
LPCSTR lpPathName, // directory name
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpPathName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CreateDirectoryA)(lpszString, lpSecurityAttributes);
|
|
|
|
FPFreeA(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(CreateDirectoryW)(
|
|
LPCWSTR lpPathName, // directory name
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpPathName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CreateDirectoryW)(lpszString, lpSecurityAttributes);
|
|
|
|
FPFreeW(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(CreateDirectoryExA)(
|
|
LPCSTR lpTemplateDirectory, // template directory
|
|
LPCSTR lpNewDirectory, // directory name
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD
|
|
)
|
|
{
|
|
LPSTR lpszStringTemplate = MassageStringForPathA(lpTemplateDirectory);
|
|
LPSTR lpszStringNew = MassageStringForPathA(lpNewDirectory);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CreateDirectoryExA)(lpszStringTemplate,
|
|
lpszStringNew,
|
|
lpSecurityAttributes);
|
|
|
|
FPFreeA(lpszStringTemplate, lpTemplateDirectory);
|
|
FPFreeA(lpszStringNew, lpNewDirectory);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(CreateDirectoryExW)(
|
|
LPCWSTR lpTemplateDirectory, // template directory
|
|
LPCWSTR lpNewDirectory, // directory name
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes // SD
|
|
)
|
|
{
|
|
LPWSTR lpszStringTemplate = MassageStringForPathW(lpTemplateDirectory);
|
|
LPWSTR lpszStringNew = MassageStringForPathW(lpNewDirectory);
|
|
|
|
BOOL returnValue = ORIGINAL_API(CreateDirectoryExW)(lpszStringTemplate,
|
|
lpszStringNew,
|
|
lpSecurityAttributes);
|
|
|
|
FPFreeW(lpszStringTemplate, lpTemplateDirectory);
|
|
FPFreeW(lpszStringNew, 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
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
HANDLE returnValue = ORIGINAL_API(CreateFileA)(lpszString,
|
|
dwDesiredAccess,
|
|
dwShareMode,
|
|
lpSecurityAttributes,
|
|
dwCreationDisposition,
|
|
dwFlagsAndAttributes,
|
|
hTemplateFile);
|
|
|
|
FPFreeA(lpszString, 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
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
HANDLE returnValue = ORIGINAL_API(CreateFileW)(lpszString,
|
|
dwDesiredAccess,
|
|
dwShareMode,
|
|
lpSecurityAttributes,
|
|
dwCreationDisposition,
|
|
dwFlagsAndAttributes,
|
|
hTemplateFile);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(DeleteFileA)(
|
|
LPCSTR lpFileName // file name
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(DeleteFileA)(lpszString);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(DeleteFileW)(
|
|
LPCWSTR lpFileName // file name
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(DeleteFileW)(lpszString);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
APIHOOK(FindFirstFileA)(
|
|
LPCSTR lpFileName, // file name
|
|
LPWIN32_FIND_DATAA lpFindFileData // data buffer
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
HANDLE returnValue = ORIGINAL_API(FindFirstFileA)(lpszString, lpFindFileData);
|
|
|
|
FPFreeA(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
HANDLE
|
|
APIHOOK(FindFirstFileW)(
|
|
LPCWSTR lpFileName, // file name
|
|
LPWIN32_FIND_DATAW lpFindFileData // data buffer
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
HANDLE returnValue = ORIGINAL_API(FindFirstFileW)(lpszString, lpFindFileData);
|
|
|
|
FPFreeW(lpszString, 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
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
HANDLE returnValue = ORIGINAL_API(FindFirstFileExA)(lpszString,
|
|
fInfoLevelId,
|
|
lpFindFileData,
|
|
fSearchOp,
|
|
lpSearchFilter,
|
|
dwAdditionalFlags);
|
|
|
|
FPFreeA(lpszString, 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
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpFileName);
|
|
|
|
HANDLE returnValue = ORIGINAL_API(FindFirstFileExW)(lpszString,
|
|
fInfoLevelId,
|
|
lpFindFileData,
|
|
fSearchOp,
|
|
lpSearchFilter,
|
|
dwAdditionalFlags);
|
|
|
|
FPFreeW(lpszString, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(GetBinaryTypeA)(
|
|
LPCSTR lpApplicationName, // full file path
|
|
LPDWORD lpBinaryType // binary type information
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpApplicationName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(GetBinaryTypeA)(lpszString, lpBinaryType);
|
|
|
|
FPFreeA(lpszString, lpApplicationName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(GetBinaryTypeW)(
|
|
LPCWSTR lpApplicationName, // full file path
|
|
LPDWORD lpBinaryType // binary type information
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpApplicationName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(GetBinaryTypeW)(lpszString, lpBinaryType);
|
|
|
|
FPFreeW(lpszString, lpApplicationName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(MoveFileA)(
|
|
LPCSTR lpExistingFileName, // file name
|
|
LPCSTR lpNewFileName // new file name
|
|
)
|
|
{
|
|
LPSTR lpszStringExisting = MassageStringForPathA(lpExistingFileName);
|
|
LPSTR lpszStringNew = MassageStringForPathA(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(MoveFileA)(lpszStringExisting, lpszStringNew);
|
|
|
|
FPFreeA(lpszStringExisting, lpExistingFileName);
|
|
FPFreeA(lpszStringNew, lpNewFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(MoveFileW)(
|
|
LPCWSTR lpExistingFileName, // file name
|
|
LPCWSTR lpNewFileName // new file name
|
|
)
|
|
{
|
|
LPWSTR lpszStringExisting = MassageStringForPathW(lpExistingFileName);
|
|
LPWSTR lpszStringNew = MassageStringForPathW(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(MoveFileW)(lpszStringExisting, lpszStringNew);
|
|
|
|
FPFreeW(lpszStringExisting, lpExistingFileName);
|
|
FPFreeW(lpszStringNew, lpNewFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(MoveFileExA)(
|
|
LPCSTR lpExistingFileName, // file name
|
|
LPCSTR lpNewFileName, // new file name
|
|
DWORD dwFlags // move options
|
|
)
|
|
{
|
|
LPSTR lpszStringExisting = MassageStringForPathA(lpExistingFileName);
|
|
LPSTR lpszStringNew = MassageStringForPathA(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(MoveFileExA)(lpszStringExisting, lpszStringNew, dwFlags);
|
|
|
|
FPFreeA(lpszStringExisting, lpExistingFileName);
|
|
FPFreeA(lpszStringNew, lpNewFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(MoveFileExW)(
|
|
LPCWSTR lpExistingFileName, // file name
|
|
LPCWSTR lpNewFileName, // new file name
|
|
DWORD dwFlags // move options
|
|
)
|
|
{
|
|
LPWSTR lpszStringExisting = MassageStringForPathW(lpExistingFileName);
|
|
LPWSTR lpszStringNew = MassageStringForPathW(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(MoveFileExW)(lpszStringExisting, lpszStringNew, dwFlags);
|
|
|
|
FPFreeW(lpszStringExisting, lpExistingFileName);
|
|
FPFreeW(lpszStringNew, 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
|
|
)
|
|
{
|
|
LPSTR lpszStringExisting = MassageStringForPathA(lpExistingFileName);
|
|
LPSTR lpszStringNew = MassageStringForPathA(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(MoveFileWithProgressA)(lpszStringExisting,
|
|
lpszStringNew,
|
|
lpProgressRoutine,
|
|
lpData,
|
|
dwFlags);
|
|
|
|
FPFreeA(lpszStringExisting, lpExistingFileName);
|
|
FPFreeA(lpszStringNew, 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
|
|
)
|
|
{
|
|
LPWSTR lpszStringExisting = MassageStringForPathW(lpExistingFileName);
|
|
LPWSTR lpszStringNew = MassageStringForPathW(lpNewFileName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(MoveFileWithProgressW)(lpExistingFileName,
|
|
lpNewFileName,
|
|
lpProgressRoutine,
|
|
lpData,
|
|
dwFlags);
|
|
|
|
FPFreeW(lpszStringExisting, lpExistingFileName);
|
|
FPFreeW(lpszStringNew, lpNewFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(RemoveDirectoryA)(
|
|
LPCSTR lpPathName // directory name
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpPathName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(RemoveDirectoryA)(lpszString);
|
|
|
|
FPFreeA(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(RemoveDirectoryW)(
|
|
LPCWSTR lpPathName // directory name
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpPathName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(RemoveDirectoryW)(lpszString);
|
|
|
|
FPFreeW(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(SetCurrentDirectoryA)(
|
|
LPCSTR lpPathName // new directory name
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpPathName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(SetCurrentDirectoryA)(lpszString);
|
|
|
|
FPFreeA(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
BOOL
|
|
APIHOOK(SetCurrentDirectoryW)(
|
|
LPCWSTR lpPathName // new directory name
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpPathName);
|
|
|
|
BOOL returnValue = ORIGINAL_API(SetCurrentDirectoryW)(lpszString);
|
|
|
|
FPFreeW(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
HMODULE
|
|
APIHOOK(LoadLibraryA)(
|
|
LPCSTR lpPathName
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpPathName);
|
|
|
|
HMODULE returnValue = ORIGINAL_API(LoadLibraryA)(lpszString);
|
|
|
|
FPFreeA(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
HMODULE
|
|
APIHOOK(LoadLibraryW)(
|
|
LPCWSTR lpPathName
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpPathName);
|
|
|
|
HMODULE returnValue = ORIGINAL_API(LoadLibraryW)(lpszString);
|
|
|
|
FPFreeW(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
HMODULE
|
|
APIHOOK(LoadLibraryExA)(
|
|
LPCSTR lpPathName,
|
|
HANDLE hFile,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpPathName);
|
|
|
|
HMODULE returnValue = ORIGINAL_API(LoadLibraryExA)(lpszString, hFile, dwFlags);
|
|
|
|
FPFreeA(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
HMODULE
|
|
APIHOOK(LoadLibraryExW)(
|
|
LPCWSTR lpPathName,
|
|
HANDLE hFile,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpPathName);
|
|
|
|
HMODULE returnValue = ORIGINAL_API(LoadLibraryExW)(lpszString, hFile, dwFlags);
|
|
|
|
FPFreeW(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
HFILE
|
|
APIHOOK(OpenFile)(
|
|
LPCSTR lpFileName, // file name
|
|
LPOFSTRUCT lpReOpenBuff, // file information
|
|
UINT uStyle // action and attributes
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpFileName);
|
|
|
|
HFILE returnValue = ORIGINAL_API(OpenFile)(lpszString, lpReOpenBuff, uStyle);
|
|
|
|
MassageRealPathToFakePathA(lpReOpenBuff->szPathName, OFS_MAXPATHNAME);
|
|
|
|
FPFreeA(lpszString, 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
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpData);
|
|
|
|
//
|
|
// Data key is length of string *not* including null byte.
|
|
//
|
|
if (lpszString != NULL) {
|
|
cbData = strlen(lpszString);
|
|
}
|
|
|
|
LONG returnValue = ORIGINAL_API(RegSetValueA)(hKey,
|
|
lpSubKey,
|
|
dwType,
|
|
lpszString,
|
|
cbData);
|
|
|
|
FPFreeA(lpszString, 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
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lpData);
|
|
|
|
//
|
|
// Data key is length of string *not* including null byte.
|
|
//
|
|
if (lpszString) {
|
|
cbData = wcslen(lpszString) * sizeof(WCHAR);
|
|
}
|
|
|
|
LONG returnValue = ORIGINAL_API(RegSetValueW)(hKey,
|
|
lpSubKey,
|
|
dwType,
|
|
lpszString,
|
|
cbData);
|
|
|
|
FPFreeW(lpszString, 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 || dwType == REG_EXPAND_SZ) {
|
|
|
|
LPSTR lpszString = MassageStringForPathA((LPCSTR)lpData);
|
|
|
|
//
|
|
// Data key is length of string *not* including null byte.
|
|
//
|
|
if (lpszString) {
|
|
cbData = strlen(lpszString);
|
|
}
|
|
|
|
LONG returnValue = ORIGINAL_API(RegSetValueExA)(hKey,
|
|
lpValueName,
|
|
Reserved,
|
|
dwType,
|
|
(CONST BYTE*)lpszString,
|
|
cbData);
|
|
FPFreeA(lpszString, (LPCSTR)lpData);
|
|
|
|
return returnValue;
|
|
|
|
} else {
|
|
//
|
|
// Pass data on through.
|
|
//
|
|
LONG returnValue = ORIGINAL_API(RegSetValueExA)(hKey,
|
|
lpValueName,
|
|
Reserved,
|
|
dwType,
|
|
lpData,
|
|
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 || dwType == REG_EXPAND_SZ) {
|
|
|
|
LPWSTR lpszString = MassageStringForPathW((LPCWSTR)lpData);
|
|
|
|
//
|
|
// Data key is length of string *not* including null byte.
|
|
//
|
|
if (lpszString) {
|
|
cbData = (wcslen(lpszString) + 1) * sizeof(WCHAR);
|
|
}
|
|
|
|
LONG returnValue = ORIGINAL_API(RegSetValueExW)(hKey,
|
|
lpValueName,
|
|
Reserved,
|
|
dwType,
|
|
(CONST BYTE*)lpszString,
|
|
cbData);
|
|
FPFreeW(lpszString, (LPCWSTR)lpData);
|
|
|
|
return returnValue;
|
|
|
|
} else {
|
|
//
|
|
// Pass data on through.
|
|
//
|
|
LONG returnValue = ORIGINAL_API(RegSetValueExW)(hKey,
|
|
lpValueName,
|
|
Reserved,
|
|
dwType,
|
|
lpData,
|
|
cbData);
|
|
return returnValue;
|
|
}
|
|
|
|
}
|
|
|
|
LONG
|
|
APIHOOK(RegQueryValueA)(
|
|
HKEY hKey,
|
|
LPCSTR lpSubKey,
|
|
LPSTR lpValue,
|
|
PLONG lpcbValue
|
|
)
|
|
{
|
|
//
|
|
// Obtain the size of the buffer prior to the call.
|
|
// When the call is complete, lpcbValue will contain
|
|
// the size of the data stored in the buffer. We
|
|
// need the size of the buffer.
|
|
//
|
|
LONG cbValue = 0;
|
|
|
|
if (lpcbValue) {
|
|
cbValue = *lpcbValue;
|
|
}
|
|
|
|
LONG returnValue = ORIGINAL_API(RegQueryValueA)(hKey,
|
|
lpSubKey,
|
|
lpValue,
|
|
lpcbValue);
|
|
|
|
if (ERROR_SUCCESS == returnValue) {
|
|
MassageRealPathToFakePathA(lpValue, (DWORD)cbValue);
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
LONG
|
|
APIHOOK(RegQueryValueW)(
|
|
HKEY hKey,
|
|
LPCWSTR lpSubKey,
|
|
LPWSTR lpValue,
|
|
PLONG lpcbValue
|
|
)
|
|
{
|
|
LONG cbValue = 0;
|
|
|
|
if (lpcbValue) {
|
|
cbValue = *lpcbValue;
|
|
}
|
|
|
|
LONG returnValue = ORIGINAL_API(RegQueryValueW)(hKey,
|
|
lpSubKey,
|
|
lpValue,
|
|
lpcbValue);
|
|
|
|
if (ERROR_SUCCESS == returnValue) {
|
|
MassageRealPathToFakePathW(lpValue, (DWORD)cbValue);
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
LONG
|
|
APIHOOK(RegQueryValueExA)(
|
|
HKEY hKey,
|
|
LPCSTR lpValueName,
|
|
LPDWORD lpReserved,
|
|
LPDWORD lpType,
|
|
LPBYTE lpData,
|
|
LPDWORD lpcbData
|
|
)
|
|
{
|
|
DWORD cbData = 0;
|
|
DWORD dwType = 0;
|
|
|
|
if (lpcbData) {
|
|
cbData = *lpcbData;
|
|
}
|
|
|
|
if (!lpType) {
|
|
lpType = &dwType;
|
|
}
|
|
|
|
LONG returnValue = ORIGINAL_API(RegQueryValueExA)(hKey,
|
|
lpValueName,
|
|
lpReserved,
|
|
lpType,
|
|
lpData,
|
|
lpcbData);
|
|
|
|
if (ERROR_SUCCESS == returnValue) {
|
|
if (*lpType == REG_SZ || *lpType == REG_EXPAND_SZ) {
|
|
MassageRealPathToFakePathA((LPSTR)lpData, cbData);
|
|
}
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
LONG
|
|
APIHOOK(RegQueryValueExW)(
|
|
HKEY hKey,
|
|
LPCWSTR lpValueName,
|
|
LPDWORD lpReserved,
|
|
LPDWORD lpType,
|
|
LPBYTE lpData,
|
|
LPDWORD lpcbData
|
|
)
|
|
{
|
|
DWORD cbData = 0;
|
|
DWORD dwType = 0;
|
|
|
|
if (lpcbData) {
|
|
cbData = *lpcbData;
|
|
}
|
|
|
|
if (!lpType) {
|
|
lpType = &dwType;
|
|
}
|
|
|
|
LONG returnValue = ORIGINAL_API(RegQueryValueExW)(hKey,
|
|
lpValueName,
|
|
lpReserved,
|
|
lpType,
|
|
lpData,
|
|
lpcbData);
|
|
|
|
if (ERROR_SUCCESS == returnValue) {
|
|
if (*lpType == REG_SZ || *lpType == REG_EXPAND_SZ) {
|
|
MassageRealPathToFakePathW((LPWSTR)lpData, cbData);
|
|
}
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
HFILE
|
|
APIHOOK(_lopen)(
|
|
LPCSTR lpPathName,
|
|
int iReadWrite
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpPathName);
|
|
|
|
HFILE returnValue = ORIGINAL_API(_lopen)(lpszString, iReadWrite);
|
|
|
|
FPFreeA(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
HFILE
|
|
APIHOOK(_lcreat)(
|
|
LPCSTR lpPathName,
|
|
int iAttribute
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lpPathName);
|
|
|
|
HFILE returnValue = ORIGINAL_API(_lcreat)(lpszString, iAttribute);
|
|
|
|
FPFreeA(lpszString, lpPathName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(SearchPathA)(
|
|
LPCSTR lpPath, // search path
|
|
LPCSTR lpFileName, // file name
|
|
LPCSTR lpExtension, // file extension
|
|
DWORD nBufferLength, // size of buffer
|
|
LPSTR lpBuffer, // found file name buffer
|
|
LPSTR *lpFilePart // file component
|
|
)
|
|
{
|
|
LPSTR lpszStringPath = MassageStringForPathA(lpPath);
|
|
LPSTR lpszStringFile = MassageStringForPathA(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(SearchPathA)(lpszStringPath,
|
|
lpszStringFile,
|
|
lpExtension,
|
|
nBufferLength,
|
|
lpBuffer,
|
|
lpFilePart);
|
|
|
|
FPFreeA(lpszStringPath, lpPath);
|
|
FPFreeA(lpszStringFile, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(SearchPathW)(
|
|
LPCWSTR lpPath, // search path
|
|
LPCWSTR lpFileName, // file name
|
|
LPCWSTR lpExtension, // file extension
|
|
DWORD nBufferLength, // size of buffer
|
|
LPWSTR lpBuffer, // found file name buffer
|
|
LPWSTR *lpFilePart // file component
|
|
)
|
|
{
|
|
LPWSTR lpszStringPath = MassageStringForPathW(lpPath);
|
|
LPWSTR lpszStringFile = MassageStringForPathW(lpFileName);
|
|
|
|
DWORD returnValue = ORIGINAL_API(SearchPathW)(lpszStringPath,
|
|
lpszStringFile,
|
|
lpExtension,
|
|
nBufferLength,
|
|
lpBuffer,
|
|
lpFilePart);
|
|
|
|
FPFreeW(lpszStringPath, lpPath);
|
|
FPFreeW(lpszStringFile, lpFileName);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(ExpandEnvironmentStringsA)(
|
|
LPCSTR lpSrc, // string with environment variables
|
|
LPSTR lpDst, // string with expanded strings
|
|
DWORD nSize // maximum characters in expanded string
|
|
)
|
|
{
|
|
DWORD returnValue = ORIGINAL_API(ExpandEnvironmentStringsA)(lpSrc,
|
|
lpDst,
|
|
nSize);
|
|
|
|
if (returnValue && (!(returnValue > nSize))) {
|
|
LPSTR lpszString = MassageStringForPathA(lpDst);
|
|
|
|
returnValue = ORIGINAL_API(ExpandEnvironmentStringsA)(lpszString,
|
|
lpDst,
|
|
nSize);
|
|
|
|
FPFreeA(lpszString, lpDst);
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(ExpandEnvironmentStringsW)(
|
|
LPCWSTR lpSrc, // string with environment variables
|
|
LPWSTR lpDst, // string with expanded strings
|
|
DWORD nSize // maximum characters in expanded string
|
|
)
|
|
{
|
|
DWORD returnValue = ORIGINAL_API(ExpandEnvironmentStringsW)(lpSrc,
|
|
lpDst,
|
|
nSize);
|
|
|
|
if (returnValue && (!(returnValue > nSize))) {
|
|
LPWSTR lpszString = MassageStringForPathW(lpDst);
|
|
|
|
returnValue = ORIGINAL_API(ExpandEnvironmentStringsW)(lpszString,
|
|
lpDst,
|
|
nSize);
|
|
|
|
FPFreeW(lpszString, lpDst);
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetFileVersionInfoSizeA)(
|
|
LPSTR lptstrFilename, // file name
|
|
LPDWORD lpdwHandle // set to zero
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lptstrFilename);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetFileVersionInfoSizeA)(lpszString,
|
|
lpdwHandle);
|
|
|
|
FPFreeA(lpszString, lptstrFilename);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetFileVersionInfoSizeW)(
|
|
LPWSTR lptstrFilename, // file name
|
|
LPDWORD lpdwHandle // set to zero
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lptstrFilename);
|
|
|
|
DWORD returnValue = ORIGINAL_API(GetFileVersionInfoSizeW)(lpszString,
|
|
lpdwHandle);
|
|
|
|
FPFreeW(lpszString, lptstrFilename);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(GetFileVersionInfoA)(
|
|
LPSTR lptstrFilename, // file name
|
|
DWORD dwHandle, // ignored
|
|
DWORD dwLen, // size of buffer
|
|
LPVOID lpData // version information buffer
|
|
)
|
|
{
|
|
LPSTR lpszString = MassageStringForPathA(lptstrFilename);
|
|
|
|
BOOL returnValue = ORIGINAL_API(GetFileVersionInfoA)(lpszString,
|
|
dwHandle,
|
|
dwLen,
|
|
lpData);
|
|
|
|
FPFreeA(lpszString, lptstrFilename);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(GetFileVersionInfoW)(
|
|
LPWSTR lptstrFilename, // file name
|
|
DWORD dwHandle, // ignored
|
|
DWORD dwLen, // size of buffer
|
|
LPVOID lpData // version information buffer
|
|
)
|
|
{
|
|
LPWSTR lpszString = MassageStringForPathW(lptstrFilename);
|
|
|
|
BOOL returnValue = ORIGINAL_API(GetFileVersionInfoW)(lpszString,
|
|
dwHandle,
|
|
dwLen,
|
|
lpData);
|
|
|
|
FPFreeW(lpszString, lptstrFilename);
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(GetOpenFileNameA)(
|
|
LPOPENFILENAMEA lpofn // initialization data
|
|
)
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
|
|
fReturn = ORIGINAL_API(GetOpenFileNameA)(lpofn);
|
|
|
|
if (fReturn) {
|
|
MassageRealPathToFakePathA(lpofn->lpstrFile, lpofn->nMaxFile);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(GetOpenFileNameW)(
|
|
LPOPENFILENAMEW lpofn // initialization data
|
|
)
|
|
{
|
|
BOOL fReturn = ORIGINAL_API(GetOpenFileNameW)(lpofn);
|
|
|
|
if (fReturn) {
|
|
MassageRealPathToFakePathW(lpofn->lpstrFile, lpofn->nMaxFile);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(GetSaveFileNameA)(
|
|
LPOPENFILENAMEA lpofn // initialization data
|
|
)
|
|
{
|
|
BOOL fReturn = ORIGINAL_API(GetSaveFileNameA)(lpofn);
|
|
|
|
if (fReturn) {
|
|
MassageRealPathToFakePathA(lpofn->lpstrFile, lpofn->nMaxFile);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(GetSaveFileNameW)(
|
|
LPOPENFILENAMEW lpofn // initialization data
|
|
)
|
|
{
|
|
BOOL fReturn = ORIGINAL_API(GetSaveFileNameW)(lpofn);
|
|
|
|
if (fReturn) {
|
|
MassageRealPathToFakePathW(lpofn->lpstrFile, lpofn->nMaxFile);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetModuleFileNameA)(
|
|
HMODULE hModule, // handle to module
|
|
LPSTR lpFilename, // path buffer
|
|
DWORD nSize // size of buffer
|
|
)
|
|
{
|
|
DWORD dwReturn = ORIGINAL_API(GetModuleFileNameA)(hModule,
|
|
lpFilename,
|
|
nSize);
|
|
|
|
if (dwReturn) {
|
|
MassageRealPathToFakePathA(lpFilename, nSize);
|
|
}
|
|
|
|
return dwReturn;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetModuleFileNameW)(
|
|
HMODULE hModule, // handle to module
|
|
LPWSTR lpFilename, // path buffer
|
|
DWORD nSize // size of buffer
|
|
)
|
|
{
|
|
DWORD dwReturn = ORIGINAL_API(GetModuleFileNameW)(hModule,
|
|
lpFilename,
|
|
nSize);
|
|
if (dwReturn) {
|
|
MassageRealPathToFakePathW(lpFilename, nSize);
|
|
}
|
|
|
|
return dwReturn;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetModuleFileNameExA)(
|
|
HANDLE hProcess, // handle to process
|
|
HMODULE hModule, // handle to module
|
|
LPSTR lpFilename, // path buffer
|
|
DWORD nSize // size of buffer
|
|
)
|
|
{
|
|
DWORD dwReturn = ORIGINAL_API(GetModuleFileNameExA)(hProcess,
|
|
hModule,
|
|
lpFilename,
|
|
nSize);
|
|
if (dwReturn) {
|
|
MassageRealPathToFakePathA(lpFilename, nSize);
|
|
}
|
|
|
|
return dwReturn;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetModuleFileNameExW)(
|
|
HANDLE hProcess, // handle to process
|
|
HMODULE hModule, // handle to module
|
|
LPWSTR lpFilename, // path buffer
|
|
DWORD nSize // size of buffer
|
|
)
|
|
{
|
|
DWORD dwReturn = ORIGINAL_API(GetModuleFileNameExW)(hProcess,
|
|
hModule,
|
|
lpFilename,
|
|
nSize);
|
|
if (dwReturn) {
|
|
MassageRealPathToFakePathW(lpFilename, nSize);
|
|
}
|
|
|
|
return dwReturn;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetCurrentDirectoryA)(
|
|
DWORD nBufferLength, // size of directory buffer
|
|
LPSTR lpBuffer // directory buffer
|
|
)
|
|
{
|
|
DWORD dwReturn = ORIGINAL_API(GetCurrentDirectoryA)(nBufferLength,
|
|
lpBuffer);
|
|
|
|
if (dwReturn) {
|
|
MassageRealPathToFakePathA(lpBuffer, nBufferLength);
|
|
}
|
|
|
|
return dwReturn;
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetCurrentDirectoryW)(
|
|
DWORD nBufferLength, // size of directory buffer
|
|
LPWSTR lpBuffer // directory buffer
|
|
)
|
|
{
|
|
DWORD dwReturn = ORIGINAL_API(GetCurrentDirectoryW)(nBufferLength,
|
|
lpBuffer);
|
|
|
|
if (dwReturn) {
|
|
MassageRealPathToFakePathW(lpBuffer, nBufferLength);
|
|
}
|
|
|
|
return dwReturn;
|
|
}
|
|
|
|
/*++
|
|
|
|
Add a corrected path to the linked list.
|
|
|
|
--*/
|
|
BOOL
|
|
AddCorrectedPath(
|
|
LPCWSTR pwszCorrectedPath,
|
|
ListType eType
|
|
)
|
|
{
|
|
int nLen = 0;
|
|
PFILELIST pFile = NULL;
|
|
LPWSTR pwszFilePath = NULL;
|
|
|
|
pFile = (PFILELIST)malloc(sizeof(FILELIST));
|
|
|
|
if (!pFile) {
|
|
DPFN(eDbgLevelError, "[AddCorrectedPath] No memory for new node!");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// We allocate the memory here to make it easier to keep track of.
|
|
// When we release the memory at the end, we can release all of it
|
|
// from one place.
|
|
//
|
|
nLen = lstrlenW(pwszCorrectedPath) + 1;
|
|
|
|
pwszFilePath = (LPWSTR)malloc(nLen * sizeof(WCHAR));
|
|
|
|
if (!pwszFilePath) {
|
|
DPFN(eDbgLevelError, "[AddCorrectedPath] No memory for wide path!");
|
|
return FALSE;
|
|
}
|
|
|
|
StringCchCopy(pwszFilePath, nLen, pwszCorrectedPath);
|
|
|
|
pFile->cchSize = nLen;
|
|
pFile->pwszFilePath = pwszFilePath;
|
|
|
|
//
|
|
// Determine which list we should add this node to.
|
|
//
|
|
if (eType == eFrom) {
|
|
pFile->pNext = g_pFileListFromHead;
|
|
g_pFileListFromHead = pFile;
|
|
} else {
|
|
pFile->pNext = g_pFileListToHead;
|
|
g_pFileListToHead = pFile;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*++
|
|
|
|
Build a list of strings separated by NULLs with two NULLs at the end.
|
|
|
|
--*/
|
|
LPWSTR
|
|
BuildStringList(
|
|
ListType eListType
|
|
)
|
|
{
|
|
UINT uMemSize = 0;
|
|
PFILELIST pFile = NULL;
|
|
PFILELIST pHead = NULL;
|
|
LPWSTR pwszReturn = NULL;
|
|
LPWSTR pwszNextString = NULL;
|
|
|
|
//
|
|
// Determine which list we're working with.
|
|
//
|
|
switch (eListType) {
|
|
case eFrom:
|
|
pHead = pFile = g_pFileListFromHead;
|
|
break;
|
|
|
|
case eTo:
|
|
pHead = pFile = g_pFileListToHead;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Walk the list and determine how large of a block we'll need to allocate.
|
|
//
|
|
while (pFile) {
|
|
uMemSize += pFile->cchSize;
|
|
pFile = pFile->pNext;
|
|
}
|
|
|
|
if (!uMemSize) {
|
|
DPFN(eDbgLevelError, "[BuildStringList] List is empty!");
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Allocate a block large enough to hold the strings with a NULL at the end.
|
|
//
|
|
pwszReturn = (LPWSTR)malloc(++uMemSize * sizeof(WCHAR));
|
|
|
|
if (!pwszReturn) {
|
|
DPFN(eDbgLevelError, "[BuildStringList] No memory for string!");
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Walk the linked list and build the list of Unicode strings.
|
|
//
|
|
pwszNextString = pwszReturn;
|
|
*pwszNextString = '\0';
|
|
|
|
while (pHead) {
|
|
wcsncpy(pwszNextString, pHead->pwszFilePath, pHead->cchSize);
|
|
pwszNextString += pHead->cchSize;
|
|
pHead = pHead->pNext;
|
|
}
|
|
|
|
*pwszNextString++ = '\0';
|
|
|
|
return pwszReturn;
|
|
}
|
|
|
|
/*++
|
|
|
|
Release memory that was allocated while processing SHFileOperation.
|
|
|
|
--*/
|
|
void
|
|
ReleaseMemAllocations(
|
|
LPWSTR pwszFinalPath,
|
|
ListType eListType
|
|
)
|
|
{
|
|
PFILELIST pHead = NULL;
|
|
PFILELIST pTemp = NULL;
|
|
|
|
switch (eListType) {
|
|
case eFrom:
|
|
pHead = g_pFileListFromHead;
|
|
break;
|
|
|
|
case eTo:
|
|
pHead = g_pFileListToHead;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Free the paths first, then the nodes next.
|
|
//
|
|
while (pHead) {
|
|
if (pHead->pwszFilePath) {
|
|
free(pHead->pwszFilePath);
|
|
}
|
|
|
|
pTemp = pHead;
|
|
pHead = pHead->pNext;
|
|
free(pTemp);
|
|
}
|
|
|
|
if (pwszFinalPath) {
|
|
free(pwszFinalPath);
|
|
}
|
|
}
|
|
|
|
/*++
|
|
|
|
Build a linked list of corrected paths.
|
|
|
|
--*/
|
|
BOOL
|
|
BuildLinkedList(
|
|
LPCWSTR pwszOriginalPath,
|
|
ListType eListType
|
|
)
|
|
{
|
|
UINT uSize = 0;
|
|
LPWSTR pwszReturnPath = NULL;
|
|
|
|
if (pwszOriginalPath) {
|
|
while (TRUE) {
|
|
pwszReturnPath = MassageStringForPathW(pwszOriginalPath);
|
|
|
|
//
|
|
// Add this corrected path to our list.
|
|
//
|
|
if (!AddCorrectedPath(pwszReturnPath, eListType)) {
|
|
DPFN(eDbgLevelError,
|
|
"[BuildLinkedList] Failed to add wide path to linked list");
|
|
return FALSE;
|
|
}
|
|
|
|
FPFreeW(pwszReturnPath, pwszOriginalPath);
|
|
|
|
uSize = lstrlenW(pwszOriginalPath) + 1;
|
|
pwszOriginalPath += uSize;
|
|
|
|
if (*pwszOriginalPath == '\0') {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
ConvertStringsToUnicode(
|
|
LPWSTR* pwszBuffer,
|
|
LPSHFILEOPSTRUCTA lpFileOp,
|
|
LPSHFILEOPSTRUCTW lpOutFileOp
|
|
)
|
|
{
|
|
UINT cchSize = 0;
|
|
UINT cchWideSize = 0;
|
|
UINT cchTotalSize = 0;
|
|
UINT cchSizeTitle = 0;
|
|
LPCSTR pszAnsi = NULL;
|
|
LPWSTR pwszTemp = NULL;
|
|
|
|
//
|
|
// Determine how large of a buffer we need to allocate.
|
|
//
|
|
if (lpFileOp->pFrom) {
|
|
pszAnsi = lpFileOp->pFrom;
|
|
|
|
do {
|
|
cchSize = lstrlenA(pszAnsi) + 1;
|
|
cchTotalSize += cchSize;
|
|
pszAnsi += cchSize;
|
|
} while (cchSize != 1);
|
|
}
|
|
|
|
if (lpFileOp->pTo) {
|
|
pszAnsi = lpFileOp->pTo;
|
|
|
|
do {
|
|
cchSize = lstrlenA(pszAnsi) + 1;
|
|
cchTotalSize += cchSize;
|
|
pszAnsi += cchSize;
|
|
} while (cchSize != 1);
|
|
}
|
|
|
|
if (lpFileOp->lpszProgressTitle) {
|
|
cchSizeTitle = lstrlenA(lpFileOp->lpszProgressTitle) + 1;
|
|
cchTotalSize += cchSizeTitle;
|
|
}
|
|
|
|
if (cchTotalSize != 0) {
|
|
pwszTemp = *pwszBuffer = (LPWSTR)malloc(cchTotalSize * sizeof(WCHAR));
|
|
|
|
if (!*pwszBuffer) {
|
|
DPFN(eDbgLevelError,
|
|
"[ConvertStringsToUnicode] No memory for buffer");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Perform the ANSI to Unicode conversion.
|
|
//
|
|
if (lpFileOp->pFrom) {
|
|
lpOutFileOp->pFrom = pwszTemp;
|
|
pszAnsi = lpFileOp->pFrom;
|
|
|
|
do {
|
|
cchSize = lstrlenA(pszAnsi) + 1;
|
|
|
|
cchWideSize = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
pszAnsi,
|
|
cchSize,
|
|
pwszTemp,
|
|
cchSize);
|
|
|
|
pszAnsi += cchSize;
|
|
pwszTemp += cchWideSize;
|
|
} while (cchSize != 1);
|
|
} else {
|
|
lpOutFileOp->pFrom = NULL;
|
|
}
|
|
|
|
if (lpFileOp->pTo) {
|
|
lpOutFileOp->pTo = pwszTemp;
|
|
pszAnsi = lpFileOp->pTo;
|
|
do {
|
|
cchSize = lstrlenA(pszAnsi) + 1;
|
|
|
|
cchWideSize = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
pszAnsi,
|
|
cchSize,
|
|
pwszTemp,
|
|
cchSize);
|
|
|
|
pszAnsi += cchSize;
|
|
pwszTemp += cchWideSize;
|
|
} while (cchSize != 1);
|
|
} else {
|
|
lpOutFileOp->pTo = NULL;
|
|
}
|
|
|
|
if (lpFileOp->lpszProgressTitle) {
|
|
lpOutFileOp->lpszProgressTitle = pwszTemp;
|
|
|
|
MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
lpFileOp->lpszProgressTitle,
|
|
cchSizeTitle,
|
|
pwszTemp,
|
|
cchSizeTitle);
|
|
} else {
|
|
lpOutFileOp->lpszProgressTitle = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int
|
|
APIHOOK(SHFileOperationW)(
|
|
LPSHFILEOPSTRUCTW lpFileOp
|
|
)
|
|
{
|
|
int nReturn = 0;
|
|
LPCWSTR pwszOriginalFrom = NULL;
|
|
LPCWSTR pwszOriginalTo = NULL;
|
|
LPWSTR pwszFinalFrom = NULL;
|
|
LPWSTR pwszFinalTo = NULL;
|
|
|
|
pwszOriginalFrom = lpFileOp->pFrom;
|
|
pwszOriginalTo = lpFileOp->pTo;
|
|
|
|
RtlEnterCriticalSection(&g_csLinkedList);
|
|
|
|
//
|
|
// Build a linked list of the 'from' paths first,
|
|
// and then process to 'to' paths.
|
|
//
|
|
if (!BuildLinkedList(pwszOriginalFrom, eFrom)) {
|
|
DPFN(eDbgLevelError,
|
|
"[SHFileOperationW] Failed to add 'from' path to linked list");
|
|
goto exit;
|
|
}
|
|
|
|
if (!BuildLinkedList(pwszOriginalTo, eTo)) {
|
|
DPFN(eDbgLevelError,
|
|
"[SHFileOperationW] Failed to add 'to' path to linked list");
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// All paths have been massaged - build a list of NULL
|
|
// separated strings with a double NULL at the end.
|
|
//
|
|
pwszFinalFrom = BuildStringList(eFrom);
|
|
|
|
if (!pwszFinalFrom) {
|
|
DPFN(eDbgLevelError, "[SHFileOperationW] Failed to build 'from' list");
|
|
goto exit;
|
|
}
|
|
|
|
pwszFinalTo = BuildStringList(eTo);
|
|
|
|
if (!pwszFinalTo) {
|
|
DPFN(eDbgLevelError, "[SHFileOperationW] Failed to build 'to' list");
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Package the strings back into the struct, call the original API
|
|
// to get the results, and then free any memory we've allocated.
|
|
//
|
|
lpFileOp->pFrom = pwszFinalFrom;
|
|
lpFileOp->pTo = pwszFinalTo;
|
|
|
|
exit:
|
|
|
|
RtlLeaveCriticalSection(&g_csLinkedList);
|
|
|
|
nReturn = ORIGINAL_API(SHFileOperationW)(lpFileOp);
|
|
|
|
ReleaseMemAllocations(pwszFinalFrom, eFrom);
|
|
ReleaseMemAllocations(pwszFinalTo, eTo);
|
|
|
|
g_pFileListFromHead = NULL;
|
|
g_pFileListToHead = NULL;
|
|
|
|
return nReturn;
|
|
}
|
|
|
|
int
|
|
APIHOOK(SHFileOperationA)(
|
|
LPSHFILEOPSTRUCTA lpFileOp
|
|
)
|
|
{
|
|
int nReturn = 0;
|
|
LPWSTR pwszBuffer = NULL;
|
|
SHFILEOPSTRUCTW shfileop;
|
|
|
|
memcpy(&shfileop, lpFileOp, sizeof(SHFILEOPSTRUCTW));
|
|
|
|
if (!ConvertStringsToUnicode(&pwszBuffer, lpFileOp, &shfileop)) {
|
|
DPFN(eDbgLevelError,
|
|
"[SHFileOperationA] Failed to convert strings");
|
|
goto exit;
|
|
}
|
|
|
|
nReturn = APIHOOK(SHFileOperationW)(&shfileop);
|
|
|
|
//
|
|
// Link up the two members that could have changed.
|
|
//
|
|
lpFileOp->fAnyOperationsAborted = shfileop.fAnyOperationsAborted;
|
|
lpFileOp->hNameMappings = shfileop.hNameMappings;
|
|
|
|
if (pwszBuffer) {
|
|
free(pwszBuffer);
|
|
}
|
|
|
|
return nReturn;
|
|
|
|
exit:
|
|
|
|
return ORIGINAL_API(SHFileOperationA)(lpFileOp);
|
|
}
|
|
|
|
NTSTATUS
|
|
APIHOOK(NtCreateFile)(
|
|
PHANDLE FileHandle,
|
|
ACCESS_MASK DesiredAccess,
|
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
PIO_STATUS_BLOCK IoStatusBlock,
|
|
PLARGE_INTEGER AllocationSize,
|
|
ULONG FileAttributes,
|
|
ULONG ShareAccess,
|
|
ULONG CreateDisposition,
|
|
ULONG CreateOptions,
|
|
PVOID EaBuffer,
|
|
ULONG EaLength
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES NewObjectAttributes;
|
|
|
|
MassageNtPath(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
NTSTATUS status = ORIGINAL_API(NtCreateFile)(FileHandle,
|
|
DesiredAccess,
|
|
&NewObjectAttributes,
|
|
IoStatusBlock,
|
|
AllocationSize,
|
|
FileAttributes,
|
|
ShareAccess,
|
|
CreateDisposition,
|
|
CreateOptions,
|
|
EaBuffer,
|
|
EaLength);
|
|
|
|
FPNtFree(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
APIHOOK(NtOpenFile)(
|
|
PHANDLE FileHandle,
|
|
ACCESS_MASK DesiredAccess,
|
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
PIO_STATUS_BLOCK IoStatusBlock,
|
|
ULONG ShareAccess,
|
|
ULONG OpenOptions
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES NewObjectAttributes;
|
|
|
|
MassageNtPath(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
NTSTATUS status = ORIGINAL_API(NtOpenFile)(FileHandle,
|
|
DesiredAccess,
|
|
&NewObjectAttributes,
|
|
IoStatusBlock,
|
|
ShareAccess,
|
|
OpenOptions);
|
|
|
|
FPNtFree(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
APIHOOK(NtQueryAttributesFile)(
|
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
PFILE_BASIC_INFORMATION FileInformation
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES NewObjectAttributes;
|
|
|
|
MassageNtPath(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
NTSTATUS status = ORIGINAL_API(NtQueryAttributesFile)(&NewObjectAttributes,
|
|
FileInformation);
|
|
|
|
FPNtFree(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
APIHOOK(NtQueryFullAttributesFile)(
|
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
PFILE_NETWORK_OPEN_INFORMATION FileInformation
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES NewObjectAttributes;
|
|
|
|
MassageNtPath(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
NTSTATUS status = ORIGINAL_API(NtQueryFullAttributesFile)(&NewObjectAttributes,
|
|
FileInformation);
|
|
|
|
FPNtFree(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
APIHOOK(NtCreateProcessEx)(
|
|
PHANDLE ProcessHandle,
|
|
ACCESS_MASK DesiredAccess,
|
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
HANDLE ParentProcess,
|
|
ULONG Flags,
|
|
HANDLE SectionHandle,
|
|
HANDLE DebugPort,
|
|
HANDLE ExceptionPort,
|
|
ULONG JobMemberLevel
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES NewObjectAttributes;
|
|
|
|
MassageNtPath(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
NTSTATUS status = ORIGINAL_API(NtCreateProcessEx)(ProcessHandle,
|
|
DesiredAccess,
|
|
&NewObjectAttributes,
|
|
ParentProcess,
|
|
Flags,
|
|
SectionHandle,
|
|
DebugPort,
|
|
ExceptionPort,
|
|
JobMemberLevel);
|
|
|
|
FPNtFree(ObjectAttributes, &NewObjectAttributes);
|
|
|
|
return status;
|
|
}
|
|
|
|
UINT
|
|
GetSimulatedPathA(
|
|
LPSTR lpBuffer,
|
|
UINT unSize,
|
|
int nWhich
|
|
)
|
|
{
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
if (unSize > (DWORD)g_Paths[nWhich].nSimulatedPathLen) {
|
|
StringCchCopyA(lpBuffer, unSize, g_Paths[nWhich].szSimulatedPathA);
|
|
return g_Paths[nWhich].nSimulatedPathLen;
|
|
} else {
|
|
return g_Paths[nWhich].nSimulatedPathLen + 1;
|
|
}
|
|
}
|
|
|
|
UINT
|
|
GetSimulatedPathW(
|
|
LPWSTR lpBuffer,
|
|
UINT unSize,
|
|
int nWhich
|
|
)
|
|
{
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
if (unSize > (DWORD)g_Paths[nWhich].nSimulatedPathLen) {
|
|
StringCchCopy(lpBuffer, unSize, g_Paths[nWhich].szSimulatedPathW);
|
|
return g_Paths[nWhich].nSimulatedPathLen;
|
|
} else {
|
|
return g_Paths[nWhich].nSimulatedPathLen + 1;
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetTempPathA)(
|
|
DWORD nBufferLength,
|
|
LPSTR lpBuffer
|
|
)
|
|
{
|
|
return GetSimulatedPathA(lpBuffer, nBufferLength, PATH_TEMP);
|
|
}
|
|
|
|
DWORD
|
|
APIHOOK(GetTempPathW)(
|
|
DWORD nBufferLength,
|
|
LPWSTR lpBuffer
|
|
)
|
|
{
|
|
return GetSimulatedPathW(lpBuffer, nBufferLength, PATH_TEMP);
|
|
}
|
|
|
|
UINT
|
|
APIHOOK(GetWindowsDirectoryA)(
|
|
LPSTR lpBuffer,
|
|
UINT unSize
|
|
)
|
|
{
|
|
return GetSimulatedPathA(lpBuffer, unSize, PATH_WINDOWS);
|
|
}
|
|
|
|
UINT
|
|
APIHOOK(GetWindowsDirectoryW)(
|
|
LPWSTR lpBuffer,
|
|
UINT unSize
|
|
)
|
|
{
|
|
return GetSimulatedPathW(lpBuffer, unSize, PATH_WINDOWS);
|
|
}
|
|
|
|
UINT
|
|
APIHOOK(GetSystemWindowsDirectoryA)(
|
|
LPSTR lpBuffer,
|
|
UINT unSize
|
|
)
|
|
{
|
|
return GetSimulatedPathA(lpBuffer, unSize, PATH_SYSTEM_WINDOWS);
|
|
}
|
|
|
|
UINT
|
|
APIHOOK(GetSystemWindowsDirectoryW)(
|
|
LPWSTR lpBuffer,
|
|
UINT unSize
|
|
)
|
|
{
|
|
return GetSimulatedPathW(lpBuffer, unSize, PATH_SYSTEM_WINDOWS);
|
|
}
|
|
|
|
UINT
|
|
APIHOOK(GetSystemDirectoryA)(
|
|
LPSTR lpBuffer,
|
|
UINT unSize
|
|
)
|
|
{
|
|
return GetSimulatedPathA(lpBuffer, unSize, PATH_SYSTEM);
|
|
}
|
|
|
|
UINT
|
|
APIHOOK(GetSystemDirectoryW)(
|
|
LPWSTR lpBuffer,
|
|
UINT unSize
|
|
)
|
|
{
|
|
return GetSimulatedPathW(lpBuffer, unSize, PATH_SYSTEM);
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(SHGetSpecialFolderPathA)(
|
|
HWND hwndOwner,
|
|
LPSTR lpszPath,
|
|
int nFolder,
|
|
BOOL fCreate
|
|
)
|
|
{
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
switch (nFolder) {
|
|
case CSIDL_PERSONAL:
|
|
StringCchCopyA(lpszPath, MAX_PATH, g_Paths[PATH_PERSONAL].szSimulatedPathA);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_SYSTEM:
|
|
StringCchCopyA(lpszPath, MAX_PATH, g_Paths[PATH_SYSTEM].szSimulatedPathA);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_WINDOWS:
|
|
StringCchCopyA(lpszPath, MAX_PATH, g_Paths[PATH_WINDOWS].szSimulatedPathA);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_PROGRAMS:
|
|
StringCchCopyA(lpszPath, MAX_PATH, g_Paths[PATH_PROGRAMS].szSimulatedPathA);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_STARTMENU:
|
|
StringCchCopyA(lpszPath, MAX_PATH, g_Paths[PATH_PROGRAMS].szSimulatedPathA);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_COMMON_PROGRAMS:
|
|
StringCchCopyA(lpszPath, MAX_PATH, g_Paths[PATH_COMMON_PROGRAMS].szSimulatedPathA);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_COMMON_STARTMENU:
|
|
StringCchCopyA(lpszPath, MAX_PATH, g_Paths[PATH_COMMON_STARTMENU].szSimulatedPathA);
|
|
return TRUE;
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// the others we aren't nabbing
|
|
//
|
|
return ORIGINAL_API(SHGetSpecialFolderPathA)(hwndOwner, lpszPath, nFolder, fCreate);
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(SHGetSpecialFolderPathW)(
|
|
HWND hwndOwner,
|
|
LPWSTR lpszPath,
|
|
int nFolder,
|
|
BOOL fCreate
|
|
)
|
|
{
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
switch (nFolder) {
|
|
case CSIDL_PERSONAL:
|
|
StringCchCopy(lpszPath, MAX_PATH, g_Paths[PATH_PERSONAL].szSimulatedPathW);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_SYSTEM:
|
|
StringCchCopy(lpszPath, MAX_PATH, g_Paths[PATH_SYSTEM].szSimulatedPathW);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_WINDOWS:
|
|
StringCchCopy(lpszPath, MAX_PATH, g_Paths[PATH_WINDOWS].szSimulatedPathW);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_PROGRAMS:
|
|
StringCchCopy(lpszPath, MAX_PATH, g_Paths[PATH_PROGRAMS].szSimulatedPathW);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_STARTMENU:
|
|
StringCchCopy(lpszPath, MAX_PATH, g_Paths[PATH_PROGRAMS].szSimulatedPathW);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_COMMON_PROGRAMS:
|
|
StringCchCopy(lpszPath, MAX_PATH, g_Paths[PATH_COMMON_PROGRAMS].szSimulatedPathW);
|
|
return TRUE;
|
|
break;
|
|
|
|
case CSIDL_COMMON_STARTMENU:
|
|
StringCchCopy(lpszPath, MAX_PATH, g_Paths[PATH_COMMON_STARTMENU].szSimulatedPathW);
|
|
return TRUE;
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// the others we aren't nabbing
|
|
//
|
|
return ORIGINAL_API(SHGetSpecialFolderPathW)(hwndOwner, lpszPath, nFolder, fCreate);
|
|
}
|
|
|
|
HRESULT
|
|
APIHOOK(SHGetFolderPathA)(
|
|
HWND hwndOwner,
|
|
int nFolder,
|
|
HANDLE hToken,
|
|
DWORD dwFlags,
|
|
LPSTR pszPath
|
|
)
|
|
{
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
switch (nFolder) {
|
|
case CSIDL_PERSONAL:
|
|
StringCchCopyA(pszPath, MAX_PATH, g_Paths[PATH_PERSONAL].szSimulatedPathA);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_SYSTEM:
|
|
StringCchCopyA(pszPath, MAX_PATH, g_Paths[PATH_SYSTEM].szSimulatedPathA);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_WINDOWS:
|
|
StringCchCopyA(pszPath, MAX_PATH, g_Paths[PATH_WINDOWS].szSimulatedPathA);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_PROGRAMS:
|
|
StringCchCopyA(pszPath, MAX_PATH, g_Paths[PATH_PROGRAMS].szSimulatedPathA);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_STARTMENU:
|
|
StringCchCopyA(pszPath, MAX_PATH, g_Paths[PATH_PROGRAMS].szSimulatedPathA);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_COMMON_PROGRAMS:
|
|
StringCchCopyA(pszPath, MAX_PATH, g_Paths[PATH_COMMON_PROGRAMS].szSimulatedPathA);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_COMMON_STARTMENU:
|
|
StringCchCopyA(pszPath, MAX_PATH, g_Paths[PATH_COMMON_STARTMENU].szSimulatedPathA);
|
|
return S_OK;
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// the others we aren't nabbing
|
|
//
|
|
return ORIGINAL_API(SHGetFolderPathA)(hwndOwner, nFolder, hToken, dwFlags, pszPath);
|
|
}
|
|
|
|
HRESULT
|
|
APIHOOK(SHGetFolderPathW)(
|
|
HWND hwndOwner,
|
|
int nFolder,
|
|
HANDLE hToken,
|
|
DWORD dwFlags,
|
|
LPWSTR pszPath
|
|
)
|
|
{
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
switch (nFolder) {
|
|
case CSIDL_PERSONAL:
|
|
StringCchCopy(pszPath, MAX_PATH, g_Paths[PATH_PERSONAL].szSimulatedPathW);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_SYSTEM:
|
|
StringCchCopy(pszPath, MAX_PATH, g_Paths[PATH_SYSTEM].szSimulatedPathW);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_WINDOWS:
|
|
StringCchCopy(pszPath, MAX_PATH, g_Paths[PATH_WINDOWS].szSimulatedPathW);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_PROGRAMS:
|
|
StringCchCopy(pszPath, MAX_PATH, g_Paths[PATH_PROGRAMS].szSimulatedPathW);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_STARTMENU:
|
|
StringCchCopy(pszPath, MAX_PATH, g_Paths[PATH_PROGRAMS].szSimulatedPathW);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_COMMON_PROGRAMS:
|
|
StringCchCopy(pszPath, MAX_PATH, g_Paths[PATH_COMMON_PROGRAMS].szSimulatedPathW);
|
|
return S_OK;
|
|
break;
|
|
|
|
case CSIDL_COMMON_STARTMENU:
|
|
StringCchCopy(pszPath, MAX_PATH, g_Paths[PATH_COMMON_STARTMENU].szSimulatedPathW);
|
|
return S_OK;
|
|
break;
|
|
|
|
}
|
|
|
|
//
|
|
// the others we aren't nabbing
|
|
//
|
|
return ORIGINAL_API(SHGetFolderPathW)(hwndOwner, nFolder, hToken, dwFlags, pszPath);
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(SHGetPathFromIDListA)(
|
|
LPCITEMIDLIST pidl,
|
|
LPSTR pszPath
|
|
)
|
|
{
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
BOOL fReturn = ORIGINAL_API(SHGetPathFromIDListA)(pidl, pszPath);
|
|
|
|
if (fReturn) {
|
|
MassageRealPathToFakePathA(pszPath, MAX_PATH);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
BOOL
|
|
APIHOOK(SHGetPathFromIDListW)(
|
|
LPCITEMIDLIST pidl,
|
|
LPWSTR pszPath
|
|
)
|
|
{
|
|
if (!g_bPathsInited) {
|
|
InitPaths();
|
|
}
|
|
|
|
BOOL fReturn = ORIGINAL_API(SHGetPathFromIDListW)(pidl, pszPath);
|
|
|
|
if (fReturn) {
|
|
MassageRealPathToFakePathW(pszPath, MAX_PATH);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
SHIM_INFO_BEGIN()
|
|
|
|
SHIM_INFO_DESCRIPTION(AVS_FILEPATHS_DESC)
|
|
SHIM_INFO_FRIENDLY_NAME(AVS_FILEPATHS_FRIENDLY)
|
|
SHIM_INFO_FLAGS(AVRF_FLAG_RUN_ALONE | AVRF_FLAG_EXTERNAL_ONLY)
|
|
SHIM_INFO_GROUPS(0)
|
|
SHIM_INFO_VERSION(1, 6)
|
|
SHIM_INFO_INCLUDE_EXCLUDE("E:ole32.dll oleaut32.dll")
|
|
|
|
SHIM_INFO_END()
|
|
|
|
BOOL
|
|
NOTIFY_FUNCTION(
|
|
DWORD fdwReason
|
|
)
|
|
{
|
|
if (fdwReason == DLL_PROCESS_ATTACH) {
|
|
|
|
UINT cchSize;
|
|
DWORD cchReturned;
|
|
|
|
//
|
|
// Initialize a critical section to keep our linked list safe.
|
|
//
|
|
RtlInitializeCriticalSection(&g_csLinkedList);
|
|
|
|
cchReturned = GetTempPathA(MAX_PATH, g_Paths[PATH_TEMP].szCorrectPathA);
|
|
|
|
if (cchReturned > sizeof(g_Paths[PATH_TEMP].szCorrectPathA) || cchReturned == 0) {
|
|
goto exit;
|
|
}
|
|
|
|
cchReturned = GetTempPathW(MAX_PATH, g_Paths[PATH_TEMP].szCorrectPathW);
|
|
|
|
if (cchReturned > ARRAYSIZE(g_Paths[PATH_TEMP].szCorrectPathW) || cchReturned == 0) {
|
|
goto exit;
|
|
}
|
|
|
|
g_Paths[PATH_TEMP].nCorrectPathLen = strlen(g_Paths[PATH_TEMP].szCorrectPathA);
|
|
g_Paths[PATH_TEMP].nSimulatedPathLen = strlen(g_Paths[PATH_TEMP].szSimulatedPathA);
|
|
|
|
cchSize = GetWindowsDirectoryA(g_Paths[PATH_WINDOWS].szCorrectPathA, MAX_PATH);
|
|
|
|
if (cchSize > sizeof(g_Paths[PATH_WINDOWS].szCorrectPathA) || cchSize == 0) {
|
|
goto exit;
|
|
}
|
|
|
|
cchSize = GetWindowsDirectoryW(g_Paths[PATH_WINDOWS].szCorrectPathW, MAX_PATH);
|
|
|
|
if (cchSize > ARRAYSIZE(g_Paths[PATH_WINDOWS].szCorrectPathW) || cchSize == 0) {
|
|
goto exit;
|
|
}
|
|
|
|
g_Paths[PATH_WINDOWS].nCorrectPathLen = strlen(g_Paths[PATH_WINDOWS].szCorrectPathA);
|
|
g_Paths[PATH_WINDOWS].nSimulatedPathLen = strlen(g_Paths[PATH_WINDOWS].szSimulatedPathA);
|
|
|
|
cchSize = GetSystemWindowsDirectoryA(g_Paths[PATH_SYSTEM_WINDOWS].szCorrectPathA, MAX_PATH);
|
|
|
|
if (cchSize > sizeof(g_Paths[PATH_SYSTEM_WINDOWS].szCorrectPathA) || cchSize == 0) {
|
|
goto exit;
|
|
}
|
|
|
|
cchSize = GetSystemWindowsDirectoryW(g_Paths[PATH_SYSTEM_WINDOWS].szCorrectPathW, MAX_PATH);
|
|
|
|
if (cchSize > ARRAYSIZE(g_Paths[PATH_SYSTEM_WINDOWS].szCorrectPathW) || cchSize == 0) {
|
|
goto exit;
|
|
}
|
|
|
|
g_Paths[PATH_SYSTEM_WINDOWS].nCorrectPathLen = strlen(g_Paths[PATH_SYSTEM_WINDOWS].szCorrectPathA);
|
|
g_Paths[PATH_SYSTEM_WINDOWS].nSimulatedPathLen = strlen(g_Paths[PATH_SYSTEM_WINDOWS].szSimulatedPathA);
|
|
|
|
cchSize = GetSystemDirectoryA(g_Paths[PATH_SYSTEM].szCorrectPathA, MAX_PATH);
|
|
|
|
if (cchSize > sizeof(g_Paths[PATH_SYSTEM].szCorrectPathA) || cchSize == 0) {
|
|
goto exit;
|
|
}
|
|
|
|
cchSize = GetSystemDirectoryW(g_Paths[PATH_SYSTEM].szCorrectPathW, MAX_PATH);
|
|
|
|
if (cchSize > ARRAYSIZE(g_Paths[PATH_SYSTEM].szCorrectPathW) || cchSize == 0) {
|
|
goto exit;
|
|
}
|
|
|
|
g_Paths[PATH_SYSTEM].nCorrectPathLen = strlen(g_Paths[PATH_SYSTEM].szCorrectPathA);
|
|
g_Paths[PATH_SYSTEM].nSimulatedPathLen = strlen(g_Paths[PATH_SYSTEM].szSimulatedPathA);
|
|
|
|
//
|
|
// Catch apps that use ExpandEnvironmentStrings.
|
|
//
|
|
SetEnvironmentVariableW(L"TEMP", g_Paths[PATH_TEMP].szSimulatedPathW);
|
|
SetEnvironmentVariableW(L"TMP", g_Paths[PATH_TEMP].szSimulatedPathW);
|
|
SetEnvironmentVariableW(L"windir", g_Paths[PATH_WINDOWS].szSimulatedPathW);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
exit:
|
|
DPFN(eDbgLevelError,
|
|
"[NOTIFY_FUNCTION] 0x%08X Failed to initialize",
|
|
GetLastError());
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*++
|
|
|
|
Register hooked functions
|
|
|
|
--*/
|
|
|
|
HOOK_BEGIN
|
|
|
|
CALL_NOTIFY_FUNCTION
|
|
|
|
DUMP_VERIFIER_LOG_ENTRY(VLOG_HARDCODED_GETTEMPPATH,
|
|
AVS_HARDCODED_GETTEMPPATH,
|
|
AVS_HARDCODED_GETTEMPPATH_R,
|
|
AVS_HARDCODED_GETTEMPPATH_URL)
|
|
|
|
DUMP_VERIFIER_LOG_ENTRY(VLOG_HARDCODED_WINDOWSPATH,
|
|
AVS_HARDCODED_WINDOWSPATH,
|
|
AVS_HARDCODED_WINDOWSPATH_R,
|
|
AVS_HARDCODED_WINDOWSPATH_URL)
|
|
|
|
DUMP_VERIFIER_LOG_ENTRY(VLOG_HARDCODED_SYSWINDOWSPATH,
|
|
AVS_HARDCODED_SYSWINDOWSPATH,
|
|
AVS_HARDCODED_SYSWINDOWSPATH_R,
|
|
AVS_HARDCODED_SYSWINDOWSPATH_URL)
|
|
|
|
DUMP_VERIFIER_LOG_ENTRY(VLOG_HARDCODED_SYSTEMPATH,
|
|
AVS_HARDCODED_SYSTEMPATH,
|
|
AVS_HARDCODED_SYSTEMPATH_R,
|
|
AVS_HARDCODED_SYSTEMPATH_URL)
|
|
|
|
DUMP_VERIFIER_LOG_ENTRY(VLOG_HARDCODED_PERSONALPATH,
|
|
AVS_HARDCODED_PERSONALPATH,
|
|
AVS_HARDCODED_PERSONALPATH_R,
|
|
AVS_HARDCODED_PERSONALPATH_URL)
|
|
|
|
DUMP_VERIFIER_LOG_ENTRY(VLOG_HARDCODED_COMMONPROGRAMS,
|
|
AVS_HARDCODED_COMMONPROGRAMS,
|
|
AVS_HARDCODED_COMMONPROGRAMS_R,
|
|
AVS_HARDCODED_COMMONPROGRAMS_URL)
|
|
|
|
DUMP_VERIFIER_LOG_ENTRY(VLOG_HARDCODED_COMMONSTARTMENU,
|
|
AVS_HARDCODED_COMMONSTARTMENU,
|
|
AVS_HARDCODED_COMMONSTARTMENU_R,
|
|
AVS_HARDCODED_COMMONSTARTMENU_URL)
|
|
|
|
DUMP_VERIFIER_LOG_ENTRY(VLOG_HARDCODED_PROGRAMS,
|
|
AVS_HARDCODED_PROGRAMS,
|
|
AVS_HARDCODED_PROGRAMS_R,
|
|
AVS_HARDCODED_PROGRAMS_URL)
|
|
|
|
DUMP_VERIFIER_LOG_ENTRY(VLOG_HARDCODED_STARTMENU,
|
|
AVS_HARDCODED_STARTMENU,
|
|
AVS_HARDCODED_STARTMENU_R,
|
|
AVS_HARDCODED_STARTMENU_URL)
|
|
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetCommandLineA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetCommandLineW)
|
|
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetTempPathA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetTempPathW)
|
|
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetSystemDirectoryA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetSystemDirectoryW)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetSystemWindowsDirectoryA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetSystemWindowsDirectoryW)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetWindowsDirectoryA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetWindowsDirectoryW)
|
|
|
|
APIHOOK_ENTRY(SHELL32.DLL, SHGetFolderPathA)
|
|
APIHOOK_ENTRY(SHELL32.DLL, SHGetFolderPathW)
|
|
|
|
APIHOOK_ENTRY(SHELL32.DLL, SHGetSpecialFolderPathA)
|
|
APIHOOK_ENTRY(SHELL32.DLL, SHGetSpecialFolderPathW)
|
|
|
|
APIHOOK_ENTRY(SHELL32.DLL, SHGetPathFromIDListA)
|
|
APIHOOK_ENTRY(SHELL32.DLL, SHGetPathFromIDListW)
|
|
|
|
APIHOOK_ENTRY(COMDLG32.DLL, GetOpenFileNameA)
|
|
APIHOOK_ENTRY(COMDLG32.DLL, GetOpenFileNameW)
|
|
|
|
APIHOOK_ENTRY(COMDLG32.DLL, GetSaveFileNameA)
|
|
APIHOOK_ENTRY(COMDLG32.DLL, GetSaveFileNameW)
|
|
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetModuleFileNameA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetModuleFileNameW)
|
|
|
|
APIHOOK_ENTRY(PSAPI.DLL, GetModuleFileNameExA)
|
|
APIHOOK_ENTRY(PSAPI.DLL, GetModuleFileNameExW)
|
|
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetCurrentDirectoryA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, GetCurrentDirectoryW)
|
|
|
|
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)
|
|
|
|
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)
|
|
|
|
// 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, LoadLibraryA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryW)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryExA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryExW)
|
|
|
|
APIHOOK_ENTRY(KERNEL32.DLL, SearchPathA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, SearchPathW)
|
|
|
|
APIHOOK_ENTRY(KERNEL32.DLL, ExpandEnvironmentStringsA)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, ExpandEnvironmentStringsW)
|
|
|
|
APIHOOK_ENTRY(VERSION.DLL, GetFileVersionInfoSizeA)
|
|
APIHOOK_ENTRY(VERSION.DLL, GetFileVersionInfoSizeW)
|
|
APIHOOK_ENTRY(VERSION.DLL, GetFileVersionInfoA)
|
|
APIHOOK_ENTRY(VERSION.DLL, GetFileVersionInfoW)
|
|
|
|
APIHOOK_ENTRY(SHELL32.DLL, SHFileOperationA)
|
|
APIHOOK_ENTRY(SHELL32.DLL, SHFileOperationW)
|
|
|
|
APIHOOK_ENTRY(KERNEL32.DLL, OpenFile)
|
|
|
|
// 16 bit compatibility file routines
|
|
APIHOOK_ENTRY(KERNEL32.DLL, _lopen)
|
|
APIHOOK_ENTRY(KERNEL32.DLL, _lcreat)
|
|
|
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegQueryValueA)
|
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegQueryValueW)
|
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegQueryValueExA)
|
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegQueryValueExW)
|
|
|
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegSetValueA)
|
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegSetValueW)
|
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegSetValueExA)
|
|
APIHOOK_ENTRY(ADVAPI32.DLL, RegSetValueExW)
|
|
|
|
APIHOOK_ENTRY(NTDLL.DLL, NtCreateFile)
|
|
APIHOOK_ENTRY(NTDLL.DLL, NtOpenFile)
|
|
APIHOOK_ENTRY(NTDLL.DLL, NtQueryAttributesFile)
|
|
APIHOOK_ENTRY(NTDLL.DLL, NtQueryFullAttributesFile)
|
|
APIHOOK_ENTRY(NTDLL.DLL, NtCreateProcessEx)
|
|
|
|
HOOK_END
|
|
|
|
IMPLEMENT_SHIM_END
|
|
|