[FLTMC]
authorGed Murphy <gedmurphy@reactos.org>
Tue, 9 Aug 2016 21:33:53 +0000 (21:33 +0000)
committerGed Murphy <gedmurphy@reactos.org>
Tue, 9 Aug 2016 21:33:53 +0000 (21:33 +0000)
- Start to implement fltMC
- It currently supports loading, unloading and listing loaded filter driver.

svn path=/trunk/; revision=72174

reactos/base/applications/fltmc/CMakeLists.txt [new file with mode: 0644]
reactos/base/applications/fltmc/fltmc.cpp [new file with mode: 0644]
reactos/base/applications/fltmc/fltmc.rc [new file with mode: 0644]
reactos/base/applications/fltmc/lang/en-US.rc [new file with mode: 0644]
reactos/base/applications/fltmc/resource.h [new file with mode: 0644]

diff --git a/reactos/base/applications/fltmc/CMakeLists.txt b/reactos/base/applications/fltmc/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0ac7538
--- /dev/null
@@ -0,0 +1,9 @@
+
+set_cpp(WITH_RUNTIME WITH_EXCEPTIONS)
+
+include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/atl)
+
+add_executable(fltmc fltmc.cpp fltmc.rc)
+set_module_type(fltmc win32cui UNICODE)
+add_importlibs(fltmc fltlib msvcrt kernel32 advapi32)
+add_cd_file(TARGET fltmc DESTINATION reactos/system32 FOR all)
diff --git a/reactos/base/applications/fltmc/fltmc.cpp b/reactos/base/applications/fltmc/fltmc.cpp
new file mode 100644 (file)
index 0000000..f8f3cdf
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+* 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)
+*/
+
+//FIXME
+#define NTDDI_VERSION NTDDI_WIN7
+
+// 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 "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 Altitude[64] = { 0 };
+
+    if (IsNewStyle)
+    {
+        PFILTER_AGGREGATE_STANDARD_INFORMATION FilterAggInfo;
+        FilterAggInfo = (PFILTER_AGGREGATE_STANDARD_INFORMATION)Buffer;
+
+        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;
+        }
+
+        if (FilterAggInfo->Type.MiniFilter.FilterNameLength < 64)
+        {
+            CopyMemory(Altitude,
+                (PCHAR)FilterAggInfo + FilterAggInfo->Type.MiniFilter.FilterAltitudeBufferOffset,
+                       FilterAggInfo->Type.MiniFilter.FilterAltitudeLength);
+            FilterName[FilterAggInfo->Type.MiniFilter.FilterAltitudeLength] = UNICODE_NULL;
+        }
+
+        wprintf(L"%-38s %-10lu %-10s %-10lu\n",
+                FilterName,
+                FilterAggInfo->Type.MiniFilter.NumberOfInstances,
+                Altitude,
+                FilterAggInfo->Type.MiniFilter.FrameID);
+    }
+    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
+ListFilters()
+{
+    HANDLE FindHandle;
+    BYTE Buffer[1024];
+    ULONG BytesReturned;
+    BOOL IsNewStyle = TRUE;
+    HRESULT hr;
+
+    hr = FilterFindFirst(FilterAggregateStandardInformation,
+                         Buffer,
+                         1024,
+                         &BytesReturned,
+                         &FindHandle);
+    if (!SUCCEEDED(hr))
+    {
+        IsNewStyle = FALSE;
+        hr = FilterFindFirst(FilterFullInformation,
+                             Buffer,
+                             1024,
+                             &BytesReturned,
+                             &FindHandle);
+    }
+
+    if (SUCCEEDED(hr))
+    {
+        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,
+                                1024,
+                                &BytesReturned);
+            if (SUCCEEDED(hr))
+            {
+                PrintFilterInfo(Buffer, IsNewStyle);
+            }
+
+        } while (SUCCEEDED(hr));
+
+        FilterFindClose(FindHandle);
+    }
+
+    if (!SUCCEEDED(hr) && hr != HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
+    {
+        LoadAndPrintString(IDS_ERROR_PRIV, hr);
+        PrintErrorText(hr);
+    }
+}
+
+int wmain(int argc, WCHAR *argv[])
+{
+    if (argc < 2)
+    {
+        LoadAndPrintString(IDS_USAGE);
+        return 0;
+    }
+
+    wprintf(L"\n");
+
+    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"filters"))
+    {
+        if (argc == 2)
+        {
+            ListFilters();
+        }
+        else
+        {
+            LoadAndPrintString(IDS_USAGE_FILTERS);
+            wprintf(L"fltmc.exe filters\n\n");
+        }
+    }
+
+    return 0;
+}
diff --git a/reactos/base/applications/fltmc/fltmc.rc b/reactos/base/applications/fltmc/fltmc.rc
new file mode 100644 (file)
index 0000000..984e648
--- /dev/null
@@ -0,0 +1,60 @@
+#include <windef.h>
+
+#include "resource.h"
+
+#define REACTOS_STR_FILE_DESCRIPTION   "ReactOS Filter Manager Control Program"
+#define REACTOS_STR_INTERNAL_NAME      "fltmc"
+#define REACTOS_STR_ORIGINAL_FILENAME  "fltmc.exe"
+//#include <reactos/version.rc>
+
+/* UTF-8 */
+#pragma code_page(65001)
+
+//#ifdef LANGUAGE_BG_BG
+//    #include "lang/bg-BG.rc"
+//#endif
+//#ifdef LANGUAGE_CS_CZ
+//    #include "lang/cs-CZ.rc"
+//#endif
+//#ifdef LANGUAGE_DE_DE
+//    #include "lang/de-DE.rc"
+//#endif
+//#ifdef LANGUAGE_EN_US
+    #include "lang/en-US.rc"
+//#endif
+//#ifdef LANGUAGE_ES_ES
+//    #include "lang/es-ES.rc"
+//#endif
+//#ifdef LANGUAGE_FR_FR
+//    #include "lang/fr-FR.rc"
+//#endif
+//#ifdef LANGUAGE_IT_IT
+//    #include "lang/it-IT.rc"
+//#endif
+//#ifdef LANGUAGE_PL_PL
+//    #include "lang/pl-PL.rc"
+//#endif
+//#ifdef LANGUAGE_RO_RO
+//    #include "lang/ro-RO.rc"
+//#endif
+//#ifdef LANGUAGE_RU_RU
+//    #include "lang/ru-RU.rc"
+//#endif
+//#ifdef LANGUAGE_SV_SE
+//    #include "lang/sv-SE.rc"
+//#endif
+//#ifdef LANGUAGE_SQ_AL
+//    #include "lang/sq-AL.rc"
+//#endif
+//#ifdef LANGUAGE_TR_TR
+//    #include "lang/tr-TR.rc"
+//#endif
+//#ifdef LANGUAGE_UK_UA
+//    #include "lang/uk-UA.rc"
+//#endif
+//#ifdef LANGUAGE_ZH_CN
+//    #include "lang/zh-CN.rc"
+//#endif
+//#ifdef LANGUAGE_ZH_TW
+//    #include "lang/zh-TW.rc"
+//#endif
\ No newline at end of file
diff --git a/reactos/base/applications/fltmc/lang/en-US.rc b/reactos/base/applications/fltmc/lang/en-US.rc
new file mode 100644 (file)
index 0000000..8b22f2f
--- /dev/null
@@ -0,0 +1,27 @@
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+STRINGTABLE
+BEGIN
+    IDS_USAGE "\nValid commands :\n\
+               load        Loads a Filter driver\n\
+               unload      Unloads a Filter driver\n\
+               filters     Lists the Filters currently registered in the system\n\n\0"
+
+    IDS_USAGE_LOAD      "Loads a filter driver\n\0"
+    IDS_USAGE_UNLOAD    "Unloads a filter driver\n\0"
+    IDS_USAGE_FILTERS   "Lists all registered filters\n\0"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_DISPLAY_FILTERS1    "Filter Name                     Num Instances    Altitude    Frame\n\0"
+    IDS_DISPLAY_FILTERS2    "Filter Name                     Num Instances   Frame\n\0"
+END
+
+STRINGTABLE
+BEGIN
+    IDS_ERROR_PRIV      "Failed to set the driver load privilige (0x%X)\n\0"
+    IDS_ERROR_FILTERS   "Failed to list the filters (0x%X)\n\0"
+    IDS_ERROR_LOAD      "Failed to load the filter (0x%X)\n\0"
+    IDS_ERROR_UNLOAD    "Failed to unload the filter (0x%X)\n\0"
+END
diff --git a/reactos/base/applications/fltmc/resource.h b/reactos/base/applications/fltmc/resource.h
new file mode 100644 (file)
index 0000000..366b6bd
--- /dev/null
@@ -0,0 +1,14 @@
+#pragma once
+
+#define IDS_USAGE                   0
+#define IDS_USAGE_LOAD              1
+#define IDS_USAGE_UNLOAD            2
+#define IDS_USAGE_FILTERS           3
+
+#define IDS_DISPLAY_FILTERS1        10
+#define IDS_DISPLAY_FILTERS2        11
+
+#define IDS_ERROR_PRIV              20
+#define IDS_ERROR_FILTERS           21
+#define IDS_ERROR_LOAD              22
+#define IDS_ERROR_UNLOAD            23