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     UNIMPLEMENTED
85     return STATUS_NOT_IMPLEMENTED;
86 }
87 
88 NTSTATUS
89 NTAPI
90 CUnregisterPhysicalConnection::UnregisterPhysicalConnection(
91     IN PDEVICE_OBJECT DeviceObject,
92     IN PUNKNOWN FromUnknown,
93     IN ULONG FromPin,
94     IN PUNKNOWN ToUnknown,
95     IN ULONG ToPin)
96 {
97     if (!DeviceObject || !FromUnknown || !ToUnknown)
98         return STATUS_INVALID_PARAMETER;
99 
100     return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin);
101 }
102 
103 NTSTATUS
104 NTAPI
105 CUnregisterPhysicalConnection::UnregisterPhysicalConnectionToExternal(
106     IN PDEVICE_OBJECT DeviceObject,
107     IN PUNKNOWN FromUnknown,
108     IN ULONG FromPin,
109     IN PUNICODE_STRING ToString,
110     IN ULONG ToPin)
111 {
112     if (!DeviceObject || !FromUnknown || !ToString)
113         return STATUS_INVALID_PARAMETER;
114 
115     return UnRegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin);
116 }
117 
118 NTSTATUS
119 NTAPI
120 CUnregisterPhysicalConnection::UnregisterPhysicalConnectionFromExternal(
121     IN PDEVICE_OBJECT DeviceObject,
122     IN PUNICODE_STRING FromString,
123     IN ULONG FromPin,
124     IN PUNKNOWN ToUnknown,
125     IN ULONG ToPin)
126 {
127     if (!DeviceObject || !FromString || !ToUnknown)
128         return STATUS_INVALID_PARAMETER;
129 
130     return UnRegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
131 }
132 
133 NTSTATUS
134 NTAPI
135 NewIUnregisterPhysicalConnection(
136     OUT PUNREGISTERPHYSICALCONNECTION *OutConnection)
137 {
138 
139     CUnregisterPhysicalConnection *new_ptr = new(NonPagedPool, TAG_PORTCLASS) CUnregisterPhysicalConnection(NULL);
140 
141     if (!new_ptr)
142         return STATUS_INSUFFICIENT_RESOURCES;
143 
144     new_ptr->AddRef();
145     *OutConnection = (PUNREGISTERPHYSICALCONNECTION)new_ptr;
146     return STATUS_SUCCESS;
147 }
148 
149 NTSTATUS
150 RegisterConnection(
151     IN OUT PDEVICE_OBJECT DeviceObject,
152     IN PUNKNOWN FromUnknown,
153     IN PUNICODE_STRING FromString,
154     IN ULONG FromPin,
155     IN PUNKNOWN ToUnknown,
156     IN PUNICODE_STRING ToString,
157     IN ULONG ToPin)
158 {
159     PSUBDEVICE_DESCRIPTOR FromSubDeviceDescriptor = NULL, ToSubDeviceDescriptor = NULL;
160     PSYMBOLICLINK_ENTRY SymEntry;
161     ISubdevice * FromSubDevice = NULL, *ToSubDevice = NULL;
162     NTSTATUS Status;
163     PPHYSICAL_CONNECTION_ENTRY FromEntry = NULL, ToEntry = NULL;
164 
165     if (FromUnknown)
166     {
167         Status = FromUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&FromSubDevice);
168         if (!NT_SUCCESS(Status))
169             goto cleanup;
170 
171         Status = FromSubDevice->GetDescriptor(&FromSubDeviceDescriptor);
172         if (!NT_SUCCESS(Status))
173             goto cleanup;
174 
175         if (IsListEmpty(&FromSubDeviceDescriptor->SymbolicLinkList))
176         {
177             Status = STATUS_UNSUCCESSFUL;
178             goto cleanup;
179         }
180 
181         SymEntry = (PSYMBOLICLINK_ENTRY)CONTAINING_RECORD(FromSubDeviceDescriptor->SymbolicLinkList.Flink, SYMBOLICLINK_ENTRY, Entry);
182         FromString = &SymEntry->SymbolicLink;
183     }
184 
185 
186     if (ToUnknown)
187     {
188         Status = ToUnknown->QueryInterface(IID_ISubdevice, (PVOID*)&ToSubDevice);
189         if (!NT_SUCCESS(Status))
190             goto cleanup;
191 
192         Status = ToSubDevice->GetDescriptor(&ToSubDeviceDescriptor);
193         if (!NT_SUCCESS(Status))
194             goto cleanup;
195 
196         if (IsListEmpty(&ToSubDeviceDescriptor->SymbolicLinkList))
197         {
198             Status = STATUS_UNSUCCESSFUL;
199             goto cleanup;
200         }
201 
202 
203         SymEntry = (PSYMBOLICLINK_ENTRY)CONTAINING_RECORD(ToSubDeviceDescriptor->SymbolicLinkList.Flink, SYMBOLICLINK_ENTRY, Entry);
204         ToString = &SymEntry->SymbolicLink;
205 
206     }
207 
208     if (FromSubDeviceDescriptor)
209     {
210         FromEntry = (PPHYSICAL_CONNECTION_ENTRY)AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION_ENTRY) + ToString->MaximumLength + sizeof(WCHAR), TAG_PORTCLASS);
211         if (!FromEntry)
212         {
213             Status = STATUS_INSUFFICIENT_RESOURCES;
214             goto cleanup;
215         }
216     }
217 
218     if (ToSubDeviceDescriptor)
219     {
220         ToEntry = (PPHYSICAL_CONNECTION_ENTRY)AllocateItem(NonPagedPool, sizeof(PHYSICAL_CONNECTION_ENTRY) + FromString->MaximumLength + sizeof(WCHAR), TAG_PORTCLASS);
221         if (!ToEntry)
222         {
223             Status = STATUS_INSUFFICIENT_RESOURCES;
224             goto cleanup;
225         }
226     }
227 
228     if (FromSubDeviceDescriptor)
229     {
230         FromEntry->FromPin = FromPin;
231         FromEntry->Connection.Pin = ToPin;
232         FromEntry->Connection.Size = sizeof(KSPIN_PHYSICALCONNECTION) + ToString->MaximumLength + sizeof(WCHAR);
233         RtlMoveMemory(&FromEntry->Connection.SymbolicLinkName, ToString->Buffer, ToString->MaximumLength);
234         FromEntry->Connection.SymbolicLinkName[ToString->Length / sizeof(WCHAR)] = UNICODE_NULL;
235 
236         InsertTailList(&FromSubDeviceDescriptor->PhysicalConnectionList, &FromEntry->Entry);
237     }
238 
239 
240     if (ToSubDeviceDescriptor)
241     {
242         ToEntry->FromPin = ToPin;
243         ToEntry->Connection.Pin = FromPin;
244         ToEntry->Connection.Size = sizeof(KSPIN_PHYSICALCONNECTION) + FromString->MaximumLength + sizeof(WCHAR);
245         RtlMoveMemory(&ToEntry->Connection.SymbolicLinkName, FromString->Buffer, FromString->MaximumLength);
246         ToEntry->Connection.SymbolicLinkName[FromString->Length /  sizeof(WCHAR)] = UNICODE_NULL;
247 
248         InsertTailList(&ToSubDeviceDescriptor->PhysicalConnectionList, &ToEntry->Entry);
249 
250     }
251 
252     return STATUS_SUCCESS;
253 
254 cleanup:
255 
256     if (FromSubDevice)
257         FromSubDevice->Release();
258 
259     if (ToSubDevice)
260         ToSubDevice->Release();
261 
262     if (FromEntry)
263         FreeItem(FromEntry, TAG_PORTCLASS);
264 
265     if (ToEntry)
266         FreeItem(ToEntry, TAG_PORTCLASS);
267 
268     return Status;
269 }
270 
271 NTSTATUS
272 NTAPI
273 PcRegisterPhysicalConnection(
274     IN  PDEVICE_OBJECT DeviceObject,
275     IN  PUNKNOWN FromUnknown,
276     IN  ULONG FromPin,
277     IN  PUNKNOWN ToUnknown,
278     IN  ULONG ToPin)
279 {
280     DPRINT("PcRegisterPhysicalConnection\n");
281     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
282 
283     if (!DeviceObject || !FromUnknown || !ToUnknown)
284         return STATUS_INVALID_PARAMETER;
285 
286     return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, ToUnknown, NULL, ToPin);
287 }
288 
289 NTSTATUS
290 NTAPI
291 PcRegisterPhysicalConnectionFromExternal(
292     IN  PDEVICE_OBJECT DeviceObject,
293     IN  PUNICODE_STRING FromString,
294     IN  ULONG FromPin,
295     IN  PUNKNOWN ToUnknown,
296     IN  ULONG ToPin)
297 {
298     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
299 
300     if (!DeviceObject || !FromString || !ToUnknown)
301         return STATUS_INVALID_PARAMETER;
302 
303     return RegisterConnection(DeviceObject, NULL, FromString, FromPin, ToUnknown, NULL, ToPin);
304 }
305 
306 NTSTATUS
307 NTAPI
308 PcRegisterPhysicalConnectionToExternal(
309     IN  PDEVICE_OBJECT DeviceObject,
310     IN  PUNKNOWN FromUnknown,
311     IN  ULONG FromPin,
312     IN  PUNICODE_STRING ToString,
313     IN  ULONG ToPin)
314 {
315     PC_ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
316 
317     if (!DeviceObject || !FromUnknown || !ToString)
318         return STATUS_INVALID_PARAMETER;
319 
320     return RegisterConnection(DeviceObject, FromUnknown, NULL, FromPin, NULL, ToString, ToPin);
321 }
322