// webgate.cpp : Implementation of CWebGate #include "stdafx.h" #include "icwhelp.h" #include "webgate.h" #include "appdefs.h" #include #define MAX_DOWNLOAD_BLOCK 1024 extern BOOL MinimizeRNAWindowEx(); // =========================================================================== // CWebGateBindStatusCallback Definition // // This class will be use to indicate download progress // // =========================================================================== class CWebGateBindStatusCallback : public IBindStatusCallback { public: // IUnknown methods STDMETHODIMP QueryInterface(REFIID riid,void ** ppv); STDMETHODIMP_(ULONG) AddRef() { return m_cRef++; } STDMETHODIMP_(ULONG) Release() { if (--m_cRef == 0) { delete this; return 0; } return m_cRef; } // IBindStatusCallback methods STDMETHODIMP OnStartBinding(DWORD dwReserved, IBinding* pbinding); STDMETHODIMP GetPriority(LONG* pnPriority); STDMETHODIMP OnLowResource(DWORD dwReserved); STDMETHODIMP OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR pwzStatusText); STDMETHODIMP OnStopBinding(HRESULT hrResult, LPCWSTR szError); STDMETHODIMP GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo); STDMETHODIMP OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pfmtetc, STGMEDIUM* pstgmed); STDMETHODIMP OnObjectAvailable(REFIID riid, IUnknown* punk); // constructors/destructors CWebGateBindStatusCallback(CWebGate * lpWebGate); ~CWebGateBindStatusCallback(); // data members BOOL m_bDoneNotification; DWORD m_cRef; IBinding* m_pbinding; IStream* m_pstm; DWORD m_cbOld; CWebGate *m_lpWebGate; private: void ProcessBuffer(void); }; UINT g_nICWFileCount = 0; BOOL CALLBACK DisconnectDlgProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); VOID CALLBACK IdleTimerProc (HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime); // =========================================================================== // CBindStatusCallback Implementation // =========================================================================== // --------------------------------------------------------------------------- // %%Function: CBindStatusCallback::CBindStatusCallback // --------------------------------------------------------------------------- CWebGateBindStatusCallback::CWebGateBindStatusCallback ( CWebGate *lpWebGate ) { m_pbinding = NULL; m_pstm = NULL; m_cRef = 1; m_cbOld = 0; m_lpWebGate = lpWebGate; } // CWebGateBindStatusCallback // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::~CWebGateBindStatusCallback // --------------------------------------------------------------------------- CWebGateBindStatusCallback::~CWebGateBindStatusCallback() { } // ~CWebGateBindStatusCallback // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::QueryInterface // --------------------------------------------------------------------------- STDMETHODIMP CWebGateBindStatusCallback::QueryInterface ( REFIID riid, void** ppv ) { *ppv = NULL; if (riid==IID_IUnknown || riid==IID_IBindStatusCallback) { *ppv = this; AddRef(); return S_OK; } return E_NOINTERFACE; } // CWebGateBindStatusCallback::QueryInterface // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::OnStartBinding // --------------------------------------------------------------------------- STDMETHODIMP CWebGateBindStatusCallback::OnStartBinding ( DWORD dwReserved, IBinding* pbinding ) { if (m_pbinding != NULL) m_pbinding->Release(); m_pbinding = pbinding; if (m_pbinding != NULL) { m_pbinding->AddRef(); } return S_OK; } // CWebGateBindStatusCallback::OnStartBinding // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::GetPriority // --------------------------------------------------------------------------- STDMETHODIMP CWebGateBindStatusCallback::GetPriority ( LONG* pnPriority ) { return E_NOTIMPL; } // CWebGateBindStatusCallback::GetPriority // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::OnLowResource // --------------------------------------------------------------------------- STDMETHODIMP CWebGateBindStatusCallback::OnLowResource ( DWORD dwReserved ) { return E_NOTIMPL; } // CWebGateBindStatusCallback::OnLowResource // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::OnProgress // --------------------------------------------------------------------------- STDMETHODIMP CWebGateBindStatusCallback::OnProgress ( ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText ) { // If no progress, check for valid connection if (0 == ulProgress) m_lpWebGate->Fire_WebGateDownloadProgress(TRUE); return(NOERROR); } // CWebGateBindStatusCallback::OnProgress void CWebGateBindStatusCallback::ProcessBuffer(void) { m_bDoneNotification = TRUE; if (m_pstm) m_pstm->Release(); m_lpWebGate->m_cbBuffer = m_cbOld; // Create a file, and copy the donwloaded content into it if (m_lpWebGate->m_bKeepFile) { TCHAR szTempFileFullName[MAX_PATH]; TCHAR szTempFileName[MAX_PATH]; HANDLE hFile; DWORD cbRet; // Make sure it is an htm extension, otherwise, IE will promp for download GetTempPath(MAX_PATH, szTempFileFullName); wsprintf( szTempFileName, TEXT("ICW%x.htm"), g_nICWFileCount++); lstrcat(szTempFileFullName, szTempFileName); hFile = CreateFile(szTempFileFullName, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile) { WriteFile(hFile, m_lpWebGate->m_lpdata, m_cbOld, (LPDWORD)&cbRet, NULL); CloseHandle(hFile); } // Copy the created file name into the webgate control m_lpWebGate->m_bstrCacheFileName = A2BSTR(szTempFileFullName); } // If the WebGate object has a complete event, then signal it, otherwise // fire an event if (m_lpWebGate->m_hEventComplete) SetEvent(m_lpWebGate->m_hEventComplete); else { // Notify the caller that we are done m_lpWebGate->Fire_WebGateDownloadComplete(TRUE); } } // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::OnStopBinding // --------------------------------------------------------------------------- STDMETHODIMP CWebGateBindStatusCallback::OnStopBinding ( HRESULT hrStatus, LPCWSTR pszError ) { if (m_pbinding) { m_pbinding->Release(); m_pbinding = NULL; } if (!m_bDoneNotification) { ProcessBuffer(); } m_lpWebGate->Fire_WebGateDownloadProgress(TRUE); return S_OK; } // CWebGateBindStatusCallback::OnStopBinding // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::GetBindInfo // --------------------------------------------------------------------------- STDMETHODIMP CWebGateBindStatusCallback::GetBindInfo ( DWORD* pgrfBINDF, BINDINFO* pbindInfo ) { *pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA | BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE; pbindInfo->cbSize = sizeof(BINDINFO); pbindInfo->szExtraInfo = NULL; memset(&pbindInfo->stgmedData, 0, sizeof(STGMEDIUM)); pbindInfo->grfBindInfoF = 0; pbindInfo->dwBindVerb = BINDVERB_GET; pbindInfo->szCustomVerb = NULL; return S_OK; } // CWebGateBindStatusCallback::GetBindInfo // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::OnDataAvailable // --------------------------------------------------------------------------- STDMETHODIMP CWebGateBindStatusCallback::OnDataAvailable ( DWORD grfBSCF, DWORD dwSize, FORMATETC* pfmtetc, STGMEDIUM* pstgmed ) { HRESULT hr = E_FAIL; //don't assume success // verify we have a read buffer if (!m_lpWebGate->m_lpdata) return(S_FALSE); // Get the Stream passed if (BSCF_FIRSTDATANOTIFICATION & grfBSCF) { m_bDoneNotification = FALSE; if (!m_pstm && pstgmed->tymed == TYMED_ISTREAM) { m_pstm = pstgmed->pstm; if (m_pstm) m_pstm->AddRef(); } } // If there is some data to be read then go ahead and read them if (m_pstm && dwSize) { DWORD dwActuallyRead = 0; // Placeholder for amount read during this pull do { if (MAX_DOWNLOAD_BLOCK + m_cbOld > m_lpWebGate->m_cbdata) { m_lpWebGate->m_cbdata += READ_BUFFER_SIZE; // ::MessageBox(NULL, TEXT("reallov DumpBufferToFile"), TEXT("E R R O R"), MB_OK); LPSTR pBuffer = (LPSTR)GlobalReAllocPtr(m_lpWebGate->m_lpdata, m_lpWebGate->m_cbdata , GHND); if (pBuffer) m_lpWebGate->m_lpdata = pBuffer; else return S_FALSE; } // Read what we can hr = m_pstm->Read(m_lpWebGate->m_lpdata+m_cbOld, MAX_DOWNLOAD_BLOCK, &dwActuallyRead); // keep track of the running total m_cbOld += dwActuallyRead; } while (hr == E_PENDING || hr != S_FALSE); } if (BSCF_LASTDATANOTIFICATION & grfBSCF) { if (!m_bDoneNotification) { ProcessBuffer(); } } return S_OK; } // CWebGateBindStatusCallback::OnDataAvailable // --------------------------------------------------------------------------- // %%Function: CWebGateBindStatusCallback::OnObjectAvailable // --------------------------------------------------------------------------- STDMETHODIMP CWebGateBindStatusCallback::OnObjectAvailable ( REFIID riid, IUnknown* punk ) { return E_NOTIMPL; } // CWebGateBindStatusCallback::OnObjectAvailable ///////////////////////////////////////////////////////////////////////////// // CWebGate HRESULT CWebGate::OnDraw(ATL_DRAWINFO& di) { return S_OK; } STDMETHODIMP CWebGate::put_Path(BSTR newVal) { // TODO: Add your implementation code here USES_CONVERSION; m_bstrPath = newVal; return S_OK; } STDMETHODIMP CWebGate::put_FormData(BSTR newVal) { // TODO: Add your implementation code here USES_CONVERSION; m_bstrFormData = newVal; return S_OK; } STDMETHODIMP CWebGate::FetchPage(DWORD dwKeepFile, DWORD dwDoWait, BOOL *pbRetVal) { USES_CONVERSION; IStream *pstm = NULL; HRESULT hr; // Empty the buffer. m_bstrBuffer.Empty(); // Clear the cache file name m_bstrCacheFileName.Empty(); // Release the binding context callback if (m_pbsc && m_pbc) { RevokeBindStatusCallback(m_pbc, m_pbsc); m_pbsc->Release(); m_pbsc = 0; } // Release the binding context if (m_pbc) { m_pbc->Release(); m_pbc = 0; } // release the monikor if (m_pmk) { m_pmk->Release(); m_pmk = 0; } *pbRetVal = FALSE; if (dwDoWait) m_hEventComplete = CreateEvent(NULL, TRUE, FALSE, NULL); m_bKeepFile = (BOOL) dwKeepFile; hr = CreateURLMoniker(NULL, m_bstrPath, &m_pmk); if (FAILED(hr)) goto LErrExit; m_pbsc = new CWebGateBindStatusCallback(this); if (m_pbsc == NULL) { hr = E_OUTOFMEMORY; goto LErrExit; } hr = CreateBindCtx(0, &m_pbc); if (FAILED(hr)) goto LErrExit; hr = RegisterBindStatusCallback(m_pbc, m_pbsc, 0, 0L); if (FAILED(hr)) goto LErrExit; hr = m_pmk->BindToStorage(m_pbc, 0, IID_IStream, (void**)&pstm); if (FAILED(hr)) goto LErrExit; // If we were requested to wait, then we wait for the m_hEventComplete to be // signaled if (dwDoWait && m_hEventComplete) { MSG msg; BOOL bGotFile = FALSE; DWORD dwRetCode; HANDLE hEventList[1]; hEventList[0] = m_hEventComplete; while (TRUE) { // We will wait on window messages and also the named event. dwRetCode = MsgWaitForMultipleObjects(1, &hEventList[0], FALSE, 300000, // 5 minutes QS_ALLINPUT); // Determine why we came out of MsgWaitForMultipleObjects(). If // we timed out then let's do some TrialWatcher work. Otherwise // process the message that woke us up. if (WAIT_TIMEOUT == dwRetCode) { bGotFile = FALSE; break; } else if (WAIT_OBJECT_0 == dwRetCode) { bGotFile = TRUE; break; } else if (WAIT_OBJECT_0 + 1 == dwRetCode) { // 0 is returned if no message retrieved. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (WM_QUIT == msg.message) { bGotFile = FALSE; break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } } } *pbRetVal = bGotFile; CloseHandle(m_hEventComplete); m_hEventComplete = 0; } else { *pbRetVal = TRUE; } return S_OK; LErrExit: if (m_pbc != NULL) { m_pbc->Release(); m_pbc = NULL; } if (m_pbsc != NULL) { m_pbsc->Release(); m_pbsc = NULL; } if (m_pmk != NULL) { m_pmk->Release(); m_pmk = NULL; } if (pstm) { pstm->Release(); pstm = NULL; } *pbRetVal = FALSE; return S_OK; } STDMETHODIMP CWebGate::get_Buffer(BSTR * pVal) { if (pVal == NULL) return E_POINTER; *pVal = m_bstrBuffer.Copy(); return S_OK; } STDMETHODIMP CWebGate::DumpBufferToFile(BSTR *pFileName, BOOL *pbRetVal) { USES_CONVERSION; TCHAR szTempFileFullName[MAX_PATH]; TCHAR szTempFileName[MAX_PATH]; DWORD cbRet; HANDLE hFile; if (pFileName == NULL) return(E_POINTER); // Delete the previous temp file it it exists if (m_bstrDumpFileName) { DeleteFile(OLE2A(m_bstrDumpFileName)); m_bstrDumpFileName.Empty(); } // Make sure it is an htm extension, otherwise, IE will promp for download GetTempPath(MAX_PATH, szTempFileFullName); wsprintf( szTempFileName, TEXT("ICW%x.htm"), g_nICWFileCount++); lstrcat(szTempFileFullName, szTempFileName); hFile = CreateFile(szTempFileFullName, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile) { WriteFile(hFile, m_lpdata, m_cbBuffer, (LPDWORD)&cbRet, NULL); CloseHandle(hFile); } // Copy the created file name into the webgate control m_bstrDumpFileName = A2BSTR(szTempFileFullName); *pFileName = m_bstrDumpFileName.Copy(); *pbRetVal = TRUE; MinimizeRNAWindowEx(); return S_OK; } STDMETHODIMP CWebGate::get_DownloadFname(BSTR *pVal) { if (pVal == NULL) return(E_POINTER); *pVal = m_bstrCacheFileName.Copy(); return(S_OK); }