├── .gitattributes ├── .gitignore ├── README.md ├── Webcam Interception and Protection in Kernel Mode in Windows.pdf ├── filter.c ├── filter.h ├── filter.inx ├── filter.rc ├── filter.sln ├── filter.vcxproj └── filter.vcxproj.filters /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc 262 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webcam-interception-driver 2 | 3 | A complementary sample driver for the article: [Through the looking glass: webcam interception and protection in kernel mode](https://www.virusbulletin.com/virusbulletin/2018/09/through-looking-glass-webcam-interception-and-protection-kernel-mode/). 4 | 5 | The driver demonstrates the following functionality: 6 | * Verbose camera-related IRP logging. 7 | * Blocking `KSSTATE_ACQUIRE` (`IOCTL_KS_PROPERTY`). 8 | * Intercepting `IOCTL_KS_READ_STREAM`. 9 | -------------------------------------------------------------------------------- /Webcam Interception and Protection in Kernel Mode in Windows.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReasonSoftware/webcam-interception-driver/7b27e69f5724579d65c6ab590ee90b0b47eb02df/Webcam Interception and Protection in Kernel Mode in Windows.pdf -------------------------------------------------------------------------------- /filter.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 6 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 7 | IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 8 | PURPOSE. 9 | 10 | Module Name: 11 | 12 | filter.c 13 | 14 | Abstract: 15 | 16 | This module shows how to a write a generic filter driver. The driver demonstrates how 17 | to support device I/O control requests through queues. All the I/O requests passed on to 18 | the lower driver. This filter driver shows how to handle IRP postprocessing by forwarding 19 | the requests with and without a completion routine. To forward with a completion routine 20 | set the define FORWARD_REQUEST_WITH_COMPLETION to 1. 21 | 22 | Environment: 23 | 24 | Kernel mode 25 | 26 | --*/ 27 | 28 | #include "filter.h" 29 | 30 | 31 | #define BLOCK_IOCTL_KS_PROPERTY 0 32 | #define BLOCK_IOCTL_KS_READ_STREAM 1 33 | 34 | 35 | #ifdef ALLOC_PRAGMA 36 | #pragma alloc_text (INIT, DriverEntry) 37 | #pragma alloc_text (PAGE, FilterEvtDeviceAdd) 38 | #endif 39 | 40 | 41 | const GUID GUID_PROPSETID_Topology = { STATIC_KSPROPSETID_Topology }; 42 | const GUID GUID_PROPSETID_Pin = { STATIC_KSPROPSETID_Pin }; 43 | const GUID GUID_PROPSETID_Stream = { STATIC_KSPROPSETID_Stream }; 44 | const GUID GUID_PROPSETID_MemoryTransport = { STATIC_KSPROPSETID_MemoryTransport }; 45 | const GUID GUID_PROPSETID_Connection = { STATIC_KSPROPSETID_Connection }; 46 | const GUID GUID_PROPSETID_VidcapCameraControl = { STATIC_PROPSETID_VIDCAP_CAMERACONTROL }; 47 | 48 | 49 | NTSTATUS 50 | DriverEntry( 51 | IN PDRIVER_OBJECT DriverObject, 52 | IN PUNICODE_STRING RegistryPath 53 | ) 54 | /*++ 55 | 56 | Routine Description: 57 | 58 | Installable driver initialization entry point. 59 | This entry point is called directly by the I/O system. 60 | 61 | Arguments: 62 | 63 | DriverObject - pointer to the driver object 64 | 65 | RegistryPath - pointer to a unicode string representing the path, 66 | to driver-specific key in the registry. 67 | 68 | Return Value: 69 | 70 | STATUS_SUCCESS if successful, 71 | STATUS_UNSUCCESSFUL otherwise. 72 | 73 | --*/ 74 | { 75 | WDF_DRIVER_CONFIG config; 76 | NTSTATUS status; 77 | WDFDRIVER hDriver; 78 | 79 | KdPrint(("[webcam-interception] Driver Sample\n")); 80 | 81 | // 82 | // Initialize driver config to control the attributes that 83 | // are global to the driver. Note that framework by default 84 | // provides a driver unload routine. If you create any resources 85 | // in the DriverEntry and want to be cleaned in driver unload, 86 | // you can override that by manually setting the EvtDriverUnload in the 87 | // config structure. In general xxx_CONFIG_INIT macros are provided to 88 | // initialize most commonly used members. 89 | // 90 | 91 | WDF_DRIVER_CONFIG_INIT( 92 | &config, 93 | FilterEvtDeviceAdd 94 | ); 95 | 96 | // 97 | // Create a framework driver object to represent our driver. 98 | // 99 | status = WdfDriverCreate(DriverObject, 100 | RegistryPath, 101 | WDF_NO_OBJECT_ATTRIBUTES, 102 | &config, 103 | &hDriver); 104 | if (!NT_SUCCESS(status)) { 105 | KdPrint(("[webcam-interception] WdfDriverCreate failed with status 0x%x\n", status)); 106 | } 107 | 108 | return status; 109 | } 110 | 111 | 112 | NTSTATUS 113 | FilterEvtDeviceAdd( 114 | IN WDFDRIVER Driver, 115 | IN PWDFDEVICE_INIT DeviceInit 116 | ) 117 | /*++ 118 | Routine Description: 119 | 120 | EvtDeviceAdd is called by the framework in response to AddDevice 121 | call from the PnP manager. Here you can query the device properties 122 | using WdfFdoInitWdmGetPhysicalDevice/IoGetDeviceProperty and based 123 | on that, decide to create a filter device object and attach to the 124 | function stack. If you are not interested in filtering this particular 125 | instance of the device, you can just return STATUS_SUCCESS without creating 126 | a framework device. 127 | 128 | Arguments: 129 | 130 | Driver - Handle to a framework driver object created in DriverEntry 131 | 132 | DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. 133 | 134 | Return Value: 135 | 136 | NTSTATUS 137 | 138 | --*/ 139 | { 140 | WDF_OBJECT_ATTRIBUTES deviceAttributes; 141 | PFILTER_EXTENSION filterExt; 142 | NTSTATUS status; 143 | WDFDEVICE device; 144 | WDF_IO_QUEUE_CONFIG ioQueueConfig; 145 | #if DBG 146 | UCHAR majorFunction; 147 | #endif // DBG 148 | 149 | PAGED_CODE(); 150 | 151 | UNREFERENCED_PARAMETER(Driver); 152 | 153 | // 154 | // Tell the framework that you are filter driver. Framework 155 | // takes care of inheriting all the device flags & characteristics 156 | // from the lower device you are attaching to. 157 | // 158 | WdfFdoInitSetFilter(DeviceInit); 159 | 160 | #if DBG 161 | // 162 | // Register the EvtDeviceWdmIrpPreprocess callback for logging. 163 | // 164 | for (majorFunction = IRP_MJ_CREATE; majorFunction <= IRP_MJ_MAXIMUM_FUNCTION; majorFunction++) { 165 | status = WdfDeviceInitAssignWdmIrpPreprocessCallback(DeviceInit, 166 | FilterEvtIrpPreprocess, 167 | majorFunction, 168 | NULL, 169 | 0); 170 | if (!NT_SUCCESS(status)) { 171 | KdPrint(("[webcam-interception] WdfDeviceInitAssignWdmIrpPreprocessCallback failed with status code 0x%x\n", status)); 172 | } 173 | } 174 | #endif // DBG 175 | 176 | // 177 | // Register the EvtIoInCallerContext callback to deal with IOCTLs that need to stay in original context. 178 | // 179 | WdfDeviceInitSetIoInCallerContextCallback(DeviceInit, FilterEvtIoInCallerContext); 180 | 181 | // 182 | // Specify the size of device extension where we track per device 183 | // context. 184 | // 185 | 186 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, FILTER_EXTENSION); 187 | 188 | // 189 | // Create a framework device object. This call will inturn create 190 | // a WDM deviceobject, attach to the lower stack and set the 191 | // appropriate flags and attributes. 192 | // 193 | status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); 194 | if (!NT_SUCCESS(status)) { 195 | KdPrint(("[webcam-interception] WdfDeviceCreate failed with status code 0x%x\n", status)); 196 | return status; 197 | } 198 | 199 | filterExt = FilterGetData(device); 200 | 201 | // 202 | // Configure the default queue to be Parallel. 203 | // 204 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, 205 | WdfIoQueueDispatchParallel); 206 | 207 | // 208 | // Framework by default creates non-power managed queues for 209 | // filter drivers. 210 | // 211 | ioQueueConfig.EvtIoDeviceControl = FilterEvtIoDeviceControl; 212 | 213 | status = WdfIoQueueCreate(device, 214 | &ioQueueConfig, 215 | WDF_NO_OBJECT_ATTRIBUTES, 216 | WDF_NO_HANDLE // pointer to default queue 217 | ); 218 | if (!NT_SUCCESS(status)) { 219 | KdPrint(("[webcam-interception] WdfIoQueueCreate failed 0x%x\n", status)); 220 | return status; 221 | } 222 | 223 | return status; 224 | } 225 | 226 | #if DBG 227 | 228 | VOID 229 | PrintGuidValues(LPCGUID lpGuid) 230 | { 231 | KdPrint(("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 232 | lpGuid->Data1, 233 | lpGuid->Data2, 234 | lpGuid->Data3, 235 | lpGuid->Data4[0], 236 | lpGuid->Data4[1], 237 | lpGuid->Data4[2], 238 | lpGuid->Data4[3], 239 | lpGuid->Data4[4], 240 | lpGuid->Data4[5], 241 | lpGuid->Data4[6], 242 | lpGuid->Data4[7])); 243 | } 244 | 245 | VOID 246 | LogIoctlKsProperty( 247 | IN PIRP Irp, 248 | IN PIO_STACK_LOCATION currentStack 249 | ) 250 | { 251 | PKSIDENTIFIER Request = currentStack->Parameters.DeviceIoControl.Type3InputBuffer; 252 | 253 | if (IsEqualGUID(&Request->Set, &GUID_PROPSETID_Topology)) { 254 | KdPrint(("\trequest: Topology\n")); 255 | } 256 | else if (IsEqualGUID(&Request->Set, &GUID_PROPSETID_Pin)) { 257 | KdPrint(("\trequest: Pin\n")); 258 | } 259 | else if (IsEqualGUID(&Request->Set, &GUID_PROPSETID_Stream)) { 260 | KdPrint(("\trequest: Stream\n")); 261 | } 262 | else if (IsEqualGUID(&Request->Set, &GUID_PROPSETID_MemoryTransport)) { 263 | KdPrint(("\trequest: MemoryTransport\n")); 264 | } 265 | else if (IsEqualGUID(&Request->Set, &GUID_PROPSETID_Connection)) { 266 | KdPrint(("\trequest: Connection\n")); 267 | 268 | switch (Request->Id) { 269 | case KSPROPERTY_CONNECTION_STATE: KdPrint(("\tKSPROPERTY_CONNECTION_STATE\n")); break; 270 | case KSPROPERTY_CONNECTION_PRIORITY: KdPrint(("\tKSPROPERTY_CONNECTION_PRIORITY\n")); break; 271 | case KSPROPERTY_CONNECTION_DATAFORMAT: KdPrint(("\tKSPROPERTY_CONNECTION_DATAFORMAT\n")); break; 272 | case KSPROPERTY_CONNECTION_ALLOCATORFRAMING: KdPrint(("\tKSPROPERTY_CONNECTION_ALLOCATORFRAMING\n")); break; 273 | case KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT: KdPrint(("\tKSPROPERTY_CONNECTION_PROPOSEDATAFORMAT\n")); break; 274 | case KSPROPERTY_CONNECTION_ACQUIREORDERING: KdPrint(("\tKSPROPERTY_CONNECTION_ACQUIREORDERING\n")); break; 275 | case KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX: KdPrint(("\tKSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX\n")); break; 276 | case KSPROPERTY_CONNECTION_STARTAT: KdPrint(("\tKSPROPERTY_CONNECTION_STARTAT\n")); break; 277 | } 278 | 279 | if (Request->Id == KSPROPERTY_CONNECTION_STATE) { 280 | PKSSTATE pksState = Irp->UserBuffer; 281 | 282 | if (Request->Flags == KSPROPERTY_TYPE_SET) { 283 | switch (*pksState) { 284 | case KSSTATE_STOP: 285 | KdPrint(("\tset type: KSSTATE_STOP\n")); 286 | break; 287 | 288 | case KSSTATE_ACQUIRE: 289 | KdPrint(("\tset type: KSSTATE_ACQUIRE\n")); 290 | break; 291 | 292 | case KSSTATE_PAUSE: 293 | KdPrint(("\tset type: KSSTATE_PAUSE\n")); 294 | break; 295 | 296 | case KSSTATE_RUN: 297 | KdPrint(("\tset type: KSSTATE_RUN\n")); 298 | break; 299 | } 300 | } 301 | else { 302 | KdPrint(("\tflags: 0x%x\n", Request->Flags)); 303 | } 304 | } 305 | } 306 | else { 307 | KdPrint(("\trequest: ")); 308 | PrintGuidValues(&Request->Set); 309 | KdPrint(("\n")); 310 | } 311 | } 312 | 313 | VOID 314 | LogDeviceControlIrp( 315 | IN PIRP Irp, 316 | IN PIO_STACK_LOCATION currentStack 317 | ) 318 | { 319 | LPSTR ioctl; 320 | 321 | ioctl = NULL; 322 | switch (currentStack->Parameters.DeviceIoControl.IoControlCode) { 323 | case IOCTL_KS_READ_STREAM: ioctl = "IOCTL_KS_READ_STREAM"; break; 324 | case IOCTL_KS_WRITE_STREAM: ioctl = "IOCTL_KS_WRITE_STREAM"; break; 325 | case IOCTL_KS_PROPERTY: ioctl = "IOCTL_KS_PROPERTY"; break; 326 | case IOCTL_KS_METHOD: ioctl = "IOCTL_KS_METHOD"; break; 327 | case IOCTL_KS_ENABLE_EVENT: ioctl = "IOCTL_KS_ENABLE_EVENT"; break; 328 | } 329 | 330 | if (ioctl) { 331 | KdPrint(("\tioctl: %s\n", ioctl)); 332 | } 333 | else { 334 | KdPrint(("\tioctl: 0x%x\n", currentStack->Parameters.DeviceIoControl.IoControlCode)); 335 | } 336 | 337 | switch (currentStack->Parameters.DeviceIoControl.IoControlCode) { 338 | case IOCTL_KS_PROPERTY: LogIoctlKsProperty(Irp, currentStack); break; 339 | } 340 | } 341 | 342 | VOID 343 | LogCreateIrp( 344 | IN PIO_STACK_LOCATION currentStack 345 | ) 346 | { 347 | USHORT i; 348 | 349 | KdPrint(("\tfilename:")); 350 | 351 | for (i = 0; i < currentStack->FileObject->FileName.Length / 2; i++) { 352 | KdPrint((" %02X", LOBYTE(currentStack->FileObject->FileName.Buffer[i]))); 353 | KdPrint((" %02X", HIBYTE(currentStack->FileObject->FileName.Buffer[i]))); 354 | } 355 | 356 | KdPrint(("\n")); 357 | } 358 | 359 | NTSTATUS 360 | FilterEvtIrpPreprocess( 361 | IN WDFDEVICE Device, 362 | PIRP Irp 363 | ) 364 | { 365 | PIO_STACK_LOCATION currentStack; 366 | LPSTR major; 367 | 368 | currentStack = IoGetCurrentIrpStackLocation(Irp); 369 | 370 | major = "???"; 371 | switch (currentStack->MajorFunction) { 372 | case IRP_MJ_CREATE: major = "IRP_MJ_CREATE"; break; 373 | case IRP_MJ_CREATE_NAMED_PIPE: major = "IRP_MJ_CREATE_NAMED_PIPE"; break; 374 | case IRP_MJ_CLOSE: major = "IRP_MJ_CLOSE"; break; 375 | case IRP_MJ_READ: major = "IRP_MJ_READ"; break; 376 | case IRP_MJ_WRITE: major = "IRP_MJ_WRITE"; break; 377 | case IRP_MJ_QUERY_INFORMATION: major = "IRP_MJ_QUERY_INFORMATION"; break; 378 | case IRP_MJ_SET_INFORMATION: major = "IRP_MJ_SET_INFORMATION"; break; 379 | case IRP_MJ_QUERY_EA: major = "IRP_MJ_QUERY_EA"; break; 380 | case IRP_MJ_SET_EA: major = "IRP_MJ_SET_EA"; break; 381 | case IRP_MJ_FLUSH_BUFFERS: major = "IRP_MJ_FLUSH_BUFFERS"; break; 382 | case IRP_MJ_QUERY_VOLUME_INFORMATION: major = "IRP_MJ_QUERY_VOLUME_INFORMATION"; break; 383 | case IRP_MJ_SET_VOLUME_INFORMATION: major = "IRP_MJ_SET_VOLUME_INFORMATION"; break; 384 | case IRP_MJ_DIRECTORY_CONTROL: major = "IRP_MJ_DIRECTORY_CONTROL"; break; 385 | case IRP_MJ_FILE_SYSTEM_CONTROL: major = "IRP_MJ_FILE_SYSTEM_CONTROL"; break; 386 | case IRP_MJ_DEVICE_CONTROL: major = "IRP_MJ_DEVICE_CONTROL"; break; 387 | case IRP_MJ_INTERNAL_DEVICE_CONTROL: major = "IRP_MJ_INTERNAL_DEVICE_CONTROL"; break; 388 | case IRP_MJ_SHUTDOWN: major = "IRP_MJ_SHUTDOWN"; break; 389 | case IRP_MJ_LOCK_CONTROL: major = "IRP_MJ_LOCK_CONTROL"; break; 390 | case IRP_MJ_CLEANUP: major = "IRP_MJ_CLEANUP"; break; 391 | case IRP_MJ_CREATE_MAILSLOT: major = "IRP_MJ_CREATE_MAILSLOT"; break; 392 | case IRP_MJ_QUERY_SECURITY: major = "IRP_MJ_QUERY_SECURITY"; break; 393 | case IRP_MJ_SET_SECURITY: major = "IRP_MJ_SET_SECURITY"; break; 394 | case IRP_MJ_POWER: major = "IRP_MJ_POWER"; break; 395 | case IRP_MJ_SYSTEM_CONTROL: major = "IRP_MJ_SYSTEM_CONTROL"; break; 396 | case IRP_MJ_DEVICE_CHANGE: major = "IRP_MJ_DEVICE_CHANGE"; break; 397 | case IRP_MJ_QUERY_QUOTA: major = "IRP_MJ_QUERY_QUOTA"; break; 398 | case IRP_MJ_SET_QUOTA: major = "IRP_MJ_SET_QUOTA"; break; 399 | case IRP_MJ_PNP: major = "IRP_MJ_PNP"; break; 400 | } 401 | 402 | if (major) { 403 | KdPrint(("[webcam-interception] major: %s\n", major)); 404 | } 405 | 406 | switch (currentStack->MajorFunction) { 407 | case IRP_MJ_CREATE: LogCreateIrp(currentStack); break; 408 | case IRP_MJ_DEVICE_CONTROL: LogDeviceControlIrp(Irp, currentStack); break; 409 | } 410 | 411 | IoSkipCurrentIrpStackLocation(Irp); 412 | return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp); 413 | } 414 | 415 | #endif // DBG 416 | 417 | VOID 418 | FilterEvtIoInCallerContext( 419 | IN WDFDEVICE Device, 420 | IN WDFREQUEST Request 421 | ) 422 | { 423 | #if BLOCK_IOCTL_KS_PROPERTY 424 | size_t inBufLen, outBufLen; 425 | PVOID inBuf, outBuf; 426 | WDFMEMORY InputMemoryBuffer, OutputMemoryBuffer; 427 | PKSIDENTIFIER pKSIdent; 428 | PKSSTATE pKSState; 429 | #endif // BLOCK_IOCTL_KS_PROPERTY 430 | 431 | WDF_REQUEST_PARAMETERS params; 432 | NTSTATUS status = STATUS_SUCCESS; 433 | 434 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 435 | WdfRequestGetParameters(Request, ¶ms); 436 | 437 | #if BLOCK_IOCTL_KS_PROPERTY 438 | if (params.Type == WdfRequestTypeDeviceControl && 439 | params.Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) { 440 | // 441 | // The I/O control code is METHOD_NEITHER. 442 | // First, retrieve the virtual addresses of 443 | // the input buffer. 444 | // 445 | status = WdfRequestRetrieveUnsafeUserInputBuffer(Request, sizeof(KSIDENTIFIER), &inBuf, &inBufLen); 446 | if (!NT_SUCCESS(status)) { 447 | goto Error; 448 | } 449 | 450 | // 451 | // Next, probe and lock the read buffer. 452 | // 453 | status = WdfRequestProbeAndLockUserBufferForRead(Request, inBuf, inBufLen, &InputMemoryBuffer); 454 | if (!NT_SUCCESS(status)) { 455 | goto Error; 456 | } 457 | 458 | pKSIdent = WdfMemoryGetBuffer(InputMemoryBuffer, NULL); 459 | 460 | if (IsEqualGUID(&pKSIdent->Set, &GUID_PROPSETID_Connection)) { 461 | if (pKSIdent->Id == KSPROPERTY_CONNECTION_STATE) { 462 | if (pKSIdent->Flags & KSPROPERTY_TYPE_SET) { 463 | status = WdfRequestRetrieveUnsafeUserOutputBuffer(Request, sizeof(KSSTATE), &outBuf, &outBufLen); 464 | if(!NT_SUCCESS(status)) { 465 | goto Error; 466 | } 467 | 468 | // 469 | // Note: even though it's an output buffer, 470 | // we're going to read from it, that's how 471 | // IOCTL_KS_PROPERTY works. 472 | // 473 | status = WdfRequestProbeAndLockUserBufferForRead(Request, outBuf, outBufLen, &OutputMemoryBuffer); 474 | if(!NT_SUCCESS(status)) { 475 | goto Error; 476 | } 477 | 478 | pKSState = WdfMemoryGetBuffer(OutputMemoryBuffer, NULL); 479 | 480 | switch(*pKSState) { 481 | case KSSTATE_ACQUIRE: 482 | status = STATUS_INSUFFICIENT_RESOURCES; 483 | break; 484 | 485 | case KSSTATE_RUN: 486 | status = STATUS_ACCESS_DENIED; 487 | break; 488 | } 489 | } 490 | } 491 | } 492 | 493 | if (!NT_SUCCESS(status)) { 494 | goto Error; 495 | } 496 | } 497 | #endif // BLOCK_IOCTL_KS_PROPERTY 498 | 499 | status = WdfDeviceEnqueueRequest(Device, Request); 500 | if (!NT_SUCCESS(status)) { 501 | KdPrint(("[webcam-interception] WdfDeviceEnqueueRequest failed: %s\n", status)); 502 | goto Error; 503 | } 504 | 505 | return; 506 | 507 | Error: 508 | 509 | WdfRequestComplete(Request, status); 510 | } 511 | 512 | VOID 513 | FilterEvtIoDeviceControl( 514 | IN WDFQUEUE Queue, 515 | IN WDFREQUEST Request, 516 | IN size_t OutputBufferLength, 517 | IN size_t InputBufferLength, 518 | IN ULONG IoControlCode 519 | ) 520 | /*++ 521 | 522 | Routine Description: 523 | 524 | This routine is the dispatch routine for internal device control requests. 525 | 526 | Arguments: 527 | 528 | Queue - Handle to the framework queue object that is associated 529 | with the I/O request. 530 | Request - Handle to a framework request object. 531 | 532 | OutputBufferLength - length of the request's output buffer, 533 | if an output buffer is available. 534 | InputBufferLength - length of the request's input buffer, 535 | if an input buffer is available. 536 | 537 | IoControlCode - the driver-defined or system-defined I/O control code 538 | (IOCTL) that is associated with the request. 539 | 540 | Return Value: 541 | 542 | VOID 543 | 544 | --*/ 545 | { 546 | PFILTER_EXTENSION filterExt; 547 | NTSTATUS status = STATUS_SUCCESS; 548 | WDFDEVICE device; 549 | WDFCONTEXT context = WDF_NO_CONTEXT; 550 | 551 | UNREFERENCED_PARAMETER(OutputBufferLength); 552 | UNREFERENCED_PARAMETER(InputBufferLength); 553 | 554 | //KdPrint(("[webcam-interception] Entered FilterEvtIoDeviceControl\n")); 555 | 556 | device = WdfIoQueueGetDevice(Queue); 557 | 558 | filterExt = FilterGetData(device); 559 | 560 | switch (IoControlCode) { 561 | #if BLOCK_IOCTL_KS_READ_STREAM 562 | case IOCTL_KS_READ_STREAM: 563 | context = "IOCTL_KS_READ_STREAM"; 564 | break; 565 | #endif // BLOCK_IOCTL_KS_READ_STREAM 566 | } 567 | 568 | if (!NT_SUCCESS(status)) { 569 | WdfRequestComplete(Request, status); 570 | return; 571 | } 572 | 573 | // 574 | // Forward the request down. WdfDeviceGetIoTarget returns 575 | // the default target, which represents the device attached to us below in 576 | // the stack. 577 | // 578 | #if FORWARD_REQUEST_WITH_COMPLETION 579 | // 580 | // Use this routine to forward a request if you are interested in post 581 | // processing the IRP. 582 | // 583 | FilterForwardRequestWithCompletionRoutine(Request, 584 | WdfDeviceGetIoTarget(device), 585 | context); 586 | #else 587 | FilterForwardRequest(Request, WdfDeviceGetIoTarget(device)); 588 | #endif 589 | 590 | return; 591 | } 592 | 593 | VOID 594 | FilterForwardRequest( 595 | IN WDFREQUEST Request, 596 | IN WDFIOTARGET Target 597 | ) 598 | /*++ 599 | Routine Description: 600 | 601 | Passes a request on to the lower driver. 602 | 603 | --*/ 604 | { 605 | WDF_REQUEST_SEND_OPTIONS options; 606 | BOOLEAN ret; 607 | NTSTATUS status; 608 | 609 | // 610 | // We are not interested in post processing the IRP so 611 | // fire and forget. 612 | // 613 | WDF_REQUEST_SEND_OPTIONS_INIT(&options, 614 | WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); 615 | 616 | ret = WdfRequestSend(Request, Target, &options); 617 | 618 | if (ret == FALSE) { 619 | status = WdfRequestGetStatus(Request); 620 | KdPrint(("[webcam-interception] WdfRequestSend failed: 0x%x\n", status)); 621 | WdfRequestComplete(Request, status); 622 | } 623 | 624 | return; 625 | } 626 | 627 | #if FORWARD_REQUEST_WITH_COMPLETION 628 | 629 | VOID 630 | FilterForwardRequestWithCompletionRoutine( 631 | IN WDFREQUEST Request, 632 | IN WDFIOTARGET Target, 633 | IN WDFCONTEXT Context 634 | ) 635 | /*++ 636 | Routine Description: 637 | 638 | This routine forwards the request to a lower driver with 639 | a completion so that when the request is completed by the 640 | lower driver, it can regain control of the request and look 641 | at the result. 642 | 643 | --*/ 644 | { 645 | BOOLEAN ret; 646 | NTSTATUS status; 647 | 648 | // 649 | // The following function essentially copies the content of 650 | // current stack location of the underlying IRP to the next one. 651 | // 652 | WdfRequestFormatRequestUsingCurrentType(Request); 653 | 654 | WdfRequestSetCompletionRoutine(Request, 655 | FilterRequestCompletionRoutine, 656 | Context); 657 | 658 | ret = WdfRequestSend(Request, 659 | Target, 660 | WDF_NO_SEND_OPTIONS); 661 | 662 | if (ret == FALSE) { 663 | status = WdfRequestGetStatus(Request); 664 | KdPrint(("[webcam-interception] WdfRequestSend failed: 0x%x\n", status)); 665 | WdfRequestComplete(Request, status); 666 | } 667 | 668 | return; 669 | } 670 | 671 | VOID 672 | FilterRequestCompletionRoutine( 673 | IN WDFREQUEST Request, 674 | IN WDFIOTARGET Target, 675 | PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, 676 | IN WDFCONTEXT Context 677 | ) 678 | /*++ 679 | 680 | Routine Description: 681 | 682 | Completion Routine 683 | 684 | Arguments: 685 | 686 | Target - Target handle 687 | Request - Request handle 688 | Params - request completion params 689 | Context - Driver supplied context 690 | 691 | 692 | Return Value: 693 | 694 | VOID 695 | 696 | --*/ 697 | { 698 | #if BLOCK_IOCTL_KS_READ_STREAM 699 | PIRP Irp; 700 | PKSSTREAM_HEADER pStreamHdr; 701 | PUCHAR pMdlBufferOut; 702 | #endif // BLOCK_IOCTL_KS_READ_STREAM 703 | 704 | UNREFERENCED_PARAMETER(Target); 705 | UNREFERENCED_PARAMETER(Context); 706 | 707 | //KdPrint(("[webcam-interception] status: 0x%x\n", CompletionParams->IoStatus.Status)); 708 | 709 | #if BLOCK_IOCTL_KS_READ_STREAM 710 | if (Context != WDF_NO_CONTEXT && CompletionParams->IoStatus.Status == STATUS_SUCCESS) { 711 | Irp = WdfRequestWdmGetIrp(Request); 712 | pStreamHdr = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; 713 | if (pStreamHdr) { 714 | if (Irp->MdlAddress) { 715 | pMdlBufferOut = (PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); 716 | 717 | // Fill the frame buffer with zero bytes. 718 | RtlSecureZeroMemory(pMdlBufferOut, pStreamHdr->DataUsed); 719 | 720 | // Set the frame size to zero. 721 | pStreamHdr->DataUsed = 0; 722 | } 723 | } 724 | } 725 | #endif // BLOCK_IOCTL_KS_READ_STREAM 726 | 727 | WdfRequestComplete(Request, CompletionParams->IoStatus.Status); 728 | 729 | return; 730 | } 731 | 732 | #endif //FORWARD_REQUEST_WITH_COMPLETION 733 | -------------------------------------------------------------------------------- /filter.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 6 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 7 | IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR 8 | PURPOSE. 9 | 10 | Module Name: 11 | 12 | filter.h 13 | 14 | Abstract: 15 | 16 | Contains structure definitions and function prototypes for a generic filter driver. 17 | 18 | Environment: 19 | 20 | Kernel mode 21 | 22 | --*/ 23 | 24 | #include 25 | #include 26 | #include // for SDDLs 27 | #define NTSTRSAFE_LIB 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #if !defined(_FILTER_H_) 35 | #define _FILTER_H_ 36 | 37 | 38 | // 39 | // Change the following define to 1 if you want to forward 40 | // the request with a completion routine. 41 | // 42 | #define FORWARD_REQUEST_WITH_COMPLETION 1 43 | 44 | 45 | typedef struct _FILTER_EXTENSION 46 | { 47 | WDFDEVICE WdfDevice; 48 | // More context data here 49 | 50 | }FILTER_EXTENSION, *PFILTER_EXTENSION; 51 | 52 | 53 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FILTER_EXTENSION, 54 | FilterGetData) 55 | 56 | DRIVER_INITIALIZE DriverEntry; 57 | EVT_WDF_DRIVER_DEVICE_ADD FilterEvtDeviceAdd; 58 | EVT_WDFDEVICE_WDM_IRP_PREPROCESS FilterEvtIrpPreprocess; 59 | EVT_WDF_IO_IN_CALLER_CONTEXT FilterEvtIoInCallerContext; 60 | EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL FilterEvtIoDeviceControl; 61 | 62 | VOID 63 | FilterForwardRequest( 64 | IN WDFREQUEST Request, 65 | IN WDFIOTARGET Target 66 | ); 67 | 68 | #if FORWARD_REQUEST_WITH_COMPLETION 69 | 70 | VOID 71 | FilterForwardRequestWithCompletionRoutine( 72 | IN WDFREQUEST Request, 73 | IN WDFIOTARGET Target, 74 | IN WDFCONTEXT Context 75 | ); 76 | 77 | VOID 78 | FilterRequestCompletionRoutine( 79 | IN WDFREQUEST Request, 80 | IN WDFIOTARGET Target, 81 | PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, 82 | IN WDFCONTEXT Context 83 | ); 84 | 85 | #endif //FORWARD_REQUEST_WITH_COMPLETION 86 | 87 | #endif 88 | 89 | -------------------------------------------------------------------------------- /filter.inx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReasonSoftware/webcam-interception-driver/7b27e69f5724579d65c6ab590ee90b0b47eb02df/filter.inx -------------------------------------------------------------------------------- /filter.rc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define DRIVERNAME "Generic.sys: " 5 | 6 | #define VER_FILETYPE VFT_DRV 7 | #define VER_FILESUBTYPE VFT2_DRV_SYSTEM 8 | #define VER_FILEDESCRIPTION_STR "Filter Driver for the Toaster Stack" 9 | #define VER_INTERNALNAME_STR DRIVERNAME 10 | #define VER_ORIGINALFILENAME_STR DRIVERNAME 11 | 12 | #include "common.ver" 13 | -------------------------------------------------------------------------------- /filter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2047 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "filter", "filter.vcxproj", "{B39F6628-73BA-4AC3-863A-EA20892F1EFD}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Debug|x64.ActiveCfg = Debug|x64 17 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Debug|x64.Build.0 = Debug|x64 18 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Debug|x64.Deploy.0 = Debug|x64 19 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Debug|x86.ActiveCfg = Debug|Win32 20 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Debug|x86.Build.0 = Debug|Win32 21 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Debug|x86.Deploy.0 = Debug|Win32 22 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Release|x64.ActiveCfg = Release|x64 23 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Release|x64.Build.0 = Release|x64 24 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Release|x64.Deploy.0 = Release|x64 25 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Release|x86.ActiveCfg = Release|Win32 26 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Release|x86.Build.0 = Release|Win32 27 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD}.Release|x86.Deploy.0 = Release|Win32 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | GlobalSection(ExtensibilityGlobals) = postSolution 33 | SolutionGuid = {4F7BEB58-5FB1-423C-BDD0-00C7EC74F54F} 34 | EndGlobalSection 35 | EndGlobal 36 | -------------------------------------------------------------------------------- /filter.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 | 22 | {B39F6628-73BA-4AC3-863A-EA20892F1EFD} 23 | $(MSBuildProjectName) 24 | 1 25 | false 26 | true 27 | Debug 28 | Win32 29 | {92082E8D-0D74-485B-9578-34DB3ED3F74D} 30 | $(LatestTargetPlatformVersion) 31 | 32 | 33 | 34 | Windows7 35 | False 36 | Desktop 37 | KMDF 38 | WindowsKernelModeDriver10.0 39 | Driver 40 | 41 | 42 | Windows7 43 | True 44 | Desktop 45 | KMDF 46 | WindowsKernelModeDriver10.0 47 | Driver 48 | 49 | 50 | Windows7 51 | False 52 | Desktop 53 | KMDF 54 | WindowsKernelModeDriver10.0 55 | Driver 56 | 57 | 58 | Windows7 59 | True 60 | Desktop 61 | KMDF 62 | WindowsKernelModeDriver10.0 63 | Driver 64 | 65 | 66 | 67 | $(IntDir) 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | $(InfArch) 84 | true 85 | .\$(IntDir)\filter.inf 86 | 87 | 88 | 89 | cam_inspect_fltr 90 | 91 | 92 | cam_inspect_fltr 93 | 94 | 95 | cam_inspect_fltr 96 | 97 | 98 | cam_inspect_fltr 99 | 100 | 101 | 102 | true 103 | Level4 104 | %(AdditionalIncludeDirectories);..\..\..\inc 105 | 106 | 107 | 108 | 109 | %(AdditionalDependencies);$(DDK_LIB_PATH)\wdmsec.lib 110 | 111 | 112 | %(AdditionalIncludeDirectories);..\..\..\inc 113 | 114 | 115 | %(AdditionalIncludeDirectories);..\..\..\inc 116 | 117 | 118 | 119 | 120 | true 121 | Level4 122 | %(AdditionalIncludeDirectories);..\..\..\inc 123 | 124 | 125 | false 126 | 127 | 128 | %(AdditionalDependencies);$(DDK_LIB_PATH)\wdmsec.lib 129 | 130 | 131 | %(AdditionalIncludeDirectories);..\..\..\inc 132 | 133 | 134 | %(AdditionalIncludeDirectories);..\..\..\inc 135 | 136 | 137 | 138 | 139 | true 140 | Level4 141 | %(AdditionalIncludeDirectories);..\..\..\inc 142 | 143 | 144 | 145 | 146 | %(AdditionalDependencies);$(DDK_LIB_PATH)\wdmsec.lib 147 | 148 | 149 | %(AdditionalIncludeDirectories);..\..\..\inc 150 | 151 | 152 | %(AdditionalIncludeDirectories);..\..\..\inc 153 | 154 | 155 | 156 | 157 | true 158 | Level4 159 | %(AdditionalIncludeDirectories);..\..\..\inc 160 | 161 | 162 | false 163 | 164 | 165 | %(AdditionalDependencies);$(DDK_LIB_PATH)\wdmsec.lib 166 | 167 | 168 | %(AdditionalIncludeDirectories);..\..\..\inc 169 | 170 | 171 | %(AdditionalIncludeDirectories);..\..\..\inc 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /filter.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* 6 | {E3242171-0D71-4EAC-94E0-E3B9FC647C16} 7 | 8 | 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | {D593E254-6A82-4D73-A34E-CD7D019FB577} 11 | 12 | 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml 14 | {5240632B-924D-4233-AE9C-CE317927559C} 15 | 16 | 17 | inf;inv;inx;mof;mc; 18 | {B6CEB15F-684F-4D1C-A9C3-400B108BC28E} 19 | 20 | 21 | 22 | 23 | Source Files 24 | 25 | 26 | 27 | 28 | Resource Files 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | 37 | 38 | Driver Files 39 | 40 | 41 | --------------------------------------------------------------------------------