1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/backpln/portcls/connection.c 5 * PURPOSE: portcls physical connection registration 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 10 #include "private.hpp" 11 12 extern 13 "C" 14 NTSYSAPI 15 BOOLEAN 16 NTAPI 17 RtlCreateUnicodeString( 18 PUNICODE_STRING DestinationString, 19 PCWSTR SourceString 20 ); 21 22 23 class CUnregisterPhysicalConnection : public IUnregisterPhysicalConnection 24 { 25 public: 26 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 27 28 STDMETHODIMP_(ULONG) AddRef() 29 { 30 InterlockedIncrement(&m_Ref); 31 return m_Ref; 32 } 33 STDMETHODIMP_(ULONG) Release() 34 { 35 InterlockedDecrement(&m_Ref); 36 37 if (!m_Ref) 38 { 39 delete this; 40 return 0; 41 } 42 return m_Ref; 43 } 44 IMP_IUnregisterPhysicalConnection; 45 46 CUnregisterPhysicalConnection(IUnknown *OuterUnknown){} 47 48 virtual ~CUnregisterPhysicalConnection(){} 49 50 protected: 51 LONG m_Ref; 52 53 }; 54 55 NTSTATUS 56 NTAPI 57 CUnregisterPhysicalConnection::QueryInterface( 58 IN REFIID refiid, 59 OUT PVOID* Output) 60 { 61 if (IsEqualGUIDAligned(refiid, IID_IUnregisterPhysicalConnection) || 62 IsEqualGUIDAligned(refiid, IID_IUnknown)) 63 { 64 *Output = PVOID(PUNKNOWN(this)); 65 66 PUNKNOWN(*Output)->AddRef(); 67 return STATUS_SUCCESS; 68 } 69 70 return STATUS_UNSUCCESSFUL; 71 } 72 73 static 74 NTSTATUS 75 UnRegisterConnection( 76 IN OUT PDEVICE_OBJECT DeviceObject, 77 IN PUNKNOWN FromUnknown, 78 IN PUNICODE_STRING FromString, 79 IN ULONG FromPin, 80 IN PUNKNOWN ToUnknown, 81 IN PUNICODE_STRING ToString, 82 IN ULONG ToPin) 83 { 84 UNIMPLEMENTED 85 return STATUS_NOT_IMPLEMENTED; 86 } 87 88 NTSTATUS 89 NTAPI 90 CUnregisterPhysicalConnection::UnregisterPhysicalConnection( 91 IN PDEVICE_OBJECT DeviceObject, 92 IN PUNKNOWN FromUnknown, 93 IN ULONG FromPin, 94 IN PUNKNOWN ToUnknown, 95 IN ULONG ToPin) 96 { 97 if (!DeviceObject || !FromUnknown || !ToUnknown) 98 return STATUS_INVALID_PARAMETER; 99 100 return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin); 101 } 102 103 NTSTATUS 104 NTAPI 105 CUnregisterPhysicalConnection::UnregisterPhysicalConnectionToExternal( 106 IN PDEVICE_OBJECT DeviceObject, 107 IN PUNKNOWN FromUnknown, 108 IN ULONG FromPin, 109 IN PUNICODE_STRING ToString, 110 IN ULONG ToPin) 111 { 112 if (!DeviceObject || !FromUnknown || !ToString) 113 return STATUS_INVALID_PARAMETER; 114 115 return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin); 116 } 117 118 NTSTATUS 119 NTAPI 120 CUnregisterPhysicalConnection::UnregisterPhysicalConnectionFromExternal( 121 IN PDEVICE_OBJECT DeviceObject, 122 IN PUNICODE_STRING FromString, 123 IN ULONG FromPin, 124 IN PUNKNOWN ToUnknown, 125 IN ULONG ToPin) 126 { 127 if (!DeviceObject || !FromString || !ToUnknown) 128 return STATUS_INVALID_PARAMETER; 129 130 return UnRegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin); 131 } 132 133 NTSTATUS 134 NTAPI 135 NewIUnregisterPhysicalConnection( 136 OUT PUNREGISTERPHYSICALCONNECTION *OutConnection) 137 { 138 139 CUnregisterPhysicalConnection *new_ptr = new(NonPagedPool, TAG_PORTCLASS) CUnregisterPhysicalConnection(NULL); 140 141 if (!new_ptr) 142 return STATUS_INSUFFICIENT_RESOURCES; 143 144 new_ptr->AddRef(); 145 *OutConnection = (PUNREGISTERPHYSICALCONNECTION)new_ptr; 146 return STATUS_SUCCESS; 147 } 148 149 NTSTATUS 150 RegisterConnection( 151 IN OUT PDEVICE_OBJECT DeviceObject, 152 IN PUNKNOWN FromUnknown, 153 IN PUNICODE_STRING FromString, 154 IN ULONG FromPin, 155 IN PUNKNOWN ToUnknown, 156 IN PUNICODE_STRING ToString, 157 IN ULONG ToPin) 158 { 159 PSUBDEVICE_DESCRIPTOR FromSubDeviceDescriptor = NULL, ToSubDeviceDescriptor = NULL; 160 PSYMBOLICLINK_ENTRY SymEntry; 161 ISubdevice * FromSubDevice = NULL, *ToSubDevice = NULL; 162 NTSTATUS Status; 163 PPHYSICAL_CONNECTION_ENTRY FromEntry = NULL, ToEntry = NULL; 164 165 if (FromUnknown) 166 { 167 Status = FromUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&FromSubDevice); 168 if (!NT_SUCCESS(Status)) 169 goto cleanup; 170 171 Status = FromSubDevice->GetDescriptor(&FromSubDeviceDescriptor); 172 if (!NT_SUCCESS(Status)) 173 goto cleanup; 174 175 if (IsListEmpty(&FromSubDeviceDescriptor->SymbolicLinkList)) 176 { 177 Status = STATUS_UNSUCCESSFUL; 178 goto cleanup; 179 } 180 181 SymEntry = (PSYMBOLICLINK_ENTRY)CONTAINING_RECORD(FromSubDeviceDescriptor->SymbolicLinkList.Flink, SYMBOLICLINK_ENTRY, Entry); 182 FromString = &SymEntry->SymbolicLink; 183 } 184 185 186 if (ToUnknown) 187 { 188 Status = ToUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&ToSubDevice); 189 if (!NT_SUCCESS(Status)) 190 goto cleanup; 191 192 Status = ToSubDevice->GetDescriptor(&ToSubDeviceDescriptor); 193 if (!NT_SUCCESS(Status)) 194 goto cleanup; 195 196 if (IsListEmpty(&ToSubDeviceDescriptor->SymbolicLinkList)) 197 { 198 Status = STATUS_UNSUCCESSFUL; 199 goto cleanup; 200 } 201 202 203 SymEntry = (PSYMBOLICLINK_ENTRY)CONTAINING_RECORD(ToSubDeviceDescriptor->SymbolicLinkList.Flink, SYMBOLICLINK_ENTRY, Entry); 204 ToString = &SymEntry->SymbolicLink; 205 206 } 207 208 if (FromSubDeviceDescriptor) 209 { 210 FromEntry = (PPHYSICAL_CONNECTION_ENTRY)AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION_ENTRY) + ToString->MaximumLength + sizeof(WCHAR), TAG_PORTCLASS); 211 if (!FromEntry) 212 { 213 Status = STATUS_INSUFFICIENT_RESOURCES; 214 goto cleanup; 215 } 216 } 217 218 if (ToSubDeviceDescriptor) 219 { 220 ToEntry = (PPHYSICAL_CONNECTION_ENTRY)AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION_ENTRY) + FromString->MaximumLength + sizeof(WCHAR), TAG_PORTCLASS); 221 if (!ToEntry) 222 { 223 Status = STATUS_INSUFFICIENT_RESOURCES; 224 goto cleanup; 225 } 226 } 227 228 if (FromSubDeviceDescriptor) 229 { 230 FromEntry->FromPin = FromPin; 231 FromEntry->Connection.Pin = ToPin; 232 FromEntry->Connection.Size = sizeof(KSPIN_PHYSICALCONNECTION) + ToString->MaximumLength + sizeof(WCHAR); 233 RtlMoveMemory(&FromEntry->Connection.SymbolicLinkName, ToString->Buffer, ToString->MaximumLength); 234 FromEntry->Connection.SymbolicLinkName[ToString->Length / sizeof(WCHAR)] = UNICODE_NULL; 235 236 InsertTailList(&FromSubDeviceDescriptor->PhysicalConnectionList, &FromEntry->Entry); 237 } 238 239 240 if (ToSubDeviceDescriptor) 241 { 242 ToEntry->FromPin = ToPin; 243 ToEntry->Connection.Pin = FromPin; 244 ToEntry->Connection.Size = sizeof(KSPIN_PHYSICALCONNECTION) + FromString->MaximumLength + sizeof(WCHAR); 245 RtlMoveMemory(&ToEntry->Connection.SymbolicLinkName, FromString->Buffer, FromString->MaximumLength); 246 ToEntry->Connection.SymbolicLinkName[FromString->Length / sizeof(WCHAR)] = UNICODE_NULL; 247 248 InsertTailList(&ToSubDeviceDescriptor->PhysicalConnectionList, &ToEntry->Entry); 249 250 } 251 252 return STATUS_SUCCESS; 253 254 cleanup: 255 256 if (FromSubDevice) 257 FromSubDevice->Release(); 258 259 if (ToSubDevice) 260 ToSubDevice->Release(); 261 262 if (FromEntry) 263 FreeItem(FromEntry, TAG_PORTCLASS); 264 265 if (ToEntry) 266 FreeItem(ToEntry, TAG_PORTCLASS); 267 268 return Status; 269 } 270 271 NTSTATUS 272 NTAPI 273 PcRegisterPhysicalConnection( 274 IN PDEVICE_OBJECT DeviceObject, 275 IN PUNKNOWN FromUnknown, 276 IN ULONG FromPin, 277 IN PUNKNOWN ToUnknown, 278 IN ULONG ToPin) 279 { 280 DPRINT("PcRegisterPhysicalConnection\n"); 281 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 282 283 if (!DeviceObject || !FromUnknown || !ToUnknown) 284 return STATUS_INVALID_PARAMETER; 285 286 return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin); 287 } 288 289 NTSTATUS 290 NTAPI 291 PcRegisterPhysicalConnectionFromExternal( 292 IN PDEVICE_OBJECT DeviceObject, 293 IN PUNICODE_STRING FromString, 294 IN ULONG FromPin, 295 IN PUNKNOWN ToUnknown, 296 IN ULONG ToPin) 297 { 298 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 299 300 if (!DeviceObject || !FromString || !ToUnknown) 301 return STATUS_INVALID_PARAMETER; 302 303 return RegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin); 304 } 305 306 NTSTATUS 307 NTAPI 308 PcRegisterPhysicalConnectionToExternal( 309 IN PDEVICE_OBJECT DeviceObject, 310 IN PUNKNOWN FromUnknown, 311 IN ULONG FromPin, 312 IN PUNICODE_STRING ToString, 313 IN ULONG ToPin) 314 { 315 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 316 317 if (!DeviceObject || !FromUnknown || !ToString) 318 return STATUS_INVALID_PARAMETER; 319 320 return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin); 321 } 322