gecko-dev/dom/plugins/ipc/FunctionBrokerIPCUtils.h

437 lines
14 KiB
C++

/* -*- 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_functionbrokeripcutils_h
#define dom_plugins_ipc_functionbrokeripcutils_h 1
#include "ipc/EnumSerializer.h"
#include "ipc/IPCMessageUtilsSpecializations.h"
#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_HttpEndRequestA,
ID_InternetQueryOptionA,
ID_InternetErrorDlg,
ID_AcquireCredentialsHandleA,
ID_QueryCredentialsAttributesA,
ID_FreeCredentialsHandle,
ID_PrintDlgW,
ID_CreateMutexW
# if defined(MOZ_SANDBOX)
,
ID_GetFileAttributesW
# endif // defined(MOZ_SANDBOX)
,
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 CopyableTArray<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);
}
};
CopyableTArray<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::IPCInternetBuffers;
using mozilla::plugins::IPCPrintDlg;
using mozilla::plugins::IPCSchannelCred;
using mozilla::plugins::NativeWindowHandle;
using mozilla::plugins::OpenFileNameIPC;
using mozilla::plugins::OpenFileNameRetIPC;
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"[%ls, %ls, %ls, %ls]", 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"[%ls, %ls, %ls, %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 */