Backed out 13 changesets (bug 1460022) for bustages in builds/worker/workspace/build/src/dom/plugins/ipc/FunctionHook.h💯24 on a CLOSED TREE

Backed out changeset 0734142a3f35 (bug 1460022)
Backed out changeset 18fbfa7ca685 (bug 1460022)
Backed out changeset 2df129bd5692 (bug 1460022)
Backed out changeset 02a7ed68933f (bug 1460022)
Backed out changeset 221137d1c2de (bug 1460022)
Backed out changeset 9cb0b7a15402 (bug 1460022)
Backed out changeset 18f8f85c0307 (bug 1460022)
Backed out changeset 867a1351efff (bug 1460022)
Backed out changeset 933e0b698f8e (bug 1460022)
Backed out changeset 09da660071e1 (bug 1460022)
Backed out changeset 8bb5142d3f53 (bug 1460022)
Backed out changeset 0ddf581bdaac (bug 1460022)
Backed out changeset 1cd5f9b4a6af (bug 1460022)
This commit is contained in:
shindli 2018-07-04 02:49:24 +03:00
parent 9bd593b66d
commit dcc88f33f9
17 changed files with 770 additions and 657 deletions

View File

@ -95,8 +95,7 @@ Compatibility::IsModuleVersionLessThan(HMODULE aModuleHandle,
////////////////////////////////////////////////////////////////////////////////
static WindowsDllInterceptor sUser32Interceptor;
static WindowsDllInterceptor::FuncHookType<decltype(&InSendMessageEx)>
sInSendMessageExStub;
static decltype(&InSendMessageEx) sInSendMessageExStub = nullptr;
static bool sInSendMessageExHackEnabled = false;
static PVOID sVectoredExceptionHandler = nullptr;
@ -268,9 +267,11 @@ Compatibility::Init()
if ((sConsumers & (~(UIAUTOMATION | NVDA))) &&
BrowserTabsRemoteAutostart()) {
sUser32Interceptor.Init("user32.dll");
sInSendMessageExStub.Set(sUser32Interceptor, "InSendMessageEx",
&InSendMessageExHook);
if (!sInSendMessageExStub) {
sUser32Interceptor.AddHook("InSendMessageEx",
reinterpret_cast<intptr_t>(&InSendMessageExHook),
(void**)&sInSendMessageExStub);
}
// The vectored exception handler allows us to catch exceptions ahead of any
// SEH handlers.
if (!sVectoredExceptionHandler) {

View File

@ -246,8 +246,7 @@ IsDllAllowed(const UNICODE_STRING& aLeafName, void* aBaseAddress)
}
typedef decltype(&NtMapViewOfSection) NtMapViewOfSection_func;
static mozilla::CrossProcessDllInterceptor::FuncHookType<NtMapViewOfSection_func>
stub_NtMapViewOfSection;
static NtMapViewOfSection_func stub_NtMapViewOfSection;
static NTSTATUS NTAPI
patched_NtMapViewOfSection(HANDLE aSection, HANDLE aProcess, PVOID* aBaseAddress,
@ -357,8 +356,9 @@ InitializeDllBlocklistOOP(HANDLE aChildProcess)
{
mozilla::CrossProcessDllInterceptor intcpt(aChildProcess);
intcpt.Init(L"ntdll.dll");
bool ok = stub_NtMapViewOfSection.SetDetour(intcpt, "NtMapViewOfSection",
&patched_NtMapViewOfSection);
bool ok = intcpt.AddDetour("NtMapViewOfSection",
reinterpret_cast<intptr_t>(&patched_NtMapViewOfSection),
(void**) &stub_NtMapViewOfSection);
if (!ok) {
return false;
}

View File

@ -197,8 +197,7 @@ typedef DWORD(WINAPI* QueryDosDeviceWFnPtr)(_In_opt_ LPCWSTR lpDeviceName,
_Out_ LPWSTR lpTargetPath,
_In_ DWORD ucchMax);
static WindowsDllInterceptor::FuncHookType<QueryDosDeviceWFnPtr>
sOriginalQueryDosDeviceWFnPtr;
static QueryDosDeviceWFnPtr sOriginalQueryDosDeviceWFnPtr = nullptr;
static std::unordered_map<std::wstring, std::wstring>* sDeviceNames = nullptr;
@ -277,8 +276,9 @@ InitializeHooks()
}
sKernel32Intercept.Init("kernelbase.dll");
sOriginalQueryDosDeviceWFnPtr.Set(sKernel32Intercept, "QueryDosDeviceW",
&QueryDosDeviceWHook);
sKernel32Intercept.AddHook("QueryDosDeviceW",
reinterpret_cast<intptr_t>(QueryDosDeviceWHook),
(void**)(&sOriginalQueryDosDeviceWFnPtr));
}
#endif

View File

@ -357,10 +357,8 @@ typedef LONG_PTR
(WINAPI *User32SetWindowLongPtrW)(HWND hWnd,
int nIndex,
LONG_PTR dwNewLong);
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrA>
sUser32SetWindowLongAHookStub;
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrW>
sUser32SetWindowLongWHookStub;
static User32SetWindowLongPtrA sUser32SetWindowLongAHookStub = nullptr;
static User32SetWindowLongPtrW sUser32SetWindowLongWHookStub = nullptr;
#else
typedef LONG
(WINAPI *User32SetWindowLongA)(HWND hWnd,
@ -370,10 +368,8 @@ typedef LONG
(WINAPI *User32SetWindowLongW)(HWND hWnd,
int nIndex,
LONG dwNewLong);
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongA>
sUser32SetWindowLongAHookStub;
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongW>
sUser32SetWindowLongWHookStub;
static User32SetWindowLongA sUser32SetWindowLongAHookStub = nullptr;
static User32SetWindowLongW sUser32SetWindowLongWHookStub = nullptr;
#endif
static inline bool
SetWindowLongHookCheck(HWND hWnd,
@ -452,15 +448,23 @@ HookSetWindowLongPtr()
{
sUser32Intercept.Init("user32.dll");
#ifdef _WIN64
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongPtrA",
&SetWindowLongPtrAHook);
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongPtrW",
&SetWindowLongPtrWHook);
if (!sUser32SetWindowLongAHookStub)
sUser32Intercept.AddHook("SetWindowLongPtrA",
reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
(void**) &sUser32SetWindowLongAHookStub);
if (!sUser32SetWindowLongWHookStub)
sUser32Intercept.AddHook("SetWindowLongPtrW",
reinterpret_cast<intptr_t>(SetWindowLongPtrWHook),
(void**) &sUser32SetWindowLongWHookStub);
#else
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongA",
&SetWindowLongAHook);
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongW",
&SetWindowLongWHook);
if (!sUser32SetWindowLongAHookStub)
sUser32Intercept.AddHook("SetWindowLongA",
reinterpret_cast<intptr_t>(SetWindowLongAHook),
(void**) &sUser32SetWindowLongAHookStub);
if (!sUser32SetWindowLongWHookStub)
sUser32Intercept.AddHook("SetWindowLongW",
reinterpret_cast<intptr_t>(SetWindowLongWHook),
(void**) &sUser32SetWindowLongWHookStub);
#endif
}

View File

@ -168,13 +168,13 @@ typedef HANDLE (WINAPI *CreateFileWPtr)(LPCWSTR aFname, DWORD aAccess,
LPSECURITY_ATTRIBUTES aSecurity,
DWORD aCreation, DWORD aFlags,
HANDLE aFTemplate);
static WindowsDllInterceptor::FuncHookType<CreateFileWPtr> sCreateFileWStub;
static CreateFileWPtr sCreateFileWStub = nullptr;
typedef HANDLE (WINAPI *CreateFileAPtr)(LPCSTR aFname, DWORD aAccess,
DWORD aShare,
LPSECURITY_ATTRIBUTES aSecurity,
DWORD aCreation, DWORD aFlags,
HANDLE aFTemplate);
static WindowsDllInterceptor::FuncHookType<CreateFileAPtr> sCreateFileAStub;
static CreateFileAPtr sCreateFileAStub = nullptr;
// Windows 8 RTM (kernelbase's version is 6.2.9200.16384) doesn't call
// CreateFileW from CreateFileA.
@ -263,7 +263,7 @@ CreateFileWHookFn(LPCWSTR aFname, DWORD aAccess, DWORD aShare,
aSecurity, TRUNCATE_EXISTING,
FILE_ATTRIBUTE_TEMPORARY |
FILE_FLAG_DELETE_ON_CLOSE,
nullptr);
NULL);
if (replacement == INVALID_HANDLE_VALUE) {
break;
}
@ -300,12 +300,23 @@ CreateFileWHookFn(LPCWSTR aFname, DWORD aAccess, DWORD aShare,
void FunctionHook::HookProtectedMode()
{
// Make sure we only do this once.
static bool sRunOnce = false;
if (sRunOnce) {
return;
}
sRunOnce = true;
// Legacy code. Uses the nsWindowsDLLInterceptor directly instead of
// using the FunctionHook
sKernel32Intercept.Init("kernel32.dll");
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Plugin);
sCreateFileWStub.Set(sKernel32Intercept, "CreateFileW", &CreateFileWHookFn);
sCreateFileAStub.Set(sKernel32Intercept, "CreateFileA", &CreateFileAHookFn);
sKernel32Intercept.AddHook("CreateFileW",
reinterpret_cast<intptr_t>(CreateFileWHookFn),
(void**) &sCreateFileWStub);
sKernel32Intercept.AddHook("CreateFileA",
reinterpret_cast<intptr_t>(CreateFileAHookFn),
(void**) &sCreateFileAStub);
}
#endif // defined(XP_WIN)

View File

@ -9,7 +9,6 @@
#include "IpdlTuple.h"
#include "base/process.h"
#include "mozilla/Atomics.h"
#if defined(XP_WIN)
#include "nsWindowsDllInterceptor.h"
@ -97,17 +96,12 @@ typedef bool(ShouldHookFunc)(int aQuirks);
template<FunctionHookId functionId, typename FunctionType>
class BasicFunctionHook : public FunctionHook
{
using FuncHookType = WindowsDllInterceptor::FuncHookType<FunctionType*>;
public:
BasicFunctionHook(const char* aModuleName,
const char* aFunctionName, FunctionType* aOldFunction,
FunctionType* aNewFunction)
: mOldFunction(aOldFunction)
, mRegistration(UNREGISTERED)
, mModuleName(aModuleName)
, mFunctionName(aFunctionName)
, mNewFunction(aNewFunction)
FunctionType* aNewFunction) :
mOldFunction(aOldFunction), mRegistration(UNREGISTERED), mModuleName(aModuleName),
mFunctionName(aFunctionName), mNewFunction(aNewFunction)
{
MOZ_ASSERT(mOldFunction);
MOZ_ASSERT(mNewFunction);
@ -134,8 +128,7 @@ protected:
// Once the function is hooked, this field will take the value of a pointer to
// a function that performs the old behavior. Before that, it is a pointer to
// the original function.
Atomic<FunctionType*> mOldFunction;
FuncHookType mStub;
FunctionType* mOldFunction;
enum RegistrationStatus { UNREGISTERED, FAILED, SUCCEEDED };
RegistrationStatus mRegistration;
@ -177,14 +170,14 @@ BasicFunctionHook<functionId, FunctionType>::Register(int aQuirks)
return false;
}
isHooked = mStub.Set(*dllInterceptor, mFunctionName.Data(), mNewFunction);
isHooked =
dllInterceptor->AddHook(mFunctionName.Data(), reinterpret_cast<intptr_t>(mNewFunction),
reinterpret_cast<void**>(&mOldFunction));
#endif
if (isHooked) {
mOldFunction = mStub.GetStub();
mRegistration = SUCCEEDED;
}
HOOK_LOG(LogLevel::Debug,
("Registering to intercept function '%s' : '%s'", mFunctionName.Data(),
SuccessMsg(isHooked)));

