xref: /reactos/dll/win32/fltlib/fltlib.c (revision 2196a06f)
1 /*
2 * PROJECT:         Filesystem Filter Manager library
3 * LICENSE:         GPL - See COPYING in the top level directory
4 * FILE:            dll/win32/fltlib/fltlib.c
5 * PURPOSE:
6 * PROGRAMMERS:     Ged Murphy (ged.murphy@reactos.org)
7 */
8 
9 #include <stdarg.h>
10 
11 #define WIN32_NO_STATUS
12 
13 #include <windef.h>
14 #include <winbase.h>
15 
16 #define NTOS_MODE_USER
17 #include <ndk/iofuncs.h>
18 #include <ndk/obfuncs.h>
19 #include <ndk/rtlfuncs.h>
20 #include <fltmgr_shared.h>
21 
22 /* DATA ****************************************************************************/
23 
24 static
25 HRESULT
26 FilterLoadUnload(_In_z_ LPCWSTR lpFilterName,
27                  _In_ BOOL Load);
28 
29 static
30 DWORD
31 SendIoctl(_In_ HANDLE Handle,
32           _In_ ULONG IoControlCode,
33           _In_reads_bytes_opt_(BufferSize) LPVOID lpInBuffer,
34           _In_ DWORD BufferSize);
35 
36 
37 /* PUBLIC FUNCTIONS ****************************************************************/
38 
39 _Must_inspect_result_
40 HRESULT
41 WINAPI
42 FilterLoad(_In_ LPCWSTR lpFilterName)
43 {
44     return FilterLoadUnload(lpFilterName, TRUE);
45 }
46 
47 _Must_inspect_result_
48 HRESULT
49 WINAPI
50 FilterUnload(_In_ LPCWSTR lpFilterName)
51 {
52     return FilterLoadUnload(lpFilterName, FALSE);
53 }
54 
55 
56 /* PRIVATE FUNCTIONS ****************************************************************/
57 
58 HRESULT
59 NtStatusToHResult(_In_ NTSTATUS Status)
60 {
61     HRESULT hr;
62     hr = RtlNtStatusToDosError(Status);
63     if (hr != ERROR_SUCCESS)
64     {
65         hr = (ULONG)hr | 0x80070000;
66     }
67     return hr;
68 }
69 
70 static
71 HRESULT
72 FilterLoadUnload(_In_z_ LPCWSTR lpFilterName,
73                  _In_ BOOL Load)
74 {
75     PFILTER_NAME FilterName;
76     HANDLE hFltMgr;
77     SIZE_T StringLength;
78     SIZE_T BufferLength;
79     DWORD dwError;
80 
81     /* Get a handle to the filter manager */
82     hFltMgr = CreateFileW(L"\\\\.\\fltmgr",
83                           GENERIC_WRITE,
84                           FILE_SHARE_WRITE,
85                           NULL,
86                           OPEN_EXISTING,
87                           FILE_ATTRIBUTE_NORMAL,
88                           &hFltMgr);
89     if (hFltMgr == INVALID_HANDLE_VALUE)
90     {
91         dwError = GetLastError();
92         return HRESULT_FROM_WIN32(dwError);
93     }
94 
95     /* Calc and allocate a buffer to hold our filter name */
96     StringLength = wcslen(lpFilterName) * sizeof(WCHAR);
97     BufferLength = StringLength + sizeof(FILTER_NAME);
98     FilterName = RtlAllocateHeap(GetProcessHeap(),
99                                  0,
100                                  BufferLength);
101     if (FilterName == NULL)
102     {
103         CloseHandle(hFltMgr);
104         return HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
105     }
106 
107     /* Build up the filter name */
108     FilterName->Length = StringLength;
109     CopyMemory(FilterName->FilterName, lpFilterName, StringLength);
110 
111     /* Tell the filter manager to load the filter for us */
112     dwError = SendIoctl(hFltMgr,
113                         Load ? IOCTL_FILTER_LOAD : IOCTL_FILTER_UNLOAD,
114                         FilterName,
115                         BufferLength);
116 
117     /* Cleanup and bail*/
118     RtlFreeHeap(GetProcessHeap(), 0, FilterName);
119     CloseHandle(hFltMgr);
120 
121     return HRESULT_FROM_WIN32(dwError);
122 }
123 
124 static
125 DWORD
126 SendIoctl(_In_ HANDLE Handle,
127           _In_ ULONG IoControlCode,
128           _In_reads_bytes_opt_(BufferSize) LPVOID lpInBuffer,
129           _In_ DWORD BufferSize)
130 {
131     IO_STATUS_BLOCK IoStatusBlock;
132     NTSTATUS Status;
133 
134     Status = NtDeviceIoControlFile(Handle,
135                                    NULL,
136                                    NULL,
137                                    NULL,
138                                    &IoStatusBlock,
139                                    IoControlCode,
140                                    lpInBuffer,
141                                    BufferSize,
142                                    NULL,
143                                    0);
144     if (Status == STATUS_PENDING)
145     {
146         Status = NtWaitForSingleObject(Handle, FALSE, NULL);
147         if (NT_SUCCESS(Status))
148         {
149             Status = IoStatusBlock.Status;
150         }
151     }
152 
153     return RtlNtStatusToDosError(Status);
154 }
155 
156 BOOL
157 WINAPI
158 DllMain(_In_ HINSTANCE hinstDLL,
159         _In_ DWORD dwReason,
160         _In_ LPVOID lpvReserved)
161 {
162     switch (dwReason)
163     {
164     case DLL_PROCESS_ATTACH:
165         DisableThreadLibraryCalls(hinstDLL);
166         break;
167     }
168 
169     return TRUE;
170 }