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