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