A deleted key returns STATUS_KEY_DELETED when ObjectNameInformation is requested, but succeeds when ObjectBasicInformation is requested.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/unix/file.c | 2 +- server/handle.c | 11 ++++++++++- server/protocol.def | 7 +++++++ 3 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 1a57a112a59..21bcb215385 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -6772,7 +6772,7 @@ NTSTATUS WINAPI NtQueryObject( HANDLE handle, OBJECT_INFORMATION_CLASS info_clas
/* not a file, treat as a generic object */
- SERVER_START_REQ( get_object_info ) + SERVER_START_REQ( get_object_name ) { req->handle = wine_server_obj_handle( handle ); if (len > sizeof(*p)) wine_server_set_reply( req, p + 1, len - sizeof(*p) ); diff --git a/server/handle.c b/server/handle.c index d86f0960ccf..6efd82f2ff9 100644 --- a/server/handle.c +++ b/server/handle.c @@ -686,13 +686,22 @@ DECL_HANDLER(dup_handle) DECL_HANDLER(get_object_info) { struct object *obj; - WCHAR *name;
if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return;
reply->access = get_handle_access( current->process, req->handle ); reply->ref_count = obj->refcount; reply->handle_count = obj->handle_count; + release_object( obj ); +} + +DECL_HANDLER(get_object_name) +{ + struct object *obj; + WCHAR *name; + + if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return; + if ((name = obj->ops->get_full_name( obj, &reply->total ))) set_reply_data_ptr( name, min( reply->total, get_reply_max_size() )); release_object( obj ); diff --git a/server/protocol.def b/server/protocol.def index 762be1fa7c0..59ed5632503 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3299,6 +3299,13 @@ struct handle_info unsigned int access; /* granted access mask */ unsigned int ref_count; /* object ref count */ unsigned int handle_count; /* object handle count */ +@END + + +/* Query the full name of an object */ +@REQ(get_object_name) + obj_handle_t handle; /* handle to the object */ +@REPLY data_size_t total; /* total needed size for name */ VARARG(name,unicode_str); /* object name */ @END
This fixes a server crash that can be triggered by deleting a key and then trying to retrieve its name. In that case key->parent is NULL.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/registry.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/server/registry.c b/server/registry.c index f36760e6cc1..b7971770728 100644 --- a/server/registry.c +++ b/server/registry.c @@ -413,6 +413,12 @@ static WCHAR *key_get_full_name( struct object *obj, data_size_t *ret_len ) data_size_t len = sizeof(root_name) - sizeof(WCHAR); char *ret;
+ if (key->flags & KEY_DELETED) + { + set_error( STATUS_KEY_DELETED ); + return NULL; + } + for (key = (struct key *)obj; key != root_key; key = key->parent) len += key->namelen + sizeof(WCHAR); if (!(ret = malloc( len ))) return NULL;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/tests/reg.c | 53 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c index 7463f98aa29..91b752ac069 100644 --- a/dlls/ntdll/tests/reg.c +++ b/dlls/ntdll/tests/reg.c @@ -125,6 +125,8 @@ static NTSTATUS (WINAPI * pRtlOpenCurrentUser)(IN ACCESS_MASK, PHANDLE); static NTSTATUS (WINAPI * pNtOpenKey)(PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES); static NTSTATUS (WINAPI * pNtOpenKeyEx)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, ULONG); static NTSTATUS (WINAPI * pNtClose)(IN HANDLE); +static NTSTATUS (WINAPI * pNtEnumerateKey)(HANDLE, ULONG, KEY_INFORMATION_CLASS, void *, DWORD, DWORD *); +static NTSTATUS (WINAPI * pNtEnumerateValueKey)(HANDLE, ULONG, KEY_VALUE_INFORMATION_CLASS, void *, DWORD, DWORD *); static NTSTATUS (WINAPI * pNtFlushKey)(HANDLE); static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE); static NTSTATUS (WINAPI * pNtCreateKey)( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr, @@ -132,6 +134,7 @@ static NTSTATUS (WINAPI * pNtCreateKey)( PHANDLE retkey, ACCESS_MASK access, con PULONG dispos ); static NTSTATUS (WINAPI * pNtQueryKey)(HANDLE,KEY_INFORMATION_CLASS,PVOID,ULONG,PULONG); static NTSTATUS (WINAPI * pNtQueryLicenseValue)(const UNICODE_STRING *,ULONG *,PVOID,ULONG,ULONG *); +static NTSTATUS (WINAPI * pNtQueryObject)(HANDLE, OBJECT_INFORMATION_CLASS, void *, ULONG, ULONG *); static NTSTATUS (WINAPI * pNtQueryValueKey)(HANDLE,const UNICODE_STRING *,KEY_VALUE_INFORMATION_CLASS,void *,DWORD,DWORD *); static NTSTATUS (WINAPI * pNtSetValueKey)(HANDLE, const PUNICODE_STRING, ULONG, ULONG, const void*, ULONG ); @@ -181,9 +184,12 @@ static BOOL InitFunctionPtrs(void) NTDLL_GET_PROC(NtClose) NTDLL_GET_PROC(NtDeleteValueKey) NTDLL_GET_PROC(NtCreateKey) + NTDLL_GET_PROC(NtEnumerateKey) + NTDLL_GET_PROC(NtEnumerateValueKey) NTDLL_GET_PROC(NtFlushKey) NTDLL_GET_PROC(NtDeleteKey) NTDLL_GET_PROC(NtQueryKey) + NTDLL_GET_PROC(NtQueryObject) NTDLL_GET_PROC(NtQueryValueKey) NTDLL_GET_PROC(NtQueryInformationProcess) NTDLL_GET_PROC(NtSetValueKey) @@ -844,20 +850,61 @@ static void test_NtQueryValueKey(void)
static void test_NtDeleteKey(void) { + UNICODE_STRING string; + char buffer[200]; NTSTATUS status; - HANDLE hkey; + HANDLE hkey, hkey2; OBJECT_ATTRIBUTES attr; - ACCESS_MASK am = KEY_ALL_ACCESS; + DWORD size;
status = pNtDeleteKey(NULL); ok(status == STATUS_INVALID_HANDLE, "Expected STATUS_INVALID_HANDLE, got: 0x%08x\n", status);
InitializeObjectAttributes(&attr, &winetestpath, 0, 0, 0); - status = pNtOpenKey(&hkey, am, &attr); + status = pNtOpenKey(&hkey, KEY_ALL_ACCESS, &attr); ok(status == STATUS_SUCCESS, "NtOpenKey Failed: 0x%08x\n", status);
status = pNtDeleteKey(hkey); ok(status == STATUS_SUCCESS, "NtDeleteKey Failed: 0x%08x\n", status); + + status = pNtQueryKey(hkey, KeyNameInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtEnumerateKey(hkey, 0, KeyFullInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + pRtlInitUnicodeString(&string, L"value"); + status = pNtQueryValueKey(hkey, &string, KeyValueBasicInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtEnumerateValueKey(hkey, 0, KeyValuePartialInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtSetValueKey(hkey, &string, 0, REG_SZ, "test", 5); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtDeleteValueKey(hkey, &string); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtDeleteKey(hkey); + todo_wine ok(!status, "got %#x\n", status); + + RtlInitUnicodeString(&string, L"subkey"); + InitializeObjectAttributes(&attr, &string, OBJ_CASE_INSENSITIVE, hkey, NULL); + status = pNtOpenKey(&hkey2, KEY_READ, &attr); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtCreateKey(&hkey2, KEY_ALL_ACCESS, &attr, 0, NULL, 0, NULL); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtQueryObject(hkey, ObjectNameInformation, buffer, sizeof(buffer), &size); + ok(status == STATUS_KEY_DELETED, "got %#x\n", status); + + status = pNtQueryObject(hkey, ObjectBasicInformation, buffer, sizeof(OBJECT_BASIC_INFORMATION), &size); + ok(!status, "got %#x\n", status); + + status = pNtClose(hkey); + ok(status == STATUS_SUCCESS, "got %#x\n", status); }
static void test_NtQueryLicenseKey(void)