Jacek Caban : ntdll: Added KeyCachedInformation key info class implementation.
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Nov 12 09:58:27 CST 2015
Module: wine
Branch: master
Commit: 5eb30353747303699ceb1ae99b6c33d6879721ca
URL: http://source.winehq.org/git/wine.git/?a=commit;h=5eb30353747303699ceb1ae99b6c33d6879721ca
Author: Jacek Caban <jacek at codeweavers.com>
Date: Wed Nov 11 14:17:09 2015 +0100
ntdll: Added KeyCachedInformation key info class implementation.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/reg.c | 26 +++++++++++++++++++----
dlls/ntdll/tests/reg.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++-
include/winternl.h | 19 ++++++++++++++++-
server/registry.c | 6 +++++-
4 files changed, 101 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/reg.c b/dlls/ntdll/reg.c
index 0701426..be95a2a 100644
--- a/dlls/ntdll/reg.c
+++ b/dlls/ntdll/reg.c
@@ -257,10 +257,11 @@ static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS i
switch(info_class)
{
- case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
- case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
- case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break;
- case KeyNameInformation: data_ptr = ((KEY_NAME_INFORMATION *)info)->Name; break;
+ case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
+ case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
+ case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break;
+ case KeyNameInformation: data_ptr = ((KEY_NAME_INFORMATION *)info)->Name; break;
+ case KeyCachedInformation: data_ptr = ((KEY_CACHED_INFORMATION *)info)+1; break;
default:
FIXME( "Information class %d not implemented\n", info_class );
return STATUS_INVALID_PARAMETER;
@@ -332,6 +333,23 @@ static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS i
memcpy( info, &keyinfo, min( length, fixed_size ) );
}
break;
+ case KeyCachedInformation:
+ {
+ KEY_CACHED_INFORMATION keyinfo;
+ fixed_size = sizeof(keyinfo);
+ keyinfo.LastWriteTime.QuadPart = reply->modif;
+ keyinfo.TitleIndex = 0;
+ keyinfo.SubKeys = reply->subkeys;
+ keyinfo.MaxNameLen = reply->max_subkey;
+ keyinfo.Values = reply->values;
+ keyinfo.MaxValueNameLen = reply->max_value;
+ keyinfo.MaxValueDataLen = reply->max_data;
+ keyinfo.NameLength = reply->namelen;
+ memcpy( info, &keyinfo, min( length, fixed_size ) );
+ }
+ break;
+ default:
+ break;
}
*result_len = fixed_size + reply->total;
if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c
index 149910a..dfec007 100644
--- a/dlls/ntdll/tests/reg.c
+++ b/dlls/ntdll/tests/reg.c
@@ -1466,12 +1466,14 @@ static void test_long_value_name(void)
static void test_NtQueryKey(void)
{
- HANDLE key;
+ HANDLE key, subkey, subkey2;
NTSTATUS status;
OBJECT_ATTRIBUTES attr;
ULONG length, len;
KEY_NAME_INFORMATION *info = NULL;
+ KEY_CACHED_INFORMATION cached_info;
UNICODE_STRING str;
+ DWORD dw;
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0);
status = pNtOpenKey(&key, KEY_READ, &attr);
@@ -1506,6 +1508,59 @@ static void test_NtQueryKey(void)
wine_dbgstr_wn(winetestpath.Buffer, winetestpath.Length/sizeof(WCHAR)));
HeapFree(GetProcessHeap(), 0, info);
+
+ attr.RootDirectory = key;
+ attr.ObjectName = &str;
+ pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey");
+ status = pNtCreateKey(&subkey, GENERIC_ALL, &attr, 0, 0, 0, 0);
+ ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
+
+ status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len);
+ ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
+
+ if (status == STATUS_SUCCESS)
+ {
+ ok(len == sizeof(cached_info), "got unexpected length %d\n", len);
+ ok(cached_info.SubKeys == 0, "cached_info.SubKeys = %u\n", cached_info.SubKeys);
+ ok(cached_info.MaxNameLen == 0, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen);
+ ok(cached_info.Values == 0, "cached_info.Values = %u\n", cached_info.Values);
+ ok(cached_info.MaxValueNameLen == 0, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen);
+ ok(cached_info.MaxValueDataLen == 0, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen);
+ ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength);
+ }
+
+ attr.RootDirectory = subkey;
+ attr.ObjectName = &str;
+ pRtlCreateUnicodeStringFromAsciiz(&str, "test_subkey2");
+ status = pNtCreateKey(&subkey2, GENERIC_ALL, &attr, 0, 0, 0, 0);
+ ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
+
+ pRtlCreateUnicodeStringFromAsciiz(&str, "val");
+ dw = 64;
+ status = pNtSetValueKey( subkey, &str, 0, REG_DWORD, &dw, sizeof(dw) );
+ ok( status == STATUS_SUCCESS, "NtSetValueKey failed: 0x%08x\n", status );
+
+ status = pNtQueryKey(subkey, KeyCachedInformation, &cached_info, sizeof(cached_info), &len);
+ ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08x\n", status);
+
+ if (status == STATUS_SUCCESS)
+ {
+ ok(len == sizeof(cached_info), "got unexpected length %d\n", len);
+ ok(cached_info.SubKeys == 1, "cached_info.SubKeys = %u\n", cached_info.SubKeys);
+ ok(cached_info.MaxNameLen == 24, "cached_info.MaxNameLen = %u\n", cached_info.MaxNameLen);
+ ok(cached_info.Values == 1, "cached_info.Values = %u\n", cached_info.Values);
+ ok(cached_info.MaxValueNameLen == 6, "cached_info.MaxValueNameLen = %u\n", cached_info.MaxValueNameLen);
+ ok(cached_info.MaxValueDataLen == 4, "cached_info.MaxValueDataLen = %u\n", cached_info.MaxValueDataLen);
+ ok(cached_info.NameLength == 22, "cached_info.NameLength = %u\n", cached_info.NameLength);
+ }
+
+ status = pNtDeleteKey(subkey2);
+ ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
+ status = pNtDeleteKey(subkey);
+ ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
+
+ pNtClose(subkey2);
+ pNtClose(subkey);
pNtClose(key);
}
diff --git a/include/winternl.h b/include/winternl.h
index 1746601..ecd5791 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -696,7 +696,12 @@ typedef enum _KEY_INFORMATION_CLASS {
KeyBasicInformation,
KeyNodeInformation,
KeyFullInformation,
- KeyNameInformation
+ KeyNameInformation,
+ KeyCachedInformation,
+ KeyFlagsInformation,
+ KeyVirtualizationInformation,
+ KeyHandleTagsInformation,
+ MaxKeyInfoClass
} KEY_INFORMATION_CLASS;
typedef enum _KEY_VALUE_INFORMATION_CLASS {
@@ -1024,6 +1029,18 @@ typedef struct _KEY_NAME_INFORMATION {
WCHAR Name[1];
} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
+typedef struct _KEY_CACHED_INFORMATION
+{
+ LARGE_INTEGER LastWriteTime;
+ ULONG TitleIndex;
+ ULONG SubKeys;
+ ULONG MaxNameLen;
+ ULONG Values;
+ ULONG MaxValueNameLen;
+ ULONG MaxValueDataLen;
+ ULONG NameLength;
+} KEY_CACHED_INFORMATION, *PKEY_CACHED_INFORMATION;
+
typedef struct _KEY_VALUE_ENTRY
{
PUNICODE_STRING ValueName;
diff --git a/server/registry.c b/server/registry.c
index 94777b3..dad86e7 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -906,6 +906,7 @@ static void enum_key( const struct key *key, int index, int info_class,
reply->max_data = 0;
break;
case KeyFullInformation:
+ case KeyCachedInformation:
for (i = 0; i <= key->last_subkey; i++)
{
if (key->subkeys[i]->namelen > max_subkey) max_subkey = key->subkeys[i]->namelen;
@@ -920,7 +921,10 @@ static void enum_key( const struct key *key, int index, int info_class,
reply->max_class = max_class;
reply->max_value = max_value;
reply->max_data = max_data;
- namelen = 0; /* only return the class */
+ reply->namelen = namelen;
+ if (info_class == KeyCachedInformation)
+ classlen = 0; /* don't return any data, only its size */
+ namelen = 0; /* don't return name */
break;
default:
set_error( STATUS_INVALID_PARAMETER );
More information about the wine-cvs
mailing list