Brad DeMorrow
authorAlexandre Julliard <julliard@winehq.org>
Mon, 14 Feb 2005 21:08:56 +0000 (21:08 +0000)
committerAlexandre Julliard <julliard@winehq.org>
Mon, 14 Feb 2005 21:08:56 +0000 (21:08 +0000)
Tests for the ntdll registry functions.

dlls/ntdll/tests/.cvsignore
dlls/ntdll/tests/Makefile.in
dlls/ntdll/tests/reg.c [new file with mode: 0644]

index e2ef7e4097ca5bd8c65f304d827a4fb1be961732..9027a6e5baf639a124bf9186eac562d3bcdcd0b7 100644 (file)
@@ -4,6 +4,7 @@ error.ok
 generated.ok
 large_int.ok
 path.ok
+reg.ok
 rtl.ok
 rtlbitmap.ok
 rtlstr.ok
index af18eeda40404bc353a263609fc8f5ff60931231..59b05a69dd1a254c254d719824f75130204403bb 100644 (file)
@@ -11,6 +11,7 @@ CTESTS = \
        generated.c \
        large_int.c \
        path.c \
+       reg.c \
        rtl.c \
        rtlbitmap.c \
        rtlstr.c \
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c
new file mode 100644 (file)
index 0000000..5dce55d
--- /dev/null
@@ -0,0 +1,364 @@
+/* Unit test suite for Rtl* Registry API functions
+ *
+ * Copyright 2003 Thomas Mertes
+ * Copyright 2005 Brad DeMorrow
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * NOTE: I don't test every RelativeTo value because it would be redundant, all calls go through
+ * helper function RTL_GetKeyHandle().--Brad DeMorrow
+ *
+ */
+
+#include "ntdll_test.h"
+#include "winternl.h"
+#include "wine/library.h"
+#include "stdio.h"
+#include "winnt.h"
+#include "winnls.h"
+#include "stdlib.h"
+#include "wine/unicode.h"
+
+/* RtlQueryRegistryValues structs and defines */
+#define RTL_REGISTRY_ABSOLUTE             0
+#define RTL_REGISTRY_SERVICES             1
+#define RTL_REGISTRY_CONTROL              2
+#define RTL_REGISTRY_WINDOWS_NT           3
+#define RTL_REGISTRY_DEVICEMAP            4
+#define RTL_REGISTRY_USER                 5
+
+#define RTL_REGISTRY_HANDLE       0x40000000
+#define RTL_REGISTRY_OPTIONAL     0x80000000
+
+#define RTL_QUERY_REGISTRY_SUBKEY         0x00000001
+#define RTL_QUERY_REGISTRY_TOPKEY         0x00000002
+#define RTL_QUERY_REGISTRY_REQUIRED       0x00000004
+#define RTL_QUERY_REGISTRY_NOVALUE        0x00000008
+#define RTL_QUERY_REGISTRY_NOEXPAND       0x00000010
+#define RTL_QUERY_REGISTRY_DIRECT         0x00000020
+#define RTL_QUERY_REGISTRY_DELETE         0x00000040
+
+typedef NTSTATUS (WINAPI *PRTL_QUERY_REGISTRY_ROUTINE)( PCWSTR  ValueName,
+                                                        ULONG  ValueType,
+                                                        PVOID  ValueData,
+                                                        ULONG  ValueLength,
+                                                        PVOID  Context,
+                                                        PVOID  EntryContext);
+
+typedef struct _RTL_QUERY_REGISTRY_TABLE {
+  PRTL_QUERY_REGISTRY_ROUTINE  QueryRoutine;
+  ULONG  Flags;
+  PWSTR  Name;
+  PVOID  EntryContext;
+  ULONG  DefaultType;
+  PVOID  DefaultData;
+  ULONG  DefaultLength;
+} RTL_QUERY_REGISTRY_TABLE, *PRTL_QUERY_REGISTRY_TABLE;
+
+static NTSTATUS (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR);
+static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING);
+static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
+static NTSTATUS (WINAPI * pRtlQueryRegistryValues)(IN ULONG, IN PCWSTR,IN PRTL_QUERY_REGISTRY_TABLE, IN PVOID,IN PVOID);
+static NTSTATUS (WINAPI * pRtlCheckRegistryKey)(IN ULONG,IN PWSTR);
+static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, OUT PHKEY);
+static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES);
+static NTSTATUS (WINAPI * pNtClose)(IN HANDLE);
+static NTSTATUS (WINAPI * pNtDeleteValueKey)(IN HANDLE, IN PUNICODE_STRING);
+static NTSTATUS (WINAPI * pNtDeleteKey)(HKEY);
+static NTSTATUS (WINAPI * pNtCreateKey)( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
+                             ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
+                             PULONG dispos );
+static NTSTATUS (WINAPI * pNtSetValueKey)( PHKEY, const PUNICODE_STRING, ULONG,
+                               ULONG, const PVOID, ULONG  );
+static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(PUNICODE_STRING);
+static NTSTATUS (WINAPI * pRtlCreateUnicodeString)( PUNICODE_STRING, LPCWSTR);
+static NTSTATUS (WINAPI * pRtlReAllocateHeap)(IN PVOID, IN ULONG, IN PVOID, IN ULONG);
+static NTSTATUS (WINAPI * pRtlAppendUnicodeToString)(PUNICODE_STRING, PCWSTR);
+static NTSTATUS (WINAPI * pRtlUnicodeStringToAnsiString)(PSTRING, PUNICODE_STRING, BOOL);
+static NTSTATUS (WINAPI * pRtlFreeHeap)(PVOID, ULONG, PVOID);
+static NTSTATUS (WINAPI * pRtlAllocateHeap)(PVOID,ULONG,ULONG);
+static NTSTATUS (WINAPI * pRtlZeroMemory)(PVOID, ULONG);
+
+static HMODULE hntdll = 0;
+static int CurrentTest = 0;
+static UNICODE_STRING winetestpath;
+
+static void InitFunctionPtrs(void)
+{
+    hntdll = LoadLibraryA("ntdll.dll");
+    ok(hntdll != 0, "LoadLibrary failed\n");
+    if (hntdll)
+    {
+        pRtlCreateUnicodeStringFromAsciiz = (void *)GetProcAddress(hntdll, "RtlCreateUnicodeStringFromAsciiz");
+        pRtlCreateUnicodeString = (void*)GetProcAddress(hntdll, "RtlCreateUnicodeString");
+        pRtlFreeUnicodeString = (void*)GetProcAddress(hntdll, "RtlFreeUnicodeString");
+        pNtDeleteValueKey = (void*)GetProcAddress(hntdll, "NtDeleteValueKey");
+        pRtlQueryRegistryValues = (void*)GetProcAddress(hntdll, "RtlQueryRegistryValues");
+        pRtlCheckRegistryKey = (void*)GetProcAddress(hntdll, "RtlCheckRegistryKey");
+        pRtlOpenCurrentUser = (void*)GetProcAddress(hntdll, "RtlOpenCurrentUser");
+        pNtClose = (void*)GetProcAddress(hntdll, "NtClose");
+        pNtDeleteValueKey = (void*)GetProcAddress(hntdll, "NtDeleteValueKey");
+        pNtCreateKey = (void*)GetProcAddress(hntdll, "NtCreateKey");
+        pNtDeleteKey = (void*)GetProcAddress(hntdll, "NtDeleteKey");
+        pNtSetValueKey = (void*)GetProcAddress(hntdll, "NtSetValueKey");
+        pNtOpenKey = (void*)GetProcAddress(hntdll, "NtOpenKey");
+        pRtlFormatCurrentUserKeyPath = (void*)GetProcAddress(hntdll, "RtlFormatCurrentUserKeyPath");
+        pRtlReAllocateHeap = (void*)GetProcAddress(hntdll, "RtlReAllocateHeap");
+        pRtlAppendUnicodeToString = (void*)GetProcAddress(hntdll, "RtlAppendUnicodeToString");
+        pRtlUnicodeStringToAnsiString = (void*)GetProcAddress(hntdll, "RtlUnicodeStringToAnsiString");
+        pRtlFreeHeap = (void*)GetProcAddress(hntdll, "RtlFreeHeap");
+        pRtlAllocateHeap = (void*)GetProcAddress(hntdll, "RtlAllocateHeap");
+        pRtlZeroMemory = (void*)GetProcAddress(hntdll, "RtlZeroMemory");
+    }
+
+
+}
+
+static NTSTATUS WINAPI QueryRoutine (IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData,
+                              IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext)
+{
+    NTSTATUS ret = STATUS_SUCCESS;
+    int ValueNameLength = 0;
+    LPSTR ValName = 0;
+    trace("**Test %d**\n", CurrentTest);
+
+    if(ValueName)
+    {
+        ValueNameLength = strlenW(ValueName);
+
+        ValName = (LPSTR)pRtlAllocateHeap(GetProcessHeap(), 0, ValueNameLength);
+
+        WideCharToMultiByte(0, 0, ValueName, ValueNameLength+1,ValName, ValueNameLength, 0, 0);
+
+        trace("ValueName: %s\n", ValName);
+    }
+    else
+        trace("ValueName: (null)\n");
+
+    switch(ValueType)
+    {
+            case REG_NONE:
+                trace("ValueType: REG_NONE\n");
+                trace("ValueData: %d\n", (int)ValueData);
+                break;
+
+            case REG_BINARY:
+                trace("ValueType: REG_BINARY\n");
+                trace("ValueData: %d\n", (int)ValueData);
+                break;
+
+            case REG_SZ:
+                trace("ValueType: REG_SZ\n");
+                trace("ValueData: %s\n", (char*)ValueData);
+                break;
+
+            case REG_MULTI_SZ:
+                trace("ValueType: REG_MULTI_SZ\n");
+                trace("ValueData: %s\n", (char*)ValueData);
+                break;
+
+            case REG_EXPAND_SZ:
+                trace("ValueType: REG_EXPAND_SZ\n");
+                trace("ValueData: %s\n", (char*)ValueData);
+                break;
+
+            case REG_DWORD:
+                trace("ValueType: REG_DWORD\n");
+                trace("ValueData: %d\n", (int)ValueData);
+                break;
+    };
+    trace("ValueLength: %d\n", (int)ValueLength);
+
+    if(CurrentTest == 0)
+        ok(1, "\n"); /*checks that QueryRoutine is called*/
+    if(CurrentTest > 7)
+        ok(!1, "Invalid Test Specified!\n");
+
+    CurrentTest++;
+
+    if(ValName)
+        pRtlFreeHeap(GetProcessHeap(), 0, ValName);
+
+    return ret;
+}
+
+static void test_RtlQueryRegistryValues(void)
+{
+
+    /*
+    ******************************
+    *       QueryTable Flags     *
+    ******************************
+    *RTL_QUERY_REGISTRY_SUBKEY   * Name is the name of a subkey relative to Path
+    *RTL_QUERY_REGISTRY_TOPKEY   * Resets location to original RelativeTo and Path
+    *RTL_QUERY_REGISTRY_REQUIRED * Key required. returns STATUS_OBJECT_NAME_NOT_FOUND if not present
+    *RTL_QUERY_REGISTRY_NOVALUE  * We just want a call-back
+    *RTL_QUERY_REGISTRY_NOEXPAND * Don't expand the variables!
+    *RTL_QUERY_REGISTRY_DIRECT   * Results of query will be stored in EntryContext(QueryRoutine ignored)
+    *RTL_QUERY_REGISTRY_DELETE   * Delete value key after query
+    ******************************
+
+
+    **Test layout(numbered according to CurrentTest value)**
+    0)NOVALUE           Just make sure call-back works
+    1)Null Name         See if QueryRoutine is called for every value in current key
+    2)SUBKEY            See if we can use SUBKEY to change the current path on the fly
+    3)REQUIRED          Test for value that's not there
+    4)NOEXPAND          See if it will return multiple strings(no expand should split strings up)
+    5)DIRECT            Make it store data directly in EntryContext and not call QueryRoutine
+    6)DefaultType       Test return values when key isn't present
+    7)DefaultValue      Test Default Value returned with key isn't present(and no REQUIRED flag set)
+    8)DefaultLength     Test Default Length with DefaultType = REG_SZ
+   9)DefaultLength      Test Default Length with DefaultType = REG_MULTI_SZ
+   10)DefaultLength     Test Default Length with DefaultType = REG_EXPAND_SZ
+   11)DefaultData       Test whether DefaultData is used while DefaltType = REG_NONE(shouldn't be)
+   12)Delete            Try to delete value key
+
+    */
+    NTSTATUS status;
+    ULONG RelativeTo;
+
+    PRTL_QUERY_REGISTRY_TABLE QueryTable = NULL;
+    RelativeTo = RTL_REGISTRY_ABSOLUTE;/*Only using absolute - no need to test all relativeto variables*/
+
+    QueryTable = (PRTL_QUERY_REGISTRY_TABLE)pRtlAllocateHeap(GetProcessHeap(), 0, sizeof(RTL_QUERY_REGISTRY_TABLE)*26);
+
+    pRtlZeroMemory( QueryTable, sizeof(RTL_QUERY_REGISTRY_TABLE) * 26);
+
+    QueryTable[0].QueryRoutine = QueryRoutine;
+    QueryTable[0].Flags = RTL_QUERY_REGISTRY_NOVALUE;
+    QueryTable[0].Name = NULL;
+    QueryTable[0].EntryContext = NULL;
+    QueryTable[0].DefaultType = REG_BINARY;
+    QueryTable[0].DefaultData = NULL;
+    QueryTable[0].DefaultLength = 100;
+
+    QueryTable[1].QueryRoutine = QueryRoutine;
+    QueryTable[1].Flags = 0;
+    QueryTable[1].Name = NULL;
+    QueryTable[1].EntryContext = 0;
+    QueryTable[1].DefaultType = REG_NONE;
+    QueryTable[1].DefaultData = NULL;
+    QueryTable[1].DefaultLength = 0;
+
+    QueryTable[2].QueryRoutine = NULL;
+    QueryTable[2].Flags = 0;
+    QueryTable[2].Name = NULL;
+    QueryTable[2].EntryContext = 0;
+    QueryTable[2].DefaultType = REG_NONE;
+    QueryTable[2].DefaultData = NULL;
+    QueryTable[2].DefaultLength = 0;
+
+    status = pRtlQueryRegistryValues(RelativeTo, winetestpath.Buffer, QueryTable, 0, 0);
+    ok(status == STATUS_SUCCESS, "RtlQueryRegistryValues return: 0x%08lx\n", status);
+
+    pRtlFreeHeap(GetProcessHeap(), 0, QueryTable);
+}
+
+static void test_NtCreateKey(void)
+{
+    /*Create WineTest*/
+    OBJECT_ATTRIBUTES attr;
+    UNICODE_STRING ValName;
+    HKEY key;
+    ACCESS_MASK am = GENERIC_ALL;
+    NTSTATUS status;
+
+    InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
+    status = pNtCreateKey(&key, am, &attr, 0, 0, 0, 0);
+    ok(status == STATUS_SUCCESS, "NtCreateKey Failed: 0x%08lx\n", status);
+
+    pRtlFreeUnicodeString(&ValName);
+    pNtClose(&key);
+}
+
+static void test_NtSetValueKey(void)
+{
+    HANDLE key;
+    NTSTATUS status;
+    OBJECT_ATTRIBUTES attr;
+    ACCESS_MASK am = KEY_WRITE;
+    UNICODE_STRING ValName;
+    DWORD data = 711;
+
+    pRtlCreateUnicodeStringFromAsciiz(&ValName, "deletetest");
+
+    InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
+    status = pNtOpenKey(&key, am, &attr);
+    ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status);
+
+    status = pNtSetValueKey(key, &ValName, 0, REG_DWORD, &data, sizeof(data));
+    ok(status == STATUS_SUCCESS, "NtSetValueKey Failed: 0x%08lx\n", status);
+
+    pRtlFreeUnicodeString(&ValName);
+    pNtClose(&key);
+}
+
+static void test_RtlOpenCurrentUser(void)
+{
+    NTSTATUS status;
+    HKEY handle;
+    status=pRtlOpenCurrentUser(KEY_READ, &handle);
+    ok(status == STATUS_SUCCESS, "RtlOpenCurrentUser Failed: 0x%08lx\n", status);
+    pNtClose(&handle);
+}
+
+static void test_RtlCheckRegistryKey(void)
+{
+    NTSTATUS status;
+
+    status = pRtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, winetestpath.Buffer);
+    ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE: 0x%08lx\n", status);
+
+    status = pRtlCheckRegistryKey((RTL_REGISTRY_ABSOLUTE & RTL_REGISTRY_OPTIONAL), winetestpath.Buffer);
+    ok(status == STATUS_SUCCESS, "RtlCheckRegistryKey with RTL_REGISTRY_ABSOLUTE & RTL_REGISTRY_OPTIONAL: 0x%08lx\n", status);
+}
+
+static void test_NtDeleteKey()
+{
+    NTSTATUS status;
+    HANDLE hkey;
+    OBJECT_ATTRIBUTES attr;
+    ACCESS_MASK am = KEY_ALL_ACCESS;
+
+    InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
+    status = pNtOpenKey(&hkey, am, &attr);
+
+    status = pNtDeleteKey(hkey);
+    ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08lx\n", status);
+}
+
+START_TEST(reg)
+{
+    static const WCHAR winetest[] = {'\\','W','i','n','e','T','e','s','t','\\',0};
+    InitFunctionPtrs();
+    pRtlFormatCurrentUserKeyPath(&winetestpath);
+    winetestpath.Buffer = (PWSTR)pRtlReAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, winetestpath.Buffer,
+                           winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR));
+    winetestpath.MaximumLength = winetestpath.MaximumLength + sizeof(winetest)*sizeof(WCHAR);
+
+    pRtlAppendUnicodeToString(&winetestpath, winetest);
+
+    test_NtCreateKey();
+    test_NtSetValueKey();
+    test_RtlCheckRegistryKey();
+    test_RtlOpenCurrentUser();
+    test_RtlQueryRegistryValues();
+    test_NtDeleteKey();
+
+    pRtlFreeUnicodeString(&winetestpath);
+
+    FreeLibrary(hntdll);
+}