combase: Move CoGetTreatAsClass().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2020-08-10 11:12:49 +03:00 committed by Alexandre Julliard
parent 9fa68c5d29
commit ea8d11a8e5
4 changed files with 205 additions and 52 deletions

View File

@ -20,14 +20,179 @@
#define COBJMACROS
#define NONAMELESSUNION
#include "ntstatus.h"
#define WIN32_NO_STATUS
#define USE_COM_CONTEXT_DEF
#include "objbase.h"
#include "oleauto.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
#define CHARS_IN_GUID 39
static NTSTATUS create_key(HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr)
{
NTSTATUS status = NtCreateKey((HANDLE *)retkey, access, attr, 0, NULL, 0, NULL);
if (status == STATUS_OBJECT_NAME_NOT_FOUND)
{
HANDLE subkey, root = attr->RootDirectory;
WCHAR *buffer = attr->ObjectName->Buffer;
DWORD attrs, pos = 0, i = 0, len = attr->ObjectName->Length / sizeof(WCHAR);
UNICODE_STRING str;
while (i < len && buffer[i] != '\\') i++;
if (i == len) return status;
attrs = attr->Attributes;
attr->ObjectName = &str;
while (i < len)
{
str.Buffer = buffer + pos;
str.Length = (i - pos) * sizeof(WCHAR);
status = NtCreateKey(&subkey, access, attr, 0, NULL, 0, NULL);
if (attr->RootDirectory != root) NtClose(attr->RootDirectory);
if (status) return status;
attr->RootDirectory = subkey;
while (i < len && buffer[i] == '\\') i++;
pos = i;
while (i < len && buffer[i] != '\\') i++;
}
str.Buffer = buffer + pos;
str.Length = (i - pos) * sizeof(WCHAR);
attr->Attributes = attrs;
status = NtCreateKey((HANDLE *)retkey, access, attr, 0, NULL, 0, NULL);
if (attr->RootDirectory != root) NtClose(attr->RootDirectory);
}
return status;
}
static HKEY classes_root_hkey;
static HKEY create_classes_root_hkey(DWORD access)
{
HKEY hkey, ret = 0;
OBJECT_ATTRIBUTES attr;
UNICODE_STRING name;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &name;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString(&name, L"\\Registry\\Machine\\Software\\Classes");
if (create_key( &hkey, access, &attr )) return 0;
TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey );
if (!(access & KEY_WOW64_64KEY))
{
if (!(ret = InterlockedCompareExchangePointer( (void **)&classes_root_hkey, hkey, 0 )))
ret = hkey;
else
NtClose( hkey ); /* somebody beat us to it */
}
else
ret = hkey;
return ret;
}
static HKEY get_classes_root_hkey(HKEY hkey, REGSAM access);
static LSTATUS create_classes_key(HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey)
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
if (!(hkey = get_classes_root_hkey(hkey, access)))
return ERROR_INVALID_HANDLE;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError(create_key(retkey, access, &attr));
}
static HKEY get_classes_root_hkey(HKEY hkey, REGSAM access)
{
HKEY ret = hkey;
const BOOL is_win64 = sizeof(void*) > sizeof(int);
const BOOL force_wow32 = is_win64 && (access & KEY_WOW64_32KEY);
if (hkey == HKEY_CLASSES_ROOT &&
((access & KEY_WOW64_64KEY) || !(ret = classes_root_hkey)))
ret = create_classes_root_hkey(MAXIMUM_ALLOWED | (access & KEY_WOW64_64KEY));
if (force_wow32 && ret && ret == classes_root_hkey)
{
access &= ~KEY_WOW64_32KEY;
if (create_classes_key(classes_root_hkey, L"Wow6432Node", access, &hkey))
return 0;
ret = hkey;
}
return ret;
}
static LSTATUS open_classes_key(HKEY hkey, const WCHAR *name, REGSAM access, HKEY *retkey)
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
if (!(hkey = get_classes_root_hkey(hkey, access)))
return ERROR_INVALID_HANDLE;
attr.Length = sizeof(attr);
attr.RootDirectory = hkey;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, name );
return RtlNtStatusToDosError(NtOpenKey((HANDLE *)retkey, access, &attr));
}
static HRESULT open_key_for_clsid(REFCLSID clsid, const WCHAR *keyname, REGSAM access, HKEY *subkey)
{
static const WCHAR clsidW[] = L"CLSID\\";
WCHAR path[CHARS_IN_GUID + ARRAY_SIZE(clsidW) - 1];
LONG res;
HKEY key;
lstrcpyW(path, clsidW);
StringFromGUID2(clsid, path + lstrlenW(clsidW), CHARS_IN_GUID);
res = open_classes_key(HKEY_CLASSES_ROOT, path, keyname ? KEY_READ : access, &key);
if (res == ERROR_FILE_NOT_FOUND)
return REGDB_E_CLASSNOTREG;
else if (res != ERROR_SUCCESS)
return REGDB_E_READREGDB;
if (!keyname)
{
*subkey = key;
return S_OK;
}
res = open_classes_key(key, keyname, access, subkey);
RegCloseKey(key);
if (res == ERROR_FILE_NOT_FOUND)
return REGDB_E_KEYMISSING;
else if (res != ERROR_SUCCESS)
return REGDB_E_READREGDB;
return S_OK;
}
/***********************************************************************
* FreePropVariantArray (combase.@)
*/
@ -628,6 +793,44 @@ HRESULT WINAPI CoGetActivationState(GUID guid, DWORD arg2, DWORD *arg3)
return E_NOTIMPL;
}
/******************************************************************************
* CoGetTreatAsClass (combase.@)
*/
HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, CLSID *clsidNew)
{
WCHAR buffW[CHARS_IN_GUID];
LONG len = sizeof(buffW);
HRESULT hr = S_OK;
HKEY hkey = NULL;
TRACE("%s, %p.\n", debugstr_guid(clsidOld), clsidNew);
if (!clsidOld || !clsidNew)
return E_INVALIDARG;
*clsidNew = *clsidOld;
hr = open_key_for_clsid(clsidOld, L"TreatAs", KEY_READ, &hkey);
if (FAILED(hr))
{
hr = S_FALSE;
goto done;
}
if (RegQueryValueW(hkey, NULL, buffW, &len))
{
hr = S_FALSE;
goto done;
}
hr = CLSIDFromString(buffW, clsidNew);
if (FAILED(hr))
ERR("Failed to get CLSID from string %s, hr %#x.\n", debugstr_w(buffW), hr);
done:
if (hkey) RegCloseKey(hkey);
return hr;
}
static void init_multi_qi(DWORD count, MULTI_QI *mqi, HRESULT hr)
{
ULONG i;

View File

@ -119,7 +119,7 @@
@ stdcall CoGetStandardMarshal(ptr ptr long ptr long ptr) ole32.CoGetStandardMarshal
@ stub CoGetStdMarshalEx
@ stub CoGetSystemSecurityPermissions
@ stdcall CoGetTreatAsClass(ptr ptr) ole32.CoGetTreatAsClass
@ stdcall CoGetTreatAsClass(ptr ptr)
@ stdcall CoImpersonateClient()
@ stdcall CoIncrementMTAUsage(ptr) ole32.CoIncrementMTAUsage
@ stdcall CoInitializeEx(ptr long) ole32.CoInitializeEx

View File

@ -3707,56 +3707,6 @@ done:
return res;
}
/******************************************************************************
* CoGetTreatAsClass [OLE32.@]
*
* Gets the TreatAs value of a class.
*
* PARAMS
* clsidOld [I] Class to get the TreatAs value of.
* clsidNew [I] The class the clsidOld should be treated as.
*
* RETURNS
* Success: S_OK.
* Failure: HRESULT code.
*
* SEE ALSO
* CoSetTreatAsClass
*/
HRESULT WINAPI CoGetTreatAsClass(REFCLSID clsidOld, LPCLSID clsidNew)
{
static const WCHAR wszTreatAs[] = {'T','r','e','a','t','A','s',0};
HKEY hkey = NULL;
WCHAR szClsidNew[CHARS_IN_GUID];
HRESULT res = S_OK;
LONG len = sizeof(szClsidNew);
TRACE("(%s,%p)\n", debugstr_guid(clsidOld), clsidNew);
if (!clsidOld || !clsidNew)
return E_INVALIDARG;
*clsidNew = *clsidOld; /* copy over old value */
res = COM_OpenKeyForCLSID(clsidOld, wszTreatAs, KEY_READ, &hkey);
if (FAILED(res))
{
res = S_FALSE;
goto done;
}
if (RegQueryValueW(hkey, NULL, szClsidNew, &len))
{
res = S_FALSE;
goto done;
}
res = CLSIDFromString(szClsidNew,clsidNew);
if (FAILED(res))
ERR("Failed CLSIDFromStringA(%s), hres 0x%08x\n", debugstr_w(szClsidNew), res);
done:
if (hkey) RegCloseKey(hkey);
return res;
}
/******************************************************************************
* CoGetCurrentProcess [OLE32.@]
*/

View File

@ -46,7 +46,7 @@
@ stdcall CoGetStandardMarshal(ptr ptr long ptr long ptr)
@ stdcall CoGetState(ptr)
@ stub CoGetTIDFromIPID
@ stdcall CoGetTreatAsClass(ptr ptr)
@ stdcall CoGetTreatAsClass(ptr ptr) combase.CoGetTreatAsClass
@ stdcall CoImpersonateClient() combase.CoImpersonateClient
@ stdcall CoIncrementMTAUsage(ptr)
@ stdcall CoInitialize(ptr)