2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 #include "wine/orpc.h"
20 #include "wine/heap.h"
21 #include "wine/list.h"
23 extern HINSTANCE hProxyDll
;
29 LONG refs
; /* refcount of the apartment (LOCK) */
30 BOOL multi_threaded
; /* multi-threaded or single-threaded apartment? (RO) */
31 DWORD tid
; /* thread id (RO) */
32 OXID oxid
; /* object exporter ID (RO) */
33 LONG ipidc
; /* interface pointer ID counter, starts at 1 (LOCK) */
34 CRITICAL_SECTION cs
; /* thread safety */
35 struct list proxies
; /* imported objects (CS cs) */
36 struct list stubmgrs
; /* stub managers for exported objects (CS cs) */
37 BOOL remunk_exported
; /* has the IRemUnknown interface for this apartment been created yet? (CS cs) */
38 LONG remoting_started
; /* has the RPC system been started for this apartment? (LOCK) */
39 struct list loaded_dlls
; /* list of dlls loaded by this apartment (CS cs) */
40 DWORD host_apt_tid
; /* thread ID of apartment hosting objects of differing threading model (CS cs) */
41 HWND host_apt_hwnd
; /* handle to apartment window of host apartment (CS cs) */
42 struct local_server
*local_server
; /* A marshallable object exposing local servers (CS cs) */
43 BOOL being_destroyed
; /* is currently being destroyed */
45 /* FIXME: OIDs should be given out by RPCSS */
46 OID oidc
; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */
49 HWND win
; /* message window (LOCK) */
50 IMessageFilter
*filter
; /* message filter (CS cs) */
51 BOOL main
; /* is this a main-threaded-apartment? (RO) */
54 struct list usage_cookies
; /* Used for refcount control with CoIncrementMTAUsage()/CoDecrementMTAUsage(). */
57 HRESULT
open_key_for_clsid(REFCLSID clsid
, const WCHAR
*keyname
, REGSAM access
, HKEY
*subkey
) DECLSPEC_HIDDEN
;
58 HRESULT
open_appidkey_from_clsid(REFCLSID clsid
, REGSAM access
, HKEY
*subkey
) DECLSPEC_HIDDEN
;
60 /* DCOM messages used by the apartment window (not compatible with native) */
61 #define DM_EXECUTERPC (WM_USER + 0) /* WPARAM = 0, LPARAM = (struct dispatch_params *) */
62 #define DM_HOSTOBJECT (WM_USER + 1) /* WPARAM = 0, LPARAM = (struct host_object_params *) */
64 #define CHARS_IN_GUID 39
68 OLETLS_UUIDINITIALIZED
= 0x2,
69 OLETLS_DISABLE_OLE1DDE
= 0x40,
70 OLETLS_APARTMENTTHREADED
= 0x80,
71 OLETLS_MULTITHREADED
= 0x100,
74 /* this is what is stored in TEB->ReservedForOle */
77 struct apartment
*apt
;
78 IErrorInfo
*errorinfo
;
79 DWORD thread_seqid
; /* returned with CoGetCurrentProcess */
80 DWORD flags
; /* tlsdata_flags (+0Ch on x86) */
82 DWORD inits
; /* number of times CoInitializeEx called */
83 DWORD ole_inits
; /* number of times OleInitialize called */
84 GUID causality_id
; /* unique identifier for each COM call */
85 LONG pending_call_count_client
; /* number of client calls pending */
86 LONG pending_call_count_server
; /* number of server calls pending */
88 IObjContext
*context_token
; /* (+38h on x86) */
89 IUnknown
*call_state
; /* current call context (+3Ch on x86) */
91 IUnknown
*cancel_object
; /* cancel object set by CoSetCancelObject (+F8h on x86) */
92 IUnknown
*state
; /* see CoSetState */
93 struct list spies
; /* Spies installed with CoRegisterInitializeSpy */
98 extern HRESULT WINAPI
InternalTlsAllocData(struct tlsdata
**data
);
100 static inline HRESULT
com_get_tlsdata(struct tlsdata
**data
)
102 *data
= NtCurrentTeb()->ReservedForOle
;
103 return *data
? S_OK
: InternalTlsAllocData(data
);
106 static inline struct apartment
* com_get_current_apt(void)
108 struct tlsdata
*tlsdata
= NULL
;
109 com_get_tlsdata(&tlsdata
);
113 HWND
apartment_getwindow(const struct apartment
*apt
) DECLSPEC_HIDDEN
;
114 HRESULT
apartment_createwindowifneeded(struct apartment
*apt
) DECLSPEC_HIDDEN
;
115 void apartment_freeunusedlibraries(struct apartment
*apt
, DWORD unload_delay
) DECLSPEC_HIDDEN
;
116 void apartment_global_cleanup(void) DECLSPEC_HIDDEN
;
117 OXID
apartment_getoxid(const struct apartment
*apt
) DECLSPEC_HIDDEN
;
118 HRESULT
apartment_disconnectproxies(struct apartment
*apt
) DECLSPEC_HIDDEN
;
120 /* RpcSs interface */
121 HRESULT
rpcss_get_next_seqid(DWORD
*id
) DECLSPEC_HIDDEN
;
122 HRESULT
rpc_get_local_class_object(REFCLSID rclsid
, REFIID riid
, void **obj
) DECLSPEC_HIDDEN
;
123 HRESULT
rpc_register_local_server(REFCLSID clsid
, IStream
*stream
, DWORD flags
, unsigned int *cookie
) DECLSPEC_HIDDEN
;
124 HRESULT
rpc_revoke_local_server(unsigned int cookie
) DECLSPEC_HIDDEN
;
125 HRESULT
rpc_create_clientchannel(const OXID
*oxid
, const IPID
*ipid
, const OXID_INFO
*oxid_info
, const IID
*iid
,
126 DWORD dest_context
, void *dest_context_data
, IRpcChannelBuffer
**chan
, struct apartment
*apt
) DECLSPEC_HIDDEN
;
127 HRESULT
rpc_create_serverchannel(DWORD dest_context
, void *dest_context_data
, IRpcChannelBuffer
**chan
) DECLSPEC_HIDDEN
;
128 HRESULT
rpc_register_interface(REFIID riid
) DECLSPEC_HIDDEN
;
129 void rpc_unregister_interface(REFIID riid
, BOOL wait
) DECLSPEC_HIDDEN
;
130 HRESULT
rpc_resolve_oxid(OXID oxid
, OXID_INFO
*oxid_info
) DECLSPEC_HIDDEN
;
131 void rpc_start_remoting(struct apartment
*apt
) DECLSPEC_HIDDEN
;
132 HRESULT
rpc_register_channel_hook(REFGUID rguid
, IChannelHook
*hook
) DECLSPEC_HIDDEN
;
133 void rpc_unregister_channel_hooks(void) DECLSPEC_HIDDEN
;
135 struct dispatch_params
;
136 void rpc_execute_call(struct dispatch_params
*params
);
138 enum class_reg_data_origin
144 struct class_reg_data
146 enum class_reg_data_origin origin
;
151 const WCHAR
*module_name
;
152 DWORD threading_model
;
159 HRESULT
enter_apartment(struct tlsdata
*data
, DWORD model
) DECLSPEC_HIDDEN
;
160 void leave_apartment(struct tlsdata
*data
) DECLSPEC_HIDDEN
;
161 void apartment_release(struct apartment
*apt
) DECLSPEC_HIDDEN
;
162 struct apartment
* apartment_get_current_or_mta(void) DECLSPEC_HIDDEN
;
163 HRESULT
apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE
*cookie
) DECLSPEC_HIDDEN
;
164 void apartment_decrement_mta_usage(CO_MTA_USAGE_COOKIE cookie
) DECLSPEC_HIDDEN
;
165 struct apartment
* apartment_get_mta(void) DECLSPEC_HIDDEN
;
166 HRESULT
apartment_get_inproc_class_object(struct apartment
*apt
, const struct class_reg_data
*regdata
,
167 REFCLSID rclsid
, REFIID riid
, DWORD class_context
, void **ppv
) DECLSPEC_HIDDEN
;
168 HRESULT
apartment_get_local_server_stream(struct apartment
*apt
, IStream
**ret
) DECLSPEC_HIDDEN
;
169 IUnknown
*com_get_registered_class_object(const struct apartment
*apartment
, REFCLSID rclsid
,
170 DWORD clscontext
) DECLSPEC_HIDDEN
;
171 void apartment_revoke_all_classes(const struct apartment
*apt
) DECLSPEC_HIDDEN
;
172 struct apartment
* apartment_findfromoxid(OXID oxid
) DECLSPEC_HIDDEN
;
173 struct apartment
* apartment_findfromtid(DWORD tid
) DECLSPEC_HIDDEN
;
175 HRESULT
marshal_object(struct apartment
*apt
, STDOBJREF
*stdobjref
, REFIID riid
, IUnknown
*object
,
176 DWORD dest_context
, void *dest_context_data
, MSHLFLAGS mshlflags
) DECLSPEC_HIDDEN
;
180 /* signal to stub manager that this is a rem unknown object */
181 #define MSHLFLAGSP_REMUNKNOWN 0x80000000
183 /* Thread-safety Annotation Legend:
185 * RO - The value is read only. It never changes after creation, so no
186 * locking is required.
187 * LOCK - The value is written to only using Interlocked* functions.
188 * CS - The value is read or written to inside a critical section.
189 * The identifier following "CS" is the specific critical section that
191 * MUTEX - The value is read or written to with a mutex held.
192 * The identifier following "MUTEX" is the specific mutex that
196 typedef enum ifstub_state
198 STUBSTATE_NORMAL_MARSHALED
,
199 STUBSTATE_NORMAL_UNMARSHALED
,
200 STUBSTATE_TABLE_WEAK_MARSHALED
,
201 STUBSTATE_TABLE_WEAK_UNMARSHALED
,
202 STUBSTATE_TABLE_STRONG
,
205 /* an interface stub */
208 struct list entry
; /* entry in stub_manager->ifstubs list (CS stub_manager->lock) */
209 IRpcStubBuffer
*stubbuffer
; /* RO */
212 IUnknown
*iface
; /* RO */
213 MSHLFLAGS flags
; /* so we can enforce process-local marshalling rules (RO) */
214 IRpcChannelBuffer
*chan
; /* channel passed to IRpcStubBuffer::Invoke (RO) */
217 /* stub managers hold refs on the object and each interface stub */
220 struct list entry
; /* entry in apartment stubmgr list (CS apt->cs) */
221 struct list ifstubs
; /* list of active ifstubs for the object (CS lock) */
222 CRITICAL_SECTION lock
;
223 struct apartment
*apt
; /* owning apt (RO) */
225 ULONG extrefs
; /* number of 'external' references (CS lock) */
226 ULONG refs
; /* internal reference count (CS apt->cs) */
227 ULONG weakrefs
; /* number of weak references (CS lock) */
228 OID oid
; /* apartment-scoped unique identifier (RO) */
229 IUnknown
*object
; /* the object we are managing the stub for (RO) */
230 ULONG next_ipid
; /* currently unused (LOCK) */
231 OXID_INFO oxid_info
; /* string binding, ipid of rem unknown and other information (RO) */
233 IExternalConnection
*extern_conn
;
235 /* We need to keep a count of the outstanding marshals, so we can enforce the
236 * marshalling rules (ie, you can only unmarshal normal marshals once). Note
237 * that these counts do NOT include unmarshalled interfaces, once a stream is
238 * unmarshalled and a proxy set up, this count is decremented.
241 ULONG norm_refs
; /* refcount of normal marshals (CS lock) */
242 BOOL disconnected
; /* CoDisconnectObject has been called (CS lock) */
245 ULONG
stub_manager_int_release(struct stub_manager
*stub_manager
) DECLSPEC_HIDDEN
;
246 struct stub_manager
* get_stub_manager_from_object(struct apartment
*apt
, IUnknown
*object
, BOOL alloc
) DECLSPEC_HIDDEN
;
247 void stub_manager_disconnect(struct stub_manager
*m
) DECLSPEC_HIDDEN
;
248 ULONG
stub_manager_ext_addref(struct stub_manager
*m
, ULONG refs
, BOOL tableweak
) DECLSPEC_HIDDEN
;
249 ULONG
stub_manager_ext_release(struct stub_manager
*m
, ULONG refs
, BOOL tableweak
, BOOL last_unlock_releases
) DECLSPEC_HIDDEN
;
250 struct stub_manager
* get_stub_manager(struct apartment
*apt
, OID oid
) DECLSPEC_HIDDEN
;
251 void stub_manager_release_marshal_data(struct stub_manager
*m
, ULONG refs
, const IPID
*ipid
, BOOL tableweak
) DECLSPEC_HIDDEN
;
252 BOOL
stub_manager_is_table_marshaled(struct stub_manager
*m
, const IPID
*ipid
) DECLSPEC_HIDDEN
;
253 BOOL
stub_manager_notify_unmarshal(struct stub_manager
*m
, const IPID
*ipid
) DECLSPEC_HIDDEN
;
254 struct ifstub
* stub_manager_find_ifstub(struct stub_manager
*m
, REFIID iid
, MSHLFLAGS flags
) DECLSPEC_HIDDEN
;
255 struct ifstub
* stub_manager_new_ifstub(struct stub_manager
*m
, IRpcStubBuffer
*sb
, REFIID iid
, DWORD dest_context
,
256 void *dest_context_data
, MSHLFLAGS flags
) DECLSPEC_HIDDEN
;
257 HRESULT
ipid_get_dispatch_params(const IPID
*ipid
, struct apartment
**stub_apt
,
258 struct stub_manager
**manager
, IRpcStubBuffer
**stub
, IRpcChannelBuffer
**chan
,
259 IID
*iid
, IUnknown
**iface
) DECLSPEC_HIDDEN
;
260 HRESULT
start_apartment_remote_unknown(struct apartment
*apt
) DECLSPEC_HIDDEN
;