- Convert portcls to a C++ driver
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / connection.cpp
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 PLIST_ENTRY Entry;
85 PPHYSICAL_CONNECTION Connection;
86 PPCLASS_DEVICE_EXTENSION DeviceExt;
87 NTSTATUS Status;
88 ISubdevice * FromSubDevice = NULL;
89 ISubdevice * ToSubDevice = NULL;
90 ULONG bFound;
91
92 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
93
94 if (FromUnknown)
95 {
96 // get our private interface
97 Status = FromUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&FromSubDevice);
98 if (!NT_SUCCESS(Status))
99 return STATUS_INVALID_PARAMETER;
100 }
101
102 if (ToUnknown)
103 {
104 Status = ToUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&ToSubDevice);
105 if (!NT_SUCCESS(Status))
106 goto cleanup;
107 }
108
109
110 Entry = DeviceExt->PhysicalConnectionList.Flink;
111 bFound = FALSE;
112 // loop physical connection list
113 while(Entry != &DeviceExt->PhysicalConnectionList)
114 {
115 Connection = (PPHYSICAL_CONNECTION)CONTAINING_RECORD(Entry, PHYSICAL_CONNECTION, Entry);
116 // compare current entry
117 if (Connection->FromPin == FromPin && Connection->ToPin == ToPin &&
118 Connection->FromSubDevice == FromSubDevice && Connection->ToSubDevice == ToSubDevice)
119 {
120 if (FromString && Connection->FromUnicodeString.Buffer)
121 {
122 if (!RtlCompareUnicodeString(FromString, &Connection->FromUnicodeString, TRUE))
123 {
124 // UnregisterPhysicalConnectionFromExternal
125 bFound = TRUE;
126 break;
127 }
128 }
129 else if (ToString && Connection->ToUnicodeString.Buffer)
130 {
131 if (!RtlCompareUnicodeString(ToString, &Connection->ToUnicodeString, TRUE))
132 {
133 // UnregisterPhysicalConnectionToExternal
134 bFound = TRUE;
135 break;
136 }
137 }
138 else
139 {
140 // UnregisterPhysicalConnection
141 bFound = TRUE;
142 break;
143 }
144 }
145 Entry = Entry->Flink;
146 }
147
148 if (!bFound)
149 {
150 // not found
151 Status = STATUS_NOT_FOUND;
152 goto cleanup;
153 }
154
155 // remove list entry
156 RemoveEntryList(&Connection->Entry);
157
158 // release resources
159 if (Connection->FromSubDevice)
160 Connection->FromSubDevice->Release();
161
162
163 if (Connection->ToSubDevice)
164 Connection->ToSubDevice->Release();
165
166 if (Connection->FromUnicodeString.Buffer)
167 RtlFreeUnicodeString(&Connection->FromUnicodeString);
168
169 if (Connection->ToUnicodeString.Buffer)
170 RtlFreeUnicodeString(&Connection->ToUnicodeString);
171
172 FreeItem(Connection, TAG_PORTCLASS);
173 Status = STATUS_SUCCESS;
174
175 cleanup:
176
177 if (FromSubDevice)
178 FromSubDevice->Release();
179
180 if (ToSubDevice)
181 ToSubDevice->Release();
182
183 return Status;
184
185 }
186
187 NTSTATUS
188 NTAPI
189 CUnregisterPhysicalConnection::UnregisterPhysicalConnection(
190 IN PDEVICE_OBJECT DeviceObject,
191 IN PUNKNOWN FromUnknown,
192 IN ULONG FromPin,
193 IN PUNKNOWN ToUnknown,
194 IN ULONG ToPin)
195 {
196 if (!DeviceObject || !FromUnknown || !ToUnknown)
197 return STATUS_INVALID_PARAMETER;
198
199 return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin);
200 }
201
202 NTSTATUS
203 NTAPI
204 CUnregisterPhysicalConnection::UnregisterPhysicalConnectionToExternal(
205 IN PDEVICE_OBJECT DeviceObject,
206 IN PUNKNOWN FromUnknown,
207 IN ULONG FromPin,
208 IN PUNICODE_STRING ToString,
209 IN ULONG ToPin)
210 {
211 if (!DeviceObject || !FromUnknown || !ToString)
212 return STATUS_INVALID_PARAMETER;
213
214 return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin);
215 }
216
217 NTSTATUS
218 NTAPI
219 CUnregisterPhysicalConnection::UnregisterPhysicalConnectionFromExternal(
220 IN PDEVICE_OBJECT DeviceObject,
221 IN PUNICODE_STRING FromString,
222 IN ULONG FromPin,
223 IN PUNKNOWN ToUnknown,
224 IN ULONG ToPin)
225 {
226 if (!DeviceObject || !FromString || !ToUnknown)
227 return STATUS_INVALID_PARAMETER;
228
229 return UnRegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
230 }
231
232 NTSTATUS
233 NTAPI
234 NewIUnregisterPhysicalConnection(
235 OUT PUNREGISTERPHYSICALCONNECTION *OutConnection)
236 {
237
238 CUnregisterPhysicalConnection *new_ptr = new(NonPagedPool, TAG_PORTCLASS) CUnregisterPhysicalConnection(NULL);
239
240 if (!new_ptr)
241 return STATUS_INSUFFICIENT_RESOURCES;
242
243 new_ptr->AddRef();
244 *OutConnection = (PUNREGISTERPHYSICALCONNECTION)new_ptr;
245 return STATUS_SUCCESS;
246 }
247
248 NTSTATUS
249 RegisterConnection(
250 IN OUT PDEVICE_OBJECT DeviceObject,
251 IN PUNKNOWN FromUnknown,
252 IN PUNICODE_STRING FromString,
253 IN ULONG FromPin,
254 IN PUNKNOWN ToUnknown,
255 IN PUNICODE_STRING ToString,
256 IN ULONG ToPin)
257 {
258 PHYSICAL_CONNECTION *NewConnection;
259 PPCLASS_DEVICE_EXTENSION DeviceExt;
260 NTSTATUS Status;
261
262 DeviceExt = (PPCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
263
264 NewConnection = (PPHYSICAL_CONNECTION)AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION), TAG_PORTCLASS);
265 if (!NewConnection)
266 {
267 return STATUS_INSUFFICIENT_RESOURCES;
268 }
269
270
271 if (FromUnknown)
272 {
273 Status = FromUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&NewConnection->FromSubDevice);
274 if (!NT_SUCCESS(Status))
275 goto cleanup;
276 }
277 else
278 {
279 if (!RtlCreateUnicodeString(&NewConnection->FromUnicodeString, (PCWSTR)FromString))
280 {
281 Status = STATUS_INSUFFICIENT_RESOURCES;
282 goto cleanup;
283 }
284 }
285
286 if (ToUnknown)
287 {
288 Status = ToUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&NewConnection->ToSubDevice);
289 if (!NT_SUCCESS(Status))
290 goto cleanup;
291 }
292 else
293 {
294 if (!RtlCreateUnicodeString(&NewConnection->ToUnicodeString, (PCWSTR)ToString))
295 {
296 Status = STATUS_INSUFFICIENT_RESOURCES;
297 goto cleanup;
298 }
299 }
300
301 InsertTailList(&DeviceExt->PhysicalConnectionList, &NewConnection->Entry);
302 return STATUS_SUCCESS;
303
304 cleanup:
305
306 if (NewConnection->FromSubDevice)
307 NewConnection->FromSubDevice->Release();
308
309 if (NewConnection->ToSubDevice)
310 NewConnection->ToSubDevice->Release();
311
312 if (NewConnection->FromUnicodeString.Buffer)
313 RtlFreeUnicodeString(&NewConnection->FromUnicodeString);
314
315 if (NewConnection->ToUnicodeString.Buffer)
316 RtlFreeUnicodeString(&NewConnection->ToUnicodeString);
317
318 FreeItem(NewConnection, TAG_PORTCLASS);
319
320 return Status;
321 }
322
323 NTSTATUS
324 NTAPI
325 PcRegisterPhysicalConnection(
326 IN PDEVICE_OBJECT DeviceObject,
327 IN PUNKNOWN FromUnknown,
328 IN ULONG FromPin,
329 IN PUNKNOWN ToUnknown,
330 IN ULONG ToPin)
331 {
332 DPRINT("PcRegisterPhysicalConnection\n");
333 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
334
335 if (!DeviceObject || !FromUnknown || !ToUnknown)
336 return STATUS_INVALID_PARAMETER;
337
338 return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin);
339 }
340
341 NTSTATUS
342 NTAPI
343 PcRegisterPhysicalConnectionFromExternal(
344 IN PDEVICE_OBJECT DeviceObject,
345 IN PUNICODE_STRING FromString,
346 IN ULONG FromPin,
347 IN PUNKNOWN ToUnknown,
348 IN ULONG ToPin)
349 {
350 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
351
352 if (!DeviceObject || !FromString || !ToUnknown)
353 return STATUS_INVALID_PARAMETER;
354
355 return RegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
356 }
357
358 NTSTATUS
359 NTAPI
360 PcRegisterPhysicalConnectionToExternal(
361 IN PDEVICE_OBJECT DeviceObject,
362 IN PUNKNOWN FromUnknown,
363 IN ULONG FromPin,
364 IN PUNICODE_STRING ToString,
365 IN ULONG ToPin)
366 {
367 PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
368
369 if (!DeviceObject || !FromUnknown || !ToString)
370 return STATUS_INVALID_PARAMETER;
371
372 return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin);
373 }