diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 4ac93ff545d..e1ffdc82539 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -146,7 +146,7 @@ @ stdcall CoRegisterPSClsid(ptr ptr) @ stdcall CoRegisterSurrogate(ptr) ole32.CoRegisterSurrogate @ stdcall CoRegisterSurrogateEx(ptr ptr) ole32.CoRegisterSurrogateEx -@ stdcall CoReleaseMarshalData(ptr) ole32.CoReleaseMarshalData +@ stdcall CoReleaseMarshalData(ptr) @ stdcall CoReleaseServerProcess() @ stdcall CoResumeClassObjects() ole32.CoResumeClassObjects @ stub CoRetireServer diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h index 898d42b3c7b..cc1c3d34388 100644 --- a/dlls/combase/combase_private.h +++ b/dlls/combase/combase_private.h @@ -222,3 +222,5 @@ struct stub_manager * WINAPI get_stub_manager_from_object(struct apartment *apt, void stub_manager_disconnect(struct stub_manager *m) DECLSPEC_HIDDEN; ULONG WINAPI stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) DECLSPEC_HIDDEN; ULONG WINAPI stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) DECLSPEC_HIDDEN; +struct stub_manager * WINAPI get_stub_manager(struct apartment *apt, OID oid); +void WINAPI stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak); diff --git a/dlls/combase/marshal.c b/dlls/combase/marshal.c index db5089f013e..bfe31ff17dd 100644 --- a/dlls/combase/marshal.c +++ b/dlls/combase/marshal.c @@ -29,6 +29,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); +/* private flag indicating that the object was marshaled as table-weak */ +#define SORFP_TABLEWEAK SORF_OXRES1 + struct ftmarshaler { IUnknown IUnknown_inner; @@ -507,3 +510,141 @@ cleanup: return hr; } + +/* Creates an IMarshal* object according to the data marshaled to the stream. + * The function leaves the stream pointer at the start of the data written + * to the stream by the IMarshal* object. + */ +static HRESULT get_unmarshaler_from_stream(IStream *stream, IMarshal **marshal, IID *iid) +{ + OBJREF objref; + HRESULT hr; + ULONG res; + + /* read common OBJREF header */ + hr = IStream_Read(stream, &objref, FIELD_OFFSET(OBJREF, u_objref), &res); + if (hr != S_OK || (res != FIELD_OFFSET(OBJREF, u_objref))) + { + ERR("Failed to read common OBJREF header, 0x%08x\n", hr); + return STG_E_READFAULT; + } + + /* sanity check on header */ + if (objref.signature != OBJREF_SIGNATURE) + { + ERR("Bad OBJREF signature 0x%08x\n", objref.signature); + return RPC_E_INVALID_OBJREF; + } + + if (iid) *iid = objref.iid; + + /* FIXME: handler marshaling */ + if (objref.flags & OBJREF_STANDARD) + { + TRACE("Using standard unmarshaling\n"); + *marshal = NULL; + return S_FALSE; + } + else if (objref.flags & OBJREF_CUSTOM) + { + ULONG custom_header_size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData) - + FIELD_OFFSET(OBJREF, u_objref.u_custom); + TRACE("Using custom unmarshaling\n"); + /* read constant sized OR_CUSTOM data from stream */ + hr = IStream_Read(stream, &objref.u_objref.u_custom, + custom_header_size, &res); + if (hr != S_OK || (res != custom_header_size)) + { + ERR("Failed to read OR_CUSTOM header, 0x%08x\n", hr); + return STG_E_READFAULT; + } + /* now create the marshaler specified in the stream */ + hr = CoCreateInstance(&objref.u_objref.u_custom.clsid, NULL, + CLSCTX_INPROC_SERVER, &IID_IMarshal, + (LPVOID*)marshal); + } + else + { + FIXME("Invalid or unimplemented marshaling type specified: %x\n", + objref.flags); + return RPC_E_INVALID_OBJREF; + } + + if (hr != S_OK) + ERR("Failed to create marshal, 0x%08x\n", hr); + + return hr; +} + +static HRESULT std_release_marshal_data(IStream *stream) +{ + struct stub_manager *stubmgr; + struct OR_STANDARD obj; + struct apartment *apt; + ULONG res; + HRESULT hr; + + hr = IStream_Read(stream, &obj, FIELD_OFFSET(struct OR_STANDARD, saResAddr.aStringArray), &res); + if (hr != S_OK) return STG_E_READFAULT; + + if (obj.saResAddr.wNumEntries) + { + ERR("unsupported size of DUALSTRINGARRAY\n"); + return E_NOTIMPL; + } + + TRACE("oxid = %s, oid = %s, ipid = %s\n", wine_dbgstr_longlong(obj.std.oxid), + wine_dbgstr_longlong(obj.std.oid), wine_dbgstr_guid(&obj.std.ipid)); + + if (!(apt = apartment_findfromoxid(obj.std.oxid))) + { + WARN("Could not map OXID %s to apartment object\n", + wine_dbgstr_longlong(obj.std.oxid)); + return RPC_E_INVALID_OBJREF; + } + + if (!(stubmgr = get_stub_manager(apt, obj.std.oid))) + { + apartment_release(apt); + ERR("could not map object ID to stub manager, oxid=%s, oid=%s\n", + wine_dbgstr_longlong(obj.std.oxid), wine_dbgstr_longlong(obj.std.oid)); + return RPC_E_INVALID_OBJREF; + } + + stub_manager_release_marshal_data(stubmgr, obj.std.cPublicRefs, &obj.std.ipid, obj.std.flags & SORFP_TABLEWEAK); + + stub_manager_int_release(stubmgr); + apartment_release(apt); + + return S_OK; +} + +/*********************************************************************** + * CoReleaseMarshalData (combase.@) + */ +HRESULT WINAPI CoReleaseMarshalData(IStream *stream) +{ + IMarshal *marshal; + HRESULT hr; + + TRACE("%p\n", stream); + + hr = get_unmarshaler_from_stream(stream, &marshal, NULL); + if (hr == S_FALSE) + { + hr = std_release_marshal_data(stream); + if (hr != S_OK) + ERR("StdMarshal ReleaseMarshalData failed with error %#x\n", hr); + return hr; + } + if (hr != S_OK) + return hr; + + /* call the helper object to do the releasing of marshal data */ + hr = IMarshal_ReleaseMarshalData(marshal, stream); + if (hr != S_OK) + ERR("IMarshal::ReleaseMarshalData failed with error %#x\n", hr); + + IMarshal_Release(marshal); + return hr; +} diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c index 87017dbc922..e462c9ffd48 100644 --- a/dlls/ole32/marshal.c +++ b/dlls/ole32/marshal.c @@ -1837,56 +1837,6 @@ HRESULT WINAPI CoUnmarshalInterface(IStream *pStream, REFIID riid, LPVOID *ppv) return hr; } -/*********************************************************************** - * CoReleaseMarshalData [OLE32.@] - * - * Releases resources associated with an object that has been marshaled into - * a stream. - * - * PARAMS - * - * pStream [I] The stream that the object has been marshaled into. - * - * RETURNS - * Success: S_OK. - * Failure: HRESULT error code. - * - * NOTES - * - * Call this function to release resources associated with a normal or - * table-weak marshal that will not be unmarshaled, and all table-strong - * marshals when they are no longer needed. - * - * SEE ALSO - * CoMarshalInterface(), CoUnmarshalInterface(). - */ -HRESULT WINAPI CoReleaseMarshalData(IStream *pStream) -{ - HRESULT hr; - LPMARSHAL pMarshal; - - TRACE("(%p)\n", pStream); - - hr = get_unmarshaler_from_stream(pStream, &pMarshal, NULL); - if (hr == S_FALSE) - { - hr = std_release_marshal_data(pStream); - if (hr != S_OK) - ERR("StdMarshal ReleaseMarshalData failed with error 0x%08x\n", hr); - return hr; - } - if (hr != S_OK) - return hr; - - /* call the helper object to do the releasing of marshal data */ - hr = IMarshal_ReleaseMarshalData(pMarshal, pStream); - if (hr != S_OK) - ERR("IMarshal::ReleaseMarshalData failed with error 0x%08x\n", hr); - - IMarshal_Release(pMarshal); - return hr; -} - static HRESULT WINAPI StdMarshalCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppv) { diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 972629ecb70..2ecfcf6b510 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -72,7 +72,7 @@ @ stdcall CoRegisterPSClsid(ptr ptr) combase.CoRegisterPSClsid @ stdcall CoRegisterSurrogate(ptr) @ stdcall CoRegisterSurrogateEx(ptr ptr) -@ stdcall CoReleaseMarshalData(ptr) +@ stdcall CoReleaseMarshalData(ptr) combase.CoReleaseMarshalData @ stdcall CoReleaseServerProcess() combase.CoReleaseServerProcess @ stdcall CoResumeClassObjects() @ stdcall CoRevertToSelf() combase.CoRevertToSelf