├── license.txt ├── readme.md └── src ├── FSFilter ├── AttachDetach.c ├── FastIo.c ├── FsFilter.h ├── FsFilter.inf ├── FsFilter.rc ├── FsFilter.vcproj ├── FsFilter.vcxproj ├── FsFilter.vcxproj.filters ├── IrpDispatch.c ├── Main.c └── Notification.c ├── FsFilter.sln └── install.cmd /license.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2017 Apriorit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apriorit/file-system-filter/fd7386baed15744c9240f9935d4e6f0a1f816ab1/readme.md -------------------------------------------------------------------------------- /src/FSFilter/AttachDetach.c: -------------------------------------------------------------------------------- 1 | #include "FsFilter.h" 2 | 3 | /////////////////////////////////////////////////////////////////////////////////////////////////// 4 | // This will attach to a DeviceObject that represents a mounted volume 5 | 6 | NTSTATUS FsFilterAttachToDevice( 7 | __in PDEVICE_OBJECT DeviceObject, 8 | __out_opt PDEVICE_OBJECT* pFilterDeviceObject 9 | ) 10 | { 11 | NTSTATUS status = STATUS_SUCCESS; 12 | PDEVICE_OBJECT filterDeviceObject = NULL; 13 | PFSFILTER_DEVICE_EXTENSION pDevExt = NULL; 14 | ULONG i = 0; 15 | 16 | ASSERT(!FsFilterIsAttachedToDevice(DeviceObject)); 17 | 18 | // 19 | // Create a new device object we can attach with. 20 | // 21 | 22 | status = IoCreateDevice( 23 | g_fsFilterDriverObject, 24 | sizeof(FSFILTER_DEVICE_EXTENSION), 25 | NULL, 26 | DeviceObject->DeviceType, 27 | 0, 28 | FALSE, 29 | &filterDeviceObject); 30 | 31 | if (!NT_SUCCESS(status)) 32 | { 33 | return status; 34 | } 35 | 36 | pDevExt = (PFSFILTER_DEVICE_EXTENSION)filterDeviceObject->DeviceExtension; 37 | 38 | // 39 | // Propagate flags from Device Object we are trying to attach to. 40 | // 41 | 42 | if (FlagOn(DeviceObject->Flags, DO_BUFFERED_IO)) 43 | { 44 | SetFlag(filterDeviceObject->Flags, DO_BUFFERED_IO); 45 | } 46 | 47 | if (FlagOn(DeviceObject->Flags, DO_DIRECT_IO)) 48 | { 49 | SetFlag(filterDeviceObject->Flags, DO_DIRECT_IO); 50 | } 51 | 52 | if (FlagOn(DeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN)) 53 | { 54 | SetFlag(filterDeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN); 55 | } 56 | 57 | // 58 | // Do the attachment. 59 | // 60 | // It is possible for this attachment request to fail because this device 61 | // object has not finished initializing. This can occur if this filter 62 | // loaded just as this volume was being mounted. 63 | // 64 | 65 | for (i = 0; i < 8; ++i) 66 | { 67 | LARGE_INTEGER interval; 68 | 69 | status = IoAttachDeviceToDeviceStackSafe( 70 | filterDeviceObject, 71 | DeviceObject, 72 | &pDevExt->AttachedToDeviceObject); 73 | 74 | if (NT_SUCCESS(status)) 75 | { 76 | break; 77 | } 78 | 79 | // 80 | // Delay, giving the device object a chance to finish its 81 | // initialization so we can try again. 82 | // 83 | 84 | interval.QuadPart = (500 * DELAY_ONE_MILLISECOND); 85 | KeDelayExecutionThread(KernelMode, FALSE, &interval); 86 | } 87 | 88 | if (!NT_SUCCESS(status)) 89 | { 90 | // 91 | // Clean up. 92 | // 93 | 94 | IoDeleteDevice(filterDeviceObject); 95 | filterDeviceObject = NULL; 96 | } 97 | else 98 | { 99 | // 100 | // Mark we are done initializing. 101 | // 102 | 103 | ClearFlag(filterDeviceObject->Flags, DO_DEVICE_INITIALIZING); 104 | 105 | if (NULL != pFilterDeviceObject) 106 | { 107 | *pFilterDeviceObject = filterDeviceObject; 108 | } 109 | } 110 | 111 | return status; 112 | } 113 | 114 | void FsFilterDetachFromDevice( 115 | __in PDEVICE_OBJECT DeviceObject 116 | ) 117 | { 118 | PFSFILTER_DEVICE_EXTENSION pDevExt = (PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 119 | 120 | IoDetachDevice(pDevExt->AttachedToDeviceObject); 121 | IoDeleteDevice(DeviceObject); 122 | } 123 | 124 | /////////////////////////////////////////////////////////////////////////////////////////////////// 125 | // This determines whether we are attached to the given device 126 | 127 | BOOLEAN FsFilterIsAttachedToDevice( 128 | __in PDEVICE_OBJECT DeviceObject 129 | ) 130 | { 131 | PDEVICE_OBJECT nextDevObj = NULL; 132 | PDEVICE_OBJECT currentDevObj = IoGetAttachedDeviceReference(DeviceObject); 133 | 134 | // 135 | // Scan down the list to find our device object. 136 | // 137 | 138 | do 139 | { 140 | if (FsFilterIsMyDeviceObject(currentDevObj)) 141 | { 142 | ObDereferenceObject(currentDevObj); 143 | return TRUE; 144 | } 145 | 146 | // 147 | // Get the next attached object. 148 | // 149 | 150 | nextDevObj = IoGetLowerDeviceObject(currentDevObj); 151 | 152 | // 153 | // Dereference our current device object, before moving to the next one. 154 | // 155 | 156 | ObDereferenceObject(currentDevObj); 157 | currentDevObj = nextDevObj; 158 | } while (NULL != currentDevObj); 159 | 160 | return FALSE; 161 | } 162 | -------------------------------------------------------------------------------- /src/FSFilter/FastIo.c: -------------------------------------------------------------------------------- 1 | #include "FsFilter.h" 2 | 3 | ///////////////////////////////////////////////////////////////////////////// 4 | // Fast-IO Handlers 5 | 6 | BOOLEAN FsFilterFastIoCheckIfPossible( 7 | __in PFILE_OBJECT FileObject, 8 | __in PLARGE_INTEGER FileOffset, 9 | __in ULONG Length, 10 | __in BOOLEAN Wait, 11 | __in ULONG LockKey, 12 | __in BOOLEAN CheckForReadOperation, 13 | __out PIO_STATUS_BLOCK IoStatus, 14 | __in PDEVICE_OBJECT DeviceObject 15 | ) 16 | { 17 | // 18 | // Pass through logic for this type of Fast I/O 19 | // 20 | 21 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 22 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 23 | 24 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoCheckIfPossible)) 25 | { 26 | return (fastIoDispatch->FastIoCheckIfPossible)( 27 | FileObject, 28 | FileOffset, 29 | Length, 30 | Wait, 31 | LockKey, 32 | CheckForReadOperation, 33 | IoStatus, 34 | nextDeviceObject); 35 | } 36 | 37 | return FALSE; 38 | } 39 | 40 | BOOLEAN FsFilterFastIoRead( 41 | __in PFILE_OBJECT FileObject, 42 | __in PLARGE_INTEGER FileOffset, 43 | __in ULONG Length, 44 | __in BOOLEAN Wait, 45 | __in ULONG LockKey, 46 | __out PVOID Buffer, 47 | __out PIO_STATUS_BLOCK IoStatus, 48 | __in PDEVICE_OBJECT DeviceObject 49 | ) 50 | { 51 | // 52 | // Pass through logic for this type of Fast I/O 53 | // 54 | 55 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 56 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 57 | 58 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoRead)) 59 | { 60 | return (fastIoDispatch->FastIoRead)( 61 | FileObject, 62 | FileOffset, 63 | Length, 64 | Wait, 65 | LockKey, 66 | Buffer, 67 | IoStatus, 68 | nextDeviceObject); 69 | } 70 | 71 | return FALSE; 72 | } 73 | 74 | BOOLEAN FsFilterFastIoWrite( 75 | __in PFILE_OBJECT FileObject, 76 | __in PLARGE_INTEGER FileOffset, 77 | __in ULONG Length, 78 | __in BOOLEAN Wait, 79 | __in ULONG LockKey, 80 | __in PVOID Buffer, 81 | __out PIO_STATUS_BLOCK IoStatus, 82 | __in PDEVICE_OBJECT DeviceObject 83 | ) 84 | { 85 | // 86 | // Pass through logic for this type of Fast I/O 87 | // 88 | 89 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 90 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 91 | 92 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoWrite)) 93 | { 94 | return (fastIoDispatch->FastIoWrite)( 95 | FileObject, 96 | FileOffset, 97 | Length, 98 | Wait, 99 | LockKey, 100 | Buffer, 101 | IoStatus, 102 | nextDeviceObject); 103 | } 104 | 105 | return FALSE; 106 | } 107 | 108 | BOOLEAN FsFilterFastIoQueryBasicInfo( 109 | __in PFILE_OBJECT FileObject, 110 | __in BOOLEAN Wait, 111 | __out PFILE_BASIC_INFORMATION Buffer, 112 | __out PIO_STATUS_BLOCK IoStatus, 113 | __in PDEVICE_OBJECT DeviceObject 114 | ) 115 | { 116 | // 117 | // Pass through logic for this type of Fast I/O 118 | // 119 | 120 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 121 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 122 | 123 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoQueryBasicInfo)) 124 | { 125 | 126 | return (fastIoDispatch->FastIoQueryBasicInfo)( 127 | FileObject, 128 | Wait, 129 | Buffer, 130 | IoStatus, 131 | nextDeviceObject); 132 | } 133 | 134 | return FALSE; 135 | } 136 | 137 | BOOLEAN FsFilterFastIoQueryStandardInfo( 138 | __in PFILE_OBJECT FileObject, 139 | __in BOOLEAN Wait, 140 | __out PFILE_STANDARD_INFORMATION Buffer, 141 | __out PIO_STATUS_BLOCK IoStatus, 142 | __in PDEVICE_OBJECT DeviceObject 143 | ) 144 | { 145 | // 146 | // Pass through logic for this type of Fast I/O 147 | // 148 | 149 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 150 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 151 | 152 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoQueryStandardInfo)) 153 | { 154 | return (fastIoDispatch->FastIoQueryStandardInfo)( 155 | FileObject, 156 | Wait, 157 | Buffer, 158 | IoStatus, 159 | nextDeviceObject); 160 | } 161 | 162 | return FALSE; 163 | } 164 | 165 | BOOLEAN FsFilterFastIoLock( 166 | __in PFILE_OBJECT FileObject, 167 | __in PLARGE_INTEGER FileOffset, 168 | __in PLARGE_INTEGER Length, 169 | __in PEPROCESS ProcessId, 170 | __in ULONG Key, 171 | __in BOOLEAN FailImmediately, 172 | __in BOOLEAN ExclusiveLock, 173 | __out PIO_STATUS_BLOCK IoStatus, 174 | __in PDEVICE_OBJECT DeviceObject 175 | ) 176 | { 177 | // 178 | // Pass through logic for this type of Fast I/O 179 | // 180 | 181 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 182 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 183 | 184 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoLock)) 185 | { 186 | return (fastIoDispatch->FastIoLock)( 187 | FileObject, 188 | FileOffset, 189 | Length, 190 | ProcessId, 191 | Key, 192 | FailImmediately, 193 | ExclusiveLock, 194 | IoStatus, 195 | nextDeviceObject); 196 | } 197 | 198 | return FALSE; 199 | } 200 | 201 | BOOLEAN FsFilterFastIoUnlockSingle( 202 | __in PFILE_OBJECT FileObject, 203 | __in PLARGE_INTEGER FileOffset, 204 | __in PLARGE_INTEGER Length, 205 | __in PEPROCESS ProcessId, 206 | __in ULONG Key, 207 | __out PIO_STATUS_BLOCK IoStatus, 208 | __in PDEVICE_OBJECT DeviceObject 209 | ) 210 | { 211 | // 212 | // Pass through logic for this type of Fast I/O 213 | // 214 | 215 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 216 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 217 | 218 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoUnlockSingle)) 219 | { 220 | return (fastIoDispatch->FastIoUnlockSingle)( 221 | FileObject, 222 | FileOffset, 223 | Length, 224 | ProcessId, 225 | Key, 226 | IoStatus, 227 | nextDeviceObject); 228 | } 229 | 230 | return FALSE; 231 | } 232 | 233 | BOOLEAN FsFilterFastIoUnlockAll( 234 | __in PFILE_OBJECT FileObject, 235 | __in PEPROCESS ProcessId, 236 | __out PIO_STATUS_BLOCK IoStatus, 237 | __in PDEVICE_OBJECT DeviceObject 238 | ) 239 | { 240 | // 241 | // Pass through logic for this type of Fast I/O 242 | // 243 | 244 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 245 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 246 | 247 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoUnlockAll)) 248 | { 249 | return (fastIoDispatch->FastIoUnlockAll)( 250 | FileObject, 251 | ProcessId, 252 | IoStatus, 253 | nextDeviceObject); 254 | } 255 | 256 | return FALSE; 257 | } 258 | 259 | BOOLEAN FsFilterFastIoUnlockAllByKey( 260 | __in PFILE_OBJECT FileObject, 261 | __in PVOID ProcessId, 262 | __in ULONG Key, 263 | __out PIO_STATUS_BLOCK IoStatus, 264 | __in PDEVICE_OBJECT DeviceObject 265 | ) 266 | { 267 | // 268 | // Pass through logic for this type of Fast I/O 269 | // 270 | 271 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 272 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 273 | 274 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoUnlockAllByKey)) 275 | { 276 | return (fastIoDispatch->FastIoUnlockAllByKey)( 277 | FileObject, 278 | ProcessId, 279 | Key, 280 | IoStatus, 281 | nextDeviceObject); 282 | } 283 | 284 | return FALSE; 285 | } 286 | 287 | BOOLEAN FsFilterFastIoDeviceControl( 288 | __in PFILE_OBJECT FileObject, 289 | __in BOOLEAN Wait, 290 | __in_opt PVOID InputBuffer, 291 | __in ULONG InputBufferLength, 292 | __out_opt PVOID OutputBuffer, 293 | __in ULONG OutputBufferLength, 294 | __in ULONG IoControlCode, 295 | __out PIO_STATUS_BLOCK IoStatus, 296 | __in PDEVICE_OBJECT DeviceObject 297 | ) 298 | { 299 | // 300 | // Pass through logic for this type of Fast I/O 301 | // 302 | 303 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 304 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 305 | 306 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoDeviceControl)) 307 | { 308 | return (fastIoDispatch->FastIoDeviceControl)( 309 | FileObject, 310 | Wait, 311 | InputBuffer, 312 | InputBufferLength, 313 | OutputBuffer, 314 | OutputBufferLength, 315 | IoControlCode, 316 | IoStatus, 317 | nextDeviceObject); 318 | } 319 | 320 | return FALSE; 321 | } 322 | 323 | VOID FsFilterFastIoDetachDevice( 324 | __in PDEVICE_OBJECT SourceDevice, 325 | __in PDEVICE_OBJECT TargetDevice 326 | ) 327 | { 328 | // 329 | // Detach from the file system's volume device object. 330 | // 331 | 332 | IoDetachDevice(TargetDevice); 333 | IoDeleteDevice(SourceDevice); 334 | } 335 | 336 | BOOLEAN FsFilterFastIoQueryNetworkOpenInfo( 337 | __in PFILE_OBJECT FileObject, 338 | __in BOOLEAN Wait, 339 | __out PFILE_NETWORK_OPEN_INFORMATION Buffer, 340 | __out PIO_STATUS_BLOCK IoStatus, 341 | __in PDEVICE_OBJECT DeviceObject 342 | ) 343 | { 344 | // 345 | // Pass through logic for this type of Fast I/O 346 | // 347 | 348 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 349 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 350 | 351 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoQueryNetworkOpenInfo)) 352 | { 353 | return (fastIoDispatch->FastIoQueryNetworkOpenInfo)( 354 | FileObject, 355 | Wait, 356 | Buffer, 357 | IoStatus, 358 | nextDeviceObject); 359 | } 360 | 361 | return FALSE; 362 | } 363 | 364 | BOOLEAN FsFilterFastIoMdlRead( 365 | __in PFILE_OBJECT FileObject, 366 | __in PLARGE_INTEGER FileOffset, 367 | __in ULONG Length, 368 | __in ULONG LockKey, 369 | __out PMDL* MdlChain, 370 | __out PIO_STATUS_BLOCK IoStatus, 371 | __in PDEVICE_OBJECT DeviceObject 372 | ) 373 | { 374 | // 375 | // Pass through logic for this type of Fast I/O 376 | // 377 | 378 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 379 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 380 | 381 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlRead)) 382 | { 383 | return (fastIoDispatch->MdlRead)( 384 | FileObject, 385 | FileOffset, 386 | Length, 387 | LockKey, 388 | MdlChain, 389 | IoStatus, 390 | nextDeviceObject); 391 | } 392 | 393 | return FALSE; 394 | } 395 | 396 | BOOLEAN FsFilterFastIoMdlReadComplete( 397 | __in PFILE_OBJECT FileObject, 398 | __in PMDL MdlChain, 399 | __in PDEVICE_OBJECT DeviceObject 400 | ) 401 | { 402 | // 403 | // Pass through logic for this type of Fast I/O 404 | // 405 | 406 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 407 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 408 | 409 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlReadComplete)) 410 | { 411 | return (fastIoDispatch->MdlReadComplete)( 412 | FileObject, 413 | MdlChain, 414 | nextDeviceObject); 415 | } 416 | 417 | return FALSE; 418 | } 419 | 420 | BOOLEAN FsFilterFastIoPrepareMdlWrite( 421 | __in PFILE_OBJECT FileObject, 422 | __in PLARGE_INTEGER FileOffset, 423 | __in ULONG Length, 424 | __in ULONG LockKey, 425 | __out PMDL* MdlChain, 426 | __out PIO_STATUS_BLOCK IoStatus, 427 | __in PDEVICE_OBJECT DeviceObject 428 | ) 429 | { 430 | // 431 | // Pass through logic for this type of Fast I/O 432 | // 433 | 434 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 435 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 436 | 437 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, PrepareMdlWrite)) 438 | { 439 | return (fastIoDispatch->PrepareMdlWrite)( 440 | FileObject, 441 | FileOffset, 442 | Length, 443 | LockKey, 444 | MdlChain, 445 | IoStatus, 446 | nextDeviceObject); 447 | } 448 | 449 | return FALSE; 450 | } 451 | 452 | BOOLEAN FsFilterFastIoMdlWriteComplete( 453 | __in PFILE_OBJECT FileObject, 454 | __in PLARGE_INTEGER FileOffset, 455 | __in PMDL MdlChain, 456 | __in PDEVICE_OBJECT DeviceObject 457 | ) 458 | { 459 | // 460 | // Pass through logic for this type of Fast I/O 461 | // 462 | 463 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 464 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 465 | 466 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlWriteComplete)) 467 | { 468 | return (fastIoDispatch->MdlWriteComplete)( 469 | FileObject, 470 | FileOffset, 471 | MdlChain, 472 | nextDeviceObject); 473 | } 474 | 475 | return FALSE; 476 | } 477 | 478 | BOOLEAN FsFilterFastIoReadCompressed( 479 | __in PFILE_OBJECT FileObject, 480 | __in PLARGE_INTEGER FileOffset, 481 | __in ULONG Length, 482 | __in ULONG LockKey, 483 | __out PVOID Buffer, 484 | __out PMDL* MdlChain, 485 | __out PIO_STATUS_BLOCK IoStatus, 486 | __out struct _COMPRESSED_DATA_INFO* CompressedDataInfo, 487 | __in ULONG CompressedDataInfoLength, 488 | __in PDEVICE_OBJECT DeviceObject 489 | ) 490 | { 491 | // 492 | // Pass through logic for this type of Fast I/O 493 | // 494 | 495 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 496 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 497 | 498 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoReadCompressed)) 499 | { 500 | return (fastIoDispatch->FastIoReadCompressed)( 501 | FileObject, 502 | FileOffset, 503 | Length, 504 | LockKey, 505 | Buffer, 506 | MdlChain, 507 | IoStatus, 508 | CompressedDataInfo, 509 | CompressedDataInfoLength, 510 | nextDeviceObject); 511 | } 512 | 513 | return FALSE; 514 | } 515 | 516 | BOOLEAN FsFilterFastIoWriteCompressed( 517 | __in PFILE_OBJECT FileObject, 518 | __in PLARGE_INTEGER FileOffset, 519 | __in ULONG Length, 520 | __in ULONG LockKey, 521 | __in PVOID Buffer, 522 | __out PMDL* MdlChain, 523 | __out PIO_STATUS_BLOCK IoStatus, 524 | __in struct _COMPRESSED_DATA_INFO* CompressedDataInfo, 525 | __in ULONG CompressedDataInfoLength, 526 | __in PDEVICE_OBJECT DeviceObject 527 | ) 528 | { 529 | // 530 | // Pass through logic for this type of Fast I/O 531 | // 532 | 533 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 534 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 535 | 536 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoWriteCompressed)) 537 | { 538 | return (fastIoDispatch->FastIoWriteCompressed)( 539 | FileObject, 540 | FileOffset, 541 | Length, 542 | LockKey, 543 | Buffer, 544 | MdlChain, 545 | IoStatus, 546 | CompressedDataInfo, 547 | CompressedDataInfoLength, 548 | nextDeviceObject ); 549 | } 550 | 551 | return FALSE; 552 | } 553 | 554 | BOOLEAN FsFilterFastIoMdlReadCompleteCompressed( 555 | __in PFILE_OBJECT FileObject, 556 | __in PMDL MdlChain, 557 | __in PDEVICE_OBJECT DeviceObject 558 | ) 559 | { 560 | // 561 | // Pass through logic for this type of Fast I/O 562 | // 563 | 564 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 565 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 566 | 567 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlReadCompleteCompressed)) 568 | { 569 | return (fastIoDispatch->MdlReadCompleteCompressed)( 570 | FileObject, 571 | MdlChain, 572 | nextDeviceObject); 573 | } 574 | 575 | return FALSE; 576 | } 577 | 578 | BOOLEAN FsFilterFastIoMdlWriteCompleteCompressed( 579 | __in PFILE_OBJECT FileObject, 580 | __in PLARGE_INTEGER FileOffset, 581 | __in PMDL MdlChain, 582 | __in PDEVICE_OBJECT DeviceObject 583 | ) 584 | { 585 | // 586 | // Pass through logic for this type of Fast I/O 587 | // 588 | 589 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 590 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 591 | 592 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, MdlWriteCompleteCompressed)) 593 | { 594 | return (fastIoDispatch->MdlWriteCompleteCompressed)( 595 | FileObject, 596 | FileOffset, 597 | MdlChain, 598 | nextDeviceObject); 599 | } 600 | 601 | return FALSE; 602 | } 603 | 604 | BOOLEAN FsFilterFastIoQueryOpen( 605 | __in PIRP Irp, 606 | __out PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, 607 | __in PDEVICE_OBJECT DeviceObject 608 | ) 609 | { 610 | // 611 | // Pass through logic for this type of Fast I/O 612 | // 613 | 614 | PDEVICE_OBJECT nextDeviceObject = ((PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject; 615 | PFAST_IO_DISPATCH fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch; 616 | 617 | if (VALID_FAST_IO_DISPATCH_HANDLER(fastIoDispatch, FastIoQueryOpen)) 618 | { 619 | BOOLEAN result; 620 | PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp ); 621 | 622 | // 623 | // Before calling the next filter, we must make sure their device 624 | // object is in the current stack entry for the given IRP 625 | // 626 | 627 | irpSp->DeviceObject = nextDeviceObject; 628 | 629 | result = (fastIoDispatch->FastIoQueryOpen)( 630 | Irp, 631 | NetworkInformation, 632 | nextDeviceObject); 633 | 634 | // 635 | // Always restore the IRP back to our device object 636 | // 637 | 638 | irpSp->DeviceObject = DeviceObject; 639 | return result; 640 | } 641 | 642 | return FALSE; 643 | } -------------------------------------------------------------------------------- /src/FSFilter/FsFilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | ////////////////////////////////////////////////////////////////////////// 5 | // Defines 6 | 7 | #define DELAY_ONE_MICROSECOND (-10) 8 | #define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND * 1000) 9 | #define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND * 1000) 10 | 11 | #define DEVOBJ_LIST_SIZE 64 12 | 13 | // Macro to test if FAST_IO_DISPATCH handling routine is valid 14 | #define VALID_FAST_IO_DISPATCH_HANDLER(_FastIoDispatchPtr, _FieldName) \ 15 | (((_FastIoDispatchPtr) != NULL) && \ 16 | (((_FastIoDispatchPtr)->SizeOfFastIoDispatch) >= \ 17 | (FIELD_OFFSET(FAST_IO_DISPATCH, _FieldName) + sizeof(void *))) && \ 18 | ((_FastIoDispatchPtr)->_FieldName != NULL)) 19 | 20 | ////////////////////////////////////////////////////////////////////////// 21 | // Structures 22 | 23 | typedef struct _FSFILTER_DEVICE_EXTENSION 24 | { 25 | PDEVICE_OBJECT AttachedToDeviceObject; 26 | } FSFILTER_DEVICE_EXTENSION, *PFSFILTER_DEVICE_EXTENSION; 27 | 28 | ////////////////////////////////////////////////////////////////////////// 29 | // General Functions 30 | 31 | NTSTATUS FsFilterDispatchPassThrough( 32 | __in PDEVICE_OBJECT DeviceObject, 33 | __in PIRP Irp 34 | ); 35 | 36 | NTSTATUS FsFilterDispatchCreate( 37 | __in PDEVICE_OBJECT DeviceObject, 38 | __in PIRP Irp 39 | ); 40 | 41 | NTSTATUS FsFilterAttachToDevice( 42 | __in PDEVICE_OBJECT DeviceObject, 43 | __out_opt PDEVICE_OBJECT* pFilterDeviceObject 44 | ); 45 | 46 | VOID FsFilterDetachFromDevice( 47 | __in PDEVICE_OBJECT DeviceObject 48 | ); 49 | 50 | BOOLEAN FsFilterIsAttachedToDevice( 51 | __in PDEVICE_OBJECT DeviceObject 52 | ); 53 | 54 | BOOLEAN FsFilterIsMyDeviceObject( 55 | __in PDEVICE_OBJECT DeviceObject 56 | ); 57 | 58 | VOID FsFilterNotificationCallback( 59 | __in PDEVICE_OBJECT DeviceObject, 60 | __in BOOLEAN FsActive 61 | ); 62 | 63 | ////////////////////////////////////////////////////////////////////////// 64 | // Fast-IO Handlers 65 | 66 | BOOLEAN FsFilterFastIoCheckIfPossible( 67 | __in PFILE_OBJECT FileObject, 68 | __in PLARGE_INTEGER FileOffset, 69 | __in ULONG Length, 70 | __in BOOLEAN Wait, 71 | __in ULONG LockKey, 72 | __in BOOLEAN CheckForReadOperation, 73 | __out PIO_STATUS_BLOCK IoStatus, 74 | __in PDEVICE_OBJECT DeviceObject 75 | ); 76 | 77 | BOOLEAN FsFilterFastIoRead( 78 | __in PFILE_OBJECT FileObject, 79 | __in PLARGE_INTEGER FileOffset, 80 | __in ULONG Length, 81 | __in BOOLEAN Wait, 82 | __in ULONG LockKey, 83 | __out PVOID Buffer, 84 | __out PIO_STATUS_BLOCK IoStatus, 85 | __in PDEVICE_OBJECT DeviceObject 86 | ); 87 | 88 | BOOLEAN FsFilterFastIoWrite( 89 | __in PFILE_OBJECT FileObject, 90 | __in PLARGE_INTEGER FileOffset, 91 | __in ULONG Length, 92 | __in BOOLEAN Wait, 93 | __in ULONG LockKey, 94 | __in PVOID Buffer, 95 | __out PIO_STATUS_BLOCK IoStatus, 96 | __in PDEVICE_OBJECT DeviceObject 97 | ); 98 | 99 | BOOLEAN FsFilterFastIoQueryBasicInfo( 100 | __in PFILE_OBJECT FileObject, 101 | __in BOOLEAN Wait, 102 | __out PFILE_BASIC_INFORMATION Buffer, 103 | __out PIO_STATUS_BLOCK IoStatus, 104 | __in PDEVICE_OBJECT DeviceObject 105 | ); 106 | 107 | BOOLEAN FsFilterFastIoQueryStandardInfo( 108 | __in PFILE_OBJECT FileObject, 109 | __in BOOLEAN Wait, 110 | __out PFILE_STANDARD_INFORMATION Buffer, 111 | __out PIO_STATUS_BLOCK IoStatus, 112 | __in PDEVICE_OBJECT DeviceObject 113 | ); 114 | 115 | BOOLEAN FsFilterFastIoLock( 116 | __in PFILE_OBJECT FileObject, 117 | __in PLARGE_INTEGER FileOffset, 118 | __in PLARGE_INTEGER Length, 119 | __in PEPROCESS ProcessId, 120 | __in ULONG Key, 121 | __in BOOLEAN FailImmediately, 122 | __in BOOLEAN ExclusiveLock, 123 | __out PIO_STATUS_BLOCK IoStatus, 124 | __in PDEVICE_OBJECT DeviceObject 125 | ); 126 | 127 | BOOLEAN FsFilterFastIoUnlockSingle( 128 | __in PFILE_OBJECT FileObject, 129 | __in PLARGE_INTEGER FileOffset, 130 | __in PLARGE_INTEGER Length, 131 | __in PEPROCESS ProcessId, 132 | __in ULONG Key, 133 | __out PIO_STATUS_BLOCK IoStatus, 134 | __in PDEVICE_OBJECT DeviceObject 135 | ); 136 | 137 | BOOLEAN FsFilterFastIoUnlockAll( 138 | __in PFILE_OBJECT FileObject, 139 | __in PEPROCESS ProcessId, 140 | __out PIO_STATUS_BLOCK IoStatus, 141 | __in PDEVICE_OBJECT DeviceObject 142 | ); 143 | 144 | BOOLEAN FsFilterFastIoUnlockAllByKey( 145 | __in PFILE_OBJECT FileObject, 146 | __in PVOID ProcessId, 147 | __in ULONG Key, 148 | __out PIO_STATUS_BLOCK IoStatus, 149 | __in PDEVICE_OBJECT DeviceObject 150 | ); 151 | 152 | BOOLEAN FsFilterFastIoDeviceControl( 153 | __in PFILE_OBJECT FileObject, 154 | __in BOOLEAN Wait, 155 | __in_opt PVOID InputBuffer, 156 | __in ULONG InputBufferLength, 157 | __out_opt PVOID OutputBuffer, 158 | __in ULONG OutputBufferLength, 159 | __in ULONG IoControlCode, 160 | __out PIO_STATUS_BLOCK IoStatus, 161 | __in PDEVICE_OBJECT DeviceObject 162 | ); 163 | 164 | VOID FsFilterFastIoDetachDevice( 165 | __in PDEVICE_OBJECT SourceDevice, 166 | __in PDEVICE_OBJECT TargetDevice 167 | ); 168 | 169 | BOOLEAN FsFilterFastIoQueryNetworkOpenInfo( 170 | __in PFILE_OBJECT FileObject, 171 | __in BOOLEAN Wait, 172 | __out PFILE_NETWORK_OPEN_INFORMATION Buffer, 173 | __out PIO_STATUS_BLOCK IoStatus, 174 | __in PDEVICE_OBJECT DeviceObject 175 | ); 176 | 177 | BOOLEAN FsFilterFastIoMdlRead( 178 | __in PFILE_OBJECT FileObject, 179 | __in PLARGE_INTEGER FileOffset, 180 | __in ULONG Length, 181 | __in ULONG LockKey, 182 | __out PMDL* MdlChain, 183 | __out PIO_STATUS_BLOCK IoStatus, 184 | __in PDEVICE_OBJECT DeviceObject 185 | ); 186 | 187 | BOOLEAN FsFilterFastIoMdlReadComplete( 188 | __in PFILE_OBJECT FileObject, 189 | __in PMDL MdlChain, 190 | __in PDEVICE_OBJECT DeviceObject 191 | ); 192 | 193 | BOOLEAN FsFilterFastIoPrepareMdlWrite( 194 | __in PFILE_OBJECT FileObject, 195 | __in PLARGE_INTEGER FileOffset, 196 | __in ULONG Length, 197 | __in ULONG LockKey, 198 | __out PMDL* MdlChain, 199 | __out PIO_STATUS_BLOCK IoStatus, 200 | __in PDEVICE_OBJECT DeviceObject 201 | ); 202 | 203 | BOOLEAN FsFilterFastIoMdlWriteComplete( 204 | __in PFILE_OBJECT FileObject, 205 | __in PLARGE_INTEGER FileOffset, 206 | __in PMDL MdlChain, 207 | __in PDEVICE_OBJECT DeviceObject 208 | ); 209 | 210 | BOOLEAN FsFilterFastIoReadCompressed( 211 | __in PFILE_OBJECT FileObject, 212 | __in PLARGE_INTEGER FileOffset, 213 | __in ULONG Length, 214 | __in ULONG LockKey, 215 | __out PVOID Buffer, 216 | __out PMDL* MdlChain, 217 | __out PIO_STATUS_BLOCK IoStatus, 218 | __out struct _COMPRESSED_DATA_INFO* CompressedDataInfo, 219 | __in ULONG CompressedDataInfoLength, 220 | __in PDEVICE_OBJECT DeviceObject 221 | ); 222 | 223 | BOOLEAN FsFilterFastIoWriteCompressed( 224 | __in PFILE_OBJECT FileObject, 225 | __in PLARGE_INTEGER FileOffset, 226 | __in ULONG Length, 227 | __in ULONG LockKey, 228 | __in PVOID Buffer, 229 | __out PMDL* MdlChain, 230 | __out PIO_STATUS_BLOCK IoStatus, 231 | __in struct _COMPRESSED_DATA_INFO* CompressedDataInfo, 232 | __in ULONG CompressedDataInfoLength, 233 | __in PDEVICE_OBJECT DeviceObject 234 | ); 235 | 236 | BOOLEAN FsFilterFastIoMdlReadCompleteCompressed( 237 | __in PFILE_OBJECT FileObject, 238 | __in PMDL MdlChain, 239 | __in PDEVICE_OBJECT DeviceObject 240 | ); 241 | 242 | BOOLEAN FsFilterFastIoMdlWriteCompleteCompressed( 243 | __in PFILE_OBJECT FileObject, 244 | __in PLARGE_INTEGER FileOffset, 245 | __in PMDL MdlChain, 246 | __in PDEVICE_OBJECT DeviceObject 247 | ); 248 | 249 | BOOLEAN FsFilterFastIoQueryOpen( 250 | __in PIRP Irp, 251 | __out PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, 252 | __in PDEVICE_OBJECT DeviceObject 253 | ); 254 | 255 | ////////////////////////////////////////////////////////////////////////// 256 | // Global data 257 | 258 | extern PDRIVER_OBJECT g_fsFilterDriverObject; 259 | -------------------------------------------------------------------------------- /src/FSFilter/FsFilter.inf: -------------------------------------------------------------------------------- 1 | ;;; 2 | ;;; FsFilter 3 | ;;; 4 | 5 | [Version] 6 | Signature = "$Windows NT$" 7 | Class = "Bottom" 8 | ClassGuid = {3CE4F760-683C-47CE-929B-24896127EEB4} 9 | Provider = %ManufacturerName% 10 | DriverVer = 11 | CatalogFile = FsFilter.cat 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | Filter.DriverFiles = 12 ;%windir%\system32\drivers 16 | 17 | ;; 18 | ;; Default install sections 19 | ;; 20 | 21 | [DefaultInstall] 22 | OptionDesc = %ServiceDescription% 23 | CopyFiles = Filter.DriverFiles 24 | 25 | [DefaultInstall.Services] 26 | AddService = %ServiceName%,,Filter.Service 27 | 28 | ;; 29 | ;; Default uninstall sections 30 | ;; 31 | 32 | [DefaultUninstall] 33 | DelFiles = Filter.DriverFiles 34 | 35 | [DefaultUninstall.Services] 36 | DelService = %ServiceName%,0x200 ;Ensure service is stopped before deleting 37 | 38 | ; 39 | ; Services Section 40 | ; 41 | 42 | [Filter.Service] 43 | DisplayName = %ServiceName% 44 | Description = %ServiceDescription% 45 | ServiceBinary = %12%\%DriverName%.sys ;%windir%\system32\drivers\ 46 | ServiceType = 2 ;SERVICE_FILE_SYSTEM_DRIVER 47 | StartType = 3 ;SERVICE_DEMAND_START 48 | ErrorControl = 1 ;SERVICE_ERROR_NORMAL 49 | LoadOrderGroup = "FSFilter Bottom" 50 | AddReg = Filter.AddRegistry 51 | 52 | ; 53 | ; Registry Modifications 54 | ; 55 | 56 | [Filter.AddRegistry] 57 | HKR,,"DebugFlags",0x00010001 ,0x0 58 | HKR,,"SupportedFeatures",0x00010001,0x3 59 | HKR,"Instances","DefaultInstance",0x00000000,%DefaultInstance% 60 | HKR,"Instances\"%Instance1.Name%,"Altitude",0x00000000,%Instance1.Altitude% 61 | HKR,"Instances\"%Instance1.Name%,"Flags",0x00010001,%Instance1.Flags% 62 | 63 | ; 64 | ; Copy Files 65 | ; 66 | 67 | [Filter.DriverFiles] 68 | %DriverName%.sys 69 | 70 | [SourceDisksFiles] 71 | FsFilter.sys = 1,, 72 | 73 | [SourceDisksNames] 74 | 1 = %DiskId1%,,, 75 | 76 | ;; 77 | ;; String Section 78 | ;; 79 | 80 | [Strings] 81 | ; TODO - Add your manufacturer 82 | ManufacturerName = "Template" 83 | ServiceDescription = "FsFilter Filter Driver" 84 | ServiceName = "FsFilter" 85 | DriverName = "FsFilter" 86 | DiskId1 = "FsFilter Device Installation Disk" 87 | 88 | ;Instances specific information. 89 | DefaultInstance = "FsFilter Instance" 90 | Instance1.Name = "FsFilter Instance" 91 | Instance1.Altitude = "47777" 92 | Instance1.Flags = 0x0 ; Allow all attachments 93 | -------------------------------------------------------------------------------- /src/FSFilter/FsFilter.rc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define VER_FILETYPE VFT_DRV 5 | #define VER_FILESUBTYPE VFT2_DRV_SYSTEM 6 | #define VER_FILEDESCRIPTION_STR "FsFilter Filter Driver" 7 | #define VER_INTERNALNAME_STR "FsFilter.sys" 8 | 9 | #include "common.ver" 10 | -------------------------------------------------------------------------------- /src/FSFilter/FsFilter.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 24 | 37 | 38 | 44 | 57 | 58 | 59 | 60 | 61 | 62 | 67 | 70 | 71 | 74 | 75 | 78 | 79 | 82 | 83 | 86 | 87 | 88 | 93 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /src/FSFilter/FsFilter.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | Debug 22 | ARM 23 | 24 | 25 | Release 26 | ARM 27 | 28 | 29 | Debug 30 | ARM64 31 | 32 | 33 | Release 34 | ARM64 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921} 43 | {f2f62967-0815-4fd7-9b86-6eedcac766eb} 44 | v4.5 45 | 12.0 46 | Debug 47 | Win32 48 | FsFilter 49 | 50 | 51 | 52 | Windows10 53 | true 54 | WindowsKernelModeDriver10.0 55 | Driver 56 | WDM 57 | 58 | 59 | Windows10 60 | false 61 | WindowsKernelModeDriver10.0 62 | Driver 63 | WDM 64 | 65 | 66 | Windows10 67 | true 68 | WindowsKernelModeDriver10.0 69 | Driver 70 | WDM 71 | 72 | 73 | Windows10 74 | false 75 | WindowsKernelModeDriver10.0 76 | Driver 77 | WDM 78 | 79 | 80 | Windows10 81 | true 82 | WindowsKernelModeDriver10.0 83 | Driver 84 | WDM 85 | 86 | 87 | Windows10 88 | false 89 | WindowsKernelModeDriver10.0 90 | Driver 91 | WDM 92 | 93 | 94 | Windows10 95 | true 96 | WindowsKernelModeDriver10.0 97 | Driver 98 | WDM 99 | 100 | 101 | Windows10 102 | false 103 | WindowsKernelModeDriver10.0 104 | Driver 105 | WDM 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | DbgengKernelDebugger 117 | 118 | 119 | DbgengKernelDebugger 120 | 121 | 122 | DbgengKernelDebugger 123 | 124 | 125 | DbgengKernelDebugger 126 | 127 | 128 | DbgengKernelDebugger 129 | 130 | 131 | DbgengKernelDebugger 132 | 133 | 134 | DbgengKernelDebugger 135 | 136 | 137 | DbgengKernelDebugger 138 | 139 | 140 | 141 | fltmgr.lib;%(AdditionalDependencies) 142 | 143 | 144 | 145 | 146 | fltmgr.lib;%(AdditionalDependencies) 147 | 148 | 149 | 150 | 151 | fltmgr.lib;%(AdditionalDependencies) 152 | 153 | 154 | 155 | 156 | fltmgr.lib;%(AdditionalDependencies) 157 | 158 | 159 | 160 | 161 | fltmgr.lib;%(AdditionalDependencies) 162 | 163 | 164 | 165 | 166 | fltmgr.lib;%(AdditionalDependencies) 167 | 168 | 169 | 170 | 171 | fltmgr.lib;%(AdditionalDependencies) 172 | 173 | 174 | 175 | 176 | fltmgr.lib;%(AdditionalDependencies) 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /src/FSFilter/FsFilter.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Resource Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | 49 | 50 | Header Files 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/FSFilter/IrpDispatch.c: -------------------------------------------------------------------------------- 1 | #include "FsFilter.h" 2 | 3 | /////////////////////////////////////////////////////////////////////////////////////////////////// 4 | // PassThrough IRP Handler 5 | 6 | NTSTATUS FsFilterDispatchPassThrough( 7 | __in PDEVICE_OBJECT DeviceObject, 8 | __in PIRP Irp 9 | ) 10 | { 11 | PFSFILTER_DEVICE_EXTENSION pDevExt = (PFSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 12 | 13 | IoSkipCurrentIrpStackLocation(Irp); 14 | return IoCallDriver(pDevExt->AttachedToDeviceObject, Irp); 15 | } 16 | 17 | /////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // IRP_MJ_CREATE IRP Handler 19 | 20 | NTSTATUS FsFilterDispatchCreate( 21 | __in PDEVICE_OBJECT DeviceObject, 22 | __in PIRP Irp 23 | ) 24 | { 25 | PFILE_OBJECT pFileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject; 26 | 27 | DbgPrint("%wZ\n", &pFileObject->FileName); 28 | 29 | return FsFilterDispatchPassThrough(DeviceObject, Irp); 30 | } -------------------------------------------------------------------------------- /src/FSFilter/Main.c: -------------------------------------------------------------------------------- 1 | #include "FsFilter.h" 2 | 3 | ////////////////////////////////////////////////////////////////////////// 4 | // Function prototypes 5 | 6 | VOID FsFilterUnload( 7 | __in PDRIVER_OBJECT DriverObject 8 | ); 9 | 10 | ////////////////////////////////////////////////////////////////////////// 11 | // Global data 12 | 13 | PDRIVER_OBJECT g_fsFilterDriverObject = NULL; 14 | 15 | FAST_IO_DISPATCH g_fastIoDispatch = 16 | { 17 | sizeof(FAST_IO_DISPATCH), 18 | FsFilterFastIoCheckIfPossible, 19 | FsFilterFastIoRead, 20 | FsFilterFastIoWrite, 21 | FsFilterFastIoQueryBasicInfo, 22 | FsFilterFastIoQueryStandardInfo, 23 | FsFilterFastIoLock, 24 | FsFilterFastIoUnlockSingle, 25 | FsFilterFastIoUnlockAll, 26 | FsFilterFastIoUnlockAllByKey, 27 | FsFilterFastIoDeviceControl, 28 | NULL, 29 | NULL, 30 | FsFilterFastIoDetachDevice, 31 | FsFilterFastIoQueryNetworkOpenInfo, 32 | NULL, 33 | FsFilterFastIoMdlRead, 34 | FsFilterFastIoMdlReadComplete, 35 | FsFilterFastIoPrepareMdlWrite, 36 | FsFilterFastIoMdlWriteComplete, 37 | FsFilterFastIoReadCompressed, 38 | FsFilterFastIoWriteCompressed, 39 | FsFilterFastIoMdlReadCompleteCompressed, 40 | FsFilterFastIoMdlWriteCompleteCompressed, 41 | FsFilterFastIoQueryOpen, 42 | NULL, 43 | NULL, 44 | NULL, 45 | }; 46 | 47 | ////////////////////////////////////////////////////////////////////////// 48 | // DriverEntry - Entry point of the driver 49 | 50 | NTSTATUS DriverEntry( 51 | __inout PDRIVER_OBJECT DriverObject, 52 | __in PUNICODE_STRING RegistryPath 53 | ) 54 | { 55 | UNREFERENCED_PARAMETER(RegistryPath); 56 | NTSTATUS status = STATUS_SUCCESS; 57 | ULONG i = 0; 58 | 59 | //ASSERT(FALSE); // This will break to debugger 60 | 61 | // 62 | // Store our driver object. 63 | // 64 | 65 | g_fsFilterDriverObject = DriverObject; 66 | 67 | // 68 | // Initialize the driver object dispatch table. 69 | // 70 | 71 | for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; ++i) 72 | { 73 | DriverObject->MajorFunction[i] = FsFilterDispatchPassThrough; 74 | } 75 | 76 | DriverObject->MajorFunction[IRP_MJ_CREATE] = FsFilterDispatchCreate; 77 | 78 | // 79 | // Set fast-io dispatch table. 80 | // 81 | 82 | DriverObject->FastIoDispatch = &g_fastIoDispatch; 83 | 84 | // 85 | // Registered callback routine for file system changes. 86 | // 87 | 88 | status = IoRegisterFsRegistrationChange(DriverObject, FsFilterNotificationCallback); 89 | if (!NT_SUCCESS(status)) 90 | { 91 | return status; 92 | } 93 | 94 | // 95 | // Set driver unload routine (debug purpose only). 96 | // 97 | 98 | DriverObject->DriverUnload = FsFilterUnload; 99 | 100 | return STATUS_SUCCESS; 101 | } 102 | 103 | ////////////////////////////////////////////////////////////////////////// 104 | // Unload routine 105 | 106 | VOID FsFilterUnload( 107 | __in PDRIVER_OBJECT DriverObject 108 | ) 109 | { 110 | ULONG numDevices = 0; 111 | ULONG i = 0; 112 | LARGE_INTEGER interval; 113 | PDEVICE_OBJECT devList[DEVOBJ_LIST_SIZE]; 114 | 115 | interval.QuadPart = (5 * DELAY_ONE_SECOND); //delay 5 seconds 116 | 117 | // 118 | // Unregistered callback routine for file system changes. 119 | // 120 | 121 | IoUnregisterFsRegistrationChange(DriverObject, FsFilterNotificationCallback); 122 | 123 | // 124 | // This is the loop that will go through all of the devices we are attached 125 | // to and detach from them. 126 | // 127 | 128 | for (;;) 129 | { 130 | IoEnumerateDeviceObjectList( 131 | DriverObject, 132 | devList, 133 | sizeof(devList), 134 | &numDevices); 135 | 136 | if (0 == numDevices) 137 | { 138 | break; 139 | } 140 | 141 | numDevices = min(numDevices, RTL_NUMBER_OF(devList)); 142 | 143 | for (i = 0; i < numDevices; ++i) 144 | { 145 | FsFilterDetachFromDevice(devList[i]); 146 | ObDereferenceObject(devList[i]); 147 | } 148 | 149 | KeDelayExecutionThread(KernelMode, FALSE, &interval); 150 | } 151 | } 152 | 153 | ////////////////////////////////////////////////////////////////////////// 154 | // Misc 155 | 156 | BOOLEAN FsFilterIsMyDeviceObject( 157 | __in PDEVICE_OBJECT DeviceObject 158 | ) 159 | { 160 | return DeviceObject->DriverObject == g_fsFilterDriverObject; 161 | } 162 | -------------------------------------------------------------------------------- /src/FSFilter/Notification.c: -------------------------------------------------------------------------------- 1 | #include "FsFilter.h" 2 | 3 | ////////////////////////////////////////////////////////////////////////// 4 | // Prototypes 5 | 6 | NTSTATUS FsFilterAttachToFileSystemDevice( 7 | __in PDEVICE_OBJECT DeviceObject 8 | ); 9 | 10 | VOID FsFilterDetachFromFileSystemDevice( 11 | __in PDEVICE_OBJECT DeviceObject 12 | ); 13 | 14 | NTSTATUS FsFilterEnumerateFileSystemVolumes( 15 | __in PDEVICE_OBJECT DeviceObject 16 | ); 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // This routine is invoked whenever a file system has either registered or 20 | // unregistered itself as an active file system. 21 | 22 | VOID FsFilterNotificationCallback( 23 | __in PDEVICE_OBJECT DeviceObject, 24 | __in BOOLEAN FsActive 25 | ) 26 | { 27 | // 28 | // Handle attaching/detaching from the given file system. 29 | // 30 | 31 | if (FsActive) 32 | { 33 | FsFilterAttachToFileSystemDevice(DeviceObject); 34 | } 35 | else 36 | { 37 | FsFilterDetachFromFileSystemDevice(DeviceObject); 38 | } 39 | } 40 | 41 | /////////////////////////////////////////////////////////////////////////////////////////////////// 42 | // This will attach to the given file system device object 43 | 44 | NTSTATUS FsFilterAttachToFileSystemDevice( 45 | __in PDEVICE_OBJECT DeviceObject 46 | ) 47 | { 48 | NTSTATUS status = STATUS_SUCCESS; 49 | PDEVICE_OBJECT filterDeviceObject = NULL; 50 | 51 | if (!FsFilterIsAttachedToDevice(DeviceObject)) 52 | { 53 | status = FsFilterAttachToDevice(DeviceObject, &filterDeviceObject); 54 | 55 | if (!NT_SUCCESS(status)) 56 | { 57 | return status; 58 | } 59 | 60 | // 61 | // Enumerate all the mounted devices that currently exist for this file system and attach to them. 62 | // 63 | 64 | status = FsFilterEnumerateFileSystemVolumes(DeviceObject); 65 | 66 | if (!NT_SUCCESS(status)) 67 | { 68 | FsFilterDetachFromDevice(filterDeviceObject); 69 | return status; 70 | } 71 | } 72 | 73 | return STATUS_SUCCESS; 74 | } 75 | 76 | /////////////////////////////////////////////////////////////////////////////////////////////////// 77 | // This will detach us from the chain 78 | 79 | VOID FsFilterDetachFromFileSystemDevice( 80 | __in PDEVICE_OBJECT DeviceObject 81 | ) 82 | { 83 | PDEVICE_OBJECT device = NULL; 84 | 85 | for (device = DeviceObject->AttachedDevice; NULL != device; device = device->AttachedDevice) 86 | { 87 | if (FsFilterIsMyDeviceObject(device)) 88 | { 89 | // 90 | // Detach us from the object just below us. Cleanup and delete the object. 91 | // 92 | 93 | FsFilterDetachFromDevice(device); 94 | 95 | break; 96 | } 97 | } 98 | } 99 | 100 | /////////////////////////////////////////////////////////////////////////////////////////////////// 101 | // Enumerate all the mounted devices that currently exist for the given file 102 | // system and attach to them 103 | 104 | NTSTATUS FsFilterEnumerateFileSystemVolumes( 105 | __in PDEVICE_OBJECT DeviceObject 106 | ) 107 | { 108 | NTSTATUS status = STATUS_SUCCESS; 109 | ULONG numDevices = 0; 110 | ULONG i = 0; 111 | PDEVICE_OBJECT devList[DEVOBJ_LIST_SIZE]; 112 | 113 | // 114 | // Now get the list of devices. 115 | // 116 | 117 | status = IoEnumerateDeviceObjectList( 118 | DeviceObject->DriverObject, 119 | devList, 120 | sizeof(devList), 121 | &numDevices); 122 | 123 | if (!NT_SUCCESS(status)) 124 | { 125 | return status; 126 | } 127 | 128 | numDevices = min(numDevices, RTL_NUMBER_OF(devList)); 129 | 130 | // 131 | // Walk the given list of devices and attach to them if we should. 132 | // 133 | 134 | for (i = 0; i < numDevices; ++i) 135 | { 136 | // 137 | // Do not attach if: 138 | // - This is the control device object (the one passed in) 139 | // - The device type does not match 140 | // - We are already attached to it. 141 | // 142 | 143 | if (devList[i] != DeviceObject && 144 | devList[i]->DeviceType == DeviceObject->DeviceType && 145 | !FsFilterIsAttachedToDevice(devList[i])) 146 | { 147 | status = FsFilterAttachToDevice(devList[i], NULL); 148 | } 149 | 150 | ObDereferenceObject(devList[i]); 151 | } 152 | 153 | return STATUS_SUCCESS; 154 | } -------------------------------------------------------------------------------- /src/FsFilter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29519.181 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FsFilter", "FsFilter\FsFilter.vcxproj", "{140A7CB4-A057-4FEB-9C5A-838ED6C1B921}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Debug|ARM64 = Debug|ARM64 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|ARM = Release|ARM 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|ARM.Build.0 = Debug|ARM 22 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|ARM.Deploy.0 = Debug|ARM 23 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|x64.ActiveCfg = Debug|x64 27 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|x64.Build.0 = Debug|x64 28 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|x64.Deploy.0 = Debug|x64 29 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|x86.ActiveCfg = Debug|Win32 30 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|x86.Build.0 = Debug|Win32 31 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Debug|x86.Deploy.0 = Debug|Win32 32 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|ARM.ActiveCfg = Release|ARM 33 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|ARM.Build.0 = Release|ARM 34 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|ARM.Deploy.0 = Release|ARM 35 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|ARM64.Build.0 = Release|ARM64 37 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|ARM64.Deploy.0 = Release|ARM64 38 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|x64.ActiveCfg = Release|x64 39 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|x64.Build.0 = Release|x64 40 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|x64.Deploy.0 = Release|x64 41 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|x86.ActiveCfg = Release|Win32 42 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|x86.Build.0 = Release|Win32 43 | {140A7CB4-A057-4FEB-9C5A-838ED6C1B921}.Release|x86.Deploy.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {58696862-052F-4411-ADFC-19BBF4E31187} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /src/install.cmd: -------------------------------------------------------------------------------- 1 | sc create FsFilter type= filesys binPath= c:\FsFilter.sys 2 | sc start FsFilter 3 | pause 4 | sc stop FsFilter 5 | sc delete FsFilter 6 | --------------------------------------------------------------------------------