https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b10dd06aa5254bf7b7caa…
commit b10dd06aa5254bf7b7caa8c3a793ee28182db6a2
Author: Ged Murphy <gedmurphy(a)gmail.com>
AuthorDate: Wed Oct 25 10:39:55 2017 +0100
[KMTEST] Initial usermode support for testing FS mini-filters (#81)
* [KMTEST] Initial usermode support for testing FS mini-filters
- Add base routines to wrap the win32 'Filter' APis
- Add support routines to be used when testing FS filter drivers
- Move KmtCreateService to a private routine so it can be shared with
KmtFltCreateService
- Completely untested at the mo, so likely contains bugs at this point
---
modules/rostests/kmtests/CMakeLists.txt | 6 +-
modules/rostests/kmtests/include/kmt_platform.h | 1 +
modules/rostests/kmtests/include/kmt_public.h | 5 +
modules/rostests/kmtests/include/kmt_test.h | 10 +
modules/rostests/kmtests/kmtest/filter.c | 428 ++++++++++++++++++++++++
modules/rostests/kmtests/kmtest/fltsupport.c | 301 +++++++++++++++++
modules/rostests/kmtests/kmtest/kmtest.h | 71 ++++
modules/rostests/kmtests/kmtest/service.c | 91 +++--
8 files changed, 882 insertions(+), 31 deletions(-)
diff --git a/modules/rostests/kmtests/CMakeLists.txt
b/modules/rostests/kmtests/CMakeLists.txt
index d51ef000c7..64b088d221 100644
--- a/modules/rostests/kmtests/CMakeLists.txt
+++ b/modules/rostests/kmtests/CMakeLists.txt
@@ -119,6 +119,8 @@ add_target_include_directories(kmtest_printf
${REACTOS_SOURCE_DIR}/sdk/lib/crt/i
#
list(APPEND KMTEST_SOURCE
+ kmtest/filter.c
+ kmtest/fltsupport.c
kmtest/kmtest.c
kmtest/service.c
kmtest/support.c
@@ -143,8 +145,8 @@ list(APPEND KMTEST_SOURCE
add_executable(kmtest ${KMTEST_SOURCE})
set_module_type(kmtest win32cui)
target_link_libraries(kmtest ${PSEH_LIB})
-add_importlibs(kmtest advapi32 ws2_32 msvcrt kernel32 ntdll)
-add_target_compile_definitions(kmtest KMT_USER_MODE)
+add_importlibs(kmtest fltlib advapi32 ws2_32 msvcrt kernel32 ntdll)
+add_target_compile_definitions(kmtest KMT_USER_MODE NTDDI_VERSION=NTDDI_WS03SP1)
#add_pch(kmtest include/kmt_test.h)
set_target_properties(kmtest PROPERTIES OUTPUT_NAME "kmtest_")
#add_rostests_file(TARGET kmtest)
diff --git a/modules/rostests/kmtests/include/kmt_platform.h
b/modules/rostests/kmtests/include/kmt_platform.h
index 9e732c397a..636f099cf6 100644
--- a/modules/rostests/kmtests/include/kmt_platform.h
+++ b/modules/rostests/kmtests/include/kmt_platform.h
@@ -42,6 +42,7 @@
#include <ndk/rtlfuncs.h>
#include <ndk/mmfuncs.h>
#include <strsafe.h>
+#include <fltuser.h>
#ifdef KMT_EMULATE_KERNEL
#define ok_irql(i)
diff --git a/modules/rostests/kmtests/include/kmt_public.h
b/modules/rostests/kmtests/include/kmt_public.h
index 963ff3b859..00442f4d3e 100644
--- a/modules/rostests/kmtests/include/kmt_public.h
+++ b/modules/rostests/kmtests/include/kmt_public.h
@@ -23,6 +23,11 @@
#define IOCTL_KMTEST_USERMODE_AWAIT_REQ \
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_READ_DATA)
+
+#define KMTFLT_GET_TESTS 0x800
+#define KMTFLT_RUN_TEST 0x801
+
+
#define KMTEST_DEVICE_NAME L"Kmtest"
#define KMTEST_DEVICE_DRIVER_PATH L"\\Device\\" KMTEST_DEVICE_NAME
#define KMTEST_DEVICE_PATH L"\\\\.\\Global\\GLOBALROOT"
KMTEST_DEVICE_DRIVER_PATH
diff --git a/modules/rostests/kmtests/include/kmt_test.h
b/modules/rostests/kmtests/include/kmt_test.h
index 5941676140..8fcc93a419 100644
--- a/modules/rostests/kmtests/include/kmt_test.h
+++ b/modules/rostests/kmtests/include/kmt_test.h
@@ -173,6 +173,16 @@ 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);
+
+DWORD KmtFltLoadDriver(_In_z_ PCWSTR ServiceName, _In_ BOOLEAN RestartIfRunning, _In_
BOOLEAN ConnectComms, _Out_ HANDLE *hPort);
+DWORD KmtFltUnloadDriver(_In_ HANDLE *hPort, _In_ BOOLEAN DisonnectComms);
+DWORD KmtFltRunKernelTest(_In_ HANDLE hPort, _In_z_ PCSTR TestName);
+DWORD KmtFltSendToDriver(_In_ HANDLE hPort, _In_ DWORD Message);
+DWORD KmtFltSendStringToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ PCSTR
String);
+DWORD KmtFltSendWStringToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ PCWSTR
String);
+DWORD KmtFltSendUlongToDriver(_In_ HANDLE hPort, _In_ DWORD Message, _In_ DWORD Value);
+DWORD KmtFltSendBufferToDriver(_In_ HANDLE hPort, _In_ DWORD Message,
_In_reads_bytes_(BufferSize) LPVOID Buffer, _In_ DWORD BufferSize,
_Out_writes_bytes_to_opt_(dwOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer, _In_
DWORD dwOutBufferSize, _Out_opt_ LPDWORD lpBytesReturned);
+
#else /* if !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */
#error either KMT_KERNEL_MODE or KMT_USER_MODE must be defined
#endif /* !defined KMT_KERNEL_MODE && !defined KMT_USER_MODE */
diff --git a/modules/rostests/kmtests/kmtest/filter.c
b/modules/rostests/kmtests/kmtest/filter.c
new file mode 100644
index 0000000000..cb5957477c
--- /dev/null
+++ b/modules/rostests/kmtests/kmtest/filter.c
@@ -0,0 +1,428 @@
+/*
+ * PROJECT: ReactOS kernel-mode tests
+ * LICENSE: GPLv2+ - See COPYING in the top level directory
+ * PURPOSE: File system filter implementation of the original service.c file
+ * PROGRAMMER: Thomas Faber <thomas.faber(a)reactos.org>
+ * Ged Murphy <gedmurphy(a)reactos.org>
+ */
+
+//#include <fltuser.h>
+#include <kmt_test.h>
+#include "kmtest.h"
+
+#include <assert.h>
+
+#define SERVICE_ACCESS (SERVICE_START | SERVICE_STOP | DELETE)
+
+/*
+ * We need to call the internal function in the service.c file
+ */
+DWORD
+KmtpCreateService(
+ IN PCWSTR ServiceName,
+ IN PCWSTR ServicePath,
+ IN PCWSTR DisplayName OPTIONAL,
+ IN DWORD ServiceType,
+ OUT SC_HANDLE *ServiceHandle);
+
+static SC_HANDLE ScmHandle;
+
+
+/**
+ * @name KmtFltCreateService
+ *
+ * Create the specified driver service and return a handle to it
+ *
+ * @param ServiceName
+ * Name of the service to create
+ * @param ServicePath
+ * File name of the driver, relative to the current directory
+ * @param DisplayName
+ * Service display name
+ * @param ServiceHandle
+ * Pointer to a variable to receive the handle to the service
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltCreateService(
+ _In_z_ PCWSTR ServiceName,
+ _In_z_ PCWSTR ServicePath,
+ _In_z_ PCWSTR DisplayName OPTIONAL,
+ _Out_ SC_HANDLE *ServiceHandle)
+{
+ return KmtpCreateService(ServiceName,
+ ServicePath,
+ DisplayName,
+ SERVICE_FILE_SYSTEM_DRIVER,
+ ServiceHandle);
+}
+
+/**
+ * @name KmtFltLoad
+ *
+ * Start the specified filter driver by name
+ *
+ * @param ServiceName
+ * The name of the filter to start
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltLoad(
+ _In_z_ PCWSTR ServiceName)
+{
+ HRESULT hResult;
+ DWORD Error = ERROR_SUCCESS;
+
+ assert(ServiceName);
+
+ hResult = FilterLoad(ServiceName);
+ Error = SCODE_CODE(hResult);
+
+ return Error;
+}
+
+/**
+ * @name KmtFltCreateAndStartService
+ *
+ * Create and load the specified filter driver and return a handle to it
+ *
+ * @param ServiceName
+ * Name of the service to create
+ * @param ServicePath
+ * File name of the driver, relative to the current directory
+ * @param DisplayName
+ * Service display name
+ * @param ServiceHandle
+ * Pointer to a variable to receive the handle to the service
+ * @param RestartIfRunning
+ * TRUE to stop and restart the service if it is already running
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltCreateAndStartService(
+ _In_z_ PCWSTR ServiceName,
+ _In_z_ PCWSTR ServicePath,
+ _In_z_ PCWSTR DisplayName OPTIONAL,
+ _Out_ SC_HANDLE *ServiceHandle,
+ _In_ BOOLEAN RestartIfRunning)
+{
+ DWORD Error = ERROR_SUCCESS;
+
+ assert(ServiceHandle);
+
+ Error = KmtFltCreateService(ServiceName, ServicePath, DisplayName, ServiceHandle);
+
+ if (Error == ERROR_SERVICE_EXISTS)
+ *ServiceHandle = OpenService(ScmHandle, ServiceName, SERVICE_ACCESS);
+
+ if (Error && Error != ERROR_SERVICE_EXISTS)
+ goto cleanup;
+
+ Error = KmtFltLoad(ServiceName);
+
+ if (Error != ERROR_SERVICE_ALREADY_RUNNING)
+ goto cleanup;
+
+ Error = ERROR_SUCCESS;
+
+ if (!RestartIfRunning)
+ goto cleanup;
+
+ Error = KmtFltUnload(ServiceName);
+ if (Error)
+ goto cleanup;
+
+ Error = KmtFltLoad(ServiceName);
+ if (Error)
+ goto cleanup;
+
+cleanup:
+ assert(Error);
+ return Error;
+}
+
+
+/**
+ * @name KmtFltConnect
+ *
+ * Create a comms connection to the specified filter
+ *
+ * @param ServiceName
+ * Name of the filter to connect to
+ * @param hPort
+ * Handle to the filter's comms port
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltConnect(
+ _In_z_ PCWSTR ServiceName,
+ _Out_ HANDLE *hPort)
+{
+ HRESULT hResult;
+ DWORD Error = ERROR_SUCCESS;
+
+ assert(ServiceName);
+ assert(hPort);
+
+ hResult = FilterConnectCommunicationPort(ServiceName,
+ 0,
+ NULL,
+ 0,
+ NULL,
+ hPort);
+ Error = SCODE_CODE(hResult);
+
+ return Error;
+}
+
+/**
+ * @name KmtFltDisconnect
+ *
+ * Disconenct from the comms port
+ *
+ * @param hPort
+ * Handle to the filter's comms port
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltDisconnect(
+ _Out_ HANDLE *hPort)
+{
+ DWORD Error = ERROR_SUCCESS;
+
+ assert(hPort);
+
+ if (!CloseHandle(hPort))
+ {
+ Error = GetLastError();
+ }
+
+ return Error;
+}
+
+/**
+ * @name KmtFltSendMessage
+ *
+ * Sneds a message to a filter driver
+ *
+ * @param hPort
+ * Handle to the filter's comms port
+ * @InBuffer
+ * Pointer to a buffer to send to the filter
+ * @InBufferSize
+ * Size of the buffer pointed to by InBuffer
+ * @OutBuffer
+ * Pointer to a buffer to receive reply data from the filter
+ * @OutBufferSize
+ * Size of the buffer pointed to by OutBuffer
+ * @BytesReturned
+ * Number of bytes written in the reply buffer
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltSendMessage(
+ _In_ HANDLE hPort,
+ _In_reads_bytes_(dwInBufferSize) LPVOID InBuffer,
+ _In_ DWORD InBufferSize,
+ _Out_writes_bytes_to_opt_(dutBufferSize, *BytesReturned) LPVOID OutBuffer,
+ _In_ DWORD OutBufferSize,
+ _Out_opt_ LPDWORD BytesReturned)
+{
+ DWORD BytesRet;
+ HRESULT hResult;
+ DWORD Error;
+
+ assert(hPort);
+ assert(InBuffer);
+ assert(InBufferSize);
+
+ if (BytesReturned) *BytesReturned = 0;
+
+ hResult = FilterSendMessage(hPort,
+ InBuffer,
+ InBufferSize,
+ OutBuffer,
+ OutBufferSize,
+ &BytesRet);
+
+ Error = SCODE_CODE(hResult);
+ if (Error == ERROR_SUCCESS)
+ {
+ if (BytesRet)
+ {
+ *BytesReturned = BytesRet;
+ }
+ }
+
+ return Error;
+}
+
+/**
+ * @name KmtFltGetMessage
+ *
+ * Gets a message from a filter driver
+ *
+ * @param hPort
+ * Handle to the filter's comms port
+ * @MessageBuffer
+ * Pointer to a buffer to receive the data from the filter
+ * @MessageBufferSize
+ * Size of the buffer pointed to by MessageBuffer
+ * @Overlapped
+ * Pointer to an overlapped structure
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltGetMessage(
+ _In_ HANDLE hPort,
+ _Out_writes_bytes_(MessageBufferSize) PFILTER_MESSAGE_HEADER MessageBuffer,
+ _In_ DWORD MessageBufferSize,
+ _In_opt_ LPOVERLAPPED Overlapped)
+{
+ HRESULT hResult;
+ DWORD Error;
+
+ assert(hPort);
+ assert(MessageBuffer);
+
+ hResult = FilterGetMessage(hPort,
+ MessageBuffer,
+ MessageBufferSize,
+ Overlapped);
+ Error = SCODE_CODE(hResult);
+ return Error;
+}
+
+/**
+ * @name KmtFltReplyMessage
+ *
+ * Replies to a message from a filter driver
+ *
+ * @param hPort
+ * Handle to the filter's comms port
+ * @ReplyBuffer
+ * Pointer to a buffer to return to the filter
+ * @ReplyBufferSize
+ * Size of the buffer pointed to by ReplyBuffer
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltReplyMessage(
+ _In_ HANDLE hPort,
+ _In_reads_bytes_(ReplyBufferSize) PFILTER_REPLY_HEADER ReplyBuffer,
+ _In_ DWORD ReplyBufferSize)
+{
+ HRESULT hResult;
+ DWORD Error;
+
+ hResult = FilterReplyMessage(hPort,
+ ReplyBuffer,
+ ReplyBufferSize);
+ Error = SCODE_CODE(hResult);
+ return Error;
+}
+
+/**
+* @name KmtFltGetMessageResult
+*
+* Gets the overlapped result from the IO
+*
+* @param hPort
+* Handle to the filter's comms port
+* @Overlapped
+* Pointer to the overlapped structure usdd in the IO
+* @BytesTransferred
+* Number of bytes transferred in the IO
+*
+* @return Win32 error code
+*/
+DWORD
+KmtFltGetMessageResult(
+ _In_ HANDLE hPort,
+ _In_ LPOVERLAPPED Overlapped,
+ _Out_ LPDWORD BytesTransferred)
+{
+ BOOL Success;
+ DWORD Error = ERROR_SUCCESS;
+
+ *BytesTransferred = 0;
+
+ Success = GetOverlappedResult(hPort, Overlapped, BytesTransferred, TRUE);
+ if (!Success)
+ {
+ Error = GetLastError();
+ }
+
+ return Error;
+}
+
+/**
+ * @name KmtFltUnload
+ *
+ * Unload the specified filter driver
+ *
+ * @param ServiceName
+ * The name of the filter to unload
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltUnload(
+ _In_z_ PCWSTR ServiceName)
+{
+ HRESULT hResult;
+ DWORD Error = ERROR_SUCCESS;
+
+ assert(ServiceName);
+
+ hResult = FilterUnload(ServiceName);
+ Error = SCODE_CODE(hResult);
+
+ return Error;
+}
+
+/**
+ * @name KmtFltDeleteService
+ *
+ * Delete the specified filter driver
+ *
+ * @param ServiceName
+ * If *ServiceHandle is NULL, name of the service to delete
+ * @param ServiceHandle
+ * Pointer to a variable containing the service handle.
+ * Will be set to NULL on success
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltDeleteService(
+ _In_z_ PCWSTR ServiceName OPTIONAL,
+ _Inout_ SC_HANDLE *ServiceHandle)
+{
+ return KmtDeleteService(ServiceName, ServiceHandle);
+}
+
+/**
+ * @name KmtFltCloseService
+ *
+ * Close the specified driver service handle
+ *
+ * @param ServiceHandle
+ * Pointer to a variable containing the service handle.
+ * Will be set to NULL on success
+ *
+ * @return Win32 error code
+ */
+DWORD KmtFltCloseService(
+ _Inout_ SC_HANDLE *ServiceHandle)
+{
+ return KmtCloseService(ServiceHandle);
+}
diff --git a/modules/rostests/kmtests/kmtest/fltsupport.c
b/modules/rostests/kmtests/kmtest/fltsupport.c
new file mode 100644
index 0000000000..772e98a211
--- /dev/null
+++ b/modules/rostests/kmtests/kmtest/fltsupport.c
@@ -0,0 +1,301 @@
+/*
+ * PROJECT: ReactOS kernel-mode tests
+ * LICENSE: GPLv2+ - See COPYING in the top level directory
+ * PURPOSE: File system mini-filter support routines
+ * PROGRAMMER: Ged Murphy <gedmurphy(a)reactos.org>
+ */
+
+#include <kmt_test.h>
+
+#include "kmtest.h"
+#include <kmt_public.h>
+
+#include <assert.h>
+#include <debug.h>
+
+// move to a shared location
+typedef struct _KMTFLT_MESSAGE_HEADER
+{
+ ULONG Message;
+ PVOID Buffer;
+ ULONG BufferSize;
+
+} KMTFLT_MESSAGE_HEADER, *PKMTFLT_MESSAGE_HEADER;
+
+extern HANDLE KmtestHandle;
+static WCHAR TestServiceName[MAX_PATH];
+
+
+/**
+ * @name KmtFltLoadDriver
+ *
+ * Load the specified filter driver
+ * This routine will create the service entry if it doesn't already exist
+ *
+ * @param ServiceName
+ * Name of the driver service (Kmtest- prefix will be added automatically)
+ * @param RestartIfRunning
+ * TRUE to stop and restart the service if it is already running
+ * @param ConnectComms
+ * TRUE to create a comms connection to the specified filter
+ * @param hPort
+ * Handle to the filter's comms port
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltLoadDriver(
+ _In_z_ PCWSTR ServiceName,
+ _In_ BOOLEAN RestartIfRunning,
+ _In_ BOOLEAN ConnectComms,
+ _Out_ HANDLE *hPort)
+{
+ DWORD Error = ERROR_SUCCESS;
+ WCHAR ServicePath[MAX_PATH];
+ SC_HANDLE TestServiceHandle;
+
+ StringCbCopy(ServicePath, sizeof ServicePath, ServiceName);
+ StringCbCat(ServicePath, sizeof ServicePath, L"_drv.sys");
+
+ StringCbCopy(TestServiceName, sizeof TestServiceName, L"Kmtest-");
+ StringCbCat(TestServiceName, sizeof TestServiceName, ServiceName);
+
+ Error = KmtFltCreateAndStartService(TestServiceName, ServicePath, NULL,
&TestServiceHandle, TRUE);
+
+ if (Error == ERROR_SUCCESS && ConnectComms)
+ {
+ Error = KmtFltConnect(ServiceName, hPort);
+ }
+
+ return Error;
+}
+
+/**
+ * @name KmtFltUnloadDriver
+ *
+ * Unload the specified filter driver
+ *
+ * @param hPort
+ * Handle to the filter's comms port
+ * @param ConnectComms
+ * TRUE to disconnect the comms connection before unloading
+ *
+ * @return Win32 error code
+ */
+DWORD
+KmtFltUnloadDriver(
+ _In_ HANDLE *hPort,
+ _In_ BOOLEAN DisonnectComms)
+{
+ DWORD Error = ERROR_SUCCESS;
+
+ if (DisonnectComms)
+ {
+ Error = KmtFltDisconnect(hPort);
+
+ if (Error)
+ {
+ return Error;
+ }
+ }
+
+ Error = KmtFltUnload(TestServiceName);
+
+ if (Error)
+ {
+ // TODO
+ __debugbreak();
+ }
+
+ return Error;
+}
+
+
+/**
+* @name KmtFltRunKernelTest
+*
+* Run the specified filter test part
+*
+* @param hPort
+* Handle to the filter's comms port
+* @param TestName
+* Name of the test to run
+*
+* @return Win32 error code
+*/
+DWORD
+KmtFltRunKernelTest(
+ _In_ HANDLE hPort,
+ _In_z_ PCSTR TestName)
+{
+ return KmtFltSendStringToDriver(hPort, KMTFLT_RUN_TEST, TestName);
+}
+
+/**
+* @name KmtFltSendToDriver
+*
+* Send an I/O control message with no arguments to the driver opened with KmtOpenDriver
+*
+* @param hPort
+* Handle to the filter's comms port
+* @param Message
+* The message to send to the filter
+*
+* @return Win32 error code as returned by DeviceIoControl
+*/
+DWORD
+KmtFltSendToDriver(
+ _In_ HANDLE hPort,
+ _In_ DWORD Message)
+{
+ assert(hPort);
+ return KmtFltSendBufferToDriver(hPort, Message, NULL, 0, NULL, 0, NULL);
+}
+
+/**
+ * @name KmtFltSendStringToDriver
+ *
+ * Send an I/O control message with a string argument to the driver opened with
KmtOpenDriver
+ *
+ *
+ * @param hPort
+ * Handle to the filter's comms port
+ * @param Message
+ * The message associated with the string
+ * @param String
+ * An ANSI string to send to the filter
+ *
+ * @return Win32 error code as returned by DeviceIoControl
+ */
+DWORD
+KmtFltSendStringToDriver(
+ _In_ HANDLE hPort,
+ _In_ DWORD Message,
+ _In_ PCSTR String)
+{
+ assert(hPort);
+ assert(String);
+ return KmtFltSendBufferToDriver(hPort, Message, (PVOID)String, (DWORD)strlen(String),
NULL, 0, NULL);
+}
+
+/**
+ * @name KmtFltSendWStringToDriver
+ *
+ * Send an I/O control message with a wide string argument to the driver opened with
KmtOpenDriver
+ *
+ * @param hPort
+ * Handle to the filter's comms port
+ * @param Message
+ * The message associated with the string
+ * @param String
+ * An wide string to send to the filter
+ *
+ * @return Win32 error code as returned by DeviceIoControl
+ */
+DWORD
+KmtFltSendWStringToDriver(
+ _In_ HANDLE hPort,
+ _In_ DWORD Message,
+ _In_ PCWSTR String)
+{
+ return KmtFltSendBufferToDriver(hPort, Message, (PVOID)String, (DWORD)wcslen(String)
* sizeof(WCHAR), NULL, 0, NULL);
+}
+
+/**
+ * @name KmtFltSendUlongToDriver
+ *
+ * Send an I/O control message with an integer argument to the driver opened with
KmtOpenDriver
+ *
+ * @param hPort
+ * Handle to the filter's comms port
+ * @param Message
+ * The message associated with the value
+ * @param Value
+ * An 32bit valueng to send to the filter
+ *
+ * @return Win32 error code as returned by DeviceIoControl
+ */
+DWORD
+KmtFltSendUlongToDriver(
+ _In_ HANDLE hPort,
+ _In_ DWORD Message,
+ _In_ DWORD Value)
+{
+ return KmtFltSendBufferToDriver(hPort, Message, &Value, sizeof(Value), NULL, 0,
NULL);
+}
+
+/**
+ * @name KmtSendBufferToDriver
+ *
+ * Send an I/O control message with the specified arguments to the driver opened with
KmtOpenDriver
+ *
+ * @param hPort
+ * Handle to the filter's comms port
+ * @param Message
+ * The message associated with the value
+ * @param InBuffer
+ * Pointer to a buffer to send to the filter
+ * @param BufferSize
+ * Size of the buffer pointed to by InBuffer
+ * @param OutBuffer
+ * Pointer to a buffer to receive a response from the filter
+ * @param OutBufferSize
+ * Size of the buffer pointed to by OutBuffer
+ * @param BytesReturned
+ * Number of bytes written in the reply buffer
+ *
+ * @return Win32 error code as returned by DeviceIoControl
+ */
+DWORD
+KmtFltSendBufferToDriver(
+ _In_ HANDLE hPort,
+ _In_ DWORD Message,
+ _In_reads_bytes_(BufferSize) LPVOID InBuffer,
+ _In_ DWORD BufferSize,
+ _Out_writes_bytes_to_opt_(OutBufferSize, *BytesReturned) LPVOID OutBuffer,
+ _In_ DWORD OutBufferSize,
+ _Out_opt_ LPDWORD BytesReturned)
+{
+ PKMTFLT_MESSAGE_HEADER Ptr;
+ KMTFLT_MESSAGE_HEADER Header;
+ BOOLEAN FreeMemory = FALSE;
+ DWORD InBufferSize;
+ DWORD Error;
+
+ assert(hPort);
+
+ if (BufferSize)
+ {
+ assert(InBuffer);
+
+ InBufferSize = sizeof(KMTFLT_MESSAGE_HEADER) + BufferSize;
+ Ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, InBufferSize);
+ if (!Ptr)
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ FreeMemory = TRUE;
+ }
+ else
+ {
+ InBufferSize = sizeof(KMTFLT_MESSAGE_HEADER);
+ Ptr = &Header;
+ }
+
+ Ptr->Message = Message;
+ if (BufferSize)
+ {
+ Ptr->Buffer = (Ptr + 1);
+ StringCbCopy(Ptr->Buffer, BufferSize, InBuffer);
+ Ptr->BufferSize = BufferSize;
+ }
+
+ Error = KmtFltSendMessage(hPort, Ptr, InBufferSize, OutBuffer, OutBufferSize,
BytesReturned);
+
+ if (FreeMemory)
+ {
+ HeapFree(GetProcessHeap(), 0, Ptr);
+ }
+
+ return Error;
+}
diff --git a/modules/rostests/kmtests/kmtest/kmtest.h
b/modules/rostests/kmtests/kmtest/kmtest.h
index 4f9709245f..7329d18e48 100644
--- a/modules/rostests/kmtests/kmtest/kmtest.h
+++ b/modules/rostests/kmtests/kmtest/kmtest.h
@@ -60,5 +60,76 @@ KmtDeleteService(
DWORD KmtCloseService(
IN OUT SC_HANDLE *ServiceHandle);
+
+
+/* FS Filter management functions */
+
+DWORD
+KmtFltCreateService(
+ _In_z_ PCWSTR ServiceName,
+ _In_z_ PCWSTR ServicePath,
+ _In_z_ PCWSTR DisplayName OPTIONAL,
+ _Out_ SC_HANDLE *ServiceHandle);
+
+DWORD
+KmtFltLoad(
+ _In_z_ PCWSTR ServiceName);
+
+DWORD
+KmtFltCreateAndStartService(
+ _In_z_ PCWSTR ServiceName,
+ _In_z_ PCWSTR ServicePath,
+ _In_z_ PCWSTR DisplayName OPTIONAL,
+ _Out_ SC_HANDLE *ServiceHandle,
+ _In_ BOOLEAN RestartIfRunning);
+
+DWORD
+KmtFltConnect(
+ _In_z_ PCWSTR ServiceName,
+ _Out_ HANDLE *hPort);
+
+DWORD
+KmtFltDisconnect(
+ _Out_ HANDLE *hPort);
+
+DWORD
+KmtFltSendMessage(
+ _In_ HANDLE hPort,
+ _In_reads_bytes_(dwInBufferSize) LPVOID lpInBuffer,
+ _In_ DWORD dwInBufferSize,
+ _Out_writes_bytes_to_opt_(dwOutBufferSize, *lpBytesReturned) LPVOID lpOutBuffer,
+ _In_ DWORD dwOutBufferSize,
+ _Out_opt_ LPDWORD lpBytesReturned);
+
+DWORD
+KmtFltGetMessage(
+ _In_ HANDLE hPort,
+ _Out_writes_bytes_(dwMessageBufferSize) PFILTER_MESSAGE_HEADER lpMessageBuffer,
+ _In_ DWORD dwMessageBufferSize,
+ _In_opt_ LPOVERLAPPED Overlapped);
+
+DWORD
+KmtFltReplyMessage(
+ _In_ HANDLE hPort,
+ _In_reads_bytes_(dwReplyBufferSize) PFILTER_REPLY_HEADER lpReplyBuffer,
+ _In_ DWORD dwReplyBufferSize);
+
+DWORD
+KmtFltGetMessageResult(
+ _In_ HANDLE hPort,
+ _In_ LPOVERLAPPED Overlapped,
+ _Out_ LPDWORD BytesTransferred);
+
+DWORD
+KmtFltUnload(
+ _In_z_ PCWSTR ServiceName);
+
+DWORD
+KmtFltDeleteService(
+ _In_z_ PCWSTR ServiceName OPTIONAL,
+ _Inout_ SC_HANDLE *ServiceHandle);
+
+DWORD KmtFltCloseService(
+ _Inout_ SC_HANDLE *ServiceHandle);
#endif /* !defined _KMTESTS_H_ */
diff --git a/modules/rostests/kmtests/kmtest/service.c
b/modules/rostests/kmtests/kmtest/service.c
index 9fa8785f48..3f617fc302 100644
--- a/modules/rostests/kmtests/kmtest/service.c
+++ b/modules/rostests/kmtests/kmtest/service.c
@@ -12,6 +12,19 @@
#define SERVICE_ACCESS (SERVICE_START | SERVICE_STOP | DELETE)
+/*
+ * This is an internal function not meant for use by the kmtests app,
+ * so we declare it here instead of kmtest.h
+ */
+DWORD
+KmtpCreateService(
+ IN PCWSTR ServiceName,
+ IN PCWSTR ServicePath,
+ IN PCWSTR DisplayName OPTIONAL,
+ IN DWORD ServiceType,
+ OUT SC_HANDLE *ServiceHandle);
+
+
static SC_HANDLE ScmHandle;
/**
@@ -80,35 +93,11 @@ KmtCreateService(
IN PCWSTR DisplayName OPTIONAL,
OUT SC_HANDLE *ServiceHandle)
{
- DWORD Error = ERROR_SUCCESS;
- WCHAR DriverPath[MAX_PATH];
- HRESULT result = S_OK;
-
- assert(ServiceHandle);
- assert(ServiceName && ServicePath);
-
- if (!GetModuleFileName(NULL, DriverPath, sizeof DriverPath / sizeof DriverPath[0]))
- error_goto(Error, cleanup);
-
- assert(wcsrchr(DriverPath, L'\\') != NULL);
- wcsrchr(DriverPath, L'\\')[1] = L'\0';
-
- result = StringCbCat(DriverPath, sizeof DriverPath, ServicePath);
- if (FAILED(result))
- error_value_goto(Error, result, cleanup);
-
- if (GetFileAttributes(DriverPath) == INVALID_FILE_ATTRIBUTES)
- error_goto(Error, cleanup);
-
- *ServiceHandle = CreateService(ScmHandle, ServiceName, DisplayName,
- SERVICE_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,
- SERVICE_ERROR_NORMAL, DriverPath, NULL, NULL, NULL, NULL,
NULL);
-
- if (!*ServiceHandle)
- error_goto(Error, cleanup);
-
-cleanup:
- return Error;
+ return KmtpCreateService(ServiceName,
+ ServicePath,
+ DisplayName,
+ SERVICE_KERNEL_DRIVER,
+ ServiceHandle);
}
/**
@@ -307,3 +296,47 @@ DWORD KmtCloseService(
cleanup:
return Error;
}
+
+
+/*
+ * Private function, not meant for use in kmtests
+ * See KmtCreateService & KmtFltCreateService
+ */
+DWORD
+KmtpCreateService(
+ IN PCWSTR ServiceName,
+ IN PCWSTR ServicePath,
+ IN PCWSTR DisplayName OPTIONAL,
+ IN DWORD ServiceType,
+ OUT SC_HANDLE *ServiceHandle)
+{
+ DWORD Error = ERROR_SUCCESS;
+ WCHAR DriverPath[MAX_PATH];
+ HRESULT result = S_OK;
+
+ assert(ServiceHandle);
+ assert(ServiceName && ServicePath);
+
+ if (!GetModuleFileName(NULL, DriverPath, sizeof DriverPath / sizeof DriverPath[0]))
+ error_goto(Error, cleanup);
+
+ assert(wcsrchr(DriverPath, L'\\') != NULL);
+ wcsrchr(DriverPath, L'\\')[1] = L'\0';
+
+ result = StringCbCat(DriverPath, sizeof DriverPath, ServicePath);
+ if (FAILED(result))
+ error_value_goto(Error, result, cleanup);
+
+ if (GetFileAttributes(DriverPath) == INVALID_FILE_ATTRIBUTES)
+ error_goto(Error, cleanup);
+
+ *ServiceHandle = CreateService(ScmHandle, ServiceName, DisplayName,
+ SERVICE_ACCESS, ServiceType, SERVICE_DEMAND_START,
+ SERVICE_ERROR_NORMAL, DriverPath, NULL, NULL, NULL,
NULL, NULL);
+
+ if (!*ServiceHandle)
+ error_goto(Error, cleanup);
+
+cleanup:
+ return Error;
+}
\ No newline at end of file