зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 11 changesets (bug 1382251) for clipbloard failures, mingw32 bustage
Backed out changeset a5f447c3bde8 (bug 1382251) Backed out changeset f9f8aba058c1 (bug 1382251) Backed out changeset dc0ce4cae588 (bug 1382251) Backed out changeset 7a304ff7873a (bug 1382251) Backed out changeset 09cb062d95ee (bug 1382251) Backed out changeset 95701ac611fa (bug 1382251) Backed out changeset 37cad137215f (bug 1382251) Backed out changeset 0d82d0b69c9e (bug 1382251) Backed out changeset 24de376fb860 (bug 1382251) Backed out changeset 5f33ad77c5b4 (bug 1382251) Backed out changeset d2f531c6a6d8 (bug 1382251)
This commit is contained in:
Родитель
6f5458a90b
Коммит
52d6539c96
|
@ -1,975 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FunctionBroker.h"
|
||||
#include "FunctionBrokerParent.h"
|
||||
#include "PluginQuirks.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include <commdlg.h>
|
||||
#include <schannel.h>
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::plugins;
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
template <int QuirkFlag>
|
||||
static bool CheckQuirks(int aQuirks)
|
||||
{
|
||||
return static_cast<bool>(aQuirks & QuirkFlag);
|
||||
}
|
||||
|
||||
void FreeDestructor(void* aObj) { free(aObj); }
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
/* GetKeyState */
|
||||
|
||||
typedef FunctionBroker<ID_GetKeyState,
|
||||
decltype(GetKeyState)> GetKeyStateFB;
|
||||
|
||||
template<>
|
||||
ShouldHookFunc* const
|
||||
GetKeyStateFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_GETKEYSTATE>;
|
||||
|
||||
/* SetCursorPos */
|
||||
|
||||
typedef FunctionBroker<ID_SetCursorPos,
|
||||
decltype(SetCursorPos)> SetCursorPosFB;
|
||||
|
||||
/* GetSaveFileNameW */
|
||||
|
||||
typedef FunctionBroker<ID_GetSaveFileNameW,
|
||||
decltype(GetSaveFileNameW)> GetSaveFileNameWFB;
|
||||
|
||||
// Remember files granted access in the chrome process
|
||||
static void GrantFileAccess(base::ProcessId aClientId, LPOPENFILENAME& aLpofn,
|
||||
bool isSave)
|
||||
{
|
||||
#if defined(MOZ_SANDBOX)
|
||||
if (aLpofn->Flags & OFN_ALLOWMULTISELECT) {
|
||||
// We only support multiselect with the OFN_EXPLORER flag.
|
||||
// This guarantees that ofn.lpstrFile follows the pattern below.
|
||||
MOZ_ASSERT(aLpofn->Flags & OFN_EXPLORER);
|
||||
|
||||
// lpstrFile is one of two things:
|
||||
// 1. A null terminated full path to a file, or
|
||||
// 2. A path to a folder, followed by a NULL, followed by a
|
||||
// list of file names, each NULL terminated, followed by an
|
||||
// additional NULL (so it is also double-NULL terminated).
|
||||
std::wstring path = std::wstring(aLpofn->lpstrFile);
|
||||
MOZ_ASSERT(aLpofn->nFileOffset > 0);
|
||||
// For condition #1, nFileOffset points to the file name in the path.
|
||||
// It will be preceeded by a non-NULL character from the path.
|
||||
if (aLpofn->lpstrFile[aLpofn->nFileOffset-1] != L'\0') {
|
||||
FunctionBrokerParent::GetSandboxPermissions()->GrantFileAccess(aClientId, path.c_str(), isSave);
|
||||
}
|
||||
else {
|
||||
// This is condition #2
|
||||
wchar_t* nextFile = aLpofn->lpstrFile + path.size() + 1;
|
||||
while (*nextFile != L'\0') {
|
||||
std::wstring nextFileStr(nextFile);
|
||||
std::wstring fullPath =
|
||||
path + std::wstring(L"\\") + nextFileStr;
|
||||
FunctionBrokerParent::GetSandboxPermissions()->GrantFileAccess(aClientId, fullPath.c_str(), isSave);
|
||||
nextFile += nextFileStr.size() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
FunctionBrokerParent::GetSandboxPermissions()->GrantFileAccess(aClientId, aLpofn->lpstrFile, isSave);
|
||||
}
|
||||
#else
|
||||
MOZ_ASSERT_UNREACHABLE("GetFileName IPC message is only available on "
|
||||
"Windows builds with sandbox.");
|
||||
#endif
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
BOOL GetSaveFileNameWFB::RunFunction(GetSaveFileNameWFB::FunctionType* aOrigFunction,
|
||||
base::ProcessId aClientId,
|
||||
LPOPENFILENAMEW& aLpofn) const
|
||||
{
|
||||
BOOL result = aOrigFunction(aLpofn);
|
||||
if (result) {
|
||||
// Record any file access permission that was just granted.
|
||||
GrantFileAccess(aClientId, aLpofn, true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
struct GetSaveFileNameWFB::Response::Info::ShouldMarshal<0> { static const bool value = true; };
|
||||
|
||||
/* GetOpenFileNameW */
|
||||
|
||||
typedef FunctionBroker<ID_GetOpenFileNameW,
|
||||
decltype(GetOpenFileNameW)> GetOpenFileNameWFB;
|
||||
|
||||
template<> template<>
|
||||
BOOL GetOpenFileNameWFB::RunFunction(GetOpenFileNameWFB::FunctionType* aOrigFunction,
|
||||
base::ProcessId aClientId,
|
||||
LPOPENFILENAMEW& aLpofn) const
|
||||
{
|
||||
BOOL result = aOrigFunction(aLpofn);
|
||||
if (result) {
|
||||
// Record any file access permission that was just granted.
|
||||
GrantFileAccess(aClientId, aLpofn, false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
struct GetOpenFileNameWFB::Response::Info::ShouldMarshal<0> { static const bool value = true; };
|
||||
|
||||
/* InternetOpenA */
|
||||
|
||||
typedef FunctionBroker<ID_InternetOpenA,
|
||||
decltype(InternetOpenA)> InternetOpenAFB;
|
||||
|
||||
/* InternetConnectA */
|
||||
|
||||
typedef FunctionBroker<ID_InternetConnectA,
|
||||
decltype(InternetConnectA)> InternetConnectAFB;
|
||||
|
||||
typedef InternetConnectAFB::Request ICAReqHandler;
|
||||
|
||||
template<>
|
||||
bool ICAReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
|
||||
const LPCSTR& srv, const INTERNET_PORT& port,
|
||||
const LPCSTR& user, const LPCSTR& pass,
|
||||
const DWORD& svc, const DWORD& flags,
|
||||
const DWORD_PTR& cxt)
|
||||
{
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
|
||||
}
|
||||
|
||||
/* InternetCloseHandle */
|
||||
|
||||
typedef FunctionBroker<ID_InternetCloseHandle,
|
||||
decltype(InternetCloseHandle)> InternetCloseHandleFB;
|
||||
|
||||
typedef InternetCloseHandleFB::Request ICHReqHandler;
|
||||
|
||||
template<>
|
||||
bool ICHReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h)
|
||||
{
|
||||
// If we are server side then we were already validated since we had to be
|
||||
// looked up in the "uint64_t <-> HINTERNET" hashtable.
|
||||
// In the client, we check that this is a dummy handle.
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
|
||||
}
|
||||
|
||||
/* InternetQueryDataAvailable */
|
||||
|
||||
typedef FunctionBroker<ID_InternetQueryDataAvailable,
|
||||
decltype(InternetQueryDataAvailable)> InternetQueryDataAvailableFB;
|
||||
|
||||
typedef InternetQueryDataAvailableFB::Request IQDAReq;
|
||||
|
||||
typedef struct RequestHandler<ID_InternetQueryDataAvailable,
|
||||
BOOL HOOK_CALL (HINTERNET)> IQDADelegateReq;
|
||||
|
||||
template<>
|
||||
void IQDAReq::Marshal(IpdlTuple& aTuple, const HINTERNET& file,
|
||||
const LPDWORD& nBytes, const DWORD& flags,
|
||||
const DWORD_PTR& cxt)
|
||||
{
|
||||
IQDADelegateReq::Marshal(aTuple, file);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool IQDAReq::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& file,
|
||||
LPDWORD& nBytes, DWORD& flags, DWORD_PTR& cxt)
|
||||
{
|
||||
bool success = IQDADelegateReq::Unmarshal(aScd, aTuple, file);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
flags = 0;
|
||||
cxt = 0;
|
||||
nBytes = aScd.Allocate<DWORD>();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool IQDAReq::ShouldBroker(Endpoint endpoint, const HINTERNET& file,
|
||||
const LPDWORD& nBytes, const DWORD& flags,
|
||||
const DWORD_PTR& cxt)
|
||||
{
|
||||
// If we are server side then we were already validated since we had to be
|
||||
// looked up in the "uint64_t <-> HINTERNET" hashtable.
|
||||
// In the client, we check that this is a dummy handle.
|
||||
return (endpoint == SERVER) ||
|
||||
((flags == 0) && (cxt == 0) &&
|
||||
IsOdd(reinterpret_cast<uint64_t>(file)));
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
struct InternetQueryDataAvailableFB::Response::Info::ShouldMarshal<1> { static const bool value = true; };
|
||||
|
||||
/* InternetReadFile */
|
||||
|
||||
typedef FunctionBroker<ID_InternetReadFile,
|
||||
decltype(InternetReadFile)> InternetReadFileFB;
|
||||
|
||||
typedef InternetReadFileFB::Request IRFRequestHandler;
|
||||
typedef struct RequestHandler<ID_InternetReadFile,
|
||||
BOOL HOOK_CALL (HINTERNET, DWORD)> IRFDelegateReq;
|
||||
|
||||
template<>
|
||||
void IRFRequestHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
|
||||
const LPVOID& buf, const DWORD& nBytesToRead,
|
||||
const LPDWORD& nBytesRead)
|
||||
{
|
||||
IRFDelegateReq::Marshal(aTuple, h, nBytesToRead);
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
bool IRFRequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
|
||||
LPVOID& buf, DWORD& nBytesToRead,
|
||||
LPDWORD& nBytesRead)
|
||||
{
|
||||
bool ret = IRFDelegateReq::Unmarshal(aScd, aTuple, h, nBytesToRead);
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nBytesRead = aScd.Allocate<DWORD>();
|
||||
MOZ_ASSERT(nBytesToRead > 0);
|
||||
aScd.AllocateMemory(nBytesToRead, buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool IRFRequestHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
|
||||
const LPVOID& buf, const DWORD& nBytesToRead,
|
||||
const LPDWORD& nBytesRead)
|
||||
{
|
||||
// For server-side validation, the HINTERNET deserialization will have
|
||||
// required it to already be looked up in the IdToPtrMap. At that point,
|
||||
// any call is valid.
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
|
||||
}
|
||||
|
||||
// Marshal the output parameter that we sent to the response delegate.
|
||||
template<> template<>
|
||||
struct InternetReadFileFB::Response::Info::ShouldMarshal<0> { static const bool value = true; };
|
||||
|
||||
typedef ResponseHandler<ID_InternetReadFile, decltype(InternetReadFile)> IRFResponseHandler;
|
||||
typedef ResponseHandler<ID_InternetReadFile,
|
||||
BOOL HOOK_CALL (nsDependentCSubstring)> IRFDelegateResponseHandler;
|
||||
|
||||
template<>
|
||||
void IRFResponseHandler::Marshal(IpdlTuple& aTuple, const BOOL& ret, const HINTERNET& h,
|
||||
const LPVOID& buf, const DWORD& nBytesToRead,
|
||||
const LPDWORD& nBytesRead)
|
||||
{
|
||||
nsDependentCSubstring str;
|
||||
if (*nBytesRead) {
|
||||
str.Assign(static_cast<const char*>(buf), *nBytesRead);
|
||||
}
|
||||
IRFDelegateResponseHandler::Marshal(aTuple, ret, str);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool IRFResponseHandler::Unmarshal(const IpdlTuple& aTuple, BOOL& ret, HINTERNET& h,
|
||||
LPVOID& buf, DWORD& nBytesToRead,
|
||||
LPDWORD& nBytesRead)
|
||||
{
|
||||
nsDependentCSubstring str;
|
||||
bool success =
|
||||
IRFDelegateResponseHandler::Unmarshal(aTuple, ret, str);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (str.Length()) {
|
||||
memcpy(buf, str.Data(), str.Length());
|
||||
*nBytesRead = str.Length();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* InternetWriteFile */
|
||||
|
||||
typedef FunctionBroker<ID_InternetWriteFile,
|
||||
decltype(InternetWriteFile)> InternetWriteFileFB;
|
||||
|
||||
typedef InternetWriteFileFB::Request IWFReqHandler;
|
||||
typedef RequestHandler<ID_InternetWriteFile,
|
||||
int HOOK_CALL (HINTERNET, nsDependentCSubstring)> IWFDelegateReqHandler;
|
||||
|
||||
template<>
|
||||
void IWFReqHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& file, const LPCVOID& buf,
|
||||
const DWORD& nToWrite, const LPDWORD& nWritten)
|
||||
{
|
||||
MOZ_ASSERT(nWritten);
|
||||
IWFDelegateReqHandler::Marshal(aTuple, file,
|
||||
nsDependentCSubstring(static_cast<const char*>(buf), nToWrite));
|
||||
}
|
||||
|
||||
template<>
|
||||
bool IWFReqHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& file,
|
||||
LPCVOID& buf, DWORD& nToWrite, LPDWORD& nWritten)
|
||||
{
|
||||
nsDependentCSubstring str;
|
||||
if (!IWFDelegateReqHandler::Unmarshal(aScd, aTuple, file, str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aScd.AllocateString(str, buf, false);
|
||||
nToWrite = str.Length();
|
||||
nWritten = aScd.Allocate<DWORD>();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool IWFReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& file,
|
||||
const LPCVOID& buf, const DWORD& nToWrite,
|
||||
const LPDWORD& nWritten)
|
||||
{
|
||||
// For server-side validation, the HINTERNET deserialization will have
|
||||
// required it to already be looked up in the IdToPtrMap. At that point,
|
||||
// any call is valid.
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(file));
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
struct InternetWriteFileFB::Response::Info::ShouldMarshal<3> { static const bool value = true; };
|
||||
|
||||
/* InternetSetOptionA */
|
||||
|
||||
typedef FunctionBroker<ID_InternetSetOptionA,
|
||||
decltype(InternetSetOptionA)> InternetSetOptionAFB;
|
||||
|
||||
typedef InternetSetOptionAFB::Request ISOAReqHandler;
|
||||
typedef RequestHandler<ID_InternetSetOptionA,
|
||||
BOOL HOOK_CALL (HINTERNET, DWORD, nsDependentCSubstring)> ISOADelegateReqHandler;
|
||||
|
||||
template<>
|
||||
void ISOAReqHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h, const DWORD& opt,
|
||||
const LPVOID& buf, const DWORD& bufLen)
|
||||
{
|
||||
ISOADelegateReqHandler::Marshal(aTuple, h, opt,
|
||||
nsDependentCSubstring(static_cast<const char*>(buf), bufLen));
|
||||
}
|
||||
|
||||
template<>
|
||||
bool ISOAReqHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
|
||||
DWORD& opt, LPVOID& buf, DWORD& bufLen)
|
||||
{
|
||||
nsDependentCSubstring str;
|
||||
if (!ISOADelegateReqHandler::Unmarshal(aScd, aTuple, h, opt, str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aScd.AllocateString(str, buf, false);
|
||||
bufLen = str.Length();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool ISOAReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h, const DWORD& opt,
|
||||
const LPVOID& buf, const DWORD& bufLen)
|
||||
{
|
||||
// For server-side validation, the HINTERNET deserialization will have
|
||||
// required it to already be looked up in the IdToPtrMap. At that point,
|
||||
// any call is valid.
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
|
||||
}
|
||||
|
||||
/* HttpAddRequestHeadersA */
|
||||
|
||||
typedef FunctionBroker<ID_HttpAddRequestHeadersA,
|
||||
decltype(HttpAddRequestHeadersA)> HttpAddRequestHeadersAFB;
|
||||
|
||||
typedef HttpAddRequestHeadersAFB::Request HARHAReqHandler;
|
||||
|
||||
template<>
|
||||
bool HARHAReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
|
||||
const LPCSTR& head, const DWORD& headLen,
|
||||
const DWORD& mods)
|
||||
{
|
||||
// For server-side validation, the HINTERNET deserialization will have
|
||||
// required it to already be looked up in the IdToPtrMap. At that point,
|
||||
// any call is valid.
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
|
||||
}
|
||||
|
||||
/* HttpOpenRequestA */
|
||||
|
||||
typedef FunctionBroker<ID_HttpOpenRequestA,
|
||||
decltype(HttpOpenRequestA)> HttpOpenRequestAFB;
|
||||
|
||||
typedef HttpOpenRequestAFB::Request HORAReqHandler;
|
||||
typedef RequestHandler<ID_HttpOpenRequestA,
|
||||
HINTERNET HOOK_CALL (HINTERNET, LPCSTR, LPCSTR, LPCSTR, LPCSTR,
|
||||
nsTArray<nsCString>, DWORD, DWORD_PTR)> HORADelegateReqHandler;
|
||||
|
||||
template<>
|
||||
void HORAReqHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
|
||||
const LPCSTR& verb, const LPCSTR& obj,
|
||||
const LPCSTR& ver, const LPCSTR& ref,
|
||||
LPCSTR * const & acceptTypes, const DWORD& flags,
|
||||
const DWORD_PTR& cxt)
|
||||
{
|
||||
nsTArray<nsCString> arrayAcceptTypes;
|
||||
LPCSTR * curAcceptType = acceptTypes;
|
||||
if (curAcceptType) {
|
||||
while (*curAcceptType) {
|
||||
arrayAcceptTypes.AppendElement(nsCString(*curAcceptType));
|
||||
++curAcceptType;
|
||||
}
|
||||
}
|
||||
HORADelegateReqHandler::Marshal(aTuple, h, verb, obj, ver, ref,
|
||||
arrayAcceptTypes, flags, cxt);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool HORAReqHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
|
||||
LPCSTR& verb, LPCSTR& obj, LPCSTR& ver,
|
||||
LPCSTR& ref, LPCSTR *& acceptTypes,
|
||||
DWORD& flags, DWORD_PTR& cxt)
|
||||
{
|
||||
nsTArray<nsCString> arrayAcceptTypes;
|
||||
if (!HORADelegateReqHandler::Unmarshal(aScd, aTuple, h, verb, obj, ver, ref, arrayAcceptTypes, flags, cxt)) {
|
||||
return false;
|
||||
}
|
||||
if (arrayAcceptTypes.Length() == 0) {
|
||||
acceptTypes = nullptr;
|
||||
} else {
|
||||
aScd.AllocateMemory((arrayAcceptTypes.Length() + 1) * sizeof(LPCSTR), acceptTypes);
|
||||
for (size_t i = 0; i < arrayAcceptTypes.Length(); ++i) {
|
||||
aScd.AllocateString(arrayAcceptTypes[i], acceptTypes[i]);
|
||||
}
|
||||
acceptTypes[arrayAcceptTypes.Length()] = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool HORAReqHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
|
||||
const LPCSTR& verb, const LPCSTR& obj,
|
||||
const LPCSTR& ver, const LPCSTR& ref,
|
||||
LPCSTR * const & acceptTypes,
|
||||
const DWORD& flags, const DWORD_PTR& cxt)
|
||||
{
|
||||
// For the server-side test, the HINTERNET deserialization will have
|
||||
// required it to already be looked up in the IdToPtrMap. At that point,
|
||||
// any call is valid.
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
|
||||
}
|
||||
|
||||
/* HttpQueryInfoA */
|
||||
|
||||
typedef FunctionBroker<ID_HttpQueryInfoA,
|
||||
decltype(HttpQueryInfoA)> HttpQueryInfoAFB;
|
||||
|
||||
typedef HttpQueryInfoAFB::Request HQIARequestHandler;
|
||||
typedef RequestHandler<ID_HttpQueryInfoA,
|
||||
BOOL HOOK_CALL (HINTERNET, DWORD, BOOL, DWORD, BOOL,
|
||||
DWORD)> HQIADelegateRequestHandler;
|
||||
|
||||
template<>
|
||||
void HQIARequestHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
|
||||
const DWORD& lvl, const LPVOID& buf, const LPDWORD& bufLen,
|
||||
const LPDWORD& idx)
|
||||
{
|
||||
HQIADelegateRequestHandler::Marshal(aTuple, h, lvl,
|
||||
bufLen != nullptr, bufLen ? *bufLen : 0,
|
||||
idx != nullptr, idx ? *idx : 0);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool HQIARequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
|
||||
DWORD& lvl, LPVOID& buf, LPDWORD& bufLen,
|
||||
LPDWORD& idx)
|
||||
{
|
||||
BOOL hasBufLen, hasIdx;
|
||||
DWORD tempBufLen, tempIdx;
|
||||
bool success =
|
||||
HQIADelegateRequestHandler::Unmarshal(aScd, aTuple, h, lvl, hasBufLen, tempBufLen, hasIdx, tempIdx);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bufLen = nullptr;
|
||||
if (hasBufLen) {
|
||||
aScd.AllocateMemory(tempBufLen, buf, bufLen);
|
||||
}
|
||||
|
||||
idx = nullptr;
|
||||
if (hasIdx) {
|
||||
idx = aScd.Allocate<DWORD>(tempIdx);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool HQIARequestHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
|
||||
const DWORD& lvl, const LPVOID& buf,
|
||||
const LPDWORD& bufLen, const LPDWORD& idx)
|
||||
{
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
|
||||
}
|
||||
|
||||
// Marshal all of the output parameters that we sent to the response delegate.
|
||||
template<> template<>
|
||||
struct HttpQueryInfoAFB::Response::Info::ShouldMarshal<0> { static const bool value = true; };
|
||||
template<> template<>
|
||||
struct HttpQueryInfoAFB::Response::Info::ShouldMarshal<1> { static const bool value = true; };
|
||||
template<> template<>
|
||||
struct HttpQueryInfoAFB::Response::Info::ShouldMarshal<2> { static const bool value = true; };
|
||||
|
||||
typedef HttpQueryInfoAFB::Response HQIAResponseHandler;
|
||||
typedef ResponseHandler<ID_HttpQueryInfoA,
|
||||
BOOL HOOK_CALL (nsDependentCSubstring,
|
||||
DWORD, DWORD)> HQIADelegateResponseHandler;
|
||||
|
||||
template<>
|
||||
void HQIAResponseHandler::Marshal(IpdlTuple& aTuple, const BOOL& ret, const HINTERNET& h,
|
||||
const DWORD& lvl, const LPVOID& buf, const LPDWORD& bufLen,
|
||||
const LPDWORD& idx)
|
||||
{
|
||||
nsDependentCSubstring str;
|
||||
if (buf && ret) {
|
||||
MOZ_ASSERT(bufLen);
|
||||
str.Assign(static_cast<const char*>(buf), *bufLen);
|
||||
}
|
||||
// Note that we send the bufLen separately to handle the case where buf wasn't
|
||||
// allocated or large enough to hold the entire return value. bufLen is then
|
||||
// the required buffer size.
|
||||
HQIADelegateResponseHandler::Marshal(aTuple, ret, str,
|
||||
bufLen ? *bufLen : 0, idx ? *idx : 0);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool HQIAResponseHandler::Unmarshal(const IpdlTuple& aTuple, BOOL& ret, HINTERNET& h,
|
||||
DWORD& lvl, LPVOID& buf, LPDWORD& bufLen,
|
||||
LPDWORD& idx)
|
||||
{
|
||||
DWORD totalBufLen = *bufLen;
|
||||
nsDependentCSubstring str;
|
||||
DWORD tempBufLen, tempIdx;
|
||||
bool success =
|
||||
HQIADelegateResponseHandler::Unmarshal(aTuple, ret, str, tempBufLen, tempIdx);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bufLen) {
|
||||
*bufLen = tempBufLen;
|
||||
}
|
||||
if (idx) {
|
||||
*idx = tempIdx;
|
||||
}
|
||||
|
||||
if (buf && ret) {
|
||||
// When HttpQueryInfo returns strings, the buffer length will not include
|
||||
// the null terminator. Rather than (brittle-y) trying to determine if the
|
||||
// return buffer is a string, we always tack on a null terminator if the
|
||||
// buffer has room for it.
|
||||
MOZ_ASSERT(str.Length() == *bufLen);
|
||||
memcpy(buf, str.Data(), str.Length());
|
||||
if (str.Length() < totalBufLen) {
|
||||
char* cbuf = static_cast<char*>(buf);
|
||||
cbuf[str.Length()] = '\0';
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* HttpSendRequestA */
|
||||
|
||||
typedef FunctionBroker<ID_HttpSendRequestA,
|
||||
decltype(HttpSendRequestA)> HttpSendRequestAFB;
|
||||
|
||||
typedef HttpSendRequestAFB::Request HSRARequestHandler;
|
||||
typedef RequestHandler<ID_HttpSendRequestA,
|
||||
BOOL HOOK_CALL (HINTERNET, nsDependentCSubstring,
|
||||
nsDependentCSubstring)> HSRADelegateRequestHandler;
|
||||
|
||||
template<>
|
||||
void HSRARequestHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
|
||||
const LPCSTR& head, const DWORD& headLen,
|
||||
const LPVOID& opt, const DWORD& optLen)
|
||||
{
|
||||
nsDependentCSubstring headStr;
|
||||
headStr.SetIsVoid(head == nullptr);
|
||||
if (head) {
|
||||
// HttpSendRequest allows headLen == -1L for length of a null terminated string.
|
||||
DWORD ncHeadLen = headLen;
|
||||
if (ncHeadLen == -1L) {
|
||||
ncHeadLen = strlen(head);
|
||||
}
|
||||
headStr.Rebind(head, ncHeadLen);
|
||||
}
|
||||
nsDependentCSubstring optStr;
|
||||
optStr.SetIsVoid(opt == nullptr);
|
||||
if (opt) {
|
||||
optStr.Rebind(static_cast<const char*>(opt), optLen);
|
||||
}
|
||||
HSRADelegateRequestHandler::Marshal(aTuple, h, headStr, optStr);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool HSRARequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
|
||||
LPCSTR& head, DWORD& headLen, LPVOID& opt,
|
||||
DWORD& optLen)
|
||||
{
|
||||
nsDependentCSubstring headStr;
|
||||
nsDependentCSubstring optStr;
|
||||
bool success = HSRADelegateRequestHandler::Unmarshal(aScd, aTuple, h, headStr, optStr);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (headStr.IsVoid()) {
|
||||
head = nullptr;
|
||||
MOZ_ASSERT(headLen == 0);
|
||||
} else {
|
||||
aScd.AllocateString(headStr, head, false);
|
||||
headLen = headStr.Length();
|
||||
}
|
||||
|
||||
if (optStr.IsVoid()) {
|
||||
opt = nullptr;
|
||||
MOZ_ASSERT(optLen == 0);
|
||||
} else {
|
||||
aScd.AllocateString(optStr, opt, false);
|
||||
optLen = optStr.Length();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool HSRARequestHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
|
||||
const LPCSTR& head, const DWORD& headLen,
|
||||
const LPVOID& opt, const DWORD& optLen)
|
||||
{
|
||||
// If we are server side then we were already validated since we had to be
|
||||
// looked up in the "uint64_t <-> HINTERNET" hashtable.
|
||||
// In the client, we check that this is a dummy handle.
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
|
||||
}
|
||||
|
||||
/* HttpSendRequestExA */
|
||||
|
||||
typedef FunctionBroker<ID_HttpSendRequestExA,
|
||||
decltype(HttpSendRequestExA)> HttpSendRequestExAFB;
|
||||
|
||||
typedef RequestInfo<ID_HttpSendRequestExA> HSRExAReqInfo;
|
||||
|
||||
template<> template<>
|
||||
struct HSRExAReqInfo::FixedValue<2> { static const LPINTERNET_BUFFERSA value; };
|
||||
const LPINTERNET_BUFFERSA HSRExAReqInfo::FixedValue<2>::value = nullptr;
|
||||
|
||||
// Docs for HttpSendRequestExA say this parameter 'must' be zero but Flash
|
||||
// passes other values.
|
||||
// template<> template<>
|
||||
// struct HSRExAReqInfo::FixedValue<3> { static const DWORD value = 0; };
|
||||
|
||||
template<> template<>
|
||||
struct HSRExAReqInfo::FixedValue<4> { static const DWORD_PTR value = 0; };
|
||||
|
||||
/* InternetQueryOptionA */
|
||||
|
||||
typedef FunctionBroker<ID_InternetQueryOptionA,
|
||||
decltype(InternetQueryOptionA)> InternetQueryOptionAFB;
|
||||
|
||||
typedef InternetQueryOptionAFB::Request IQOARequestHandler;
|
||||
typedef RequestHandler<ID_InternetQueryOptionA,
|
||||
BOOL HOOK_CALL (HINTERNET, DWORD, DWORD)> IQOADelegateRequestHandler;
|
||||
|
||||
template<>
|
||||
void IQOARequestHandler::Marshal(IpdlTuple& aTuple, const HINTERNET& h,
|
||||
const DWORD& opt, const LPVOID& buf, const LPDWORD& bufLen)
|
||||
{
|
||||
MOZ_ASSERT(bufLen);
|
||||
IQOADelegateRequestHandler::Marshal(aTuple, h, opt, buf ? *bufLen : 0);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool IQOARequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, HINTERNET& h,
|
||||
DWORD& opt, LPVOID& buf, LPDWORD& bufLen)
|
||||
{
|
||||
DWORD tempBufLen;
|
||||
bool success =
|
||||
IQOADelegateRequestHandler::Unmarshal(aScd, aTuple, h, opt, tempBufLen);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aScd.AllocateMemory(tempBufLen, buf, bufLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool IQOARequestHandler::ShouldBroker(Endpoint endpoint, const HINTERNET& h,
|
||||
const DWORD& opt, const LPVOID& buf,
|
||||
const LPDWORD& bufLen)
|
||||
{
|
||||
// If we are server side then we were already validated since we had to be
|
||||
// looked up in the "uint64_t <-> HINTERNET" hashtable.
|
||||
// In the client, we check that this is a dummy handle.
|
||||
return (endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h));
|
||||
}
|
||||
|
||||
// Marshal all of the output parameters that we sent to the response delegate.
|
||||
template<> template<>
|
||||
struct InternetQueryOptionAFB::Response::Info::ShouldMarshal<0> { static const bool value = true; };
|
||||
template<> template<>
|
||||
struct InternetQueryOptionAFB::Response::Info::ShouldMarshal<1> { static const bool value = true; };
|
||||
|
||||
typedef InternetQueryOptionAFB::Response IQOAResponseHandler;
|
||||
typedef ResponseHandler<ID_InternetQueryOptionA,
|
||||
BOOL HOOK_CALL (nsDependentCSubstring, DWORD)> IQOADelegateResponseHandler;
|
||||
|
||||
template<>
|
||||
void IQOAResponseHandler::Marshal(IpdlTuple& aTuple, const BOOL& ret, const HINTERNET& h,
|
||||
const DWORD& opt, const LPVOID& buf, const LPDWORD& bufLen)
|
||||
{
|
||||
nsDependentCSubstring str;
|
||||
if (buf && ret) {
|
||||
MOZ_ASSERT(*bufLen);
|
||||
str.Assign(static_cast<const char*>(buf), *bufLen);
|
||||
}
|
||||
IQOADelegateResponseHandler::Marshal(aTuple, ret, str, *bufLen);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool IQOAResponseHandler::Unmarshal(const IpdlTuple& aTuple, BOOL& ret, HINTERNET& h,
|
||||
DWORD& opt, LPVOID& buf, LPDWORD& bufLen)
|
||||
{
|
||||
nsDependentCSubstring str;
|
||||
bool success =
|
||||
IQOADelegateResponseHandler::Unmarshal(aTuple, ret, str, *bufLen);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buf && ret) {
|
||||
MOZ_ASSERT(str.Length() == *bufLen);
|
||||
memcpy(buf, str.Data(), str.Length());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* InternetErrorDlg */
|
||||
|
||||
typedef FunctionBroker<ID_InternetErrorDlg,
|
||||
decltype(InternetErrorDlg)> InternetErrorDlgFB;
|
||||
|
||||
typedef RequestInfo<ID_InternetErrorDlg> IEDReqInfo;
|
||||
|
||||
template<> template<>
|
||||
struct IEDReqInfo::FixedValue<4> { static LPVOID* const value; };
|
||||
LPVOID* const IEDReqInfo::FixedValue<4>::value = nullptr;
|
||||
|
||||
typedef InternetErrorDlgFB::Request IEDReqHandler;
|
||||
|
||||
template<>
|
||||
bool IEDReqHandler::ShouldBroker(Endpoint endpoint, const HWND& hwnd,
|
||||
const HINTERNET& h, const DWORD& err,
|
||||
const DWORD& flags, LPVOID* const & data)
|
||||
{
|
||||
const DWORD SUPPORTED_FLAGS =
|
||||
FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
|
||||
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_NO_UI;
|
||||
|
||||
// We broker if (1) the handle h is brokered (odd in client),
|
||||
// (2) we support the requested action flags and (3) there is no user
|
||||
// data, which wouldn't make sense for our supported flags anyway.
|
||||
return ((endpoint == SERVER) || IsOdd(reinterpret_cast<uint64_t>(h))) &&
|
||||
(!(flags & ~SUPPORTED_FLAGS)) && (data == nullptr);
|
||||
}
|
||||
|
||||
/* AcquireCredentialsHandleA */
|
||||
|
||||
typedef FunctionBroker<ID_AcquireCredentialsHandleA,
|
||||
decltype(AcquireCredentialsHandleA)> AcquireCredentialsHandleAFB;
|
||||
|
||||
typedef RequestInfo<ID_AcquireCredentialsHandleA> ACHAReqInfo;
|
||||
|
||||
template<> template<>
|
||||
struct ACHAReqInfo::FixedValue<0> { static const LPSTR value; };
|
||||
const LPSTR ACHAReqInfo::FixedValue<0>::value = nullptr;
|
||||
|
||||
template<> template<>
|
||||
struct ACHAReqInfo::FixedValue<1> { static const LPSTR value; };
|
||||
const LPSTR ACHAReqInfo::FixedValue<1>::value = UNISP_NAME_A;
|
||||
|
||||
template<> template<>
|
||||
struct ACHAReqInfo::FixedValue<2> { static const unsigned long value; };
|
||||
const unsigned long ACHAReqInfo::FixedValue<2>::value = SECPKG_CRED_OUTBOUND;
|
||||
|
||||
template<> template<>
|
||||
struct ACHAReqInfo::FixedValue<3> { static void* const value; };
|
||||
void* const ACHAReqInfo::FixedValue<3>::value = nullptr;
|
||||
|
||||
template<> template<>
|
||||
struct ACHAReqInfo::FixedValue<5> { static const SEC_GET_KEY_FN value; };
|
||||
const SEC_GET_KEY_FN ACHAReqInfo::FixedValue<5>::value = nullptr;
|
||||
|
||||
template<> template<>
|
||||
struct ACHAReqInfo::FixedValue<6> { static void* const value; };
|
||||
void* const ACHAReqInfo::FixedValue<6>::value = nullptr;
|
||||
|
||||
typedef AcquireCredentialsHandleAFB::Request ACHARequestHandler;
|
||||
typedef RequestHandler<ID_AcquireCredentialsHandleA,
|
||||
SECURITY_STATUS HOOK_CALL (LPSTR, LPSTR, unsigned long,
|
||||
void*, PSCHANNEL_CRED, SEC_GET_KEY_FN,
|
||||
void*)> ACHADelegateRequestHandler;
|
||||
|
||||
template<>
|
||||
void ACHARequestHandler::Marshal(IpdlTuple& aTuple, const LPSTR& principal,
|
||||
const LPSTR& pkg, const unsigned long& credUse,
|
||||
const PVOID& logonId, const PVOID& auth,
|
||||
const SEC_GET_KEY_FN& getKeyFn,
|
||||
const PVOID& getKeyArg, const PCredHandle& cred,
|
||||
const PTimeStamp& expiry)
|
||||
{
|
||||
const PSCHANNEL_CRED& scCred = reinterpret_cast<const PSCHANNEL_CRED&>(auth);
|
||||
ACHADelegateRequestHandler::Marshal(aTuple, principal, pkg, credUse, logonId,
|
||||
scCred, getKeyFn, getKeyArg);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool ACHARequestHandler::Unmarshal(ServerCallData& aScd, const IpdlTuple& aTuple, LPSTR& principal,
|
||||
LPSTR& pkg, unsigned long& credUse,
|
||||
PVOID& logonId, PVOID& auth, SEC_GET_KEY_FN& getKeyFn,
|
||||
PVOID& getKeyArg, PCredHandle& cred, PTimeStamp& expiry)
|
||||
{
|
||||
PSCHANNEL_CRED& scCred = reinterpret_cast<PSCHANNEL_CRED&>(auth);
|
||||
if (!ACHADelegateRequestHandler::Unmarshal(aScd, aTuple, principal, pkg, credUse,
|
||||
logonId, scCred, getKeyFn, getKeyArg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cred = aScd.Allocate<CredHandle>();
|
||||
expiry = aScd.Allocate<::TimeStamp>();
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef ResponseInfo<ID_AcquireCredentialsHandleA> ACHARspInfo;
|
||||
|
||||
// Response phase must send output parameters
|
||||
template<> template<>
|
||||
struct ACHARspInfo::ShouldMarshal<7> { static const bool value = true; };
|
||||
template<> template<>
|
||||
struct ACHARspInfo::ShouldMarshal<8> { static const bool value = true; };
|
||||
|
||||
/* QueryCredentialsAttributesA */
|
||||
|
||||
typedef FunctionBroker<ID_QueryCredentialsAttributesA,
|
||||
decltype(QueryCredentialsAttributesA)> QueryCredentialsAttributesAFB;
|
||||
|
||||
/* FreeCredentialsHandle */
|
||||
|
||||
typedef FunctionBroker<ID_FreeCredentialsHandle,
|
||||
decltype(FreeCredentialsHandle)> FreeCredentialsHandleFB;
|
||||
|
||||
typedef FreeCredentialsHandleFB::Request FCHReq;
|
||||
|
||||
template<>
|
||||
bool FCHReq::ShouldBroker(Endpoint endpoint, const PCredHandle& h)
|
||||
{
|
||||
// If we are server side then we were already validated since we had to be
|
||||
// looked up in the "uint64_t <-> CredHandle" hashtable.
|
||||
// In the client, we check that this is a dummy handle.
|
||||
return (endpoint == SERVER) ||
|
||||
((h->dwLower == h->dwUpper) && IsOdd(static_cast<uint64_t>(h->dwLower)));
|
||||
}
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define FUN_HOOK(x) static_cast<FunctionHook*>(x)
|
||||
void
|
||||
AddBrokeredFunctionHooks(FunctionHookArray& aHooks)
|
||||
{
|
||||
// We transfer ownership of the FunctionHook objects to the array.
|
||||
#if defined(XP_WIN)
|
||||
aHooks[ID_GetKeyState] =
|
||||
FUN_HOOK(new GetKeyStateFB("user32.dll", "GetKeyState", &GetKeyState));
|
||||
aHooks[ID_SetCursorPos] =
|
||||
FUN_HOOK(new SetCursorPosFB("user32.dll", "SetCursorPos", &SetCursorPos));
|
||||
aHooks[ID_GetSaveFileNameW] =
|
||||
FUN_HOOK(new GetSaveFileNameWFB("comdlg32.dll", "GetSaveFileNameW",
|
||||
&GetSaveFileNameW));
|
||||
aHooks[ID_GetOpenFileNameW] =
|
||||
FUN_HOOK(new GetOpenFileNameWFB("comdlg32.dll", "GetOpenFileNameW",
|
||||
&GetOpenFileNameW));
|
||||
aHooks[ID_InternetOpenA] =
|
||||
FUN_HOOK(new InternetOpenAFB("wininet.dll", "InternetOpenA", &InternetOpenA));
|
||||
aHooks[ID_InternetConnectA] =
|
||||
FUN_HOOK(new InternetConnectAFB("wininet.dll", "InternetConnectA",
|
||||
&InternetConnectA));
|
||||
aHooks[ID_InternetCloseHandle] =
|
||||
FUN_HOOK(new InternetCloseHandleFB("wininet.dll", "InternetCloseHandle",
|
||||
&InternetCloseHandle));
|
||||
aHooks[ID_InternetQueryDataAvailable] =
|
||||
FUN_HOOK(new InternetQueryDataAvailableFB("wininet.dll",
|
||||
"InternetQueryDataAvailable",
|
||||
&InternetQueryDataAvailable));
|
||||
aHooks[ID_InternetReadFile] =
|
||||
FUN_HOOK(new InternetReadFileFB("wininet.dll", "InternetReadFile",
|
||||
&InternetReadFile));
|
||||
aHooks[ID_InternetWriteFile] =
|
||||
FUN_HOOK(new InternetWriteFileFB("wininet.dll", "InternetWriteFile",
|
||||
&InternetWriteFile));
|
||||
aHooks[ID_InternetSetOptionA] =
|
||||
FUN_HOOK(new InternetSetOptionAFB("wininet.dll", "InternetSetOptionA",
|
||||
&InternetSetOptionA));
|
||||
aHooks[ID_HttpAddRequestHeadersA] =
|
||||
FUN_HOOK(new HttpAddRequestHeadersAFB("wininet.dll",
|
||||
"HttpAddRequestHeadersA",
|
||||
&HttpAddRequestHeadersA));
|
||||
aHooks[ID_HttpOpenRequestA] =
|
||||
FUN_HOOK(new HttpOpenRequestAFB("wininet.dll", "HttpOpenRequestA",
|
||||
&HttpOpenRequestA));
|
||||
aHooks[ID_HttpQueryInfoA] =
|
||||
FUN_HOOK(new HttpQueryInfoAFB("wininet.dll", "HttpQueryInfoA",
|
||||
&HttpQueryInfoA));
|
||||
aHooks[ID_HttpSendRequestA] =
|
||||
FUN_HOOK(new HttpSendRequestAFB("wininet.dll", "HttpSendRequestA",
|
||||
&HttpSendRequestA));
|
||||
aHooks[ID_HttpSendRequestExA] =
|
||||
FUN_HOOK(new HttpSendRequestExAFB("wininet.dll", "HttpSendRequestExA",
|
||||
&HttpSendRequestExA));
|
||||
aHooks[ID_InternetQueryOptionA] =
|
||||
FUN_HOOK(new InternetQueryOptionAFB("wininet.dll", "InternetQueryOptionA",
|
||||
&InternetQueryOptionA));
|
||||
aHooks[ID_InternetErrorDlg] =
|
||||
FUN_HOOK(new InternetErrorDlgFB("wininet.dll", "InternetErrorDlg",
|
||||
InternetErrorDlg));
|
||||
aHooks[ID_AcquireCredentialsHandleA] =
|
||||
FUN_HOOK(new AcquireCredentialsHandleAFB("sspicli.dll",
|
||||
"AcquireCredentialsHandleA",
|
||||
&AcquireCredentialsHandleA));
|
||||
aHooks[ID_QueryCredentialsAttributesA] =
|
||||
FUN_HOOK(new QueryCredentialsAttributesAFB("sspicli.dll",
|
||||
"QueryCredentialsAttributesA",
|
||||
&QueryCredentialsAttributesA));
|
||||
aHooks[ID_FreeCredentialsHandle] =
|
||||
FUN_HOOK(new FreeCredentialsHandleFB("sspicli.dll",
|
||||
"FreeCredentialsHandle",
|
||||
&FreeCredentialsHandle));
|
||||
#endif // defined(XP_WIN)
|
||||
}
|
||||
|
||||
#undef FUN_HOOK
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,123 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FunctionBrokerChild.h"
|
||||
#include "FunctionBrokerThread.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
FunctionBrokerChild* FunctionBrokerChild::sInstance = nullptr;
|
||||
|
||||
bool
|
||||
FunctionBrokerChild::IsDispatchThread()
|
||||
{
|
||||
return mThread->IsOnThread();
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBrokerChild::PostToDispatchThread(already_AddRefed<nsIRunnable>&& runnable)
|
||||
{
|
||||
mThread->Dispatch(Move(runnable));
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
FunctionBrokerChild::Initialize(Endpoint<PFunctionBrokerChild>&& aBrokerEndpoint)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(XRE_IsPluginProcess(),
|
||||
"FunctionBrokerChild can only be used in plugin processes");
|
||||
|
||||
MOZ_ASSERT(!sInstance);
|
||||
FunctionBrokerThread* thread = FunctionBrokerThread::Create();
|
||||
if (!thread) {
|
||||
return false;
|
||||
}
|
||||
sInstance = new FunctionBrokerChild(thread, Move(aBrokerEndpoint));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ FunctionBrokerChild*
|
||||
FunctionBrokerChild::GetInstance()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(XRE_IsPluginProcess(),
|
||||
"FunctionBrokerChild can only be used in plugin processes");
|
||||
|
||||
MOZ_ASSERT(sInstance, "Must initialize FunctionBrokerChild before using it");
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
FunctionBrokerChild::FunctionBrokerChild(FunctionBrokerThread* aThread,
|
||||
Endpoint<PFunctionBrokerChild>&& aEndpoint) :
|
||||
mThread(aThread)
|
||||
, mShutdownDone(false)
|
||||
, mMonitor("FunctionBrokerChild Lock")
|
||||
{
|
||||
MOZ_ASSERT(aThread);
|
||||
PostToDispatchThread(NewNonOwningRunnableMethod<Endpoint<PFunctionBrokerChild>&&>(
|
||||
"FunctionBrokerChild::Bind", this, &FunctionBrokerChild::Bind,
|
||||
Move(aEndpoint)));
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBrokerChild::Bind(Endpoint<PFunctionBrokerChild>&& aEndpoint)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mThread->IsOnThread());
|
||||
DebugOnly<bool> ok = aEndpoint.Bind(this);
|
||||
MOZ_ASSERT(ok);
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBrokerChild::ShutdownOnDispatchThread()
|
||||
{
|
||||
MOZ_ASSERT(mThread->IsOnThread());
|
||||
|
||||
// Set mShutdownDone and notify waiting thread (if any) that we are done.
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mShutdownDone = true;
|
||||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBrokerChild::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
MOZ_ASSERT(mThread->IsOnThread());
|
||||
|
||||
// Queue up a task on the PD thread. When that task is executed then
|
||||
// we know that anything queued before ActorDestroy has completed.
|
||||
// At that point, we can set mShutdownDone and alert any waiting
|
||||
// threads that it is safe to destroy us.
|
||||
sInstance->PostToDispatchThread(NewNonOwningRunnableMethod(
|
||||
"FunctionBrokerChild::ShutdownOnDispatchThread", sInstance,
|
||||
&FunctionBrokerChild::ShutdownOnDispatchThread));
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBrokerChild::Destroy()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
// mShutdownDone will tell us when ActorDestroy has been run and any tasks
|
||||
// on the FunctionBrokerThread have completed. At that point, we can
|
||||
// safely delete the actor.
|
||||
{
|
||||
MonitorAutoLock lock(sInstance->mMonitor);
|
||||
while (!sInstance->mShutdownDone) {
|
||||
// Release lock and wait. Regain lock when we are notified that
|
||||
// we have ShutdownOnDispatchThread.
|
||||
sInstance->mMonitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
delete sInstance;
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,53 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_plugins_functionbrokerchild_h
|
||||
#define mozilla_plugins_functionbrokerchild_h
|
||||
|
||||
#include "mozilla/plugins/PFunctionBrokerChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class FunctionBrokerThread;
|
||||
|
||||
/**
|
||||
* Dispatches brokered methods to the Parent process to allow functionality
|
||||
* that is otherwise blocked by the sandbox.
|
||||
*/
|
||||
class FunctionBrokerChild : public PFunctionBrokerChild
|
||||
{
|
||||
public:
|
||||
static bool Initialize(Endpoint<PFunctionBrokerChild>&& aBrokerEndpoint);
|
||||
static FunctionBrokerChild* GetInstance();
|
||||
static void Destroy();
|
||||
|
||||
bool IsDispatchThread();
|
||||
void PostToDispatchThread(already_AddRefed<nsIRunnable>&& runnable);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
explicit FunctionBrokerChild(FunctionBrokerThread* aThread,
|
||||
Endpoint<PFunctionBrokerChild>&& aEndpoint);
|
||||
void ShutdownOnDispatchThread();
|
||||
void Bind(Endpoint<PFunctionBrokerChild>&& aEndpoint);
|
||||
|
||||
nsAutoPtr<FunctionBrokerThread> mThread;
|
||||
|
||||
// True if tasks on the FunctionBrokerThread have completed
|
||||
bool mShutdownDone;
|
||||
// This monitor guards mShutdownDone.
|
||||
Monitor mMonitor;
|
||||
|
||||
static FunctionBrokerChild* sInstance;
|
||||
};
|
||||
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_functionbrokerchild_h
|
|
@ -1,359 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FunctionBrokerIPCUtils.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
#include <schannel.h>
|
||||
|
||||
/* these defines are missing from mingw headers */
|
||||
#ifndef SP_PROT_TLS1_1_CLIENT
|
||||
#define SP_PROT_TLS1_1_CLIENT 0x00000200
|
||||
#endif
|
||||
|
||||
#ifndef SP_PROT_TLS1_2_CLIENT
|
||||
#define SP_PROT_TLS1_2_CLIENT 0x00000800
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
mozilla::LazyLogModule sPluginHooksLog("PluginHooks");
|
||||
|
||||
static const DWORD SCHANNEL_SUPPORTED_PROTOCOLS =
|
||||
SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
|
||||
|
||||
static const DWORD SCHANNEL_SUPPORTED_FLAGS =
|
||||
SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS |
|
||||
SCH_CRED_REVOCATION_CHECK_END_CERT;
|
||||
|
||||
void
|
||||
OpenFileNameIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
|
||||
{
|
||||
mHwndOwner = nullptr;
|
||||
|
||||
// Filter is double-NULL terminated. mFilter should include the double-NULL.
|
||||
mHasFilter = aLpofn->lpstrFilter != nullptr;
|
||||
if (mHasFilter) {
|
||||
uint32_t dNullIdx = 0;
|
||||
while (aLpofn->lpstrFilter[dNullIdx] != L'\0' ||
|
||||
aLpofn->lpstrFilter[dNullIdx+1] != L'\0') {
|
||||
dNullIdx++;
|
||||
}
|
||||
mFilter.assign(aLpofn->lpstrFilter, dNullIdx+2);
|
||||
}
|
||||
mHasCustomFilter = aLpofn->lpstrCustomFilter != nullptr;
|
||||
if (mHasCustomFilter) {
|
||||
mCustomFilterIn = std::wstring(aLpofn->lpstrCustomFilter);
|
||||
mNMaxCustFilterOut =
|
||||
aLpofn->nMaxCustFilter - (wcslen(aLpofn->lpstrCustomFilter) + 1);
|
||||
}
|
||||
else {
|
||||
mNMaxCustFilterOut = 0;
|
||||
}
|
||||
mFilterIndex = aLpofn->nFilterIndex;
|
||||
mFile = std::wstring(aLpofn->lpstrFile);
|
||||
mNMaxFile = aLpofn->nMaxFile;
|
||||
mNMaxFileTitle =
|
||||
aLpofn->lpstrFileTitle != nullptr ? aLpofn->nMaxFileTitle : 0;
|
||||
mHasInitialDir = aLpofn->lpstrInitialDir != nullptr;
|
||||
if (mHasInitialDir) {
|
||||
mInitialDir = std::wstring(aLpofn->lpstrInitialDir);
|
||||
}
|
||||
mHasTitle = aLpofn->lpstrTitle != nullptr;
|
||||
if (mHasTitle) {
|
||||
mTitle = std::wstring(aLpofn->lpstrTitle);
|
||||
}
|
||||
mHasDefExt = aLpofn->lpstrDefExt != nullptr;
|
||||
if (mHasDefExt) {
|
||||
mDefExt = std::wstring(aLpofn->lpstrDefExt);
|
||||
}
|
||||
|
||||
mFlags = aLpofn->Flags;
|
||||
// If the user sets OFN_ALLOWMULTISELECT then we require OFN_EXPLORER
|
||||
// as well. Without OFN_EXPLORER, the method has ancient legacy
|
||||
// behavior that we don't support.
|
||||
MOZ_ASSERT((mFlags & OFN_EXPLORER) || !(mFlags & OFN_ALLOWMULTISELECT));
|
||||
|
||||
// We ignore any visual customization and callbacks that the user set.
|
||||
mFlags &= ~(OFN_ENABLEHOOK | OFN_ENABLETEMPLATEHANDLE | OFN_ENABLETEMPLATE);
|
||||
|
||||
mFlagsEx = aLpofn->FlagsEx;
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileNameIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
|
||||
{
|
||||
aLpofn->lStructSize = sizeof(OPENFILENAMEW);
|
||||
aLpofn->hwndOwner = mHwndOwner;
|
||||
if (mHasFilter) {
|
||||
memcpy(const_cast<LPWSTR>(aLpofn->lpstrFilter),
|
||||
mFilter.data(), mFilter.size() * sizeof(wchar_t));
|
||||
}
|
||||
if (mHasCustomFilter) {
|
||||
aLpofn->nMaxCustFilter = mCustomFilterIn.size() + 1 + mNMaxCustFilterOut;
|
||||
wcscpy(aLpofn->lpstrCustomFilter, mCustomFilterIn.c_str());
|
||||
memset(aLpofn->lpstrCustomFilter + mCustomFilterIn.size() + 1, 0,
|
||||
mNMaxCustFilterOut * sizeof(wchar_t));
|
||||
}
|
||||
else {
|
||||
aLpofn->nMaxCustFilter = 0;
|
||||
}
|
||||
aLpofn->nFilterIndex = mFilterIndex;
|
||||
if (mNMaxFile > 0) {
|
||||
wcsncpy(aLpofn->lpstrFile, mFile.c_str(),
|
||||
std::min(static_cast<uint32_t>(mFile.size()+1), mNMaxFile));
|
||||
aLpofn->lpstrFile[mNMaxFile - 1] = L'\0';
|
||||
}
|
||||
aLpofn->nMaxFile = mNMaxFile;
|
||||
aLpofn->nMaxFileTitle = mNMaxFileTitle;
|
||||
if (mHasInitialDir) {
|
||||
wcscpy(const_cast<LPWSTR>(aLpofn->lpstrInitialDir), mInitialDir.c_str());
|
||||
}
|
||||
if (mHasTitle) {
|
||||
wcscpy(const_cast<LPWSTR>(aLpofn->lpstrTitle), mTitle.c_str());
|
||||
}
|
||||
aLpofn->Flags = mFlags; /* TODO: Consider adding OFN_NOCHANGEDIR */
|
||||
if (mHasDefExt) {
|
||||
wcscpy(const_cast<LPWSTR>(aLpofn->lpstrDefExt), mDefExt.c_str());
|
||||
}
|
||||
aLpofn->FlagsEx = mFlagsEx;
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileNameIPC::AllocateOfnStrings(LPOPENFILENAMEW aLpofn) const
|
||||
{
|
||||
if (mHasFilter) {
|
||||
// mFilter is double-NULL terminated and it includes the double-NULL in its length.
|
||||
aLpofn->lpstrFilter =
|
||||
static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mFilter.size())));
|
||||
}
|
||||
if (mHasCustomFilter) {
|
||||
aLpofn->lpstrCustomFilter =
|
||||
static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * (mCustomFilterIn.size() + 1 + mNMaxCustFilterOut)));
|
||||
}
|
||||
aLpofn->lpstrFile =
|
||||
static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFile));
|
||||
if (mNMaxFileTitle > 0) {
|
||||
aLpofn->lpstrFileTitle =
|
||||
static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFileTitle));
|
||||
}
|
||||
if (mHasInitialDir) {
|
||||
aLpofn->lpstrInitialDir =
|
||||
static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mInitialDir.size() + 1)));
|
||||
}
|
||||
if (mHasTitle) {
|
||||
aLpofn->lpstrTitle =
|
||||
static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mTitle.size() + 1)));
|
||||
}
|
||||
if (mHasDefExt) {
|
||||
aLpofn->lpstrDefExt =
|
||||
static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mDefExt.size() + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
OpenFileNameIPC::FreeOfnStrings(LPOPENFILENAMEW aLpofn)
|
||||
{
|
||||
if (aLpofn->lpstrFilter) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrFilter));
|
||||
}
|
||||
if (aLpofn->lpstrCustomFilter) {
|
||||
free(aLpofn->lpstrCustomFilter);
|
||||
}
|
||||
if (aLpofn->lpstrFile) {
|
||||
free(aLpofn->lpstrFile);
|
||||
}
|
||||
if (aLpofn->lpstrFileTitle) {
|
||||
free(aLpofn->lpstrFileTitle);
|
||||
}
|
||||
if (aLpofn->lpstrInitialDir) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrInitialDir));
|
||||
}
|
||||
if (aLpofn->lpstrTitle) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrTitle));
|
||||
}
|
||||
if (aLpofn->lpstrDefExt) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrDefExt));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileNameRetIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
|
||||
{
|
||||
if (aLpofn->lpstrCustomFilter != nullptr) {
|
||||
mCustomFilterOut =
|
||||
std::wstring(aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1);
|
||||
}
|
||||
mFile.assign(aLpofn->lpstrFile, aLpofn->nMaxFile);
|
||||
if (aLpofn->lpstrFileTitle != nullptr) {
|
||||
mFileTitle.assign(aLpofn->lpstrFileTitle, wcslen(aLpofn->lpstrFileTitle) + 1);
|
||||
}
|
||||
mFileOffset = aLpofn->nFileOffset;
|
||||
mFileExtension = aLpofn->nFileExtension;
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileNameRetIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
|
||||
{
|
||||
if (aLpofn->lpstrCustomFilter) {
|
||||
LPWSTR secondString =
|
||||
aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1;
|
||||
const wchar_t* customFilterOut = mCustomFilterOut.c_str();
|
||||
MOZ_ASSERT(wcslen(aLpofn->lpstrCustomFilter) + 1 +
|
||||
wcslen(customFilterOut) + 1 + 1 <= aLpofn->nMaxCustFilter);
|
||||
wcscpy(secondString, customFilterOut);
|
||||
secondString[wcslen(customFilterOut) + 1] = L'\0'; // terminated with two NULLs
|
||||
}
|
||||
MOZ_ASSERT(mFile.size() <= aLpofn->nMaxFile);
|
||||
memcpy(aLpofn->lpstrFile,
|
||||
mFile.data(), mFile.size() * sizeof(wchar_t));
|
||||
if (aLpofn->lpstrFileTitle != nullptr) {
|
||||
MOZ_ASSERT(mFileTitle.size() + 1 < aLpofn->nMaxFileTitle);
|
||||
wcscpy(aLpofn->lpstrFileTitle, mFileTitle.c_str());
|
||||
}
|
||||
aLpofn->nFileOffset = mFileOffset;
|
||||
aLpofn->nFileExtension = mFileExtension;
|
||||
}
|
||||
|
||||
void
|
||||
IPCSchannelCred::CopyFrom(const PSCHANNEL_CRED& aSCred)
|
||||
{
|
||||
// We assert that the aSCred fields take supported values.
|
||||
// If they do not then we ignore the values we were given.
|
||||
MOZ_ASSERT(aSCred->dwVersion == SCHANNEL_CRED_VERSION);
|
||||
MOZ_ASSERT(aSCred->cCreds == 0);
|
||||
MOZ_ASSERT(aSCred->paCred == nullptr);
|
||||
MOZ_ASSERT(aSCred->hRootStore == nullptr);
|
||||
MOZ_ASSERT(aSCred->cMappers == 0);
|
||||
MOZ_ASSERT(aSCred->aphMappers == nullptr);
|
||||
MOZ_ASSERT(aSCred->cSupportedAlgs == 0);
|
||||
MOZ_ASSERT(aSCred->palgSupportedAlgs == nullptr);
|
||||
MOZ_ASSERT((aSCred->grbitEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS) ==
|
||||
aSCred->grbitEnabledProtocols);
|
||||
mEnabledProtocols =
|
||||
aSCred->grbitEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS;
|
||||
mMinStrength = aSCred->dwMinimumCipherStrength;
|
||||
mMaxStrength = aSCred->dwMaximumCipherStrength;
|
||||
MOZ_ASSERT(aSCred->dwSessionLifespan == 0);
|
||||
MOZ_ASSERT((aSCred->dwFlags & SCHANNEL_SUPPORTED_FLAGS) == aSCred->dwFlags);
|
||||
mFlags = aSCred->dwFlags & SCHANNEL_SUPPORTED_FLAGS;
|
||||
MOZ_ASSERT(aSCred->dwCredFormat == 0);
|
||||
}
|
||||
|
||||
void
|
||||
IPCSchannelCred::CopyTo(PSCHANNEL_CRED& aSCred) const
|
||||
{
|
||||
// Validate values as they come from an untrusted process.
|
||||
memset(aSCred, 0, sizeof(SCHANNEL_CRED));
|
||||
aSCred->dwVersion = SCHANNEL_CRED_VERSION;
|
||||
aSCred->grbitEnabledProtocols =
|
||||
mEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS;
|
||||
aSCred->dwMinimumCipherStrength = mMinStrength;
|
||||
aSCred->dwMaximumCipherStrength = mMaxStrength;
|
||||
aSCred->dwFlags = mFlags & SCHANNEL_SUPPORTED_FLAGS;
|
||||
}
|
||||
|
||||
void
|
||||
IPCInternetBuffers::CopyFrom(const LPINTERNET_BUFFERSA& aBufs)
|
||||
{
|
||||
mBuffers.Clear();
|
||||
|
||||
LPINTERNET_BUFFERSA inetBuf = aBufs;
|
||||
while (inetBuf) {
|
||||
MOZ_ASSERT(inetBuf->dwStructSize == sizeof(INTERNET_BUFFERSA));
|
||||
Buffer* ipcBuf = mBuffers.AppendElement();
|
||||
|
||||
ipcBuf->mHeader.SetIsVoid(inetBuf->lpcszHeader == nullptr);
|
||||
if (inetBuf->lpcszHeader) {
|
||||
ipcBuf->mHeader.Assign(inetBuf->lpcszHeader, inetBuf->dwHeadersLength);
|
||||
}
|
||||
ipcBuf->mHeaderTotal = inetBuf->dwHeadersTotal;
|
||||
|
||||
ipcBuf->mBuffer.SetIsVoid(inetBuf->lpvBuffer == nullptr);
|
||||
if (inetBuf->lpvBuffer) {
|
||||
ipcBuf->mBuffer.Assign(static_cast<char*>(inetBuf->lpvBuffer),
|
||||
inetBuf->dwBufferLength);
|
||||
}
|
||||
ipcBuf->mBufferTotal = inetBuf->dwBufferTotal;
|
||||
inetBuf = inetBuf->Next;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IPCInternetBuffers::CopyTo(LPINTERNET_BUFFERSA& aBufs) const
|
||||
{
|
||||
MOZ_ASSERT(!aBufs);
|
||||
|
||||
LPINTERNET_BUFFERSA lastBuf = nullptr;
|
||||
for (size_t idx = 0; idx < mBuffers.Length(); ++idx) {
|
||||
const Buffer& ipcBuf = mBuffers[idx];
|
||||
LPINTERNET_BUFFERSA newBuf =
|
||||
static_cast<LPINTERNET_BUFFERSA>(moz_xcalloc(1, sizeof(INTERNET_BUFFERSA)));
|
||||
if (idx == 0) {
|
||||
aBufs = newBuf;
|
||||
} else {
|
||||
MOZ_ASSERT(lastBuf);
|
||||
lastBuf->Next = newBuf;
|
||||
lastBuf = newBuf;
|
||||
}
|
||||
|
||||
newBuf->dwStructSize = sizeof(INTERNET_BUFFERSA);
|
||||
|
||||
newBuf->dwHeadersTotal = ipcBuf.mHeaderTotal;
|
||||
if (!ipcBuf.mHeader.IsVoid()) {
|
||||
newBuf->lpcszHeader =
|
||||
static_cast<LPCSTR>(moz_xmalloc(ipcBuf.mHeader.Length()));
|
||||
memcpy(const_cast<char*>(newBuf->lpcszHeader), ipcBuf.mHeader.Data(),
|
||||
ipcBuf.mHeader.Length());
|
||||
newBuf->dwHeadersLength = ipcBuf.mHeader.Length();
|
||||
}
|
||||
|
||||
newBuf->dwBufferTotal = ipcBuf.mBufferTotal;
|
||||
if (!ipcBuf.mBuffer.IsVoid()) {
|
||||
newBuf->lpvBuffer = moz_xmalloc(ipcBuf.mBuffer.Length());
|
||||
memcpy(newBuf->lpvBuffer, ipcBuf.mBuffer.Data(),
|
||||
ipcBuf.mBuffer.Length());
|
||||
newBuf->dwBufferLength = ipcBuf.mBuffer.Length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
IPCInternetBuffers::FreeBuffers(LPINTERNET_BUFFERSA& aBufs)
|
||||
{
|
||||
if (!aBufs) {
|
||||
return;
|
||||
}
|
||||
while (aBufs) {
|
||||
LPINTERNET_BUFFERSA temp = aBufs->Next;
|
||||
free(const_cast<char*>(aBufs->lpcszHeader));
|
||||
free(aBufs->lpvBuffer);
|
||||
free(aBufs);
|
||||
aBufs = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IPCPrintDlg::CopyFrom(const LPPRINTDLGW& aDlg)
|
||||
{
|
||||
// DLP: Trouble -- my prior impl "worked" but didn't return anything
|
||||
// AFAIR. So... ??? But it printed a page!!! How?!
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
}
|
||||
|
||||
void
|
||||
IPCPrintDlg::CopyTo(LPPRINTDLGW& aDlg) const
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // defined(XP_WIN)
|
|
@ -1,459 +0,0 @@
|
|||
#ifndef dom_plugins_ipc_functionbrokeripcutils_h
|
||||
#define dom_plugins_ipc_functionbrokeripcutils_h 1
|
||||
|
||||
#include "PluginMessageUtils.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
#define SECURITY_WIN32
|
||||
#include <security.h>
|
||||
#include <wininet.h>
|
||||
#include <schannel.h>
|
||||
#include <commdlg.h>
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* This enum represents all of the methods hooked by the main facility in BrokerClient.
|
||||
* It is used to allow quick lookup in the sFunctionsToHook structure.
|
||||
*/
|
||||
enum FunctionHookId
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
ID_GetWindowInfo = 0
|
||||
, ID_GetKeyState
|
||||
, ID_SetCursorPos
|
||||
, ID_GetSaveFileNameW
|
||||
, ID_GetOpenFileNameW
|
||||
, ID_InternetOpenA
|
||||
, ID_InternetConnectA
|
||||
, ID_InternetCloseHandle
|
||||
, ID_InternetQueryDataAvailable
|
||||
, ID_InternetReadFile
|
||||
, ID_InternetWriteFile
|
||||
, ID_InternetSetOptionA
|
||||
, ID_HttpAddRequestHeadersA
|
||||
, ID_HttpOpenRequestA
|
||||
, ID_HttpQueryInfoA
|
||||
, ID_HttpSendRequestA
|
||||
, ID_HttpSendRequestExA
|
||||
, ID_InternetQueryOptionA
|
||||
, ID_InternetErrorDlg
|
||||
, ID_AcquireCredentialsHandleA
|
||||
, ID_QueryCredentialsAttributesA
|
||||
, ID_FreeCredentialsHandle
|
||||
, ID_PrintDlgW
|
||||
, ID_FunctionHookCount
|
||||
#else // defined(XP_WIN)
|
||||
ID_FunctionHookCount
|
||||
#endif // defined(XP_WIN)
|
||||
};
|
||||
|
||||
// Max number of bytes to show when logging a blob of raw memory
|
||||
static const uint32_t MAX_BLOB_CHARS_TO_LOG = 12;
|
||||
|
||||
// Format strings for safe logging despite the fact that they are sometimes
|
||||
// used as raw binary blobs.
|
||||
inline nsCString FormatBlob(const nsACString& aParam)
|
||||
{
|
||||
if (aParam.IsVoid() || aParam.IsEmpty()) {
|
||||
return nsCString(aParam.IsVoid() ? "<void>" : "<empty>");
|
||||
}
|
||||
|
||||
nsCString str;
|
||||
uint32_t totalLen = std::min(MAX_BLOB_CHARS_TO_LOG, aParam.Length());
|
||||
// If we are printing only a portion of the string then follow it with ellipsis
|
||||
const char* maybeEllipsis = (MAX_BLOB_CHARS_TO_LOG < aParam.Length()) ? "..." : "";
|
||||
for (uint32_t idx = 0; idx < totalLen; ++idx) {
|
||||
// Should be %02x but I've run into a AppendPrintf bug...
|
||||
str.AppendPrintf("0x%2x ", aParam.Data()[idx] & 0xff);
|
||||
}
|
||||
str.AppendPrintf("%s | '", maybeEllipsis);
|
||||
for (uint32_t idx = 0; idx < totalLen; ++idx) {
|
||||
str.AppendPrintf("%c", (aParam.Data()[idx] > 0) ? aParam.Data()[idx] : '.');
|
||||
}
|
||||
str.AppendPrintf("'%s", maybeEllipsis);
|
||||
return str;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
// Values indicate GetOpenFileNameW and GetSaveFileNameW.
|
||||
enum GetFileNameFunc { OPEN_FUNC, SAVE_FUNC };
|
||||
|
||||
typedef nsTArray<nsCString> StringArray;
|
||||
|
||||
// IPC-capable version of the Windows OPENFILENAMEW struct.
|
||||
typedef struct _OpenFileNameIPC
|
||||
{
|
||||
// Allocates memory for the strings in this object. This should usually
|
||||
// be used with a zeroed out OPENFILENAMEW structure.
|
||||
void AllocateOfnStrings(LPOPENFILENAMEW aLpofn) const;
|
||||
static void FreeOfnStrings(LPOPENFILENAMEW aLpofn);
|
||||
void AddToOfn(LPOPENFILENAMEW aLpofn) const;
|
||||
void CopyFromOfn(LPOPENFILENAMEW aLpofn);
|
||||
bool operator==(const _OpenFileNameIPC& o) const
|
||||
{
|
||||
return (o.mHwndOwner == mHwndOwner) &&
|
||||
(o.mFilter == mFilter) &&
|
||||
(o.mHasFilter == mHasFilter) &&
|
||||
(o.mCustomFilterIn == mCustomFilterIn) &&
|
||||
(o.mHasCustomFilter == mHasCustomFilter) &&
|
||||
(o.mNMaxCustFilterOut == mNMaxCustFilterOut) &&
|
||||
(o.mFilterIndex == mFilterIndex) &&
|
||||
(o.mFile == mFile) &&
|
||||
(o.mNMaxFile == mNMaxFile) &&
|
||||
(o.mNMaxFileTitle == mNMaxFileTitle) &&
|
||||
(o.mInitialDir == mInitialDir) &&
|
||||
(o.mHasInitialDir == mHasInitialDir) &&
|
||||
(o.mTitle == mTitle) &&
|
||||
(o.mHasTitle == mHasTitle) &&
|
||||
(o.mFlags == mFlags) &&
|
||||
(o.mDefExt == mDefExt) &&
|
||||
(o.mHasDefExt == mHasDefExt) &&
|
||||
(o.mFlagsEx == mFlagsEx);
|
||||
}
|
||||
|
||||
NativeWindowHandle mHwndOwner;
|
||||
std::wstring mFilter; // Double-NULL terminated (i.e. L"\0\0") if mHasFilter is true
|
||||
bool mHasFilter;
|
||||
std::wstring mCustomFilterIn;
|
||||
bool mHasCustomFilter;
|
||||
uint32_t mNMaxCustFilterOut;
|
||||
uint32_t mFilterIndex;
|
||||
std::wstring mFile;
|
||||
uint32_t mNMaxFile;
|
||||
uint32_t mNMaxFileTitle;
|
||||
std::wstring mInitialDir;
|
||||
bool mHasInitialDir;
|
||||
std::wstring mTitle;
|
||||
bool mHasTitle;
|
||||
uint32_t mFlags;
|
||||
std::wstring mDefExt;
|
||||
bool mHasDefExt;
|
||||
uint32_t mFlagsEx;
|
||||
} OpenFileNameIPC;
|
||||
|
||||
// GetOpenFileNameW and GetSaveFileNameW overwrite fields of their OPENFILENAMEW
|
||||
// parameter. This represents those values so that they can be returned via IPC.
|
||||
typedef struct _OpenFileNameRetIPC
|
||||
{
|
||||
void CopyFromOfn(LPOPENFILENAMEW aLpofn);
|
||||
void AddToOfn(LPOPENFILENAMEW aLpofn) const;
|
||||
bool operator==(const _OpenFileNameRetIPC& o) const
|
||||
{
|
||||
return (o.mCustomFilterOut == mCustomFilterOut) &&
|
||||
(o.mFile == mFile) &&
|
||||
(o.mFileTitle == mFileTitle) &&
|
||||
(o.mFileOffset == mFileOffset) &&
|
||||
(o.mFileExtension == mFileExtension);
|
||||
}
|
||||
|
||||
std::wstring mCustomFilterOut;
|
||||
std::wstring mFile; // Double-NULL terminated (i.e. L"\0\0")
|
||||
std::wstring mFileTitle;
|
||||
uint16_t mFileOffset;
|
||||
uint16_t mFileExtension;
|
||||
} OpenFileNameRetIPC;
|
||||
|
||||
typedef struct _IPCSchannelCred
|
||||
{
|
||||
void CopyFrom(const PSCHANNEL_CRED& aSCred);
|
||||
void CopyTo(PSCHANNEL_CRED& aSCred) const;
|
||||
bool operator==(const _IPCSchannelCred& o) const
|
||||
{
|
||||
return (o.mEnabledProtocols == mEnabledProtocols) &&
|
||||
(o.mMinStrength == mMinStrength) &&
|
||||
(o.mMaxStrength == mMaxStrength) &&
|
||||
(o.mFlags == mFlags);
|
||||
}
|
||||
|
||||
|
||||
DWORD mEnabledProtocols;
|
||||
DWORD mMinStrength;
|
||||
DWORD mMaxStrength;
|
||||
DWORD mFlags;
|
||||
} IPCSchannelCred;
|
||||
|
||||
typedef struct _IPCInternetBuffers
|
||||
{
|
||||
void CopyFrom(const LPINTERNET_BUFFERSA& aBufs);
|
||||
void CopyTo(LPINTERNET_BUFFERSA& aBufs) const;
|
||||
bool operator==(const _IPCInternetBuffers& o) const
|
||||
{
|
||||
return o.mBuffers == mBuffers;
|
||||
}
|
||||
static void FreeBuffers(LPINTERNET_BUFFERSA& aBufs);
|
||||
|
||||
struct Buffer
|
||||
{
|
||||
nsCString mHeader;
|
||||
uint32_t mHeaderTotal;
|
||||
nsCString mBuffer;
|
||||
uint32_t mBufferTotal;
|
||||
bool operator==(const Buffer& o) const
|
||||
{
|
||||
return (o.mHeader == mHeader) && (o.mHeaderTotal == mHeaderTotal) &&
|
||||
(o.mBuffer == mBuffer) && (o.mBufferTotal == mBufferTotal);
|
||||
}
|
||||
};
|
||||
nsTArray<Buffer> mBuffers;
|
||||
} IPCInternetBuffers;
|
||||
|
||||
typedef struct _IPCPrintDlg
|
||||
{
|
||||
void CopyFrom(const LPPRINTDLGW& aDlg);
|
||||
void CopyTo(LPPRINTDLGW& aDlg) const;
|
||||
bool operator==(const _IPCPrintDlg& o) const
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("DLP: TODO:"); return false;
|
||||
}
|
||||
} IPCPrintDlg;
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
using mozilla::plugins::FunctionHookId;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
using mozilla::plugins::OpenFileNameIPC;
|
||||
using mozilla::plugins::OpenFileNameRetIPC;
|
||||
using mozilla::plugins::IPCSchannelCred;
|
||||
using mozilla::plugins::IPCInternetBuffers;
|
||||
using mozilla::plugins::IPCPrintDlg;
|
||||
using mozilla::plugins::NativeWindowHandle;
|
||||
using mozilla::plugins::StringArray;
|
||||
|
||||
template <>
|
||||
struct ParamTraits<OpenFileNameIPC>
|
||||
{
|
||||
typedef OpenFileNameIPC paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mHwndOwner);
|
||||
WriteParam(aMsg, aParam.mFilter);
|
||||
WriteParam(aMsg, aParam.mHasFilter);
|
||||
WriteParam(aMsg, aParam.mCustomFilterIn);
|
||||
WriteParam(aMsg, aParam.mHasCustomFilter);
|
||||
WriteParam(aMsg, aParam.mNMaxCustFilterOut);
|
||||
WriteParam(aMsg, aParam.mFilterIndex);
|
||||
WriteParam(aMsg, aParam.mFile);
|
||||
WriteParam(aMsg, aParam.mNMaxFile);
|
||||
WriteParam(aMsg, aParam.mNMaxFileTitle);
|
||||
WriteParam(aMsg, aParam.mInitialDir);
|
||||
WriteParam(aMsg, aParam.mHasInitialDir);
|
||||
WriteParam(aMsg, aParam.mTitle);
|
||||
WriteParam(aMsg, aParam.mHasTitle);
|
||||
WriteParam(aMsg, aParam.mFlags);
|
||||
WriteParam(aMsg, aParam.mDefExt);
|
||||
WriteParam(aMsg, aParam.mHasDefExt);
|
||||
WriteParam(aMsg, aParam.mFlagsEx);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
if (ReadParam(aMsg, aIter, &aResult->mHwndOwner) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFilter) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasFilter) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mCustomFilterIn) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasCustomFilter) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNMaxCustFilterOut) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFilterIndex) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNMaxFile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNMaxFileTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mInitialDir) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasInitialDir) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFlags) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDefExt) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasDefExt) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFlagsEx)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(StringPrintf(L"[%S, %S, %S, %S]", aParam.mFilter.c_str(),
|
||||
aParam.mCustomFilterIn.c_str(), aParam.mFile.c_str(),
|
||||
aParam.mTitle.c_str()));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<OpenFileNameRetIPC>
|
||||
{
|
||||
typedef OpenFileNameRetIPC paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mCustomFilterOut);
|
||||
WriteParam(aMsg, aParam.mFile);
|
||||
WriteParam(aMsg, aParam.mFileTitle);
|
||||
WriteParam(aMsg, aParam.mFileOffset);
|
||||
WriteParam(aMsg, aParam.mFileExtension);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
if (ReadParam(aMsg, aIter, &aResult->mCustomFilterOut) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFileTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFileOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFileExtension)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(StringPrintf(L"[%S, %S, %S, %d, %d]", aParam.mCustomFilterOut.c_str(),
|
||||
aParam.mFile.c_str(), aParam.mFileTitle.c_str(),
|
||||
aParam.mFileOffset, aParam.mFileExtension));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::GetFileNameFunc> :
|
||||
public ContiguousEnumSerializerInclusive<mozilla::plugins::GetFileNameFunc,
|
||||
mozilla::plugins::OPEN_FUNC,
|
||||
mozilla::plugins::SAVE_FUNC>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IPCSchannelCred>
|
||||
{
|
||||
typedef mozilla::plugins::IPCSchannelCred paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, static_cast<uint32_t>(aParam.mEnabledProtocols));
|
||||
WriteParam(aMsg, static_cast<uint32_t>(aParam.mMinStrength));
|
||||
WriteParam(aMsg, static_cast<uint32_t>(aParam.mMaxStrength));
|
||||
WriteParam(aMsg, static_cast<uint32_t>(aParam.mFlags));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
uint32_t proto, minStr, maxStr, flags;
|
||||
if (!ReadParam(aMsg, aIter, &proto) ||
|
||||
!ReadParam(aMsg, aIter, &minStr) ||
|
||||
!ReadParam(aMsg, aIter, &maxStr) ||
|
||||
!ReadParam(aMsg, aIter, &flags)) {
|
||||
return false;
|
||||
}
|
||||
aResult->mEnabledProtocols = proto;
|
||||
aResult->mMinStrength = minStr;
|
||||
aResult->mMaxStrength = maxStr;
|
||||
aResult->mFlags = flags;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(StringPrintf(L"[%d,%d,%d,%d]",
|
||||
aParam.mEnabledProtocols, aParam.mMinStrength,
|
||||
aParam.mMaxStrength, aParam.mFlags));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IPCInternetBuffers::Buffer>
|
||||
{
|
||||
typedef mozilla::plugins::IPCInternetBuffers::Buffer paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mHeader);
|
||||
WriteParam(aMsg, aParam.mHeaderTotal);
|
||||
WriteParam(aMsg, aParam.mBuffer);
|
||||
WriteParam(aMsg, aParam.mBufferTotal);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->mHeader) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHeaderTotal) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mBuffer) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mBufferTotal);
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
nsCString head = mozilla::plugins::FormatBlob(aParam.mHeader);
|
||||
nsCString buffer = mozilla::plugins::FormatBlob(aParam.mBuffer);
|
||||
std::string msg = StringPrintf("[%s, %d, %s, %d]",
|
||||
head.Data(), aParam.mHeaderTotal,
|
||||
buffer.Data(), aParam.mBufferTotal);
|
||||
aLog->append(msg.begin(), msg.end());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IPCInternetBuffers>
|
||||
{
|
||||
typedef mozilla::plugins::IPCInternetBuffers paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mBuffers);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->mBuffers);
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
ParamTraits<nsTArray<IPCInternetBuffers::Buffer>>::Log(aParam.mBuffers, aLog);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IPCPrintDlg>
|
||||
{
|
||||
typedef mozilla::plugins::IPCPrintDlg paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
}
|
||||
};
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
template <>
|
||||
struct ParamTraits<FunctionHookId> :
|
||||
public ContiguousEnumSerializer<FunctionHookId,
|
||||
static_cast<FunctionHookId>(0),
|
||||
FunctionHookId::ID_FunctionHookCount>
|
||||
{};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif /* dom_plugins_ipc_functionbrokeripcutils_h */
|
|
@ -1,152 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FunctionBrokerParent.h"
|
||||
#include "FunctionBroker.h"
|
||||
#include "FunctionBrokerThread.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
#if defined(XP_WIN)
|
||||
UlongPairToIdMap sPairToIdMap;
|
||||
IdToUlongPairMap sIdToPairMap;
|
||||
PtrToIdMap sPtrToIdMap;
|
||||
IdToPtrMap sIdToPtrMap;
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
/* static */ FunctionBrokerParent*
|
||||
FunctionBrokerParent::Create(Endpoint<PFunctionBrokerParent>&& aParentEnd)
|
||||
{
|
||||
FunctionBrokerThread* thread = FunctionBrokerThread::Create();
|
||||
if (!thread) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We get the FunctionHooks so that they are created here, not on the
|
||||
// message thread.
|
||||
FunctionHook::GetHooks();
|
||||
|
||||
return new FunctionBrokerParent(thread, Move(aParentEnd));
|
||||
}
|
||||
|
||||
FunctionBrokerParent::FunctionBrokerParent(FunctionBrokerThread* aThread,
|
||||
Endpoint<PFunctionBrokerParent>&& aParentEnd) :
|
||||
mThread(aThread)
|
||||
, mMonitor("FunctionBrokerParent Lock")
|
||||
, mShutdownDone(false)
|
||||
{
|
||||
MOZ_ASSERT(mThread);
|
||||
mThread->Dispatch(NewNonOwningRunnableMethod<Endpoint<PFunctionBrokerParent>&&>(
|
||||
"FunctionBrokerParent::Bind", this, &FunctionBrokerParent::Bind, Move(aParentEnd)));
|
||||
}
|
||||
|
||||
FunctionBrokerParent::~FunctionBrokerParent()
|
||||
{
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
// Clean up any file permissions that we granted to the child process.
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
RemovePermissionsForProcess(OtherPid());
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBrokerParent::Bind(Endpoint<PFunctionBrokerParent>&& aEnd)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mThread->IsOnThread());
|
||||
DebugOnly<bool> ok = aEnd.Bind(this);
|
||||
MOZ_ASSERT(ok);
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBrokerParent::ShutdownOnBrokerThread()
|
||||
{
|
||||
MOZ_ASSERT(mThread->IsOnThread());
|
||||
Close();
|
||||
|
||||
// Notify waiting thread that we are done.
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mShutdownDone = true;
|
||||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBrokerParent::Destroy(FunctionBrokerParent* aInst)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aInst);
|
||||
|
||||
{
|
||||
// Hold the lock while we destroy the actor on the broker thread.
|
||||
MonitorAutoLock lock(aInst->mMonitor);
|
||||
aInst->mThread->Dispatch(NewNonOwningRunnableMethod(
|
||||
"FunctionBrokerParent::ShutdownOnBrokerThread", aInst,
|
||||
&FunctionBrokerParent::ShutdownOnBrokerThread));
|
||||
|
||||
// Wait for broker thread to complete destruction.
|
||||
while (!aInst->mShutdownDone) {
|
||||
aInst->mMonitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
delete aInst;
|
||||
}
|
||||
|
||||
void
|
||||
FunctionBrokerParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(mThread->IsOnThread());
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
FunctionBrokerParent::RecvBrokerFunction(const FunctionHookId &aFunctionId,
|
||||
const IpdlTuple &aInTuple,
|
||||
IpdlTuple *aOutTuple)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
MOZ_ASSERT(mThread->IsOnThread());
|
||||
if (RunBrokeredFunction(OtherPid(), aFunctionId, aInTuple, aOutTuple)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
#else
|
||||
MOZ_ASSERT_UNREACHABLE("BrokerFunction is currently only implemented on Windows.");
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
FunctionBrokerParent::RunBrokeredFunction(base::ProcessId aClientId,
|
||||
const FunctionHookId &aFunctionId,
|
||||
const IPC::IpdlTuple &aInTuple,
|
||||
IPC::IpdlTuple *aOutTuple)
|
||||
{
|
||||
if ((size_t)aFunctionId >= FunctionHook::GetHooks()->Length()) {
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid function ID");
|
||||
return false;
|
||||
}
|
||||
|
||||
FunctionHook* hook = FunctionHook::GetHooks()->ElementAt(aFunctionId);
|
||||
MOZ_ASSERT(hook->FunctionId() == aFunctionId);
|
||||
return hook->RunOriginalFunction(aClientId, aInTuple, aOutTuple);
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
||||
mozilla::SandboxPermissions FunctionBrokerParent::sSandboxPermissions;
|
||||
|
||||
// static
|
||||
void
|
||||
FunctionBrokerParent::RemovePermissionsForProcess(base::ProcessId aClientId)
|
||||
{
|
||||
sSandboxPermissions.RemovePermissionsForProcess(aClientId);
|
||||
}
|
||||
|
||||
#endif // defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,66 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_plugins_functionbrokerparent_h
|
||||
#define mozilla_plugins_functionbrokerparent_h
|
||||
|
||||
#include "mozilla/plugins/PFunctionBrokerParent.h"
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
#include "sandboxPermissions.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class FunctionBrokerThread;
|
||||
|
||||
/**
|
||||
* Top-level actor run on the process to which we broker calls from sandboxed
|
||||
* plugin processes.
|
||||
*/
|
||||
class FunctionBrokerParent : public PFunctionBrokerParent
|
||||
{
|
||||
public:
|
||||
static FunctionBrokerParent* Create(Endpoint<PFunctionBrokerParent>&& aParentEnd);
|
||||
static void Destroy(FunctionBrokerParent* aInst);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvBrokerFunction(const FunctionHookId &aFunctionId, const IpdlTuple &aInTuple,
|
||||
IpdlTuple *aOutTuple) override;
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
static mozilla::SandboxPermissions*
|
||||
GetSandboxPermissions() { return &sSandboxPermissions; }
|
||||
#endif // defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
||||
private:
|
||||
explicit FunctionBrokerParent(FunctionBrokerThread* aThread,
|
||||
Endpoint<PFunctionBrokerParent>&& aParentEnd);
|
||||
~FunctionBrokerParent();
|
||||
void ShutdownOnBrokerThread();
|
||||
void Bind(Endpoint<PFunctionBrokerParent>&& aEnd);
|
||||
|
||||
static bool RunBrokeredFunction(base::ProcessId aClientId,
|
||||
const FunctionHookId &aFunctionId,
|
||||
const IPC::IpdlTuple &aInTuple,
|
||||
IPC::IpdlTuple *aOutTuple);
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
static void RemovePermissionsForProcess(base::ProcessId aClientId);
|
||||
static mozilla::SandboxPermissions sSandboxPermissions;
|
||||
#endif // defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
||||
nsAutoPtr<FunctionBrokerThread> mThread;
|
||||
Monitor mMonitor;
|
||||
bool mShutdownDone;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_functionbrokerparent_hk
|
|
@ -1,57 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_plugins_functionbrokerthread_h
|
||||
#define mozilla_plugins_functionbrokerthread_h
|
||||
|
||||
#include "nsThreadManager.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class FunctionBrokerThread
|
||||
{
|
||||
public:
|
||||
void Dispatch(already_AddRefed<nsIRunnable>&& aRunnable)
|
||||
{
|
||||
mThread->Dispatch(Move(aRunnable), nsIEventTarget::NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
bool IsOnThread()
|
||||
{
|
||||
bool on;
|
||||
return NS_SUCCEEDED(mThread->IsOnCurrentThread(&on)) && on;
|
||||
}
|
||||
|
||||
static FunctionBrokerThread* Create()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
if (NS_FAILED(NS_NewNamedThread("Function Broker", getter_AddRefs(thread)))) {
|
||||
return nullptr;
|
||||
}
|
||||
return new FunctionBrokerThread(thread);
|
||||
}
|
||||
|
||||
~FunctionBrokerThread()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
mThread->Shutdown();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit FunctionBrokerThread(nsIThread* aThread) : mThread(aThread)
|
||||
{
|
||||
MOZ_ASSERT(mThread);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_functionbrokerthread_h
|
|
@ -1,332 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FunctionHook.h"
|
||||
#include "FunctionBroker.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include <shlobj.h>
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
StaticAutoPtr<FunctionHookArray> FunctionHook::sFunctionHooks;
|
||||
|
||||
bool AlwaysHook(int) { return true; }
|
||||
|
||||
FunctionHookArray*
|
||||
FunctionHook::GetHooks()
|
||||
{
|
||||
if (sFunctionHooks) {
|
||||
return sFunctionHooks;
|
||||
}
|
||||
|
||||
// sFunctionHooks is the StaticAutoPtr to the singleton array of FunctionHook
|
||||
// objects. We free it by clearing the StaticAutoPtr on shutdown.
|
||||
sFunctionHooks = new FunctionHookArray();
|
||||
ClearOnShutdown(&sFunctionHooks);
|
||||
sFunctionHooks->SetLength(ID_FunctionHookCount);
|
||||
|
||||
AddFunctionHooks(*sFunctionHooks);
|
||||
AddBrokeredFunctionHooks(*sFunctionHooks);
|
||||
return sFunctionHooks;
|
||||
}
|
||||
|
||||
void
|
||||
FunctionHook::HookFunctions(int aQuirks)
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Plugin);
|
||||
FunctionHookArray* hooks = FunctionHook::GetHooks();
|
||||
MOZ_ASSERT(hooks);
|
||||
for(size_t i=0; i < hooks->Length(); ++i) {
|
||||
FunctionHook* mhb = hooks->ElementAt(i);
|
||||
// Check that the FunctionHook array is in the same order as the
|
||||
// FunctionHookId enum.
|
||||
MOZ_ASSERT((size_t)mhb->FunctionId() == i);
|
||||
mhb->Register(aQuirks);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
// This cache is created when a DLL is registered with a FunctionHook.
|
||||
// It is cleared on a call to ClearDllInterceptorCache(). It
|
||||
// must be freed before exit to avoid leaks.
|
||||
typedef nsClassHashtable<nsCStringHashKey, WindowsDllInterceptor> DllInterceptors;
|
||||
DllInterceptors* sDllInterceptorCache = nullptr;
|
||||
|
||||
WindowsDllInterceptor*
|
||||
FunctionHook::GetDllInterceptorFor(const char* aModuleName)
|
||||
{
|
||||
if (!sDllInterceptorCache) {
|
||||
sDllInterceptorCache = new DllInterceptors();
|
||||
}
|
||||
|
||||
WindowsDllInterceptor* ret =
|
||||
sDllInterceptorCache->LookupOrAdd(nsCString(aModuleName), aModuleName);
|
||||
MOZ_ASSERT(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
FunctionHook::ClearDllInterceptorCache()
|
||||
{
|
||||
delete sDllInterceptorCache;
|
||||
sDllInterceptorCache = nullptr;
|
||||
}
|
||||
|
||||
/* GetWindowInfo */
|
||||
|
||||
typedef BasicFunctionHook<ID_GetWindowInfo, decltype(GetWindowInfo)> GetWindowInfoFH;
|
||||
|
||||
template<>
|
||||
ShouldHookFunc* const
|
||||
GetWindowInfoFH::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_GETWINDOWINFO>;
|
||||
|
||||
static const wchar_t * kMozillaWindowClass = L"MozillaWindowClass";
|
||||
static HWND sBrowserHwnd = nullptr;
|
||||
|
||||
|
||||
BOOL WINAPI
|
||||
GetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
|
||||
{
|
||||
if (!pwi) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(ID_GetWindowInfo < FunctionHook::GetHooks()->Length());
|
||||
GetWindowInfoFH* functionHook =
|
||||
static_cast<GetWindowInfoFH*>(FunctionHook::GetHooks()->ElementAt(ID_GetWindowInfo));
|
||||
if (!functionHook->OriginalFunction()) {
|
||||
NS_ASSERTION(FALSE, "Something is horribly wrong in PHGetWindowInfoHook!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!sBrowserHwnd) {
|
||||
wchar_t szClass[20];
|
||||
// GetClassNameW returns the length it copied w/o null terminator.
|
||||
// Therefore, if the name and null-terminator fit then it returns a
|
||||
// value less than the buffer's length.
|
||||
int nameLen = GetClassNameW(hWnd, szClass, ArrayLength(szClass));
|
||||
if ((nameLen < (int)ArrayLength(szClass)) &&
|
||||
!wcscmp(szClass, kMozillaWindowClass)) {
|
||||
sBrowserHwnd = hWnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Oddity: flash does strange rect comparisons for mouse input destined for
|
||||
// it's internal settings window. Post removing sub widgets for tabs, touch
|
||||
// this up so they get the rect they expect.
|
||||
// XXX potentially tie this to a specific major version?
|
||||
typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
|
||||
GetWindowInfoPtr gwiFunc =
|
||||
static_cast<GetWindowInfoPtr>(functionHook->OriginalFunction());
|
||||
BOOL result = gwiFunc(hWnd, pwi);
|
||||
if (sBrowserHwnd && sBrowserHwnd == hWnd) {
|
||||
pwi->rcWindow = pwi->rcClient;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* PrintDlgW */
|
||||
|
||||
typedef BasicFunctionHook<ID_PrintDlgW, decltype(PrintDlgW)> PrintDlgWFH;
|
||||
|
||||
template<>
|
||||
ShouldHookFunc* const
|
||||
PrintDlgWFH::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_PRINTDLGW>;
|
||||
|
||||
BOOL WINAPI PrintDlgWHook(LPPRINTDLGW aDlg)
|
||||
{
|
||||
// Zero out the HWND supplied by the plugin. We are sacrificing window
|
||||
// parentage for the ability to run in the NPAPI sandbox.
|
||||
HWND hwnd = aDlg->hwndOwner;
|
||||
aDlg->hwndOwner = 0;
|
||||
MOZ_ASSERT(ID_PrintDlgW < FunctionHook::GetHooks()->Length());
|
||||
PrintDlgWFH* functionHook =
|
||||
static_cast<PrintDlgWFH*>(FunctionHook::GetHooks()->ElementAt(ID_PrintDlgW));
|
||||
MOZ_ASSERT(functionHook);
|
||||
BOOL ret = functionHook->OriginalFunction()(aDlg);
|
||||
aDlg->hwndOwner = hwnd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Hooking CreateFileW for protected-mode magic
|
||||
static WindowsDllInterceptor sKernel32Intercept;
|
||||
typedef HANDLE (WINAPI *CreateFileWPtr)(LPCWSTR aFname, DWORD aAccess,
|
||||
DWORD aShare,
|
||||
LPSECURITY_ATTRIBUTES aSecurity,
|
||||
DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate);
|
||||
static CreateFileWPtr sCreateFileWStub = nullptr;
|
||||
typedef HANDLE (WINAPI *CreateFileAPtr)(LPCSTR aFname, DWORD aAccess,
|
||||
DWORD aShare,
|
||||
LPSECURITY_ATTRIBUTES aSecurity,
|
||||
DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate);
|
||||
static CreateFileAPtr sCreateFileAStub = nullptr;
|
||||
|
||||
// Windows 8 RTM (kernelbase's version is 6.2.9200.16384) doesn't call
|
||||
// CreateFileW from CreateFileA.
|
||||
// So we hook CreateFileA too to use CreateFileW hook.
|
||||
static HANDLE WINAPI
|
||||
CreateFileAHookFn(LPCSTR aFname, DWORD aAccess, DWORD aShare,
|
||||
LPSECURITY_ATTRIBUTES aSecurity, DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate)
|
||||
{
|
||||
while (true) { // goto out
|
||||
// Our hook is for mms.cfg into \Windows\System32\Macromed\Flash
|
||||
// We don't require supporting too long path.
|
||||
WCHAR unicodeName[MAX_PATH];
|
||||
size_t len = strlen(aFname);
|
||||
|
||||
if (len >= MAX_PATH) {
|
||||
break;
|
||||
}
|
||||
|
||||
// We call to CreateFileW for workaround of Windows 8 RTM
|
||||
int newLen = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, aFname,
|
||||
len, unicodeName, MAX_PATH);
|
||||
if (newLen == 0 || newLen >= MAX_PATH) {
|
||||
break;
|
||||
}
|
||||
unicodeName[newLen] = '\0';
|
||||
|
||||
return CreateFileW(unicodeName, aAccess, aShare, aSecurity, aCreation, aFlags, aFTemplate);
|
||||
}
|
||||
|
||||
return sCreateFileAStub(aFname, aAccess, aShare, aSecurity, aCreation, aFlags,
|
||||
aFTemplate);
|
||||
}
|
||||
|
||||
static bool
|
||||
GetLocalLowTempPath(size_t aLen, LPWSTR aPath)
|
||||
{
|
||||
NS_NAMED_LITERAL_STRING(tempname, "\\Temp");
|
||||
LPWSTR path;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0,
|
||||
nullptr, &path))) {
|
||||
if (wcslen(path) + tempname.Length() < aLen) {
|
||||
wcscpy(aPath, path);
|
||||
wcscat(aPath, tempname.get());
|
||||
CoTaskMemFree(path);
|
||||
return true;
|
||||
}
|
||||
CoTaskMemFree(path);
|
||||
}
|
||||
|
||||
// XP doesn't support SHGetKnownFolderPath and LocalLow
|
||||
if (!GetTempPathW(aLen, aPath)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HANDLE WINAPI
|
||||
CreateFileWHookFn(LPCWSTR aFname, DWORD aAccess, DWORD aShare,
|
||||
LPSECURITY_ATTRIBUTES aSecurity, DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate)
|
||||
{
|
||||
static const WCHAR kConfigFile[] = L"mms.cfg";
|
||||
static const size_t kConfigLength = ArrayLength(kConfigFile) - 1;
|
||||
|
||||
while (true) { // goto out, in sheep's clothing
|
||||
size_t len = wcslen(aFname);
|
||||
if (len < kConfigLength) {
|
||||
break;
|
||||
}
|
||||
if (wcscmp(aFname + len - kConfigLength, kConfigFile) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// This is the config file we want to rewrite
|
||||
WCHAR tempPath[MAX_PATH+1];
|
||||
if (GetLocalLowTempPath(MAX_PATH, tempPath) == 0) {
|
||||
break;
|
||||
}
|
||||
WCHAR tempFile[MAX_PATH+1];
|
||||
if (GetTempFileNameW(tempPath, L"fx", 0, tempFile) == 0) {
|
||||
break;
|
||||
}
|
||||
HANDLE replacement =
|
||||
sCreateFileWStub(tempFile, GENERIC_READ | GENERIC_WRITE, aShare,
|
||||
aSecurity, TRUNCATE_EXISTING,
|
||||
FILE_ATTRIBUTE_TEMPORARY |
|
||||
FILE_FLAG_DELETE_ON_CLOSE,
|
||||
NULL);
|
||||
if (replacement == INVALID_HANDLE_VALUE) {
|
||||
break;
|
||||
}
|
||||
|
||||
HANDLE original = sCreateFileWStub(aFname, aAccess, aShare, aSecurity,
|
||||
aCreation, aFlags, aFTemplate);
|
||||
if (original != INVALID_HANDLE_VALUE) {
|
||||
// copy original to replacement
|
||||
static const size_t kBufferSize = 1024;
|
||||
char buffer[kBufferSize];
|
||||
DWORD bytes;
|
||||
while (ReadFile(original, buffer, kBufferSize, &bytes, NULL)) {
|
||||
if (bytes == 0) {
|
||||
break;
|
||||
}
|
||||
DWORD wbytes;
|
||||
WriteFile(replacement, buffer, bytes, &wbytes, NULL);
|
||||
if (bytes < kBufferSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseHandle(original);
|
||||
}
|
||||
static const char kSettingString[] = "\nProtectedMode=0\n";
|
||||
DWORD wbytes;
|
||||
WriteFile(replacement, static_cast<const void*>(kSettingString),
|
||||
sizeof(kSettingString) - 1, &wbytes, NULL);
|
||||
SetFilePointer(replacement, 0, NULL, FILE_BEGIN);
|
||||
return replacement;
|
||||
}
|
||||
return sCreateFileWStub(aFname, aAccess, aShare, aSecurity, aCreation, aFlags,
|
||||
aFTemplate);
|
||||
}
|
||||
|
||||
void FunctionHook::HookProtectedMode()
|
||||
{
|
||||
// Legacy code. Uses the nsWindowsDLLInterceptor directly instead of
|
||||
// using the FunctionHook
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Plugin);
|
||||
WindowsDllInterceptor k32Intercept("kernel32.dll");
|
||||
k32Intercept.AddHook("CreateFileW",
|
||||
reinterpret_cast<intptr_t>(CreateFileWHookFn),
|
||||
(void**) &sCreateFileWStub);
|
||||
k32Intercept.AddHook("CreateFileA",
|
||||
reinterpret_cast<intptr_t>(CreateFileAHookFn),
|
||||
(void**) &sCreateFileAStub);
|
||||
}
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#define FUN_HOOK(x) static_cast<FunctionHook*>(x)
|
||||
|
||||
void
|
||||
FunctionHook::AddFunctionHooks(FunctionHookArray& aHooks)
|
||||
{
|
||||
// We transfer ownership of the FunctionHook objects to the array.
|
||||
#if defined(XP_WIN)
|
||||
aHooks[ID_GetWindowInfo] =
|
||||
FUN_HOOK(new GetWindowInfoFH("user32.dll", "GetWindowInfo",
|
||||
&GetWindowInfo, &GetWindowInfoHook));
|
||||
aHooks[ID_PrintDlgW] =
|
||||
FUN_HOOK(new PrintDlgWFH("comdlg32.dll", "PrintDlgW", &PrintDlgW,
|
||||
PrintDlgWHook));
|
||||
#endif // defined(XP_WIN)
|
||||
}
|
||||
|
||||
#undef FUN_HOOK
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,183 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef dom_plugins_ipc_functionhook_h
|
||||
#define dom_plugins_ipc_functionhook_h 1
|
||||
|
||||
#include "IpdlTuple.h"
|
||||
#include "base/process.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "nsWindowsDllInterceptor.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
// "PluginHooks" logging helpers
|
||||
extern mozilla::LazyLogModule sPluginHooksLog;
|
||||
#define HOOK_LOG(lvl, msg) MOZ_LOG(mozilla::plugins::sPluginHooksLog, lvl, msg);
|
||||
inline const char *SuccessMsg(bool aVal) { return aVal ? "succeeded" : "failed"; }
|
||||
|
||||
class FunctionHook;
|
||||
class FunctionHookArray;
|
||||
|
||||
class FunctionHook
|
||||
{
|
||||
public:
|
||||
virtual ~FunctionHook() {}
|
||||
|
||||
virtual FunctionHookId FunctionId() const = 0;
|
||||
|
||||
/**
|
||||
* Register to hook the function represented by this class.
|
||||
* Returns false if we should have hooked but didn't.
|
||||
*/
|
||||
virtual bool Register(int aQuirks) = 0;
|
||||
|
||||
/**
|
||||
* Run the original function with parameters stored in a tuple.
|
||||
* This is only supported on server-side and for auto-brokered methods.
|
||||
*/
|
||||
virtual bool RunOriginalFunction(base::ProcessId aClientId,
|
||||
const IPC::IpdlTuple &aInTuple,
|
||||
IPC::IpdlTuple *aOutTuple) const = 0;
|
||||
|
||||
/**
|
||||
* Hook the Win32 methods needed by the plugin process.
|
||||
*/
|
||||
static void HookFunctions(int aQuirks);
|
||||
|
||||
static FunctionHookArray* GetHooks();
|
||||
|
||||
#if defined(XP_WIN)
|
||||
/**
|
||||
* Special handler for hooking some kernel32.dll methods that we use to
|
||||
* disable Flash protected mode.
|
||||
*/
|
||||
static void HookProtectedMode();
|
||||
|
||||
/**
|
||||
* Get the WindowsDllInterceptor for the given module. Creates a cache of
|
||||
* WindowsDllInterceptors by name.
|
||||
*/
|
||||
static WindowsDllInterceptor* GetDllInterceptorFor(const char* aModuleName);
|
||||
|
||||
/**
|
||||
* Must be called to clear the cache created by calls to GetDllInterceptorFor.
|
||||
*/
|
||||
static void ClearDllInterceptorCache();
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
private:
|
||||
static StaticAutoPtr<FunctionHookArray> sFunctionHooks;
|
||||
static void AddFunctionHooks(FunctionHookArray& aHooks);
|
||||
};
|
||||
|
||||
// The FunctionHookArray deletes its FunctionHook objects when freed.
|
||||
class FunctionHookArray : public nsTArray<FunctionHook*> {
|
||||
public:
|
||||
~FunctionHookArray()
|
||||
{
|
||||
for (uint32_t idx = 0; idx < Length(); ++idx) {
|
||||
FunctionHook* elt = ElementAt(idx);
|
||||
MOZ_ASSERT(elt);
|
||||
delete elt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Type of function that returns true if a function should be hooked according to quirks.
|
||||
typedef bool(ShouldHookFunc)(int aQuirks);
|
||||
|
||||
template<FunctionHookId functionId, typename FunctionType>
|
||||
class BasicFunctionHook : public FunctionHook
|
||||
{
|
||||
public:
|
||||
BasicFunctionHook(const char* aModuleName,
|
||||
const char* aFunctionName, FunctionType* aOldFunction,
|
||||
FunctionType* aNewFunction) :
|
||||
mOldFunction(aOldFunction), mIsHooked(false), mModuleName(aModuleName),
|
||||
mFunctionName(aFunctionName), mNewFunction(aNewFunction)
|
||||
{
|
||||
MOZ_ASSERT(mOldFunction);
|
||||
MOZ_ASSERT(mNewFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks the function if we haven't already and if ShouldHook() says to.
|
||||
*/
|
||||
bool Register(int aQuirks) override;
|
||||
|
||||
/**
|
||||
* Can be specialized to perform "extra" operations when running the
|
||||
* function on the server side.
|
||||
*/
|
||||
bool RunOriginalFunction(base::ProcessId aClientId,
|
||||
const IPC::IpdlTuple &aInTuple,
|
||||
IPC::IpdlTuple *aOutTuple) const override { return false; }
|
||||
|
||||
FunctionHookId FunctionId() const override { return functionId; }
|
||||
|
||||
FunctionType* OriginalFunction() const { return mOldFunction; }
|
||||
|
||||
protected:
|
||||
// Once the function is hooked, this field will take the value of a pointer to
|
||||
// a function that performs the old behavior. Before that, it is a pointer to
|
||||
// the original function.
|
||||
FunctionType* mOldFunction;
|
||||
// True if we have already hooked the function.
|
||||
bool mIsHooked;
|
||||
|
||||
// The name of the module containing the function to hook. E.g. "user32.dll".
|
||||
const nsCString mModuleName;
|
||||
// The name of the function in the module.
|
||||
const nsCString mFunctionName;
|
||||
// The function that we should replace functionName with. The signature of
|
||||
// newFunction must match that of functionName.
|
||||
FunctionType* const mNewFunction;
|
||||
static ShouldHookFunc* const mShouldHook;
|
||||
};
|
||||
|
||||
// Default behavior is to hook every registered function.
|
||||
extern bool AlwaysHook(int);
|
||||
template<FunctionHookId functionId, typename FunctionType>
|
||||
ShouldHookFunc* const BasicFunctionHook<functionId, FunctionType>::mShouldHook = AlwaysHook;
|
||||
|
||||
template <FunctionHookId functionId, typename FunctionType>
|
||||
bool
|
||||
BasicFunctionHook<functionId, FunctionType>::Register(int aQuirks)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(XRE_IsPluginProcess());
|
||||
|
||||
// If we have already hooked or if quirks tell us not to then don't hook.
|
||||
if (mIsHooked || !mShouldHook(aQuirks)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
WindowsDllInterceptor* dllInterceptor =
|
||||
FunctionHook::GetDllInterceptorFor(mModuleName.Data());
|
||||
if (!dllInterceptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mIsHooked =
|
||||
dllInterceptor->AddHook(mFunctionName.Data(), reinterpret_cast<intptr_t>(mNewFunction),
|
||||
reinterpret_cast<void**>(&mOldFunction));
|
||||
#endif
|
||||
|
||||
HOOK_LOG(LogLevel::Debug,
|
||||
("Registering to intercept function '%s' : '%s'", mFunctionName.Data(),
|
||||
SuccessMsg(mIsHooked)));
|
||||
|
||||
return mIsHooked;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // dom_plugins_ipc_functionhook_h
|
|
@ -1,184 +0,0 @@
|
|||
#ifndef dom_plugins_ipc_ipdltuple_h
|
||||
#define dom_plugins_ipc_ipdltuple_h
|
||||
|
||||
#include "mozilla/plugins/FunctionBrokerIPCUtils.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* IpdlTuple is used by automatic function brokering to pass parameter
|
||||
* lists for brokered functions. It supports a limited set of types
|
||||
* (see IpdlTuple::IpdlTupleElement).
|
||||
*/
|
||||
class IpdlTuple
|
||||
{
|
||||
public:
|
||||
uint32_t NumElements() const { return mTupleElements.Length(); }
|
||||
|
||||
template<typename EltType>
|
||||
EltType* Element(uint32_t index)
|
||||
{
|
||||
if ((index >= mTupleElements.Length()) ||
|
||||
!mTupleElements[index].GetVariant().is<EltType>()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &mTupleElements[index].GetVariant().as<EltType>();
|
||||
}
|
||||
|
||||
template<typename EltType>
|
||||
const EltType* Element(uint32_t index) const
|
||||
{
|
||||
return const_cast<IpdlTuple*>(this)->Element<EltType>(index);
|
||||
}
|
||||
|
||||
template <typename EltType>
|
||||
void AddElement(const EltType& aElt)
|
||||
{
|
||||
IpdlTupleElement* newEntry = mTupleElements.AppendElement();
|
||||
newEntry->Set(aElt);
|
||||
}
|
||||
|
||||
private:
|
||||
struct InvalidType {};
|
||||
|
||||
// Like Variant but with a default constructor.
|
||||
template <typename ... Types>
|
||||
struct MaybeVariant
|
||||
{
|
||||
public:
|
||||
MaybeVariant() : mValue(InvalidType()) {}
|
||||
MaybeVariant(MaybeVariant&& o) : mValue(Move(o.mValue)) {}
|
||||
|
||||
template <typename Param> void Set(const Param& aParam)
|
||||
{
|
||||
mValue = mozilla::AsVariant(aParam);
|
||||
}
|
||||
|
||||
typedef mozilla::Variant<InvalidType, Types...> MaybeVariantType;
|
||||
MaybeVariantType& GetVariant() { return mValue; }
|
||||
const MaybeVariantType& GetVariant() const { return mValue; }
|
||||
|
||||
private:
|
||||
MaybeVariantType mValue;
|
||||
};
|
||||
|
||||
#if defined(XP_WIN)
|
||||
typedef MaybeVariant<int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,
|
||||
int64_t,uint64_t,nsCString,bool,OpenFileNameIPC,
|
||||
OpenFileNameRetIPC,NativeWindowHandle,
|
||||
IPCSchannelCred,IPCInternetBuffers,StringArray,
|
||||
IPCPrintDlg> IpdlTupleElement;
|
||||
#else
|
||||
typedef MaybeVariant<int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,
|
||||
int64_t,uint64_t,nsCString,bool> IpdlTupleElement;
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
friend struct IPC::ParamTraits<IpdlTuple>;
|
||||
friend struct IPC::ParamTraits<IpdlTuple::IpdlTupleElement>;
|
||||
friend struct IPC::ParamTraits<IpdlTuple::InvalidType>;
|
||||
|
||||
nsTArray<IpdlTupleElement> mTupleElements;
|
||||
};
|
||||
|
||||
template <> template<>
|
||||
inline void IpdlTuple::IpdlTupleElement::Set<nsDependentCSubstring>(const nsDependentCSubstring& aParam)
|
||||
{
|
||||
mValue = MaybeVariantType(mozilla::VariantType<nsCString>(), aParam);
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
using namespace mozilla::plugins;
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IpdlTuple>
|
||||
{
|
||||
typedef IpdlTuple paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mTupleElements);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aParam)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aParam->mTupleElements);
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
LogParam(aParam.mTupleElements, aLog);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<IpdlTuple::IpdlTupleElement>
|
||||
{
|
||||
typedef IpdlTuple::IpdlTupleElement paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!aParam.GetVariant().is<IpdlTuple::InvalidType>());
|
||||
WriteParam(aMsg, aParam.GetVariant());
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aParam)
|
||||
{
|
||||
bool ret = ReadParam(aMsg, aIter, &aParam->GetVariant());
|
||||
MOZ_RELEASE_ASSERT(!aParam->GetVariant().is<IpdlTuple::InvalidType>());
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct LogMatcher
|
||||
{
|
||||
explicit LogMatcher(std::wstring* aLog) : mLog(aLog) {}
|
||||
|
||||
template <typename EntryType>
|
||||
void match(const EntryType& aParam)
|
||||
{
|
||||
LogParam(aParam, mLog);
|
||||
}
|
||||
|
||||
private:
|
||||
std::wstring* mLog;
|
||||
};
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aParam.GetVariant().match(LogMatcher(aLog));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<IpdlTuple::InvalidType>
|
||||
{
|
||||
typedef IpdlTuple::InvalidType paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Attempt to serialize an invalid tuple element");
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aParam)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Attempt to deserialize an invalid tuple element");
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(L"<Invalid Tuple Entry>");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif /* dom_plugins_ipc_ipdltuple_h */
|
|
@ -1,23 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
using mozilla::plugins::FunctionHookId from "mozilla/plugins/FunctionBrokerIPCUtils.h";
|
||||
using IPC::IpdlTuple from "mozilla/plugins/IpdlTuple.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* Top-level actor that brokers functions for the client process.
|
||||
*/
|
||||
sync protocol PFunctionBroker
|
||||
{
|
||||
parent:
|
||||
sync BrokerFunction(FunctionHookId aFunctionId, IpdlTuple aFunctionParams)
|
||||
returns (IpdlTuple aFunctionRet);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -7,7 +7,6 @@ include protocol PPluginInstance;
|
|||
include protocol PPluginScriptableObject;
|
||||
include protocol PContent;
|
||||
include protocol PProfiler;
|
||||
include protocol PFunctionBroker;
|
||||
|
||||
using NPError from "npapi.h";
|
||||
using NPNVariable from "npapi.h";
|
||||
|
@ -15,6 +14,9 @@ using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
|
|||
using class mac_plugin_interposing::NSCursorInfo from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using struct nsID from "nsID.h";
|
||||
using struct mozilla::plugins::NPAudioDeviceChangeDetailsIPC from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using mozilla::plugins::GetFileNameFunc from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using mozilla::plugins::OpenFileNameIPC from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using mozilla::plugins::OpenFileNameRetIPC from "mozilla/plugins/PluginMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
@ -96,8 +98,6 @@ child:
|
|||
|
||||
async InitPluginModuleChild(Endpoint<PPluginModuleChild> endpoint);
|
||||
|
||||
async InitPluginFunctionBroker(Endpoint<PFunctionBrokerChild> endpoint);
|
||||
|
||||
parent:
|
||||
/**
|
||||
* This message is only used on X11 platforms.
|
||||
|
@ -145,8 +145,17 @@ parent:
|
|||
|
||||
async ReturnSitesWithData(nsCString[] aSites, uint64_t aCallbackId);
|
||||
|
||||
intr GetKeyState(int32_t aVirtKey)
|
||||
returns (int16_t aState);
|
||||
|
||||
intr NPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(bool shouldRegister)
|
||||
returns (NPError result);
|
||||
|
||||
// Used to broker the GetOpenFileName/GetSaveFileName file pickers on Windows.
|
||||
intr GetFileName(GetFileNameFunc aFunc, OpenFileNameIPC aOfnIn)
|
||||
returns (OpenFileNameRetIPC aOfnOut, bool aResult);
|
||||
|
||||
intr SetCursorPos(int x, int y) returns (bool aResult);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
|
|
@ -152,5 +152,196 @@ void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v)
|
|||
VOID_TO_NPVARIANT(*v);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
void
|
||||
OpenFileNameIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
|
||||
{
|
||||
mHwndOwner = nullptr;
|
||||
|
||||
// Filter is double-NULL terminated. mFilter should include the double-NULL.
|
||||
mHasFilter = aLpofn->lpstrFilter != nullptr;
|
||||
if (mHasFilter) {
|
||||
uint32_t dNullIdx = 0;
|
||||
while (aLpofn->lpstrFilter[dNullIdx] != L'\0' ||
|
||||
aLpofn->lpstrFilter[dNullIdx+1] != L'\0') {
|
||||
dNullIdx++;
|
||||
}
|
||||
mFilter.assign(aLpofn->lpstrFilter, dNullIdx+2);
|
||||
}
|
||||
mHasCustomFilter = aLpofn->lpstrCustomFilter != nullptr;
|
||||
if (mHasCustomFilter) {
|
||||
mCustomFilterIn = std::wstring(aLpofn->lpstrCustomFilter);
|
||||
mNMaxCustFilterOut =
|
||||
aLpofn->nMaxCustFilter - (wcslen(aLpofn->lpstrCustomFilter) + 1);
|
||||
}
|
||||
else {
|
||||
mNMaxCustFilterOut = 0;
|
||||
}
|
||||
mFilterIndex = aLpofn->nFilterIndex;
|
||||
mFile = std::wstring(aLpofn->lpstrFile);
|
||||
mNMaxFile = aLpofn->nMaxFile;
|
||||
mNMaxFileTitle =
|
||||
aLpofn->lpstrFileTitle != nullptr ? aLpofn->nMaxFileTitle : 0;
|
||||
mHasInitialDir = aLpofn->lpstrInitialDir != nullptr;
|
||||
if (mHasInitialDir) {
|
||||
mInitialDir = std::wstring(aLpofn->lpstrInitialDir);
|
||||
}
|
||||
mHasTitle = aLpofn->lpstrTitle != nullptr;
|
||||
if (mHasTitle) {
|
||||
mTitle = std::wstring(aLpofn->lpstrTitle);
|
||||
}
|
||||
mHasDefExt = aLpofn->lpstrDefExt != nullptr;
|
||||
if (mHasDefExt) {
|
||||
mDefExt = std::wstring(aLpofn->lpstrDefExt);
|
||||
}
|
||||
|
||||
mFlags = aLpofn->Flags;
|
||||
// If the user sets OFN_ALLOWMULTISELECT then we require OFN_EXPLORER
|
||||
// as well. Without OFN_EXPLORER, the method has ancient legacy
|
||||
// behavior that we don't support.
|
||||
MOZ_ASSERT((mFlags & OFN_EXPLORER) || !(mFlags & OFN_ALLOWMULTISELECT));
|
||||
|
||||
// We ignore any visual customization and callbacks that the user set.
|
||||
mFlags &= ~(OFN_ENABLEHOOK | OFN_ENABLETEMPLATEHANDLE | OFN_ENABLETEMPLATE);
|
||||
|
||||
mFlagsEx = aLpofn->FlagsEx;
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileNameIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
|
||||
{
|
||||
aLpofn->lStructSize = sizeof(OPENFILENAMEW);
|
||||
aLpofn->hwndOwner = mHwndOwner;
|
||||
if (mHasFilter) {
|
||||
memcpy(const_cast<LPWSTR>(aLpofn->lpstrFilter),
|
||||
mFilter.data(), mFilter.size() * sizeof(wchar_t));
|
||||
}
|
||||
if (mHasCustomFilter) {
|
||||
aLpofn->nMaxCustFilter = mCustomFilterIn.size() + 1 + mNMaxCustFilterOut;
|
||||
wcscpy(aLpofn->lpstrCustomFilter, mCustomFilterIn.c_str());
|
||||
memset(aLpofn->lpstrCustomFilter + mCustomFilterIn.size() + 1, 0,
|
||||
mNMaxCustFilterOut * sizeof(wchar_t));
|
||||
}
|
||||
else {
|
||||
aLpofn->nMaxCustFilter = 0;
|
||||
}
|
||||
aLpofn->nFilterIndex = mFilterIndex;
|
||||
if (mNMaxFile > 0) {
|
||||
wcsncpy(aLpofn->lpstrFile, mFile.c_str(),
|
||||
std::min(static_cast<uint32_t>(mFile.size()+1), mNMaxFile));
|
||||
aLpofn->lpstrFile[mNMaxFile - 1] = L'\0';
|
||||
}
|
||||
aLpofn->nMaxFile = mNMaxFile;
|
||||
aLpofn->nMaxFileTitle = mNMaxFileTitle;
|
||||
if (mHasInitialDir) {
|
||||
wcscpy(const_cast<LPWSTR>(aLpofn->lpstrInitialDir), mInitialDir.c_str());
|
||||
}
|
||||
if (mHasTitle) {
|
||||
wcscpy(const_cast<LPWSTR>(aLpofn->lpstrTitle), mTitle.c_str());
|
||||
}
|
||||
aLpofn->Flags = mFlags; /* TODO: Consider adding OFN_NOCHANGEDIR */
|
||||
if (mHasDefExt) {
|
||||
wcscpy(const_cast<LPWSTR>(aLpofn->lpstrDefExt), mDefExt.c_str());
|
||||
}
|
||||
aLpofn->FlagsEx = mFlagsEx;
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileNameIPC::AllocateOfnStrings(LPOPENFILENAMEW aLpofn) const
|
||||
{
|
||||
if (mHasFilter) {
|
||||
// mFilter is double-NULL terminated and it includes the double-NULL in its length.
|
||||
aLpofn->lpstrFilter =
|
||||
static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mFilter.size())));
|
||||
}
|
||||
if (mHasCustomFilter) {
|
||||
aLpofn->lpstrCustomFilter =
|
||||
static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * (mCustomFilterIn.size() + 1 + mNMaxCustFilterOut)));
|
||||
}
|
||||
aLpofn->lpstrFile =
|
||||
static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFile));
|
||||
if (mNMaxFileTitle > 0) {
|
||||
aLpofn->lpstrFileTitle =
|
||||
static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFileTitle));
|
||||
}
|
||||
if (mHasInitialDir) {
|
||||
aLpofn->lpstrInitialDir =
|
||||
static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mInitialDir.size() + 1)));
|
||||
}
|
||||
if (mHasTitle) {
|
||||
aLpofn->lpstrTitle =
|
||||
static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mTitle.size() + 1)));
|
||||
}
|
||||
if (mHasDefExt) {
|
||||
aLpofn->lpstrDefExt =
|
||||
static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mDefExt.size() + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileNameIPC::FreeOfnStrings(LPOPENFILENAMEW aLpofn) const
|
||||
{
|
||||
if (aLpofn->lpstrFilter) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrFilter));
|
||||
}
|
||||
if (aLpofn->lpstrCustomFilter) {
|
||||
free(aLpofn->lpstrCustomFilter);
|
||||
}
|
||||
if (aLpofn->lpstrFile) {
|
||||
free(aLpofn->lpstrFile);
|
||||
}
|
||||
if (aLpofn->lpstrFileTitle) {
|
||||
free(aLpofn->lpstrFileTitle);
|
||||
}
|
||||
if (aLpofn->lpstrInitialDir) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrInitialDir));
|
||||
}
|
||||
if (aLpofn->lpstrTitle) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrTitle));
|
||||
}
|
||||
if (aLpofn->lpstrDefExt) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrDefExt));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileNameRetIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn)
|
||||
{
|
||||
if (aLpofn->lpstrCustomFilter != nullptr) {
|
||||
mCustomFilterOut =
|
||||
std::wstring(aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1);
|
||||
}
|
||||
mFile.assign(aLpofn->lpstrFile, aLpofn->nMaxFile);
|
||||
if (aLpofn->lpstrFileTitle != nullptr) {
|
||||
mFileTitle.assign(aLpofn->lpstrFileTitle, wcslen(aLpofn->lpstrFileTitle) + 1);
|
||||
}
|
||||
mFileOffset = aLpofn->nFileOffset;
|
||||
mFileExtension = aLpofn->nFileExtension;
|
||||
}
|
||||
|
||||
void
|
||||
OpenFileNameRetIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const
|
||||
{
|
||||
if (aLpofn->lpstrCustomFilter) {
|
||||
LPWSTR secondString =
|
||||
aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1;
|
||||
const wchar_t* customFilterOut = mCustomFilterOut.c_str();
|
||||
MOZ_ASSERT(wcslen(aLpofn->lpstrCustomFilter) + 1 +
|
||||
wcslen(customFilterOut) + 1 + 1 <= aLpofn->nMaxCustFilter);
|
||||
wcscpy(secondString, customFilterOut);
|
||||
secondString[wcslen(customFilterOut) + 1] = L'\0'; // terminated with two NULLs
|
||||
}
|
||||
MOZ_ASSERT(mFile.size() <= aLpofn->nMaxFile);
|
||||
memcpy(aLpofn->lpstrFile,
|
||||
mFile.data(), mFile.size() * sizeof(wchar_t));
|
||||
if (aLpofn->lpstrFileTitle != nullptr) {
|
||||
MOZ_ASSERT(mFileTitle.size() + 1 < aLpofn->nMaxFileTitle);
|
||||
wcscpy(aLpofn->lpstrFileTitle, mFileTitle.c_str());
|
||||
}
|
||||
aLpofn->nFileOffset = mFileOffset;
|
||||
aLpofn->nFileExtension = mFileExtension;
|
||||
}
|
||||
#endif // XP_WIN
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
namespace mac_plugin_interposing { class NSCursorInfo { }; }
|
||||
#endif
|
||||
using mac_plugin_interposing::NSCursorInfo;
|
||||
#ifdef XP_WIN
|
||||
#include "commdlg.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
@ -123,9 +126,59 @@ typedef intptr_t NativeWindowHandle; // never actually used, will always be 0
|
|||
#ifdef XP_WIN
|
||||
typedef base::SharedMemoryHandle WindowsSharedMemoryHandle;
|
||||
typedef HANDLE DXGISharedSurfaceHandle;
|
||||
|
||||
// Values indicate GetOpenFileNameW and GetSaveFileNameW.
|
||||
enum GetFileNameFunc { OPEN_FUNC, SAVE_FUNC };
|
||||
|
||||
// IPC-capable version of the Windows OPENFILENAMEW struct.
|
||||
typedef struct _OpenFileNameIPC
|
||||
{
|
||||
// Allocates memory for the strings in this object. This should usually
|
||||
// be used with a zeroed out OPENFILENAMEW structure.
|
||||
void AllocateOfnStrings(LPOPENFILENAMEW aLpofn) const;
|
||||
void FreeOfnStrings(LPOPENFILENAMEW aLpofn) const;
|
||||
void AddToOfn(LPOPENFILENAMEW aLpofn) const;
|
||||
void CopyFromOfn(LPOPENFILENAMEW aLpofn);
|
||||
|
||||
NativeWindowHandle mHwndOwner;
|
||||
std::wstring mFilter; // Double-NULL terminated (i.e. L"\0\0") if mHasFilter is true
|
||||
bool mHasFilter;
|
||||
std::wstring mCustomFilterIn;
|
||||
bool mHasCustomFilter;
|
||||
uint32_t mNMaxCustFilterOut;
|
||||
uint32_t mFilterIndex;
|
||||
std::wstring mFile;
|
||||
uint32_t mNMaxFile;
|
||||
uint32_t mNMaxFileTitle;
|
||||
std::wstring mInitialDir;
|
||||
bool mHasInitialDir;
|
||||
std::wstring mTitle;
|
||||
bool mHasTitle;
|
||||
uint32_t mFlags;
|
||||
std::wstring mDefExt;
|
||||
bool mHasDefExt;
|
||||
uint32_t mFlagsEx;
|
||||
} OpenFileNameIPC;
|
||||
|
||||
// GetOpenFileNameW and GetSaveFileNameW overwrite fields of their OPENFILENAMEW
|
||||
// parameter. This represents those values so that they can be returned via IPC.
|
||||
typedef struct _OpenFileNameRetIPC
|
||||
{
|
||||
void CopyFromOfn(LPOPENFILENAMEW aLpofn);
|
||||
void AddToOfn(LPOPENFILENAMEW aLpofn) const;
|
||||
|
||||
std::wstring mCustomFilterOut;
|
||||
std::wstring mFile; // Double-NULL terminated (i.e. L"\0\0")
|
||||
std::wstring mFileTitle;
|
||||
uint16_t mFileOffset;
|
||||
uint16_t mFileExtension;
|
||||
} OpenFileNameRetIPC;
|
||||
#else // XP_WIN
|
||||
typedef mozilla::null_t WindowsSharedMemoryHandle;
|
||||
typedef mozilla::null_t DXGISharedSurfaceHandle;
|
||||
typedef mozilla::null_t GetFileNameFunc;
|
||||
typedef mozilla::null_t OpenFileNameIPC;
|
||||
typedef mozilla::null_t OpenFileNameRetIPC;
|
||||
#endif
|
||||
|
||||
// XXX maybe not the best place for these. better one?
|
||||
|
@ -654,6 +707,109 @@ struct ParamTraits<mozilla::plugins::NPAudioDeviceChangeDetailsIPC>
|
|||
}
|
||||
};
|
||||
|
||||
#ifdef XP_WIN
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::_OpenFileNameIPC>
|
||||
{
|
||||
typedef mozilla::plugins::_OpenFileNameIPC paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mHwndOwner);
|
||||
WriteParam(aMsg, aParam.mFilter);
|
||||
WriteParam(aMsg, aParam.mHasFilter);
|
||||
WriteParam(aMsg, aParam.mCustomFilterIn);
|
||||
WriteParam(aMsg, aParam.mHasCustomFilter);
|
||||
WriteParam(aMsg, aParam.mNMaxCustFilterOut);
|
||||
WriteParam(aMsg, aParam.mFilterIndex);
|
||||
WriteParam(aMsg, aParam.mFile);
|
||||
WriteParam(aMsg, aParam.mNMaxFile);
|
||||
WriteParam(aMsg, aParam.mNMaxFileTitle);
|
||||
WriteParam(aMsg, aParam.mInitialDir);
|
||||
WriteParam(aMsg, aParam.mHasInitialDir);
|
||||
WriteParam(aMsg, aParam.mTitle);
|
||||
WriteParam(aMsg, aParam.mHasTitle);
|
||||
WriteParam(aMsg, aParam.mFlags);
|
||||
WriteParam(aMsg, aParam.mDefExt);
|
||||
WriteParam(aMsg, aParam.mHasDefExt);
|
||||
WriteParam(aMsg, aParam.mFlagsEx);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
if (ReadParam(aMsg, aIter, &aResult->mHwndOwner) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFilter) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasFilter) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mCustomFilterIn) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasCustomFilter) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNMaxCustFilterOut) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFilterIndex) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNMaxFile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNMaxFileTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mInitialDir) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasInitialDir) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFlags) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDefExt) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasDefExt) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFlagsEx)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(StringPrintf(L"[%S, %S, %S, %S]", aParam.mFilter.c_str(),
|
||||
aParam.mCustomFilterIn.c_str(), aParam.mFile.c_str(),
|
||||
aParam.mTitle.c_str()));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::_OpenFileNameRetIPC>
|
||||
{
|
||||
typedef mozilla::plugins::_OpenFileNameRetIPC paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mCustomFilterOut);
|
||||
WriteParam(aMsg, aParam.mFile);
|
||||
WriteParam(aMsg, aParam.mFileTitle);
|
||||
WriteParam(aMsg, aParam.mFileOffset);
|
||||
WriteParam(aMsg, aParam.mFileExtension);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
if (ReadParam(aMsg, aIter, &aResult->mCustomFilterOut) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFileTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFileOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFileExtension)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(StringPrintf(L"[%S, %S, %S, %d, %d]", aParam.mCustomFilterOut.c_str(),
|
||||
aParam.mFile.c_str(), aParam.mFileTitle.c_str(),
|
||||
aParam.mFileOffset, aParam.mFileExtension));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::GetFileNameFunc> :
|
||||
public ContiguousEnumSerializerInclusive<mozilla::plugins::GetFileNameFunc,
|
||||
mozilla::plugins::OPEN_FUNC,
|
||||
mozilla::plugins::SAVE_FUNC>
|
||||
{};
|
||||
#endif // XP_WIN
|
||||
|
||||
} /* namespace IPC */
|
||||
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@
|
|||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "nsNPAPIPlugin.h"
|
||||
#include "FunctionHook.h"
|
||||
#include "FunctionBrokerChild.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "nsWindowsDllInterceptor.h"
|
||||
#include "mozilla/widget/AudioSession.h"
|
||||
#include <knownfolders.h>
|
||||
#include <shlobj.h>
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
|
@ -61,6 +61,7 @@ using namespace mozilla::widget;
|
|||
|
||||
#if defined(XP_WIN)
|
||||
const wchar_t * kFlashFullscreenClass = L"ShockwaveFlashFullScreen";
|
||||
const wchar_t * kMozillaWindowClass = L"MozillaWindowClass";
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
@ -69,8 +70,49 @@ PluginModuleChild* gChromeInstance = nullptr;
|
|||
} // namespace
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Hooking CreateFileW for protected-mode magic
|
||||
static WindowsDllInterceptor sKernel32Intercept;
|
||||
typedef HANDLE (WINAPI *CreateFileWPtr)(LPCWSTR fname, DWORD access,
|
||||
DWORD share,
|
||||
LPSECURITY_ATTRIBUTES security,
|
||||
DWORD creation, DWORD flags,
|
||||
HANDLE ftemplate);
|
||||
static CreateFileWPtr sCreateFileWStub = nullptr;
|
||||
typedef HANDLE (WINAPI *CreateFileAPtr)(LPCSTR fname, DWORD access,
|
||||
DWORD share,
|
||||
LPSECURITY_ATTRIBUTES security,
|
||||
DWORD creation, DWORD flags,
|
||||
HANDLE ftemplate);
|
||||
static CreateFileAPtr sCreateFileAStub = nullptr;
|
||||
|
||||
// Used with fix for flash fullscreen window loosing focus.
|
||||
static bool gDelayFlashFocusReplyUntilEval = false;
|
||||
// Used to fix GetWindowInfo problems with internal flash settings dialogs
|
||||
static WindowsDllInterceptor sUser32Intercept;
|
||||
typedef BOOL (WINAPI *GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
|
||||
static GetWindowInfoPtr sGetWindowInfoPtrStub = nullptr;
|
||||
static HWND sBrowserHwnd = nullptr;
|
||||
// sandbox process doesn't get current key states. So we need get it on chrome.
|
||||
typedef SHORT (WINAPI *GetKeyStatePtr)(int);
|
||||
static GetKeyStatePtr sGetKeyStatePtrStub = nullptr;
|
||||
|
||||
static WindowsDllInterceptor sComDlg32Intercept;
|
||||
|
||||
// proxy GetSaveFileName/GetOpenFileName on chrome so that we can know which
|
||||
// files the user has given permission to access
|
||||
// We count on GetOpenFileNameA/GetSaveFileNameA calling
|
||||
// GetOpenFileNameW/GetSaveFileNameW so we don't proxy them explicitly.
|
||||
typedef BOOL (WINAPI *GetOpenFileNameWPtr)(LPOPENFILENAMEW lpofn);
|
||||
static GetOpenFileNameWPtr sGetOpenFileNameWPtrStub = nullptr;
|
||||
typedef BOOL (WINAPI *GetSaveFileNameWPtr)(LPOPENFILENAMEW lpofn);
|
||||
static GetSaveFileNameWPtr sGetSaveFileNameWPtrStub = nullptr;
|
||||
|
||||
typedef BOOL (WINAPI *SetCursorPosPtr)(int x, int y);
|
||||
static SetCursorPosPtr sSetCursorPosPtrStub = nullptr;
|
||||
|
||||
typedef BOOL (WINAPI *PrintDlgWPtr)(LPPRINTDLGW aDlg);
|
||||
static PrintDlgWPtr sPrintDlgWPtrStub = nullptr;
|
||||
|
||||
#endif
|
||||
|
||||
/* static */
|
||||
|
@ -184,7 +226,7 @@ PluginModuleChild::RecvDisableFlashProtectedMode()
|
|||
{
|
||||
MOZ_ASSERT(mIsChrome);
|
||||
#ifdef XP_WIN
|
||||
FunctionHook::HookProtectedMode();
|
||||
HookProtectedMode();
|
||||
#else
|
||||
MOZ_ASSERT(false, "Should not be called");
|
||||
#endif
|
||||
|
@ -702,21 +744,6 @@ PluginModuleChild::RecvInitPluginModuleChild(Endpoint<PPluginModuleChild>&& aEnd
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChild::RecvInitPluginFunctionBroker(Endpoint<PFunctionBrokerChild>&& aEndpoint)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
MOZ_ASSERT(mIsChrome);
|
||||
if (!FunctionBrokerChild::Initialize(Move(aEndpoint))) {
|
||||
return IPC_FAIL(this,
|
||||
"InitPluginFunctionBroker failed to initialize broker child.");
|
||||
}
|
||||
return IPC_OK();
|
||||
#else
|
||||
return IPC_FAIL(this, "InitPluginFunctionBroker not supported on this platform.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChild::AnswerInitCrashReporter(Shmem&& aShmem, mozilla::dom::NativeThreadId* aOutId)
|
||||
|
@ -760,11 +787,6 @@ PluginModuleChild::ActorDestroy(ActorDestroyReason why)
|
|||
NP_Shutdown();
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
FunctionBrokerChild::Destroy();
|
||||
FunctionHook::ClearDllInterceptorCache();
|
||||
#endif
|
||||
|
||||
// doesn't matter why we're being destroyed; it's up to us to
|
||||
// initiate (clean) shutdown
|
||||
CrashReporterClient::DestroySingleton();
|
||||
|
@ -1767,6 +1789,426 @@ PluginModuleChild::DoNP_Initialize(const PluginSettings& aSettings)
|
|||
return result;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
// Windows 8 RTM (kernelbase's version is 6.2.9200.16384) doesn't call
|
||||
// CreateFileW from CreateFileA.
|
||||
// So we hook CreateFileA too to use CreateFileW hook.
|
||||
|
||||
static HANDLE WINAPI
|
||||
CreateFileAHookFn(LPCSTR fname, DWORD access, DWORD share,
|
||||
LPSECURITY_ATTRIBUTES security, DWORD creation, DWORD flags,
|
||||
HANDLE ftemplate)
|
||||
{
|
||||
while (true) { // goto out
|
||||
// Our hook is for mms.cfg into \Windows\System32\Macromed\Flash
|
||||
// We don't requrie supporting too long path.
|
||||
WCHAR unicodeName[MAX_PATH];
|
||||
size_t len = strlen(fname);
|
||||
|
||||
if (len >= MAX_PATH) {
|
||||
break;
|
||||
}
|
||||
|
||||
// We call to CreateFileW for workaround of Windows 8 RTM
|
||||
int newLen = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, fname,
|
||||
len, unicodeName, MAX_PATH);
|
||||
if (newLen == 0 || newLen >= MAX_PATH) {
|
||||
break;
|
||||
}
|
||||
unicodeName[newLen] = '\0';
|
||||
|
||||
return CreateFileW(unicodeName, access, share, security, creation, flags, ftemplate);
|
||||
}
|
||||
|
||||
return sCreateFileAStub(fname, access, share, security, creation, flags,
|
||||
ftemplate);
|
||||
}
|
||||
|
||||
static bool
|
||||
GetLocalLowTempPath(size_t aLen, LPWSTR aPath)
|
||||
{
|
||||
NS_NAMED_LITERAL_STRING(tempname, "\\Temp");
|
||||
LPWSTR path;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0,
|
||||
nullptr, &path))) {
|
||||
if (wcslen(path) + tempname.Length() < aLen) {
|
||||
wcscpy(aPath, path);
|
||||
wcscat(aPath, tempname.get());
|
||||
::CoTaskMemFree(path);
|
||||
return true;
|
||||
}
|
||||
::CoTaskMemFree(path);
|
||||
}
|
||||
|
||||
// XP doesn't support SHGetKnownFolderPath and LocalLow
|
||||
if (!GetTempPathW(aLen, aPath)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HANDLE WINAPI
|
||||
CreateFileWHookFn(LPCWSTR fname, DWORD access, DWORD share,
|
||||
LPSECURITY_ATTRIBUTES security, DWORD creation, DWORD flags,
|
||||
HANDLE ftemplate)
|
||||
{
|
||||
static const WCHAR kConfigFile[] = L"mms.cfg";
|
||||
static const size_t kConfigLength = ArrayLength(kConfigFile) - 1;
|
||||
|
||||
while (true) { // goto out, in sheep's clothing
|
||||
size_t len = wcslen(fname);
|
||||
if (len < kConfigLength) {
|
||||
break;
|
||||
}
|
||||
if (wcscmp(fname + len - kConfigLength, kConfigFile) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// This is the config file we want to rewrite
|
||||
WCHAR tempPath[MAX_PATH+1];
|
||||
if (GetLocalLowTempPath(MAX_PATH, tempPath) == 0) {
|
||||
break;
|
||||
}
|
||||
WCHAR tempFile[MAX_PATH+1];
|
||||
if (GetTempFileNameW(tempPath, L"fx", 0, tempFile) == 0) {
|
||||
break;
|
||||
}
|
||||
HANDLE replacement =
|
||||
sCreateFileWStub(tempFile, GENERIC_READ | GENERIC_WRITE, share,
|
||||
security, TRUNCATE_EXISTING,
|
||||
FILE_ATTRIBUTE_TEMPORARY |
|
||||
FILE_FLAG_DELETE_ON_CLOSE,
|
||||
NULL);
|
||||
if (replacement == INVALID_HANDLE_VALUE) {
|
||||
break;
|
||||
}
|
||||
|
||||
HANDLE original = sCreateFileWStub(fname, access, share, security,
|
||||
creation, flags, ftemplate);
|
||||
if (original != INVALID_HANDLE_VALUE) {
|
||||
// copy original to replacement
|
||||
static const size_t kBufferSize = 1024;
|
||||
char buffer[kBufferSize];
|
||||
DWORD bytes;
|
||||
while (ReadFile(original, buffer, kBufferSize, &bytes, NULL)) {
|
||||
if (bytes == 0) {
|
||||
break;
|
||||
}
|
||||
DWORD wbytes;
|
||||
WriteFile(replacement, buffer, bytes, &wbytes, NULL);
|
||||
if (bytes < kBufferSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseHandle(original);
|
||||
}
|
||||
static const char kSettingString[] = "\nProtectedMode=0\n";
|
||||
DWORD wbytes;
|
||||
WriteFile(replacement, static_cast<const void*>(kSettingString),
|
||||
sizeof(kSettingString) - 1, &wbytes, NULL);
|
||||
SetFilePointer(replacement, 0, NULL, FILE_BEGIN);
|
||||
return replacement;
|
||||
}
|
||||
return sCreateFileWStub(fname, access, share, security, creation, flags,
|
||||
ftemplate);
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleChild::HookProtectedMode()
|
||||
{
|
||||
sKernel32Intercept.Init("kernel32.dll");
|
||||
sKernel32Intercept.AddHook("CreateFileW",
|
||||
reinterpret_cast<intptr_t>(CreateFileWHookFn),
|
||||
(void**) &sCreateFileWStub);
|
||||
sKernel32Intercept.AddHook("CreateFileA",
|
||||
reinterpret_cast<intptr_t>(CreateFileAHookFn),
|
||||
(void**) &sCreateFileAStub);
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
PMCGetWindowInfoHook(HWND hWnd, PWINDOWINFO pwi)
|
||||
{
|
||||
if (!pwi)
|
||||
return FALSE;
|
||||
|
||||
if (!sGetWindowInfoPtrStub) {
|
||||
NS_ASSERTION(FALSE, "Something is horribly wrong in PMCGetWindowInfoHook!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!sBrowserHwnd) {
|
||||
wchar_t szClass[20];
|
||||
if (GetClassNameW(hWnd, szClass, ArrayLength(szClass)) &&
|
||||
!wcscmp(szClass, kMozillaWindowClass)) {
|
||||
sBrowserHwnd = hWnd;
|
||||
}
|
||||
}
|
||||
// Oddity: flash does strange rect comparisons for mouse input destined for
|
||||
// it's internal settings window. Post removing sub widgets for tabs, touch
|
||||
// this up so they get the rect they expect.
|
||||
// XXX potentially tie this to a specific major version?
|
||||
BOOL result = sGetWindowInfoPtrStub(hWnd, pwi);
|
||||
if (sBrowserHwnd && sBrowserHwnd == hWnd)
|
||||
pwi->rcWindow = pwi->rcClient;
|
||||
return result;
|
||||
}
|
||||
|
||||
SHORT WINAPI PMCGetKeyState(int aVirtKey);
|
||||
|
||||
// Runnable that performs GetKeyState on the main thread so that it can be
|
||||
// synchronously run on the PluginModuleParent via IPC.
|
||||
// The task alerts the given semaphore when it is finished.
|
||||
class GetKeyStateTask : public Runnable
|
||||
{
|
||||
SHORT* mKeyState;
|
||||
int mVirtKey;
|
||||
HANDLE mSemaphore;
|
||||
|
||||
public:
|
||||
explicit GetKeyStateTask(int aVirtKey, HANDLE aSemaphore, SHORT* aKeyState) :
|
||||
Runnable("GetKeyStateTask"),
|
||||
mKeyState(aKeyState),
|
||||
mVirtKey(aVirtKey),
|
||||
mSemaphore(aSemaphore)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
AssertPluginThread();
|
||||
*mKeyState = PMCGetKeyState(mVirtKey);
|
||||
if (!ReleaseSemaphore(mSemaphore, 1, nullptr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
// static
|
||||
SHORT WINAPI
|
||||
PMCGetKeyState(int aVirtKey)
|
||||
{
|
||||
if (!IsPluginThread()) {
|
||||
// synchronously request the key state from the main thread
|
||||
|
||||
// Start a semaphore at 0. We Release the semaphore (bringing its count to 1)
|
||||
// when the synchronous call is done.
|
||||
HANDLE semaphore = CreateSemaphore(NULL, 0, 1, NULL);
|
||||
if (semaphore == nullptr) {
|
||||
MOZ_ASSERT(semaphore != nullptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SHORT keyState;
|
||||
RefPtr<GetKeyStateTask> task = new GetKeyStateTask(aVirtKey, semaphore, &keyState);
|
||||
ProcessChild::message_loop()->PostTask(task.forget());
|
||||
DWORD err = WaitForSingleObject(semaphore, INFINITE);
|
||||
if (err != WAIT_FAILED) {
|
||||
CloseHandle(semaphore);
|
||||
return keyState;
|
||||
}
|
||||
PLUGIN_LOG_DEBUG(("Error while waiting for GetKeyState semaphore: %d",
|
||||
GetLastError()));
|
||||
MOZ_ASSERT(err != WAIT_FAILED);
|
||||
CloseHandle(semaphore);
|
||||
return 0;
|
||||
}
|
||||
PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
|
||||
if (chromeInstance) {
|
||||
int16_t ret = 0;
|
||||
if (chromeInstance->CallGetKeyState(aVirtKey, &ret)) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return sGetKeyStatePtrStub(aVirtKey);
|
||||
}
|
||||
|
||||
class PluginThreadTaskData
|
||||
{
|
||||
public:
|
||||
virtual bool RunTask() = 0;
|
||||
};
|
||||
|
||||
// Runnable that performs a task on the main thread so that the call can be
|
||||
// synchronously run on the PluginModuleParent via IPC.
|
||||
// The task alerts the given semaphore when it is finished.
|
||||
class PluginThreadTask : public Runnable
|
||||
{
|
||||
bool mSuccess;
|
||||
PluginThreadTaskData* mTaskData;
|
||||
HANDLE mSemaphore;
|
||||
|
||||
public:
|
||||
explicit PluginThreadTask(PluginThreadTaskData* aTaskData,
|
||||
HANDLE aSemaphore) :
|
||||
Runnable("PluginThreadTask"),
|
||||
mSuccess(false),
|
||||
mTaskData(aTaskData),
|
||||
mSemaphore(aSemaphore)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
AssertPluginThread();
|
||||
mSuccess = mTaskData->RunTask();
|
||||
if (!ReleaseSemaphore(mSemaphore, 1, nullptr)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool Success() { return mSuccess; }
|
||||
};
|
||||
|
||||
// static
|
||||
BOOL
|
||||
PostToPluginThread(PluginThreadTaskData* aTaskData)
|
||||
{
|
||||
MOZ_ASSERT(!IsPluginThread());
|
||||
|
||||
// Synchronously run GetFileNameTask from the main thread.
|
||||
// Start a semaphore at 0. We release the semaphore (bringing its
|
||||
// count to 1) when the synchronous call is done.
|
||||
nsAutoHandle semaphore(CreateSemaphore(NULL, 0, 1, NULL));
|
||||
if (semaphore == nullptr) {
|
||||
MOZ_ASSERT(semaphore != nullptr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RefPtr<PluginThreadTask> task = new PluginThreadTask(aTaskData, semaphore);
|
||||
ProcessChild::message_loop()->PostTask(do_AddRef(task));
|
||||
DWORD err = WaitForSingleObject(semaphore, INFINITE);
|
||||
if (err != WAIT_FAILED) {
|
||||
return task->Success();
|
||||
}
|
||||
PLUGIN_LOG_DEBUG(("Error while waiting for semaphore: %d",
|
||||
GetLastError()));
|
||||
MOZ_ASSERT(err != WAIT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL WINAPI PMCGetSaveFileNameW(LPOPENFILENAMEW lpofn);
|
||||
BOOL WINAPI PMCGetOpenFileNameW(LPOPENFILENAMEW lpofn);
|
||||
|
||||
class GetFileNameTaskData : public PluginThreadTaskData
|
||||
{
|
||||
public:
|
||||
GetFileNameTaskData(GetFileNameFunc aFunc, void* aLpOpenFileName) :
|
||||
mFunc(aFunc), mLpOpenFileName(aLpOpenFileName)
|
||||
{}
|
||||
|
||||
bool RunTask()
|
||||
{
|
||||
switch (mFunc) {
|
||||
case OPEN_FUNC:
|
||||
return PMCGetOpenFileNameW(static_cast<LPOPENFILENAMEW>(mLpOpenFileName));
|
||||
case SAVE_FUNC:
|
||||
return PMCGetSaveFileNameW(static_cast<LPOPENFILENAMEW>(mLpOpenFileName));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
GetFileNameFunc mFunc;
|
||||
void* mLpOpenFileName;
|
||||
};
|
||||
|
||||
// static
|
||||
BOOL WINAPI
|
||||
PMCGetFileNameW(GetFileNameFunc aFunc, LPOPENFILENAMEW aLpofn)
|
||||
{
|
||||
if (!IsPluginThread()) {
|
||||
GetFileNameTaskData gfnData(aFunc, aLpofn);
|
||||
return PostToPluginThread(&gfnData);
|
||||
}
|
||||
|
||||
PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
|
||||
if (chromeInstance) {
|
||||
bool ret = FALSE;
|
||||
OpenFileNameIPC inputOfn;
|
||||
inputOfn.CopyFromOfn(aLpofn);
|
||||
OpenFileNameRetIPC outputOfn;
|
||||
if (chromeInstance->CallGetFileName(aFunc, inputOfn,
|
||||
&outputOfn, &ret)) {
|
||||
if (ret) {
|
||||
outputOfn.AddToOfn(aLpofn);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (aFunc) {
|
||||
case OPEN_FUNC:
|
||||
return sGetOpenFileNameWPtrStub(aLpofn);
|
||||
case SAVE_FUNC:
|
||||
return sGetSaveFileNameWPtrStub(aLpofn);
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("Illegal GetFileNameFunc value");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// static
|
||||
BOOL WINAPI
|
||||
PMCGetSaveFileNameW(LPOPENFILENAMEW aLpofn)
|
||||
{
|
||||
return PMCGetFileNameW(SAVE_FUNC, aLpofn);
|
||||
}
|
||||
// static
|
||||
BOOL WINAPI
|
||||
PMCGetOpenFileNameW(LPOPENFILENAMEW aLpofn)
|
||||
{
|
||||
return PMCGetFileNameW(OPEN_FUNC, aLpofn);
|
||||
}
|
||||
|
||||
//static
|
||||
BOOL WINAPI
|
||||
PMCPrintDlgW(LPPRINTDLGW aDlg)
|
||||
{
|
||||
// Zero out the HWND supplied by the plugin. We are sacrificing window
|
||||
// parentage for the ability to run in the NPAPI sandbox.
|
||||
HWND hwnd = aDlg->hwndOwner;
|
||||
aDlg->hwndOwner = 0;
|
||||
BOOL ret = sPrintDlgWPtrStub(aDlg);
|
||||
aDlg->hwndOwner = hwnd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI PMCSetCursorPos(int x, int y);
|
||||
|
||||
class SetCursorPosTaskData : public PluginThreadTaskData
|
||||
{
|
||||
public:
|
||||
SetCursorPosTaskData(int x, int y) : mX(x), mY(y) {}
|
||||
bool RunTask() { return PMCSetCursorPos(mX, mY); }
|
||||
private:
|
||||
int mX, mY;
|
||||
};
|
||||
|
||||
// static
|
||||
BOOL WINAPI
|
||||
PMCSetCursorPos(int x, int y)
|
||||
{
|
||||
if (!IsPluginThread()) {
|
||||
SetCursorPosTaskData scpData(x, y);
|
||||
return PostToPluginThread(&scpData);
|
||||
}
|
||||
|
||||
PluginModuleChild* chromeInstance = PluginModuleChild::GetChrome();
|
||||
if (chromeInstance) {
|
||||
bool ret = FALSE;
|
||||
chromeInstance->CallSetCursorPos(x, y, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return sSetCursorPosPtrStub(x, y);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
PPluginInstanceChild*
|
||||
PluginModuleChild::AllocPPluginInstanceChild(const nsCString& aMimeType,
|
||||
const InfallibleTArray<nsCString>& aNames,
|
||||
|
@ -1784,7 +2226,40 @@ PluginModuleChild::AllocPPluginInstanceChild(const nsCString& aMimeType,
|
|||
mQuirks = GetChrome()->mQuirks;
|
||||
|
||||
#ifdef XP_WIN
|
||||
FunctionHook::HookFunctions(mQuirks);
|
||||
sUser32Intercept.Init("user32.dll");
|
||||
if ((mQuirks & QUIRK_FLASH_HOOK_GETWINDOWINFO) &&
|
||||
!sGetWindowInfoPtrStub) {
|
||||
sUser32Intercept.AddHook("GetWindowInfo", reinterpret_cast<intptr_t>(PMCGetWindowInfoHook),
|
||||
(void**) &sGetWindowInfoPtrStub);
|
||||
}
|
||||
|
||||
if ((mQuirks & QUIRK_FLASH_HOOK_GETKEYSTATE) &&
|
||||
!sGetKeyStatePtrStub) {
|
||||
sUser32Intercept.AddHook("GetKeyState", reinterpret_cast<intptr_t>(PMCGetKeyState),
|
||||
(void**) &sGetKeyStatePtrStub);
|
||||
}
|
||||
|
||||
if (!sSetCursorPosPtrStub) {
|
||||
sUser32Intercept.AddHook("SetCursorPos", reinterpret_cast<intptr_t>(PMCSetCursorPos),
|
||||
(void**) &sSetCursorPosPtrStub);
|
||||
}
|
||||
|
||||
sComDlg32Intercept.Init("comdlg32.dll");
|
||||
if (!sGetSaveFileNameWPtrStub) {
|
||||
sComDlg32Intercept.AddHook("GetSaveFileNameW", reinterpret_cast<intptr_t>(PMCGetSaveFileNameW),
|
||||
(void**) &sGetSaveFileNameWPtrStub);
|
||||
}
|
||||
|
||||
if (!sGetOpenFileNameWPtrStub) {
|
||||
sComDlg32Intercept.AddHook("GetOpenFileNameW", reinterpret_cast<intptr_t>(PMCGetOpenFileNameW),
|
||||
(void**) &sGetOpenFileNameWPtrStub);
|
||||
}
|
||||
|
||||
if ((mQuirks & QUIRK_FLASH_HOOK_PRINTDLGW) &&
|
||||
!sPrintDlgWPtrStub) {
|
||||
sComDlg32Intercept.AddHook("PrintDlgW", reinterpret_cast<intptr_t>(PMCPrintDlgW),
|
||||
(void**) &sPrintDlgWPtrStub);
|
||||
}
|
||||
#endif
|
||||
|
||||
return new PluginInstanceChild(&mFunctions, aMimeType, aNames,
|
||||
|
|
|
@ -78,9 +78,6 @@ protected:
|
|||
virtual mozilla::ipc::IPCResult
|
||||
RecvInitPluginModuleChild(Endpoint<PPluginModuleChild>&& endpoint) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
RecvInitPluginFunctionBroker(Endpoint<PFunctionBrokerChild>&& endpoint) override;
|
||||
|
||||
virtual PPluginInstanceChild*
|
||||
AllocPPluginInstanceChild(const nsCString& aMimeType,
|
||||
const InfallibleTArray<nsCString>& aNames,
|
||||
|
@ -236,6 +233,10 @@ private:
|
|||
bool InitGraphics();
|
||||
void DeinitGraphics();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
void HookProtectedMode();
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
static gboolean DetectNestedEventLoop(gpointer data);
|
||||
static gboolean ProcessBrowserEvents(gpointer data);
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "mozilla/plugins/PluginSurfaceParent.h"
|
||||
#include "mozilla/widget/AudioSession.h"
|
||||
#include "PluginHangUIParent.h"
|
||||
#include "FunctionBrokerParent.h"
|
||||
#include "PluginUtilsWin.h"
|
||||
#endif
|
||||
|
||||
|
@ -487,23 +486,6 @@ PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId,
|
|||
parent->mShutdown = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
Endpoint<PFunctionBrokerParent> brokerParentEnd;
|
||||
Endpoint<PFunctionBrokerChild> brokerChildEnd;
|
||||
rv = PFunctionBroker::CreateEndpoints(base::GetCurrentProcId(), parent->OtherPid(),
|
||||
&brokerParentEnd, &brokerChildEnd);
|
||||
if (NS_FAILED(rv)) {
|
||||
parent->mShutdown = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
parent->mBrokerParent =
|
||||
FunctionBrokerParent::Create(Move(brokerParentEnd));
|
||||
if (parent->mBrokerParent) {
|
||||
parent->SendInitPluginFunctionBroker(Move(brokerChildEnd));
|
||||
}
|
||||
#endif
|
||||
return parent.forget();
|
||||
}
|
||||
|
||||
|
@ -640,7 +622,6 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath,
|
|||
, mHangUIParent(nullptr)
|
||||
, mHangUIEnabled(true)
|
||||
, mIsTimerReset(true)
|
||||
, mBrokerParent(nullptr)
|
||||
#endif
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
, mFlashProcess1(0)
|
||||
|
@ -667,6 +648,10 @@ PluginModuleChromeParent::~PluginModuleChromeParent()
|
|||
false);
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
mSandboxPermissions.RemovePermissionsForProcess(OtherPid());
|
||||
#endif
|
||||
|
||||
if (!mShutdown) {
|
||||
NS_WARNING("Plugin host deleted the module without shutting down.");
|
||||
NPError err;
|
||||
|
@ -1611,13 +1596,6 @@ PluginModuleChromeParent::ActorDestroy(ActorDestroyReason why)
|
|||
// We can't broadcast settings changes anymore.
|
||||
UnregisterSettingsCallbacks();
|
||||
|
||||
#if defined(XP_WIN)
|
||||
if (mBrokerParent) {
|
||||
FunctionBrokerParent::Destroy(mBrokerParent);
|
||||
mBrokerParent = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
PluginModuleParent::ActorDestroy(why);
|
||||
}
|
||||
|
||||
|
@ -2901,3 +2879,102 @@ PluginModuleChromeParent::OnCrash(DWORD processID)
|
|||
}
|
||||
|
||||
#endif // MOZ_CRASHREPORTER_INJECTOR
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleParent::AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet)
|
||||
{
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChromeParent::AnswerGetKeyState(const int32_t& aVirtKey,
|
||||
int16_t* aRet)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
*aRet = ::GetKeyState(aVirtKey);
|
||||
return IPC_OK();
|
||||
#else
|
||||
return PluginModuleParent::AnswerGetKeyState(aVirtKey, aRet);
|
||||
#endif
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChromeParent::AnswerGetFileName(const GetFileNameFunc& aFunc,
|
||||
const OpenFileNameIPC& aOfnIn,
|
||||
OpenFileNameRetIPC* aOfnOut,
|
||||
bool* aResult)
|
||||
{
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
OPENFILENAMEW ofn;
|
||||
memset(&ofn, 0, sizeof(ofn));
|
||||
aOfnIn.AllocateOfnStrings(&ofn);
|
||||
aOfnIn.AddToOfn(&ofn);
|
||||
switch (aFunc) {
|
||||
case OPEN_FUNC:
|
||||
*aResult = GetOpenFileName(&ofn);
|
||||
break;
|
||||
case SAVE_FUNC:
|
||||
*aResult = GetSaveFileName(&ofn);
|
||||
break;
|
||||
default:
|
||||
*aResult = false;
|
||||
break;
|
||||
}
|
||||
if (*aResult) {
|
||||
if (ofn.Flags & OFN_ALLOWMULTISELECT) {
|
||||
// We only support multiselect with the OFN_EXPLORER flag.
|
||||
// This guarantees that ofn.lpstrFile follows the pattern below.
|
||||
MOZ_ASSERT(ofn.Flags & OFN_EXPLORER);
|
||||
|
||||
// lpstrFile is one of two things:
|
||||
// 1. A null terminated full path to a file, or
|
||||
// 2. A path to a folder, followed by a NULL, followed by a
|
||||
// list of file names, each NULL terminated, followed by an
|
||||
// additional NULL (so it is also double-NULL terminated).
|
||||
std::wstring path = std::wstring(ofn.lpstrFile);
|
||||
MOZ_ASSERT(ofn.nFileOffset > 0);
|
||||
// For condition #1, nFileOffset points to the file name in the path.
|
||||
// It will be preceeded by a non-NULL character from the path.
|
||||
if (ofn.lpstrFile[ofn.nFileOffset-1] != L'\0') {
|
||||
mSandboxPermissions.GrantFileAccess(OtherPid(), path.c_str(),
|
||||
aFunc == SAVE_FUNC);
|
||||
}
|
||||
else {
|
||||
// This is condition #2
|
||||
wchar_t* nextFile = ofn.lpstrFile + path.size() + 1;
|
||||
while (*nextFile != L'\0') {
|
||||
std::wstring nextFileStr(nextFile);
|
||||
std::wstring fullPath =
|
||||
path + std::wstring(L"\\") + nextFileStr;
|
||||
mSandboxPermissions.GrantFileAccess(OtherPid(), fullPath.c_str(),
|
||||
aFunc == SAVE_FUNC);
|
||||
nextFile += nextFileStr.size() + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
mSandboxPermissions.GrantFileAccess(OtherPid(), ofn.lpstrFile,
|
||||
aFunc == SAVE_FUNC);
|
||||
}
|
||||
aOfnOut->CopyFromOfn(&ofn);
|
||||
}
|
||||
aOfnIn.FreeOfnStrings(&ofn);
|
||||
return IPC_OK();
|
||||
#else
|
||||
MOZ_ASSERT_UNREACHABLE("GetFileName IPC message is only available on "
|
||||
"Windows builds with sandbox.");
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
PluginModuleChromeParent::AnswerSetCursorPos(const int &x, const int &y,
|
||||
bool* aResult)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
*aResult = ::SetCursorPos(x, y);
|
||||
return IPC_OK();
|
||||
#else
|
||||
return PluginModuleParent::AnswerSetCursorPos(x, y, aResult);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "nsIObserver.h"
|
||||
#ifdef XP_WIN
|
||||
#include "nsWindowsHelpers.h"
|
||||
#if defined(MOZ_SANDBOX)
|
||||
#include "sandboxPermissions.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class nsPluginTag;
|
||||
|
@ -45,7 +48,6 @@ class PluginInstanceParent;
|
|||
|
||||
#ifdef XP_WIN
|
||||
class PluginHangUIParent;
|
||||
class FunctionBrokerParent;
|
||||
#endif
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
class FinishInjectorInitTask;
|
||||
|
@ -166,6 +168,20 @@ protected:
|
|||
const bool& shouldRegister,
|
||||
NPError* result) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
AnswerGetFileName(const GetFileNameFunc& aFunc,
|
||||
const OpenFileNameIPC& aOfnIn,
|
||||
OpenFileNameRetIPC* aOfnOut, bool* aResult) override
|
||||
{
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
AnswerSetCursorPos(const int &x, const int &y, bool* aResult) override
|
||||
{
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetChildTimeout(const int32_t aChildTimeout);
|
||||
static void TimeoutChanged(const char* aPref, void* aModule);
|
||||
|
@ -174,6 +190,8 @@ protected:
|
|||
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyContentModuleDestroyed() override { return IPC_OK(); }
|
||||
|
||||
virtual mozilla::ipc::IPCResult AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvReturnClearSiteData(const NPError& aRv,
|
||||
const uint64_t& aCallbackId) override;
|
||||
|
||||
|
@ -466,6 +484,19 @@ class PluginModuleChromeParent
|
|||
|
||||
void CachedSettingChanged();
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override;
|
||||
|
||||
// Proxy GetOpenFileName/GetSaveFileName on Windows.
|
||||
virtual mozilla::ipc::IPCResult
|
||||
AnswerGetFileName(const GetFileNameFunc& aFunc,
|
||||
const OpenFileNameIPC& aOfnIn,
|
||||
OpenFileNameRetIPC* aOfnOut, bool* aResult) override;
|
||||
|
||||
// Proxy SetCursorPos on Windows.
|
||||
virtual mozilla::ipc::IPCResult
|
||||
AnswerSetCursorPos(const int &x, const int &y, bool* aResult) override;
|
||||
|
||||
private:
|
||||
virtual void
|
||||
EnteredCxxStack() override;
|
||||
|
@ -557,8 +588,6 @@ private:
|
|||
*/
|
||||
void
|
||||
FinishHangUI();
|
||||
|
||||
FunctionBrokerParent* mBrokerParent;
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
|
@ -600,6 +629,9 @@ private:
|
|||
|
||||
nsCOMPtr<nsIObserver> mPluginOfflineObserver;
|
||||
bool mIsBlocklisted;
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
mozilla::SandboxPermissions mSandboxPermissions;
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIFile> mBrowserDumpFile;
|
||||
TakeFullMinidumpCallback mTakeFullMinidumpCallback;
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
#include "base/command_line.h"
|
||||
#include "base/string_util.h"
|
||||
#include "nsDebugImpl.h"
|
||||
#include "nsThreadManager.h"
|
||||
#include "ClearOnShutdown.h"
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#include "nsCocoaFeatures.h"
|
||||
|
@ -108,14 +106,6 @@ PluginProcessChild::Init(int aArgc, char* aArgv[])
|
|||
|
||||
pluginFilename = WideToUTF8(values[0]);
|
||||
|
||||
// We don't initialize XPCOM but we need the thread manager and the
|
||||
// logging framework for the FunctionBroker.
|
||||
NS_SetMainThread();
|
||||
mozilla::TimeStamp::Startup();
|
||||
NS_LogInit();
|
||||
mozilla::LogModule::Init();
|
||||
nsThreadManager::get().Init();
|
||||
|
||||
#if defined(MOZ_SANDBOX)
|
||||
// This is probably the earliest we would want to start the sandbox.
|
||||
// As we attempt to tighten the sandbox, we may need to consider moving this
|
||||
|
@ -151,18 +141,6 @@ PluginProcessChild::Init(int aArgc, char* aArgv[])
|
|||
void
|
||||
PluginProcessChild::CleanUp()
|
||||
{
|
||||
#if defined(OS_WIN)
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Shutdown components we started in Init. Note that KillClearOnShutdown
|
||||
// is an event that is regularly part of XPCOM shutdown. We do not
|
||||
// call XPCOM's shutdown but we need this event to be sent to avoid
|
||||
// leaking objects labeled as ClearOnShutdown.
|
||||
nsThreadManager::get().Shutdown();
|
||||
mozilla::KillClearOnShutdown(ShutdownPhase::ShutdownFinal);
|
||||
NS_LogTerm();
|
||||
#endif
|
||||
|
||||
nsRegion::ShutdownStatic();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
#ifndef dom_plugins_PluginQuirks_h
|
||||
#define dom_plugins_PluginQuirks_h
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
|
|
|
@ -16,8 +16,6 @@ EXPORTS.mozilla.plugins += [
|
|||
'BrowserStreamChild.h',
|
||||
'BrowserStreamParent.h',
|
||||
'ChildTimer.h',
|
||||
'FunctionBrokerIPCUtils.h',
|
||||
'IpdlTuple.h',
|
||||
'NPEventAndroid.h',
|
||||
'NPEventOSX.h',
|
||||
'NPEventUnix.h',
|
||||
|
@ -66,15 +64,9 @@ UNIFIED_SOURCES += [
|
|||
'BrowserStreamChild.cpp',
|
||||
'BrowserStreamParent.cpp',
|
||||
'ChildTimer.cpp',
|
||||
'FunctionBroker.cpp',
|
||||
'FunctionBrokerChild.cpp',
|
||||
'FunctionBrokerIPCUtils.cpp',
|
||||
'FunctionBrokerParent.cpp',
|
||||
'FunctionHook.cpp',
|
||||
'PluginBackgroundDestroyer.cpp',
|
||||
'PluginInstanceParent.cpp',
|
||||
'PluginMessageUtils.cpp',
|
||||
'PluginModuleChild.cpp',
|
||||
'PluginModuleParent.cpp',
|
||||
'PluginProcessChild.cpp',
|
||||
'PluginProcessParent.cpp',
|
||||
|
@ -85,6 +77,7 @@ UNIFIED_SOURCES += [
|
|||
|
||||
SOURCES += [
|
||||
'PluginInstanceChild.cpp', # 'PluginThreadCallback' : ambiguous symbol
|
||||
'PluginModuleChild.cpp', # Redefinition of mozilla::WindowsDllInterceptor sUser32Intercept
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
|
@ -109,7 +102,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
|||
|
||||
IPDL_SOURCES += [
|
||||
'PBrowserStream.ipdl',
|
||||
'PFunctionBroker.ipdl',
|
||||
'PluginTypes.ipdlh',
|
||||
'PPluginBackgroundDestroyer.ipdl',
|
||||
'PPluginInstance.ipdl',
|
||||
|
@ -125,7 +117,6 @@ FINAL_LIBRARY = 'xul'
|
|||
LOCAL_INCLUDES += [
|
||||
'../base',
|
||||
'/xpcom/base/',
|
||||
'/xpcom/threads/',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
|
||||
|
|
|
@ -310,12 +310,6 @@ struct ParamTraits<int8_t>
|
|||
{
|
||||
return aMsg->ReadBytesInto(aIter, aResult, sizeof(*aResult));
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
// Use 0xff to avoid sign extension.
|
||||
aLog->append(StringPrintf(L"0x%02x", aParam & 0xff));
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
|
@ -332,11 +326,6 @@ struct ParamTraits<uint8_t>
|
|||
{
|
||||
return aMsg->ReadBytesInto(aIter, aResult, sizeof(*aResult));
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog)
|
||||
{
|
||||
aLog->append(StringPrintf(L"0x%02x", aParam));
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(OS_POSIX)
|
||||
|
|
|
@ -659,8 +659,6 @@ description =
|
|||
description =
|
||||
[PPluginWidget::SetNativeChildWindow]
|
||||
description =
|
||||
[PFunctionBroker::BrokerFunction]
|
||||
description =
|
||||
[PPluginInstance::__delete__]
|
||||
description =
|
||||
[PPluginInstance::CreateChildPluginWindow]
|
||||
|
@ -773,10 +771,16 @@ description =
|
|||
description =
|
||||
[PPluginModule::NPN_SetException]
|
||||
description =
|
||||
[PPluginModule::GetKeyState]
|
||||
description =
|
||||
[PPluginModule::NPN_SetValue_NPPVpluginRequiresAudioDeviceChanges]
|
||||
description =
|
||||
[PPluginModule::InitCrashReporter]
|
||||
description =
|
||||
[PPluginModule::GetFileName]
|
||||
description =
|
||||
[PPluginModule::SetCursorPos]
|
||||
description =
|
||||
[PPluginScriptableObject::NPN_Evaluate]
|
||||
description =
|
||||
[PPluginScriptableObject::Invalidate]
|
||||
|
|
|
@ -5054,12 +5054,6 @@ XRE_IsContentProcess()
|
|||
return XRE_GetProcessType() == GeckoProcessType_Content;
|
||||
}
|
||||
|
||||
bool
|
||||
XRE_IsPluginProcess()
|
||||
{
|
||||
return XRE_GetProcessType() == GeckoProcessType_Plugin;
|
||||
}
|
||||
|
||||
bool
|
||||
XRE_UseNativeEventProcessing()
|
||||
{
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
#include <shlobj.h>
|
||||
#include <stdio.h>
|
||||
#include <commdlg.h>
|
||||
#define SECURITY_WIN32
|
||||
#include <security.h>
|
||||
#include <wininet.h>
|
||||
#include <schnlsp.h>
|
||||
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "nsWindowsDllInterceptor.h"
|
||||
|
@ -444,141 +440,6 @@ bool TestPrintDlgW(void* aFunc)
|
|||
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()
|
||||
{
|
||||
// We disable this part of the test because the code coverage instrumentation
|
||||
|
@ -695,26 +556,6 @@ int main()
|
|||
TestHook(TestSetCursorPos, "user32.dll", "SetCursorPos") &&
|
||||
TestHook(TestTlsAlloc, "kernel32.dll", "TlsAlloc") &&
|
||||
TestHook(TestTlsFree, "kernel32.dll", "TlsFree") &&
|
||||
|
||||
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") &&
|
||||
|
||||
TestHook(TestAcquireCredentialsHandleA, "sspicli.dll", "AcquireCredentialsHandleA") &&
|
||||
TestHook(TestQueryCredentialsAttributesA, "sspicli.dll", "QueryCredentialsAttributesA") &&
|
||||
TestHook(TestFreeCredentialsHandle, "sspicli.dll", "FreeCredentialsHandle") &&
|
||||
|
||||
TestDetour("kernel32.dll", "BaseThreadInitThunk") &&
|
||||
TestDetour("ntdll.dll", "LdrLoadDll")) {
|
||||
printf("TEST-PASS | WindowsDllInterceptor | all checks passed\n");
|
||||
|
|
|
@ -1043,31 +1043,6 @@ protected:
|
|||
MOZ_ASSERT_UNREACHABLE("Unrecognized opcode sequence");
|
||||
return;
|
||||
}
|
||||
} else if (origBytes[nOrigBytes] == 0x8d) {
|
||||
// LEA reg, addr
|
||||
if ((origBytes[nOrigBytes + 1] & kMaskMod) == 0x0 &&
|
||||
(origBytes[nOrigBytes + 1] & kMaskRm) == 0x5) {
|
||||
// [rip+disp32]
|
||||
// convert 32bit offset to 64bit direct and convert instruction
|
||||
// to a simple 64-bit mov
|
||||
BYTE reg = (origBytes[nOrigBytes + 1] & kMaskReg) >> kRegFieldShift;
|
||||
intptr_t absAddr =
|
||||
reinterpret_cast<intptr_t>(origBytes + nOrigBytes + 6 +
|
||||
*reinterpret_cast<int32_t*>(origBytes + nOrigBytes + 2));
|
||||
nOrigBytes += 6;
|
||||
tramp[nTrampBytes] = 0xb8 + reg; // mov
|
||||
++nTrampBytes;
|
||||
intptr_t* trampOperandPtr = reinterpret_cast<intptr_t*>(tramp + nTrampBytes);
|
||||
*trampOperandPtr = absAddr;
|
||||
nTrampBytes += 8;
|
||||
} else {
|
||||
// Above we dealt with RIP-relative instructions. Any other
|
||||
// operand form can simply be copied.
|
||||
int len = CountModRmSib(origBytes + nOrigBytes + 1);
|
||||
// We handled the kModOperand64 -- ie RIP-relative -- case above
|
||||
MOZ_ASSERT(len > 0);
|
||||
COPY_CODES(len + 1);
|
||||
}
|
||||
} else if (origBytes[nOrigBytes] == 0x63 &&
|
||||
(origBytes[nOrigBytes + 1] & kMaskMod) == kModReg) {
|
||||
// movsxd r64, r32 (move + sign extend)
|
||||
|
@ -1102,17 +1077,6 @@ protected:
|
|||
MOZ_ASSERT_UNREACHABLE("Unrecognized MOV opcode sequence");
|
||||
return;
|
||||
}
|
||||
} else if (origBytes[nOrigBytes] == 0x44 &&
|
||||
origBytes[nOrigBytes+1] == 0x89) {
|
||||
// mov word ptr [reg+disp8], reg
|
||||
COPY_CODES(2);
|
||||
int len = CountModRmSib(origBytes + nOrigBytes);
|
||||
if (len < 0) {
|
||||
// no way to support this yet.
|
||||
MOZ_ASSERT_UNREACHABLE("Unrecognized opcode sequence");
|
||||
return;
|
||||
}
|
||||
COPY_CODES(len);
|
||||
}
|
||||
} else if ((origBytes[nOrigBytes] & 0xf0) == 0x50) {
|
||||
// 1-byte push/pop
|
||||
|
@ -1258,19 +1222,6 @@ protected:
|
|||
MOZ_ASSERT_UNREACHABLE("Unrecognized opcode sequence");
|
||||
return;
|
||||
}
|
||||
} else if (origBytes[nOrigBytes] == 0x83 &&
|
||||
(origBytes[nOrigBytes + 1] & 0xf8) == 0x60) {
|
||||
// and [r+d], imm8
|
||||
COPY_CODES(5);
|
||||
} else if (origBytes[nOrigBytes] == 0xc6) {
|
||||
// mov [r+d], imm8
|
||||
int len = CountModRmSib(&origBytes[nOrigBytes + 1]);
|
||||
if (len < 0) {
|
||||
// RIP-relative not yet supported
|
||||
MOZ_ASSERT_UNREACHABLE("Unrecognized opcode sequence");
|
||||
return;
|
||||
}
|
||||
COPY_CODES(len + 1);
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("Unrecognized opcode sequence");
|
||||
return;
|
||||
|
@ -1401,15 +1352,10 @@ class WindowsDllInterceptor
|
|||
int mNHooks;
|
||||
|
||||
public:
|
||||
explicit WindowsDllInterceptor(const char* aModuleName = nullptr,
|
||||
int aNumHooks = 0)
|
||||
WindowsDllInterceptor()
|
||||
: mModuleName(nullptr)
|
||||
, mNHooks(0)
|
||||
{
|
||||
if (aModuleName) {
|
||||
Init(aModuleName, aNumHooks);
|
||||
}
|
||||
}
|
||||
{}
|
||||
|
||||
void Init(const char* aModuleName, int aNumHooks = 0)
|
||||
{
|
||||
|
|
|
@ -447,9 +447,6 @@ XRE_API(bool,
|
|||
XRE_API(bool,
|
||||
XRE_IsGPUProcess, ())
|
||||
|
||||
XRE_API(bool,
|
||||
XRE_IsPluginProcess, ())
|
||||
|
||||
/**
|
||||
* Returns true if the appshell should run its own native event loop. Returns
|
||||
* false if we should rely solely on the Gecko event loop.
|
||||
|
|
Загрузка…
Ссылка в новой задаче