Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 50 +++++++++++++++++++++++++++++++ dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 63 --------------------------------------- dlls/ole32/ole32.spec | 2 +- 4 files changed, 52 insertions(+), 65 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 06fc97e17d4..88da5fb888e 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -725,3 +725,53 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoGetInstanceFromFile(COSERVERINFO *server_info return hr; } } + +/*********************************************************************** + * CoGetInstanceFromIStorage (combase.@) + */ +HRESULT WINAPI CoGetInstanceFromIStorage(COSERVERINFO *server_info, CLSID *rclsid, + IUnknown *outer, DWORD cls_context, IStorage *storage, DWORD count, MULTI_QI *results) +{ + IPersistStorage *ps = NULL; + IUnknown *obj = NULL; + STATSTG stat; + HRESULT hr; + + if (!count || !results || !storage) + return E_INVALIDARG; + + if (server_info) + FIXME("() non-NULL server_info not supported\n"); + + init_multi_qi(count, results, E_NOINTERFACE); + + if (!rclsid) + { + memset(&stat.clsid, 0, sizeof(stat.clsid)); + hr = IStorage_Stat(storage, &stat, STATFLAG_NONAME); + if (FAILED(hr)) + { + ERR("Failed to get CLSID from a storage.\n"); + return hr; + } + + rclsid = &stat.clsid; + } + + hr = CoCreateInstance(rclsid, outer, cls_context, &IID_IUnknown, (void **)&obj); + if (hr != S_OK) + return hr; + + /* Init from IStorage */ + hr = IUnknown_QueryInterface(obj, &IID_IPersistStorage, (void **)&ps); + if (FAILED(hr)) + ERR("failed to get IPersistStorage\n"); + + if (ps) + { + IPersistStorage_Load(ps, storage); + IPersistStorage_Release(ps); + } + + return return_multi_qi(obj, count, results, FALSE); +} diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index e90df05446e..de0ebe7cd31 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -108,7 +108,7 @@ @ stdcall CoGetDefaultContext(long ptr ptr) ole32.CoGetDefaultContext @ stub CoGetErrorInfo @ stdcall CoGetInstanceFromFile(ptr ptr ptr long long wstr long ptr) -@ stdcall CoGetInstanceFromIStorage(ptr ptr ptr long ptr long ptr) ole32.CoGetInstanceFromIStorage +@ stdcall CoGetInstanceFromIStorage(ptr ptr ptr long ptr long ptr) @ stdcall CoGetInterfaceAndReleaseStream(ptr ptr ptr) ole32.CoGetInterfaceAndReleaseStream @ stdcall CoGetMalloc(long ptr) @ stdcall CoGetMarshalSizeMax(ptr ptr ptr long ptr long) ole32.CoGetMarshalSizeMax diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 1ad8a4b1d1d..e63759c0609 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3434,69 +3434,6 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstanceEx( return return_multi_qi(unk, cmq, pResults, TRUE); }
-/*********************************************************************** - * CoGetInstanceFromIStorage [OLE32.@] - */ -HRESULT WINAPI CoGetInstanceFromIStorage( - COSERVERINFO *server_info, - CLSID *rclsid, - IUnknown *outer, - DWORD cls_context, - IStorage *storage, - DWORD count, - MULTI_QI *results -) -{ - IPersistStorage *ps = NULL; - IUnknown* unk = NULL; - STATSTG stat; - HRESULT hr; - - if (count == 0 || !results || !storage) - return E_INVALIDARG; - - if (server_info) - FIXME("() non-NULL server_info not supported\n"); - - init_multi_qi(count, results, E_NOINTERFACE); - - /* optionally get CLSID from a file */ - if (!rclsid) - { - memset(&stat.clsid, 0, sizeof(stat.clsid)); - hr = IStorage_Stat(storage, &stat, STATFLAG_NONAME); - if (FAILED(hr)) - { - ERR("failed to get CLSID from a file\n"); - return hr; - } - - rclsid = &stat.clsid; - } - - hr = CoCreateInstance(rclsid, - outer, - cls_context, - &IID_IUnknown, - (void**)&unk); - - if (hr != S_OK) - return hr; - - /* init from IStorage */ - hr = IUnknown_QueryInterface(unk, &IID_IPersistStorage, (void**)&ps); - if (FAILED(hr)) - ERR("failed to get IPersistStorage\n"); - - if (ps) - { - IPersistStorage_Load(ps, storage); - IPersistStorage_Release(ps); - } - - return return_multi_qi(unk, count, results, FALSE); -} - /*********************************************************************** * CoLoadLibrary (OLE32.@) * diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index b1949eec8ec..6f44e298af8 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -36,7 +36,7 @@ @ stdcall CoGetCurrentProcess() @ stdcall CoGetDefaultContext(long ptr ptr) @ stdcall CoGetInstanceFromFile(ptr ptr ptr long long wstr long ptr) combase.CoGetInstanceFromFile -@ stdcall CoGetInstanceFromIStorage(ptr ptr ptr long ptr long ptr) +@ stdcall CoGetInstanceFromIStorage(ptr ptr ptr long ptr long ptr) combase.CoGetInstanceFromIStorage @ stdcall CoGetInterfaceAndReleaseStream(ptr ptr ptr) @ stdcall CoGetMalloc(long ptr) combase.CoGetMalloc @ stdcall CoGetMarshalSizeMax(ptr ptr ptr long ptr long)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 19 ++++++++++++++ dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 52 --------------------------------------- dlls/ole32/ole32.spec | 2 +- 4 files changed, 21 insertions(+), 54 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 88da5fb888e..bcf9912cbc1 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -775,3 +775,22 @@ HRESULT WINAPI CoGetInstanceFromIStorage(COSERVERINFO *server_info, CLSID *rclsi
return return_multi_qi(obj, count, results, FALSE); } + +/*********************************************************************** + * CoCreateInstance (combase.@) + */ +HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, IUnknown *outer, DWORD cls_context, + REFIID riid, void **obj) +{ + MULTI_QI multi_qi = { .pIID = riid }; + HRESULT hr; + + TRACE("%s, %p, %#x, %s, %p.\n", debugstr_guid(rclsid), outer, cls_context, debugstr_guid(riid), obj); + + if (!obj) + return E_POINTER; + + hr = CoCreateInstanceEx(rclsid, outer, cls_context, NULL, 1, &multi_qi); + *obj = multi_qi.pItf; + return hr; +} diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index de0ebe7cd31..b8e374924aa 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -79,7 +79,7 @@ @ stdcall CoCreateErrorInfo(ptr) CreateErrorInfo @ stdcall CoCreateFreeThreadedMarshaler(ptr ptr) ole32.CoCreateFreeThreadedMarshaler @ stdcall CoCreateGuid(ptr) -@ stdcall CoCreateInstance(ptr ptr long ptr ptr) ole32.CoCreateInstance +@ stdcall CoCreateInstance(ptr ptr long ptr ptr) @ stdcall CoCreateInstanceEx(ptr ptr long ptr long ptr) ole32.CoCreateInstanceEx @ stub CoCreateInstanceFromApp @ stub CoCreateObjectInContext diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index e63759c0609..cc64d7c036f 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3263,58 +3263,6 @@ HRESULT WINAPI CoResumeClassObjects(void) return S_OK; }
-/*********************************************************************** - * CoCreateInstance [OLE32.@] - * - * Creates an instance of the specified class. - * - * PARAMS - * rclsid [I] Class ID to create an instance of. - * pUnkOuter [I] Optional outer unknown to allow aggregation with another object. - * dwClsContext [I] Flags to restrict the location of the created instance. - * iid [I] The ID of the interface of the instance to return. - * ppv [O] On returns, contains a pointer to the specified interface of the instance. - * - * RETURNS - * Success: S_OK - * Failure: HRESULT code. - * - * NOTES - * The dwClsContext parameter can be one or more of the following: - *| CLSCTX_INPROC_SERVER - Use an in-process server, such as from a DLL. - *| CLSCTX_INPROC_HANDLER - Use an in-process object which handles certain functions for an object running in another process. - *| CLSCTX_LOCAL_SERVER - Connect to an object running in another process. - *| CLSCTX_REMOTE_SERVER - Connect to an object running on another machine. - * - * Aggregation is the concept of deferring the IUnknown of an object to another - * object. This allows a separate object to behave as though it was part of - * the object and to allow this the pUnkOuter parameter can be set. Note that - * not all objects support having an outer of unknown. - * - * SEE ALSO - * CoGetClassObject() - */ -HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance( - REFCLSID rclsid, - LPUNKNOWN pUnkOuter, - DWORD dwClsContext, - REFIID iid, - LPVOID *ppv) -{ - MULTI_QI multi_qi = { iid }; - HRESULT hres; - - TRACE("(rclsid=%s, pUnkOuter=%p, dwClsContext=%08x, riid=%s, ppv=%p)\n", debugstr_guid(rclsid), - pUnkOuter, dwClsContext, debugstr_guid(iid), ppv); - - if (ppv==0) - return E_POINTER; - - hres = CoCreateInstanceEx(rclsid, pUnkOuter, dwClsContext, NULL, 1, &multi_qi); - *ppv = multi_qi.pItf; - return hres; -} - static void init_multi_qi(DWORD count, MULTI_QI *mqi, HRESULT hr) { ULONG i; diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 6f44e298af8..550b3149d49 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -12,7 +12,7 @@ @ stdcall CoCopyProxy(ptr ptr) combase.CoCopyProxy @ stdcall CoCreateFreeThreadedMarshaler(ptr ptr) @ stdcall CoCreateGuid(ptr) combase.CoCreateGuid -@ stdcall CoCreateInstance(ptr ptr long ptr ptr) +@ stdcall CoCreateInstance(ptr ptr long ptr ptr) combase.CoCreateInstance @ stdcall CoCreateInstanceEx(ptr ptr long ptr long ptr) @ stdcall CoDecrementMTAUsage(ptr) @ stdcall CoDisableCallCancellation(ptr)
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 203 ++++++++++++++++++++++++++++++++++++++ dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 50 ---------- dlls/ole32/ole32.spec | 2 +- 4 files changed, 205 insertions(+), 52 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index bcf9912cbc1..a757407c71e 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -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; diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index b8e374924aa..497af6da8c0 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -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 diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index cc64d7c036f..1f6a952f15a 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -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.@] */ diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 550b3149d49..e51b2b5887d 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -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)
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 84 +++++++++++++++++++++++++++++++++++++++ dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 73 ---------------------------------- dlls/ole32/ole32.spec | 2 +- 4 files changed, 86 insertions(+), 75 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index a757407c71e..6b8eb4ee7a9 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -33,6 +33,28 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
#define CHARS_IN_GUID 39
+struct comclassredirect_data +{ + ULONG size; + ULONG flags; + DWORD model; + GUID clsid; + GUID alias; + GUID clsid2; + GUID tlbid; + ULONG name_len; + ULONG name_offset; + ULONG progid_len; + ULONG progid_offset; + ULONG clrdata_len; + ULONG clrdata_offset; + DWORD miscstatus; + DWORD miscstatuscontent; + DWORD miscstatusthumbnail; + DWORD miscstatusicon; + DWORD miscstatusdocprint; +}; + static NTSTATUS create_key(HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr) { NTSTATUS status = NtCreateKey((HANDLE *)retkey, access, attr, 0, NULL, 0, NULL); @@ -831,6 +853,68 @@ done: return hr; }
+/****************************************************************************** + * ProgIDFromCLSID (combase.@) + */ +HRESULT WINAPI DECLSPEC_HOTPATCH ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *progid) +{ + ACTCTX_SECTION_KEYED_DATA data; + LONG progidlen = 0; + HKEY hkey; + HRESULT hr; + + if (!progid) + return E_INVALIDARG; + + *progid = NULL; + + data.cbSize = sizeof(data); + if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, + clsid, &data)) + { + struct comclassredirect_data *comclass = (struct comclassredirect_data *)data.lpData; + if (comclass->progid_len) + { + WCHAR *ptrW; + + *progid = CoTaskMemAlloc(comclass->progid_len + sizeof(WCHAR)); + if (!*progid) return E_OUTOFMEMORY; + + ptrW = (WCHAR *)((BYTE *)comclass + comclass->progid_offset); + memcpy(*progid, ptrW, comclass->progid_len + sizeof(WCHAR)); + return S_OK; + } + else + return REGDB_E_CLASSNOTREG; + } + + hr = open_key_for_clsid(clsid, L"ProgID", KEY_READ, &hkey); + if (FAILED(hr)) + return hr; + + if (RegQueryValueW(hkey, NULL, NULL, &progidlen)) + hr = REGDB_E_CLASSNOTREG; + + if (hr == S_OK) + { + *progid = CoTaskMemAlloc(progidlen * sizeof(WCHAR)); + if (*progid) + { + if (RegQueryValueW(hkey, NULL, *progid, &progidlen)) + { + hr = REGDB_E_CLASSNOTREG; + CoTaskMemFree(*progid); + *progid = NULL; + } + } + else + hr = E_OUTOFMEMORY; + } + + RegCloseKey(hkey); + return hr; +} + static void init_multi_qi(DWORD count, MULTI_QI *mqi, HRESULT hr) { ULONG i; diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 497af6da8c0..a90a418764d 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -279,7 +279,7 @@ @ stub NdrExtStubInitialize @ stub NdrOleDllGetClassObject @ stub NdrpFindInterface -@ stdcall ProgIDFromCLSID(ptr ptr) ole32.ProgIDFromCLSID +@ stdcall ProgIDFromCLSID(ptr ptr) @ stdcall PropVariantClear(ptr) @ stdcall PropVariantCopy(ptr ptr) @ stub ReleaseFuncDescs diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 1f6a952f15a..47b815b752e 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -2485,79 +2485,6 @@ HRESULT COM_OpenKeyForAppIdFromCLSID(REFCLSID clsid, REGSAM access, HKEY *subkey return S_OK; }
-/****************************************************************************** - * ProgIDFromCLSID [OLE32.@] - * - * Converts a class id into the respective program ID. - * - * PARAMS - * clsid [I] Class ID, as found in registry. - * ppszProgID [O] Associated ProgID. - * - * RETURNS - * S_OK - * E_OUTOFMEMORY - * REGDB_E_CLASSNOTREG if the given clsid has no associated ProgID - */ -HRESULT WINAPI DECLSPEC_HOTPATCH ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *ppszProgID) -{ - static const WCHAR wszProgID[] = {'P','r','o','g','I','D',0}; - ACTCTX_SECTION_KEYED_DATA data; - HKEY hkey; - HRESULT ret; - LONG progidlen = 0; - - if (!ppszProgID) - return E_INVALIDARG; - - *ppszProgID = NULL; - - data.cbSize = sizeof(data); - if (FindActCtxSectionGuid(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION, - clsid, &data)) - { - struct comclassredirect_data *comclass = (struct comclassredirect_data*)data.lpData; - if (comclass->progid_len) - { - WCHAR *ptrW; - - *ppszProgID = CoTaskMemAlloc(comclass->progid_len + sizeof(WCHAR)); - if (!*ppszProgID) return E_OUTOFMEMORY; - - ptrW = (WCHAR*)((BYTE*)comclass + comclass->progid_offset); - memcpy(*ppszProgID, ptrW, comclass->progid_len + sizeof(WCHAR)); - return S_OK; - } - else - return REGDB_E_CLASSNOTREG; - } - - ret = COM_OpenKeyForCLSID(clsid, wszProgID, KEY_READ, &hkey); - if (FAILED(ret)) - return ret; - - if (RegQueryValueW(hkey, NULL, NULL, &progidlen)) - ret = REGDB_E_CLASSNOTREG; - - if (ret == S_OK) - { - *ppszProgID = CoTaskMemAlloc(progidlen * sizeof(WCHAR)); - if (*ppszProgID) - { - if (RegQueryValueW(hkey, NULL, *ppszProgID, &progidlen)) { - ret = REGDB_E_CLASSNOTREG; - CoTaskMemFree(*ppszProgID); - *ppszProgID = NULL; - } - } - else - ret = E_OUTOFMEMORY; - } - - RegCloseKey(hkey); - return ret; -} - /****************************************************************************** * CLSIDFromProgID [OLE32.@] * diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index e51b2b5887d..74eb6f01062 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -237,7 +237,7 @@ @ stdcall OleTranslateAccelerator(ptr ptr ptr) @ stdcall OleUninitialize() @ stub OpenOrCreateStream -@ stdcall ProgIDFromCLSID(ptr ptr) +@ stdcall ProgIDFromCLSID(ptr ptr) combase.ProgIDFromCLSID @ stdcall PropStgNameToFmtId(wstr ptr) @ stdcall PropSysAllocString(wstr) @ stdcall PropSysFreeString(wstr)
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 138 ++++++++++++++++++++++++++++++++++++++ dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 33 --------- dlls/ole32/ole32.spec | 2 +- 4 files changed, 140 insertions(+), 35 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 6b8eb4ee7a9..2d202c796d5 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -28,6 +28,7 @@ #include "winternl.h"
#include "wine/debug.h" +#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
@@ -55,6 +56,13 @@ struct comclassredirect_data DWORD miscstatusdocprint; };
+struct progidredirect_data +{ + ULONG size; + DWORD reserved; + ULONG clsid_offset; +}; + static NTSTATUS create_key(HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr) { NTSTATUS status = NtCreateKey((HANDLE *)retkey, access, attr, 0, NULL, 0, NULL); @@ -915,6 +923,136 @@ HRESULT WINAPI DECLSPEC_HOTPATCH ProgIDFromCLSID(REFCLSID clsid, LPOLESTR *progi return hr; }
+static inline BOOL is_valid_hex(WCHAR c) +{ + if (!(((c >= '0') && (c <= '9')) || + ((c >= 'a') && (c <= 'f')) || + ((c >= 'A') && (c <= 'F')))) + return FALSE; + return TRUE; +} + +static const BYTE guid_conv_table[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */ + 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */ + 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */ +}; + +static BOOL guid_from_string(LPCWSTR s, GUID *id) +{ + int i; + + if (!s || s[0] != '{') + { + memset(id, 0, sizeof(*id)); + if (!s) return TRUE; + return FALSE; + } + + TRACE("%s -> %p\n", debugstr_w(s), id); + + /* In form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */ + + id->Data1 = 0; + for (i = 1; i < 9; ++i) + { + if (!is_valid_hex(s[i])) return FALSE; + id->Data1 = (id->Data1 << 4) | guid_conv_table[s[i]]; + } + if (s[9] != '-') return FALSE; + + id->Data2 = 0; + for (i = 10; i < 14; ++i) + { + if (!is_valid_hex(s[i])) return FALSE; + id->Data2 = (id->Data2 << 4) | guid_conv_table[s[i]]; + } + if (s[14] != '-') return FALSE; + + id->Data3 = 0; + for (i = 15; i < 19; ++i) + { + if (!is_valid_hex(s[i])) return FALSE; + id->Data3 = (id->Data3 << 4) | guid_conv_table[s[i]]; + } + if (s[19] != '-') return FALSE; + + for (i = 20; i < 37; i += 2) + { + if (i == 24) + { + if (s[i] != '-') return FALSE; + i++; + } + if (!is_valid_hex(s[i]) || !is_valid_hex(s[i + 1])) return FALSE; + id->Data4[(i - 20) / 2] = guid_conv_table[s[i]] << 4 | guid_conv_table[s[i + 1]]; + } + + if (s[37] == '}' && s[38] == '\0') + return TRUE; + + return FALSE; +} + +static HRESULT clsid_from_string_reg(LPCOLESTR progid, CLSID *clsid) +{ + WCHAR buf2[CHARS_IN_GUID]; + LONG buf2len = sizeof(buf2); + HKEY xhkey; + WCHAR *buf; + + memset(clsid, 0, sizeof(*clsid)); + buf = heap_alloc((lstrlenW(progid) + 8) * sizeof(WCHAR)); + if (!buf) return E_OUTOFMEMORY; + + lstrcpyW(buf, progid); + lstrcatW(buf, L"\CLSID"); + if (open_classes_key(HKEY_CLASSES_ROOT, buf, MAXIMUM_ALLOWED, &xhkey)) + { + heap_free(buf); + WARN("couldn't open key for ProgID %s\n", debugstr_w(progid)); + return CO_E_CLASSSTRING; + } + heap_free(buf); + + if (RegQueryValueW(xhkey, NULL, buf2, &buf2len)) + { + RegCloseKey(xhkey); + WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid)); + return CO_E_CLASSSTRING; + } + RegCloseKey(xhkey); + return guid_from_string(buf2, clsid) ? S_OK : CO_E_CLASSSTRING; +} + +/****************************************************************************** + * CLSIDFromProgID (combase.@) + */ +HRESULT WINAPI DECLSPEC_HOTPATCH CLSIDFromProgID(LPCOLESTR progid, CLSID *clsid) +{ + ACTCTX_SECTION_KEYED_DATA data; + + if (!progid || !clsid) + return E_INVALIDARG; + + data.cbSize = sizeof(data); + if (FindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION, + progid, &data)) + { + struct progidredirect_data *progiddata = (struct progidredirect_data *)data.lpData; + CLSID *alias = (CLSID *)((BYTE *)data.lpSectionBase + progiddata->clsid_offset); + *clsid = *alias; + return S_OK; + } + + return clsid_from_string_reg(progid, clsid); +} + static void init_multi_qi(DWORD count, MULTI_QI *mqi, HRESULT hr) { ULONG i; diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index a90a418764d..4e5c5a9dc9e 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -67,7 +67,7 @@ @ stdcall CLIPFORMAT_UserSize(ptr long ptr) @ stdcall CLIPFORMAT_UserUnmarshal(ptr ptr ptr) @ stub CLSIDFromOle1Class -@ stdcall CLSIDFromProgID(wstr ptr) ole32.CLSIDFromProgID +@ stdcall CLSIDFromProgID(wstr ptr) @ stdcall CLSIDFromString(wstr ptr) ole32.CLSIDFromString @ stub CleanupOleStateInAllTls @ stdcall CleanupTlsOleState(ptr) diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 47b815b752e..91ff8124282 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -2485,39 +2485,6 @@ HRESULT COM_OpenKeyForAppIdFromCLSID(REFCLSID clsid, REGSAM access, HKEY *subkey return S_OK; }
-/****************************************************************************** - * CLSIDFromProgID [OLE32.@] - * - * Converts a program id into the respective GUID. - * - * PARAMS - * progid [I] Unicode program ID, as found in registry. - * clsid [O] Associated CLSID. - * - * RETURNS - * Success: S_OK - * Failure: CO_E_CLASSSTRING - the given ProgID cannot be found. - */ -HRESULT WINAPI DECLSPEC_HOTPATCH CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid) -{ - ACTCTX_SECTION_KEYED_DATA data; - - if (!progid || !clsid) - return E_INVALIDARG; - - data.cbSize = sizeof(data); - if (FindActCtxSectionStringW(0, NULL, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION, - progid, &data)) - { - struct progidredirect_data *progiddata = (struct progidredirect_data*)data.lpData; - CLSID *alias = (CLSID*)((BYTE*)data.lpSectionBase + progiddata->clsid_offset); - *clsid = *alias; - return S_OK; - } - - return clsid_from_string_reg(progid, clsid); -} - /****************************************************************************** * CLSIDFromProgIDEx [OLE32.@] */ diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 74eb6f01062..ce5d7987d94 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -3,7 +3,7 @@ @ stdcall CLIPFORMAT_UserMarshal(ptr ptr ptr) combase.CLIPFORMAT_UserMarshal @ stdcall CLIPFORMAT_UserSize(ptr long ptr) combase.CLIPFORMAT_UserSize @ stdcall CLIPFORMAT_UserUnmarshal(ptr ptr ptr) combase.CLIPFORMAT_UserUnmarshal -@ stdcall CLSIDFromProgID(wstr ptr) +@ stdcall CLSIDFromProgID(wstr ptr) combase.CLSIDFromProgID @ stdcall CLSIDFromProgIDEx(wstr ptr) @ stdcall CLSIDFromString(wstr ptr) @ stdcall CoAddRefServerProcess()
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=76746
Your paranoid android.
=== debiant (32 bit Chinese:China report) ===
ole32: clipboard.c:882: Test failed: IDataObject_GetData failed with error 0x800401d0 clipboard.c:887: Test failed: IDataObject_GetData failed with error 0x800401d0 clipboard.c:892: Test failed: IDataObject_GetData failed with error 0x800401d0 clipboard.c:897: Test failed: IDataObject_GetData failed with error 0x800401d0 clipboard.c:900: Test failed: DataObjectImpl_GetData called 5 times instead of 0 times clipboard.c:864: Test failed: didn't find cf_dataobject clipboard.c:865: Test failed: didn't find cf_ole_priv_data clipboard.c:626: Test failed: got 800401d0 clipboard.c:1019: Test failed: failed to clear clipboard, hr = 0x800401d0. clipboard.c:626: Test failed: got 800401d0 clipboard.c:1029: Test failed: expected data_cmpl ref=0, got 4
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 22 +++++++++++++ dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 69 --------------------------------------- dlls/ole32/ole32.spec | 2 +- 4 files changed, 24 insertions(+), 71 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 2d202c796d5..2bfd1d79a7d 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -1053,6 +1053,28 @@ HRESULT WINAPI DECLSPEC_HOTPATCH CLSIDFromProgID(LPCOLESTR progid, CLSID *clsid) return clsid_from_string_reg(progid, clsid); }
+/****************************************************************************** + * CLSIDFromString (combase.@) + */ +HRESULT WINAPI CLSIDFromString(LPCOLESTR str, LPCLSID clsid) +{ + CLSID tmp_id; + HRESULT hr; + + if (!clsid) + return E_INVALIDARG; + + if (guid_from_string(str, clsid)) + return S_OK; + + /* It appears a ProgID is also valid */ + hr = clsid_from_string_reg(str, &tmp_id); + if (SUCCEEDED(hr)) + *clsid = tmp_id; + + return hr; +} + static void init_multi_qi(DWORD count, MULTI_QI *mqi, HRESULT hr) { ULONG i; diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 4e5c5a9dc9e..97e8f254dcb 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -68,7 +68,7 @@ @ stdcall CLIPFORMAT_UserUnmarshal(ptr ptr ptr) @ stub CLSIDFromOle1Class @ stdcall CLSIDFromProgID(wstr ptr) -@ stdcall CLSIDFromString(wstr ptr) ole32.CLSIDFromString +@ stdcall CLSIDFromString(wstr ptr) @ stub CleanupOleStateInAllTls @ stdcall CleanupTlsOleState(ptr) @ stub ClearCleanupFlag diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 91ff8124282..ff0c352c645 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -2257,75 +2257,6 @@ static BOOL guid_from_string(LPCWSTR s, GUID *id) return FALSE; }
-/*****************************************************************************/ - -static HRESULT clsid_from_string_reg(LPCOLESTR progid, CLSID *clsid) -{ - static const WCHAR clsidW[] = { '\','C','L','S','I','D',0 }; - WCHAR buf2[CHARS_IN_GUID]; - LONG buf2len = sizeof(buf2); - HKEY xhkey; - WCHAR *buf; - - memset(clsid, 0, sizeof(*clsid)); - buf = HeapAlloc( GetProcessHeap(),0,(lstrlenW(progid)+8) * sizeof(WCHAR) ); - if (!buf) return E_OUTOFMEMORY; - lstrcpyW( buf, progid ); - lstrcatW( buf, clsidW ); - if (open_classes_key(HKEY_CLASSES_ROOT, buf, MAXIMUM_ALLOWED, &xhkey)) - { - HeapFree(GetProcessHeap(),0,buf); - WARN("couldn't open key for ProgID %s\n", debugstr_w(progid)); - return CO_E_CLASSSTRING; - } - HeapFree(GetProcessHeap(),0,buf); - - if (RegQueryValueW(xhkey,NULL,buf2,&buf2len)) - { - RegCloseKey(xhkey); - WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid)); - return CO_E_CLASSSTRING; - } - RegCloseKey(xhkey); - return guid_from_string(buf2, clsid) ? S_OK : CO_E_CLASSSTRING; -} - -/****************************************************************************** - * CLSIDFromString [OLE32.@] - * - * Converts a unique identifier from its string representation into - * the GUID struct. - * - * PARAMS - * idstr [I] The string representation of the GUID. - * id [O] GUID converted from the string. - * - * RETURNS - * S_OK on success - * CO_E_CLASSSTRING if idstr is not a valid CLSID - * - * SEE ALSO - * StringFromCLSID - */ -HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id ) -{ - HRESULT ret = CO_E_CLASSSTRING; - CLSID tmp_id; - - if (!id) - return E_INVALIDARG; - - if (guid_from_string(idstr, id)) - return S_OK; - - /* It appears a ProgID is also valid */ - ret = clsid_from_string_reg(idstr, &tmp_id); - if(SUCCEEDED(ret)) - *id = tmp_id; - - return ret; -} - /****************************************************************************** * IIDFromString [OLE32.@] * diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index ce5d7987d94..f71fd52032b 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -5,7 +5,7 @@ @ stdcall CLIPFORMAT_UserUnmarshal(ptr ptr ptr) combase.CLIPFORMAT_UserUnmarshal @ stdcall CLSIDFromProgID(wstr ptr) combase.CLSIDFromProgID @ stdcall CLSIDFromProgIDEx(wstr ptr) -@ stdcall CLSIDFromString(wstr ptr) +@ stdcall CLSIDFromString(wstr ptr) combase.CLSIDFromString @ stdcall CoAddRefServerProcess() @ stdcall CoAllowSetForegroundWindow(ptr ptr) @ stdcall CoBuildVersion()
Signed-off-by: Huw Davies huw@codeweavers.com