You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
508 lines
17 KiB
508 lines
17 KiB
//
|
|
// marshal.h
|
|
//
|
|
|
|
#ifndef MARSHAL_H
|
|
#define MARSHAL_H
|
|
|
|
#include "private.h"
|
|
#include "globals.h"
|
|
#include "cicmutex.h"
|
|
#include "winuserp.h"
|
|
#include "systhrd.h"
|
|
#include "smblock.h"
|
|
#include "cregkey.h"
|
|
|
|
#define DEFAULTMARSHALTIMEOUT 30000
|
|
#define DEFAULTMARSHALCONNECTIONTIMEOUT 2000
|
|
|
|
|
|
#ifdef QS_RAWINPUT
|
|
#define QS_ALLINPUT400 (QS_ALLINPUT & ~QS_RAWINPUT)
|
|
#else
|
|
#define QS_ALLINPUT400 (QS_ALLINPUT)
|
|
#endif
|
|
#define QS_DEFAULTWAITFLAG (QS_ALLINPUT400 | QS_TRANSFER | QS_ALLPOSTMESSAGE)
|
|
|
|
#ifdef DEBUG
|
|
extern ULONG g_ulMarshalTimeOut;
|
|
#define MARSHALTIMEOUT g_ulMarshalTimeOut
|
|
|
|
|
|
const TCHAR c_szMarshal[] = TEXT("SOFTWARE\\Microsoft\\CTF\\Marshal\\");
|
|
const TCHAR c_szTimeOut[] = TEXT("TimeOut");
|
|
__inline void dbg_InitMarshalTimeOut()
|
|
{
|
|
CMyRegKey key;
|
|
DWORD dw;
|
|
|
|
if (key.Open(HKEY_CURRENT_USER, c_szMarshal, KEY_READ) != S_OK)
|
|
return;
|
|
|
|
if (key.QueryValue(dw, c_szTimeOut) != S_OK)
|
|
return;
|
|
|
|
g_ulMarshalTimeOut = (ULONG)dw;
|
|
}
|
|
|
|
#else
|
|
#define MARSHALTIMEOUT DEFAULTMARSHALTIMEOUT
|
|
#define dbg_InitMarshalTimeOut()
|
|
#endif
|
|
|
|
#define SZMARSHALINTERFACEFILEMAP __TEXT("MSCTF.MarshalInterface.FileMap.")
|
|
#define SZRPCSENDRECEIVEEVENT __TEXT("MSCTF.SendReceive.Event.")
|
|
#define SZRPCSENDRECEIVECONNECTIONEVENT __TEXT("MSCTF.SendReceiveConection.Event.")
|
|
|
|
HRESULT CicCoMarshalInterface(REFIID riid, IUnknown *punk, ULONG *pulStubId, DWORD *pdwStubTime, DWORD dwSrcThreadId);
|
|
HRESULT CicCoUnmarshalInterface(REFIID riid, DWORD dwStubThreadId, ULONG ulStubId, DWORD dwStubTIme, void **ppv);
|
|
void HandleSendReceiveMsg(DWORD dwSrcThreadId, ULONG ulCnt);
|
|
|
|
void FreeMarshaledStubs(SYSTHREAD *psfn);
|
|
void FreeMarshaledStubsForThread(SYSTHREAD *psfn, DWORD dwThread);
|
|
void StubCleanUp(ULONG ulStubId);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MARSHALINTERFACE structure
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct tag_MARSHALINTERFACE
|
|
{
|
|
IID iid;
|
|
DWORD dwStubTime;
|
|
} MARSHALINTERFACE;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MARSHALPARAM structure
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define MPARAM_IN 0x000000001
|
|
#define MPARAM_OUT 0x000000002
|
|
#define MPARAM_INTERFACE 0x000010000
|
|
#define MPARAM_POINTER 0x000020000
|
|
#define MPARAM_ULONG 0x000040000
|
|
#define MPARAM_BSTR 0x000080000
|
|
#define MPARAM_STRUCT 0x000100000
|
|
#define MPARAM_HBITMAP 0x000200000
|
|
#define MPARAM_TF_LBBALLOONINFO 0x000400000
|
|
#define MPARAM_HICON 0x000800000
|
|
|
|
#define MPARAM_IN_POINTER (MPARAM_IN | MPARAM_POINTER)
|
|
#define MPARAM_IN_INTERFACE (MPARAM_IN | MPARAM_INTERFACE)
|
|
#define MPARAM_IN_ULONG (MPARAM_IN | MPARAM_ULONG)
|
|
#define MPARAM_IN_STRUCT (MPARAM_IN | MPARAM_STRUCT)
|
|
#define MPARAM_IN_HBITMAP (MPARAM_IN | MPARAM_HBITMAP)
|
|
#define MPARAM_IN_HICON (MPARAM_IN | MPARAM_HICON)
|
|
|
|
#define MPARAM_OUT_POINTER (MPARAM_OUT | MPARAM_POINTER)
|
|
#define MPARAM_OUT_INTERFACE (MPARAM_OUT | MPARAM_INTERFACE)
|
|
#define MPARAM_OUT_BSTR (MPARAM_OUT | MPARAM_BSTR)
|
|
#define MPARAM_OUT_HBITMAP (MPARAM_OUT | MPARAM_HBITMAP)
|
|
#define MPARAM_OUT_TF_LBBALLOONINFO (MPARAM_OUT | MPARAM_TF_LBBALLOONINFO)
|
|
#define MPARAM_OUT_HICON (MPARAM_OUT | MPARAM_HICON)
|
|
|
|
#define MPARAM_IN_OUT_INTERFACE (MPARAM_IN | MPARAM_OUT | MPARAM_INTERFACE)
|
|
|
|
typedef struct tag_MARSHALPARAM
|
|
{
|
|
ULONG cbBufSize;
|
|
DWORD dwFlags;
|
|
// DWORD buf[1];
|
|
} MARSHALPARAM;
|
|
|
|
typedef struct tag_MARSHALMSG
|
|
{
|
|
ULONG cbSize;
|
|
ULONG cbBufSize;
|
|
IID iid;
|
|
ULONG ulMethodId;
|
|
ULONG ulParamNum;
|
|
union {
|
|
HRESULT hrRet;
|
|
ULONG ulRet;
|
|
};
|
|
DWORD dwSrcThreadId;
|
|
DWORD dwSrcProcessId;
|
|
ULONG ulStubId;
|
|
DWORD dwStubTime;
|
|
HRESULT hrMarshalOutParam;
|
|
ULONG ulParamOffset[1];
|
|
} MARSHALMSG;
|
|
|
|
__inline MARSHALPARAM *GetMarshalParam(MARSHALMSG *pMsg, ULONG ulParam)
|
|
{
|
|
return (MARSHALPARAM *)(((BYTE *)pMsg) + pMsg->ulParamOffset[ulParam]);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ParamExtractor
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
__inline void *ParamToBufferPointer(MARSHALPARAM *pParam)
|
|
{
|
|
return (void *)((BYTE *)pParam + sizeof(MARSHALPARAM));
|
|
}
|
|
|
|
__inline void *ParamToBufferPointer(MARSHALMSG *pMsg, ULONG ulParam)
|
|
{
|
|
MARSHALPARAM *pParam = GetMarshalParam(pMsg, ulParam);
|
|
return (void *)((BYTE *)pParam + sizeof(MARSHALPARAM));
|
|
}
|
|
|
|
__inline void *ParamToPointer(MARSHALPARAM *pParam)
|
|
{
|
|
return *(void **)((BYTE *)pParam + sizeof(MARSHALPARAM));
|
|
}
|
|
|
|
__inline void *ParamToPointer(MARSHALMSG *pMsg , ULONG ulParam)
|
|
{
|
|
MARSHALPARAM *pParam = GetMarshalParam(pMsg, ulParam);
|
|
return *(void **)((BYTE *)pParam + sizeof(MARSHALPARAM));
|
|
}
|
|
|
|
__inline ULONG ParamToULONG(MARSHALMSG *pMsg , ULONG ulParam)
|
|
{
|
|
MARSHALPARAM *pParam = GetMarshalParam(pMsg, ulParam);
|
|
return *(ULONG *)((BYTE *)pParam + sizeof(MARSHALPARAM));
|
|
}
|
|
|
|
HBITMAP ParamToHBITMAP(MARSHALMSG *pMsg , ULONG ulParam);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CModalLoop
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class CModalLoop : public CSysThreadRef
|
|
{
|
|
public:
|
|
CModalLoop(SYSTHREAD *psfn);
|
|
~CModalLoop();
|
|
|
|
HRESULT BlockFn(CCicEvent *pevent, DWORD dwWaitingThreadId, DWORD &dwWaitFlags);
|
|
|
|
private:
|
|
void WaitHandleWndMessages(DWORD dwQueueFlags);
|
|
BOOL WaitRemoveMessage(UINT uMsgFirst, UINT uMsgLast, DWORD dwFlags);
|
|
BOOL MyPeekMessage(MSG *pMsg, HWND hwnd, UINT min, UINT max, WORD wFlag);
|
|
|
|
ULONG _wQuitCode;
|
|
BOOL _fQuitReceived;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CThreadMarshalWnd
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class CThreadMarshalWnd
|
|
{
|
|
public:
|
|
CThreadMarshalWnd();
|
|
~CThreadMarshalWnd();
|
|
|
|
BOOL Init(DWORD dwThreadId);
|
|
BOOL PostMarshalThreadMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
static BOOL DestroyAll();
|
|
static BOOL DestroyThreadMarshalWnd(DWORD dwThread);
|
|
static HWND GetThreadMarshalWnd(DWORD dwThread);
|
|
static void ClearMarshalWndProc(DWORD dwProcessId);
|
|
|
|
BOOL IsWindow()
|
|
{
|
|
return ::IsWindow(_hwnd);
|
|
}
|
|
|
|
BOOL IsThreadWindow();
|
|
|
|
void SetMarshalWindow(HWND hwndMarshal)
|
|
{
|
|
_hwnd = hwndMarshal;
|
|
}
|
|
|
|
private:
|
|
static BOOL EnumThreadWndProc(HWND hwnd, LPARAM lParam);
|
|
|
|
DWORD _dwThreadId;
|
|
HWND _hwnd;
|
|
};
|
|
|
|
void RegisterMarshalWndClass();
|
|
HWND EnsureMarshalWnd();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CProxy
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
#define CPROXY_PARAM_START() CPROXY_PARAM param[] = {
|
|
|
|
#define CPROXY_PARAM_ULONG_IN(ul) \
|
|
{MPARAM_IN_ULONG, NULL, ul, NULL, sizeof(ULONG), 1},
|
|
|
|
#define CPROXY_PARAM_WCHAR_IN(pch, cch) \
|
|
{MPARAM_IN_POINTER, (void *)(pch), 0, NULL, cch * sizeof(WCHAR), 1},
|
|
|
|
#define CPROXY_PARAM_POINTER_IN(p) \
|
|
{MPARAM_IN_POINTER, (void *)(p), 0, NULL, sizeof(*p), 1},
|
|
|
|
#define CPROXY_PARAM_POINTER_ARRAY_IN(p, nCnt) \
|
|
{MPARAM_IN_POINTER, (void *)(p), 0, NULL, sizeof(*p), nCnt},
|
|
|
|
#define CPROXY_PARAM_INTERFACE_IN(p, iid) \
|
|
{MPARAM_IN_INTERFACE, p, 0, &iid, sizeof(void *), 1},
|
|
|
|
#define CPROXY_PARAM_INTERFACE_ARRAY_IN(p, iid, nCnt) \
|
|
{MPARAM_IN_INTERFACE, p, 0, &iid, sizeof(void *), nCnt},
|
|
|
|
#define CPROXY_PARAM_POINTER_OUT(p) \
|
|
{MPARAM_OUT_POINTER, p, 0, NULL, sizeof(*p), 1},
|
|
|
|
#define CPROXY_PARAM_POINTER_ARRAY_OUT(p, nCnt) \
|
|
{MPARAM_OUT_POINTER, p, 0, NULL, sizeof(*p), nCnt},
|
|
|
|
#define CPROXY_PARAM_INTERFACE_OUT(p, iid) \
|
|
{MPARAM_OUT_INTERFACE, p, 0, &iid, sizeof(void *), 1},
|
|
|
|
#define CPROXY_PARAM_INTERFACE_ARRAY_OUT(p, iid, nCnt) \
|
|
{MPARAM_OUT_INTERFACE, p, 0, &iid, sizeof(void *), nCnt},
|
|
|
|
#define CPROXY_PARAM_INTERFACE_IN_OUT(p, iid) \
|
|
{MPARAM_IN_OUT_INTERFACE, p, 0, &iid, sizeof(void *), 1},
|
|
|
|
#define CPROXY_PARAM_INTERFACE_ARRAY_IN_OUT(p, iid, nCnt) \
|
|
{MPARAM_IN_OUT_INTERFACE, p, 0, &iid, sizeof(void *), nCnt},
|
|
|
|
#define CPROXY_PARAM_BSTR_OUT(p) \
|
|
{MPARAM_OUT_BSTR, p, 0, NULL, 0, 1},
|
|
|
|
#define CPROXY_PARAM_HBITMAP_OUT(p) \
|
|
{MPARAM_OUT_HBITMAP, p, 0, NULL, 0, 1},
|
|
|
|
#define CPROXY_PARAM_HICON_OUT(p) \
|
|
{MPARAM_OUT_HICON, p, 0, NULL, 0, 1},
|
|
|
|
#define CPROXY_PARAM_HBITMAP_IN(hbmp) \
|
|
{MPARAM_IN_HBITMAP, &hbmp, 0, NULL, 0, 1},
|
|
|
|
#define CPROXY_PARAM_HICON_IN(hicon) \
|
|
{MPARAM_IN_HICON, &hicon, 0, NULL, 0, 1},
|
|
|
|
#define CPROXY_PARAM_TF_LBBALLOONINFO_OUT(p) \
|
|
{MPARAM_OUT_TF_LBBALLOONINFO, (void *)p, 0, NULL, sizeof(*p), 1},
|
|
|
|
#define CPROXY_PARAM_STRUCT_IN(s) \
|
|
{MPARAM_IN_STRUCT, &s, 0, NULL, sizeof(s), 1},
|
|
|
|
#define CPROXY_PARAM_CALL(uMethodId) \
|
|
}; \
|
|
return proxy_Param(uMethodId, ARRAYSIZE(param), param);
|
|
|
|
#define CPROXY_PARAM_CALL_NOPARAM(x) return proxy_Param(x, 0, NULL);
|
|
|
|
typedef struct {
|
|
DWORD dwFlags;
|
|
void *pv;
|
|
ULONG ul;
|
|
const IID *piid;
|
|
ULONG cbUnitSize;
|
|
ULONG ulCount; // if this is array, the number of unit.
|
|
|
|
ULONG GetBufSize() {return cbUnitSize * ulCount;}
|
|
} CPROXY_PARAM;
|
|
|
|
|
|
class CProxy : public CSysThreadRef
|
|
{
|
|
public:
|
|
CProxy(SYSTHREAD *psfn);
|
|
virtual ~CProxy();
|
|
|
|
ULONG InternalAddRef();
|
|
ULONG InternalRelease();
|
|
void Init(REFIID riid,
|
|
ULONG ulProxyId,
|
|
ULONG ulIdStubId,
|
|
DWORD dwStubTime,
|
|
DWORD dwStubThreadId,
|
|
DWORD dwCurThreadId,
|
|
DWORD dwCurProcessId);
|
|
|
|
//
|
|
// IRpcChannelBuffer
|
|
//
|
|
HRESULT SendReceive( MARSHALMSG *pMsg , ULONG ulBlockId);
|
|
ULONG GetStubId() {return _ulStubId;}
|
|
DWORD GetStubThreadId() {return _dwStubThreadId;}
|
|
|
|
|
|
protected:
|
|
HRESULT proxy_Param(ULONG ulMethodId, ULONG ulParamNum, CPROXY_PARAM *pProsyParam);
|
|
|
|
|
|
protected:
|
|
IID _iid; // interface id for this proxy.
|
|
ULONG _cRef;
|
|
|
|
private:
|
|
CThreadMarshalWnd _tmw;
|
|
ULONG _ulProxyId; // unique proxy id in src thread.
|
|
ULONG _ulStubId; // unique stub id in stub thread.
|
|
DWORD _dwStubTime; // stub created time stamp.
|
|
DWORD _dwStubThreadId; // stub thread id.
|
|
DWORD _dwSrcThreadId; // src thread id.
|
|
DWORD _dwSrcProcessId; // src process id.
|
|
|
|
#ifdef DEBUG
|
|
BOOL _fInLoop;
|
|
#endif
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CMarshalInterfaceFileMapping
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
class CMarshalInterfaceFileMapping : public CCicFileMapping
|
|
{
|
|
public:
|
|
CMarshalInterfaceFileMapping(DWORD dwThreadId, ULONG ulStubId, ULONG ulStubTime) : CCicFileMapping()
|
|
{
|
|
if (SetName2(szFileMap, ARRAYSIZE(szFileMap), SZMARSHALINTERFACEFILEMAP, dwThreadId, ulStubId, ulStubTime))
|
|
_pszFile = szFileMap;
|
|
}
|
|
|
|
private:
|
|
char szFileMap[MAX_PATH];
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CStub
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define CSTUB_PARAM_START() CPROXY_PARAM param[] = {
|
|
|
|
#define CSTUB_PARAM_ULONG_IN(ul) \
|
|
{MPARAM_IN_ULONG, NULL, ul, NULL, 0 /*sizeof(ULONG)*/, 1},
|
|
|
|
#define CSTUB_PARAM_POINTER_IN(p) \
|
|
{MPARAM_IN_POINTER, (void *)(p), 0, NULL, 0 /*sizeof(*p)*/, 1},
|
|
|
|
#define CSTUB_PARAM_POINTER_ARRAY_IN(p, nCnt) \
|
|
{MPARAM_IN_POINTER, (void *)(p), 0, NULL, 0 /*sizeof(*p)*/, nCnt},
|
|
|
|
#define CSTUB_PARAM_INTERFACE_IN(p, iid) \
|
|
{MPARAM_IN_INTERFACE, p, 0, &iid, 0 /*sizeof(void *)*/, 1},
|
|
|
|
#define CSTUB_PARAM_INTERFACE_ARRAY_IN(p, iid, cnt) \
|
|
{MPARAM_IN_INTERFACE, p, 0, &iid, 0 /*sizeof(void *)*/, cnt},
|
|
|
|
#define CSTUB_PARAM_POINTER_OUT(p) \
|
|
{MPARAM_OUT_POINTER, p, 0, NULL, sizeof(*p), 1},
|
|
|
|
#define CSTUB_PARAM_POINTER_ARRAY_OUT(p, nCnt) \
|
|
{MPARAM_OUT_POINTER, p, 0, NULL, sizeof(*p), nCnt},
|
|
|
|
#define CSTUB_PARAM_INTERFACE_OUT(p, iid) \
|
|
{MPARAM_OUT_INTERFACE, p, 0, &iid, sizeof(void *), 1},
|
|
|
|
#define CSTUB_PARAM_INTERFACE_ARRAY_OUT(p, iid, cnt) \
|
|
{MPARAM_OUT_INTERFACE, p, 0, &iid, sizeof(void *), cnt},
|
|
|
|
#define CSTUB_PARAM_BSTR_OUT(p) \
|
|
{MPARAM_OUT_BSTR, p, 0, NULL, 0, 1},
|
|
|
|
#define CSTUB_PARAM_HBITMAP_OUT(p) \
|
|
{MPARAM_OUT_HBITMAP, p, 0, NULL, 0, 1},
|
|
|
|
#define CSTUB_PARAM_HICON_OUT(p) \
|
|
{MPARAM_OUT_HICON, p, 0, NULL, 0, 1},
|
|
|
|
#define CSTUB_PARAM_TF_LBBALLOONINFO_OUT(p) \
|
|
{MPARAM_OUT_TF_LBBALLOONINFO, (void *)p, 0, NULL, sizeof(*p), 1},
|
|
|
|
#define CSTUB_PARAM_HBITMAP_IN(hbmp) \
|
|
{MPARAM_IN_HBITMAP, &hbmp, 0, NULL, 0, 1},
|
|
|
|
#define CSTUB_PARAM_HICON_IN(hicon) \
|
|
{MPARAM_IN_HICON, &hicon, 0, NULL, 0, 1},
|
|
|
|
|
|
#define CSTUB_PARAM_END() \
|
|
};
|
|
|
|
#define CSTUB_PARAM_INTERFACE_OUT_RELEASE(p) \
|
|
if (p) ((IUnknown *)p)->Release();
|
|
|
|
#define CSTUB_PARAM_INTERFACE_ARRAY_OUT_RELEASE(p, ulCnt) \
|
|
for (ULONG __ul = 0; __ul < ulCnt; __ul++) \
|
|
if (p[__ul]) ((IUnknown *)p[__ul])->Release();
|
|
|
|
|
|
#define CSTUB_PARAM_CALL(pMsg, hrRet, psb) \
|
|
stub_OutParam(_this, pMsg, pMsg->ulMethodId, ARRAYSIZE(param), param, psb); \
|
|
pMsg->hrRet = hrRet;
|
|
|
|
#define CSTUB_PARAM_RETURN() \
|
|
return S_OK;
|
|
|
|
#define CSTUB_NOT_IMPL() \
|
|
Assert(0); \
|
|
return S_OK;
|
|
class CStub
|
|
{
|
|
public:
|
|
CStub();
|
|
virtual ~CStub();
|
|
ULONG _AddRef();
|
|
ULONG _Release();
|
|
ULONG GetStubId() {return _ulStubId;}
|
|
virtual HRESULT Invoke(MARSHALMSG *pMsg, CSharedBlock *psb) = 0;
|
|
|
|
void ClearFileMap()
|
|
{
|
|
if (_pfm)
|
|
{
|
|
_pfm->Close();
|
|
delete _pfm;
|
|
_pfm = NULL;
|
|
}
|
|
}
|
|
|
|
static HRESULT stub_OutParam(CStub *_this,
|
|
MARSHALMSG *pMsg,
|
|
ULONG ulMethodId,
|
|
ULONG ulParamNum,
|
|
CPROXY_PARAM *pProxyParam,
|
|
CSharedBlock *psb);
|
|
|
|
CMarshalInterfaceFileMapping *_pfm;
|
|
|
|
IID _iid; // interface id for this stub.
|
|
IUnknown *_punk; // actual object.
|
|
ULONG _ulStubId; // unique stubid of this thread.
|
|
DWORD _dwStubTime; // stub created time stamp.
|
|
DWORD _dwStubThreadId; // stub thread id.
|
|
DWORD _dwStubProcessId; // stub process id.
|
|
DWORD _dwSrcThreadId; // src thread id.
|
|
|
|
BOOL _fNoRemoveInDtor; // this stub has been removed from list.
|
|
// so don't try at dtor.
|
|
ULONG _cRef;
|
|
};
|
|
|
|
#endif // MARSHAL_H
|