⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 control.cpp

📁 Programming the Microsoft Windows Driver Model(2nd)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	}							// DeregisterAll



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



VOID KillRegRecord(PREG_RECORD reg)

	{							// KillRegRecord

	if (reg->InterfaceNotificationEntry)

		IoUnregisterPlugPlayNotification(reg->InterfaceNotificationEntry);

	reg->InterfaceNotificationEntry = NULL;



	if (reg->HandleNotificationEntry)

		IoUnregisterPlugPlayNotification(reg->HandleNotificationEntry);

	reg->HandleNotificationEntry = NULL;



	if (reg->TargetFileReferenced)

		ObDereferenceObject(reg->TargetFile);

	reg->TargetFileReferenced = FALSE;



	if (reg->Event)

		ObDereferenceObject(reg->Event);

	reg->Event = NULL;



	// Make sure we don't release the registration structure while a

	// work item is outstanding.



	if (reg->WorkItemCount == 0)

		ExFreePool(reg);

	else

		reg->DeferredRelease = TRUE;

	}							// KillRegRecord



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



NTSTATUS OnPnpNotify(PPLUGPLAY_NOTIFICATION_HEADER p, PREG_RECORD reg)

	{							// OnPnpNotify

	PAGED_CODE();

	NTSTATUS status;



	// Report the event



#if DBG



	char *msg;

	

	if (p->Event == GUID_DEVICE_INTERFACE_ARRIVAL)

		msg = "arrival";

	else if (p->Event == GUID_DEVICE_INTERFACE_REMOVAL)

		msg = "removal";

	else if (p->Event == GUID_TARGET_DEVICE_QUERY_REMOVE)

		msg = "target query remove";

	else if (p->Event == GUID_TARGET_DEVICE_REMOVE_CANCELLED)

		msg = "target remove cancelled";

	else if (p->Event == GUID_TARGET_DEVICE_REMOVE_COMPLETE)

		msg = "target remove complete";

	else 

		msg = "custom notification";



	KdPrint((DRIVERNAME " - PnP notification (%s event)\n", msg));



#endif // DBG



	// Create an event record for reporting back to the application



	PDEVICE_EXTENSION pdx = reg->DeviceExtension;

	

	PEVENT_RECORD evrec = (PEVENT_RECORD) ExAllocatePool(NonPagedPool, sizeof(EVENT_RECORD));

	if (!evrec)

		{

		KdPrint((DRIVERNAME " - can't allocate %d bytes for event record\n", sizeof(EVENT_RECORD)));

		return STATUS_SUCCESS;

		}

	RtlZeroMemory(evrec, sizeof(EVENT_RECORD));



	evrec->params.event = p->Event;



	if (p->Event == GUID_DEVICE_INTERFACE_ARRIVAL || p->Event == GUID_DEVICE_INTERFACE_REMOVAL)

		{						// interface notification

		PDEVICE_INTERFACE_CHANGE_NOTIFICATION q = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION) p;

		evrec->params.guid = q->InterfaceClassGuid;



		// N.B.: Don't just rely on an ASSERT like the following one in a production

		// driver -- handle the case where the name is too long in the free build too!



		ASSERT(q->SymbolicLinkName->Length + 2 <= sizeof(reg->LinkName));

		memcpy(reg->LinkName, q->SymbolicLinkName->Buffer, q->SymbolicLinkName->Length);

		reg->LinkName[q->SymbolicLinkName->Length/2] = 0;

		wcscpy(evrec->params.linkname, reg->LinkName);



		// For an arrival notification, we want to register for target device change notifications. To

		// do this, we must get a pointer to a file object for the device. Doing *that* entails opening

		// the device, which might cause a deadlock if the target device performs blocking PnP operations.

		// Therefore, arrange to do the open in another thread by queuing a work item.



		if (p->Event == GUID_DEVICE_INTERFACE_ARRIVAL)

			SubscribeForTargetNotifications(q, reg);

		}						// interface notification



	else if (p->Event == GUID_TARGET_DEVICE_QUERY_REMOVE

		|| p->Event == GUID_TARGET_DEVICE_REMOVE_COMPLETE)

		{						// target device notification

		PTARGET_DEVICE_REMOVAL_NOTIFICATION q = (PTARGET_DEVICE_REMOVAL_NOTIFICATION) p;

		wcscpy(evrec->params.linkname, reg->LinkName);



		// You need to close the file object when the query arrives,

		// or else the removal will get cancelled. Makes the idea

		// of getting a remove complete seem kind of silly, eh?



		if (reg->TargetFileReferenced)

			{					// dereference target

			if (reg->HandleNotificationEntry)

				IoUnregisterPlugPlayNotification(reg->HandleNotificationEntry);

			reg->HandleNotificationEntry = NULL;

			ObDereferenceObject(reg->TargetFile);

			reg->TargetFile = NULL;

			reg->TargetFileReferenced = FALSE;

			}					// dereference target

		}						// target device notification



	else if (p->Event == GUID_TARGET_DEVICE_REMOVE_CANCELLED)

		{						// remove cancelled

		PTARGET_DEVICE_REMOVAL_NOTIFICATION q = (PTARGET_DEVICE_REMOVAL_NOTIFICATION) p;

		wcscpy(evrec->params.linkname, reg->LinkName);

		}						// remove cancelled



	else

		{						// custom notification

		PTARGET_DEVICE_CUSTOM_NOTIFICATION q = (PTARGET_DEVICE_CUSTOM_NOTIFICATION) p;

		ASSERT(q->FileObject == reg->TargetFile);

		wcscpy(evrec->params.linkname, reg->LinkName);

		evrec->params.guid = q->Event;

		ULONG datasize = q->Size - FIELD_OFFSET(TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer);

		

		// Don't just rely on an ASSERT for a production driver -- make it work even

		// in the free build!



		ASSERT(datasize <= sizeof(evrec->params.data));

		memcpy(evrec->params.data, q->CustomDataBuffer, datasize);

		evrec->params.datasize = datasize;

		evrec->params.textoffset = q->NameBufferOffset;

		}						// custom notification



	ExInterlockedInsertTailList(&pdx->events, &evrec->ListEntry, &pdx->eventlock);



	KeSetEvent(reg->Event, IO_NO_INCREMENT, FALSE);



	return STATUS_SUCCESS;

	}							// OnPnpNotify



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