View File

@ -73,17 +73,21 @@ typedef BOOL (WINAPI *User32TrackPopupMenu)(HMENU hMenu,
CONST RECT *prcRect);
static WindowsDllInterceptor sUser32Intercept;
static HWND sWinlessPopupSurrogateHWND = nullptr;
static WindowsDllInterceptor::FuncHookType<User32TrackPopupMenu> sUser32TrackPopupMenuStub;
static User32TrackPopupMenu sUser32TrackPopupMenuStub = nullptr;
static WindowsDllInterceptor sImm32Intercept;
static WindowsDllInterceptor::FuncHookType<decltype(&ImmGetContext)> sImm32ImmGetContextStub;
static WindowsDllInterceptor::FuncHookType<decltype(&ImmGetCompositionStringW)> sImm32ImmGetCompositionStringStub;
static WindowsDllInterceptor::FuncHookType<decltype(&ImmSetCandidateWindow)> sImm32ImmSetCandidateWindowStub;
static WindowsDllInterceptor::FuncHookType<decltype(&ImmNotifyIME)> sImm32ImmNotifyIME;
static WindowsDllInterceptor::FuncHookType<decltype(&ImmAssociateContextEx)> sImm32ImmAssociateContextExStub;
static decltype(ImmGetContext)* sImm32ImmGetContextStub = nullptr;
static decltype(ImmGetCompositionStringW)* sImm32ImmGetCompositionStringStub =
nullptr;
static decltype(ImmSetCandidateWindow)* sImm32ImmSetCandidateWindowStub =
nullptr;
static decltype(ImmNotifyIME)* sImm32ImmNotifyIME = nullptr;
static decltype(ImmAssociateContextEx)* sImm32ImmAssociateContextExStub =
nullptr;
static PluginInstanceChild* sCurrentPluginInstance = nullptr;
static const HIMC sHookIMC = (const HIMC)0xefefefef;
static bool sPopupMenuHookSet;
static bool sSetWindowLongHookSet;
using mozilla::gfx::SharedDIB;
@ -1789,8 +1793,8 @@ typedef LONG_PTR
(WINAPI *User32SetWindowLongPtrW)(HWND hWnd,
int nIndex,
LONG_PTR dwNewLong);
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrA> sUser32SetWindowLongAHookStub;
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrW> sUser32SetWindowLongWHookStub;
static User32SetWindowLongPtrA sUser32SetWindowLongAHookStub = nullptr;
static User32SetWindowLongPtrW sUser32SetWindowLongWHookStub = nullptr;
#else
typedef LONG
(WINAPI *User32SetWindowLongA)(HWND hWnd,
@ -1800,8 +1804,8 @@ typedef LONG
(WINAPI *User32SetWindowLongW)(HWND hWnd,
int nIndex,
LONG dwNewLong);
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongA> sUser32SetWindowLongAHookStub;
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongW> sUser32SetWindowLongWHookStub;
static User32SetWindowLongA sUser32SetWindowLongAHookStub = nullptr;
static User32SetWindowLongW sUser32SetWindowLongWHookStub = nullptr;
#endif
extern LRESULT CALLBACK
@ -1911,17 +1915,27 @@ PluginInstanceChild::HookSetWindowLongPtr()
return;
}
// Only pass through here once
if (sSetWindowLongHookSet) {
return;
}
sSetWindowLongHookSet = true;
sUser32Intercept.Init("user32.dll");
#ifdef _WIN64
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongPtrA",
&SetWindowLongPtrAHook);
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongPtrW",
&SetWindowLongPtrWHook);
if (!sUser32SetWindowLongAHookStub)
sUser32Intercept.AddHook("SetWindowLongPtrA", reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
(void**) &sUser32SetWindowLongAHookStub);
if (!sUser32SetWindowLongWHookStub)
sUser32Intercept.AddHook("SetWindowLongPtrW", reinterpret_cast<intptr_t>(SetWindowLongPtrWHook),
(void**) &sUser32SetWindowLongWHookStub);
#else
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongA",
&SetWindowLongAHook);
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongW",
&SetWindowLongWHook);
if (!sUser32SetWindowLongAHookStub)
sUser32Intercept.AddHook("SetWindowLongA", reinterpret_cast<intptr_t>(SetWindowLongAHook),
(void**) &sUser32SetWindowLongAHookStub);
if (!sUser32SetWindowLongWHookStub)
sUser32Intercept.AddHook("SetWindowLongW", reinterpret_cast<intptr_t>(SetWindowLongWHook),
(void**) &sUser32SetWindowLongWHookStub);
#endif
}
@ -1989,13 +2003,19 @@ PluginInstanceChild::InitPopupMenuHook()
return;
}
// Only pass through here once
if (sPopupMenuHookSet) {
return;
}
sPopupMenuHookSet = true;
// Note, once WindowsDllInterceptor is initialized for a module,
// it remains initialized for that particular module for it's
// lifetime. Additional instances are needed if other modules need
// to be hooked.
sUser32Intercept.Init("user32.dll");
sUser32TrackPopupMenuStub.Set(sUser32Intercept, "TrackPopupMenu",
&TrackPopupHookProc);
sUser32Intercept.AddHook("TrackPopupMenu", reinterpret_cast<intptr_t>(TrackPopupHookProc),
(void**) &sUser32TrackPopupMenuStub);
}
void
@ -2137,23 +2157,36 @@ PluginInstanceChild::InitImm32Hook()
return;
}
if (sImm32ImmGetContextStub) {
return;
}
// When using windowless plugin, IMM API won't work due ot OOP.
//
// ImmReleaseContext on Windows 7+ just returns TRUE only, so we don't
// need to hook this.
sImm32Intercept.Init("imm32.dll");
sImm32ImmGetContextStub.Set(sImm32Intercept, "ImmGetContext",
&ImmGetContextProc);
sImm32ImmGetCompositionStringStub.Set(sImm32Intercept,
"ImmGetCompositionStringW",
&ImmGetCompositionStringProc);
sImm32ImmSetCandidateWindowStub.Set(sImm32Intercept,
"ImmSetCandidateWindow",
&ImmSetCandidateWindowProc);
sImm32ImmNotifyIME.Set(sImm32Intercept, "ImmNotifyIME", &ImmNotifyIME);
sImm32ImmAssociateContextExStub.Set(sImm32Intercept, "ImmAssociateContextEx",
&ImmAssociateContextExProc);
sImm32Intercept.AddHook(
"ImmGetContext",
reinterpret_cast<intptr_t>(ImmGetContextProc),
(void**)&sImm32ImmGetContextStub);
sImm32Intercept.AddHook(
"ImmGetCompositionStringW",
reinterpret_cast<intptr_t>(ImmGetCompositionStringProc),
(void**)&sImm32ImmGetCompositionStringStub);
sImm32Intercept.AddHook(
"ImmSetCandidateWindow",
reinterpret_cast<intptr_t>(ImmSetCandidateWindowProc),
(void**)&sImm32ImmSetCandidateWindowStub);
sImm32Intercept.AddHook(
"ImmNotifyIME",
reinterpret_cast<intptr_t>(ImmNotifyIME),
(void**)&sImm32ImmNotifyIME);
sImm32Intercept.AddHook(
"ImmAssociateContextEx",
reinterpret_cast<intptr_t>(ImmAssociateContextExProc),
(void**)&sImm32ImmAssociateContextExStub);
}
void

View File

