mirror of
https://github.com/reactos/reactos.git
synced 2024-08-25 12:48:53 +00:00
437 lines
11 KiB
C++
437 lines
11 KiB
C++
/*
|
|
* PROJECT: ReactOS fltmc utility
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: base/applications/fltmc/fltmc.c
|
|
* PURPOSE: Control utility for file system filter drivers
|
|
* PROGRAMMERS: Copyright 2016 Ged Murphy (gedmurphy@gmail.com)
|
|
*/
|
|
|
|
// Please leave this temporary hack in place
|
|
// it's used to keep VS2015 happy for development.
|
|
#ifdef __REACTOS__
|
|
#include <stdarg.h>
|
|
#include <windef.h>
|
|
#include <winbase.h>
|
|
#include <wchar.h>
|
|
#else
|
|
#include <Windows.h>
|
|
#endif
|
|
#include <fltuser.h>
|
|
#include <atlstr.h>
|
|
#include <strsafe.h>
|
|
#include "resource.h"
|
|
|
|
EXTERN_C int wmain(int argc, WCHAR *argv[]);
|
|
|
|
void
|
|
LoadAndPrintString(ULONG MessageId, ...)
|
|
{
|
|
va_list args;
|
|
|
|
CAtlStringW Message;
|
|
if (Message.LoadStringW(MessageId))
|
|
{
|
|
va_start(args, MessageId);
|
|
vwprintf(Message.GetBuffer(), args);
|
|
va_end(args);
|
|
}
|
|
}
|
|
|
|
void
|
|
PrintErrorText(_In_ ULONG ErrorCode)
|
|
{
|
|
WCHAR Buffer[256];
|
|
if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
|
|
0,
|
|
ErrorCode,
|
|
0,
|
|
Buffer,
|
|
256,
|
|
0))
|
|
{
|
|
wprintf(L"%s\n", Buffer);
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
SetDriverLoadPrivilege()
|
|
{
|
|
TOKEN_PRIVILEGES TokenPrivileges;
|
|
HANDLE hToken;
|
|
LUID luid;
|
|
BOOL bSuccess;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
bSuccess = OpenProcessToken(GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES,
|
|
&hToken);
|
|
if (bSuccess == FALSE)
|
|
return GetLastError();
|
|
|
|
if (!LookupPrivilegeValueW(NULL, SE_LOAD_DRIVER_NAME, &luid))
|
|
return GetLastError();
|
|
|
|
TokenPrivileges.PrivilegeCount = 1;
|
|
TokenPrivileges.Privileges[0].Luid = luid;
|
|
TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
|
|
bSuccess = AdjustTokenPrivileges(hToken,
|
|
FALSE,
|
|
&TokenPrivileges,
|
|
sizeof(TOKEN_PRIVILEGES),
|
|
NULL,
|
|
NULL);
|
|
if (bSuccess == FALSE)
|
|
dwError = GetLastError();
|
|
|
|
CloseHandle(hToken);
|
|
|
|
return dwError;
|
|
}
|
|
|
|
void
|
|
LoadFilter(_In_ LPWSTR FilterName)
|
|
{
|
|
DWORD dwError;
|
|
dwError = SetDriverLoadPrivilege();
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
LoadAndPrintString(IDS_ERROR_PRIV, HRESULT_FROM_WIN32(dwError));
|
|
return;
|
|
}
|
|
|
|
HRESULT hr = FilterLoad(FilterName);
|
|
if (hr != S_OK)
|
|
{
|
|
LoadAndPrintString(IDS_ERROR_LOAD, hr);
|
|
PrintErrorText(hr);
|
|
}
|
|
}
|
|
|
|
void
|
|
UnloadFilter(_In_ LPWSTR FilterName)
|
|
{
|
|
DWORD dwError;
|
|
dwError = SetDriverLoadPrivilege();
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
LoadAndPrintString(IDS_ERROR_PRIV, HRESULT_FROM_WIN32(dwError));
|
|
return;
|
|
}
|
|
|
|
HRESULT hr = FilterUnload(FilterName);
|
|
if (hr != S_OK)
|
|
{
|
|
LoadAndPrintString(IDS_ERROR_UNLOAD, hr);
|
|
PrintErrorText(hr);
|
|
}
|
|
}
|
|
|
|
void
|
|
PrintFilterInfo(_In_ PVOID Buffer,
|
|
_In_ BOOL IsNewStyle)
|
|
{
|
|
WCHAR FilterName[128] = { 0 };
|
|
WCHAR NumOfInstances[16] = { 0 };
|
|
WCHAR Altitude[64] = { 0 };
|
|
WCHAR Frame[16] = { 0 };
|
|
|
|
if (IsNewStyle)
|
|
{
|
|
PFILTER_AGGREGATE_STANDARD_INFORMATION FilterAggInfo;
|
|
FilterAggInfo = (PFILTER_AGGREGATE_STANDARD_INFORMATION)Buffer;
|
|
|
|
if (FilterAggInfo->Flags & FLTFL_ASI_IS_MINIFILTER)
|
|
{
|
|
if (FilterAggInfo->Type.MiniFilter.FilterNameLength < 128)
|
|
{
|
|
CopyMemory(FilterName,
|
|
(PCHAR)FilterAggInfo + FilterAggInfo->Type.MiniFilter.FilterNameBufferOffset,
|
|
FilterAggInfo->Type.MiniFilter.FilterNameLength);
|
|
FilterName[FilterAggInfo->Type.MiniFilter.FilterNameLength] = UNICODE_NULL;
|
|
}
|
|
|
|
StringCchPrintfW(NumOfInstances, 16, L"%lu", FilterAggInfo->Type.MiniFilter.NumberOfInstances);
|
|
|
|
if (FilterAggInfo->Type.MiniFilter.FilterAltitudeLength < 64)
|
|
{
|
|
CopyMemory(Altitude,
|
|
(PCHAR)FilterAggInfo + FilterAggInfo->Type.MiniFilter.FilterAltitudeBufferOffset,
|
|
FilterAggInfo->Type.MiniFilter.FilterAltitudeLength);
|
|
FilterName[FilterAggInfo->Type.MiniFilter.FilterAltitudeLength] = UNICODE_NULL;
|
|
}
|
|
|
|
StringCchPrintfW(Frame, 16, L"%lu", FilterAggInfo->Type.MiniFilter.FrameID);
|
|
}
|
|
else if (FilterAggInfo->Flags & FLTFL_ASI_IS_LEGACYFILTER)
|
|
{
|
|
if (FilterAggInfo->Type.LegacyFilter.FilterNameLength < 128)
|
|
{
|
|
CopyMemory(FilterName,
|
|
(PCHAR)FilterAggInfo + FilterAggInfo->Type.LegacyFilter.FilterNameBufferOffset,
|
|
FilterAggInfo->Type.LegacyFilter.FilterNameLength);
|
|
FilterName[FilterAggInfo->Type.LegacyFilter.FilterNameLength] = UNICODE_NULL;
|
|
}
|
|
|
|
StringCchCopyW(Frame, 16, L"<Legacy>"); //Fixme: is this localized?
|
|
}
|
|
|
|
wprintf(L"%-38s %-10s %-10s %3s\n",
|
|
FilterName,
|
|
NumOfInstances,
|
|
Altitude,
|
|
Frame);
|
|
}
|
|
else
|
|
{
|
|
PFILTER_FULL_INFORMATION FilterInfo;
|
|
FilterInfo = (PFILTER_FULL_INFORMATION)Buffer;
|
|
|
|
if (FilterInfo->FilterNameLength < 128)
|
|
{
|
|
CopyMemory(FilterName,
|
|
FilterInfo->FilterNameBuffer,
|
|
FilterInfo->FilterNameLength);
|
|
FilterName[FilterInfo->FilterNameLength] = UNICODE_NULL;
|
|
}
|
|
|
|
wprintf(L"%-38s %-10lu %-10lu\n",
|
|
FilterName,
|
|
FilterInfo->NumberOfInstances,
|
|
FilterInfo->FrameID);
|
|
}
|
|
}
|
|
|
|
void
|
|
PrintVolumeInfo(_In_ PVOID Buffer)
|
|
{
|
|
PFILTER_VOLUME_STANDARD_INFORMATION FilterVolInfo;
|
|
WCHAR DosName[16] = { 0 };
|
|
WCHAR VolName[128] = { 0 };
|
|
WCHAR FileSystem[32] = { 0 };
|
|
|
|
FilterVolInfo = (PFILTER_VOLUME_STANDARD_INFORMATION)Buffer;
|
|
|
|
if (FilterVolInfo->FilterVolumeNameLength < 128)
|
|
{
|
|
CopyMemory(VolName,
|
|
(PCHAR)FilterVolInfo->FilterVolumeName,
|
|
FilterVolInfo->FilterVolumeNameLength);
|
|
VolName[FilterVolInfo->FilterVolumeNameLength] = UNICODE_NULL;
|
|
}
|
|
|
|
if (!SUCCEEDED(FilterGetDosName(VolName, DosName, _countof(DosName))))
|
|
DosName[0] = L'\0';
|
|
|
|
switch (FilterVolInfo->FileSystemType)
|
|
{
|
|
case FLT_FSTYPE_MUP:
|
|
StringCchCopyW(FileSystem, 32, L"Remote");
|
|
break;
|
|
|
|
case FLT_FSTYPE_NTFS:
|
|
StringCchCopyW(FileSystem, 32, L"NTFS");
|
|
break;
|
|
|
|
case FLT_FSTYPE_FAT:
|
|
StringCchCopyW(FileSystem, 32, L"FAT");
|
|
break;
|
|
|
|
case FLT_FSTYPE_EXFAT:
|
|
StringCchCopyW(FileSystem, 32, L"exFAT");
|
|
break;
|
|
|
|
case FLT_FSTYPE_NPFS:
|
|
StringCchCopyW(FileSystem, 32, L"NamedPipe");
|
|
break;
|
|
|
|
case FLT_FSTYPE_MSFS:
|
|
StringCchCopyW(FileSystem, 32, L"Mailslot");
|
|
break;
|
|
|
|
case FLT_FSTYPE_UNKNOWN:
|
|
default:
|
|
StringCchCopyW(FileSystem, 32, L"<Unknown>");
|
|
break;
|
|
}
|
|
|
|
wprintf(L"%-31s %-40s %-10s\n",
|
|
DosName,
|
|
VolName,
|
|
FileSystem);
|
|
}
|
|
|
|
void
|
|
ListFilters()
|
|
{
|
|
HANDLE FindHandle;
|
|
BYTE Buffer[1024];
|
|
ULONG BytesReturned;
|
|
BOOL IsNewStyle = TRUE;
|
|
HRESULT hr;
|
|
|
|
hr = FilterFindFirst(FilterAggregateStandardInformation,
|
|
Buffer,
|
|
sizeof(Buffer),
|
|
&BytesReturned,
|
|
&FindHandle);
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
IsNewStyle = FALSE;
|
|
hr = FilterFindFirst(FilterFullInformation,
|
|
Buffer,
|
|
sizeof(Buffer),
|
|
&BytesReturned,
|
|
&FindHandle);
|
|
}
|
|
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
LoadAndPrintString(IDS_ERROR_FILTERS, hr);
|
|
PrintErrorText(hr);
|
|
return;
|
|
}
|
|
|
|
if (IsNewStyle)
|
|
{
|
|
LoadAndPrintString(IDS_DISPLAY_FILTERS1);
|
|
wprintf(L"------------------------------ ------------- ------------ -----\n");
|
|
}
|
|
else
|
|
{
|
|
LoadAndPrintString(IDS_DISPLAY_FILTERS2);
|
|
wprintf(L"------------------------------ ------------- -----\n");
|
|
}
|
|
|
|
PrintFilterInfo(Buffer, IsNewStyle);
|
|
|
|
do
|
|
{
|
|
hr = FilterFindNext(FindHandle,
|
|
IsNewStyle ? FilterAggregateStandardInformation : FilterFullInformation,
|
|
Buffer,
|
|
sizeof(Buffer),
|
|
&BytesReturned);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PrintFilterInfo(Buffer, IsNewStyle);
|
|
}
|
|
else if (hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
|
|
{
|
|
LoadAndPrintString(IDS_ERROR_FILTERS, hr);
|
|
PrintErrorText(hr);
|
|
}
|
|
} while (SUCCEEDED(hr));
|
|
|
|
hr = FilterFindClose(FindHandle);
|
|
if (!SUCCEEDED(hr))
|
|
{
|
|
LoadAndPrintString(IDS_ERROR_FILTERS, hr);
|
|
PrintErrorText(hr);
|
|
}
|
|
}
|
|
|
|
void
|
|
ListVolumes()
|
|
{
|
|
HANDLE FindHandle;
|
|
BYTE Buffer[1024];
|
|
ULONG BytesReturned;
|
|
HRESULT hr;
|
|
|
|
hr = FilterVolumeFindFirst(FilterVolumeStandardInformation,
|
|
Buffer,
|
|
1024,
|
|
&BytesReturned,
|
|
&FindHandle);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LoadAndPrintString(IDS_DISPLAY_VOLUMES);
|
|
wprintf(L"------------------------------ --------------------------------------- ---------- --------\n");
|
|
|
|
PrintVolumeInfo(Buffer);
|
|
|
|
do
|
|
{
|
|
hr = FilterVolumeFindNext(FindHandle,
|
|
FilterVolumeStandardInformation,
|
|
Buffer,
|
|
1024,
|
|
&BytesReturned);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PrintVolumeInfo(Buffer);
|
|
}
|
|
|
|
} while (SUCCEEDED(hr));
|
|
|
|
FilterVolumeFindClose(FindHandle);
|
|
}
|
|
|
|
if (!SUCCEEDED(hr) && hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
|
|
{
|
|
LoadAndPrintString(IDS_ERROR_VOLUMES, hr);
|
|
PrintErrorText(hr);
|
|
}
|
|
}
|
|
|
|
int wmain(int argc, WCHAR *argv[])
|
|
{
|
|
wprintf(L"\n");
|
|
|
|
if ((argc < 2) || (!_wcsicmp(argv[1], L"filters")))
|
|
{
|
|
if (argc < 3)
|
|
{
|
|
ListFilters();
|
|
}
|
|
else
|
|
{
|
|
LoadAndPrintString(IDS_USAGE_FILTERS);
|
|
wprintf(L"fltmc.exe filters\n\n");
|
|
}
|
|
}
|
|
else if (!_wcsicmp(argv[1], L"help"))
|
|
{
|
|
LoadAndPrintString(IDS_USAGE);
|
|
}
|
|
else if (!_wcsicmp(argv[1], L"load"))
|
|
{
|
|
if (argc == 3)
|
|
{
|
|
LoadFilter(argv[2]);
|
|
}
|
|
else
|
|
{
|
|
LoadAndPrintString(IDS_USAGE_LOAD);
|
|
wprintf(L"fltmc.exe load [name]\n\n");
|
|
}
|
|
}
|
|
else if (!_wcsicmp(argv[1], L"unload"))
|
|
{
|
|
if (argc == 3)
|
|
{
|
|
UnloadFilter(argv[2]);
|
|
}
|
|
else
|
|
{
|
|
LoadAndPrintString(IDS_USAGE_UNLOAD);
|
|
wprintf(L"fltmc.exe unload [name]\n\n");
|
|
}
|
|
}
|
|
else if (!_wcsicmp(argv[1], L"volumes"))
|
|
{
|
|
if (argc == 2)
|
|
{
|
|
ListVolumes();
|
|
}
|
|
else
|
|
{
|
|
LoadAndPrintString(IDS_USAGE_VOLUMES);
|
|
wprintf(L"fltmc.exe volumes\n\n");
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|