Commit e00ea31d authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

combase: Move local proxy-stub registration functions.

parent 5e1753f0
......@@ -59,6 +59,18 @@ struct comclassredirect_data
DWORD miscstatusdocprint;
};
struct ifacepsredirect_data
{
ULONG size;
DWORD mask;
GUID iid;
ULONG nummethods;
GUID tlbid;
GUID base;
ULONG name_len;
ULONG name_offset;
};
struct progidredirect_data
{
ULONG size;
......@@ -73,6 +85,26 @@ struct init_spy
unsigned int id;
};
struct registered_ps
{
struct list entry;
IID iid;
CLSID clsid;
};
static struct list registered_proxystubs = LIST_INIT(registered_proxystubs);
static CRITICAL_SECTION cs_registered_ps;
static CRITICAL_SECTION_DEBUG psclsid_cs_debug =
{
0, 0, &cs_registered_ps,
{ &psclsid_cs_debug.ProcessLocksList, &psclsid_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": cs_registered_psclsid_list") }
};
static CRITICAL_SECTION cs_registered_ps = { &psclsid_cs_debug, -1, 0, 0, 0, 0 };
extern BOOL WINAPI InternalIsInitialized(void);
static struct init_spy *get_spy_entry(struct tlsdata *tlsdata, unsigned int id)
{
struct init_spy *spy;
......@@ -1721,3 +1753,148 @@ HRESULT WINAPI CoRegisterMessageFilter(IMessageFilter *filter, IMessageFilter **
return S_OK;
}
void WINAPI InternalRevokeAllPSClsids(void)
{
struct registered_ps *cur, *cur2;
EnterCriticalSection(&cs_registered_ps);
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &registered_proxystubs, struct registered_ps, entry)
{
list_remove(&cur->entry);
heap_free(cur);
}
LeaveCriticalSection(&cs_registered_ps);
}
static HRESULT get_ps_clsid_from_registry(const WCHAR* path, REGSAM access, CLSID *pclsid)
{
WCHAR value[CHARS_IN_GUID];
HKEY hkey;
DWORD len;
access |= KEY_READ;
if (open_classes_key(HKEY_CLASSES_ROOT, path, access, &hkey))
return REGDB_E_IIDNOTREG;
len = sizeof(value);
if (ERROR_SUCCESS != RegQueryValueExW(hkey, NULL, NULL, NULL, (BYTE *)value, &len))
return REGDB_E_IIDNOTREG;
RegCloseKey(hkey);
if (CLSIDFromString(value, pclsid) != NOERROR)
return REGDB_E_IIDNOTREG;
return S_OK;
}
/*****************************************************************************
* CoGetPSClsid (combase.@)
*/
HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
{
static const WCHAR interfaceW[] = L"Interface\\";
static const WCHAR psW[] = L"\\ProxyStubClsid32";
WCHAR path[ARRAY_SIZE(interfaceW) - 1 + CHARS_IN_GUID - 1 + ARRAY_SIZE(psW)];
ACTCTX_SECTION_KEYED_DATA data;
struct registered_ps *cur;
REGSAM opposite = (sizeof(void*) > sizeof(int)) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
BOOL is_wow64;
HRESULT hr;
TRACE("%s, %p\n", debugstr_guid(riid), pclsid);
if (!InternalIsInitialized())
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
if (!pclsid)
return E_INVALIDARG;
EnterCriticalSection(&cs_registered_ps);
LIST_FOR_EACH_ENTRY(cur, &registered_proxystubs, struct registered_ps, entry)
{
if (IsEqualIID(&cur->iid, riid))
{
*pclsid = cur->clsid;
LeaveCriticalSection(&cs_registered_ps);
return S_OK;
}
}
LeaveCriticalSection(&cs_registered_ps);
data.cbSize = sizeof(data);
if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
riid, &data))
{
struct ifacepsredirect_data *ifaceps = (struct ifacepsredirect_data *)data.lpData;
*pclsid = ifaceps->iid;
return S_OK;
}
/* Interface\\{string form of riid}\\ProxyStubClsid32 */
lstrcpyW(path, interfaceW);
StringFromGUID2(riid, path + ARRAY_SIZE(interfaceW) - 1, CHARS_IN_GUID);
lstrcpyW(path + ARRAY_SIZE(interfaceW) - 1 + CHARS_IN_GUID - 1, psW);
hr = get_ps_clsid_from_registry(path, 0, pclsid);
if (FAILED(hr) && (opposite == KEY_WOW64_32KEY || (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
hr = get_ps_clsid_from_registry(path, opposite, pclsid);
if (hr == S_OK)
TRACE("() Returning CLSID %s\n", debugstr_guid(pclsid));
else
WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid));
return hr;
}
/*****************************************************************************
* CoRegisterPSClsid (combase.@)
*/
HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
{
struct registered_ps *cur;
TRACE("%s, %s\n", debugstr_guid(riid), debugstr_guid(rclsid));
if (!InternalIsInitialized())
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
EnterCriticalSection(&cs_registered_ps);
LIST_FOR_EACH_ENTRY(cur, &registered_proxystubs, struct registered_ps, entry)
{
if (IsEqualIID(&cur->iid, riid))
{
cur->clsid = *rclsid;
LeaveCriticalSection(&cs_registered_ps);
return S_OK;
}
}
cur = heap_alloc(sizeof(*cur));
if (!cur)
{
LeaveCriticalSection(&cs_registered_ps);
return E_OUTOFMEMORY;
}
cur->iid = *riid;
cur->clsid = *rclsid;
list_add_head(&registered_proxystubs, &cur->entry);
LeaveCriticalSection(&cs_registered_ps);
return S_OK;
}
......@@ -115,7 +115,7 @@
@ stdcall CoGetMarshalSizeMax(ptr ptr ptr long ptr long)
@ stub CoGetModuleType
@ stdcall CoGetObjectContext(ptr ptr)
@ stdcall CoGetPSClsid(ptr ptr) ole32.CoGetPSClsid
@ stdcall CoGetPSClsid(ptr ptr)
@ stub CoGetProcessIdentifier
@ stdcall CoGetStandardMarshal(ptr ptr long ptr long ptr) ole32.CoGetStandardMarshal
@ stub CoGetStdMarshalEx
......@@ -143,7 +143,7 @@
@ stdcall CoRegisterInitializeSpy(ptr ptr)
@ stdcall CoRegisterMallocSpy(ptr)
@ stdcall CoRegisterMessageFilter(ptr ptr)
@ stdcall CoRegisterPSClsid(ptr ptr) ole32.CoRegisterPSClsid
@ stdcall CoRegisterPSClsid(ptr ptr)
@ stdcall CoRegisterSurrogate(ptr) ole32.CoRegisterSurrogate
@ stdcall CoRegisterSurrogateEx(ptr ptr) ole32.CoRegisterSurrogateEx
@ stdcall CoReleaseMarshalData(ptr) ole32.CoReleaseMarshalData
......@@ -268,6 +268,7 @@
@ stub InternalNotifyDDStartOrStop
@ stub InternalOleModalLoopBlockFn
@ stub InternalRegisterWindowPropInterface
@ stdcall InternalRevokeAllPSClsids()
@ stub InternalReleaseMarshalObjRef
@ stub InternalSTAInvoke
@ stub InternalServerExceptionFilter
......
......@@ -164,24 +164,6 @@ struct class_reg_data
} u;
};
struct registered_psclsid
{
struct list entry;
IID iid;
CLSID clsid;
};
static struct list registered_psclsid_list = LIST_INIT(registered_psclsid_list);
static CRITICAL_SECTION cs_registered_psclsid_list;
static CRITICAL_SECTION_DEBUG psclsid_cs_debug =
{
0, 0, &cs_registered_psclsid_list,
{ &psclsid_cs_debug.ProcessLocksList, &psclsid_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": cs_registered_psclsid_list") }
};
static CRITICAL_SECTION cs_registered_psclsid_list = { &psclsid_cs_debug, -1, 0, 0, 0, 0 };
/*
* This is a marshallable object exposing registered local servers.
* IServiceProvider is used only because it happens meet requirements
......@@ -236,6 +218,8 @@ static CRITICAL_SECTION_DEBUG class_cs_debug =
};
static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0, 0 };
extern void WINAPI InternalRevokeAllPSClsids(void);
static inline enum comclass_miscfields dvaspect_to_miscfields(DWORD aspect)
{
switch (aspect)
......@@ -776,21 +760,6 @@ static void COM_RevokeAllClasses(const struct apartment *apt)
LeaveCriticalSection( &csRegisteredClassList );
}
static void revoke_registered_psclsids(void)
{
struct registered_psclsid *psclsid, *psclsid2;
EnterCriticalSection( &cs_registered_psclsid_list );
LIST_FOR_EACH_ENTRY_SAFE(psclsid, psclsid2, &registered_psclsid_list, struct registered_psclsid, entry)
{
list_remove(&psclsid->entry);
HeapFree(GetProcessHeap(), 0, psclsid);
}
LeaveCriticalSection( &cs_registered_psclsid_list );
}
/******************************************************************************
* Implementation of the manual reset event object. (CLSID_ManualResetEvent)
*/
......@@ -1997,7 +1966,7 @@ void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
{
TRACE("() - Releasing the COM libraries\n");
revoke_registered_psclsids();
InternalRevokeAllPSClsids();
RunningObjectTableImpl_UnInitialize();
}
else if (lCOMRefCnt<1) {
......@@ -2145,193 +2114,6 @@ HRESULT COM_OpenKeyForAppIdFromCLSID(REFCLSID clsid, REGSAM access, HKEY *subkey
return S_OK;
}
static HRESULT get_ps_clsid_from_registry(const WCHAR* path, REGSAM access, CLSID *pclsid)
{
HKEY hkey;
WCHAR value[CHARS_IN_GUID];
DWORD len;
access |= KEY_READ;
if (open_classes_key(HKEY_CLASSES_ROOT, path, access, &hkey))
return REGDB_E_IIDNOTREG;
len = sizeof(value);
if (ERROR_SUCCESS != RegQueryValueExW(hkey, NULL, NULL, NULL, (BYTE *)value, &len))
return REGDB_E_IIDNOTREG;
RegCloseKey(hkey);
if (CLSIDFromString(value, pclsid) != NOERROR)
return REGDB_E_IIDNOTREG;
return S_OK;
}
/*****************************************************************************
* CoGetPSClsid [OLE32.@]
*
* Retrieves the CLSID of the proxy/stub factory that implements
* IPSFactoryBuffer for the specified interface.
*
* PARAMS
* riid [I] Interface whose proxy/stub CLSID is to be returned.
* pclsid [O] Where to store returned proxy/stub CLSID.
*
* RETURNS
* S_OK
* E_OUTOFMEMORY
* REGDB_E_IIDNOTREG if no PSFactoryBuffer is associated with the IID, or it could not be parsed
*
* NOTES
*
* The standard marshaller activates the object with the CLSID
* returned and uses the CreateProxy and CreateStub methods on its
* IPSFactoryBuffer interface to construct the proxies and stubs for a
* given object.
*
* CoGetPSClsid determines this CLSID by searching the
* HKEY_CLASSES_ROOT\Interface\{string form of riid}\ProxyStubClsid32
* in the registry and any interface id registered by
* CoRegisterPSClsid within the current process.
*
* BUGS
*
* Native returns S_OK for interfaces with a key in HKCR\Interface, but
* without a ProxyStubClsid32 key and leaves garbage in pclsid. This should be
* considered a bug in native unless an application depends on this (unlikely).
*
* SEE ALSO
* CoRegisterPSClsid.
*/
HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
{
static const WCHAR wszInterface[] = {'I','n','t','e','r','f','a','c','e','\\',0};
static const WCHAR wszPSC[] = {'\\','P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
WCHAR path[ARRAY_SIZE(wszInterface) - 1 + CHARS_IN_GUID - 1 + ARRAY_SIZE(wszPSC)];
APARTMENT *apt;
struct registered_psclsid *registered_psclsid;
ACTCTX_SECTION_KEYED_DATA data;
HRESULT hr;
REGSAM opposite = (sizeof(void*) > sizeof(int)) ? KEY_WOW64_32KEY : KEY_WOW64_64KEY;
BOOL is_wow64;
TRACE("() riid=%s, pclsid=%p\n", debugstr_guid(riid), pclsid);
if (!(apt = apartment_get_current_or_mta()))
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
apartment_release(apt);
if (!pclsid)
return E_INVALIDARG;
EnterCriticalSection(&cs_registered_psclsid_list);
LIST_FOR_EACH_ENTRY(registered_psclsid, &registered_psclsid_list, struct registered_psclsid, entry)
if (IsEqualIID(&registered_psclsid->iid, riid))
{
*pclsid = registered_psclsid->clsid;
LeaveCriticalSection(&cs_registered_psclsid_list);
return S_OK;
}
LeaveCriticalSection(&cs_registered_psclsid_list);
data.cbSize = sizeof(data);
if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION,
riid, &data))
{
struct ifacepsredirect_data *ifaceps = (struct ifacepsredirect_data*)data.lpData;
*pclsid = ifaceps->iid;
return S_OK;
}
/* Interface\\{string form of riid}\\ProxyStubClsid32 */
lstrcpyW(path, wszInterface);
StringFromGUID2(riid, path + ARRAY_SIZE(wszInterface) - 1, CHARS_IN_GUID);
lstrcpyW(path + ARRAY_SIZE(wszInterface) - 1 + CHARS_IN_GUID - 1, wszPSC);
hr = get_ps_clsid_from_registry(path, 0, pclsid);
if (FAILED(hr) && (opposite == KEY_WOW64_32KEY ||
(IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)))
hr = get_ps_clsid_from_registry(path, opposite, pclsid);
if (hr == S_OK)
TRACE ("() Returning CLSID=%s\n", debugstr_guid(pclsid));
else
WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid));
return hr;
}
/*****************************************************************************
* CoRegisterPSClsid [OLE32.@]
*
* Register a proxy/stub CLSID for the given interface in the current process
* only.
*
* PARAMS
* riid [I] Interface whose proxy/stub CLSID is to be registered.
* rclsid [I] CLSID of the proxy/stub.
*
* RETURNS
* Success: S_OK
* Failure: E_OUTOFMEMORY
*
* NOTES
*
* Unlike CoRegisterClassObject(), CLSIDs registered with CoRegisterPSClsid()
* will be returned from other apartments in the same process.
*
* This function does not add anything to the registry and the effects are
* limited to the lifetime of the current process.
*
* SEE ALSO
* CoGetPSClsid.
*/
HRESULT WINAPI CoRegisterPSClsid(REFIID riid, REFCLSID rclsid)
{
APARTMENT *apt;
struct registered_psclsid *registered_psclsid;
TRACE("(%s, %s)\n", debugstr_guid(riid), debugstr_guid(rclsid));
if (!(apt = apartment_get_current_or_mta()))
{
ERR("apartment not initialised\n");
return CO_E_NOTINITIALIZED;
}
apartment_release(apt);
EnterCriticalSection(&cs_registered_psclsid_list);
LIST_FOR_EACH_ENTRY(registered_psclsid, &registered_psclsid_list, struct registered_psclsid, entry)
if (IsEqualIID(&registered_psclsid->iid, riid))
{
registered_psclsid->clsid = *rclsid;
LeaveCriticalSection(&cs_registered_psclsid_list);
return S_OK;
}
registered_psclsid = HeapAlloc(GetProcessHeap(), 0, sizeof(struct registered_psclsid));
if (!registered_psclsid)
{
LeaveCriticalSection(&cs_registered_psclsid_list);
return E_OUTOFMEMORY;
}
registered_psclsid->iid = *riid;
registered_psclsid->clsid = *rclsid;
list_add_head(&registered_psclsid_list, &registered_psclsid->entry);
LeaveCriticalSection(&cs_registered_psclsid_list);
return S_OK;
}
/***
* COM_GetRegisteredClassObject
*
......@@ -3872,6 +3654,17 @@ HRESULT WINAPI CoRegisterSurrogateEx(REFGUID guid, void *reserved)
return E_NOTIMPL;
}
BOOL WINAPI InternalIsInitialized(void)
{
struct apartment *apt;
if (!(apt = apartment_get_current_or_mta()))
return FALSE;
apartment_release(apt);
return TRUE;
}
typedef struct {
IGlobalOptions IGlobalOptions_iface;
LONG ref;
......
......@@ -42,7 +42,7 @@
@ stdcall CoGetMarshalSizeMax(ptr ptr ptr long ptr long) combase.CoGetMarshalSizeMax
@ stdcall CoGetObject(wstr ptr ptr ptr)
@ stdcall CoGetObjectContext(ptr ptr) combase.CoGetObjectContext
@ stdcall CoGetPSClsid(ptr ptr)
@ stdcall CoGetPSClsid(ptr ptr) combase.CoGetPSClsid
@ stdcall CoGetStandardMarshal(ptr ptr long ptr long ptr)
@ stdcall CoGetState(ptr)
@ stub CoGetTIDFromIPID
......@@ -69,7 +69,7 @@
@ stdcall CoRegisterInitializeSpy(ptr ptr) combase.CoRegisterInitializeSpy
@ stdcall CoRegisterMallocSpy(ptr) combase.CoRegisterMallocSpy
@ stdcall CoRegisterMessageFilter(ptr ptr) combase.CoRegisterMessageFilter
@ stdcall CoRegisterPSClsid(ptr ptr)
@ stdcall CoRegisterPSClsid(ptr ptr) combase.CoRegisterPSClsid
@ stdcall CoRegisterSurrogate(ptr)
@ stdcall CoRegisterSurrogateEx(ptr ptr)
@ stdcall CoReleaseMarshalData(ptr)
......@@ -297,3 +297,4 @@
@ stdcall WriteFmtUserTypeStg(ptr long ptr)
@ stub WriteOleStg
@ stub WriteStringStream
@ stdcall InternalIsInitialized()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment