xref: /reactos/base/applications/fltmc/fltmc.cpp (revision 5aafeb47)
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
LoadAndPrintString(ULONG MessageId,...)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
PrintErrorText(_In_ ULONG ErrorCode)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
SetDriverLoadPrivilege()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
LoadFilter(_In_ LPWSTR FilterName)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
UnloadFilter(_In_ LPWSTR FilterName)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
PrintFilterInfo(_In_ PVOID Buffer,_In_ BOOL IsNewStyle)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
PrintVolumeInfo(_In_ PVOID Buffer)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     if (!SUCCEEDED(FilterGetDosName(VolName, DosName, _countof(DosName))))
224         DosName[0] = L'\0';
225 
226     switch (FilterVolInfo->FileSystemType)
227     {
228     case FLT_FSTYPE_MUP:
229         StringCchCopyW(FileSystem, 32, L"Remote");
230         break;
231 
232     case FLT_FSTYPE_NTFS:
233         StringCchCopyW(FileSystem, 32, L"NTFS");
234         break;
235 
236     case FLT_FSTYPE_FAT:
237         StringCchCopyW(FileSystem, 32, L"FAT");
238         break;
239 
240     case FLT_FSTYPE_EXFAT:
241         StringCchCopyW(FileSystem, 32, L"exFAT");
242         break;
243 
244     case FLT_FSTYPE_NPFS:
245         StringCchCopyW(FileSystem, 32, L"NamedPipe");
246         break;
247 
248     case FLT_FSTYPE_MSFS:
249         StringCchCopyW(FileSystem, 32, L"Mailslot");
250         break;
251 
252     case FLT_FSTYPE_UNKNOWN:
253     default:
254         StringCchCopyW(FileSystem, 32, L"<Unknown>");
255         break;
256     }
257 
258     wprintf(L"%-31s %-40s %-10s\n",
259             DosName,
260             VolName,
261             FileSystem);
262 }
263 
264 void
ListFilters()265 ListFilters()
266 {
267     HANDLE FindHandle;
268     BYTE Buffer[1024];
269     ULONG BytesReturned;
270     BOOL IsNewStyle = TRUE;
271     HRESULT hr;
272 
273     hr = FilterFindFirst(FilterAggregateStandardInformation,
274                          Buffer,
275                          sizeof(Buffer),
276                          &BytesReturned,
277                          &FindHandle);
278     if (!SUCCEEDED(hr))
279     {
280         IsNewStyle = FALSE;
281         hr = FilterFindFirst(FilterFullInformation,
282                              Buffer,
283                              sizeof(Buffer),
284                              &BytesReturned,
285                              &FindHandle);
286     }
287 
288     if (!SUCCEEDED(hr))
289     {
290         LoadAndPrintString(IDS_ERROR_FILTERS, hr);
291         PrintErrorText(hr);
292         return;
293     }
294 
295     if (IsNewStyle)
296     {
297         LoadAndPrintString(IDS_DISPLAY_FILTERS1);
298         wprintf(L"------------------------------  -------------  ------------  -----\n");
299     }
300     else
301     {
302         LoadAndPrintString(IDS_DISPLAY_FILTERS2);
303         wprintf(L"------------------------------  -------------  -----\n");
304     }
305 
306     PrintFilterInfo(Buffer, IsNewStyle);
307 
308     do
309     {
310         hr = FilterFindNext(FindHandle,
311                             IsNewStyle ? FilterAggregateStandardInformation : FilterFullInformation,
312                             Buffer,
313                             sizeof(Buffer),
314                             &BytesReturned);
315         if (SUCCEEDED(hr))
316         {
317             PrintFilterInfo(Buffer, IsNewStyle);
318         }
319         else if (hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
320         {
321             LoadAndPrintString(IDS_ERROR_FILTERS, hr);
322             PrintErrorText(hr);
323         }
324     } while (SUCCEEDED(hr));
325 
326     hr = FilterFindClose(FindHandle);
327     if (!SUCCEEDED(hr))
328     {
329         LoadAndPrintString(IDS_ERROR_FILTERS, hr);
330         PrintErrorText(hr);
331     }
332 }
333 
334 void
ListVolumes()335 ListVolumes()
336 {
337     HANDLE FindHandle;
338     BYTE Buffer[1024];
339     ULONG BytesReturned;
340     HRESULT hr;
341 
342     hr = FilterVolumeFindFirst(FilterVolumeStandardInformation,
343                                Buffer,
344                                1024,
345                                &BytesReturned,
346                                &FindHandle);
347     if (SUCCEEDED(hr))
348     {
349         LoadAndPrintString(IDS_DISPLAY_VOLUMES);
350         wprintf(L"------------------------------  ---------------------------------------  ----------  --------\n");
351 
352         PrintVolumeInfo(Buffer);
353 
354         do
355         {
356             hr = FilterVolumeFindNext(FindHandle,
357                                       FilterVolumeStandardInformation,
358                                       Buffer,
359                                       1024,
360                                       &BytesReturned);
361             if (SUCCEEDED(hr))
362             {
363                 PrintVolumeInfo(Buffer);
364             }
365 
366         } while (SUCCEEDED(hr));
367 
368         FilterVolumeFindClose(FindHandle);
369     }
370 
371     if (!SUCCEEDED(hr) && hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
372     {
373         LoadAndPrintString(IDS_ERROR_VOLUMES, hr);
374         PrintErrorText(hr);
375     }
376 }
377 
wmain(int argc,WCHAR * argv[])378 int wmain(int argc, WCHAR *argv[])
379 {
380     wprintf(L"\n");
381 
382     if ((argc < 2) || (!_wcsicmp(argv[1], L"filters")))
383     {
384         if (argc < 3)
385         {
386             ListFilters();
387         }
388         else
389         {
390             LoadAndPrintString(IDS_USAGE_FILTERS);
391             wprintf(L"fltmc.exe filters\n\n");
392         }
393     }
394     else if (!_wcsicmp(argv[1], L"help"))
395     {
396         LoadAndPrintString(IDS_USAGE);
397     }
398     else if (!_wcsicmp(argv[1], L"load"))
399     {
400         if (argc == 3)
401         {
402             LoadFilter(argv[2]);
403         }
404         else
405         {
406             LoadAndPrintString(IDS_USAGE_LOAD);
407             wprintf(L"fltmc.exe load [name]\n\n");
408         }
409     }
410     else if (!_wcsicmp(argv[1], L"unload"))
411     {
412         if (argc == 3)
413         {
414             UnloadFilter(argv[2]);
415         }
416         else
417         {
418             LoadAndPrintString(IDS_USAGE_UNLOAD);
419             wprintf(L"fltmc.exe unload [name]\n\n");
420         }
421     }
422     else if (!_wcsicmp(argv[1], L"volumes"))
423     {
424         if (argc == 2)
425         {
426             ListVolumes();
427         }
428         else
429         {
430             LoadAndPrintString(IDS_USAGE_VOLUMES);
431             wprintf(L"fltmc.exe volumes\n\n");
432         }
433     }
434 
435     return 0;
436 }
437