https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3b430eefddf79bd524f04…
commit 3b430eefddf79bd524f040cb79ad8b63a591b422
Author:     Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Sun Dec 29 13:49:18 2019 +0100
Commit:     Thomas Faber <thomas.faber(a)reactos.org>
CommitDate: Tue Dec 31 15:18:59 2019 +0100
    [NTDLL_APITEST] Add a test for NtUnloadDriver.
---
 modules/rostests/apitests/ntdll/CMakeLists.txt   |   1 +
 modules/rostests/apitests/ntdll/NtUnloadDriver.c | 108 +++++++++++++++++++++++
 modules/rostests/apitests/ntdll/testlist.c       |   2 +
 3 files changed, 111 insertions(+)
diff --git a/modules/rostests/apitests/ntdll/CMakeLists.txt
b/modules/rostests/apitests/ntdll/CMakeLists.txt
index cf0bbb4e284..0cce35587ed 100644
--- a/modules/rostests/apitests/ntdll/CMakeLists.txt
+++ b/modules/rostests/apitests/ntdll/CMakeLists.txt
@@ -35,6 +35,7 @@ list(APPEND SOURCE
     NtSetInformationFile.c
     NtSetValueKey.c
     NtSetVolumeInformationFile.c
+    NtUnloadDriver.c
     NtWriteFile.c
     RtlAllocateHeap.c
     RtlBitmap.c
diff --git a/modules/rostests/apitests/ntdll/NtUnloadDriver.c
b/modules/rostests/apitests/ntdll/NtUnloadDriver.c
new file mode 100644
index 00000000000..5b827053f4a
--- /dev/null
+++ b/modules/rostests/apitests/ntdll/NtUnloadDriver.c
@@ -0,0 +1,108 @@
+/*
+ * PROJECT:     ReactOS API Tests
+ * LICENSE:     LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE:     Test for NtUnloadDriver
+ * COPYRIGHT:   Copyright 2019 Thomas Faber (thomas.faber(a)reactos.org)
+ */
+
+#include "precomp.h"
+
+START_TEST(NtUnloadDriver)
+{
+    NTSTATUS Status;
+    BOOLEAN OldPrivilege, OldPrivilege2;
+    UNICODE_STRING ServiceName;
+    PWCHAR Buffer = NULL;
+
+    Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, FALSE, FALSE,
&OldPrivilege);
+    if (!NT_SUCCESS(Status))
+    {
+        skip("Failed to drop driver load privilege\n");
+        return;
+    }
+
+    Status = NtUnloadDriver(NULL);
+    ok_hex(Status, STATUS_PRIVILEGE_NOT_HELD);
+
+    Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE,
&OldPrivilege2);
+    if (!NT_SUCCESS(Status))
+    {
+        skip("Failed to acquire driver load privilege\n");
+        goto Exit;
+    }
+
+    Status = NtUnloadDriver(NULL);
+    ok_hex(Status, STATUS_ACCESS_VIOLATION);
+
+    RtlInitEmptyUnicodeString(&ServiceName, NULL, 0);
+    Status = NtUnloadDriver(&ServiceName);
+    ok_hex(Status, STATUS_INVALID_PARAMETER);
+
+    Buffer = AllocateGuarded(0x10000);
+    if (!Buffer)
+    {
+        skip("Failed to allocate memory\n");
+        goto Exit;
+    }
+
+    RtlFillMemoryUlong(Buffer, 0x10000, 'A' << 16 | 'A');
+
+    ServiceName.Buffer = Buffer;
+    ServiceName.Length = 0xFFFF;
+    ServiceName.MaximumLength = MAXUSHORT;
+    Status = NtUnloadDriver(&ServiceName);
+    ok_hex(Status, STATUS_OBJECT_NAME_INVALID);
+
+    ServiceName.Buffer = Buffer;
+    ServiceName.Length = 0xFFFE;
+    ServiceName.MaximumLength = MAXUSHORT;
+    Status = NtUnloadDriver(&ServiceName);
+    ok_hex(Status, STATUS_OBJECT_NAME_INVALID);
+
+    ServiceName.Buffer = Buffer;
+    ServiceName.Length = 0xFFFD;
+    ServiceName.MaximumLength = MAXUSHORT;
+    Status = NtUnloadDriver(&ServiceName);
+    ok_hex(Status, STATUS_OBJECT_NAME_INVALID);
+
+    ServiceName.Buffer = Buffer;
+    ServiceName.Length = 0xFFFC;
+    ServiceName.MaximumLength = MAXUSHORT;
+    Status = NtUnloadDriver(&ServiceName);
+    ok_hex(Status, STATUS_OBJECT_PATH_SYNTAX_BAD);
+
+    ServiceName.Buffer = Buffer;
+    ServiceName.Length = 0x1000;
+    ServiceName.MaximumLength = MAXUSHORT;
+    Status = NtUnloadDriver(&ServiceName);
+    ok_hex(Status, STATUS_OBJECT_PATH_SYNTAX_BAD);
+
+    ServiceName.Buffer = Buffer;
+    ServiceName.Length = 1;
+    ServiceName.MaximumLength = MAXUSHORT;
+    Status = NtUnloadDriver(&ServiceName);
+    ok_hex(Status, STATUS_OBJECT_NAME_INVALID);
+
+    Buffer[0xFFFC / sizeof(WCHAR)] = L'\\';
+    ServiceName.Buffer = Buffer;
+    ServiceName.Length = 0xFFFC;
+    ServiceName.MaximumLength = MAXUSHORT;
+    Status = NtUnloadDriver(&ServiceName);
+    ok_hex(Status, STATUS_OBJECT_PATH_SYNTAX_BAD);
+
+    Buffer[0xFFFC / sizeof(WCHAR) - 1] = L'\\';
+    ServiceName.Buffer = Buffer;
+    ServiceName.Length = 0xFFFC;
+    ServiceName.MaximumLength = MAXUSHORT;
+    Status = NtUnloadDriver(&ServiceName);
+    ok_hex(Status, STATUS_OBJECT_PATH_SYNTAX_BAD);
+
+Exit:
+    if (Buffer != NULL)
+    {
+        FreeGuarded(Buffer);
+    }
+
+    Status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, OldPrivilege, FALSE,
&OldPrivilege2);
+    ok_hex(Status, STATUS_SUCCESS);
+}
diff --git a/modules/rostests/apitests/ntdll/testlist.c
b/modules/rostests/apitests/ntdll/testlist.c
index cfcf8cefe04..9359f36808b 100644
--- a/modules/rostests/apitests/ntdll/testlist.c
+++ b/modules/rostests/apitests/ntdll/testlist.c
@@ -34,6 +34,7 @@ extern void func_NtSetInformationFile(void);
 extern void func_NtSetValueKey(void);
 extern void func_NtSetVolumeInformationFile(void);
 extern void func_NtSystemInformation(void);
+extern void func_NtUnloadDriver(void);
 extern void func_NtWriteFile(void);
 extern void func_RtlAllocateHeap(void);
 extern void func_RtlBitmap(void);
@@ -99,6 +100,7 @@ const struct test winetest_testlist[] =
     { "NtSetValueKey",                  func_NtSetValueKey},
     { "NtSetVolumeInformationFile",     func_NtSetVolumeInformationFile },
     { "NtSystemInformation",            func_NtSystemInformation },
+    { "NtUnloadDriver",                 func_NtUnloadDriver },
     { "NtWriteFile",                    func_NtWriteFile },
     { "RtlAllocateHeap",                func_RtlAllocateHeap },
     { "RtlBitmapApi",                   func_RtlBitmap },