diff --git a/rostests/kmtests/CMakeLists.txt b/rostests/kmtests/CMakeLists.txt index 292f13181a0..dfc6c98d0a1 100644 --- a/rostests/kmtests/CMakeLists.txt +++ b/rostests/kmtests/CMakeLists.txt @@ -125,6 +125,7 @@ list(APPEND KMTEST_SOURCE example/Example_user.c hidparse/HidP_user.c + kernel32/FileAttributes_user.c kernel32/FindFile_user.c ntos_cc/CcCopyRead_user.c ntos_io/IoCreateFile_user.c diff --git a/rostests/kmtests/include/kmt_test.h b/rostests/kmtests/include/kmt_test.h index 5560891ad9f..b2de5bc19ac 100644 --- a/rostests/kmtests/include/kmt_test.h +++ b/rostests/kmtests/include/kmt_test.h @@ -148,6 +148,7 @@ VOID KmtCloseDriver(VOID); DWORD KmtSendToDriver(IN DWORD ControlCode); DWORD KmtSendStringToDriver(IN DWORD ControlCode, IN PCSTR String); DWORD KmtSendWStringToDriver(IN DWORD ControlCode, IN PCWSTR String); +DWORD KmtSendUlongToDriver(IN DWORD ControlCode, IN DWORD Value); DWORD KmtSendBufferToDriver(IN DWORD ControlCode, IN OUT PVOID Buffer OPTIONAL, IN DWORD InLength, IN OUT PDWORD OutLength); #else /* if !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */ #error either KMT_KERNEL_MODE or KMT_USER_MODE must be defined diff --git a/rostests/kmtests/kernel32/FileAttributes_user.c b/rostests/kmtests/kernel32/FileAttributes_user.c new file mode 100644 index 00000000000..a644b999bc2 --- /dev/null +++ b/rostests/kmtests/kernel32/FileAttributes_user.c @@ -0,0 +1,58 @@ +/* + * PROJECT: ReactOS kernel-mode tests + * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory + * PURPOSE: Test for GetFileAttributes/SetFileAttributes + * PROGRAMMER: Thomas Faber + */ + +#include + +#include "kernel32_test.h" + +START_TEST(FileAttributes) +{ + PCWSTR FileName = L"\\\\.\\Global\\GLOBALROOT\\Device\\Kmtest-kernel32\\Somefile"; + BOOL Ret; + DWORD Attributes; + + KmtLoadDriver(L"kernel32", FALSE); + KmtOpenDriver(); + + /* Set read-only attribute */ + KmtSendUlongToDriver(IOCTL_EXPECT_SET_ATTRIBUTES, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_NORMAL); + Ret = SetFileAttributesW(FileName, FILE_ATTRIBUTE_READONLY); + ok(Ret == TRUE, "SetFileAttributesW returned %d, error %lu\n", Ret, GetLastError()); + + /* Set normal attribute */ + KmtSendUlongToDriver(IOCTL_EXPECT_SET_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL); + Ret = SetFileAttributesW(FileName, FILE_ATTRIBUTE_NORMAL); + ok(Ret == TRUE, "SetFileAttributesW returned %d, error %lu\n", Ret, GetLastError()); + + /* Set 0 attribute (driver should receive normal) */ + KmtSendUlongToDriver(IOCTL_EXPECT_SET_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL); + Ret = SetFileAttributesW(FileName, 0); + ok(Ret == TRUE, "SetFileAttributesW returned %d, error %lu\n", Ret, GetLastError()); + + /* Query read-only attribute */ + KmtSendUlongToDriver(IOCTL_RETURN_QUERY_ATTRIBUTES, FILE_ATTRIBUTE_READONLY); + Attributes = GetFileAttributesW(FileName); + ok_eq_hex(Attributes, FILE_ATTRIBUTE_READONLY); + + /* Query read-only + normal attribute */ + KmtSendUlongToDriver(IOCTL_RETURN_QUERY_ATTRIBUTES, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_NORMAL); + Attributes = GetFileAttributesW(FileName); + ok_eq_hex(Attributes, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_NORMAL); + + /* Query normal attribute */ + KmtSendUlongToDriver(IOCTL_RETURN_QUERY_ATTRIBUTES, FILE_ATTRIBUTE_NORMAL); + Attributes = GetFileAttributesW(FileName); + ok_eq_hex(Attributes, FILE_ATTRIBUTE_NORMAL); + + /* Query 0 attribute */ + KmtSendUlongToDriver(IOCTL_RETURN_QUERY_ATTRIBUTES, 0); + Attributes = GetFileAttributesW(FileName); + ok_eq_hex(Attributes, 0); + + KmtCloseDriver(); + KmtUnloadDriver(); +} diff --git a/rostests/kmtests/kernel32/kernel32_drv.c b/rostests/kmtests/kernel32/kernel32_drv.c index a4fdc80db35..6432fdf6e70 100644 --- a/rostests/kmtests/kernel32/kernel32_drv.c +++ b/rostests/kmtests/kernel32/kernel32_drv.c @@ -14,9 +14,13 @@ static KMT_MESSAGE_HANDLER TestMessageHandler; static KMT_IRP_HANDLER TestDirectoryControl; +static KMT_IRP_HANDLER TestQueryInformation; +static KMT_IRP_HANDLER TestSetInformation; static UNICODE_STRING ExpectedExpression = RTL_CONSTANT_STRING(L""); static WCHAR ExpressionBuffer[MAX_PATH]; +static ULONG ExpectedSetAttributes = -1; +static ULONG ReturnQueryAttributes = -1; NTSTATUS TestEntry( @@ -35,6 +39,8 @@ TestEntry( *Flags = TESTENTRY_NO_EXCLUSIVE_DEVICE; KmtRegisterIrpHandler(IRP_MJ_DIRECTORY_CONTROL, NULL, TestDirectoryControl); + KmtRegisterIrpHandler(IRP_MJ_QUERY_INFORMATION, NULL, TestQueryInformation); + KmtRegisterIrpHandler(IRP_MJ_SET_INFORMATION, NULL, TestSetInformation); KmtRegisterMessageHandler(0, NULL, TestMessageHandler); return Status; @@ -79,6 +85,26 @@ TestMessageHandler( break; } + case IOCTL_RETURN_QUERY_ATTRIBUTES: + { + DPRINT("IOCTL_RETURN_QUERY_ATTRIBUTES, InLength = %lu\n", InLength); + if (InLength != sizeof(ULONG)) + return STATUS_INVALID_PARAMETER; + + ReturnQueryAttributes = *(PULONG)Buffer; + DPRINT("IOCTL_RETURN_QUERY_ATTRIBUTES: %lu\n", ReturnQueryAttributes); + break; + } + case IOCTL_EXPECT_SET_ATTRIBUTES: + { + DPRINT("IOCTL_EXPECT_SET_ATTRIBUTES, InLength = %lu\n", InLength); + if (InLength != sizeof(ULONG)) + return STATUS_INVALID_PARAMETER; + + ExpectedSetAttributes = *(PULONG)Buffer; + DPRINT("IOCTL_EXPECT_SET_ATTRIBUTES: %lu\n", ExpectedSetAttributes); + break; + } default: return STATUS_NOT_SUPPORTED; } @@ -121,3 +147,79 @@ TestDirectoryControl( return Status; } + +static +NTSTATUS +TestQueryInformation( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IoStackLocation) +{ + NTSTATUS Status = STATUS_NOT_SUPPORTED; + PFILE_BASIC_INFORMATION BasicInfo; + + PAGED_CODE(); + + DPRINT("IRP %x/%x\n", IoStackLocation->MajorFunction, IoStackLocation->MinorFunction); + ASSERT(IoStackLocation->MajorFunction == IRP_MJ_QUERY_INFORMATION); + + Irp->IoStatus.Information = 0; + + ok_eq_ulong(IoStackLocation->Parameters.QueryFile.FileInformationClass, FileBasicInformation); + if (IoStackLocation->Parameters.QueryFile.FileInformationClass == FileBasicInformation) + { + ok(ReturnQueryAttributes != (ULONG)-1, "Unexpected QUERY_INFORMATION call\n"); + BasicInfo = Irp->AssociatedIrp.SystemBuffer; + BasicInfo->CreationTime.QuadPart = 126011664000000000; + BasicInfo->LastAccessTime.QuadPart = 130899112800000000; + BasicInfo->LastWriteTime.QuadPart = 130899112800000000; + BasicInfo->ChangeTime.QuadPart = 130899112800000000; + BasicInfo->FileAttributes = ReturnQueryAttributes; + ReturnQueryAttributes = -1; + Status = STATUS_SUCCESS; + Irp->IoStatus.Information = sizeof(*BasicInfo); + } + + Irp->IoStatus.Status = Status; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +} + +static +NTSTATUS +TestSetInformation( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IoStackLocation) +{ + NTSTATUS Status = STATUS_NOT_SUPPORTED; + PFILE_BASIC_INFORMATION BasicInfo; + + PAGED_CODE(); + + DPRINT("IRP %x/%x\n", IoStackLocation->MajorFunction, IoStackLocation->MinorFunction); + ASSERT(IoStackLocation->MajorFunction == IRP_MJ_SET_INFORMATION); + + ok_eq_ulong(IoStackLocation->Parameters.SetFile.FileInformationClass, FileBasicInformation); + if (IoStackLocation->Parameters.SetFile.FileInformationClass == FileBasicInformation) + { + ok(ExpectedSetAttributes != (ULONG)-1, "Unexpected SET_INFORMATION call\n"); + BasicInfo = Irp->AssociatedIrp.SystemBuffer; + ok_eq_longlong(BasicInfo->CreationTime.QuadPart, 0LL); + ok_eq_longlong(BasicInfo->LastAccessTime.QuadPart, 0LL); + ok_eq_longlong(BasicInfo->LastWriteTime.QuadPart, 0LL); + ok_eq_longlong(BasicInfo->ChangeTime.QuadPart, 0LL); + ok_eq_ulong(BasicInfo->FileAttributes, ExpectedSetAttributes); + ExpectedSetAttributes = -1; + Status = STATUS_SUCCESS; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +} diff --git a/rostests/kmtests/kernel32/kernel32_test.h b/rostests/kmtests/kernel32/kernel32_test.h index 1923285f4c9..2e0a2957c37 100644 --- a/rostests/kmtests/kernel32/kernel32_test.h +++ b/rostests/kmtests/kernel32/kernel32_test.h @@ -9,5 +9,7 @@ #define _KMTEST_FINDFILE_H_ #define IOCTL_EXPECT_EXPRESSION 1 +#define IOCTL_RETURN_QUERY_ATTRIBUTES 2 +#define IOCTL_EXPECT_SET_ATTRIBUTES 3 #endif /* !defined _KMTEST_FINDFILE_H_ */ diff --git a/rostests/kmtests/kmtest/support.c b/rostests/kmtests/kmtest/support.c index 05f0bc3a895..1ac2c3ac469 100644 --- a/rostests/kmtests/kmtest/support.c +++ b/rostests/kmtests/kmtest/support.c @@ -213,7 +213,7 @@ KmtCloseDriver(VOID) /** * @name KmtSendToDriver * - * Unload special-purpose driver (stop the service) + * Send an I/O control message with no arguments to the driver opened with KmtOpenDriver * * @param ControlCode * @@ -236,7 +236,7 @@ KmtSendToDriver( /** * @name KmtSendStringToDriver * - * Unload special-purpose driver (stop the service) + * Send an I/O control message with a string argument to the driver opened with KmtOpenDriver * * @param ControlCode * @param String @@ -259,9 +259,9 @@ KmtSendStringToDriver( } /** - * @name KmtSendStringToDriver + * @name KmtSendWStringToDriver * - * Unload special-purpose driver (stop the service) + * Send an I/O control message with a wide string argument to the driver opened with KmtOpenDriver * * @param ControlCode * @param String @@ -283,9 +283,36 @@ KmtSendWStringToDriver( return ERROR_SUCCESS; } +/** + * @name KmtSendUlongToDriver + * + * Send an I/O control message with an integer argument to the driver opened with KmtOpenDriver + * + * @param ControlCode + * @param Value + * + * @return Win32 error code as returned by DeviceIoControl + */ +DWORD +KmtSendUlongToDriver( + IN DWORD ControlCode, + IN DWORD Value) +{ + DWORD BytesRead; + + assert(ControlCode < 0x400); + + if (!DeviceIoControl(TestDeviceHandle, KMT_MAKE_CODE(ControlCode), &Value, sizeof(Value), NULL, 0, &BytesRead, NULL)) + return GetLastError(); + + return ERROR_SUCCESS; +} + /** * @name KmtSendBufferToDriver * + * Send an I/O control message with the specified arguments to the driver opened with KmtOpenDriver + * * @param ControlCode * @param Buffer * @param InLength @@ -308,4 +335,4 @@ KmtSendBufferToDriver( return GetLastError(); return ERROR_SUCCESS; -} \ No newline at end of file +} diff --git a/rostests/kmtests/kmtest/testlist.c b/rostests/kmtests/kmtest/testlist.c index f8881845f92..562691d6f06 100644 --- a/rostests/kmtests/kmtest/testlist.c +++ b/rostests/kmtests/kmtest/testlist.c @@ -9,6 +9,7 @@ KMT_TESTFUNC Test_CcCopyRead; KMT_TESTFUNC Test_Example; +KMT_TESTFUNC Test_FileAttributes; KMT_TESTFUNC Test_FindFile; KMT_TESTFUNC Test_HidPDescription; KMT_TESTFUNC Test_IoCreateFile; @@ -34,6 +35,7 @@ const KMT_TEST TestList[] = { { "CcCopyRead", Test_CcCopyRead }, { "-Example", Test_Example }, + { "FileAttributes", Test_FileAttributes }, { "FindFile", Test_FindFile }, { "HidPDescription", Test_HidPDescription }, { "IoCreateFile", Test_IoCreateFile },