[1/2] ole32: Use wrappers around NT functions to access the registry in CoGetPSClsid.
Hans Leidekker
hans at codeweavers.com
Mon Nov 26 08:20:13 CST 2012
Code adapted from advapi32/registry.c.
---
dlls/ole32/compobj.c | 119 +++++++++++++++++++++++++++++++++++++++++-
dlls/ole32/compobj_private.h | 3 ++
dlls/ole32/tests/compobj.c | 2 +-
3 files changed, 122 insertions(+), 2 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 9c92c32..70508b6 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -47,6 +47,8 @@
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
@@ -135,6 +137,121 @@ static CRITICAL_SECTION_DEBUG class_cs_debug =
};
static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0, 0 };
+/* wrapper for NtCreateKey that creates the key recursively if necessary */
+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( (PHANDLE)retkey, access, attr, 0, NULL, 0, NULL );
+ if (attr->RootDirectory != root) NtClose( attr->RootDirectory );
+ }
+ return status;
+}
+
+static const WCHAR classes_rootW[] =
+ {'M','a','c','h','i','n','e','\\','S','o','f','t','w','a','r','e','\\','C','l','a','s','s','e','s',0};
+
+static HKEY classes_root_hkey;
+
+/* create the special HKEY_CLASSES_ROOT key */
+static HKEY create_classes_root_hkey(void)
+{
+ 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, classes_rootW );
+ if (create_key( &hkey, MAXIMUM_ALLOWED, &attr )) return 0;
+ TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey );
+
+ if (!(ret = InterlockedCompareExchangePointer( (void **)&classes_root_hkey, hkey, 0 )))
+ ret = hkey;
+ else
+ NtClose( hkey ); /* somebody beat us to it */
+ return ret;
+}
+
+/* map the hkey from special root to normal key if necessary */
+static inline HKEY get_classes_root_hkey( HKEY hkey )
+{
+ HKEY ret = hkey;
+
+ if (hkey == HKEY_CLASSES_ROOT && !(ret = classes_root_hkey))
+ ret = create_classes_root_hkey();
+
+ return ret;
+}
+
+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 ))) 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 ) );
+}
+
+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 ))) 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 ) );
+}
+
/*****************************************************************************
* This section contains OpenDllList definitions
*
@@ -2055,7 +2172,7 @@ HRESULT WINAPI CoGetPSClsid(REFIID riid, CLSID *pclsid)
strcpyW(path + ARRAYSIZE(wszInterface) - 1 + CHARS_IN_GUID - 1, wszPSC);
/* Open the key.. */
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &hkey))
+ if (open_classes_key(HKEY_CLASSES_ROOT, path, KEY_READ, &hkey))
{
WARN("No PSFactoryBuffer object is registered for IID %s\n", debugstr_guid(riid));
return REGDB_E_IIDNOTREG;
diff --git a/dlls/ole32/compobj_private.h b/dlls/ole32/compobj_private.h
index 0039655..b76e3a7 100644
--- a/dlls/ole32/compobj_private.h
+++ b/dlls/ole32/compobj_private.h
@@ -309,4 +309,7 @@ extern UINT object_descriptor_clipboard_format DECLSPEC_HIDDEN;
extern UINT link_source_descriptor_clipboard_format DECLSPEC_HIDDEN;
extern UINT ole_private_data_clipboard_format DECLSPEC_HIDDEN;
+extern LSTATUS create_classes_key(HKEY, const WCHAR *, REGSAM, HKEY *) DECLSPEC_HIDDEN;
+extern LSTATUS open_classes_key(HKEY, const WCHAR *, REGSAM, HKEY *) DECLSPEC_HIDDEN;
+
#endif /* __WINE_OLE_COMPOBJ_H */
diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c
index 048b082..714feee 100644
--- a/dlls/ole32/tests/compobj.c
+++ b/dlls/ole32/tests/compobj.c
@@ -755,7 +755,7 @@ static void test_CoGetPSClsid(void)
ok(!res, "RegOverridePredefKey returned %d\n", res);
hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
- todo_wine ok_ole_success(hr, "CoGetPSClsid");
+ ok_ole_success(hr, "CoGetPSClsid");
res = pRegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
ok(!res, "RegOverridePredefKey returned %d\n", res);
--
1.7.10.4
More information about the wine-patches
mailing list