/* * @implemented */ VOID RegisterForTargetDeviceNotification(IN PDEVICE_EXTENSION DeviceExtension, IN PDEVICE_INFORMATION DeviceInformation) { NTSTATUS Status; PFILE_OBJECT FileObject; PDEVICE_OBJECT DeviceObject; /* Get device object */ Status = IoGetDeviceObjectPointer(&(DeviceInformation->DeviceName), FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject); if (!NT_SUCCESS(Status)) { return; } /* And simply register for notifications */ Status = IoRegisterPlugPlayNotification(EventCategoryTargetDeviceChange, 0, FileObject, DeviceExtension->DriverObject, MountMgrTargetDeviceNotification, DeviceInformation, &(DeviceInformation->TargetDeviceNotificationEntry)); if (!NT_SUCCESS(Status)) { DeviceInformation->TargetDeviceNotificationEntry = NULL; } ObDereferenceObject(FileObject); return; }
NTSTATUS SysAudioRegisterNotifications( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT DeviceObject) { NTSTATUS Status; PSYSAUDIODEVEXT DeviceExtension; DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension; Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&KS_CATEGORY_AUDIO, DriverObject, DeviceInterfaceChangeCallback, (PVOID)DeviceObject, (PVOID*)&DeviceExtension->KsAudioNotificationEntry); if (!NT_SUCCESS(Status)) { DPRINT("IoRegisterPlugPlayNotification failed with %x\n", Status); } Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&DMOCATEGORY_ACOUSTIC_ECHO_CANCEL, DriverObject, DeviceInterfaceChangeCallback, (PVOID)DeviceObject, (PVOID*)&DeviceExtension->EchoCancelNotificationEntry); if (!NT_SUCCESS(Status)) { /* ignore failure for now */ DPRINT("IoRegisterPlugPlayNotification failed for DMOCATEGORY_ACOUSTIC_ECHO_CANCEL\n", Status); } return STATUS_SUCCESS; }
static VOID Test_IoRegisterPlugPlayNotification(VOID) { NTSTATUS Status; PVOID NotificationEntry; Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&GUID_DEVICE_SYS_BUTTON, KmtDriverObject, NotificationCallback, &NotificationContext, &NotificationEntry); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "PlugPlayNotification not registered\n")) { Status = IoUnregisterPlugPlayNotification(NotificationEntry); ok_eq_hex(Status, STATUS_SUCCESS); } }
NTSTATUS mydrvEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath){ UNREFERENCED_PARAMETER(pRegPath); UNICODE_STRING uKbdClassDrv; NTSTATUS status = STATUS_UNSUCCESSFUL; DbgPrint("Keyboard Filter Driver - DriverEntry\nCompiled at " __TIME__ " on " __DATE__ "\n"); //DbgPrint("sizeof(DEVICE_EXTENSION): %llu", sizeof(KBDFNFLT_DEVICE_EXTENSION)); //DbgPrint("offset, size: %llu, %llu", FIELD_OFFSET(KBDFNFLT_DEVICE_EXTENSION, pKeyboardDevice), FIELD_SIZE(KBDFNFLT_DEVICE_EXTENSION, pKeyboardDevice)); //DbgPrint("offset, size: %llu, %llu", FIELD_OFFSET(KBDFNFLT_DEVICE_EXTENSION, pKbdClassDrv), FIELD_SIZE(KBDFNFLT_DEVICE_EXTENSION, pKbdClassDrv)); //DbgPrint("offset, size: %llu, %llu", FIELD_OFFSET(KBDFNFLT_DEVICE_EXTENSION, pDevObjString), FIELD_SIZE(KBDFNFLT_DEVICE_EXTENSION, pDevObjString)); //DbgPrint("offset, size: %llu, %llu", FIELD_OFFSET(KBDFNFLT_DEVICE_EXTENSION, kState), FIELD_SIZE(KBDFNFLT_DEVICE_EXTENSION, kState)); //DbgPrint("offset, size: %llu, %llu", FIELD_OFFSET(KBDFNFLT_DEVICE_EXTENSION, workitem), 0);//FIELD_SIZE(KBDFNFLT_DEVICE_EXTENSION, workitem)); ///////////////////////////////////////////////////////////////////////////////////////// // Fill in IRP dispatch table in the DriverObject to handle I/O Request Packets (IRPs) ///////////////////////////////////////////////////////////////////////////////////////// // For a filter driver, we want pass down ALL IRP_MJ_XX requests to the driver which // we are hooking except for those we are interested in modifying. for (int i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) #pragma warning(suppress: 28168) pDrvObj->MajorFunction[i] = dispatchPassDown; DbgPrint("Filled dispatch table with generic pass down routine...\n"); //Explicitly fill in the IRP's we want to hook pDrvObj->MajorFunction[IRP_MJ_READ] = dispatchRead; //Create a keyboard device object PDEVICE_OBJECT pKbdFnFltDevice = NULL; status = IoCreateDevice(pDrvObj, sizeof(KBDFNFLT_DEVICE_EXTENSION) + IoSizeofWorkItem(), NULL, //no name FILE_DEVICE_KEYBOARD, 0, TRUE, &pKbdFnFltDevice); //Make sure the device was created ok if (status) return status; RtlInitUnicodeString(&uKbdClassDrv, KBDCLASS_NAME); status = ObReferenceObjectByName(&uKbdClassDrv, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, 0, IoDriverObjectType, KernelMode, NULL, &((PKBDFNFLT_DEVICE_EXTENSION)pKbdFnFltDevice->DeviceExtension)->pKbdClassDrv); if (status){ IoDeleteDevice(pKbdFnFltDevice); return status; } GUID kbdDevClass = GUID_CLASS_KEYBOARD; PIO_WORKITEM pWorkitem = (PIO_WORKITEM)&((PKBDFNFLT_DEVICE_EXTENSION)pKbdFnFltDevice->DeviceExtension)->workitem; IoInitializeWorkItem(pKbdFnFltDevice, pWorkitem); ((PKBDFNFLT_DEVICE_EXTENSION)pKbdFnFltDevice->DeviceExtension)->pWorkitem = pWorkitem; //PIO_WORKITEM pWorkitem = ExAllocatePoolWithTag(NonPagedPool, IoSizeofWorkItem(), g_poolTag); //if (!pWorkitem){ // //} DbgPrint("%p", &((PKBDFNFLT_DEVICE_EXTENSION)pKbdFnFltDevice->DeviceExtension)->pKeyboardDevice); DbgPrint("%p", &((PKBDFNFLT_DEVICE_EXTENSION)pKbdFnFltDevice->DeviceExtension)->pKbdClassDrv); DbgPrint("%p", &((PKBDFNFLT_DEVICE_EXTENSION)pKbdFnFltDevice->DeviceExtension)->pDevObjString); DbgPrint("%p", &((PKBDFNFLT_DEVICE_EXTENSION)pKbdFnFltDevice->DeviceExtension)->keyState); DbgPrint("%p", &((PKBDFNFLT_DEVICE_EXTENSION)pKbdFnFltDevice->DeviceExtension)->workitem); //IoInitializeWorkItem(&pKbdFnFltDevice) //PVOID pNotificationEntry = NULL; status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, &kbdDevClass, pDrvObj, keyboardAddedOrRemoved, pKbdFnFltDevice, &g_pNotificationEntry); if (status){ DbgPrint("something went wrong %lX", status); IoUninitializeWorkItem(pWorkitem); IoDeleteDevice(pKbdFnFltDevice); return status; } //Go ahead and hook the keyboard now //status = hookKeyboard(pDrvObj); //if (status){ // DbgPrint("something went wrong%lX", status); // return status; //} DbgPrint("Hooked IRP_MJ_READ routine...\n"); // Set the DriverUnload procedure pDrvObj->DriverUnload = mydrvUnload; DbgPrint("Set DriverUnload function pointer...\n"); DbgPrint("Exiting Driver Entry......\n"); return STATUS_SUCCESS; }
BOOLEAN NTAPI INIT_FUNCTION PoInitSystem(IN ULONG BootPhase) { PVOID NotificationEntry; PCHAR CommandLine; BOOLEAN ForceAcpiDisable = FALSE; /* Check if this is phase 1 init */ if (BootPhase == 1) { /* Register power button notification */ IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&GUID_DEVICE_SYS_BUTTON, IopRootDeviceNode-> PhysicalDeviceObject->DriverObject, PopAddRemoveSysCapsCallback, NULL, &NotificationEntry); /* Register lid notification */ IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&GUID_DEVICE_LID, IopRootDeviceNode-> PhysicalDeviceObject->DriverObject, PopAddRemoveSysCapsCallback, NULL, &NotificationEntry); return TRUE; } /* Get the Command Line */ CommandLine = KeLoaderBlock->LoadOptions; /* Upcase it */ _strupr(CommandLine); /* Check for ACPI disable */ if (strstr(CommandLine, "NOACPI")) ForceAcpiDisable = TRUE; if (ForceAcpiDisable) { /* Set the ACPI State to False if it's been forced that way */ PopAcpiPresent = FALSE; } else { /* Otherwise check if the LoaderBlock has a ACPI Table */ PopAcpiPresent = KeLoaderBlock->Extension->AcpiTable != NULL ? TRUE : FALSE; } /* Initialize volume support */ InitializeListHead(&PopVolumeDevices); KeInitializeGuardedMutex(&PopVolumeLock); /* Initialize support for dope */ KeInitializeSpinLock(&PopDopeGlobalLock); /* Initialize support for shutdown waits and work-items */ PopInitShutdownList(); return TRUE; }
NTSTATUS ToastMon_EvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: ToastMon_EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a device object to represent a new instance of toaster device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES attributes; NTSTATUS status = STATUS_SUCCESS; WDFDEVICE device; PDEVICE_EXTENSION deviceExtension; KdPrint( ("ToastMon_EvtDeviceAdd routine\n")); UNREFERENCED_PARAMETER(Driver); PAGED_CODE(); // // Specify the size of device extension where we track per device // context. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_EXTENSION); attributes.EvtCleanupCallback = ToastMon_EvtDeviceContextCleanup; // // Create a framework device object.This call will inturn create // a WDM deviceobject, attach to the lower stack and set the // appropriate flags and attributes. // status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { KdPrint( ("WdfDeviceCreate failed with Status 0x%x\n", status)); return status; } // // Get the DeviceExtension and initialize it. // deviceExtension = GetDeviceExtension(device); deviceExtension->WdfDevice = device; // // Create a collection to store information about target devices. // WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfCollectionCreate(&attributes, &deviceExtension->TargetDeviceCollection); if (!NT_SUCCESS(status)) { KdPrint( ("WdfCollectionCreate failed with status 0x%x\n", status)); return status; } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = device; status = WdfWaitLockCreate(&attributes, &deviceExtension->TargetDeviceCollectionLock); if (!NT_SUCCESS(status)) { KdPrint( ("WdfWaitLockCreate failed with status 0x%x\n", status)); return status; } // // Register for TOASTER device interface change notification. // We will get GUID_DEVICE_INTERFACE_ARRIVAL and // GUID_DEVICE_INTERFACE_REMOVAL notification when the toaster // device is started and removed. // Framework doesn't provide a WDF interface to register for interface change // notification. However if the target device is opened by symboliclink using // IoTarget, framework registers itself EventCategoryTargetDeviceChange // notification on the handle and responds to the pnp notifications. // // Note that as soon as you register, arrival notification will be sent // about all existing toaster devices even before this device is started. So if // you cannot handle these notification before start then you should register this in // PrepareHardware or SelfManagedIoInit callback. // You must unregister this notification when the device is removed in the // DeviceContextCleanup callback. This call takes a reference on the driverobject. // So if you don't unregister it will prevent the driver from unloading. // status = IoRegisterPlugPlayNotification ( EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&GUID_DEVINTERFACE_TOASTER, WdfDriverWdmGetDriverObject(WdfDeviceGetDriver(device)), (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) ToastMon_PnpNotifyInterfaceChange, (PVOID)deviceExtension, &deviceExtension->NotificationHandle); if (!NT_SUCCESS(status)) { KdPrint(("RegisterPnPNotifiction failed: 0x%x\n", status)); return status; } RegisterForWMINotification(deviceExtension); return status; }
void add_volume_device(superblock* sb, PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath, UINT64 length, ULONG disk_num, ULONG part_num) { NTSTATUS Status; LIST_ENTRY* le; PDEVICE_OBJECT DeviceObject; volume_child* vc; PFILE_OBJECT FileObject; UNICODE_STRING devpath2; BOOL inserted = FALSE, new_pdo = FALSE; pdo_device_extension* pdode = NULL; PDEVICE_OBJECT pdo = NULL; if (devpath->Length == 0) return; ExAcquireResourceExclusiveLite(&pdo_list_lock, TRUE); le = pdo_list.Flink; while (le != &pdo_list) { pdo_device_extension* pdode2 = CONTAINING_RECORD(le, pdo_device_extension, list_entry); if (RtlCompareMemory(&pdode2->uuid, &sb->uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { pdode = pdode2; break; } le = le->Flink; } Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &FileObject, &DeviceObject); if (!NT_SUCCESS(Status)) { ERR("IoGetDeviceObjectPointer returned %08x\n", Status); ExReleaseResourceLite(&pdo_list_lock); return; } if (!pdode) { if (no_pnp) { Status = IoReportDetectedDevice(drvobj, InterfaceTypeUndefined, 0xFFFFFFFF, 0xFFFFFFFF, NULL, NULL, 0, &pdo); if (!NT_SUCCESS(Status)) { ERR("IoReportDetectedDevice returned %08x\n", Status); ExReleaseResourceLite(&pdo_list_lock); return; } pdode = ExAllocatePoolWithTag(NonPagedPool, sizeof(pdo_device_extension), ALLOC_TAG); if (!pdode) { ERR("out of memory\n"); ExReleaseResourceLite(&pdo_list_lock); return; } } else { Status = IoCreateDevice(drvobj, sizeof(pdo_device_extension), NULL, FILE_DEVICE_DISK, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &pdo); if (!NT_SUCCESS(Status)) { ERR("IoCreateDevice returned %08x\n", Status); ExReleaseResourceLite(&pdo_list_lock); goto fail; } pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; pdode = pdo->DeviceExtension; } RtlZeroMemory(pdode, sizeof(pdo_device_extension)); pdode->type = VCB_TYPE_PDO; pdode->pdo = pdo; pdode->uuid = sb->uuid; ExInitializeResourceLite(&pdode->child_lock); InitializeListHead(&pdode->children); pdode->num_children = sb->num_devices; pdode->children_loaded = 0; pdo->Flags &= ~DO_DEVICE_INITIALIZING; pdo->SectorSize = (USHORT)sb->sector_size; ExAcquireResourceExclusiveLite(&pdode->child_lock, TRUE); new_pdo = TRUE; } else { ExAcquireResourceExclusiveLite(&pdode->child_lock, TRUE); ExConvertExclusiveToSharedLite(&pdo_list_lock); le = pdode->children.Flink; while (le != &pdode->children) { volume_child* vc2 = CONTAINING_RECORD(le, volume_child, list_entry); if (RtlCompareMemory(&vc2->uuid, &sb->dev_item.device_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { // duplicate, ignore ExReleaseResourceLite(&pdode->child_lock); ExReleaseResourceLite(&pdo_list_lock); goto fail; } le = le->Flink; } } vc = ExAllocatePoolWithTag(PagedPool, sizeof(volume_child), ALLOC_TAG); if (!vc) { ERR("out of memory\n"); ExReleaseResourceLite(&pdode->child_lock); ExReleaseResourceLite(&pdo_list_lock); goto fail; } vc->uuid = sb->dev_item.device_uuid; vc->devid = sb->dev_item.dev_id; vc->generation = sb->generation; vc->notification_entry = NULL; Status = IoRegisterPlugPlayNotification(EventCategoryTargetDeviceChange, 0, FileObject, drvobj, pnp_removal, pdode, &vc->notification_entry); if (!NT_SUCCESS(Status)) WARN("IoRegisterPlugPlayNotification returned %08x\n", Status); vc->devobj = DeviceObject; vc->fileobj = FileObject; devpath2 = *devpath; // The PNP path sometimes begins \\?\ and sometimes \??\. We need to remove this prefix // so we can compare properly if the device is removed. if (devpath->Length > 4 * sizeof(WCHAR) && devpath->Buffer[0] == '\\' && (devpath->Buffer[1] == '\\' || devpath->Buffer[1] == '?') && devpath->Buffer[2] == '?' && devpath->Buffer[3] == '\\') { devpath2.Buffer = &devpath2.Buffer[3]; devpath2.Length -= 3 * sizeof(WCHAR); devpath2.MaximumLength -= 3 * sizeof(WCHAR); } vc->pnp_name.Length = vc->pnp_name.MaximumLength = devpath2.Length; vc->pnp_name.Buffer = ExAllocatePoolWithTag(PagedPool, devpath2.Length, ALLOC_TAG); if (vc->pnp_name.Buffer) RtlCopyMemory(vc->pnp_name.Buffer, devpath2.Buffer, devpath2.Length); else { ERR("out of memory\n"); vc->pnp_name.Length = vc->pnp_name.MaximumLength = 0; } vc->size = length; vc->seeding = sb->flags & BTRFS_SUPERBLOCK_FLAGS_SEEDING ? TRUE : FALSE; vc->disk_num = disk_num; vc->part_num = part_num; vc->had_drive_letter = FALSE; le = pdode->children.Flink; while (le != &pdode->children) { volume_child* vc2 = CONTAINING_RECORD(le, volume_child, list_entry); if (vc2->generation < vc->generation) { if (le == pdode->children.Flink) pdode->num_children = sb->num_devices; InsertHeadList(vc2->list_entry.Blink, &vc->list_entry); inserted = TRUE; break; } le = le->Flink; } if (!inserted) InsertTailList(&pdode->children, &vc->list_entry); pdode->children_loaded++; if (pdode->vde && pdode->vde->mounted_device) { device_extension* Vcb = pdode->vde->mounted_device->DeviceExtension; ExAcquireResourceExclusiveLite(&Vcb->tree_lock, TRUE); le = Vcb->devices.Flink; while (le != &Vcb->devices) { device* dev = CONTAINING_RECORD(le, device, list_entry); if (!dev->devobj && RtlCompareMemory(&dev->devitem.device_uuid, &sb->dev_item.device_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { dev->devobj = DeviceObject; dev->disk_num = disk_num; dev->part_num = part_num; init_device(Vcb, dev, FALSE); break; } le = le->Flink; } ExReleaseResourceLite(&Vcb->tree_lock); } if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) { pdode->removable = TRUE; if (pdode->vde && pdode->vde->device) pdode->vde->device->Characteristics |= FILE_REMOVABLE_MEDIA; } if (pdode->num_children == pdode->children_loaded || (pdode->children_loaded == 1 && allow_degraded_mount(&sb->uuid))) { if (pdode->num_children == 1) { Status = remove_drive_letter(mountmgr, devpath); if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) WARN("remove_drive_letter returned %08x\n", Status); vc->had_drive_letter = NT_SUCCESS(Status); } else { le = pdode->children.Flink; while (le != &pdode->children) { UNICODE_STRING name; vc = CONTAINING_RECORD(le, volume_child, list_entry); name.Length = name.MaximumLength = vc->pnp_name.Length + (3 * sizeof(WCHAR)); name.Buffer = ExAllocatePoolWithTag(PagedPool, name.Length, ALLOC_TAG); if (!name.Buffer) { ERR("out of memory\n"); ExReleaseResourceLite(&pdode->child_lock); ExReleaseResourceLite(&pdo_list_lock); goto fail; } RtlCopyMemory(name.Buffer, L"\\??", 3 * sizeof(WCHAR)); RtlCopyMemory(&name.Buffer[3], vc->pnp_name.Buffer, vc->pnp_name.Length); Status = remove_drive_letter(mountmgr, &name); if (!NT_SUCCESS(Status) && Status != STATUS_NOT_FOUND) WARN("remove_drive_letter returned %08x\n", Status); ExFreePool(name.Buffer); vc->had_drive_letter = NT_SUCCESS(Status); le = le->Flink; } } if ((!new_pdo || !no_pnp) && pdode->vde) { Status = IoSetDeviceInterfaceState(&pdode->vde->bus_name, TRUE); if (!NT_SUCCESS(Status)) WARN("IoSetDeviceInterfaceState returned %08x\n", Status); } } ExReleaseResourceLite(&pdode->child_lock); if (new_pdo) { control_device_extension* cde = master_devobj->DeviceExtension; InsertTailList(&pdo_list, &pdode->list_entry); if (!no_pnp) IoInvalidateDeviceRelations(cde->buspdo, BusRelations); } ExReleaseResourceLite(&pdo_list_lock); if (new_pdo && no_pnp) AddDevice(drvobj, pdo); return; fail: ObDereferenceObject(FileObject); }
NTSTATUS WdmAudOpenSysAudioDevices( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) { NTSTATUS Status = STATUS_SUCCESS; LPWSTR SymbolicLinkList; SYSAUDIO_ENTRY * Entry; ULONG Length; HANDLE hSysAudio; PFILE_OBJECT FileObject; UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio\\GLOBAL"); if (DeviceExtension->DeviceInterfaceSupport) { Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO, NULL, 0, &SymbolicLinkList); if (NT_SUCCESS(Status)) { WdmAudOpenSysAudioDeviceInterfaces(DeviceExtension, SymbolicLinkList); FreeItem(SymbolicLinkList); } Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&KSCATEGORY_SYSAUDIO, DeviceObject->DriverObject, DeviceInterfaceChangeCallback, (PVOID)DeviceExtension, &DeviceExtension->SysAudioNotification); } else { Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY)); if (!Entry) { return STATUS_INSUFFICIENT_RESOURCES; } Length = wcslen(DeviceName.Buffer) + 1; Entry->SymbolicLink.Length = 0; Entry->SymbolicLink.MaximumLength = Length * sizeof(WCHAR); Entry->SymbolicLink.Buffer = AllocateItem(NonPagedPool, Entry->SymbolicLink.MaximumLength); if (!Entry->SymbolicLink.Buffer) { FreeItem(Entry); return STATUS_INSUFFICIENT_RESOURCES; } Status = RtlAppendUnicodeStringToString(&Entry->SymbolicLink, &DeviceName); if (!NT_SUCCESS(Status)) { FreeItem(Entry->SymbolicLink.Buffer); FreeItem(Entry); return Status; } InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry); DeviceExtension->NumSysAudioDevices++; DPRINT("Opening device %S\n", Entry->SymbolicLink.Buffer); Status = WdmAudOpenSysAudioDevice(Entry->SymbolicLink.Buffer, &hSysAudio); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to open sysaudio %x\n", Status); return Status; } /* get the file object */ Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to reference FileObject %x\n", Status); ZwClose(hSysAudio); return Status; } DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; DeviceExtension->hSysAudio = hSysAudio; DeviceExtension->FileObject = FileObject; } return Status; }