[PATCH v5 1/3] server: Use a separate request to retrieve the object name.
A deleted key returns STATUS_KEY_DELETED when ObjectNameInformation is requested, but succeeds when ObjectBasicInformation is requested. Signed-off-by: Zebediah Figura <z.figura12(a)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 */ +(a)END + + +/* Query the full name of an object */ +(a)REQ(get_object_name) + obj_handle_t handle; /* handle to the object */ +(a)REPLY data_size_t total; /* total needed size for name */ VARARG(name,unicode_str); /* object name */ @END -- 2.30.2
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(a)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; -- 2.30.2
Signed-off-by: Zebediah Figura <z.figura12(a)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) -- 2.30.2
participants (1)
-
Zebediah Figura