// // 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