79855baac61986b9a0013ea9e0ad90b06adec0ac
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / connection.c
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.h"
11
12 typedef struct
13 {
14 IUnregisterPhysicalConnectionVtbl *lpVtbl;
15 LONG ref;
16
17 }IUnregisterPhysicalConnectionImpl;
18
19 NTSTATUS
20 NTAPI
21 IUnregisterPhysicalConnection_fnQueryInterface(
22 IUnregisterPhysicalConnection* iface,
23 IN REFIID refiid,
24 OUT PVOID* Output)
25 {
26 IUnregisterPhysicalConnectionImpl * This = (IUnregisterPhysicalConnectionImpl*)iface;
27
28 if (IsEqualGUIDAligned(refiid, &IID_IUnregisterPhysicalConnection) ||
29 IsEqualGUIDAligned(refiid, &IID_IUnknown))
30 {
31 *Output = &This->lpVtbl;
32 InterlockedIncrement(&This->ref);
33 return STATUS_SUCCESS;
34 }
35
36 return STATUS_UNSUCCESSFUL;
37 }
38
39 ULONG
40 NTAPI
41 IUnregisterPhysicalConnection_fnAddRef(
42 IUnregisterPhysicalConnection* iface)
43 {
44 IUnregisterPhysicalConnectionImpl * This = (IUnregisterPhysicalConnectionImpl*)iface;
45
46 return InterlockedIncrement(&This->ref);
47 }
48
49 ULONG
50 NTAPI
51 IUnregisterPhysicalConnection_fnRelease(
52 IUnregisterPhysicalConnection* iface)
53 {
54 IUnregisterPhysicalConnectionImpl * This = (IUnregisterPhysicalConnectionImpl*)iface;
55
56 InterlockedDecrement(&This->ref);
57
58 if (This->ref == 0)
59 {
60 FreeItem(This, TAG_PORTCLASS);
61 return 0;
62 }
63 return This->ref;
64 }
65
66 static
67 NTSTATUS
68 UnRegisterConnection(
69 IN OUT PDEVICE_OBJECT DeviceObject,
70 IN PUNKNOWN FromUnknown,
71 IN PUNICODE_STRING FromString,
72 IN ULONG FromPin,
73 IN PUNKNOWN ToUnknown,
74 IN PUNICODE_STRING ToString,
75 IN ULONG ToPin)
76 {
77 PLIST_ENTRY Entry;
78 PPHYSICAL_CONNECTION Connection;
79 PPCLASS_DEVICE_EXTENSION DeviceExt;
80 NTSTATUS Status;
81 ISubdevice * FromSubDevice = NULL;
82 ISubdevice * ToSubDevice = NULL;
83 ULONG bFound;
84
85 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
86
87 if (FromUnknown)
88 {
89 /* get our private interface */
90 Status = FromUnknown->lpVtbl->QueryInterface(FromUnknown, &IID_ISubdevice, (PVOID*)&FromSubDevice);
91 if (!NT_SUCCESS(Status))
92 return STATUS_INVALID_PARAMETER;
93 }
94
95 if (ToUnknown)
96 {
97 Status = ToUnknown->lpVtbl->QueryInterface(ToUnknown, &IID_ISubdevice, (PVOID*)&ToSubDevice);
98 if (!NT_SUCCESS(Status))
99 goto cleanup;
100 }
101
102
103 Entry = DeviceExt->PhysicalConnectionList.Flink;
104 bFound = FALSE;
105 /* loop physical connection list */
106 while(Entry != &DeviceExt->PhysicalConnectionList)
107 {
108 Connection = (PPHYSICAL_CONNECTION)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION, Entry);
109 /* compare current entry */
110 if (Connection->FromPin == FromPin && Connection->ToPin == ToPin &&
111 Connection->FromSubDevice == FromSubDevice && Connection->ToSubDevice == ToSubDevice)
112 {
113 if (FromString && Connection->FromUnicodeString.Buffer)
114 {
115 if (!RtlCompareUnicodeString(FromString, &Connection->FromUnicodeString, TRUE))
116 {
117 /* UnregisterPhysicalConnectionFromExternal */
118 bFound = TRUE;
119 break;
120 }
121 }
122 else if (ToString && Connection->ToUnicodeString.Buffer)
123 {
124 if (!RtlCompareUnicodeString(ToString, &Connection->ToUnicodeString, TRUE))
125 {
126 /* UnregisterPhysicalConnectionToExternal */
127 bFound = TRUE;
128 break;
129 }
130 }
131 else
132 {
133 /* UnregisterPhysicalConnection */
134 bFound = TRUE;
135 break;
136 }
137 }
138 Entry = Entry->Flink;
139 }
140
141 if (!bFound)
142 {
143 /* not found */
144 Status = STATUS_NOT_FOUND;
145 goto cleanup;
146 }
147
148 /* remove list entry */
149 RemoveEntryList(&Connection->Entry);
150
151 /* release resources */
152 if (Connection->FromSubDevice)
153 Connection->FromSubDevice->lpVtbl->Release(Connection->FromSubDevice);
154
155
156 if (Connection->ToSubDevice)
157 Connection->ToSubDevice->lpVtbl->Release(Connection->ToSubDevice);
158
159 if (Connection->FromUnicodeString.Buffer)
160 RtlFreeUnicodeString(&Connection->FromUnicodeString);
161
162 if (Connection->ToUnicodeString.Buffer)
163 RtlFreeUnicodeString(&Connection->ToUnicodeString);
164
165 FreeItem(Connection, TAG_PORTCLASS);
166 Status = STATUS_SUCCESS;
167
168 cleanup:
169
170 if (FromSubDevice)
171 FromSubDevice->lpVtbl->Release(FromSubDevice);
172
173 if (ToSubDevice)
174 ToSubDevice->lpVtbl->Release(ToSubDevice);
175
176 return Status;
177
178 }
179
180 NTSTATUS
181 NTAPI
182 IUnregisterPhysicalConnection_fnUnregisterPhysicalConnection(
183 IN IUnregisterPhysicalConnection* iface,
184 IN PDEVICE_OBJECT DeviceObject,
185 IN PUNKNOWN FromUnknown,
186 IN ULONG FromPin,
187 IN PUNKNOWN ToUnknown,
188 IN ULONG ToPin)
189 {
190 if (!DeviceObject || !FromUnknown || !ToUnknown)
191 return STATUS_INVALID_PARAMETER;
192
193 return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin);
194 }
195
196 NTSTATUS
197 NTAPI
198 IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionToExternal(
199 IN IUnregisterPhysicalConnection* iface,
200 IN PDEVICE_OBJECT DeviceObject,
201 IN PUNKNOWN FromUnknown,
202 IN ULONG FromPin,
203 IN PUNICODE_STRING ToString,
204 IN ULONG ToPin)
205 {
206 if (!DeviceObject || !FromUnknown || !ToString)
207 return STATUS_INVALID_PARAMETER;
208
209 return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin);
210 }
211
212 NTSTATUS
213 NTAPI
214 IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionFromExternal(
215 IN IUnregisterPhysicalConnection* iface,
216 IN PDEVICE_OBJECT DeviceObject,
217 IN PUNICODE_STRING FromString,
218 IN ULONG FromPin,
219 IN PUNKNOWN ToUnknown,
220 IN ULONG ToPin)
221 {
222 if (!DeviceObject || !FromString || !ToUnknown)
223 return STATUS_INVALID_PARAMETER;
224
225 return UnRegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
226 }
227
228 static IUnregisterPhysicalConnectionVtbl vt_IUnregisterPhysicalConnection =
229 {
230 IUnregisterPhysicalConnection_fnQueryInterface,
231 IUnregisterPhysicalConnection_fnAddRef,
232 IUnregisterPhysicalConnection_fnRelease,
233 IUnregisterPhysicalConnection_fnUnregisterPhysicalConnection,
234 IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionToExternal,
235 IUnregisterPhysicalConnection_fnUnregisterPhysicalConnectionFromExternal
236 };
237
238 NTSTATUS
239 NTAPI
240 NewIUnregisterPhysicalConnection(
241 OUT PUNREGISTERPHYSICALCONNECTION *OutConnection)
242 {
243 IUnregisterPhysicalConnectionImpl * This = (IUnregisterPhysicalConnectionImpl*)AllocateItem(NonPagedPool, sizeof(IUnregisterPhysicalConnectionImpl), TAG_PORTCLASS);
244
245 if (!This)
246 return STATUS_INSUFFICIENT_RESOURCES;
247
248 This->lpVtbl = &vt_IUnregisterPhysicalConnection;
249 This->ref = 1;
250 *OutConnection = (PUNREGISTERPHYSICALCONNECTION)&This->lpVtbl;
251 return STATUS_SUCCESS;
252 }
253
254 NTSYSAPI
255 BOOLEAN
256 NTAPI
257 RtlCreateUnicodeString(
258 PUNICODE_STRING DestinationString,
259 PCWSTR SourceString
260 );
261
262 static
263 NTSTATUS
264 RegisterConnection(
265 IN OUT PDEVICE_OBJECT DeviceObject,
266 IN PUNKNOWN FromUnknown,
267 IN PUNICODE_STRING FromString,
268 IN ULONG FromPin,
269 IN PUNKNOWN ToUnknown,
270 IN PUNICODE_STRING ToString,
271 IN ULONG ToPin)
272 {
273 PHYSICAL_CONNECTION *NewConnection;
274 PPCLASS_DEVICE_EXTENSION DeviceExt;
275 NTSTATUS Status;
276
277 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
278
279 NewConnection = AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION), TAG_PORTCLASS);
280 if (!NewConnection)
281 {
282 return STATUS_INSUFFICIENT_RESOURCES;
283 }
284
285
286 if (FromUnknown)
287 {
288 Status = FromUnknown->lpVtbl->QueryInterface(FromUnknown, &IID_ISubdevice, (PVOID*)&NewConnection->FromSubDevice);
289 if (!NT_SUCCESS(Status))
290 goto cleanup;
291 }
292 else
293 {
294 if (!RtlCreateUnicodeString(&NewConnection->FromUnicodeString, (PCWSTR)FromString))
295 {
296 Status = STATUS_INSUFFICIENT_RESOURCES;
297 goto cleanup;
298 }
299 }
300
301 if (ToUnknown)
302 {
303 Status = ToUnknown->lpVtbl->QueryInterface(ToUnknown, &IID_ISubdevice, (PVOID*)&NewConnection->ToSubDevice);
304 if (!NT_SUCCESS(Status))
305 goto cleanup;
306 }
307 else
308 {
309 if (!RtlCreateUnicodeString(&NewConnection->ToUnicodeString, (PCWSTR)ToString))
310 {
311 Status = STATUS_INSUFFICIENT_RESOURCES;
312 goto cleanup;
313 }
314 }
315
316 InsertTailList(&DeviceExt->PhysicalConnectionList, &NewConnection->Entry);
317 return STATUS_SUCCESS;
318
319 cleanup:
320
321 if (NewConnection->FromSubDevice)
322 NewConnection->FromSubDevice->lpVtbl->Release(NewConnection->FromSubDevice);
323
324 if (NewConnection->ToSubDevice)
325 NewConnection->ToSubDevice->lpVtbl->Release(NewConnection->ToSubDevice);
326
327 if (NewConnection->FromUnicodeString.Buffer)
328 RtlFreeUnicodeString(&NewConnection->FromUnicodeString);
329
330 if (NewConnection->ToUnicodeString.Buffer)
331 RtlFreeUnicodeString(&NewConnection->ToUnicodeString);
332
333 FreeItem(NewConnection, TAG_PORTCLASS);
334
335 return Status;
336 }
337
338 /*
339 * @implemented
340 */
341 NTSTATUS NTAPI
342 PcRegisterPhysicalConnection(
343 IN PDEVICE_OBJECT DeviceObject,
344 IN PUNKNOWN FromUnknown,
345 IN ULONG FromPin,
346 IN PUNKNOWN ToUnknown,
347 IN ULONG ToPin)
348 {
349 DPRINT("PcRegisterPhysicalConnection\n");
350 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
351
352 if (!DeviceObject || !FromUnknown || !ToUnknown)
353 return STATUS_INVALID_PARAMETER;
354
355 return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin);
356 }
357
358 /*
359 * @implemented
360 */
361 NTSTATUS NTAPI
362 PcRegisterPhysicalConnectionFromExternal(
363 IN PDEVICE_OBJECT DeviceObject,
364 IN PUNICODE_STRING FromString,
365 IN ULONG FromPin,
366 IN PUNKNOWN ToUnknown,
367 IN ULONG ToPin)
368 {
369 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
370
371 if (!DeviceObject || !FromString || !ToUnknown)
372 return STATUS_INVALID_PARAMETER;
373
374 return RegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
375 }
376
377 /*
378 * @implemented
379 */
380 NTSTATUS NTAPI
381 PcRegisterPhysicalConnectionToExternal(
382 IN PDEVICE_OBJECT DeviceObject,
383 IN PUNKNOWN FromUnknown,
384 IN ULONG FromPin,
385 IN PUNICODE_STRING ToString,
386 IN ULONG ToPin)
387 {
388 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
389
390 if (!DeviceObject || !FromUnknown || !ToString)
391 return STATUS_INVALID_PARAMETER;
392
393 return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin);
394 }