[PATCH v3 0/4] MR10247: server, ntoskrnl.exe: Implement FsRtlGetFileSize().
Needed by Persona 5: The Phantom X (SEA/KR/CN) in order to launch the game. -- v3: ntoskrnl.exe/tests: Add tests for FsRtlGetFileSize(). ntoskrnl.exe: Implement FsRtlGetFileSize(). ntoskrnl.exe/tests: Add tests for directory kernel objects. server: Allow creating directory kernel objects. https://gitlab.winehq.org/wine/wine/-/merge_requests/10247
From: Nello De Gregoris <bluechxindv@gmail.com> Based on https://gitlab.winehq.org/wine/wine/-/commit/dcaeddd4db127ebabc4f27627e1278b.... --- server/change.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/server/change.c b/server/change.c index 5cbc5bdacfc..f7c2ac9a6d5 100644 --- a/server/change.c +++ b/server/change.c @@ -93,6 +93,7 @@ struct dir struct inode *inode; /* inode of the associated directory */ struct process *client_process; /* client process that has a cache for this directory */ int client_entry; /* entry in client process cache */ + struct list kernel_object; /* list of kernel object pointers */ }; static struct fd *dir_get_fd( struct object *obj ); @@ -102,6 +103,7 @@ static int dir_set_sd( struct object *obj, const struct security_descriptor *sd, static void dir_dump( struct object *obj, int verbose ); static int dir_close_handle( struct object *obj, struct process *process, obj_handle_t handle ); static void dir_destroy( struct object *obj ); +static struct list *dir_get_kernel_obj_list( struct object *obj ); static const struct object_ops dir_ops = { @@ -123,7 +125,7 @@ static const struct object_ops dir_ops = no_link_name, /* link_name */ NULL, /* unlink_name */ no_open_file, /* open_file */ - no_kernel_obj_list, /* get_kernel_obj_list */ + dir_get_kernel_obj_list, /* get_kernel_obj_list */ dir_close_handle, /* close_handle */ dir_destroy /* destroy */ }; @@ -451,6 +453,12 @@ static void dir_destroy( struct object *obj ) } } +static struct list *dir_get_kernel_obj_list( struct object *obj ) +{ + struct dir *dir = (struct dir *)obj; + return &dir->kernel_object; +} + struct dir *get_dir_obj( struct process *process, obj_handle_t handle, unsigned int access ) { return (struct dir *)get_handle_obj( process, handle, access, &dir_ops ); @@ -1142,6 +1150,7 @@ struct object *create_dir_obj( struct fd *fd, unsigned int access, mode_t mode ) return NULL; list_init( &dir->change_records ); + list_init( &dir->kernel_object ); dir->filter = 0; dir->notified = 0; dir->want_data = 0; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10247
From: Nello De Gregoris <bluechxindv@gmail.com> --- dlls/ntoskrnl.exe/tests/driver.c | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 9358cf605a4..12fc1b8fc0a 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -1981,6 +1981,40 @@ static void test_object_name(void) ok(!name->Name.MaximumLength, "got maximum length %u\n", name->Name.MaximumLength); } +static void test_dir_kernel_object(void) +{ + OBJECT_ATTRIBUTES attr = { sizeof(attr) }; + UNICODE_STRING pathU; + IO_STATUS_BLOCK io; + FILE_OBJECT *file_obj; + HANDLE dir_handle, handle; + NTSTATUS status; + + RtlInitUnicodeString(&pathU, L"\\??\\C:\\windows"); + InitializeObjectAttributes(&attr, &pathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwOpenFile(&dir_handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &io, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); + ok(!status, "ZwOpenFile failed: %#lx\n", status); + if (status) + return; + + status = ObReferenceObjectByHandle(dir_handle, 0, *pIoFileObjectType, KernelMode, + (void **)&file_obj, NULL); + ok(!status, "ObReferenceObjectByHandle failed: %#lx\n", status); + if (!status) + { + status = ObOpenObjectByPointer(file_obj, OBJ_KERNEL_HANDLE, NULL, 0, + *pIoFileObjectType, KernelMode, &handle); + ok(!status, "ObOpenObjectByPointer failed: %#lx\n", status); + if (!status) + ZwClose(handle); + ObDereferenceObject(file_obj); + } + + ZwClose(dir_handle); +} + static PIO_WORKITEM work_item; static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context) @@ -2523,6 +2557,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st test_lookup_thread(); test_IoAttachDeviceToDeviceStack(); test_object_name(); + test_dir_kernel_object(); #if defined(__i386__) || defined(__x86_64__) test_executable_pool(); #endif -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10247
From: Nello De Gregoris <bluechxindv@gmail.com> --- dlls/ntoskrnl.exe/ntoskrnl.c | 25 +++++++++++++++++++++++++ dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +- include/ddk/ntifs.h | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 0855749249f..adf5a9bcd3f 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -2460,6 +2460,31 @@ NTSTATUS WINAPI ExInitializeZone(PZONE_HEADER Zone, return STATUS_NOT_IMPLEMENTED; } +/*********************************************************************** + * FsRtlGetFileSize (NTOSKRNL.EXE.@) + */ +NTSTATUS WINAPI FsRtlGetFileSize( PFILE_OBJECT file_obj, PLARGE_INTEGER file_size ) +{ + FILE_STANDARD_INFORMATION info; + IO_STATUS_BLOCK iosb; + NTSTATUS status; + HANDLE handle; + + TRACE( "file_obj %p, file_size %p\n", file_obj, file_size ); + + status = ObOpenObjectByPointer( file_obj, 0, NULL, 0, IoFileObjectType, KernelMode, &handle ); + if (status) return status; + + status = NtQueryInformationFile( handle, &iosb, &info, sizeof(info), FileStandardInformation ); + NtClose( handle ); + if (!status) + { + if (info.Directory) return STATUS_FILE_IS_A_DIRECTORY; + file_size->QuadPart = info.EndOfFile.QuadPart; + } + return status; +} + /*********************************************************************** * FsRtlIsNameInExpression (NTOSKRNL.EXE.@) */ diff --git a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec index f4699c6c65a..17c74b9322e 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.exe.spec +++ b/dlls/ntoskrnl.exe/ntoskrnl.exe.spec @@ -237,7 +237,7 @@ @ stub FsRtlFastUnlockSingle @ stub FsRtlFindInTunnelCache @ stub FsRtlFreeFileLock -@ stub FsRtlGetFileSize +@ stdcall FsRtlGetFileSize(ptr ptr) @ stub FsRtlGetNextFileLock @ stub FsRtlGetNextLargeMcbEntry @ stub FsRtlGetNextMcbEntry diff --git a/include/ddk/ntifs.h b/include/ddk/ntifs.h index 980235abdc9..965715738d7 100644 --- a/include/ddk/ntifs.h +++ b/include/ddk/ntifs.h @@ -203,6 +203,7 @@ typedef struct _REPARSE_GUID_DATA_BUFFER #define COMPRESSION_FORMAT_MASK 0x00ff #define COMPRESSION_ENGINE_MASK 0xff00 +NTSTATUS WINAPI FsRtlGetFileSize(PFILE_OBJECT, PLARGE_INTEGER); BOOLEAN WINAPI FsRtlIsNameInExpression(PUNICODE_STRING, PUNICODE_STRING, BOOLEAN, PWCH); DEVICE_OBJECT * WINAPI IoGetAttachedDevice(DEVICE_OBJECT*); PEPROCESS WINAPI IoGetRequestorProcess(IRP*); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10247
From: Nello De Gregoris <bluechxindv@gmail.com> --- dlls/ntoskrnl.exe/tests/driver.c | 66 ++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index 12fc1b8fc0a..030c6476a52 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -2015,6 +2015,71 @@ static void test_dir_kernel_object(void) ZwClose(dir_handle); } +static void test_fsrtl_get_file_size(void) +{ + static const char data[] = "hello, world!"; + OBJECT_ATTRIBUTES attr = { sizeof(attr) }; + UNICODE_STRING pathU; + IO_STATUS_BLOCK io; + LARGE_INTEGER file_size, offset; + HANDLE file_handle, dir_handle; + FILE_OBJECT *file_obj, *dir_obj; + NTSTATUS status; + + /* test regular file */ + RtlInitUnicodeString(&pathU, L"\\??\\C:\\windows\\winetest_ntoskrnl_fsrtl.tmp"); + InitializeObjectAttributes(&attr, &pathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwCreateFile(&file_handle, DELETE | FILE_WRITE_DATA | SYNCHRONIZE, &attr, &io, NULL, + FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_CREATE, FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); + ok(!status, "ZwCreateFile failed: %#lx\n", status); + if (status) + return; + + offset.QuadPart = 0; + status = ZwWriteFile(file_handle, NULL, NULL, NULL, &io, (void *)data, sizeof(data), &offset, NULL); + ok(!status, "ZwWriteFile failed: %#lx\n", status); + + status = ObReferenceObjectByHandle(file_handle, 0, *pIoFileObjectType, KernelMode, + (void **)&file_obj, NULL); + ok(!status, "ObReferenceObjectByHandle failed: %#lx\n", status); + if (!status) + { + file_size.QuadPart = 0; + status = FsRtlGetFileSize(file_obj, &file_size); + ok(!status, "FsRtlGetFileSize failed: %#lx\n", status); + ok(file_size.QuadPart == sizeof(data), "expected %Iu, got %I64d\n", + sizeof(data), file_size.QuadPart); + ObDereferenceObject(file_obj); + } + + ZwClose(file_handle); + + /* test directory returns STATUS_FILE_IS_A_DIRECTORY */ + RtlInitUnicodeString(&pathU, L"\\??\\C:\\windows"); + InitializeObjectAttributes(&attr, &pathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + status = ZwOpenFile(&dir_handle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &io, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); + ok(!status, "ZwOpenFile failed: %#lx\n", status); + if (status) + return; + + status = ObReferenceObjectByHandle(dir_handle, 0, *pIoFileObjectType, KernelMode, + (void **)&dir_obj, NULL); + ok(!status, "ObReferenceObjectByHandle failed: %#lx\n", status); + if (!status) + { + file_size.QuadPart = 0; + status = FsRtlGetFileSize(dir_obj, &file_size); + ok(status == STATUS_FILE_IS_A_DIRECTORY, + "expected STATUS_FILE_IS_A_DIRECTORY, got %#lx\n", status); + ObDereferenceObject(dir_obj); + } + + ZwClose(dir_handle); +} + static PIO_WORKITEM work_item; static void WINAPI main_test_task(DEVICE_OBJECT *device, void *context) @@ -2558,6 +2623,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st test_IoAttachDeviceToDeviceStack(); test_object_name(); test_dir_kernel_object(); + test_fsrtl_get_file_size(); #if defined(__i386__) || defined(__x86_64__) test_executable_pool(); #endif -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10247
participants (2)
-
Nello De Gregoris -
Nello De Gregoris (@bluechxin)