Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
7.9 KiB

  1. //==========================================================================;
  2. //
  3. // Copyright (c) Microsoft Corporation 1998-2000.
  4. //
  5. //--------------------------------------------------------------------------;
  6. //
  7. // vidprot.cpp : Implementation of CTVProt
  8. //
  9. #include "stdafx.h"
  10. #ifndef TUNING_MODEL_ONLY
  11. #include <string.h>
  12. #include <shlwapi.h>
  13. #include "vidprot.h"
  14. #include "devices.h"
  15. DEFINE_EXTERN_OBJECT_ENTRY(__uuidof(CTVProt), CTVProt)
  16. DEFINE_EXTERN_OBJECT_ENTRY(__uuidof(CDVDProt), CDVDProt)
  17. /////////////////////////////////////////////////////////////////////////////
  18. /////////////////////////////////////////////////////////////////////////////
  19. // CTVProt
  20. /////////////////////////////////////////////////////////////////////////////
  21. /////////////////////////////////////////////////////////////////////////////
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CTVProt -- IInternetProtocolRoot
  24. STDMETHODIMP CTVProt::Start(LPCWSTR szUrl,
  25. IInternetProtocolSink* pOIProtSink,
  26. IInternetBindInfo* pOIBindInfo,
  27. DWORD grfPI,
  28. HANDLE_PTR /* dwReserved */)
  29. {
  30. TRACELM(TRACE_DEBUG, "CTVProt::Start()");
  31. if (!pOIProtSink)
  32. {
  33. TRACELM(TRACE_DEBUG, "CTVProt::Start() IInternetProctocolSink * == NULL");
  34. return E_POINTER;
  35. }
  36. m_pSink.Release();
  37. m_pSink = pOIProtSink;
  38. m_pSink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, 0);
  39. #if 0
  40. // this bug is fixed in ie 5.5+ on whistler. if you want to run on earlier versions of ie such as 2k gold then you need this.
  41. m_pSink->ReportProgress(BINDSTATUS_CONNECTING, NULL); // put binding in downloading state so it doesn't ignore our IUnknown*
  42. #endif
  43. if (!pOIBindInfo) {
  44. m_pSink->ReportResult(E_NOINTERFACE, 0, 0);
  45. return E_NOINTERFACE;
  46. }
  47. // don't run unless we're being invoked from a safe site
  48. HRESULT hr = IsSafeSite(m_pSink);
  49. if (FAILED(hr)) {
  50. m_pSink->ReportResult(hr, 0, 0);
  51. return hr;
  52. }
  53. ULONG count;
  54. LPOLESTR pb;
  55. hr = pOIBindInfo->GetBindString(BINDSTRING_FLAG_BIND_TO_OBJECT, &pb, 1, &count);
  56. if (FAILED(hr)) {
  57. m_pSink->ReportResult(hr, 0, 0);
  58. return hr;
  59. }
  60. if (wcscmp(pb, BIND_TO_OBJ_VAL)) {
  61. // we must be getting a bind to storage so skip the expensive stuff and
  62. // wait for the bind to object which is coming next
  63. m_pSink->ReportData(BSCF_LASTDATANOTIFICATION |
  64. BSCF_DATAFULLYAVAILABLE, 0, 0);
  65. m_pSink->ReportResult(S_OK, 0, 0);
  66. m_pSink.Release();
  67. return S_OK;
  68. }
  69. // and, in one of the most bizarre maneuvers i've ever seen, rather than casting,
  70. // urlmon passes back the ascii value of the ibindctx pointer in the string
  71. hr = pOIBindInfo->GetBindString(BINDSTRING_PTR_BIND_CONTEXT, &pb, 1, &count);
  72. if (FAILED(hr)) {
  73. m_pSink->ReportResult(hr, 0, 0);
  74. return hr;
  75. }
  76. _ASSERT(count == 1);
  77. PQBindCtx pbindctx;
  78. #define RADIX_BASE_10 (10)
  79. #ifdef _WIN64
  80. #if 0
  81. // undone: turn this back on for win64 when _wcstoxi64 get into libc.c, they're in the header
  82. // but not implemented so this doesn't link
  83. pbindctx.Attach(reinterpret_cast<IBindCtx*>(_wcstoui64(pb, NULL, RADIX_BASE_10))); // urlmon already did an addref
  84. #else
  85. swscanf(pb, L"%I64d", &pbindctx.p);
  86. #endif
  87. #else
  88. pbindctx.Attach(reinterpret_cast<IBindCtx*>(wcstol(pb, NULL, RADIX_BASE_10))); // urlmon already did an addref
  89. #endif
  90. if (!pbindctx) {
  91. m_pSink->ReportResult(E_NOINTERFACE, 0, 0);
  92. return E_NOINTERFACE;
  93. }
  94. TRACELM(TRACE_DEBUG, "CTVProt::Start(): creating control object");
  95. PQVidCtl pCtl;
  96. hr = GetVidCtl(pCtl);
  97. if (FAILED(hr)) {
  98. m_pSink->ReportResult(hr, 0, 0);
  99. return hr;
  100. }
  101. hr = pbindctx->RegisterObjectParam(OLESTR("IUnknown Pointer"), pCtl);
  102. if (FAILED(hr)) {
  103. m_pSink->ReportResult(hr, 0, 0);
  104. return hr;
  105. }
  106. TRACELSM(TRACE_DEBUG, (dbgDump << "BINDSTATUS_IUNKNOWNAVAILABLE(29), " << KEY_CLSID_VidCtl), "");
  107. m_pSink->ReportProgress(BINDSTATUS_IUNKNOWNAVAILABLE, NULL);
  108. m_pSink->ReportData(BSCF_LASTDATANOTIFICATION |
  109. BSCF_DATAFULLYAVAILABLE, 0, 0);
  110. m_pSink->ReportResult(S_OK, 0, 0);
  111. m_pSink.Release();
  112. return S_OK;
  113. }
  114. HRESULT CTVProt::GetCachedVidCtl(PQVidCtl &pCtl, PQWebBrowser2& pW2) {
  115. // hunt for cached object
  116. PQServiceProvider pSP(m_pSink);
  117. if (!pSP) {
  118. return E_UNEXPECTED;
  119. }
  120. HRESULT hr = pSP->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID *)&pW2);
  121. if (FAILED(hr)) {
  122. return hr;
  123. }
  124. CComVariant v;
  125. CComBSTR propname(KEY_CLSID_VidCtl);
  126. if (!propname) {
  127. return E_UNEXPECTED;
  128. }
  129. hr = pW2->GetProperty(propname, &v);
  130. if (FAILED(hr)) {
  131. return hr;
  132. }
  133. if (v.vt == VT_UNKNOWN) {
  134. pCtl = v.punkVal;
  135. } else if (v.vt == VT_DISPATCH) {
  136. pCtl = v.pdispVal;
  137. } else {
  138. TRACELM(TRACE_ERROR, "CTVProt::GetCachedObject(): non-object cached w/ our key");
  139. pCtl.Release();
  140. // don't return error. we'll ignore this and create a new one
  141. }
  142. // undone: look and see if pCtl already has a site.because
  143. // this means we're seeing the second tv: on this page
  144. // so just get the current TR/channel from it if necessary (tv: w/ no rhs)
  145. // and create a new ctl
  146. return NOERROR;
  147. }
  148. HRESULT CTVProt::GetVidCtl(PQVidCtl &pCtl) {
  149. PQWebBrowser2 pW2;
  150. HRESULT hr = GetCachedVidCtl(pCtl, pW2);
  151. if (FAILED(hr)) {
  152. return hr;
  153. }
  154. if (!pCtl) {
  155. // undone: long term, we want to move a bunch of this create/setup logic into factoryhelp
  156. // so we can share more code with the dvd: protocol and the behavior factory
  157. hr = pCtl.CoCreateInstance(CLSID_MSVidCtl, NULL, CLSCTX_INPROC_SERVER);
  158. if (FAILED(hr)) {
  159. return hr;
  160. }
  161. // cache this ctl for next time
  162. if (pW2) {
  163. VARIANT v;
  164. v.vt = VT_UNKNOWN;
  165. v.punkVal = pCtl;
  166. CComBSTR propname(KEY_CLSID_VidCtl);
  167. if (!propname) {
  168. return E_UNEXPECTED;
  169. }
  170. hr = pW2->PutProperty(propname, v);
  171. if (FAILED(hr)) {
  172. TRACELM(TRACE_ERROR, "CTVProt::Start() Can't cache ctl");
  173. // ignore this error. it shouldn't ever happen and if it does then it will
  174. // just cause a perf degradation. trace it and move on
  175. }
  176. }
  177. // undone: parse rhs of url and create the right tuning request
  178. CComVariant pTR(CFactoryHelper::GetDefaultTR());
  179. if (!pTR) {
  180. TRACELM(TRACE_ERROR, "CTVProt::Start() Can't find default Tune Request");
  181. return E_INVALIDARG;
  182. }
  183. hr = pCtl->View(&pTR);
  184. if (FAILED(hr)) {
  185. TRACELM(TRACE_ERROR, "CTVProt::Start() Can't view default Tune Request");
  186. return hr;
  187. }
  188. // undone: once we know where vidctl will live in the registry then we need to put a flag
  189. // in the registry just disables including any features in the tv: prot
  190. PQFeatures pF;
  191. hr = pCtl->get_FeaturesAvailable(&pF);
  192. if (FAILED(hr)) {
  193. TRACELM(TRACE_ERROR, "CTVProt::Start() Can't get features collection");
  194. return hr;
  195. }
  196. // undone: look up default feature segments for tv: in registry
  197. // for now we're just going to hard code the ones we want
  198. CFeatures* pC = static_cast<CFeatures *>(pF.p);
  199. CFeatures* pNewColl = new CFeatures;
  200. if (!pNewColl) {
  201. return E_OUTOFMEMORY;
  202. }
  203. for (DeviceCollection::iterator i = pC->m_Devices.begin(); i != pC->m_Devices.end(); ++i) {
  204. PQFeature f(*i);
  205. GUID2 clsid;
  206. hr = f->get__ClassID(&clsid);
  207. if (FAILED(hr)) {
  208. TRACELM(TRACE_ERROR, "CTVProt::GetVidCtl() Can't get feature class id");
  209. continue;
  210. }
  211. if (clsid == CLSID_MSVidClosedCaptioning ||
  212. clsid == CLSID_MSVidDataServices) {
  213. pNewColl->m_Devices.push_back(*i);
  214. }
  215. }
  216. hr = pCtl->put_FeaturesActive(pNewColl);
  217. if (FAILED(hr)) {
  218. TRACELM(TRACE_ERROR, "CTVProt::Start() Can't put features collection");
  219. return hr;
  220. }
  221. }
  222. ASSERT(pCtl);
  223. hr = pCtl->Run();
  224. if (FAILED(hr)) {
  225. TRACELSM(TRACE_ERROR, (dbgDump << "CTVProt::Start() run failed. hr = " << hexdump(hr)), "");
  226. return hr;
  227. }
  228. return NOERROR;
  229. }
  230. #endif // TUNING_MODEL_ONLY
  231. // end of file vidprot.cpp