ntdll: Added KeyCachedInformation key info class implementation.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2015-11-11 14:17:09 +01:00 committed by Alexandre Julliard
parent 3d5db6bdf5
commit 5eb3035374
4 changed files with 101 additions and 7 deletions

View File

@ -261,6 +261,7 @@ static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS i
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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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 );