我正在编写一个附加到网络摄像头的 WDF 过滤器驱动程序。我的代码在下面链接,虽然它可以工作(大部分情况下),但我遇到的一个问题是,当我解开网络摄像头时,驱动程序保持运行状态并且永远不会关闭。驱动程序注册表显示计数为 0 并且没有活动的枚举键,所以我知道它不再附加到任何东西,但我不确定它为什么不会卸载。有什么帮助吗?
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
{
WDF_DRIVER_CONFIG Config;
WDF_DRIVER_CONFIG_INIT(&Config, WebcamFilterEvtDeviceAdd);
NTSTATUS Status = WdfDriverCreate(pDriverObject, pRegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &Config, WDF_NO_HANDLE);
if (!NT_SUCCESS(Status)) {
// TODO: Error handling
}
return Status;
}
NTSTATUS WebcamFilterEvtDeviceAdd(IN WDFDRIVER Driver, IN OUT PWDFDEVICE_INIT DeviceInit)
{
UNREFERENCED_PARAMETER(Driver);
WDF_OBJECT_ATTRIBUTES ObjectAttributes;
WDF_OBJECT_ATTRIBUTES_INIT(&ObjectAttributes);
WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&ObjectAttributes, WebcamFilter_DEVICE_CONTEXT);
WdfFdoInitSetFilter(DeviceInit);
WDFDEVICE Device = NULL;
NTSTATUS Status = WdfDeviceCreate(&DeviceInit, &ObjectAttributes, &Device);
if (!NT_SUCCESS(Status)) {
return Status;
}
PWebcamFilter_DEVICE_CONTEXT DeviceContext = GetContextFromWebcamFilterDevice(Device);
DeviceContext->TargetToSendRequestsTo = WdfDeviceGetIoTarget(Device);
WDF_IO_QUEUE_CONFIG IoCallbacks;
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoCallbacks, WdfIoQueueDispatchParallel);
IoCallbacks.PowerManaged = WdfFalse;
IoCallbacks.EvtIoRead = WebcamFilterEvtIoRead;
IoCallbacks.EvtIoWrite = WebcamFilterEvtIoWrite;
IoCallbacks.EvtIoDeviceControl = WebcamFilterEvtIoDeviceControl;
IoCallbacks.EvtIoDefault = WebcamFilterEvtIoDefault;
Status = WdfIoQueueCreate(Device, &IoCallbacks, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE);
if (!NT_SUCCESS(Status)) {
return Status;
}
if (InterlockedIncrement(&WebcamFilterFilterDeviceCount) == 1) {
Status = CreateControlDevice(Driver);
if (!NT_SUCCESS(Status)) {
return Status;
}
}
WDF_IO_QUEUE_CONFIG NotificationCallbacks;
WDF_IO_QUEUE_CONFIG_INIT(&NotificationCallbacks, WdfIoQueueDispatchManual);
NotificationCallbacks.PowerManaged = WdfFalse;
Status = WdfIoQueueCreate(Device, &NotificationCallbacks, WDF_NO_OBJECT_ATTRIBUTES, &DeviceContext->NotificationQueue);
if (!NT_SUCCESS(Status)) {
return Status;
}
return STATUS_SUCCESS;
}
NTSTATUS CreateControlDevice(IN WDFDRIVER Driver)
{
if (ControlDeviceExists) {
return STATUS_SUCCESS;
}
PWDFDEVICE_INIT DeviceInit = WdfControlDeviceInitAllocate(Driver, &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_RWX);
if (!DeviceInit) {
return STATUS_INSUFFICIENT_RESOURCES;
}
WdfDeviceInitSetExclusive(DeviceInit, TRUE);
DECLARE_CONST_UNICODE_STRING(NTDeviceName, L"\\Device\\WebcamFilter");
NTSTATUS Status = WdfDeviceInitAssignName(DeviceInit, &NTDeviceName);
if (!NT_SUCCESS(Status)) {
return Status;
}
WDF_FILEOBJECT_CONFIG FileObjectConfig;
WDF_FILEOBJECT_CONFIG_INIT(&FileObjectConfig, WebcamFilterControlCreate, WebcamFilterControlClose, WDF_NO_EVENT_CALLBACK);
WdfDeviceInitSetFileObjectConfig(DeviceInit, &FileObjectConfig, NULL);
Status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &WebcamFilterControlDevice);
if (!NT_SUCCESS(Status)) {
return Status;
}
DECLARE_CONST_UNICODE_STRING(DosDeviceName, L"\\DosDevices\\WebcamFilter");
Status = WdfDeviceCreateSymbolicLink(WebcamFilterControlDevice, &DosDeviceName);
if (!NT_SUCCESS(Status)) {
return Status;
}
WDF_IO_QUEUE_CONFIG IoCallbacks;
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoCallbacks, WdfIoQueueDispatchSequential);
IoCallbacks.EvtIoDeviceControl = WebcamFilterControlEvtIoDeviceControl;
Status = WdfIoQueueCreate(WebcamFilterControlDevice, &IoCallbacks, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE);
if (!NT_SUCCESS(Status)) {
return Status;
}
WdfControlFinishInitializing(WebcamFilterControlDevice);
return STATUS_SUCCESS;
}
VOID WebcamFilterEvtIoRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length)
{
UNREFERENCED_PARAMETER(Queue);
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Length);
return;
}
VOID WebcamFilterEvtIoWrite(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length)
{
UNREFERENCED_PARAMETER(Queue);
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Length);
return;
}
VOID WebcamFilterEvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode)
{
UNREFERENCED_PARAMETER(OutputBufferLength);
UNREFERENCED_PARAMETER(InputBufferLength);
UNREFERENCED_PARAMETER(IoControlCode);
WdfRequestComplete(Request, STATUS_SUCCESS);
return;
}
VOID WebcamFilterControlCreate(IN WDFDEVICE Device, IN WDFREQUEST Request, IN WDFFILEOBJECT FileObject)
{
UNREFERENCED_PARAMETER(Device);
UNREFERENCED_PARAMETER(Request);
UNREFERENCED_PARAMETER(FileObject);
ControlDeviceExists = TRUE;
WdfRequestComplete(Request, STATUS_SUCCESS);
return;
}
VOID WebcamFilterControlClose(IN WDFFILEOBJECT FileObject)
{
UNREFERENCED_PARAMETER(FileObject);
ControlDeviceExists = FALSE;
return;
}
VOID WebcamFilterControlEvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode)
{
UNREFERENCED_PARAMETER(InputBufferLength);
PWebcamFilter_DEVICE_CONTEXT DeviceContext = GetContextFromWebcamFilterDevice(WdfIoQueueGetDevice(Queue));
switch (IoControlCode) {
default:
WdfRequestComplete(Request, STATUS_INVALID_DEVICE_REQUEST);
break;
}
return;
}