ORPC. , , . , ORPC- . (custom marshaling). , (custom proxies), . IMarshal:
[uuid(00000003-0000-0000-C000-000000000046), local, object] interface IMarshal : IUnknown { // get CLSID for custom proxy (CoMarshalInterface) // CLSID (CoMarshalInterface) HRESULT GetUnmarshalClass( [in] REFIID riid, [in, iid_is(riid) ] void *pv, [in] DWORD dwDestCtx, [in] void *pvDestCtx, [in] DWORD mshlflags, [out] CLSID *pclsid); // get size of custom marshaled objref (CoGetMarshalSizeMax) // (CoGetMarshalSizeMax) HRESULT GetMarshalSizeMax( [in] REFIID riid, [in, iid_is(riid)] void *pv, [in] DWORD dwDestCtx, [in] void *pvDestCtx, [in] DWORD mshlflags, [out] DWORD *pSize); // write out custom marshaled objref (CoMarshalInterface) // (CoMarshalInterface) HRESULT MarshalInterface([in] IStream *pStm, [in] REFIID riid, [in, iid_is(riid)] void *pv, [in] DWORD dwDestCtx, [in] void *pvDestCtx, [in] DWORD mshlflags); // read objref and return proxy (CoUnmarshalInterface) // // ( CoUnmarshalInterface) HRESULT UnmarshalInterface([in] IStream *pStm, [in] REFIID riid, [out, iid_is(riid)] void **ppv); // revoke a marshal (CoReleaseMarshalData) // (CoReleaseMarshalData) HRESULT ReleaseMarshalData([in] IStream *pStm); // tear down connection-state (CoDisconnectObject) // (CoDisconnectObject) HRESULT DisconnectObject([in] DWORD dwReserved); }
, , , API- .
CoMarshalInterface , , ( , . 5.7. , MEOW CLSID, , . CoMarshalInterface CLSID IMarshal::GetUnmarshal lass. CoMarshalInterface , IMarshal::MarshalInterface . MarshalInterface , .
CoUnmarshalInterface IMarshal::UnmarshalInterface. , , IMarshal. MarshalInterface . UnmarshalInterface . UnmarshalInterface , / . . , . , .
, . , , . - . . , . , , , , , IMarshal , . IMarshal , .
CoGetStandardMarshal:
HRESULT CoGetStandardMarshal( [in] REFIID riid, // type of itf marshaled? // , ? [in, iid_is(riid)] IUnknown *pUnk, // the itf to marshal // [in] DWORD dwDestCtx, // MSHCTX [in] void *pvDestCtx, // reserved // [in] DWORD mshlflags, // normal vs. table // [out] IMarshal **ppMarshal); // ptr to std. Marshal //
, , , . GetMarshalSizeMax :
STDMETHODIMP CustStd::GetMarshalSizeMax( ULONG *pcb, REFIID riid, void *pv, DWORD dwDestCtx, void *pvDestCtx, DWORD mshlflags) { // if context is supported, do work! // , ! if (dwDestCtx == MSHCTX_LOCAL || dwDestCtx == MSHCTX_INPROC) return this->MyCustomMarshalingRoutine(pcb); // unsupported context, delegate to std marshal // , IMarshal *pMsh = 0; HRESULT hr = CoGetStandardMarshal (riid, pv, dwDestCtx, pvDestCtx, mshlflags, &pMsh); if (SUCCEEDED(hr)) { hr = pMsh->GetMarshalSizeMax(pcb, riid, pv, dwDestCtx, pvDestCtx, mshlflags); pMsh->Retease(); } return hr; }
, , . , IMarshal ( (custom) ). , , , IMarshal . , IMarshal (marshal-by-value).
, . , , . . . . , . , , ( ) , CLSID , .
- :
class Point : public IPoint, public IMarshal { long m_x; long m_y; public: Point(void) : m_x(0), m_y(0) {} IMPLEMENT_UNKNOWN (Point) BEGIN_INTERFACE_TABLE(Point) IMPLEMENTS_INTERFACE(IPoint) IMPLEMENTS_INTERFACE(IMarshal) END_INTERFACE_TABLE() // IPoint methods // IPoint // IMarshal methods // IMarshal };
MarshalInterface :
STOMETHODIMP Point::MarshalInterface(IStream *pStm, REFIID, void *, DWORD, void *, DWORD) { // write out endian header // DWORD dw = OxFF669900; HRESULT hr = pStm->Write(&dw, sizeof(DWORD), 0); if (FAILED(hr)) return hr; dw = m_x; hr = pStm->Write(&dw, sizeof(DWORD), 0); if (FAILED(hr)) return hr; dw = m_y; return pStm->Write(&dw, sizeof (DWORD), 0); }
, , , GetUnmarshalClass:
STDMETHODIMP Point::GetUnmarshalClass(REFIID, void *, DWORD, void *, DWORD, CLSID *pclsid) { *pclsid = CLSID_Point; // this class's CLSID // CLSID return hr; }
, , GetMarshalSizeMax :
STDMETHODIMP Point::GetMarshalSizeMax(REFIID, void *, DWORD, void *, DWORD, DWORD *pcb) { *pcb = 3 * sizeof (DWORD); // m_x + m_y + header return hr; }
CoUnmarshalInterface, , , . CLSID , GetUnmarshalClass. , UnmarshalInterface , MarshalInterface:
STDMETHODIMP Point::UnmarshalInterface(IStream *pStm, REFIID riid, void ** ppv) { *ppv = 0; // read endian header // DWORD dw; ULONG cbRead; HRESULT hr = pStm->Read(&dw, sizeof (DWORD), &cbRead); if (FAILED(hr) || cbRead != sizeof(DWORD)) return RPC_E_INVALID_DATA; bool bSwapEndian = dw == 0x009966FF; // read m_x and m_y // m_x m_y hr = pStm->Read(&dw, sizeof(DWORD), &cbRead); m_x = dw; if (FAILED(hr) || cbRead != sizeof(DWORD)) return RPC_E_INVALID_DATA; hr = pStm->Read(&dw, sizeof(DWORD), &cbRead); m_y = dw; if (FAILED(hr)) || cbRead != sizeof(DWORD)) return RPC_E_INVALID_DATA; // byte swap members if necessary // , if (bSwapEndian) byteswapdata(&m_x, &m_y); // return pointer to this object // return this->QueryInterface(riid, ppv); }
, MarshalInterface UnmarshalInterface , . , .
UnmarshalInterface . , , . UnmarshalInterface , , , . , .