1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS BDA Proxy 4 * FILE: dll/directx/bdaplgin/pincontrol.cpp 5 * PURPOSE: ClassFactory interface 6 * 7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org) 8 */ 9 10 #include "precomp.h" 11 12 #ifndef _MSC_VER 13 const GUID KSPROPSETID_BdaPinControl = {0x0ded49d5, 0xa8b7, 0x4d5d, {0x97, 0xa1, 0x12, 0xb0, 0xc1, 0x95, 0x87, 0x4d}}; 14 const GUID IID_IBDA_PinControl = {0x0DED49D5, 0xA8B7, 0x4d5d, {0x97, 0xA1, 0x12, 0xB0, 0xC1, 0x95, 0x87, 0x4D}}; 15 const GUID IID_IPin = {0x56a86891, 0x0ad4, 0x11ce, {0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}}; 16 #endif 17 18 19 class CBDAPinControl : public IBDA_PinControl 20 { 21 public: 22 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 23 24 STDMETHODIMP_(ULONG) AddRef() 25 { 26 InterlockedIncrement(&m_Ref); 27 return m_Ref; 28 } 29 STDMETHODIMP_(ULONG) Release() 30 { 31 InterlockedDecrement(&m_Ref); 32 if (!m_Ref) 33 { 34 delete this; 35 return 0; 36 } 37 return m_Ref; 38 } 39 // IBDA_PinControl methods 40 HRESULT STDMETHODCALLTYPE GetPinID(ULONG *pulPinID); 41 HRESULT STDMETHODCALLTYPE GetPinType(ULONG *pulPinType); 42 HRESULT STDMETHODCALLTYPE RegistrationContext(ULONG *pulRegistrationCtx); 43 44 45 CBDAPinControl(HANDLE hFile, IBDA_NetworkProvider * pProvider, IPin * pConnectedPin, ULONG RegistrationCtx) : m_Ref(0), m_Handle(hFile), m_pProvider(pProvider), m_pConnectedPin(pConnectedPin), m_RegistrationCtx(RegistrationCtx){}; 46 virtual ~CBDAPinControl() 47 { 48 //m_pConnectedPin->Release(); 49 //m_pProvider->Release(); 50 }; 51 52 protected: 53 LONG m_Ref; 54 HANDLE m_Handle; 55 IBDA_NetworkProvider * m_pProvider; 56 IPin * m_pConnectedPin; 57 ULONG m_RegistrationCtx; 58 }; 59 60 HRESULT 61 STDMETHODCALLTYPE 62 CBDAPinControl::QueryInterface( 63 IN REFIID refiid, 64 OUT PVOID* Output) 65 { 66 *Output = NULL; 67 if (IsEqualGUID(refiid, IID_IUnknown)) 68 { 69 *Output = PVOID(this); 70 reinterpret_cast<IUnknown*>(*Output)->AddRef(); 71 return NOERROR; 72 } 73 if (IsEqualGUID(refiid, IID_IBDA_PinControl)) 74 { 75 *Output = (IBDA_PinControl*)(this); 76 reinterpret_cast<IBDA_PinControl*>(*Output)->AddRef(); 77 return NOERROR; 78 } 79 DebugBreak(); 80 return E_NOINTERFACE; 81 } 82 //------------------------------------------------------------------- 83 // IBDA_PinControl methods 84 // 85 HRESULT 86 STDMETHODCALLTYPE 87 CBDAPinControl::GetPinID(ULONG *pulPinID) 88 { 89 KSPROPERTY Property; 90 ULONG BytesReturned; 91 HRESULT hr; 92 93 // setup request 94 Property.Set = KSPROPSETID_BdaPinControl; 95 Property.Id = KSPROPERTY_BDA_PIN_ID; 96 Property.Flags = KSPROPERTY_TYPE_GET; 97 98 // perform request 99 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), pulPinID, sizeof(ULONG), &BytesReturned); 100 101 #ifdef BDAPLGIN_TRACE 102 WCHAR Buffer[100]; 103 swprintf(Buffer, L"CBDAPinControl::GetPinID: hr %lx pulPinID %lu BytesReturned %lx\n", hr, *pulPinID, BytesReturned); 104 OutputDebugStringW(Buffer); 105 #endif 106 107 return hr; 108 } 109 110 HRESULT 111 STDMETHODCALLTYPE 112 CBDAPinControl::GetPinType(ULONG *pulPinType) 113 { 114 KSPROPERTY Property; 115 ULONG BytesReturned; 116 HRESULT hr; 117 118 // setup request 119 Property.Set = KSPROPSETID_BdaPinControl; 120 Property.Id = KSPROPERTY_BDA_PIN_TYPE; 121 Property.Flags = KSPROPERTY_TYPE_GET; 122 123 // perform request 124 hr = KsSynchronousDeviceControl(m_Handle, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), pulPinType, sizeof(ULONG), &BytesReturned); 125 126 #ifdef BDAPLGIN_TRACE 127 WCHAR Buffer[100]; 128 swprintf(Buffer, L"CBDAPinControl::GetPinType: hr %lx pulPinType %lu BytesReturned %lx\n", hr, *pulPinType, BytesReturned); 129 OutputDebugStringW(Buffer); 130 #endif 131 132 return hr; 133 } 134 135 HRESULT 136 STDMETHODCALLTYPE 137 CBDAPinControl::RegistrationContext(ULONG *pulRegistrationCtx) 138 { 139 #ifdef BDAPLGIN_TRACE 140 OutputDebugStringW(L"CBDAPinControl::RegistrationContext\n"); 141 #endif 142 143 if (!pulRegistrationCtx) 144 { 145 // invalid argument 146 return E_POINTER; 147 } 148 149 if (m_RegistrationCtx) 150 { 151 // is registered 152 *pulRegistrationCtx = m_RegistrationCtx; 153 return NOERROR; 154 } 155 156 //pin not registered 157 return E_FAIL; 158 } 159 160 //------------------------------------------------------------------- 161 HRESULT 162 GetNetworkProviderFromGraph( 163 IFilterGraph * pGraph, 164 IBDA_NetworkProvider ** pOutNetworkProvider) 165 { 166 IEnumFilters *pEnumFilters = NULL; 167 IBaseFilter * ppFilter[1]; 168 IBDA_NetworkProvider * pNetworkProvider = NULL; 169 HRESULT hr; 170 171 // get IEnumFilters interface 172 hr = pGraph->EnumFilters(&pEnumFilters); 173 174 if (FAILED(hr)) 175 { 176 //clean up 177 *pOutNetworkProvider = NULL; 178 return hr; 179 } 180 181 while(pEnumFilters->Next(1, ppFilter, NULL) == S_OK) 182 { 183 // check if that filter supports the IBDA_NetworkProvider interface 184 hr = ppFilter[0]->QueryInterface(IID_IBDA_NetworkProvider, (void**)&pNetworkProvider); 185 186 // release IBaseFilter 187 ppFilter[0]->Release(); 188 189 if (SUCCEEDED(hr)) 190 break; 191 } 192 193 // release IEnumFilters interface 194 pEnumFilters->Release(); 195 196 //store result 197 *pOutNetworkProvider = pNetworkProvider; 198 199 if (pNetworkProvider) 200 return S_OK; 201 else 202 return E_FAIL; 203 } 204 205 HRESULT 206 CBDAPinControl_RealConstructor( 207 HANDLE hPin, 208 IBDA_NetworkProvider *pNetworkProvider, 209 IPin * pConnectedPin, 210 ULONG RegistrationCtx, 211 IUnknown * pUnkOuter, 212 REFIID riid, 213 LPVOID * ppv) 214 { 215 CBDAPinControl * handler = new CBDAPinControl(hPin, pNetworkProvider, pConnectedPin, RegistrationCtx); 216 217 #ifdef BDAPLGIN_TRACE 218 OutputDebugStringW(L"CBDAPinControl_fnConstructor\n"); 219 #endif 220 221 if (!handler) 222 return E_OUTOFMEMORY; 223 224 if (FAILED(handler->QueryInterface(riid, ppv))) 225 { 226 /* not supported */ 227 delete handler; 228 return E_NOINTERFACE; 229 } 230 231 return NOERROR; 232 } 233 234 HRESULT 235 WINAPI 236 CBDAPinControl_fnConstructor( 237 IUnknown * pUnkOuter, 238 REFIID riid, 239 LPVOID * ppv) 240 { 241 IPin * pConnectedPin = NULL; 242 IBDA_NetworkProvider * pNetworkProvider = NULL; 243 HANDLE hFile = INVALID_HANDLE_VALUE; 244 HRESULT hr; 245 IKsObject * pObject = NULL; 246 IPin * pPin = NULL; 247 IUnknown * pUnknown = NULL; 248 PIN_INFO PinInfo; 249 FILTER_INFO FilterInfo; 250 ULONG RegistrationCtx = 0; 251 252 if (!pUnkOuter) 253 return E_POINTER; 254 255 OutputDebugStringW(L"CBDAPinControl_fnConstructor\n"); 256 //DebugBreak(); 257 258 // query for IKsObject interface 259 hr = pUnkOuter->QueryInterface(IID_IKsObject, (void**)&pObject); 260 261 if (FAILED(hr)) 262 return hr; 263 264 // query for IPin interface 265 hr = pObject->QueryInterface(IID_IPin, (void**)&pPin); 266 267 if (FAILED(hr)) 268 { 269 //clean up 270 pObject->Release(); 271 return hr; 272 } 273 274 // get pin info 275 hr = pPin->QueryPinInfo(&PinInfo); 276 277 if (FAILED(hr)) 278 { 279 //clean up 280 pObject->Release(); 281 pPin->Release(); 282 return hr; 283 } 284 285 if (!PinInfo.pFilter) 286 { 287 //clean up 288 pObject->Release(); 289 pPin->Release(); 290 return hr; 291 } 292 293 // sanity checks 294 assert(PinInfo.pFilter != NULL); 295 296 // query filter info 297 hr = PinInfo.pFilter->QueryFilterInfo(&FilterInfo); 298 299 // sanity check 300 assert(FilterInfo.pGraph != NULL); 301 302 // get network provider interface 303 hr = GetNetworkProviderFromGraph(FilterInfo.pGraph, &pNetworkProvider); 304 305 if (SUCCEEDED(hr)) 306 { 307 if (PinInfo.dir == PINDIR_OUTPUT) 308 { 309 // get connected pin handle 310 hr = pPin->ConnectedTo(&pConnectedPin); 311 if (SUCCEEDED(hr)) 312 { 313 // get file handle 314 hFile = pObject->KsGetObjectHandle(); 315 if (hFile) 316 { 317 hr = CBDAPinControl_RealConstructor(hFile, pNetworkProvider, pConnectedPin, 0, pUnkOuter, riid, ppv); 318 if (SUCCEEDED(hr)) 319 { 320 // set to null to prevent releasing 321 pNetworkProvider = NULL; 322 pConnectedPin = NULL; 323 } 324 } 325 else 326 { 327 // expected file handle 328 hr = E_UNEXPECTED; 329 } 330 } 331 } 332 else 333 { 334 // get IUnknown from base filter 335 hr = PinInfo.pFilter->QueryInterface(IID_IUnknown, (void**)&pUnknown); 336 if (SUCCEEDED(hr)) 337 { 338 // register device filter 339 OutputDebugStringW(L"CBDAPinControl_fnConstructor registering device filter with network provider\n"); 340 hr = pNetworkProvider->RegisterDeviceFilter(pUnknown, &RegistrationCtx); 341 if (SUCCEEDED(hr)) 342 { 343 // get file handle 344 hFile = pObject->KsGetObjectHandle(); 345 if (hFile) 346 { 347 hr = CBDAPinControl_RealConstructor(hFile, pNetworkProvider, NULL, RegistrationCtx, pUnkOuter, riid, ppv); 348 if (SUCCEEDED(hr)) 349 { 350 // set to null to prevent releasing 351 pNetworkProvider = NULL; 352 } 353 } 354 else 355 { 356 // expected file handle 357 hr = E_UNEXPECTED; 358 } 359 } 360 else 361 { 362 WCHAR Buffer[100]; 363 swprintf(Buffer, L"CBDAPinControl_fnConstructor failed to register filter with %lx\n", hr); 364 OutputDebugStringW(Buffer); 365 } 366 } 367 } 368 } 369 370 // release IFilterGraph interface 371 FilterInfo.pGraph->Release(); 372 373 // release IBaseFilter interface 374 PinInfo.pFilter->Release(); 375 376 // release IPin 377 pPin->Release(); 378 379 // release IKsObject 380 pObject->Release(); 381 382 383 if (pNetworkProvider) 384 { 385 // release network provider 386 pNetworkProvider->Release(); 387 } 388 389 if (pConnectedPin) 390 { 391 // release connected pin 392 pConnectedPin->Release(); 393 } 394 395 if (pUnknown) 396 { 397 // release filter 398 pUnknown->Release(); 399 } 400 401 return hr; 402 } 403