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:
Gé van Geldorp 2005-02-13 20:52:16 +00:00
parent 4267da8a2f
commit f4477fcb16
17 changed files with 2976 additions and 1710 deletions

View file

@ -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) }

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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]
*

View file

@ -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]
*/

View file

@ -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)

View file

@ -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;
}

View file

@ -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 */

View file

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

View file

@ -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

View file

@ -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;
}

View file

@ -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)

View file

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