зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
Коммит
112c3bb6dd
|
@ -95,7 +95,8 @@ Compatibility::IsModuleVersionLessThan(HMODULE aModuleHandle,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static WindowsDllInterceptor sUser32Interceptor;
|
||||
static decltype(&InSendMessageEx) sInSendMessageExStub = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<decltype(&InSendMessageEx)>
|
||||
sInSendMessageExStub;
|
||||
static bool sInSendMessageExHackEnabled = false;
|
||||
static PVOID sVectoredExceptionHandler = nullptr;
|
||||
|
||||
|
@ -267,11 +268,9 @@ Compatibility::Init()
|
|||
if ((sConsumers & (~(UIAUTOMATION | NVDA))) &&
|
||||
BrowserTabsRemoteAutostart()) {
|
||||
sUser32Interceptor.Init("user32.dll");
|
||||
if (!sInSendMessageExStub) {
|
||||
sUser32Interceptor.AddHook("InSendMessageEx",
|
||||
reinterpret_cast<intptr_t>(&InSendMessageExHook),
|
||||
(void**)&sInSendMessageExStub);
|
||||
}
|
||||
sInSendMessageExStub.Set(sUser32Interceptor, "InSendMessageEx",
|
||||
&InSendMessageExHook);
|
||||
|
||||
// The vectored exception handler allows us to catch exceptions ahead of any
|
||||
// SEH handlers.
|
||||
if (!sVectoredExceptionHandler) {
|
||||
|
|
|
@ -246,7 +246,8 @@ IsDllAllowed(const UNICODE_STRING& aLeafName, void* aBaseAddress)
|
|||
}
|
||||
|
||||
typedef decltype(&NtMapViewOfSection) NtMapViewOfSection_func;
|
||||
static NtMapViewOfSection_func stub_NtMapViewOfSection;
|
||||
static mozilla::CrossProcessDllInterceptor::FuncHookType<NtMapViewOfSection_func>
|
||||
stub_NtMapViewOfSection;
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
patched_NtMapViewOfSection(HANDLE aSection, HANDLE aProcess, PVOID* aBaseAddress,
|
||||
|
@ -356,9 +357,8 @@ InitializeDllBlocklistOOP(HANDLE aChildProcess)
|
|||
{
|
||||
mozilla::CrossProcessDllInterceptor intcpt(aChildProcess);
|
||||
intcpt.Init(L"ntdll.dll");
|
||||
bool ok = intcpt.AddDetour("NtMapViewOfSection",
|
||||
reinterpret_cast<intptr_t>(&patched_NtMapViewOfSection),
|
||||
(void**) &stub_NtMapViewOfSection);
|
||||
bool ok = stub_NtMapViewOfSection.SetDetour(intcpt, "NtMapViewOfSection",
|
||||
&patched_NtMapViewOfSection);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -995,12 +995,22 @@ nsContextMenu.prototype = {
|
|||
target: this.target,
|
||||
});
|
||||
|
||||
// Cache this because we fetch the data async
|
||||
let {documentURIObject} = gContextMenuContentData;
|
||||
|
||||
let onMessage = (message) => {
|
||||
mm.removeMessageListener("ContextMenu:SaveVideoFrameAsImage:Result", onMessage);
|
||||
// FIXME can we switch this to a blob URL?
|
||||
let dataURL = message.data.dataURL;
|
||||
saveImageURL(dataURL, name, "SaveImageTitle", true, false,
|
||||
document.documentURIObject, null, null, null,
|
||||
isPrivate);
|
||||
saveImageURL(dataURL, name, "SaveImageTitle",
|
||||
true, // bypass cache
|
||||
false, // don't skip prompt for where to save
|
||||
documentURIObject, // referrer
|
||||
null, // document
|
||||
null, // content type
|
||||
null, // content disposition
|
||||
isPrivate,
|
||||
this.principal);
|
||||
};
|
||||
mm.addMessageListener("ContextMenu:SaveVideoFrameAsImage:Result", onMessage);
|
||||
},
|
||||
|
@ -1238,13 +1248,15 @@ nsContextMenu.prototype = {
|
|||
this._canvasToBlobURL(this.target).then(function(blobURL) {
|
||||
saveImageURL(blobURL, "canvas.png", "SaveImageTitle",
|
||||
true, false, referrerURI, null, null, null,
|
||||
isPrivate);
|
||||
isPrivate,
|
||||
document.nodePrincipal /* system, because blob: */);
|
||||
}, Cu.reportError);
|
||||
} else if (this.onImage) {
|
||||
urlSecurityCheck(this.mediaURL, this.principal);
|
||||
saveImageURL(this.mediaURL, null, "SaveImageTitle", false,
|
||||
false, referrerURI, null, gContextMenuContentData.contentType,
|
||||
gContextMenuContentData.contentDisposition, isPrivate);
|
||||
gContextMenuContentData.contentDisposition, isPrivate,
|
||||
this.principal);
|
||||
} else if (this.onVideo || this.onAudio) {
|
||||
var dialogTitle = this.onVideo ? "SaveVideoTitle" : "SaveAudioTitle";
|
||||
this.saveHelper(this.mediaURL, null, dialogTitle, false, doc, referrerURI,
|
||||
|
|
|
@ -689,7 +689,8 @@ function saveMedia() {
|
|||
var saveAnImage = function(aURIString, aChosenData, aBaseURI) {
|
||||
uniqueFile(aChosenData.file);
|
||||
internalSave(aURIString, null, null, null, null, false, "SaveImageTitle",
|
||||
aChosenData, aBaseURI, null, false, null, gDocInfo.isContentWindowPrivate);
|
||||
aChosenData, aBaseURI, null, false, null,
|
||||
gDocInfo.isContentWindowPrivate, gDocInfo.principal);
|
||||
};
|
||||
|
||||
for (var i = 0; i < rowArray.length; i++) {
|
||||
|
|
|
@ -305,7 +305,8 @@ function openLinkIn(url, where, params) {
|
|||
|
||||
// ContentClick.jsm passes isContentWindowPrivate for saveURL instead of passing a CPOW initiatingDoc
|
||||
if ("isContentWindowPrivate" in params) {
|
||||
saveURL(url, null, null, true, true, aNoReferrer ? null : aReferrerURI, null, params.isContentWindowPrivate);
|
||||
saveURL(url, null, null, true, true, aNoReferrer ? null : aReferrerURI,
|
||||
null, params.isContentWindowPrivate, aPrincipal);
|
||||
} else {
|
||||
if (!aInitiatingDoc) {
|
||||
Cu.reportError("openUILink/openLinkIn was called with " +
|
||||
|
|
|
@ -153,7 +153,7 @@ nsMacShellService::SetDesktopBackground(Element* aElement,
|
|||
loadContext = do_QueryInterface(docShell);
|
||||
}
|
||||
|
||||
return wbp->SaveURI(imageURI, 0,
|
||||
return wbp->SaveURI(imageURI, aElement->NodePrincipal(), 0,
|
||||
docURI, aElement->OwnerDoc()->GetReferrerPolicy(),
|
||||
nullptr, nullptr,
|
||||
mBackgroundFile, loadContext);
|
||||
|
|
|
@ -554,7 +554,6 @@ var saveToFile = Task.async(function* (context, reply) {
|
|||
// the downloads toolbar button when the save is done.
|
||||
const nsIWBP = Ci.nsIWebBrowserPersist;
|
||||
const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
|
||||
nsIWBP.PERSIST_FLAGS_FORCE_ALLOW_COOKIES |
|
||||
nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
|
||||
nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
||||
const isPrivate =
|
||||
|
@ -573,7 +572,9 @@ var saveToFile = Task.async(function* (context, reply) {
|
|||
isPrivate);
|
||||
const listener = new DownloadListener(window, tr);
|
||||
persist.progressListener = listener;
|
||||
const principal = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
persist.savePrivacyAwareURI(sourceURI,
|
||||
principal,
|
||||
0,
|
||||
document.documentURIObject,
|
||||
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
|
|
|
@ -355,7 +355,6 @@ async function saveToFile(window, image) {
|
|||
// the downloads toolbar button when the save is done.
|
||||
const nsIWBP = Ci.nsIWebBrowserPersist;
|
||||
const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
|
||||
nsIWBP.PERSIST_FLAGS_FORCE_ALLOW_COOKIES |
|
||||
nsIWBP.PERSIST_FLAGS_BYPASS_CACHE |
|
||||
nsIWBP.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
|
||||
const isPrivate =
|
||||
|
@ -374,7 +373,9 @@ async function saveToFile(window, image) {
|
|||
isPrivate);
|
||||
const listener = new DownloadListener(window, tr);
|
||||
persist.progressListener = listener;
|
||||
const principal = Services.scriptSecurityManager.getSystemPrincipal();
|
||||
persist.savePrivacyAwareURI(sourceURI,
|
||||
principal,
|
||||
0,
|
||||
document.documentURIObject,
|
||||
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
|
|
|
@ -40,6 +40,8 @@ ChromeUtils.defineModuleGetter(this, "CustomizableUI",
|
|||
"resource:///modules/CustomizableUI.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "CustomizableWidgets",
|
||||
"resource:///modules/CustomizableWidgets.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
|
||||
"resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
|
||||
// We don't want to spend time initializing the full loader here so we create
|
||||
// our own lazy require.
|
||||
|
@ -948,16 +950,32 @@ const JsonView = {
|
|||
// Save original contents
|
||||
chrome.saveBrowser(browser);
|
||||
} else {
|
||||
if (!message.data.startsWith("blob:null") || !browser.contentPrincipal.isNullPrincipal) {
|
||||
Cu.reportError("Got invalid request to save JSON data");
|
||||
return;
|
||||
}
|
||||
// The following code emulates saveBrowser, but:
|
||||
// - Uses the given blob URL containing the custom contents to save.
|
||||
// - Obtains the file name from the URL of the document, not the blob.
|
||||
// - avoids passing the document and explicitly passes system principal.
|
||||
// We have a blob created by a null principal to save, and the null
|
||||
// principal is from the child. Null principals don't survive crossing
|
||||
// over IPC, so there's no other principal that'll work.
|
||||
const persistable = browser.frameLoader;
|
||||
persistable.startPersistence(0, {
|
||||
onDocumentReady(doc) {
|
||||
const uri = chrome.makeURI(doc.documentURI, doc.characterSet);
|
||||
const filename = chrome.getDefaultFileName(undefined, uri, doc, null);
|
||||
chrome.internalSave(message.data, doc, filename, null, doc.contentType,
|
||||
false, null, null, null, doc, false, null, undefined);
|
||||
chrome.internalSave(message.data, null, filename, null, doc.contentType,
|
||||
false /* bypass cache */,
|
||||
null, /* filepicker title key */
|
||||
null, /* file chosen */
|
||||
null, /* referrer */
|
||||
null, /* initiating document */
|
||||
false, /* don't skip prompt for a location */
|
||||
null, /* cache key */
|
||||
PrivateBrowsingUtils.isBrowserPrivate(browser), /* private browsing ? */
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
},
|
||||
onError(status) {
|
||||
throw new Error("JSON Viewer's onSave failed in startPersistence");
|
||||
|
|
|
@ -115,3 +115,7 @@ method console.exception
|
|||
method console.timeStamp
|
||||
method console.profile
|
||||
method console.profileEnd
|
||||
|
||||
// document.open information
|
||||
custom DocumentOpen calls document.open in a way that creates a new Window object
|
||||
custom DocumentOpenReplace calls document.open in a way that creates a new Window object and replaces the old history entry.
|
||||
|
|
|
@ -141,6 +141,7 @@ NS_IMPL_ISUPPORTS(nsContentAreaDragDropDataProvider, nsIFlavorDataProvider)
|
|||
// into the file system
|
||||
nsresult
|
||||
nsContentAreaDragDropDataProvider::SaveURIToFile(nsIURI* inSourceURI,
|
||||
nsIPrincipal* inTriggeringPrincipal,
|
||||
nsIFile* inDestFile,
|
||||
bool isPrivate)
|
||||
{
|
||||
|
@ -162,7 +163,8 @@ nsContentAreaDragDropDataProvider::SaveURIToFile(nsIURI* inSourceURI,
|
|||
persist->SetPersistFlags(nsIWebBrowserPersist::PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION);
|
||||
|
||||
// referrer policy can be anything since the referrer is nullptr
|
||||
return persist->SavePrivacyAwareURI(inSourceURI, 0, nullptr,
|
||||
return persist->SavePrivacyAwareURI(inSourceURI,
|
||||
inTriggeringPrincipal, 0, nullptr,
|
||||
mozilla::net::RP_Unset,
|
||||
nullptr, nullptr,
|
||||
inDestFile, isPrivate);
|
||||
|
@ -342,7 +344,9 @@ nsContentAreaDragDropDataProvider::GetFlavorData(nsITransferable *aTransferable,
|
|||
bool isPrivate;
|
||||
aTransferable->GetIsPrivateData(&isPrivate);
|
||||
|
||||
rv = SaveURIToFile(sourceURI, file, isPrivate);
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
aTransferable->GetRequestingPrincipal(getter_AddRefs(principal));
|
||||
rv = SaveURIToFile(sourceURI, principal, file, isPrivate);
|
||||
// send back an nsIFile
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
CallQueryInterface(file, aData);
|
||||
|
|
|
@ -77,6 +77,7 @@ public:
|
|||
NS_DECL_NSIFLAVORDATAPROVIDER
|
||||
|
||||
nsresult SaveURIToFile(nsIURI* inSourceURI,
|
||||
nsIPrincipal* inTriggeringPrincipal,
|
||||
nsIFile* inDestFile, bool isPrivate);
|
||||
};
|
||||
|
||||
|
|
|
@ -1339,6 +1339,14 @@ nsHTMLDocument::Open(JSContext* cx,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// At this point we know this is a valid-enough document.open() call
|
||||
// and not a no-op. Increment our use counters.
|
||||
SetDocumentAndPageUseCounter(eUseCounter_custom_DocumentOpen);
|
||||
bool isReplace = aReplace.LowerCaseEqualsLiteral("replace");
|
||||
if (isReplace) {
|
||||
SetDocumentAndPageUseCounter(eUseCounter_custom_DocumentOpenReplace);
|
||||
}
|
||||
|
||||
// Stop current loads targeted at the window this document is in.
|
||||
if (mScriptGlobalObject) {
|
||||
nsCOMPtr<nsIContentViewer> cv;
|
||||
|
@ -1567,8 +1575,7 @@ nsHTMLDocument::Open(JSContext* cx,
|
|||
// so, we need to tell the docshell to not create a new history
|
||||
// entry for this load. Otherwise, make sure that we're doing a normal load,
|
||||
// not whatever type of load was previously done on this docshell.
|
||||
shell->SetLoadType(aReplace.LowerCaseEqualsLiteral("replace") ?
|
||||
LOAD_NORMAL_REPLACE : LOAD_NORMAL);
|
||||
shell->SetLoadType(isReplace ? LOAD_NORMAL_REPLACE : LOAD_NORMAL);
|
||||
|
||||
nsCOMPtr<nsIContentViewer> cv;
|
||||
shell->GetContentViewer(getter_AddRefs(cv));
|
||||
|
|
|
@ -197,7 +197,8 @@ typedef DWORD(WINAPI* QueryDosDeviceWFnPtr)(_In_opt_ LPCWSTR lpDeviceName,
|
|||
_Out_ LPWSTR lpTargetPath,
|
||||
_In_ DWORD ucchMax);
|
||||
|
||||
static QueryDosDeviceWFnPtr sOriginalQueryDosDeviceWFnPtr = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<QueryDosDeviceWFnPtr>
|
||||
sOriginalQueryDosDeviceWFnPtr;
|
||||
|
||||
static std::unordered_map<std::wstring, std::wstring>* sDeviceNames = nullptr;
|
||||
|
||||
|
@ -276,9 +277,8 @@ InitializeHooks()
|
|||
}
|
||||
|
||||
sKernel32Intercept.Init("kernelbase.dll");
|
||||
sKernel32Intercept.AddHook("QueryDosDeviceW",
|
||||
reinterpret_cast<intptr_t>(QueryDosDeviceWHook),
|
||||
(void**)(&sOriginalQueryDosDeviceWFnPtr));
|
||||
sOriginalQueryDosDeviceWFnPtr.Set(sKernel32Intercept, "QueryDosDeviceW",
|
||||
&QueryDosDeviceWHook);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -357,8 +357,10 @@ typedef LONG_PTR
|
|||
(WINAPI *User32SetWindowLongPtrW)(HWND hWnd,
|
||||
int nIndex,
|
||||
LONG_PTR dwNewLong);
|
||||
static User32SetWindowLongPtrA sUser32SetWindowLongAHookStub = nullptr;
|
||||
static User32SetWindowLongPtrW sUser32SetWindowLongWHookStub = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrA>
|
||||
sUser32SetWindowLongAHookStub;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrW>
|
||||
sUser32SetWindowLongWHookStub;
|
||||
#else
|
||||
typedef LONG
|
||||
(WINAPI *User32SetWindowLongA)(HWND hWnd,
|
||||
|
@ -368,8 +370,10 @@ typedef LONG
|
|||
(WINAPI *User32SetWindowLongW)(HWND hWnd,
|
||||
int nIndex,
|
||||
LONG dwNewLong);
|
||||
static User32SetWindowLongA sUser32SetWindowLongAHookStub = nullptr;
|
||||
static User32SetWindowLongW sUser32SetWindowLongWHookStub = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongA>
|
||||
sUser32SetWindowLongAHookStub;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongW>
|
||||
sUser32SetWindowLongWHookStub;
|
||||
#endif
|
||||
static inline bool
|
||||
SetWindowLongHookCheck(HWND hWnd,
|
||||
|
@ -448,23 +452,15 @@ HookSetWindowLongPtr()
|
|||
{
|
||||
sUser32Intercept.Init("user32.dll");
|
||||
#ifdef _WIN64
|
||||
if (!sUser32SetWindowLongAHookStub)
|
||||
sUser32Intercept.AddHook("SetWindowLongPtrA",
|
||||
reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
|
||||
(void**) &sUser32SetWindowLongAHookStub);
|
||||
if (!sUser32SetWindowLongWHookStub)
|
||||
sUser32Intercept.AddHook("SetWindowLongPtrW",
|
||||
reinterpret_cast<intptr_t>(SetWindowLongPtrWHook),
|
||||
(void**) &sUser32SetWindowLongWHookStub);
|
||||
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongPtrA",
|
||||
&SetWindowLongPtrAHook);
|
||||
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongPtrW",
|
||||
&SetWindowLongPtrWHook);
|
||||
#else
|
||||
if (!sUser32SetWindowLongAHookStub)
|
||||
sUser32Intercept.AddHook("SetWindowLongA",
|
||||
reinterpret_cast<intptr_t>(SetWindowLongAHook),
|
||||
(void**) &sUser32SetWindowLongAHookStub);
|
||||
if (!sUser32SetWindowLongWHookStub)
|
||||
sUser32Intercept.AddHook("SetWindowLongW",
|
||||
reinterpret_cast<intptr_t>(SetWindowLongWHook),
|
||||
(void**) &sUser32SetWindowLongWHookStub);
|
||||
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongA",
|
||||
&SetWindowLongAHook);
|
||||
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongW",
|
||||
&SetWindowLongWHook);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -168,13 +168,13 @@ typedef HANDLE (WINAPI *CreateFileWPtr)(LPCWSTR aFname, DWORD aAccess,
|
|||
LPSECURITY_ATTRIBUTES aSecurity,
|
||||
DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate);
|
||||
static CreateFileWPtr sCreateFileWStub = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<CreateFileWPtr> sCreateFileWStub;
|
||||
typedef HANDLE (WINAPI *CreateFileAPtr)(LPCSTR aFname, DWORD aAccess,
|
||||
DWORD aShare,
|
||||
LPSECURITY_ATTRIBUTES aSecurity,
|
||||
DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate);
|
||||
static CreateFileAPtr sCreateFileAStub = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<CreateFileAPtr> sCreateFileAStub;
|
||||
|
||||
// Windows 8 RTM (kernelbase's version is 6.2.9200.16384) doesn't call
|
||||
// CreateFileW from CreateFileA.
|
||||
|
@ -263,7 +263,7 @@ CreateFileWHookFn(LPCWSTR aFname, DWORD aAccess, DWORD aShare,
|
|||
aSecurity, TRUNCATE_EXISTING,
|
||||
FILE_ATTRIBUTE_TEMPORARY |
|
||||
FILE_FLAG_DELETE_ON_CLOSE,
|
||||
NULL);
|
||||
nullptr);
|
||||
if (replacement == INVALID_HANDLE_VALUE) {
|
||||
break;
|
||||
}
|
||||
|
@ -300,23 +300,12 @@ CreateFileWHookFn(LPCWSTR aFname, DWORD aAccess, DWORD aShare,
|
|||
|
||||
void FunctionHook::HookProtectedMode()
|
||||
{
|
||||
// Make sure we only do this once.
|
||||
static bool sRunOnce = false;
|
||||
if (sRunOnce) {
|
||||
return;
|
||||
}
|
||||
sRunOnce = true;
|
||||
|
||||
// Legacy code. Uses the nsWindowsDLLInterceptor directly instead of
|
||||
// using the FunctionHook
|
||||
sKernel32Intercept.Init("kernel32.dll");
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Plugin);
|
||||
sKernel32Intercept.AddHook("CreateFileW",
|
||||
reinterpret_cast<intptr_t>(CreateFileWHookFn),
|
||||
(void**) &sCreateFileWStub);
|
||||
sKernel32Intercept.AddHook("CreateFileA",
|
||||
reinterpret_cast<intptr_t>(CreateFileAHookFn),
|
||||
(void**) &sCreateFileAStub);
|
||||
sCreateFileWStub.Set(sKernel32Intercept, "CreateFileW", &CreateFileWHookFn);
|
||||
sCreateFileAStub.Set(sKernel32Intercept, "CreateFileA", &CreateFileAHookFn);
|
||||
}
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "IpdlTuple.h"
|
||||
#include "base/process.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "nsWindowsDllInterceptor.h"
|
||||
|
@ -96,12 +97,19 @@ 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);
|
||||
|
@ -128,7 +136,10 @@ 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.
|
||||
FunctionType* mOldFunction;
|
||||
Atomic<FunctionType*> mOldFunction;
|
||||
#if defined(XP_WIN)
|
||||
FuncHookType mStub;
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
enum RegistrationStatus { UNREGISTERED, FAILED, SUCCEEDED };
|
||||
RegistrationStatus mRegistration;
|
||||
|
@ -170,14 +181,16 @@ BasicFunctionHook<functionId, FunctionType>::Register(int aQuirks)
|
|||
return false;
|
||||
}
|
||||
|
||||
isHooked =
|
||||
dllInterceptor->AddHook(mFunctionName.Data(), reinterpret_cast<intptr_t>(mNewFunction),
|
||||
reinterpret_cast<void**>(&mOldFunction));
|
||||
isHooked = mStub.Set(*dllInterceptor, mFunctionName.Data(), mNewFunction);
|
||||
#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)));
|
||||
|
|
|
@ -73,21 +73,17 @@ typedef BOOL (WINAPI *User32TrackPopupMenu)(HMENU hMenu,
|
|||
CONST RECT *prcRect);
|
||||
static WindowsDllInterceptor sUser32Intercept;
|
||||
static HWND sWinlessPopupSurrogateHWND = nullptr;
|
||||
static User32TrackPopupMenu sUser32TrackPopupMenuStub = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<User32TrackPopupMenu> sUser32TrackPopupMenuStub;
|
||||
|
||||
static WindowsDllInterceptor sImm32Intercept;
|
||||
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 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 PluginInstanceChild* sCurrentPluginInstance = nullptr;
|
||||
static const HIMC sHookIMC = (const HIMC)0xefefefef;
|
||||
static bool sPopupMenuHookSet;
|
||||
static bool sSetWindowLongHookSet;
|
||||
|
||||
using mozilla::gfx::SharedDIB;
|
||||
|
||||
|
@ -1793,8 +1789,8 @@ typedef LONG_PTR
|
|||
(WINAPI *User32SetWindowLongPtrW)(HWND hWnd,
|
||||
int nIndex,
|
||||
LONG_PTR dwNewLong);
|
||||
static User32SetWindowLongPtrA sUser32SetWindowLongAHookStub = nullptr;
|
||||
static User32SetWindowLongPtrW sUser32SetWindowLongWHookStub = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrA> sUser32SetWindowLongAHookStub;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrW> sUser32SetWindowLongWHookStub;
|
||||
#else
|
||||
typedef LONG
|
||||
(WINAPI *User32SetWindowLongA)(HWND hWnd,
|
||||
|
@ -1804,8 +1800,8 @@ typedef LONG
|
|||
(WINAPI *User32SetWindowLongW)(HWND hWnd,
|
||||
int nIndex,
|
||||
LONG dwNewLong);
|
||||
static User32SetWindowLongA sUser32SetWindowLongAHookStub = nullptr;
|
||||
static User32SetWindowLongW sUser32SetWindowLongWHookStub = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongA> sUser32SetWindowLongAHookStub;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongW> sUser32SetWindowLongWHookStub;
|
||||
#endif
|
||||
|
||||
extern LRESULT CALLBACK
|
||||
|
@ -1915,27 +1911,17 @@ PluginInstanceChild::HookSetWindowLongPtr()
|
|||
return;
|
||||
}
|
||||
|
||||
// Only pass through here once
|
||||
if (sSetWindowLongHookSet) {
|
||||
return;
|
||||
}
|
||||
sSetWindowLongHookSet = true;
|
||||
|
||||
sUser32Intercept.Init("user32.dll");
|
||||
#ifdef _WIN64
|
||||
if (!sUser32SetWindowLongAHookStub)
|
||||
sUser32Intercept.AddHook("SetWindowLongPtrA", reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
|
||||
(void**) &sUser32SetWindowLongAHookStub);
|
||||
if (!sUser32SetWindowLongWHookStub)
|
||||
sUser32Intercept.AddHook("SetWindowLongPtrW", reinterpret_cast<intptr_t>(SetWindowLongPtrWHook),
|
||||
(void**) &sUser32SetWindowLongWHookStub);
|
||||
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongPtrA",
|
||||
&SetWindowLongPtrAHook);
|
||||
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongPtrW",
|
||||
&SetWindowLongPtrWHook);
|
||||
#else
|
||||
if (!sUser32SetWindowLongAHookStub)
|
||||
sUser32Intercept.AddHook("SetWindowLongA", reinterpret_cast<intptr_t>(SetWindowLongAHook),
|
||||
(void**) &sUser32SetWindowLongAHookStub);
|
||||
if (!sUser32SetWindowLongWHookStub)
|
||||
sUser32Intercept.AddHook("SetWindowLongW", reinterpret_cast<intptr_t>(SetWindowLongWHook),
|
||||
(void**) &sUser32SetWindowLongWHookStub);
|
||||
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongA",
|
||||
&SetWindowLongAHook);
|
||||
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongW",
|
||||
&SetWindowLongWHook);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -2003,19 +1989,13 @@ PluginInstanceChild::InitPopupMenuHook()
|
|||
return;
|
||||
}
|
||||
|
||||
// Only pass through here once
|
||||
if (sPopupMenuHookSet) {
|
||||
return;
|
||||
}
|
||||
sPopupMenuHookSet = true;
|
||||
|
||||
// Note, once WindowsDllInterceptor is initialized for a module,
|
||||
// it remains initialized for that particular module for it's
|
||||
// lifetime. Additional instances are needed if other modules need
|
||||
// to be hooked.
|
||||
sUser32Intercept.Init("user32.dll");
|
||||
sUser32Intercept.AddHook("TrackPopupMenu", reinterpret_cast<intptr_t>(TrackPopupHookProc),
|
||||
(void**) &sUser32TrackPopupMenuStub);
|
||||
sUser32TrackPopupMenuStub.Set(sUser32Intercept, "TrackPopupMenu",
|
||||
&TrackPopupHookProc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2157,36 +2137,23 @@ PluginInstanceChild::InitImm32Hook()
|
|||
return;
|
||||
}
|
||||
|
||||
if (sImm32ImmGetContextStub) {
|
||||
return;
|
||||
}
|
||||
|
||||
// When using windowless plugin, IMM API won't work due ot OOP.
|
||||
//
|
||||
// ImmReleaseContext on Windows 7+ just returns TRUE only, so we don't
|
||||
// need to hook this.
|
||||
|
||||
sImm32Intercept.Init("imm32.dll");
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -57,6 +57,10 @@ skip-if = !e10s || (os == "win" && processor == "x86") || (verify && debug && (o
|
|||
[browser_localStorage_e10s.js]
|
||||
skip-if = !e10s || verify # This is a test of e10s functionality.
|
||||
[browser_localStorage_privatestorageevent.js]
|
||||
[browser_persist_cookies.js]
|
||||
support-files =
|
||||
set-samesite-cookies-and-redirect.sjs
|
||||
mimeme.sjs
|
||||
[browser_test_focus_after_modal_state.js]
|
||||
skip-if = verify
|
||||
support-files =
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_PATH = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.org");
|
||||
const TEST_PATH2 = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "https://example.com");
|
||||
|
||||
var MockFilePicker = SpecialPowers.MockFilePicker;
|
||||
MockFilePicker.init(window);
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
info("Running the cleanup code");
|
||||
MockFilePicker.cleanup();
|
||||
Services.obs.removeObserver(checkRequest, "http-on-modify-request");
|
||||
if (gTestDir && gTestDir.exists()) {
|
||||
// On Windows, sometimes nsIFile.remove() throws, probably because we're
|
||||
// still writing to the directory we're trying to remove, despite
|
||||
// waiting for the download to complete. Just retry a bit later...
|
||||
let succeeded = false;
|
||||
while (!succeeded) {
|
||||
try {
|
||||
gTestDir.remove(true);
|
||||
succeeded = true;
|
||||
} catch (ex) {
|
||||
await new Promise(requestAnimationFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let gTestDir = null;
|
||||
|
||||
|
||||
function checkRequest(subject) {
|
||||
let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
|
||||
let spec = httpChannel.URI.spec;
|
||||
// Ignore initial requests for page that sets cookies and its favicon, which may not have
|
||||
// cookies.
|
||||
if (httpChannel.URI.host == "example.org" && !spec.endsWith("favicon.ico") && !spec.includes("redirect.sjs")) {
|
||||
let cookie = httpChannel.getRequestHeader("cookie");
|
||||
is(cookie.trim(), "normalCookie=true", "Should have correct cookie in request for " + spec);
|
||||
}
|
||||
}
|
||||
|
||||
function createTemporarySaveDirectory() {
|
||||
var saveDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
|
||||
saveDir.append("testsavedir");
|
||||
if (!saveDir.exists()) {
|
||||
info("create testsavedir!");
|
||||
saveDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
}
|
||||
info("return from createTempSaveDir: " + saveDir.path);
|
||||
return saveDir;
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
await BrowserTestUtils.withNewTab("about:blank", async function(browser) {
|
||||
Services.obs.addObserver(checkRequest, "http-on-modify-request");
|
||||
BrowserTestUtils.loadURI(browser, TEST_PATH + "set-samesite-cookies-and-redirect.sjs");
|
||||
// Test that the original document load doesn't send same-site cookies.
|
||||
await BrowserTestUtils.browserLoaded(browser, true, TEST_PATH2 + "set-samesite-cookies-and-redirect.sjs");
|
||||
// Now check the saved page.
|
||||
// Create the folder the link will be saved into.
|
||||
gTestDir = createTemporarySaveDirectory();
|
||||
let destFile = gTestDir.clone();
|
||||
|
||||
MockFilePicker.displayDirectory = gTestDir;
|
||||
let fileName;
|
||||
MockFilePicker.showCallback = function(fp) {
|
||||
info("showCallback");
|
||||
fileName = fp.defaultString;
|
||||
info("fileName: " + fileName);
|
||||
destFile.append(fileName);
|
||||
info("path: " + destFile.path);
|
||||
MockFilePicker.setFiles([destFile]);
|
||||
MockFilePicker.filterIndex = 0; // kSaveAsType_Complete
|
||||
info("done showCallback");
|
||||
};
|
||||
saveBrowser(browser);
|
||||
await new Promise(async (resolve) => {
|
||||
let dls = await Downloads.getList(Downloads.PUBLIC);
|
||||
dls.addView({
|
||||
onDownloadChanged(download) {
|
||||
if (download.succeeded) {
|
||||
dls.removeView(this);
|
||||
dls.removeFinished();
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,26 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
let mimeType = request.queryString.match(/type=([a-z]*)/)[1];
|
||||
switch (mimeType) {
|
||||
case "css":
|
||||
response.setHeader("Content-Type", "text/css");
|
||||
response.write("#hi {color: red}");
|
||||
break;
|
||||
case "js":
|
||||
response.setHeader("Content-Type", "application/javascript");
|
||||
response.write("var foo;");
|
||||
break;
|
||||
case "png":
|
||||
response.setHeader("Content-Type", "image/png");
|
||||
response.write("");
|
||||
break;
|
||||
case "html":
|
||||
response.setHeader("Content-Type", "text/html");
|
||||
response.write("<body>I am a subframe</body>");
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function handleRequest(request, response) {
|
||||
// Set cookies and redirect for .org:
|
||||
if (request.host.endsWith(".org")) {
|
||||
response.setHeader("Set-Cookie", "normalCookie=true; path=/;", true);
|
||||
response.setHeader("Set-Cookie", "laxHeader=true; path=/; SameSite=Lax", true);
|
||||
response.setHeader("Set-Cookie", "strictHeader=true; path=/; SameSite=Strict", true);
|
||||
response.write(`
|
||||
<head>
|
||||
<meta http-equiv='set-cookie' content='laxMeta=true; path=/; SameSite=Lax'>
|
||||
<meta http-equiv='set-cookie' content='strictMeta=true; path=/; SameSite=Strict'>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
document.cookie = 'laxScript=true; path=/; SameSite=Lax';
|
||||
document.cookie = 'strictScript=true; path=/; SameSite=Strict';
|
||||
location.href = location.href.replace(/\.org/, ".com");
|
||||
</script>
|
||||
</body>`);
|
||||
} else {
|
||||
let baseURI = "https://example.org/" + request.path.replace(/[a-z-]*\.sjs/, "mimeme.sjs?type=");
|
||||
response.write(`
|
||||
<link rel="stylesheet" type="text/css" href="${baseURI}css">
|
||||
<iframe src="${baseURI}html"></iframe>
|
||||
<script src="${baseURI}js"></script>
|
||||
<img src="${baseURI}png">
|
||||
`);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ include protocol PFileDescriptorSet;
|
|||
include protocol PChildToParentStream; //FIXME: bug #792908
|
||||
include protocol PParentToChildStream; //FIXME: bug #792908
|
||||
|
||||
include PBackgroundSharedTypes;
|
||||
include IPCStream;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -29,6 +30,7 @@ struct WebBrowserPersistDocumentAttrs {
|
|||
nsString contentDisposition;
|
||||
uint32_t cacheKey;
|
||||
uint32_t persistFlags;
|
||||
PrincipalInfo principal;
|
||||
};
|
||||
|
||||
// IPDL doesn't have tuples, so this gives the pair of strings from
|
||||
|
|
|
@ -41,6 +41,7 @@ WebBrowserPersistDocumentChild::Start(nsIWebBrowserPersistDocument* aDocument)
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
WebBrowserPersistDocumentAttrs attrs;
|
||||
nsCOMPtr<nsIInputStream> postDataStream;
|
||||
#define ENSURE(e) do { \
|
||||
|
@ -60,6 +61,10 @@ WebBrowserPersistDocumentChild::Start(nsIWebBrowserPersistDocument* aDocument)
|
|||
ENSURE(aDocument->GetContentDisposition(attrs.contentDisposition()));
|
||||
ENSURE(aDocument->GetCacheKey(&(attrs.cacheKey())));
|
||||
ENSURE(aDocument->GetPersistFlags(&(attrs.persistFlags())));
|
||||
|
||||
ENSURE(aDocument->GetPrincipal(getter_AddRefs(principal)));
|
||||
ENSURE(ipc::PrincipalToPrincipalInfo(principal, &(attrs.principal())));
|
||||
|
||||
ENSURE(aDocument->GetPostData(getter_AddRefs(postDataStream)));
|
||||
#undef ENSURE
|
||||
|
||||
|
|
|
@ -184,6 +184,14 @@ WebBrowserPersistLocalDocument::GetPostData(nsIInputStream** aStream)
|
|||
return history->GetPostData(aStream);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebBrowserPersistLocalDocument::GetPrincipal(nsIPrincipal** aPrincipal)
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> nodePrincipal = mDocument->NodePrincipal();
|
||||
nodePrincipal.forget(aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsISHEntry>
|
||||
WebBrowserPersistLocalDocument::GetHistory()
|
||||
{
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include "WebBrowserPersistResourcesParent.h"
|
||||
#include "WebBrowserPersistSerializeParent.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/ipc/BackgroundUtils.h"
|
||||
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -23,6 +26,8 @@ WebBrowserPersistRemoteDocument
|
|||
, mAttrs(aAttrs)
|
||||
, mPostData(aPostData)
|
||||
{
|
||||
nsresult rv;
|
||||
mPrincipal = ipc::PrincipalInfoToPrincipal(mAttrs.principal(), &rv);
|
||||
}
|
||||
|
||||
WebBrowserPersistRemoteDocument::~WebBrowserPersistRemoteDocument()
|
||||
|
@ -132,6 +137,14 @@ WebBrowserPersistRemoteDocument::GetPostData(nsIInputStream** aStream)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebBrowserPersistRemoteDocument::GetPrincipal(nsIPrincipal** aPrincipal)
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> nodePrincipal = mPrincipal;
|
||||
nodePrincipal.forget(aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WebBrowserPersistRemoteDocument::ReadResources(nsIWebBrowserPersistResourceVisitor* aVisitor)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "nsIWebBrowserPersistDocument.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
class nsIPrincipal;
|
||||
|
||||
// This class is the XPCOM half of the glue between the
|
||||
// nsIWebBrowserPersistDocument interface and a remote document; it is
|
||||
// created by WebBrowserPersistDocumentParent when (and if) it
|
||||
|
@ -40,6 +42,7 @@ private:
|
|||
WebBrowserPersistDocumentParent* mActor;
|
||||
Attrs mAttrs;
|
||||
nsCOMPtr<nsIInputStream> mPostData;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
|
||||
friend class WebBrowserPersistDocumentParent;
|
||||
WebBrowserPersistRemoteDocument(WebBrowserPersistDocumentParent* aActor,
|
||||
|
|
|
@ -12,6 +12,7 @@ interface nsIWebProgressListener;
|
|||
interface nsIFile;
|
||||
interface nsIChannel;
|
||||
interface nsILoadContext;
|
||||
interface nsIPrincipal;
|
||||
|
||||
/**
|
||||
* Interface for persisting DOM documents and URIs to local or remote storage.
|
||||
|
@ -65,12 +66,6 @@ interface nsIWebBrowserPersist : nsICancelable
|
|||
*/
|
||||
const unsigned long PERSIST_FLAGS_APPEND_TO_FILE = 32768;
|
||||
|
||||
/**
|
||||
* Force relevant cookies to be sent with this load even if normally they
|
||||
* wouldn't be.
|
||||
*/
|
||||
const unsigned long PERSIST_FLAGS_FORCE_ALLOW_COOKIES = 65536;
|
||||
|
||||
/**
|
||||
* Flags governing how data is fetched and saved from the network.
|
||||
* It is best to set this value explicitly unless you are prepared
|
||||
|
@ -116,6 +111,8 @@ interface nsIWebBrowserPersist : nsICancelable
|
|||
* @param aURI URI to save to file. Some implementations of this interface
|
||||
* may also support <CODE>nullptr</CODE> to imply the currently
|
||||
* loaded URI.
|
||||
* @param aTriggeringPrincipal
|
||||
* The triggering principal for the URI we're saving.
|
||||
* @param aCacheKey The necko cache key integer.
|
||||
* @param aReferrer The referrer URI to pass with an HTTP request or
|
||||
* <CODE>nullptr</CODE>.
|
||||
|
@ -142,7 +139,8 @@ interface nsIWebBrowserPersist : nsICancelable
|
|||
*
|
||||
* @throws NS_ERROR_INVALID_ARG One or more arguments was invalid.
|
||||
*/
|
||||
void saveURI(in nsIURI aURI, in unsigned long aCacheKey,
|
||||
void saveURI(in nsIURI aURI, in nsIPrincipal aTriggeringPrincipal,
|
||||
in unsigned long aCacheKey,
|
||||
in nsIURI aReferrer, in unsigned long aReferrerPolicy,
|
||||
in nsIInputStream aPostData,
|
||||
in string aExtraHeaders, in nsISupports aFile,
|
||||
|
@ -154,7 +152,8 @@ interface nsIWebBrowserPersist : nsICancelable
|
|||
* of intermediate data, etc.)
|
||||
* @see saveURI for all other parameter descriptions
|
||||
*/
|
||||
void savePrivacyAwareURI(in nsIURI aURI, in unsigned long aCacheKey,
|
||||
void savePrivacyAwareURI(in nsIURI aURI,
|
||||
in nsIPrincipal aTriggeringPrincipal, in unsigned long aCacheKey,
|
||||
in nsIURI aReferrer, in unsigned long aReferrerPolicy,
|
||||
in nsIInputStream aPostData,
|
||||
in string aExtraHeaders, in nsISupports aFile,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
interface nsIInputStream;
|
||||
interface nsIOutputStream;
|
||||
interface nsIPrincipal;
|
||||
interface nsITabParent;
|
||||
interface nsIWebBrowserPersistResourceVisitor;
|
||||
interface nsIWebBrowserPersistWriteCompletion;
|
||||
|
@ -60,6 +61,7 @@ interface nsIWebBrowserPersistDocument : nsISupports
|
|||
readonly attribute AString referrer;
|
||||
readonly attribute AString contentDisposition;
|
||||
readonly attribute nsIInputStream postData;
|
||||
readonly attribute nsIPrincipal principal;
|
||||
|
||||
/**
|
||||
* The cache key. Unlike in nsISHEntry, where it's wrapped in an
|
||||
|
|
|
@ -83,6 +83,7 @@ struct nsWebBrowserPersist::DocData
|
|||
nsCOMPtr<nsIURI> mBaseURI;
|
||||
nsCOMPtr<nsIWebBrowserPersistDocument> mDocument;
|
||||
nsCOMPtr<nsIURI> mFile;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
nsCString mCharset;
|
||||
};
|
||||
|
||||
|
@ -413,18 +414,20 @@ NS_IMETHODIMP nsWebBrowserPersist::SetProgressListener(
|
|||
}
|
||||
|
||||
NS_IMETHODIMP nsWebBrowserPersist::SaveURI(
|
||||
nsIURI *aURI, uint32_t aCacheKey,
|
||||
nsIURI *aURI, nsIPrincipal *aPrincipal, uint32_t aCacheKey,
|
||||
nsIURI *aReferrer, uint32_t aReferrerPolicy,
|
||||
nsIInputStream *aPostData, const char *aExtraHeaders,
|
||||
nsISupports *aFile, nsILoadContext* aPrivacyContext)
|
||||
{
|
||||
return SavePrivacyAwareURI(aURI, aCacheKey, aReferrer, aReferrerPolicy,
|
||||
aPostData, aExtraHeaders, aFile,
|
||||
aPrivacyContext && aPrivacyContext->UsePrivateBrowsing());
|
||||
bool isPrivate =
|
||||
aPrivacyContext && aPrivacyContext->UsePrivateBrowsing();
|
||||
return SavePrivacyAwareURI(aURI, aPrincipal, aCacheKey,
|
||||
aReferrer, aReferrerPolicy,
|
||||
aPostData, aExtraHeaders, aFile, isPrivate);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsWebBrowserPersist::SavePrivacyAwareURI(
|
||||
nsIURI *aURI, uint32_t aCacheKey,
|
||||
nsIURI *aURI, nsIPrincipal *aPrincipal, uint32_t aCacheKey,
|
||||
nsIURI *aReferrer, uint32_t aReferrerPolicy,
|
||||
nsIInputStream *aPostData, const char *aExtraHeaders,
|
||||
nsISupports *aFile, bool aIsPrivate)
|
||||
|
@ -439,8 +442,10 @@ NS_IMETHODIMP nsWebBrowserPersist::SavePrivacyAwareURI(
|
|||
|
||||
// SaveURI doesn't like broken uris.
|
||||
mPersistFlags |= PERSIST_FLAGS_FAIL_ON_BROKEN_LINKS;
|
||||
rv = SaveURIInternal(aURI, aCacheKey, aReferrer, aReferrerPolicy,
|
||||
aPostData, aExtraHeaders, fileAsURI, false, aIsPrivate);
|
||||
rv = SaveURIInternal(aURI, aPrincipal, aCacheKey,
|
||||
aReferrer, aReferrerPolicy,
|
||||
aPostData, aExtraHeaders, fileAsURI,
|
||||
false, aIsPrivate);
|
||||
return NS_FAILED(rv) ? rv : NS_OK;
|
||||
}
|
||||
|
||||
|
@ -599,6 +604,13 @@ nsWebBrowserPersist::SerializeNextFile()
|
|||
}
|
||||
|
||||
if (urisToPersist > 0) {
|
||||
nsCOMPtr<nsIPrincipal> docPrincipal;
|
||||
//XXXgijs I *think* this is already always true, but let's be sure.
|
||||
MOZ_ASSERT(mDocList.Length() > 0,
|
||||
"Should have the document for any walked URIs to persist!");
|
||||
nsresult rv = mDocList.ElementAt(0)->mDocument->
|
||||
GetPrincipal(getter_AddRefs(docPrincipal));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
// Persist each file in the uri map. The document(s)
|
||||
// will be saved after the last one of these is saved.
|
||||
for (auto iter = mURIMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
|
@ -608,8 +620,6 @@ nsWebBrowserPersist::SerializeNextFile()
|
|||
continue;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Create a URI from the key.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), iter.Key(),
|
||||
|
@ -627,7 +637,7 @@ nsWebBrowserPersist::SerializeNextFile()
|
|||
|
||||
// The Referrer Policy doesn't matter here since the referrer is
|
||||
// nullptr.
|
||||
rv = SaveURIInternal(uri, 0, nullptr,
|
||||
rv = SaveURIInternal(uri, docPrincipal, 0, nullptr,
|
||||
mozilla::net::RP_Unset, nullptr, nullptr,
|
||||
fileAsURI, true, mIsPrivate);
|
||||
// If SaveURIInternal fails, then it will have called EndDownload,
|
||||
|
@ -1324,7 +1334,8 @@ nsWebBrowserPersist::AppendPathToURI(nsIURI *aURI, const nsAString & aPath, nsCO
|
|||
}
|
||||
|
||||
nsresult nsWebBrowserPersist::SaveURIInternal(
|
||||
nsIURI *aURI, uint32_t aCacheKey, nsIURI *aReferrer,
|
||||
nsIURI *aURI, nsIPrincipal* aTriggeringPrincipal,
|
||||
uint32_t aCacheKey, nsIURI *aReferrer,
|
||||
uint32_t aReferrerPolicy, nsIInputStream *aPostData,
|
||||
const char *aExtraHeaders, nsIURI *aFile,
|
||||
bool aCalcFileExt, bool aIsPrivate)
|
||||
|
@ -1350,7 +1361,7 @@ nsresult nsWebBrowserPersist::SaveURIInternal(
|
|||
nsCOMPtr<nsIChannel> inputChannel;
|
||||
rv = NS_NewChannel(getter_AddRefs(inputChannel),
|
||||
aURI,
|
||||
nsContentUtils::GetSystemPrincipal(),
|
||||
aTriggeringPrincipal,
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
nullptr, // aPerformanceStorage
|
||||
|
@ -1380,16 +1391,6 @@ nsresult nsWebBrowserPersist::SaveURIInternal(
|
|||
}
|
||||
}
|
||||
|
||||
if (mPersistFlags & PERSIST_FLAGS_FORCE_ALLOW_COOKIES)
|
||||
{
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
|
||||
do_QueryInterface(inputChannel);
|
||||
if (httpChannelInternal) {
|
||||
rv = httpChannelInternal->SetThirdPartyFlags(nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
}
|
||||
|
||||
// Set the referrer, post data and headers if any
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(inputChannel));
|
||||
if (httpChannel)
|
||||
|
|
|
@ -57,7 +57,8 @@ public:
|
|||
private:
|
||||
virtual ~nsWebBrowserPersist();
|
||||
nsresult SaveURIInternal(
|
||||
nsIURI *aURI, uint32_t aCacheKey, nsIURI *aReferrer,
|
||||
nsIURI *aURI, nsIPrincipal* aTriggeringPrincipal,
|
||||
uint32_t aCacheKey, nsIURI *aReferrer,
|
||||
uint32_t aReferrerPolicy, nsIInputStream *aPostData,
|
||||
const char *aExtraHeaders, nsIURI *aFile,
|
||||
bool aCalcFileExt, bool aIsPrivate);
|
||||
|
|
|
@ -162,7 +162,7 @@ struct ParamTraits<mozilla::mscom::COMPtrHolder<Interface, _IID>>
|
|||
const bool sIsStreamPreservationNeeded = false;
|
||||
#endif // defined(MOZ_CONTENT_SANDBOX)
|
||||
|
||||
paramType::EnvType env;
|
||||
typename paramType::EnvType env;
|
||||
|
||||
mozilla::mscom::ProxyStreamFlags flags = sIsStreamPreservationNeeded ?
|
||||
mozilla::mscom::ProxyStreamFlags::ePreservable :
|
||||
|
|
|
@ -244,7 +244,7 @@ Interceptor::Create(STAUniquePtr<IUnknown> aTarget, IInterceptorSink* aSink,
|
|||
|
||||
detail::LiveSetAutoLock lock(GetLiveSet());
|
||||
|
||||
RefPtr<IWeakReference> existingWeak(std::move(GetLiveSet().Get(aTarget.get())));
|
||||
RefPtr<IWeakReference> existingWeak(GetLiveSet().Get(aTarget.get()));
|
||||
if (existingWeak) {
|
||||
RefPtr<IWeakReferenceSource> existingStrong;
|
||||
if (SUCCEEDED(existingWeak->ToStrongRef(getter_AddRefs(existingStrong)))) {
|
||||
|
@ -891,7 +891,7 @@ Interceptor::DisconnectRemotesForTarget(IUnknown* aTarget)
|
|||
|
||||
// It is not an error if the interceptor doesn't exist, so we return
|
||||
// S_FALSE instead of an error in that case.
|
||||
RefPtr<IWeakReference> existingWeak(std::move(GetLiveSet().Get(aTarget)));
|
||||
RefPtr<IWeakReference> existingWeak(GetLiveSet().Get(aTarget));
|
||||
if (!existingWeak) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
|
|
@ -2952,6 +2952,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
|
||||
}
|
||||
|
||||
|
||||
bool needsActiveOpacityLayer = false;
|
||||
// We build an opacity item if it's not going to be drawn by SVG content, or
|
||||
// SVG effects. SVG effects won't handle the opacity if we want an active
|
||||
// layer (for async animations), see
|
||||
|
@ -2959,7 +2961,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
// nsSVGIntegrationsUtils::PaintFilter.
|
||||
bool useOpacity = HasVisualOpacity(effectSet) &&
|
||||
!nsSVGUtils::CanOptimizeOpacity(this) &&
|
||||
(!usingSVGEffects || nsDisplayOpacity::NeedsActiveLayer(aBuilder, this));
|
||||
((needsActiveOpacityLayer = nsDisplayOpacity::NeedsActiveLayer(aBuilder, this)) || !usingSVGEffects);
|
||||
bool useBlendMode = effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
|
||||
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
|
||||
IsScrollFrameActive(aBuilder,
|
||||
|
@ -3259,9 +3261,10 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
// all descendant content, but some should not be clipped.
|
||||
DisplayListClipState::AutoSaveRestore opacityClipState(aBuilder);
|
||||
resultList.AppendToTop(
|
||||
MakeDisplayItem<nsDisplayOpacity>(aBuilder, this, &resultList,
|
||||
MakeDisplayItem<nsDisplayOpacity>(aBuilder, this, &resultList,
|
||||
containerItemASR,
|
||||
opacityItemForEventsAndPluginsOnly));
|
||||
opacityItemForEventsAndPluginsOnly,
|
||||
needsActiveOpacityLayer));
|
||||
if (aCreatedContainerItem) {
|
||||
*aCreatedContainerItem = true;
|
||||
}
|
||||
|
|
|
@ -297,6 +297,7 @@ public:
|
|||
aNewItem->GetChildren(),
|
||||
containerASRForChildren,
|
||||
aNewItem->GetPerFrameKey())) {
|
||||
aNewItem->InvalidateCachedChildInfo();
|
||||
mResultIsModified = true;
|
||||
|
||||
}
|
||||
|
@ -401,6 +402,7 @@ public:
|
|||
nsDisplayList empty;
|
||||
if (mBuilder->MergeDisplayLists(&empty, item->GetChildren(), item->GetChildren(),
|
||||
containerASRForChildren, item->GetPerFrameKey())) {
|
||||
item->InvalidateCachedChildInfo();
|
||||
mResultIsModified = true;
|
||||
}
|
||||
UpdateASR(item, containerASRForChildren);
|
||||
|
|
|
@ -6237,11 +6237,13 @@ nsresult nsDisplayWrapper::WrapListsInPlace(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayOpacity::nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
const ActiveScrolledRoot* aActiveScrolledRoot,
|
||||
bool aForEventsAndPluginsOnly)
|
||||
bool aForEventsAndPluginsOnly,
|
||||
bool aNeedsActiveLayer)
|
||||
: nsDisplayWrapList(aBuilder, aFrame, aList, aActiveScrolledRoot, true)
|
||||
, mOpacity(aFrame->StyleEffects()->mOpacity)
|
||||
, mForEventsAndPluginsOnly(aForEventsAndPluginsOnly)
|
||||
, mOpacityAppliedToChildren(false)
|
||||
, mNeedsActiveLayer(aNeedsActiveLayer)
|
||||
, mChildOpacityState(ChildOpacityState::Unknown)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayOpacity);
|
||||
mState.mOpacity = mOpacity;
|
||||
|
@ -6378,6 +6380,10 @@ CollectItemsWithOpacity(nsDisplayList* aList,
|
|||
bool
|
||||
nsDisplayOpacity::ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
if (mChildOpacityState == ChildOpacityState::Deferred) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only try folding our opacity down if we have at most kMaxChildCount
|
||||
// children that don't overlap and can all apply the opacity to themselves.
|
||||
static const size_t kMaxChildCount = 3;
|
||||
|
@ -6386,6 +6392,7 @@ nsDisplayOpacity::ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder)
|
|||
// child display item pointers to a temporary list.
|
||||
AutoTArray<nsDisplayItem*, kMaxChildCount> items;
|
||||
if (!CollectItemsWithOpacity(&mList, items, kMaxChildCount)) {
|
||||
mChildOpacityState = ChildOpacityState::Deferred;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -6405,6 +6412,7 @@ nsDisplayOpacity::ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder)
|
|||
for (size_t i = 0; i < childCount; i++) {
|
||||
for (size_t j = i+1; j < childCount; j++) {
|
||||
if (children[i].bounds.Intersects(children[j].bounds)) {
|
||||
mChildOpacityState = ChildOpacityState::Deferred;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -6414,16 +6422,13 @@ nsDisplayOpacity::ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder)
|
|||
children[i].item->ApplyOpacity(aBuilder, mOpacity, mClipChain);
|
||||
}
|
||||
|
||||
mOpacityAppliedToChildren = true;
|
||||
mChildOpacityState = ChildOpacityState::Applied;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayOpacity::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
// ShouldFlattenAway() should be called only once during painting.
|
||||
MOZ_ASSERT(!mOpacityAppliedToChildren);
|
||||
|
||||
if (mFrame->GetPrevContinuation() || mFrame->GetNextContinuation() ||
|
||||
mFrame->HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT)) {
|
||||
// If we've been split, then we might need to merge, so
|
||||
|
@ -6431,7 +6436,7 @@ nsDisplayOpacity::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (NeedsActiveLayer(aBuilder, mFrame) || mOpacity == 0.0) {
|
||||
if (mNeedsActiveLayer || mOpacity == 0.0) {
|
||||
// If our opacity is zero then we'll discard all descendant display items
|
||||
// except for layer event regions, so there's no point in doing this
|
||||
// optimization (and if we do do it, then invalidations of those descendants
|
||||
|
@ -6461,7 +6466,7 @@ nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
|
|||
return LAYER_INACTIVE;
|
||||
}
|
||||
|
||||
if (NeedsActiveLayer(aBuilder, mFrame)) {
|
||||
if (mNeedsActiveLayer) {
|
||||
// Returns LAYER_ACTIVE_FORCE to avoid flatterning the layer for async
|
||||
// animations.
|
||||
return LAYER_ACTIVE_FORCE;
|
||||
|
@ -6649,7 +6654,7 @@ nsDisplayBlendMode::CanMerge(const nsDisplayItem* aItem) const
|
|||
{
|
||||
// Items for the same content element should be merged into a single
|
||||
// compositing group.
|
||||
if (!HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
|
||||
if (!HasDifferentFrame(aItem) || !HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -9365,7 +9370,7 @@ nsDisplayMask::CanMerge(const nsDisplayItem* aItem) const
|
|||
{
|
||||
// Items for the same content element should be merged into a single
|
||||
// compositing group.
|
||||
if (!HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
|
||||
if (!HasDifferentFrame(aItem) || !HasSameTypeAndClip(aItem) || !HasSameContent(aItem)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2372,6 +2372,12 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called when an item's list of children has been omdified
|
||||
* by RetaineDisplayListBuilder.
|
||||
*/
|
||||
virtual void InvalidateCachedChildInfo() {}
|
||||
|
||||
/**
|
||||
* @param aSnap set to true if the edges of the rectangles of the opaque
|
||||
* region would be snapped to device pixels when drawing
|
||||
|
@ -2785,6 +2791,11 @@ public:
|
|||
return mBackfaceHidden;
|
||||
}
|
||||
|
||||
bool HasDifferentFrame(const nsDisplayItem* aOther) const
|
||||
{
|
||||
return mFrame != aOther->mFrame;
|
||||
}
|
||||
|
||||
bool HasSameTypeAndClip(const nsDisplayItem* aOther) const
|
||||
{
|
||||
return GetPerFrameKey() == aOther->GetPerFrameKey() &&
|
||||
|
@ -4967,6 +4978,7 @@ public:
|
|||
virtual void Merge(const nsDisplayItem* aItem) override
|
||||
{
|
||||
MOZ_ASSERT(CanMerge(aItem));
|
||||
MOZ_ASSERT(Frame() != aItem->Frame());
|
||||
MergeFromTrackingMergedFrames(static_cast<const nsDisplayWrapList*>(aItem));
|
||||
}
|
||||
|
||||
|
@ -5115,17 +5127,19 @@ public:
|
|||
nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList,
|
||||
const ActiveScrolledRoot* aActiveScrolledRoot,
|
||||
bool aForEventsAndPluginsOnly);
|
||||
bool aForEventsAndPluginsOnly,
|
||||
bool aNeedsActiveLayer);
|
||||
|
||||
nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
|
||||
const nsDisplayOpacity& aOther)
|
||||
: nsDisplayWrapList(aBuilder, aOther)
|
||||
, mOpacity(aOther.mOpacity)
|
||||
, mForEventsAndPluginsOnly(aOther.mForEventsAndPluginsOnly)
|
||||
, mOpacityAppliedToChildren(false)
|
||||
, mNeedsActiveLayer(aOther.mNeedsActiveLayer)
|
||||
, mChildOpacityState(ChildOpacityState::Unknown)
|
||||
{
|
||||
// We should not try to merge flattened opacities.
|
||||
MOZ_ASSERT(!aOther.mOpacityAppliedToChildren);
|
||||
MOZ_ASSERT(aOther.mChildOpacityState != ChildOpacityState::Applied);
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
|
@ -5136,7 +5150,6 @@ public:
|
|||
{
|
||||
nsDisplayItem::RestoreState();
|
||||
mOpacity = mState.mOpacity;
|
||||
mOpacityAppliedToChildren = false;
|
||||
}
|
||||
|
||||
virtual nsDisplayWrapList* Clone(nsDisplayListBuilder* aBuilder) const override
|
||||
|
@ -5145,6 +5158,8 @@ public:
|
|||
return MakeDisplayItem<nsDisplayOpacity>(aBuilder, *this);
|
||||
}
|
||||
|
||||
virtual void InvalidateCachedChildInfo() override { mChildOpacityState = ChildOpacityState::Unknown; }
|
||||
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap) const override;
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
|
@ -5161,7 +5176,7 @@ public:
|
|||
// items for the same content element should be merged into a single
|
||||
// compositing group
|
||||
// aItem->GetUnderlyingFrame() returns non-null because it's nsDisplayOpacity
|
||||
return HasSameTypeAndClip(aItem) && HasSameContent(aItem);
|
||||
return HasDifferentFrame(aItem) && HasSameTypeAndClip(aItem) && HasSameContent(aItem);
|
||||
}
|
||||
|
||||
virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) override
|
||||
|
@ -5189,7 +5204,7 @@ public:
|
|||
/**
|
||||
* Returns true if ShouldFlattenAway() applied opacity to children.
|
||||
*/
|
||||
bool OpacityAppliedToChildren() const { return mOpacityAppliedToChildren; }
|
||||
bool OpacityAppliedToChildren() const { return mChildOpacityState == ChildOpacityState::Applied; }
|
||||
|
||||
static bool NeedsActiveLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
|
||||
NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
|
||||
|
@ -5209,8 +5224,21 @@ private:
|
|||
bool ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
float mOpacity;
|
||||
bool mForEventsAndPluginsOnly;
|
||||
bool mOpacityAppliedToChildren;
|
||||
bool mForEventsAndPluginsOnly : 1;
|
||||
enum class ChildOpacityState : uint8_t {
|
||||
// Our child list has changed since the last time ApplyOpacityToChildren was called.
|
||||
Unknown,
|
||||
// Our children defer opacity handling to us.
|
||||
Deferred,
|
||||
// Opacity is applied to our children.
|
||||
Applied
|
||||
};
|
||||
bool mNeedsActiveLayer : 1;
|
||||
#ifndef __GNUC__
|
||||
ChildOpacityState mChildOpacityState : 2;
|
||||
#else
|
||||
ChildOpacityState mChildOpacityState;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
float mOpacity;
|
||||
|
@ -5381,7 +5409,7 @@ public:
|
|||
{
|
||||
// Items for the same content element should be merged into a single
|
||||
// compositing group.
|
||||
return HasSameTypeAndClip(aItem) && HasSameContent(aItem)
|
||||
return HasDifferentFrame(aItem) && HasSameTypeAndClip(aItem) && HasSameContent(aItem)
|
||||
&& mIsForBackground == static_cast<const nsDisplayBlendContainer*>(aItem)->mIsForBackground;
|
||||
}
|
||||
|
||||
|
@ -6136,7 +6164,7 @@ public:
|
|||
{
|
||||
// Items for the same content element should be merged into a single
|
||||
// compositing group.
|
||||
return HasSameTypeAndClip(aItem) && HasSameContent(aItem);
|
||||
return HasDifferentFrame(aItem) && HasSameTypeAndClip(aItem) && HasSameContent(aItem);
|
||||
}
|
||||
|
||||
virtual void Merge(const nsDisplayItem* aItem) override
|
||||
|
|
|
@ -90,14 +90,14 @@ printf_stderr(const char *fmt, ...)
|
|||
|
||||
|
||||
typedef MOZ_NORETURN_PTR void (__fastcall* BaseThreadInitThunk_func)(BOOL aIsInitialThread, void* aStartAddress, void* aThreadParam);
|
||||
static BaseThreadInitThunk_func stub_BaseThreadInitThunk = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<BaseThreadInitThunk_func> stub_BaseThreadInitThunk;
|
||||
|
||||
typedef NTSTATUS (NTAPI *LdrLoadDll_func) (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle);
|
||||
static LdrLoadDll_func stub_LdrLoadDll;
|
||||
static WindowsDllInterceptor::FuncHookType<LdrLoadDll_func> stub_LdrLoadDll;
|
||||
|
||||
#ifdef _M_AMD64
|
||||
typedef decltype(RtlInstallFunctionTableCallback)* RtlInstallFunctionTableCallback_func;
|
||||
static RtlInstallFunctionTableCallback_func stub_RtlInstallFunctionTableCallback;
|
||||
static WindowsDllInterceptor::FuncHookType<RtlInstallFunctionTableCallback_func> stub_RtlInstallFunctionTableCallback;
|
||||
|
||||
extern uint8_t* sMsMpegJitCodeRegionStart;
|
||||
extern size_t sMsMpegJitCodeRegionSize;
|
||||
|
@ -662,7 +662,8 @@ DllBlocklist_Initialize(uint32_t aInitFlags)
|
|||
// We specifically use a detour, because there are cases where external
|
||||
// code also tries to hook LdrLoadDll, and doesn't know how to relocate our
|
||||
// nop space patches. (Bug 951827)
|
||||
bool ok = NtDllIntercept.AddDetour("LdrLoadDll", reinterpret_cast<intptr_t>(patched_LdrLoadDll), (void**) &stub_LdrLoadDll);
|
||||
bool ok = stub_LdrLoadDll.SetDetour(NtDllIntercept, "LdrLoadDll",
|
||||
&patched_LdrLoadDll);
|
||||
|
||||
if (!ok) {
|
||||
sBlocklistInitFailed = true;
|
||||
|
@ -683,18 +684,18 @@ DllBlocklist_Initialize(uint32_t aInitFlags)
|
|||
#ifdef _M_AMD64
|
||||
if (!IsWin8OrLater()) {
|
||||
// The crash that this hook works around is only seen on Win7.
|
||||
Kernel32Intercept.AddHook("RtlInstallFunctionTableCallback",
|
||||
reinterpret_cast<intptr_t>(patched_RtlInstallFunctionTableCallback),
|
||||
(void**)&stub_RtlInstallFunctionTableCallback);
|
||||
stub_RtlInstallFunctionTableCallback.Set(Kernel32Intercept,
|
||||
"RtlInstallFunctionTableCallback",
|
||||
&patched_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(!Kernel32Intercept.AddDetour("BaseThreadInitThunk",
|
||||
reinterpret_cast<intptr_t>(patched_BaseThreadInitThunk),
|
||||
(void**) &stub_BaseThreadInitThunk)) {
|
||||
if (!stub_BaseThreadInitThunk.SetDetour(Kernel32Intercept,
|
||||
"BaseThreadInitThunk",
|
||||
&patched_BaseThreadInitThunk)) {
|
||||
#ifdef DEBUG
|
||||
printf_stderr("BaseThreadInitThunk hook failed\n");
|
||||
#endif
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
|
||||
void Clear()
|
||||
{
|
||||
if (!mVMPolicy.ShouldUnhookUponDestruction()) {
|
||||
if (!this->mVMPolicy.ShouldUnhookUponDestruction()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ public:
|
|||
#error "Unknown processor type"
|
||||
#endif
|
||||
|
||||
const auto& tramps = mVMPolicy.Items();
|
||||
const auto& tramps = this->mVMPolicy.Items();
|
||||
for (auto&& tramp : tramps) {
|
||||
// First we read the pointer to the interceptor instance.
|
||||
Maybe<uintptr_t> instance = tramp.ReadEncodedPointer();
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
continue;
|
||||
}
|
||||
|
||||
WritableTargetFunction<MMPolicyT> origBytes(mVMPolicy,
|
||||
WritableTargetFunction<MMPolicyT> origBytes(this->mVMPolicy,
|
||||
interceptedFn.value(), nBytes);
|
||||
if (!origBytes) {
|
||||
continue;
|
||||
|
@ -135,7 +135,7 @@ public:
|
|||
origBytes.Commit();
|
||||
}
|
||||
|
||||
mVMPolicy.Clear();
|
||||
this->mVMPolicy.Clear();
|
||||
}
|
||||
|
||||
void Init(int aNumHooks = 0)
|
||||
|
@ -148,20 +148,20 @@ public:
|
|||
// Win32 allocates VM addresses at a 64KiB granularity, so by default we
|
||||
// might as well utilize that entire 64KiB reservation instead of
|
||||
// artifically constraining ourselves to the page size.
|
||||
aNumHooks = mVMPolicy.GetAllocGranularity() / kHookSize;
|
||||
aNumHooks = this->mVMPolicy.GetAllocGranularity() / kHookSize;
|
||||
}
|
||||
|
||||
mVMPolicy.Reserve(aNumHooks);
|
||||
this->mVMPolicy.Reserve(aNumHooks);
|
||||
}
|
||||
|
||||
bool Initialized() const
|
||||
{
|
||||
return !!mVMPolicy;
|
||||
return !!this->mVMPolicy;
|
||||
}
|
||||
|
||||
bool AddHook(FARPROC aTargetFn, intptr_t aHookDest, void** aOrigFunc)
|
||||
{
|
||||
ReadOnlyTargetFunction<MMPolicyT> target(ResolveRedirectedAddress(aTargetFn));
|
||||
ReadOnlyTargetFunction<MMPolicyT> target(this->ResolveRedirectedAddress(aTargetFn));
|
||||
|
||||
CreateTrampoline(target, aHookDest, aOrigFunc);
|
||||
if (!*aOrigFunc) {
|
||||
|
|
|
@ -34,13 +34,13 @@ public:
|
|||
Trampoline<MMPolicy> GetNextTrampoline()
|
||||
{
|
||||
uint32_t offset = mNextChunkIndex * kChunkSize;
|
||||
if (!MaybeCommitNextPage(offset, kChunkSize)) {
|
||||
if (!this->MaybeCommitNextPage(offset, kChunkSize)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Trampoline<MMPolicy> result(this, GetLocalView() + offset,
|
||||
GetRemoteView() + offset, kChunkSize);
|
||||
Trampoline<MMPolicy> result(this, this->GetLocalView() + offset,
|
||||
this->GetRemoteView() + offset, kChunkSize);
|
||||
if (!!result) {
|
||||
++mNextChunkIndex;
|
||||
}
|
||||
|
@ -50,7 +50,8 @@ public:
|
|||
|
||||
TrampolineCollection<MMPolicy> Items() const
|
||||
{
|
||||
return TrampolineCollection<MMPolicy>(*this, GetLocalView(), GetRemoteView(),
|
||||
return TrampolineCollection<MMPolicy>(*this, this->GetLocalView(),
|
||||
this->GetRemoteView(),
|
||||
kChunkSize, mNextChunkIndex);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
#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/NotNull.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Tuple.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#include "mozilla/Types.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -82,6 +84,143 @@
|
|||
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
|
||||
|
@ -92,6 +231,8 @@ template <typename VMPolicy =
|
|||
mozilla::interceptor::MMPolicyInProcess, kDefaultTrampolineSize>>
|
||||
class WindowsDllInterceptor final
|
||||
{
|
||||
typedef WindowsDllInterceptor<VMPolicy> ThisType;
|
||||
|
||||
interceptor::WindowsDllDetourPatcher<VMPolicy> mDetourPatcher;
|
||||
#if defined(_M_IX86)
|
||||
interceptor::WindowsDllNopSpacePatcher<typename VMPolicy::MMPolicyT> mNopSpacePatcher;
|
||||
|
@ -160,6 +301,7 @@ public:
|
|||
// NB: We intentionally leak mModule
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Hook/detour the method aName from the DLL we set in Init so that it calls
|
||||
* aHookDest instead. Returns the original method pointer in aOrigFunc
|
||||
|
@ -219,7 +361,6 @@ public:
|
|||
return AddDetour(proc, aHookDest, aOrigFunc);
|
||||
}
|
||||
|
||||
private:
|
||||
bool AddDetour(FARPROC aProc, intptr_t aHookDest, void** aOrigFunc)
|
||||
{
|
||||
MOZ_ASSERT(mModule && aProc);
|
||||
|
@ -230,6 +371,14 @@ private:
|
|||
|
||||
return mDetourPatcher.AddHook(aProc, aHookDest, aOrigFunc);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename FuncPtrT>
|
||||
using FuncHookType = FuncHook<ThisType, FuncPtrT>;
|
||||
|
||||
private:
|
||||
template <typename InterceptorT, typename FuncPtrT>
|
||||
friend class FuncHook;
|
||||
};
|
||||
|
||||
} // namespace interceptor
|
||||
|
|
|
@ -10,10 +10,33 @@
|
|||
#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 {
|
||||
|
@ -38,7 +61,8 @@ extern "C" __declspec(dllexport) __declspec(noinline) payload rotatePayload(payl
|
|||
|
||||
static bool patched_func_called = false;
|
||||
|
||||
static payload (*orig_rotatePayload)(payload);
|
||||
static WindowsDllInterceptor::FuncHookType<decltype(&rotatePayload)>
|
||||
orig_rotatePayload;
|
||||
|
||||
static payload
|
||||
patched_rotatePayload(payload p)
|
||||
|
@ -47,11 +71,61 @@ patched_rotatePayload(payload p)
|
|||
return orig_rotatePayload(p);
|
||||
}
|
||||
|
||||
typedef bool(*HookTestFunc)(void*);
|
||||
bool CheckHook(HookTestFunc aHookTestFunc, void* aOrigFunc,
|
||||
const char* aDllName, const char* aFuncName)
|
||||
// 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...>)
|
||||
{
|
||||
if (aHookTestFunc(aOrigFunc)) {
|
||||
return std::forward<CallableT>(aFunc)(Get<Indices>(std::forward<ArgTuple>(aArgs))...);
|
||||
}
|
||||
|
||||
template <typename CallableT>
|
||||
bool TestFunction(CallableT aFunc);
|
||||
|
||||
#define DEFINE_TEST_FUNCTION(calling_convention) \
|
||||
template <typename R, typename... Args, typename... TestArgs> \
|
||||
bool TestFunction(WindowsDllInterceptor::FuncHookType<R (calling_convention *)(Args...)>&& aFunc, \
|
||||
bool (* aPred)(R), TestArgs... aArgs) \
|
||||
{ \
|
||||
using FuncHookType = WindowsDllInterceptor::FuncHookType<R (calling_convention *)(Args...)>; \
|
||||
using ArgTuple = Tuple<Args...>; \
|
||||
using Indices = std::index_sequence_for<Args...>; \
|
||||
ArgTuple fakeArgs{ std::forward<TestArgs>(aArgs)... }; \
|
||||
return aPred(Apply(std::forward<FuncHookType>(aFunc), std::forward<ArgTuple>(fakeArgs), Indices())); \
|
||||
} \
|
||||
\
|
||||
/* Specialization for functions returning void */ \
|
||||
template <typename... Args, typename PredicateT, typename... TestArgs> \
|
||||
bool TestFunction(WindowsDllInterceptor::FuncHookType<void (calling_convention *)(Args...)>&& aFunc, \
|
||||
PredicateT&& aPred, TestArgs... aArgs) \
|
||||
{ \
|
||||
using FuncHookType = WindowsDllInterceptor::FuncHookType<void (calling_convention *)(Args...)>; \
|
||||
using ArgTuple = Tuple<Args...>; \
|
||||
using Indices = std::index_sequence_for<Args...>; \
|
||||
ArgTuple fakeArgs{ std::forward<TestArgs>(aArgs)... }; \
|
||||
Apply(std::forward<FuncHookType>(aFunc), std::forward<ArgTuple>(fakeArgs), Indices()); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
// C++11 allows empty arguments to macros. clang works just fine. MSVC does the
|
||||
// right thing, but it also throws up warning C4003.
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
DEFINE_TEST_FUNCTION(__cdecl)
|
||||
#else
|
||||
DEFINE_TEST_FUNCTION()
|
||||
#endif
|
||||
|
||||
#ifdef _M_IX86
|
||||
DEFINE_TEST_FUNCTION(__stdcall)
|
||||
DEFINE_TEST_FUNCTION(__fastcall)
|
||||
#endif // _M_IX86
|
||||
|
||||
// Test the hooked function against the supplied predicate
|
||||
template <typename OrigFuncT, typename PredicateT, typename... Args>
|
||||
bool CheckHook(WindowsDllInterceptor::FuncHookType<OrigFuncT> &aOrigFunc,
|
||||
const char* aDllName, const char* aFuncName, PredicateT&& aPred,
|
||||
Args... aArgs)
|
||||
{
|
||||
if (TestFunction(std::forward<WindowsDllInterceptor::FuncHookType<OrigFuncT>>(aOrigFunc), std::forward<PredicateT>(aPred), std::forward<Args>(aArgs)...)) {
|
||||
printf("TEST-PASS | WindowsDllInterceptor | "
|
||||
"Executed hooked function %s from %s\n", aFuncName, aDllName);
|
||||
return true;
|
||||
|
@ -61,57 +135,235 @@ bool CheckHook(HookTestFunc aHookTestFunc, void* aOrigFunc,
|
|||
return false;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
bool TestHook(HookTestFunc funcTester, const char (&dll)[N], const char *func)
|
||||
// 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)
|
||||
{
|
||||
void *orig_func;
|
||||
auto orig_func(mozilla::MakeUnique<WindowsDllInterceptor::FuncHookType<OrigFuncT>>());
|
||||
|
||||
bool successful = false;
|
||||
{
|
||||
WindowsDllInterceptor TestIntercept;
|
||||
TestIntercept.Init(dll);
|
||||
successful = TestIntercept.AddHook(func, 0, &orig_func);
|
||||
successful = orig_func->Set(TestIntercept, func, nullptr);
|
||||
}
|
||||
|
||||
if (successful) {
|
||||
printf("TEST-PASS | WindowsDllInterceptor | Could hook %s from %s\n", func, dll);
|
||||
return CheckHook(funcTester, orig_func, dll, func);
|
||||
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)...);
|
||||
} else {
|
||||
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to hook %s from %s\n", func, dll);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
bool TestDetour(const char (&dll)[N], const char *func)
|
||||
// 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)
|
||||
{
|
||||
void *orig_func;
|
||||
auto orig_func(mozilla::MakeUnique<WindowsDllInterceptor::FuncHookType<OrigFuncT>>());
|
||||
|
||||
bool successful = false;
|
||||
{
|
||||
WindowsDllInterceptor TestIntercept;
|
||||
TestIntercept.Init(dll);
|
||||
successful = TestIntercept.AddDetour(func, 0, &orig_func);
|
||||
successful = orig_func->SetDetour(TestIntercept, func, nullptr);
|
||||
}
|
||||
|
||||
if (successful) {
|
||||
printf("TEST-PASS | WindowsDllInterceptor | Could detour %s from %s\n", func, dll);
|
||||
return true;
|
||||
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));
|
||||
} else {
|
||||
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to detour %s from %s\n", func, dll);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
bool MaybeTestHook(const bool cond, HookTestFunc funcTester, const char (&dll)[N], const char* func)
|
||||
// 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)
|
||||
{
|
||||
if (!cond) {
|
||||
printf("TEST-SKIPPED | WindowsDllInterceptor | Skipped hook test for %s from %s\n", func, dll);
|
||||
return true;
|
||||
}
|
||||
|
||||
return TestHook(funcTester, dll, func);
|
||||
return TestHook<OrigFuncT>(dll, func, std::forward<PredicateT>(aPred), std::forward<Args>(aArgs)...);
|
||||
}
|
||||
|
||||
// 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()) {
|
||||
|
@ -147,455 +399,6 @@ bool ShouldTestTipTsf()
|
|||
return true;
|
||||
}
|
||||
|
||||
// These test the patched function returned by the DLL
|
||||
// interceptor. They check that the patched assembler preamble does
|
||||
// something sane. The parameter is a pointer to the patched function.
|
||||
bool TestGetWindowInfo(void* aFunc)
|
||||
{
|
||||
auto patchedGetWindowInfo =
|
||||
reinterpret_cast<decltype(&GetWindowInfo)>(aFunc);
|
||||
return patchedGetWindowInfo(0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestSetWindowLongPtr(void* aFunc)
|
||||
{
|
||||
auto patchedSetWindowLongPtr =
|
||||
reinterpret_cast<decltype(&SetWindowLongPtr)>(aFunc);
|
||||
return patchedSetWindowLongPtr(0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestSetWindowLong(void* aFunc)
|
||||
{
|
||||
auto patchedSetWindowLong =
|
||||
reinterpret_cast<decltype(&SetWindowLong)>(aFunc);
|
||||
return patchedSetWindowLong(0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestTrackPopupMenu(void* aFunc)
|
||||
{
|
||||
auto patchedTrackPopupMenu =
|
||||
reinterpret_cast<decltype(&TrackPopupMenu)>(aFunc);
|
||||
return patchedTrackPopupMenu(0, 0, 0, 0, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestNtFlushBuffersFile(void* aFunc)
|
||||
{
|
||||
typedef NTSTATUS(WINAPI *NtFlushBuffersFileType)(HANDLE, PIO_STATUS_BLOCK);
|
||||
auto patchedNtFlushBuffersFile =
|
||||
reinterpret_cast<NtFlushBuffersFileType>(aFunc);
|
||||
patchedNtFlushBuffersFile(0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestNtCreateFile(void* aFunc)
|
||||
{
|
||||
auto patchedNtCreateFile =
|
||||
reinterpret_cast<decltype(&NtCreateFile)>(aFunc);
|
||||
return patchedNtCreateFile(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
|
||||
}
|
||||
|
||||
bool TestNtReadFile(void* aFunc)
|
||||
{
|
||||
typedef NTSTATUS(WINAPI *NtReadFileType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
|
||||
PIO_STATUS_BLOCK, PVOID, ULONG,
|
||||
PLARGE_INTEGER, PULONG);
|
||||
auto patchedNtReadFile =
|
||||
reinterpret_cast<NtReadFileType>(aFunc);
|
||||
return patchedNtReadFile(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
|
||||
}
|
||||
|
||||
bool TestNtReadFileScatter(void* aFunc)
|
||||
{
|
||||
typedef NTSTATUS(WINAPI *NtReadFileScatterType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
|
||||
PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
|
||||
PLARGE_INTEGER, PULONG);
|
||||
auto patchedNtReadFileScatter =
|
||||
reinterpret_cast<NtReadFileScatterType>(aFunc);
|
||||
return patchedNtReadFileScatter(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
|
||||
}
|
||||
|
||||
bool TestNtWriteFile(void* aFunc)
|
||||
{
|
||||
typedef NTSTATUS(WINAPI *NtWriteFileType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
|
||||
PIO_STATUS_BLOCK, PVOID, ULONG,
|
||||
PLARGE_INTEGER, PULONG);
|
||||
auto patchedNtWriteFile =
|
||||
reinterpret_cast<NtWriteFileType>(aFunc);
|
||||
return patchedNtWriteFile(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
|
||||
}
|
||||
|
||||
bool TestNtWriteFileGather(void* aFunc)
|
||||
{
|
||||
typedef NTSTATUS(WINAPI *NtWriteFileGatherType)(HANDLE, HANDLE, PIO_APC_ROUTINE, PVOID,
|
||||
PIO_STATUS_BLOCK, PFILE_SEGMENT_ELEMENT, ULONG,
|
||||
PLARGE_INTEGER, PULONG);
|
||||
auto patchedNtWriteFileGather =
|
||||
reinterpret_cast<NtWriteFileGatherType>(aFunc);
|
||||
return patchedNtWriteFileGather(0, 0, 0, 0, 0, 0, 0, 0, 0) != 0;
|
||||
}
|
||||
|
||||
bool TestNtQueryFullAttributesFile(void* aFunc)
|
||||
{
|
||||
typedef NTSTATUS(WINAPI *NtQueryFullAttributesFileType)(POBJECT_ATTRIBUTES,
|
||||
PVOID);
|
||||
auto patchedNtQueryFullAttributesFile =
|
||||
reinterpret_cast<NtQueryFullAttributesFileType>(aFunc);
|
||||
return patchedNtQueryFullAttributesFile(0, 0) != 0;
|
||||
}
|
||||
|
||||
bool TestLdrUnloadDll(void* aFunc)
|
||||
{
|
||||
typedef NTSTATUS (NTAPI *LdrUnloadDllType)(HMODULE);
|
||||
auto patchedLdrUnloadDll = reinterpret_cast<LdrUnloadDllType>(aFunc);
|
||||
return patchedLdrUnloadDll(0) != 0;
|
||||
}
|
||||
|
||||
bool TestLdrResolveDelayLoadedAPI(void* aFunc)
|
||||
{
|
||||
// These pointers are disguised as PVOID to avoid pulling in obscure headers
|
||||
typedef PVOID (WINAPI *LdrResolveDelayLoadedAPIType)(PVOID, PVOID, PVOID,
|
||||
PVOID, PVOID, ULONG);
|
||||
auto patchedLdrResolveDelayLoadedAPI =
|
||||
reinterpret_cast<LdrResolveDelayLoadedAPIType>(aFunc);
|
||||
// No idea how to call this API. Flags==99 is just an arbitrary number that
|
||||
// doesn't crash when the other params are null.
|
||||
return patchedLdrResolveDelayLoadedAPI(0, 0, 0, 0, 0, 99) == 0;
|
||||
}
|
||||
|
||||
#ifdef _M_AMD64
|
||||
bool TestRtlInstallFunctionTableCallback(void* aFunc)
|
||||
{
|
||||
auto patchedRtlInstallFunctionTableCallback =
|
||||
reinterpret_cast<decltype(RtlInstallFunctionTableCallback)*>(aFunc);
|
||||
|
||||
return patchedRtlInstallFunctionTableCallback(0, 0, 0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool TestSetUnhandledExceptionFilter(void* aFunc)
|
||||
{
|
||||
auto patchedSetUnhandledExceptionFilter =
|
||||
reinterpret_cast<decltype(&SetUnhandledExceptionFilter)>(aFunc);
|
||||
// Retrieve the current filter as we set the new filter to null, then restore the current filter.
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER current = patchedSetUnhandledExceptionFilter(0);
|
||||
patchedSetUnhandledExceptionFilter(current);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestVirtualAlloc(void* aFunc)
|
||||
{
|
||||
auto patchedVirtualAlloc =
|
||||
reinterpret_cast<decltype(&VirtualAlloc)>(aFunc);
|
||||
return patchedVirtualAlloc(0, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestMapViewOfFile(void* aFunc)
|
||||
{
|
||||
auto patchedMapViewOfFile =
|
||||
reinterpret_cast<decltype(&MapViewOfFile)>(aFunc);
|
||||
return patchedMapViewOfFile(0, 0, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestCreateDIBSection(void* aFunc)
|
||||
{
|
||||
auto patchedCreateDIBSection =
|
||||
reinterpret_cast<decltype(&CreateDIBSection)>(aFunc);
|
||||
// MSDN is wrong here. This does not return ERROR_INVALID_PARAMETER. It
|
||||
// sets the value of GetLastError to ERROR_INVALID_PARAMETER.
|
||||
// CreateDIBSection returns 0 on error.
|
||||
return patchedCreateDIBSection(0, 0, 0, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestCreateFileW(void* aFunc)
|
||||
{
|
||||
auto patchedCreateFileW =
|
||||
reinterpret_cast<decltype(&CreateFileW)>(aFunc);
|
||||
return patchedCreateFileW(0, 0, 0, 0, 0, 0, 0) == INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
bool TestCreateFileA(void* aFunc)
|
||||
{
|
||||
auto patchedCreateFileA =
|
||||
reinterpret_cast<decltype(&CreateFileA)>(aFunc);
|
||||
// return patchedCreateFileA(0, 0, 0, 0, 0, 0, 0) == INVALID_HANDLE_VALUE;
|
||||
printf("TEST-SKIPPED | WindowsDllInterceptor | "
|
||||
"Will not attempt to execute patched CreateFileA -- patched method is known to fail.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestQueryDosDeviceW(void* aFunc)
|
||||
{
|
||||
auto patchedQueryDosDeviceW =
|
||||
reinterpret_cast<decltype(&QueryDosDeviceW)>(aFunc);
|
||||
return patchedQueryDosDeviceW(nullptr, nullptr, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestInSendMessageEx(void* aFunc)
|
||||
{
|
||||
auto patchedInSendMessageEx =
|
||||
reinterpret_cast<decltype(&InSendMessageEx)>(aFunc);
|
||||
patchedInSendMessageEx(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestImmGetContext(void* aFunc)
|
||||
{
|
||||
auto patchedImmGetContext =
|
||||
reinterpret_cast<decltype(&ImmGetContext)>(aFunc);
|
||||
patchedImmGetContext(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestImmGetCompositionStringW(void* aFunc)
|
||||
{
|
||||
auto patchedImmGetCompositionStringW =
|
||||
reinterpret_cast<decltype(&ImmGetCompositionStringW)>(aFunc);
|
||||
patchedImmGetCompositionStringW(0, 0, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestImmSetCandidateWindow(void* aFunc)
|
||||
{
|
||||
auto patchedImmSetCandidateWindow =
|
||||
reinterpret_cast<decltype(&ImmSetCandidateWindow)>(aFunc);
|
||||
// return patchedImmSetCandidateWindow(0, 0) == 0;
|
||||
// ImmSetCandidateWindow crashes if given bad parameters.
|
||||
printf("TEST-SKIPPED | WindowsDllInterceptor | "
|
||||
"Will not attempt to execute patched ImmSetCandidateWindow.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestImmNotifyIME(void* aFunc)
|
||||
{
|
||||
auto patchedImmNotifyIME =
|
||||
reinterpret_cast<decltype(&ImmNotifyIME)>(aFunc);
|
||||
return patchedImmNotifyIME(0, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestGetSaveFileNameW(void* aFunc)
|
||||
{
|
||||
auto patchedGetSaveFileNameWType =
|
||||
reinterpret_cast<decltype(&GetSaveFileNameW)>(aFunc);
|
||||
patchedGetSaveFileNameWType(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestGetOpenFileNameW(void* aFunc)
|
||||
{
|
||||
auto patchedGetOpenFileNameWType =
|
||||
reinterpret_cast<decltype(&GetOpenFileNameW)>(aFunc);
|
||||
patchedGetOpenFileNameWType(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestGetKeyState(void* aFunc)
|
||||
{
|
||||
auto patchedGetKeyState =
|
||||
reinterpret_cast<decltype(&GetKeyState)>(aFunc);
|
||||
patchedGetKeyState(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestSendMessageTimeoutW(void* aFunc)
|
||||
{
|
||||
auto patchedSendMessageTimeoutW =
|
||||
reinterpret_cast<decltype(&SendMessageTimeoutW)>(aFunc);
|
||||
return patchedSendMessageTimeoutW(0, 0, 0, 0, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestProcessCaretEvents(void* aFunc)
|
||||
{
|
||||
auto patchedProcessCaretEvents =
|
||||
reinterpret_cast<WINEVENTPROC>(aFunc);
|
||||
patchedProcessCaretEvents(0, 0, 0, 0, 0, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestSetCursorPos(void* aFunc)
|
||||
{
|
||||
// SetCursorPos has some issues in automation -- see bug 1368033.
|
||||
// For that reason, we don't check the return value -- we only
|
||||
// check that the method runs without producing an exception.
|
||||
auto patchedSetCursorPos =
|
||||
reinterpret_cast<decltype(&SetCursorPos)>(aFunc);
|
||||
patchedSetCursorPos(512, 512);
|
||||
return true;
|
||||
}
|
||||
|
||||
static DWORD sTlsIndex = 0;
|
||||
|
||||
bool TestTlsAlloc(void* aFunc)
|
||||
{
|
||||
auto patchedTlsAlloc =
|
||||
reinterpret_cast<decltype(&TlsAlloc)>(aFunc);
|
||||
sTlsIndex = patchedTlsAlloc();
|
||||
return sTlsIndex != TLS_OUT_OF_INDEXES;
|
||||
}
|
||||
|
||||
bool TestTlsFree(void* aFunc)
|
||||
{
|
||||
auto patchedTlsFree =
|
||||
reinterpret_cast<decltype(&TlsFree)>(aFunc);
|
||||
return sTlsIndex != 0 && patchedTlsFree(sTlsIndex);
|
||||
}
|
||||
|
||||
bool TestCloseHandle(void* aFunc)
|
||||
{
|
||||
auto patchedCloseHandle =
|
||||
reinterpret_cast<decltype(&CloseHandle)>(aFunc);
|
||||
return patchedCloseHandle(0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestDuplicateHandle(void* aFunc)
|
||||
{
|
||||
auto patchedDuplicateHandle =
|
||||
reinterpret_cast<decltype(&DuplicateHandle)>(aFunc);
|
||||
return patchedDuplicateHandle(0, 0, 0, 0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestPrintDlgW(void* aFunc)
|
||||
{
|
||||
auto patchedPrintDlgW =
|
||||
reinterpret_cast<decltype(&PrintDlgW)>(aFunc);
|
||||
patchedPrintDlgW(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestInternetConnectA(void* aFunc)
|
||||
{
|
||||
auto patchedInternetConnectA =
|
||||
reinterpret_cast<decltype(&InternetConnectA)>(aFunc);
|
||||
return patchedInternetConnectA(0, 0, 0, 0, 0, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
HINTERNET sInternet = 0;
|
||||
|
||||
bool TestInternetOpenA(void* aFunc)
|
||||
{
|
||||
auto patchedInternetOpenA =
|
||||
reinterpret_cast<decltype(&InternetOpenA)>(aFunc);
|
||||
sInternet = patchedInternetOpenA(0, 0, 0, 0, 0);
|
||||
return sInternet != 0;
|
||||
}
|
||||
|
||||
bool TestInternetCloseHandle(void* aFunc)
|
||||
{
|
||||
auto patchedInternetCloseHandle =
|
||||
reinterpret_cast<decltype(&InternetCloseHandle)>(aFunc);
|
||||
return patchedInternetCloseHandle(sInternet);
|
||||
}
|
||||
|
||||
bool TestInternetQueryDataAvailable(void* aFunc)
|
||||
{
|
||||
auto patchedInternetQueryDataAvailable =
|
||||
reinterpret_cast<decltype(&InternetQueryDataAvailable)>(aFunc);
|
||||
return patchedInternetQueryDataAvailable(0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestInternetReadFile(void* aFunc)
|
||||
{
|
||||
auto patchedInternetReadFile =
|
||||
reinterpret_cast<decltype(&InternetReadFile)>(aFunc);
|
||||
return patchedInternetReadFile(0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestInternetWriteFile(void* aFunc)
|
||||
{
|
||||
auto patchedInternetWriteFile =
|
||||
reinterpret_cast<decltype(&InternetWriteFile)>(aFunc);
|
||||
return patchedInternetWriteFile(0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestInternetSetOptionA(void* aFunc)
|
||||
{
|
||||
auto patchedInternetSetOptionA =
|
||||
reinterpret_cast<decltype(&InternetSetOptionA)>(aFunc);
|
||||
return patchedInternetSetOptionA(0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestHttpAddRequestHeadersA(void* aFunc)
|
||||
{
|
||||
auto patchedHttpAddRequestHeadersA =
|
||||
reinterpret_cast<decltype(&HttpAddRequestHeadersA)>(aFunc);
|
||||
return patchedHttpAddRequestHeadersA(0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestHttpOpenRequestA(void* aFunc)
|
||||
{
|
||||
auto patchedHttpOpenRequestA =
|
||||
reinterpret_cast<decltype(&HttpOpenRequestA)>(aFunc);
|
||||
return patchedHttpOpenRequestA(0, 0, 0, 0, 0, 0, 0, 0) == 0;
|
||||
}
|
||||
|
||||
bool TestHttpQueryInfoA(void* aFunc)
|
||||
{
|
||||
auto patchedHttpQueryInfoA =
|
||||
reinterpret_cast<decltype(&HttpQueryInfoA)>(aFunc);
|
||||
return patchedHttpQueryInfoA(0, 0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestHttpSendRequestA(void* aFunc)
|
||||
{
|
||||
auto patchedHttpSendRequestA =
|
||||
reinterpret_cast<decltype(&HttpSendRequestA)>(aFunc);
|
||||
return patchedHttpSendRequestA(0, 0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestHttpSendRequestExA(void* aFunc)
|
||||
{
|
||||
auto patchedHttpSendRequestExA =
|
||||
reinterpret_cast<decltype(&HttpSendRequestExA)>(aFunc);
|
||||
return patchedHttpSendRequestExA(0, 0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestHttpEndRequestA(void* aFunc)
|
||||
{
|
||||
auto patchedHttpEndRequestA =
|
||||
reinterpret_cast<decltype(&HttpEndRequestA)>(aFunc);
|
||||
return patchedHttpEndRequestA(0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestInternetQueryOptionA(void* aFunc)
|
||||
{
|
||||
auto patchedInternetQueryOptionA =
|
||||
reinterpret_cast<decltype(&InternetQueryOptionA)>(aFunc);
|
||||
return patchedInternetQueryOptionA(0, 0, 0, 0) == FALSE;
|
||||
}
|
||||
|
||||
bool TestInternetErrorDlg(void* aFunc)
|
||||
{
|
||||
auto patchedInternetErrorDlg =
|
||||
reinterpret_cast<decltype(&InternetErrorDlg)>(aFunc);
|
||||
return patchedInternetErrorDlg(0, 0, 0, 0, 0) == ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
CredHandle sCredHandle;
|
||||
|
||||
bool TestAcquireCredentialsHandleA(void* aFunc)
|
||||
{
|
||||
auto patchedAcquireCredentialsHandleA =
|
||||
reinterpret_cast<decltype(&AcquireCredentialsHandleA)>(aFunc);
|
||||
SCHANNEL_CRED cred;
|
||||
memset(&cred, 0, sizeof(cred));
|
||||
cred.dwVersion = SCHANNEL_CRED_VERSION;
|
||||
return patchedAcquireCredentialsHandleA(0, UNISP_NAME, SECPKG_CRED_OUTBOUND,
|
||||
0, &cred, 0, 0, &sCredHandle, 0) == S_OK;
|
||||
}
|
||||
|
||||
bool TestQueryCredentialsAttributesA(void* aFunc)
|
||||
{
|
||||
auto patchedQueryCredentialsAttributesA =
|
||||
reinterpret_cast<decltype(&QueryCredentialsAttributesA)>(aFunc);
|
||||
return patchedQueryCredentialsAttributesA(&sCredHandle, 0, 0) == SEC_E_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
|
||||
bool TestFreeCredentialsHandle(void* aFunc)
|
||||
{
|
||||
auto patchedFreeCredentialsHandle =
|
||||
reinterpret_cast<decltype(&FreeCredentialsHandle)>(aFunc);
|
||||
return patchedFreeCredentialsHandle(&sCredHandle) == S_OK;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
LARGE_INTEGER start;
|
||||
|
@ -615,7 +418,7 @@ int main()
|
|||
{
|
||||
WindowsDllInterceptor ExeIntercept;
|
||||
ExeIntercept.Init("TestDllInterceptor.exe");
|
||||
if (ExeIntercept.AddHook("rotatePayload", reinterpret_cast<intptr_t>(patched_rotatePayload), (void**) &orig_rotatePayload)) {
|
||||
if (orig_rotatePayload.Set(ExeIntercept, "rotatePayload", &patched_rotatePayload)) {
|
||||
printf("TEST-PASS | WindowsDllInterceptor | Hook added\n");
|
||||
} else {
|
||||
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to add hook\n");
|
||||
|
@ -659,85 +462,85 @@ int main()
|
|||
}
|
||||
#endif
|
||||
|
||||
if (TestHook(TestGetWindowInfo, "user32.dll", "GetWindowInfo") &&
|
||||
if (TEST_HOOK(user32.dll, GetWindowInfo, Equals, FALSE) &&
|
||||
#ifdef _WIN64
|
||||
TestHook(TestSetWindowLongPtr, "user32.dll", "SetWindowLongPtrA") &&
|
||||
TestHook(TestSetWindowLongPtr, "user32.dll", "SetWindowLongPtrW") &&
|
||||
TEST_HOOK(user32.dll, SetWindowLongPtrA, Equals, 0) &&
|
||||
TEST_HOOK(user32.dll, SetWindowLongPtrW, Equals, 0) &&
|
||||
#else
|
||||
TestHook(TestSetWindowLong, "user32.dll", "SetWindowLongA") &&
|
||||
TestHook(TestSetWindowLong, "user32.dll", "SetWindowLongW") &&
|
||||
TEST_HOOK(user32.dll, SetWindowLongA, Equals, 0) &&
|
||||
TEST_HOOK(user32.dll, SetWindowLongW, Equals, 0) &&
|
||||
#endif
|
||||
TestHook(TestTrackPopupMenu, "user32.dll", "TrackPopupMenu") &&
|
||||
TEST_HOOK(user32.dll, TrackPopupMenu, Equals, FALSE) &&
|
||||
#ifdef _M_IX86
|
||||
// We keep this test to hook complex code on x86. (Bug 850957)
|
||||
TestHook(TestNtFlushBuffersFile, "ntdll.dll", "NtFlushBuffersFile") &&
|
||||
TEST_HOOK(ntdll.dll, NtFlushBuffersFile, NotEquals, 0) &&
|
||||
#endif
|
||||
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") &&
|
||||
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) &&
|
||||
#ifndef MOZ_ASAN
|
||||
// Bug 733892: toolkit/crashreporter/nsExceptionHandler.cpp
|
||||
// This fails on ASan because the ASan runtime already hooked this function
|
||||
TestHook(TestSetUnhandledExceptionFilter, "kernel32.dll", "SetUnhandledExceptionFilter") &&
|
||||
TEST_HOOK(kernel32.dll, SetUnhandledExceptionFilter, Ignore, nullptr) &&
|
||||
#endif
|
||||
#ifdef _M_IX86
|
||||
// Bug 670967: xpcom/base/AvailableMemoryTracker.cpp
|
||||
TestHook(TestVirtualAlloc, "kernel32.dll", "VirtualAlloc") &&
|
||||
TestHook(TestMapViewOfFile, "kernel32.dll", "MapViewOfFile") &&
|
||||
TestHook(TestCreateDIBSection, "gdi32.dll", "CreateDIBSection") &&
|
||||
TestHook(TestCreateFileW, "kernel32.dll", "CreateFileW") && // see Bug 1316415
|
||||
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) &&
|
||||
#endif
|
||||
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") &&
|
||||
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) &&
|
||||
#ifdef _M_X64
|
||||
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") &&
|
||||
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) &&
|
||||
#endif
|
||||
MaybeTestHook(ShouldTestTipTsf(), TestProcessCaretEvents, "tiptsf.dll", "ProcessCaretEvents") &&
|
||||
MAYBE_TEST_HOOK(ShouldTestTipTsf(), tiptsf.dll, ProcessCaretEvents, Ignore, nullptr) &&
|
||||
#ifdef _M_IX86
|
||||
TestHook(TestSendMessageTimeoutW, "user32.dll", "SendMessageTimeoutW") &&
|
||||
TEST_HOOK(user32.dll, SendMessageTimeoutW, Equals, 0) &&
|
||||
#endif
|
||||
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(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(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(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(TestAcquireCredentialsHandleA, "sspicli.dll", "AcquireCredentialsHandleA") &&
|
||||
TestHook(TestQueryCredentialsAttributesA, "sspicli.dll", "QueryCredentialsAttributesA") &&
|
||||
TestHook(TestFreeCredentialsHandle, "sspicli.dll", "FreeCredentialsHandle") &&
|
||||
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) &&
|
||||
|
||||
TestDetour("kernel32.dll", "BaseThreadInitThunk") &&
|
||||
TestDetour("ntdll.dll", "LdrLoadDll")) {
|
||||
TEST_DETOUR_SKIP_EXEC(kernel32.dll, BaseThreadInitThunk) &&
|
||||
TEST_DETOUR_SKIP_EXEC(ntdll.dll, LdrLoadDll)) {
|
||||
printf("TEST-PASS | WindowsDllInterceptor | all checks passed\n");
|
||||
|
||||
LARGE_INTEGER end, freq;
|
||||
|
|
|
@ -11,19 +11,19 @@
|
|||
|
||||
using std::wstring;
|
||||
|
||||
static void* gOrigReturnResult;
|
||||
|
||||
extern "C" __declspec(dllexport) int
|
||||
ReturnResult()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
static mozilla::CrossProcessDllInterceptor::FuncHookType<decltype(&ReturnResult)>
|
||||
gOrigReturnResult;
|
||||
|
||||
static int
|
||||
ReturnResultHook()
|
||||
{
|
||||
auto origFn = reinterpret_cast<decltype(&ReturnResult)>(gOrigReturnResult);
|
||||
if (origFn() != 2) {
|
||||
if (gOrigReturnResult() != 2) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
@ -73,9 +73,7 @@ int ParentMain()
|
|||
mozilla::CrossProcessDllInterceptor intcpt(childProcess.get());
|
||||
intcpt.Init("TestDllInterceptorCrossProcess.exe");
|
||||
|
||||
if (!intcpt.AddHook("ReturnResult",
|
||||
reinterpret_cast<intptr_t>(&ReturnResultHook),
|
||||
&gOrigReturnResult)) {
|
||||
if (!gOrigReturnResult.Set(intcpt, "ReturnResult", &ReturnResultHook)) {
|
||||
printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Failed to add hook\n");
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ On Error GoTo 0
|
|||
' Download installer
|
||||
On Error Resume Next
|
||||
Download "https://conemu.github.io/install2.ps1", "install2.ps1"
|
||||
conemuSettingsURI = "https://api.pub.build.mozilla.org/tooltool/sha512/9aa384ecc8025a974999e913c83064b3b797e05d19806e62ef558c8300e4c3f72967e9464ace59759f76216fc2fc66f338a1e5cdea3b9aa264529487f091d929"
|
||||
conemuSettingsURI = "https://tooltool.mozilla-releng.net/sha512/9aa384ecc8025a974999e913c83064b3b797e05d19806e62ef558c8300e4c3f72967e9464ace59759f76216fc2fc66f338a1e5cdea3b9aa264529487f091d929"
|
||||
' Run installer
|
||||
errorCode = shell.Run("powershell.exe -NoProfile -ExecutionPolicy Unrestricted set dst '" & conemuPath & "'; set ver 'stable'; set lnk 'Mozilla Development Shell'; set xml '" & conemuSettingsURI & "'; set run $FALSE; .\install2.ps1", 0, true)
|
||||
' Delete ConEmu installer
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace mozilla {
|
|||
namespace sandboxing {
|
||||
|
||||
typedef BOOL(WINAPI* CloseHandle_func) (HANDLE hObject);
|
||||
static CloseHandle_func stub_CloseHandle = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<CloseHandle_func> stub_CloseHandle;
|
||||
|
||||
typedef BOOL(WINAPI* DuplicateHandle_func)(HANDLE hSourceProcessHandle,
|
||||
HANDLE hSourceHandle,
|
||||
|
@ -24,7 +24,8 @@ typedef BOOL(WINAPI* DuplicateHandle_func)(HANDLE hSourceProcessHandle,
|
|||
DWORD dwDesiredAccess,
|
||||
BOOL bInheritHandle,
|
||||
DWORD dwOptions);
|
||||
static DuplicateHandle_func stub_DuplicateHandle = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<DuplicateHandle_func>
|
||||
stub_DuplicateHandle;
|
||||
|
||||
static BOOL WINAPI
|
||||
patched_CloseHandle(HANDLE hObject)
|
||||
|
@ -62,17 +63,14 @@ EnableHandleCloseMonitoring()
|
|||
{
|
||||
Kernel32Intercept.Init("kernel32.dll");
|
||||
bool hooked =
|
||||
Kernel32Intercept.AddHook("CloseHandle",
|
||||
reinterpret_cast<intptr_t>(patched_CloseHandle),
|
||||
(void**)&stub_CloseHandle);
|
||||
stub_CloseHandle.Set(Kernel32Intercept, "CloseHandle", &patched_CloseHandle);
|
||||
if (!hooked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hooked =
|
||||
Kernel32Intercept.AddHook("DuplicateHandle",
|
||||
reinterpret_cast<intptr_t>(patched_DuplicateHandle),
|
||||
(void**)&stub_DuplicateHandle);
|
||||
stub_DuplicateHandle.Set(Kernel32Intercept, "DuplicateHandle",
|
||||
&patched_DuplicateHandle);
|
||||
if (!hooked) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ config = {
|
|||
# from android_common.py
|
||||
"download_tooltool": True,
|
||||
"download_minidump_stackwalk": True,
|
||||
"tooltool_servers": ['https://api.pub.build.mozilla.org/tooltool/'],
|
||||
"tooltool_servers": ['https://tooltool.mozilla-releng.net/'],
|
||||
# minidump_tooltool_manifest_path is relative to workspace/build/tests/
|
||||
"minidump_tooltool_manifest_path": "config/tooltool-manifests/linux64/releng.manifest",
|
||||
"xpcshell_extra": "--remoteTestRoot=/data/local/tests",
|
||||
|
|
|
@ -29,7 +29,7 @@ config = {
|
|||
|
||||
# ToolTool
|
||||
"tooltool_manifest_src": 'browser\\config\\tooltool-manifests\\{}\\releng.manifest'.format(platform),
|
||||
'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
|
||||
'tooltool_url': 'https://tooltool.mozilla-releng.net/',
|
||||
'tooltool_cache': os.environ.get('TOOLTOOL_CACHE'),
|
||||
|
||||
'run_configure': False,
|
||||
|
|
|
@ -29,7 +29,7 @@ config = {
|
|||
|
||||
# ToolTool
|
||||
"tooltool_manifest_src": 'browser\\config\\tooltool-manifests\\{}\\releng.manifest'.format(platform),
|
||||
'tooltool_url': 'https://api.pub.build.mozilla.org/tooltool/',
|
||||
'tooltool_url': 'https://tooltool.mozilla-releng.net/',
|
||||
'tooltool_cache': os.environ.get('TOOLTOOL_CACHE'),
|
||||
|
||||
'run_configure': False,
|
||||
|
|
|
@ -986,6 +986,7 @@ nsWebBrowser::SetProgressListener(nsIWebProgressListener* aProgressListener)
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsWebBrowser::SaveURI(nsIURI* aURI,
|
||||
nsIPrincipal* aPrincipal,
|
||||
uint32_t aCacheKey,
|
||||
nsIURI* aReferrer,
|
||||
uint32_t aReferrerPolicy,
|
||||
|
@ -995,12 +996,14 @@ nsWebBrowser::SaveURI(nsIURI* aURI,
|
|||
nsILoadContext* aPrivacyContext)
|
||||
{
|
||||
return SavePrivacyAwareURI(
|
||||
aURI, aCacheKey, aReferrer, aReferrerPolicy, aPostData, aExtraHeaders,
|
||||
aFile, aPrivacyContext && aPrivacyContext->UsePrivateBrowsing());
|
||||
aURI, aPrincipal, aCacheKey, aReferrer, aReferrerPolicy, aPostData,
|
||||
aExtraHeaders, aFile,
|
||||
aPrivacyContext && aPrivacyContext->UsePrivateBrowsing());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebBrowser::SavePrivacyAwareURI(nsIURI* aURI,
|
||||
nsIPrincipal* aPrincipal,
|
||||
uint32_t aCacheKey,
|
||||
nsIURI* aReferrer,
|
||||
uint32_t aReferrerPolicy,
|
||||
|
@ -1038,8 +1041,9 @@ nsWebBrowser::SavePrivacyAwareURI(nsIURI* aURI,
|
|||
mPersist->SetPersistFlags(mPersistFlags);
|
||||
mPersist->GetCurrentState(&mPersistCurrentState);
|
||||
|
||||
rv = mPersist->SavePrivacyAwareURI(uri, aCacheKey, aReferrer, aReferrerPolicy,
|
||||
aPostData, aExtraHeaders, aFile, aIsPrivate);
|
||||
rv = mPersist->SavePrivacyAwareURI(uri, aPrincipal, aCacheKey,
|
||||
aReferrer, aReferrerPolicy, aPostData,
|
||||
aExtraHeaders, aFile, aIsPrivate);
|
||||
if (NS_FAILED(rv)) {
|
||||
mPersist = nullptr;
|
||||
}
|
||||
|
|
|
@ -283,7 +283,8 @@ function promiseStartLegacyDownload(aSourceUrl, aOptions) {
|
|||
|
||||
// Start the actual download process.
|
||||
persist.savePrivacyAwareURI(
|
||||
sourceURI, 0, referrer, Ci.nsIHttpChannel.REFERRER_POLICY_UNSAFE_URL,
|
||||
sourceURI, Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
0, referrer, Ci.nsIHttpChannel.REFERRER_POLICY_UNSAFE_URL,
|
||||
null, null, targetFile, isPrivate);
|
||||
}).catch(do_report_unexpected_exception);
|
||||
|
||||
|
|
|
@ -226,7 +226,11 @@ var gViewSourceUtils = {
|
|||
webBrowserPersist.persistFlags = this.mnsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
|
||||
webBrowserPersist.progressListener = this.viewSourceProgressListener;
|
||||
let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_NO_REFERRER;
|
||||
webBrowserPersist.savePrivacyAwareURI(uri, null, null, referrerPolicy, null, null, file, data.isPrivate);
|
||||
let ssm = Services.scriptSecurityManager;
|
||||
let principal = ssm.createCodebasePrincipal(data.uri,
|
||||
browser.contentPrincipal.originAttributes);
|
||||
webBrowserPersist.savePrivacyAwareURI(uri, principal, null, null,
|
||||
referrerPolicy, null, null, file, data.isPrivate);
|
||||
|
||||
let helperService = Cc["@mozilla.org/uriloader/external-helper-app-service;1"]
|
||||
.getService(Ci.nsPIExternalAppLauncher);
|
||||
|
|
|
@ -62,14 +62,15 @@ function forbidCPOW(arg, func, argname) {
|
|||
// - A linked document using Alt-click Save Link As...
|
||||
//
|
||||
function saveURL(aURL, aFileName, aFilePickerTitleKey, aShouldBypassCache,
|
||||
aSkipPrompt, aReferrer, aSourceDocument, aIsContentWindowPrivate) {
|
||||
aSkipPrompt, aReferrer, aSourceDocument,
|
||||
aIsContentWindowPrivate, aPrincipal) {
|
||||
forbidCPOW(aURL, "saveURL", "aURL");
|
||||
forbidCPOW(aReferrer, "saveURL", "aReferrer");
|
||||
// Allow aSourceDocument to be a CPOW.
|
||||
|
||||
internalSave(aURL, null, aFileName, null, null, aShouldBypassCache,
|
||||
aFilePickerTitleKey, null, aReferrer, aSourceDocument,
|
||||
aSkipPrompt, null, aIsContentWindowPrivate);
|
||||
aSkipPrompt, null, aIsContentWindowPrivate, aPrincipal);
|
||||
}
|
||||
|
||||
// Just like saveURL, but will get some info off the image before
|
||||
|
@ -112,7 +113,7 @@ const nsISupportsCString = Ci.nsISupportsCString;
|
|||
*/
|
||||
function saveImageURL(aURL, aFileName, aFilePickerTitleKey, aShouldBypassCache,
|
||||
aSkipPrompt, aReferrer, aDoc, aContentType, aContentDisp,
|
||||
aIsContentWindowPrivate) {
|
||||
aIsContentWindowPrivate, aPrincipal) {
|
||||
forbidCPOW(aURL, "saveImageURL", "aURL");
|
||||
forbidCPOW(aReferrer, "saveImageURL", "aReferrer");
|
||||
|
||||
|
@ -156,7 +157,7 @@ function saveImageURL(aURL, aFileName, aFilePickerTitleKey, aShouldBypassCache,
|
|||
|
||||
internalSave(aURL, null, aFileName, aContentDisp, aContentType,
|
||||
aShouldBypassCache, aFilePickerTitleKey, null, aReferrer,
|
||||
null, aSkipPrompt, null, aIsContentWindowPrivate);
|
||||
aDoc, aSkipPrompt, null, aIsContentWindowPrivate, aPrincipal);
|
||||
}
|
||||
|
||||
// This is like saveDocument, but takes any browser/frame-like element
|
||||
|
@ -331,11 +332,15 @@ XPCOMUtils.defineConstant(this, "kSaveAsType_Text", kSaveAsType_Text);
|
|||
* This parameter is provided when the aInitiatingDocument is not a
|
||||
* real document object. Stores whether aInitiatingDocument.defaultView
|
||||
* was private or not.
|
||||
* @param aPrincipal [optional]
|
||||
* This parameter is provided when neither aDocument nor
|
||||
* aInitiatingDocument is provided. Used to determine what level of
|
||||
* privilege to load the URI with.
|
||||
*/
|
||||
function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition,
|
||||
aContentType, aShouldBypassCache, aFilePickerTitleKey,
|
||||
aChosenData, aReferrer, aInitiatingDocument, aSkipPrompt,
|
||||
aCacheKey, aIsContentWindowPrivate) {
|
||||
aCacheKey, aIsContentWindowPrivate, aPrincipal) {
|
||||
forbidCPOW(aURL, "internalSave", "aURL");
|
||||
forbidCPOW(aReferrer, "internalSave", "aReferrer");
|
||||
forbidCPOW(aCacheKey, "internalSave", "aCacheKey");
|
||||
|
@ -411,8 +416,17 @@ function internalSave(aURL, aDocument, aDefaultFileName, aContentDisposition,
|
|||
: aInitiatingDocument.isPrivate;
|
||||
}
|
||||
|
||||
// We have to cover the cases here where we were either passed an explicit
|
||||
// principal, or a 'real' document (with a nodePrincipal property), or an
|
||||
// nsIWebBrowserPersistDocument which has a principal property.
|
||||
let sourcePrincipal =
|
||||
aPrincipal ||
|
||||
(aDocument && (aDocument.nodePrincipal || aDocument.principal)) ||
|
||||
(aInitiatingDocument && aInitiatingDocument.nodePrincipal);
|
||||
|
||||
var persistArgs = {
|
||||
sourceURI,
|
||||
sourcePrincipal,
|
||||
sourceReferrer: aReferrer,
|
||||
sourceDocument: useSaveDocument ? aDocument : null,
|
||||
targetContentType: (saveAsType == kSaveAsType_Text) ? "text/plain" : null,
|
||||
|
@ -463,8 +477,7 @@ function internalPersist(persistArgs) {
|
|||
|
||||
// Calculate persist flags.
|
||||
const nsIWBP = Ci.nsIWebBrowserPersist;
|
||||
const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
|
||||
nsIWBP.PERSIST_FLAGS_FORCE_ALLOW_COOKIES;
|
||||
const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
|
||||
if (persistArgs.bypassCache)
|
||||
persist.persistFlags = flags | nsIWBP.PERSIST_FLAGS_BYPASS_CACHE;
|
||||
else
|
||||
|
@ -511,6 +524,7 @@ function internalPersist(persistArgs) {
|
|||
persistArgs.targetContentType, encodingFlags, kWrapColumn);
|
||||
} else {
|
||||
persist.savePrivacyAwareURI(persistArgs.sourceURI,
|
||||
persistArgs.sourcePrincipal,
|
||||
persistArgs.sourceCacheKey,
|
||||
persistArgs.sourceReferrer,
|
||||
Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
|
|
|
@ -36,7 +36,8 @@ add_task(async function preferred_API() {
|
|||
return image.href;
|
||||
});
|
||||
|
||||
saveImageURL(url, "image.jpg", null, true, false, null, null, null, null, false);
|
||||
saveImageURL(url, "image.jpg", null, true, false, null, null, null, null,
|
||||
false, gBrowser.contentPrincipal);
|
||||
let channel = gBrowser.contentDocumentAsCPOW.docShell.currentDocumentChannel;
|
||||
if (channel) {
|
||||
ok(true, channel.QueryInterface(Ci.nsIHttpChannelInternal)
|
||||
|
|
|
@ -4,10 +4,6 @@
|
|||
# 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/.
|
||||
|
||||
SOURCES += [
|
||||
'../google-breakpad/src/common/windows/http_upload.cc',
|
||||
]
|
||||
|
||||
Library('google_breakpad_libxul_s')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -22,14 +18,12 @@ LOCAL_INCLUDES += [
|
|||
|
||||
include('/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild')
|
||||
include('/toolkit/crashreporter/breakpad-client/windows/handler/objs.mozbuild')
|
||||
include('/toolkit/crashreporter/breakpad-client/windows/sender/objs.mozbuild')
|
||||
include('/toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild')
|
||||
include('/toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild')
|
||||
|
||||
SOURCES += objs_common
|
||||
SOURCES += objs_crash_generation
|
||||
SOURCES += objs_handler
|
||||
SOURCES += objs_sender
|
||||
SOURCES += objs_client_common
|
||||
|
||||
DisableStlWrapping()
|
||||
|
|
|
@ -24,10 +24,20 @@ if CONFIG['OS_ARCH'] == 'WINNT':
|
|||
UNIFIED_SOURCES += [
|
||||
'crashreporter_win.cpp',
|
||||
]
|
||||
include('/toolkit/crashreporter/google-breakpad/src/common/windows/objs.mozbuild')
|
||||
include('/toolkit/crashreporter/breakpad-client/windows/sender/objs.mozbuild')
|
||||
include('/toolkit/crashreporter/breakpad-client/windows/crash_generation/objs.mozbuild')
|
||||
include('/toolkit/crashreporter/breakpad-client/windows/common/objs.mozbuild')
|
||||
SOURCES += objs_common
|
||||
SOURCES += objs_sender
|
||||
SOURCES += objs_crash_generation
|
||||
SOURCES += objs_client_common
|
||||
SOURCES += [
|
||||
'../google-breakpad/src/common/windows/http_upload.cc',
|
||||
]
|
||||
DEFINES['UNICODE'] = True
|
||||
DEFINES['_UNICODE'] = True
|
||||
USE_LIBS += [
|
||||
'google_breakpad_libxul_s',
|
||||
'nss',
|
||||
]
|
||||
OS_LIBS += [
|
||||
|
|
|
@ -338,7 +338,8 @@ nsTArray<nsAutoPtr<DelayedNote> >* gDelayedAnnotations;
|
|||
// reporter is loaded instead (in case it became unloaded somehow)
|
||||
typedef LPTOP_LEVEL_EXCEPTION_FILTER (WINAPI *SetUnhandledExceptionFilter_func)
|
||||
(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);
|
||||
static SetUnhandledExceptionFilter_func stub_SetUnhandledExceptionFilter = 0;
|
||||
static WindowsDllInterceptor::FuncHookType<SetUnhandledExceptionFilter_func>
|
||||
stub_SetUnhandledExceptionFilter;
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER previousUnhandledExceptionFilter = nullptr;
|
||||
static WindowsDllInterceptor gKernel32Intercept;
|
||||
static bool gBlockUnhandledExceptionFilter = true;
|
||||
|
@ -1639,9 +1640,9 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory,
|
|||
// protect the crash reporter from being unloaded
|
||||
gBlockUnhandledExceptionFilter = true;
|
||||
gKernel32Intercept.Init("kernel32.dll");
|
||||
bool ok = gKernel32Intercept.AddHook("SetUnhandledExceptionFilter",
|
||||
reinterpret_cast<intptr_t>(patched_SetUnhandledExceptionFilter),
|
||||
(void**) &stub_SetUnhandledExceptionFilter);
|
||||
bool ok = stub_SetUnhandledExceptionFilter.Set(gKernel32Intercept,
|
||||
"SetUnhandledExceptionFilter",
|
||||
&patched_SetUnhandledExceptionFilter);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!ok)
|
||||
|
|
|
@ -971,7 +971,8 @@ function _persistImage(sourceURL, localFileName, successCallback) {
|
|||
|
||||
persist.progressListener = new _persistProgressListener(successCallback);
|
||||
|
||||
persist.saveURI(sourceURI, 0,
|
||||
let sourcePrincipal = Services.scriptSecurityManager.createCodebasePrincipal(sourceURI, {});
|
||||
persist.saveURI(sourceURI, sourcePrincipal, 0,
|
||||
null, Ci.nsIHttpChannel.REFERRER_POLICY_UNSET,
|
||||
null, null, targetURI, null);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd $DIR
|
||||
|
||||
echo "To complete this script you will need the following tokens from https://api.pub.build.mozilla.org/tokenauth/"
|
||||
echo "To complete this script you will need the following tokens from https://mozilla-releng.net/tokens"
|
||||
echo " - tooltool.upload.public"
|
||||
echo " - tooltool.download.public"
|
||||
echo ""
|
||||
|
@ -14,7 +14,7 @@ read -p "Are these tokens visible at the above URL (y/n)?" choice
|
|||
case "$choice" in
|
||||
y|Y )
|
||||
echo ""
|
||||
echo "1. Go to https://api.pub.build.mozilla.org/"
|
||||
echo "1. Go to https://mozilla-releng.net"
|
||||
echo "2. Log in using your Mozilla LDAP account."
|
||||
echo "3. Click on \"Tokens.\""
|
||||
echo "4. Issue a user token with the permissions tooltool.upload.public and tooltool.download.public."
|
||||
|
@ -49,10 +49,10 @@ tar cvz -f eslint-plugin-mozilla.tar.gz node_modules
|
|||
|
||||
echo "Adding eslint-plugin-mozilla.tar.gz to tooltool..."
|
||||
rm -f manifest.tt
|
||||
../../../../python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint-plugin-mozilla.tar.gz --url="https://api.pub.build.mozilla.org/tooltool/"
|
||||
../../../../python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint-plugin-mozilla.tar.gz --url="https://tooltool.mozilla-releng.net/"
|
||||
|
||||
echo "Uploading eslint-plugin-mozilla.tar.gz to tooltool..."
|
||||
../../../../python/mozbuild/mozbuild/action/tooltool.py upload --authentication-file=~/.tooltool-token --message "node_modules folder update for tools/lint/eslint/eslint-plugin-mozilla" --url="https://api.pub.build.mozilla.org/tooltool/"
|
||||
../../../../python/mozbuild/mozbuild/action/tooltool.py upload --authentication-file=~/.tooltool-token --message "node_modules folder update for tools/lint/eslint/eslint-plugin-mozilla" --url="https://tooltool.mozilla-releng.net/"
|
||||
|
||||
echo "Cleaning up..."
|
||||
rm eslint-plugin-mozilla.tar.gz
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
cd $DIR
|
||||
|
||||
echo "To complete this script you will need the following tokens from https://api.pub.build.mozilla.org/tokenauth/"
|
||||
echo "To complete this script you will need the following tokens from https://mozilla-releng.net/tokens"
|
||||
echo " - tooltool.upload.public"
|
||||
echo " - tooltool.download.public"
|
||||
echo ""
|
||||
|
@ -14,7 +14,7 @@ read -p "Are these tokens visible at the above URL (y/n)?" choice
|
|||
case "$choice" in
|
||||
y|Y )
|
||||
echo ""
|
||||
echo "1. Go to https://api.pub.build.mozilla.org/"
|
||||
echo "1. Go to https://mozilla-releng.net"
|
||||
echo "2. Log in using your Mozilla LDAP account."
|
||||
echo "3. Click on \"Tokens.\""
|
||||
echo "4. Issue a user token with the permissions tooltool.upload.public and tooltool.download.public."
|
||||
|
@ -56,10 +56,10 @@ tar cvz --exclude=eslint-plugin-mozilla --exclude=eslint-plugin-spidermonkey-js
|
|||
|
||||
echo "Adding eslint.tar.gz to tooltool..."
|
||||
rm tools/lint/eslint/manifest.tt
|
||||
./python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint.tar.gz --url="https://api.pub.build.mozilla.org/tooltool/"
|
||||
./python/mozbuild/mozbuild/action/tooltool.py add --visibility public --unpack eslint.tar.gz --url="https://tooltool.mozilla-releng.net/"
|
||||
|
||||
echo "Uploading eslint.tar.gz to tooltool..."
|
||||
./python/mozbuild/mozbuild/action/tooltool.py upload --authentication-file=~/.tooltool-token --message "node_modules folder update for tools/lint/eslint" --url="https://api.pub.build.mozilla.org/tooltool/"
|
||||
./python/mozbuild/mozbuild/action/tooltool.py upload --authentication-file=~/.tooltool-token --message "node_modules folder update for tools/lint/eslint" --url="https://tooltool.mozilla-releng.net/"
|
||||
|
||||
echo "Cleaning up..."
|
||||
mv manifest.tt tools/lint/eslint/manifest.tt
|
||||
|
|
|
@ -303,7 +303,8 @@ Registers::SyncPopulate()
|
|||
static WindowsDllInterceptor NtDllIntercept;
|
||||
|
||||
typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module);
|
||||
static LdrUnloadDll_func stub_LdrUnloadDll;
|
||||
static WindowsDllInterceptor::FuncHookType<LdrUnloadDll_func>
|
||||
stub_LdrUnloadDll;
|
||||
|
||||
static NTSTATUS NTAPI
|
||||
patched_LdrUnloadDll(HMODULE module)
|
||||
|
@ -318,7 +319,8 @@ patched_LdrUnloadDll(HMODULE module)
|
|||
typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
|
||||
PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
|
||||
PVOID ThunkAddress, ULONG Flags);
|
||||
static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
|
||||
static WindowsDllInterceptor::FuncHookType<LdrResolveDelayLoadedAPI_func>
|
||||
stub_LdrResolveDelayLoadedAPI;
|
||||
|
||||
static PVOID WINAPI
|
||||
patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
|
||||
|
@ -336,20 +338,12 @@ patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
|
|||
void
|
||||
InitializeWin64ProfilerHooks()
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
NtDllIntercept.Init("ntdll.dll");
|
||||
NtDllIntercept.AddHook("LdrUnloadDll",
|
||||
reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
|
||||
(void**)&stub_LdrUnloadDll);
|
||||
stub_LdrUnloadDll.Set(NtDllIntercept, "LdrUnloadDll", &patched_LdrUnloadDll);
|
||||
if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8
|
||||
NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI",
|
||||
reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
|
||||
(void**)&stub_LdrResolveDelayLoadedAPI);
|
||||
stub_LdrResolveDelayLoadedAPI.Set(NtDllIntercept,
|
||||
"LdrResolveDelayLoadedAPI",
|
||||
&patched_LdrResolveDelayLoadedAPI);
|
||||
}
|
||||
}
|
||||
#endif // defined(GP_PLAT_amd64_windows)
|
||||
|
|
|
@ -352,9 +352,6 @@ 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.
|
||||
|
@ -461,17 +458,17 @@ private:
|
|||
if (!IsWin10OrLater() && GetModuleHandle(L"tiptsf.dll") &&
|
||||
!sProcessCaretEventsStub) {
|
||||
sTipTsfInterceptor.Init("tiptsf.dll");
|
||||
DebugOnly<bool> ok = sTipTsfInterceptor.AddHook("ProcessCaretEvents",
|
||||
reinterpret_cast<intptr_t>(&ProcessCaretEventsHook),
|
||||
(void**) &sProcessCaretEventsStub);
|
||||
DebugOnly<bool> ok = sProcessCaretEventsStub.Set(sTipTsfInterceptor,
|
||||
"ProcessCaretEvents",
|
||||
&ProcessCaretEventsHook);
|
||||
MOZ_ASSERT(ok);
|
||||
}
|
||||
|
||||
if (!sSendMessageTimeoutWStub) {
|
||||
sUser32Intercept.Init("user32.dll");
|
||||
DebugOnly<bool> hooked = sUser32Intercept.AddHook("SendMessageTimeoutW",
|
||||
reinterpret_cast<intptr_t>(&SendMessageTimeoutWHook),
|
||||
(void**) &sSendMessageTimeoutWStub);
|
||||
DebugOnly<bool> hooked = sSendMessageTimeoutWStub.Set(sUser32Intercept,
|
||||
"SendMessageTimeoutW",
|
||||
&SendMessageTimeoutWHook);
|
||||
MOZ_ASSERT(hooked);
|
||||
}
|
||||
}
|
||||
|
@ -556,8 +553,10 @@ private:
|
|||
}
|
||||
|
||||
static WindowsDllInterceptor sTipTsfInterceptor;
|
||||
static WINEVENTPROC sProcessCaretEventsStub;
|
||||
static decltype(&SendMessageTimeoutW) sSendMessageTimeoutWStub;
|
||||
static WindowsDllInterceptor::FuncHookType<WINEVENTPROC>
|
||||
sProcessCaretEventsStub;
|
||||
static WindowsDllInterceptor::FuncHookType<decltype(&SendMessageTimeoutW)>
|
||||
sSendMessageTimeoutWStub;
|
||||
static StaticAutoPtr<TIPMessageHandler> sInstance;
|
||||
|
||||
HHOOK mHook;
|
||||
|
@ -566,8 +565,10 @@ private:
|
|||
};
|
||||
|
||||
WindowsDllInterceptor TIPMessageHandler::sTipTsfInterceptor;
|
||||
WINEVENTPROC TIPMessageHandler::sProcessCaretEventsStub;
|
||||
decltype(&SendMessageTimeoutW) TIPMessageHandler::sSendMessageTimeoutWStub;
|
||||
WindowsDllInterceptor::FuncHookType<WINEVENTPROC>
|
||||
TIPMessageHandler::sProcessCaretEventsStub;
|
||||
WindowsDllInterceptor::FuncHookType<decltype(&SendMessageTimeoutW)>
|
||||
TIPMessageHandler::sSendMessageTimeoutWStub;
|
||||
StaticAutoPtr<TIPMessageHandler> TIPMessageHandler::sInstance;
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -2472,7 +2473,7 @@ nsWindow::ResetLayout()
|
|||
// margins are set.
|
||||
static const wchar_t kManageWindowInfoProperty[] = L"ManageWindowInfoProperty";
|
||||
typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
|
||||
static GetWindowInfoPtr sGetWindowInfoPtrStub = nullptr;
|
||||
static WindowsDllInterceptor::FuncHookType<GetWindowInfoPtr> sGetWindowInfoPtrStub;
|
||||
|
||||
BOOL WINAPI
|
||||
GetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
|
||||
|
@ -2500,18 +2501,15 @@ nsWindow::UpdateGetWindowInfoCaptionStatus(bool aActiveCaption)
|
|||
if (!mWnd)
|
||||
return;
|
||||
|
||||
if (sHookedGetWindowInfo.isNothing()) {
|
||||
sUser32Intercept.Init("user32.dll");
|
||||
sHookedGetWindowInfo =
|
||||
Some(sUser32Intercept.AddHook("GetWindowInfo",
|
||||
reinterpret_cast<intptr_t>(GetWindowInfoHook),
|
||||
(void**) &sGetWindowInfoPtrStub));
|
||||
if (!sHookedGetWindowInfo.value()) {
|
||||
return;
|
||||
}
|
||||
sUser32Intercept.Init("user32.dll");
|
||||
sGetWindowInfoPtrStub.Set(sUser32Intercept, "GetWindowInfo",
|
||||
&GetWindowInfoHook);
|
||||
if (!sGetWindowInfoPtrStub) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update our internally tracked caption status
|
||||
SetPropW(mWnd, kManageWindowInfoProperty,
|
||||
SetPropW(mWnd, kManageWindowInfoProperty,
|
||||
reinterpret_cast<HANDLE>(static_cast<INT_PTR>(aActiveCaption) + 1));
|
||||
}
|
||||
|
||||
|
|
|
@ -84,16 +84,14 @@ volatile PRIntervalTime sLastLowMemoryNotificationTime;
|
|||
|
||||
// These are function pointers to the functions we wrap in Init().
|
||||
|
||||
void* (WINAPI* sVirtualAllocOrig)(LPVOID aAddress, SIZE_T aSize,
|
||||
DWORD aAllocationType, DWORD aProtect);
|
||||
static WindowsDllInterceptor::FuncHookType<decltype(&VirtualAlloc)>
|
||||
sVirtualAllocOrig;
|
||||
|
||||
void* (WINAPI* sMapViewOfFileOrig)(HANDLE aFileMappingObject,
|
||||
DWORD aDesiredAccess, DWORD aFileOffsetHigh,
|
||||
DWORD aFileOffsetLow, SIZE_T aNumBytesToMap);
|
||||
static WindowsDllInterceptor::FuncHookType<decltype(&MapViewOfFile)>
|
||||
sMapViewOfFileOrig;
|
||||
|
||||
HBITMAP(WINAPI* sCreateDIBSectionOrig)(HDC aDC, const BITMAPINFO* aBitmapInfo,
|
||||
UINT aUsage, VOID** aBits,
|
||||
HANDLE aSection, DWORD aOffset);
|
||||
static WindowsDllInterceptor::FuncHookType<decltype(&CreateDIBSection)>
|
||||
sCreateDIBSectionOrig;
|
||||
|
||||
/**
|
||||
* Fire a memory pressure event if we were not under memory pressure yet, or
|
||||
|
@ -645,17 +643,12 @@ Init()
|
|||
// VirtualAllocHook from reentering itself.
|
||||
if (!PR_GetEnv("MOZ_PGO_INSTRUMENTED")) {
|
||||
sKernel32Intercept.Init("Kernel32.dll");
|
||||
sKernel32Intercept.AddHook("VirtualAlloc",
|
||||
reinterpret_cast<intptr_t>(VirtualAllocHook),
|
||||
reinterpret_cast<void**>(&sVirtualAllocOrig));
|
||||
sKernel32Intercept.AddHook("MapViewOfFile",
|
||||
reinterpret_cast<intptr_t>(MapViewOfFileHook),
|
||||
reinterpret_cast<void**>(&sMapViewOfFileOrig));
|
||||
sVirtualAllocOrig.Set(sKernel32Intercept, "VirtualAlloc", &VirtualAllocHook);
|
||||
sMapViewOfFileOrig.Set(sKernel32Intercept, "MapViewOfFile", &MapViewOfFileHook);
|
||||
|
||||
sGdi32Intercept.Init("Gdi32.dll");
|
||||
sGdi32Intercept.AddHook("CreateDIBSection",
|
||||
reinterpret_cast<intptr_t>(CreateDIBSectionHook),
|
||||
reinterpret_cast<void**>(&sCreateDIBSectionOrig));
|
||||
sCreateDIBSectionOrig.Set(sGdi32Intercept, "CreateDIBSection",
|
||||
&CreateDIBSectionHook);
|
||||
}
|
||||
|
||||
sInitialized = true;
|
||||
|
|
|
@ -209,13 +209,20 @@ WinIOAutoObservation::Filename(nsAString& aFilename)
|
|||
/*************************** IO Interposing Methods ***************************/
|
||||
|
||||
// Function pointers to original functions
|
||||
static NtCreateFileFn gOriginalNtCreateFile;
|
||||
static NtReadFileFn gOriginalNtReadFile;
|
||||
static NtReadFileScatterFn gOriginalNtReadFileScatter;
|
||||
static NtWriteFileFn gOriginalNtWriteFile;
|
||||
static NtWriteFileGatherFn gOriginalNtWriteFileGather;
|
||||
static NtFlushBuffersFileFn gOriginalNtFlushBuffersFile;
|
||||
static NtQueryFullAttributesFileFn gOriginalNtQueryFullAttributesFile;
|
||||
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 NTSTATUS NTAPI
|
||||
InterposedNtCreateFile(PHANDLE aFileHandle,
|
||||
|
@ -448,34 +455,21 @@ InitPoisonIOInterposer()
|
|||
|
||||
// Initialize dll interceptor and add hooks
|
||||
sNtDllInterceptor.Init("ntdll.dll");
|
||||
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));
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Загрузка…
Ссылка в новой задаче