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 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 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 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 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