[KMTEST] Initial usermode support for testing FS mini-filters (#81)
[reactos.git] / modules / rostests / kmtests / kmtest / fltsupport.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: File system mini-filter support routines
5 * PROGRAMMER: Ged Murphy <gedmurphy@reactos.org>
6 */
7
8 #include <kmt_test.h>
9
10 #include "kmtest.h"
11 #include <kmt_public.h>
12
13 #include <assert.h>
14 #include <debug.h>
15
16 // move to a shared location
17 typedef struct _KMTFLT_MESSAGE_HEADER
18 {
19 ULONG Message;
20 PVOID Buffer;
21 ULONG BufferSize;
22
23 } KMTFLT_MESSAGE_HEADER, *PKMTFLT_MESSAGE_HEADER;
24
25 extern HANDLE KmtestHandle;
26 static WCHAR TestServiceName[MAX_PATH];
27
28
29 /**
30 * @name KmtFltLoadDriver
31 *
32 * Load the specified filter driver
33 * This routine will create the service entry if it doesn't already exist
34 *
35 * @param ServiceName
36 * Name of the driver service (Kmtest- prefix will be added automatically)
37 * @param RestartIfRunning
38 * TRUE to stop and restart the service if it is already running
39 * @param ConnectComms
40 * TRUE to create a comms connection to the specified filter
41 * @param hPort
42 * Handle to the filter's comms port
43 *
44 * @return Win32 error code
45 */
46 DWORD
47 KmtFltLoadDriver(
48 _In_z_ PCWSTR ServiceName,
49 _In_ BOOLEAN RestartIfRunning,
50 _In_ BOOLEAN ConnectComms,
51 _Out_ HANDLE *hPort)
52 {
53 DWORD Error = ERROR_SUCCESS;
54 WCHAR ServicePath[MAX_PATH];
55 SC_HANDLE TestServiceHandle;
56
57 StringCbCopy(ServicePath, sizeof ServicePath, ServiceName);
58 StringCbCat(ServicePath, sizeof ServicePath, L"_drv.sys");
59
60 StringCbCopy(TestServiceName, sizeof TestServiceName, L"Kmtest-");
61 StringCbCat(TestServiceName, sizeof TestServiceName, ServiceName);
62
63 Error = KmtFltCreateAndStartService(TestServiceName, ServicePath, NULL, &TestServiceHandle, TRUE);
64
65 if (Error == ERROR_SUCCESS && ConnectComms)
66 {
67 Error = KmtFltConnect(ServiceName, hPort);
68 }
69
70 return Error;
71 }
72
73 /**
74 * @name KmtFltUnloadDriver
75 *
76 * Unload the specified filter driver
77 *
78 * @param hPort
79 * Handle to the filter's comms port
80 * @param ConnectComms
81 * TRUE to disconnect the comms connection before unloading
82 *
83 * @return Win32 error code
84 */
85 DWORD
86 KmtFltUnloadDriver(
87 _In_ HANDLE *hPort,
88 _In_ BOOLEAN DisonnectComms)
89 {
90 DWORD Error = ERROR_SUCCESS;
91
92 if (DisonnectComms)
93 {
94 Error = KmtFltDisconnect(hPort);
95
96 if (Error)
97 {
98 return Error;
99 }
100 }
101
102 Error = KmtFltUnload(TestServiceName);
103
104 if (Error)
105 {
106 // TODO
107 __debugbreak();
108 }
109
110 return Error;
111 }
112
113
114 /**
115 * @name KmtFltRunKernelTest
116 *
117 * Run the specified filter test part
118 *
119 * @param hPort
120 * Handle to the filter's comms port
121 * @param TestName
122 * Name of the test to run
123 *
124 * @return Win32 error code
125 */
126 DWORD
127 KmtFltRunKernelTest(
128 _In_ HANDLE hPort,
129 _In_z_ PCSTR TestName)
130 {
131 return KmtFltSendStringToDriver(hPort, KMTFLT_RUN_TEST, TestName);
132 }
133
134 /**
135 * @name KmtFltSendToDriver
136 *
137 * Send an I/O control message with no arguments to the driver opened with KmtOpenDriver
138 *
139 * @param hPort
140 * Handle to the filter's comms port
141 * @param Message
142 * The message to send to the filter
143 *
144 * @return Win32 error code as returned by DeviceIoControl
145 */
146 DWORD
147 KmtFltSendToDriver(
148 _In_ HANDLE hPort,
149 _In_ DWORD Message)
150 {
151 assert(hPort);
152 return KmtFltSendBufferToDriver(hPort, Message, NULL, 0, NULL, 0, NULL);
153 }
154
155 /**
156 * @name KmtFltSendStringToDriver
157 *
158 * Send an I/O control message with a string argument to the driver opened with KmtOpenDriver
159 *
160 *
161 * @param hPort
162 * Handle to the filter's comms port
163 * @param Message
164 * The message associated with the string
165 * @param String
166 * An ANSI string to send to the filter
167 *
168 * @return Win32 error code as returned by DeviceIoControl
169 */
170 DWORD
171 KmtFltSendStringToDriver(
172 _In_ HANDLE hPort,
173 _In_ DWORD Message,
174 _In_ PCSTR String)
175 {
176 assert(hPort);
177 assert(String);
178 return KmtFltSendBufferToDriver(hPort, Message, (PVOID)String, (DWORD)strlen(String), NULL, 0, NULL);
179 }
180
181 /**
182 * @name KmtFltSendWStringToDriver
183 *
184 * Send an I/O control message with a wide string argument to the driver opened with KmtOpenDriver
185 *
186 * @param hPort
187 * Handle to the filter's comms port
188 * @param Message
189 * The message associated with the string
190 * @param String
191 * An wide string to send to the filter
192 *
193 * @return Win32 error code as returned by DeviceIoControl
194 */
195 DWORD
196 KmtFltSendWStringToDriver(
197 _In_ HANDLE hPort,
198 _In_ DWORD Message,
199 _In_ PCWSTR String)
200 {
201 return KmtFltSendBufferToDriver(hPort, Message, (PVOID)String, (DWORD)wcslen(String) * sizeof(WCHAR), NULL, 0, NULL);
202 }
203
204 /**
205 * @name KmtFltSendUlongToDriver
206 *
207 * Send an I/O control message with an integer argument to the driver opened with KmtOpenDriver
208 *
209 * @param hPort
210 * Handle to the filter's comms port
211 * @param Message
212 * The message associated with the value
213 * @param Value
214 * An 32bit valueng to send to the filter
215 *
216 * @return Win32 error code as returned by DeviceIoControl
217 */
218 DWORD
219 KmtFltSendUlongToDriver(
220 _In_ HANDLE hPort,
221 _In_ DWORD Message,
222 _In_ DWORD Value)
223 {
224 return KmtFltSendBufferToDriver(hPort, Message, &Value, sizeof(Value), NULL, 0, NULL);
225 }
226
227 /**
228 * @name KmtSendBufferToDriver
229 *
230 * Send an I/O control message with the specified arguments to the driver opened with KmtOpenDriver
231 *
232 * @param hPort
233 * Handle to the filter's comms port
234 * @param Message
235 * The message associated with the value
236 * @param InBuffer
237 * Pointer to a buffer to send to the filter
238 * @param BufferSize
239 * Size of the buffer pointed to by InBuffer
240 * @param OutBuffer
241 * Pointer to a buffer to receive a response from the filter
242 * @param OutBufferSize
243 * Size of the buffer pointed to by OutBuffer
244 * @param BytesReturned
245 * Number of bytes written in the reply buffer
246 *
247 * @return Win32 error code as returned by DeviceIoControl
248 */
249 DWORD
250 KmtFltSendBufferToDriver(
251 _In_ HANDLE hPort,
252 _In_ DWORD Message,
253 _In_reads_bytes_(BufferSize) LPVOID InBuffer,
254 _In_ DWORD BufferSize,
255 _Out_writes_bytes_to_opt_(OutBufferSize, *BytesReturned) LPVOID OutBuffer,
256 _In_ DWORD OutBufferSize,
257 _Out_opt_ LPDWORD BytesReturned)
258 {
259 PKMTFLT_MESSAGE_HEADER Ptr;
260 KMTFLT_MESSAGE_HEADER Header;
261 BOOLEAN FreeMemory = FALSE;
262 DWORD InBufferSize;
263 DWORD Error;
264
265 assert(hPort);
266
267 if (BufferSize)
268 {
269 assert(InBuffer);
270
271 InBufferSize = sizeof(KMTFLT_MESSAGE_HEADER) + BufferSize;
272 Ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, InBufferSize);
273 if (!Ptr)
274 {
275 return ERROR_NOT_ENOUGH_MEMORY;
276 }
277 FreeMemory = TRUE;
278 }
279 else
280 {
281 InBufferSize = sizeof(KMTFLT_MESSAGE_HEADER);
282 Ptr = &Header;
283 }
284
285 Ptr->Message = Message;
286 if (BufferSize)
287 {
288 Ptr->Buffer = (Ptr + 1);
289 StringCbCopy(Ptr->Buffer, BufferSize, InBuffer);
290 Ptr->BufferSize = BufferSize;
291 }
292
293 Error = KmtFltSendMessage(hPort, Ptr, InBufferSize, OutBuffer, OutBufferSize, BytesReturned);
294
295 if (FreeMemory)
296 {
297 HeapFree(GetProcessHeap(), 0, Ptr);
298 }
299
300 return Error;
301 }