void SubscribeCallback(PDEVICE_OBJECT DeviceObject, PSUBSCRIBE_CALLBACK_CONTEXT context)

	{							// SubscribeCallback

	PREG_RECORD reg = context->reg;

	PDEVICE_EXTENSION pdx = reg->DeviceExtension;

	InterlockedDecrement(&reg->WorkItemCount);

	IoFreeWorkItem(context->item);



	if (reg->DeferredRelease)

		{						// no-one interested anymore

		KillRegRecord(reg);

		ExFreePool(context);

		return;

		}						// no-one interested anymore



	PDEVICE_OBJECT junk;

	UNICODE_STRING name;

	RtlInitUnicodeString(&name, context->name);

	NTSTATUS status = IoGetDeviceObjectPointer(&name, 0, &reg->TargetFile, &junk);

	if (NT_SUCCESS(status))

		{				// register for notifications

		reg->TargetFileReferenced = TRUE;

		status = IoRegisterPlugPlayNotification(EventCategoryTargetDeviceChange, 0,

			reg->TargetFile, pdx->DriverObject, (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) OnPnpNotify,

			reg, &reg->HandleNotificationEntry);

		if (!NT_SUCCESS(status))

			{			// error registering

			KdPrint((DRIVERNAME " - IoRegisterPlugPlayNotification failed - %X\n", status));

			ObDereferenceObject(reg->TargetFile);

			reg->TargetFile = NULL;

			reg->TargetFileReferenced = FALSE;

			}			// error registering

		}				// register for notifications

	else

		KdPrint((DRIVERNAME " - IoGetDeviceObjectPointer failed - %X\n", status));



	ExFreePool(context);

	}							// SubscribeCallback



///////////////////////////////////////////////////////////////////////////////



#pragma PAGEDCODE



void SubscribeForTargetNotifications(PDEVICE_INTERFACE_CHANGE_NOTIFICATION q, PREG_RECORD reg)

	{							// SubscribeForTargetNotifications



	// Use IoAllocateWorkItem so our driver can't disappear from memory while

	// the work item is outstanding. Note that we don't have access to a remove lock

	// in this driver, so we can't just call IoAcquireRemoveLock.



	PIO_WORKITEM item = IoAllocateWorkItem(reg->DeviceExtension->DeviceObject);

	if (!item)

		return;



	ULONG size = sizeof(SUBSCRIBE_CALLBACK_CONTEXT) + q->SymbolicLinkName->Length;

	PSUBSCRIBE_CALLBACK_CONTEXT context = (PSUBSCRIBE_CALLBACK_CONTEXT) ExAllocatePool(NonPagedPool, size);

	if (!context)

		{

		IoFreeWorkItem(item);

		return;

		}



	RtlZeroMemory(context, size);



	context->reg = reg;

	context->item = item;

	RtlCopyMemory(context->name, q->SymbolicLinkName->Buffer, q->SymbolicLinkName->Length);



	InterlockedIncrement(&reg->WorkItemCount);



	IoQueueWorkItem(item, (PIO_WORKITEM_ROUTINE) SubscribeCallback, DelayedWorkQueue, context);

	}							// SubscribeForTargetNotifications





⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -