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.

364 lines
10 KiB

  1. //
  2. // MODULE: DOWNLOAD.CPP
  3. //
  4. // PURPOSE: Downloads and installs the latest trouble shooters.
  5. //
  6. // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
  7. //
  8. // COMPANY: Saltmine Creative, Inc. (206)-633-4743 [email protected]
  9. //
  10. // AUTHOR: Roman Mach
  11. //
  12. // ORIGINAL DATE: 6/4/96
  13. //
  14. // NOTES:
  15. // 1. Based on PROGRESS.CPP from Microsoft Platform Preview SDK
  16. //
  17. // Version Date By Comments
  18. //--------------------------------------------------------------------
  19. // V0.1 - RM Original
  20. // V0.3 04/09/98 JM/OK+ Local Version for NT5
  21. //
  22. #include "stdafx.h"
  23. class CTSHOOTCtrl;
  24. #include "download.h"
  25. #include "dnldlist.h"
  26. #include "TSHOOT.h"
  27. #include "time.h"
  28. #include "apgts.h"
  29. #include "ErrorEnums.h"
  30. #include "BasicException.h"
  31. #include "apgtsfst.h"
  32. #include "ErrorEnums.h"
  33. #include "bnts.h"
  34. #include "BackupInfo.h"
  35. #include "cachegen.h"
  36. #include "apgtsinf.h"
  37. #include "apgtscmd.h"
  38. #include "apgtshtx.h"
  39. #include "apgtscls.h"
  40. #include "TSHOOTCtl.h"
  41. // ===========================================================================
  42. // CBindStatusCallback Implementation
  43. // ===========================================================================
  44. // ---------------------------------------------------------------------------
  45. // %%Function: CBindStatusCallback::CBindStatusCallback
  46. // ---------------------------------------------------------------------------
  47. CBindStatusCallback::CBindStatusCallback(CTSHOOTCtrl *pEvent, DLITEMTYPES dwItem)
  48. {
  49. m_pbinding = NULL;
  50. m_pstm = NULL;
  51. m_cRef = 1;
  52. m_pEvent = pEvent;
  53. m_data = NULL;
  54. m_datalen = 0;
  55. m_dwItem = dwItem;
  56. } // CBindStatusCallback
  57. // ---------------------------------------------------------------------------
  58. // %%Function: CBindStatusCallback::~CBindStatusCallback
  59. // ---------------------------------------------------------------------------
  60. CBindStatusCallback::~CBindStatusCallback()
  61. {
  62. if (m_data)
  63. delete[] m_data;
  64. } // ~CBindStatusCallback
  65. // ---------------------------------------------------------------------------
  66. // %%Function: CBindStatusCallback::QueryInterface
  67. // ---------------------------------------------------------------------------
  68. STDMETHODIMP
  69. CBindStatusCallback::QueryInterface(REFIID riid, void** ppv)
  70. {
  71. *ppv = NULL;
  72. if (riid==IID_IUnknown || riid==IID_IBindStatusCallback)
  73. {
  74. *ppv = this;
  75. AddRef();
  76. return S_OK;
  77. }
  78. return E_NOINTERFACE;
  79. } // CBindStatusCallback::QueryInterface
  80. // ---------------------------------------------------------------------------
  81. // %%Function: CBindStatusCallback::OnStartBinding
  82. // ---------------------------------------------------------------------------
  83. STDMETHODIMP
  84. CBindStatusCallback::OnStartBinding(DWORD dwReserved, IBinding* pbinding)
  85. {
  86. if (m_pbinding != NULL)
  87. m_pbinding->Release();
  88. m_pbinding = pbinding;
  89. if (m_pbinding != NULL)
  90. {
  91. m_pbinding->AddRef();
  92. //m_pEvent->StatusEventHelper(m_dwItem, LTSC_STARTBIND);
  93. }
  94. return S_OK;
  95. } // CBindStatusCallback::OnStartBinding
  96. // ---------------------------------------------------------------------------
  97. // %%Function: CBindStatusCallback::GetPriority
  98. // ---------------------------------------------------------------------------
  99. STDMETHODIMP
  100. CBindStatusCallback::GetPriority(LONG* pnPriority)
  101. {
  102. return E_NOTIMPL;
  103. } // CBindStatusCallback::GetPriority
  104. // ---------------------------------------------------------------------------
  105. // %%Function: CBindStatusCallback::OnLowResource
  106. // ---------------------------------------------------------------------------
  107. STDMETHODIMP
  108. CBindStatusCallback::OnLowResource(DWORD dwReserved)
  109. {
  110. return E_NOTIMPL;
  111. } // CBindStatusCallback::OnLowResource
  112. // ---------------------------------------------------------------------------
  113. // %%Function: CBindStatusCallback::OnProgress
  114. // ---------------------------------------------------------------------------
  115. STDMETHODIMP
  116. CBindStatusCallback::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
  117. {
  118. m_pEvent->ProgressEventHelper(m_dwItem, ulProgress, (ulProgress>ulProgressMax)?ulProgress:ulProgressMax);
  119. return(NOERROR);
  120. } // CBindStatusCallback::OnProgress
  121. // ---------------------------------------------------------------------------
  122. // %%Function: CBindStatusCallback::OnStopBinding
  123. // ---------------------------------------------------------------------------
  124. STDMETHODIMP
  125. CBindStatusCallback::OnStopBinding(HRESULT hrStatus, LPCWSTR pszError)
  126. {
  127. if (hrStatus)
  128. m_pEvent->StatusEventHelper(m_dwItem, LTSCERR_STOPBINDINT, hrStatus & 0xFFFF, TRUE);
  129. else
  130. {
  131. DLSTATTYPES dwStat = m_pEvent->ProcessReceivedData(m_dwItem, m_data, m_datalen);
  132. if (dwStat == LTSC_OK)
  133. m_pEvent->StatusEventHelper(m_dwItem, LTSC_STOPBIND, 0, TRUE);
  134. else
  135. m_pEvent->StatusEventHelper(m_dwItem, LTSCERR_STOPBINDPROC, dwStat, TRUE);
  136. }
  137. if (m_pbinding)
  138. {
  139. m_pbinding->Release();
  140. m_pbinding = NULL;
  141. }
  142. return S_OK;
  143. } // CBindStatusCallback::OnStopBinding
  144. // ---------------------------------------------------------------------------
  145. // %%Function: CBindStatusCallback::GetBindInfo
  146. // ---------------------------------------------------------------------------
  147. STDMETHODIMP
  148. CBindStatusCallback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindInfo)
  149. {
  150. *pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
  151. *pgrfBINDF |= BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE;
  152. pbindInfo->cbSize = sizeof(BINDINFO);
  153. pbindInfo->szExtraInfo = NULL;
  154. memset(&pbindInfo->stgmedData, 0, sizeof(STGMEDIUM));
  155. pbindInfo->grfBindInfoF = 0;
  156. pbindInfo->dwBindVerb = BINDVERB_GET;
  157. pbindInfo->szCustomVerb = NULL;
  158. return S_OK;
  159. } // CBindStatusCallback::GetBindInfo
  160. // ---------------------------------------------------------------------------
  161. // %%Function: CBindStatusCallback::OnDataAvailable
  162. // ---------------------------------------------------------------------------
  163. STDMETHODIMP
  164. CBindStatusCallback::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC* pfmtetc, STGMEDIUM* pstgmed)
  165. {
  166. HRESULT hr=S_OK;
  167. DWORD dStrlength=0;
  168. //m_pEvent->StatusEventHelper(m_dwItem, LTSC_START);
  169. // Get the Stream passed
  170. if (BSCF_FIRSTDATANOTIFICATION & grfBSCF)
  171. {
  172. if (!m_pstm && pstgmed->tymed == TYMED_ISTREAM)
  173. {
  174. m_pstm = pstgmed->pstm;
  175. if (m_pstm)
  176. m_pstm->AddRef();
  177. //m_pEvent->StatusEventHelper(m_dwItem, LTSC_FIRST);
  178. }
  179. }
  180. // If there is some data to be read then go ahead and read them
  181. if (m_pstm && dwSize)
  182. {
  183. DWORD dwActuallyRead = 0; // Placeholder for amount read during this pull
  184. do
  185. {
  186. TCHAR * pNewstr = new TCHAR[dwSize + 1 + m_datalen];
  187. if (pNewstr==NULL)
  188. {
  189. hr = S_FALSE;
  190. break;
  191. }
  192. hr = m_pstm->Read(&pNewstr[m_datalen], dwSize, &dwActuallyRead);
  193. if (dwActuallyRead)
  194. {
  195. pNewstr[m_datalen + dwActuallyRead] = 0;
  196. if (m_data && m_datalen)
  197. {
  198. memcpy(pNewstr, m_data, m_datalen);
  199. delete[] m_data;
  200. m_data = NULL;
  201. }
  202. //m_pEvent->StatusEventHelper(m_dwItem, LTSC_RCVDATA);
  203. m_data = pNewstr;
  204. m_datalen += dwActuallyRead;
  205. }
  206. else
  207. delete[] pNewstr;
  208. } while (!(hr == E_PENDING || hr == S_FALSE) && SUCCEEDED(hr));
  209. }
  210. if (BSCF_LASTDATANOTIFICATION & grfBSCF)
  211. {
  212. if (m_pstm)
  213. m_pstm->Release();
  214. hr=S_OK; // If it was the last data then we should return S_OK as we just finished reading everything
  215. //m_pEvent->StatusEventHelper(m_dwItem, LTSC_DATADONE);
  216. }
  217. //m_pEvent->StatusEventHelper(m_dwItem, LTSC_STOP);
  218. return hr;
  219. } // CBindStatusCallback::OnDataAvailable
  220. // ---------------------------------------------------------------------------
  221. // %%Function: CBindStatusCallback::OnObjectAvailable
  222. // ---------------------------------------------------------------------------
  223. STDMETHODIMP
  224. CBindStatusCallback::OnObjectAvailable(REFIID riid, IUnknown* punk)
  225. {
  226. return E_NOTIMPL;
  227. } // CBindStatusCallback::OnObjectAvailable
  228. // ===========================================================================
  229. // CDownload Implementation
  230. // ===========================================================================
  231. // ---------------------------------------------------------------------------
  232. // %%Function: CDownload::CDownload
  233. // ---------------------------------------------------------------------------
  234. CDownload::CDownload()
  235. {
  236. m_pmk = 0;
  237. m_pbc = 0;
  238. m_pbsc = 0;
  239. } // CDownload
  240. // ---------------------------------------------------------------------------
  241. // %%Function: CDownload::~CDownload
  242. // ---------------------------------------------------------------------------
  243. CDownload::~CDownload()
  244. {
  245. if (m_pmk)
  246. m_pmk->Release();
  247. if (m_pbc)
  248. m_pbc->Release();
  249. if (m_pbsc)
  250. m_pbsc->Release();
  251. } // ~CDownload
  252. // ---------------------------------------------------------------------------
  253. // %%Function: CDownload::DoDownload
  254. // ---------------------------------------------------------------------------
  255. HRESULT
  256. CDownload::DoDownload(CTSHOOTCtrl *pEvent, LPCTSTR pURL, DLITEMTYPES dwItem)
  257. {
  258. IStream* pstm = NULL;
  259. HRESULT hr;
  260. #ifndef _UNICODE
  261. WCHAR rgwchPath[MAX_PATH];
  262. MultiByteToWideChar(CP_ACP, 0, pURL, -1, rgwchPath, MAX_PATH);
  263. hr = CreateURLMoniker(NULL, rgwchPath, &m_pmk);
  264. #else
  265. hr = CreateURLMoniker(NULL, pURL, &m_pmk);
  266. #endif
  267. if (FAILED(hr))
  268. goto LErrExit;
  269. m_pbsc = new CBindStatusCallback(pEvent, dwItem);
  270. if (m_pbsc == NULL)
  271. {
  272. hr = E_OUTOFMEMORY;
  273. goto LErrExit;
  274. }
  275. hr = CreateBindCtx(0, &m_pbc);
  276. if (FAILED(hr))
  277. goto LErrExit;
  278. hr = RegisterBindStatusCallback(m_pbc,
  279. m_pbsc,
  280. 0,
  281. 0L);
  282. if (FAILED(hr))
  283. goto LErrExit;
  284. hr = m_pmk->BindToStorage(m_pbc, 0, IID_IStream, (void**)&pstm);
  285. if (FAILED(hr))
  286. goto LErrExit;
  287. return hr;
  288. while (S_OK == m_pmk->IsRunning(m_pbc, NULL, NULL));
  289. Sleep(200);
  290. LErrExit:
  291. if (m_pbc != NULL)
  292. {
  293. m_pbc->Release();
  294. m_pbc = NULL;
  295. }
  296. if (m_pbsc != NULL)
  297. {
  298. m_pbsc->Release();
  299. m_pbsc = NULL;
  300. }
  301. if (m_pmk != NULL)
  302. {
  303. m_pmk->Release();
  304. m_pmk = NULL;
  305. }
  306. if (pstm)
  307. {
  308. pstm->Release();
  309. pstm = NULL;
  310. }
  311. return hr;
  312. } // CDownload::DoDownload