Backed out 13 changesets (bug 1460022) for bustages in :/build/build/src/mozglue/tests/interceptor/TestDllInterceptor.cpp(113) on a CLOSED TREE
authorshindli <shindli@mozilla.com>
Wed, 04 Jul 2018 03:37:11 +0300
changeset 480058 9cfc3fe9fe3832f29ebcba0318db8ee21f926db2
parent 480057 93540ca16c31b162c6c11a120da897428f094398
child 480059 f1727b36a3fec9645b44fc21563713dfcf5f916f
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1460022
milestone63.0a1
backs outb798c3689bbf11e6d16844df3c79a6b15c8622cc
c3b3b854affd7efdae5631ed024d19900b90a501
ecb1b6fd3134ad8336338cdff1d231fc24015ee9
91fed649dd5a3f6c3dc48ca69711560851553a50
be7032cddad2709068fb4606e10167697ba1944d
d4a036b976e65d417fa571788e7dd111038d2c4c
5f3dfde41e384ad6374a22cdd5d4964bd0602491
a16486a6f685099ef25a1bde3aa63ee5eb66f42a
69eacc5c3ab87fdeb2a91e7ee00bf2bc5ef2bde5
34aa7c29b31e7fa888e8ef1c7ae8c78806c945d3
00b20c0a763741ef161ecc48794d28b1db97cbe9
b8e8aea4a01f596dc543216fa946ac0170b4d616
15822d9848d8647ef9a143f4b718d8d5d66a4c0a
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 13 changesets (bug 1460022) for bustages in :/build/build/src/mozglue/tests/interceptor/TestDllInterceptor.cpp(113) on a CLOSED TREE Backed out changeset b798c3689bbf (bug 1460022) Backed out changeset c3b3b854affd (bug 1460022) Backed out changeset ecb1b6fd3134 (bug 1460022) Backed out changeset 91fed649dd5a (bug 1460022) Backed out changeset be7032cddad2 (bug 1460022) Backed out changeset d4a036b976e6 (bug 1460022) Backed out changeset 5f3dfde41e38 (bug 1460022) Backed out changeset a16486a6f685 (bug 1460022) Backed out changeset 69eacc5c3ab8 (bug 1460022) Backed out changeset 34aa7c29b31e (bug 1460022) Backed out changeset 00b20c0a7637 (bug 1460022) Backed out changeset b8e8aea4a01f (bug 1460022) Backed out changeset 15822d9848d8 (bug 1460022)
accessible/windows/msaa/Compatibility.cpp
browser/app/winlauncher/DllBlocklistWin.cpp
dom/media/gmp/ChromiumCDMAdapter.cpp
dom/plugins/base/nsPluginNativeWindowWin.cpp
dom/plugins/ipc/FunctionHook.cpp
dom/plugins/ipc/FunctionHook.h
dom/plugins/ipc/PluginInstanceChild.cpp
mozglue/build/WindowsDllBlocklist.cpp
mozglue/misc/nsWindowsDllInterceptor.h
mozglue/tests/interceptor/TestDllInterceptor.cpp
mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp
security/sandbox/win/SandboxInitialization.cpp
toolkit/crashreporter/nsExceptionHandler.cpp
tools/profiler/core/platform-win32.cpp
widget/windows/nsWindow.cpp
xpcom/base/AvailableMemoryTracker.cpp
xpcom/build/PoisonIOInterposerWin.cpp
--- a/accessible/windows/msaa/Compatibility.cpp
+++ b/accessible/windows/msaa/Compatibility.cpp
@@ -90,18 +90,17 @@ Compatibility::IsModuleVersionLessThan(H
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Compatibility
 ////////////////////////////////////////////////////////////////////////////////
 
 static WindowsDllInterceptor sUser32Interceptor;
-static WindowsDllInterceptor::FuncHookType<decltype(&InSendMessageEx)>
-  sInSendMessageExStub;
+static decltype(&InSendMessageEx) sInSendMessageExStub = nullptr;
 static bool sInSendMessageExHackEnabled = false;
 static PVOID sVectoredExceptionHandler = nullptr;
 
 #if defined(_MSC_VER)
 #include <intrin.h>
 #pragma intrinsic(_ReturnAddress)
 #define RETURN_ADDRESS() _ReturnAddress()
 #elif defined(__GNUC__) || defined(__clang__)
@@ -263,19 +262,21 @@ Compatibility::Init()
   }
 
   // If we have a consumer who is not NVDA, we enable detection for the
   // InSendMessageEx compatibility hack. NVDA does not require this.
   // We also skip UIA, as we see crashes there.
   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) {
       // We need to let ASan's ShadowExceptionHandler remain in the firstHandler
       // position, otherwise we'll get infinite recursion when our handler
       // faults on shadow memory.
       const ULONG firstHandler = FALSE;
       sVectoredExceptionHandler =
--- a/browser/app/winlauncher/DllBlocklistWin.cpp
+++ b/browser/app/winlauncher/DllBlocklistWin.cpp
@@ -241,18 +241,17 @@ IsDllAllowed(const UNICODE_STRING& aLeaf
     gBlockSet.Add(info->name, version);
     return false;
   }
 
   return true;
 }
 
 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,
                            ULONG_PTR aZeroBits, SIZE_T aCommitSize,
                            PLARGE_INTEGER aSectionOffset, PSIZE_T aViewSize,
                            SECTION_INHERIT aInheritDisposition,
                            ULONG aAllocationType, ULONG aProtectionFlags)
 {
@@ -352,18 +351,19 @@ private:
   DWORD   mPrevProt;
 };
 
 bool
 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;
   }
 
   // Set the child process's copy of stub_NtMapViewOfSection
   SIZE_T bytesWritten;
   ok = !!::WriteProcessMemory(aChildProcess, &stub_NtMapViewOfSection,
                               &stub_NtMapViewOfSection,
--- a/dom/media/gmp/ChromiumCDMAdapter.cpp
+++ b/dom/media/gmp/ChromiumCDMAdapter.cpp
@@ -192,18 +192,17 @@ ChromiumCDMAdapter::Supports(int32_t aMo
 #ifdef XP_WIN
 
 static WindowsDllInterceptor sKernel32Intercept;
 
 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;
 
 DWORD WINAPI
 QueryDosDeviceWHook(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
 {
   if (!sDeviceNames) {
     return 0;
@@ -272,18 +271,19 @@ InitializeHooks()
   }
   initialized = true;
   sDeviceNames = new std::unordered_map<std::wstring, std::wstring>();
   for (const std::wstring& name : GetDosDeviceNames()) {
     sDeviceNames->emplace(name, GetDeviceMapping(name));
   }
 
   sKernel32Intercept.Init("kernelbase.dll");
-  sOriginalQueryDosDeviceWFnPtr.Set(sKernel32Intercept, "QueryDosDeviceW",
-                                    &QueryDosDeviceWHook);
+  sKernel32Intercept.AddHook("QueryDosDeviceW",
+                             reinterpret_cast<intptr_t>(QueryDosDeviceWHook),
+                             (void**)(&sOriginalQueryDosDeviceWFnPtr));
 }
 #endif
 
 HostFile::HostFile(HostFile&& aOther)
   : mPath(aOther.mPath)
   , mFile(aOther.TakePlatformFile())
 {
 }
--- a/dom/plugins/base/nsPluginNativeWindowWin.cpp
+++ b/dom/plugins/base/nsPluginNativeWindowWin.cpp
@@ -352,33 +352,29 @@ static WindowsDllInterceptor sUser32Inte
 typedef LONG_PTR
   (WINAPI *User32SetWindowLongPtrA)(HWND hWnd,
                                     int nIndex,
                                     LONG_PTR dwNewLong);
 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,
                                int nIndex,
                                LONG dwNewLong);
 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,
                        int nIndex,
                        LONG_PTR newLong)
 {
   nsPluginNativeWindowWin * win =
     (nsPluginNativeWindowWin *)GetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
@@ -447,25 +443,33 @@ SetWindowLongWHook(HWND hWnd,
   return proc;
 }
 
 static void
 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
 }
 
 /**
  *   nsPluginNativeWindowWin implementation
  */
 nsPluginNativeWindowWin::nsPluginNativeWindowWin() : nsPluginNativeWindow()
 {
--- a/dom/plugins/ipc/FunctionHook.cpp
+++ b/dom/plugins/ipc/FunctionHook.cpp
@@ -163,23 +163,23 @@ BOOL WINAPI PrintDlgWHook(LPPRINTDLGW aD
 
 // Hooking CreateFileW for protected-mode magic
 static WindowsDllInterceptor sKernel32Intercept;
 typedef HANDLE (WINAPI *CreateFileWPtr)(LPCWSTR aFname, DWORD aAccess,
                                         DWORD aShare,
                                         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.
 // So we hook CreateFileA too to use CreateFileW hook.
 static HANDLE WINAPI
 CreateFileAHookFn(LPCSTR aFname, DWORD aAccess, DWORD aShare,
                   LPSECURITY_ATTRIBUTES aSecurity, DWORD aCreation, DWORD aFlags,
                   HANDLE aFTemplate)
@@ -258,17 +258,17 @@ CreateFileWHookFn(LPCWSTR aFname, DWORD 
     if (GetTempFileNameW(tempPath, L"fx", 0, tempFile) == 0) {
       break;
     }
     HANDLE replacement =
       sCreateFileWStub(tempFile, GENERIC_READ | GENERIC_WRITE, aShare,
                        aSecurity, TRUNCATE_EXISTING,
                        FILE_ATTRIBUTE_TEMPORARY |
                          FILE_FLAG_DELETE_ON_CLOSE,
-                       nullptr);
+                       NULL);
     if (replacement == INVALID_HANDLE_VALUE) {
       break;
     }
 
     HANDLE original = sCreateFileWStub(aFname, aAccess, aShare, aSecurity,
                                        aCreation, aFlags, aFTemplate);
     if (original != INVALID_HANDLE_VALUE) {
       // copy original to replacement
@@ -295,22 +295,33 @@ CreateFileWHookFn(LPCWSTR aFname, DWORD 
     return replacement;
   }
   return sCreateFileWStub(aFname, aAccess, aShare, aSecurity, aCreation, aFlags,
                           aFTemplate);
 }
 
 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)
 
 #define FUN_HOOK(x) static_cast<FunctionHook*>(x)
 
 void
 FunctionHook::AddFunctionHooks(FunctionHookArray& aHooks)
--- a/dom/plugins/ipc/FunctionHook.h
+++ b/dom/plugins/ipc/FunctionHook.h
@@ -4,17 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef dom_plugins_ipc_functionhook_h
 #define dom_plugins_ipc_functionhook_h 1
 
 #include "IpdlTuple.h"
 #include "base/process.h"
-#include "mozilla/Atomics.h"
 
 #if defined(XP_WIN)
 #include "nsWindowsDllInterceptor.h"
 #endif
 
 namespace mozilla {
 namespace plugins {
 
@@ -92,29 +91,22 @@ public:
 };
 
 // Type of function that returns true if a function should be hooked according to quirks.
 typedef bool(ShouldHookFunc)(int aQuirks);
 
 template<FunctionHookId functionId, typename FunctionType>
 class BasicFunctionHook : public FunctionHook
 {
-#if defined(XP_WIN)
-  using FuncHookType = WindowsDllInterceptor::FuncHookType<FunctionType*>;
-#endif // defined(XP_WIN)
-
 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);
   }
 
   /**
    * Hooks the function if we haven't already and if ShouldHook() says to.
    */
@@ -131,20 +123,17 @@ public:
   FunctionHookId FunctionId() const override { return functionId; }
 
   FunctionType* OriginalFunction() const { return mOldFunction; }
 
 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;
-#if defined(XP_WIN)
-  FuncHookType mStub;
-#endif // defined(XP_WIN)
+  FunctionType* mOldFunction;
 
   enum RegistrationStatus { UNREGISTERED, FAILED, SUCCEEDED };
   RegistrationStatus mRegistration;
 
   // The name of the module containing the function to hook.  E.g. "user32.dll".
   const nsCString mModuleName;
   // The name of the function in the module.
   const nsCString mFunctionName;
@@ -176,26 +165,24 @@ BasicFunctionHook<functionId, FunctionTy
 
 #if defined(XP_WIN)
   WindowsDllInterceptor* dllInterceptor =
     FunctionHook::GetDllInterceptorFor(mModuleName.Data());
   if (!dllInterceptor) {
     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) {
-#if defined(XP_WIN)
-    mOldFunction = mStub.GetStub();
-#endif
     mRegistration = SUCCEEDED;
   }
-
   HOOK_LOG(LogLevel::Debug,
            ("Registering to intercept function '%s' : '%s'", mFunctionName.Data(),
             SuccessMsg(isHooked)));
 
   return isHooked;
 }
 
 }
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -68,27 +68,31 @@ typedef BOOL (WINAPI *User32TrackPopupMe
                                             UINT uFlags,
                                             int x,
                                             int y,
                                             int nReserved,
                                             HWND hWnd,
                                             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;
 
 // Flash WM_USER message delay time for PostDelayedTask. Borrowed
 // from Chromium's web plugin delegate src. See 'flash msg throttling
 // helpers' section for details.
 const int kFlashWMUSERMessageThrottleDelayMs = 5;
 
@@ -1784,29 +1788,29 @@ PluginInstanceChild::MaybePostKeyMessage
 typedef LONG_PTR
   (WINAPI *User32SetWindowLongPtrA)(HWND hWnd,
                                     int nIndex,
                                     LONG_PTR dwNewLong);
 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,
                                int nIndex,
                                LONG dwNewLong);
 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
 NeuteredWindowProc(HWND hwnd,
                    UINT uMsg,
                    WPARAM wParam,
                    LPARAM lParam);
 
@@ -1906,27 +1910,37 @@ PluginInstanceChild::SetWindowLongWHook(
 
 void
 PluginInstanceChild::HookSetWindowLongPtr()
 {
     if (!(GetQuirks() & QUIRK_FLASH_HOOK_SETLONGPTR)) {
         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
 }
 
 /* windowless track popup menu helpers */
 
 BOOL
 WINAPI
 PluginInstanceChild::TrackPopupHookProc(HMENU hMenu,
@@ -1984,23 +1998,29 @@ PluginInstanceChild::TrackPopupHookProc(
 
 void
 PluginInstanceChild::InitPopupMenuHook()
 {
     if (!(GetQuirks() & QUIRK_WINLESS_TRACKPOPUP_HOOK)) {
         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
 PluginInstanceChild::CreateWinlessPopupSurrogate()
 {
     // already initialized
     if (mWinlessPopupSurrogateHWND)
         return;
@@ -2132,33 +2152,46 @@ PluginInstanceChild::ImmAssociateContext
 
 void
 PluginInstanceChild::InitImm32Hook()
 {
     if (!(GetQuirks() & QUIRK_WINLESS_HOOK_IME)) {
         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
 PluginInstanceChild::DestroyWinlessPopupSurrogate()
 {
     if (mWinlessPopupSurrogateHWND)
         DestroyWindow(mWinlessPopupSurrogateHWND);
     mWinlessPopupSurrogateHWND = nullptr;
--- a/mozglue/build/WindowsDllBlocklist.cpp
+++ b/mozglue/build/WindowsDllBlocklist.cpp
@@ -85,24 +85,24 @@ printf_stderr(const char *fmt, ...)
   vfprintf(fp, fmt, args);
   va_end(args);
 
   fclose(fp);
 }
 
 
 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;
 
 BOOLEAN WINAPI patched_RtlInstallFunctionTableCallback(DWORD64 TableIdentifier,
   DWORD64 BaseAddress, DWORD Length, PGET_RUNTIME_FUNCTION_CALLBACK Callback,
   PVOID Context, PCWSTR OutOfProcessCallbackDll)
 {
@@ -657,18 +657,17 @@ DllBlocklist_Initialize(uint32_t aInitFl
 
   NtDllIntercept.Init("ntdll.dll");
 
   ReentrancySentinel::InitializeStatics();
 
   // 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;
 #ifdef DEBUG
     printf_stderr("LdrLoadDll hook failed, no dll blocklisting active\n");
 #endif
   }
 
@@ -679,28 +678,28 @@ DllBlocklist_Initialize(uint32_t aInitFl
     ::LoadLibraryW(L"user32.dll");
   }
 
   Kernel32Intercept.Init("kernel32.dll");
 
 #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
     }
   }
 
 #if defined(NIGHTLY_BUILD)
   // Populate a list of thread start addresses to block.
--- a/mozglue/misc/nsWindowsDllInterceptor.h
+++ b/mozglue/misc/nsWindowsDllInterceptor.h
@@ -3,22 +3,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef NS_WINDOWS_DLL_INTERCEPTOR_H_
 #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"
 #include "mozilla/Vector.h"
 #include "nsWindowsHelpers.h"
 
 #include <wchar.h>
 #include <windows.h>
@@ -79,165 +77,26 @@
  *
  * Note that this is not thread-safe.  Sad day.
  *
  */
 
 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
 };
 
 template <typename VMPolicy =
             mozilla::interceptor::VMSharingPolicyShared<
               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;
 #endif // defined(_M_IX86)
 
   HMODULE mModule;
   int mNHooks;
 
@@ -296,17 +155,16 @@ public:
 #if defined(_M_IX86)
     mNopSpacePatcher.Clear();
 #endif // defined(_M_IX86)
     mDetourPatcher.Clear();
 
     // 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
    * and returns true if successful.
    *
    * IMPORTANT: If you use this method, please add your case to the
    * TestDllInterceptor in order to detect future failures.  Even if this
    * succeeds now, updates to the hooked DLL could cause it to fail in
@@ -356,34 +214,27 @@ private:
     FARPROC proc = ::GetProcAddress(mModule, aName);
     if (!proc) {
       return false;
     }
 
     return AddDetour(proc, aHookDest, aOrigFunc);
   }
 
+private:
   bool AddDetour(FARPROC aProc, intptr_t aHookDest, void** aOrigFunc)
   {
     MOZ_ASSERT(mModule && aProc);
 
     if (!mDetourPatcher.Initialized()) {
       mDetourPatcher.Init(mNHooks);
     }
 
     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
 
 using WindowsDllInterceptor = interceptor::WindowsDllInterceptor<>;
 
 using CrossProcessDllInterceptor = interceptor::WindowsDllInterceptor<
   mozilla::interceptor::VMSharingPolicyUnique<
--- a/mozglue/tests/interceptor/TestDllInterceptor.cpp
+++ b/mozglue/tests/interceptor/TestDllInterceptor.cpp
@@ -5,43 +5,20 @@
 #include <shlobj.h>
 #include <stdio.h>
 #include <commdlg.h>
 #define SECURITY_WIN32
 #include <security.h>
 #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 {
   UINT64 a;
   UINT64 b;
   UINT64 c;
 
   bool operator==(const payload &other) const {
@@ -56,316 +33,90 @@ extern "C" __declspec(dllexport) __decls
   p.a = p.b;
   p.b = p.c;
   p.c = tmp;
   return p;
 }
 
 static bool patched_func_called = false;
 
-static WindowsDllInterceptor::FuncHookType<decltype(&rotatePayload)>
-  orig_rotatePayload;
+static payload (*orig_rotatePayload)(payload);
 
 static payload
 patched_rotatePayload(payload p)
 {
   patched_func_called = true;
   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. We'll suppress that
-// behavior here.
-#pragma warning(suppress: 4003)
-DEFINE_TEST_FUNCTION()
-#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;
   }
   printf("TEST-FAILED | WindowsDllInterceptor | "
          "Failed to execute hooked function %s from %s\n", aFuncName, aDllName);
   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()) {
     return false;
   }
 
   nsModuleHandle shell32(LoadLibraryW(L"shell32.dll"));
   if (!shell32) {
@@ -391,16 +142,465 @@ bool ShouldTestTipTsf()
   if (!LoadLibraryW(fullPath)) {
     return false;
   }
 
   // Leak the module so that it's loaded for the interceptor test
   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;
   QueryPerformanceCounter(&start);
 
   // We disable this part of the test because the code coverage instrumentation
   // injects code in rotatePayload in a way that WindowsDllInterceptor doesn't
   // understand.
@@ -410,17 +610,17 @@ int main()
   ZeroMemory(&p0, sizeof(p0));
   ZeroMemory(&p1, sizeof(p1));
 
   p0 = rotatePayload(initial);
 
   {
     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");
       return 1;
     }
 
     p1 = rotatePayload(initial);
 
@@ -454,95 +654,95 @@ int main()
   if (p0 == p1) {
     printf("TEST-PASS | WindowsDllInterceptor | Original function worked properly\n");
   } else {
     printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Original function didn't return the right information\n");
     return 1;
   }
 #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;
     QueryPerformanceCounter(&end);
 
     QueryPerformanceFrequency(&freq);
 
     LARGE_INTEGER result;
--- a/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp
+++ b/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp
@@ -6,29 +6,29 @@
 
 #include "nsWindowsDllInterceptor.h"
 #include "nsWindowsHelpers.h"
 
 #include <string>
 
 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;
   }
 
   return 0;
 }
 
 int ParentMain()
 {
@@ -68,17 +68,19 @@ int ParentMain()
     printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Failed to assign child process to job\n");
     ::TerminateProcess(childProcess.get(), 1);
     return 1;
   }
 
   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;
   }
 
   printf("TEST-PASS | DllInterceptorCrossProcess | Hook added\n");
 
   // Let's save the original hook
   SIZE_T bytesWritten;
--- a/security/sandbox/win/SandboxInitialization.cpp
+++ b/security/sandbox/win/SandboxInitialization.cpp
@@ -10,27 +10,26 @@
 #include "nsWindowsDllInterceptor.h"
 #include "sandbox/win/src/sandbox_factory.h"
 #include "mozilla/sandboxing/permissionsService.h"
 
 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,
                                            HANDLE hTargetProcessHandle,
                                            LPHANDLE lpTargetHandle,
                                            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)
 {
   // Check all handles being closed against the sandbox's tracked handles.
   base::win::OnHandleBeingClosed(hObject);
   return stub_CloseHandle(hObject);
 }
@@ -58,24 +57,27 @@ patched_DuplicateHandle(HANDLE hSourcePr
 
 static WindowsDllInterceptor Kernel32Intercept;
 
 static bool
 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;
   }
 
   return true;
 }
 
 static bool
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -333,18 +333,17 @@ nsTArray<nsAutoPtr<DelayedNote> >* gDela
 
 #if defined(XP_WIN)
 // the following are used to prevent other DLLs reverting the last chance
 // exception handler to the windows default. Any attempt to change the
 // unhandled exception filter or to reset it is ignored and our crash
 // 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;
 
 static LPTOP_LEVEL_EXCEPTION_FILTER GetUnhandledExceptionFilter()
 {
   // Set a dummy value to get the current filter, then restore
   LPTOP_LEVEL_EXCEPTION_FILTER current = SetUnhandledExceptionFilter(nullptr);
@@ -1635,19 +1634,19 @@ nsresult SetExceptionHandler(nsIFile* aX
 #ifdef _WIN64
   // Tell JS about the new filter before we disable SetUnhandledExceptionFilter
   SetJitExceptionHandler();
 #endif
 
   // 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)
     printf_stderr ("SetUnhandledExceptionFilter hook failed; crash reporter is vulnerable.\n");
 #endif
 #endif
 
   // store application start time
--- a/tools/profiler/core/platform-win32.cpp
+++ b/tools/profiler/core/platform-win32.cpp
@@ -298,34 +298,32 @@ Registers::SyncPopulate()
   PopulateRegsFromContext(*this, &context);
 }
 #endif
 
 #if defined(GP_PLAT_amd64_windows)
 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)
 {
   // Prevent the stack walker from suspending this thread when LdrUnloadDll
   // holds the RtlLookupFunctionEntry lock.
   AutoSuppressStackWalking suppress;
   return stub_LdrUnloadDll(module);
 }
 
 // These pointers are disguised as PVOID to avoid pulling in obscure headers
 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,
   PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
   PVOID ThunkAddress, ULONG Flags)
 {
   // Prevent the stack walker from suspending this thread when
   // LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock.
@@ -333,18 +331,26 @@ patched_LdrResolveDelayLoadedAPI(PVOID P
   return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor,
                                        FailureDllHook, FailureSystemHook,
                                        ThunkAddress, Flags);
 }
 
 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)
 
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -347,16 +347,19 @@ static bool     gWindowsVisible         
 // True if we have sent a notification that we are suspending/sleeping.
 static bool     gIsSleepMode                      = false;
 
 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.
 static const int32_t kGlassMarginAdjustment = 2;
 
 // When the client area is extended out into the default window frame area,
 // this is the minimum amount of space along the edge of resizable windows
 // we will always display a resize cursor in, regardless of the underlying
@@ -453,27 +456,27 @@ private:
                                ::GetCurrentThreadId());
     MOZ_ASSERT(mHook);
 
     // On touchscreen devices, tiptsf.dll will have been loaded when STA COM was
     // first initialized.
     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);
     }
   }
 
   class MOZ_RAII A11yInstantiationBlocker
   {
   public:
     A11yInstantiationBlocker()
@@ -548,32 +551,28 @@ private:
     // off to DefWindowProc to accomplish this.
     *aMsgResult = static_cast<DWORD_PTR>(::DefWindowProcW(aHwnd, aMsgCode,
                                                           aWParam, aLParam));
 
     return static_cast<LRESULT>(TRUE);
   }
 
   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;
   UINT                  mMessages[7];
   uint32_t              mA11yBlockCount;
 };
 
 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
 
 #endif // defined(ACCESSIBILITY)
 
 /**************************************************************
  **************************************************************
@@ -2468,17 +2467,17 @@ nsWindow::ResetLayout()
   Invalidate();
 }
 
 // Internally track the caption status via a window property. Required
 // due to our internal handling of WM_NCACTIVATE when custom client
 // 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)
 {
   if (!sGetWindowInfoPtrStub) {
     NS_ASSERTION(FALSE, "Something is horribly wrong in GetWindowInfoHook!");
     return FALSE;
   }
@@ -2496,25 +2495,28 @@ GetWindowInfoHook(HWND hWnd, PWINDOWINFO
 }
 
 void
 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));
 }
 
 /**
  * Called when the window layout changes: full screen mode transitions,
  * theme changes, and composition changes. Calculates the new non-client
  * margins and fires off a frame changed event, which triggers an nc calc
  * size windows event, kicking the changes in.
--- a/xpcom/base/AvailableMemoryTracker.cpp
+++ b/xpcom/base/AvailableMemoryTracker.cpp
@@ -79,24 +79,26 @@ bool sHooksActive = false;
 
 // Alas, we'd like to use mozilla::TimeStamp, but we can't, because it acquires
 // a lock!
 volatile bool sUnderMemoryPressure = false;
 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
  * fire an ongoing one if it's been long enough since the last one we
  * fired.
  */
 bool
 MaybeScheduleMemoryPressureEvent()
