- Make apartment access thread-safe by introducing refcounting and
wider usage of the apartment lock. - Rework OLE TLS management to eliminate uninitialised apartments and parent chaining.
This commit is contained in:
parent
a790b2d1c5
commit
a6a416cb4e
|
@ -30,6 +30,8 @@
|
|||
* - Rewrite the CoLockObjectExternal code, it does totally the wrong
|
||||
* thing currently (should be controlling the stub manager)
|
||||
*
|
||||
* - Make the MTA dynamically allocated and refcounted
|
||||
*
|
||||
* - Implement the service control manager (in rpcss) to keep track
|
||||
* of registered class objects: ISCM::ServerRegisterClsid et al
|
||||
* - Implement the OXID resolver so we don't need magic pipe names for
|
||||
|
@ -99,7 +101,8 @@ static void COM_ExternalLockFreeList(void);
|
|||
|
||||
const CLSID CLSID_StdGlobalInterfaceTable = { 0x00000323, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46} };
|
||||
|
||||
APARTMENT MTA, *apts;
|
||||
APARTMENT MTA;
|
||||
struct list apts = LIST_INIT( apts );
|
||||
|
||||
static CRITICAL_SECTION csApartment;
|
||||
static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||
|
@ -236,6 +239,7 @@ static void COM_UninitMTA(void)
|
|||
MTA.oxid = 0;
|
||||
}
|
||||
|
||||
|
||||
/* creates an apartment structure which stores OLE thread-local
|
||||
* information. Call with COINIT_UNINITIALIZED to create an apartment
|
||||
* that will be initialized with a model later. Note: do not call
|
||||
|
@ -243,93 +247,131 @@ static void COM_UninitMTA(void)
|
|||
* with a different COINIT value */
|
||||
APARTMENT* COM_CreateApartment(DWORD model)
|
||||
{
|
||||
APARTMENT *apt;
|
||||
BOOL create = (NtCurrentTeb()->ReservedForOle == NULL);
|
||||
APARTMENT *apt = COM_CurrentApt();
|
||||
|
||||
if (create)
|
||||
if (!apt)
|
||||
{
|
||||
if (model & COINIT_MULTITHREADED)
|
||||
{
|
||||
TRACE("thread 0x%lx is entering the multithreaded apartment\n", GetCurrentThreadId());
|
||||
COM_CurrentInfo()->apt = &MTA;
|
||||
return apt;
|
||||
}
|
||||
|
||||
TRACE("creating new apartment, model=%ld\n", model);
|
||||
|
||||
apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APARTMENT));
|
||||
apt->tid = GetCurrentThreadId();
|
||||
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
|
||||
GetCurrentProcess(), &apt->thread,
|
||||
THREAD_ALL_ACCESS, FALSE, 0);
|
||||
}
|
||||
else
|
||||
apt = NtCurrentTeb()->ReservedForOle;
|
||||
|
||||
list_init(&apt->proxies);
|
||||
list_init(&apt->stubmgrs);
|
||||
apt->oidc = 1;
|
||||
apt->refs = 1;
|
||||
InitializeCriticalSection(&apt->cs);
|
||||
|
||||
apt->model = model;
|
||||
if (model & COINIT_APARTMENTTHREADED) {
|
||||
|
||||
/* we don't ref the apartment as CoInitializeEx will do it for us */
|
||||
|
||||
if (model & COINIT_APARTMENTTHREADED)
|
||||
{
|
||||
/* FIXME: how does windoze create OXIDs? */
|
||||
apt->oxid = MTA.oxid | GetCurrentThreadId();
|
||||
apt->win = CreateWindowA(aptWinClass, NULL, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, OLE32_hInstance, NULL);
|
||||
InitializeCriticalSection(&apt->cs);
|
||||
}
|
||||
else if (!(model & COINIT_UNINITIALIZED)) {
|
||||
apt->parent = &MTA;
|
||||
apt->oxid = MTA.oxid;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&csApartment);
|
||||
if (create)
|
||||
{
|
||||
if (apts) apts->prev = apt;
|
||||
apt->next = apts;
|
||||
apts = apt;
|
||||
}
|
||||
list_add_head(&apts, &apt->entry);
|
||||
LeaveCriticalSection(&csApartment);
|
||||
NtCurrentTeb()->ReservedForOle = apt;
|
||||
|
||||
COM_CurrentInfo()->apt = apt;
|
||||
}
|
||||
|
||||
return apt;
|
||||
}
|
||||
|
||||
static void COM_DestroyApartment(APARTMENT *apt)
|
||||
DWORD COM_ApartmentAddRef(struct apartment *apt)
|
||||
{
|
||||
return InterlockedIncrement(&apt->refs);
|
||||
}
|
||||
|
||||
DWORD COM_ApartmentRelease(struct apartment *apt)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
EnterCriticalSection(&csApartment);
|
||||
if (apt->prev) apt->prev->next = apt->next;
|
||||
if (apt->next) apt->next->prev = apt->prev;
|
||||
if (apts == apt) apts = apt->next;
|
||||
apt->prev = NULL; apt->next = NULL;
|
||||
LeaveCriticalSection(&csApartment);
|
||||
if (apt->model & COINIT_APARTMENTTHREADED) {
|
||||
/* disconnect proxies to release the corresponding stubs.
|
||||
* It is confirmed in "Essential COM" in the sub-chapter on
|
||||
* "Lifecycle Management and Marshalling" that the native version also
|
||||
* disconnects proxies in this function. */
|
||||
/* FIXME: this should also be called for MTA destruction, but that
|
||||
* requires restructuring how apartments work slightly. */
|
||||
|
||||
ret = InterlockedDecrement(&apt->refs);
|
||||
if (ret == 0)
|
||||
{
|
||||
TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid));
|
||||
|
||||
MARSHAL_Disconnect_Proxies(apt);
|
||||
|
||||
if (apt->win) DestroyWindow(apt->win);
|
||||
DeleteCriticalSection(&apt->cs);
|
||||
list_remove(&apt->entry);
|
||||
if ((apt->model & COINIT_APARTMENTTHREADED) && apt->win) DestroyWindow(apt->win);
|
||||
|
||||
if (!list_empty(&apt->stubmgrs))
|
||||
{
|
||||
FIXME("PANIC: Apartment being destroyed with outstanding stubs, what do we do now?\n");
|
||||
}
|
||||
|
||||
if (apt->filter) IUnknown_Release(apt->filter);
|
||||
|
||||
|
||||
DeleteCriticalSection(&apt->cs);
|
||||
CloseHandle(apt->thread);
|
||||
HeapFree(GetProcessHeap(), 0, apt);
|
||||
}
|
||||
|
||||
/* The given OXID must be local to this process: you cannot use apartment
|
||||
windows to send RPCs to other processes. This all needs to move to rpcrt4 */
|
||||
apt = NULL;
|
||||
}
|
||||
|
||||
APARTMENT *COM_ApartmentFromOXID(OXID oxid)
|
||||
{
|
||||
APARTMENT *apt = NULL;
|
||||
|
||||
EnterCriticalSection(&csApartment);
|
||||
apt = apts;
|
||||
while (apt && apt->oxid != oxid) apt = apt->next;
|
||||
LeaveCriticalSection(&csApartment);
|
||||
|
||||
return apt;
|
||||
return ret;
|
||||
}
|
||||
|
||||
HWND COM_GetApartmentWin(OXID oxid)
|
||||
/* The given OXID must be local to this process: you cannot use
|
||||
* apartment windows to send RPCs to other processes. This all needs
|
||||
* to move to rpcrt4.
|
||||
*
|
||||
* The ref parameter is here mostly to ensure people remember that
|
||||
* they get one, you should normally take a ref for thread safety.
|
||||
*/
|
||||
APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref)
|
||||
{
|
||||
APARTMENT *apt = COM_ApartmentFromOXID(oxid);
|
||||
APARTMENT *result = NULL;
|
||||
struct list *cursor;
|
||||
|
||||
return apt ? apt->win : NULL;
|
||||
EnterCriticalSection(&csApartment);
|
||||
LIST_FOR_EACH( cursor, &apts )
|
||||
{
|
||||
struct apartment *apt = LIST_ENTRY( cursor, struct apartment, entry );
|
||||
if (apt->oxid == oxid)
|
||||
{
|
||||
result = apt;
|
||||
if (ref) COM_ApartmentAddRef(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&csApartment);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
HWND COM_GetApartmentWin(OXID oxid, BOOL ref)
|
||||
{
|
||||
APARTMENT *apt;
|
||||
|
||||
apt = COM_ApartmentFromOXID(oxid, ref);
|
||||
if (!apt) return NULL;
|
||||
|
||||
return apt->win;
|
||||
}
|
||||
|
||||
/* Currently inter-thread marshalling is not fully implemented, so this does nothing */
|
||||
|
@ -467,8 +509,7 @@ HRESULT WINAPI CoInitialize(
|
|||
* CoUninitialize
|
||||
*/
|
||||
HRESULT WINAPI CoInitializeEx(
|
||||
LPVOID lpReserved, /* [in] pointer to win32 malloc interface
|
||||
(obsolete, should be NULL) */
|
||||
LPVOID lpReserved, /* [in] pointer to win32 malloc interface (obsolete, should be NULL) */
|
||||
DWORD dwCoInit /* [in] A value from COINIT specifies the threading model */
|
||||
)
|
||||
{
|
||||
|
@ -482,21 +523,6 @@ HRESULT WINAPI CoInitializeEx(
|
|||
ERR("(%p, %x) - Bad parameter passed-in %p, must be an old Windows Application\n", lpReserved, (int)dwCoInit, lpReserved);
|
||||
}
|
||||
|
||||
apt = NtCurrentTeb()->ReservedForOle;
|
||||
if (apt && !(apt->model == COINIT_UNINITIALIZED))
|
||||
{
|
||||
if (dwCoInit != apt->model)
|
||||
{
|
||||
/* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine
|
||||
code then we are probably using the wrong threading model to implement that API. */
|
||||
ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit);
|
||||
return RPC_E_CHANGED_MODE;
|
||||
}
|
||||
hr = S_FALSE;
|
||||
}
|
||||
else
|
||||
hr = S_OK;
|
||||
|
||||
/*
|
||||
* Check the lock count. If this is the first time going through the initialize
|
||||
* process, we have to initialize the libraries.
|
||||
|
@ -512,13 +538,27 @@ HRESULT WINAPI CoInitializeEx(
|
|||
|
||||
COM_InitMTA();
|
||||
|
||||
/* we may need to defer this until after apartment initialisation */
|
||||
RunningObjectTableImpl_Initialize();
|
||||
}
|
||||
|
||||
if (!apt || apt->model == COINIT_UNINITIALIZED) apt = COM_CreateApartment(dwCoInit);
|
||||
if (!(apt = COM_CurrentInfo()->apt))
|
||||
{
|
||||
apt = COM_CreateApartment(dwCoInit);
|
||||
}
|
||||
else
|
||||
{
|
||||
InterlockedIncrement(&apt->refs);
|
||||
}
|
||||
|
||||
if (dwCoInit != apt->model)
|
||||
{
|
||||
/* Changing the threading model after it's been set is illegal. If this warning is triggered by Wine
|
||||
code then we are probably using the wrong threading model to implement that API. */
|
||||
ERR("Attempt to change threading model of this apartment from 0x%lx to 0x%lx\n", apt->model, dwCoInit);
|
||||
return RPC_E_CHANGED_MODE;
|
||||
}
|
||||
|
||||
InterlockedIncrement(&apt->inits);
|
||||
if (hr == S_OK) NtCurrentTeb()->ReservedForOle = apt;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
@ -529,14 +569,20 @@ HRESULT WINAPI CoInitializeEx(
|
|||
void COM_FlushMessageQueue(void)
|
||||
{
|
||||
MSG message;
|
||||
APARTMENT *apt = NtCurrentTeb()->ReservedForOle;
|
||||
APARTMENT *apt = COM_CurrentApt();
|
||||
|
||||
if (!apt || !apt->win) return;
|
||||
|
||||
TRACE("Flushing STA message queue\n");
|
||||
|
||||
while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (message.hwnd != apt->win) continue;
|
||||
while (PeekMessageA(&message, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (message.hwnd != apt->win)
|
||||
{
|
||||
WARN("discarding message 0x%x for window %p\n", message.message, message.hwnd);
|
||||
continue;
|
||||
}
|
||||
|
||||
TranslateMessage(&message);
|
||||
DispatchMessageA(&message);
|
||||
}
|
||||
|
@ -561,17 +607,11 @@ void COM_FlushMessageQueue(void)
|
|||
void WINAPI CoUninitialize(void)
|
||||
{
|
||||
LONG lCOMRefCnt;
|
||||
APARTMENT *apt;
|
||||
|
||||
TRACE("()\n");
|
||||
|
||||
apt = NtCurrentTeb()->ReservedForOle;
|
||||
if (!apt) return;
|
||||
if (InterlockedDecrement(&apt->inits)==0) {
|
||||
NtCurrentTeb()->ReservedForOle = NULL;
|
||||
COM_DestroyApartment(apt);
|
||||
apt = NULL;
|
||||
}
|
||||
if (!COM_ApartmentRelease(COM_CurrentInfo()->apt))
|
||||
COM_CurrentInfo()->apt = NULL;
|
||||
|
||||
/*
|
||||
* Decrease the reference count.
|
||||
|
@ -2000,19 +2040,19 @@ HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) {
|
|||
*/
|
||||
HRESULT WINAPI CoGetState(IUnknown ** ppv)
|
||||
{
|
||||
APARTMENT * apt = COM_CurrentInfo();
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
FIXME("\n");
|
||||
|
||||
if(apt && apt->state) {
|
||||
IUnknown_AddRef(apt->state);
|
||||
*ppv = apt->state;
|
||||
FIXME("-- %p\n", *ppv);
|
||||
return S_OK;
|
||||
}
|
||||
*ppv = NULL;
|
||||
return E_FAIL;
|
||||
|
||||
if (COM_CurrentInfo()->state)
|
||||
{
|
||||
IUnknown_AddRef(COM_CurrentInfo()->state);
|
||||
*ppv = COM_CurrentInfo()->state;
|
||||
TRACE("apt->state=%p\n", COM_CurrentInfo()->state);
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -2021,21 +2061,16 @@ HRESULT WINAPI CoGetState(IUnknown ** ppv)
|
|||
*/
|
||||
HRESULT WINAPI CoSetState(IUnknown * pv)
|
||||
{
|
||||
APARTMENT * apt = COM_CurrentInfo();
|
||||
if (pv) IUnknown_AddRef(pv);
|
||||
|
||||
if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED);
|
||||
|
||||
FIXME("(%p),stub!\n", pv);
|
||||
|
||||
if (pv) {
|
||||
IUnknown_AddRef(pv);
|
||||
if (COM_CurrentInfo()->state)
|
||||
{
|
||||
TRACE("-- release %p now\n", COM_CurrentInfo()->state);
|
||||
IUnknown_Release(COM_CurrentInfo()->state);
|
||||
}
|
||||
|
||||
if (apt->state) {
|
||||
TRACE("-- release %p now\n", apt->state);
|
||||
IUnknown_Release(apt->state);
|
||||
}
|
||||
apt->state = pv;
|
||||
COM_CurrentInfo()->state = pv;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,12 +38,8 @@
|
|||
#include "winreg.h"
|
||||
#include "winternl.h"
|
||||
|
||||
/* Windows maps COINIT values to 0x80 for apartment threaded, 0x140
|
||||
* for free threaded, and 0 for uninitialized apartments. There is
|
||||
* no real advantage in us doing this and certainly no release version
|
||||
* of an app should be poking around with these flags. So we need a
|
||||
* special value for uninitialized */
|
||||
#define COINIT_UNINITIALIZED 0x100
|
||||
struct apartment;
|
||||
|
||||
|
||||
/* exported interface */
|
||||
typedef struct tagXIF {
|
||||
|
@ -59,7 +55,7 @@ typedef struct tagXIF {
|
|||
/* exported object */
|
||||
typedef struct tagXOBJECT {
|
||||
IRpcStubBufferVtbl *lpVtbl;
|
||||
struct tagAPARTMENT *parent;
|
||||
struct apartment *parent;
|
||||
struct tagXOBJECT *next;
|
||||
LPUNKNOWN obj; /* object identity (IUnknown) */
|
||||
OID oid; /* object ID */
|
||||
|
@ -83,7 +79,7 @@ struct ifproxy
|
|||
struct proxy_manager
|
||||
{
|
||||
const IInternalUnknownVtbl *lpVtbl;
|
||||
struct tagAPARTMENT *parent;
|
||||
struct apartment *parent;
|
||||
struct list entry;
|
||||
LPRPCCHANNELBUFFER chan; /* channel to object */
|
||||
OXID oxid; /* object exported ID */
|
||||
|
@ -93,11 +89,13 @@ struct proxy_manager
|
|||
CRITICAL_SECTION cs; /* thread safety for this object and children */
|
||||
};
|
||||
|
||||
/* apartment */
|
||||
typedef struct tagAPARTMENT {
|
||||
struct tagAPARTMENT *next, *prev, *parent;
|
||||
/* this needs to become a COM object that implements IRemUnknown */
|
||||
struct apartment
|
||||
{
|
||||
struct list entry;
|
||||
|
||||
DWORD refs; /* refcount of the apartment */
|
||||
DWORD model; /* threading model */
|
||||
DWORD inits; /* CoInitialize count */
|
||||
DWORD tid; /* thread id */
|
||||
HANDLE thread; /* thread handle */
|
||||
OXID oxid; /* object exporter ID */
|
||||
|
@ -107,13 +105,11 @@ typedef struct tagAPARTMENT {
|
|||
LPMESSAGEFILTER filter; /* message filter */
|
||||
XOBJECT *objs; /* exported objects */
|
||||
struct list proxies; /* imported objects */
|
||||
LPUNKNOWN state; /* state object (see Co[Get,Set]State) */
|
||||
LPVOID ErrorInfo; /* thread error info */
|
||||
DWORD listenertid; /* id of apartment_listener_thread */
|
||||
struct list stubmgrs; /* stub managers for exported objects */
|
||||
} APARTMENT;
|
||||
};
|
||||
|
||||
extern APARTMENT MTA, *apts;
|
||||
typedef struct apartment APARTMENT;
|
||||
|
||||
extern void* StdGlobalInterfaceTable_Construct(void);
|
||||
extern void StdGlobalInterfaceTable_Destroy(void* self);
|
||||
|
@ -196,26 +192,40 @@ 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);
|
||||
DWORD COM_ApartmentAddRef(struct apartment *apt);
|
||||
DWORD COM_ApartmentRelease(struct apartment *apt);
|
||||
|
||||
extern CRITICAL_SECTION csApartment;
|
||||
|
||||
/* this is what is stored in TEB->ReservedForOle */
|
||||
struct oletls
|
||||
{
|
||||
struct apartment *apt;
|
||||
IErrorInfo *errorinfo; /* see errorinfo.c */
|
||||
IUnknown *state; /* see CoSetState */
|
||||
};
|
||||
|
||||
/*
|
||||
* Per-thread values are stored in the TEB on offset 0xF80,
|
||||
* see http://www.microsoft.com/msj/1099/bugslayer/bugslayer1099.htm
|
||||
*/
|
||||
static inline APARTMENT* COM_CurrentInfo(void)
|
||||
|
||||
/* will create if necessary */
|
||||
static inline struct oletls *COM_CurrentInfo(void)
|
||||
{
|
||||
APARTMENT* apt = NtCurrentTeb()->ReservedForOle;
|
||||
return apt;
|
||||
}
|
||||
static inline APARTMENT* COM_CurrentApt(void)
|
||||
{
|
||||
APARTMENT* apt = COM_CurrentInfo();
|
||||
if (apt && apt->parent) apt = apt->parent;
|
||||
return apt;
|
||||
if (!NtCurrentTeb()->ReservedForOle)
|
||||
NtCurrentTeb()->ReservedForOle = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct oletls));
|
||||
|
||||
return NtCurrentTeb()->ReservedForOle;
|
||||
}
|
||||
|
||||
/* compobj.c */
|
||||
APARTMENT *COM_CreateApartment(DWORD model);
|
||||
HWND COM_GetApartmentWin(OXID oxid);
|
||||
APARTMENT *COM_ApartmentFromOXID(OXID oxid);
|
||||
static inline APARTMENT* COM_CurrentApt(void)
|
||||
{
|
||||
return COM_CurrentInfo()->apt;
|
||||
}
|
||||
|
||||
#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* NOTES:
|
||||
*
|
||||
* The errorinfo is a per-thread object. The reference is stored in the
|
||||
* TEB at offset 0xf80
|
||||
* TEB at offset 0xf80.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
@ -483,20 +483,20 @@ HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo)
|
|||
*/
|
||||
HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo)
|
||||
{
|
||||
APARTMENT * apt = COM_CurrentInfo();
|
||||
|
||||
TRACE("(%ld, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->ErrorInfo);
|
||||
TRACE("(%ld, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->errorinfo);
|
||||
|
||||
if(!pperrinfo) return E_INVALIDARG;
|
||||
if (!apt || !apt->ErrorInfo)
|
||||
|
||||
if (!COM_CurrentInfo()->errorinfo)
|
||||
{
|
||||
*pperrinfo = NULL;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
*pperrinfo = (IErrorInfo*)(apt->ErrorInfo);
|
||||
*pperrinfo = COM_CurrentInfo()->errorinfo;
|
||||
|
||||
/* clear thread error state */
|
||||
apt->ErrorInfo = NULL;
|
||||
COM_CurrentInfo()->errorinfo = NULL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -506,18 +506,16 @@ HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo)
|
|||
HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo)
|
||||
{
|
||||
IErrorInfo * pei;
|
||||
APARTMENT * apt = COM_CurrentInfo();
|
||||
|
||||
TRACE("(%ld, %p)\n", dwReserved, perrinfo);
|
||||
|
||||
if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED);
|
||||
|
||||
/* release old errorinfo */
|
||||
pei = (IErrorInfo*)apt->ErrorInfo;
|
||||
if(pei) IErrorInfo_Release(pei);
|
||||
pei = COM_CurrentInfo()->errorinfo;
|
||||
if (pei) IErrorInfo_Release(pei);
|
||||
|
||||
/* set to new value */
|
||||
apt->ErrorInfo = perrinfo;
|
||||
if(perrinfo) IErrorInfo_AddRef(perrinfo);
|
||||
COM_CurrentInfo()->errorinfo = perrinfo;
|
||||
if (perrinfo) IErrorInfo_AddRef(perrinfo);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -109,9 +109,13 @@ static HRESULT register_ifstub(wine_marshal_id *mid, IUnknown *obj, IRpcStubBuff
|
|||
}
|
||||
else
|
||||
{
|
||||
struct apartment *apt;
|
||||
|
||||
TRACE("constructing new stub manager\n");
|
||||
|
||||
manager = new_stub_manager(COM_ApartmentFromOXID(mid->oxid), obj);
|
||||
apt = COM_ApartmentFromOXID(mid->oxid, TRUE);
|
||||
manager = new_stub_manager(apt, obj);
|
||||
COM_ApartmentRelease(apt);
|
||||
if (!manager) return E_OUTOFMEMORY;
|
||||
|
||||
if (!tablemarshal) stub_manager_ref(manager, 1);
|
||||
|
|
|
@ -308,8 +308,6 @@ PipeBuf_Release(LPRPCCHANNELBUFFER iface) {
|
|||
if (ref)
|
||||
return ref;
|
||||
|
||||
FIXME("Free all stuff\n");
|
||||
|
||||
memcpy(&header.mid, &This->mid, sizeof(wine_marshal_id));
|
||||
|
||||
pipe = PIPE_FindByMID(&This->mid);
|
||||
|
@ -892,7 +890,7 @@ static DWORD WINAPI apartment_listener_thread(LPVOID param)
|
|||
HANDLE listenPipe;
|
||||
APARTMENT *apt = (APARTMENT *) param;
|
||||
|
||||
/* we must join the marshalling threads apartment */
|
||||
/* we must join the marshalling threads apartment. we already have a ref here */
|
||||
NtCurrentTeb()->ReservedForOle = apt;
|
||||
|
||||
sprintf(pipefn,OLESTUBMGR"_%08lx%08lx", (DWORD)(apt->oxid >> 32), (DWORD)(apt->oxid));
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ole);
|
||||
|
||||
/* this refs the apartment on success, otherwise there is no ref */
|
||||
struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
|
||||
{
|
||||
struct stub_manager *sm;
|
||||
|
@ -71,6 +72,7 @@ struct stub_manager *new_stub_manager(APARTMENT *apt, IUnknown *object)
|
|||
list_add_head(&apt->stubmgrs, &sm->entry);
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
COM_ApartmentAddRef(apt);
|
||||
TRACE("Created new stub manager (oid=%s) at %p for object with IUnknown %p\n", wine_dbgstr_longlong(sm->oid), sm, object);
|
||||
|
||||
return sm;
|
||||
|
@ -82,7 +84,7 @@ struct stub_manager *get_stub_manager_from_object(OXID oxid, void *object)
|
|||
struct list *cursor;
|
||||
APARTMENT *apt;
|
||||
|
||||
if (!(apt = COM_ApartmentFromOXID(oxid)))
|
||||
if (!(apt = COM_ApartmentFromOXID(oxid, TRUE)))
|
||||
{
|
||||
WARN("Could not map OXID %s to apartment object\n", wine_dbgstr_longlong(oxid));
|
||||
return NULL;
|
||||
|
@ -101,6 +103,8 @@ 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);
|
||||
|
||||
return result;
|
||||
|
@ -112,14 +116,13 @@ struct stub_manager *get_stub_manager(OXID oxid, OID oid)
|
|||
struct list *cursor;
|
||||
APARTMENT *apt;
|
||||
|
||||
if (!(apt = COM_ApartmentFromOXID(oxid)))
|
||||
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 );
|
||||
|
@ -130,9 +133,10 @@ struct stub_manager *get_stub_manager(OXID oxid, OID oid)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&apt->cs);
|
||||
|
||||
COM_ApartmentRelease(apt);
|
||||
|
||||
TRACE("found %p from oid %s\n", result, wine_dbgstr_longlong(oid));
|
||||
|
||||
return result;
|
||||
|
|
Loading…
Reference in New Issue