//+----------------------------------------------------------------------- // // Tabular Data Control // Copyright (C) Microsoft Corporation, 1996, 1997 // // File: TDCCtl.h // // Contents: Declaration of the CTDCCtl ActiveX Control. // //------------------------------------------------------------------------ #include "resource.h" // main symbols #include #include "wch.h" #include // for INTERNET_MAX_URL_LENGTH #pragma comment(lib, "wininet.lib") #ifndef DISPID_AMBIENT_CODEPAGE #define DISPID_AMBIENT_CODEPAGE (-725) #endif // Declare helper needed in IHttpNegotiateImpl HRESULT GetHostURL(IOleClientSite *pSite, LPOLESTR *ppszHostName); //------------------------------------------------------------------------ // // Template: CMyBindStatusCallback // // Synopsis: This is a temporary kludge to get around an ATL feature // while we're waiting for it to become official code. // //------------------------------------------------------------------------ template class ATL_NO_VTABLE IServiceProviderImpl { public: // IUnknown // STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0; _ATL_DEBUG_ADDREF_RELEASE_IMPL(IServiceProviderImpl) STDMETHOD(QueryService) (REFGUID guidService, REFIID riid, void **ppvObject) { return S_OK; } }; template class ATL_NO_VTABLE IHttpNegotiateImpl { public: // IUnknown // STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0; _ATL_DEBUG_ADDREF_RELEASE_IMPL(IHttpNegotiateImpl) STDMETHOD(BeginningTransaction) (LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) { return S_OK; } STDMETHOD(OnResponse) (DWORD dwResponseCode, LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) { return S_OK; } }; // IE5 85290: mshtml needs a way to recognize the TDC from // its IBindStatusCallback. We define a dummy interface for this. template class ATL_NO_VTABLE IAmTheTDCImpl { public: // IUnknown // STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0; _ATL_DEBUG_ADDREF_RELEASE_IMPL(IAmTheTDCImpl) }; template class ATL_NO_VTABLE CMyBindStatusCallback : public CComObjectRootEx, public IBindStatusCallbackImpl, public IHttpNegotiateImpl, public IServiceProviderImpl, public IAmTheTDCImpl { typedef void (T::*ATL_PDATAAVAILABLE)(CMyBindStatusCallback* pbsc, BYTE* pBytes, DWORD dwSize); public: BEGIN_COM_MAP(CMyBindStatusCallback) COM_INTERFACE_ENTRY_IID(IID_IBindStatusCallback, IBindStatusCallbackImpl) COM_INTERFACE_ENTRY_IID(IID_IHttpNegotiate, IHttpNegotiateImpl) COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProviderImpl) COM_INTERFACE_ENTRY_IID(IID_IAmTheTDC, IAmTheTDCImpl) END_COM_MAP() CMyBindStatusCallback() { m_pT = NULL; m_pFunc = NULL; m_fReload = FALSE; } ~CMyBindStatusCallback() { ATLTRACE(_T("~CMyBindStatusCallback\n")); } // IServiceProvider methods STDMETHOD(QueryService) (REFGUID guidService, REFIID riid, void **ppvObject) { // As it turns out, the service ID for IHttpNegotiate is the same // as it's IID (confusing). This is the only service we support. if (IsEqualGUID(IID_IHttpNegotiate, guidService)) { return ((IHttpNegotiate *)this)->QueryInterface(riid, ppvObject); } else return E_NOTIMPL; } // // IHttpNegotiate methods // STDMETHOD(BeginningTransaction) (LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) { HRESULT hr = S_OK; WCHAR swzHostScheme[INTERNET_MAX_URL_LENGTH]; DWORD cchHostScheme = INTERNET_MAX_URL_LENGTH; WCHAR swzFileScheme[INTERNET_MAX_URL_LENGTH]; DWORD cchFileScheme = INTERNET_MAX_URL_LENGTH; LPOLESTR pszHostName; *pszAdditionalHeaders = NULL; hr = GetHostURL(m_spClientSite, &pszHostName); if (FAILED(hr)) goto Cleanup; // PARSE_SCHEMA didn't work, so we'll just CANONICALIZE and then use the first N // characters of the URL hr = CoInternetParseUrl(pszHostName, PARSE_CANONICALIZE, 0, swzHostScheme, cchHostScheme, &cchHostScheme, 0); if (FAILED(hr)) goto Cleanup; // Don't send a referer which isn't http: or https:, it's none // of the servers' business. Further, don't send an https: // referer when requesting an http: file. if (0 != wch_incmp(swzHostScheme, L"https:", 6) && 0 != wch_incmp(swzHostScheme, L"http:", 5)) goto Cleanup; if (0 == wch_incmp(swzHostScheme, L"https:", 6)) { hr = CoInternetParseUrl(szURL, PARSE_CANONICALIZE, 0, swzFileScheme, cchFileScheme, &cchFileScheme, 0); if (0 == wch_incmp(swzFileScheme, L"http:", 5)) // don't send https: referer goto Cleanup; // to an http: file. } // 3*sizeof(WCHAR) is for CR, LF, & '\0' *pszAdditionalHeaders = (WCHAR *)CoTaskMemAlloc(sizeof(L"Referer: ") + ocslen(pszHostName)*sizeof(WCHAR) + 3*sizeof(WCHAR)); if (NULL != *pszAdditionalHeaders) { ocscpy(*pszAdditionalHeaders, L"Referer: "); ocscpy(&((*pszAdditionalHeaders)[9]), pszHostName); ocscpy(&((*pszAdditionalHeaders)[9+ocslen(pszHostName)]), L"\r\n"); } Cleanup: CoTaskMemFree(pszHostName); return hr; } STDMETHOD(OnResponse) (DWORD dwResponseCode, LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) { return S_OK; } // // IBindStatusCallback methods // STDMETHOD(OnStartBinding)(DWORD dwReserved, IBinding *pBinding) { ATLTRACE(_T("CMyBindStatusCallback::OnStartBinding\n")); m_spBinding = pBinding; return S_OK; } STDMETHOD(GetPriority)(LONG *pnPriority) { ATLTRACENOTIMPL(_T("CMyBindStatusCallback::GetPriority")); } STDMETHOD(OnLowResource)(DWORD reserved) { ATLTRACENOTIMPL(_T("CMyBindStatusCallback::OnLowResource")); } STDMETHOD(OnProgress)(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) { if (BINDSTATUS_REDIRECTING == ulStatusCode && szStatusText != NULL) { ocscpy(m_pszURL, szStatusText); } return S_OK; } STDMETHOD(OnStopBinding)(HRESULT hresult, LPCWSTR szError) { // ATLTRACE(_T("CMyBindStatusCallback::OnStopBinding\n")); (m_pT->*m_pFunc)(this, NULL, 0); if (m_spWinInetFileStream) { m_spWinInetFileStream.Release(); } m_spBinding.Release(); m_spBindCtx.Release(); m_spMoniker.Release(); return S_OK; } STDMETHOD(GetBindInfo)(DWORD *pgrfBINDF, BINDINFO *pbindInfo) { ATLTRACE(_T("CMyBindStatusCallback::GetBindInfo\n")); if (!pbindInfo || !pbindInfo->cbSize || !pgrfBINDF) return E_INVALIDARG; *pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE ; // ;begin_internal #ifdef NEVER // I want DEBUG mode to NOT cache things!! -cfranks *pgrfBINDF |= BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE | BINDF_RESYNCHRONIZE ; #endif // ;end_internal #ifndef DISPID_AMBIENT_OFFLINE #define DISPID_AMBIENT_OFFLINE (-5501) #endif // Get our offline property from container VARIANT var; VariantInit(&var); DWORD dwConnectedStateFlags; m_pT->GetAmbientProperty(DISPID_AMBIENT_OFFLINE, var); if (var.vt==VT_BOOL && var.boolVal) { if (!(InternetGetConnectedState(&dwConnectedStateFlags, 0)) && (0 == (dwConnectedStateFlags & INTERNET_CONNECTION_MODEM_BUSY))) { ATLTRACE(_T("CMyBindStatusCallback::GetBindInfo OFFLINE\n")); // We're not even dialed out to another connectoid *pgrfBINDF |= BINDF_OFFLINEOPERATION; } else { ATLTRACE(_T("CMyBindStatusCallback::GetBindInfo OFFLINE\n")); *pgrfBINDF &= ~BINDF_OFFLINEOPERATION; } } // See if we should force a reload, iff we're not offline. if (!(*pgrfBINDF & BINDF_OFFLINEOPERATION) && m_fReload) { *pgrfBINDF |= BINDF_RESYNCHRONIZE|BINDF_PRAGMA_NO_CACHE; } ULONG cbSize = pbindInfo->cbSize; memset(pbindInfo, 0, cbSize); pbindInfo->cbSize = cbSize; pbindInfo->dwBindVerb = BINDVERB_GET; return S_OK; } STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) { ATLTRACE(_T("CMyBindStatusCallback::OnDataAvailable\n")); HRESULT hr = S_OK; // Get the Stream passed if (BSCF_FIRSTDATANOTIFICATION & grfBSCF) { if (!m_spStream && pstgmed->tymed == TYMED_ISTREAM) { m_spStream = pstgmed->pstm; (void)m_spStream->QueryInterface(IID_IWinInetFileStream, (void **)&m_spWinInetFileStream); if (m_spWinInetFileStream) { CComPtr spWinInetHttpInfo; (void)m_spBinding->QueryInterface(IID_IWinInetHttpInfo, (void **)&spWinInetHttpInfo); if (spWinInetHttpInfo) { HANDLE hWinInetLock = NULL; DWORD dwHandleSize = sizeof(HANDLE); HRESULT hr = spWinInetHttpInfo->QueryOption(WININETINFO_OPTION_LOCK_HANDLE, (LPVOID)&hWinInetLock, &dwHandleSize); if (SUCCEEDED(hr) && hWinInetLock) { m_spWinInetFileStream->SetHandleForUnlock((DWORD_PTR)hWinInetLock, 0); } spWinInetHttpInfo.Release(); } } } } DWORD dwRead = dwSize - m_dwTotalRead; // Minimum amount available that hasn't been read DWORD dwActuallyRead = 0; // Placeholder for amount read during this pull // If there is some data to be read then go ahead and read them if (m_spStream) { if (dwRead > 0) { BYTE* pBytes = NULL; ATLTRY(pBytes = new BYTE[dwRead + 1]); if (pBytes == NULL) return S_FALSE; hr = m_spStream->Read(pBytes, dwRead, &dwActuallyRead); if (SUCCEEDED(hr)) { pBytes[dwActuallyRead] = 0; if (dwActuallyRead>0) { (m_pT->*m_pFunc)(this, pBytes, dwActuallyRead); m_dwTotalRead += dwActuallyRead; } } delete[] pBytes; } } if (BSCF_LASTDATANOTIFICATION & grfBSCF) m_spStream.Release(); return hr; } STDMETHOD(OnObjectAvailable)(REFIID riid, IUnknown *punk) { ATLTRACENOTIMPL(_T("CMyBindStatusCallback::OnObjectAvailable")); } HRESULT _StartAsyncDownload(BSTR bstrURL, IUnknown* pUnkContainer, BOOL bRelative) { m_dwTotalRead = 0; m_dwAvailableToRead = 0; HRESULT hr = S_OK; CComQIPtr spServiceProvider(pUnkContainer); CComPtr spBindHost; CComPtr spStream; if (spServiceProvider) spServiceProvider->QueryService(SID_IBindHost, IID_IBindHost, (void**)&spBindHost); // We don't bother checking this QI, because the only failure mode is that our // BeginningNegotitation method won't be able able to properly add the referer string. (void)pUnkContainer->QueryInterface(IID_IOleClientSite, (void **)&m_spClientSite); if (spBindHost == NULL) { if (bRelative) return E_NOINTERFACE; // relative asked for, but no IBindHost hr = CreateURLMoniker(NULL, bstrURL, &m_spMoniker); if (SUCCEEDED(hr)) hr = CreateBindCtx(0, &m_spBindCtx); if (SUCCEEDED(hr)) hr = RegisterBindStatusCallback(m_spBindCtx, reinterpret_cast(static_cast*>(this)), 0, 0L); else m_spMoniker.Release(); if (SUCCEEDED(hr)) { LPOLESTR pszTemp = NULL; hr = m_spMoniker->GetDisplayName(m_spBindCtx, NULL, &pszTemp); if (!hr && pszTemp != NULL) ocscpy(m_pszURL, pszTemp); CoTaskMemFree(pszTemp); hr = m_spMoniker->BindToStorage(m_spBindCtx, 0, IID_IStream, (void**)&spStream); } } else { hr = CreateBindCtx(0, &m_spBindCtx); if (SUCCEEDED(hr)) hr = RegisterBindStatusCallback(m_spBindCtx, reinterpret_cast(static_cast*>(this)), 0, 0L); if (SUCCEEDED(hr)) { if (bRelative) hr = spBindHost->CreateMoniker(bstrURL, m_spBindCtx, &m_spMoniker, 0); else hr = CreateURLMoniker(NULL, bstrURL, &m_spMoniker); } if (SUCCEEDED(hr)) { LPOLESTR pszTemp = NULL; hr = m_spMoniker->GetDisplayName(m_spBindCtx, NULL, &pszTemp); if (!hr && pszTemp != NULL) ocscpy(m_pszURL, pszTemp); CoTaskMemFree(pszTemp); hr = spBindHost->MonikerBindToStorage(m_spMoniker, NULL, reinterpret_cast(static_cast*>(this)), IID_IStream, (void**)&spStream); ATLTRACE(_T("Bound")); } } return hr; } HRESULT StartAsyncDownload(T* pT, ATL_PDATAAVAILABLE pFunc, BSTR bstrURL, IUnknown* pUnkContainer, BOOL bRelative, BOOL fReload) { m_pT = pT; m_pFunc = pFunc; m_fReload = fReload; // force reload if TRUE return _StartAsyncDownload(bstrURL, pUnkContainer, bRelative); } static HRESULT Download(T* pT, ATL_PDATAAVAILABLE pFunc, BSTR bstrURL, IUnknown* pUnkContainer = NULL, BOOL bRelative = FALSE) { CComObject > *pbsc; HRESULT hRes = CComObject >::CreateInstance(&pbsc); if (FAILED(hRes)) return hRes; return pbsc->StartAsyncDownload(pT, pFunc, bstrURL, pUnkContainer, bRelative, FALSE); } void DeleteDataFile() { // we can't delete the file at the time of the call (it's in use), so // mark it for deletion later - at stream destruction time if (m_spWinInetFileStream) { m_spWinInetFileStream->SetDeleteFile(0); } } CComPtr m_spMoniker; CComPtr m_spBindCtx; CComPtr m_spBinding; CComPtr m_spWinInetFileStream; CComPtr m_spStream; CComPtr m_spClientSite; BOOL m_fReload; OLECHAR m_pszURL[INTERNET_MAX_URL_LENGTH]; T* m_pT; ATL_PDATAAVAILABLE m_pFunc; DWORD m_dwTotalRead; DWORD m_dwAvailableToRead; }; ////////////////////////////////////////////////////////////////////////////////////////////////// // CTimer template class CTimer { public: CTimer() { m_bTimerOn = FALSE; } HRESULT TimerOn(DWORD dwTimerInterval) { Derived* pDerived = ((Derived*)this); m_dwTimerInterval = dwTimerInterval; if (m_bTimerOn) // already on, just change interval return S_OK; m_bTimerOn = TRUE; m_dwTimerInterval = dwTimerInterval; m_pStream = NULL; HRESULT hRes; hRes = CoMarshalInterThreadInterfaceInStream(*piid, (T*)pDerived, &m_pStream); // Create thread and pass the thread proc the this ptr m_hThread = CreateThread(NULL, 0, &_Apartment, (void*)this, 0, &m_dwThreadID); return S_OK; } void TimerOff() { if (m_bTimerOn) { m_bTimerOn = FALSE; AtlWaitWithMessageLoop(m_hThread); } } // Implementation private: static DWORD WINAPI _Apartment(void* pv) { CTimer* pThis = (CTimer*) pv; pThis->Apartment(); return 0; } DWORD Apartment() { CoInitialize(NULL); HRESULT hRes; m_spT.Release(); if (m_pStream) { hRes = CoGetInterfaceAndReleaseStream(m_pStream, *piid, (void**)&m_spT); } while(m_bTimerOn) { Sleep(m_dwTimerInterval); if (!m_bTimerOn) break; m_spT->_OnTimer(); } m_spT.Release(); CoUninitialize(); return 0; } // Attributes public: DWORD m_dwTimerInterval; // Implementation private: HANDLE m_hThread; DWORD m_dwThreadID; LPSTREAM m_pStream; CComPtr m_spT; BOOL m_bTimerOn; }; class CEventBroker; ////////////////////////////////////////////////////////////////////////////// // CProxyITDCCtlEvents template class CProxyITDCCtlEvents : public IConnectionPointImpl { //ITDCCtlEvents : IDispatch public: void FireOnReadyStateChanged() { T* pT = (T*)this; pT->Lock(); IUnknown** pp = m_vec.begin(); while (pp < m_vec.end()) { if (*pp != NULL) { DISPPARAMS dispParams; dispParams.cArgs = 0; dispParams.cNamedArgs = 0; dispParams.rgvarg = NULL; dispParams.rgdispidNamedArgs = NULL; ITDCCtlEvents* pITDCCtlEvents = reinterpret_cast(*pp); pITDCCtlEvents->Invoke(DISPID_READYSTATECHANGE, IID_NULL, CP_ACP, DISPATCH_METHOD, &dispParams, NULL, NULL, NULL); } pp++; } pT->Unlock(); return; } }; //------------------------------------------------------------------------ // // Class: CTDCCtl // // Synopsis: This is the TabularDataControl COM object. // It creates a CTDCArr object to manage the control's data. // //------------------------------------------------------------------------ class CTDCCtl : public CComObjectRoot, public CComCoClass, public CComControl, public CStockPropImpl, public IProvideClassInfo2Impl<&CLSID_CTDCCtl, &IID_ITDCCtlEvents, &LIBID_TDCLib>, public IPersistStreamInitImpl, public IOleControlImpl, public IOleObjectImpl, public IOleInPlaceActiveObjectImpl, public IViewObjectExImpl, public IOleInPlaceObjectWindowlessImpl, public IPersistPropertyBagImpl, public CTimer, public IRunnableObjectImpl, public IConnectionPointContainerImpl, public IPropertyNotifySinkCP, public CProxyITDCCtlEvents { public: CTDCCtl(); ~CTDCCtl(); DECLARE_REGISTRY_RESOURCEID(IDR_TDCCtl) DECLARE_NOT_AGGREGATABLE(CTDCCtl) BEGIN_COM_MAP(CTDCCtl) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITDCCtl) COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject, IViewObjectEx) COM_INTERFACE_ENTRY_IMPL_IID(IID_IViewObject2, IViewObjectEx) COM_INTERFACE_ENTRY_IMPL(IViewObjectEx) COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleWindow, IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY_IMPL_IID(IID_IOleInPlaceObject, IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY_IMPL(IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY_IMPL(IOleInPlaceActiveObject) COM_INTERFACE_ENTRY_IMPL(IOleControl) COM_INTERFACE_ENTRY_IMPL(IOleObject) COM_INTERFACE_ENTRY_IMPL(IPersistStreamInit) COM_INTERFACE_ENTRY(IProvideClassInfo) COM_INTERFACE_ENTRY(IProvideClassInfo2) COM_INTERFACE_ENTRY_IMPL(IPersistPropertyBag) COM_INTERFACE_ENTRY_IMPL(IRunnableObject) COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer) END_COM_MAP() BEGIN_PROPERTY_MAP(CTDCCtl) PROP_ENTRY("RowDelim", DISPID_ROWDELIM, CLSID_CTDCCtl) PROP_ENTRY("FieldDelim", DISPID_FIELDDELIM, CLSID_CTDCCtl) PROP_ENTRY("TextQualifier", DISPID_TEXTQUALIFIER, CLSID_CTDCCtl) PROP_ENTRY("EscapeChar", DISPID_ESCAPECHAR, CLSID_CTDCCtl) PROP_ENTRY("UseHeader", DISPID_USEHEADER, CLSID_CTDCCtl) PROP_ENTRY("SortAscending", DISPID_SORTASCENDING, CLSID_CTDCCtl) PROP_ENTRY("SortColumn", DISPID_SORTCOLUMN, CLSID_CTDCCtl) PROP_ENTRY("FilterValue", DISPID_FILTERVALUE, CLSID_CTDCCtl) PROP_ENTRY("FilterCriterion", DISPID_FILTERCRITERION, CLSID_CTDCCtl) PROP_ENTRY("FilterColumn", DISPID_FILTERCOLUMN,CLSID_CTDCCtl) PROP_ENTRY("CharSet", DISPID_CHARSET, CLSID_CTDCCtl) PROP_ENTRY("Language", DISPID_LANGUAGE, CLSID_CTDCCtl) PROP_ENTRY("CaseSensitive", DISPID_CASESENSITIVE, CLSID_CTDCCtl) PROP_ENTRY("Sort", DISPID_SORT, CLSID_CTDCCtl) // ;begin_internal // Doesn't work right yet. // PROP_ENTRY("RefreshInterval", DISPID_TIMER, CLSID_CTDCCtl) // ;end_internal PROP_ENTRY("Filter", DISPID_FILTER, CLSID_CTDCCtl) PROP_ENTRY("AppendData", DISPID_APPENDDATA, CLSID_CTDCCtl) // ;begin_internal // Trying to save this property causes OLEAUT to GP Fault trying // to conver the IDispatch * to a BSTR! // PROP_ENTRY("OSP", DISPID_OSP, CLSID_CTDCCtl) // ;end_internal // This will be removed when we learn more about the HTML // sub-tag "OBJECT" PROP_ENTRY("DataURL", DISPID_DATAURL, CLSID_CTDCCtl) PROP_ENTRY("ReadyState", DISPID_READYSTATE, CLSID_CTDCCtl) END_PROPERTY_MAP() BEGIN_CONNECTION_POINT_MAP(CTDCCtl) CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink) CONNECTION_POINT_ENTRY(IID_ITDCCtlEvents) END_CONNECTION_POINT_MAP() BEGIN_MSG_MAP(CTDCCtl) MESSAGE_HANDLER(WM_PAINT, OnPaint) MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode) MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) END_MSG_MAP() private: CComBSTR m_cbstrFieldDelim; CComBSTR m_cbstrRowDelim; CComBSTR m_cbstrQuoteChar; CComBSTR m_cbstrEscapeChar; BOOL m_fUseHeader; CComBSTR m_cbstrSortColumn; BOOL m_fSortAscending; CComBSTR m_cbstrFilterValue; OSPCOMP m_enumFilterCriterion; CComBSTR m_cbstrFilterColumn; UINT m_nCodePage; UINT m_nAmbientCodePage; CComBSTR m_cbstrLanguage; CComBSTR m_cbstrDataURL; LCID m_lcidRead; boolean m_fDataURLChanged; HRESULT m_hrDownloadStatus; LONG m_lTimer; CComBSTR m_cbstrFilterExpr; CComBSTR m_cbstrSortExpr; BOOL m_fAppendData; BOOL m_fCaseSensitive; boolean m_fInReset; OLEDBSimpleProvider *m_pSTD; CTDCArr *m_pArr; IMultiLanguage *m_pML; BOOL m_fSecurityChecked; // ;begin_internal DATASRCListener *m_pDATASRCListener; // ;end_internal DataSourceListener *m_pDataSourceListener; CEventBroker *m_pEventBroker; // These member objects are used while parsing the input stream // CTDCUnify *m_pUnify; CComObject > *m_pBSC; // These members and methods expose the ITDCCtl interface // public: // Control Properties // STDMETHOD(get_FieldDelim)(BSTR* pbstrFieldDelim); STDMETHOD(put_FieldDelim)(BSTR bstrFieldDelim); STDMETHOD(get_RowDelim)(BSTR* pbstrRowDelim); STDMETHOD(put_RowDelim)(BSTR bstrRowDelim); STDMETHOD(get_TextQualifier)(BSTR* pbstrTextQualifier); STDMETHOD(put_TextQualifier)(BSTR bstrTextQualifier); STDMETHOD(get_EscapeChar)(BSTR* pbstrEscapeChar); STDMETHOD(put_EscapeChar)(BSTR bstrEscapeChar); STDMETHOD(get_UseHeader)(VARIANT_BOOL* pfUseHeader); STDMETHOD(put_UseHeader)(VARIANT_BOOL fUseHeader); STDMETHOD(get_SortColumn)(BSTR* pbstrSortColumn); STDMETHOD(put_SortColumn)(BSTR bstrSortColumn); STDMETHOD(get_SortAscending)(VARIANT_BOOL* pfSortAscending); STDMETHOD(put_SortAscending)(VARIANT_BOOL fSortAscending); STDMETHOD(get_FilterValue)(BSTR* pbstrFilterValue); STDMETHOD(put_FilterValue)(BSTR bstrFilterValue); STDMETHOD(get_FilterCriterion)(BSTR* pbstrFilterCriterion); STDMETHOD(put_FilterCriterion)(BSTR bstrFilterCriterion); STDMETHOD(get_FilterColumn)(BSTR* pbstrFilterColumn); STDMETHOD(put_FilterColumn)(BSTR bstrFilterColumn); STDMETHOD(get_CharSet)(BSTR *pbstrCharSet); STDMETHOD(put_CharSet)(BSTR bstrCharSet); STDMETHOD(get_Language)(BSTR* pbstrLanguage); STDMETHOD(put_Language_)(LPWCH pwchLanguage); STDMETHOD(put_Language)(BSTR bstrLanguage); STDMETHOD(get_CaseSensitive)(VARIANT_BOOL *pfCaseSensitive); STDMETHOD(put_CaseSensitive)(VARIANT_BOOL fCaseSensitive); STDMETHOD(get_DataURL)(BSTR* pbstrDataURL); // STDMETHOD(put_DataURL)(BSTR bstrDataURL); // ;begin_internal // STDMETHOD(get_RefreshInterval)(LONG* plTimer); // STDMETHOD(put_RefreshInterval)(LONG lTimer); // ;end_internal STDMETHOD(get_Filter)(BSTR* pbstrFilterExpr); STDMETHOD(put_Filter)(BSTR bstrFilterExpr); STDMETHOD(get_Sort)(BSTR* pbstrSortExpr); STDMETHOD(put_Sort)(BSTR bstrSortExpr); STDMETHOD(get_AppendData)(VARIANT_BOOL* pfAppendData); STDMETHOD(put_AppendData)(VARIANT_BOOL fAppendData); STDMETHOD(get_OSP)(OLEDBSimpleProviderX ** ppISTD); STDMETHOD(get_ReadyState)(LONG *lReadyState); STDMETHOD(put_ReadyState)(LONG lReadyState); // Override IPersistPropertyBagImpl::Load STDMETHOD(Load)(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog); void UpdateReadyState(LONG lReadyState); // Data source notification methods STDMETHOD(msDataSourceObject)(BSTR qualifier, IUnknown **ppUnk); STDMETHOD(addDataSourceListener)(IUnknown *pEvent); // Control Methods // STDMETHOD(Reset)(); STDMETHOD(_OnTimer)(void); private: STDMETHOD(CreateTDCArr)(boolean fAppend); STDMETHOD(ReleaseTDCArr)(boolean fReplacing); void LockBSC(); void UnlockBSC(); STDMETHOD(InitiateDataLoad)(boolean fAppend); STDMETHOD(SecurityCheckDataURL)(LPOLESTR pszURL); STDMETHOD(SecurityMatchAllowDomainList)(); STDMETHOD(SecurityMatchProtocols)(LPOLESTR pszURL); STDMETHOD(TerminateDataLoad)(CMyBindStatusCallback *pBSC); BSTR bstrConstructSortExpr(); BSTR bstrConstructFilterExpr(); protected: void OnData(CMyBindStatusCallback *pbsc, BYTE *pBytes, DWORD dwSize); };