mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
Sync to Wine-20050211
Robert Shearman <rob@codeweavers.com> - Add documentation for most Co* functions. - Move several functions into different files to group them with similar functions. - Implement CoDisconnectObject. - Change CoLockObjectExternal so that it does the correct action now and eliminate a fair few lines of now redundant code. - Rename OLE32_Dll{Register,Unregister}Server to Dll{Register,Unregister}Server. - Move OLE automation interface registration to oleaut32. - Add IRemUnknown to list of interfaces to register. - Make proxy manager use IMultiQI instead of IInternalUnknown as tests show that IInternalUnknown isn't exposed. - Implement IMultiQI on top of IRemUnknown calls. - Silence some fixmes that occur during tests and don't give us any useful information. - Fix typo in class factory proxy that caused us to use the wrong offset into the CFProxy structure, causing us to not call the outer_unknown properly. - Use InterlockedIncrement for the ipid counter instead of a critical section (suggested by Mike Hearn). - Remove a line added by a bad merge. - Implement RemUnkStub_Disconnect. - Remove all of the RPC disconnect code. - Implement IRemUnknown. - Use IRemUnknown for life-cycle management instead of the current hacks. - Generate machine-local IPIDs. - Make pipes be uniquely identified only by their IPID. - Implement table marshaling. - The apartment reference should be held while the stub manager reference is held. - Fix same apartment-unmarshal detection. - Proxies/stubs for IRemUnknown methods, based on code written by Ove Ksven. - Initialize ppv pointer in ClientIdentity_QueryInterface to NULL as apps depend on this. - Don't release IRpcProxyBuffer on ifproxy destruction - the caller will do this for us. - Make find_proxy_manager add a reference to the proxy manager and make proxy_manager_construct return an object with a valid ref-count. - Remove stray not operator to fix a memory leak / crash in proxy_manager_destroy. - More debug messages, especially on errors. - Fix ref-count leak in the Class Factory proxy. - Add a test case for IClassFactory_CreateInstance. - Split up apartment creation so that the long code paths that don't need locking no longer have locking. - Add special cases for the threads that join apartments but can't increase the refcount of the apartment. - Free TLS storage on thread destruction (including releasing the apartment the thread is in, if any, and so making another test pass). - More tests. - Change return code of CoGetPSClsid to match test result. - Do a slight hack to make IRemUnknown proxies be added after the proxy that uses them to stop them being used after they are destroyed. - Fix multiple local server connections. - The apartment reference should be held while the stub manager reference is held. - Fix same apartment-unmarshal detection. - Don't use the pipe caching code because it doesn't work correctly at the moment. - Always write disconnect reply packet, even in failure cases. - Move object-to-stub-manager mapping rule to register_ifstub. - Pass the original IID to IMarshal_UnmarshalInterface and query for the requested interface. - Unmarshaling IID_NULL means use the IID the interface was originally marshaled with. - Add code for destroying the thread-local storage data, but don't use it yet. - Don't release apartment on changing modes because we didn't add a reference anywhere. - Quieten the RPC_E_DISCONNECTED error message as it is an expected return code. - Treat IID_NULL the same as IID_IUnknown. - Make tests compile on Win95 again. - Fix copy+paste error where the test failure should be from the CoUnmarshalInterface function. - Give IUnknown its own ifstub to fix ref-counting and ipid storage issues. - Add a new flag SORFP_NOLIFETIMEMGMT to tell the proxy manager not to call any IRemUnknown functions. - Move the low-level unmarshaling code into a new function, unmarshal_object, so that it can be easily reused for unmarshaling IRemUnknown. - Consolidate more stub creation details into register_ifstub. - Replace the current wine_marshal_id structure with STDOBJREF for the on-the-wire format. - Initialize clsid member to the marshaler clsid to fix custom marshaling. - Make proxy shutdown test succeed by releasing the channel on disconnect. - Remove wine_marshal_data: it is unneeded and there is no equivalent in STDOBJREF. - Remove obsolete structs, rearrange things to group the structs together and to group similar functions. - Document thread-safety of members of structs. - Document CoSetState & CoGetState. - Rewrite them to only retrieve TLS info once. - Remove trailing whitespace in COM_CurrentInfo. - Release the client security objects when no longer needed (reported by Mike McCormack). - Implement CoSetProxyBlanket, CoQueryProxyBlanket and CoCopyProxy. - Update todo list. - Destroy stubs on apartment shutdown. - Make MTA dynamically allocated so that proxies and other resources are freed at the proper time. - Changed/removed some incorrect comments regarding apartments. Mike Hearn <mh@codeweavers.com> - Various formatting/style changes. - Force context switch on chanbuf disconnect to avoid a race in the test suite. Mike Hearn <mh@codeweavers.com> Robert Shearman <rob@codeweavers.com> - Rework RPC dispatch layer to be simpler and not get confused by server/client duality. - Make threads shut down at the right time and not access freed memory after apartment destruction. - Rename stub_dispatch_thread to client_dispatch_thread. - Add some more tracing - Check return value of WaitNamedPipe. - Change named pipe timeouts to 0.5s, which should be enough for even the slowest machines. Christian Costa <titan.costa@wanadoo.fr> - CoInitialize(Ex) should return S_FALSE when COM is already initialized for the current thread. svn path=/trunk/; revision=13532
This commit is contained in:
parent
4267da8a2f
commit
f4477fcb16
17 changed files with 2976 additions and 1710 deletions
|
@ -143,6 +143,18 @@ inline static void list_init( struct list *list )
|
|||
#define LIST_FOR_EACH(cursor,list) \
|
||||
for ((cursor) = (list)->next; (cursor) != (list); (cursor) = (cursor)->next)
|
||||
|
||||
/* iterate through the list, with safety against removal */
|
||||
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list) \
|
||||
for ((cursor) = (list)->next, (cursor2) = (cursor)->next; \
|
||||
(cursor) != (list); \
|
||||
(cursor) = (cursor2), (cursor2) = (cursor)->next)
|
||||
|
||||
/* iterate through the list using a list entry */
|
||||
#define LIST_FOR_EACH_ENTRY(elem, list, type, field) \
|
||||
for ((elem) = LIST_ENTRY((list)->next, type, field); \
|
||||
&(elem)->field != (list); \
|
||||
(elem) = LIST_ENTRY((elem)->field.next, type, field))
|
||||
|
||||
/* macros for statically initialized lists */
|
||||
#define LIST_INIT(list) { &(list), &(list) }
|
||||
|
||||
|
|
|
@ -984,6 +984,17 @@ DECLARE_INTERFACE_(IClientSecurity,IUnknown)
|
|||
};
|
||||
#undef INTERFACE
|
||||
|
||||
#ifdef COBJMACROS
|
||||
/*** IUnknown methods ***/
|
||||
#define IClientSecurity_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
||||
#define IClientSecurity_AddRef(p) (p)->lpVtbl->AddRef(p)
|
||||
#define IClientSecurity_Release(p) (p)->lpVtbl->Release(p)
|
||||
/*** IClientSecurity methods ***/
|
||||
#define IClientSecurity_QueryBlanket(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->QueryBlanket(p,a,b,c,d,e,f,g,h)
|
||||
#define IClientSecurity_SetBlanket(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->SetBlanket(p,a,b,c,d,e,f,g,h)
|
||||
#define IClientSecurity_CopyProxy(p,a,b) (p)->lpVtbl->CopyProxy(p,a,b)
|
||||
#endif
|
||||
|
||||
EXTERN_C const IID IID_IServerSecurity;
|
||||
#define INTERFACE IServerSecurity
|
||||
DECLARE_INTERFACE_(IServerSecurity,IUnknown)
|
||||
|
@ -2005,5 +2016,78 @@ struct IInternalUnknownVtbl {
|
|||
|
||||
#endif /* __IInternalUnknown_INTERFACE_DEFINED__ */
|
||||
|
||||
#ifndef __IMultiQI_FWD_DEFINED__
|
||||
#define __IMultiQI_FWD_DEFINED__
|
||||
typedef struct IMultiQI IMultiQI;
|
||||
#endif
|
||||
|
||||
typedef IMultiQI *LPMULTIQI;
|
||||
|
||||
/*****************************************************************************
|
||||
* IMultiQI interface
|
||||
*/
|
||||
#ifndef __IMultiQI_INTERFACE_DEFINED__
|
||||
#define __IMultiQI_INTERFACE_DEFINED__
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
struct IMultiQI : public IUnknown
|
||||
{
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryMultipleInterfaces(
|
||||
ULONG cMQIs,
|
||||
MULTI_QI* pMQIs) = 0;
|
||||
|
||||
};
|
||||
#else
|
||||
typedef struct IMultiQIVtbl IMultiQIVtbl;
|
||||
struct IMultiQI {
|
||||
const IMultiQIVtbl* lpVtbl;
|
||||
};
|
||||
struct IMultiQIVtbl {
|
||||
BEGIN_INTERFACE
|
||||
|
||||
/*** IUnknown methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
|
||||
IMultiQI* This,
|
||||
REFIID riid,
|
||||
void** ppvObject);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *AddRef)(
|
||||
IMultiQI* This);
|
||||
|
||||
ULONG (STDMETHODCALLTYPE *Release)(
|
||||
IMultiQI* This);
|
||||
|
||||
/*** IMultiQI methods ***/
|
||||
HRESULT (STDMETHODCALLTYPE *QueryMultipleInterfaces)(
|
||||
IMultiQI* This,
|
||||
ULONG cMQIs,
|
||||
MULTI_QI* pMQIs);
|
||||
|
||||
END_INTERFACE
|
||||
};
|
||||
|
||||
#ifdef COBJMACROS
|
||||
/*** IUnknown methods ***/
|
||||
#define IMultiQI_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b)
|
||||
#define IMultiQI_AddRef(p) (p)->lpVtbl->AddRef(p)
|
||||
#define IMultiQI_Release(p) (p)->lpVtbl->Release(p)
|
||||
/*** IMultiQI methods ***/
|
||||
#define IMultiQI_QueryMultipleInterfaces(p,a,b) (p)->lpVtbl->QueryMultipleInterfaces(p,a,b)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
HRESULT CALLBACK IMultiQI_QueryMultipleInterfaces_Proxy(
|
||||
IMultiQI* This,
|
||||
ULONG cMQIs,
|
||||
MULTI_QI* pMQIs);
|
||||
void __RPC_STUB IMultiQI_QueryMultipleInterfaces_Stub(
|
||||
struct IRpcStubBuffer* This,
|
||||
struct IRpcChannelBuffer* pRpcChannelBuffer,
|
||||
PRPC_MESSAGE pRpcMessage,
|
||||
DWORD* pdwStubPhase);
|
||||
|
||||
#endif /* __IMultiQI_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#endif /* __WINE_OBJIDL_H */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,7 +5,7 @@
|
|||
* Copyright 1999 Sylvain St-Germain
|
||||
* Copyright 2002 Marcus Meissner
|
||||
* Copyright 2003 Ove Kåven, TransGaming Technologies
|
||||
* Copyright 2004 Mike Hearn, CodeWeavers Inc
|
||||
* Copyright 2004 Mike Hearn, Rob Shearman, CodeWeavers Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -39,54 +39,78 @@
|
|||
#include "winternl.h"
|
||||
|
||||
struct apartment;
|
||||
typedef struct apartment APARTMENT;
|
||||
|
||||
/* 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 with a critical section held.
|
||||
* The identifier following "CS" is the specific critical section that
|
||||
* must be used.
|
||||
*/
|
||||
|
||||
typedef enum ifstub_state
|
||||
{
|
||||
IFSTUB_STATE_NORMAL_MARSHALED,
|
||||
IFSTUB_STATE_NORMAL_UNMARSHALED,
|
||||
IFSTUB_STATE_TABLE_MARSHALED
|
||||
} IFSTUB_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 */
|
||||
IFSTUB_STATE state; /* CS stub_manager->lock */
|
||||
};
|
||||
|
||||
|
||||
/* exported interface */
|
||||
typedef struct tagXIF {
|
||||
struct tagXIF *next;
|
||||
LPVOID iface; /* interface pointer */
|
||||
IID iid; /* interface ID */
|
||||
IPID ipid; /* exported interface ID */
|
||||
LPRPCSTUBBUFFER stub; /* interface stub */
|
||||
DWORD refs; /* external reference count */
|
||||
HRESULT hres; /* result of stub creation attempt */
|
||||
} XIF;
|
||||
/* 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;
|
||||
APARTMENT *apt; /* owning apt (RO) */
|
||||
|
||||
/* exported object */
|
||||
typedef struct tagXOBJECT {
|
||||
IRpcStubBufferVtbl *lpVtbl;
|
||||
struct apartment *parent;
|
||||
struct tagXOBJECT *next;
|
||||
LPUNKNOWN obj; /* object identity (IUnknown) */
|
||||
OID oid; /* object ID */
|
||||
DWORD ifc; /* interface ID counter */
|
||||
XIF *ifaces; /* exported interfaces */
|
||||
DWORD refs; /* external reference count */
|
||||
} XOBJECT;
|
||||
ULONG extrefs; /* number of 'external' references (LOCK) */
|
||||
ULONG refs; /* internal reference count (CS apt->cs) */
|
||||
OID oid; /* apartment-scoped unique identifier (RO) */
|
||||
IUnknown *object; /* the object we are managing the stub for (RO) */
|
||||
ULONG next_ipid; /* currently unused (LOCK) */
|
||||
};
|
||||
|
||||
/* imported interface proxy */
|
||||
struct ifproxy
|
||||
{
|
||||
struct list entry;
|
||||
LPVOID iface; /* interface pointer */
|
||||
IID iid; /* interface ID */
|
||||
IPID ipid; /* imported interface ID */
|
||||
LPRPCPROXYBUFFER proxy; /* interface proxy */
|
||||
DWORD refs; /* imported (public) references */
|
||||
struct list entry; /* entry in proxy_manager list (CS parent->cs) */
|
||||
struct proxy_manager *parent; /* owning proxy_manager (RO) */
|
||||
LPVOID iface; /* interface pointer (RO) */
|
||||
IID iid; /* interface ID (RO) */
|
||||
IPID ipid; /* imported interface ID (RO) */
|
||||
LPRPCPROXYBUFFER proxy; /* interface proxy (RO) */
|
||||
DWORD refs; /* imported (public) references (CS parent->cs) */
|
||||
};
|
||||
|
||||
/* imported object / proxy manager */
|
||||
struct proxy_manager
|
||||
{
|
||||
const IInternalUnknownVtbl *lpVtbl;
|
||||
struct apartment *parent;
|
||||
struct list entry;
|
||||
LPRPCCHANNELBUFFER chan; /* channel to object */
|
||||
OXID oxid; /* object exported ID */
|
||||
OID oid; /* object ID */
|
||||
struct list interfaces; /* imported interfaces */
|
||||
DWORD refs; /* proxy reference count */
|
||||
CRITICAL_SECTION cs; /* thread safety for this object and children */
|
||||
const IMultiQIVtbl *lpVtbl;
|
||||
struct apartment *parent; /* owning apartment (RO) */
|
||||
struct list entry; /* entry in apartment (CS parent->cs) */
|
||||
LPRPCCHANNELBUFFER chan; /* channel to object (CS cs) */
|
||||
OXID oxid; /* object exported ID (RO) */
|
||||
OID oid; /* object ID (RO) */
|
||||
struct list interfaces; /* imported interfaces (CS cs) */
|
||||
DWORD refs; /* proxy reference count (LOCK) */
|
||||
CRITICAL_SECTION cs; /* thread safety for this object and children */
|
||||
ULONG sorflags; /* STDOBJREF flags (RO) */
|
||||
IRemUnknown *remunk; /* proxy to IRemUnknown used for lifecycle management (CS cs) */
|
||||
};
|
||||
|
||||
/* this needs to become a COM object that implements IRemUnknown */
|
||||
|
@ -94,28 +118,42 @@ struct apartment
|
|||
{
|
||||
struct list entry;
|
||||
|
||||
DWORD refs; /* refcount of the apartment */
|
||||
DWORD model; /* threading model */
|
||||
DWORD tid; /* thread id */
|
||||
HANDLE thread; /* thread handle */
|
||||
OXID oxid; /* object exporter ID */
|
||||
OID oidc; /* object ID counter, starts at 1, zero is invalid OID */
|
||||
HWND win; /* message window */
|
||||
DWORD refs; /* refcount of the apartment (LOCK) */
|
||||
DWORD model; /* threading model (RO) */
|
||||
DWORD tid; /* thread id (RO) */
|
||||
HANDLE thread; /* thread handle (RO) */
|
||||
OXID oxid; /* object exporter ID (RO) */
|
||||
DWORD ipidc; /* interface pointer ID counter, starts at 1 (LOCK) */
|
||||
HWND win; /* message window (RO) */
|
||||
CRITICAL_SECTION cs; /* thread safety */
|
||||
LPMESSAGEFILTER filter; /* message filter */
|
||||
XOBJECT *objs; /* exported objects */
|
||||
struct list proxies; /* imported objects */
|
||||
LPMESSAGEFILTER filter; /* message filter (CS cs) */
|
||||
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) */
|
||||
|
||||
/* FIXME: These should all be removed long term as they leak information that should be encapsulated */
|
||||
OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */
|
||||
DWORD listenertid; /* id of apartment_listener_thread */
|
||||
struct list stubmgrs; /* stub managers for exported objects */
|
||||
HANDLE shutdown_event; /* event used to tell the client_dispatch_thread to shut down */
|
||||
};
|
||||
|
||||
typedef struct apartment APARTMENT;
|
||||
/* this is what is stored in TEB->ReservedForOle */
|
||||
struct oletls
|
||||
{
|
||||
struct apartment *apt;
|
||||
IErrorInfo *errorinfo; /* see errorinfo.c */
|
||||
IUnknown *state; /* see CoSetState */
|
||||
DWORD inits; /* number of times CoInitializeEx called */
|
||||
};
|
||||
|
||||
extern void* StdGlobalInterfaceTable_Construct(void);
|
||||
extern void StdGlobalInterfaceTable_Destroy(void* self);
|
||||
extern HRESULT StdGlobalInterfaceTable_GetFactory(LPVOID *ppv);
|
||||
|
||||
/* 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;
|
||||
|
@ -139,52 +177,21 @@ MARSHAL_Compare_Mids(wine_marshal_id *mid1,wine_marshal_id *mid2) {
|
|||
HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt);
|
||||
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
|
||||
|
||||
/* 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 with a critical section held.
|
||||
* The identifier following "CS" is the specific critical section that
|
||||
* must be used.
|
||||
*/
|
||||
|
||||
/* 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 */
|
||||
BOOL table; /* CS stub_manager->lock */
|
||||
};
|
||||
|
||||
|
||||
/* 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;
|
||||
APARTMENT *apt; /* owning apt (RO) */
|
||||
|
||||
ULONG extrefs; /* number of 'external' references (LOCK) */
|
||||
ULONG refs; /* internal reference count (CS apt->cs) */
|
||||
OID oid; /* apartment-scoped unique identifier (RO) */
|
||||
IUnknown *object; /* the object we are managing the stub for (RO) */
|
||||
ULONG next_ipid; /* currently unused (LOCK) */
|
||||
};
|
||||
|
||||
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);
|
||||
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs);
|
||||
ULONG stub_manager_ext_release(struct stub_manager *m, ULONG refs);
|
||||
IRpcStubBuffer *stub_manager_ipid_to_stubbuffer(struct stub_manager *m, const IPID *iid);
|
||||
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid, BOOL tablemarshal);
|
||||
struct stub_manager *get_stub_manager(OXID oxid, OID oid);
|
||||
struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object);
|
||||
struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid);
|
||||
struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object);
|
||||
void apartment_disconnect_object(APARTMENT *apt, void *object);
|
||||
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid);
|
||||
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid);
|
||||
HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags);
|
||||
HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret);
|
||||
IRpcStubBuffer *ipid_to_stubbuffer(const IPID *ipid);
|
||||
HRESULT start_apartment_remote_unknown(void);
|
||||
|
||||
IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid);
|
||||
|
||||
|
@ -202,23 +209,12 @@ 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);
|
||||
|
||||
HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id);
|
||||
|
||||
/* compobj.c */
|
||||
APARTMENT *COM_CreateApartment(DWORD model);
|
||||
APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref);
|
||||
APARTMENT *COM_ApartmentFromTID(DWORD tid);
|
||||
DWORD COM_ApartmentAddRef(struct apartment *apt);
|
||||
DWORD COM_ApartmentRelease(struct apartment *apt);
|
||||
|
||||
/* this is what is stored in TEB->ReservedForOle */
|
||||
struct oletls
|
||||
{
|
||||
struct apartment *apt;
|
||||
IErrorInfo *errorinfo; /* see errorinfo.c */
|
||||
IUnknown *state; /* see CoSetState */
|
||||
DWORD inits; /* number of times CoInitializeEx called */
|
||||
};
|
||||
|
||||
/*
|
||||
* Per-thread values are stored in the TEB on offset 0xF80,
|
||||
* see http://www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm
|
||||
|
@ -227,9 +223,9 @@ struct oletls
|
|||
/* will create if necessary */
|
||||
static inline struct oletls *COM_CurrentInfo(void)
|
||||
{
|
||||
if (!NtCurrentTeb()->ReservedForOle)
|
||||
if (!NtCurrentTeb()->ReservedForOle)
|
||||
NtCurrentTeb()->ReservedForOle = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct oletls));
|
||||
|
||||
|
||||
return NtCurrentTeb()->ReservedForOle;
|
||||
}
|
||||
|
||||
|
|
|
@ -527,8 +527,15 @@ static IMallocSpyVtbl VT_IMallocSpy =
|
|||
/******************************************************************************
|
||||
* CoGetMalloc [OLE32.@]
|
||||
*
|
||||
* Retrieves the current IMalloc interface for the process.
|
||||
*
|
||||
* PARAMS
|
||||
* dwMemContext [I]
|
||||
* lpMalloc [O] Address where memory allocator object will be stored.
|
||||
*
|
||||
* RETURNS
|
||||
* The win32 IMalloc
|
||||
* Success: S_OK.
|
||||
* Failure: HRESULT code.
|
||||
*/
|
||||
HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC *lpMalloc)
|
||||
{
|
||||
|
@ -538,15 +545,31 @@ HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC *lpMalloc)
|
|||
|
||||
/***********************************************************************
|
||||
* CoTaskMemAlloc [OLE32.@]
|
||||
*
|
||||
* Allocates memory using the current process memory allocator.
|
||||
*
|
||||
* PARAMS
|
||||
* size [I] Size of the memory block to allocate.
|
||||
*
|
||||
* RETURNS
|
||||
* pointer to newly allocated block
|
||||
* Success: Pointer to newly allocated memory block.
|
||||
* Failure: NULL.
|
||||
*/
|
||||
LPVOID WINAPI CoTaskMemAlloc(ULONG size)
|
||||
{
|
||||
return IMalloc_Alloc((LPMALLOC)&Malloc32,size);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CoTaskMemFree [OLE32.@]
|
||||
*
|
||||
* Frees memory allocated from the current process memory allocator.
|
||||
*
|
||||
* PARAMS
|
||||
* ptr [I] Memory block to free.
|
||||
*
|
||||
* RETURNS
|
||||
* Nothing.
|
||||
*/
|
||||
VOID WINAPI CoTaskMemFree(LPVOID ptr)
|
||||
{
|
||||
|
@ -555,8 +578,16 @@ VOID WINAPI CoTaskMemFree(LPVOID ptr)
|
|||
|
||||
/***********************************************************************
|
||||
* CoTaskMemRealloc [OLE32.@]
|
||||
*
|
||||
* Allocates memory using the current process memory allocator.
|
||||
*
|
||||
* PARAMS
|
||||
* pvOld [I] Pointer to old memory block.
|
||||
* size [I] Size of the new memory block.
|
||||
*
|
||||
* RETURNS
|
||||
* pointer to newly allocated block
|
||||
* Success: Pointer to newly allocated memory block.
|
||||
* Failure: NULL.
|
||||
*/
|
||||
LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, ULONG size)
|
||||
{
|
||||
|
@ -566,6 +597,16 @@ LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, ULONG size)
|
|||
/***********************************************************************
|
||||
* CoRegisterMallocSpy [OLE32.@]
|
||||
*
|
||||
* Registers an object that receives notifications on memory allocations and
|
||||
* frees.
|
||||
*
|
||||
* PARAMS
|
||||
* pMallocSpy [I] New spy object.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: S_OK.
|
||||
* Failure: HRESULT code.
|
||||
*
|
||||
* NOTES
|
||||
* if a mallocspy is already registered, we can't do it again since
|
||||
* only the spy knows, how to free a memory block
|
||||
|
@ -597,6 +638,16 @@ HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
|
|||
/***********************************************************************
|
||||
* CoRevokeMallocSpy [OLE32.@]
|
||||
*
|
||||
* Revokes a previousl registered object that receives notifications on memory
|
||||
* allocations and frees.
|
||||
*
|
||||
* PARAMS
|
||||
* pMallocSpy [I] New spy object.
|
||||
*
|
||||
* RETURNS
|
||||
* Success: S_OK.
|
||||
* Failure: HRESULT code.
|
||||
*
|
||||
* NOTES
|
||||
* we can't revoke a malloc spy as long as memory blocks allocated with
|
||||
* the spy are active since only the spy knows how to free them
|
||||
|
@ -629,12 +680,16 @@ HRESULT WINAPI CoRevokeMallocSpy(void)
|
|||
/******************************************************************************
|
||||
* IsValidInterface [OLE32.@]
|
||||
*
|
||||
* Determines whether a pointer is a valid interface.
|
||||
*
|
||||
* PARAMS
|
||||
* punk [I] Interface to be tested.
|
||||
*
|
||||
* RETURNS
|
||||
* True, if the passed pointer is a valid interface
|
||||
* TRUE, if the passed pointer is a valid interface, or FALSE otherwise.
|
||||
*/
|
||||
BOOL WINAPI IsValidInterface(
|
||||
LPUNKNOWN punk /* [in] interface to be tested */
|
||||
) {
|
||||
BOOL WINAPI IsValidInterface(LPUNKNOWN punk)
|
||||
{
|
||||
return !(
|
||||
IsBadReadPtr(punk,4) ||
|
||||
IsBadReadPtr(punk->lpVtbl,4) ||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -48,6 +48,7 @@
|
|||
#include "wine/wingdi16.h"
|
||||
#include "wine/winuser16.h"
|
||||
#include "ole32_main.h"
|
||||
#include "compobj_private.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -243,18 +244,6 @@ HRESULT WINAPI OleInitialize(LPVOID reserved)
|
|||
return hr;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* CoGetCurrentProcess [COMPOBJ.34]
|
||||
* CoGetCurrentProcess [OLE32.@]
|
||||
*
|
||||
* NOTES
|
||||
* Is DWORD really the correct return type for this function?
|
||||
*/
|
||||
DWORD WINAPI CoGetCurrentProcess(void)
|
||||
{
|
||||
return GetCurrentProcessId();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* OleUninitialize [OLE2.3]
|
||||
* OleUninitialize [OLE32.@]
|
||||
|
@ -300,20 +289,6 @@ void WINAPI OleUninitialize(void)
|
|||
CoUninitialize();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* CoRegisterMessageFilter [OLE32.@]
|
||||
*/
|
||||
HRESULT WINAPI CoRegisterMessageFilter(
|
||||
LPMESSAGEFILTER lpMessageFilter, /* [in] Pointer to interface */
|
||||
LPMESSAGEFILTER *lplpMessageFilter /* [out] Indirect pointer to prior instance if non-NULL */
|
||||
) {
|
||||
FIXME("stub\n");
|
||||
if (lplpMessageFilter) {
|
||||
*lplpMessageFilter = NULL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* OleInitializeWOW [OLE32.@]
|
||||
*/
|
||||
|
@ -2313,6 +2288,44 @@ HRESULT WINAPI OleCreate(
|
|||
return hres;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* OleSetAutoConvert [OLE32.@]
|
||||
*/
|
||||
/* FIXME: convert to Unicode */
|
||||
HRESULT WINAPI OleSetAutoConvert(REFCLSID clsidOld, REFCLSID clsidNew)
|
||||
{
|
||||
HKEY hkey = 0;
|
||||
char buf[200], szClsidNew[200];
|
||||
HRESULT res = S_OK;
|
||||
|
||||
TRACE("(%s,%s)\n", debugstr_guid(clsidOld), debugstr_guid(clsidNew));
|
||||
sprintf(buf,"CLSID\\");WINE_StringFromCLSID(clsidOld,&buf[6]);
|
||||
WINE_StringFromCLSID(clsidNew, szClsidNew);
|
||||
if (RegOpenKeyA(HKEY_CLASSES_ROOT,buf,&hkey))
|
||||
{
|
||||
res = REGDB_E_CLASSNOTREG;
|
||||
goto done;
|
||||
}
|
||||
if (RegSetValueA(hkey, "AutoConvertTo", REG_SZ, szClsidNew, strlen(szClsidNew)+1))
|
||||
{
|
||||
res = REGDB_E_WRITEREGDB;
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
if (hkey) RegCloseKey(hkey);
|
||||
return res;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* OleDoAutoConvert [OLE32.@]
|
||||
*/
|
||||
HRESULT WINAPI OleDoAutoConvert(IStorage *pStg, LPCLSID pClsidNew)
|
||||
{
|
||||
FIXME("(%p,%p) : stub\n",pStg,pClsidNew);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* OLE_FreeClipDataArray [internal]
|
||||
*
|
||||
|
|
|
@ -138,15 +138,6 @@ HRESULT WINAPI OleRegEnumFormatEtc (
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CoIsOle1Class [OLE32.@]
|
||||
*/
|
||||
BOOL WINAPI CoIsOle1Class(REFCLSID clsid)
|
||||
{
|
||||
FIXME("%s\n", debugstr_guid(clsid));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DllGetClassObject [OLE2.4]
|
||||
*/
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
@ stdcall CLSIDFromString(wstr ptr)
|
||||
@ stdcall CoAddRefServerProcess()
|
||||
@ stdcall CoBuildVersion()
|
||||
@ stub CoCopyProxy #@ stdcall (ptr ptr) return 0,ERR_NOTIMPLEMENTED
|
||||
@ stdcall CoCopyProxy(ptr ptr)
|
||||
@ stdcall CoCreateFreeThreadedMarshaler(ptr ptr)
|
||||
@ stdcall CoCreateGuid(ptr)
|
||||
@ stdcall CoCreateInstance(ptr ptr long ptr ptr)
|
||||
|
@ -49,7 +49,7 @@
|
|||
@ stdcall CoMarshalInterface(ptr ptr ptr long ptr long)
|
||||
@ stub CoQueryAuthenticationServices
|
||||
@ stub CoQueryClientBlanket
|
||||
@ stub CoQueryProxyBlanket
|
||||
@ stdcall CoQueryProxyBlanket(ptr ptr ptr ptr ptr ptr ptr ptr)
|
||||
@ stub CoQueryReleaseObject
|
||||
@ stub CoRegisterChannelHook
|
||||
@ stdcall CoRegisterClassObject(ptr ptr long long ptr)
|
||||
|
@ -63,7 +63,7 @@
|
|||
@ stub CoRevertToSelf #@ stdcall () return 0,ERR_NOTIMPLEMENTED
|
||||
@ stdcall CoRevokeClassObject(long)
|
||||
@ stdcall CoRevokeMallocSpy()
|
||||
@ stub CoSetProxyBlanket #@ stdcall (ptr long long wstr long long ptr long) return 0,ERR_NOTIMPLEMENTED
|
||||
@ stdcall CoSetProxyBlanket(ptr long long wstr long long ptr long)
|
||||
@ stdcall CoSetState(ptr)
|
||||
@ stub CoSwitchCallContext
|
||||
@ stdcall CoSuspendClassObjects()
|
||||
|
@ -92,8 +92,8 @@
|
|||
@ stdcall DllDebugObjectRPCHook(long ptr)
|
||||
@ stdcall -private DllGetClassObject (ptr ptr ptr) OLE32_DllGetClassObject
|
||||
@ stub DllGetClassObjectWOW
|
||||
@ stdcall -private DllRegisterServer() OLE32_DllRegisterServer
|
||||
@ stdcall -private DllUnregisterServer() OLE32_DllUnregisterServer
|
||||
@ stdcall -private DllRegisterServer()
|
||||
@ stdcall -private DllUnregisterServer()
|
||||
@ stdcall DoDragDrop(ptr ptr long ptr)
|
||||
@ stub EnableHookObject
|
||||
@ stdcall FreePropVariantArray(long ptr)
|
||||
|
|
|
@ -121,7 +121,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
|||
|
||||
switch(fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
DisableThreadLibraryCalls(hinstDLL);
|
||||
OLE32_hInstance = hinstDLL;
|
||||
COMPOBJ_InitProcess();
|
||||
if (TRACE_ON(ole)) CoRegisterMallocSpy((LPVOID)-1);
|
||||
|
@ -132,6 +131,10 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
|||
COMPOBJ_UninitProcess();
|
||||
OLE32_hInstance = 0;
|
||||
break;
|
||||
|
||||
case DLL_THREAD_DETACH:
|
||||
COM_TlsDestroy();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -29,5 +29,6 @@ extern HINSTANCE OLE32_hInstance;
|
|||
|
||||
void COMPOBJ_InitProcess( void );
|
||||
void COMPOBJ_UninitProcess( void );
|
||||
void COM_TlsDestroy( void );
|
||||
|
||||
#endif /* __WINE_OLE32_MAIN_H */
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* OLE32 proxy/stub handler
|
||||
*
|
||||
* Copyright 2002 Marcus Meissner
|
||||
* Copyright 2001 Ove Kåven, TransGaming Technologies
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -176,6 +177,7 @@ CFStub_Invoke(
|
|||
return hres;
|
||||
}
|
||||
hres = CoMarshalInterface(pStm,&iid,ppv,0,NULL,0);
|
||||
IUnknown_Release((IUnknown*)ppv);
|
||||
if (hres) {
|
||||
FIXME("CoMarshalInterface failed, %lx!\n",hres);
|
||||
msg->cbBuffer = 0;
|
||||
|
@ -266,8 +268,8 @@ CFStub_Construct(LPRPCSTUBBUFFER *ppv) {
|
|||
* the refcount.
|
||||
*/
|
||||
typedef struct _CFProxy {
|
||||
IClassFactoryVtbl *lpvtbl_cf;
|
||||
IRpcProxyBufferVtbl *lpvtbl_proxy;
|
||||
const IClassFactoryVtbl *lpvtbl_cf;
|
||||
const IRpcProxyBufferVtbl *lpvtbl_proxy;
|
||||
DWORD ref;
|
||||
|
||||
IRpcChannelBuffer *chanbuf;
|
||||
|
@ -318,7 +320,7 @@ static void WINAPI IRpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface) {
|
|||
|
||||
static HRESULT WINAPI
|
||||
CFProxy_QueryInterface(LPCLASSFACTORY iface,REFIID riid, LPVOID *ppv) {
|
||||
ICOM_THIS_MULTI(CFProxy,lpvtbl_proxy,iface);
|
||||
ICOM_THIS_MULTI(CFProxy,lpvtbl_cf,iface);
|
||||
if (This->outer_unknown) return IUnknown_QueryInterface(This->outer_unknown, riid, ppv);
|
||||
*ppv = NULL;
|
||||
if (IsEqualIID(&IID_IClassFactory,riid) || IsEqualIID(&IID_IUnknown,riid)) {
|
||||
|
@ -444,13 +446,459 @@ CFProxy_Construct(IUnknown *pUnkOuter, LPVOID *ppv,LPVOID *ppProxy) {
|
|||
|
||||
cf->lpvtbl_cf = &cfproxyvt;
|
||||
cf->lpvtbl_proxy = &pspbvtbl;
|
||||
/* 1 reference for the proxy... */
|
||||
/* only one reference for the proxy buffer */
|
||||
cf->ref = 1;
|
||||
cf->outer_unknown = pUnkOuter;
|
||||
*ppv = &(cf->lpvtbl_cf);
|
||||
*ppProxy = &(cf->lpvtbl_proxy);
|
||||
/* ...and 1 for the object */
|
||||
IUnknown_AddRef((IUnknown *)*ppv);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/********************* IRemUnknown Proxy/Stub ********************************/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const IRpcStubBufferVtbl *lpVtbl;
|
||||
ULONG refs;
|
||||
IRemUnknown *iface;
|
||||
} RemUnkStub;
|
||||
|
||||
static HRESULT WINAPI RemUnkStub_QueryInterface(LPRPCSTUBBUFFER iface,
|
||||
REFIID riid,
|
||||
LPVOID *obj)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(riid),obj);
|
||||
if (IsEqualGUID(&IID_IUnknown,riid) ||
|
||||
IsEqualGUID(&IID_IRpcStubBuffer,riid)) {
|
||||
*obj = This;
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI RemUnkStub_AddRef(LPRPCSTUBBUFFER iface)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
TRACE("(%p)->AddRef()\n",This);
|
||||
return InterlockedIncrement(&This->refs);
|
||||
}
|
||||
|
||||
static ULONG WINAPI RemUnkStub_Release(LPRPCSTUBBUFFER iface)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
ULONG refs;
|
||||
TRACE("(%p)->Release()\n",This);
|
||||
refs = InterlockedDecrement(&This->refs);
|
||||
if (!refs)
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
return refs;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnkStub_Connect(LPRPCSTUBBUFFER iface,
|
||||
LPUNKNOWN lpUnkServer)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
TRACE("(%p)->Connect(%p)\n",This,lpUnkServer);
|
||||
This->iface = (IRemUnknown*)lpUnkServer;
|
||||
IRemUnknown_AddRef(This->iface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void WINAPI RemUnkStub_Disconnect(LPRPCSTUBBUFFER iface)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
TRACE("(%p)->Disconnect()\n",This);
|
||||
IUnknown_Release(This->iface);
|
||||
This->iface = NULL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnkStub_Invoke(LPRPCSTUBBUFFER iface,
|
||||
PRPCOLEMESSAGE pMsg,
|
||||
LPRPCCHANNELBUFFER pChannel)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
ULONG iMethod = pMsg->iMethod;
|
||||
LPBYTE buf = pMsg->Buffer;
|
||||
HRESULT hr = RPC_E_INVALIDMETHOD;
|
||||
|
||||
TRACE("(%p)->Invoke(%p,%p) method %ld\n", This, pMsg, pChannel, iMethod);
|
||||
switch (iMethod)
|
||||
{
|
||||
case 3: /* RemQueryInterface */
|
||||
{
|
||||
IPID ipid;
|
||||
ULONG cRefs;
|
||||
USHORT cIids;
|
||||
IID *iids;
|
||||
REMQIRESULT *pQIResults = NULL;
|
||||
|
||||
/* in */
|
||||
memcpy(&ipid, buf, sizeof(ipid));
|
||||
buf += sizeof(ipid);
|
||||
memcpy(&cRefs, buf, sizeof(cRefs));
|
||||
buf += sizeof(cRefs);
|
||||
memcpy(&cIids, buf, sizeof(cIids));
|
||||
buf += sizeof(cIids);
|
||||
iids = (IID *)buf;
|
||||
|
||||
hr = IRemUnknown_RemQueryInterface(This->iface, &ipid, cRefs, cIids, iids, &pQIResults);
|
||||
|
||||
/* out */
|
||||
pMsg->cbBuffer = cIids * sizeof(REMQIRESULT);
|
||||
if (pMsg->Buffer)
|
||||
pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->cbBuffer);
|
||||
else
|
||||
pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->cbBuffer);
|
||||
buf = pMsg->Buffer;
|
||||
/* FIXME: pQIResults is a unique pointer so pQIResults can be NULL! */
|
||||
memcpy(buf, pQIResults, cIids * sizeof(REMQIRESULT));
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: /* RemAddRef */
|
||||
{
|
||||
USHORT cIids;
|
||||
REMINTERFACEREF *ir;
|
||||
HRESULT *pResults;
|
||||
|
||||
/* in */
|
||||
memcpy(&cIids, buf, sizeof(USHORT));
|
||||
buf += sizeof(USHORT);
|
||||
ir = (REMINTERFACEREF*)buf;
|
||||
pResults = CoTaskMemAlloc(cIids * sizeof(HRESULT));
|
||||
if (!pResults) return E_OUTOFMEMORY;
|
||||
|
||||
hr = IRemUnknown_RemAddRef(This->iface, cIids, ir, pResults);
|
||||
|
||||
/* out */
|
||||
pMsg->cbBuffer = cIids * sizeof(HRESULT);
|
||||
if (pMsg->Buffer)
|
||||
pMsg->Buffer = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->cbBuffer);
|
||||
else
|
||||
pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->cbBuffer);
|
||||
buf = pMsg->Buffer;
|
||||
memcpy(buf, pResults, cIids * sizeof(HRESULT));
|
||||
|
||||
CoTaskMemFree(pResults);
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: /* RemRelease */
|
||||
{
|
||||
USHORT cIids;
|
||||
REMINTERFACEREF *ir;
|
||||
|
||||
/* in */
|
||||
memcpy(&cIids, buf, sizeof(USHORT));
|
||||
buf += sizeof(USHORT);
|
||||
ir = (REMINTERFACEREF*)buf;
|
||||
|
||||
hr = IRemUnknown_RemRelease(This->iface, cIids, ir);
|
||||
|
||||
/* out */
|
||||
pMsg->cbBuffer = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static LPRPCSTUBBUFFER WINAPI RemUnkStub_IsIIDSupported(LPRPCSTUBBUFFER iface,
|
||||
REFIID riid)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
TRACE("(%p)->IsIIDSupported(%s)\n", This, debugstr_guid(riid));
|
||||
return IsEqualGUID(&IID_IRemUnknown, riid) ? iface : NULL;
|
||||
}
|
||||
|
||||
static ULONG WINAPI RemUnkStub_CountRefs(LPRPCSTUBBUFFER iface)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
FIXME("(%p)->CountRefs()\n", This);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnkStub_DebugServerQueryInterface(LPRPCSTUBBUFFER iface,
|
||||
LPVOID *ppv)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
FIXME("(%p)->DebugServerQueryInterface(%p)\n",This,ppv);
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static void WINAPI RemUnkStub_DebugServerRelease(LPRPCSTUBBUFFER iface,
|
||||
LPVOID pv)
|
||||
{
|
||||
RemUnkStub *This = (RemUnkStub *)iface;
|
||||
FIXME("(%p)->DebugServerRelease(%p)\n", This, pv);
|
||||
}
|
||||
|
||||
static const IRpcStubBufferVtbl RemUnkStub_VTable =
|
||||
{
|
||||
RemUnkStub_QueryInterface,
|
||||
RemUnkStub_AddRef,
|
||||
RemUnkStub_Release,
|
||||
RemUnkStub_Connect,
|
||||
RemUnkStub_Disconnect,
|
||||
RemUnkStub_Invoke,
|
||||
RemUnkStub_IsIIDSupported,
|
||||
RemUnkStub_CountRefs,
|
||||
RemUnkStub_DebugServerQueryInterface,
|
||||
RemUnkStub_DebugServerRelease
|
||||
};
|
||||
|
||||
static HRESULT RemUnkStub_Construct(IRpcStubBuffer **ppStub)
|
||||
{
|
||||
RemUnkStub *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
||||
if (!This) return E_OUTOFMEMORY;
|
||||
This->lpVtbl = &RemUnkStub_VTable;
|
||||
This->refs = 0;
|
||||
This->iface = NULL;
|
||||
*ppStub = (IRpcStubBuffer*)This;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
typedef struct _RemUnkProxy {
|
||||
const IRemUnknownVtbl *lpvtbl_remunk;
|
||||
const IRpcProxyBufferVtbl *lpvtbl_proxy;
|
||||
DWORD refs;
|
||||
|
||||
IRpcChannelBuffer *chan;
|
||||
IUnknown *outer_unknown;
|
||||
} RemUnkProxy;
|
||||
|
||||
static HRESULT WINAPI RemUnkProxy_QueryInterface(LPREMUNKNOWN iface, REFIID riid, void **ppv)
|
||||
{
|
||||
RemUnkProxy *This = (RemUnkProxy *)iface;
|
||||
if (This->outer_unknown)
|
||||
return IUnknown_QueryInterface(This->outer_unknown, riid, ppv);
|
||||
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||
IsEqualIID(riid, &IID_IRemUnknown))
|
||||
{
|
||||
IRemUnknown_AddRef(iface);
|
||||
*ppv = (LPVOID)iface;
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI RemUnkProxy_AddRef(LPREMUNKNOWN iface)
|
||||
{
|
||||
RemUnkProxy *This = (RemUnkProxy *)iface;
|
||||
|
||||
TRACE("(%p)->AddRef()\n",This);
|
||||
return InterlockedIncrement(&This->refs);
|
||||
}
|
||||
|
||||
static ULONG WINAPI RemUnkProxy_Release(LPREMUNKNOWN iface)
|
||||
{
|
||||
RemUnkProxy *This = (RemUnkProxy *)iface;
|
||||
ULONG refs;
|
||||
|
||||
TRACE("(%p)->Release()\n",This);
|
||||
if (This->outer_unknown)
|
||||
refs = IUnknown_Release(This->outer_unknown);
|
||||
else
|
||||
refs = InterlockedDecrement(&This->refs);
|
||||
|
||||
if (!refs) {
|
||||
if (This->chan) IRpcChannelBuffer_Release(This->chan);
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
}
|
||||
return refs;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnkProxy_RemQueryInterface(LPREMUNKNOWN iface,
|
||||
REFIPID ripid,
|
||||
ULONG cRefs,
|
||||
USHORT cIids,
|
||||
IID* iids,
|
||||
REMQIRESULT** ppQIResults)
|
||||
{
|
||||
RemUnkProxy *This = (RemUnkProxy *)iface;
|
||||
RPCOLEMESSAGE msg;
|
||||
HRESULT hr = S_OK;
|
||||
ULONG status;
|
||||
|
||||
TRACE("(%p)->(%s,%ld,%d,%p,%p)\n",This,
|
||||
debugstr_guid(ripid),cRefs,cIids,iids,ppQIResults);
|
||||
|
||||
*ppQIResults = NULL;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.iMethod = 3;
|
||||
msg.cbBuffer = sizeof(IPID) + sizeof(ULONG) +
|
||||
sizeof(USHORT) + cIids*sizeof(IID);
|
||||
hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
|
||||
if (SUCCEEDED(hr)) {
|
||||
LPBYTE buf = msg.Buffer;
|
||||
memcpy(buf, ripid, sizeof(IPID));
|
||||
buf += sizeof(IPID);
|
||||
memcpy(buf, &cRefs, sizeof(ULONG));
|
||||
buf += sizeof(ULONG);
|
||||
memcpy(buf, &cIids, sizeof(USHORT));
|
||||
buf += sizeof(USHORT);
|
||||
memcpy(buf, iids, cIids*sizeof(IID));
|
||||
|
||||
hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
buf = msg.Buffer;
|
||||
*ppQIResults = CoTaskMemAlloc(cIids*sizeof(REMQIRESULT));
|
||||
memcpy(*ppQIResults, buf, cIids*sizeof(REMQIRESULT));
|
||||
}
|
||||
|
||||
IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnkProxy_RemAddRef(LPREMUNKNOWN iface,
|
||||
USHORT cInterfaceRefs,
|
||||
REMINTERFACEREF* InterfaceRefs,
|
||||
HRESULT* pResults)
|
||||
{
|
||||
RemUnkProxy *This = (RemUnkProxy *)iface;
|
||||
RPCOLEMESSAGE msg;
|
||||
HRESULT hr = S_OK;
|
||||
ULONG status;
|
||||
|
||||
TRACE("(%p)->(%d,%p,%p)\n",This,
|
||||
cInterfaceRefs,InterfaceRefs,pResults);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.iMethod = 4;
|
||||
msg.cbBuffer = sizeof(USHORT) + cInterfaceRefs*sizeof(REMINTERFACEREF);
|
||||
hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
|
||||
if (SUCCEEDED(hr)) {
|
||||
LPBYTE buf = msg.Buffer;
|
||||
memcpy(buf, &cInterfaceRefs, sizeof(USHORT));
|
||||
buf += sizeof(USHORT);
|
||||
memcpy(buf, InterfaceRefs, cInterfaceRefs*sizeof(REMINTERFACEREF));
|
||||
|
||||
hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
buf = msg.Buffer;
|
||||
memcpy(pResults, buf, cInterfaceRefs*sizeof(HRESULT));
|
||||
}
|
||||
|
||||
IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnkProxy_RemRelease(LPREMUNKNOWN iface,
|
||||
USHORT cInterfaceRefs,
|
||||
REMINTERFACEREF* InterfaceRefs)
|
||||
{
|
||||
RemUnkProxy *This = (RemUnkProxy *)iface;
|
||||
RPCOLEMESSAGE msg;
|
||||
HRESULT hr = S_OK;
|
||||
ULONG status;
|
||||
|
||||
TRACE("(%p)->(%d,%p)\n",This,
|
||||
cInterfaceRefs,InterfaceRefs);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.iMethod = 5;
|
||||
msg.cbBuffer = sizeof(USHORT) + cInterfaceRefs*sizeof(REMINTERFACEREF);
|
||||
hr = IRpcChannelBuffer_GetBuffer(This->chan, &msg, &IID_IRemUnknown);
|
||||
if (SUCCEEDED(hr)) {
|
||||
LPBYTE buf = msg.Buffer;
|
||||
memcpy(buf, &cInterfaceRefs, sizeof(USHORT));
|
||||
buf += sizeof(USHORT);
|
||||
memcpy(buf, InterfaceRefs, cInterfaceRefs*sizeof(REMINTERFACEREF));
|
||||
|
||||
hr = IRpcChannelBuffer_SendReceive(This->chan, &msg, &status);
|
||||
|
||||
IRpcChannelBuffer_FreeBuffer(This->chan, &msg);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static const IRemUnknownVtbl RemUnkProxy_VTable =
|
||||
{
|
||||
RemUnkProxy_QueryInterface,
|
||||
RemUnkProxy_AddRef,
|
||||
RemUnkProxy_Release,
|
||||
RemUnkProxy_RemQueryInterface,
|
||||
RemUnkProxy_RemAddRef,
|
||||
RemUnkProxy_RemRelease
|
||||
};
|
||||
|
||||
|
||||
static HRESULT WINAPI RURpcProxyBufferImpl_QueryInterface(LPRPCPROXYBUFFER iface,REFIID riid,LPVOID *ppv) {
|
||||
*ppv = NULL;
|
||||
if (IsEqualIID(riid,&IID_IRpcProxyBuffer)||IsEqualIID(riid,&IID_IUnknown)) {
|
||||
IRpcProxyBuffer_AddRef(iface);
|
||||
*ppv = (LPVOID)iface;
|
||||
return S_OK;
|
||||
}
|
||||
FIXME("(%s), no interface.\n",debugstr_guid(riid));
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI RURpcProxyBufferImpl_AddRef(LPRPCPROXYBUFFER iface) {
|
||||
ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
|
||||
return InterlockedIncrement(&This->refs);
|
||||
}
|
||||
|
||||
static ULONG WINAPI RURpcProxyBufferImpl_Release(LPRPCPROXYBUFFER iface) {
|
||||
ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
|
||||
ULONG ref = InterlockedDecrement(&This->refs);
|
||||
|
||||
if (!ref) {
|
||||
IRpcChannelBuffer_Release(This->chan);This->chan = NULL;
|
||||
HeapFree(GetProcessHeap(),0,This);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RURpcProxyBufferImpl_Connect(LPRPCPROXYBUFFER iface,IRpcChannelBuffer* pRpcChannelBuffer) {
|
||||
ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
|
||||
|
||||
This->chan = pRpcChannelBuffer;
|
||||
IRpcChannelBuffer_AddRef(This->chan);
|
||||
return S_OK;
|
||||
}
|
||||
static void WINAPI RURpcProxyBufferImpl_Disconnect(LPRPCPROXYBUFFER iface) {
|
||||
ICOM_THIS_MULTI(RemUnkProxy,lpvtbl_proxy,iface);
|
||||
if (This->chan) {
|
||||
IRpcChannelBuffer_Release(This->chan);
|
||||
This->chan = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const IRpcProxyBufferVtbl RURpcProxyBuffer_VTable = {
|
||||
RURpcProxyBufferImpl_QueryInterface,
|
||||
RURpcProxyBufferImpl_AddRef,
|
||||
RURpcProxyBufferImpl_Release,
|
||||
RURpcProxyBufferImpl_Connect,
|
||||
RURpcProxyBufferImpl_Disconnect
|
||||
};
|
||||
|
||||
static HRESULT
|
||||
RemUnkProxy_Construct(IUnknown *pUnkOuter, LPVOID *ppv,LPVOID *ppProxy) {
|
||||
RemUnkProxy *This;
|
||||
|
||||
This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*This));
|
||||
if (!This)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
This->lpvtbl_remunk = &RemUnkProxy_VTable;
|
||||
This->lpvtbl_proxy = &RURpcProxyBuffer_VTable;
|
||||
/* only one reference for the proxy buffer */
|
||||
This->refs = 1;
|
||||
This->outer_unknown = pUnkOuter;
|
||||
*ppv = &(This->lpvtbl_remunk);
|
||||
*ppProxy = &(This->lpvtbl_proxy);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -475,10 +923,10 @@ PSFacBuf_CreateProxy(
|
|||
LPPSFACTORYBUFFER iface, IUnknown* pUnkOuter, REFIID riid,
|
||||
IRpcProxyBuffer **ppProxy, LPVOID *ppv
|
||||
) {
|
||||
if (IsEqualIID(&IID_IClassFactory,riid) ||
|
||||
IsEqualIID(&IID_IUnknown,riid)
|
||||
)
|
||||
if (IsEqualIID(&IID_IClassFactory,riid))
|
||||
return CFProxy_Construct(pUnkOuter, ppv,(LPVOID*)ppProxy);
|
||||
else if (IsEqualIID(&IID_IRemUnknown,riid))
|
||||
return RemUnkProxy_Construct(pUnkOuter, ppv,(LPVOID*)ppProxy);
|
||||
FIXME("proxying not implemented for (%s) yet!\n",debugstr_guid(riid));
|
||||
return E_FAIL;
|
||||
}
|
||||
|
@ -492,13 +940,17 @@ PSFacBuf_CreateStub(
|
|||
|
||||
TRACE("(%s,%p,%p)\n",debugstr_guid(riid),pUnkServer,ppStub);
|
||||
|
||||
if (IsEqualIID(&IID_IClassFactory,riid) ||
|
||||
IsEqualIID(&IID_IUnknown,riid)
|
||||
) {
|
||||
if (IsEqualIID(&IID_IClassFactory, riid) ||
|
||||
IsEqualIID(&IID_IUnknown, riid) /* FIXME: fixup stub manager and remove this*/) {
|
||||
hres = CFStub_Construct(ppStub);
|
||||
if (!hres)
|
||||
IRpcStubBuffer_Connect((*ppStub),pUnkServer);
|
||||
return hres;
|
||||
} else if (IsEqualIID(&IID_IRemUnknown,riid)) {
|
||||
hres = RemUnkStub_Construct(ppStub);
|
||||
if (!hres)
|
||||
IRpcStubBuffer_Connect((*ppStub),pUnkServer);
|
||||
return hres;
|
||||
}
|
||||
FIXME("stubbing not implemented for (%s) yet!\n",debugstr_guid(riid));
|
||||
return E_FAIL;
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
#include "winuser.h"
|
||||
#include "winreg.h"
|
||||
#include "winerror.h"
|
||||
#include "objbase.h"
|
||||
|
||||
#include "compobj_private.h"
|
||||
#include "ole2.h"
|
||||
#include "olectl.h"
|
||||
|
||||
|
@ -448,396 +450,27 @@ static struct regsvr_coclass const coclass_list[] = {
|
|||
* interface list
|
||||
*/
|
||||
|
||||
/* FIXME: perhaps the interfaces that are proxied by another dll
|
||||
* should be registered in that dll? Or maybe the choice of proxy is
|
||||
* arbitrary at this point? */
|
||||
|
||||
static GUID const CLSID_PSFactoryBuffer_ole2disp = {
|
||||
0x00020420, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
|
||||
|
||||
static GUID const CLSID_PSFactoryBuffer_oleaut32 = {
|
||||
0xB196B286, 0xBAB4, 0x101A, {0xB6,0x9C,0x00,0xAA,0x00,0x34,0x1D,0x07} };
|
||||
|
||||
/* FIXME: these interfaces should be defined in ocidl.idl */
|
||||
|
||||
static IID const IID_IFontEventsDisp = {
|
||||
0x4EF6100A, 0xAF88, 0x11D0, {0x98,0x46,0x00,0xC0,0x4F,0xC2,0x99,0x93} };
|
||||
|
||||
static IID const IID_IProvideMultipleClassInfo = {
|
||||
0xA7ABA9C1, 0x8983, 0x11CF, {0x8F,0x20,0x00,0x80,0x5F,0x2C,0xD0,0x64} };
|
||||
#define INTERFACE_ENTRY(interface, base, clsid32, clsid16) { &IID_##interface, #interface, base, sizeof(interface##Vtbl)/sizeof(void*), clsid16, clsid32 }
|
||||
#define STD_INTERFACE_ENTRY(interface) INTERFACE_ENTRY(interface, NULL, &CLSID_PSFactoryBuffer, NULL)
|
||||
|
||||
static struct regsvr_interface const interface_list[] = {
|
||||
{ &IID_IUnknown,
|
||||
"IUnknown",
|
||||
NULL,
|
||||
3,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer
|
||||
},
|
||||
{ &IID_IClassFactory,
|
||||
"IClassFactory",
|
||||
NULL,
|
||||
5,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer
|
||||
},
|
||||
{ &IID_IStorage,
|
||||
"IStorage",
|
||||
NULL,
|
||||
18,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer
|
||||
},
|
||||
{ &IID_IStream,
|
||||
"IStream",
|
||||
NULL,
|
||||
14,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer
|
||||
},
|
||||
{ &IID_IPersistStorage,
|
||||
"IPersistStorage",
|
||||
&IID_IPersist,
|
||||
10,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer
|
||||
},
|
||||
{ &IID_IDataObject,
|
||||
"IDataObject",
|
||||
NULL,
|
||||
12,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer
|
||||
},
|
||||
{ &IID_IAdviseSink,
|
||||
"IAdviseSink",
|
||||
NULL,
|
||||
8,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer
|
||||
},
|
||||
{ &IID_IOleObject,
|
||||
"IOleObject",
|
||||
NULL,
|
||||
24,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer
|
||||
},
|
||||
{ &IID_IOleClientSite,
|
||||
"IOleClientSite",
|
||||
NULL,
|
||||
9,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer
|
||||
},
|
||||
{ &IID_IDispatch,
|
||||
"IDispatch",
|
||||
NULL,
|
||||
7,
|
||||
&CLSID_PSFactoryBuffer_ole2disp,
|
||||
&CLSID_PSFactoryBuffer_ole2disp
|
||||
},
|
||||
{ &IID_ITypeLib2,
|
||||
"ITypeLib2",
|
||||
NULL,
|
||||
16,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_ole2disp
|
||||
},
|
||||
{ &IID_ITypeInfo2,
|
||||
"ITypeInfo2",
|
||||
NULL,
|
||||
32,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_ole2disp
|
||||
},
|
||||
{ &IID_IPropertyPage2,
|
||||
"IPropertyPage2",
|
||||
NULL,
|
||||
15,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IErrorInfo,
|
||||
"IErrorInfo",
|
||||
NULL,
|
||||
8,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_ICreateErrorInfo,
|
||||
"ICreateErrorInfo",
|
||||
NULL,
|
||||
8,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPersistPropertyBag2,
|
||||
"IPersistPropertyBag2",
|
||||
NULL,
|
||||
8,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPropertyBag2,
|
||||
"IPropertyBag2",
|
||||
NULL,
|
||||
8,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IErrorLog,
|
||||
"IErrorLog",
|
||||
NULL,
|
||||
4,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPerPropertyBrowsing,
|
||||
"IPerPropertyBrowsing",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPersistPropertyBag,
|
||||
"IPersistPropertyBag",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IAdviseSinkEx,
|
||||
"IAdviseSinkEx",
|
||||
NULL,
|
||||
9,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IFontEventsDisp,
|
||||
"IFontEventsDisp",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPropertyBag,
|
||||
"IPropertyBag",
|
||||
NULL,
|
||||
5,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPointerInactive,
|
||||
"IPointerInactive",
|
||||
NULL,
|
||||
6,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_ISimpleFrameSite,
|
||||
"ISimpleFrameSite",
|
||||
NULL,
|
||||
5,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPicture,
|
||||
"IPicture",
|
||||
NULL,
|
||||
17,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPictureDisp,
|
||||
"IPictureDisp",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPersistStreamInit,
|
||||
"IPersistStreamInit",
|
||||
NULL,
|
||||
9,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IOleUndoUnit,
|
||||
"IOleUndoUnit",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPropertyNotifySink,
|
||||
"IPropertyNotifySink",
|
||||
NULL,
|
||||
5,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IOleInPlaceSiteEx,
|
||||
"IOleInPlaceSiteEx",
|
||||
NULL,
|
||||
18,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IOleParentUndoUnit,
|
||||
"IOleParentUndoUnit",
|
||||
NULL,
|
||||
12,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IProvideClassInfo2,
|
||||
"IProvideClassInfo2",
|
||||
NULL,
|
||||
5,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IProvideMultipleClassInfo,
|
||||
"IProvideMultipleClassInfo",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IProvideClassInfo,
|
||||
"IProvideClassInfo",
|
||||
NULL,
|
||||
4,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IConnectionPointContainer,
|
||||
"IConnectionPointContainer",
|
||||
NULL,
|
||||
5,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IEnumConnectionPoints,
|
||||
"IEnumConnectionPoints",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IConnectionPoint,
|
||||
"IConnectionPoint",
|
||||
NULL,
|
||||
8,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IEnumConnections,
|
||||
"IEnumConnections",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IOleControl,
|
||||
"IOleControl",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IOleControlSite,
|
||||
"IOleControlSite",
|
||||
NULL,
|
||||
10,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_ISpecifyPropertyPages,
|
||||
"ISpecifyPropertyPages",
|
||||
NULL,
|
||||
4,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPropertyPageSite,
|
||||
"IPropertyPageSite",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPropertyPage,
|
||||
"IPropertyPage",
|
||||
NULL,
|
||||
14,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IClassFactory2,
|
||||
"IClassFactory2",
|
||||
NULL,
|
||||
8,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IEnumOleUndoUnits,
|
||||
"IEnumOleUndoUnits",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IPersistMemory,
|
||||
"IPersistMemory",
|
||||
NULL,
|
||||
9,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IFont,
|
||||
"IFont",
|
||||
NULL,
|
||||
27,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IFontDisp,
|
||||
"IFontDisp",
|
||||
NULL,
|
||||
7,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IQuickActivate,
|
||||
"IQuickActivate",
|
||||
NULL,
|
||||
6,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IOleUndoManager,
|
||||
"IOleUndoManager",
|
||||
NULL,
|
||||
15,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
{ &IID_IObjectWithSite,
|
||||
"IObjectWithSite",
|
||||
NULL,
|
||||
5,
|
||||
NULL,
|
||||
&CLSID_PSFactoryBuffer_oleaut32
|
||||
},
|
||||
STD_INTERFACE_ENTRY(IUnknown),
|
||||
STD_INTERFACE_ENTRY(IClassFactory),
|
||||
STD_INTERFACE_ENTRY(IStorage),
|
||||
STD_INTERFACE_ENTRY(IStream ),
|
||||
STD_INTERFACE_ENTRY(IPersistStorage),
|
||||
STD_INTERFACE_ENTRY(IDataObject),
|
||||
STD_INTERFACE_ENTRY(IAdviseSink),
|
||||
STD_INTERFACE_ENTRY(IOleObject),
|
||||
STD_INTERFACE_ENTRY(IOleClientSite),
|
||||
STD_INTERFACE_ENTRY(IRemUnknown),
|
||||
{ NULL } /* list terminator */
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* DllRegisterServer (OLE32.@)
|
||||
*/
|
||||
HRESULT WINAPI OLE32_DllRegisterServer()
|
||||
HRESULT WINAPI DllRegisterServer()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -852,7 +485,7 @@ HRESULT WINAPI OLE32_DllRegisterServer()
|
|||
/***********************************************************************
|
||||
* DllUnregisterServer (OLE32.@)
|
||||
*/
|
||||
HRESULT WINAPI OLE32_DllUnregisterServer()
|
||||
HRESULT WINAPI DllUnregisterServer()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -94,6 +94,7 @@ static void stub_manager_delete(struct stub_manager *m)
|
|||
|
||||
list_remove(&m->entry);
|
||||
|
||||
/* release every ifstub */
|
||||
while ((cursor = list_head(&m->ifstubs)))
|
||||
{
|
||||
struct ifstub *ifstub = LIST_ENTRY(cursor, struct ifstub, entry);
|
||||
|
@ -107,19 +108,13 @@ static void stub_manager_delete(struct stub_manager *m)
|
|||
HeapFree(GetProcessHeap(), 0, m);
|
||||
}
|
||||
|
||||
/* gets the stub manager associated with an object - caller must call
|
||||
* release on the stub manager when it is no longer needed */
|
||||
struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object)
|
||||
/* gets the stub manager associated with an object - caller must have
|
||||
* a reference to the apartment while a reference to the stub manager is held.
|
||||
* it must also call release on the stub manager when it is no longer needed */
|
||||
struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object)
|
||||
{
|
||||
struct stub_manager *result = NULL;
|
||||
struct list *cursor;
|
||||
APARTMENT *apt;
|
||||
|
||||
if (!(apt = COM_ApartmentFromOXID(oxid, TRUE)))
|
||||
{
|
||||
WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(oxid));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
LIST_FOR_EACH( cursor, &apt->stubmgrs )
|
||||
|
@ -135,13 +130,69 @@ struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object)
|
|||
}
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
COM_ApartmentRelease(apt);
|
||||
|
||||
TRACE("found %p from object %p\n", result, object);
|
||||
if (result)
|
||||
TRACE("found %p for object %p\n", result, object);
|
||||
else
|
||||
TRACE("not found for object %p\n", object);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* removes the apartment reference to an object, destroying it when no other
|
||||
* threads have a reference to it */
|
||||
void apartment_disconnect_object(APARTMENT *apt, void *object)
|
||||
{
|
||||
int found = FALSE;
|
||||
struct stub_manager *stubmgr;
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
LIST_FOR_EACH_ENTRY( stubmgr, &apt->stubmgrs, struct stub_manager, entry )
|
||||
{
|
||||
if (stubmgr->object == object)
|
||||
{
|
||||
found = TRUE;
|
||||
stub_manager_int_release(stubmgr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
if (found)
|
||||
TRACE("disconnect object %p\n", object);
|
||||
else
|
||||
WARN("couldn't find object %p\n", object);
|
||||
}
|
||||
|
||||
/* gets the stub manager associated with an object id - caller must have
|
||||
* a reference to the apartment while a reference to the stub manager is held.
|
||||
* it must also call release on the stub manager when it is no longer needed */
|
||||
struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid)
|
||||
{
|
||||
struct stub_manager *result = NULL;
|
||||
struct list *cursor;
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
LIST_FOR_EACH( cursor, &apt->stubmgrs )
|
||||
{
|
||||
struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
|
||||
|
||||
if (m->oid == oid)
|
||||
{
|
||||
result = m;
|
||||
stub_manager_int_addref(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
if (result)
|
||||
TRACE("found %p for oid %s\n", result, wine_dbgstr_longlong(oid));
|
||||
else
|
||||
TRACE("not found for oid %s\n", wine_dbgstr_longlong(oid));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* increments the internal refcount */
|
||||
ULONG stub_manager_int_addref(struct stub_manager *This)
|
||||
{
|
||||
|
@ -174,41 +225,6 @@ ULONG stub_manager_int_release(struct stub_manager *This)
|
|||
return refs;
|
||||
}
|
||||
|
||||
/* gets the stub manager associated with an object id - caller must call
|
||||
* release on the stub manager when it is no longer needed */
|
||||
struct stub_manager *get_stub_manager(OXID oxid, OID oid)
|
||||
{
|
||||
struct stub_manager *result = NULL;
|
||||
struct list *cursor;
|
||||
APARTMENT *apt;
|
||||
|
||||
if (!(apt = COM_ApartmentFromOXID(oxid, TRUE)))
|
||||
{
|
||||
WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(oxid));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
LIST_FOR_EACH( cursor, &apt->stubmgrs )
|
||||
{
|
||||
struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
|
||||
|
||||
if (m->oid == oid)
|
||||
{
|
||||
result = m;
|
||||
stub_manager_int_addref(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
COM_ApartmentRelease(apt);
|
||||
|
||||
TRACE("found %p from oid %s\n", result, wine_dbgstr_longlong(oid));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* add some external references (ie from a client that unmarshaled an ifptr) */
|
||||
ULONG stub_manager_ext_addref(struct stub_manager *m, ULONG refs)
|
||||
{
|
||||
|
@ -253,11 +269,101 @@ static struct ifstub *stub_manager_ipid_to_ifstub(struct stub_manager *m, const
|
|||
return result;
|
||||
}
|
||||
|
||||
IRpcStubBuffer *stub_manager_ipid_to_stubbuffer(struct stub_manager *m, const IPID *ipid)
|
||||
/* gets the stub manager associated with an ipid - caller must have
|
||||
* a reference to the apartment while a reference to the stub manager is held.
|
||||
* it must also call release on the stub manager when it is no longer needed */
|
||||
static struct stub_manager *get_stub_manager_from_ipid(APARTMENT *apt, const IPID *ipid)
|
||||
{
|
||||
struct ifstub *ifstub = stub_manager_ipid_to_ifstub(m, ipid);
|
||||
|
||||
return ifstub ? ifstub->stubbuffer : NULL;
|
||||
struct stub_manager *result = NULL;
|
||||
struct list *cursor;
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
LIST_FOR_EACH( cursor, &apt->stubmgrs )
|
||||
{
|
||||
struct stub_manager *m = LIST_ENTRY( cursor, struct stub_manager, entry );
|
||||
|
||||
if (stub_manager_ipid_to_ifstub(m, ipid))
|
||||
{
|
||||
result = m;
|
||||
stub_manager_int_addref(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
if (result)
|
||||
TRACE("found %p for ipid %s\n", result, debugstr_guid(ipid));
|
||||
else
|
||||
ERR("not found for ipid %s\n", debugstr_guid(ipid));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret)
|
||||
{
|
||||
/* FIXME: hack for IRemUnknown */
|
||||
if (ipid->Data2 == 0xffff)
|
||||
*stub_apt = COM_ApartmentFromOXID(*(OXID *)ipid->Data4, TRUE);
|
||||
else
|
||||
*stub_apt = COM_ApartmentFromTID(ipid->Data2);
|
||||
if (!*stub_apt)
|
||||
{
|
||||
ERR("Couldn't find apartment corresponding to TID 0x%04x\n", ipid->Data2);
|
||||
return RPC_E_INVALID_OBJECT;
|
||||
}
|
||||
*stubmgr_ret = get_stub_manager_from_ipid(*stub_apt, ipid);
|
||||
if (!*stubmgr_ret)
|
||||
{
|
||||
COM_ApartmentRelease(*stub_apt);
|
||||
*stub_apt = NULL;
|
||||
return RPC_E_INVALID_OBJECT;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IRpcStubBuffer *ipid_to_stubbuffer(const IPID *ipid)
|
||||
{
|
||||
IRpcStubBuffer *ret = NULL;
|
||||
APARTMENT *apt;
|
||||
struct stub_manager *stubmgr;
|
||||
struct ifstub *ifstub;
|
||||
HRESULT hr;
|
||||
|
||||
hr = ipid_to_stub_manager(ipid, &apt, &stubmgr);
|
||||
if (hr != S_OK) return NULL;
|
||||
|
||||
ifstub = stub_manager_ipid_to_ifstub(stubmgr, ipid);
|
||||
if (ifstub)
|
||||
ret = ifstub->stubbuffer;
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
|
||||
COM_ApartmentRelease(apt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* generates an ipid in the following format (similar to native version):
|
||||
* Data1 = apartment-local ipid counter
|
||||
* Data2 = apartment creator thread ID
|
||||
* Data3 = process ID
|
||||
* Data4 = random value
|
||||
*/
|
||||
static inline HRESULT generate_ipid(struct stub_manager *m, IPID *ipid)
|
||||
{
|
||||
HRESULT hr;
|
||||
hr = UuidCreate(ipid);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ERR("couldn't create IPID for stub manager %p\n", m);
|
||||
UuidCreateNil(ipid);
|
||||
return hr;
|
||||
}
|
||||
|
||||
ipid->Data1 = InterlockedIncrement(&m->apt->ipidc);
|
||||
ipid->Data2 = (USHORT)m->apt->tid;
|
||||
ipid->Data3 = (USHORT)GetCurrentProcessId();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/* registers a new interface stub COM object with the stub manager and returns registration record */
|
||||
|
@ -276,14 +382,33 @@ struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *s
|
|||
|
||||
/* no need to ref this, same object as sb */
|
||||
stub->iface = iptr;
|
||||
stub->table = tablemarshal;
|
||||
|
||||
if (tablemarshal)
|
||||
stub->state = IFSTUB_STATE_TABLE_MARSHALED;
|
||||
else
|
||||
stub->state = IFSTUB_STATE_NORMAL_MARSHALED;
|
||||
|
||||
stub->iid = *iid;
|
||||
stub->ipid = *iid; /* FIXME: should be globally unique */
|
||||
|
||||
/* FIXME: hack for IRemUnknown because we don't notify SCM of our IPID
|
||||
* yet, so we need to use a well-known one */
|
||||
if (IsEqualIID(iid, &IID_IRemUnknown))
|
||||
{
|
||||
stub->ipid.Data1 = 0xffffffff;
|
||||
stub->ipid.Data2 = 0xffff;
|
||||
stub->ipid.Data3 = 0xffff;
|
||||
assert(sizeof(stub->ipid.Data4) == sizeof(m->apt->oxid));
|
||||
memcpy(&stub->ipid.Data4, &m->apt->oxid, sizeof(OXID));
|
||||
}
|
||||
else
|
||||
generate_ipid(m, &stub->ipid);
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
list_add_head(&m->ifstubs, &stub->entry);
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
TRACE("ifstub %p created with ipid %s\n", stub, debugstr_guid(&stub->ipid));
|
||||
|
||||
return stub;
|
||||
}
|
||||
|
||||
|
@ -298,3 +423,278 @@ static void stub_manager_delete_ifstub(struct stub_manager *m, struct ifstub *if
|
|||
|
||||
HeapFree(GetProcessHeap(), 0, ifstub);
|
||||
}
|
||||
|
||||
/* returns TRUE if it is possible to unmarshal, FALSE otherwise. */
|
||||
BOOL stub_manager_notify_unmarshal(struct stub_manager *m, const IPID *ipid)
|
||||
{
|
||||
struct ifstub *ifstub;
|
||||
BOOL ret;
|
||||
|
||||
ifstub = stub_manager_ipid_to_ifstub(m, ipid);
|
||||
if (!ifstub)
|
||||
{
|
||||
WARN("Can't find ifstub for OID %s, IPID %s\n",
|
||||
wine_dbgstr_longlong(m->oid), wine_dbgstr_guid(ipid));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
|
||||
switch (ifstub->state)
|
||||
{
|
||||
case IFSTUB_STATE_TABLE_MARSHALED:
|
||||
ret = TRUE;
|
||||
break;
|
||||
case IFSTUB_STATE_NORMAL_MARSHALED:
|
||||
ifstub->state = IFSTUB_STATE_NORMAL_UNMARSHALED;
|
||||
ret = TRUE;
|
||||
break;
|
||||
default:
|
||||
WARN("object OID %s, IPID %s already unmarshaled\n",
|
||||
wine_dbgstr_longlong(m->oid), wine_dbgstr_guid(ipid));
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* is an ifstub table marshaled? */
|
||||
BOOL stub_manager_is_table_marshaled(struct stub_manager *m, const IPID *ipid)
|
||||
{
|
||||
struct ifstub *ifstub;
|
||||
BOOL ret;
|
||||
|
||||
ifstub = stub_manager_ipid_to_ifstub(m, ipid);
|
||||
if (!ifstub)
|
||||
{
|
||||
WARN("Can't find ifstub for OID %s, IPID %s\n",
|
||||
wine_dbgstr_longlong(m->oid), wine_dbgstr_guid(ipid));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&m->lock);
|
||||
ret = (ifstub->state == IFSTUB_STATE_TABLE_MARSHALED);
|
||||
LeaveCriticalSection(&m->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* IRemUnknown implementation
|
||||
*
|
||||
*
|
||||
* Note: this object is not related to the lifetime of a stub_manager, but it
|
||||
* interacts with stub managers.
|
||||
*/
|
||||
|
||||
const IID IID_IRemUnknown = { 0x00000131, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
|
||||
|
||||
typedef struct rem_unknown
|
||||
{
|
||||
const IRemUnknownVtbl *lpVtbl;
|
||||
ULONG refs;
|
||||
} RemUnknown;
|
||||
|
||||
static const IRemUnknownVtbl RemUnknown_Vtbl;
|
||||
|
||||
|
||||
/* construct an IRemUnknown object with one outstanding reference */
|
||||
static HRESULT RemUnknown_Construct(IRemUnknown **ppRemUnknown)
|
||||
{
|
||||
RemUnknown *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
|
||||
|
||||
if (!This) return E_OUTOFMEMORY;
|
||||
|
||||
This->lpVtbl = &RemUnknown_Vtbl;
|
||||
This->refs = 1;
|
||||
|
||||
*ppRemUnknown = (IRemUnknown *)This;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnknown_QueryInterface(IRemUnknown *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
|
||||
|
||||
if (IsEqualIID(riid, &IID_IUnknown) ||
|
||||
IsEqualIID(riid, &IID_IRemUnknown))
|
||||
{
|
||||
*ppv = (LPVOID)iface;
|
||||
IRemUnknown_AddRef(iface);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
FIXME("No interface for iid %s\n", debugstr_guid(riid));
|
||||
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI RemUnknown_AddRef(IRemUnknown *iface)
|
||||
{
|
||||
ULONG refs;
|
||||
RemUnknown *This = (RemUnknown *)iface;
|
||||
|
||||
refs = InterlockedIncrement(&This->refs);
|
||||
|
||||
TRACE("%p before: %ld\n", iface, refs-1);
|
||||
return refs;
|
||||
}
|
||||
|
||||
static ULONG WINAPI RemUnknown_Release(IRemUnknown *iface)
|
||||
{
|
||||
ULONG refs;
|
||||
RemUnknown *This = (RemUnknown *)iface;
|
||||
|
||||
refs = InterlockedDecrement(&This->refs);
|
||||
if (!refs)
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
|
||||
TRACE("%p after: %ld\n", iface, refs);
|
||||
return refs;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnknown_RemQueryInterface(IRemUnknown *iface,
|
||||
REFIPID ripid, ULONG cRefs, USHORT cIids, IID *iids /* [size_is(cIids)] */,
|
||||
REMQIRESULT **ppQIResults /* [size_is(,cIids)] */)
|
||||
{
|
||||
HRESULT hr;
|
||||
USHORT i;
|
||||
USHORT successful_qis = 0;
|
||||
APARTMENT *apt;
|
||||
struct stub_manager *stubmgr;
|
||||
|
||||
TRACE("(%p)->(%s, %ld, %d, %p, %p)\n", iface, debugstr_guid(ripid), cRefs, cIids, iids, ppQIResults);
|
||||
|
||||
hr = ipid_to_stub_manager(ripid, &apt, &stubmgr);
|
||||
if (hr != S_OK) return hr;
|
||||
|
||||
*ppQIResults = CoTaskMemAlloc(sizeof(REMQIRESULT) * cIids);
|
||||
|
||||
for (i = 0; i < cIids; i++)
|
||||
{
|
||||
HRESULT hrobj = register_ifstub(apt, &(*ppQIResults)[i].std, &iids[i],
|
||||
stubmgr->object, MSHLFLAGS_NORMAL);
|
||||
if (hrobj == S_OK)
|
||||
successful_qis++;
|
||||
(*ppQIResults)[i].hResult = hrobj;
|
||||
}
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
COM_ApartmentRelease(apt);
|
||||
|
||||
if (successful_qis == cIids)
|
||||
return S_OK; /* we got all requested interfaces */
|
||||
else if (successful_qis == 0)
|
||||
return E_NOINTERFACE; /* we didn't get any interfaces */
|
||||
else
|
||||
return S_FALSE; /* we got some interfaces */
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnknown_RemAddRef(IRemUnknown *iface,
|
||||
USHORT cInterfaceRefs,
|
||||
REMINTERFACEREF* InterfaceRefs /* [size_is(cInterfaceRefs)] */,
|
||||
HRESULT *pResults /* [size_is(cInterfaceRefs)] */)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
USHORT i;
|
||||
|
||||
TRACE("(%p)->(%d, %p, %p)\n", iface, cInterfaceRefs, InterfaceRefs, pResults);
|
||||
|
||||
for (i = 0; i < cInterfaceRefs; i++)
|
||||
{
|
||||
APARTMENT *apt;
|
||||
struct stub_manager *stubmgr;
|
||||
|
||||
pResults[i] = ipid_to_stub_manager(&InterfaceRefs[i].ipid, &apt, &stubmgr);
|
||||
if (pResults[i] != S_OK)
|
||||
{
|
||||
hr = S_FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
stub_manager_ext_addref(stubmgr, InterfaceRefs[i].cPublicRefs);
|
||||
if (InterfaceRefs[i].cPrivateRefs)
|
||||
FIXME("Adding %ld refs securely not implemented\n", InterfaceRefs[i].cPrivateRefs);
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
COM_ApartmentRelease(apt);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI RemUnknown_RemRelease(IRemUnknown *iface,
|
||||
USHORT cInterfaceRefs,
|
||||
REMINTERFACEREF* InterfaceRefs /* [size_is(cInterfaceRefs)] */)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
USHORT i;
|
||||
|
||||
TRACE("(%p)->(%d, %p)\n", iface, cInterfaceRefs, InterfaceRefs);
|
||||
|
||||
for (i = 0; i < cInterfaceRefs; i++)
|
||||
{
|
||||
APARTMENT *apt;
|
||||
struct stub_manager *stubmgr;
|
||||
|
||||
hr = ipid_to_stub_manager(&InterfaceRefs[i].ipid, &apt, &stubmgr);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
/* FIXME: we should undo any changes already made in this function */
|
||||
break;
|
||||
}
|
||||
|
||||
stub_manager_ext_release(stubmgr, InterfaceRefs[i].cPublicRefs);
|
||||
if (InterfaceRefs[i].cPrivateRefs)
|
||||
FIXME("Releasing %ld refs securely not implemented\n", InterfaceRefs[i].cPrivateRefs);
|
||||
|
||||
stub_manager_int_release(stubmgr);
|
||||
COM_ApartmentRelease(apt);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static const IRemUnknownVtbl RemUnknown_Vtbl =
|
||||
{
|
||||
RemUnknown_QueryInterface,
|
||||
RemUnknown_AddRef,
|
||||
RemUnknown_Release,
|
||||
RemUnknown_RemQueryInterface,
|
||||
RemUnknown_RemAddRef,
|
||||
RemUnknown_RemRelease
|
||||
};
|
||||
|
||||
/* starts the IRemUnknown listener for the current apartment */
|
||||
HRESULT start_apartment_remote_unknown()
|
||||
{
|
||||
IRemUnknown *pRemUnknown;
|
||||
HRESULT hr = S_OK;
|
||||
APARTMENT *apt = COM_CurrentApt();
|
||||
|
||||
EnterCriticalSection(&apt->cs);
|
||||
if (!apt->remunk_exported)
|
||||
{
|
||||
/* create the IRemUnknown object */
|
||||
hr = RemUnknown_Construct(&pRemUnknown);
|
||||
if (hr == S_OK)
|
||||
{
|
||||
STDOBJREF stdobjref; /* dummy - not used */
|
||||
/* register it with the stub manager */
|
||||
hr = register_ifstub(COM_CurrentApt(), &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, MSHLFLAGS_NORMAL);
|
||||
/* release our reference to the object as the stub manager will manage the life cycle for us */
|
||||
IRemUnknown_Release(pRemUnknown);
|
||||
if (hr == S_OK)
|
||||
apt->remunk_exported = TRUE;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
return hr;
|
||||
}
|
||||
|
|
|
@ -2198,6 +2198,7 @@
|
|||
#define RPC_E_CANTCALLOUT_ININPUTSYNCCALL ((HRESULT)0x8001010DL)
|
||||
#define RPC_E_WRONG_THREAD ((HRESULT)0x8001010EL)
|
||||
#define RPC_E_THREAD_NOT_INIT ((HRESULT)0x8001010FL)
|
||||
#define RPC_E_INVALID_OBJECT ((HRESULT)0x80010114L)
|
||||
#define RPC_E_INVALID_OBJREF ((HRESULT)0x8001011DL)
|
||||
#define RPC_E_UNEXPECTED ((HRESULT)0x8001FFFFL)
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ typedef enum tagCLSCTX {
|
|||
CLSCTX_INPROC_SERVER16=8,CLSCTX_REMOTE_SERVER=16
|
||||
} CLSCTX;
|
||||
typedef enum tagMSHLFLAGS {
|
||||
MSHLFLAGS_NORMAL,MSHLFLAGS_TABLESTRONG,MSHLFLAGS_TABLEWEAK
|
||||
MSHLFLAGS_NORMAL,MSHLFLAGS_TABLESTRONG,MSHLFLAGS_TABLEWEAK,MSHLFLAGS_NOPING
|
||||
} MSHLFLAGS;
|
||||
typedef struct _FLAGGED_WORD_BLOB {
|
||||
unsigned long fFlags;
|
||||
|
|
Loading…
Reference in a new issue