1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/legacy/wdmaud/deviface.c 5 * PURPOSE: System Audio graph builder 6 * PROGRAMMER: Andrew Greenwood 7 * Johannes Anderwald 8 */ 9 10 #include "wdmaud.h" 11 12 #define NDEBUG 13 #include <debug.h> 14 15 NTSTATUS 16 WdmAudOpenSysAudioDevice( 17 IN LPWSTR DeviceName, 18 OUT PHANDLE Handle) 19 { 20 UNICODE_STRING SymbolicLink; 21 OBJECT_ATTRIBUTES ObjectAttributes; 22 IO_STATUS_BLOCK IoStatusBlock; 23 NTSTATUS Status; 24 25 RtlInitUnicodeString(&SymbolicLink, DeviceName); 26 InitializeObjectAttributes(&ObjectAttributes, &SymbolicLink, OBJ_OPENIF | OBJ_KERNEL_HANDLE, NULL, NULL); 27 28 Status = IoCreateFile(Handle, 29 SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE, 30 &ObjectAttributes, 31 &IoStatusBlock, 32 NULL, 33 0, 34 0, 35 FILE_OPEN, 36 FILE_SYNCHRONOUS_IO_NONALERT, 37 NULL, 38 0, 39 CreateFileTypeNone, 40 NULL, 41 IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK); 42 43 return Status; 44 } 45 46 NTSTATUS 47 NTAPI 48 DeviceInterfaceChangeCallback( 49 IN PVOID NotificationStructure, 50 IN PVOID Context) 51 { 52 DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure; 53 54 DPRINT1("DeviceInterfaceChangeCallback called %p\n", Event); 55 DbgBreakPoint(); 56 return STATUS_SUCCESS; 57 } 58 59 NTSTATUS 60 WdmAudOpenSysAudioDeviceInterfaces( 61 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, 62 IN LPWSTR SymbolicLinkList) 63 { 64 SYSAUDIO_ENTRY * Entry; 65 ULONG Length; 66 67 DPRINT1("WdmAudOpenSysAudioDeviceInterfaces called\n"); 68 69 while(*SymbolicLinkList) 70 { 71 Length = wcslen(SymbolicLinkList) + 1; 72 Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY) + Length * sizeof(WCHAR)); 73 if (!Entry) 74 { 75 return STATUS_INSUFFICIENT_RESOURCES; 76 } 77 78 Entry->SymbolicLink.Length = Length * sizeof(WCHAR); 79 Entry->SymbolicLink.MaximumLength = Length * sizeof(WCHAR); 80 Entry->SymbolicLink.Buffer = (LPWSTR) (Entry + 1); 81 wcscpy(Entry->SymbolicLink.Buffer, SymbolicLinkList); 82 83 InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry); 84 85 DeviceExtension->NumSysAudioDevices++; 86 SymbolicLinkList += Length; 87 } 88 return STATUS_SUCCESS; 89 } 90 91 92 NTSTATUS 93 WdmAudOpenSysAudioDevices( 94 IN PDEVICE_OBJECT DeviceObject, 95 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 96 { 97 NTSTATUS Status = STATUS_SUCCESS; 98 LPWSTR SymbolicLinkList; 99 SYSAUDIO_ENTRY * Entry; 100 ULONG Length; 101 HANDLE hSysAudio; 102 PFILE_OBJECT FileObject; 103 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio\\GLOBAL"); 104 105 if (DeviceExtension->DeviceInterfaceSupport) 106 { 107 Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO, 108 NULL, 109 0, 110 &SymbolicLinkList); 111 112 if (NT_SUCCESS(Status)) 113 { 114 WdmAudOpenSysAudioDeviceInterfaces(DeviceExtension, SymbolicLinkList); 115 FreeItem(SymbolicLinkList); 116 } 117 118 119 Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, 120 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, 121 (PVOID)&KSCATEGORY_SYSAUDIO, 122 DeviceObject->DriverObject, 123 DeviceInterfaceChangeCallback, 124 (PVOID)DeviceExtension, 125 &DeviceExtension->SysAudioNotification); 126 } 127 else 128 { 129 Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY)); 130 if (!Entry) 131 { 132 return STATUS_INSUFFICIENT_RESOURCES; 133 } 134 135 136 Length = wcslen(DeviceName.Buffer) + 1; 137 Entry->SymbolicLink.Length = 0; 138 Entry->SymbolicLink.MaximumLength = Length * sizeof(WCHAR); 139 Entry->SymbolicLink.Buffer = AllocateItem(NonPagedPool, Entry->SymbolicLink.MaximumLength); 140 141 if (!Entry->SymbolicLink.Buffer) 142 { 143 FreeItem(Entry); 144 return STATUS_INSUFFICIENT_RESOURCES; 145 } 146 147 Status = RtlAppendUnicodeStringToString(&Entry->SymbolicLink, &DeviceName); 148 149 if (!NT_SUCCESS(Status)) 150 { 151 FreeItem(Entry->SymbolicLink.Buffer); 152 FreeItem(Entry); 153 return Status; 154 } 155 156 DPRINT("Opening device %S\n", Entry->SymbolicLink.Buffer); 157 Status = WdmAudOpenSysAudioDevice(Entry->SymbolicLink.Buffer, &hSysAudio); 158 if (!NT_SUCCESS(Status)) 159 { 160 DPRINT1("Failed to open sysaudio %x\n", Status); 161 FreeItem(Entry->SymbolicLink.Buffer); 162 FreeItem(Entry); 163 return Status; 164 } 165 166 InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry); 167 DeviceExtension->NumSysAudioDevices++; 168 169 /* get the file object */ 170 Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); 171 if (!NT_SUCCESS(Status)) 172 { 173 DPRINT1("Failed to reference FileObject %x\n", Status); 174 ZwClose(hSysAudio); 175 return Status; 176 } 177 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 178 DeviceExtension->hSysAudio = hSysAudio; 179 DeviceExtension->FileObject = FileObject; 180 } 181 182 return Status; 183 } 184 185 NTSTATUS 186 WdmAudRegisterDeviceInterface( 187 IN PDEVICE_OBJECT PhysicalDeviceObject, 188 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 189 { 190 NTSTATUS Status; 191 UNICODE_STRING SymbolicLinkName; 192 193 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &KSCATEGORY_WDMAUD, NULL, &SymbolicLinkName); 194 if (NT_SUCCESS(Status)) 195 { 196 IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE); 197 RtlFreeUnicodeString(&SymbolicLinkName); 198 //DeviceExtension->DeviceInterfaceSupport = TRUE; 199 return Status; 200 } 201 202 return Status; 203 } 204 205 NTSTATUS 206 WdmAudOpenSysaudio( 207 IN PDEVICE_OBJECT DeviceObject, 208 IN PWDMAUD_CLIENT *pClient) 209 { 210 PWDMAUD_CLIENT Client; 211 PWDMAUD_DEVICE_EXTENSION DeviceExtension; 212 213 /* get device extension */ 214 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 215 216 if (!DeviceExtension->NumSysAudioDevices) 217 { 218 /* wdmaud failed to open sysaudio */ 219 return STATUS_UNSUCCESSFUL; 220 } 221 222 /* sanity check */ 223 ASSERT(!IsListEmpty(&DeviceExtension->SysAudioDeviceList)); 224 225 /* allocate client context struct */ 226 Client = AllocateItem(NonPagedPool, sizeof(WDMAUD_CLIENT)); 227 228 /* check for allocation failure */ 229 if (!Client) 230 { 231 /* not enough memory */ 232 return STATUS_INSUFFICIENT_RESOURCES; 233 } 234 235 /* zero client context struct */ 236 RtlZeroMemory(Client, sizeof(WDMAUD_CLIENT)); 237 238 /* initialize mixer event list */ 239 InitializeListHead(&Client->MixerEventList); 240 241 /* store result */ 242 *pClient = Client; 243 244 /* insert client into list */ 245 ExInterlockedInsertTailList(&DeviceExtension->WdmAudClientList, &Client->Entry, &DeviceExtension->Lock); 246 247 /* done */ 248 return STATUS_SUCCESS; 249 } 250