661eba547a017058b059593580a3c578f2a89d37
[reactos.git] / reactos / dll / directx / bdaplgin / devicecontrol.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS BDA Proxy
4 * FILE: dll/directx/bdaplgin/classfactory.cpp
5 * PURPOSE: ClassFactory interface
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9
10 #include "precomp.h"
11
12 const GUID CLSID_DVBTNetworkProvider = {0x216c62df, 0x6d7f, 0x4e9a, {0x85, 0x71, 0x5, 0xf1, 0x4e, 0xdb, 0x76, 0x6a}};
13 const GUID IID_IAC3Filter = {0xe4539501, 0xc609, 0x46ea, {0xad, 0x2a, 0x0e, 0x97, 0x00, 0x24, 0x56, 0x83}};
14 const GUID IID_IAsyncReader = {0x56A868AA, 0x0AD4, 0x11CE, {0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
15 const GUID IID_IMatrixMixer = {0xafc57835, 0x2fd1, 0x4541, {0xa6, 0xd9, 0x0d, 0xb7, 0x18, 0x56, 0xe5, 0x89}};
16 const GUID IID_IBDA_NetworkProvider = {0xfd501041, 0x8ebe, 0x11ce, {0x81, 0x83, 0x00, 0xaa, 0x00, 0x57, 0x7d, 0xa2}};
17 const GUID IID_IAMOpenProgress = {0x8E1C39A1, 0xDE53, 0x11cf, {0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D}};
18 const GUID IID_IDistributorNotify = {0x56a868af, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}};
19 const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}};
20 const GUID IID_IBDA_Topology = {0x79B56888, 0x7FEA, 0x4690, {0xB4, 0x5D, 0x38, 0xFD, 0x3C, 0x78, 0x49, 0xBE}};
21 const GUID IID_IKsObject = {0x423c13a2, 0x2070, 0x11d0, {0x9e, 0xf7, 0x00, 0xaa, 0x00, 0xa2, 0x16, 0xa1}};
22 const GUID KSPROPSETID_BdaTopology = {0xa14ee835, 0x0a23, 0x11d3, {0x9c, 0xc7, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}};
23 const GUID KSMETHODSETID_BdaDeviceConfiguration = {0x71985f45, 0x1ca1, 0x11d3, {0x9c, 0xc8, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}};
24 const GUID IID_IBaseFilter = {0x56a86895, 0x0ad4, 0x11ce, {0xb0,0x3a, 0x00,0x20,0xaf,0x0b,0xa7,0x70}};
25 const GUID KSMETHODSETID_BdaChangeSync = {0xfd0a5af3, 0xb41d, 0x11d2, {0x9c, 0x95, 0x0, 0xc0, 0x4f, 0x79, 0x71, 0xe0}};
26
27 class CBDADeviceControl : public IBDA_DeviceControl,
28 public IBDA_Topology
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 if (!m_Ref)
42 {
43 delete this;
44 return 0;
45 }
46 return m_Ref;
47 }
48
49 // IBDA_DeviceControl methods
50 HRESULT STDMETHODCALLTYPE StartChanges( void);
51 HRESULT STDMETHODCALLTYPE CheckChanges( void);
52 HRESULT STDMETHODCALLTYPE CommitChanges( void);
53 HRESULT STDMETHODCALLTYPE GetChangeState(ULONG *pState);
54
55 // IBDA_Topology methods
56 HRESULT STDMETHODCALLTYPE GetNodeTypes(ULONG *pulcNodeTypes, ULONG ulcNodeTypesMax, ULONG * rgulNodeTypes);
57 HRESULT STDMETHODCALLTYPE GetNodeDescriptors(ULONG *ulcNodeDescriptors, ULONG ulcNodeDescriptorsMax, BDANODE_DESCRIPTOR * rgNodeDescriptors);
58 HRESULT STDMETHODCALLTYPE GetNodeInterfaces(ULONG ulNodeType, ULONG *pulcInterfaces, ULONG ulcInterfacesMax, GUID * rgguidInterfaces);
59 HRESULT STDMETHODCALLTYPE GetPinTypes(ULONG *pulcPinTypes, ULONG ulcPinTypesMax, ULONG *rgulPinTypes);
60 HRESULT STDMETHODCALLTYPE GetTemplateConnections(ULONG *pulcConnections, ULONG ulcConnectionsMax, BDA_TEMPLATE_CONNECTION * rgConnections);
61 HRESULT STDMETHODCALLTYPE CreatePin(ULONG ulPinType, ULONG *pulPinId);
62 HRESULT STDMETHODCALLTYPE DeletePin(ULONG ulPinId);
63 HRESULT STDMETHODCALLTYPE SetMediaType(ULONG ulPinId, AM_MEDIA_TYPE *pMediaType);
64 HRESULT STDMETHODCALLTYPE SetMedium(ULONG ulPinId, REGPINMEDIUM *pMedium);
65 HRESULT STDMETHODCALLTYPE CreateTopology(ULONG ulInputPinId, ULONG ulOutputPinId);
66 HRESULT STDMETHODCALLTYPE GetControlNode(ULONG ulInputPinId, ULONG ulOutputPinId, ULONG ulNodeType, IUnknown **ppControlNode);
67
68 CBDADeviceControl(IUnknown * pUnkOuter, IBaseFilter *pFilter, HANDLE hFile) : m_Ref(0), m_pUnkOuter(pUnkOuter), m_Handle(hFile), m_pFilter(pFilter){};
69 virtual ~CBDADeviceControl(){};
70
71 protected:
72 LONG m_Ref;
73 IUnknown * m_pUnkOuter;
74 HANDLE m_Handle;
75 IBaseFilter * m_pFilter;
76 };
77
78 HRESULT
79 STDMETHODCALLTYPE
80 CBDADeviceControl::QueryInterface(
81 IN REFIID refiid,
82 OUT PVOID* Output)
83 {
84 *Output = NULL;
85
86 if (IsEqualGUID(refiid, IID_IUnknown))
87 {
88 *Output = PVOID(this);
89 reinterpret_cast<IUnknown*>(*Output)->AddRef();
90 return NOERROR;
91 }
92 if (IsEqualGUID(refiid, IID_IBDA_DeviceControl))
93 {
94 *Output = (IBDA_DeviceControl*)(this);
95 reinterpret_cast<IBDA_DeviceControl*>(*Output)->AddRef();
96 return NOERROR;
97 }
98
99 if (IsEqualGUID(refiid, IID_IBDA_Topology))
100 {
101 *Output = (IBDA_Topology*)(this);
102 reinterpret_cast<IBDA_Topology*>(*Output)->AddRef();
103 return NOERROR;
104 }
105
106 return E_NOINTERFACE;
107 }
108
109
110 //-------------------------------------------------------------------
111 // IBDA_DeviceControl methods
112 //
113 HRESULT
114 STDMETHODCALLTYPE
115 CBDADeviceControl::StartChanges( void)
116 {
117 KSMETHOD Method;
118 HRESULT hr;
119 ULONG BytesReturned;
120
121 /* setup request */
122 Method.Set = KSMETHODSETID_BdaChangeSync;
123 Method.Id = KSMETHOD_BDA_START_CHANGES;
124 Method.Flags = KSMETHOD_TYPE_NONE;
125
126 /* execute request */
127 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)&Method, sizeof(KSMETHOD), NULL, 0, &BytesReturned);
128
129 #ifdef BDAPLGIN_TRACE
130 WCHAR Buffer[100];
131 swprintf(Buffer, L"CBDADeviceControl::StartChanges: hr %lx, BytesReturned %lu\n", hr, BytesReturned);
132 OutputDebugStringW(Buffer);
133 #endif
134
135 return hr;
136 }
137
138
139 HRESULT
140 STDMETHODCALLTYPE
141 CBDADeviceControl::CheckChanges( void)
142 {
143 KSMETHOD Method;
144 HRESULT hr;
145 ULONG BytesReturned;
146
147 /* setup request */
148 Method.Set = KSMETHODSETID_BdaChangeSync;
149 Method.Id = KSMETHOD_BDA_CHECK_CHANGES;
150 Method.Flags = KSMETHOD_TYPE_NONE;
151
152 /* execute request */
153 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)&Method, sizeof(KSMETHOD), NULL, 0, &BytesReturned);
154
155 #ifdef BDAPLGIN_TRACE
156 WCHAR Buffer[100];
157 swprintf(Buffer, L"CBDADeviceControl::CheckChanges: hr %lx, BytesReturned %lu\n", hr, BytesReturned);
158 OutputDebugStringW(Buffer);
159 #endif
160
161 return hr;
162 }
163
164
165 HRESULT
166 STDMETHODCALLTYPE
167 CBDADeviceControl::CommitChanges( void)
168 {
169 KSMETHOD Method;
170 HRESULT hr;
171 ULONG BytesReturned;
172
173 /* setup request */
174 Method.Set = KSMETHODSETID_BdaChangeSync;
175 Method.Id = KSMETHOD_BDA_COMMIT_CHANGES;
176 Method.Flags = KSMETHOD_TYPE_NONE;
177
178 /* execute request */
179 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)&Method, sizeof(KSMETHOD), NULL, 0, &BytesReturned);
180
181 #ifdef BDAPLGIN_TRACE
182 WCHAR Buffer[100];
183 swprintf(Buffer, L"CBDADeviceControl::CommitChanges: hr %lx, BytesReturned %lu\n", hr, BytesReturned);
184 OutputDebugStringW(Buffer);
185 #endif
186
187 return hr;
188 }
189
190 HRESULT
191 STDMETHODCALLTYPE
192 CBDADeviceControl::GetChangeState(ULONG *pState)
193 {
194 if (pState)
195 {
196 *pState = BDA_CHANGES_COMPLETE;
197 return S_OK;
198 }
199 else
200 {
201 return E_POINTER;
202 }
203 }
204
205 //-------------------------------------------------------------------
206 // IBDA_Topology methods
207 //
208 HRESULT
209 STDMETHODCALLTYPE
210 CBDADeviceControl::GetNodeTypes(ULONG *pulcNodeTypes, ULONG ulcNodeTypesMax, ULONG * rgulNodeTypes)
211 {
212 KSPROPERTY Property;
213 HRESULT hr;
214 ULONG BytesReturned;
215
216 // setup request
217 Property.Set = KSPROPSETID_BdaTopology;
218 Property.Id = KSPROPERTY_BDA_NODE_TYPES;
219 Property.Flags = KSPROPERTY_TYPE_GET;
220
221 // perform request
222 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), rgulNodeTypes, sizeof(ULONG) * ulcNodeTypesMax, &BytesReturned);
223
224 *pulcNodeTypes = (BytesReturned / sizeof(ULONG));
225
226 #ifdef BDAPLGIN_TRACE
227 WCHAR Buffer[100];
228 swprintf(Buffer, L"CBDADeviceControl::GetNodeTypes: hr %lx, BytesReturned %lu\n", hr, BytesReturned);
229 OutputDebugStringW(Buffer);
230
231 if (SUCCEEDED(hr))
232 {
233 for(ULONG Index = 0; Index < *pulcNodeTypes; Index++)
234 {
235 swprintf(Buffer, L"CBDADeviceControl::GetPinTypes: Index %lu Value %lx\n", Index, rgulNodeTypes[Index]);
236 OutputDebugStringW(Buffer);
237 }
238 }
239 #endif
240
241 return hr;
242 }
243
244 HRESULT
245 STDMETHODCALLTYPE
246 CBDADeviceControl::GetNodeDescriptors(ULONG *ulcNodeDescriptors, ULONG ulcNodeDescriptorsMax, BDANODE_DESCRIPTOR * rgNodeDescriptors)
247 {
248 KSPROPERTY Property;
249 HRESULT hr;
250 ULONG BytesReturned;
251
252
253 // setup request
254 Property.Set = KSPROPSETID_BdaTopology;
255 Property.Id = KSPROPERTY_BDA_NODE_DESCRIPTORS;
256 Property.Flags = KSPROPERTY_TYPE_GET;
257
258 // perform request
259 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), rgNodeDescriptors, sizeof(BDANODE_DESCRIPTOR) * ulcNodeDescriptorsMax, &BytesReturned);
260
261 *ulcNodeDescriptors = (BytesReturned / sizeof(BDANODE_DESCRIPTOR));
262
263 #ifdef BDAPLGIN_TRACE
264 WCHAR Buffer[1000];
265 swprintf(Buffer, L"CBDADeviceControl::GetNodeDescriptors: hr %lx, BytesReturned %lu\n", hr, BytesReturned);
266 OutputDebugStringW(Buffer);
267
268
269 if (SUCCEEDED(hr))
270 {
271 for(ULONG Index = 0; Index < min(*ulcNodeDescriptors, ulcNodeDescriptorsMax); Index++)
272 {
273 LPOLESTR pGUIDFunction, pGUIDName;
274
275 StringFromCLSID(rgNodeDescriptors[Index].guidFunction, &pGUIDFunction);
276 StringFromCLSID(rgNodeDescriptors[Index].guidName, &pGUIDName);
277
278 swprintf(Buffer, L"CBDADeviceControl::GetPinTypes: Index %lu Value %lx\nFunction %s\n Name %s\n-----\n", Index, rgNodeDescriptors[Index].ulBdaNodeType, pGUIDFunction, pGUIDName);
279 OutputDebugStringW(Buffer);
280 }
281 }
282 #endif
283
284
285 return hr;
286 }
287
288 HRESULT
289 STDMETHODCALLTYPE
290 CBDADeviceControl::GetNodeInterfaces(ULONG ulNodeType, ULONG *pulcInterfaces, ULONG ulcInterfacesMax, GUID * rgguidInterfaces)
291 {
292 KSP_NODE Property;
293 HRESULT hr;
294 ULONG BytesReturned;
295
296
297 // setup request
298 Property.Property.Set = KSPROPSETID_BdaTopology;
299 Property.Property.Id = KSPROPERTY_BDA_NODE_PROPERTIES;
300 Property.Property.Flags = KSPROPERTY_TYPE_GET;
301 Property.NodeId = ulNodeType;
302 Property.Reserved = 0;
303
304 // perform request
305 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_NODE), rgguidInterfaces, sizeof(GUID) * ulcInterfacesMax, &BytesReturned);
306
307 *pulcInterfaces = (BytesReturned / sizeof(GUID));
308
309 #ifdef BDAPLGIN_TRACE
310 WCHAR Buffer[100];
311 swprintf(Buffer, L"CBDADeviceControl::GetNodeInterfaces: hr %lx, BytesReturned %lu ulNodeType %lu\n", hr, BytesReturned, ulNodeType);
312 OutputDebugStringW(Buffer);
313
314 if (SUCCEEDED(hr))
315 {
316 for(ULONG Index = 0; Index < min(*pulcInterfaces, ulcInterfacesMax); Index++)
317 {
318 LPOLESTR pstr;
319
320 StringFromCLSID(rgguidInterfaces[Index], &pstr);
321
322 swprintf(Buffer, L"CBDADeviceControl::GetNodeInterfaces: Index %lu Name %s\n", Index, pstr);
323 OutputDebugStringW(Buffer);
324 }
325 }
326 #endif
327
328 return hr;
329 }
330
331 HRESULT
332 STDMETHODCALLTYPE
333 CBDADeviceControl::GetPinTypes(ULONG *pulcPinTypes, ULONG ulcPinTypesMax, ULONG *rgulPinTypes)
334 {
335 KSPROPERTY Property;
336 HRESULT hr;
337 ULONG BytesReturned;
338
339 // setup request
340 Property.Set = KSPROPSETID_BdaTopology;
341 Property.Id = KSPROPERTY_BDA_PIN_TYPES;
342 Property.Flags = KSPROPERTY_TYPE_GET;
343
344 // perform request
345 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), rgulPinTypes, sizeof(ULONG) * ulcPinTypesMax, &BytesReturned);
346
347 *pulcPinTypes = (BytesReturned / sizeof(ULONG));
348
349 #ifdef BDAPLGIN_TRACE
350 WCHAR Buffer[100];
351 swprintf(Buffer, L"CBDADeviceControl::GetPinTypes: hr %lx, BytesReturned %lu\n", hr, BytesReturned);
352 OutputDebugStringW(Buffer);
353
354 if (SUCCEEDED(hr))
355 {
356 for(ULONG Index = 0; Index < *pulcPinTypes; Index++)
357 {
358 swprintf(Buffer, L"CBDADeviceControl::GetPinTypes: Index %lu Value %lx\n", Index, rgulPinTypes[Index]);
359 OutputDebugStringW(Buffer);
360 }
361 }
362 #endif
363
364 return hr;
365 }
366
367 HRESULT
368 STDMETHODCALLTYPE
369 CBDADeviceControl::GetTemplateConnections(ULONG *pulcConnections, ULONG ulcConnectionsMax, BDA_TEMPLATE_CONNECTION * rgConnections)
370 {
371 #ifdef BDAPLGIN_TRACE
372 OutputDebugStringW(L"CBDADeviceControl::GetTemplateConnections: NotImplemented\n");
373 #endif
374
375 return E_NOTIMPL;
376 }
377
378 HRESULT
379 STDMETHODCALLTYPE
380 CBDADeviceControl::CreatePin(ULONG ulPinType, ULONG *pulPinId)
381 {
382 #ifdef BDAPLGIN_TRACE
383 OutputDebugStringW(L"CBDADeviceControl::CreatePin: NotImplemented\n");
384 #endif
385
386 return E_NOTIMPL;
387 }
388
389 HRESULT
390 STDMETHODCALLTYPE
391 CBDADeviceControl::DeletePin(ULONG ulPinId)
392 {
393 #ifdef BDAPLGIN_TRACE
394 OutputDebugStringW(L"CBDADeviceControl::DeletePin: NotImplemented\n");
395 #endif
396
397 return E_NOTIMPL;
398 }
399
400 HRESULT
401 STDMETHODCALLTYPE
402 CBDADeviceControl::SetMediaType(ULONG ulPinId, AM_MEDIA_TYPE *pMediaType)
403 {
404 #ifdef BDAPLGIN_TRACE
405 OutputDebugStringW(L"CBDADeviceControl::SetMediaType: NotImplemented\n");
406 #endif
407
408 return E_NOTIMPL;
409 }
410
411 HRESULT
412 STDMETHODCALLTYPE
413 CBDADeviceControl::SetMedium(ULONG ulPinId, REGPINMEDIUM *pMedium)
414 {
415 #ifdef BDAPLGIN_TRACE
416 OutputDebugStringW(L"CBDADeviceControl::SetMedium: NotImplemented\n");
417 #endif
418
419 return E_NOTIMPL;
420 }
421
422 HRESULT
423 STDMETHODCALLTYPE
424 CBDADeviceControl::CreateTopology(ULONG ulInputPinId, ULONG ulOutputPinId)
425 {
426 KSM_BDA_PIN_PAIR Method;
427 HRESULT hr;
428 ULONG BytesReturned = 0;
429
430 Method.Method.Flags = KSMETHOD_TYPE_NONE;
431 Method.Method.Id = KSMETHOD_BDA_CREATE_TOPOLOGY;
432 Method.Method.Set = KSMETHODSETID_BdaDeviceConfiguration;
433 Method.InputPinId = ulInputPinId;
434 Method.OutputPinId = ulOutputPinId;
435
436 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_METHOD, (PVOID)&Method, sizeof(KSM_BDA_PIN_PAIR), NULL, 0, &BytesReturned);
437
438 #ifdef BDAPLGIN_TRACE
439 WCHAR Buffer[100];
440 swprintf(Buffer, L"CBDADeviceControl::CreateTopology: hr %lx, BytesReturned %lu\n", hr, BytesReturned);
441 OutputDebugStringW(Buffer);
442 #endif
443
444 return hr;
445 }
446
447 HRESULT
448 STDMETHODCALLTYPE
449 CBDADeviceControl::GetControlNode(ULONG ulInputPinId, ULONG ulOutputPinId, ULONG ulNodeType, IUnknown **ppControlNode)
450 {
451 HRESULT hr;
452 ULONG PinId = 0;
453 ULONG BytesReturned;
454 KSP_BDA_NODE_PIN Property;
455
456 //setup request
457 Property.Property.Set = KSPROPSETID_BdaTopology;
458 Property.Property.Id = KSPROPERTY_BDA_CONTROLLING_PIN_ID;
459 Property.Property.Flags = KSPROPERTY_TYPE_GET;
460 Property.ulInputPinId = ulInputPinId;
461 Property.ulOutputPinId = ulOutputPinId;
462 Property.ulNodeType = ulNodeType;
463
464 // perform request
465 // WinXP SP3 expects minimum sizeof(KSP_BDA_NODE_PIN) + sizeof(ULONG)
466 // seems a driver to be a driver bug
467
468 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_BDA_NODE_PIN) + sizeof(ULONG), &PinId, sizeof(ULONG), &BytesReturned);
469
470 #ifdef BDAPLGIN_TRACE
471 WCHAR Buffer[100];
472 swprintf(Buffer, L"CBDADeviceControl::GetControlNode: hr %lx, BytesReturned %lu PinId %lu\n", hr, BytesReturned, PinId);
473 OutputDebugStringW(Buffer);
474 #endif
475
476 if (FAILED(hr))
477 return hr;
478
479 hr = CControlNode_fnConstructor(m_Handle, m_pFilter, ulNodeType, PinId, IID_IUnknown, (LPVOID*)ppControlNode);
480
481 #ifdef BDAPLGIN_TRACE
482 swprintf(Buffer, L"CBDADeviceControl::GetControlNode: hr %lx\n", hr);
483 OutputDebugStringW(Buffer);
484 #endif
485
486 return hr;
487 }
488
489 HRESULT
490 WINAPI
491 CBDADeviceControl_fnConstructor(
492 IUnknown * pUnkOuter,
493 REFIID riid,
494 LPVOID * ppv)
495 {
496 HRESULT hr;
497 IKsObject *pObject = NULL;
498 IBaseFilter *pFilter = NULL;
499 HANDLE hFile;
500
501 #ifdef BDAPLGIN_TRACE
502 OutputDebugStringW(L"CBDADeviceControl_fnConstructor\n");
503 #endif
504
505 //DebugBreak();
506
507 // sanity check
508 assert(pUnkOuter);
509
510 // query for IKsObject
511 hr = pUnkOuter->QueryInterface(IID_IKsObject, (void**)&pObject);
512
513 if (FAILED(hr))
514 return E_NOINTERFACE;
515
516 // sanity check
517 assert(hr == NOERROR);
518
519 // query for IBaseFilter interface support
520 hr = pUnkOuter->QueryInterface(IID_IBaseFilter, (void**)&pFilter);
521
522 if (FAILED(hr))
523 {
524 // release
525 pObject->Release();
526 return E_NOINTERFACE;
527 }
528
529 // another sanity check
530 assert(pObject != NULL);
531
532 // get file handle
533 hFile = pObject->KsGetObjectHandle();
534
535 // one more sanity check
536 assert(hFile != NULL && hFile != INVALID_HANDLE_VALUE);
537
538 // release IKsObject interface
539 pObject->Release();
540
541 // release filter
542 pFilter->Release();
543
544 // construct device control
545 CBDADeviceControl * handler = new CBDADeviceControl(pUnkOuter, pFilter, hFile);
546
547 if (!handler)
548 return E_OUTOFMEMORY;
549
550 if (FAILED(handler->QueryInterface(riid, ppv)))
551 {
552 /* not supported */
553 delete handler;
554 return E_NOINTERFACE;
555 }
556
557 return NOERROR;
558 }