From a9a1d6103856ddb47a8e467581d22f2a518e7c07 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 14 Feb 2005 21:08:56 +0000 Subject: [PATCH] Brad DeMorrow Tests for the ntdll registry functions. --- dlls/ntdll/tests/.cvsignore | 1 + dlls/ntdll/tests/Makefile.in | 1 + dlls/ntdll/tests/reg.c | 364 +++++++++++++++++++++++++++++++++++ 3 files changed, 366 insertions(+) create mode 100644 dlls/ntdll/tests/reg.c diff --git a/dlls/ntdll/tests/.cvsignore b/dlls/ntdll/tests/.cvsignore index e2ef7e4097c..9027a6e5baf 100644 --- a/dlls/ntdll/tests/.cvsignore +++ b/dlls/ntdll/tests/.cvsignore @@ -4,6 +4,7 @@ error.ok generated.ok large_int.ok path.ok +reg.ok rtl.ok rtlbitmap.ok rtlstr.ok diff --git a/dlls/ntdll/tests/Makefile.in b/dlls/ntdll/tests/Makefile.in index af18eeda404..59b05a69dd1 100644 --- a/dlls/ntdll/tests/Makefile.in +++ b/dlls/ntdll/tests/Makefile.in @@ -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 index 00000000000..5dce55d3637 --- /dev/null +++ b/dlls/ntdll/tests/reg.c @@ -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); +}