[KMTESTS:KERNEL32]
authorThomas Faber <thomas.faber@reactos.org>
Thu, 29 Jun 2017 16:16:20 +0000 (16:16 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Thu, 29 Jun 2017 16:16:20 +0000 (16:16 +0000)
- Add a test for SetFileAttributes/GetFileAttributes
- Add KmtSendUlongToDriver helper and fix some doc comments
CORE-13495

svn path=/trunk/; revision=75236

rostests/kmtests/CMakeLists.txt
rostests/kmtests/include/kmt_test.h
rostests/kmtests/kernel32/FileAttributes_user.c [new file with mode: 0644]
rostests/kmtests/kernel32/kernel32_drv.c
rostests/kmtests/kernel32/kernel32_test.h
rostests/kmtests/kmtest/support.c
rostests/kmtests/kmtest/testlist.c

index 292f131..dfc6c98 100644 (file)
@@ -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
index 5560891..b2de5bc 100644 (file)
@@ -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 (file)
index 0000000..a644b99
--- /dev/null
@@ -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 <thomas.faber@reactos.org>
+ */
+
+#include <kmt_test.h>
+
+#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();
+}
index a4fdc80..6432fdf 100644 (file)
 
 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"<not set>");
 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;
+}
index 1923285..2e0a295 100644 (file)
@@ -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_ */
index 05f0bc3..1ac2c3a 100644 (file)
@@ -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
+}
index f888184..562691d 100644 (file)
@@ -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 },