From 552cc7d5b35cc3499eb3517b3831ddadec53d0f3 Mon Sep 17 00:00:00 2001 From: Robert Shearman Date: Tue, 15 Feb 2005 15:44:25 +0000 Subject: [PATCH] - Remove cruft left over from previous RPC backend implementation in the apartment structure. - Don't pass an IPID by value for proxy_manager_create_ifproxy. - Disable more of RPC_UnregisterInterface to prevent the RPC runtime using freed memory. - Rename various external RPC backend functions so that they all have the same "RPC_" prefix. - Reduce the timeout of the function that connects to a local server to 30s, like native. --- dlls/ole32/compobj.c | 6 +---- dlls/ole32/compobj_private.h | 47 +++++++++++++----------------------- dlls/ole32/marshal.c | 19 ++++++--------- dlls/ole32/rpc.c | 36 +++++++++++++-------------- 4 files changed, 42 insertions(+), 66 deletions(-) diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index bf75c1ec4f7..6e2c9f27fb1 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -245,8 +245,6 @@ static APARTMENT *apartment_construct(DWORD model) apt->oxid = ((OXID)GetCurrentProcessId() << 32) | 0xcafe; } - apt->shutdown_event = CreateEventW(NULL, TRUE, FALSE, NULL); - TRACE("Created apartment on OXID %s\n", wine_dbgstr_longlong(apt->oxid)); /* the locking here is not currently needed for the MTA case, but it @@ -350,8 +348,6 @@ DWORD COM_ApartmentRelease(struct apartment *apt) if (apt->filter) IUnknown_Release(apt->filter); DeleteCriticalSection(&apt->cs); - SetEvent(apt->shutdown_event); - CloseHandle(apt->shutdown_event); CloseHandle(apt->thread); HeapFree(GetProcessHeap(), 0, apt); } @@ -1630,7 +1626,7 @@ HRESULT WINAPI CoGetClassObject( /* Next try out of process */ if (CLSCTX_LOCAL_SERVER & dwClsContext) { - return create_marshalled_proxy(rclsid,iid,ppv); + return RPC_GetLocalClassObject(rclsid,iid,ppv); } /* Finally try remote: this requires networked DCOM (a lot of work) */ diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h index 870a1800a13..4704b3f936f 100644 --- a/dlls/ole32/compobj_private.h +++ b/dlls/ole32/compobj_private.h @@ -130,11 +130,10 @@ struct apartment struct list proxies; /* imported objects (CS cs) */ struct list stubmgrs; /* stub managers for exported objects (CS cs) */ BOOL remunk_exported; /* has the IRemUnknown interface for this apartment been created yet? (CS cs) */ + LONG remoting_started; /* has the RPC system been started for this apartment? (LOCK) */ - /* FIXME: These should all be removed long term as they leak information that should be encapsulated */ + /* FIXME: OID's should be given out by RPCSS */ OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */ - DWORD listenertid; /* id of apartment_listener_thread */ - HANDLE shutdown_event; /* event used to tell the client_dispatch_thread to shut down */ }; /* this is what is stored in TEB->ReservedForOle */ @@ -146,37 +145,23 @@ struct oletls DWORD inits; /* number of times CoInitializeEx called */ }; + +/* Global Interface Table Functions */ + extern void* StdGlobalInterfaceTable_Construct(void); extern void StdGlobalInterfaceTable_Destroy(void* self); extern HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv); +extern void* StdGlobalInterfaceTableInstance; /* FIXME: these shouldn't be needed, except for 16-bit functions */ extern HRESULT WINE_StringFromCLSID(const CLSID *id,LPSTR idstr); HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id); -extern HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv); - -extern void* StdGlobalInterfaceTableInstance; - -/* Standard Marshalling definitions */ -typedef struct _wine_marshal_id { - OXID oxid; /* id of apartment */ - OID oid; /* id of stub manager */ - IPID ipid; /* id of interface pointer */ -} wine_marshal_id; - -inline static BOOL -MARSHAL_Compare_Mids(wine_marshal_id *mid1,wine_marshal_id *mid2) { - return - (mid1->oxid == mid2->oxid) && - (mid1->oid == mid2->oid) && - IsEqualGUID(&(mid1->ipid),&(mid2->ipid)) - ; -} - HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt); HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv); +/* Stub Manager */ + ULONG stub_manager_int_addref(struct stub_manager *This); ULONG stub_manager_int_release(struct stub_manager *This); struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object); @@ -193,15 +178,15 @@ HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt); HRESULT start_apartment_remote_unknown(void); -IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid); +/* RPC Backend */ -void start_apartment_listener_thread(void); - -HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **pipebuf); +void RPC_StartRemoting(struct apartment *apt); +HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **pipebuf); HRESULT RPC_ExecuteCall(RPCOLEMESSAGE *msg, IRpcStubBuffer *stub); HRESULT RPC_RegisterInterface(REFIID riid); -void RPC_UnregisterInterface(REFIID riid); -void RPC_StartLocalServer(REFCLSID clsid, IStream *stream); +void RPC_UnregisterInterface(REFIID riid); +void RPC_StartLocalServer(REFCLSID clsid, IStream *stream); +HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv); /* This function initialize the Running Object Table */ HRESULT WINAPI RunningObjectTableImpl_Initialize(void); @@ -212,7 +197,9 @@ HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void); /* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */ int WINAPI FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable); -/* compobj.c */ + +/* Apartment Functions */ + APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref); APARTMENT *COM_ApartmentFromTID(DWORD tid); DWORD COM_ApartmentAddRef(struct apartment *apt); diff --git a/dlls/ole32/marshal.c b/dlls/ole32/marshal.c index bcc54d861de..6492594ba4e 100644 --- a/dlls/ole32/marshal.c +++ b/dlls/ole32/marshal.c @@ -476,7 +476,7 @@ static HRESULT proxy_manager_query_local_interface(struct proxy_manager * This, } static HRESULT proxy_manager_create_ifproxy( - struct proxy_manager * This, IPID ipid, REFIID riid, ULONG cPublicRefs, + struct proxy_manager * This, const IPID *ipid, REFIID riid, ULONG cPublicRefs, struct ifproxy ** iif_out) { HRESULT hr; @@ -487,7 +487,7 @@ static HRESULT proxy_manager_create_ifproxy( list_init(&ifproxy->entry); ifproxy->parent = This; - ifproxy->ipid = ipid; + ifproxy->ipid = *ipid; ifproxy->iid = *riid; ifproxy->refs = cPublicRefs; ifproxy->proxy = NULL; @@ -535,7 +535,7 @@ static HRESULT proxy_manager_create_ifproxy( *iif_out = ifproxy; TRACE("ifproxy %p created for IPID %s, interface %s with %lu public refs\n", - ifproxy, debugstr_guid(&ipid), debugstr_guid(riid), cPublicRefs); + ifproxy, debugstr_guid(ipid), debugstr_guid(riid), cPublicRefs); } else ifproxy_destroy(ifproxy); @@ -795,8 +795,8 @@ StdMarshalImpl_MarshalInterface( return CO_E_NOTINITIALIZED; } - start_apartment_listener_thread(); /* just to be sure we have one running. */ - start_apartment_remote_unknown(); + /* make sure this apartment can be reached from other threads / processes */ + RPC_StartRemoting(apt); hres = IUnknown_QueryInterface((LPUNKNOWN)pv, riid, (LPVOID*)&pUnk); if (hres != S_OK) @@ -843,13 +843,8 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI if (!find_proxy_manager(apt, stdobjref->oxid, stdobjref->oid, &proxy_manager)) { IRpcChannelBuffer *chanbuf; - wine_marshal_id mid; - mid.oxid = stdobjref->oxid; - mid.oid = stdobjref->oid; - mid.ipid = stdobjref->ipid; - - hr = PIPE_GetNewPipeBuf(&mid,&chanbuf); + hr = RPC_CreateClientChannel(&stdobjref->oxid, &stdobjref->ipid, &chanbuf); if (hr == S_OK) hr = proxy_manager_construct(apt, stdobjref->flags, stdobjref->oxid, stdobjref->oid, @@ -863,7 +858,7 @@ static HRESULT unmarshal_object(const STDOBJREF *stdobjref, APARTMENT *apt, REFI struct ifproxy * ifproxy; hr = proxy_manager_find_ifproxy(proxy_manager, riid, &ifproxy); if (hr == E_NOINTERFACE) - hr = proxy_manager_create_ifproxy(proxy_manager, stdobjref->ipid, + hr = proxy_manager_create_ifproxy(proxy_manager, &stdobjref->ipid, riid, stdobjref->cPublicRefs, &ifproxy); diff --git a/dlls/ole32/rpc.c b/dlls/ole32/rpc.c index 523f74230c1..1fb178176e9 100644 --- a/dlls/ole32/rpc.c +++ b/dlls/ole32/rpc.c @@ -280,8 +280,7 @@ static const IRpcChannelBufferVtbl ServerRpcChannelBufferVtbl = }; /* returns a channel buffer for proxies */ -/* FIXME: needs renaming and mid removing */ -HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **chan) +HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **chan) { ClientRpcChannelBuffer *This; WCHAR endpoint[200]; @@ -290,7 +289,7 @@ HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **chan) LPWSTR string_binding; /* connect to the apartment listener thread */ - get_rpc_endpoint(endpoint, &mid->oxid); + get_rpc_endpoint(endpoint, oxid); TRACE("proxy pipe: connecting to endpoint: %s\n", debugstr_w(endpoint)); @@ -308,7 +307,8 @@ HRESULT PIPE_GetNewPipeBuf(wine_marshal_id *mid, IRpcChannelBuffer **chan) if (status == RPC_S_OK) { - status = RpcBindingSetObject(bind, &mid->ipid); + IPID ipid2 = *ipid; /* why can't RpcBindingSetObject take a const? */ + status = RpcBindingSetObject(bind, &ipid2); if (status != RPC_S_OK) RpcBindingFree(&bind); } @@ -459,9 +459,9 @@ void RPC_UnregisterInterface(REFIID riid) #if 0 /* this is a stub in builtin and spams the console with FIXME's */ IID iid = *riid; /* RpcServerUnregisterIf doesn't take const IID */ RpcServerUnregisterIf((RPC_IF_HANDLE)&rif->If, &iid, 0); -#endif list_remove(&rif->entry); HeapFree(GetProcessHeap(), 0, rif); +#endif } break; } @@ -469,12 +469,11 @@ void RPC_UnregisterInterface(REFIID riid) LeaveCriticalSection(&csRegIf); } -/* FIXME: needs renaming */ -void start_apartment_listener_thread() +/* make the apartment reachable by other threads and processes and create the + * IRemUnknown object */ +void RPC_StartRemoting(struct apartment *apt) { - APARTMENT *apt = COM_CurrentApt(); /* FIXME: pass as parameter */ - - if (!apt->listenertid) + if (!InterlockedExchange(&apt->remoting_started, TRUE)) { WCHAR endpoint[200]; RPC_STATUS status; @@ -488,13 +487,14 @@ void start_apartment_listener_thread() NULL); if (status != RPC_S_OK) ERR("Couldn't register endpoint %s\n", debugstr_w(endpoint)); - apt->listenertid = TRUE; /* FIXME: don't abuse this field and use remunk_exported, by moving remunk exporting into this function */ + + /* FIXME: move remote unknown exporting into this function */ } + start_apartment_remote_unknown(); } -static HRESULT -create_server(REFCLSID rclsid) +static HRESULT create_server(REFCLSID rclsid) { static const WCHAR embedding[] = { ' ', '-','E','m','b','e','d','d','i','n','g',0 }; HKEY key; @@ -548,8 +548,7 @@ create_server(REFCLSID rclsid) /* * start_local_service() - start a service given its name and parameters */ -static DWORD -start_local_service(LPCWSTR name, DWORD num, LPWSTR *params) +static DWORD start_local_service(LPCWSTR name, DWORD num, LPWSTR *params) { SC_HANDLE handle, hsvc; DWORD r = ERROR_FUNCTION_FAILED; @@ -586,8 +585,7 @@ start_local_service(LPCWSTR name, DWORD num, LPWSTR *params) * * Note: Local Services are not supported under Windows 9x */ -static HRESULT -create_local_service(REFCLSID rclsid) +static HRESULT create_local_service(REFCLSID rclsid) { HRESULT hres = REGDB_E_READREGDB; WCHAR buf[40], keyname[50]; @@ -655,7 +653,7 @@ create_local_service(REFCLSID rclsid) #define PIPEPREF "\\\\.\\pipe\\" /* FIXME: should call to rpcss instead */ -HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) +HRESULT RPC_GetLocalClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) { HRESULT hres; HANDLE hPipe; @@ -667,7 +665,7 @@ HRESULT create_marshalled_proxy(REFCLSID rclsid, REFIID iid, LPVOID *ppv) ULARGE_INTEGER newpos; int tries = 0; - static const int MAXTRIES = 10000; + static const int MAXTRIES = 30; /* 30 seconds */ TRACE("rclsid=%s, iid=%s\n", debugstr_guid(rclsid), debugstr_guid(iid));