static VOID DeviceInterfaceTest_Func() { NTSTATUS Status; PWSTR SymbolicLinkList; PWSTR SymbolicLinkListPtr; GUID Guid = {0x378de44c, 0x56ef, 0x11d1, {0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd}}; Status = IoGetDeviceInterfaces( &Guid, NULL, 0, &SymbolicLinkList); ok(NT_SUCCESS(Status), "IoGetDeviceInterfaces failed with status 0x%X\n", (unsigned int)Status); if (!NT_SUCCESS(Status)) { return; } DPRINT("IoGetDeviceInterfaces results:\n"); for (SymbolicLinkListPtr = SymbolicLinkList; SymbolicLinkListPtr[0] != 0 && SymbolicLinkListPtr[1] != 0; SymbolicLinkListPtr += wcslen(SymbolicLinkListPtr) + 1) { DPRINT1("Symbolic Link: %S\n", SymbolicLinkListPtr); } #if 0 DPRINT("[PnP Test] Trying to get aliases\n"); for (SymbolicLinkListPtr = SymbolicLinkList; SymbolicLinkListPtr[0] != 0 && SymbolicLinkListPtr[1] != 0; SymbolicLinkListPtr += wcslen(SymbolicLinkListPtr) + 1) { UNICODE_STRING SymbolicLink; UNICODE_STRING AliasSymbolicLink; SymbolicLink.Buffer = SymbolicLinkListPtr; SymbolicLink.Length = SymbolicLink.MaximumLength = wcslen(SymbolicLinkListPtr); RtlInitUnicodeString(&AliasSymbolicLink, NULL); IoGetDeviceInterfaceAlias( &SymbolicLink, &AliasGuid, &AliasSymbolicLink); if (AliasSymbolicLink.Buffer != NULL) { DPRINT("[PnP Test] Original: %S\n", SymbolicLinkListPtr); DPRINT("[PnP Test] Alias: %S\n", AliasSymbolicLink.Buffer); } } #endif ExFreePool(SymbolicLinkList); }
////////////////////////////////////////////////////////////////////////// // // // added by hootch 01172004 NTSTATUS NDCtrlOpenLanScsiBus( OUT PDEVICE_OBJECT *LanScsiDev, OUT PFILE_OBJECT *FileObject ) { NTSTATUS ntStatus; PWSTR symbolicLinkList; UNICODE_STRING objectName; PFILE_OBJECT fileObject; PDEVICE_OBJECT deviceObject; SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ( "[LFS] NDCtrlOpenLanScsiBus: entered.\n")); ASSERT(LanScsiDev); ASSERT(KeGetCurrentIrql() <= PASSIVE_LEVEL); ntStatus = IoGetDeviceInterfaces( &GUID_LANSCSI_BUS_ENUMERATOR_INTERFACE_CLASS, NULL, 0, &symbolicLinkList ); if(!NT_SUCCESS(ntStatus)) { SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ( "[LFS] NDCtrlOpenLanScsiBus: IoGetDeviceInterfaces ntStatus = 0x%x\n", ntStatus)); return ntStatus; } ASSERT(symbolicLinkList != NULL); SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ( "[LFS] NDCtrlOpenLanScsiBus: symbolicLinkList = %ws\n", symbolicLinkList)); RtlInitUnicodeString(&objectName, symbolicLinkList); ntStatus = IoGetDeviceObjectPointer( &objectName, FILE_ALL_ACCESS, &fileObject, &deviceObject ); if(!NT_SUCCESS(ntStatus)) { SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ( "[LFS] NDCtrlOpenLanScsiBus: ntStatus = 0x%x\n", ntStatus)); ExFreePool(symbolicLinkList); return ntStatus; } ExFreePool(symbolicLinkList); *LanScsiDev = deviceObject; *FileObject = fileObject; SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO, ( "NDCtrlOpenLanScsiBus: Done.\n")); return ntStatus; }
NTSTATUS NTAPI IopFetchConfigurationInformation(OUT PWSTR * SymbolicLinkList, IN GUID Guid, IN ULONG ExpectedInterfaces, IN PULONG Interfaces) { NTSTATUS Status; ULONG IntInterfaces = 0; PWSTR IntSymbolicLinkList; /* Get the associated enabled interfaces with the given GUID */ Status = IoGetDeviceInterfaces(&Guid, NULL, 0, SymbolicLinkList); if (!NT_SUCCESS(Status)) { /* Zero output and leave */ if (SymbolicLinkList != 0) { *SymbolicLinkList = 0; } return STATUS_UNSUCCESSFUL; } IntSymbolicLinkList = *SymbolicLinkList; /* Count the number of enabled interfaces by counting the number of symbolic links */ while (*IntSymbolicLinkList != UNICODE_NULL) { IntInterfaces++; IntSymbolicLinkList += wcslen(IntSymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); } /* Matching result will define the result */ Status = (IntInterfaces >= ExpectedInterfaces) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; /* Finally, give back to the caller the number of found interfaces */ *Interfaces = IntInterfaces; return Status; }
// // General ioctl to NDASBUS // NTSTATUS IoctlToLanscsiBus( IN ULONG IoControlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, OUT PULONG BufferNeeded ) { NTSTATUS ntStatus; PWSTR symbolicLinkList; UNICODE_STRING objectName; PFILE_OBJECT fileObject; PDEVICE_OBJECT deviceObject; PIRP irp; KEVENT event; IO_STATUS_BLOCK ioStatus; KDPrint(3,("IoControlCode = %x\n", IoControlCode)); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); ntStatus = IoGetDeviceInterfaces( &GUID_NDAS_BUS_ENUMERATOR_INTERFACE_CLASS, NULL, 0, &symbolicLinkList ); if(!NT_SUCCESS(ntStatus)) { KDPrint(2,("IoGetDeviceInterfaces ntStatus = 0x%x\n", ntStatus)); return ntStatus; } ASSERT(symbolicLinkList != NULL); KDPrint(2,("symbolicLinkList = %ws\n", symbolicLinkList)); RtlInitUnicodeString(&objectName, symbolicLinkList); ntStatus = IoGetDeviceObjectPointer( &objectName, FILE_ALL_ACCESS, &fileObject, &deviceObject ); if(!NT_SUCCESS(ntStatus)) { KDPrint(2,("ntStatus = 0x%x\n", ntStatus)); ExFreePool(symbolicLinkList); return ntStatus; } KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest( IoControlCode, deviceObject, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, FALSE, &event, &ioStatus ); if (irp == NULL) { KDPrint(2,("irp NULL\n")); ExFreePool(symbolicLinkList); ObDereferenceObject(fileObject); return ntStatus; } KDPrint(3,("Before Done...ioStatus.Status = 0x%08x Information = %d\n", ioStatus.Status, ioStatus.Information)); ntStatus = IoCallDriver(deviceObject, irp); if (ntStatus == STATUS_PENDING) { KDPrint(2,("IoCallDriver STATUS_PENDING\n")); KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); ntStatus = ioStatus.Status; } else if(NT_SUCCESS(ntStatus)) { ntStatus = ioStatus.Status; } if(BufferNeeded) *BufferNeeded = (ULONG)ioStatus.Information; ExFreePool(symbolicLinkList); ObDereferenceObject(fileObject); KDPrint(2,("Done...ioStatus.Status = 0x%08x Information = %d\n", ioStatus.Status, ioStatus.Information)); return ntStatus; }
/** * Find and hot-swap to a backing file. Internal. * * We search all filesystems for a particular filename, then swap * to using it as the backing store. This is currently useful for * sector-mapped disks which should really have a file-in-use lock * for the file they represent. Once the backing file is established, * the work item is freed. Otherwise, it is re-enqueued and the * thread will keep trying. */ static BOOLEAN STDCALL WvFilediskHotSwap_( IN WV_SP_FILEDISK_T filedisk, IN PUNICODE_STRING filename ) { NTSTATUS status; GUID vol_guid = GUID_DEVINTERFACE_VOLUME; PWSTR sym_links; PWCHAR pos; KIRQL irql; /* Do we currently have a backing disk? If not, re-enqueue for later. */ if (filedisk->file == NULL) return FALSE; /* * Find the backing volume and use it. We walk a list * of unicode volume device names and check each one for the file. */ status = IoGetDeviceInterfaces(&vol_guid, NULL, 0, &sym_links); if (!NT_SUCCESS(status)) return FALSE; pos = sym_links; status = STATUS_UNSUCCESSFUL; while (*pos != UNICODE_NULL) { UNICODE_STRING path; PFILE_OBJECT vol_file_obj; PDEVICE_OBJECT vol_dev_obj; UNICODE_STRING vol_dos_name; UNICODE_STRING filepath; static const WCHAR obj_path_prefix[] = L"\\??\\"; static const WCHAR path_sep = L'\\'; OBJECT_ATTRIBUTES obj_attrs; HANDLE file = 0; IO_STATUS_BLOCK io_status; RtlInitUnicodeString(&path, pos); /* Get some object pointers for the volume. */ status = IoGetDeviceObjectPointer( &path, FILE_READ_DATA, &vol_file_obj, &vol_dev_obj ); if (!NT_SUCCESS(status)) goto err_obj_ptrs; /* Get the DOS name. */ vol_dos_name.Buffer = NULL; vol_dos_name.Length = vol_dos_name.MaximumLength = 0; status = RtlVolumeDeviceToDosName( vol_file_obj->DeviceObject, &vol_dos_name ); if (!NT_SUCCESS(status)) goto err_dos_name; /* Build the file path. Ugh, what a mess. */ filepath.Length = filepath.MaximumLength = sizeof obj_path_prefix - sizeof UNICODE_NULL + vol_dos_name.Length + sizeof path_sep + filename->Length; filepath.Buffer = wv_malloc(filepath.Length); if (filepath.Buffer == NULL) { status = STATUS_UNSUCCESSFUL; goto err_alloc_buf; } { PCHAR buf = (PCHAR) filepath.Buffer; RtlCopyMemory( buf, obj_path_prefix, sizeof obj_path_prefix - sizeof UNICODE_NULL ); buf += sizeof obj_path_prefix - sizeof UNICODE_NULL; RtlCopyMemory(buf, vol_dos_name.Buffer, vol_dos_name.Length); buf += vol_dos_name.Length; RtlCopyMemory(buf, &path_sep, sizeof path_sep); buf += sizeof path_sep; RtlCopyMemory(buf, filename->Buffer, filename->Length); } /* buf scope */ InitializeObjectAttributes( &obj_attrs, &filepath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL ); /* Look for the file on this volume. */ status = ZwCreateFile( &file, GENERIC_READ | GENERIC_WRITE, &obj_attrs, &io_status, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if (!NT_SUCCESS(status)) goto err_open; /* We could open it. Do the hot-swap. */ { HANDLE old = filedisk->file; filedisk->file = 0; filedisk->offset.QuadPart = 0; filedisk->file = file; ZwClose(old); } /* old scope */ err_open: wv_free(filepath.Buffer); err_alloc_buf: wv_free(vol_dos_name.Buffer); err_dos_name: ObDereferenceObject(vol_file_obj); err_obj_ptrs: /* Walk to the next terminator. */ while (*pos != UNICODE_NULL) pos++; /* If everything succeeded, stop. Otherwise try the next volume. */ if (!NT_SUCCESS(status)) pos++; } /* while */ wv_free(sym_links); /* Success? */ if (NT_SUCCESS(status)) { DBG("Finished hot-swapping.\n"); return TRUE; } return FALSE; }
static NTSTATUS IopGetInterfaceDeviceList(PPLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA DeviceList) { NTSTATUS Status; UNICODE_STRING DeviceInstance; PDEVICE_OBJECT DeviceObject = NULL; ULONG BufferSize = 0; GUID FilterGuid; PZZWSTR SymbolicLinkList = NULL, LinkList; ULONG TotalLength = 0; _SEH2_TRY { ProbeForRead(DeviceList->FilterGuid, sizeof(GUID), sizeof(UCHAR)); RtlCopyMemory(&FilterGuid, DeviceList->FilterGuid, sizeof(GUID)); if (DeviceList->Buffer != NULL && DeviceList->BufferSize != 0) { BufferSize = DeviceList->BufferSize; ProbeForWrite(DeviceList->Buffer, BufferSize, sizeof(UCHAR)); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; Status = IopCaptureUnicodeString(&DeviceInstance, &DeviceList->DeviceInstance); if (NT_SUCCESS(Status)) { /* Get the device object */ DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance); ExFreePool(DeviceInstance.Buffer); } Status = IoGetDeviceInterfaces(&FilterGuid, DeviceObject, DeviceList->Flags, &SymbolicLinkList); ObDereferenceObject(DeviceObject); if (!NT_SUCCESS(Status)) { /* failed */ return Status; } LinkList = SymbolicLinkList; while (*SymbolicLinkList != UNICODE_NULL) { TotalLength += (wcslen(SymbolicLinkList) + 1) * sizeof(WCHAR); SymbolicLinkList += wcslen(SymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); } TotalLength += sizeof(UNICODE_NULL); if (BufferSize >= TotalLength) { RtlCopyMemory(DeviceList->Buffer, SymbolicLinkList, TotalLength * sizeof(WCHAR)); } DeviceList->BufferSize = TotalLength; ExFreePool(LinkList); return STATUS_SUCCESS; }
/** * Stalls the arrival of a GRUB4DOS sector-mapped disk until * the backing disk is found, and stalls driver re-initialization. */ static VOID STDCALL WvFilediskG4dFindBackingDisk_( IN OUT WVL_SP_THREAD_ITEM item ) { static U_WV_LARGE_INT delay_time = {-10000000LL}; SP_WV_FILEDISK_G4D_FIND_BACKING_DISK finder = CONTAINING_RECORD( item, S_WV_FILEDISK_G4D_FIND_BACKING_DISK, item[0] ); WV_SP_FILEDISK_T filedisk_ptr; NTSTATUS status; GUID disk_guid = GUID_DEVINTERFACE_DISK; PWSTR sym_links; PWCHAR pos; HANDLE file; int count = 0; KIRQL irql; /* Establish pointer to the filedisk. */ filedisk_ptr = finder->filedisk; /* Free the work item. */ wv_free(item); do { /* * Find the backing disk and use it. We walk a list * of unicode disk device names and check each one. */ status = IoGetDeviceInterfaces(&disk_guid, NULL, 0, &sym_links); if (!NT_SUCCESS(status)) goto retry; pos = sym_links; while (*pos != UNICODE_NULL) { UNICODE_STRING path; OBJECT_ATTRIBUTES obj_attrs; IO_STATUS_BLOCK io_status; RtlInitUnicodeString(&path, pos); InitializeObjectAttributes( &obj_attrs, &path, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL ); /* Try this disk. */ file = 0; status = ZwCreateFile( &file, GENERIC_READ | GENERIC_WRITE, &obj_attrs, &io_status, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); /* If we could open it, check it out. */ if (NT_SUCCESS(status)) { /* If we liked this disk as our backing disk, stop looking. */ if (WvFilediskG4dCheckDiskMatch_(file, filedisk_ptr)) break; } /* We could not open this disk or didn't like it. Try the next one. */ if (file) ZwClose(file); while (*pos != UNICODE_NULL) pos++; pos++; } /* while */ wv_free(sym_links); /* If we did not find the backing disk, we are a dud. */ if (!NT_SUCCESS(status)) goto retry; /* Use the backing disk and report the sector-mapped disk. */ filedisk_ptr->file = file; /* Release the driver re-initialization stall. */ KeAcquireSpinLock(&WvFindDiskLock, &irql); --WvFindDisk; KeReleaseSpinLock(&WvFindDiskLock, irql); DBG("Found backing disk for filedisk %p\n", (PVOID) filedisk_ptr); return; retry: /* Sleep. */ DBG("Sleeping..."); KeDelayExecutionThread(KernelMode, FALSE, &delay_time.large_int); } while (count++ < 10); }
static NTSTATUS IopGetInterfaceDeviceList(PPLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA DeviceList) { NTSTATUS Status; PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA StackList; UNICODE_STRING DeviceInstance; PDEVICE_OBJECT DeviceObject = NULL; GUID FilterGuid; PZZWSTR SymbolicLinkList = NULL, LinkList; SIZE_T TotalLength; _SEH2_TRY { RtlCopyMemory(&StackList, DeviceList, sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA)); ProbeForRead(StackList.FilterGuid, sizeof(GUID), sizeof(UCHAR)); RtlCopyMemory(&FilterGuid, StackList.FilterGuid, sizeof(GUID)); if (StackList.Buffer != NULL && StackList.BufferSize != 0) { ProbeForWrite(StackList.Buffer, StackList.BufferSize, sizeof(UCHAR)); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; Status = IopCaptureUnicodeString(&DeviceInstance, &StackList.DeviceInstance); if (NT_SUCCESS(Status)) { /* Get the device object */ DeviceObject = IopGetDeviceObjectFromDeviceInstance(&DeviceInstance); if (DeviceInstance.Buffer != NULL) { ExFreePool(DeviceInstance.Buffer); } } Status = IoGetDeviceInterfaces(&FilterGuid, DeviceObject, StackList.Flags, &SymbolicLinkList); ObDereferenceObject(DeviceObject); if (!NT_SUCCESS(Status)) { /* failed */ return Status; } LinkList = SymbolicLinkList; while (*SymbolicLinkList != UNICODE_NULL) { SymbolicLinkList += wcslen(SymbolicLinkList) + (sizeof(UNICODE_NULL) / sizeof(WCHAR)); } TotalLength = ((SymbolicLinkList - LinkList + 1) * sizeof(WCHAR)); _SEH2_TRY { if (StackList.Buffer != NULL && StackList.BufferSize >= TotalLength) { // We've already probed the buffer for writing above. RtlCopyMemory(StackList.Buffer, LinkList, TotalLength); } DeviceList->BufferSize = TotalLength; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ExFreePool(LinkList); _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; ExFreePool(LinkList); return STATUS_SUCCESS; }
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; }