These tests have to live in ntoskrnl, since only kernel drivers and processes running as LOCAL SYSTEM can create permanent objects.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 6 ++-- dlls/ntoskrnl.exe/tests/driver.c | 49 +++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index 6acdec5dc5a..0f65490b487 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -1378,7 +1378,7 @@ @ stdcall ZwClose(long) NtClose @ stub ZwCloseObjectAuditAlarm @ stdcall -private ZwConnectPort(ptr ptr ptr ptr ptr ptr ptr ptr) NtConnectPort -@ stdcall -private ZwCreateDirectoryObject(ptr long ptr) NtCreateDirectoryObject +@ stdcall ZwCreateDirectoryObject(ptr long ptr) NtCreateDirectoryObject @ stdcall ZwCreateEvent(ptr long ptr long long) NtCreateEvent @ stdcall ZwCreateFile(ptr long ptr ptr ptr long long long long ptr long) NtCreateFile @ stdcall -private ZwCreateIoCompletion(ptr long ptr long) NtCreateIoCompletion @@ -1412,11 +1412,11 @@ @ stdcall -private ZwLoadKey(ptr ptr) NtLoadKey @ stdcall -private ZwLockFile(long long ptr ptr ptr ptr ptr ptr long long) NtLockFile @ stdcall -private ZwLockVirtualMemory(long ptr ptr long) NtLockVirtualMemory -@ stdcall -private ZwMakeTemporaryObject(long) NtMakeTemporaryObject +@ stdcall ZwMakeTemporaryObject(long) NtMakeTemporaryObject @ stdcall -private ZwMapViewOfSection(long long ptr long long ptr ptr long long long) NtMapViewOfSection @ stdcall -private ZwNotifyChangeDirectoryFile(long long ptr ptr ptr ptr long long long) NtNotifyChangeDirectoryFile @ stdcall -private ZwNotifyChangeKey(long long ptr ptr ptr long long ptr long long) NtNotifyChangeKey -@ stdcall -private ZwOpenDirectoryObject(ptr long ptr) NtOpenDirectoryObject +@ stdcall ZwOpenDirectoryObject(ptr long ptr) NtOpenDirectoryObject @ stdcall -private ZwOpenEvent(ptr long ptr) NtOpenEvent @ stdcall ZwOpenFile(ptr long ptr ptr long long) NtOpenFile @ stdcall -private ZwOpenJobObject(ptr long ptr) NtOpenJobObject diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index bb5bbeb4fa5..0ae63ffafb3 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -2024,6 +2024,54 @@ static void test_process_memory(const struct test_input *test_input) ObDereferenceObject(process); }
+static void test_permanence(void) +{ + OBJECT_ATTRIBUTES attr; + HANDLE handle, handle2; + UNICODE_STRING str; + NTSTATUS status; + + RtlInitUnicodeString(&str, L"\BaseNamedObjects\wine_test_dir"); + InitializeObjectAttributes(&attr, &str, 0, 0, NULL); + status = ZwCreateDirectoryObject( &handle, GENERIC_ALL, &attr ); + ok(!status, "got %#x\n", status); + status = ZwClose( handle ); + ok(!status, "got %#x\n", status); + status = ZwOpenDirectoryObject( &handle, 0, &attr ); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#x\n", status); + + attr.Attributes = OBJ_PERMANENT; + status = ZwCreateDirectoryObject( &handle, GENERIC_ALL, &attr ); + ok(!status, "got %#x\n", status); + status = ZwClose( handle ); + ok(!status, "got %#x\n", status); + + attr.Attributes = 0; + status = ZwOpenDirectoryObject( &handle, 0, &attr ); + todo_wine ok(!status, "got %#x\n", status); + status = ZwMakeTemporaryObject( handle ); + ok(!status, "got %#x\n", status); + status = ZwMakeTemporaryObject( handle ); + ok(!status, "got %#x\n", status); + status = ZwClose( handle ); + todo_wine ok(!status, "got %#x\n", status); + status = ZwOpenDirectoryObject( &handle, 0, &attr ); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#x\n", status); + + status = ZwCreateDirectoryObject( &handle, GENERIC_ALL, &attr ); + ok(!status, "got %#x\n", status); + attr.Attributes = OBJ_PERMANENT; + status = ZwOpenDirectoryObject( &handle2, 0, &attr ); + ok(status == STATUS_SUCCESS, "got %#x\n", status); + status = ZwClose( handle2 ); + ok(!status, "got %#x\n", status); + status = ZwClose( handle ); + ok(!status, "got %#x\n", status); + attr.Attributes = 0; + status = ZwOpenDirectoryObject( &handle, 0, &attr ); + ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#x\n", status); +} + static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) { ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; @@ -2080,6 +2128,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st test_affinity(); test_dpc(); test_process_memory(test_input); + test_permanence();
if (main_test_work_item) return STATUS_UNEXPECTED_IO_ERROR;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/object.c | 11 +++++++++-- server/object.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/server/object.c b/server/object.c index dacfe1d71a0..6c0bb9be3ab 100644 --- a/server/object.c +++ b/server/object.c @@ -278,7 +278,8 @@ data_size_t get_path_element( const WCHAR *name, data_size_t len ) }
static struct object *create_object( struct object *parent, const struct object_ops *ops, - const struct unicode_str *name, const struct security_descriptor *sd ) + const struct unicode_str *name, unsigned int attributes, + const struct security_descriptor *sd ) { struct object *obj; struct object_name *name_ptr; @@ -292,6 +293,11 @@ static struct object *create_object( struct object *parent, const struct object_
name_ptr->obj = obj; obj->name = name_ptr; + if (attributes & OBJ_PERMANENT) + { + make_object_static( obj ); + grab_object( obj ); + } return obj;
failed: @@ -340,7 +346,7 @@ void *create_named_object( struct object *parent, const struct object_ops *ops, return obj; }
- new_obj = create_object( obj, ops, &new_name, sd ); + new_obj = create_object( obj, ops, &new_name, attributes, sd ); release_object( obj ); return new_obj; } @@ -401,6 +407,7 @@ void unlink_named_object( struct object *obj ) /* mark an object as being stored statically, i.e. only released at shutdown */ void make_object_static( struct object *obj ) { + obj->is_permanent = 1; #ifdef DEBUG_OBJECTS list_remove( &obj->obj_list ); list_add_head( &static_object_list, &obj->obj_list ); diff --git a/server/object.h b/server/object.h index f0b889d5899..fac35f0984e 100644 --- a/server/object.h +++ b/server/object.h @@ -105,6 +105,7 @@ struct object struct list wait_queue; struct object_name *name; struct security_descriptor *sd; + unsigned int is_permanent:1; #ifdef DEBUG_OBJECTS struct list obj_list; #endif
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=75493
Your paranoid android.
=== debiant (32 bit report) ===
ntoskrnl.exe: driver.c:2051: Test succeeded inside todo block: got 0 driver.c:2057: Test succeeded inside todo block: got 0 driver.c:2059: Test failed: got 0 driver.c:2062: Test failed: got 0xc0000035 driver.c:2069: Test failed: got 0xc0000008 driver.c:2072: Test failed: got 0
=== debiant (32 bit Chinese:China report) ===
ntoskrnl.exe: driver.c:2051: Test succeeded inside todo block: got 0 driver.c:2057: Test succeeded inside todo block: got 0 driver.c:2059: Test failed: got 0 driver.c:2062: Test failed: got 0xc0000035 driver.c:2069: Test failed: got 0xc0000008 driver.c:2072: Test failed: got 0
=== debiant (32 bit WoW report) ===
ntoskrnl.exe: driver.c:2051: Test succeeded inside todo block: got 0 driver.c:2057: Test succeeded inside todo block: got 0 driver.c:2059: Test failed: got 0 driver.c:2062: Test failed: got 0xc0000035 driver.c:2069: Test failed: got 0xc0000008 driver.c:2072: Test failed: got 0
=== debiant (64 bit WoW report) ===
ntoskrnl.exe: driver.c:2051: Test succeeded inside todo block: got 0 driver.c:2057: Test succeeded inside todo block: got 0 driver.c:2059: Test failed: got 0 driver.c:2062: Test failed: got 0xc0000035 driver.c:2069: Test failed: got 0xc0000008 driver.c:2072: Test failed: got 0
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntdll/om.c | 16 +++++++++++++--- dlls/ntoskrnl.exe/tests/driver.c | 4 ++-- server/handle.c | 14 ++++++++++++++ server/object.c | 10 ++++++++++ server/object.h | 1 + server/protocol.def | 6 ++++++ 6 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/om.c b/dlls/ntdll/om.c index 601e6ede123..b2ea815b78f 100644 --- a/dlls/ntdll/om.c +++ b/dlls/ntdll/om.c @@ -511,8 +511,18 @@ NTSTATUS WINAPI NtAllocateUuids( ULARGE_INTEGER *time, ULONG *delta, ULONG *sequ * Success: STATUS_SUCCESS. * Failure: An NTSTATUS error code. */ -NTSTATUS WINAPI NtMakeTemporaryObject( HANDLE Handle ) +NTSTATUS WINAPI NtMakeTemporaryObject( HANDLE handle ) { - FIXME("(%p), stub.\n", Handle); - return STATUS_SUCCESS; + NTSTATUS ret; + + TRACE("%p\n", handle); + + SERVER_START_REQ( make_temporary ) + { + req->handle = wine_server_obj_handle( handle ); + ret = wine_server_call( req ); + } + SERVER_END_REQ; + + return ret; } diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 0ae63ffafb3..0671a56efc7 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -2048,13 +2048,13 @@ static void test_permanence(void)
attr.Attributes = 0; status = ZwOpenDirectoryObject( &handle, 0, &attr ); - todo_wine ok(!status, "got %#x\n", status); + ok(!status, "got %#x\n", status); status = ZwMakeTemporaryObject( handle ); ok(!status, "got %#x\n", status); status = ZwMakeTemporaryObject( handle ); ok(!status, "got %#x\n", status); status = ZwClose( handle ); - todo_wine ok(!status, "got %#x\n", status); + ok(!status, "got %#x\n", status); status = ZwOpenDirectoryObject( &handle, 0, &attr ); ok(status == STATUS_OBJECT_NAME_NOT_FOUND, "got %#x\n", status);
diff --git a/server/handle.c b/server/handle.c index a2a8bb5479c..9ae99cd0c63 100644 --- a/server/handle.c +++ b/server/handle.c @@ -833,3 +833,17 @@ DECL_HANDLER(get_system_handles) enum_processes( enum_handles, &info ); } } + +DECL_HANDLER(make_temporary) +{ + struct object *obj; + + if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return; + + if (obj->is_permanent) + { + make_object_temporary( obj ); + release_object( obj ); + } + release_object( obj ); +} diff --git a/server/object.c b/server/object.c index 6c0bb9be3ab..8ec6609f69d 100644 --- a/server/object.c +++ b/server/object.c @@ -414,6 +414,16 @@ void make_object_static( struct object *obj ) #endif }
+/* mark an object as no longer static */ +void make_object_temporary( struct object *obj ) +{ + obj->is_permanent = 0; +#ifdef DEBUG_OBJECTS + list_remove( &obj->obj_list ); + list_add_head( &object_list, &obj->obj_list ); +#endif +} + /* grab an object (i.e. increment its refcount) and return the object */ struct object *grab_object( void *ptr ) { diff --git a/server/object.h b/server/object.h index fac35f0984e..1f5c4a5f061 100644 --- a/server/object.h +++ b/server/object.h @@ -144,6 +144,7 @@ extern void *open_named_object( struct object *parent, const struct object_ops * const struct unicode_str *name, unsigned int attributes ); extern void unlink_named_object( struct object *obj ); extern void make_object_static( struct object *obj ); +extern void make_object_temporary( struct object *obj ); extern struct namespace *create_namespace( unsigned int hash_size ); extern void free_kernel_objects( struct object *obj ); /* grab/release_object can take any pointer, but you better make sure */ diff --git a/server/protocol.def b/server/protocol.def index 03e567c3dd4..9c8aec6960b 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1080,6 +1080,12 @@ struct rawinput_device #define DUP_HANDLE_MAKE_GLOBAL 0x80000000 /* Not a Windows flag */
+/* Make an object temporary */ +@REQ(make_temporary) + obj_handle_t handle; /* handle to the object */ +@END + + /* Open a handle to a process */ @REQ(open_process) process_id_t pid; /* process id to open */
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=75494
Your paranoid android.
=== debiant (64 bit WoW report) ===
ntdll: om.c:2133: Test failed: got 88
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index d407cffee69..fa85979d0bf 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -1591,17 +1591,19 @@ NTSTATUS WINAPI IoCreateSymbolicLink( UNICODE_STRING *name, UNICODE_STRING *targ { HANDLE handle; OBJECT_ATTRIBUTES attr; + NTSTATUS ret;
attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = name; - attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; + attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL;
TRACE( "%s -> %s\n", debugstr_us(name), debugstr_us(target) ); - /* FIXME: store handle somewhere */ - return NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target ); + if (!(ret = NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target ))) + NtClose( handle ); + return ret; }
@@ -1612,17 +1614,19 @@ NTSTATUS WINAPI IoCreateUnprotectedSymbolicLink( UNICODE_STRING *name, UNICODE_S { HANDLE handle; OBJECT_ATTRIBUTES attr; + NTSTATUS ret;
attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = name; - attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF; + attr.Attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF | OBJ_PERMANENT; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL;
TRACE( "%s -> %s\n", debugstr_us(name), debugstr_us(target) ); - /* FIXME: store handle somewhere */ - return NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target ); + if (!(ret = NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, target ))) + NtClose( handle ); + return ret; }
@@ -1644,12 +1648,7 @@ NTSTATUS WINAPI IoDeleteSymbolicLink( UNICODE_STRING *name )
if (!(status = NtOpenSymbolicLinkObject( &handle, 0, &attr ))) { - SERVER_START_REQ( unlink_object ) - { - req->handle = wine_server_obj_handle( handle ); - status = wine_server_call( req ); - } - SERVER_END_REQ; + NtMakeTemporaryObject( handle ); NtClose( handle ); } return status;
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=75495
Your paranoid android.
=== debiant (32 bit report) ===
ntdll: om.c:2118: Test failed: got 84
=== debiant (32 bit Chinese:China report) ===
ntdll: om.c:2118: Test failed: got 88
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/kernelbase/volume.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/dlls/kernelbase/volume.c b/dlls/kernelbase/volume.c index 9939ea3bef4..b10fe771a6e 100644 --- a/dlls/kernelbase/volume.c +++ b/dlls/kernelbase/volume.c @@ -972,18 +972,13 @@ BOOL WINAPI DECLSPEC_HOTPATCH DefineDosDeviceW( DWORD flags, const WCHAR *device
lstrcatW( link_name, device ); RtlInitUnicodeString( &nt_name, link_name ); - InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE, 0, NULL ); + InitializeObjectAttributes( &attr, &nt_name, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 0, NULL ); if (flags & DDD_REMOVE_DEFINITION) { if (!set_ntstatus( NtOpenSymbolicLinkObject( &handle, 0, &attr ) )) return FALSE;
- SERVER_START_REQ( unlink_object ) - { - req->handle = wine_server_obj_handle( handle ); - status = wine_server_call( req ); - } - SERVER_END_REQ; + status = NtMakeTemporaryObject( handle ); NtClose( handle );
return set_ntstatus( status ); @@ -1000,7 +995,9 @@ BOOL WINAPI DECLSPEC_HOTPATCH DefineDosDeviceW( DWORD flags, const WCHAR *device else RtlInitUnicodeString( &nt_target, target );
- return set_ntstatus( NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, &nt_target ) ); + if (!(status = NtCreateSymbolicLinkObject( &handle, SYMBOLIC_LINK_ALL_ACCESS, &attr, &nt_target ))) + NtClose( handle ); + return set_ntstatus( status ); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- server/directory.c | 12 ------------ server/protocol.def | 6 ------ 2 files changed, 18 deletions(-)
diff --git a/server/directory.c b/server/directory.c index 4d38393a6c8..198fc48ece2 100644 --- a/server/directory.c +++ b/server/directory.c @@ -534,18 +534,6 @@ DECL_HANDLER(get_directory_entry) } }
-/* unlink a named object */ -DECL_HANDLER(unlink_object) -{ - struct object *obj = get_handle_obj( current->process, req->handle, 0, NULL ); - - if (obj) - { - unlink_named_object( obj ); - release_object( obj ); - } -} - /* query object type name information */ DECL_HANDLER(get_object_type) { diff --git a/server/protocol.def b/server/protocol.def index 9c8aec6960b..4a59c327287 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3442,12 +3442,6 @@ struct handle_info @END
-/* Unlink a named object */ -@REQ(unlink_object) - obj_handle_t handle; /* handle to the object */ -@END - - /* Query the impersonation level of an impersonation token */ @REQ(get_token_impersonation_level) obj_handle_t handle; /* handle to the object */