- CoSetState info should be thread local.
- SetErrorInfo should allocate an apartment when no apartment present.
This commit is contained in:
parent
9d956b2395
commit
2eee76703d
|
@ -184,16 +184,27 @@ static void COM_UninitMTA(void)
|
||||||
MTA.oxid = 0;
|
MTA.oxid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static APARTMENT* COM_CreateApartment(DWORD model)
|
/* 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
|
||||||
|
* with COINIT_UNINITIALIZED if the apartment has already been initialized
|
||||||
|
* with a different COINIT value */
|
||||||
|
APARTMENT* COM_CreateApartment(DWORD model)
|
||||||
{
|
{
|
||||||
APARTMENT *apt;
|
APARTMENT *apt;
|
||||||
|
BOOL create = (NtCurrentTeb()->ReservedForOle == NULL);
|
||||||
|
|
||||||
|
if (create)
|
||||||
|
{
|
||||||
apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APARTMENT));
|
apt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(APARTMENT));
|
||||||
apt->model = model;
|
|
||||||
apt->tid = GetCurrentThreadId();
|
apt->tid = GetCurrentThreadId();
|
||||||
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
|
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
|
||||||
GetCurrentProcess(), &apt->thread,
|
GetCurrentProcess(), &apt->thread,
|
||||||
THREAD_ALL_ACCESS, FALSE, 0);
|
THREAD_ALL_ACCESS, FALSE, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
apt = NtCurrentTeb()->ReservedForOle;
|
||||||
|
apt->model = model;
|
||||||
if (model & COINIT_APARTMENTTHREADED) {
|
if (model & COINIT_APARTMENTTHREADED) {
|
||||||
/* FIXME: how does windoze create OXIDs? */
|
/* FIXME: how does windoze create OXIDs? */
|
||||||
apt->oxid = MTA.oxid | GetCurrentThreadId();
|
apt->oxid = MTA.oxid | GetCurrentThreadId();
|
||||||
|
@ -202,14 +213,17 @@ static APARTMENT* COM_CreateApartment(DWORD model)
|
||||||
0, 0, OLE32_hInstance, NULL);
|
0, 0, OLE32_hInstance, NULL);
|
||||||
InitializeCriticalSection(&apt->cs);
|
InitializeCriticalSection(&apt->cs);
|
||||||
}
|
}
|
||||||
else {
|
else if (!(model & COINIT_UNINITIALIZED)) {
|
||||||
apt->parent = &MTA;
|
apt->parent = &MTA;
|
||||||
apt->oxid = MTA.oxid;
|
apt->oxid = MTA.oxid;
|
||||||
}
|
}
|
||||||
EnterCriticalSection(&csApartment);
|
EnterCriticalSection(&csApartment);
|
||||||
|
if (create)
|
||||||
|
{
|
||||||
if (apts) apts->prev = apt;
|
if (apts) apts->prev = apt;
|
||||||
apt->next = apts;
|
apt->next = apts;
|
||||||
apts = apt;
|
apts = apt;
|
||||||
|
}
|
||||||
LeaveCriticalSection(&csApartment);
|
LeaveCriticalSection(&csApartment);
|
||||||
NtCurrentTeb()->ReservedForOle = apt;
|
NtCurrentTeb()->ReservedForOle = apt;
|
||||||
return apt;
|
return apt;
|
||||||
|
@ -384,8 +398,17 @@ HRESULT WINAPI CoInitializeEx(
|
||||||
}
|
}
|
||||||
|
|
||||||
apt = NtCurrentTeb()->ReservedForOle;
|
apt = NtCurrentTeb()->ReservedForOle;
|
||||||
if (apt && dwCoInit != apt->model) return RPC_E_CHANGED_MODE;
|
if (apt && !(apt->model == COINIT_UNINITIALIZED))
|
||||||
hr = apt ? S_FALSE : S_OK;
|
{
|
||||||
|
if (dwCoInit != apt->model)
|
||||||
|
{
|
||||||
|
WARN("Apartment threading model already initialized with another model\n");
|
||||||
|
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
|
* Check the lock count. If this is the first time going through the initialize
|
||||||
|
@ -405,7 +428,7 @@ HRESULT WINAPI CoInitializeEx(
|
||||||
RunningObjectTableImpl_Initialize();
|
RunningObjectTableImpl_Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!apt) apt = COM_CreateApartment(dwCoInit);
|
if (!apt || apt->model == COINIT_UNINITIALIZED) apt = COM_CreateApartment(dwCoInit);
|
||||||
|
|
||||||
InterlockedIncrement(&apt->inits);
|
InterlockedIncrement(&apt->inits);
|
||||||
if (hr == S_OK) NtCurrentTeb()->ReservedForOle = apt;
|
if (hr == S_OK) NtCurrentTeb()->ReservedForOle = apt;
|
||||||
|
@ -1861,7 +1884,6 @@ HRESULT WINAPI CoInitializeWOW(DWORD x,DWORD y) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IUnknown * pUnkState = 0; /* FIXME: thread local */
|
|
||||||
static int nStatCounter = 0; /* global */
|
static int nStatCounter = 0; /* global */
|
||||||
static HMODULE hOleAut32 = 0; /* global */
|
static HMODULE hOleAut32 = 0; /* global */
|
||||||
|
|
||||||
|
@ -1872,11 +1894,13 @@ static HMODULE hOleAut32 = 0; /* global */
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI CoGetState(IUnknown ** ppv)
|
HRESULT WINAPI CoGetState(IUnknown ** ppv)
|
||||||
{
|
{
|
||||||
|
APARTMENT * apt = COM_CurrentInfo();
|
||||||
|
|
||||||
FIXME("\n");
|
FIXME("\n");
|
||||||
|
|
||||||
if(pUnkState) {
|
if(apt && apt->state) {
|
||||||
IUnknown_AddRef(pUnkState);
|
IUnknown_AddRef(apt->state);
|
||||||
*ppv = pUnkState;
|
*ppv = apt->state;
|
||||||
FIXME("-- %p\n", *ppv);
|
FIXME("-- %p\n", *ppv);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1892,6 +1916,10 @@ HRESULT WINAPI CoGetState(IUnknown ** ppv)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI CoSetState(IUnknown * pv)
|
HRESULT WINAPI CoSetState(IUnknown * pv)
|
||||||
{
|
{
|
||||||
|
APARTMENT * apt = COM_CurrentInfo();
|
||||||
|
|
||||||
|
if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED);
|
||||||
|
|
||||||
FIXME("(%p),stub!\n", pv);
|
FIXME("(%p),stub!\n", pv);
|
||||||
|
|
||||||
if (pv) {
|
if (pv) {
|
||||||
|
@ -1900,13 +1928,13 @@ HRESULT WINAPI CoSetState(IUnknown * pv)
|
||||||
if (nStatCounter == 1) LoadLibraryA("OLEAUT32.DLL");
|
if (nStatCounter == 1) LoadLibraryA("OLEAUT32.DLL");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pUnkState) {
|
if (apt->state) {
|
||||||
TRACE("-- release %p now\n", pUnkState);
|
TRACE("-- release %p now\n", apt->state);
|
||||||
IUnknown_Release(pUnkState);
|
IUnknown_Release(apt->state);
|
||||||
nStatCounter--;
|
nStatCounter--;
|
||||||
if (!nStatCounter) FreeLibrary(hOleAut32);
|
if (!nStatCounter) FreeLibrary(hOleAut32);
|
||||||
}
|
}
|
||||||
pUnkState = pv;
|
apt->state = pv;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,13 @@
|
||||||
#include "winreg.h"
|
#include "winreg.h"
|
||||||
#include "winternl.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
|
||||||
|
|
||||||
/* exported interface */
|
/* exported interface */
|
||||||
typedef struct tagXIF {
|
typedef struct tagXIF {
|
||||||
struct tagXIF *next;
|
struct tagXIF *next;
|
||||||
|
@ -96,6 +103,7 @@ typedef struct tagAPARTMENT {
|
||||||
LPMESSAGEFILTER filter; /* message filter */
|
LPMESSAGEFILTER filter; /* message filter */
|
||||||
XOBJECT *objs; /* exported objects */
|
XOBJECT *objs; /* exported objects */
|
||||||
IOBJECT *proxies; /* imported objects */
|
IOBJECT *proxies; /* imported objects */
|
||||||
|
LPUNKNOWN state; /* state object (see Co[Get,Set]State) */
|
||||||
LPVOID ErrorInfo; /* thread error info */
|
LPVOID ErrorInfo; /* thread error info */
|
||||||
} APARTMENT;
|
} APARTMENT;
|
||||||
|
|
||||||
|
@ -217,6 +225,7 @@ static inline APARTMENT* COM_CurrentApt(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* compobj.c */
|
/* compobj.c */
|
||||||
|
APARTMENT* COM_CreateApartment(DWORD model);
|
||||||
HWND COM_GetApartmentWin(OXID oxid);
|
HWND COM_GetApartmentWin(OXID oxid);
|
||||||
|
|
||||||
#endif /* __WINE_OLE_COMPOBJ_H */
|
#endif /* __WINE_OLE_COMPOBJ_H */
|
||||||
|
|
|
@ -484,13 +484,20 @@ HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo)
|
HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo)
|
||||||
{
|
{
|
||||||
TRACE("(%ld, %p, %p): stub:\n", dwReserved, pperrinfo, COM_CurrentInfo()->ErrorInfo);
|
APARTMENT * apt = COM_CurrentInfo();
|
||||||
|
|
||||||
if(! pperrinfo ) return E_INVALIDARG;
|
TRACE("(%ld, %p, %p)\n", dwReserved, pperrinfo, COM_CurrentInfo()->ErrorInfo);
|
||||||
if(!(*pperrinfo = (IErrorInfo*)(COM_CurrentInfo()->ErrorInfo))) return S_FALSE;
|
|
||||||
|
|
||||||
|
if(!pperrinfo) return E_INVALIDARG;
|
||||||
|
if (!apt || !apt->ErrorInfo)
|
||||||
|
{
|
||||||
|
*pperrinfo = NULL;
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pperrinfo = (IErrorInfo*)(apt->ErrorInfo);
|
||||||
/* clear thread error state */
|
/* clear thread error state */
|
||||||
COM_CurrentInfo()->ErrorInfo = NULL;
|
apt->ErrorInfo = NULL;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,14 +507,18 @@ HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo)
|
||||||
HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo)
|
HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo)
|
||||||
{
|
{
|
||||||
IErrorInfo * pei;
|
IErrorInfo * pei;
|
||||||
TRACE("(%ld, %p): stub:\n", dwReserved, perrinfo);
|
APARTMENT * apt = COM_CurrentInfo();
|
||||||
|
|
||||||
|
TRACE("(%ld, %p)\n", dwReserved, perrinfo);
|
||||||
|
|
||||||
|
if (!apt) apt = COM_CreateApartment(COINIT_UNINITIALIZED);
|
||||||
|
|
||||||
/* release old errorinfo */
|
/* release old errorinfo */
|
||||||
pei = (IErrorInfo*)COM_CurrentInfo()->ErrorInfo;
|
pei = (IErrorInfo*)apt->ErrorInfo;
|
||||||
if(pei) IErrorInfo_Release(pei);
|
if(pei) IErrorInfo_Release(pei);
|
||||||
|
|
||||||
/* set to new value */
|
/* set to new value */
|
||||||
COM_CurrentInfo()->ErrorInfo = perrinfo;
|
apt->ErrorInfo = perrinfo;
|
||||||
if(perrinfo) IErrorInfo_AddRef(perrinfo);
|
if(perrinfo) IErrorInfo_AddRef(perrinfo);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue