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