예제 #1
0
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);
}
예제 #2
0
//////////////////////////////////////////////////////////////////////////
//
//
// 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;
}
예제 #3
0
파일: iorsrce.c 프로젝트: hoangduit/reactos
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;
}
예제 #4
0
//
//	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;
}
예제 #5
0
/**
 * 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;
  }
예제 #6
0
파일: plugplay.c 프로젝트: RPG-7/reactos
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;
}
예제 #7
0
파일: grub4dos.c 프로젝트: Sha0/winvblock
/**
 * 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);
  }
예제 #8
0
파일: plugplay.c 프로젝트: GYGit/reactos
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;
}
예제 #9
0
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;
}