@ -90,14 +90,14 @@ printf_stderr(const char *fmt, ...)
typedef MOZ_NORETURN_PTR void (__fastcall* BaseThreadInitThunk_func)(BOOL aIsInitialThread, void* aStartAddress, void* aThreadParam);
static WindowsDllInterceptor::FuncHookType<BaseThreadInitThunk_func> stub_BaseThreadInitThunk;
static BaseThreadInitThunk_func stub_BaseThreadInitThunk = nullptr;
typedef NTSTATUS (NTAPI *LdrLoadDll_func) (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle);
static WindowsDllInterceptor::FuncHookType<LdrLoadDll_func> stub_LdrLoadDll;
static LdrLoadDll_func stub_LdrLoadDll;
#ifdef _M_AMD64
typedef decltype(RtlInstallFunctionTableCallback)* RtlInstallFunctionTableCallback_func;
static WindowsDllInterceptor::FuncHookType<RtlInstallFunctionTableCallback_func> stub_RtlInstallFunctionTableCallback;
static RtlInstallFunctionTableCallback_func stub_RtlInstallFunctionTableCallback;
extern uint8_t* sMsMpegJitCodeRegionStart;
extern size_t sMsMpegJitCodeRegionSize;
@ -662,8 +662,7 @@ DllBlocklist_Initialize(uint32_t aInitFlags)
// We specifically use a detour, because there are cases where external
// code also tries to hook LdrLoadDll, and doesn't know how to relocate our
// nop space patches. (Bug 951827)
bool ok = stub_LdrLoadDll.SetDetour(NtDllIntercept, "LdrLoadDll",
&patched_LdrLoadDll);
bool ok = NtDllIntercept.AddDetour("LdrLoadDll", reinterpret_cast<intptr_t>(patched_LdrLoadDll), (void**) &stub_LdrLoadDll);
if (!ok) {
sBlocklistInitFailed = true;
@ -684,18 +683,18 @@ DllBlocklist_Initialize(uint32_t aInitFlags)
#ifdef _M_AMD64
if (!IsWin8OrLater()) {
// The crash that this hook works around is only seen on Win7.
stub_RtlInstallFunctionTableCallback.Set(Kernel32Intercept,
"RtlInstallFunctionTableCallback",
&patched_RtlInstallFunctionTableCallback);
Kernel32Intercept.AddHook("RtlInstallFunctionTableCallback",
reinterpret_cast<intptr_t>(patched_RtlInstallFunctionTableCallback),
(void**)&stub_RtlInstallFunctionTableCallback);
}
#endif
// Bug 1361410: WRusr.dll will overwrite our hook and cause a crash.
// Workaround: If we detect WRusr.dll, don't hook.
if (!GetModuleHandleW(L"WRusr.dll")) {
if (!stub_BaseThreadInitThunk.SetDetour(Kernel32Intercept,
"BaseThreadInitThunk",
&patched_BaseThreadInitThunk)) {
if(!Kernel32Intercept.AddDetour("BaseThreadInitThunk",
reinterpret_cast<intptr_t>(patched_BaseThreadInitThunk),
(void**) &stub_BaseThreadInitThunk)) {
#ifdef DEBUG
printf_stderr("BaseThreadInitThunk hook failed\n");
#endif

View File

@ -8,12 +8,10 @@
#define NS_WINDOWS_DLL_INTERCEPTOR_H_
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Move.h"
#include "mozilla/Tuple.h"
#include "mozilla/NotNull.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/Types.h"
#include "mozilla/UniquePtr.h"
@ -84,143 +82,6 @@
namespace mozilla {
namespace interceptor {
template <typename InterceptorT, typename FuncPtrT>
class FuncHook final
{
template <typename T>
struct OriginalFunctionPtrTraits;
template <typename R, typename... Args>
struct OriginalFunctionPtrTraits<R (*)(Args...)>
{
using ReturnType = R;
};
#if defined(_M_IX86)
template <typename R, typename... Args>
struct OriginalFunctionPtrTraits<R (__stdcall*)(Args...)>
{
using ReturnType = R;
};
template <typename R, typename... Args>
struct OriginalFunctionPtrTraits<R (__fastcall*)(Args...)>
{
using ReturnType = R;
};
#endif // defined(_M_IX86)
public:
using ThisType = FuncHook<InterceptorT, FuncPtrT>;
using ReturnType = typename OriginalFunctionPtrTraits<FuncPtrT>::ReturnType;
constexpr FuncHook()
: mOrigFunc(nullptr)
, mInitOnce(INIT_ONCE_STATIC_INIT)
{
}
~FuncHook() = default;
bool Set(InterceptorT& aInterceptor, const char* aName,
FuncPtrT aHookDest)
{
LPVOID addHookOk;
InitOnceContext ctx(this, &aInterceptor, aName, aHookDest, false);
return ::InitOnceExecuteOnce(&mInitOnce, &InitOnceCallback, &ctx,
&addHookOk) && addHookOk;
}
bool SetDetour(InterceptorT& aInterceptor, const char* aName,
FuncPtrT aHookDest)
{
LPVOID addHookOk;
InitOnceContext ctx(this, &aInterceptor, aName, aHookDest, true);
return ::InitOnceExecuteOnce(&mInitOnce, &InitOnceCallback, &ctx,
&addHookOk) && addHookOk;
}
explicit operator bool() const
{
return !!mOrigFunc;
}
template <typename... ArgsType>
ReturnType operator()(ArgsType... aArgs) const
{
return mOrigFunc(std::forward<ArgsType>(aArgs)...);
}
FuncPtrT GetStub() const
{
return mOrigFunc;
}
// One-time init stuff cannot be moved or copied
FuncHook(const FuncHook&) = delete;
FuncHook(FuncHook&&) = delete;
FuncHook& operator=(const FuncHook&) = delete;
FuncHook& operator=(FuncHook&& aOther) = delete;
private:
struct MOZ_RAII InitOnceContext final
{
InitOnceContext(ThisType* aHook, InterceptorT* aInterceptor,
const char* aName, void* aHookDest, bool aForceDetour)
: mHook(aHook)
, mInterceptor(aInterceptor)
, mName(aName)
, mHookDest(aHookDest)
, mForceDetour(aForceDetour)
{
}
ThisType* mHook;
InterceptorT* mInterceptor;
const char* mName;
void* mHookDest;
bool mForceDetour;
};
private:
bool Apply(InterceptorT* aInterceptor, const char* aName, void* aHookDest)
{
return aInterceptor->AddHook(aName, reinterpret_cast<intptr_t>(aHookDest),
reinterpret_cast<void**>(&mOrigFunc));
}
bool ApplyDetour(InterceptorT* aInterceptor, const char* aName,
void* aHookDest)
{
return aInterceptor->AddDetour(aName, reinterpret_cast<intptr_t>(aHookDest),
reinterpret_cast<void**>(&mOrigFunc));
}
static BOOL CALLBACK
InitOnceCallback(PINIT_ONCE aInitOnce, PVOID aParam, PVOID* aOutContext)
{
MOZ_ASSERT(aOutContext);
bool result;
auto ctx = reinterpret_cast<InitOnceContext*>(aParam);
if (ctx->mForceDetour) {
result = ctx->mHook->ApplyDetour(ctx->mInterceptor, ctx->mName,
ctx->mHookDest);
} else {
result = ctx->mHook->Apply(ctx->mInterceptor, ctx->mName, ctx->mHookDest);
}
*aOutContext = result ? reinterpret_cast<PVOID>(1U << INIT_ONCE_CTX_RESERVED_BITS) : nullptr;
return TRUE;
}
private:
FuncPtrT mOrigFunc;
INIT_ONCE mInitOnce;
};
enum
{
kDefaultTrampolineSize = 128
@ -231,8 +92,6 @@ template <typename VMPolicy =
mozilla::interceptor::MMPolicyInProcess, kDefaultTrampolineSize>>
class WindowsDllInterceptor final
{
typedef WindowsDllInterceptor<VMPolicy> ThisType;
interceptor::WindowsDllDetourPatcher<VMPolicy> mDetourPatcher;
#if defined(_M_IX86)
interceptor::WindowsDllNopSpacePatcher<typename VMPolicy::MMPolicyT> mNopSpacePatcher;
@ -301,7 +160,6 @@ public:
// NB: We intentionally leak mModule
}
private:
/**
* Hook/detour the method aName from the DLL we set in Init so that it calls
* aHookDest instead. Returns the original method pointer in aOrigFunc
@ -361,6 +219,7 @@ private:
return AddDetour(proc, aHookDest, aOrigFunc);
}
private:
bool AddDetour(FARPROC aProc, intptr_t aHookDest, void** aOrigFunc)
{
MOZ_ASSERT(mModule && aProc);
@ -371,14 +230,6 @@ private:
return mDetourPatcher.AddHook(aProc, aHookDest, aOrigFunc);
}
public:
template <typename FuncPtrT>
using FuncHookType = FuncHook<ThisType, FuncPtrT>;
private:
template <typename InterceptorT, typename FuncPtrT>
friend class FuncHook;
};
} // namespace interceptor

View File

@ -10,33 +10,10 @@
#include <wininet.h>
#include <schnlsp.h>
#include "mozilla/TypeTraits.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WindowsVersion.h"
#include "nsWindowsDllInterceptor.h"
#include "nsWindowsHelpers.h"
NTSTATUS NTAPI NtFlushBuffersFile(HANDLE, PIO_STATUS_BLOCK);
NTSTATUS NTAPI NtReadFile(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, PVOID, ULONG,
PLARGE_INTEGER, PULONG);
NTSTATUS NTAPI NtReadFileScatter(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
PLARGE_INTEGER, PULONG);
NTSTATUS NTAPI NtWriteFile(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, PVOID, ULONG,
PLARGE_INTEGER, PULONG);
NTSTATUS NTAPI NtWriteFileGather(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
PLARGE_INTEGER, PULONG);
NTSTATUS NTAPI NtQueryFullAttributesFile(POBJECT_ATTRIBUTES, PVOID);
NTSTATUS NTAPI LdrLoadDll(PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle);
NTSTATUS NTAPI LdrUnloadDll(HMODULE);
// These pointers are disguised as PVOID to avoid pulling in obscure headers
PVOID NTAPI LdrResolveDelayLoadedAPI(PVOID, PVOID, PVOID, PVOID, PVOID, ULONG);
void CALLBACK ProcessCaretEvents(HWINEVENTHOOK, DWORD, HWND, LONG, LONG, DWORD, DWORD);
void __fastcall BaseThreadInitThunk(BOOL aIsInitialThread, void* aStartAddress, void* aThreadParam);
using namespace mozilla;
struct payload {
@ -61,8 +38,7 @@ extern "C" __declspec(dllexport) __declspec(noinline) payload rotatePayload(payl
static bool patched_func_called = false;
static WindowsDllInterceptor::FuncHookType<decltype(&rotatePayload)>
orig_rotatePayload;
static payload (*orig_rotatePayload)(payload);
static payload
patched_rotatePayload(payload p)
@ -71,61 +47,11 @@ patched_rotatePayload(payload p)
return orig_rotatePayload(p);
}
// Invoke aFunc by taking aArg's contents and using them as aFunc's arguments
template <typename CallableT, typename... Args, typename ArgTuple = Tuple<Args...>, size_t... Indices>
decltype(auto) Apply(CallableT&& aFunc, ArgTuple&& aArgs, std::index_sequence<Indices...>)
typedef bool(*HookTestFunc)(void*);
bool CheckHook(HookTestFunc aHookTestFunc, void* aOrigFunc,
const char* aDllName, const char* aFuncName)
{
return std::forward<CallableT>(aFunc)(Get<Indices>(std::forward<ArgTuple>(aArgs))...);
}
template <typename CallableT>
bool TestFunction(CallableT aFunc);
#define DEFINE_TEST_FUNCTION(calling_convention) \
template <typename R, typename... Args, typename... TestArgs> \
bool TestFunction(WindowsDllInterceptor::FuncHookType<R (calling_convention *)(Args...)>&& aFunc, \
bool (* aPred)(R), TestArgs... aArgs) \
{ \
using FuncHookType = WindowsDllInterceptor::FuncHookType<R (calling_convention *)(Args...)>; \
using ArgTuple = Tuple<Args...>; \
using Indices = std::index_sequence_for<Args...>; \
ArgTuple fakeArgs{ std::forward<TestArgs>(aArgs)... }; \
return aPred(Apply(std::forward<FuncHookType>(aFunc), std::forward<ArgTuple>(fakeArgs), Indices())); \
} \
\
/* Specialization for functions returning void */ \
template <typename... Args, typename PredicateT, typename... TestArgs> \
bool TestFunction(WindowsDllInterceptor::FuncHookType<void (calling_convention *)(Args...)>&& aFunc, \
PredicateT&& aPred, TestArgs... aArgs) \
{ \
using FuncHookType = WindowsDllInterceptor::FuncHookType<void (calling_convention *)(Args...)>; \
using ArgTuple = Tuple<Args...>; \
using Indices = std::index_sequence_for<Args...>; \
ArgTuple fakeArgs{ std::forward<TestArgs>(aArgs)... }; \
Apply(std::forward<FuncHookType>(aFunc), std::forward<ArgTuple>(fakeArgs), Indices()); \
return true; \
}
// C++11 allows empty arguments to macros. clang works just fine. MSVC does the
// right thing, but it also throws up warning C4003.
#if defined(_MSC_VER) && !defined(__clang__)
DEFINE_TEST_FUNCTION(__cdecl)
#else
DEFINE_TEST_FUNCTION()
#endif
#ifdef _M_IX86
DEFINE_TEST_FUNCTION(__stdcall)
DEFINE_TEST_FUNCTION(__fastcall)
#endif // _M_IX86
// Test the hooked function against the supplied predicate
template <typename OrigFuncT, typename PredicateT, typename... Args>
bool CheckHook(WindowsDllInterceptor::FuncHookType<OrigFuncT> &aOrigFunc,
const char* aDllName, const char* aFuncName, PredicateT&& aPred,
Args... aArgs)
{
if (TestFunction(std::forward<WindowsDllInterceptor::FuncHookType<OrigFuncT>>(aOrigFunc), std::forward<PredicateT>(aPred), std::forward<Args>(aArgs)...)) {
if (aHookTestFunc(aOrigFunc)) {
printf("TEST-PASS | WindowsDllInterceptor | "
"Executed hooked function %s from %s\n", aFuncName, aDllName);
return true;
@ -135,235 +61,57 @@ bool CheckHook(WindowsDllInterceptor::FuncHookType<OrigFuncT> &aOrigFunc,
return false;
}
// Hook the function and optionally attempt calling it
template <typename OrigFuncT, size_t N, typename PredicateT, typename... Args>
bool TestHook(const char (&dll)[N], const char *func, PredicateT&& aPred, Args... aArgs)
template <size_t N>
bool TestHook(HookTestFunc funcTester, const char (&dll)[N], const char *func)
{
auto orig_func(mozilla::MakeUnique<WindowsDllInterceptor::FuncHookType<OrigFuncT>>());
void *orig_func;
bool successful = false;
{
WindowsDllInterceptor TestIntercept;
TestIntercept.Init(dll);
successful = orig_func->Set(TestIntercept, func, nullptr);
successful = TestIntercept.AddHook(func, 0, &orig_func);
}
if (successful) {
printf("TEST-PASS | WindowsDllInterceptor | Could hook %s from %s\n", func, dll);
if (!aPred) {
printf("TEST-SKIPPED | WindowsDllInterceptor | "
"Will not attempt to execute patched %s.\n", func);
return true;
}
return CheckHook(*orig_func, dll, func, std::forward<PredicateT>(aPred), std::forward<Args>(aArgs)...);
return CheckHook(funcTester, orig_func, dll, func);
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to hook %s from %s\n", func, dll);
return false;
}
}
// Detour the function and optionally attempt calling it
template <typename OrigFuncT, size_t N, typename PredicateT>
bool TestDetour(const char (&dll)[N], const char *func, PredicateT&& aPred)
template <size_t N>
bool TestDetour(const char (&dll)[N], const char *func)
{
auto orig_func(mozilla::MakeUnique<WindowsDllInterceptor::FuncHookType<OrigFuncT>>());
void *orig_func;
bool successful = false;
{
WindowsDllInterceptor TestIntercept;
TestIntercept.Init(dll);
successful = orig_func->SetDetour(TestIntercept, func, nullptr);
successful = TestIntercept.AddDetour(func, 0, &orig_func);
}
if (successful) {
printf("TEST-PASS | WindowsDllInterceptor | Could detour %s from %s\n", func, dll);
if (!aPred) {
printf("TEST-SKIPPED | WindowsDllInterceptor | "
"Will not attempt to execute patched %s.\n", func);
return true;
}
return CheckHook(*orig_func, dll, func, std::forward<PredicateT>(aPred));
return true;
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to detour %s from %s\n", func, dll);
return false;
}
}
// If a function pointer's type returns void*, this template converts that type
// to return uintptr_t instead, for the purposes of predicates.
template <typename FuncT>
struct SubstituteForVoidPtr
{
using Type = FuncT;
};
template <typename... Args>
struct SubstituteForVoidPtr<void* (*)(Args...)>
{
using Type = uintptr_t (*)(Args...);
};
#ifdef _M_IX86
template <typename... Args>
struct SubstituteForVoidPtr<void* (__stdcall*)(Args...)>
{
using Type = uintptr_t (__stdcall*)(Args...);
};
template <typename... Args>
struct SubstituteForVoidPtr<void* (__fastcall*)(Args...)>
{
using Type = uintptr_t (__fastcall*)(Args...);
};
#endif // _M_IX86
// Determines the function's return type
template <typename FuncT>
struct ReturnType;
template <typename R, typename... Args>
struct ReturnType<R (*)(Args...)>
{
using Type = R;
};
#ifdef _M_IX86
template <typename R, typename... Args>
struct ReturnType<R (__stdcall*)(Args...)>
{
using Type = R;
};
template <typename R, typename... Args>
struct ReturnType<R (__fastcall*)(Args...)>
{
using Type = R;
};
#endif // _M_IX86
// Predicates that may be supplied during tests
template <typename FuncT>
struct Predicates
{
using ArgType = typename ReturnType<FuncT>::Type;
template <ArgType CompVal>
static bool Equals(ArgType aValue)
{
return CompVal == aValue;
}
template <ArgType CompVal>
static bool NotEquals(ArgType aValue)
{
return CompVal != aValue;
}
template <ArgType CompVal>
static bool Ignore(ArgType aValue)
{
return true;
}
};
// Functions that return void should be ignored, so we specialize the
// Ignore predicate for that case. Use nullptr as the value to compare against.
template <typename... Args>
struct Predicates<void (*)(Args...)>
{
template <nullptr_t DummyVal>
static bool Ignore()
{
return true;
}
};
#ifdef _M_IX86
template <typename... Args>
struct Predicates<void (__stdcall*)(Args...)>
{
template <nullptr_t DummyVal>
static bool Ignore()
{
return true;
}
};
template <typename... Args>
struct Predicates<void (__fastcall*)(Args...)>
{
template <nullptr_t DummyVal>
static bool Ignore()
{
return true;
}
};
#endif // _M_IX86
// The standard test. Hook |func|, and then try executing it with all zero
// arguments, using |pred| and |comp| to determine whether the call successfully
// executed. In general, you want set pred and comp such that they return true
// when the function is returning whatever value is expected with all-zero
// arguments.
//
// Note: When |func| returns void, you must supply |Ignore| and |nullptr| as the
// |pred| and |comp| arguments, respectively.
#define TEST_HOOK(dll, func, pred, comp) \
TestHook<decltype(&func)>(#dll, #func, &Predicates<decltype(&func)>::pred<comp>)
// We need to special-case functions that return INVALID_HANDLE_VALUE
// (ie, CreateFile). Our template machinery for comparing values doesn't work
// with integer constants passed as pointers (well, it works on MSVC, but not
// clang, because that is not standard-compliant).
#define TEST_HOOK_FOR_INVALID_HANDLE_VALUE(dll, func) \
TestHook<SubstituteForVoidPtr<decltype(&func)>::Type>(#dll, #func, &Predicates<SubstituteForVoidPtr<decltype(&func)>::Type>::Equals<uintptr_t(-1)>)
// This variant allows you to explicitly supply arguments to the hooked function
// during testing. You want to provide arguments that produce the conditions that
// induce the function to return a value that is accepted by your predicate.
#define TEST_HOOK_PARAMS(dll, func, pred, comp, ...) \
TestHook<decltype(&func)>(#dll, #func, &Predicates<decltype(&func)>::pred<comp>, __VA_ARGS__)
// This is for cases when we want to hook |func|, but it is unsafe to attempt
// to execute the function in the context of a test.
#define TEST_HOOK_SKIP_EXEC(dll, func) \
TestHook<decltype(&func)>(#dll, #func, reinterpret_cast<bool (*)(typename ReturnType<decltype(&func)>::Type)>(NULL))
// The following three variants are identical to the previous macros,
// however the forcibly use a Detour on 32-bit Windows. On 64-bit Windows,
// these macros are identical to their TEST_HOOK variants.
#define TEST_DETOUR(dll, func, pred, comp) \
TestDetour<decltype(&func)>(#dll, #func, &Predicates<decltype(&func)>::pred<comp>)
#define TEST_DETOUR_PARAMS(dll, func, pred, comp, ...) \
TestDetour<decltype(&func)>(#dll, #func, &Predicates<decltype(&func)>::pred<comp>, __VA_ARGS__)
#define TEST_DETOUR_SKIP_EXEC(dll, func) \
TestDetour<decltype(&func)>(#dll, #func, reinterpret_cast<bool (*)(typename ReturnType<decltype(&func)>::Type)>(NULL))
template <typename OrigFuncT, size_t N, typename PredicateT, typename... Args>
bool MaybeTestHook(const bool cond, const char (&dll)[N], const char *func, PredicateT&& aPred, Args... aArgs)
template <size_t N>
bool MaybeTestHook(const bool cond, HookTestFunc funcTester, const char (&dll)[N], const char* func)
{
if (!cond) {
printf("TEST-SKIPPED | WindowsDllInterceptor | Skipped hook test for %s from %s\n", func, dll);
return true;
}
return TestHook<OrigFuncT>(dll, func, std::forward<PredicateT>(aPred), std::forward<Args>(aArgs)...);
return TestHook(funcTester, dll, func);
}
// Like TEST_HOOK, but the test is only executed when cond is true.
#define MAYBE_TEST_HOOK(cond, dll, func, pred, comp) \
MaybeTestHook<decltype(&func)>(cond, #dll, #func, &Predicates<decltype(&func)>::pred<comp>)
#define MAYBE_TEST_HOOK_PARAMS(cond, dll, func, pred, comp, ...) \
MaybeTestHook<decltype(&func)>(cond, #dll, #func, &Predicates<decltype(&func)>::pred<comp>, __VA_ARGS__)
#define MAYBE_TEST_HOOK_SKIP_EXEC(cond, dll, func) \
MaybeTestHook<decltype(&func)>(cond, #dll, #func, reinterpret_cast<bool (*)(typename ReturnType<decltype(&func)>::Type)>(NULL))
bool ShouldTestTipTsf()
{
if (!IsWin8OrLater()) {
@ -399,6 +147,455 @@ bool ShouldTestTipTsf()
return true;
}
// These test the patched function returned by the DLL
// interceptor. They check that the patched assembler preamble does
// something sane. The parameter is a pointer to the patched function.
bool TestGetWindowInfo(void* aFunc)
{
auto patchedGetWindowInfo =
reinterpret_cast<decltype(&GetWindowInfo)>(aFunc);
return patchedGetWindowInfo(0, 0) == FALSE;
}
bool TestSetWindowLongPtr(void* aFunc)
{
auto patchedSetWindowLongPtr =
reinterpret_cast<decltype(&SetWindowLongPtr)>(aFunc);
return patchedSetWindowLongPtr(0, 0, 0) == 0;
}
bool TestSetWindowLong(void* aFunc)
{
auto patchedSetWindowLong =
reinterpret_cast<decltype(&SetWindowLong)>(aFunc);
return patchedSetWindowLong(0, 0, 0) == 0;
}
bool TestTrackPopupMenu(void* aFunc)
{
auto patchedTrackPopupMenu =
reinterpret_cast<decltype(&TrackPopupMenu)>(aFunc);
return patchedTrackPopupMenu(0, 0, 0, 0, 0, 0, 0) == 0;
}
bool TestNtFlushBuffersFile(void* aFunc)
{
typedef NTSTATUS(WINAPI *NtFlushBuffersFileType)(HANDLE, PIO_STATUS_BLOCK);
auto patchedNtFlushBuffersFile =
reinterpret_cast<NtFlushBuffersFileType>(aFunc);
patchedNtFlushBuffersFile(0, 0);
return true;
}
bool TestNtCreateFile(void* aFunc)
{
auto patchedNtCreateFile =
reinterpret_cast<decltype(&NtCreateFile)>(aFunc);
return patchedNtCreateFile(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
}
bool TestNtReadFile(void* aFunc)
{
typedef NTSTATUS(WINAPI *NtReadFileType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, PVOID, ULONG,
PLARGE_INTEGER, PULONG);
auto patchedNtReadFile =
reinterpret_cast<NtReadFileType>(aFunc);
return patchedNtReadFile(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
}
bool TestNtReadFileScatter(void* aFunc)
{
typedef NTSTATUS(WINAPI *NtReadFileScatterType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
PLARGE_INTEGER, PULONG);
auto patchedNtReadFileScatter =
reinterpret_cast<NtReadFileScatterType>(aFunc);
return patchedNtReadFileScatter(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
}
bool TestNtWriteFile(void* aFunc)
{
typedef NTSTATUS(WINAPI *NtWriteFileType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, PVOID, ULONG,
PLARGE_INTEGER, PULONG);
auto patchedNtWriteFile =
reinterpret_cast<NtWriteFileType>(aFunc);
return patchedNtWriteFile(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
}
bool TestNtWriteFileGather(void* aFunc)
{
typedef NTSTATUS(WINAPI *NtWriteFileGatherType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
PLARGE_INTEGER, PULONG);
auto patchedNtWriteFileGather =
reinterpret_cast<NtWriteFileGatherType>(aFunc);
return patchedNtWriteFileGather(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
}
bool TestNtQueryFullAttributesFile(void* aFunc)
{
typedef NTSTATUS(WINAPI *NtQueryFullAttributesFileType)(POBJECT_ATTRIBUTES,
PVOID);
auto patchedNtQueryFullAttributesFile =
reinterpret_cast<NtQueryFullAttributesFileType>(aFunc);
return patchedNtQueryFullAttributesFile(0, 0) != 0;
}
bool TestLdrUnloadDll(void* aFunc)
{
typedef NTSTATUS (NTAPI *LdrUnloadDllType)(HMODULE);
auto patchedLdrUnloadDll = reinterpret_cast<LdrUnloadDllType>(aFunc);
return patchedLdrUnloadDll(0) != 0;
}
bool TestLdrResolveDelayLoadedAPI(void* aFunc)
{
// These pointers are disguised as PVOID to avoid pulling in obscure headers
typedef PVOID (WINAPI *LdrResolveDelayLoadedAPIType)(PVOID, PVOID, PVOID,
PVOID, PVOID, ULONG);
auto patchedLdrResolveDelayLoadedAPI =
reinterpret_cast<LdrResolveDelayLoadedAPIType>(aFunc);
// No idea how to call this API. Flags==99 is just an arbitrary number that
// doesn't crash when the other params are null.
return patchedLdrResolveDelayLoadedAPI(0, 0, 0, 0, 0, 99) == 0;
}
#ifdef _M_AMD64
bool TestRtlInstallFunctionTableCallback(void* aFunc)
{
auto patchedRtlInstallFunctionTableCallback =
reinterpret_cast<decltype(RtlInstallFunctionTableCallback)*>(aFunc);
return patchedRtlInstallFunctionTableCallback(0, 0, 0, 0, 0, 0) == FALSE;
}
#endif
bool TestSetUnhandledExceptionFilter(void* aFunc)
{
auto patchedSetUnhandledExceptionFilter =
reinterpret_cast<decltype(&SetUnhandledExceptionFilter)>(aFunc);
// Retrieve the current filter as we set the new filter to null, then restore the current filter.
LPTOP_LEVEL_EXCEPTION_FILTER current = patchedSetUnhandledExceptionFilter(0);
patchedSetUnhandledExceptionFilter(current);
return true;
}
bool TestVirtualAlloc(void* aFunc)
{
auto patchedVirtualAlloc =
reinterpret_cast<decltype(&VirtualAlloc)>(aFunc);
return patchedVirtualAlloc(0, 0, 0, 0) == 0;
}
bool TestMapViewOfFile(void* aFunc)
{
auto patchedMapViewOfFile =
reinterpret_cast<decltype(&MapViewOfFile)>(aFunc);
return patchedMapViewOfFile(0, 0, 0, 0, 0) == 0;
}
bool TestCreateDIBSection(void* aFunc)
{
auto patchedCreateDIBSection =
reinterpret_cast<decltype(&CreateDIBSection)>(aFunc);
// MSDN is wrong here. This does not return ERROR_INVALID_PARAMETER. It
// sets the value of GetLastError to ERROR_INVALID_PARAMETER.
// CreateDIBSection returns 0 on error.
return patchedCreateDIBSection(0, 0, 0, 0, 0, 0) == 0;
}
bool TestCreateFileW(void* aFunc)
{
auto patchedCreateFileW =
reinterpret_cast<decltype(&CreateFileW)>(aFunc);
return patchedCreateFileW(0, 0, 0, 0, 0, 0, 0) == INVALID_HANDLE_VALUE;
}
bool TestCreateFileA(void* aFunc)
{
auto patchedCreateFileA =
reinterpret_cast<decltype(&CreateFileA)>(aFunc);
// return patchedCreateFileA(0, 0, 0, 0, 0, 0, 0) == INVALID_HANDLE_VALUE;
printf("TEST-SKIPPED | WindowsDllInterceptor | "
"Will not attempt to execute patched CreateFileA -- patched method is known to fail.\n");
return true;
}
bool TestQueryDosDeviceW(void* aFunc)
{
auto patchedQueryDosDeviceW =
reinterpret_cast<decltype(&QueryDosDeviceW)>(aFunc);
return patchedQueryDosDeviceW(nullptr, nullptr, 0) == 0;
}
bool TestInSendMessageEx(void* aFunc)
{
auto patchedInSendMessageEx =
reinterpret_cast<decltype(&InSendMessageEx)>(aFunc);
patchedInSendMessageEx(0);
return true;
}
bool TestImmGetContext(void* aFunc)
{
auto patchedImmGetContext =
reinterpret_cast<decltype(&ImmGetContext)>(aFunc);
patchedImmGetContext(0);
return true;
}
bool TestImmGetCompositionStringW(void* aFunc)
{
auto patchedImmGetCompositionStringW =
reinterpret_cast<decltype(&ImmGetCompositionStringW)>(aFunc);
patchedImmGetCompositionStringW(0, 0, 0, 0);
return true;
}
bool TestImmSetCandidateWindow(void* aFunc)
{
auto patchedImmSetCandidateWindow =
reinterpret_cast<decltype(&ImmSetCandidateWindow)>(aFunc);
// return patchedImmSetCandidateWindow(0, 0) == 0;
// ImmSetCandidateWindow crashes if given bad parameters.
printf("TEST-SKIPPED | WindowsDllInterceptor | "
"Will not attempt to execute patched ImmSetCandidateWindow.\n");
return true;
}
bool TestImmNotifyIME(void* aFunc)
{
auto patchedImmNotifyIME =
reinterpret_cast<decltype(&ImmNotifyIME)>(aFunc);
return patchedImmNotifyIME(0, 0, 0, 0) == 0;
}
bool TestGetSaveFileNameW(void* aFunc)
{
auto patchedGetSaveFileNameWType =
reinterpret_cast<decltype(&GetSaveFileNameW)>(aFunc);
patchedGetSaveFileNameWType(0);
return true;
}
bool TestGetOpenFileNameW(void* aFunc)
{
auto patchedGetOpenFileNameWType =
reinterpret_cast<decltype(&GetOpenFileNameW)>(aFunc);
patchedGetOpenFileNameWType(0);
return true;
}
bool TestGetKeyState(void* aFunc)
{
auto patchedGetKeyState =
reinterpret_cast<decltype(&GetKeyState)>(aFunc);
patchedGetKeyState(0);
return true;
}
bool TestSendMessageTimeoutW(void* aFunc)
{
auto patchedSendMessageTimeoutW =
reinterpret_cast<decltype(&SendMessageTimeoutW)>(aFunc);
return patchedSendMessageTimeoutW(0, 0, 0, 0, 0, 0, 0) == 0;
}
bool TestProcessCaretEvents(void* aFunc)
{
auto patchedProcessCaretEvents =
reinterpret_cast<WINEVENTPROC>(aFunc);
patchedProcessCaretEvents(0, 0, 0, 0, 0, 0, 0);
return true;
}
bool TestSetCursorPos(void* aFunc)
{
// SetCursorPos has some issues in automation -- see bug 1368033.
// For that reason, we don't check the return value -- we only
// check that the method runs without producing an exception.
auto patchedSetCursorPos =
reinterpret_cast<decltype(&SetCursorPos)>(aFunc);
patchedSetCursorPos(512, 512);
return true;
}
static DWORD sTlsIndex = 0;
bool TestTlsAlloc(void* aFunc)
{
auto patchedTlsAlloc =
reinterpret_cast<decltype(&TlsAlloc)>(aFunc);
sTlsIndex = patchedTlsAlloc();
return sTlsIndex != TLS_OUT_OF_INDEXES;
}
bool TestTlsFree(void* aFunc)
{
auto patchedTlsFree =
reinterpret_cast<decltype(&TlsFree)>(aFunc);
return sTlsIndex != 0 && patchedTlsFree(sTlsIndex);
}
bool TestCloseHandle(void* aFunc)
{
auto patchedCloseHandle =
reinterpret_cast<decltype(&CloseHandle)>(aFunc);
return patchedCloseHandle(0) == FALSE;
}
bool TestDuplicateHandle(void* aFunc)
{
auto patchedDuplicateHandle =
reinterpret_cast<decltype(&DuplicateHandle)>(aFunc);
return patchedDuplicateHandle(0, 0, 0, 0, 0, 0, 0) == FALSE;
}
bool TestPrintDlgW(void* aFunc)
{
auto patchedPrintDlgW =
reinterpret_cast<decltype(&PrintDlgW)>(aFunc);
patchedPrintDlgW(0);
return true;
}
bool TestInternetConnectA(void* aFunc)
{
auto patchedInternetConnectA =
reinterpret_cast<decltype(&InternetConnectA)>(aFunc);
return patchedInternetConnectA(0, 0, 0, 0, 0, 0, 0, 0) == 0;
}
HINTERNET sInternet = 0;
bool TestInternetOpenA(void* aFunc)
{
auto patchedInternetOpenA =
reinterpret_cast<decltype(&InternetOpenA)>(aFunc);
sInternet = patchedInternetOpenA(0, 0, 0, 0, 0);
return sInternet != 0;
}
bool TestInternetCloseHandle(void* aFunc)
{
auto patchedInternetCloseHandle =
reinterpret_cast<decltype(&InternetCloseHandle)>(aFunc);
return patchedInternetCloseHandle(sInternet);
}
bool TestInternetQueryDataAvailable(void* aFunc)
{
auto patchedInternetQueryDataAvailable =
reinterpret_cast<decltype(&InternetQueryDataAvailable)>(aFunc);
return patchedInternetQueryDataAvailable(0, 0, 0, 0) == FALSE;
}
bool TestInternetReadFile(void* aFunc)
{
auto patchedInternetReadFile =
reinterpret_cast<decltype(&InternetReadFile)>(aFunc);
return patchedInternetReadFile(0, 0, 0, 0) == FALSE;
}
bool TestInternetWriteFile(void* aFunc)
{
auto patchedInternetWriteFile =
reinterpret_cast<decltype(&InternetWriteFile)>(aFunc);
return patchedInternetWriteFile(0, 0, 0, 0) == FALSE;
}
bool TestInternetSetOptionA(void* aFunc)
{
auto patchedInternetSetOptionA =
reinterpret_cast<decltype(&InternetSetOptionA)>(aFunc);
return patchedInternetSetOptionA(0, 0, 0, 0) == FALSE;
}
bool TestHttpAddRequestHeadersA(void* aFunc)
{
auto patchedHttpAddRequestHeadersA =
reinterpret_cast<decltype(&HttpAddRequestHeadersA)>(aFunc);
return patchedHttpAddRequestHeadersA(0, 0, 0, 0) == FALSE;
}
bool TestHttpOpenRequestA(void* aFunc)
{
auto patchedHttpOpenRequestA =
reinterpret_cast<decltype(&HttpOpenRequestA)>(aFunc);
return patchedHttpOpenRequestA(0, 0, 0, 0, 0, 0, 0, 0) == 0;
}
bool TestHttpQueryInfoA(void* aFunc)
{
auto patchedHttpQueryInfoA =
reinterpret_cast<decltype(&HttpQueryInfoA)>(aFunc);
return patchedHttpQueryInfoA(0, 0, 0, 0, 0) == FALSE;
}
bool TestHttpSendRequestA(void* aFunc)
{
auto patchedHttpSendRequestA =
reinterpret_cast<decltype(&HttpSendRequestA)>(aFunc);
return patchedHttpSendRequestA(0, 0, 0, 0, 0) == FALSE;
}
bool TestHttpSendRequestExA(void* aFunc)
{
auto patchedHttpSendRequestExA =
reinterpret_cast<decltype(&HttpSendRequestExA)>(aFunc);
return patchedHttpSendRequestExA(0, 0, 0, 0, 0) == FALSE;
}
bool TestHttpEndRequestA(void* aFunc)
{
auto patchedHttpEndRequestA =
reinterpret_cast<decltype(&HttpEndRequestA)>(aFunc);
return patchedHttpEndRequestA(0, 0, 0, 0) == FALSE;
}
bool TestInternetQueryOptionA(void* aFunc)
{
auto patchedInternetQueryOptionA =
reinterpret_cast<decltype(&InternetQueryOptionA)>(aFunc);
return patchedInternetQueryOptionA(0, 0, 0, 0) == FALSE;
}
bool TestInternetErrorDlg(void* aFunc)
{
auto patchedInternetErrorDlg =
reinterpret_cast<decltype(&InternetErrorDlg)>(aFunc);
return patchedInternetErrorDlg(0, 0, 0, 0, 0) == ERROR_INVALID_HANDLE;
}
CredHandle sCredHandle;
bool TestAcquireCredentialsHandleA(void* aFunc)
{
auto patchedAcquireCredentialsHandleA =
reinterpret_cast<decltype(&AcquireCredentialsHandleA)>(aFunc);
SCHANNEL_CRED cred;
memset(&cred, 0, sizeof(cred));
cred.dwVersion = SCHANNEL_CRED_VERSION;
return patchedAcquireCredentialsHandleA(0, UNISP_NAME, SECPKG_CRED_OUTBOUND,
0, &cred, 0, 0, &sCredHandle, 0) == S_OK;
}
bool TestQueryCredentialsAttributesA(void* aFunc)
{
auto patchedQueryCredentialsAttributesA =
reinterpret_cast<decltype(&QueryCredentialsAttributesA)>(aFunc);
return patchedQueryCredentialsAttributesA(&sCredHandle, 0, 0) == SEC_E_UNSUPPORTED_FUNCTION;
}
bool TestFreeCredentialsHandle(void* aFunc)
{
auto patchedFreeCredentialsHandle =
reinterpret_cast<decltype(&FreeCredentialsHandle)>(aFunc);
return patchedFreeCredentialsHandle(&sCredHandle) == S_OK;
}
int main()
{
LARGE_INTEGER start;
@ -418,7 +615,7 @@ int main()
{
WindowsDllInterceptor ExeIntercept;
ExeIntercept.Init("TestDllInterceptor.exe");
if (orig_rotatePayload.Set(ExeIntercept, "rotatePayload", &patched_rotatePayload)) {
if (ExeIntercept.AddHook("rotatePayload", reinterpret_cast<intptr_t>(patched_rotatePayload), (void**) &orig_rotatePayload)) {
printf("TEST-PASS | WindowsDllInterceptor | Hook added\n");
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to add hook\n");
@ -462,85 +659,85 @@ int main()
}
#endif
if (TEST_HOOK(user32.dll, GetWindowInfo, Equals, FALSE) &&
if (TestHook(TestGetWindowInfo, "user32.dll", "GetWindowInfo") &&
#ifdef _WIN64
TEST_HOOK(user32.dll, SetWindowLongPtrA, Equals, 0) &&
TEST_HOOK(user32.dll, SetWindowLongPtrW, Equals, 0) &&
TestHook(TestSetWindowLongPtr, "user32.dll", "SetWindowLongPtrA") &&
TestHook(TestSetWindowLongPtr, "user32.dll", "SetWindowLongPtrW") &&
#else
TEST_HOOK(user32.dll, SetWindowLongA, Equals, 0) &&
TEST_HOOK(user32.dll, SetWindowLongW, Equals, 0) &&
TestHook(TestSetWindowLong, "user32.dll", "SetWindowLongA") &&
TestHook(TestSetWindowLong, "user32.dll", "SetWindowLongW") &&
#endif
TEST_HOOK(user32.dll, TrackPopupMenu, Equals, FALSE) &&
TestHook(TestTrackPopupMenu, "user32.dll", "TrackPopupMenu") &&
#ifdef _M_IX86
// We keep this test to hook complex code on x86. (Bug 850957)
TEST_HOOK(ntdll.dll, NtFlushBuffersFile, NotEquals, 0) &&
TestHook(TestNtFlushBuffersFile, "ntdll.dll", "NtFlushBuffersFile") &&
#endif
TEST_HOOK(ntdll.dll, NtCreateFile, NotEquals, 0) &&
TEST_HOOK(ntdll.dll, NtReadFile, NotEquals, 0) &&
TEST_HOOK(ntdll.dll, NtReadFileScatter, NotEquals, 0) &&
TEST_HOOK(ntdll.dll, NtWriteFile, NotEquals, 0) &&
TEST_HOOK(ntdll.dll, NtWriteFileGather, NotEquals, 0) &&
TEST_HOOK(ntdll.dll, NtQueryFullAttributesFile, NotEquals, 0) &&
TestHook(TestNtCreateFile, "ntdll.dll", "NtCreateFile") &&
TestHook(TestNtReadFile, "ntdll.dll", "NtReadFile") &&
TestHook(TestNtReadFileScatter, "ntdll.dll", "NtReadFileScatter") &&
TestHook(TestNtWriteFile, "ntdll.dll", "NtWriteFile") &&
TestHook(TestNtWriteFileGather, "ntdll.dll", "NtWriteFileGather") &&
TestHook(TestNtQueryFullAttributesFile, "ntdll.dll", "NtQueryFullAttributesFile") &&
#ifndef MOZ_ASAN
// Bug 733892: toolkit/crashreporter/nsExceptionHandler.cpp
// This fails on ASan because the ASan runtime already hooked this function
TEST_HOOK(kernel32.dll, SetUnhandledExceptionFilter, Ignore, nullptr) &&
TestHook(TestSetUnhandledExceptionFilter, "kernel32.dll", "SetUnhandledExceptionFilter") &&
#endif
#ifdef _M_IX86
// Bug 670967: xpcom/base/AvailableMemoryTracker.cpp
TEST_HOOK(kernel32.dll, VirtualAlloc, Equals, nullptr) &&
TEST_HOOK(kernel32.dll, MapViewOfFile, Equals, nullptr) &&
TEST_HOOK(gdi32.dll, CreateDIBSection, Equals, nullptr) &&
TEST_HOOK_FOR_INVALID_HANDLE_VALUE(kernel32.dll, CreateFileW) &&
TestHook(TestVirtualAlloc, "kernel32.dll", "VirtualAlloc") &&
TestHook(TestMapViewOfFile, "kernel32.dll", "MapViewOfFile") &&
TestHook(TestCreateDIBSection, "gdi32.dll", "CreateDIBSection") &&
TestHook(TestCreateFileW, "kernel32.dll", "CreateFileW") && // see Bug 1316415
#endif
TEST_HOOK_FOR_INVALID_HANDLE_VALUE(kernel32.dll, CreateFileA) &&
TEST_HOOK(kernelbase.dll, QueryDosDeviceW, Equals, 0) &&
TEST_DETOUR(user32.dll, CreateWindowExW, Equals, nullptr) &&
TEST_HOOK(user32.dll, InSendMessageEx, Equals, ISMEX_NOSEND) &&
TEST_HOOK(imm32.dll, ImmGetContext, Equals, nullptr) &&
TEST_HOOK(imm32.dll, ImmGetCompositionStringW, Ignore, 0) &&
TEST_HOOK_SKIP_EXEC(imm32.dll, ImmSetCandidateWindow) &&
TEST_HOOK(imm32.dll, ImmNotifyIME, Equals, 0) &&
TEST_HOOK(comdlg32.dll, GetSaveFileNameW, Ignore, FALSE) &&
TEST_HOOK(comdlg32.dll, GetOpenFileNameW, Ignore, FALSE) &&
TestHook(TestCreateFileA, "kernel32.dll", "CreateFileA") &&
TestHook(TestQueryDosDeviceW, "kernelbase.dll", "QueryDosDeviceW") &&
TestDetour("user32.dll", "CreateWindowExW") &&
TestHook(TestInSendMessageEx, "user32.dll", "InSendMessageEx") &&
TestHook(TestImmGetContext, "imm32.dll", "ImmGetContext") &&
TestHook(TestImmGetCompositionStringW, "imm32.dll", "ImmGetCompositionStringW") &&
TestHook(TestImmSetCandidateWindow, "imm32.dll", "ImmSetCandidateWindow") &&
TestHook(TestImmNotifyIME, "imm32.dll", "ImmNotifyIME") &&
TestHook(TestGetSaveFileNameW, "comdlg32.dll", "GetSaveFileNameW") &&
TestHook(TestGetOpenFileNameW, "comdlg32.dll", "GetOpenFileNameW") &&
#ifdef _M_X64
TEST_HOOK(user32.dll, GetKeyState, Ignore, 0) && // see Bug 1316415
TEST_HOOK(ntdll.dll, LdrUnloadDll, NotEquals, 0) &&
MAYBE_TEST_HOOK_SKIP_EXEC(IsWin8OrLater(), ntdll.dll, LdrResolveDelayLoadedAPI) &&
MAYBE_TEST_HOOK(!IsWin8OrLater(), kernel32.dll, RtlInstallFunctionTableCallback, Equals, FALSE) &&
TEST_HOOK(comdlg32.dll, PrintDlgW, Ignore, 0) &&
TestHook(TestGetKeyState, "user32.dll", "GetKeyState") && // see Bug 1316415
TestHook(TestLdrUnloadDll, "ntdll.dll", "LdrUnloadDll") &&
MaybeTestHook(IsWin8OrLater(), TestLdrResolveDelayLoadedAPI, "ntdll.dll", "LdrResolveDelayLoadedAPI") &&
MaybeTestHook(!IsWin8OrLater(), TestRtlInstallFunctionTableCallback, "kernel32.dll", "RtlInstallFunctionTableCallback") &&
TestHook(TestPrintDlgW, "comdlg32.dll", "PrintDlgW") &&
#endif
MAYBE_TEST_HOOK(ShouldTestTipTsf(), tiptsf.dll, ProcessCaretEvents, Ignore, nullptr) &&
MaybeTestHook(ShouldTestTipTsf(), TestProcessCaretEvents, "tiptsf.dll", "ProcessCaretEvents") &&
#ifdef _M_IX86
TEST_HOOK(user32.dll, SendMessageTimeoutW, Equals, 0) &&
TestHook(TestSendMessageTimeoutW, "user32.dll", "SendMessageTimeoutW") &&
#endif
TEST_HOOK(user32.dll, SetCursorPos, NotEquals, FALSE) &&
TEST_HOOK(kernel32.dll, TlsAlloc, NotEquals, TLS_OUT_OF_INDEXES) &&
TEST_HOOK_PARAMS(kernel32.dll, TlsFree, Equals, FALSE, TLS_OUT_OF_INDEXES) &&
TEST_HOOK(kernel32.dll, CloseHandle, Equals, FALSE) &&
TEST_HOOK(kernel32.dll, DuplicateHandle, Equals, FALSE) &&
TestHook(TestSetCursorPos, "user32.dll", "SetCursorPos") &&
TestHook(TestTlsAlloc, "kernel32.dll", "TlsAlloc") &&
TestHook(TestTlsFree, "kernel32.dll", "TlsFree") &&
TestHook(TestCloseHandle, "kernel32.dll", "CloseHandle") &&
TestHook(TestDuplicateHandle, "kernel32.dll", "DuplicateHandle") &&
TEST_HOOK(wininet.dll, InternetOpenA, NotEquals, nullptr) &&
TEST_HOOK(wininet.dll, InternetCloseHandle, Equals, FALSE) &&
TEST_HOOK(wininet.dll, InternetConnectA, Equals, nullptr) &&
TEST_HOOK(wininet.dll, InternetQueryDataAvailable, Equals, FALSE) &&
TEST_HOOK(wininet.dll, InternetReadFile, Equals, FALSE) &&
TEST_HOOK(wininet.dll, InternetWriteFile, Equals, FALSE) &&
TEST_HOOK(wininet.dll, InternetSetOptionA, Equals, FALSE) &&
TEST_HOOK(wininet.dll, HttpAddRequestHeadersA, Equals, FALSE) &&
TEST_HOOK(wininet.dll, HttpOpenRequestA, Equals, nullptr) &&
TEST_HOOK(wininet.dll, HttpQueryInfoA, Equals, FALSE) &&
TEST_HOOK(wininet.dll, HttpSendRequestA, Equals, FALSE) &&
TEST_HOOK(wininet.dll, HttpSendRequestExA, Equals, FALSE) &&
TEST_HOOK(wininet.dll, HttpEndRequestA, Equals, FALSE) &&
TEST_HOOK(wininet.dll, InternetQueryOptionA, Equals, FALSE) &&
TestHook(TestInternetOpenA, "wininet.dll", "InternetOpenA") &&
TestHook(TestInternetCloseHandle, "wininet.dll", "InternetCloseHandle") &&
TestHook(TestInternetConnectA, "wininet.dll", "InternetConnectA") &&
TestHook(TestInternetQueryDataAvailable, "wininet.dll", "InternetQueryDataAvailable") &&
TestHook(TestInternetReadFile, "wininet.dll", "InternetReadFile") &&
TestHook(TestInternetWriteFile, "wininet.dll", "InternetWriteFile") &&
TestHook(TestInternetSetOptionA, "wininet.dll", "InternetSetOptionA") &&
TestHook(TestHttpAddRequestHeadersA, "wininet.dll", "HttpAddRequestHeadersA") &&
TestHook(TestHttpOpenRequestA, "wininet.dll", "HttpOpenRequestA") &&
TestHook(TestHttpQueryInfoA, "wininet.dll", "HttpQueryInfoA") &&
TestHook(TestHttpSendRequestA, "wininet.dll", "HttpSendRequestA") &&
TestHook(TestHttpSendRequestExA, "wininet.dll", "HttpSendRequestExA") &&
TestHook(TestHttpEndRequestA, "wininet.dll", "HttpEndRequestA") &&
TestHook(TestInternetQueryOptionA, "wininet.dll", "InternetQueryOptionA") &&
TEST_HOOK(sspicli.dll, AcquireCredentialsHandleA, NotEquals, SEC_E_OK) &&
TEST_HOOK(sspicli.dll, QueryCredentialsAttributesA, NotEquals, SEC_E_OK) &&
TEST_HOOK(sspicli.dll, FreeCredentialsHandle, NotEquals, SEC_E_OK) &&
TestHook(TestAcquireCredentialsHandleA, "sspicli.dll", "AcquireCredentialsHandleA") &&
TestHook(TestQueryCredentialsAttributesA, "sspicli.dll", "QueryCredentialsAttributesA") &&
TestHook(TestFreeCredentialsHandle, "sspicli.dll", "FreeCredentialsHandle") &&
TEST_DETOUR_SKIP_EXEC(kernel32.dll, BaseThreadInitThunk) &&
TEST_DETOUR_SKIP_EXEC(ntdll.dll, LdrLoadDll)) {
TestDetour("kernel32.dll", "BaseThreadInitThunk") &&
TestDetour("ntdll.dll", "LdrLoadDll")) {
printf("TEST-PASS | WindowsDllInterceptor | all checks passed\n");
LARGE_INTEGER end, freq;

View File

@ -11,19 +11,19 @@
using std::wstring;
static void* gOrigReturnResult;
extern "C" __declspec(dllexport) int
ReturnResult()
{
return 2;
}
static mozilla::CrossProcessDllInterceptor::FuncHookType<decltype(&ReturnResult)>
gOrigReturnResult;
static int
ReturnResultHook()
{
if (gOrigReturnResult() != 2) {
auto origFn = reinterpret_cast<decltype(&ReturnResult)>(gOrigReturnResult);
if (origFn() != 2) {
return 3;
}
@ -73,7 +73,9 @@ int ParentMain()
mozilla::CrossProcessDllInterceptor intcpt(childProcess.get());
intcpt.Init("TestDllInterceptorCrossProcess.exe");
if (!gOrigReturnResult.Set(intcpt, "ReturnResult", &ReturnResultHook)) {
if (!intcpt.AddHook("ReturnResult",
reinterpret_cast<intptr_t>(&ReturnResultHook),
&gOrigReturnResult)) {
printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Failed to add hook\n");
return 1;
}

View File

@ -15,7 +15,7 @@ namespace mozilla {
namespace sandboxing {
typedef BOOL(WINAPI* CloseHandle_func) (HANDLE hObject);
static WindowsDllInterceptor::FuncHookType<CloseHandle_func> stub_CloseHandle;
static CloseHandle_func stub_CloseHandle = nullptr;
typedef BOOL(WINAPI* DuplicateHandle_func)(HANDLE hSourceProcessHandle,
HANDLE hSourceHandle,
@ -24,8 +24,7 @@ typedef BOOL(WINAPI* DuplicateHandle_func)(HANDLE hSourceProcessHandle,
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwOptions);
static WindowsDllInterceptor::FuncHookType<DuplicateHandle_func>
stub_DuplicateHandle;
static DuplicateHandle_func stub_DuplicateHandle = nullptr;
static BOOL WINAPI
patched_CloseHandle(HANDLE hObject)
@ -63,14 +62,17 @@ EnableHandleCloseMonitoring()
{
Kernel32Intercept.Init("kernel32.dll");
bool hooked =
stub_CloseHandle.Set(Kernel32Intercept, "CloseHandle", &patched_CloseHandle);
Kernel32Intercept.AddHook("CloseHandle",
reinterpret_cast<intptr_t>(patched_CloseHandle),
(void**)&stub_CloseHandle);
if (!hooked) {
return false;
}
hooked =
stub_DuplicateHandle.Set(Kernel32Intercept, "DuplicateHandle",
&patched_DuplicateHandle);
Kernel32Intercept.AddHook("DuplicateHandle",
reinterpret_cast<intptr_t>(patched_DuplicateHandle),
(void**)&stub_DuplicateHandle);
if (!hooked) {
return false;
}

View File

@ -338,8 +338,7 @@ nsTArray<nsAutoPtr<DelayedNote> >* gDelayedAnnotations;
// reporter is loaded instead (in case it became unloaded somehow)
typedef LPTOP_LEVEL_EXCEPTION_FILTER (WINAPI *SetUnhandledExceptionFilter_func)
(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
static WindowsDllInterceptor::FuncHookType<SetUnhandledExceptionFilter_func>
stub_SetUnhandledExceptionFilter;
static SetUnhandledExceptionFilter_func stub_SetUnhandledExceptionFilter = 0;
static LPTOP_LEVEL_EXCEPTION_FILTER previousUnhandledExceptionFilter = nullptr;
static WindowsDllInterceptor gKernel32Intercept;
static bool gBlockUnhandledExceptionFilter = true;
@ -1640,9 +1639,9 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory,
// protect the crash reporter from being unloaded
gBlockUnhandledExceptionFilter = true;
gKernel32Intercept.Init("kernel32.dll");
bool ok = stub_SetUnhandledExceptionFilter.Set(gKernel32Intercept,
"SetUnhandledExceptionFilter",
&patched_SetUnhandledExceptionFilter);
bool ok = gKernel32Intercept.AddHook("SetUnhandledExceptionFilter",
reinterpret_cast<intptr_t>(patched_SetUnhandledExceptionFilter),
(void**) &stub_SetUnhandledExceptionFilter);
#ifdef DEBUG
if (!ok)

View File

@ -303,8 +303,7 @@ Registers::SyncPopulate()
static WindowsDllInterceptor NtDllIntercept;
typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module);
static WindowsDllInterceptor::FuncHookType<LdrUnloadDll_func>
stub_LdrUnloadDll;
static LdrUnloadDll_func stub_LdrUnloadDll;
static NTSTATUS NTAPI
patched_LdrUnloadDll(HMODULE module)
@ -319,8 +318,7 @@ patched_LdrUnloadDll(HMODULE module)
typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
PVOID ThunkAddress, ULONG Flags);
static WindowsDllInterceptor::FuncHookType<LdrResolveDelayLoadedAPI_func>
stub_LdrResolveDelayLoadedAPI;
static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
static PVOID WINAPI
patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
@ -338,12 +336,20 @@ patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
void
InitializeWin64ProfilerHooks()
{
static bool initialized = false;
if (initialized) {
return;
}
initialized = true;
NtDllIntercept.Init("ntdll.dll");
stub_LdrUnloadDll.Set(NtDllIntercept, "LdrUnloadDll", &patched_LdrUnloadDll);
NtDllIntercept.AddHook("LdrUnloadDll",
reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
(void**)&stub_LdrUnloadDll);
if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8
stub_LdrResolveDelayLoadedAPI.Set(NtDllIntercept,
"LdrResolveDelayLoadedAPI",
&patched_LdrResolveDelayLoadedAPI);
NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI",
reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
(void**)&stub_LdrResolveDelayLoadedAPI);
}
}
#endif // defined(GP_PLAT_amd64_windows)

View File

@ -352,6 +352,9 @@ static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
// General purpose user32.dll hook object
static WindowsDllInterceptor sUser32Intercept;
// AddHook success checks
static mozilla::Maybe<bool> sHookedGetWindowInfo;
// 2 pixel offset for eTransparencyBorderlessGlass which equals the size of
// the default window border Windows paints. Glass will be extended inward
// this distance to remove the border.
@ -458,17 +461,17 @@ private:
if (!IsWin10OrLater() && GetModuleHandle(L"tiptsf.dll") &&
!sProcessCaretEventsStub) {
sTipTsfInterceptor.Init("tiptsf.dll");
DebugOnly<bool> ok = sProcessCaretEventsStub.Set(sTipTsfInterceptor,
"ProcessCaretEvents",
&ProcessCaretEventsHook);
DebugOnly<bool> ok = sTipTsfInterceptor.AddHook("ProcessCaretEvents",
reinterpret_cast<intptr_t>(&ProcessCaretEventsHook),
(void**) &sProcessCaretEventsStub);
MOZ_ASSERT(ok);
}
if (!sSendMessageTimeoutWStub) {
sUser32Intercept.Init("user32.dll");
DebugOnly<bool> hooked = sSendMessageTimeoutWStub.Set(sUser32Intercept,
"SendMessageTimeoutW",
&SendMessageTimeoutWHook);
DebugOnly<bool> hooked = sUser32Intercept.AddHook("SendMessageTimeoutW",
reinterpret_cast<intptr_t>(&SendMessageTimeoutWHook),
(void**) &sSendMessageTimeoutWStub);
MOZ_ASSERT(hooked);
}
}
@ -553,10 +556,8 @@ private:
}
static WindowsDllInterceptor sTipTsfInterceptor;
static WindowsDllInterceptor::FuncHookType<WINEVENTPROC>
sProcessCaretEventsStub;
static WindowsDllInterceptor::FuncHookType<decltype(&SendMessageTimeoutW)>
sSendMessageTimeoutWStub;
static WINEVENTPROC sProcessCaretEventsStub;
static decltype(&SendMessageTimeoutW) sSendMessageTimeoutWStub;
static StaticAutoPtr<TIPMessageHandler> sInstance;
HHOOK mHook;
@ -565,10 +566,8 @@ private:
};
WindowsDllInterceptor TIPMessageHandler::sTipTsfInterceptor;
WindowsDllInterceptor::FuncHookType<WINEVENTPROC>
TIPMessageHandler::sProcessCaretEventsStub;
WindowsDllInterceptor::FuncHookType<decltype(&SendMessageTimeoutW)>
TIPMessageHandler::sSendMessageTimeoutWStub;
WINEVENTPROC TIPMessageHandler::sProcessCaretEventsStub;
decltype(&SendMessageTimeoutW) TIPMessageHandler::sSendMessageTimeoutWStub;
StaticAutoPtr<TIPMessageHandler> TIPMessageHandler::sInstance;
} // namespace mozilla
@ -2473,7 +2472,7 @@ nsWindow::ResetLayout()
// margins are set.
static const wchar_t kManageWindowInfoProperty[] = L"ManageWindowInfoProperty";
typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
static WindowsDllInterceptor::FuncHookType<GetWindowInfoPtr> sGetWindowInfoPtrStub;
static GetWindowInfoPtr sGetWindowInfoPtrStub = nullptr;
BOOL WINAPI
GetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
@ -2501,15 +2500,18 @@ nsWindow::UpdateGetWindowInfoCaptionStatus(bool aActiveCaption)
if (!mWnd)
return;
sUser32Intercept.Init("user32.dll");
sGetWindowInfoPtrStub.Set(sUser32Intercept, "GetWindowInfo",
&GetWindowInfoHook);
if (!sGetWindowInfoPtrStub) {
return;
if (sHookedGetWindowInfo.isNothing()) {
sUser32Intercept.Init("user32.dll");
sHookedGetWindowInfo =
Some(sUser32Intercept.AddHook("GetWindowInfo",
reinterpret_cast<intptr_t>(GetWindowInfoHook),
(void**) &sGetWindowInfoPtrStub));
if (!sHookedGetWindowInfo.value()) {
return;
}
}
// Update our internally tracked caption status
SetPropW(mWnd, kManageWindowInfoProperty,
SetPropW(mWnd, kManageWindowInfoProperty,
reinterpret_cast<HANDLE>(static_cast<INT_PTR>(aActiveCaption) + 1));
}

View File

@ -84,14 +84,16 @@ volatile PRIntervalTime sLastLowMemoryNotificationTime;
// These are function pointers to the functions we wrap in Init().
static WindowsDllInterceptor::FuncHookType<decltype(&VirtualAlloc)>
sVirtualAllocOrig;
void* (WINAPI* sVirtualAllocOrig)(LPVOID aAddress, SIZE_T aSize,
DWORD aAllocationType, DWORD aProtect);
static WindowsDllInterceptor::FuncHookType<decltype(&MapViewOfFile)>
sMapViewOfFileOrig;
void* (WINAPI* sMapViewOfFileOrig)(HANDLE aFileMappingObject,
DWORD aDesiredAccess, DWORD aFileOffsetHigh,
DWORD aFileOffsetLow, SIZE_T aNumBytesToMap);
static WindowsDllInterceptor::FuncHookType<decltype(&CreateDIBSection)>
sCreateDIBSectionOrig;
HBITMAP(WINAPI* sCreateDIBSectionOrig)(HDC aDC, const BITMAPINFO* aBitmapInfo,
UINT aUsage, VOID** aBits,
HANDLE aSection, DWORD aOffset);
/**
* Fire a memory pressure event if we were not under memory pressure yet, or
@ -643,12 +645,17 @@ Init()
// VirtualAllocHook from reentering itself.
if (!PR_GetEnv("MOZ_PGO_INSTRUMENTED")) {
sKernel32Intercept.Init("Kernel32.dll");
sVirtualAllocOrig.Set(sKernel32Intercept, "VirtualAlloc", &VirtualAllocHook);
sMapViewOfFileOrig.Set(sKernel32Intercept, "MapViewOfFile", &MapViewOfFileHook);
sKernel32Intercept.AddHook("VirtualAlloc",
reinterpret_cast<intptr_t>(VirtualAllocHook),
reinterpret_cast<void**>(&sVirtualAllocOrig));
sKernel32Intercept.AddHook("MapViewOfFile",
reinterpret_cast<intptr_t>(MapViewOfFileHook),
reinterpret_cast<void**>(&sMapViewOfFileOrig));
sGdi32Intercept.Init("Gdi32.dll");
sCreateDIBSectionOrig.Set(sGdi32Intercept, "CreateDIBSection",
&CreateDIBSectionHook);
sGdi32Intercept.AddHook("CreateDIBSection",
reinterpret_cast<intptr_t>(CreateDIBSectionHook),
reinterpret_cast<void**>(&sCreateDIBSectionOrig));
}
sInitialized = true;

View File

@ -209,20 +209,13 @@ WinIOAutoObservation::Filename(nsAString& aFilename)
/*************************** IO Interposing Methods ***************************/
// Function pointers to original functions
static WindowsDllInterceptor::FuncHookType<NtCreateFileFn>
gOriginalNtCreateFile;
static WindowsDllInterceptor::FuncHookType<NtReadFileFn>
gOriginalNtReadFile;
static WindowsDllInterceptor::FuncHookType<NtReadFileScatterFn>
gOriginalNtReadFileScatter;
static WindowsDllInterceptor::FuncHookType<NtWriteFileFn>
gOriginalNtWriteFile;
static WindowsDllInterceptor::FuncHookType<NtWriteFileGatherFn>
gOriginalNtWriteFileGather;
static WindowsDllInterceptor::FuncHookType<NtFlushBuffersFileFn>
gOriginalNtFlushBuffersFile;
static WindowsDllInterceptor::FuncHookType<NtQueryFullAttributesFileFn>
gOriginalNtQueryFullAttributesFile;
static NtCreateFileFn gOriginalNtCreateFile;
static NtReadFileFn gOriginalNtReadFile;
static NtReadFileScatterFn gOriginalNtReadFileScatter;
static NtWriteFileFn gOriginalNtWriteFile;
static NtWriteFileGatherFn gOriginalNtWriteFileGather;
static NtFlushBuffersFileFn gOriginalNtFlushBuffersFile;
static NtQueryFullAttributesFileFn gOriginalNtQueryFullAttributesFile;
static NTSTATUS NTAPI
InterposedNtCreateFile(PHANDLE aFileHandle,
@ -455,21 +448,34 @@ InitPoisonIOInterposer()
// Initialize dll interceptor and add hooks
sNtDllInterceptor.Init("ntdll.dll");
gOriginalNtCreateFile.Set(sNtDllInterceptor, "NtCreateFile",
&InterposedNtCreateFile);
gOriginalNtReadFile.Set(sNtDllInterceptor, "NtReadFile",
&InterposedNtReadFile);
gOriginalNtReadFileScatter.Set(sNtDllInterceptor, "NtReadFileScatter",
&InterposedNtReadFileScatter);
gOriginalNtWriteFile.Set(sNtDllInterceptor, "NtWriteFile",
&InterposedNtWriteFile);
gOriginalNtWriteFileGather.Set(sNtDllInterceptor, "NtWriteFileGather",
&InterposedNtWriteFileGather);
gOriginalNtFlushBuffersFile.Set(sNtDllInterceptor, "NtFlushBuffersFile",
&InterposedNtFlushBuffersFile);
gOriginalNtQueryFullAttributesFile.Set(sNtDllInterceptor,
"NtQueryFullAttributesFile",
&InterposedNtQueryFullAttributesFile);
sNtDllInterceptor.AddHook(
"NtCreateFile",
reinterpret_cast<intptr_t>(InterposedNtCreateFile),
reinterpret_cast<void**>(&gOriginalNtCreateFile));
sNtDllInterceptor.AddHook(
"NtReadFile",
reinterpret_cast<intptr_t>(InterposedNtReadFile),
reinterpret_cast<void**>(&gOriginalNtReadFile));
sNtDllInterceptor.AddHook(
"NtReadFileScatter",
reinterpret_cast<intptr_t>(InterposedNtReadFileScatter),
reinterpret_cast<void**>(&gOriginalNtReadFileScatter));
sNtDllInterceptor.AddHook(
"NtWriteFile",
reinterpret_cast<intptr_t>(InterposedNtWriteFile),
reinterpret_cast<void**>(&gOriginalNtWriteFile));
sNtDllInterceptor.AddHook(
"NtWriteFileGather",
reinterpret_cast<intptr_t>(InterposedNtWriteFileGather),
reinterpret_cast<void**>(&gOriginalNtWriteFileGather));
sNtDllInterceptor.AddHook(
"NtFlushBuffersFile",
reinterpret_cast<intptr_t>(InterposedNtFlushBuffersFile),
reinterpret_cast<void**>(&gOriginalNtFlushBuffersFile));
sNtDllInterceptor.AddHook(
"NtQueryFullAttributesFile",
reinterpret_cast<intptr_t>(InterposedNtQueryFullAttributesFile),
reinterpret_cast<void**>(&gOriginalNtQueryFullAttributesFile));
}
void