Leaked source code of windows server 2003
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.

839 lines
30 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Tabular Data Control
  4. // Copyright (C) Microsoft Corporation, 1996, 1997
  5. //
  6. // File: TDCCtl.h
  7. //
  8. // Contents: Declaration of the CTDCCtl ActiveX Control.
  9. //
  10. //------------------------------------------------------------------------
  11. #include "resource.h" // main symbols
  12. #include <simpdata.h>
  13. #include "wch.h"
  14. #include <wininet.h> // for INTERNET_MAX_URL_LENGTH
  15. #pragma comment(lib, "wininet.lib")
  16. #ifndef DISPID_AMBIENT_CODEPAGE
  17. #define DISPID_AMBIENT_CODEPAGE (-725)
  18. #endif
  19. // Declare helper needed in IHttpNegotiateImpl
  20. HRESULT
  21. GetHostURL(IOleClientSite *pSite, LPOLESTR *ppszHostName);
  22. //------------------------------------------------------------------------
  23. //
  24. // Template: CMyBindStatusCallback
  25. //
  26. // Synopsis: This is a temporary kludge to get around an ATL feature
  27. // while we're waiting for it to become official code.
  28. //
  29. //------------------------------------------------------------------------
  30. template <class T>
  31. class ATL_NO_VTABLE IServiceProviderImpl
  32. {
  33. public:
  34. // IUnknown
  35. //
  36. STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
  37. _ATL_DEBUG_ADDREF_RELEASE_IMPL(IServiceProviderImpl)
  38. STDMETHOD(QueryService) (REFGUID guidService,
  39. REFIID riid,
  40. void **ppvObject)
  41. {
  42. return S_OK;
  43. }
  44. };
  45. template <class T>
  46. class ATL_NO_VTABLE IHttpNegotiateImpl
  47. {
  48. public:
  49. // IUnknown
  50. //
  51. STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
  52. _ATL_DEBUG_ADDREF_RELEASE_IMPL(IHttpNegotiateImpl)
  53. STDMETHOD(BeginningTransaction) (LPCWSTR szURL,
  54. LPCWSTR szHeaders,
  55. DWORD dwReserved,
  56. LPWSTR *pszAdditionalHeaders)
  57. {
  58. return S_OK;
  59. }
  60. STDMETHOD(OnResponse) (DWORD dwResponseCode,
  61. LPCWSTR szResponseHeaders,
  62. LPCWSTR szRequestHeaders,
  63. LPWSTR *pszAdditionalRequestHeaders)
  64. {
  65. return S_OK;
  66. }
  67. };
  68. // IE5 85290: mshtml needs a way to recognize the TDC from
  69. // its IBindStatusCallback. We define a dummy interface for this.
  70. template <class T>
  71. class ATL_NO_VTABLE IAmTheTDCImpl
  72. {
  73. public:
  74. // IUnknown
  75. //
  76. STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
  77. _ATL_DEBUG_ADDREF_RELEASE_IMPL(IAmTheTDCImpl)
  78. };
  79. template <class T>
  80. class ATL_NO_VTABLE CMyBindStatusCallback :
  81. public CComObjectRootEx<typename T::_ThreadModel::ThreadModelNoCS>,
  82. public IBindStatusCallbackImpl<T>, public IHttpNegotiateImpl<T>, public IServiceProviderImpl<T>,
  83. public IAmTheTDCImpl<T>
  84. {
  85. typedef void (T::*ATL_PDATAAVAILABLE)(CMyBindStatusCallback<T>* pbsc, BYTE* pBytes, DWORD dwSize);
  86. public:
  87. BEGIN_COM_MAP(CMyBindStatusCallback<T>)
  88. COM_INTERFACE_ENTRY_IID(IID_IBindStatusCallback, IBindStatusCallbackImpl<T>)
  89. COM_INTERFACE_ENTRY_IID(IID_IHttpNegotiate, IHttpNegotiateImpl<T>)
  90. COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProviderImpl<T>)
  91. COM_INTERFACE_ENTRY_IID(IID_IAmTheTDC, IAmTheTDCImpl<T>)
  92. END_COM_MAP()
  93. CMyBindStatusCallback()
  94. {
  95. m_pT = NULL;
  96. m_pFunc = NULL;
  97. m_fReload = FALSE;
  98. }
  99. ~CMyBindStatusCallback()
  100. {
  101. ATLTRACE(_T("~CMyBindStatusCallback\n"));
  102. }
  103. // IServiceProvider methods
  104. STDMETHOD(QueryService) (REFGUID guidService,
  105. REFIID riid,
  106. void **ppvObject)
  107. {
  108. // As it turns out, the service ID for IHttpNegotiate is the same
  109. // as it's IID (confusing). This is the only service we support.
  110. if (IsEqualGUID(IID_IHttpNegotiate, guidService))
  111. {
  112. return ((IHttpNegotiate *)this)->QueryInterface(riid, ppvObject);
  113. }
  114. else return E_NOTIMPL;
  115. }
  116. //
  117. // IHttpNegotiate methods
  118. //
  119. STDMETHOD(BeginningTransaction) (LPCWSTR szURL,
  120. LPCWSTR szHeaders,
  121. DWORD dwReserved,
  122. LPWSTR *pszAdditionalHeaders)
  123. {
  124. HRESULT hr = S_OK;
  125. WCHAR swzHostScheme[INTERNET_MAX_URL_LENGTH];
  126. DWORD cchHostScheme = INTERNET_MAX_URL_LENGTH;
  127. WCHAR swzFileScheme[INTERNET_MAX_URL_LENGTH];
  128. DWORD cchFileScheme = INTERNET_MAX_URL_LENGTH;
  129. LPOLESTR pszHostName;
  130. *pszAdditionalHeaders = NULL;
  131. hr = GetHostURL(m_spClientSite, &pszHostName);
  132. if (FAILED(hr))
  133. goto Cleanup;
  134. // PARSE_SCHEMA didn't work, so we'll just CANONICALIZE and then use the first N
  135. // characters of the URL
  136. hr = CoInternetParseUrl(pszHostName, PARSE_CANONICALIZE, 0, swzHostScheme, cchHostScheme,
  137. &cchHostScheme, 0);
  138. if (FAILED(hr))
  139. goto Cleanup;
  140. // Don't send a referer which isn't http: or https:, it's none
  141. // of the servers' business. Further, don't send an https:
  142. // referer when requesting an http: file.
  143. if (0 != wch_incmp(swzHostScheme, L"https:", 6) &&
  144. 0 != wch_incmp(swzHostScheme, L"http:", 5))
  145. goto Cleanup;
  146. if (0 == wch_incmp(swzHostScheme, L"https:", 6))
  147. {
  148. hr = CoInternetParseUrl(szURL, PARSE_CANONICALIZE, 0, swzFileScheme, cchFileScheme,
  149. &cchFileScheme, 0);
  150. if (0 == wch_incmp(swzFileScheme, L"http:", 5)) // don't send https: referer
  151. goto Cleanup; // to an http: file.
  152. }
  153. // 3*sizeof(WCHAR) is for CR, LF, & '\0'
  154. *pszAdditionalHeaders = (WCHAR *)CoTaskMemAlloc(sizeof(L"Referer: ") +
  155. ocslen(pszHostName)*sizeof(WCHAR) +
  156. 3*sizeof(WCHAR));
  157. if (NULL != *pszAdditionalHeaders)
  158. {
  159. ocscpy(*pszAdditionalHeaders, L"Referer: ");
  160. ocscpy(&((*pszAdditionalHeaders)[9]), pszHostName);
  161. ocscpy(&((*pszAdditionalHeaders)[9+ocslen(pszHostName)]), L"\r\n");
  162. }
  163. Cleanup:
  164. CoTaskMemFree(pszHostName);
  165. return hr;
  166. }
  167. STDMETHOD(OnResponse) (DWORD dwResponseCode,
  168. LPCWSTR szResponseHeaders,
  169. LPCWSTR szRequestHeaders,
  170. LPWSTR *pszAdditionalRequestHeaders)
  171. {
  172. return S_OK;
  173. }
  174. //
  175. // IBindStatusCallback methods
  176. //
  177. STDMETHOD(OnStartBinding)(DWORD dwReserved, IBinding *pBinding)
  178. {
  179. ATLTRACE(_T("CMyBindStatusCallback::OnStartBinding\n"));
  180. m_spBinding = pBinding;
  181. return S_OK;
  182. }
  183. STDMETHOD(GetPriority)(LONG *pnPriority)
  184. {
  185. ATLTRACENOTIMPL(_T("CMyBindStatusCallback::GetPriority"));
  186. }
  187. STDMETHOD(OnLowResource)(DWORD reserved)
  188. {
  189. ATLTRACENOTIMPL(_T("CMyBindStatusCallback::OnLowResource"));
  190. }
  191. STDMETHOD(OnProgress)(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
  192. {
  193. if (BINDSTATUS_REDIRECTING == ulStatusCode && szStatusText != NULL)
  194. {
  195. ocscpy(m_pszURL, szStatusText);
  196. }
  197. return S_OK;
  198. }
  199. STDMETHOD(OnStopBinding)(HRESULT hresult, LPCWSTR szError)
  200. {
  201. // ATLTRACE(_T("CMyBindStatusCallback::OnStopBinding\n"));
  202. (m_pT->*m_pFunc)(this, NULL, 0);
  203. if (m_spWinInetFileStream)
  204. {
  205. m_spWinInetFileStream.Release();
  206. }
  207. m_spBinding.Release();
  208. m_spBindCtx.Release();
  209. m_spMoniker.Release();
  210. return S_OK;
  211. }
  212. STDMETHOD(GetBindInfo)(DWORD *pgrfBINDF, BINDINFO *pbindInfo)
  213. {
  214. ATLTRACE(_T("CMyBindStatusCallback::GetBindInfo\n"));
  215. if (!pbindInfo || !pbindInfo->cbSize || !pgrfBINDF)
  216. return E_INVALIDARG;
  217. *pgrfBINDF = BINDF_ASYNCHRONOUS
  218. | BINDF_ASYNCSTORAGE
  219. ;
  220. // ;begin_internal
  221. #ifdef NEVER
  222. // I want DEBUG mode to NOT cache things!! -cfranks
  223. *pgrfBINDF |= BINDF_GETNEWESTVERSION
  224. | BINDF_NOWRITECACHE
  225. | BINDF_RESYNCHRONIZE
  226. ;
  227. #endif
  228. // ;end_internal
  229. #ifndef DISPID_AMBIENT_OFFLINE
  230. #define DISPID_AMBIENT_OFFLINE (-5501)
  231. #endif
  232. // Get our offline property from container
  233. VARIANT var;
  234. VariantInit(&var);
  235. DWORD dwConnectedStateFlags;
  236. m_pT->GetAmbientProperty(DISPID_AMBIENT_OFFLINE, var);
  237. if (var.vt==VT_BOOL && var.boolVal)
  238. {
  239. if (!(InternetGetConnectedState(&dwConnectedStateFlags, 0)) &&
  240. (0 == (dwConnectedStateFlags & INTERNET_CONNECTION_MODEM_BUSY)))
  241. {
  242. ATLTRACE(_T("CMyBindStatusCallback::GetBindInfo OFFLINE\n"));
  243. // We're not even dialed out to another connectoid
  244. *pgrfBINDF |= BINDF_OFFLINEOPERATION;
  245. }
  246. else
  247. {
  248. ATLTRACE(_T("CMyBindStatusCallback::GetBindInfo OFFLINE\n"));
  249. *pgrfBINDF &= ~BINDF_OFFLINEOPERATION;
  250. }
  251. }
  252. // See if we should force a reload, iff we're not offline.
  253. if (!(*pgrfBINDF & BINDF_OFFLINEOPERATION) && m_fReload)
  254. {
  255. *pgrfBINDF |= BINDF_RESYNCHRONIZE|BINDF_PRAGMA_NO_CACHE;
  256. }
  257. ULONG cbSize = pbindInfo->cbSize;
  258. memset(pbindInfo, 0, cbSize);
  259. pbindInfo->cbSize = cbSize;
  260. pbindInfo->dwBindVerb = BINDVERB_GET;
  261. return S_OK;
  262. }
  263. STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
  264. {
  265. ATLTRACE(_T("CMyBindStatusCallback::OnDataAvailable\n"));
  266. HRESULT hr = S_OK;
  267. // Get the Stream passed
  268. if (BSCF_FIRSTDATANOTIFICATION & grfBSCF)
  269. {
  270. if (!m_spStream && pstgmed->tymed == TYMED_ISTREAM)
  271. {
  272. m_spStream = pstgmed->pstm;
  273. (void)m_spStream->QueryInterface(IID_IWinInetFileStream, (void **)&m_spWinInetFileStream);
  274. if (m_spWinInetFileStream)
  275. {
  276. CComPtr<IWinInetHttpInfo> spWinInetHttpInfo;
  277. (void)m_spBinding->QueryInterface(IID_IWinInetHttpInfo, (void **)&spWinInetHttpInfo);
  278. if (spWinInetHttpInfo)
  279. {
  280. HANDLE hWinInetLock = NULL;
  281. DWORD dwHandleSize = sizeof(HANDLE);
  282. HRESULT hr = spWinInetHttpInfo->QueryOption(WININETINFO_OPTION_LOCK_HANDLE, (LPVOID)&hWinInetLock, &dwHandleSize);
  283. if (SUCCEEDED(hr) && hWinInetLock)
  284. {
  285. m_spWinInetFileStream->SetHandleForUnlock((DWORD_PTR)hWinInetLock, 0);
  286. }
  287. spWinInetHttpInfo.Release();
  288. }
  289. }
  290. }
  291. }
  292. DWORD dwRead = dwSize - m_dwTotalRead; // Minimum amount available that hasn't been read
  293. DWORD dwActuallyRead = 0; // Placeholder for amount read during this pull
  294. // If there is some data to be read then go ahead and read them
  295. if (m_spStream)
  296. {
  297. if (dwRead > 0)
  298. {
  299. BYTE* pBytes = NULL;
  300. ATLTRY(pBytes = new BYTE[dwRead + 1]);
  301. if (pBytes == NULL)
  302. return S_FALSE;
  303. hr = m_spStream->Read(pBytes, dwRead, &dwActuallyRead);
  304. if (SUCCEEDED(hr))
  305. {
  306. pBytes[dwActuallyRead] = 0;
  307. if (dwActuallyRead>0)
  308. {
  309. (m_pT->*m_pFunc)(this, pBytes, dwActuallyRead);
  310. m_dwTotalRead += dwActuallyRead;
  311. }
  312. }
  313. delete[] pBytes;
  314. }
  315. }
  316. if (BSCF_LASTDATANOTIFICATION & grfBSCF)
  317. m_spStream.Release();
  318. return hr;
  319. }
  320. STDMETHOD(OnObjectAvailable)(REFIID riid, IUnknown *punk)
  321. {
  322. ATLTRACENOTIMPL(_T("CMyBindStatusCallback::OnObjectAvailable"));
  323. }
  324. HRESULT _StartAsyncDownload(BSTR bstrURL, IUnknown* pUnkContainer, BOOL bRelative)
  325. {
  326. m_dwTotalRead = 0;
  327. m_dwAvailableToRead = 0;
  328. HRESULT hr = S_OK;
  329. CComQIPtr<IServiceProvider, &IID_IServiceProvider> spServiceProvider(pUnkContainer);
  330. CComPtr<IBindHost> spBindHost;
  331. CComPtr<IStream> spStream;
  332. if (spServiceProvider)
  333. spServiceProvider->QueryService(SID_IBindHost, IID_IBindHost, (void**)&spBindHost);
  334. // We don't bother checking this QI, because the only failure mode is that our
  335. // BeginningNegotitation method won't be able able to properly add the referer string.
  336. (void)pUnkContainer->QueryInterface(IID_IOleClientSite, (void **)&m_spClientSite);
  337. if (spBindHost == NULL)
  338. {
  339. if (bRelative)
  340. return E_NOINTERFACE; // relative asked for, but no IBindHost
  341. hr = CreateURLMoniker(NULL, bstrURL, &m_spMoniker);
  342. if (SUCCEEDED(hr))
  343. hr = CreateBindCtx(0, &m_spBindCtx);
  344. if (SUCCEEDED(hr))
  345. hr = RegisterBindStatusCallback(m_spBindCtx, reinterpret_cast<IBindStatusCallback*>(static_cast<IBindStatusCallbackImpl<T>*>(this)), 0, 0L);
  346. else
  347. m_spMoniker.Release();
  348. if (SUCCEEDED(hr))
  349. {
  350. LPOLESTR pszTemp = NULL;
  351. hr = m_spMoniker->GetDisplayName(m_spBindCtx, NULL, &pszTemp);
  352. if (!hr && pszTemp != NULL)
  353. ocscpy(m_pszURL, pszTemp);
  354. CoTaskMemFree(pszTemp);
  355. hr = m_spMoniker->BindToStorage(m_spBindCtx, 0, IID_IStream, (void**)&spStream);
  356. }
  357. }
  358. else
  359. {
  360. hr = CreateBindCtx(0, &m_spBindCtx);
  361. if (SUCCEEDED(hr))
  362. hr = RegisterBindStatusCallback(m_spBindCtx, reinterpret_cast<IBindStatusCallback*>(static_cast<IBindStatusCallbackImpl<T>*>(this)), 0, 0L);
  363. if (SUCCEEDED(hr))
  364. {
  365. if (bRelative)
  366. hr = spBindHost->CreateMoniker(bstrURL, m_spBindCtx, &m_spMoniker, 0);
  367. else
  368. hr = CreateURLMoniker(NULL, bstrURL, &m_spMoniker);
  369. }
  370. if (SUCCEEDED(hr))
  371. {
  372. LPOLESTR pszTemp = NULL;
  373. hr = m_spMoniker->GetDisplayName(m_spBindCtx, NULL, &pszTemp);
  374. if (!hr && pszTemp != NULL)
  375. ocscpy(m_pszURL, pszTemp);
  376. CoTaskMemFree(pszTemp);
  377. hr = spBindHost->MonikerBindToStorage(m_spMoniker, NULL, reinterpret_cast<IBindStatusCallback*>(static_cast<IBindStatusCallbackImpl<T>*>(this)), IID_IStream, (void**)&spStream);
  378. ATLTRACE(_T("Bound"));
  379. }
  380. }
  381. return hr;
  382. }
  383. HRESULT StartAsyncDownload(T* pT, ATL_PDATAAVAILABLE pFunc, BSTR bstrURL, IUnknown* pUnkContainer, BOOL bRelative,
  384. BOOL fReload)
  385. {
  386. m_pT = pT;
  387. m_pFunc = pFunc;
  388. m_fReload = fReload; // force reload if TRUE
  389. return _StartAsyncDownload(bstrURL, pUnkContainer, bRelative);
  390. }
  391. static HRESULT Download(T* pT, ATL_PDATAAVAILABLE pFunc, BSTR bstrURL, IUnknown* pUnkContainer = NULL, BOOL bRelative = FALSE)
  392. {
  393. CComObject<CMyBindStatusCallback<T> > *pbsc;
  394. HRESULT hRes = CComObject<CMyBindStatusCallback<T> >::CreateInstance(&pbsc);
  395. if (FAILED(hRes))
  396. return hRes;
  397. return pbsc->StartAsyncDownload(pT, pFunc, bstrURL, pUnkContainer, bRelative, FALSE);
  398. }
  399. void DeleteDataFile()
  400. {
  401. // we can't delete the file at the time of the call (it's in use), so
  402. // mark it for deletion later - at stream destruction time
  403. if (m_spWinInetFileStream)
  404. {
  405. m_spWinInetFileStream->SetDeleteFile(0);
  406. }
  407. }
  408. CComPtr<IMoniker> m_spMoniker;
  409. CComPtr<IBindCtx> m_spBindCtx;
  410. CComPtr<IBinding> m_spBinding;
  411. CComPtr<IWinInetFileStream> m_spWinInetFileStream;
  412. CComPtr<IStream> m_spStream;
  413. CComPtr<IOleClientSite> m_spClientSite;
  414. BOOL m_fReload;
  415. OLECHAR m_pszURL[INTERNET_MAX_URL_LENGTH];
  416. T* m_pT;
  417. ATL_PDATAAVAILABLE m_pFunc;
  418. DWORD m_dwTotalRead;
  419. DWORD m_dwAvailableToRead;
  420. };
  421. //////////////////////////////////////////////////////////////////////////////////////////////////
  422. // CTimer
  423. template <class Derived, class T, const IID* piid>
  424. class CTimer
  425. {
  426. public:
  427. CTimer()
  428. {
  429. m_bTimerOn = FALSE;
  430. }
  431. HRESULT TimerOn(DWORD dwTimerInterval)
  432. {
  433. Derived* pDerived = ((Derived*)this);
  434. m_dwTimerInterval = dwTimerInterval;
  435. if (m_bTimerOn) // already on, just change interval
  436. return S_OK;
  437. m_bTimerOn = TRUE;
  438. m_dwTimerInterval = dwTimerInterval;
  439. m_pStream = NULL;
  440. HRESULT hRes;
  441. hRes = CoMarshalInterThreadInterfaceInStream(*piid, (T*)pDerived, &m_pStream);
  442. // Create thread and pass the thread proc the this ptr
  443. m_hThread = CreateThread(NULL, 0, &_Apartment, (void*)this, 0, &m_dwThreadID);
  444. return S_OK;
  445. }
  446. void TimerOff()
  447. {
  448. if (m_bTimerOn)
  449. {
  450. m_bTimerOn = FALSE;
  451. AtlWaitWithMessageLoop(m_hThread);
  452. }
  453. }
  454. // Implementation
  455. private:
  456. static DWORD WINAPI _Apartment(void* pv)
  457. {
  458. CTimer<Derived, T, piid>* pThis = (CTimer<Derived, T, piid>*) pv;
  459. pThis->Apartment();
  460. return 0;
  461. }
  462. DWORD Apartment()
  463. {
  464. CoInitialize(NULL);
  465. HRESULT hRes;
  466. m_spT.Release();
  467. if (m_pStream)
  468. {
  469. hRes = CoGetInterfaceAndReleaseStream(m_pStream, *piid, (void**)&m_spT);
  470. }
  471. while(m_bTimerOn)
  472. {
  473. Sleep(m_dwTimerInterval);
  474. if (!m_bTimerOn)
  475. break;
  476. m_spT->_OnTimer();
  477. }
  478. m_spT.Release();
  479. CoUninitialize();
  480. return 0;
  481. }
  482. // Attributes
  483. public:
  484. DWORD m_dwTimerInterval;
  485. // Implementation
  486. private:
  487. HANDLE m_hThread;
  488. DWORD m_dwThreadID;
  489. LPSTREAM m_pStream;
  490. CComPtr<T> m_spT;
  491. BOOL m_bTimerOn;
  492. };
  493. class CEventBroker;
  494. //////////////////////////////////////////////////////////////////////////////
  495. // CProxyITDCCtlEvents
  496. template <class T>
  497. class CProxyITDCCtlEvents : public IConnectionPointImpl<T, &IID_ITDCCtlEvents, CComDynamicUnkArray>
  498. {
  499. //ITDCCtlEvents : IDispatch
  500. public:
  501. void FireOnReadyStateChanged()
  502. {
  503. T* pT = (T*)this;
  504. pT->Lock();
  505. IUnknown** pp = m_vec.begin();
  506. while (pp < m_vec.end())
  507. {
  508. if (*pp != NULL)
  509. {
  510. DISPPARAMS dispParams;
  511. dispParams.cArgs = 0;
  512. dispParams.cNamedArgs = 0;
  513. dispParams.rgvarg = NULL;
  514. dispParams.rgdispidNamedArgs = NULL;
  515. ITDCCtlEvents* pITDCCtlEvents = reinterpret_cast<ITDCCtlEvents*>(*pp);
  516. pITDCCtlEvents->Invoke(DISPID_READYSTATECHANGE, IID_NULL, CP_ACP, DISPATCH_METHOD, &dispParams,
  517. NULL, NULL, NULL);
  518. }
  519. pp++;
  520. }
  521. pT->Unlock();
  522. return;
  523. }
  524. };
  525. //------------------------------------------------------------------------
  526. //
  527. // Class: CTDCCtl
  528. //
  529. // Synopsis: This is the TabularDataControl COM object.
  530. // It creates a CTDCArr object to manage the control's data.
  531. //
  532. //------------------------------------------------------------------------
  533. class CTDCCtl :
  534. public CComObjectRoot,
  535. public CComCoClass<CTDCCtl, &CLSID_CTDCCtl>,
  536. public CComControl<CTDCCtl>,
  537. public CStockPropImpl<CTDCCtl, ITDCCtl, &IID_ITDCCtl, &LIBID_TDCLib>,
  538. public IProvideClassInfo2Impl<&CLSID_CTDCCtl, &IID_ITDCCtlEvents, &LIBID_TDCLib>,
  539. public IPersistStreamInitImpl<CTDCCtl>,
  540. public IOleControlImpl<CTDCCtl>,
  541. public IOleObjectImpl<CTDCCtl>,
  542. public IOleInPlaceActiveObjectImpl<CTDCCtl>,
  543. public IViewObjectExImpl<CTDCCtl>,
  544. public IOleInPlaceObjectWindowlessImpl<CTDCCtl>,
  545. public IPersistPropertyBagImpl<CTDCCtl>,
  546. public CTimer<CTDCCtl, ITDCCtl, &IID_ITDCCtl>,
  547. public IRunnableObjectImpl<CTDCCtl>,
  548. public IConnectionPointContainerImpl<CTDCCtl>,
  549. public IPropertyNotifySinkCP<CTDCCtl>,
  550. public CProxyITDCCtlEvents<CTDCCtl>
  551. {
  552. public:
  553. CTDCCtl();
  554. ~CTDCCtl();
  555. DECLARE_REGISTRY_RESOURCEID(IDR_TDCCtl)
  556. DECLARE_NOT_AGGREGATABLE(CTDCCtl)
  557. BEGIN_COM_MAP(CTDCCtl)
  558. COM_INTERFACE_ENTRY(IDispatch)
  559. COM_INTERFACE_ENTRY(ITDCCtl)
  560. COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject, IViewObjectEx)
  561. COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject2, IViewObjectEx)
  562. COM_INTERFACE_ENTRY_IMPL(IViewObjectEx)
  563. COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleWindow, IOleInPlaceObjectWindowless)
  564. COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleInPlaceObject, IOleInPlaceObjectWindowless)
  565. COM_INTERFACE_ENTRY_IMPL(IOleInPlaceObjectWindowless)
  566. COM_INTERFACE_ENTRY_IMPL(IOleInPlaceActiveObject)
  567. COM_INTERFACE_ENTRY_IMPL(IOleControl)
  568. COM_INTERFACE_ENTRY_IMPL(IOleObject)
  569. COM_INTERFACE_ENTRY_IMPL(IPersistStreamInit)
  570. COM_INTERFACE_ENTRY(IProvideClassInfo)
  571. COM_INTERFACE_ENTRY(IProvideClassInfo2)
  572. COM_INTERFACE_ENTRY_IMPL(IPersistPropertyBag)
  573. COM_INTERFACE_ENTRY_IMPL(IRunnableObject)
  574. COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
  575. END_COM_MAP()
  576. BEGIN_PROPERTY_MAP(CTDCCtl)
  577. PROP_ENTRY("RowDelim", DISPID_ROWDELIM, CLSID_CTDCCtl)
  578. PROP_ENTRY("FieldDelim", DISPID_FIELDDELIM, CLSID_CTDCCtl)
  579. PROP_ENTRY("TextQualifier", DISPID_TEXTQUALIFIER, CLSID_CTDCCtl)
  580. PROP_ENTRY("EscapeChar", DISPID_ESCAPECHAR, CLSID_CTDCCtl)
  581. PROP_ENTRY("UseHeader", DISPID_USEHEADER, CLSID_CTDCCtl)
  582. PROP_ENTRY("SortAscending", DISPID_SORTASCENDING, CLSID_CTDCCtl)
  583. PROP_ENTRY("SortColumn", DISPID_SORTCOLUMN, CLSID_CTDCCtl)
  584. PROP_ENTRY("FilterValue", DISPID_FILTERVALUE, CLSID_CTDCCtl)
  585. PROP_ENTRY("FilterCriterion", DISPID_FILTERCRITERION, CLSID_CTDCCtl)
  586. PROP_ENTRY("FilterColumn", DISPID_FILTERCOLUMN,CLSID_CTDCCtl)
  587. PROP_ENTRY("CharSet", DISPID_CHARSET, CLSID_CTDCCtl)
  588. PROP_ENTRY("Language", DISPID_LANGUAGE, CLSID_CTDCCtl)
  589. PROP_ENTRY("CaseSensitive", DISPID_CASESENSITIVE, CLSID_CTDCCtl)
  590. PROP_ENTRY("Sort", DISPID_SORT, CLSID_CTDCCtl)
  591. // ;begin_internal
  592. // Doesn't work right yet.
  593. // PROP_ENTRY("RefreshInterval", DISPID_TIMER, CLSID_CTDCCtl)
  594. // ;end_internal
  595. PROP_ENTRY("Filter", DISPID_FILTER, CLSID_CTDCCtl)
  596. PROP_ENTRY("AppendData", DISPID_APPENDDATA, CLSID_CTDCCtl)
  597. // ;begin_internal
  598. // Trying to save this property causes OLEAUT to GP Fault trying
  599. // to conver the IDispatch * to a BSTR!
  600. // PROP_ENTRY("OSP", DISPID_OSP, CLSID_CTDCCtl)
  601. // ;end_internal
  602. // This will be removed when we learn more about the HTML
  603. // sub-tag "OBJECT"
  604. PROP_ENTRY("DataURL", DISPID_DATAURL, CLSID_CTDCCtl)
  605. PROP_ENTRY("ReadyState", DISPID_READYSTATE, CLSID_CTDCCtl)
  606. END_PROPERTY_MAP()
  607. BEGIN_CONNECTION_POINT_MAP(CTDCCtl)
  608. CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
  609. CONNECTION_POINT_ENTRY(IID_ITDCCtlEvents)
  610. END_CONNECTION_POINT_MAP()
  611. BEGIN_MSG_MAP(CTDCCtl)
  612. MESSAGE_HANDLER(WM_PAINT, OnPaint)
  613. MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
  614. MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
  615. MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
  616. END_MSG_MAP()
  617. private:
  618. CComBSTR m_cbstrFieldDelim;
  619. CComBSTR m_cbstrRowDelim;
  620. CComBSTR m_cbstrQuoteChar;
  621. CComBSTR m_cbstrEscapeChar;
  622. BOOL m_fUseHeader;
  623. CComBSTR m_cbstrSortColumn;
  624. BOOL m_fSortAscending;
  625. CComBSTR m_cbstrFilterValue;
  626. OSPCOMP m_enumFilterCriterion;
  627. CComBSTR m_cbstrFilterColumn;
  628. UINT m_nCodePage;
  629. UINT m_nAmbientCodePage;
  630. CComBSTR m_cbstrLanguage;
  631. CComBSTR m_cbstrDataURL;
  632. LCID m_lcidRead;
  633. boolean m_fDataURLChanged;
  634. HRESULT m_hrDownloadStatus;
  635. LONG m_lTimer;
  636. CComBSTR m_cbstrFilterExpr;
  637. CComBSTR m_cbstrSortExpr;
  638. BOOL m_fAppendData;
  639. BOOL m_fCaseSensitive;
  640. boolean m_fInReset;
  641. OLEDBSimpleProvider *m_pSTD;
  642. CTDCArr *m_pArr;
  643. IMultiLanguage *m_pML;
  644. BOOL m_fSecurityChecked;
  645. // ;begin_internal
  646. DATASRCListener *m_pDATASRCListener;
  647. // ;end_internal
  648. DataSourceListener *m_pDataSourceListener;
  649. CEventBroker *m_pEventBroker;
  650. // These member objects are used while parsing the input stream
  651. //
  652. CTDCUnify *m_pUnify;
  653. CComObject<CMyBindStatusCallback<CTDCCtl> > *m_pBSC;
  654. // These members and methods expose the ITDCCtl interface
  655. //
  656. public:
  657. // Control Properties
  658. //
  659. STDMETHOD(get_FieldDelim)(BSTR* pbstrFieldDelim);
  660. STDMETHOD(put_FieldDelim)(BSTR bstrFieldDelim);
  661. STDMETHOD(get_RowDelim)(BSTR* pbstrRowDelim);
  662. STDMETHOD(put_RowDelim)(BSTR bstrRowDelim);
  663. STDMETHOD(get_TextQualifier)(BSTR* pbstrTextQualifier);
  664. STDMETHOD(put_TextQualifier)(BSTR bstrTextQualifier);
  665. STDMETHOD(get_EscapeChar)(BSTR* pbstrEscapeChar);
  666. STDMETHOD(put_EscapeChar)(BSTR bstrEscapeChar);
  667. STDMETHOD(get_UseHeader)(VARIANT_BOOL* pfUseHeader);
  668. STDMETHOD(put_UseHeader)(VARIANT_BOOL fUseHeader);
  669. STDMETHOD(get_SortColumn)(BSTR* pbstrSortColumn);
  670. STDMETHOD(put_SortColumn)(BSTR bstrSortColumn);
  671. STDMETHOD(get_SortAscending)(VARIANT_BOOL* pfSortAscending);
  672. STDMETHOD(put_SortAscending)(VARIANT_BOOL fSortAscending);
  673. STDMETHOD(get_FilterValue)(BSTR* pbstrFilterValue);
  674. STDMETHOD(put_FilterValue)(BSTR bstrFilterValue);
  675. STDMETHOD(get_FilterCriterion)(BSTR* pbstrFilterCriterion);
  676. STDMETHOD(put_FilterCriterion)(BSTR bstrFilterCriterion);
  677. STDMETHOD(get_FilterColumn)(BSTR* pbstrFilterColumn);
  678. STDMETHOD(put_FilterColumn)(BSTR bstrFilterColumn);
  679. STDMETHOD(get_CharSet)(BSTR *pbstrCharSet);
  680. STDMETHOD(put_CharSet)(BSTR bstrCharSet);
  681. STDMETHOD(get_Language)(BSTR* pbstrLanguage);
  682. STDMETHOD(put_Language_)(LPWCH pwchLanguage);
  683. STDMETHOD(put_Language)(BSTR bstrLanguage);
  684. STDMETHOD(get_CaseSensitive)(VARIANT_BOOL *pfCaseSensitive);
  685. STDMETHOD(put_CaseSensitive)(VARIANT_BOOL fCaseSensitive);
  686. STDMETHOD(get_DataURL)(BSTR* pbstrDataURL); //
  687. STDMETHOD(put_DataURL)(BSTR bstrDataURL);
  688. // ;begin_internal
  689. // STDMETHOD(get_RefreshInterval)(LONG* plTimer);
  690. // STDMETHOD(put_RefreshInterval)(LONG lTimer);
  691. // ;end_internal
  692. STDMETHOD(get_Filter)(BSTR* pbstrFilterExpr);
  693. STDMETHOD(put_Filter)(BSTR bstrFilterExpr);
  694. STDMETHOD(get_Sort)(BSTR* pbstrSortExpr);
  695. STDMETHOD(put_Sort)(BSTR bstrSortExpr);
  696. STDMETHOD(get_AppendData)(VARIANT_BOOL* pfAppendData);
  697. STDMETHOD(put_AppendData)(VARIANT_BOOL fAppendData);
  698. STDMETHOD(get_OSP)(OLEDBSimpleProviderX ** ppISTD);
  699. STDMETHOD(get_ReadyState)(LONG *lReadyState);
  700. STDMETHOD(put_ReadyState)(LONG lReadyState);
  701. // Override IPersistPropertyBagImpl::Load
  702. STDMETHOD(Load)(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog);
  703. void UpdateReadyState(LONG lReadyState);
  704. // Data source notification methods
  705. STDMETHOD(msDataSourceObject)(BSTR qualifier, IUnknown **ppUnk);
  706. STDMETHOD(addDataSourceListener)(IUnknown *pEvent);
  707. // Control Methods
  708. //
  709. STDMETHOD(Reset)();
  710. STDMETHOD(_OnTimer)(void);
  711. private:
  712. STDMETHOD(CreateTDCArr)(boolean fAppend);
  713. STDMETHOD(ReleaseTDCArr)(boolean fReplacing);
  714. void LockBSC();
  715. void UnlockBSC();
  716. STDMETHOD(InitiateDataLoad)(boolean fAppend);
  717. STDMETHOD(SecurityCheckDataURL)(LPOLESTR pszURL);
  718. STDMETHOD(SecurityMatchAllowDomainList)();
  719. STDMETHOD(SecurityMatchProtocols)(LPOLESTR pszURL);
  720. STDMETHOD(TerminateDataLoad)(CMyBindStatusCallback<CTDCCtl> *pBSC);
  721. BSTR bstrConstructSortExpr();
  722. BSTR bstrConstructFilterExpr();
  723. protected:
  724. void OnData(CMyBindStatusCallback<CTDCCtl> *pbsc, BYTE *pBytes, DWORD dwSize);
  725. };