combase_private.h 12.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

17
#include "winternl.h"
18
#include "wine/orpc.h"
19

20
#include "wine/heap.h"
21 22
#include "wine/list.h"

23 24
extern HINSTANCE hProxyDll;

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
struct apartment
{
    struct list entry;

    LONG  refs;              /* refcount of the apartment (LOCK) */
    BOOL multi_threaded;     /* multi-threaded or single-threaded apartment? (RO) */
    DWORD tid;               /* thread id (RO) */
    OXID oxid;               /* object exporter ID (RO) */
    LONG ipidc;              /* interface pointer ID counter, starts at 1 (LOCK) */
    CRITICAL_SECTION cs;     /* thread safety */
    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) */
    struct list loaded_dlls; /* list of dlls loaded by this apartment (CS cs) */
    DWORD host_apt_tid;      /* thread ID of apartment hosting objects of differing threading model (CS cs) */
    HWND host_apt_hwnd;      /* handle to apartment window of host apartment (CS cs) */
    struct local_server *local_server; /* A marshallable object exposing local servers (CS cs) */
    BOOL being_destroyed;    /* is currently being destroyed */

    /* FIXME: OIDs should be given out by RPCSS */
    OID oidc;                /* object ID counter, starts at 1, zero is invalid OID (CS cs) */

    /* STA-only fields */
    HWND win;                /* message window (LOCK) */
    IMessageFilter *filter;  /* message filter (CS cs) */
    BOOL main;               /* is this a main-threaded-apartment? (RO) */

    /* MTA-only */
    struct list usage_cookies; /* Used for refcount control with CoIncrementMTAUsage()/CoDecrementMTAUsage(). */
};
56

57 58 59
HRESULT open_key_for_clsid(REFCLSID clsid, const WCHAR *keyname, REGSAM access, HKEY *subkey) DECLSPEC_HIDDEN;
HRESULT open_appidkey_from_clsid(REFCLSID clsid, REGSAM access, HKEY *subkey) DECLSPEC_HIDDEN;

60 61 62 63
/* DCOM messages used by the apartment window (not compatible with native) */
#define DM_EXECUTERPC   (WM_USER + 0) /* WPARAM = 0, LPARAM = (struct dispatch_params *) */
#define DM_HOSTOBJECT   (WM_USER + 1) /* WPARAM = 0, LPARAM = (struct host_object_params *) */

64 65
#define CHARS_IN_GUID 39

66 67 68
enum tlsdata_flags
{
    OLETLS_UUIDINITIALIZED = 0x2,
69 70 71
    OLETLS_DISABLE_OLE1DDE = 0x40,
    OLETLS_APARTMENTTHREADED = 0x80,
    OLETLS_MULTITHREADED = 0x100,
72 73
};

74 75 76 77 78
/* this is what is stored in TEB->ReservedForOle */
struct tlsdata
{
    struct apartment *apt;
    IErrorInfo       *errorinfo;
79 80
    DWORD             thread_seqid;  /* returned with CoGetCurrentProcess */
    DWORD             flags;         /* tlsdata_flags (+0Ch on x86) */
81
    void             *unknown0;
82 83 84
    DWORD             inits;         /* number of times CoInitializeEx called */
    DWORD             ole_inits;     /* number of times OleInitialize called */
    GUID              causality_id;  /* unique identifier for each COM call */
85 86 87 88 89 90 91 92 93 94
    LONG              pending_call_count_client; /* number of client calls pending */
    LONG              pending_call_count_server; /* number of server calls pending */
    DWORD             unknown;
    IObjContext      *context_token; /* (+38h on x86) */
    IUnknown         *call_state;    /* current call context (+3Ch on x86) */
    DWORD             unknown2[46];
    IUnknown         *cancel_object; /* cancel object set by CoSetCancelObject (+F8h on x86) */
    IUnknown         *state;         /* see CoSetState */
    struct list       spies;         /* Spies installed with CoRegisterInitializeSpy */
    DWORD             spies_lock;
95
    DWORD             cancelcount;
96
};
97 98 99 100 101 102 103 104

extern HRESULT WINAPI InternalTlsAllocData(struct tlsdata **data);

static inline HRESULT com_get_tlsdata(struct tlsdata **data)
{
    *data = NtCurrentTeb()->ReservedForOle;
    return *data ? S_OK : InternalTlsAllocData(data);
}
105 106 107 108 109 110 111

static inline struct apartment* com_get_current_apt(void)
{
    struct tlsdata *tlsdata = NULL;
    com_get_tlsdata(&tlsdata);
    return tlsdata->apt;
}
112

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;
119

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 124
HRESULT rpc_register_local_server(REFCLSID clsid, IStream *stream, DWORD flags, unsigned int *cookie) DECLSPEC_HIDDEN;
HRESULT rpc_revoke_local_server(unsigned int cookie) DECLSPEC_HIDDEN;
125 126 127 128 129 130 131 132 133 134 135 136
HRESULT rpc_create_clientchannel(const OXID *oxid, const IPID *ipid, const OXID_INFO *oxid_info, const IID *iid,
        DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan, struct apartment *apt) DECLSPEC_HIDDEN;
HRESULT rpc_create_serverchannel(DWORD dest_context, void *dest_context_data, IRpcChannelBuffer **chan) DECLSPEC_HIDDEN;
HRESULT rpc_register_interface(REFIID riid) DECLSPEC_HIDDEN;
void rpc_unregister_interface(REFIID riid, BOOL wait) DECLSPEC_HIDDEN;
HRESULT rpc_resolve_oxid(OXID oxid, OXID_INFO *oxid_info) DECLSPEC_HIDDEN;
void rpc_start_remoting(struct apartment *apt) DECLSPEC_HIDDEN;
HRESULT rpc_register_channel_hook(REFGUID rguid, IChannelHook *hook) DECLSPEC_HIDDEN;
void rpc_unregister_channel_hooks(void) DECLSPEC_HIDDEN;

