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.

591 lines
17 KiB

  1. // webgate.cpp : Implementation of CWebGate
  2. #include "stdafx.h"
  3. #include "icwhelp.h"
  4. #include "webgate.h"
  5. #include "appdefs.h"
  6. #include <wininet.h>
  7. #define MAX_DOWNLOAD_BLOCK 1024
  8. extern BOOL MinimizeRNAWindowEx();
  9. // ===========================================================================
  10. // CWebGateBindStatusCallback Definition
  11. //
  12. // This class will be use to indicate download progress
  13. //
  14. // ===========================================================================
  15. class CWebGateBindStatusCallback : public IBindStatusCallback
  16. {
  17. public:
  18. // IUnknown methods
  19. STDMETHODIMP QueryInterface(REFIID riid,void ** ppv);
  20. STDMETHODIMP_(ULONG) AddRef() { return m_cRef++; }
  21. STDMETHODIMP_(ULONG) Release() { if (--m_cRef == 0) { delete this; return 0; } return m_cRef; }
  22. // IBindStatusCallback methods
  23. STDMETHODIMP OnStartBinding(DWORD dwReserved, IBinding* pbinding);
  24. STDMETHODIMP GetPriority(LONG* pnPriority);
  25. STDMETHODIMP OnLowResource(DWORD dwReserved);
  26. STDMETHODIMP OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode,
  27. LPCWSTR pwzStatusText);
  28. STDMETHODIMP OnStopBinding(HRESULT hrResult, LPCWSTR szError);
  29. STDMETHODIMP GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo);
  30. STDMETHODIMP OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pfmtetc,
  31. STGMEDIUM* pstgmed);
  32. STDMETHODIMP OnObjectAvailable(REFIID riid, IUnknown* punk);
  33. // constructors/destructors
  34. CWebGateBindStatusCallback(CWebGate * lpWebGate);
  35. ~CWebGateBindStatusCallback();
  36. // data members
  37. BOOL m_bDoneNotification;
  38. DWORD m_cRef;
  39. IBinding* m_pbinding;
  40. IStream* m_pstm;
  41. DWORD m_cbOld;
  42. CWebGate *m_lpWebGate;
  43. private:
  44. void ProcessBuffer(void);
  45. };
  46. UINT g_nICWFileCount = 0;
  47. BOOL CALLBACK DisconnectDlgProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  48. VOID CALLBACK IdleTimerProc (HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  49. // ===========================================================================
  50. // CBindStatusCallback Implementation
  51. // ===========================================================================
  52. // ---------------------------------------------------------------------------
  53. // %%Function: CBindStatusCallback::CBindStatusCallback
  54. // ---------------------------------------------------------------------------
  55. CWebGateBindStatusCallback::CWebGateBindStatusCallback
  56. (
  57. CWebGate *lpWebGate
  58. )
  59. {
  60. m_pbinding = NULL;
  61. m_pstm = NULL;
  62. m_cRef = 1;
  63. m_cbOld = 0;
  64. m_lpWebGate = lpWebGate;
  65. } // CWebGateBindStatusCallback
  66. // ---------------------------------------------------------------------------
  67. // %%Function: CWebGateBindStatusCallback::~CWebGateBindStatusCallback
  68. // ---------------------------------------------------------------------------
  69. CWebGateBindStatusCallback::~CWebGateBindStatusCallback()
  70. {
  71. } // ~CWebGateBindStatusCallback
  72. // ---------------------------------------------------------------------------
  73. // %%Function: CWebGateBindStatusCallback::QueryInterface
  74. // ---------------------------------------------------------------------------
  75. STDMETHODIMP CWebGateBindStatusCallback::QueryInterface
  76. (
  77. REFIID riid,
  78. void** ppv
  79. )
  80. {
  81. *ppv = NULL;
  82. if (riid==IID_IUnknown || riid==IID_IBindStatusCallback)
  83. {
  84. *ppv = this;
  85. AddRef();
  86. return S_OK;
  87. }
  88. return E_NOINTERFACE;
  89. } // CWebGateBindStatusCallback::QueryInterface
  90. // ---------------------------------------------------------------------------
  91. // %%Function: CWebGateBindStatusCallback::OnStartBinding
  92. // ---------------------------------------------------------------------------
  93. STDMETHODIMP CWebGateBindStatusCallback::OnStartBinding
  94. (
  95. DWORD dwReserved,
  96. IBinding* pbinding
  97. )
  98. {
  99. if (m_pbinding != NULL)
  100. m_pbinding->Release();
  101. m_pbinding = pbinding;
  102. if (m_pbinding != NULL)
  103. {
  104. m_pbinding->AddRef();
  105. }
  106. return S_OK;
  107. } // CWebGateBindStatusCallback::OnStartBinding
  108. // ---------------------------------------------------------------------------
  109. // %%Function: CWebGateBindStatusCallback::GetPriority
  110. // ---------------------------------------------------------------------------
  111. STDMETHODIMP CWebGateBindStatusCallback::GetPriority
  112. (
  113. LONG* pnPriority
  114. )
  115. {
  116. return E_NOTIMPL;
  117. } // CWebGateBindStatusCallback::GetPriority
  118. // ---------------------------------------------------------------------------
  119. // %%Function: CWebGateBindStatusCallback::OnLowResource
  120. // ---------------------------------------------------------------------------
  121. STDMETHODIMP CWebGateBindStatusCallback::OnLowResource
  122. (
  123. DWORD dwReserved
  124. )
  125. {
  126. return E_NOTIMPL;
  127. } // CWebGateBindStatusCallback::OnLowResource
  128. // ---------------------------------------------------------------------------
  129. // %%Function: CWebGateBindStatusCallback::OnProgress
  130. // ---------------------------------------------------------------------------
  131. STDMETHODIMP CWebGateBindStatusCallback::OnProgress
  132. (
  133. ULONG ulProgress,
  134. ULONG ulProgressMax,
  135. ULONG ulStatusCode,
  136. LPCWSTR szStatusText
  137. )
  138. {
  139. // If no progress, check for valid connection
  140. if (0 == ulProgress)
  141. m_lpWebGate->Fire_WebGateDownloadProgress(TRUE);
  142. return(NOERROR);
  143. } // CWebGateBindStatusCallback::OnProgress
  144. void CWebGateBindStatusCallback::ProcessBuffer(void)
  145. {
  146. m_bDoneNotification = TRUE;
  147. if (m_pstm)
  148. m_pstm->Release();
  149. m_lpWebGate->m_cbBuffer = m_cbOld;
  150. // Create a file, and copy the donwloaded content into it
  151. if (m_lpWebGate->m_bKeepFile)
  152. {
  153. TCHAR szTempFileFullName[MAX_PATH];
  154. TCHAR szTempFileName[MAX_PATH];
  155. HANDLE hFile;
  156. DWORD cbRet;
  157. // Make sure it is an htm extension, otherwise, IE will promp for download
  158. GetTempPath(MAX_PATH, szTempFileFullName);
  159. wsprintf( szTempFileName, TEXT("ICW%x.htm"), g_nICWFileCount++);
  160. lstrcat(szTempFileFullName, szTempFileName);
  161. hFile = CreateFile(szTempFileFullName,
  162. GENERIC_WRITE,
  163. 0,
  164. NULL,
  165. OPEN_ALWAYS,
  166. FILE_ATTRIBUTE_NORMAL,
  167. NULL);
  168. if (hFile)
  169. {
  170. WriteFile(hFile, m_lpWebGate->m_lpdata, m_cbOld, (LPDWORD)&cbRet, NULL);
  171. CloseHandle(hFile);
  172. }
  173. // Copy the created file name into the webgate control
  174. m_lpWebGate->m_bstrCacheFileName = A2BSTR(szTempFileFullName);
  175. }
  176. // If the WebGate object has a complete event, then signal it, otherwise
  177. // fire an event
  178. if (m_lpWebGate->m_hEventComplete)
  179. SetEvent(m_lpWebGate->m_hEventComplete);
  180. else
  181. {
  182. // Notify the caller that we are done
  183. m_lpWebGate->Fire_WebGateDownloadComplete(TRUE);
  184. }
  185. }
  186. // ---------------------------------------------------------------------------
  187. // %%Function: CWebGateBindStatusCallback::OnStopBinding
  188. // ---------------------------------------------------------------------------
  189. STDMETHODIMP CWebGateBindStatusCallback::OnStopBinding
  190. (
  191. HRESULT hrStatus,
  192. LPCWSTR pszError
  193. )
  194. {
  195. if (m_pbinding)
  196. {
  197. m_pbinding->Release();
  198. m_pbinding = NULL;
  199. }
  200. if (!m_bDoneNotification)
  201. {
  202. ProcessBuffer();
  203. }
  204. m_lpWebGate->Fire_WebGateDownloadProgress(TRUE);
  205. return S_OK;
  206. } // CWebGateBindStatusCallback::OnStopBinding
  207. // ---------------------------------------------------------------------------
  208. // %%Function: CWebGateBindStatusCallback::GetBindInfo
  209. // ---------------------------------------------------------------------------
  210. STDMETHODIMP CWebGateBindStatusCallback::GetBindInfo
  211. (
  212. DWORD* pgrfBINDF,
  213. BINDINFO* pbindInfo
  214. )
  215. {
  216. *pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE |
  217. BINDF_PULLDATA | BINDF_GETNEWESTVERSION |
  218. BINDF_NOWRITECACHE;
  219. pbindInfo->cbSize = sizeof(BINDINFO);
  220. pbindInfo->szExtraInfo = NULL;
  221. memset(&pbindInfo->stgmedData, 0, sizeof(STGMEDIUM));
  222. pbindInfo->grfBindInfoF = 0;
  223. pbindInfo->dwBindVerb = BINDVERB_GET;
  224. pbindInfo->szCustomVerb = NULL;
  225. return S_OK;
  226. } // CWebGateBindStatusCallback::GetBindInfo
  227. // ---------------------------------------------------------------------------
  228. // %%Function: CWebGateBindStatusCallback::OnDataAvailable
  229. // ---------------------------------------------------------------------------
  230. STDMETHODIMP CWebGateBindStatusCallback::OnDataAvailable
  231. (
  232. DWORD grfBSCF,
  233. DWORD dwSize,
  234. FORMATETC* pfmtetc,
  235. STGMEDIUM* pstgmed
  236. )
  237. {
  238. HRESULT hr = E_FAIL; //don't assume success
  239. // verify we have a read buffer
  240. if (!m_lpWebGate->m_lpdata)
  241. return(S_FALSE);
  242. // Get the Stream passed
  243. if (BSCF_FIRSTDATANOTIFICATION & grfBSCF)
  244. {
  245. m_bDoneNotification = FALSE;
  246. if (!m_pstm && pstgmed->tymed == TYMED_ISTREAM)
  247. {
  248. m_pstm = pstgmed->pstm;
  249. if (m_pstm)
  250. m_pstm->AddRef();
  251. }
  252. }
  253. // If there is some data to be read then go ahead and read them
  254. if (m_pstm && dwSize)
  255. {
  256. DWORD dwActuallyRead = 0; // Placeholder for amount read during this pull
  257. do
  258. {
  259. if (MAX_DOWNLOAD_BLOCK + m_cbOld > m_lpWebGate->m_cbdata)
  260. {
  261. m_lpWebGate->m_cbdata += READ_BUFFER_SIZE;
  262. // ::MessageBox(NULL, TEXT("reallov DumpBufferToFile"), TEXT("E R R O R"), MB_OK);
  263. LPSTR pBuffer = (LPSTR)GlobalReAllocPtr(m_lpWebGate->m_lpdata, m_lpWebGate->m_cbdata , GHND);
  264. if (pBuffer)
  265. m_lpWebGate->m_lpdata = pBuffer;
  266. else
  267. return S_FALSE;
  268. }
  269. // Read what we can
  270. hr = m_pstm->Read(m_lpWebGate->m_lpdata+m_cbOld, MAX_DOWNLOAD_BLOCK, &dwActuallyRead);
  271. // keep track of the running total
  272. m_cbOld += dwActuallyRead;
  273. } while (hr == E_PENDING || hr != S_FALSE);
  274. }
  275. if (BSCF_LASTDATANOTIFICATION & grfBSCF)
  276. {
  277. if (!m_bDoneNotification)
  278. {
  279. ProcessBuffer();
  280. }
  281. }
  282. return S_OK;
  283. } // CWebGateBindStatusCallback::OnDataAvailable
  284. // ---------------------------------------------------------------------------
  285. // %%Function: CWebGateBindStatusCallback::OnObjectAvailable
  286. // ---------------------------------------------------------------------------
  287. STDMETHODIMP CWebGateBindStatusCallback::OnObjectAvailable
  288. (
  289. REFIID riid,
  290. IUnknown* punk
  291. )
  292. {
  293. return E_NOTIMPL;
  294. } // CWebGateBindStatusCallback::OnObjectAvailable
  295. /////////////////////////////////////////////////////////////////////////////
  296. // CWebGate
  297. HRESULT CWebGate::OnDraw(ATL_DRAWINFO& di)
  298. {
  299. return S_OK;
  300. }
  301. STDMETHODIMP CWebGate::put_Path(BSTR newVal)
  302. {
  303. // TODO: Add your implementation code here
  304. USES_CONVERSION;
  305. m_bstrPath = newVal;
  306. return S_OK;
  307. }
  308. STDMETHODIMP CWebGate::put_FormData(BSTR newVal)
  309. {
  310. // TODO: Add your implementation code here
  311. USES_CONVERSION;
  312. m_bstrFormData = newVal;
  313. return S_OK;
  314. }
  315. STDMETHODIMP CWebGate::FetchPage(DWORD dwKeepFile, DWORD dwDoWait, BOOL *pbRetVal)
  316. {
  317. USES_CONVERSION;
  318. IStream *pstm = NULL;
  319. HRESULT hr;
  320. // Empty the buffer.
  321. m_bstrBuffer.Empty();
  322. // Clear the cache file name
  323. m_bstrCacheFileName.Empty();
  324. // Release the binding context callback
  325. if (m_pbsc && m_pbc)
  326. {
  327. RevokeBindStatusCallback(m_pbc, m_pbsc);
  328. m_pbsc->Release();
  329. m_pbsc = 0;
  330. }
  331. // Release the binding context
  332. if (m_pbc)
  333. {
  334. m_pbc->Release();
  335. m_pbc = 0;
  336. }
  337. // release the monikor
  338. if (m_pmk)
  339. {
  340. m_pmk->Release();
  341. m_pmk = 0;
  342. }
  343. *pbRetVal = FALSE;
  344. if (dwDoWait)
  345. m_hEventComplete = CreateEvent(NULL, TRUE, FALSE, NULL);
  346. m_bKeepFile = (BOOL) dwKeepFile;
  347. hr = CreateURLMoniker(NULL, m_bstrPath, &m_pmk);
  348. if (FAILED(hr))
  349. goto LErrExit;
  350. m_pbsc = new CWebGateBindStatusCallback(this);
  351. if (m_pbsc == NULL)
  352. {
  353. hr = E_OUTOFMEMORY;
  354. goto LErrExit;
  355. }
  356. hr = CreateBindCtx(0, &m_pbc);
  357. if (FAILED(hr))
  358. goto LErrExit;
  359. hr = RegisterBindStatusCallback(m_pbc,
  360. m_pbsc,
  361. 0,
  362. 0L);
  363. if (FAILED(hr))
  364. goto LErrExit;
  365. hr = m_pmk->BindToStorage(m_pbc, 0, IID_IStream, (void**)&pstm);
  366. if (FAILED(hr))
  367. goto LErrExit;
  368. // If we were requested to wait, then we wait for the m_hEventComplete to be
  369. // signaled
  370. if (dwDoWait && m_hEventComplete)
  371. {
  372. MSG msg;
  373. BOOL bGotFile = FALSE;
  374. DWORD dwRetCode;
  375. HANDLE hEventList[1];
  376. hEventList[0] = m_hEventComplete;
  377. while (TRUE)
  378. {
  379. // We will wait on window messages and also the named event.
  380. dwRetCode = MsgWaitForMultipleObjects(1,
  381. &hEventList[0],
  382. FALSE,
  383. 300000, // 5 minutes
  384. QS_ALLINPUT);
  385. // Determine why we came out of MsgWaitForMultipleObjects(). If
  386. // we timed out then let's do some TrialWatcher work. Otherwise
  387. // process the message that woke us up.
  388. if (WAIT_TIMEOUT == dwRetCode)
  389. {
  390. bGotFile = FALSE;
  391. break;
  392. }
  393. else if (WAIT_OBJECT_0 == dwRetCode)
  394. {
  395. bGotFile = TRUE;
  396. break;
  397. }
  398. else if (WAIT_OBJECT_0 + 1 == dwRetCode)
  399. {
  400. // 0 is returned if no message retrieved.
  401. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  402. {
  403. if (WM_QUIT == msg.message)
  404. {
  405. bGotFile = FALSE;
  406. break;
  407. }
  408. else
  409. {
  410. TranslateMessage(&msg);
  411. DispatchMessage(&msg);
  412. }
  413. }
  414. }
  415. }
  416. *pbRetVal = bGotFile;
  417. CloseHandle(m_hEventComplete);
  418. m_hEventComplete = 0;
  419. }
  420. else
  421. {
  422. *pbRetVal = TRUE;
  423. }
  424. return S_OK;
  425. LErrExit:
  426. if (m_pbc != NULL)
  427. {
  428. m_pbc->Release();
  429. m_pbc = NULL;
  430. }
  431. if (m_pbsc != NULL)
  432. {
  433. m_pbsc->Release();
  434. m_pbsc = NULL;
  435. }
  436. if (m_pmk != NULL)
  437. {
  438. m_pmk->Release();
  439. m_pmk = NULL;
  440. }
  441. if (pstm)
  442. {
  443. pstm->Release();
  444. pstm = NULL;
  445. }
  446. *pbRetVal = FALSE;
  447. return S_OK;
  448. }
  449. STDMETHODIMP CWebGate::get_Buffer(BSTR * pVal)
  450. {
  451. if (pVal == NULL)
  452. return E_POINTER;
  453. *pVal = m_bstrBuffer.Copy();
  454. return S_OK;
  455. }
  456. STDMETHODIMP CWebGate::DumpBufferToFile(BSTR *pFileName, BOOL *pbRetVal)
  457. {
  458. USES_CONVERSION;
  459. TCHAR szTempFileFullName[MAX_PATH];
  460. TCHAR szTempFileName[MAX_PATH];
  461. DWORD cbRet;
  462. HANDLE hFile;
  463. if (pFileName == NULL)
  464. return(E_POINTER);
  465. // Delete the previous temp file it it exists
  466. if (m_bstrDumpFileName)
  467. {
  468. DeleteFile(OLE2A(m_bstrDumpFileName));
  469. m_bstrDumpFileName.Empty();
  470. }
  471. // Make sure it is an htm extension, otherwise, IE will promp for download
  472. GetTempPath(MAX_PATH, szTempFileFullName);
  473. wsprintf( szTempFileName, TEXT("ICW%x.htm"), g_nICWFileCount++);
  474. lstrcat(szTempFileFullName, szTempFileName);
  475. hFile = CreateFile(szTempFileFullName,
  476. GENERIC_WRITE,
  477. 0,
  478. NULL,
  479. OPEN_ALWAYS,
  480. FILE_ATTRIBUTE_NORMAL,
  481. NULL);
  482. if (hFile)
  483. {
  484. WriteFile(hFile, m_lpdata, m_cbBuffer, (LPDWORD)&cbRet, NULL);
  485. CloseHandle(hFile);
  486. }
  487. // Copy the created file name into the webgate control
  488. m_bstrDumpFileName = A2BSTR(szTempFileFullName);
  489. *pFileName = m_bstrDumpFileName.Copy();
  490. *pbRetVal = TRUE;
  491. MinimizeRNAWindowEx();
  492. return S_OK;
  493. }
  494. STDMETHODIMP CWebGate::get_DownloadFname(BSTR *pVal)
  495. {
  496. if (pVal == NULL)
  497. return(E_POINTER);
  498. *pVal = m_bstrCacheFileName.Copy();
  499. return(S_OK);
  500. }