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