mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
7e818f6e97
--HG-- extra : rebase_source : e04ab81d4686a4ab487ba51cb6a221d862760792
335 lines
8.2 KiB
C++
335 lines
8.2 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=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 mozilla_plugins_MiniShmBase_h
|
|
#define mozilla_plugins_MiniShmBase_h
|
|
|
|
#include "base/basictypes.h"
|
|
|
|
#include "nsDebug.h"
|
|
|
|
#include <windows.h>
|
|
|
|
namespace mozilla {
|
|
namespace plugins {
|
|
|
|
/**
|
|
* This class is used to provide RAII semantics for mapped views.
|
|
* @see ScopedHandle
|
|
*/
|
|
class ScopedMappedFileView
|
|
{
|
|
public:
|
|
explicit
|
|
ScopedMappedFileView(LPVOID aView)
|
|
: mView(aView)
|
|
{
|
|
}
|
|
|
|
~ScopedMappedFileView()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
void
|
|
Close()
|
|
{
|
|
if (mView) {
|
|
::UnmapViewOfFile(mView);
|
|
mView = nullptr;
|
|
}
|
|
}
|
|
|
|
void
|
|
Set(LPVOID aView)
|
|
{
|
|
Close();
|
|
mView = aView;
|
|
}
|
|
|
|
LPVOID
|
|
Get() const
|
|
{
|
|
return mView;
|
|
}
|
|
|
|
LPVOID
|
|
Take()
|
|
{
|
|
LPVOID result = mView;
|
|
mView = nullptr;
|
|
return result;
|
|
}
|
|
|
|
operator LPVOID()
|
|
{
|
|
return mView;
|
|
}
|
|
|
|
bool
|
|
IsValid() const
|
|
{
|
|
return (mView);
|
|
}
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(ScopedMappedFileView);
|
|
|
|
LPVOID mView;
|
|
};
|
|
|
|
class MiniShmBase;
|
|
|
|
class MiniShmObserver
|
|
{
|
|
public:
|
|
/**
|
|
* This function is called whenever there is a new shared memory request.
|
|
* @param aMiniShmObj MiniShmBase object that may be used to read and
|
|
* write from shared memory.
|
|
*/
|
|
virtual void OnMiniShmEvent(MiniShmBase *aMiniShmObj) = 0;
|
|
/**
|
|
* This function is called once when a MiniShmParent and a MiniShmChild
|
|
* object have successfully negotiated a connection.
|
|
*
|
|
* @param aMiniShmObj MiniShmBase object that may be used to read and
|
|
* write from shared memory.
|
|
*/
|
|
virtual void OnMiniShmConnect(MiniShmBase *aMiniShmObj) { }
|
|
};
|
|
|
|
/**
|
|
* Base class for MiniShm connections. This class defines the common
|
|
* interfaces and code between parent and child.
|
|
*/
|
|
class MiniShmBase
|
|
{
|
|
public:
|
|
/**
|
|
* Obtains a writable pointer into shared memory of type T.
|
|
* typename T must be plain-old-data and contain an unsigned integral
|
|
* member T::identifier that uniquely identifies T with respect to
|
|
* other types used by the protocol being implemented.
|
|
*
|
|
* @param aPtr Pointer to receive the shared memory address.
|
|
* This value is set if and only if the function
|
|
* succeeded.
|
|
* @return NS_OK if and only if aPtr was successfully obtained.
|
|
* NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm.
|
|
* NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection.
|
|
* NS_ERROR_NOT_AVAILABLE if the memory is not safe to write.
|
|
*/
|
|
template<typename T> nsresult
|
|
GetWritePtr(T*& aPtr)
|
|
{
|
|
if (!mWriteHeader || !mGuard) {
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
}
|
|
if (sizeof(T) > mPayloadMaxLen ||
|
|
T::identifier <= RESERVED_CODE_LAST) {
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
if (::WaitForSingleObject(mGuard, mTimeout) != WAIT_OBJECT_0) {
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
mWriteHeader->mId = T::identifier;
|
|
mWriteHeader->mPayloadLen = sizeof(T);
|
|
aPtr = reinterpret_cast<T*>(mWriteHeader + 1);
|
|
return NS_OK;
|
|
}
|
|
|
|
/**
|
|
* Obtains a readable pointer into shared memory of type T.
|
|
* typename T must be plain-old-data and contain an unsigned integral
|
|
* member T::identifier that uniquely identifies T with respect to
|
|
* other types used by the protocol being implemented.
|
|
*
|
|
* @param aPtr Pointer to receive the shared memory address.
|
|
* This value is set if and only if the function
|
|
* succeeded.
|
|
* @return NS_OK if and only if aPtr was successfully obtained.
|
|
* NS_ERROR_ILLEGAL_VALUE if type T is not valid for MiniShm or if
|
|
* type T does not match the type of the data
|
|
* stored in shared memory.
|
|
* NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection.
|
|
*/
|
|
template<typename T> nsresult
|
|
GetReadPtr(const T*& aPtr)
|
|
{
|
|
if (!mReadHeader) {
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
}
|
|
if (mReadHeader->mId != T::identifier ||
|
|
sizeof(T) != mReadHeader->mPayloadLen) {
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
aPtr = reinterpret_cast<const T*>(mReadHeader + 1);
|
|
return NS_OK;
|
|
}
|
|
|
|
/**
|
|
* Fires the peer's event causing its request handler to execute.
|
|
*
|
|
* @return Should return NS_OK if the send was successful.
|
|
*/
|
|
virtual nsresult
|
|
Send() = 0;
|
|
|
|
protected:
|
|
/**
|
|
* MiniShm reserves some identifier codes for its own use. Any
|
|
* identifiers used by MiniShm protocol implementations must be
|
|
* greater than RESERVED_CODE_LAST.
|
|
*/
|
|
enum ReservedCodes
|
|
{
|
|
RESERVED_CODE_INIT = 0,
|
|
RESERVED_CODE_INIT_COMPLETE = 1,
|
|
RESERVED_CODE_LAST = RESERVED_CODE_INIT_COMPLETE
|
|
};
|
|
|
|
struct MiniShmHeader
|
|
{
|
|
unsigned int mId;
|
|
unsigned int mPayloadLen;
|
|
};
|
|
|
|
struct MiniShmInit
|
|
{
|
|
enum identifier_t
|
|
{
|
|
identifier = RESERVED_CODE_INIT
|
|
};
|
|
HANDLE mParentEvent;
|
|
HANDLE mParentGuard;
|
|
HANDLE mChildEvent;
|
|
HANDLE mChildGuard;
|
|
};
|
|
|
|
struct MiniShmInitComplete
|
|
{
|
|
enum identifier_t
|
|
{
|
|
identifier = RESERVED_CODE_INIT_COMPLETE
|
|
};
|
|
bool mSucceeded;
|
|
};
|
|
|
|
MiniShmBase()
|
|
: mObserver(nullptr),
|
|
mWriteHeader(nullptr),
|
|
mReadHeader(nullptr),
|
|
mPayloadMaxLen(0),
|
|
mGuard(nullptr),
|
|
mTimeout(INFINITE)
|
|
{
|
|
}
|
|
virtual ~MiniShmBase()
|
|
{ }
|
|
|
|
virtual void
|
|
OnEvent()
|
|
{
|
|
if (mObserver) {
|
|
mObserver->OnMiniShmEvent(this);
|
|
}
|
|
}
|
|
|
|
virtual void
|
|
OnConnect()
|
|
{
|
|
if (mObserver) {
|
|
mObserver->OnMiniShmConnect(this);
|
|
}
|
|
}
|
|
|
|
nsresult
|
|
SetView(LPVOID aView, const unsigned int aSize, bool aIsChild)
|
|
{
|
|
if (!aView || aSize <= 2 * sizeof(MiniShmHeader)) {
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
// Divide the region into halves for parent and child
|
|
if (aIsChild) {
|
|
mReadHeader = static_cast<MiniShmHeader*>(aView);
|
|
mWriteHeader = reinterpret_cast<MiniShmHeader*>(static_cast<char*>(aView)
|
|
+ aSize / 2U);
|
|
} else {
|
|
mWriteHeader = static_cast<MiniShmHeader*>(aView);
|
|
mReadHeader = reinterpret_cast<MiniShmHeader*>(static_cast<char*>(aView)
|
|
+ aSize / 2U);
|
|
}
|
|
mPayloadMaxLen = aSize / 2U - sizeof(MiniShmHeader);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
SetGuard(HANDLE aGuard, DWORD aTimeout)
|
|
{
|
|
if (!aGuard || !aTimeout) {
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
mGuard = aGuard;
|
|
mTimeout = aTimeout;
|
|
return NS_OK;
|
|
}
|
|
|
|
inline void
|
|
SetObserver(MiniShmObserver *aObserver) { mObserver = aObserver; }
|
|
|
|
/**
|
|
* Obtains a writable pointer into shared memory of type T. This version
|
|
* differs from GetWritePtr in that it allows typename T to be one of
|
|
* the private data structures declared in MiniShmBase.
|
|
*
|
|
* @param aPtr Pointer to receive the shared memory address.
|
|
* This value is set if and only if the function
|
|
* succeeded.
|
|
* @return NS_OK if and only if aPtr was successfully obtained.
|
|
* NS_ERROR_ILLEGAL_VALUE if type T not an internal MiniShm struct.
|
|
* NS_ERROR_NOT_INITIALIZED if there is no valid MiniShm connection.
|
|
*/
|
|
template<typename T> nsresult
|
|
GetWritePtrInternal(T*& aPtr)
|
|
{
|
|
if (!mWriteHeader) {
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
}
|
|
if (sizeof(T) > mPayloadMaxLen ||
|
|
T::identifier > RESERVED_CODE_LAST) {
|
|
return NS_ERROR_ILLEGAL_VALUE;
|
|
}
|
|
mWriteHeader->mId = T::identifier;
|
|
mWriteHeader->mPayloadLen = sizeof(T);
|
|
aPtr = reinterpret_cast<T*>(mWriteHeader + 1);
|
|
return NS_OK;
|
|
}
|
|
|
|
static VOID CALLBACK
|
|
SOnEvent(PVOID aContext, BOOLEAN aIsTimer)
|
|
{
|
|
MiniShmBase* object = static_cast<MiniShmBase*>(aContext);
|
|
object->OnEvent();
|
|
}
|
|
|
|
private:
|
|
MiniShmObserver* mObserver;
|
|
MiniShmHeader* mWriteHeader;
|
|
MiniShmHeader* mReadHeader;
|
|
unsigned int mPayloadMaxLen;
|
|
HANDLE mGuard;
|
|
DWORD mTimeout;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(MiniShmBase);
|
|
};
|
|
|
|
} // namespace plugins
|
|
} // namespace mozilla
|
|
|
|
#endif // mozilla_plugins_MiniShmBase_h
|
|
|