xref: /reactos/base/applications/fltmc/fltmc.cpp (revision 40462c92)
1 /*
2 * PROJECT:     ReactOS fltmc utility
3 * LICENSE:     GPL - See COPYING in the top level directory
4 * FILE:        base/applications/fltmc/fltmc.c
5 * PURPOSE:     Control utility for file system filter drivers
6 * PROGRAMMERS: Copyright 2016 Ged Murphy (gedmurphy@gmail.com)
7 */
8 
9 // Please leave this temporary hack in place
10 // it's used to keep VS2015 happy for development.
11 #ifdef __REACTOS__
12 #include <stdarg.h>
13 #include <windef.h>
14 #include <winbase.h>
15 #include <wchar.h>
16 #else
17 #include <Windows.h>
18 #endif
19 #include <fltuser.h>
20 #include <atlstr.h>
21 #include <strsafe.h>
22 #include "resource.h"
23 
24 EXTERN_C int wmain(int argc, WCHAR *argv[]);
25 
26 void
27 LoadAndPrintString(ULONG MessageId, ...)
28 {
29     va_list args;
30 
31     CAtlStringW Message;
32     if (Message.LoadStringW(MessageId))
33     {
34         va_start(args, MessageId);
35         vwprintf(Message.GetBuffer(), args);
36         va_end(args);
37     }
38 }
39 
40 void
41 PrintErrorText(_In_ ULONG ErrorCode)
42 {
43     WCHAR Buffer[256];
44     if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
45                        0,
46                        ErrorCode,
47                        0,
48                        Buffer,
49                        256,
50                        0))
51     {
52         wprintf(L"%s\n", Buffer);
53     }
54 }
55 
56 DWORD
57 SetDriverLoadPrivilege()
58 {
59     TOKEN_PRIVILEGES TokenPrivileges;
60     HANDLE hToken;
61     LUID luid;
62     BOOL bSuccess;
63     DWORD dwError = ERROR_SUCCESS;
64 
65     bSuccess = OpenProcessToken(GetCurrentProcess(),
66                                 TOKEN_ADJUST_PRIVILEGES,
67                                 &hToken);
68     if (bSuccess == FALSE)
69         return GetLastError();
70 
71     if (!LookupPrivilegeValueW(NULL, SE_LOAD_DRIVER_NAME, &luid))
72         return GetLastError();
73 
74     TokenPrivileges.PrivilegeCount = 1;
75     TokenPrivileges.Privileges[0].Luid = luid;
76     TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
77 
78     bSuccess = AdjustTokenPrivileges(hToken,
79                                      FALSE,
80                                      &TokenPrivileges,
81                                      sizeof(TOKEN_PRIVILEGES),
82                                      NULL,
83                                      NULL);
84     if (bSuccess == FALSE)
85         dwError = GetLastError();
86 
87     CloseHandle(hToken);
88 
89     return dwError;
90 }
91 
92 void
93 LoadFilter(_In_ LPWSTR FilterName)
94 {
95     DWORD dwError;
96     dwError = SetDriverLoadPrivilege();
97     if (dwError != ERROR_SUCCESS)
98     {
99         LoadAndPrintString(IDS_ERROR_PRIV, HRESULT_FROM_WIN32(dwError));
100         return;
101     }
102 
103     HRESULT hr = FilterLoad(FilterName);
104     if (hr != S_OK)
105     {
106         LoadAndPrintString(IDS_ERROR_LOAD, hr);
107         PrintErrorText(hr);
108     }
109 }
110 
111 void
112 UnloadFilter(_In_ LPWSTR FilterName)
113 {
114     DWORD dwError;
115     dwError = SetDriverLoadPrivilege();
116     if (dwError != ERROR_SUCCESS)
117     {
118         LoadAndPrintString(IDS_ERROR_PRIV, HRESULT_FROM_WIN32(dwError));
119         return;
120     }
121 
122     HRESULT hr = FilterUnload(FilterName);
123     if (hr != S_OK)
124     {
125         LoadAndPrintString(IDS_ERROR_UNLOAD, hr);
126         PrintErrorText(hr);
127     }
128 }
129 
130 void
131 PrintFilterInfo(_In_ PVOID Buffer,
132                 _In_ BOOL IsNewStyle)
133 {
134     WCHAR FilterName[128] = { 0 };
135     WCHAR NumOfInstances[16] = { 0 };
136     WCHAR Altitude[64] = { 0 };
137     WCHAR Frame[16] = { 0 };
138 
139     if (IsNewStyle)
140     {
141         PFILTER_AGGREGATE_STANDARD_INFORMATION FilterAggInfo;
142         FilterAggInfo = (PFILTER_AGGREGATE_STANDARD_INFORMATION)Buffer;
143 
144         if (FilterAggInfo->Flags & FLTFL_ASI_IS_MINIFILTER)
145         {
146             if (FilterAggInfo->Type.MiniFilter.FilterNameLength < 128)
147             {
148                 CopyMemory(FilterName,
149                            (PCHAR)FilterAggInfo + FilterAggInfo->Type.MiniFilter.FilterNameBufferOffset,
150                            FilterAggInfo->Type.MiniFilter.FilterNameLength);
151                 FilterName[FilterAggInfo->Type.MiniFilter.FilterNameLength] = UNICODE_NULL;
152             }
153 
154             StringCchPrintfW(NumOfInstances, 16, L"%lu", FilterAggInfo->Type.MiniFilter.NumberOfInstances);
155 
156             if (FilterAggInfo->Type.MiniFilter.FilterAltitudeLength < 64)
157             {
158                 CopyMemory(Altitude,
159                            (PCHAR)FilterAggInfo + FilterAggInfo->Type.MiniFilter.FilterAltitudeBufferOffset,
160                            FilterAggInfo->Type.MiniFilter.FilterAltitudeLength);
161                 FilterName[FilterAggInfo->Type.MiniFilter.FilterAltitudeLength] = UNICODE_NULL;
162             }
163 
164             StringCchPrintfW(Frame, 16, L"%lu", FilterAggInfo->Type.MiniFilter.FrameID);
165         }
166         else if (FilterAggInfo->Flags & FLTFL_ASI_IS_LEGACYFILTER)
167         {
168             if (FilterAggInfo->Type.LegacyFilter.FilterNameLength < 128)
169             {
170                 CopyMemory(FilterName,
171                            (PCHAR)FilterAggInfo + FilterAggInfo->Type.LegacyFilter.FilterNameBufferOffset,
172                            FilterAggInfo->Type.LegacyFilter.FilterNameLength);
173                 FilterName[FilterAggInfo->Type.LegacyFilter.FilterNameLength] = UNICODE_NULL;
174             }
175 
176             StringCchCopyW(Frame, 16, L"<Legacy>"); //Fixme: is this localized?
177         }
178 
179         wprintf(L"%-38s %-10s %-10s %3s\n",
180                 FilterName,
181                 NumOfInstances,
182                 Altitude,
183                 Frame);
184     }
185     else
186     {
187         PFILTER_FULL_INFORMATION FilterInfo;
188         FilterInfo = (PFILTER_FULL_INFORMATION)Buffer;
189 
190         if (FilterInfo->FilterNameLength < 128)
191         {
192             CopyMemory(FilterName,
193                        FilterInfo->FilterNameBuffer,
194                        FilterInfo->FilterNameLength);
195             FilterName[FilterInfo->FilterNameLength] = UNICODE_NULL;
196         }
197 
198         wprintf(L"%-38s %-10lu %-10lu\n",
199                 FilterName,
200                 FilterInfo->NumberOfInstances,
201                 FilterInfo->FrameID);
202     }
203 }
204 
205 void
206 PrintVolumeInfo(_In_ PVOID Buffer)
207 {
208     PFILTER_VOLUME_STANDARD_INFORMATION FilterVolInfo;
209     WCHAR DosName[16] = { 0 };
210     WCHAR VolName[128] = { 0 };
211     WCHAR FileSystem[32] = { 0 };
212 
213     FilterVolInfo = (PFILTER_VOLUME_STANDARD_INFORMATION)Buffer;
214 
215     if (FilterVolInfo->FilterVolumeNameLength < 128)
216     {
217         CopyMemory(VolName,
218                    (PCHAR)FilterVolInfo->FilterVolumeName,
219                    FilterVolInfo->FilterVolumeNameLength);
220         VolName[FilterVolInfo->FilterVolumeNameLength] = UNICODE_NULL;
221     }
222 
223     (void)FilterGetDosName(VolName, DosName, 16);
224 
225     switch (FilterVolInfo->FileSystemType)
226     {
227     case FLT_FSTYPE_MUP:
228         StringCchCopyW(FileSystem, 32, L"Remote");
229         break;
230 
231     case FLT_FSTYPE_NTFS:
232         StringCchCopyW(FileSystem, 32, L"NTFS");
233         break;
234 
235     case FLT_FSTYPE_FAT:
236         StringCchCopyW(FileSystem, 32, L"FAT");
237         break;
238 
239     case FLT_FSTYPE_EXFAT:
240         StringCchCopyW(FileSystem, 32, L"exFAT");
241         break;
242 
243     case FLT_FSTYPE_NPFS:
244         StringCchCopyW(FileSystem, 32, L"NamedPipe");
245         break;
246 
247     case FLT_FSTYPE_MSFS:
248         StringCchCopyW(FileSystem, 32, L"Mailslot");
249         break;
250 
251     case FLT_FSTYPE_UNKNOWN:
252     default:
253         StringCchCopyW(FileSystem, 32, L"<Unknown>");
254         break;
255     }
256 
257     wprintf(L"%-31s %-40s %-10s\n",
258             DosName,
259             VolName,
260             FileSystem);
261 }
262 
263 void
264 ListFilters()
265 {
266     HANDLE FindHandle;
267     BYTE Buffer[1024];
268     ULONG BytesReturned;
269     BOOL IsNewStyle = TRUE;
270     HRESULT hr;
271 
272     hr = FilterFindFirst(FilterAggregateStandardInformation,
273                          Buffer,
274                          1024,
275                          &BytesReturned,
276                          &FindHandle);
277     if (!SUCCEEDED(hr))
278     {
279         IsNewStyle = FALSE;
280         hr = FilterFindFirst(FilterFullInformation,
281                              Buffer,
282                              1024,
283                              &BytesReturned,
284                              &FindHandle);
285     }
286 
287     if (SUCCEEDED(hr))
288     {
289         if (IsNewStyle)
290         {
291             LoadAndPrintString(IDS_DISPLAY_FILTERS1);
292             wprintf(L"------------------------------  -------------  ------------  -----\n");
293         }
294         else
295         {
296             LoadAndPrintString(IDS_DISPLAY_FILTERS2);
297             wprintf(L"------------------------------  -------------  -----\n");
298         }
299 
300         PrintFilterInfo(Buffer, IsNewStyle);
301 
302         do
303         {
304             hr = FilterFindNext(FindHandle,
305                                 IsNewStyle ? FilterAggregateStandardInformation : FilterFullInformation,
306                                 Buffer,
307                                 1024,
308                                 &BytesReturned);
309             if (SUCCEEDED(hr))
310             {
311                 PrintFilterInfo(Buffer, IsNewStyle);
312             }
313 
314         } while (SUCCEEDED(hr));
315 
316         FilterFindClose(FindHandle);
317     }
318 
319     if (!SUCCEEDED(hr) && hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
320     {
321         LoadAndPrintString(IDS_ERROR_FILTERS, hr);
322         PrintErrorText(hr);
323     }
324 }
325 
326 void
327 ListVolumes()
328 {
329     HANDLE FindHandle;
330     BYTE Buffer[1024];
331     ULONG BytesReturned;
332     HRESULT hr;
333 
334     hr = FilterVolumeFindFirst(FilterVolumeStandardInformation,
335                                Buffer,
336                                1024,
337                                &BytesReturned,
338                                &FindHandle);
339     if (SUCCEEDED(hr))
340     {
341         LoadAndPrintString(IDS_DISPLAY_VOLUMES);
342         wprintf(L"------------------------------  ---------------------------------------  ----------  --------\n");
343 
344         PrintVolumeInfo(Buffer);
345 
346         do
347         {
348             hr = FilterVolumeFindNext(FindHandle,
349                                       FilterVolumeStandardInformation,
350                                       Buffer,
351                                       1024,
352                                       &BytesReturned);
353             if (SUCCEEDED(hr))
354             {
355                 PrintVolumeInfo(Buffer);
356             }
357 
358         } while (SUCCEEDED(hr));
359 
360         FilterVolumeFindClose(FindHandle);
361     }
362 
363     if (!SUCCEEDED(hr) && hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
364     {
365         LoadAndPrintString(IDS_ERROR_VOLUMES, hr);
366         PrintErrorText(hr);
367     }
368 }
369 
370 int wmain(int argc, WCHAR *argv[])
371 {
372     wprintf(L"\n");
373 
374     if ((argc < 2) || (!_wcsicmp(argv[1], L"filters")))
375     {
376         if (argc < 3)
377         {
378             ListFilters();
379         }
380         else
381         {
382             LoadAndPrintString(IDS_USAGE_FILTERS);
383             wprintf(L"fltmc.exe filters\n\n");
384         }
385     }
386     else if (!_wcsicmp(argv[1], L"help"))
387     {
388         LoadAndPrintString(IDS_USAGE);
389     }
390     else if (!_wcsicmp(argv[1], L"load"))
391     {
392         if (argc == 3)
393         {
394             LoadFilter(argv[2]);
395         }
396         else
397         {
398             LoadAndPrintString(IDS_USAGE_LOAD);
399             wprintf(L"fltmc.exe load [name]\n\n");
400         }
401     }
402     else if (!_wcsicmp(argv[1], L"unload"))
403     {
404         if (argc == 3)
405         {
406             UnloadFilter(argv[2]);
407         }
408         else
409         {
410             LoadAndPrintString(IDS_USAGE_UNLOAD);
411             wprintf(L"fltmc.exe unload [name]\n\n");
412         }
413     }
414     else if (!_wcsicmp(argv[1], L"volumes"))
415     {
416         if (argc == 2)
417         {
418             ListVolumes();
419         }
420         else
421         {
422             LoadAndPrintString(IDS_USAGE_VOLUMES);
423             wprintf(L"fltmc.exe volumes\n\n");
424         }
425     }
426 
427     return 0;
428 }
429