struct dispatch_params;
void rpc_execute_call(struct dispatch_params *params);
137

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
enum class_reg_data_origin
{
    CLASS_REG_ACTCTX,
    CLASS_REG_REGISTRY,
};

struct class_reg_data
{
    enum class_reg_data_origin origin;
    union
    {
        struct
        {
            const WCHAR *module_name;
            DWORD threading_model;
            HANDLE hactctx;
        } actctx;
        HKEY hkey;
    } u;
};

159 160 161 162
HRESULT enter_apartment(struct tlsdata *data, DWORD model) DECLSPEC_HIDDEN;
void leave_apartment(struct tlsdata *data) DECLSPEC_HIDDEN;
void apartment_release(struct apartment *apt) DECLSPEC_HIDDEN;
struct apartment * apartment_get_current_or_mta(void) DECLSPEC_HIDDEN;
163 164
HRESULT apartment_increment_mta_usage(CO_MTA_USAGE_COOKIE *cookie) DECLSPEC_HIDDEN;
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 169 170 171
HRESULT apartment_get_local_server_stream(struct apartment *apt, IStream **ret) DECLSPEC_HIDDEN;
IUnknown *com_get_registered_class_object(const struct apartment *apartment, REFCLSID rclsid,
        DWORD clscontext) DECLSPEC_HIDDEN;
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;
174

175 176 177
HRESULT marshal_object(struct apartment *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *object,
        DWORD dest_context, void *dest_context_data, MSHLFLAGS mshlflags) DECLSPEC_HIDDEN;

178 179
/* Stub Manager */

180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
/* signal to stub manager that this is a rem unknown object */
#define MSHLFLAGSP_REMUNKNOWN   0x80000000

/* Thread-safety Annotation Legend:
 *
 * RO    - The value is read only. It never changes after creation, so no
 *         locking is required.
 * LOCK  - The value is written to only using Interlocked* functions.
 * CS    - The value is read or written to inside a critical section.
 *         The identifier following "CS" is the specific critical section that
 *         must be used.
 * MUTEX - The value is read or written to with a mutex held.
 *         The identifier following "MUTEX" is the specific mutex that
 *         must be used.
 */

typedef enum ifstub_state
{
    STUBSTATE_NORMAL_MARSHALED,
    STUBSTATE_NORMAL_UNMARSHALED,
    STUBSTATE_TABLE_WEAK_MARSHALED,
    STUBSTATE_TABLE_WEAK_UNMARSHALED,
    STUBSTATE_TABLE_STRONG,
} STUB_STATE;

/* an interface stub */
struct ifstub
{
    struct list       entry;      /* entry in stub_manager->ifstubs list (CS stub_manager->lock) */
    IRpcStubBuffer   *stubbuffer; /* RO */
    IID               iid;        /* RO */
    IPID              ipid;       /* RO */
    IUnknown         *iface;      /* RO */
    MSHLFLAGS         flags;      /* so we can enforce process-local marshalling rules (RO) */
    IRpcChannelBuffer*chan;       /* channel passed to IRpcStubBuffer::Invoke (RO) */
};

/* stub managers hold refs on the object and each interface stub */
struct stub_manager
{
    struct list       entry;      /* entry in apartment stubmgr list (CS apt->cs) */
    struct list       ifstubs;    /* list of active ifstubs for the object (CS lock) */
    CRITICAL_SECTION  lock;
    struct apartment *apt;        /* owning apt (RO) */

    ULONG             extrefs;    /* number of 'external' references (CS lock) */
    ULONG             refs;       /* internal reference count (CS apt->cs) */
    ULONG             weakrefs;   /* number of weak references (CS lock) */
    OID               oid;        /* apartment-scoped unique identifier (RO) */
    IUnknown         *object;     /* the object we are managing the stub for (RO) */
    ULONG             next_ipid;  /* currently unused (LOCK) */
    OXID_INFO         oxid_info;  /* string binding, ipid of rem unknown and other information (RO) */

    IExternalConnection *extern_conn;

    /* We need to keep a count of the outstanding marshals, so we can enforce the
     * marshalling rules (ie, you can only unmarshal normal marshals once). Note
     * that these counts do NOT include unmarshalled interfaces, once a stream is
     * unmarshalled and a proxy set up, this count is decremented.
     */

    ULONG             norm_refs;  /* refcount of normal marshals (CS lock) */
    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 249 250 251 252 253 254 255 256
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs, BOOL tableweak) DECLSPEC_HIDDEN;
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs, BOOL tableweak, BOOL last_unlock_releases) DECLSPEC_HIDDEN;
struct stub_manager * get_stub_manager(struct apartment *apt, OID oid) DECLSPEC_HIDDEN;
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs, const IPID *ipid, BOOL tableweak) DECLSPEC_HIDDEN;
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN;
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid) DECLSPEC_HIDDEN;
struct ifstub * stub_manager_find_ifstub(struct stub_manager *m, REFIID iid, MSHLFLAGS flags) DECLSPEC_HIDDEN;
struct ifstub * stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, REFIID iid, DWORD dest_context,
    void *dest_context_data, MSHLFLAGS flags) DECLSPEC_HIDDEN;
257 258 259 260
HRESULT ipid_get_dispatch_params(const IPID *ipid, struct apartment **stub_apt,
        struct stub_manager **manager, IRpcStubBuffer **stub, IRpcChannelBuffer **chan,
        IID *iid, IUnknown **iface) DECLSPEC_HIDDEN;
HRESULT start_apartment_remote_unknown(struct apartment *apt) DECLSPEC_HIDDEN;