ntoskrnl.exe/tests: Add some tests for file names.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2020-07-30 18:04:20 -05:00 committed by Alexandre Julliard
parent 218409c2d6
commit f53c2df6db
2 changed files with 226 additions and 8 deletions

View File

@ -37,6 +37,19 @@
#include "utils.h" #include "utils.h"
/* memcmp() isn't exported from ntoskrnl on i386 */
static int kmemcmp( const void *ptr1, const void *ptr2, size_t n )
{
const unsigned char *p1, *p2;
for (p1 = ptr1, p2 = ptr2; n; n--, p1++, p2++)
{
if (*p1 < *p2) return -1;
if (*p1 > *p2) return 1;
}
return 0;
}
static const WCHAR device_name[] = {'\\','D','e','v','i','c','e', static const WCHAR device_name[] = {'\\','D','e','v','i','c','e',
'\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0}; '\\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0};
static const WCHAR upper_name[] = {'\\','D','e','v','i','c','e', static const WCHAR upper_name[] = {'\\','D','e','v','i','c','e',
@ -55,6 +68,13 @@ static PETHREAD create_irp_thread;
NTSTATUS WINAPI ZwQueryInformationProcess(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*); NTSTATUS WINAPI ZwQueryInformationProcess(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*);
struct file_context
{
DWORD id;
ULONG namelen;
WCHAR name[10];
};
static void *get_proc_address(const char *name) static void *get_proc_address(const char *name)
{ {
UNICODE_STRING name_u; UNICODE_STRING name_u;
@ -2175,15 +2195,15 @@ static NTSTATUS get_fscontext(IRP *irp, IO_STACK_LOCATION *stack, ULONG_PTR *inf
{ {
ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength;
char *buffer = irp->AssociatedIrp.SystemBuffer; char *buffer = irp->AssociatedIrp.SystemBuffer;
DWORD *context = stack->FileObject->FsContext; struct file_context *context = stack->FileObject->FsContext;
if (!buffer || !context) if (!buffer)
return STATUS_ACCESS_VIOLATION; return STATUS_ACCESS_VIOLATION;
if (length < sizeof(DWORD)) if (length < sizeof(DWORD))
return STATUS_BUFFER_TOO_SMALL; return STATUS_BUFFER_TOO_SMALL;
*(DWORD*)buffer = *context; *(DWORD*)buffer = context->id;
*info = sizeof(DWORD); *info = sizeof(DWORD);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -2271,13 +2291,21 @@ static NTSTATUS test_completion_ioctl(DEVICE_OBJECT *device, IRP *irp)
static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp) static NTSTATUS WINAPI driver_Create(DEVICE_OBJECT *device, IRP *irp)
{ {
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
DWORD *context = ExAllocatePool(PagedPool, sizeof(*context)); struct file_context *context = ExAllocatePool(PagedPool, sizeof(*context));
if (!context)
{
irp->IoStatus.Status = STATUS_NO_MEMORY;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_NO_MEMORY;
}
context->id = ++create_count;
context->namelen = min(irpsp->FileObject->FileName.Length, sizeof(context->name));
memcpy(context->name, irpsp->FileObject->FileName.Buffer, context->namelen);
irpsp->FileObject->FsContext = context;
last_created_file = irpsp->FileObject; last_created_file = irpsp->FileObject;
++create_count;
if (context)
*context = create_count;
irpsp->FileObject->FsContext = context;
create_caller_thread = KeGetCurrentThread(); create_caller_thread = KeGetCurrentThread();
create_irp_thread = irp->Tail.Overlay.Thread; create_irp_thread = irp->Tail.Overlay.Thread;
@ -2356,6 +2384,81 @@ static NTSTATUS WINAPI driver_FlushBuffers(DEVICE_OBJECT *device, IRP *irp)
return STATUS_PENDING; return STATUS_PENDING;
} }
static BOOL compare_file_name(const struct file_context *context, const WCHAR *expect)
{
return context->namelen == wcslen(expect) * sizeof(WCHAR)
&& !kmemcmp(context->name, expect, context->namelen);
}
static NTSTATUS WINAPI driver_QueryInformation(DEVICE_OBJECT *device, IRP *irp)
{
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
NTSTATUS ret;
switch (stack->Parameters.QueryFile.FileInformationClass)
{
case FileNameInformation:
{
const struct file_context *context = stack->FileObject->FsContext;
FILE_NAME_INFORMATION *info = irp->AssociatedIrp.SystemBuffer;
ULONG len;
if (stack->Parameters.QueryFile.Length < sizeof(*info))
{
ret = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (compare_file_name(context, L"\\notimpl"))
{
ret = STATUS_NOT_IMPLEMENTED;
break;
}
else if (compare_file_name(context, L""))
{
ret = STATUS_INVALID_DEVICE_REQUEST;
break;
}
else if (compare_file_name(context, L"\\badparam"))
{
ret = STATUS_INVALID_PARAMETER;
break;
}
else if (compare_file_name(context, L"\\genfail"))
{
ret = STATUS_UNSUCCESSFUL;
break;
}
else if (compare_file_name(context, L"\\badtype"))
{
ret = STATUS_OBJECT_TYPE_MISMATCH;
break;
}
len = stack->Parameters.QueryFile.Length - FIELD_OFFSET(FILE_NAME_INFORMATION, FileName);
if (len < context->namelen)
ret = STATUS_BUFFER_OVERFLOW;
else
{
len = context->namelen;
ret = STATUS_SUCCESS;
}
irp->IoStatus.Information = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + len;
info->FileNameLength = context->namelen;
memcpy(info->FileName, context->name, len);
break;
}
default:
ret = STATUS_NOT_IMPLEMENTED;
break;
}
irp->IoStatus.Status = ret;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return ret;
}
static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp) static NTSTATUS WINAPI driver_Close(DEVICE_OBJECT *device, IRP *irp)
{ {
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
@ -2400,6 +2503,7 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry)
driver->MajorFunction[IRP_MJ_CREATE] = driver_Create; driver->MajorFunction[IRP_MJ_CREATE] = driver_Create;
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_IoControl; driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_IoControl;
driver->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = driver_FlushBuffers; driver->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = driver_FlushBuffers;
driver->MajorFunction[IRP_MJ_QUERY_INFORMATION] = driver_QueryInformation;
driver->MajorFunction[IRP_MJ_CLOSE] = driver_Close; driver->MajorFunction[IRP_MJ_CLOSE] = driver_Close;
RtlInitUnicodeString(&nameW, IoDriverObjectTypeW); RtlInitUnicodeString(&nameW, IoDriverObjectTypeW);

View File

@ -493,6 +493,119 @@ static void test_return_status(void)
ok(ret_size == 3, "got size %u\n", ret_size); ok(ret_size == 3, "got size %u\n", ret_size);
} }
static BOOL compare_unicode_string(const WCHAR *buffer, ULONG len, const WCHAR *expect)
{
return len == wcslen(expect) * sizeof(WCHAR) && !memcmp(buffer, expect, len);
}
static void test_object_info(void)
{
char buffer[200];
OBJECT_NAME_INFORMATION *name_info = (OBJECT_NAME_INFORMATION *)buffer;
OBJECT_TYPE_INFORMATION *type_info = (OBJECT_TYPE_INFORMATION *)buffer;
FILE_NAME_INFORMATION *file_info = (FILE_NAME_INFORMATION *)buffer;
HANDLE file;
NTSTATUS status;
IO_STATUS_BLOCK io;
ULONG size;
status = NtQueryObject(device, ObjectNameInformation, buffer, sizeof(buffer), NULL);
ok(!status, "got %#x\n", status);
todo_wine ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver"),
"wrong name %s\n", debugstr_w(name_info->Name.Buffer));
status = NtQueryObject(device, ObjectTypeInformation, buffer, sizeof(buffer), NULL);
ok(!status, "got %#x\n", status);
ok(compare_unicode_string(type_info->TypeName.Buffer, type_info->TypeName.Length, L"File"),
"wrong name %s\n", debugstr_wn(type_info->TypeName.Buffer, type_info->TypeName.Length / sizeof(WCHAR)));
status = NtQueryInformationFile(device, &io, buffer, sizeof(buffer), FileNameInformation);
todo_wine ok(status == STATUS_INVALID_DEVICE_REQUEST, "got %#x\n", status);
file = CreateFileA("\\\\.\\WineTestDriver\\subfile", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
todo_wine ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
if (file == INVALID_HANDLE_VALUE) return;
memset(buffer, 0xcc, sizeof(buffer));
status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), &size);
ok(!status, "got %#x\n", status);
ok(size == sizeof(*name_info) + sizeof(L"\\Device\\WineTestDriver\\subfile"), "wrong size %u\n", size);
ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver\\subfile"),
"wrong name %s\n", debugstr_w(name_info->Name.Buffer));
memset(buffer, 0xcc, sizeof(buffer));
status = NtQueryObject(file, ObjectNameInformation, buffer, size - 2, &size);
ok(status == STATUS_BUFFER_OVERFLOW, "got %#x\n", status);
ok(size == sizeof(*name_info) + sizeof(L"\\Device\\WineTestDriver\\subfile"), "wrong size %u\n", size);
ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver\\subfil"),
"wrong name %s\n", debugstr_w(name_info->Name.Buffer));
memset(buffer, 0xcc, sizeof(buffer));
status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(*name_info), &size);
ok(status == STATUS_BUFFER_OVERFLOW, "got %#x\n", status);
ok(size == sizeof(*name_info) + sizeof(L"\\Device\\WineTestDriver\\subfile"), "wrong size %u\n", size);
status = NtQueryObject(file, ObjectTypeInformation, buffer, sizeof(buffer), NULL);
ok(!status, "got %#x\n", status);
ok(compare_unicode_string(type_info->TypeName.Buffer, type_info->TypeName.Length, L"File"),
"wrong name %s\n", debugstr_wn(type_info->TypeName.Buffer, type_info->TypeName.Length / sizeof(WCHAR)));
status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
ok(!status, "got %#x\n", status);
ok(compare_unicode_string(file_info->FileName, file_info->FileNameLength, L"\\subfile"),
"wrong name %s\n", debugstr_wn(file_info->FileName, file_info->FileNameLength / sizeof(WCHAR)));
CloseHandle(file);
file = CreateFileA("\\\\.\\WineTestDriver\\notimpl", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
ok(!status, "got %#x\n", status);
ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver"),
"wrong name %s\n", debugstr_w(name_info->Name.Buffer));
status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
ok(status == STATUS_NOT_IMPLEMENTED, "got %#x\n", status);
CloseHandle(file);
file = CreateFileA("\\\\.\\WineTestDriver\\badparam", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
ok(!status, "got %#x\n", status);
ok(compare_unicode_string(name_info->Name.Buffer, name_info->Name.Length, L"\\Device\\WineTestDriver"),
"wrong name %s\n", debugstr_w(name_info->Name.Buffer));
status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
ok(status == STATUS_INVALID_PARAMETER, "got %#x\n", status);
CloseHandle(file);
file = CreateFileA("\\\\.\\WineTestDriver\\genfail", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
ok(status == STATUS_UNSUCCESSFUL, "got %#x\n", status);
status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
ok(status == STATUS_UNSUCCESSFUL, "got %#x\n", status);
CloseHandle(file);
file = CreateFileA("\\\\.\\WineTestDriver\\badtype", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
ok(file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError());
status = NtQueryObject(file, ObjectNameInformation, buffer, sizeof(buffer), NULL);
ok(status == STATUS_OBJECT_TYPE_MISMATCH, "got %#x\n", status);
status = NtQueryInformationFile(file, &io, buffer, sizeof(buffer), FileNameInformation);
ok(status == STATUS_OBJECT_TYPE_MISMATCH, "got %#x\n", status);
CloseHandle(file);
}
static void test_driver3(void) static void test_driver3(void)
{ {
char filename[MAX_PATH]; char filename[MAX_PATH];
@ -644,6 +757,7 @@ START_TEST(ntoskrnl)
test_load_driver(service2); test_load_driver(service2);
test_file_handles(); test_file_handles();
test_return_status(); test_return_status();
test_object_info();
/* We need a separate ioctl to call IoDetachDevice(); calling it in the /* We need a separate ioctl to call IoDetachDevice(); calling it in the
* driver unload routine causes a live-lock. */ * driver unload routine causes a live-lock. */