@@ -638,22 +640,27 @@ Init()
 
 #if defined(XP_WIN) && !defined(HAVE_64BIT_BUILD)
   // Don't register the hooks if we're a build instrumented for PGO: If we're
   // an instrumented build, the compiler adds function calls all over the place
   // which may call VirtualAlloc; this makes it hard to prevent
   // 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;
 #endif // defined(XP_WIN) && !defined(HAVE_64BIT_BUILD)
 }
 
 } // namespace AvailableMemoryTracker
 } // namespace mozilla
--- a/xpcom/build/PoisonIOInterposerWin.cpp
+++ b/xpcom/build/PoisonIOInterposerWin.cpp
@@ -204,30 +204,23 @@ WinIOAutoObservation::Filename(nsAString
   mHasQueriedFilename = true;
 
   aFilename = mFilename;
 }
 
 /*************************** 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,
                        ACCESS_MASK aDesiredAccess,
                        POBJECT_ATTRIBUTES aObjectAttributes,
                        PIO_STATUS_BLOCK aIoStatusBlock,
                        PLARGE_INTEGER aAllocationSize,
                        ULONG aFileAttributes,
@@ -450,31 +443,44 @@ InitPoisonIOInterposer()
   // at any moment, so the instance needs to persist longer than the scope
   // of this functions.
   static DebugFdRegistry registry;
   ReplaceMalloc::InitDebugFd(registry);
 #endif
 
   // 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
 ClearPoisonIOInterposer()
 {
   MOZ_ASSERT(false);
   if (sIOPoisoned) {
     // Destroy the DLL interceptor