1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS WDM Streaming ActiveMovie Proxy 4 * FILE: dll/directx/ksproxy/proxy.cpp 5 * PURPOSE: IKsProxy interface 6 * 7 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org) 8 */ 9 #include "precomp.h" 10 11 const GUID IID_IPersistPropertyBag = {0x37D84F60, 0x42CB, 0x11CE, {0x81, 0x35, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51}}; 12 const GUID IID_ISpecifyPropertyPages = {0xB196B28B, 0xBAB4, 0x101A, {0xB6, 0x9C, 0x00, 0xAA, 0x00, 0x34, 0x1D, 0x07}}; 13 const GUID IID_IPersistStream = {0x00000109, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; 14 const GUID IID_IPersist = {0x0000010c, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; 15 const GUID IID_IBDA_DeviceControl = {0xFD0A5AF3, 0xB41D, 0x11d2, {0x9C, 0x95, 0x00, 0xC0, 0x4F, 0x79, 0x71, 0xE0}}; 16 const GUID IID_IKsAggregateControl = {0x7F40EAC0, 0x3947, 0x11D2, {0x87, 0x4E, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 17 const GUID IID_IKsClockPropertySet = {0x5C5CBD84, 0xE755, 0x11D0, {0xAC, 0x18, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 18 const GUID IID_IKsTopology = {0x28F54683, 0x06FD, 0x11D2, {0xB2, 0x7A, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 19 const GUID IID_IKsClock = {0x877E4351, 0x6FEA, 0x11D0, {0xB8, 0x63, 0x00, 0xAA, 0x00, 0xA2, 0x16, 0xA1}}; 20 /* 21 Needs IKsClock, IKsNotifyEvent 22 */ 23 24 class CKsProxy : public IBaseFilter, 25 public IAMovieSetup, 26 public IPersistPropertyBag, 27 public IKsObject, 28 public IPersistStream, 29 public IAMDeviceRemoval, 30 public ISpecifyPropertyPages, 31 public IReferenceClock, 32 public IMediaSeeking, 33 public IKsPropertySet, 34 public IKsClock, 35 public IKsClockPropertySet, 36 public IAMFilterMiscFlags, 37 public IKsControl, 38 public IKsTopology, 39 public IKsAggregateControl 40 41 { 42 public: 43 typedef std::vector<IUnknown *>ProxyPluginVector; 44 typedef std::vector<IPin *> PinVector; 45 46 STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface); 47 48 STDMETHODIMP_(ULONG) AddRef() 49 { 50 InterlockedIncrement(&m_Ref); 51 return m_Ref; 52 } 53 STDMETHODIMP_(ULONG) Release() 54 { 55 InterlockedDecrement(&m_Ref); 56 if (!m_Ref) 57 { 58 //delete this; 59 return 0; 60 } 61 return m_Ref; 62 } 63 64 // IBaseFilter methods 65 HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID); 66 HRESULT STDMETHODCALLTYPE Stop( void); 67 HRESULT STDMETHODCALLTYPE Pause( void); 68 HRESULT STDMETHODCALLTYPE Run(REFERENCE_TIME tStart); 69 HRESULT STDMETHODCALLTYPE GetState(DWORD dwMilliSecsTimeout, FILTER_STATE *State); 70 HRESULT STDMETHODCALLTYPE SetSyncSource(IReferenceClock *pClock); 71 HRESULT STDMETHODCALLTYPE GetSyncSource(IReferenceClock **pClock); 72 HRESULT STDMETHODCALLTYPE EnumPins(IEnumPins **ppEnum); 73 HRESULT STDMETHODCALLTYPE FindPin(LPCWSTR Id, IPin **ppPin); 74 HRESULT STDMETHODCALLTYPE QueryFilterInfo(FILTER_INFO *pInfo); 75 HRESULT STDMETHODCALLTYPE JoinFilterGraph(IFilterGraph *pGraph, LPCWSTR pName); 76 HRESULT STDMETHODCALLTYPE QueryVendorInfo(LPWSTR *pVendorInfo); 77 78 //IReferenceClock 79 HRESULT STDMETHODCALLTYPE GetTime(REFERENCE_TIME *pTime); 80 HRESULT STDMETHODCALLTYPE AdviseTime(REFERENCE_TIME baseTime, REFERENCE_TIME streamTime, HEVENT hEvent, DWORD_PTR *pdwAdviseCookie); 81 HRESULT STDMETHODCALLTYPE AdvisePeriodic(REFERENCE_TIME startTime, REFERENCE_TIME periodTime, HSEMAPHORE hSemaphore, DWORD_PTR *pdwAdviseCookie); 82 HRESULT STDMETHODCALLTYPE Unadvise(DWORD_PTR dwAdviseCookie); 83 84 //IMediaSeeking 85 HRESULT STDMETHODCALLTYPE GetCapabilities(DWORD *pCapabilities); 86 HRESULT STDMETHODCALLTYPE CheckCapabilities(DWORD *pCapabilities); 87 HRESULT STDMETHODCALLTYPE IsFormatSupported(const GUID *pFormat); 88 HRESULT STDMETHODCALLTYPE QueryPreferredFormat(GUID *pFormat); 89 HRESULT STDMETHODCALLTYPE GetTimeFormat(GUID *pFormat); 90 HRESULT STDMETHODCALLTYPE IsUsingTimeFormat(const GUID *pFormat); 91 HRESULT STDMETHODCALLTYPE SetTimeFormat(const GUID *pFormat); 92 HRESULT STDMETHODCALLTYPE GetDuration(LONGLONG *pDuration); 93 HRESULT STDMETHODCALLTYPE GetStopPosition(LONGLONG *pStop); 94 HRESULT STDMETHODCALLTYPE GetCurrentPosition(LONGLONG *pCurrent); 95 HRESULT STDMETHODCALLTYPE ConvertTimeFormat(LONGLONG *pTarget, const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat); 96 HRESULT STDMETHODCALLTYPE SetPositions(LONGLONG *pCurrent, DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags); 97 HRESULT STDMETHODCALLTYPE GetPositions(LONGLONG *pCurrent, LONGLONG *pStop); 98 HRESULT STDMETHODCALLTYPE GetAvailable(LONGLONG *pEarliest, LONGLONG *pLatest); 99 HRESULT STDMETHODCALLTYPE SetRate(double dRate); 100 HRESULT STDMETHODCALLTYPE GetRate(double *pdRate); 101 HRESULT STDMETHODCALLTYPE GetPreroll(LONGLONG *pllPreroll); 102 103 //IKsPropertySet 104 HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData); 105 HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, LPVOID pInstanceData, DWORD cbInstanceData, LPVOID pPropData, DWORD cbPropData, DWORD *pcbReturned); 106 HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport); 107 108 //IAMFilterMiscFlags 109 ULONG STDMETHODCALLTYPE GetMiscFlags( void); 110 111 //IKsControl 112 HRESULT STDMETHODCALLTYPE KsProperty(PKSPROPERTY Property, ULONG PropertyLength, LPVOID PropertyData, ULONG DataLength, ULONG* BytesReturned); 113 HRESULT STDMETHODCALLTYPE KsMethod(PKSMETHOD Method, ULONG MethodLength, LPVOID MethodData, ULONG DataLength, ULONG* BytesReturned); 114 HRESULT STDMETHODCALLTYPE KsEvent(PKSEVENT Event, ULONG EventLength, LPVOID EventData, ULONG DataLength, ULONG* BytesReturned); 115 116 //IKsTopolology 117 HRESULT STDMETHODCALLTYPE CreateNodeInstance(ULONG NodeId, ULONG Flags, ACCESS_MASK DesiredAccess, IUnknown* UnkOuter, REFGUID InterfaceId, LPVOID* Interface); 118 119 //IKsAggregateControl 120 HRESULT STDMETHODCALLTYPE KsAddAggregate(IN REFGUID AggregateClass); 121 HRESULT STDMETHODCALLTYPE KsRemoveAggregate(REFGUID AggregateClass); 122 123 //IKsClockPropertySet 124 HRESULT STDMETHODCALLTYPE KsGetTime(LONGLONG* Time); 125 HRESULT STDMETHODCALLTYPE KsSetTime(LONGLONG Time); 126 HRESULT STDMETHODCALLTYPE KsGetPhysicalTime(LONGLONG* Time); 127 HRESULT STDMETHODCALLTYPE KsSetPhysicalTime(LONGLONG Time); 128 HRESULT STDMETHODCALLTYPE KsGetCorrelatedTime(KSCORRELATED_TIME* CorrelatedTime); 129 HRESULT STDMETHODCALLTYPE KsSetCorrelatedTime(KSCORRELATED_TIME* CorrelatedTime); 130 HRESULT STDMETHODCALLTYPE KsGetCorrelatedPhysicalTime(KSCORRELATED_TIME* CorrelatedTime); 131 HRESULT STDMETHODCALLTYPE KsSetCorrelatedPhysicalTime(KSCORRELATED_TIME* CorrelatedTime); 132 HRESULT STDMETHODCALLTYPE KsGetResolution(KSRESOLUTION* Resolution); 133 HRESULT STDMETHODCALLTYPE KsGetState(KSSTATE* State); 134 135 136 //IAMovieSetup methods 137 HRESULT STDMETHODCALLTYPE Register( void); 138 HRESULT STDMETHODCALLTYPE Unregister( void); 139 140 // IPersistPropertyBag methods 141 HRESULT STDMETHODCALLTYPE InitNew( void); 142 HRESULT STDMETHODCALLTYPE Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog); 143 HRESULT STDMETHODCALLTYPE Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties); 144 145 // IKsObject 146 HANDLE STDMETHODCALLTYPE KsGetObjectHandle(); 147 148 // IKsClock 149 HANDLE STDMETHODCALLTYPE KsGetClockHandle(); 150 151 //IAMDeviceRemoval 152 HRESULT STDMETHODCALLTYPE DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink); 153 HRESULT STDMETHODCALLTYPE Reassociate(void); 154 HRESULT STDMETHODCALLTYPE Disassociate( void); 155 156 //IPersistStream 157 HRESULT STDMETHODCALLTYPE IsDirty( void); 158 HRESULT STDMETHODCALLTYPE Load(IStream *pStm); 159 HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty); 160 HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize); 161 162 // ISpecifyPropertyPages 163 HRESULT STDMETHODCALLTYPE GetPages(CAUUID *pPages); 164 165 166 CKsProxy(); 167 ~CKsProxy() 168 { 169 if (m_hDevice) 170 CloseHandle(m_hDevice); 171 }; 172 173 HRESULT STDMETHODCALLTYPE GetSupportedSets(LPGUID * pOutGuid, PULONG NumGuids); 174 HRESULT STDMETHODCALLTYPE LoadProxyPlugins(LPGUID pGuids, ULONG NumGuids); 175 HRESULT STDMETHODCALLTYPE GetNumberOfPins(PULONG NumPins); 176 HRESULT STDMETHODCALLTYPE GetPinInstanceCount(ULONG PinId, PKSPIN_CINSTANCES Instances); 177 HRESULT STDMETHODCALLTYPE GetPinDataflow(ULONG PinId, KSPIN_DATAFLOW * DataFlow); 178 HRESULT STDMETHODCALLTYPE GetPinName(ULONG PinId, KSPIN_DATAFLOW DataFlow, ULONG PinCount, LPWSTR * OutPinName); 179 HRESULT STDMETHODCALLTYPE GetPinCommunication(ULONG PinId, KSPIN_COMMUNICATION * Communication); 180 HRESULT STDMETHODCALLTYPE CreatePins(); 181 HRESULT STDMETHODCALLTYPE GetMediaSeekingFormats(PKSMULTIPLE_ITEM *FormatList); 182 HRESULT STDMETHODCALLTYPE CreateClockInstance(); 183 HRESULT STDMETHODCALLTYPE PerformClockProperty(ULONG PropertyId, ULONG PropertyFlags, PVOID OutputBuffer, ULONG OutputBufferSize); 184 HRESULT STDMETHODCALLTYPE SetPinState(KSSTATE State); 185 186 187 protected: 188 LONG m_Ref; 189 IFilterGraph *m_pGraph; 190 IReferenceClock * m_ReferenceClock; 191 FILTER_STATE m_FilterState; 192 HANDLE m_hDevice; 193 ProxyPluginVector m_Plugins; 194 PinVector m_Pins; 195 LPWSTR m_DevicePath; 196 CLSID m_DeviceInterfaceGUID; 197 HANDLE m_hClock; 198 CRITICAL_SECTION m_Lock; 199 }; 200 201 CKsProxy::CKsProxy() : m_Ref(0), 202 m_pGraph(0), 203 m_FilterState(State_Stopped), 204 m_hDevice(0), 205 m_Plugins(), 206 m_Pins(), 207 m_DevicePath(0), 208 m_hClock(0) 209 { 210 m_ReferenceClock = this; 211 InitializeCriticalSection(&m_Lock); 212 } 213 214 215 HRESULT 216 STDMETHODCALLTYPE 217 CKsProxy::QueryInterface( 218 IN REFIID refiid, 219 OUT PVOID* Output) 220 { 221 *Output = NULL; 222 223 if (IsEqualGUID(refiid, IID_IUnknown) || 224 IsEqualGUID(refiid, IID_IBaseFilter)) 225 { 226 *Output = PVOID(this); 227 reinterpret_cast<IUnknown*>(*Output)->AddRef(); 228 return NOERROR; 229 } 230 else if (IsEqualGUID(refiid, IID_IPersistPropertyBag)) 231 { 232 *Output = (IPersistPropertyBag*)(this); 233 reinterpret_cast<IPersistPropertyBag*>(*Output)->AddRef(); 234 return NOERROR; 235 } 236 else if (IsEqualGUID(refiid, IID_IAMDeviceRemoval)) 237 { 238 *Output = (IAMDeviceRemoval*)(this); 239 reinterpret_cast<IAMDeviceRemoval*>(*Output)->AddRef(); 240 return NOERROR; 241 } 242 else if (IsEqualGUID(refiid, IID_IPersistStream)) 243 { 244 *Output = (IPersistStream*)(this); 245 reinterpret_cast<IPersistStream*>(*Output)->AddRef(); 246 return NOERROR; 247 } 248 else if (IsEqualGUID(refiid, IID_IPersist)) 249 { 250 *Output = (IPersistStream*)(this); 251 reinterpret_cast<IPersist*>(*Output)->AddRef(); 252 return NOERROR; 253 } 254 else if (IsEqualGUID(refiid, IID_IKsObject)) 255 { 256 *Output = (IKsObject*)(this); 257 reinterpret_cast<IKsObject*>(*Output)->AddRef(); 258 return NOERROR; 259 } 260 else if (IsEqualGUID(refiid, IID_IKsClock)) 261 { 262 *Output = (IKsClock*)(this); 263 reinterpret_cast<IKsClock*>(*Output)->AddRef(); 264 return NOERROR; 265 } 266 else if (IsEqualGUID(refiid, IID_IReferenceClock)) 267 { 268 if (!m_hClock) 269 { 270 HRESULT hr = CreateClockInstance(); 271 if (FAILED(hr)) 272 return hr; 273 } 274 275 *Output = (IReferenceClock*)(this); 276 reinterpret_cast<IReferenceClock*>(*Output)->AddRef(); 277 return NOERROR; 278 } 279 else if (IsEqualGUID(refiid, IID_IMediaSeeking)) 280 { 281 *Output = (IMediaSeeking*)(this); 282 reinterpret_cast<IMediaSeeking*>(*Output)->AddRef(); 283 return NOERROR; 284 } 285 else if (IsEqualGUID(refiid, IID_IAMFilterMiscFlags)) 286 { 287 *Output = (IAMFilterMiscFlags*)(this); 288 reinterpret_cast<IAMFilterMiscFlags*>(*Output)->AddRef(); 289 return NOERROR; 290 } 291 else if (IsEqualGUID(refiid, IID_IKsControl)) 292 { 293 *Output = (IKsControl*)(this); 294 reinterpret_cast<IKsControl*>(*Output)->AddRef(); 295 return NOERROR; 296 } 297 else if (IsEqualGUID(refiid, IID_IKsPropertySet)) 298 { 299 *Output = (IKsPropertySet*)(this); 300 reinterpret_cast<IKsPropertySet*>(*Output)->AddRef(); 301 return NOERROR; 302 } 303 else if (IsEqualGUID(refiid, IID_IKsTopology)) 304 { 305 *Output = (IKsTopology*)(this); 306 reinterpret_cast<IKsTopology*>(*Output)->AddRef(); 307 return NOERROR; 308 } 309 else if (IsEqualGUID(refiid, IID_IKsAggregateControl)) 310 { 311 *Output = (IKsAggregateControl*)(this); 312 reinterpret_cast<IKsAggregateControl*>(*Output)->AddRef(); 313 return NOERROR; 314 } 315 else if (IsEqualGUID(refiid, IID_IKsClockPropertySet)) 316 { 317 if (!m_hClock) 318 { 319 HRESULT hr = CreateClockInstance(); 320 if (FAILED(hr)) 321 return hr; 322 } 323 324 *Output = (IKsClockPropertySet*)(this); 325 reinterpret_cast<IKsClockPropertySet*>(*Output)->AddRef(); 326 return NOERROR; 327 } 328 else if (IsEqualGUID(refiid, IID_ISpecifyPropertyPages)) 329 { 330 *Output = (ISpecifyPropertyPages*)(this); 331 reinterpret_cast<ISpecifyPropertyPages*>(*Output)->AddRef(); 332 return NOERROR; 333 } 334 335 for(ULONG Index = 0; Index < m_Plugins.size(); Index++) 336 { 337 if (m_Pins[Index]) 338 { 339 HRESULT hr = m_Plugins[Index]->QueryInterface(refiid, Output); 340 if (SUCCEEDED(hr)) 341 { 342 #ifdef KSPROXY_TRACE 343 WCHAR Buffer[100]; 344 LPOLESTR lpstr; 345 StringFromCLSID(refiid, &lpstr); 346 swprintf(Buffer, L"CKsProxy::QueryInterface plugin %lu supports interface %s\n", Index, lpstr); 347 OutputDebugStringW(Buffer); 348 CoTaskMemFree(lpstr); 349 #endif 350 return hr; 351 } 352 } 353 } 354 #ifdef KSPROXY_TRACE 355 WCHAR Buffer[MAX_PATH]; 356 LPOLESTR lpstr; 357 StringFromCLSID(refiid, &lpstr); 358 swprintf(Buffer, L"CKsProxy::QueryInterface: NoInterface for %s !!!\n", lpstr); 359 OutputDebugStringW(Buffer); 360 CoTaskMemFree(lpstr); 361 #endif 362 363 return E_NOINTERFACE; 364 } 365 366 //------------------------------------------------------------------- 367 // ISpecifyPropertyPages 368 // 369 370 HRESULT 371 STDMETHODCALLTYPE 372 CKsProxy::GetPages(CAUUID *pPages) 373 { 374 #ifdef KSPROXY_TRACE 375 OutputDebugStringW(L"CKsProxy::GetPages NotImplemented\n"); 376 #endif 377 378 if (!pPages) 379 return E_POINTER; 380 381 pPages->cElems = 0; 382 pPages->pElems = NULL; 383 384 return S_OK; 385 } 386 387 //------------------------------------------------------------------- 388 // IKsClockPropertySet interface 389 // 390 391 HRESULT 392 STDMETHODCALLTYPE 393 CKsProxy::CreateClockInstance() 394 { 395 HRESULT hr; 396 HANDLE hPin = INVALID_HANDLE_VALUE; 397 ULONG Index; 398 PIN_DIRECTION PinDir; 399 IKsObject *pObject; 400 KSCLOCK_CREATE ClockCreate; 401 402 // find output pin and handle 403 for(Index = 0; Index < m_Pins.size(); Index++) 404 { 405 //get pin 406 IPin * pin = m_Pins[Index]; 407 if (!pin) 408 continue; 409 410 // get direction 411 hr = pin->QueryDirection(&PinDir); 412 if (FAILED(hr)) 413 continue; 414 415 // query IKsObject interface 416 hr = pin->QueryInterface(IID_IKsObject, (void**)&pObject); 417 if (FAILED(hr)) 418 continue; 419 420 421 // get pin handle 422 hPin = pObject->KsGetObjectHandle(); 423 424 //release IKsObject 425 pObject->Release(); 426 427 if (hPin != INVALID_HANDLE_VALUE) 428 break; 429 } 430 431 if (hPin == INVALID_HANDLE_VALUE) 432 { 433 // clock can only be instantiated on a pin handle 434 return E_NOTIMPL; 435 } 436 437 if (m_hClock) 438 { 439 // release clock handle 440 CloseHandle(m_hClock); 441 } 442 443 //setup clock create request 444 ClockCreate.CreateFlags = 0; 445 446 // setup clock create request 447 hr = KsCreateClock(hPin, &ClockCreate, &m_hClock); // FIXME KsCreateClock returns NTSTATUS 448 if (SUCCEEDED(hr)) 449 { 450 // failed to create clock 451 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); 452 } 453 454 return S_OK; 455 } 456 457 HRESULT 458 STDMETHODCALLTYPE 459 CKsProxy::PerformClockProperty( 460 ULONG PropertyId, 461 ULONG PropertyFlags, 462 PVOID OutputBuffer, 463 ULONG OutputBufferSize) 464 { 465 KSPROPERTY Property; 466 HRESULT hr; 467 ULONG BytesReturned; 468 469 if (!m_hClock) 470 { 471 // create clock 472 hr = CreateClockInstance(); 473 if (FAILED(hr)) 474 return hr; 475 } 476 477 // setup request 478 Property.Set = KSPROPSETID_Clock; 479 Property.Id = PropertyId; 480 Property.Flags = PropertyFlags; 481 482 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)OutputBuffer, OutputBufferSize, &BytesReturned); 483 484 return hr; 485 } 486 487 HRESULT 488 STDMETHODCALLTYPE 489 CKsProxy::KsGetTime( 490 LONGLONG* Time) 491 { 492 #ifdef KSPROXY_TRACE 493 OutputDebugStringW(L"CKsProxy::KsGetTime\n"); 494 #endif 495 496 return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG)); 497 } 498 499 HRESULT 500 STDMETHODCALLTYPE 501 CKsProxy::KsSetTime( 502 LONGLONG Time) 503 { 504 #ifdef KSPROXY_TRACE 505 OutputDebugStringW(L"CKsProxy::KsSetTime\n"); 506 #endif 507 508 return PerformClockProperty(KSPROPERTY_CLOCK_TIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG)); 509 } 510 511 HRESULT 512 STDMETHODCALLTYPE 513 CKsProxy::KsGetPhysicalTime( 514 LONGLONG* Time) 515 { 516 #ifdef KSPROXY_TRACE 517 OutputDebugStringW(L"CKsProxy::KsGetPhysicalTime\n"); 518 #endif 519 520 return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)Time, sizeof(LONGLONG)); 521 } 522 523 HRESULT 524 STDMETHODCALLTYPE 525 CKsProxy::KsSetPhysicalTime( 526 LONGLONG Time) 527 { 528 #ifdef KSPROXY_TRACE 529 OutputDebugStringW(L"CKsProxy::KsSetPhysicalTime\n"); 530 #endif 531 532 return PerformClockProperty(KSPROPERTY_CLOCK_PHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)&Time, sizeof(LONGLONG)); 533 } 534 535 HRESULT 536 STDMETHODCALLTYPE 537 CKsProxy::KsGetCorrelatedTime( 538 KSCORRELATED_TIME* CorrelatedTime) 539 { 540 #ifdef KSPROXY_TRACE 541 OutputDebugStringW(L"CKsProxy::KsGetCorrelatedTime\n"); 542 #endif 543 544 return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME)); 545 } 546 547 HRESULT 548 STDMETHODCALLTYPE 549 CKsProxy::KsSetCorrelatedTime( 550 KSCORRELATED_TIME* CorrelatedTime) 551 { 552 #ifdef KSPROXY_TRACE 553 OutputDebugStringW(L"CKsProxy::KsSetCorrelatedTime\n"); 554 #endif 555 return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME)); 556 } 557 558 HRESULT 559 STDMETHODCALLTYPE 560 CKsProxy::KsGetCorrelatedPhysicalTime( 561 KSCORRELATED_TIME* CorrelatedTime) 562 { 563 #ifdef KSPROXY_TRACE 564 OutputDebugStringW(L"CKsProxy::KsGetCorrelatedPhysicalTime\n"); 565 #endif 566 return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_GET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME)); 567 } 568 569 HRESULT 570 STDMETHODCALLTYPE 571 CKsProxy::KsSetCorrelatedPhysicalTime( 572 KSCORRELATED_TIME* CorrelatedTime) 573 { 574 #ifdef KSPROXY_TRACE 575 OutputDebugStringW(L"CKsProxy::KsSetCorrelatedPhysicalTime\n"); 576 #endif 577 578 return PerformClockProperty(KSPROPERTY_CLOCK_CORRELATEDPHYSICALTIME, KSPROPERTY_TYPE_SET, (PVOID)CorrelatedTime, sizeof(KSCORRELATED_TIME)); 579 } 580 581 HRESULT 582 STDMETHODCALLTYPE 583 CKsProxy::KsGetResolution( 584 KSRESOLUTION* Resolution) 585 { 586 #ifdef KSPROXY_TRACE 587 OutputDebugStringW(L"CKsProxy::KsGetResolution\n"); 588 #endif 589 return PerformClockProperty(KSPROPERTY_CLOCK_RESOLUTION, KSPROPERTY_TYPE_GET, (PVOID)Resolution, sizeof(KSRESOLUTION)); 590 } 591 592 HRESULT 593 STDMETHODCALLTYPE 594 CKsProxy::KsGetState( 595 KSSTATE* State) 596 { 597 #ifdef KSPROXY_TRACE 598 OutputDebugStringW(L"CKsProxy::KsGetState\n"); 599 #endif 600 return PerformClockProperty(KSPROPERTY_CLOCK_STATE, KSPROPERTY_TYPE_GET, (PVOID)State, sizeof(KSSTATE)); 601 } 602 603 //------------------------------------------------------------------- 604 // IReferenceClock interface 605 // 606 HRESULT 607 STDMETHODCALLTYPE 608 CKsProxy::GetTime( 609 REFERENCE_TIME *pTime) 610 { 611 HRESULT hr; 612 KSPROPERTY Property; 613 ULONG BytesReturned; 614 615 #ifdef KSPROXY_TRACE 616 OutputDebugStringW(L"CKsProxy::GetTime\n"); 617 #endif 618 619 if (!pTime) 620 return E_POINTER; 621 622 // 623 //FIXME locks 624 // 625 626 if (!m_hClock) 627 { 628 // create clock 629 hr = CreateClockInstance(); 630 if (FAILED(hr)) 631 return hr; 632 } 633 634 // setup request 635 Property.Set = KSPROPSETID_Clock; 636 Property.Id = KSPROPERTY_CLOCK_TIME; 637 Property.Flags = KSPROPERTY_TYPE_GET; 638 639 // perform request 640 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pTime, sizeof(REFERENCE_TIME), &BytesReturned); 641 642 // TODO 643 // increment value 644 // 645 646 return hr; 647 } 648 649 HRESULT 650 STDMETHODCALLTYPE 651 CKsProxy::AdviseTime( 652 REFERENCE_TIME baseTime, 653 REFERENCE_TIME streamTime, 654 HEVENT hEvent, 655 DWORD_PTR *pdwAdviseCookie) 656 { 657 HRESULT hr; 658 KSEVENT Property; 659 ULONG BytesReturned; 660 PKSEVENT_TIME_MARK Event; 661 662 #ifdef KSPROXY_TRACE 663 OutputDebugStringW(L"CKsProxy::AdviseTime\n"); 664 #endif 665 666 // 667 //FIXME locks 668 // 669 670 if (!pdwAdviseCookie) 671 return E_POINTER; 672 673 if (!m_hClock) 674 { 675 // create clock 676 hr = CreateClockInstance(); 677 if (FAILED(hr)) 678 return hr; 679 } 680 681 // allocate event entry 682 Event = (PKSEVENT_TIME_MARK)CoTaskMemAlloc(sizeof(KSEVENT_TIME_MARK)); 683 if (Event) 684 { 685 // setup request 686 Property.Set = KSEVENTSETID_Clock; 687 Property.Id = KSEVENT_CLOCK_POSITION_MARK; 688 Property.Flags = KSEVENT_TYPE_ENABLE; 689 690 Event->EventData.NotificationType = KSEVENTF_EVENT_HANDLE; 691 Event->EventData.EventHandle.Event = (HANDLE)hEvent; 692 Event->EventData.Alignment.Alignment[0] = 0; 693 Event->EventData.Alignment.Alignment[1] = 0; 694 Event->MarkTime = baseTime + streamTime; 695 696 // perform request 697 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSEVENT), (PVOID)Event, sizeof(KSEVENT_TIME_MARK), &BytesReturned); 698 if (SUCCEEDED(hr)) 699 { 700 // store event handle 701 *pdwAdviseCookie = (DWORD_PTR)Event; 702 } 703 else 704 { 705 // failed to enable event 706 CoTaskMemFree(Event); 707 } 708 } 709 else 710 { 711 hr = E_OUTOFMEMORY; 712 } 713 714 return hr; 715 } 716 717 HRESULT 718 STDMETHODCALLTYPE 719 CKsProxy::AdvisePeriodic( 720 REFERENCE_TIME startTime, 721 REFERENCE_TIME periodTime, 722 HSEMAPHORE hSemaphore, 723 DWORD_PTR *pdwAdviseCookie) 724 { 725 HRESULT hr; 726 KSEVENT Property; 727 ULONG BytesReturned; 728 PKSEVENT_TIME_INTERVAL Event; 729 730 #ifdef KSPROXY_TRACE 731 OutputDebugStringW(L"CKsProxy::AdvisePeriodic\n"); 732 #endif 733 734 // 735 //FIXME locks 736 // 737 738 if (!pdwAdviseCookie) 739 return E_POINTER; 740 741 if (!m_hClock) 742 { 743 // create clock 744 hr = CreateClockInstance(); 745 if (FAILED(hr)) 746 return hr; 747 } 748 749 // allocate event entry 750 Event = (PKSEVENT_TIME_INTERVAL)CoTaskMemAlloc(sizeof(KSEVENT_TIME_INTERVAL)); 751 if (Event) 752 { 753 // setup request 754 Property.Set = KSEVENTSETID_Clock; 755 Property.Id = KSEVENT_CLOCK_INTERVAL_MARK; 756 Property.Flags = KSEVENT_TYPE_ENABLE; 757 758 Event->EventData.NotificationType = KSEVENTF_SEMAPHORE_HANDLE; 759 Event->EventData.SemaphoreHandle.Semaphore = (HANDLE)hSemaphore; 760 Event->EventData.SemaphoreHandle.Reserved = 0; 761 Event->EventData.SemaphoreHandle.Adjustment = 1; 762 Event->TimeBase = startTime; 763 Event->Interval = periodTime; 764 765 // perform request 766 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSEVENT), (PVOID)Event, sizeof(KSEVENT_TIME_INTERVAL), &BytesReturned); 767 if (SUCCEEDED(hr)) 768 { 769 // store event handle 770 *pdwAdviseCookie = (DWORD_PTR)Event; 771 } 772 else 773 { 774 // failed to enable event 775 CoTaskMemFree(Event); 776 } 777 } 778 else 779 { 780 hr = E_OUTOFMEMORY; 781 } 782 783 return hr; 784 } 785 786 HRESULT 787 STDMETHODCALLTYPE 788 CKsProxy::Unadvise( 789 DWORD_PTR dwAdviseCookie) 790 { 791 HRESULT hr; 792 ULONG BytesReturned; 793 794 #ifdef KSPROXY_TRACE 795 OutputDebugStringW(L"CKsProxy::Unadvise\n"); 796 #endif 797 798 if (m_hClock) 799 { 800 //lets disable the event 801 hr = KsSynchronousDeviceControl(m_hClock, IOCTL_KS_DISABLE_EVENT, (PVOID)dwAdviseCookie, sizeof(KSEVENTDATA), 0, 0, &BytesReturned); 802 if (SUCCEEDED(hr)) 803 { 804 // lets free event data 805 CoTaskMemFree((LPVOID)dwAdviseCookie); 806 } 807 } 808 else 809 { 810 // no clock available 811 hr = E_FAIL; 812 } 813 814 return hr; 815 } 816 817 //------------------------------------------------------------------- 818 // IMediaSeeking interface 819 // 820 HRESULT 821 STDMETHODCALLTYPE 822 CKsProxy::GetCapabilities( 823 DWORD *pCapabilities) 824 { 825 KSPROPERTY Property; 826 ULONG BytesReturned, Index; 827 HRESULT hr = S_OK; 828 DWORD TempCaps; 829 830 Property.Set = KSPROPSETID_MediaSeeking; 831 Property.Id = KSPROPERTY_MEDIASEEKING_CAPABILITIES; 832 Property.Flags = KSPROPERTY_TYPE_GET; 833 834 #ifdef KSPROXY_TRACE 835 OutputDebugStringW(L"CKsProxy::GetCapabilities\n"); 836 #endif 837 838 839 if (!pCapabilities) 840 return E_POINTER; 841 842 843 *pCapabilities = (KS_SEEKING_CanSeekAbsolute | KS_SEEKING_CanSeekForwards | KS_SEEKING_CanSeekBackwards | KS_SEEKING_CanGetCurrentPos | 844 KS_SEEKING_CanGetStopPos | KS_SEEKING_CanGetDuration | KS_SEEKING_CanPlayBackwards); 845 846 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pCapabilities, sizeof(KS_SEEKING_CAPABILITIES), &BytesReturned); 847 // check if plugins support it 848 for(Index = 0; Index < m_Plugins.size(); Index++) 849 { 850 // get plugin 851 IUnknown * Plugin = m_Plugins[Index]; 852 853 if (!Plugin) 854 continue; 855 856 // query for IMediaSeeking interface 857 IMediaSeeking *pSeek = NULL; 858 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 859 if (FAILED(hr)) 860 { 861 *pCapabilities = 0; 862 return hr; 863 } 864 865 TempCaps = 0; 866 // set time format 867 hr = pSeek->GetCapabilities(&TempCaps); 868 if (SUCCEEDED(hr)) 869 { 870 // and with supported flags 871 *pCapabilities = (*pCapabilities & TempCaps); 872 } 873 // release IMediaSeeking interface 874 pSeek->Release(); 875 } 876 return hr; 877 } 878 879 HRESULT 880 STDMETHODCALLTYPE 881 CKsProxy::CheckCapabilities( 882 DWORD *pCapabilities) 883 { 884 DWORD Capabilities; 885 HRESULT hr; 886 887 #ifdef KSPROXY_TRACE 888 OutputDebugStringW(L"CKsProxy::CheckCapabilities\n"); 889 #endif 890 891 if (!pCapabilities) 892 return E_POINTER; 893 894 if (!*pCapabilities) 895 return E_FAIL; 896 897 hr = GetCapabilities(&Capabilities); 898 if (SUCCEEDED(hr)) 899 { 900 if ((Capabilities | *pCapabilities) == Capabilities) 901 { 902 // all present 903 return S_OK; 904 } 905 906 Capabilities = (Capabilities & *pCapabilities); 907 if (Capabilities) 908 { 909 // not all present 910 *pCapabilities = Capabilities; 911 return S_FALSE; 912 } 913 // no capabilities are present 914 return E_FAIL; 915 } 916 917 return hr; 918 } 919 920 HRESULT 921 STDMETHODCALLTYPE 922 CKsProxy::GetMediaSeekingFormats( 923 PKSMULTIPLE_ITEM *FormatList) 924 { 925 KSPROPERTY Property; 926 HRESULT hr; 927 ULONG BytesReturned; 928 929 Property.Set = KSPROPSETID_MediaSeeking; 930 Property.Id = KSPROPERTY_MEDIASEEKING_FORMATS; 931 Property.Flags = KSPROPERTY_TYPE_GET; 932 933 // query for format size list 934 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &BytesReturned); 935 936 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA)) 937 { 938 // allocate format list 939 *FormatList = (PKSMULTIPLE_ITEM)CoTaskMemAlloc(BytesReturned); 940 if (!*FormatList) 941 { 942 // not enough memory 943 return E_OUTOFMEMORY; 944 } 945 946 // get format list 947 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)*FormatList, BytesReturned, &BytesReturned); 948 if (FAILED(hr)) 949 { 950 // failed to query format list 951 CoTaskMemFree(FormatList); 952 } 953 } 954 return hr; 955 } 956 957 HRESULT 958 STDMETHODCALLTYPE 959 CKsProxy::IsFormatSupported( 960 const GUID *pFormat) 961 { 962 PKSMULTIPLE_ITEM FormatList; 963 LPGUID pGuid; 964 ULONG Index; 965 HRESULT hr = S_FALSE; 966 967 #ifdef KSPROXY_TRACE 968 WCHAR Buffer[100]; 969 LPOLESTR pstr; 970 StringFromCLSID(*pFormat, &pstr); 971 swprintf(Buffer, L"CKsProxy::IsFormatSupported %s\n",pstr); 972 OutputDebugStringW(Buffer); 973 #endif 974 975 if (!pFormat) 976 return E_POINTER; 977 978 // get media formats 979 hr = GetMediaSeekingFormats(&FormatList); 980 if (SUCCEEDED(hr)) 981 { 982 #ifdef KSPROXY_TRACE 983 swprintf(Buffer, L"CKsProxy::IsFormatSupported NumFormat %lu\n",FormatList->Count); 984 OutputDebugStringW(Buffer); 985 #endif 986 987 //iterate through format list 988 pGuid = (LPGUID)(FormatList + 1); 989 for(Index = 0; Index < FormatList->Count; Index++) 990 { 991 if (IsEqualGUID(*pGuid, *pFormat)) 992 { 993 CoTaskMemFree(FormatList); 994 return S_OK; 995 } 996 pGuid++; 997 } 998 // free format list 999 CoTaskMemFree(FormatList); 1000 } 1001 1002 // check if all plugins support it 1003 for(Index = 0; Index < m_Plugins.size(); Index++) 1004 { 1005 // get plugin 1006 IUnknown * Plugin = m_Plugins[Index]; 1007 1008 if (!Plugin) 1009 continue; 1010 1011 // query for IMediaSeeking interface 1012 IMediaSeeking *pSeek = NULL; 1013 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1014 if (FAILED(hr)) 1015 { 1016 // plugin does not support interface 1017 hr = S_FALSE; 1018 #ifdef KSPROXY_TRACE 1019 OutputDebugStringW(L"CKsProxy::IsFormatSupported plugin does not support IMediaSeeking interface\n"); 1020 #endif 1021 break; 1022 } 1023 1024 // query if it is supported 1025 hr = pSeek->IsFormatSupported(pFormat); 1026 // release interface 1027 pSeek->Release(); 1028 1029 if (FAILED(hr) || hr == S_FALSE) 1030 break; 1031 } 1032 1033 return hr; 1034 } 1035 1036 HRESULT 1037 STDMETHODCALLTYPE 1038 CKsProxy::QueryPreferredFormat( 1039 GUID *pFormat) 1040 { 1041 PKSMULTIPLE_ITEM FormatList; 1042 HRESULT hr; 1043 ULONG Index; 1044 1045 #ifdef KSPROXY_TRACE 1046 OutputDebugStringW(L"CKsProxy::QueryPreferredFormat\n"); 1047 #endif 1048 1049 if (!pFormat) 1050 return E_POINTER; 1051 1052 hr = GetMediaSeekingFormats(&FormatList); 1053 if (SUCCEEDED(hr)) 1054 { 1055 if (FormatList->Count) 1056 { 1057 CopyMemory(pFormat, (FormatList + 1), sizeof(GUID)); 1058 CoTaskMemFree(FormatList); 1059 return S_OK; 1060 } 1061 CoTaskMemFree(FormatList); 1062 } 1063 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1064 { 1065 // check if plugins support it 1066 for(Index = 0; Index < m_Plugins.size(); Index++) 1067 { 1068 // get plugin 1069 IUnknown * Plugin = m_Plugins[Index]; 1070 1071 if (!Plugin) 1072 continue; 1073 1074 // query for IMediaSeeking interface 1075 IMediaSeeking *pSeek = NULL; 1076 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1077 if (SUCCEEDED(hr)) 1078 { 1079 // get preferred time format 1080 hr = pSeek->QueryPreferredFormat(pFormat); 1081 // release IMediaSeeking interface 1082 pSeek->Release(); 1083 1084 if (hr != S_FALSE) 1085 return hr; 1086 } 1087 } 1088 hr = S_FALSE; 1089 } 1090 1091 return hr; 1092 } 1093 1094 HRESULT 1095 STDMETHODCALLTYPE 1096 CKsProxy::GetTimeFormat( 1097 GUID *pFormat) 1098 { 1099 KSPROPERTY Property; 1100 ULONG BytesReturned, Index; 1101 HRESULT hr; 1102 1103 Property.Set = KSPROPSETID_MediaSeeking; 1104 Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT; 1105 Property.Flags = KSPROPERTY_TYPE_GET; 1106 1107 #ifdef KSPROXY_TRACE 1108 OutputDebugStringW(L"CKsProxy::GetTimeFormat\n"); 1109 #endif 1110 1111 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned); 1112 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1113 { 1114 // check if plugins support it 1115 for(Index = 0; Index < m_Plugins.size(); Index++) 1116 { 1117 hr = E_NOTIMPL; 1118 // get plugin 1119 IUnknown * Plugin = m_Plugins[Index]; 1120 1121 if (!Plugin) 1122 continue; 1123 1124 // query for IMediaSeeking interface 1125 IMediaSeeking *pSeek = NULL; 1126 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1127 if (SUCCEEDED(hr)) 1128 { 1129 // set time format 1130 hr = pSeek->GetTimeFormat(pFormat); 1131 // release IMediaSeeking interface 1132 pSeek->Release(); 1133 1134 if (hr != S_FALSE) 1135 break; 1136 } 1137 } 1138 } 1139 return hr; 1140 } 1141 1142 HRESULT 1143 STDMETHODCALLTYPE 1144 CKsProxy::IsUsingTimeFormat( 1145 const GUID *pFormat) 1146 { 1147 GUID Format; 1148 1149 #ifdef KSPROXY_TRACE 1150 OutputDebugStringW(L"CKsProxy::IsUsingTimeFormat\n"); 1151 #endif 1152 1153 if (FAILED(QueryPreferredFormat(&Format))) 1154 return S_FALSE; 1155 1156 if (IsEqualGUID(Format, *pFormat)) 1157 return S_OK; 1158 else 1159 return S_FALSE; 1160 } 1161 1162 HRESULT 1163 STDMETHODCALLTYPE 1164 CKsProxy::SetTimeFormat( 1165 const GUID *pFormat) 1166 { 1167 KSPROPERTY Property; 1168 ULONG BytesReturned, Index; 1169 HRESULT hr; 1170 1171 Property.Set = KSPROPSETID_MediaSeeking; 1172 Property.Id = KSPROPERTY_MEDIASEEKING_TIMEFORMAT; 1173 Property.Flags = KSPROPERTY_TYPE_SET; 1174 1175 #ifdef KSPROXY_TRACE 1176 OutputDebugStringW(L"CKsProxy::SetTimeFormat\n"); 1177 #endif 1178 1179 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pFormat, sizeof(GUID), &BytesReturned); 1180 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1181 { 1182 // check if plugins support it 1183 for(Index = 0; Index < m_Plugins.size(); Index++) 1184 { 1185 hr = E_NOTIMPL; 1186 // get plugin 1187 IUnknown * Plugin = m_Plugins[Index]; 1188 1189 if (!Plugin) 1190 continue; 1191 1192 // query for IMediaSeeking interface 1193 IMediaSeeking *pSeek = NULL; 1194 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1195 if (FAILED(hr)) 1196 { 1197 //not supported 1198 break; 1199 } 1200 // set time format 1201 hr = pSeek->SetTimeFormat(pFormat); 1202 // release IMediaSeeking interface 1203 pSeek->Release(); 1204 1205 if (FAILED(hr)) 1206 break; 1207 } 1208 } 1209 return hr; 1210 } 1211 1212 HRESULT 1213 STDMETHODCALLTYPE 1214 CKsProxy::GetDuration( 1215 LONGLONG *pDuration) 1216 { 1217 KSPROPERTY Property; 1218 ULONG BytesReturned, Index; 1219 HRESULT hr; 1220 1221 Property.Set = KSPROPSETID_MediaSeeking; 1222 Property.Id = KSPROPERTY_MEDIASEEKING_DURATION; 1223 Property.Flags = KSPROPERTY_TYPE_GET; 1224 1225 #ifdef KSPROXY_TRACE 1226 OutputDebugStringW(L"CKsProxy::GetDuration\n"); 1227 #endif 1228 1229 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pDuration, sizeof(LONGLONG), &BytesReturned); 1230 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1231 { 1232 // check if plugins support it 1233 for(Index = 0; Index < m_Plugins.size(); Index++) 1234 { 1235 hr = E_NOTIMPL; 1236 // get plugin 1237 IUnknown * Plugin = m_Plugins[Index]; 1238 1239 if (!Plugin) 1240 continue; 1241 1242 // query for IMediaSeeking interface 1243 IMediaSeeking *pSeek = NULL; 1244 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1245 if (SUCCEEDED(hr)) 1246 { 1247 // get duration 1248 hr = pSeek->GetStopPosition(pDuration); 1249 // release IMediaSeeking interface 1250 pSeek->Release(); 1251 1252 if (hr != S_FALSE) // plugin implements it 1253 break; 1254 } 1255 } 1256 } 1257 return hr; 1258 } 1259 1260 HRESULT 1261 STDMETHODCALLTYPE 1262 CKsProxy::GetStopPosition( 1263 LONGLONG *pStop) 1264 { 1265 KSPROPERTY Property; 1266 ULONG BytesReturned, Index; 1267 HRESULT hr; 1268 1269 Property.Set = KSPROPSETID_MediaSeeking; 1270 Property.Id = KSPROPERTY_MEDIASEEKING_STOPPOSITION; 1271 Property.Flags = KSPROPERTY_TYPE_GET; 1272 1273 #ifdef KSPROXY_TRACE 1274 OutputDebugStringW(L"CKsProxy::GetStopPosition\n"); 1275 #endif 1276 1277 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pStop, sizeof(LONGLONG), &BytesReturned); 1278 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1279 { 1280 // check if plugins support it 1281 for(Index = 0; Index < m_Plugins.size(); Index++) 1282 { 1283 hr = E_NOTIMPL; 1284 // get plugin 1285 IUnknown * Plugin = m_Plugins[Index]; 1286 1287 if (!Plugin) 1288 continue; 1289 1290 // query for IMediaSeeking interface 1291 IMediaSeeking *pSeek = NULL; 1292 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1293 if (SUCCEEDED(hr)) 1294 { 1295 // get stop position 1296 hr = pSeek->GetStopPosition(pStop); 1297 // release IMediaSeeking interface 1298 pSeek->Release(); 1299 1300 if (hr != S_FALSE) // plugin implements it 1301 break; 1302 } 1303 } 1304 } 1305 return hr; 1306 } 1307 1308 HRESULT 1309 STDMETHODCALLTYPE 1310 CKsProxy::GetCurrentPosition( 1311 LONGLONG *pCurrent) 1312 { 1313 KSPROPERTY Property; 1314 ULONG BytesReturned, Index; 1315 HRESULT hr; 1316 1317 Property.Set = KSPROPSETID_MediaSeeking; 1318 Property.Id = KSPROPERTY_MEDIASEEKING_POSITION; 1319 Property.Flags = KSPROPERTY_TYPE_GET; 1320 1321 #ifdef KSPROXY_TRACE 1322 OutputDebugStringW(L"CKsProxy::GetCurrentPosition\n"); 1323 #endif 1324 1325 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pCurrent, sizeof(LONGLONG), &BytesReturned); 1326 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1327 { 1328 // check if plugins support it 1329 for(Index = 0; Index < m_Plugins.size(); Index++) 1330 { 1331 hr = E_NOTIMPL; 1332 // get plugin 1333 IUnknown * Plugin = m_Plugins[Index]; 1334 1335 if (!Plugin) 1336 continue; 1337 1338 // query for IMediaSeeking interface 1339 IMediaSeeking *pSeek = NULL; 1340 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1341 if (SUCCEEDED(hr)) 1342 { 1343 // get current position 1344 hr = pSeek->GetCurrentPosition(pCurrent); 1345 // release IMediaSeeking interface 1346 pSeek->Release(); 1347 1348 if (hr != S_FALSE) // plugin implements it 1349 break; 1350 } 1351 } 1352 } 1353 return hr; 1354 } 1355 1356 HRESULT 1357 STDMETHODCALLTYPE 1358 CKsProxy::ConvertTimeFormat( 1359 LONGLONG *pTarget, 1360 const GUID *pTargetFormat, 1361 LONGLONG Source, 1362 const GUID *pSourceFormat) 1363 { 1364 KSP_TIMEFORMAT Property; 1365 ULONG BytesReturned, Index; 1366 GUID SourceFormat, TargetFormat; 1367 HRESULT hr; 1368 1369 Property.Property.Set = KSPROPSETID_MediaSeeking; 1370 Property.Property.Id = KSPROPERTY_MEDIASEEKING_CONVERTTIMEFORMAT; 1371 Property.Property.Flags = KSPROPERTY_TYPE_GET; 1372 1373 #ifdef KSPROXY_TRACE 1374 OutputDebugStringW(L"CKsProxy::ConvertTimeFormat\n"); 1375 #endif 1376 1377 if (!pTargetFormat) 1378 { 1379 // get current format 1380 hr = GetTimeFormat(&TargetFormat); 1381 if (FAILED(hr)) 1382 return hr; 1383 1384 pTargetFormat = &TargetFormat; 1385 } 1386 1387 if (!pSourceFormat) 1388 { 1389 // get current format 1390 hr = GetTimeFormat(&SourceFormat); 1391 if (FAILED(hr)) 1392 return hr; 1393 1394 pSourceFormat = &SourceFormat; 1395 } 1396 1397 Property.SourceFormat = *pSourceFormat; 1398 Property.TargetFormat = *pTargetFormat; 1399 Property.Time = Source; 1400 1401 1402 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_TIMEFORMAT), (PVOID)pTarget, sizeof(LONGLONG), &BytesReturned); 1403 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1404 { 1405 //default error 1406 hr = E_NOTIMPL; 1407 1408 // check if plugins support it 1409 for(Index = 0; Index < m_Plugins.size(); Index++) 1410 { 1411 // get plugin 1412 IUnknown * Plugin = m_Plugins[Index]; 1413 1414 if (!Plugin) 1415 continue; 1416 1417 // query for IMediaSeeking interface 1418 IMediaSeeking *pSeek = NULL; 1419 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1420 if (SUCCEEDED(hr)) 1421 { 1422 // convert time format 1423 hr = pSeek->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat); 1424 // release IMediaSeeking interface 1425 pSeek->Release(); 1426 1427 if (hr != S_FALSE) // plugin implements it 1428 break; 1429 } 1430 } 1431 } 1432 1433 return hr; 1434 } 1435 1436 HRESULT 1437 STDMETHODCALLTYPE 1438 CKsProxy::SetPositions( 1439 LONGLONG *pCurrent, 1440 DWORD dwCurrentFlags, 1441 LONGLONG *pStop, 1442 DWORD dwStopFlags) 1443 { 1444 KSPROPERTY Property; 1445 KSPROPERTY_POSITIONS Positions; 1446 ULONG BytesReturned, Index; 1447 HRESULT hr; 1448 1449 Property.Set = KSPROPSETID_MediaSeeking; 1450 Property.Id = KSPROPERTY_MEDIASEEKING_POSITIONS; 1451 Property.Flags = KSPROPERTY_TYPE_SET; 1452 1453 Positions.Current = *pCurrent; 1454 Positions.CurrentFlags = (KS_SEEKING_FLAGS)dwCurrentFlags; 1455 Positions.Stop = *pStop; 1456 Positions.StopFlags = (KS_SEEKING_FLAGS)dwStopFlags; 1457 1458 #ifdef KSPROXY_TRACE 1459 OutputDebugStringW(L"CKsProxy::SetPositions\n"); 1460 #endif 1461 1462 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Positions, sizeof(KSPROPERTY_POSITIONS), &BytesReturned); 1463 if (SUCCEEDED(hr)) 1464 { 1465 if (dwCurrentFlags & AM_SEEKING_ReturnTime) 1466 { 1467 // retrieve current position 1468 hr = GetCurrentPosition(pCurrent); 1469 } 1470 1471 if (SUCCEEDED(hr)) 1472 { 1473 if (dwStopFlags & AM_SEEKING_ReturnTime) 1474 { 1475 // retrieve current position 1476 hr = GetStopPosition(pStop); 1477 } 1478 } 1479 return hr; 1480 } 1481 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1482 { 1483 hr = E_NOTIMPL; 1484 1485 // check if plugins support it 1486 for(Index = 0; Index < m_Plugins.size(); Index++) 1487 { 1488 // get plugin 1489 IUnknown * Plugin = m_Plugins[Index]; 1490 1491 if (!Plugin) 1492 continue; 1493 1494 // query for IMediaSeeking interface 1495 IMediaSeeking *pSeek = NULL; 1496 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1497 if (SUCCEEDED(hr)) 1498 { 1499 // set positions 1500 hr = pSeek->SetPositions(pCurrent, dwCurrentFlags, pStop, dwStopFlags); 1501 // release IMediaSeeking interface 1502 pSeek->Release(); 1503 1504 if (FAILED(hr)) 1505 break; 1506 } 1507 } 1508 } 1509 1510 return hr; 1511 } 1512 1513 HRESULT 1514 STDMETHODCALLTYPE 1515 CKsProxy::GetPositions( 1516 LONGLONG *pCurrent, 1517 LONGLONG *pStop) 1518 { 1519 HRESULT hr; 1520 1521 #ifdef KSPROXY_TRACE 1522 OutputDebugStringW(L"CKsProxy::GetPositions\n"); 1523 #endif 1524 1525 hr = GetCurrentPosition(pCurrent); 1526 if (SUCCEEDED(hr)) 1527 hr = GetStopPosition(pStop); 1528 1529 return hr; 1530 } 1531 1532 HRESULT 1533 STDMETHODCALLTYPE 1534 CKsProxy::GetAvailable( 1535 LONGLONG *pEarliest, 1536 LONGLONG *pLatest) 1537 { 1538 KSPROPERTY Property; 1539 KSPROPERTY_MEDIAAVAILABLE Media; 1540 ULONG BytesReturned, Index; 1541 HRESULT hr; 1542 1543 Property.Set = KSPROPSETID_MediaSeeking; 1544 Property.Id = KSPROPERTY_MEDIASEEKING_AVAILABLE; 1545 Property.Flags = KSPROPERTY_TYPE_GET; 1546 1547 #ifdef KSPROXY_TRACE 1548 OutputDebugStringW(L"CKsProxy::GetAvailable\n"); 1549 #endif 1550 1551 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Media, sizeof(KSPROPERTY_MEDIAAVAILABLE), &BytesReturned); 1552 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1553 { 1554 // check if plugins support it 1555 for(Index = 0; Index < m_Plugins.size(); Index++) 1556 { 1557 hr = E_NOTIMPL; 1558 // get plugin 1559 IUnknown * Plugin = m_Plugins[Index]; 1560 1561 if (!Plugin) 1562 continue; 1563 1564 // query for IMediaSeeking interface 1565 IMediaSeeking *pSeek = NULL; 1566 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1567 if (SUCCEEDED(hr)) 1568 { 1569 // delegate call 1570 hr = pSeek->GetAvailable(pEarliest, pLatest); 1571 // release IMediaSeeking interface 1572 pSeek->Release(); 1573 1574 if (hr != S_FALSE) // plugin implements it 1575 break; 1576 } 1577 } 1578 } 1579 else if (SUCCEEDED(hr)) 1580 { 1581 *pEarliest = Media.Earliest; 1582 *pLatest = Media.Latest; 1583 } 1584 1585 return hr; 1586 } 1587 1588 HRESULT 1589 STDMETHODCALLTYPE 1590 CKsProxy::SetRate( 1591 double dRate) 1592 { 1593 #ifdef KSPROXY_TRACE 1594 OutputDebugStringW(L"CKsProxy::SetRate\n"); 1595 #endif 1596 return E_NOTIMPL; 1597 } 1598 1599 HRESULT 1600 STDMETHODCALLTYPE 1601 CKsProxy::GetRate( 1602 double *pdRate) 1603 { 1604 #ifdef KSPROXY_TRACE 1605 OutputDebugStringW(L"CKsProxy::GetRate\n"); 1606 #endif 1607 return E_NOTIMPL; 1608 } 1609 1610 HRESULT 1611 STDMETHODCALLTYPE 1612 CKsProxy::GetPreroll( 1613 LONGLONG *pllPreroll) 1614 { 1615 KSPROPERTY Property; 1616 ULONG BytesReturned, Index; 1617 HRESULT hr; 1618 1619 Property.Set = KSPROPSETID_MediaSeeking; 1620 Property.Id = KSPROPERTY_MEDIASEEKING_PREROLL; 1621 Property.Flags = KSPROPERTY_TYPE_GET; 1622 1623 #ifdef KSPROXY_TRACE 1624 OutputDebugStringW(L"CKsProxy::GetPreroll\n"); 1625 #endif 1626 1627 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pllPreroll, sizeof(LONGLONG), &BytesReturned); 1628 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND) || hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND)) 1629 { 1630 // check if all plugins support it 1631 for(Index = 0; Index < m_Plugins.size(); Index++) 1632 { 1633 // get plugin 1634 IUnknown * Plugin = m_Plugins[Index]; 1635 1636 if (!Plugin) 1637 continue; 1638 1639 // query for IMediaSeeking interface 1640 IMediaSeeking *pSeek = NULL; 1641 hr = Plugin->QueryInterface(IID_IMediaSeeking, (void**)&pSeek); 1642 if (SUCCEEDED(hr)) 1643 { 1644 // get preroll 1645 hr = pSeek->GetPreroll(pllPreroll); 1646 // release IMediaSeeking interface 1647 pSeek->Release(); 1648 1649 if (hr != S_FALSE) // plugin implements it 1650 break; 1651 } 1652 } 1653 hr = E_NOTIMPL; 1654 } 1655 return hr; 1656 } 1657 1658 //------------------------------------------------------------------- 1659 // IAMFilterMiscFlags interface 1660 // 1661 1662 ULONG 1663 STDMETHODCALLTYPE 1664 CKsProxy::GetMiscFlags() 1665 { 1666 ULONG Index; 1667 ULONG Flags = 0; 1668 HRESULT hr; 1669 PIN_DIRECTION PinDirection; 1670 KSPIN_COMMUNICATION Communication; 1671 1672 1673 for(Index = 0; Index < m_Pins.size(); Index++) 1674 { 1675 // get current pin 1676 IPin * pin = m_Pins[Index]; 1677 // query direction 1678 hr = pin->QueryDirection(&PinDirection); 1679 if (SUCCEEDED(hr)) 1680 { 1681 if (PinDirection == PINDIR_INPUT) 1682 { 1683 if (SUCCEEDED(GetPinCommunication(Index, //FIXME verify PinId 1684 &Communication))) 1685 { 1686 if (Communication != KSPIN_COMMUNICATION_NONE && Communication != KSPIN_COMMUNICATION_BRIDGE) 1687 { 1688 Flags |= AM_FILTER_MISC_FLAGS_IS_SOURCE; 1689 } 1690 } 1691 } 1692 } 1693 } 1694 1695 #ifdef KSPROXY_TRACE 1696 WCHAR Buffer[100]; 1697 swprintf(Buffer, L"CKsProxy::GetMiscFlags stub Flags %x\n", Flags); 1698 OutputDebugStringW(Buffer); 1699 #endif 1700 1701 return Flags; 1702 } 1703 1704 //------------------------------------------------------------------- 1705 // IKsControl 1706 // 1707 HRESULT 1708 STDMETHODCALLTYPE 1709 CKsProxy::KsProperty( 1710 PKSPROPERTY Property, 1711 ULONG PropertyLength, 1712 LPVOID PropertyData, 1713 ULONG DataLength, 1714 ULONG* BytesReturned) 1715 { 1716 #ifdef KSPROXY_TRACE 1717 OutputDebugStringW(L"CKsProxy::KsProperty\n"); 1718 #endif 1719 1720 assert(m_hDevice != 0); 1721 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)Property, PropertyLength, (PVOID)PropertyData, DataLength, BytesReturned); 1722 } 1723 1724 HRESULT 1725 STDMETHODCALLTYPE 1726 CKsProxy::KsMethod( 1727 PKSMETHOD Method, 1728 ULONG MethodLength, 1729 LPVOID MethodData, 1730 ULONG DataLength, 1731 ULONG* BytesReturned) 1732 { 1733 #ifdef KSPROXY_TRACE 1734 OutputDebugStringW(L"CKsProxy::KsMethod\n"); 1735 #endif 1736 1737 assert(m_hDevice != 0); 1738 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)Method, MethodLength, (PVOID)MethodData, DataLength, BytesReturned); 1739 } 1740 1741 HRESULT 1742 STDMETHODCALLTYPE 1743 CKsProxy::KsEvent( 1744 PKSEVENT Event, 1745 ULONG EventLength, 1746 LPVOID EventData, 1747 ULONG DataLength, 1748 ULONG* BytesReturned) 1749 { 1750 #ifdef KSPROXY_TRACE 1751 OutputDebugStringW(L"CKsProxy::KsEvent\n"); 1752 #endif 1753 1754 assert(m_hDevice != 0); 1755 if (EventLength) 1756 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)Event, EventLength, (PVOID)EventData, DataLength, BytesReturned); 1757 else 1758 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_DISABLE_EVENT, (PVOID)Event, EventLength, NULL, 0, BytesReturned); 1759 } 1760 1761 1762 //------------------------------------------------------------------- 1763 // IKsPropertySet 1764 // 1765 HRESULT 1766 STDMETHODCALLTYPE 1767 CKsProxy::Set( 1768 REFGUID guidPropSet, 1769 DWORD dwPropID, 1770 LPVOID pInstanceData, 1771 DWORD cbInstanceData, 1772 LPVOID pPropData, 1773 DWORD cbPropData) 1774 { 1775 ULONG BytesReturned; 1776 1777 #ifdef KSPROXY_TRACE 1778 OutputDebugStringW(L"CKsProxy::Set\n"); 1779 #endif 1780 1781 if (cbInstanceData) 1782 { 1783 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); 1784 if (!Property) 1785 return E_OUTOFMEMORY; 1786 1787 Property->Set = guidPropSet; 1788 Property->Id = dwPropID; 1789 Property->Flags = KSPROPERTY_TYPE_SET; 1790 1791 CopyMemory((Property+1), pInstanceData, cbInstanceData); 1792 1793 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); 1794 CoTaskMemFree(Property); 1795 return hr; 1796 } 1797 else 1798 { 1799 KSPROPERTY Property; 1800 1801 Property.Set = guidPropSet; 1802 Property.Id = dwPropID; 1803 Property.Flags = KSPROPERTY_TYPE_SET; 1804 1805 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); 1806 return hr; 1807 } 1808 } 1809 1810 HRESULT 1811 STDMETHODCALLTYPE 1812 CKsProxy::Get( 1813 REFGUID guidPropSet, 1814 DWORD dwPropID, 1815 LPVOID pInstanceData, 1816 DWORD cbInstanceData, 1817 LPVOID pPropData, 1818 DWORD cbPropData, 1819 DWORD *pcbReturned) 1820 { 1821 ULONG BytesReturned; 1822 1823 #ifdef KSPROXY_TRACE 1824 OutputDebugStringW(L"CKsProxy::Get\n"); 1825 #endif 1826 1827 if (cbInstanceData) 1828 { 1829 PKSPROPERTY Property = (PKSPROPERTY)CoTaskMemAlloc(sizeof(KSPROPERTY) + cbInstanceData); 1830 if (!Property) 1831 return E_OUTOFMEMORY; 1832 1833 Property->Set = guidPropSet; 1834 Property->Id = dwPropID; 1835 Property->Flags = KSPROPERTY_TYPE_GET; 1836 1837 CopyMemory((Property+1), pInstanceData, cbInstanceData); 1838 1839 HRESULT hr = KsProperty(Property, sizeof(KSPROPERTY) + cbInstanceData, pPropData, cbPropData, &BytesReturned); 1840 CoTaskMemFree(Property); 1841 return hr; 1842 } 1843 else 1844 { 1845 KSPROPERTY Property; 1846 1847 Property.Set = guidPropSet; 1848 Property.Id = dwPropID; 1849 Property.Flags = KSPROPERTY_TYPE_GET; 1850 1851 HRESULT hr = KsProperty(&Property, sizeof(KSPROPERTY), pPropData, cbPropData, &BytesReturned); 1852 return hr; 1853 } 1854 } 1855 1856 HRESULT 1857 STDMETHODCALLTYPE 1858 CKsProxy::QuerySupported( 1859 REFGUID guidPropSet, 1860 DWORD dwPropID, 1861 DWORD *pTypeSupport) 1862 { 1863 KSPROPERTY Property; 1864 ULONG BytesReturned; 1865 1866 #ifdef KSPROXY_TRACE 1867 OutputDebugStringW(L"CKsProxy::QuerySupported\n"); 1868 #endif 1869 1870 Property.Set = guidPropSet; 1871 Property.Id = dwPropID; 1872 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; 1873 1874 return KsProperty(&Property, sizeof(KSPROPERTY), pTypeSupport, sizeof(DWORD), &BytesReturned); 1875 } 1876 1877 1878 //------------------------------------------------------------------- 1879 // IKsTopology interface 1880 // 1881 HRESULT 1882 STDMETHODCALLTYPE 1883 CKsProxy::CreateNodeInstance( 1884 ULONG NodeId, 1885 ULONG Flags, 1886 ACCESS_MASK DesiredAccess, 1887 IUnknown* UnkOuter, 1888 REFGUID InterfaceId, 1889 LPVOID* Interface) 1890 { 1891 HRESULT hr; 1892 1893 #ifdef KSPROXY_TRACE 1894 OutputDebugStringW(L"CKsProxy::CreateNodeInstance\n"); 1895 #endif 1896 1897 *Interface = NULL; 1898 1899 if (IsEqualIID(IID_IUnknown, InterfaceId) || !UnkOuter) 1900 { 1901 hr = CKsNode_Constructor(UnkOuter, m_hDevice, NodeId, DesiredAccess, InterfaceId, Interface); 1902 } 1903 else 1904 { 1905 // interface not supported 1906 hr = E_NOINTERFACE; 1907 } 1908 1909 return hr; 1910 } 1911 1912 //------------------------------------------------------------------- 1913 // IKsAggregateControl interface 1914 // 1915 HRESULT 1916 STDMETHODCALLTYPE 1917 CKsProxy::KsAddAggregate( 1918 IN REFGUID AggregateClass) 1919 { 1920 #ifdef KSPROXY_TRACE 1921 OutputDebugStringW(L"CKsProxy::KsAddAggregate NotImplemented\n"); 1922 #endif 1923 return E_NOTIMPL; 1924 } 1925 1926 HRESULT 1927 STDMETHODCALLTYPE 1928 CKsProxy::KsRemoveAggregate( 1929 REFGUID AggregateClass) 1930 { 1931 #ifdef KSPROXY_TRACE 1932 OutputDebugStringW(L"CKsProxy::KsRemoveAggregate NotImplemented\n"); 1933 #endif 1934 1935 return E_NOTIMPL; 1936 } 1937 1938 1939 //------------------------------------------------------------------- 1940 // IPersistStream interface 1941 // 1942 1943 HRESULT 1944 STDMETHODCALLTYPE 1945 CKsProxy::IsDirty() 1946 { 1947 #ifdef KSPROXY_TRACE 1948 OutputDebugStringW(L"CKsProxy::IsDirty Notimplemented\n"); 1949 #endif 1950 return E_NOTIMPL; 1951 } 1952 1953 HRESULT 1954 STDMETHODCALLTYPE 1955 CKsProxy::Load( 1956 IStream *pStm) 1957 { 1958 HRESULT hr; 1959 WCHAR Buffer[1000]; 1960 AM_MEDIA_TYPE MediaType; 1961 ULONG BytesReturned; 1962 LONG Length; 1963 1964 ULONG PinId; 1965 LPOLESTR pMajor, pSub, pFormat; 1966 1967 #ifdef KSPROXY_TRACE 1968 OutputDebugStringW(L"CKsProxy::Load\n"); 1969 #endif 1970 1971 #if 0 1972 ULONG Version = ReadInt(pStm, hr); 1973 if (Version != 1) 1974 return E_FAIL; 1975 #endif 1976 1977 hr = pStm->Read(&Length, sizeof(ULONG), &BytesReturned); 1978 swprintf(Buffer, L"Length hr %x hr length %lu\n", hr, Length); 1979 OutputDebugStringW(Buffer); 1980 1981 do 1982 { 1983 hr = pStm->Read(&PinId, sizeof(ULONG), &BytesReturned); 1984 swprintf(Buffer, L"Read: hr %08x PinId %lx BytesReturned %lu\n", hr, PinId, BytesReturned); 1985 OutputDebugStringW(Buffer); 1986 1987 if (FAILED(hr) || !BytesReturned) 1988 break; 1989 1990 Length -= BytesReturned; 1991 1992 hr = pStm->Read(&MediaType, sizeof(AM_MEDIA_TYPE), &BytesReturned); 1993 if (FAILED(hr) || BytesReturned != sizeof(AM_MEDIA_TYPE)) 1994 { 1995 swprintf(Buffer, L"Read failed with %lx\n", hr); 1996 OutputDebugStringW(Buffer); 1997 break; 1998 } 1999 2000 2001 StringFromIID(MediaType.majortype, &pMajor); 2002 StringFromIID(MediaType.subtype , &pSub); 2003 StringFromIID(MediaType.formattype, &pFormat); 2004 2005 swprintf(Buffer, L"BytesReturned %lu majortype %s subtype %s bFixedSizeSamples %u bTemporalCompression %u lSampleSize %u formattype %s, pUnk %p cbFormat %u pbFormat %p\n", BytesReturned, pMajor, pSub, MediaType.bFixedSizeSamples, MediaType.bTemporalCompression, MediaType.lSampleSize, pFormat, MediaType.pUnk, MediaType.cbFormat, MediaType.pbFormat); 2006 OutputDebugStringW(Buffer); 2007 2008 Length -= BytesReturned; 2009 2010 2011 if (MediaType.cbFormat) 2012 { 2013 MediaType.pbFormat = (BYTE*)CoTaskMemAlloc(MediaType.cbFormat); 2014 if (!MediaType.pbFormat) 2015 return E_OUTOFMEMORY; 2016 2017 hr = pStm->Read(&MediaType.pbFormat, sizeof(MediaType.cbFormat), &BytesReturned); 2018 if (FAILED(hr)) 2019 { 2020 swprintf(Buffer, L"ReadFormat failed with %lx\n", hr); 2021 OutputDebugStringW(Buffer); 2022 break; 2023 } 2024 Length -= BytesReturned; 2025 } 2026 2027 }while(Length > 0); 2028 2029 return S_OK; 2030 } 2031 2032 HRESULT 2033 STDMETHODCALLTYPE 2034 CKsProxy::Save( 2035 IStream *pStm, 2036 BOOL fClearDirty) 2037 { 2038 #ifdef KSPROXY_TRACE 2039 OutputDebugStringW(L"CKsProxy::Save Notimplemented\n"); 2040 #endif 2041 2042 return E_NOTIMPL; 2043 } 2044 2045 HRESULT 2046 STDMETHODCALLTYPE 2047 CKsProxy::GetSizeMax( 2048 ULARGE_INTEGER *pcbSize) 2049 { 2050 #ifdef KSPROXY_TRACE 2051 OutputDebugStringW(L"CKsProxy::GetSizeMax Notimplemented\n"); 2052 #endif 2053 2054 return E_NOTIMPL; 2055 } 2056 2057 //------------------------------------------------------------------- 2058 // IAMDeviceRemoval interface 2059 // 2060 2061 HRESULT 2062 STDMETHODCALLTYPE 2063 CKsProxy::DeviceInfo(CLSID *pclsidInterfaceClass, LPWSTR *pwszSymbolicLink) 2064 { 2065 #ifdef KSPROXY_TRACE 2066 OutputDebugStringW(L"CKsProxy::DeviceInfo\n"); 2067 #endif 2068 2069 if (!m_DevicePath) 2070 { 2071 // object not initialized 2072 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND); 2073 } 2074 2075 // copy device interface guid 2076 CopyMemory(pclsidInterfaceClass, &m_DeviceInterfaceGUID, sizeof(GUID)); 2077 2078 if (pwszSymbolicLink) 2079 { 2080 *pwszSymbolicLink = (LPWSTR)CoTaskMemAlloc((wcslen(m_DevicePath)+1) * sizeof(WCHAR)); 2081 if (!*pwszSymbolicLink) 2082 return E_OUTOFMEMORY; 2083 2084 wcscpy(*pwszSymbolicLink, m_DevicePath); 2085 } 2086 return S_OK; 2087 } 2088 HRESULT 2089 STDMETHODCALLTYPE 2090 CKsProxy::Reassociate(void) 2091 { 2092 #ifdef KSPROXY_TRACE 2093 OutputDebugStringW(L"CKsProxy::Reassociate\n"); 2094 #endif 2095 2096 if (!m_DevicePath || m_hDevice) 2097 { 2098 // file path not available 2099 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND); 2100 } 2101 2102 m_hDevice = CreateFileW(m_DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); 2103 if (!m_hDevice) 2104 { 2105 // failed to open device 2106 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); 2107 } 2108 2109 // success 2110 return NOERROR; 2111 } 2112 2113 HRESULT 2114 STDMETHODCALLTYPE 2115 CKsProxy::Disassociate(void) 2116 { 2117 #ifdef KSPROXY_TRACE 2118 OutputDebugStringW(L"CKsProxy::Disassociate\n"); 2119 #endif 2120 2121 if (!m_hDevice) 2122 return E_HANDLE; 2123 2124 CloseHandle(m_hDevice); 2125 m_hDevice = NULL; 2126 return NOERROR; 2127 } 2128 2129 //------------------------------------------------------------------- 2130 // IKsClock interface 2131 // 2132 2133 HANDLE 2134 STDMETHODCALLTYPE 2135 CKsProxy::KsGetClockHandle() 2136 { 2137 #ifdef KSPROXY_TRACE 2138 OutputDebugStringW(L"CKsProxy::KsGetClockHandle\n"); 2139 #endif 2140 2141 return m_hClock; 2142 } 2143 2144 2145 //------------------------------------------------------------------- 2146 // IKsObject interface 2147 // 2148 2149 HANDLE 2150 STDMETHODCALLTYPE 2151 CKsProxy::KsGetObjectHandle() 2152 { 2153 #ifdef KSPROXY_TRACE 2154 OutputDebugStringW(L"CKsProxy::KsGetObjectHandle\n"); 2155 #endif 2156 2157 return m_hDevice; 2158 } 2159 2160 //------------------------------------------------------------------- 2161 // IPersistPropertyBag interface 2162 // 2163 HRESULT 2164 STDMETHODCALLTYPE 2165 CKsProxy::InitNew( void) 2166 { 2167 #ifdef KSPROXY_TRACE 2168 OutputDebugStringW(L"CKsProxy::InitNew\n"); 2169 #endif 2170 2171 return S_OK; 2172 } 2173 2174 HRESULT 2175 STDMETHODCALLTYPE 2176 CKsProxy::GetSupportedSets( 2177 LPGUID * pOutGuid, 2178 PULONG NumGuids) 2179 { 2180 KSPROPERTY Property; 2181 LPGUID pGuid; 2182 ULONG NumProperty = 0; 2183 ULONG NumMethods = 0; 2184 ULONG NumEvents = 0; 2185 ULONG Length; 2186 ULONG BytesReturned; 2187 HRESULT hr; 2188 2189 Property.Set = GUID_NULL; 2190 Property.Id = 0; 2191 Property.Flags = KSPROPERTY_TYPE_SETSUPPORT; 2192 2193 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumProperty); 2194 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumMethods); 2195 KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), NULL, 0, &NumEvents); 2196 2197 Length = NumProperty + NumMethods + NumEvents; 2198 2199 // allocate guid buffer 2200 pGuid = (LPGUID)CoTaskMemAlloc(Length); 2201 if (!pGuid) 2202 { 2203 // failed 2204 return E_OUTOFMEMORY; 2205 } 2206 2207 NumProperty /= sizeof(GUID); 2208 NumMethods /= sizeof(GUID); 2209 NumEvents /= sizeof(GUID); 2210 2211 // get all properties 2212 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)pGuid, Length, &BytesReturned); 2213 if (FAILED(hr)) 2214 { 2215 CoTaskMemFree(pGuid); 2216 return E_FAIL; 2217 } 2218 Length -= BytesReturned; 2219 2220 // get all methods 2221 if (Length) 2222 { 2223 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_METHOD, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty], Length, &BytesReturned); 2224 if (FAILED(hr)) 2225 { 2226 CoTaskMemFree(pGuid); 2227 return E_FAIL; 2228 } 2229 Length -= BytesReturned; 2230 } 2231 2232 // get all events 2233 if (Length) 2234 { 2235 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&pGuid[NumProperty+NumMethods], Length, &BytesReturned); 2236 if (FAILED(hr)) 2237 { 2238 CoTaskMemFree(pGuid); 2239 return E_FAIL; 2240 } 2241 Length -= BytesReturned; 2242 } 2243 2244 #ifdef KSPROXY_TRACE 2245 WCHAR Buffer[200]; 2246 swprintf(Buffer, L"NumProperty %lu NumMethods %lu NumEvents %lu\n", NumProperty, NumMethods, NumEvents); 2247 OutputDebugStringW(Buffer); 2248 #endif 2249 2250 *pOutGuid = pGuid; 2251 *NumGuids = NumProperty+NumEvents+NumMethods; 2252 return S_OK; 2253 } 2254 2255 HRESULT 2256 STDMETHODCALLTYPE 2257 CKsProxy::LoadProxyPlugins( 2258 LPGUID pGuids, 2259 ULONG NumGuids) 2260 { 2261 ULONG Index; 2262 LPOLESTR pStr; 2263 HKEY hKey, hSubKey; 2264 HRESULT hr; 2265 IUnknown * pUnknown; 2266 2267 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\MediaInterfaces", 0, KEY_READ, &hKey) != ERROR_SUCCESS) 2268 { 2269 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed to open MediaInterfaces key\n"); 2270 return E_FAIL; 2271 } 2272 2273 // enumerate all sets 2274 for(Index = 0; Index < NumGuids; Index++) 2275 { 2276 // convert to string 2277 hr = StringFromCLSID(pGuids[Index], &pStr); 2278 if (FAILED(hr)) 2279 return E_FAIL; 2280 2281 // now try open class key 2282 if (RegOpenKeyExW(hKey, pStr, 0, KEY_READ, &hSubKey) != ERROR_SUCCESS) 2283 { 2284 // no plugin for that set exists 2285 CoTaskMemFree(pStr); 2286 continue; 2287 } 2288 2289 // try load plugin 2290 hr = CoCreateInstance(pGuids[Index], (IBaseFilter*)this, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown); 2291 if (SUCCEEDED(hr)) 2292 { 2293 // store plugin 2294 m_Plugins.push_back(pUnknown); 2295 } 2296 // close key 2297 RegCloseKey(hSubKey); 2298 } 2299 2300 // close media interfaces key 2301 RegCloseKey(hKey); 2302 return S_OK; 2303 } 2304 2305 HRESULT 2306 STDMETHODCALLTYPE 2307 CKsProxy::GetNumberOfPins( 2308 PULONG NumPins) 2309 { 2310 KSPROPERTY Property; 2311 ULONG BytesReturned; 2312 2313 // setup request 2314 Property.Set = KSPROPSETID_Pin; 2315 Property.Id = KSPROPERTY_PIN_CTYPES; 2316 Property.Flags = KSPROPERTY_TYPE_GET; 2317 2318 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)NumPins, sizeof(ULONG), &BytesReturned); 2319 } 2320 2321 HRESULT 2322 STDMETHODCALLTYPE 2323 CKsProxy::GetPinInstanceCount( 2324 ULONG PinId, 2325 PKSPIN_CINSTANCES Instances) 2326 { 2327 KSP_PIN Property; 2328 ULONG BytesReturned; 2329 2330 // setup request 2331 Property.Property.Set = KSPROPSETID_Pin; 2332 Property.Property.Id = KSPROPERTY_PIN_CINSTANCES; 2333 Property.Property.Flags = KSPROPERTY_TYPE_GET; 2334 Property.PinId = PinId; 2335 Property.Reserved = 0; 2336 2337 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Instances, sizeof(KSPIN_CINSTANCES), &BytesReturned); 2338 } 2339 2340 HRESULT 2341 STDMETHODCALLTYPE 2342 CKsProxy::GetPinCommunication( 2343 ULONG PinId, 2344 KSPIN_COMMUNICATION * Communication) 2345 { 2346 KSP_PIN Property; 2347 ULONG BytesReturned; 2348 2349 // setup request 2350 Property.Property.Set = KSPROPSETID_Pin; 2351 Property.Property.Id = KSPROPERTY_PIN_COMMUNICATION; 2352 Property.Property.Flags = KSPROPERTY_TYPE_GET; 2353 Property.PinId = PinId; 2354 Property.Reserved = 0; 2355 2356 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned); 2357 } 2358 2359 HRESULT 2360 STDMETHODCALLTYPE 2361 CKsProxy::GetPinDataflow( 2362 ULONG PinId, 2363 KSPIN_DATAFLOW * DataFlow) 2364 { 2365 KSP_PIN Property; 2366 ULONG BytesReturned; 2367 2368 // setup request 2369 Property.Property.Set = KSPROPSETID_Pin; 2370 Property.Property.Id = KSPROPERTY_PIN_DATAFLOW; 2371 Property.Property.Flags = KSPROPERTY_TYPE_GET; 2372 Property.PinId = PinId; 2373 Property.Reserved = 0; 2374 2375 return KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned); 2376 } 2377 2378 HRESULT 2379 STDMETHODCALLTYPE 2380 CKsProxy::GetPinName( 2381 ULONG PinId, 2382 KSPIN_DATAFLOW DataFlow, 2383 ULONG PinCount, 2384 LPWSTR * OutPinName) 2385 { 2386 KSP_PIN Property; 2387 LPWSTR PinName; 2388 ULONG BytesReturned; 2389 HRESULT hr; 2390 WCHAR Buffer[100]; 2391 2392 // setup request 2393 Property.Property.Set = KSPROPSETID_Pin; 2394 Property.Property.Id = KSPROPERTY_PIN_NAME; 2395 Property.Property.Flags = KSPROPERTY_TYPE_GET; 2396 Property.PinId = PinId; 2397 Property.Reserved = 0; 2398 2399 // #1 try get it from pin directly 2400 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), NULL, 0, &BytesReturned); 2401 2402 if (hr == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_MORE_DATA)) 2403 { 2404 // allocate pin name 2405 PinName = (LPWSTR)CoTaskMemAlloc(BytesReturned); 2406 if (!PinName) 2407 return E_OUTOFMEMORY; 2408 2409 // retry with allocated buffer 2410 hr = KsSynchronousDeviceControl(m_hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSP_PIN), PinName, BytesReturned, &BytesReturned); 2411 if (SUCCEEDED(hr)) 2412 { 2413 *OutPinName = PinName; 2414 return hr; 2415 } 2416 2417 //free buffer 2418 CoTaskMemFree(PinName); 2419 } 2420 2421 // 2422 // TODO: retrieve pin name from topology node 2423 // 2424 2425 if (DataFlow == KSPIN_DATAFLOW_IN) 2426 { 2427 swprintf(Buffer, L"Input%lu", PinCount); 2428 } 2429 else 2430 { 2431 swprintf(Buffer, L"Output%lu", PinCount); 2432 } 2433 2434 // allocate pin name 2435 PinName = (LPWSTR)CoTaskMemAlloc((wcslen(Buffer)+1) * sizeof(WCHAR)); 2436 if (!PinName) 2437 return E_OUTOFMEMORY; 2438 2439 // copy pin name 2440 wcscpy(PinName, Buffer); 2441 2442 // store result 2443 *OutPinName = PinName; 2444 // done 2445 return S_OK; 2446 } 2447 2448 HRESULT 2449 STDMETHODCALLTYPE 2450 CKsProxy::CreatePins() 2451 { 2452 ULONG NumPins, Index; 2453 KSPIN_CINSTANCES Instances; 2454 KSPIN_DATAFLOW DataFlow; 2455 KSPIN_COMMUNICATION Communication; 2456 HRESULT hr; 2457 LPWSTR PinName; 2458 IPin * pPin; 2459 ULONG InputPin = 0; 2460 ULONG OutputPin = 0; 2461 2462 // get number of pins 2463 hr = GetNumberOfPins(&NumPins); 2464 if (FAILED(hr)) 2465 return hr; 2466 2467 for(Index = 0; Index < NumPins; Index++) 2468 { 2469 // query current instance count 2470 hr = GetPinInstanceCount(Index, &Instances); 2471 if (FAILED(hr)) 2472 { 2473 #ifdef KSPROXY_TRACE 2474 WCHAR Buffer[100]; 2475 swprintf(Buffer, L"CKsProxy::CreatePins GetPinInstanceCount failed with %lx\n", hr); 2476 OutputDebugStringW(Buffer); 2477 #endif 2478 continue; 2479 } 2480 2481 2482 // query pin communication; 2483 hr = GetPinCommunication(Index, &Communication); 2484 if (FAILED(hr)) 2485 { 2486 #ifdef KSPROXY_TRACE 2487 WCHAR Buffer[100]; 2488 swprintf(Buffer, L"CKsProxy::CreatePins GetPinCommunication failed with %lx\n", hr); 2489 OutputDebugStringW(Buffer); 2490 #endif 2491 continue; 2492 } 2493 2494 if (Instances.CurrentCount == Instances.PossibleCount) 2495 { 2496 // already maximum reached for this pin 2497 #ifdef KSPROXY_TRACE 2498 WCHAR Buffer[100]; 2499 swprintf(Buffer, L"CKsProxy::CreatePins Instances.CurrentCount == Instances.PossibleCount\n"); 2500 OutputDebugStringW(Buffer); 2501 #endif 2502 continue; 2503 } 2504 2505 // get direction of pin 2506 hr = GetPinDataflow(Index, &DataFlow); 2507 if (FAILED(hr)) 2508 { 2509 #ifdef KSPROXY_TRACE 2510 WCHAR Buffer[100]; 2511 swprintf(Buffer, L"CKsProxy::CreatePins GetPinDataflow failed with %lx\n", hr); 2512 OutputDebugStringW(Buffer); 2513 #endif 2514 continue; 2515 } 2516 2517 if (DataFlow == KSPIN_DATAFLOW_IN) 2518 hr = GetPinName(Index, DataFlow, InputPin, &PinName); 2519 else 2520 hr = GetPinName(Index, DataFlow, OutputPin, &PinName); 2521 2522 if (FAILED(hr)) 2523 { 2524 #ifdef KSPROXY_TRACE 2525 WCHAR Buffer[100]; 2526 swprintf(Buffer, L"CKsProxy::CreatePins GetPinName failed with %lx\n", hr); 2527 OutputDebugStringW(Buffer); 2528 #endif 2529 continue; 2530 } 2531 2532 // construct the pins 2533 if (DataFlow == KSPIN_DATAFLOW_IN) 2534 { 2535 hr = CInputPin_Constructor((IBaseFilter*)this, PinName, m_hDevice, Index, Communication, IID_IPin, (void**)&pPin); 2536 if (FAILED(hr)) 2537 { 2538 #ifdef KSPROXY_TRACE 2539 WCHAR Buffer[100]; 2540 swprintf(Buffer, L"CKsProxy::CreatePins CInputPin_Constructor failed with %lx\n", hr); 2541 OutputDebugStringW(Buffer); 2542 #endif 2543 CoTaskMemFree(PinName); 2544 continue; 2545 } 2546 InputPin++; 2547 } 2548 else 2549 { 2550 hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, Communication, IID_IPin, (void**)&pPin); 2551 if (FAILED(hr)) 2552 { 2553 #ifdef KSPROXY_TRACE 2554 WCHAR Buffer[100]; 2555 swprintf(Buffer, L"CKsProxy::CreatePins COutputPin_Constructor failed with %lx\n", hr); 2556 OutputDebugStringW(Buffer); 2557 #endif 2558 CoTaskMemFree(PinName); 2559 continue; 2560 } 2561 OutputPin++; 2562 } 2563 2564 // store pins 2565 m_Pins.push_back(pPin); 2566 2567 #ifdef KSPROXY_TRACE 2568 WCHAR Buffer[100]; 2569 swprintf(Buffer, L"Index %lu DataFlow %lu Name %s\n", Index, DataFlow, PinName); 2570 OutputDebugStringW(Buffer); 2571 #endif 2572 2573 } 2574 2575 return S_OK; 2576 } 2577 2578 HRESULT 2579 STDMETHODCALLTYPE 2580 CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog) 2581 { 2582 HRESULT hr; 2583 VARIANT varName; 2584 LPGUID pGuid; 2585 ULONG NumGuids = 0; 2586 HDEVINFO hList; 2587 SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; 2588 2589 #ifdef KSPROXY_TRACE 2590 WCHAR Buffer[100]; 2591 OutputDebugStringW(L"CKsProxy::Load\n"); 2592 #endif 2593 2594 // read device path 2595 varName.vt = VT_BSTR; 2596 hr = pPropBag->Read(L"DevicePath", &varName, pErrorLog); 2597 2598 if (FAILED(hr)) 2599 { 2600 #ifdef KSPROXY_TRACE 2601 swprintf(Buffer, L"CKsProxy::Load Read %lx\n", hr); 2602 OutputDebugStringW(Buffer); 2603 #endif 2604 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); 2605 } 2606 2607 #ifdef KSPROXY_TRACE 2608 OutputDebugStringW(L"DevicePath: "); 2609 OutputDebugStringW(varName.bstrVal); 2610 OutputDebugStringW(L"\n"); 2611 #endif 2612 2613 // create device list 2614 hList = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL); 2615 if (hList == INVALID_HANDLE_VALUE) 2616 { 2617 // failed to create device list 2618 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); 2619 } 2620 2621 DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 2622 if (!SetupDiOpenDeviceInterfaceW(hList, (PCWSTR)varName.bstrVal, 0, &DeviceInterfaceData)) 2623 { 2624 // failed to open device interface 2625 SetupDiDestroyDeviceInfoList(hList); 2626 } 2627 2628 // FIXME handle device interface links(aliases) 2629 CopyMemory(&m_DeviceInterfaceGUID, &DeviceInterfaceData.InterfaceClassGuid, sizeof(GUID)); 2630 2631 // close device info list 2632 SetupDiDestroyDeviceInfoList(hList); 2633 2634 // open device 2635 m_hDevice = CreateFileW(varName.bstrVal, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); 2636 2637 if (m_hDevice == INVALID_HANDLE_VALUE) 2638 { 2639 // failed to open device 2640 #ifdef KSPROXY_TRACE 2641 swprintf(Buffer, L"CKsProxy:: failed to open device with %lx\n", GetLastError()); 2642 OutputDebugStringW(Buffer); 2643 #endif 2644 return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, GetLastError()); 2645 } 2646 2647 // store device path 2648 m_DevicePath = varName.bstrVal; 2649 2650 // get all supported sets 2651 hr = GetSupportedSets(&pGuid, &NumGuids); 2652 if (FAILED(hr)) 2653 { 2654 CloseHandle(m_hDevice); 2655 m_hDevice = NULL; 2656 return hr; 2657 } 2658 2659 // load all proxy plugins 2660 hr = LoadProxyPlugins(pGuid, NumGuids); 2661 if (FAILED(hr)) 2662 { 2663 #if 0 //HACK 2664 CloseHandle(m_hDevice); 2665 m_hDevice = NULL; 2666 return hr; 2667 #endif 2668 OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed!\n"); 2669 } 2670 2671 // free sets 2672 CoTaskMemFree(pGuid); 2673 2674 // now create the input / output pins 2675 hr = CreatePins(); 2676 2677 #ifdef KSPROXY_TRACE 2678 swprintf(Buffer, L"CKsProxy::Load CreatePins %lx\n", hr); 2679 OutputDebugStringW(Buffer); 2680 #endif 2681 2682 //HACK 2683 hr = S_OK; 2684 2685 return hr; 2686 } 2687 2688 HRESULT 2689 STDMETHODCALLTYPE 2690 CKsProxy::Save(IPropertyBag *pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties) 2691 { 2692 #ifdef KSPROXY_TRACE 2693 OutputDebugStringW(L"CKsProxy::Save\n"); 2694 #endif 2695 return E_NOTIMPL; 2696 } 2697 2698 //------------------------------------------------------------------- 2699 // IBaseFilter interface 2700 // 2701 2702 HRESULT 2703 STDMETHODCALLTYPE 2704 CKsProxy::GetClassID( 2705 CLSID *pClassID) 2706 { 2707 #ifdef KSPROXY_TRACE 2708 OutputDebugStringW(L"CKsProxy::GetClassID\n"); 2709 #endif 2710 CopyMemory(pClassID, &CLSID_Proxy, sizeof(GUID)); 2711 2712 return S_OK; 2713 } 2714 2715 HRESULT 2716 STDMETHODCALLTYPE 2717 CKsProxy::Stop() 2718 { 2719 HRESULT hr; 2720 2721 #ifdef KSPROXY_TRACE 2722 OutputDebugStringW(L"CKsProxy::Stop\n"); 2723 #endif 2724 2725 EnterCriticalSection(&m_Lock); 2726 2727 hr = SetPinState(KSSTATE_STOP); 2728 if (SUCCEEDED(hr)) 2729 m_FilterState = State_Stopped; 2730 2731 LeaveCriticalSection(&m_Lock); 2732 2733 return hr; 2734 } 2735 2736 HRESULT 2737 STDMETHODCALLTYPE 2738 CKsProxy::Pause() 2739 { 2740 HRESULT hr = S_OK; 2741 2742 #ifdef KSPROXY_TRACE 2743 OutputDebugStringW(L"CKsProxy::Pause\n"); 2744 #endif 2745 2746 EnterCriticalSection(&m_Lock); 2747 2748 if (m_FilterState == State_Running) 2749 { 2750 hr = SetPinState(KSSTATE_STOP); 2751 } 2752 if (SUCCEEDED(hr)) 2753 { 2754 if (m_FilterState == State_Stopped) 2755 { 2756 hr = SetPinState(KSSTATE_PAUSE); 2757 } 2758 } 2759 2760 if (SUCCEEDED(hr)) 2761 m_FilterState = State_Paused; 2762 2763 LeaveCriticalSection(&m_Lock); 2764 return hr; 2765 2766 } 2767 2768 HRESULT 2769 STDMETHODCALLTYPE 2770 CKsProxy::Run( 2771 REFERENCE_TIME tStart) 2772 { 2773 HRESULT hr; 2774 2775 #ifdef KSPROXY_TRACE 2776 OutputDebugStringW(L"CKsProxy::Run\n"); 2777 #endif 2778 2779 EnterCriticalSection(&m_Lock); 2780 2781 if (m_FilterState == State_Stopped) 2782 { 2783 LeaveCriticalSection(&m_Lock); 2784 // setting filter state to pause 2785 hr = Pause(); 2786 if (FAILED(hr)) 2787 return hr; 2788 2789 EnterCriticalSection(&m_Lock); 2790 assert(m_FilterState == State_Paused); 2791 } 2792 2793 hr = SetPinState(KSSTATE_RUN); 2794 2795 if (SUCCEEDED(hr)) 2796 { 2797 m_FilterState = State_Running; 2798 } 2799 2800 LeaveCriticalSection(&m_Lock); 2801 return hr; 2802 } 2803 2804 HRESULT 2805 STDMETHODCALLTYPE 2806 CKsProxy::SetPinState( 2807 KSSTATE State) 2808 { 2809 HRESULT hr = S_OK; 2810 ULONG Index; 2811 IKsObject *pObject; 2812 ULONG BytesReturned; 2813 KSPROPERTY Property; 2814 PIN_INFO PinInfo; 2815 2816 Property.Set = KSPROPSETID_Connection; 2817 Property.Id = KSPROPERTY_CONNECTION_STATE; 2818 Property.Flags = KSPROPERTY_TYPE_SET; 2819 2820 // set all pins to running state 2821 for(Index = 0; Index < m_Pins.size(); Index++) 2822 { 2823 IPin * Pin = m_Pins[Index]; 2824 if (!Pin) 2825 continue; 2826 2827 //check if the pin is connected 2828 IPin * TempPin; 2829 hr = Pin->ConnectedTo(&TempPin); 2830 if (FAILED(hr)) 2831 { 2832 // skip unconnected pins 2833 continue; 2834 } 2835 2836 // release connected pin 2837 TempPin->Release(); 2838 2839 // query for the pin info 2840 hr = Pin->QueryPinInfo(&PinInfo); 2841 2842 if (SUCCEEDED(hr)) 2843 { 2844 if (PinInfo.pFilter) 2845 PinInfo.pFilter->Release(); 2846 2847 if (PinInfo.dir == PINDIR_OUTPUT) 2848 { 2849 hr = COutputPin_SetState(Pin, State); 2850 if (SUCCEEDED(hr)) 2851 continue; 2852 } 2853 } 2854 2855 //query IKsObject interface 2856 hr = Pin->QueryInterface(IID_IKsObject, (void**)&pObject); 2857 2858 // get pin handle 2859 HANDLE hPin = pObject->KsGetObjectHandle(); 2860 2861 // sanity check 2862 assert(hPin && hPin != INVALID_HANDLE_VALUE); 2863 2864 // now set state 2865 hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned); 2866 2867 #ifdef KSPROXY_TRACE 2868 WCHAR Buffer[100]; 2869 swprintf(Buffer, L"CKsProxy::SetPinState Index %u State %u hr %lx\n", Index, State, hr); 2870 OutputDebugStringW(Buffer); 2871 #endif 2872 2873 if (FAILED(hr)) 2874 return hr; 2875 } 2876 return hr; 2877 } 2878 2879 HRESULT 2880 STDMETHODCALLTYPE 2881 CKsProxy::GetState( 2882 DWORD dwMilliSecsTimeout, 2883 FILTER_STATE *State) 2884 { 2885 if (!State) 2886 return E_POINTER; 2887 2888 *State = m_FilterState; 2889 return S_OK; 2890 } 2891 2892 HRESULT 2893 STDMETHODCALLTYPE 2894 CKsProxy::SetSyncSource( 2895 IReferenceClock *pClock) 2896 { 2897 HRESULT hr; 2898 IKsClock *pKsClock; 2899 HANDLE hClock, hPin; 2900 ULONG Index; 2901 IPin * pin; 2902 IKsObject * pObject; 2903 KSPROPERTY Property; 2904 ULONG BytesReturned; 2905 PIN_DIRECTION PinDir; 2906 2907 #ifdef KSPROXY_TRACE 2908 OutputDebugStringW(L"CKsProxy::SetSyncSource\n"); 2909 #endif 2910 2911 // FIXME 2912 // need locks 2913 2914 if (pClock) 2915 { 2916 hr = pClock->QueryInterface(IID_IKsClock, (void**)&pKsClock); 2917 if (FAILED(hr)) 2918 { 2919 hr = m_ReferenceClock->QueryInterface(IID_IKsClock, (void**)&pKsClock); 2920 if (FAILED(hr)) 2921 return hr; 2922 } 2923 2924 // get clock handle 2925 hClock = pKsClock->KsGetClockHandle(); 2926 2927 // release IKsClock interface 2928 pKsClock->Release(); 2929 m_hClock = hClock; 2930 } 2931 else 2932 { 2933 // no clock handle 2934 m_hClock = NULL; 2935 } 2936 2937 2938 // distribute clock to all pins 2939 for(Index = 0; Index < m_Pins.size(); Index++) 2940 { 2941 // get current pin 2942 pin = m_Pins[Index]; 2943 if (!pin) 2944 continue; 2945 2946 // get IKsObject interface 2947 hr = pin->QueryInterface(IID_IKsObject, (void **)&pObject); 2948 if (SUCCEEDED(hr)) 2949 { 2950 // get pin handle 2951 hPin = pObject->KsGetObjectHandle(); 2952 if (hPin != INVALID_HANDLE_VALUE && hPin) 2953 { 2954 // set clock 2955 Property.Set = KSPROPSETID_Stream; 2956 Property.Id = KSPROPERTY_STREAM_MASTERCLOCK; 2957 Property.Flags = KSPROPERTY_TYPE_SET; 2958 2959 // set master clock 2960 hr = KsSynchronousDeviceControl(hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&m_hClock, sizeof(HANDLE), &BytesReturned); 2961 2962 if (FAILED(hr)) 2963 { 2964 if (hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_SET_NOT_FOUND) && 2965 hr != MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_NOT_FOUND)) 2966 { 2967 // failed to set master clock 2968 pObject->Release(); 2969 WCHAR Buffer[100]; 2970 swprintf(Buffer, L"CKsProxy::SetSyncSource KSPROPERTY_STREAM_MASTERCLOCK failed with %lx\n", hr); 2971 OutputDebugStringW(Buffer); 2972 return hr; 2973 } 2974 } 2975 } 2976 // release IKsObject 2977 pObject->Release(); 2978 } 2979 2980 // now get the direction 2981 hr = pin->QueryDirection(&PinDir); 2982 if (SUCCEEDED(hr)) 2983 { 2984 if (PinDir == PINDIR_OUTPUT) 2985 { 2986 // notify pin via 2987 //CBaseStreamControl::SetSyncSource(pClock) 2988 } 2989 } 2990 } 2991 2992 if (pClock) 2993 { 2994 pClock->AddRef(); 2995 } 2996 2997 if (m_ReferenceClock) 2998 { 2999 m_ReferenceClock->Release(); 3000 } 3001 3002 m_ReferenceClock = pClock; 3003 #ifdef KSPROXY_TRACE 3004 OutputDebugStringW(L"CKsProxy::SetSyncSource done\n"); 3005 #endif 3006 return S_OK; 3007 } 3008 3009 HRESULT 3010 STDMETHODCALLTYPE 3011 CKsProxy::GetSyncSource( 3012 IReferenceClock **pClock) 3013 { 3014 #ifdef KSPROXY_TRACE 3015 OutputDebugStringW(L"CKsProxy::GetSyncSource\n"); 3016 #endif 3017 3018 if (!pClock) 3019 return E_POINTER; 3020 3021 if (m_ReferenceClock) 3022 m_ReferenceClock->AddRef(); 3023 3024 *pClock = m_ReferenceClock; 3025 return S_OK; 3026 } 3027 3028 HRESULT 3029 STDMETHODCALLTYPE 3030 CKsProxy::EnumPins( 3031 IEnumPins **ppEnum) 3032 { 3033 return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum); 3034 } 3035 3036 HRESULT 3037 STDMETHODCALLTYPE 3038 CKsProxy::FindPin( 3039 LPCWSTR Id, IPin **ppPin) 3040 { 3041 ULONG PinId; 3042 3043 #ifdef KSPROXY_TRACE 3044 OutputDebugStringW(L"CKsProxy::FindPin\n"); 3045 #endif 3046 3047 if (!ppPin) 3048 return E_POINTER; 3049 3050 // convert to pin 3051 int ret = swscanf(Id, L"%u", &PinId); 3052 3053 if (!ret || ret == EOF) 3054 { 3055 // invalid id 3056 return VFW_E_NOT_FOUND; 3057 } 3058 3059 if (PinId >= m_Pins.size() || m_Pins[PinId] == NULL) 3060 { 3061 // invalid id 3062 return VFW_E_NOT_FOUND; 3063 } 3064 3065 // found pin 3066 *ppPin = m_Pins[PinId]; 3067 m_Pins[PinId]->AddRef(); 3068 3069 return S_OK; 3070 } 3071 3072 3073 HRESULT 3074 STDMETHODCALLTYPE 3075 CKsProxy::QueryFilterInfo( 3076 FILTER_INFO *pInfo) 3077 { 3078 if (!pInfo) 3079 return E_POINTER; 3080 3081 #ifdef KSPROXY_TRACE 3082 OutputDebugStringW(L"CKsProxy::QueryFilterInfo\n"); 3083 #endif 3084 3085 pInfo->achName[0] = L'\0'; 3086 pInfo->pGraph = m_pGraph; 3087 3088 if (m_pGraph) 3089 m_pGraph->AddRef(); 3090 3091 return S_OK; 3092 } 3093 3094 HRESULT 3095 STDMETHODCALLTYPE 3096 CKsProxy::JoinFilterGraph( 3097 IFilterGraph *pGraph, 3098 LPCWSTR pName) 3099 { 3100 #ifdef KSPROXY_TRACE 3101 WCHAR Buffer[100]; 3102 swprintf(Buffer, L"CKsProxy::JoinFilterGraph pName %s pGraph %p m_Ref %u\n", pName, pGraph, m_Ref); 3103 OutputDebugStringW(Buffer); 3104 #endif 3105 3106 if (pGraph) 3107 { 3108 // joining filter graph 3109 m_pGraph = pGraph; 3110 } 3111 else 3112 { 3113 // leaving graph 3114 m_pGraph = 0; 3115 } 3116 3117 return S_OK; 3118 } 3119 3120 3121 HRESULT 3122 STDMETHODCALLTYPE 3123 CKsProxy::QueryVendorInfo( 3124 LPWSTR *pVendorInfo) 3125 { 3126 #ifdef KSPROXY_TRACE 3127 OutputDebugStringW(L"CKsProxy::QueryVendorInfo\n"); 3128 #endif 3129 return StringFromCLSID(CLSID_Proxy, pVendorInfo); 3130 } 3131 3132 //------------------------------------------------------------------- 3133 // IAMovieSetup interface 3134 // 3135 3136 HRESULT 3137 STDMETHODCALLTYPE 3138 CKsProxy::Register() 3139 { 3140 #ifdef KSPROXY_TRACE 3141 OutputDebugStringW(L"CKsProxy::Register : NotImplemented\n"); 3142 #endif 3143 3144 return E_NOTIMPL; 3145 } 3146 3147 HRESULT 3148 STDMETHODCALLTYPE 3149 CKsProxy::Unregister() 3150 { 3151 #ifdef KSPROXY_TRACE 3152 OutputDebugStringW(L"CKsProxy::Unregister : NotImplemented\n"); 3153 #endif 3154 return E_NOTIMPL; 3155 } 3156 3157 HRESULT 3158 WINAPI 3159 CKsProxy_Constructor( 3160 IUnknown * pUnkOuter, 3161 REFIID riid, 3162 LPVOID * ppv) 3163 { 3164 #ifdef KSPROXY_TRACE 3165 WCHAR Buffer[100]; 3166 LPOLESTR pstr; 3167 StringFromCLSID(riid, &pstr); 3168 swprintf(Buffer, L"CKsProxy_Constructor pUnkOuter %p riid %s\n", pUnkOuter, pstr); 3169 OutputDebugStringW(Buffer); 3170 #endif 3171 3172 CKsProxy * handler = new CKsProxy(); 3173 3174 if (!handler) 3175 return E_OUTOFMEMORY; 3176 3177 if (FAILED(handler->QueryInterface(riid, ppv))) 3178 { 3179 /* not supported */ 3180 delete handler; 3181 return E_NOINTERFACE; 3182 } 3183 3184 return S_OK; 3185 } 3186