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