From: Sven Baars sbaars@codeweavers.com
--- dlls/ntdll/tests/reg.c | 52 ++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/registry.c | 18 +++++++++++- include/wine/server_protocol.h | 4 ++- server/protocol.def | 1 + server/registry.c | 23 +++++++++++++++ server/request.h | 9 +++--- server/trace.c | 1 + 7 files changed, 102 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 978d50dbd0d..49f53e3f04b 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -115,6 +115,12 @@ typedef enum _KEY_VALUE_INFORMATION_CLASS {
#endif
+typedef struct _KEY_FLAGS_INFORMATION{ + ULONG Unknown1; + ULONG Unknown2; + ULONG WowShare; +} KEY_FLAGS_INFORMATION, *PKEY_FLAGS_INFORMATION; + static BOOLEAN (WINAPI * pRtlCreateUnicodeStringFromAsciiz)(PUNICODE_STRING, LPCSTR); static void (WINAPI * pRtlInitUnicodeString)(PUNICODE_STRING,PCWSTR); static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING); @@ -2135,6 +2141,7 @@ static void test_NtQueryKey(void) OBJECT_ATTRIBUTES attr; ULONG length, len; KEY_NAME_INFORMATION *info = NULL; + KEY_FLAGS_INFORMATION flags_info; KEY_CACHED_INFORMATION cached_info; UNICODE_STRING str; DWORD dw; @@ -2242,6 +2249,51 @@ static void test_NtQueryKey(void)
pNtClose(subkey2); pNtClose(subkey); + + status = pNtQueryKey(key, KeyFlagsInformation, &flags_info, sizeof(flags_info), &len); + ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08lx\n", status); + ok(len == sizeof(flags_info), "got unexpected length %ld\n", len); + ok(flags_info.WowShare == 0, "flags_info.WowShare = %lu\n", flags_info.WowShare); + + pNtClose(key); + + pRtlCreateUnicodeStringFromAsciiz(&str, "\REGISTRY\Machine\Software\Classes"); + attr.RootDirectory = 0; + status = pNtOpenKey(&key, KEY_READ, &attr); + ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status); + pRtlFreeUnicodeString(&str); + + status = pNtQueryKey(key, KeyFlagsInformation, &flags_info, sizeof(flags_info), &len); + ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08lx\n", status); + ok(len == sizeof(flags_info), "got unexpected length %ld\n", len); + ok(flags_info.WowShare == 10, "flags_info.WowShare = %lu\n", flags_info.WowShare); + + pNtClose(key); + + pRtlCreateUnicodeStringFromAsciiz(&str, "\REGISTRY\Machine\Software\Classes\Interface"); + attr.RootDirectory = 0; + status = pNtOpenKey(&key, KEY_READ, &attr); + ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status); + pRtlFreeUnicodeString(&str); + + status = pNtQueryKey(key, KeyFlagsInformation, &flags_info, sizeof(flags_info), &len); + ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08lx\n", status); + ok(len == sizeof(flags_info), "got unexpected length %ld\n", len); + ok(flags_info.WowShare == 10, "flags_info.WowShare = %lu\n", flags_info.WowShare); + + pNtClose(key); + + pRtlCreateUnicodeStringFromAsciiz(&str, "\REGISTRY\Machine\Software\Classes\Wow6432Node"); + attr.RootDirectory = 0; + status = pNtOpenKey(&key, KEY_READ, &attr); + ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08lx\n", status); + pRtlFreeUnicodeString(&str); + + status = pNtQueryKey(key, KeyFlagsInformation, &flags_info, sizeof(flags_info), &len); + ok(status == STATUS_SUCCESS, "NtQueryKey Failed: 0x%08lx\n", status); + ok(len == sizeof(flags_info), "got unexpected length %ld\n", len); + ok(flags_info.WowShare == 10, "flags_info.WowShare = %lu\n", flags_info.WowShare); + pNtClose(key); }
diff --git a/dlls/ntdll/unix/registry.c b/dlls/ntdll/unix/registry.c index d183474b53f..272782ef7a7 100644 --- a/dlls/ntdll/unix/registry.c +++ b/dlls/ntdll/unix/registry.c @@ -232,7 +232,6 @@ NTSTATUS WINAPI NtRenameKey( HANDLE key, UNICODE_STRING *name ) return ret; }
- /****************************************************************************** * enumerate_key * @@ -242,6 +241,12 @@ static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS i void *info, DWORD length, DWORD *result_len )
{ + typedef struct { + ULONG Unknown1; + ULONG Unknown2; + ULONG WowShare; + } KEY_FLAGS_INFORMATION; + unsigned int ret; void *data_ptr; size_t fixed_size; @@ -253,6 +258,7 @@ static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS i 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; + case KeyFlagsInformation: data_ptr = ((KEY_FLAGS_INFORMATION *)info)+1; break; default: FIXME( "Information class %d not implemented\n", info_class ); return STATUS_INVALID_PARAMETER; @@ -339,6 +345,16 @@ static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS i break; }
+ case KeyFlagsInformation: + { + KEY_FLAGS_INFORMATION keyinfo; + keyinfo.Unknown1 = 0; + keyinfo.Unknown2 = 0; + keyinfo.WowShare = reply->wowshare; + memcpy( info, &keyinfo, min( length, fixed_size ) ); + break; + } + default: break; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 472c0ea709d..fbdaf965a06 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2301,6 +2301,8 @@ struct enum_key_reply int values; int max_value; int max_data; + int wowshare; + char __pad_36[4]; timeout_t modif; data_size_t total; data_size_t namelen; @@ -6356,7 +6358,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 758 +#define SERVER_PROTOCOL_VERSION 759
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index 8c2fbeb4afe..0dba49f75d3 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1791,6 +1791,7 @@ struct process_info int values; /* number of values */ int max_value; /* longest value name */ int max_data; /* longest value data */ + int wowshare; /* wowshare flags */ timeout_t modif; /* last modification time */ data_size_t total; /* total length needed for full name and class */ data_size_t namelen; /* length of key name in bytes */ diff --git a/server/registry.c b/server/registry.c index 03e5f20cae5..895a962d3a7 100644 --- a/server/registry.c +++ b/server/registry.c @@ -900,6 +900,17 @@ static struct key *create_key_recursive( struct key *root, const struct unicode_ return parent; }
+static int has_wowshare_parent( struct key *key ) +{ + if (!key) + return 0; + + if (key->wow6432node) + return (key->wow6432node->flags & KEY_WOWSHARE) ? 1 : 0; + + return has_wowshare_parent( get_parent( key ) ); +} + /* query information about a key or a subkey */ static void enum_key( struct key *key, int index, int info_class, struct enum_key_reply *reply ) { @@ -942,6 +953,7 @@ static void enum_key( struct key *key, int index, int info_class, struct enum_ke reply->max_class = 0; reply->max_value = 0; reply->max_data = 0; + reply->wowshare = 0; break; case KeyFullInformation: case KeyCachedInformation: @@ -959,11 +971,22 @@ static void enum_key( struct key *key, int index, int info_class, struct enum_ke reply->max_class = max_class; reply->max_value = max_value; reply->max_data = max_data; + reply->wowshare = 0; reply->namelen = namelen; if (info_class == KeyCachedInformation) classlen = 0; /* don't return any data, only its size */ namelen = 0; /* don't return name */ break; + case KeyFlagsInformation: + namelen = 0; + classlen = 0; + reply->max_subkey = 0; + reply->max_class = 0; + reply->max_value = 0; + reply->max_data = 0; + reply->wowshare = has_wowshare_parent(key) ? 10 : 0; + reply->namelen = 0; + break; default: set_error( STATUS_INVALID_PARAMETER ); return; diff --git a/server/request.h b/server/request.h index 089af79e199..befd1cf93f1 100644 --- a/server/request.h +++ b/server/request.h @@ -1209,10 +1209,11 @@ C_ASSERT( FIELD_OFFSET(struct enum_key_reply, max_class) == 16 ); C_ASSERT( FIELD_OFFSET(struct enum_key_reply, values) == 20 ); C_ASSERT( FIELD_OFFSET(struct enum_key_reply, max_value) == 24 ); C_ASSERT( FIELD_OFFSET(struct enum_key_reply, max_data) == 28 ); -C_ASSERT( FIELD_OFFSET(struct enum_key_reply, modif) == 32 ); -C_ASSERT( FIELD_OFFSET(struct enum_key_reply, total) == 40 ); -C_ASSERT( FIELD_OFFSET(struct enum_key_reply, namelen) == 44 ); -C_ASSERT( sizeof(struct enum_key_reply) == 48 ); +C_ASSERT( FIELD_OFFSET(struct enum_key_reply, wowshare) == 32 ); +C_ASSERT( FIELD_OFFSET(struct enum_key_reply, modif) == 40 ); +C_ASSERT( FIELD_OFFSET(struct enum_key_reply, total) == 48 ); +C_ASSERT( FIELD_OFFSET(struct enum_key_reply, namelen) == 52 ); +C_ASSERT( sizeof(struct enum_key_reply) == 56 ); C_ASSERT( FIELD_OFFSET(struct set_key_value_request, hkey) == 12 ); C_ASSERT( FIELD_OFFSET(struct set_key_value_request, type) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_key_value_request, namelen) == 20 ); diff --git a/server/trace.c b/server/trace.c index a0076d5449b..301f1a0ff35 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2360,6 +2360,7 @@ static void dump_enum_key_reply( const struct enum_key_reply *req ) fprintf( stderr, ", values=%d", req->values ); fprintf( stderr, ", max_value=%d", req->max_value ); fprintf( stderr, ", max_data=%d", req->max_data ); + fprintf( stderr, ", wowshare=%d", req->wowshare ); dump_timeout( ", modif=", &req->modif ); fprintf( stderr, ", total=%u", req->total ); fprintf( stderr, ", namelen=%u", req->namelen );