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:
parent
218409c2d6
commit
f53c2df6db
|
@ -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);
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
Loading…
Reference in New Issue