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.

3353 lines
96 KiB

  1. // ===========================================================================
  2. // File: DL.CXX
  3. // implements CDownload, CBindStatusCallback classes
  4. //
  5. #include <cdlpch.h>
  6. // SILENT MODE
  7. #include <winineti.h>
  8. #include <shlwapi.h>
  9. #include <shlwapip.h>
  10. #include <comcat.h>
  11. #include <initguid.h> // office antivirus goo
  12. #define AVVENDOR // don't look at unwanted office defs
  13. #include <msoav.h>
  14. extern char g_szOCXTempDir[MAX_PATH];
  15. extern IEnumFORMATETC *g_pEFmtETC;
  16. extern FORMATETC g_rgfmtetc[];
  17. // ---------------------------------------------------------------------------
  18. // %%Function: CDownload::CDownload
  19. // CDownload is the basic download obj.
  20. // ---------------------------------------------------------------------------
  21. CDownload::CDownload(LPCWSTR szURL, FILEXTN extn, HRESULT *phr)
  22. {
  23. DEBUG_ENTER((DBG_DOWNLOAD,
  24. None,
  25. "CDownload::CDownload",
  26. "this=%#x, %.80wq, %#x, %#x",
  27. this, szURL, extn, phr
  28. ));
  29. DllAddRef();
  30. DWORD len = lstrlenW(szURL); // make private copy
  31. m_url = new WCHAR [len + 1];
  32. if (m_url)
  33. StrCpyW(m_url, szURL);
  34. else
  35. *phr = E_OUTOFMEMORY;
  36. m_pmk = 0;
  37. m_pbc = 0;
  38. m_pbsc = 0;
  39. m_pdlnext= NULL;
  40. m_ParentCDL.RemoveAll();
  41. m_extn = extn;
  42. m_pFileName = NULL; // we don't know the dest filename
  43. // till we create a temp file in the first
  44. // notification of OnDataAvailable
  45. // This is guaranteed to get set before
  46. // OnStopBinding
  47. m_ulProgress = 0;
  48. m_ulProgressMax = 0;
  49. m_state = DLSTATE_INIT;
  50. m_psess = NULL;
  51. m_pFilesToExtract = NULL;
  52. m_pSetuphead = NULL;
  53. m_hPostData = NULL;
  54. m_cbPostData = 0;
  55. m_hrOSB = S_OK;
  56. m_hrStatus = S_OK;
  57. m_hrResponseHdr = S_OK;
  58. m_bCompleteSignalled = FALSE;
  59. m_flags = DL_FLAGS_INIT;
  60. m_SetupHooks.RemoveAll();
  61. m_JavaSetupList.RemoveAll();
  62. m_pUnkForCacheFileRelease = NULL;
  63. m_pbJavaTrust = NULL;
  64. m_wszDistUnit = NULL;
  65. m_pcbhList = NULL;
  66. m_ppmkContext = NULL;
  67. m_grfBINDF = 0;
  68. m_bExactVersion = FALSE;
  69. DEBUG_LEAVE(0);
  70. } // CDownload
  71. // ---------------------------------------------------------------------------
  72. // %%Function: CDownload::~CDownload
  73. // ---------------------------------------------------------------------------
  74. CDownload::~CDownload()
  75. {
  76. DEBUG_ENTER((DBG_DOWNLOAD,
  77. None,
  78. "CDownload::~CDownload",
  79. "this=%#x",
  80. this
  81. ));
  82. int i;
  83. CCodeBaseHold *pcbh = NULL;
  84. LISTPOSITION lpos = 0;
  85. CleanUp();
  86. LISTPOSITION pos = m_ParentCDL.GetHeadPosition();
  87. int iNum = m_ParentCDL.GetCount();
  88. Assert(iNum == 0);
  89. for (i=0; i < iNum; i++) {
  90. CParentCDL *pParentCDL = m_ParentCDL.GetNext(pos); // pass ref!
  91. delete pParentCDL;
  92. }
  93. m_ParentCDL.RemoveAll();
  94. if (m_pcbhList != NULL) {
  95. lpos = m_pcbhList->GetHeadPosition();
  96. while (lpos) {
  97. pcbh = m_pcbhList->GetNext(lpos);
  98. delete pcbh;
  99. }
  100. m_pcbhList->RemoveAll();
  101. }
  102. SAFEDELETE(m_pcbhList);
  103. SAFEDELETE(m_wszDistUnit);
  104. pos = m_SetupHooks.GetHeadPosition();
  105. iNum = m_SetupHooks.GetCount();
  106. for (i=0; i < iNum; i++) {
  107. CSetupHook *pSetupHook = m_SetupHooks.GetNext(pos); // pass ref!
  108. delete pSetupHook;
  109. }
  110. m_SetupHooks.RemoveAll();
  111. pos = m_JavaSetupList.GetHeadPosition();
  112. iNum = m_JavaSetupList.GetCount();
  113. for (i=0; i < iNum; i++) {
  114. CJavaSetup *pJavaSetup = m_JavaSetupList.GetNext(pos); // pass ref!
  115. delete pJavaSetup;
  116. }
  117. m_JavaSetupList.RemoveAll();
  118. DllRelease();
  119. DEBUG_LEAVE(0);
  120. } // ~CDownload
  121. // ---------------------------------------------------------------------------
  122. // %%Function: CDownload::HasJavaPermissions
  123. // ---------------------------------------------------------------------------
  124. BOOL
  125. CDownload::HasJavaPermissions()
  126. {
  127. DEBUG_ENTER((DBG_DOWNLOAD,
  128. Bool,
  129. "CDownload::HasJavaPermissions",
  130. "this=%#x",
  131. this
  132. ));
  133. if (m_pbJavaTrust) {
  134. // new jaavcypt > 2151 succeeds even if one of activex/java
  135. // is allowed
  136. DEBUG_LEAVE((m_pbJavaTrust->pbJavaPermissions != NULL));
  137. return (m_pbJavaTrust->pbJavaPermissions != NULL);
  138. }
  139. DEBUG_LEAVE(FALSE);
  140. return FALSE;
  141. }
  142. // ---------------------------------------------------------------------------
  143. // %%Function: CDownload::HasAllActiveXPermissions
  144. // ---------------------------------------------------------------------------
  145. BOOL
  146. CDownload::HasAllActiveXPermissions()
  147. {
  148. DEBUG_ENTER((DBG_DOWNLOAD,
  149. Bool,
  150. "CDownload::HasAllActiveXPermissions",
  151. "this=%#x",
  152. this
  153. ));
  154. PJAVA_TRUST pbJavaTrust = NULL;
  155. if (m_pbJavaTrust) {
  156. // new jaavcypt > 2151 succeeds even if one of activex/java
  157. // is allowed
  158. DEBUG_LEAVE(m_pbJavaTrust->fAllActiveXPermissions);
  159. return m_pbJavaTrust->fAllActiveXPermissions;
  160. }
  161. else {
  162. pbJavaTrust = GetCodeDownload()->GetJavaTrust();
  163. if (pbJavaTrust) {
  164. DEBUG_LEAVE(pbJavaTrust->fAllActiveXPermissions);
  165. return pbJavaTrust->fAllActiveXPermissions;
  166. }
  167. }
  168. DEBUG_LEAVE(FALSE);
  169. return FALSE;
  170. }
  171. // ---------------------------------------------------------------------------
  172. // %%Function: CDownload::CompleteSignal
  173. // ---------------------------------------------------------------------------
  174. HRESULT
  175. CDownload::CompleteSignal(HRESULT hrOSB, HRESULT hrStatus, HRESULT hrResponseHdr, LPCWSTR szError)
  176. {
  177. DEBUG_ENTER((DBG_DOWNLOAD,
  178. Hresult,
  179. "CDownload::CompleteSignal",
  180. "this=%#x, %#x, %#x, %#x, %.80wq",
  181. this, hrOSB, hrStatus, hrResponseHdr, szError
  182. ));
  183. int i, iNum;
  184. LISTPOSITION pos;
  185. m_hrOSB = hrOSB;
  186. m_hrStatus = hrStatus;
  187. m_hrResponseHdr = hrResponseHdr;
  188. m_bCompleteSignalled = TRUE;
  189. restart:
  190. iNum = m_ParentCDL.GetCount();
  191. Assert(iNum);
  192. pos = m_ParentCDL.GetHeadPosition();
  193. for (i=0; i < iNum; i++) {
  194. CParentCDL *pParentCDL = m_ParentCDL.GetNext(pos); // pass ref!
  195. if (!pParentCDL->m_bCompleteSignalled) {
  196. // unsignalled code download
  197. pParentCDL->m_bCompleteSignalled = TRUE;
  198. pParentCDL->m_pcdl->CompleteOne( this ,hrOSB, hrStatus, hrResponseHdr, szError);
  199. if (iNum > 1) {
  200. // failed complete reports could cause CodeDownloads to release
  201. // us and thus change the list
  202. goto restart;
  203. }
  204. }
  205. }
  206. DEBUG_LEAVE(S_OK);
  207. return S_OK;
  208. }
  209. // ---------------------------------------------------------------------------
  210. // %%Function: CDownload::AddParent(CCodeDownload *pcdl)
  211. // ---------------------------------------------------------------------------
  212. HRESULT
  213. CDownload::AddParent(CCodeDownload *pcdl)
  214. {
  215. DEBUG_ENTER((DBG_DOWNLOAD,
  216. Hresult,
  217. "CDownload::AddParent",
  218. "this=%#x, %#x",
  219. this, pcdl
  220. ));
  221. HRESULT hr = S_OK;
  222. CParentCDL *pParentCDL = new CParentCDL(pcdl);
  223. if (pParentCDL)
  224. m_ParentCDL.AddTail(pParentCDL);
  225. else
  226. hr = E_OUTOFMEMORY;
  227. if (SUCCEEDED(hr)) {
  228. if (m_bCompleteSignalled) {
  229. pParentCDL->m_bCompleteSignalled = TRUE;
  230. pcdl->CompleteOne(this ,m_hrOSB, m_hrStatus, m_hrResponseHdr, NULL);
  231. } else {
  232. hr = FAILED(m_hrOSB)?m_hrOSB:(FAILED(m_hrStatus)?m_hrStatus:(FAILED(m_hrResponseHdr)?m_hrResponseHdr:S_OK));
  233. }
  234. }
  235. DEBUG_LEAVE(hr);
  236. return hr;
  237. }
  238. // ---------------------------------------------------------------------------
  239. // %%Function: CDownload::IsSignalled(CCodeDownload *pcdl)
  240. // ---------------------------------------------------------------------------
  241. BOOL
  242. CDownload::IsSignalled(CCodeDownload *pcdl)
  243. {
  244. DEBUG_ENTER((DBG_DOWNLOAD,
  245. Bool,
  246. "CDownload::IsSignalled",
  247. "this=%#x, %#x",
  248. this, pcdl
  249. ));
  250. CParentCDL *pParentCDL = NULL;
  251. BOOL bRet = FALSE;
  252. LISTPOSITION pos = 0;
  253. DLSTATE dls;
  254. int iNum = 0;
  255. int i;
  256. dls = GetDLState();
  257. if (dls == DLSTATE_DONE || dls == DLSTATE_READY_TO_SETUP) {
  258. bRet = TRUE;
  259. goto Exit;
  260. }
  261. iNum = m_ParentCDL.GetCount();
  262. Assert(iNum);
  263. pos = m_ParentCDL.GetHeadPosition();
  264. for (i=0; i < iNum; i++) {
  265. pParentCDL = m_ParentCDL.GetNext(pos); // pass ref!
  266. if (pParentCDL->m_pcdl == pcdl && pParentCDL->m_bCompleteSignalled) {
  267. bRet = TRUE;
  268. break;
  269. }
  270. }
  271. Exit:
  272. DEBUG_LEAVE(bRet);
  273. return bRet;
  274. }
  275. // ---------------------------------------------------------------------------
  276. // %%Function: CDownload::Abort(CCodeDownload *pcdl)
  277. // ---------------------------------------------------------------------------
  278. HRESULT
  279. CDownload::Abort(CCodeDownload *pcdl)
  280. {
  281. DEBUG_ENTER((DBG_DOWNLOAD,
  282. Hresult,
  283. "CDownload::Abort",
  284. "this=%#x, %#x",
  285. this, pcdl
  286. ));
  287. int i;
  288. CParentCDL *pThisParentCDL = NULL;
  289. BOOL bDelinkParent = FALSE;
  290. BOOL fWaitForAbortCompletion = FALSE;
  291. HRESULT hr = S_OK;
  292. int iNum = m_ParentCDL.GetCount();
  293. Assert(iNum);
  294. LISTPOSITION pos = m_ParentCDL.GetHeadPosition();
  295. for (i=0; i < iNum; i++) {
  296. CParentCDL *pParentCDL = m_ParentCDL.GetNext(pos); // pass ref!
  297. if (pParentCDL->m_pcdl == pcdl)
  298. pThisParentCDL = pParentCDL;
  299. else if ( !pParentCDL->m_bCompleteSignalled )
  300. bDelinkParent = TRUE;
  301. }
  302. Assert(pThisParentCDL);
  303. if (!pThisParentCDL)
  304. {
  305. DEBUG_LEAVE(E_FAIL);
  306. return E_FAIL;
  307. }
  308. if (bDelinkParent) {
  309. // multiple code downloads interested in this
  310. // delink this parent, by marking as complete signalled
  311. pThisParentCDL->m_bCompleteSignalled = TRUE;
  312. DEBUG_LEAVE(S_OK);
  313. return S_OK;
  314. }
  315. switch ( GetDLState()) {
  316. case DLSTATE_BINDING:
  317. GetBSC()->GetBinding()->Abort();
  318. break;
  319. case DLSTATE_ABORT:
  320. // have aborted this but the OSB has not been recieved yet
  321. // so wait for that to come to us before we complteall
  322. // or post the setup packet to completeall
  323. fWaitForAbortCompletion = TRUE;
  324. break;
  325. case DLSTATE_DONE:
  326. case DLSTATE_READY_TO_SETUP:
  327. break;
  328. default:
  329. // packet processing pending for this state. we will check for
  330. // DLSTATE_ABORT in each packet processing state and if true
  331. // it will call CompleteOne(us), which marks each piece DLSTATE_DONE
  332. SetDLState(DLSTATE_ABORT);
  333. fWaitForAbortCompletion = TRUE;
  334. }
  335. if (fWaitForAbortCompletion) {
  336. hr = S_FALSE;
  337. }
  338. DEBUG_LEAVE(hr);
  339. return hr;
  340. }
  341. // ---------------------------------------------------------------------------
  342. // %%Function: CDownload::ReleaseParent(CCodeDownload *pcdl)
  343. // ---------------------------------------------------------------------------
  344. HRESULT
  345. CDownload::ReleaseParent(CCodeDownload *pcdl)
  346. {
  347. DEBUG_ENTER((DBG_DOWNLOAD,
  348. Hresult,
  349. "CDownload::ReleaseParent",
  350. "this=%#x, %#x",
  351. this, pcdl
  352. ));
  353. int iNum = m_ParentCDL.GetCount();
  354. Assert(iNum);
  355. LISTPOSITION pos = m_ParentCDL.GetHeadPosition();
  356. for (int i=0; i < iNum; i++) {
  357. CParentCDL *pParentCDL = m_ParentCDL.GetNext(pos); // pass ref!
  358. if (pParentCDL->m_pcdl == pcdl) {
  359. // found the item
  360. // getnext would have stepped past the position
  361. pos = m_ParentCDL.Find(pParentCDL);
  362. m_ParentCDL.RemoveAt(pos);
  363. iNum = m_ParentCDL.GetCount();
  364. if (iNum == 0) {
  365. CleanupFiles();
  366. delete this;
  367. }
  368. DEBUG_LEAVE(S_OK);
  369. return S_OK;
  370. }
  371. }
  372. // not found in list
  373. Assert(TRUE);
  374. DEBUG_LEAVE(E_FAIL);
  375. return E_FAIL;
  376. }
  377. // ---------------------------------------------------------------------------
  378. // HRESULT CDownload::IsDownloadedVersionRequired()
  379. // returns S_OK if downloaded version is required
  380. // error if local version is OK and new verison is not required
  381. // ---------------------------------------------------------------------------
  382. HRESULT CDownload::IsDownloadedVersionRequired()
  383. {
  384. DEBUG_ENTER((DBG_DOWNLOAD,
  385. Hresult,
  386. "CDownload::IsDownloadedVersionRequired",
  387. "this=%#x",
  388. this
  389. ));
  390. HRESULT hr = S_OK;
  391. char szFullURL[INTERNET_MAX_URL_LENGTH];
  392. DWORD dwLen = INTERNET_MAX_URL_LENGTH;
  393. FILETIME *pftLastMod = GetCodeDownload()->GetLastModifiedTime();
  394. HANDLE hf = INVALID_HANDLE_VALUE;
  395. if (!GetCodeDownload()->LocalVersionPresent()) {
  396. // if no prev version always download
  397. DEBUG_LEAVE(hr);
  398. return hr;
  399. } else {
  400. // if prev version exists, but we are not doing Get Latest
  401. // then accept the download.
  402. if (!GetCodeDownload()->NeedLatestVersion())
  403. {
  404. DEBUG_LEAVE(hr);
  405. return hr;
  406. }
  407. }
  408. if (GetMoniker() != GetCodeDownload()->GetContextMoniker()){
  409. // if we are not the context (or the main moniker then
  410. // -1 does not apply (to secondary CABs)
  411. DEBUG_LEAVE(hr);
  412. return hr;
  413. }
  414. dwLen = WideCharToMultiByte(CP_ACP, 0, GetURL(), -1,
  415. szFullURL, INTERNET_MAX_URL_LENGTH, NULL, NULL);
  416. Assert(dwLen);
  417. if (!dwLen) {
  418. hr = HRESULT_FROM_WIN32(GetLastError());
  419. goto Exit;
  420. }
  421. if (StrCmpNI(szFullURL, "file:", 5) == 0) {
  422. WIN32_FIND_DATA fd;
  423. hf = FindFirstFile(GetFileName(), &fd);
  424. if (hf == INVALID_HANDLE_VALUE) {
  425. hr = HRESULT_FROM_WIN32(GetLastError());
  426. goto Exit;
  427. }
  428. // BUGBUG: Defend against Bug#40696 - Vatsan should check to see if this is the _right_ defense.
  429. if ( pftLastMod != NULL &&
  430. CompareFileTime(pftLastMod, &(fd.ftLastWriteTime)) >= 0) {
  431. // if the file needs no upgrade then fail!
  432. // if we succeed then an update will take place.
  433. hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  434. goto Exit;
  435. }
  436. }
  437. Exit:
  438. if ( hf != INVALID_HANDLE_VALUE)
  439. FindClose(hf);
  440. DEBUG_LEAVE(hr);
  441. return hr;
  442. }
  443. // ---------------------------------------------------------------------------
  444. // %%Function: CDownload::GetFriendlyName
  445. // ---------------------------------------------------------------------------
  446. HRESULT CDownload::GetFriendlyName(LPSTR szUrlPath, LPSTR *ppBaseFileName)
  447. {
  448. DEBUG_ENTER((DBG_DOWNLOAD,
  449. Hresult,
  450. "CDownload::GetFriendlyName",
  451. "this=%#x, %.80q, %#x",
  452. this, szUrlPath, ppBaseFileName
  453. ));
  454. HRESULT hr = S_OK;
  455. char szFullURL[INTERNET_MAX_URL_LENGTH];
  456. DWORD dwLen = INTERNET_MAX_URL_LENGTH;
  457. URL_COMPONENTS UrlComponents;
  458. char *pBaseFileName = NULL;
  459. dwLen = WideCharToMultiByte(CP_ACP, 0, GetURL(), -1,
  460. szFullURL, INTERNET_MAX_URL_LENGTH, NULL, NULL);
  461. memset(&UrlComponents, 0, sizeof(URL_COMPONENTS));
  462. UrlComponents.dwStructSize = sizeof(URL_COMPONENTS);
  463. UrlComponents.lpszUrlPath = szUrlPath;
  464. UrlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
  465. if (!InternetCrackUrl( szFullURL, 0,
  466. ICU_DECODE, &UrlComponents)) {
  467. hr = HRESULT_FROM_WIN32(GetLastError());
  468. goto Exit;
  469. }
  470. Assert(UrlComponents.lpszUrlPath);
  471. Assert(UrlComponents.dwUrlPathLength);
  472. if ( !UrlComponents.dwUrlPathLength ||
  473. !UrlComponents.lpszUrlPath ) {
  474. hr = E_UNEXPECTED;
  475. goto Exit;
  476. }
  477. if (ppBaseFileName)
  478. GetExtnAndBaseFileName(szUrlPath, ppBaseFileName);
  479. Exit:
  480. DEBUG_LEAVE(hr);
  481. return hr;
  482. }
  483. // ---------------------------------------------------------------------------
  484. // %%Function: CDownload::SniffType
  485. // ---------------------------------------------------------------------------
  486. HRESULT CDownload::SniffType()
  487. {
  488. DEBUG_ENTER((DBG_DOWNLOAD,
  489. Hresult,
  490. "CDownload::SniffType",
  491. "this=%#x",
  492. this
  493. ));
  494. HANDLE hFile = INVALID_HANDLE_VALUE;
  495. HRESULT hr = S_OK;
  496. DWORD dwSignature;
  497. DWORD dwBytesRead = 0;
  498. #define CAB_SIG 0x4643534d
  499. if (GetExtn() != FILEXTN_CAB) {
  500. if ( (hFile = CreateFile(GetFileName(), GENERIC_READ, FILE_SHARE_READ,
  501. NULL, OPEN_EXISTING,
  502. FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) {
  503. hr = HRESULT_FROM_WIN32(GetLastError());
  504. goto Exit;
  505. }
  506. if ((ReadFile(hFile, &dwSignature, sizeof(DWORD), &dwBytesRead, NULL))
  507. && (dwSignature == CAB_SIG)) {
  508. SetURLAndExtn(NULL, FILEXTN_CAB);
  509. } else {
  510. // here if its not a CAB
  511. // check if of compatible type
  512. hr = IsCompatibleFile(GetFileName());
  513. }
  514. }
  515. Exit:
  516. if (hFile != INVALID_HANDLE_VALUE)
  517. CloseHandle(hFile);
  518. DEBUG_LEAVE(hr);
  519. return hr;
  520. }
  521. // ---------------------------------------------------------------------------
  522. // %%Function: CDownload::VerifyTrust
  523. // ---------------------------------------------------------------------------
  524. VOID CDownload::VerifyTrust()
  525. {
  526. DEBUG_ENTER((DBG_DOWNLOAD,
  527. None,
  528. "CDownload::VerifyTrust",
  529. "this=%#x",
  530. this
  531. ));
  532. HANDLE hFile = INVALID_HANDLE_VALUE;
  533. HRESULT hr = S_OK;
  534. HWND hWnd = GetCodeDownload()->GetClientBinding()->GetHWND();
  535. WCHAR szDisplayUrl[INTERNET_MAX_URL_LENGTH];
  536. DWORD cchDisplayUrl = INTERNET_MAX_URL_LENGTH;
  537. LPSTR szCatalogFile = NULL;
  538. CUrlMkTls tls(hr); // hr passed by reference!
  539. if (FAILED(hr)) // if tls ctor failed above
  540. goto Exit;
  541. if ( GetDLState() == DLSTATE_ABORT) {
  542. hr = E_ABORT;
  543. goto Exit;
  544. }
  545. // sniff file for detecting CAB extensions
  546. // and if not CAB, assume PE and check if of compatible type
  547. // before calling trust on it. The reason we presniff for
  548. // compat is because it will make for better user experience to
  549. // fail if not of correct binary before we present trust dialogs
  550. hr = SniffType();
  551. if (FAILED(hr))
  552. goto Exit;
  553. Assert(tls->pTrustCookie);
  554. // need to serialize all trust verification on this thread
  555. // grab the trust cookie
  556. hr = tls->pTrustCookie->Acquire(this);
  557. if (hr != S_OK) {
  558. Assert(!tls->pTrustCookie->IsFree());
  559. Assert(!tls->pTrustCookie->IsOwner(this));
  560. DEBUG_LEAVE(0);
  561. return; // wait till we get posted a message when the current owner
  562. // relinquishes the cookie
  563. }
  564. // have the cookie
  565. Assert(tls->pTrustCookie->IsOwner(this));
  566. if ( (hFile = CreateFile(GetFileName(), GENERIC_READ, FILE_SHARE_READ,
  567. NULL, OPEN_EXISTING,
  568. FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) {
  569. hr = HRESULT_FROM_WIN32(GetLastError());
  570. goto Exit;
  571. }
  572. // form friendly displayable URL (ie. decode) in browser mode
  573. hr = UrlUnescapeW((LPWSTR)GetURL(), szDisplayUrl, &cchDisplayUrl, 0);
  574. Assert(!GetCodeDownload()->IsSilentMode() || hWnd == INVALID_HANDLE_VALUE);
  575. // Try to get a catalog file
  576. szCatalogFile = GetCodeDownload()->GetCatalogFile();
  577. hr = m_wvt.VerifyTrust(hFile, hWnd, &m_pbJavaTrust, szDisplayUrl,
  578. GetCodeDownload()->GetClientBinding()->GetHostSecurityManager(),
  579. (char *)GetFileName(), szCatalogFile, this);
  580. if(SUCCEEDED(hr)) {
  581. SetTrustVerified();
  582. } else {
  583. // trust failed on this file. Delete it from the cache for
  584. // added safety.
  585. // remove entry from cache only if we're not in silent mode.
  586. // or we are in silent mode and the hr != TRUST_E_SUBJECT_NOT_TRUSTED
  587. // when ui choice is NONE, WVT reurns the special error code to
  588. // mean that all was OK but could not trust because we did not
  589. // allow them to put up confirmation UI.
  590. if (!GetCodeDownload()->IsSilentMode())
  591. {
  592. CHAR szURL[INTERNET_MAX_URL_LENGTH];
  593. DWORD cchURL = INTERNET_MAX_URL_LENGTH;
  594. WideCharToMultiByte(CP_ACP, 0, GetURL(), -1, szURL,
  595. INTERNET_MAX_URL_LENGTH, 0,0);
  596. // If we still have the file open when we call DeleteUrlCacheEntry, then
  597. // WinInet won't be able to delete it. Having untrusted bits in the cache
  598. // is dangerous.
  599. if ( hFile != INVALID_HANDLE_VALUE)
  600. {
  601. CloseHandle(hFile);
  602. hFile = INVALID_HANDLE_VALUE;
  603. }
  604. DeleteUrlCacheEntryA(szURL);
  605. }
  606. else
  607. GetCodeDownload()->SetTrustSomeFailed();
  608. }
  609. Exit:
  610. // reset status to resume the rest of download if we're in
  611. // silent mode
  612. if (GetCodeDownload()->IsSilentMode() && FAILED(hr) && (hr != E_ABORT))
  613. hr = S_OK;
  614. if (tls->pTrustCookie->IsOwner(this)) {
  615. tls->pTrustCookie->Relinquish(this);
  616. }
  617. if (SUCCEEDED(hr)) {
  618. CCDLPacket *pPkt= new CCDLPacket(CODE_DOWNLOAD_PROCESS_PIECE, this, 0);
  619. if (pPkt) {
  620. hr = pPkt->Post();
  621. } else {
  622. hr = E_OUTOFMEMORY;
  623. }
  624. }
  625. if (FAILED(hr)) {
  626. // does all the master state analysis
  627. CompleteSignal(hr, S_OK, S_OK, NULL);
  628. }
  629. if ( hFile != INVALID_HANDLE_VALUE)
  630. CloseHandle(hFile);
  631. DEBUG_LEAVE(0);
  632. return;
  633. }
  634. // ---------------------------------------------------------------------------
  635. // %%Function: CDownload::SetCdlProtocol
  636. // ---------------------------------------------------------------------------
  637. HRESULT
  638. CDownload::SetUsingCdlProtocol(LPWSTR wszDistUnit)
  639. {
  640. DEBUG_ENTER((DBG_DOWNLOAD,
  641. Hresult,
  642. "CDownload::SetUsingCdlProtocol",
  643. "this=%#x, %.80wq",
  644. this, wszDistUnit
  645. ));
  646. HRESULT hr = S_OK;
  647. m_wszDistUnit = new WCHAR [lstrlenW(wszDistUnit) + 1];
  648. if (m_wszDistUnit)
  649. StrCpyW(m_wszDistUnit, wszDistUnit);
  650. else
  651. hr = E_OUTOFMEMORY;
  652. m_flags |= DL_FLAGS_CDL_PROTOCOL;
  653. DEBUG_LEAVE(hr);
  654. return hr;
  655. }
  656. // ---------------------------------------------------------------------------
  657. // %%Function: CDownload::ExtractManifest()
  658. // ---------------------------------------------------------------------------
  659. HRESULT
  660. CDownload::ExtractManifest(FILEXTN extn, LPSTR szFileName, LPSTR& pBaseFileName)
  661. {
  662. DEBUG_ENTER((DBG_DOWNLOAD,
  663. Hresult,
  664. "CDownload::ExtractManifest",
  665. "this=%#x, %#x, %.80q, %#x",
  666. this, extn, szFileName, &pBaseFileName
  667. ));
  668. CCodeDownload *pcdl = GetCodeDownload();
  669. char * pFileName;
  670. PSESSION psess = NULL;
  671. PFNAME pf = NULL;
  672. HRESULT hr = S_FALSE; // assume not found
  673. Assert(m_psess);
  674. for (pf = m_psess->pFileList; pf != NULL; pf = pf->pNextName) {
  675. FILEXTN curextn = ::GetExtnAndBaseFileName(pf->pszFilename,
  676. &pBaseFileName);
  677. if (( curextn == extn) &&
  678. ((szFileName[0] == '\0') ||
  679. (lstrcmpi(szFileName, pBaseFileName) == 0))) {
  680. FNAME fne;
  681. memset(&fne, 0, sizeof(FNAME));
  682. fne.pszFilename = pf->pszFilename;
  683. // INF present in CAB, extract it and process it
  684. m_psess->pFilesToExtract = &fne;
  685. m_psess->flags &= ~SESSION_FLAG_ENUMERATE; // already enumerated
  686. if (FAILED((hr=ExtractFromCabinet(m_psess, GetFileName()))))
  687. goto Exit;
  688. // side effect!
  689. // if extract succeeds we also have set the return hr to S_OK.
  690. // hr = S_OK;
  691. m_psess->pFilesToExtract = NULL;
  692. if (!catDirAndFile(szFileName, MAX_PATH, m_psess->achLocation,
  693. pf->pszFilename)) {
  694. hr = E_UNEXPECTED;
  695. }
  696. goto Exit;
  697. }
  698. }
  699. Exit:
  700. DEBUG_LEAVE(hr);
  701. return hr;
  702. }
  703. // ---------------------------------------------------------------------------
  704. // %%Function: CDownload::ProcessPiece
  705. // CBSC::OnStopBinding calls us as soon as a piece gets downloaded
  706. // and trust is verified.
  707. // ie. this CDownload obj has completed binding
  708. // Depending on the Content type we will process further
  709. // This triggers a change state in our state machine. Depending on the
  710. // obj we have downloaded (a CAB or INF or DLL/OCX/EXE) we:
  711. //
  712. // OCX:
  713. // Csetup for this download is usually previously created
  714. // mark this download as done and
  715. // call into main CodeDownload::CompleteOne (state analyser)
  716. //
  717. // CAB:
  718. // if we don't have an INF already we look for one in the CAB
  719. // if INF in CAB
  720. // process INF (may trigger further extractions/downloads/Csetup)
  721. // else
  722. // look for primary OCX in CAB and create CSetup or it.
  723. //
  724. // INF:
  725. // Process INF
  726. //
  727. // ---------------------------------------------------------------------------
  728. VOID
  729. CDownload::ProcessPiece()
  730. {
  731. DEBUG_ENTER((DBG_DOWNLOAD,
  732. None,
  733. "CDownload::ProcessPiece",
  734. "this=%#x",
  735. this
  736. ));
  737. CCodeDownload *pcdl = GetCodeDownload();
  738. char * pFileName;
  739. char *pBaseFileName;
  740. PSESSION psess = NULL;
  741. PFNAME pf = NULL;
  742. HRESULT hr = S_OK; // assume all OK
  743. CSetup *pSetup;
  744. char szBuf[INTERNET_MAX_URL_LENGTH];
  745. char szCatalogBuf[INTERNET_MAX_URL_LENGTH];
  746. FILEXTN extn = m_extn;
  747. if ( GetDLState() == DLSTATE_ABORT) {
  748. hr = E_ABORT;
  749. goto Exit;
  750. }
  751. //REVIEW: Virus scanning a CAB or INF file may not be a bright thing to do since
  752. // they are not executable.
  753. if (FAILED(hr = PerformVirusScan((char *)GetFileName()))) {
  754. goto Exit;
  755. }
  756. switch (extn) {
  757. case FILEXTN_EXE:
  758. case FILEXTN_OCX:
  759. case FILEXTN_DLL:
  760. case FILEXTN_NONE:
  761. case FILEXTN_UNKNOWN:
  762. pSetup = GetSetupHead();
  763. if (pSetup) {
  764. // If a CSetup exists for this m_pdl then initialize its
  765. // m_pSrcFileName using the m_pFileName
  766. Assert(pSetup->GetNext() == NULL);
  767. pSetup->SetSrcFileName(GetFileName());
  768. } else {
  769. if (!HasAllActiveXPermissions()) {
  770. if (GetCodeDownload()->IsSilentMode())
  771. {
  772. GetCodeDownload()->SetBitsInCache();
  773. }
  774. hr = TRUST_E_FAIL;
  775. goto Exit;
  776. }
  777. // If no CSetup exists then make one and attach it to the m_pdl
  778. // initiated at top level
  779. hr = GetFriendlyName(szBuf, &pBaseFileName);
  780. if (pBaseFileName[0] == '\0') {
  781. hr = E_UNEXPECTED; // No filename to setup!
  782. goto Exit;
  783. }
  784. if (FAILED(hr)) {
  785. goto Exit;
  786. }
  787. pSetup = new CSetup(GetFileName(), pBaseFileName, extn,
  788. pcdl->GetDestDirHint(), &hr);
  789. if (!pSetup) {
  790. hr = E_OUTOFMEMORY;
  791. goto Exit;
  792. } else if (FAILED(hr)) {
  793. delete pSetup;
  794. goto Exit;
  795. }
  796. AddSetupToList(pSetup);
  797. }
  798. break;
  799. case FILEXTN_CAB:
  800. // if CAB then make SESSION for this CDownload
  801. Assert(!(GetSession()));
  802. psess = new SESSION;
  803. if (!psess) {
  804. hr = E_OUTOFMEMORY;
  805. goto Exit;
  806. }
  807. SetSession(psess);
  808. // Initialize the structure
  809. psess->pFileList = NULL;
  810. psess->cFiles = 0;
  811. psess->cbCabSize = 0;
  812. psess->flags = SESSION_FLAG_ENUMERATE;
  813. // extract files in a CAB into a unique dir so that
  814. // parallel downloads of CABs containing same name
  815. // components can go on without conflict.
  816. // By serailizing the setup phase we make sure the right
  817. // latest version is finally left on client machine.
  818. hr = MakeUniqueTempDirectory(g_szOCXTempDir, psess->achLocation, sizeof(psess->achLocation));
  819. if (FAILED(hr)) {
  820. goto Exit;
  821. }
  822. psess->pFilesToExtract = NULL; // just enumerate first
  823. if (!pcdl->HaveManifest() || NeedToExtractAllFiles()) {
  824. psess->flags |= SESSION_FLAG_EXTRACT_ALL;
  825. }
  826. // enumerate the files of the CAB
  827. if (FAILED((hr = ExtractFromCabinet(psess, GetFileName()))))
  828. goto Exit;
  829. if (!pcdl->HaveManifest() || NeedToExtractAllFiles()) {
  830. psess->flags |= SESSION_FLAG_EXTRACTED_ALL;
  831. }
  832. // if we don't have INF already look for one
  833. if (!pcdl->HaveManifest()) {
  834. // Extract catalog file
  835. szCatalogBuf[0] = '\0';
  836. if (ExtractManifest(FILEXTN_CAT, szCatalogBuf, pBaseFileName) == S_OK) {
  837. if (FAILED(pcdl->SetCatalogFile(szCatalogBuf))) {
  838. goto Exit;
  839. }
  840. }
  841. szBuf[0] = '\0';
  842. hr = ExtractManifest(FILEXTN_OSD , szBuf, pBaseFileName);
  843. if (FAILED(hr))
  844. goto Exit;
  845. if (hr == S_FALSE) {
  846. szBuf[0] = '\0';
  847. // if no dist unit profile, process old INF
  848. hr = ExtractManifest(FILEXTN_INF , szBuf, pBaseFileName);
  849. if (FAILED(hr))
  850. goto Exit;
  851. if (hr == S_OK) {
  852. hr=pcdl->SetupInf(szBuf, pBaseFileName, this);
  853. goto Exit;
  854. }
  855. } else {
  856. // process dist unit profile
  857. hr=pcdl->ParseOSD(szBuf, pBaseFileName, this);
  858. goto Exit;
  859. }
  860. if (!pcdl->HaveManifest()) { // still don't have an INF?
  861. if (!HasAllActiveXPermissions()) {
  862. if (GetCodeDownload()->IsSilentMode())
  863. {
  864. GetCodeDownload()->SetBitsInCache();
  865. }
  866. hr = TRUST_E_FAIL;
  867. goto Exit;
  868. }
  869. // only valid case at this point is
  870. // case where we have a CAB file with ONE file in it
  871. if (psess->cFiles != 1) {
  872. hr = E_INVALIDARG;
  873. goto Exit;
  874. }
  875. pf = psess->pFilesToExtract = psess->pFileList;
  876. psess->flags &= ~SESSION_FLAG_ENUMERATE; // already enumerated
  877. if (FAILED((hr=ExtractFromCabinet(psess, GetFileName()))))
  878. goto Exit;
  879. extn = GetExtnAndBaseFileName(pf->pszFilename, &pBaseFileName);
  880. if (!catDirAndFile(szBuf, MAX_PATH, psess->achLocation,
  881. pf->pszFilename)) {
  882. hr = E_UNEXPECTED;
  883. goto Exit;
  884. }
  885. psess->pFilesToExtract = NULL;
  886. pSetup = new CSetup(szBuf, pBaseFileName, extn,
  887. pcdl->GetDestDirHint(), &hr);
  888. if (!pSetup) {
  889. hr = E_OUTOFMEMORY;
  890. goto Exit;
  891. } else if (FAILED(hr)) {
  892. delete pSetup;
  893. goto Exit;
  894. }
  895. AddSetupToList(pSetup);
  896. }
  897. } else { /* have inf */
  898. // INF processor would have made Csetup already
  899. psess->pFilesToExtract = GetFilesToExtract();
  900. if (!psess->pFilesToExtract) {
  901. // no files to extract, means there was only a hook
  902. // in this CAB and no other particular files
  903. // the general code downloader is looking for
  904. // so no setup work either.
  905. Assert(NeedToExtractAllFiles());
  906. break;
  907. }
  908. psess->flags &= ~SESSION_FLAG_ENUMERATE; // already enumerated
  909. CSetup *pSetupCur = m_pSetuphead;
  910. Assert(m_pSetuphead);
  911. // set fully qual names for all of these
  912. for (; pSetupCur; pSetupCur = pSetupCur->GetNext()) {
  913. if (!catDirAndFile(szBuf, MAX_PATH, m_psess->achLocation,
  914. (LPSTR)pSetupCur->GetSrcFileName())) {
  915. hr = E_UNEXPECTED;
  916. goto Exit;
  917. }
  918. pSetupCur->SetSrcFileName(szBuf);
  919. }
  920. if (FAILED((hr=ExtractFromCabinet(psess, GetFileName()))))
  921. goto Exit;
  922. }
  923. break;
  924. case FILEXTN_INF:
  925. if(pcdl->HaveManifest()) {
  926. hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  927. goto Exit;
  928. }
  929. hr = GetFriendlyName(szBuf, &pBaseFileName);
  930. if (FAILED(hr)) {
  931. goto Exit;
  932. }
  933. // get friendly name for INF from URL
  934. hr=pcdl->SetupInf(GetFileName(), pBaseFileName, this);
  935. if (FAILED(hr)) {
  936. SetDLState(DLSTATE_DONE);
  937. }
  938. goto Exit;
  939. case FILEXTN_OSD:
  940. if(pcdl->HaveManifest()) {
  941. hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  942. goto Exit;
  943. }
  944. hr = GetFriendlyName(szBuf, &pBaseFileName);
  945. if (FAILED(hr)) {
  946. goto Exit;
  947. }
  948. // get friendly name for OSD from URL
  949. hr=pcdl->ParseOSD(GetFileName(), pBaseFileName, this);
  950. goto Exit;
  951. } /* end switch (extn) */
  952. // done with this CDownload. Mark it ready for setup
  953. SetDLState(DLSTATE_READY_TO_SETUP);
  954. Assert(SUCCEEDED(hr));
  955. Exit:
  956. if ( (FAILED(hr)) || (GetDLState() == DLSTATE_READY_TO_SETUP)) {
  957. CompleteSignal(hr, S_OK, S_OK, NULL);
  958. }
  959. // if success setupInf would have dispatched a msg for
  960. // INF processing and only when that completes this
  961. // CDownload is deemed completed/ready_to_setup
  962. DEBUG_LEAVE(0);
  963. return;
  964. }
  965. // ---------------------------------------------------------------------------
  966. // %%Function: CDownload::SetURLAndExnt(LPCWSTR szURL, FILEXTN extn);
  967. // ---------------------------------------------------------------------------
  968. HRESULT
  969. CDownload::SetURLAndExtn(LPCWSTR szURL, FILEXTN extn)
  970. {
  971. DEBUG_ENTER((DBG_DOWNLOAD,
  972. Hresult,
  973. "CDownload::ProcessPiece",
  974. "this=%#x, %.80wq, %#x",
  975. this, szURL, extn
  976. ));
  977. m_extn = extn;
  978. if (!szURL)
  979. {
  980. DEBUG_LEAVE(S_OK);
  981. return S_OK;
  982. }
  983. DWORD len = lstrlenW(szURL); // make private copy
  984. LPWSTR lpch = new WCHAR [len + 1];
  985. if (!lpch)
  986. {
  987. DEBUG_LEAVE(E_OUTOFMEMORY);
  988. return E_OUTOFMEMORY;
  989. }
  990. StrCpyW(lpch, szURL);
  991. if (m_url)
  992. SAFEDELETE(m_url);
  993. m_url = lpch;
  994. DEBUG_LEAVE(S_OK);
  995. return S_OK;
  996. }
  997. // ---------------------------------------------------------------------------
  998. // %%Function: CDownload::CheckForNameCollision(LPCSTR szCacheDir);
  999. // for each in list CSetup::CheckForNameCollision
  1000. // ---------------------------------------------------------------------------
  1001. HRESULT
  1002. CDownload::CheckForNameCollision(LPCSTR szCacheDir)
  1003. {
  1004. DEBUG_ENTER((DBG_DOWNLOAD,
  1005. Hresult,
  1006. "CDownload::CheckForNameCollision",
  1007. "this=%#x, %.80q",
  1008. this, szCacheDir
  1009. ));
  1010. CSetup *pSetupCur = m_pSetuphead;
  1011. HRESULT hr = S_OK;
  1012. for (pSetupCur = m_pSetuphead; pSetupCur; pSetupCur =pSetupCur->GetNext()) {
  1013. if ((hr=pSetupCur->CheckForNameCollision(GetCodeDownload(), szCacheDir)) == S_FALSE)
  1014. break;
  1015. }
  1016. DEBUG_LEAVE(hr);
  1017. return hr;
  1018. }
  1019. // ---------------------------------------------------------------------------
  1020. // %%Function: CDownload::FindJavaSetup
  1021. // ---------------------------------------------------------------------------
  1022. CJavaSetup*
  1023. CDownload::FindJavaSetup(LPCWSTR szPackageName)
  1024. {
  1025. DEBUG_ENTER((DBG_DOWNLOAD,
  1026. Pointer,
  1027. "CDownload::FindJavaSetup",
  1028. "this=%#x, %.80wq",
  1029. this, szPackageName
  1030. ));
  1031. HRESULT hr = S_OK;
  1032. CJavaSetup *pjs = NULL;
  1033. if (!szPackageName)
  1034. {
  1035. DEBUG_LEAVE(NULL);
  1036. return NULL;
  1037. }
  1038. int iNumJavaSetup = m_JavaSetupList.GetCount();
  1039. LISTPOSITION curpos = m_JavaSetupList.GetHeadPosition();
  1040. for (int i=0; i < iNumJavaSetup; i++) {
  1041. pjs = m_JavaSetupList.GetNext(curpos);
  1042. if (pjs->GetPackageName() && (StrCmpIW(szPackageName, pjs->GetPackageName()) == 0)) {
  1043. DEBUG_LEAVE(pjs);
  1044. return pjs;
  1045. }
  1046. }
  1047. DEBUG_LEAVE(NULL);
  1048. return NULL;
  1049. }
  1050. // ---------------------------------------------------------------------------
  1051. // %%Function: CDownload::FindHook
  1052. // ---------------------------------------------------------------------------
  1053. CSetupHook*
  1054. CDownload::FindHook(LPCSTR szHook)
  1055. {
  1056. DEBUG_ENTER((DBG_DOWNLOAD,
  1057. Pointer,
  1058. "CDownload::FindHook",
  1059. "this=%#x, %.80q",
  1060. this, szHook
  1061. ));
  1062. HRESULT hr = S_OK;
  1063. CSetupHook *psh = NULL;
  1064. if (!szHook)
  1065. {
  1066. DEBUG_LEAVE(NULL);
  1067. return NULL;
  1068. }
  1069. int iNumHooks = m_SetupHooks.GetCount();
  1070. LISTPOSITION curpos = m_SetupHooks.GetHeadPosition();
  1071. for (int i=0; i < iNumHooks; i++) {
  1072. psh = m_SetupHooks.GetNext(curpos);
  1073. if (psh->GetHookName() && (lstrcmpi(szHook, psh->GetHookName()) == 0)) {
  1074. DEBUG_LEAVE(psh);
  1075. return psh;
  1076. }
  1077. }
  1078. DEBUG_LEAVE(NULL);
  1079. return NULL;
  1080. }
  1081. // ---------------------------------------------------------------------------
  1082. // %%Function: CDownload::DoSetup
  1083. // ---------------------------------------------------------------------------
  1084. HRESULT
  1085. CDownload::DoSetup()
  1086. {
  1087. DEBUG_ENTER((DBG_DOWNLOAD,
  1088. Hresult,
  1089. "CDownload::DoSetup",
  1090. "this=%#x",
  1091. this
  1092. ));
  1093. CSetup *pSetupCur = m_pSetuphead;
  1094. HRESULT hr = S_OK;
  1095. int nSetupsPerCall = 0;
  1096. int iNumHooks,i;
  1097. POSITION curpos;
  1098. SetDLState(DLSTATE_SETUP);
  1099. // SILENT MODE
  1100. // determine if we're in silent mode
  1101. if (GetCodeDownload()->IsSilentMode() && !GetCodeDownload()->IsAllTrusted())
  1102. {
  1103. SetDLState(DLSTATE_DONE);
  1104. DEBUG_LEAVE(hr);
  1105. return hr;
  1106. }
  1107. if (m_JavaSetupList.GetCount() != 0) {
  1108. CJavaSetup *pjs = m_JavaSetupList.GetHead();
  1109. curpos = m_JavaSetupList.GetHeadPosition();
  1110. BOOL bInstallReqd = FALSE;
  1111. if (pjs != NULL) {
  1112. for (int i=0; i< m_JavaSetupList.GetCount(); i++) {
  1113. CJavaSetup *pjs = m_JavaSetupList.GetNext(curpos);
  1114. Assert(pjs != NULL);
  1115. if (pjs->GetState() != INSTALL_DONE) {
  1116. bInstallReqd = TRUE;
  1117. break;
  1118. }
  1119. }
  1120. if (bInstallReqd) {
  1121. Assert(HasJavaPermissions());
  1122. // the below check is our final security test
  1123. // we should never need to test this in retail
  1124. // but, we do anyway
  1125. if (HasJavaPermissions())
  1126. hr = pjs->DoSetup();
  1127. else
  1128. hr = TRUST_E_FAIL;
  1129. if (FAILED(hr))
  1130. goto Exit;
  1131. else
  1132. {
  1133. DEBUG_LEAVE(S_OK);
  1134. return S_OK;
  1135. }
  1136. }
  1137. }
  1138. }
  1139. // done processing Java Setups
  1140. // process all hooks
  1141. iNumHooks = m_SetupHooks.GetCount();
  1142. curpos = m_SetupHooks.GetHeadPosition();
  1143. for (i=0; i < iNumHooks; i++) {
  1144. CSetupHook *psh = m_SetupHooks.GetNext(curpos);
  1145. if (psh->GetState() == INSTALL_DONE)
  1146. continue;
  1147. if (nSetupsPerCall++) {
  1148. // here if we have already done 1 hook and there's more to
  1149. // do in this CDownload
  1150. // we don't set DLState to DONE and just return
  1151. DEBUG_LEAVE(S_OK);
  1152. return S_OK;
  1153. }
  1154. Assert(HasAllActiveXPermissions());
  1155. // the below check is our final security test
  1156. // we should never need to test this in retail
  1157. // but, we do anyway
  1158. if (HasAllActiveXPermissions())
  1159. hr=psh->Run();
  1160. else
  1161. hr = TRUST_E_FAIL;
  1162. if (FAILED(hr))
  1163. goto Exit;
  1164. if (psh->GetState() != INSTALL_DONE) {
  1165. // more work left in this setup hook
  1166. // wait for next msg, don't mark ourselves done yet.
  1167. DEBUG_LEAVE(S_OK);
  1168. return S_OK;
  1169. }
  1170. }
  1171. // processed all Java Setups, hooks, now run setups
  1172. for (pSetupCur = m_pSetuphead; pSetupCur; pSetupCur = pSetupCur->GetNext()) {
  1173. if (pSetupCur->GetState() == INSTALL_DONE)
  1174. continue;
  1175. if (nSetupsPerCall++) {
  1176. // here if we have already done 1 setup and there's more to
  1177. // do in this CDownload
  1178. // we don't set DLState to DONE and just return
  1179. DEBUG_LEAVE(S_OK);
  1180. return S_OK;
  1181. }
  1182. if (m_bExactVersion) {
  1183. pSetupCur->SetExactVersion(TRUE);
  1184. }
  1185. if (pSetupCur->GetExtn() == FILEXTN_OSD) {
  1186. hr=pSetupCur->DoSetup(GetCodeDownload(), this);
  1187. } else {
  1188. Assert(HasAllActiveXPermissions());
  1189. // the below check is our final security test
  1190. // we should never need to test this in retail
  1191. // but, we do anyway
  1192. if (HasAllActiveXPermissions())
  1193. hr=pSetupCur->DoSetup(GetCodeDownload(), this);
  1194. else
  1195. hr = TRUST_E_FAIL;
  1196. }
  1197. if (FAILED(hr))
  1198. break;
  1199. if (pSetupCur->GetState() != INSTALL_DONE) {
  1200. // more work left in this CSetup (pSetupCur)
  1201. // wait for next msg, don't mark ourselves done yet.
  1202. DEBUG_LEAVE(S_OK);
  1203. return S_OK;
  1204. }
  1205. } /* for each CSetup */
  1206. Exit:
  1207. SetDLState(DLSTATE_DONE);
  1208. DEBUG_LEAVE(hr);
  1209. return hr;
  1210. }
  1211. // ---------------------------------------------------------------------------
  1212. // %%Function: CDownload::AddJavaSetup
  1213. //
  1214. // create and add a new JavaSetup to the list of setup hooks in this cab
  1215. // ---------------------------------------------------------------------------
  1216. HRESULT
  1217. CDownload::AddJavaSetup(
  1218. LPCWSTR szPackageName,
  1219. LPCWSTR szNameSpace,
  1220. IXMLElement *pPackage,
  1221. DWORD dwVersionMS,
  1222. DWORD dwVersionLS,
  1223. DWORD flags)
  1224. {
  1225. DEBUG_ENTER((DBG_DOWNLOAD,
  1226. Hresult,
  1227. "CDownload::AddJavaSetup",
  1228. "this=%#x, %.80wq, %.80wq, %#x, %#x, %#x, %#x",
  1229. this, szPackageName, szNameSpace, pPackage, dwVersionMS, dwVersionLS, flags
  1230. ));
  1231. HRESULT hr = S_OK;
  1232. CJavaSetup *pJavaSetup = NULL;
  1233. if (GetCodeDownload()->IsDuplicateJavaSetup(szPackageName) == S_OK) {
  1234. goto Exit;
  1235. }
  1236. // create a CJavaSetup OBJ and add it to the CDownload obj
  1237. pJavaSetup = new CJavaSetup(this, szPackageName, szNameSpace, pPackage, dwVersionMS, dwVersionLS, flags, &hr);
  1238. if(!pJavaSetup) {
  1239. hr = E_OUTOFMEMORY;
  1240. }
  1241. if (FAILED(hr)) {
  1242. SAFEDELETE(pJavaSetup);
  1243. goto Exit;
  1244. }
  1245. m_JavaSetupList.AddTail(pJavaSetup);
  1246. Exit:
  1247. DEBUG_LEAVE(hr);
  1248. return hr;
  1249. }
  1250. // ---------------------------------------------------------------------------
  1251. // %%Function: CDownload::AddHook
  1252. //
  1253. // create and add a new hook to the list of setup hooks in this cab
  1254. // ---------------------------------------------------------------------------
  1255. HRESULT
  1256. CDownload::AddHook(
  1257. LPCSTR szHook,
  1258. LPCSTR szInf,
  1259. LPCSTR szInfSection,
  1260. DWORD flags)
  1261. {
  1262. DEBUG_ENTER((DBG_DOWNLOAD,
  1263. Hresult,
  1264. "CDownload::AddHook",
  1265. "this=%#x, %.80wq, %.80wq, %.80wq, %#x",
  1266. this, szHook, szInf, szInfSection, flags
  1267. ));
  1268. HRESULT hr = S_OK;
  1269. CSetupHook *psh;
  1270. Assert(m_state != DLSTATE_EXTRACTING);
  1271. if (GetCodeDownload()->IsDuplicateHook(szHook) == S_OK) {
  1272. goto Exit;
  1273. }
  1274. if (m_extn == FILEXTN_CAB) { // if a CAB
  1275. if (m_state > DLSTATE_DOWNLOADED) {
  1276. // this CAB is ready, extract this code first
  1277. // BUGBUG: multi-threading issue: we are relying on
  1278. // not being re-enterant in our extraction
  1279. Assert(m_psess);
  1280. if (!m_psess) {
  1281. hr = E_UNEXPECTED;
  1282. goto Exit;
  1283. }
  1284. if (!(m_psess->flags & SESSION_FLAG_EXTRACTED_ALL)) {
  1285. m_psess->pFilesToExtract = NULL;
  1286. m_psess->flags &= ~SESSION_FLAG_ENUMERATE; // already enumerated
  1287. m_psess->flags |= SESSION_FLAG_EXTRACT_ALL;
  1288. if (FAILED((hr = ExtractFromCabinet(m_psess, m_pFileName)))) {
  1289. goto Exit;
  1290. }
  1291. m_psess->flags |= SESSION_FLAG_EXTRACTED_ALL;
  1292. }
  1293. } else {
  1294. // newly initiated download, mark CDownload as extract all.
  1295. SetNeedToExtractAll();
  1296. }
  1297. }
  1298. psh = new CSetupHook(this, szHook, szInf, szInfSection, flags, &hr);
  1299. if (psh && SUCCEEDED(hr)) {
  1300. m_SetupHooks.AddTail(psh);
  1301. } else {
  1302. if (psh)
  1303. delete psh;
  1304. hr = E_OUTOFMEMORY;
  1305. }
  1306. Exit:
  1307. DEBUG_LEAVE(hr);
  1308. return hr;
  1309. }
  1310. // ---------------------------------------------------------------------------
  1311. // %%Function: CDownload::AddSetupToExistingCAB
  1312. // if CAB is already downloaded
  1313. // extract file; create CSetup to install it (piggy back to pdl)
  1314. // else if some other CAB that has been set for download
  1315. // attach file to be extracted to pFilesToExtract
  1316. // attach a CSetup for this file
  1317. // else
  1318. // ---------------------------------------------------------------------------
  1319. HRESULT
  1320. CDownload::AddSetupToExistingCAB(char * lpCode, const char * szDestDir, DESTINATION_DIR dest, DWORD dwRegisterServer, DWORD dwCopyFlags)
  1321. {
  1322. DEBUG_ENTER((DBG_DOWNLOAD,
  1323. Hresult,
  1324. "CDownload::AddSetupToExistingCAB",
  1325. "this=%#x, %.80q, %.80q, %#x, %#x, %#x",
  1326. this, lpCode, szDestDir, dest, dwRegisterServer, dwCopyFlags
  1327. ));
  1328. char *pBaseFileName = lpCode;
  1329. FILEXTN extn;
  1330. HRESULT hr = NO_ERROR;
  1331. CSetup* pSetup = NULL;
  1332. char szBuf[MAX_PATH];
  1333. Assert(lpCode);
  1334. if (!lpCode) {
  1335. hr = E_INVALIDARG;
  1336. goto Exit;
  1337. }
  1338. if (IsDuplicateSetup(lpCode))
  1339. goto Exit;
  1340. // assumes that both CAB extraction and download
  1341. // are into same temp dir
  1342. // make a name for extraction ie: tempdir\curcode
  1343. extn = GetExtnAndBaseFileName( lpCode, &pBaseFileName);
  1344. // this check is totally legit : ie no race condition here
  1345. // we are on the main wininet thread and all onstopbindgs get
  1346. // posted on this thread. So a newly initialted download could not
  1347. // have completed, and even if so CAB extraction could not have started
  1348. Assert(m_state != DLSTATE_EXTRACTING);
  1349. Assert(m_state != DLSTATE_SETUP);
  1350. Assert(m_state != DLSTATE_DONE);
  1351. if (m_state > DLSTATE_DOWNLOADED) {
  1352. // part of CAB that the INF is in,
  1353. // or part of a CAB of some other code download that matches our spec.
  1354. // extract this code first
  1355. Assert(m_psess);
  1356. if (!m_psess) {
  1357. hr = E_UNEXPECTED;
  1358. goto Exit;
  1359. }
  1360. FNAME fname;
  1361. fname.pszFilename = pBaseFileName;
  1362. fname.pNextName = NULL;
  1363. fname.status = SFNAME_INIT;
  1364. m_psess->pFilesToExtract = &fname;
  1365. m_psess->flags &= ~SESSION_FLAG_ENUMERATE; // already enumerated
  1366. if (FAILED((hr = ExtractFromCabinet(m_psess, m_pFileName)))) {
  1367. goto Exit;
  1368. }
  1369. m_psess->pFilesToExtract = NULL;
  1370. } else {
  1371. // newly initiated download, piggy back to end of extraction list
  1372. PFNAME pf = new FNAME;
  1373. if (!pf) {
  1374. hr = E_OUTOFMEMORY;
  1375. goto Exit;
  1376. }
  1377. pf->pszFilename = new char [lstrlen(pBaseFileName)+1];
  1378. if (!pf->pszFilename) {
  1379. delete pf;
  1380. hr = E_OUTOFMEMORY;
  1381. goto Exit;
  1382. }
  1383. lstrcpy(pf->pszFilename, pBaseFileName);
  1384. pf->status = SFNAME_INIT;
  1385. pf->pNextName = m_pFilesToExtract; // add to list
  1386. m_pFilesToExtract = pf;
  1387. }
  1388. if (!catDirAndFile(szBuf, MAX_PATH,
  1389. (m_psess)?m_psess->achLocation:NULL, pBaseFileName)) {
  1390. hr = E_UNEXPECTED;
  1391. goto Exit;
  1392. }
  1393. // create a CSetup OBJ and add it to us
  1394. pSetup = new CSetup(szBuf, pBaseFileName, extn, szDestDir, &hr, dest);
  1395. if (!pSetup) {
  1396. hr = E_OUTOFMEMORY;
  1397. goto Exit;
  1398. } else if (FAILED(hr)) {
  1399. delete pSetup;
  1400. goto Exit;
  1401. }
  1402. AddSetupToList(pSetup);
  1403. pSetup->SetCopyFlags (dwCopyFlags);
  1404. if (dwRegisterServer) {
  1405. pSetup->SetUserOverrideRegisterServer(dwRegisterServer&CST_FLAG_REGISTERSERVER);
  1406. }
  1407. Exit:
  1408. DEBUG_LEAVE(hr);
  1409. return hr;
  1410. }
  1411. // ---------------------------------------------------------------------------
  1412. // %%Function: CDownload::IsDuplicateSetup
  1413. // ---------------------------------------------------------------------------
  1414. BOOL
  1415. CDownload::IsDuplicateSetup(LPCSTR pBaseFileName)
  1416. {
  1417. DEBUG_ENTER((DBG_DOWNLOAD,
  1418. Bool,
  1419. "CDownload::IsDuplicateSetup",
  1420. "this=%#x, %.80q",
  1421. this, pBaseFileName
  1422. ));
  1423. CSetup *pSetupCur = m_pSetuphead;
  1424. for (pSetupCur = m_pSetuphead; pSetupCur; pSetupCur=pSetupCur->GetNext()) {
  1425. if (lstrcmpi(pBaseFileName, pSetupCur->GetBaseFileName()) == 0)
  1426. {
  1427. DEBUG_LEAVE(TRUE);
  1428. return TRUE;
  1429. }
  1430. }
  1431. DEBUG_LEAVE(FALSE);
  1432. return FALSE;
  1433. }
  1434. // ---------------------------------------------------------------------------
  1435. // %%Function: CDownload::AddSetupToList
  1436. // ---------------------------------------------------------------------------
  1437. VOID
  1438. CDownload::AddSetupToList(CSetup *pSetup)
  1439. {
  1440. DEBUG_ENTER((DBG_DOWNLOAD,
  1441. None,
  1442. "CDownload::AddSetupToList",
  1443. "this=%#x, %#x",
  1444. this, pSetup
  1445. ));
  1446. pSetup->SetNext(m_pSetuphead);
  1447. m_pSetuphead = pSetup;
  1448. DEBUG_LEAVE(0);
  1449. }
  1450. // ---------------------------------------------------------------------------
  1451. // %%Function: CDownload::RemoveSetupFromList
  1452. // ---------------------------------------------------------------------------
  1453. HRESULT
  1454. CDownload::RemoveSetupFromList(CSetup *pSetup)
  1455. {
  1456. DEBUG_ENTER((DBG_DOWNLOAD,
  1457. Hresult,
  1458. "CDownload::RemoveSetupFromList",
  1459. "this=%#x, %#x",
  1460. this, pSetup
  1461. ));
  1462. CSetup *pSetupCur = m_pSetuphead;
  1463. HRESULT hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
  1464. Assert(pSetup);
  1465. Assert(pSetupCur); // empty list?
  1466. if (pSetupCur == pSetup) {
  1467. m_pSetuphead = pSetup->GetNext();
  1468. hr = S_OK;
  1469. goto Exit;
  1470. }
  1471. do {
  1472. if (pSetupCur->GetNext() == pSetup) {
  1473. pSetupCur->SetNext(pSetup->GetNext());
  1474. hr = S_OK;
  1475. goto Exit;
  1476. }
  1477. } while ( (pSetupCur = pSetupCur->GetNext()));
  1478. Exit:
  1479. DEBUG_LEAVE(hr);
  1480. return hr; // not found in list!
  1481. }
  1482. // ---------------------------------------------------------------------------
  1483. // %%Function: CDownload::CleanupFiles
  1484. // ---------------------------------------------------------------------------
  1485. HRESULT
  1486. CDownload::CleanupFiles()
  1487. {
  1488. DEBUG_ENTER((DBG_DOWNLOAD,
  1489. Hresult,
  1490. "CDownload::CleanupFiles",
  1491. "this=%#x",
  1492. this
  1493. ));
  1494. if (m_psess) { // CAB?
  1495. DeleteExtractedFiles(m_psess);
  1496. RemoveDirectoryAndChildren(m_psess->achLocation);
  1497. SAFEDELETE(m_psess);
  1498. }
  1499. if (!m_pSetuphead) {
  1500. if (m_pFileName) {
  1501. delete (LPSTR)m_pFileName;
  1502. m_pFileName = NULL;
  1503. }
  1504. } else {
  1505. CSetup *pSetupCur = m_pSetuphead;
  1506. CSetup *pSetupNext;
  1507. for (pSetupCur = m_pSetuphead; pSetupCur;
  1508. pSetupCur = pSetupNext) {
  1509. pSetupNext = pSetupCur->GetNext();
  1510. SAFEDELETE(pSetupCur);
  1511. }
  1512. }
  1513. if (m_pUnkForCacheFileRelease)
  1514. SAFERELEASE(m_pUnkForCacheFileRelease);
  1515. DEBUG_LEAVE(S_OK);
  1516. return S_OK;
  1517. }
  1518. // ---------------------------------------------------------------------------
  1519. // %%Function: CDownload::DoDownload
  1520. // CDownload is the basic download obj. It's action entry point is DoDownload
  1521. // Here it creates a URL moniker for the given m_url and a bind ctx to go
  1522. // with it and then calls pmk->BindToStorage to get the bits. Note how we
  1523. // use URL mon's services to get the bits even as URLmon is our client for
  1524. // the Code Download. We are its client for individual downloads. CDownload
  1525. // has a BSC implementation to track progress and completion. This BSC is
  1526. // where the magic of taking us from one state to next occurs.
  1527. //
  1528. // ---------------------------------------------------------------------------
  1529. HRESULT
  1530. CDownload::DoDownload(LPMONIKER *ppmkContext, DWORD grfBINDF,
  1531. CList<CCodeBaseHold *, CCodeBaseHold *> *pcbhList)
  1532. {
  1533. DEBUG_ENTER((DBG_DOWNLOAD,
  1534. Hresult,
  1535. "CDownload::DoDownload",
  1536. "this=%#x, %#x, %#x, %#x",
  1537. this, ppmkContext, grfBINDF, pcbhList
  1538. ));
  1539. HRESULT hr = NOERROR;
  1540. IBindHost *pBindHost = NULL;
  1541. m_pcbhList = pcbhList;
  1542. m_ppmkContext = ppmkContext;
  1543. m_grfBINDF = grfBINDF;
  1544. pBindHost = GetCodeDownload()->GetClientBinding()->GetIBindHost();
  1545. hr = CreateBindCtx(0, &m_pbc);
  1546. if (FAILED(hr)) {
  1547. goto Exit;
  1548. }
  1549. // register the format enumerator with the bind ctx if one exists
  1550. if (g_pEFmtETC) {
  1551. hr = RegisterFormatEnumerator(m_pbc, g_pEFmtETC, 0);
  1552. }
  1553. if( SUCCEEDED(hr) ) {
  1554. m_pbsc = new CBindStatusCallback(this, grfBINDF);
  1555. if (m_pbsc == NULL)
  1556. hr = E_OUTOFMEMORY;
  1557. if (!pBindHost)
  1558. if (SUCCEEDED(hr))
  1559. hr = RegisterBindStatusCallback(m_pbc, m_pbsc, 0, 0);
  1560. }
  1561. if (FAILED(hr)) {
  1562. goto Exit;
  1563. }
  1564. if (pBindHost) {
  1565. IMoniker *pmk;
  1566. hr = pBindHost->CreateMoniker(m_url, m_pbc, &pmk, 0);
  1567. if (FAILED(hr)) {
  1568. goto Exit;
  1569. }
  1570. if (*ppmkContext == NULL) { // no context moniker yet?
  1571. m_pmk = pmk;
  1572. m_ppmkContext = &pmk;
  1573. } else {
  1574. hr = (*ppmkContext)->ComposeWith(pmk, FALSE, &m_pmk);
  1575. pmk->Release();
  1576. }
  1577. } else {
  1578. hr = CreateURLMoniker(*ppmkContext, m_url, &m_pmk);
  1579. }
  1580. if( SUCCEEDED(hr) ) {
  1581. // store away the full URL
  1582. SAFEDELETE(m_url);
  1583. hr = m_pmk->GetDisplayName(m_pbc, NULL, &m_url);
  1584. if (FAILED(hr))
  1585. goto Exit;
  1586. // everything succeeded
  1587. if (*ppmkContext == NULL) { // no context moniker yet?
  1588. // make this the context moniker
  1589. *ppmkContext = m_pmk;
  1590. }
  1591. IUnknown *pUnk = NULL;
  1592. if (pBindHost) {
  1593. hr = pBindHost->MonikerBindToStorage(m_pmk, m_pbc, m_pbsc,
  1594. IID_IUnknown, (void **)&pUnk);
  1595. } else {
  1596. hr = m_pmk->BindToStorage(m_pbc, 0, IID_IUnknown, (void**)&pUnk);
  1597. }
  1598. // m_pbc will get the onstopbinding, ondatavailable, and onprogress
  1599. // messages and pass them on to m_pbsc; wait asynchronously
  1600. if (pUnk) {
  1601. pUnk->Release();
  1602. }
  1603. }
  1604. Exit:
  1605. if (FAILED(hr) && hr != E_PENDING) {
  1606. // real failure!
  1607. m_hrOSB = hr;
  1608. SetDLState(DLSTATE_DONE);
  1609. if (*ppmkContext == m_pmk)
  1610. *ppmkContext = NULL;
  1611. }
  1612. else {
  1613. /*
  1614. // everything succeeded
  1615. if (*ppmkContext == NULL) { // no context moniker yet?
  1616. // make this the context moniker
  1617. *ppmkContext = m_pmk;
  1618. }
  1619. */
  1620. hr = MK_S_ASYNCHRONOUS;
  1621. }
  1622. DEBUG_LEAVE(hr);
  1623. return hr;
  1624. } // CDownload::DoDownload
  1625. // ---------------------------------------------------------------------------
  1626. // %%Function: CDownload::PerformVirusScan
  1627. // S_OK : continue with operation
  1628. // S_FALSE : cancel operation.
  1629. // ---------------------------------------------------------------------------
  1630. HRESULT CDownload::PerformVirusScan(LPSTR szFileName)
  1631. {
  1632. DEBUG_ENTER((DBG_DOWNLOAD,
  1633. Hresult,
  1634. "CDownload::PerformVirusScan",
  1635. "this=%#x, %.80q",
  1636. this, szFileName
  1637. ));
  1638. HRESULT hr = S_OK, hrReturn = S_OK;
  1639. ICatInformation * pci = NULL; // category manager
  1640. IEnumCLSID * peclsid = NULL; // enum of av objects
  1641. IOfficeAntiVirus * poav = NULL; // current av interface
  1642. CLSID clsidCurrent; // current av clsid
  1643. ULONG pcFetched;
  1644. MSOAVINFO msavi; // antivirus struct
  1645. BOOL fInitStruct = FALSE;
  1646. //
  1647. // Get COM category manager and get an enumerator for our virus
  1648. // scanner category
  1649. //
  1650. // If something goes wrong finding AV objects, proceed as normal.
  1651. //
  1652. hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL,
  1653. CLSCTX_INPROC_SERVER, IID_ICatInformation, (void **)&pci);
  1654. if(FAILED(hr))
  1655. {
  1656. DEBUG_LEAVE(NOERROR);
  1657. return NOERROR;
  1658. }
  1659. hr = pci->EnumClassesOfCategories(1, (GUID *)&CATID_MSOfficeAntiVirus, 0, NULL, &peclsid);
  1660. pci->Release();
  1661. if(FAILED(hr))
  1662. {
  1663. DEBUG_LEAVE(NOERROR);
  1664. return NOERROR;
  1665. }
  1666. //
  1667. // Call all scanners. If any fail, return E_FAIL.
  1668. //
  1669. hr = peclsid->Next(1, &clsidCurrent, &pcFetched);
  1670. while(SUCCEEDED(hr) && pcFetched > 0)
  1671. {
  1672. if(FALSE == fInitStruct)
  1673. {
  1674. if (FAILED(Ansi2Unicode(szFileName,&msavi.u.pwzFullPath)))
  1675. {
  1676. break;
  1677. }
  1678. msavi.cbsize = sizeof(msavi);
  1679. msavi.fPath = TRUE;
  1680. msavi.fHttpDownload = TRUE;
  1681. msavi.fReadOnlyRequest = FALSE;
  1682. msavi.fInstalled = FALSE;
  1683. msavi.hwnd = GetCodeDownload()->GetClientBinding()->GetHWND();
  1684. msavi.pwzOrigURL = (LPWSTR)GetURL();
  1685. // per office spec, this is only meant as a method for the scanner
  1686. // to differentiate the caller. Not localized.
  1687. msavi.pwzHostName = L"Urlmon";
  1688. fInitStruct = TRUE;
  1689. }
  1690. // have clsid of av component
  1691. hr = CoCreateInstance(clsidCurrent, NULL, CLSCTX_INPROC_SERVER,
  1692. IID_IOfficeAntiVirus, (void **)&poav);
  1693. if(SUCCEEDED(hr))
  1694. {
  1695. // call scan method
  1696. hr = poav->Scan(&msavi);
  1697. poav->Release();
  1698. if(hr == E_FAIL)
  1699. {
  1700. // file could not be cleaned
  1701. hrReturn = E_FAIL;
  1702. }
  1703. }
  1704. hr = peclsid->Next(1, &clsidCurrent, &pcFetched);
  1705. }
  1706. //
  1707. // clean up
  1708. //
  1709. peclsid->Release();
  1710. if(fInitStruct)
  1711. {
  1712. SAFEDELETE(msavi.u.pwzFullPath);
  1713. }
  1714. DEBUG_LEAVE(hrReturn);
  1715. return hrReturn;
  1716. }
  1717. // ---------------------------------------------------------------------------
  1718. // %%Function: CDownload::DownloadRedundantCodeBase()
  1719. // Returns S_OK if starting next download, or S_FALSE if no redundant
  1720. // codebases remaining to try.
  1721. // ---------------------------------------------------------------------------
  1722. STDMETHODIMP CDownload::DownloadRedundantCodeBase()
  1723. {
  1724. DEBUG_ENTER((DBG_DOWNLOAD,
  1725. Hresult,
  1726. "CDownload::DownloadRedundantCodeBase",
  1727. "this=%#x",
  1728. this
  1729. ));
  1730. HRESULT hr = S_FALSE;
  1731. LISTPOSITION lpos = 0;
  1732. CCodeBaseHold *pcbh = NULL;
  1733. if (m_pcbhList == NULL) {
  1734. goto Exit;
  1735. }
  1736. lpos = m_pcbhList->GetHeadPosition();
  1737. while (lpos) {
  1738. pcbh = m_pcbhList->GetNext(lpos);
  1739. if (!(pcbh->dwFlags & CBH_FLAGS_DOWNLOADED)) {
  1740. RevokeBindStatusCallback(GetBindCtx(), GetBSC());
  1741. CleanUp();
  1742. m_url = new WCHAR[lstrlenW(pcbh->wszCodeBase) + 1];
  1743. if (m_url == NULL) {
  1744. hr = E_OUTOFMEMORY;
  1745. goto Exit;
  1746. }
  1747. StrCpyW(m_url, pcbh->wszCodeBase);
  1748. SetResponseHeaderStatus(S_OK);
  1749. pcbh->dwFlags |= CBH_FLAGS_DOWNLOADED;
  1750. // Try another download
  1751. hr = DoDownload(m_ppmkContext, m_grfBINDF, m_pcbhList);
  1752. break;
  1753. }
  1754. }
  1755. Exit:
  1756. if (hr == S_FALSE) {
  1757. GetCodeDownload()->CodeDownloadDebugOut(DEB_CODEDL, FALSE, ID_CDLDBG_DL_REDUNDANT_FAILED);
  1758. }
  1759. else {
  1760. LPSTR szUrl = NULL;
  1761. Unicode2Ansi(m_url, &szUrl);
  1762. GetCodeDownload()->CodeDownloadDebugOut(DEB_CODEDL, FALSE, ID_CDLDBG_DL_REDUNDANT, (szUrl == NULL) ? ("") : (szUrl), hr);
  1763. delete szUrl;
  1764. }
  1765. DEBUG_LEAVE(hr);
  1766. return hr;
  1767. }
  1768. void CDownload::CleanUp()
  1769. {
  1770. DEBUG_ENTER((DBG_DOWNLOAD,
  1771. None,
  1772. "CDownload::CleanUp",
  1773. "this=%#x",
  1774. this
  1775. ));
  1776. LISTPOSITION pos = 0;
  1777. int i, iNum;
  1778. SAFERELEASE(m_pmk);
  1779. SAFERELEASE(m_pbc);
  1780. SAFERELEASE(m_pbsc);
  1781. SAFEDELETE(m_url);
  1782. if (m_pFilesToExtract) {
  1783. PFNAME pf = m_pFilesToExtract;
  1784. PFNAME pfnext;
  1785. for (;pf != NULL; pf = pfnext) {
  1786. delete pf->pszFilename;
  1787. pfnext = pf->pNextName;
  1788. delete pf;
  1789. }
  1790. }
  1791. m_pFilesToExtract = NULL;
  1792. if (m_hPostData)
  1793. GlobalFree(m_hPostData);
  1794. SAFERELEASE(m_pUnkForCacheFileRelease);
  1795. SAFEDELETE(m_pbJavaTrust);
  1796. DEBUG_LEAVE(0);
  1797. }
  1798. HRESULT CDownload::SetMainCABJavaTrustPermissions(PJAVA_TRUST pbJavaTrust)
  1799. {
  1800. DEBUG_ENTER((DBG_DOWNLOAD,
  1801. None,
  1802. "CDownload::SetMainCABJavaTrustPermissions",
  1803. "this=%#x, %#x",
  1804. this, pbJavaTrust
  1805. ));
  1806. HRESULT hr = GetCodeDownload()->SetMainCABJavaTrustPermissions(pbJavaTrust);
  1807. DEBUG_LEAVE(hr);
  1808. return hr;
  1809. }
  1810. // ---------------------------------------------------------------------------
  1811. // %%Function: CBindStatusCallback::CBindStatusCallback
  1812. // The BSC implementation for CDownload to track progress of indiv dwlds
  1813. // ---------------------------------------------------------------------------
  1814. CBindStatusCallback::CBindStatusCallback(CDownload *pdl, DWORD grfBINDF)
  1815. {
  1816. DEBUG_ENTER((DBG_DOWNLOAD,
  1817. None,
  1818. "CBindStatusCallback::CBindStatusCallback",
  1819. "this=%#x, %#x, %#x",
  1820. this, pdl, grfBINDF
  1821. ));
  1822. DllAddRef();
  1823. m_pbinding = NULL;
  1824. m_cRef = 1; // equ of internal addref
  1825. m_pdl = pdl;
  1826. m_grfBINDF = grfBINDF;
  1827. DEBUG_LEAVE(0);
  1828. } // CBindStatusCallback
  1829. // ---------------------------------------------------------------------------
  1830. // %%Function: CBindStatusCallback::~CBindStatusCallback
  1831. // ---------------------------------------------------------------------------
  1832. CBindStatusCallback::~CBindStatusCallback()
  1833. {
  1834. DEBUG_ENTER((DBG_DOWNLOAD,
  1835. None,
  1836. "CBindStatusCallback::~CBindStatusCallback",
  1837. "this=%#x",
  1838. this
  1839. ));
  1840. SAFERELEASE(m_pbinding);
  1841. DllRelease();
  1842. DEBUG_LEAVE(0);
  1843. } // ~CBindStatusCallback
  1844. // ---------------------------------------------------------------------------
  1845. // %%Function: CBindStatusCallback::AddRef
  1846. // ---------------------------------------------------------------------------
  1847. STDMETHODIMP_(ULONG)
  1848. CBindStatusCallback::AddRef()
  1849. {
  1850. DEBUG_ENTER((DBG_DOWNLOAD,
  1851. Dword,
  1852. "CBindStatusCallback::IUnknown::AddRef",
  1853. "this=%#x",
  1854. this
  1855. ));
  1856. ULONG ulRet = m_cRef++;
  1857. DEBUG_LEAVE(ulRet);
  1858. return ulRet;
  1859. }
  1860. // ---------------------------------------------------------------------------
  1861. // %%Function: CBindStatusCallback::Release
  1862. // ---------------------------------------------------------------------------
  1863. STDMETHODIMP_(ULONG)
  1864. CBindStatusCallback::Release()
  1865. {
  1866. DEBUG_ENTER((DBG_DOWNLOAD,
  1867. Dword,
  1868. "CBindStatusCallback::IUnknown::Release",
  1869. "this=%#x",
  1870. this
  1871. ));
  1872. if (--m_cRef == 0) {
  1873. delete this;
  1874. DEBUG_LEAVE(0);
  1875. return 0;
  1876. }
  1877. DEBUG_LEAVE(m_cRef);
  1878. return m_cRef;
  1879. }
  1880. // ---------------------------------------------------------------------------
  1881. // %%Function: CBindStatusCallback::QueryInterface
  1882. // ---------------------------------------------------------------------------
  1883. STDMETHODIMP
  1884. CBindStatusCallback::QueryInterface(REFIID riid, void** ppv)
  1885. {
  1886. DEBUG_ENTER((DBG_DOWNLOAD,
  1887. Hresult,
  1888. "CBindStatusCallback::IUnknown::QueryInterface",
  1889. "this=%#x, %#x, %#x",
  1890. this, &riid, ppv
  1891. ));
  1892. *ppv = NULL;
  1893. if (riid==IID_IUnknown || riid==IID_IBindStatusCallback)
  1894. *ppv = (IBindStatusCallback *)this;
  1895. if (riid==IID_IHttpNegotiate)
  1896. *ppv = (IHttpNegotiate *)this;
  1897. if (riid==IID_IWindowForBindingUI)
  1898. *ppv = (IWindowForBindingUI*)this;
  1899. if (riid==IID_IServiceProvider)
  1900. *ppv = (IServiceProvider *)this;
  1901. if (riid==IID_ICatalogFileInfo)
  1902. *ppv = (ICatalogFileInfo *)this;
  1903. if (*ppv == NULL)
  1904. {
  1905. DEBUG_LEAVE(E_NOINTERFACE);
  1906. return E_NOINTERFACE;
  1907. }
  1908. AddRef();
  1909. DEBUG_LEAVE(S_OK);
  1910. return S_OK;
  1911. } // CBindStatusCallback::QueryInterface
  1912. // ---------------------------------------------------------------------------
  1913. // %%Function: CBindStatusCallback::GetWindow
  1914. // ---------------------------------------------------------------------------
  1915. STDMETHODIMP
  1916. CBindStatusCallback::GetWindow(REFGUID rguidreason, HWND *phWnd)
  1917. {
  1918. DEBUG_ENTER((DBG_DOWNLOAD,
  1919. Hresult,
  1920. "CBindStatusCallback::IWindowForBindingUI::GetWindow",
  1921. "this=%#x, %#x, %#x",
  1922. this, &rguidreason, phWnd
  1923. ));
  1924. HRESULT hr = S_OK;
  1925. CCodeDownload *pcdl = m_pdl->GetCodeDownload();
  1926. HWND hWnd = pcdl->GetClientBinding()->GetHWND(rguidreason);
  1927. if (hWnd == INVALID_HANDLE_VALUE)
  1928. hr = S_FALSE;
  1929. *phWnd = hWnd;
  1930. DEBUG_LEAVE(hr);
  1931. return hr;
  1932. }
  1933. // ---------------------------------------------------------------------------
  1934. // %%Function: CBindStatusCallback::QueryService
  1935. // ---------------------------------------------------------------------------
  1936. STDMETHODIMP
  1937. CBindStatusCallback::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppv)
  1938. {
  1939. DEBUG_ENTER((DBG_DOWNLOAD,
  1940. Hresult,
  1941. "CBindStatusCallback::IServiceProvider::QueryService",
  1942. "this=%#x, %#x, %#x, %#x",
  1943. this, &guidService, &riid, ppv
  1944. ));
  1945. IBindStatusCallback *pbsc = m_pdl->GetCodeDownload()->GetClientBSC();
  1946. IServiceProvider *psp = NULL;
  1947. HRESULT hr = E_NOINTERFACE;
  1948. ASSERT(pbsc);
  1949. if (pbsc && SUCCEEDED(pbsc->QueryInterface(IID_IServiceProvider, (void **)&psp)) && psp) {
  1950. hr = psp->QueryService(guidService, riid, ppv);
  1951. SAFERELEASE(psp);
  1952. }
  1953. // Since this is QueryService we can QI on our client's BSC object too.
  1954. if (FAILED(hr)) {
  1955. // This is special case we handle so we can bind to client's ultimate IBindHost
  1956. // if one exists. BUG BUG: Support other interfaces here, in general?
  1957. // BUG BUG: Rearrange order of comparisons for performance.
  1958. if (IsEqualGUID(guidService, riid) &&
  1959. (IsEqualGUID(riid, IID_IBindHost) ||
  1960. IsEqualGUID(riid, IID_IWindowForBindingUI) ||
  1961. IsEqualGUID(riid, IID_ICodeInstall) ||
  1962. IsEqualGUID(riid, IID_ICatalogFileInfo) ||
  1963. IsEqualGUID(riid, IID_IInternetHostSecurityManager))) {
  1964. hr = pbsc->QueryInterface(riid, (void **)ppv);
  1965. }
  1966. }
  1967. DEBUG_LEAVE(hr);
  1968. return hr;
  1969. }
  1970. // ---------------------------------------------------------------------------
  1971. // %%Function: CBindStatusCallback::GetBindInfo
  1972. // ---------------------------------------------------------------------------
  1973. STDMETHODIMP
  1974. CBindStatusCallback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindInfo)
  1975. {
  1976. DEBUG_ENTER((DBG_DOWNLOAD,
  1977. Hresult,
  1978. "CBindStatusCallback::IBindingStatusCallback::GetBindInfo",
  1979. "this=%#x, %#x, %#x",
  1980. this, pgrfBINDF, pbindInfo
  1981. ));
  1982. if ((pgrfBINDF == NULL) || (pbindInfo == NULL) || (pbindInfo->cbSize == 0))
  1983. {
  1984. DEBUG_LEAVE(E_INVALIDARG);
  1985. return E_INVALIDARG;
  1986. }
  1987. *pgrfBINDF = m_grfBINDF;
  1988. // clear BINDINFO but keep its size
  1989. DWORD cbSize = pbindInfo->cbSize;
  1990. ZeroMemory( pbindInfo, cbSize );
  1991. pbindInfo->cbSize = cbSize;
  1992. // use IE5's utf-8 policy
  1993. pbindInfo->dwOptions |= BINDINFO_OPTIONS_USE_IE_ENCODING;
  1994. if (m_pdl->DoPost()) {
  1995. pbindInfo->dwBindVerb = BINDVERB_POST;
  1996. pbindInfo->stgmedData.tymed = TYMED_HGLOBAL;
  1997. pbindInfo->stgmedData.hGlobal = m_pdl->GetPostData(&(pbindInfo->cbstgmedData));
  1998. pbindInfo->stgmedData.pUnkForRelease = (IUnknown *) (IBindStatusCallback *) this;
  1999. AddRef(); // AddRef ourselves so we stick around; caller must release!
  2000. }
  2001. DWORD grfBINDF = 0;
  2002. BINDINFO bindInfo;
  2003. memset(&bindInfo, 0, sizeof(BINDINFO));
  2004. bindInfo.cbSize = sizeof(BINDINFO);
  2005. CCodeDownload *pcdl = m_pdl->GetCodeDownload();
  2006. pcdl->GetClientBSC()->GetBindInfo(&grfBINDF, &bindInfo);
  2007. if (grfBINDF & BINDF_SILENTOPERATION)
  2008. {
  2009. *pgrfBINDF |= BINDF_SILENTOPERATION;
  2010. pcdl->SetSilentMode();
  2011. }
  2012. if (grfBINDF & BINDF_OFFLINEOPERATION)
  2013. *pgrfBINDF |= BINDF_OFFLINEOPERATION;
  2014. if (grfBINDF & BINDF_GETNEWESTVERSION)
  2015. *pgrfBINDF |= BINDF_GETNEWESTVERSION;
  2016. if (grfBINDF & BINDF_RESYNCHRONIZE)
  2017. *pgrfBINDF |= BINDF_RESYNCHRONIZE;
  2018. // or should we always insist on this regardless of what client wants?
  2019. if (grfBINDF & BINDF_PREFERDEFAULTHANDLER)
  2020. *pgrfBINDF |= BINDF_PREFERDEFAULTHANDLER;
  2021. if (grfBINDF & BINDF_ENFORCERESTRICTED)
  2022. *pgrfBINDF |= BINDF_ENFORCERESTRICTED;
  2023. // To make sure the file winds up on disk even for SSL connections, we need to add
  2024. *pgrfBINDF |= BINDF_NEEDFILE;
  2025. // BINDINFO_FIX(LaszloG 8/15/97)
  2026. ReleaseBindInfo(&bindInfo);
  2027. DEBUG_LEAVE(S_OK);
  2028. return S_OK;
  2029. } // CBindStatusCallback::GetBindInfo
  2030. // ---------------------------------------------------------------------------
  2031. // %%Function: CBindStatusCallback::OnStartBinding
  2032. // ---------------------------------------------------------------------------
  2033. STDMETHODIMP
  2034. CBindStatusCallback::OnStartBinding(DWORD grfBSCOPTION,IBinding* pbinding)
  2035. {
  2036. DEBUG_ENTER((DBG_DOWNLOAD,
  2037. Hresult,
  2038. "CBindStatusCallback::IBindingStatusCallback::OnStartBinding",
  2039. "this=%#x, %#x, %#x",
  2040. this, grfBSCOPTION, pbinding
  2041. ));
  2042. CCodeDownload *pcdl = m_pdl->GetCodeDownload();
  2043. Assert(pbinding);
  2044. if (m_pbinding != NULL)
  2045. SAFERELEASE(m_pbinding);
  2046. m_pbinding = pbinding;
  2047. if (m_pbinding != NULL)
  2048. m_pbinding->AddRef();
  2049. m_pdl->SetDLState(DLSTATE_BINDING);
  2050. // call the client BSC::OnStartBinding if not already done
  2051. CClBinding *pClientBinding = pcdl->GetClientBinding();
  2052. if(pClientBinding->GetState() == CDL_NoOperation){
  2053. Assert(pClientBinding->GetAssBSC() == pcdl->GetClientBSC());
  2054. pClientBinding->SetState(CDL_Downloading);
  2055. pcdl->AddRef();
  2056. pcdl->GetClientBSC()->OnStartBinding(grfBSCOPTION, pClientBinding);
  2057. }
  2058. DEBUG_LEAVE(S_OK);
  2059. return S_OK;
  2060. } // CBindStatusCallback::OnStartBinding
  2061. // ---------------------------------------------------------------------------
  2062. // %%Function: CBindStatusCallback::GetPriority
  2063. // ---------------------------------------------------------------------------
  2064. STDMETHODIMP
  2065. CBindStatusCallback::GetPriority(LONG* pnPriority)
  2066. {
  2067. DEBUG_ENTER((DBG_DOWNLOAD,
  2068. Hresult,
  2069. "CBindStatusCallback::IBindingStatusCallback::GetPriority",
  2070. "this=%#x, %#x",
  2071. this, pnPriority
  2072. ));
  2073. DEBUG_LEAVE(E_NOTIMPL);
  2074. return E_NOTIMPL;
  2075. } // CBindStatusCallback::GetPriority
  2076. // ---------------------------------------------------------------------------
  2077. // %%Function: CBindStatusCallback::OnProgress
  2078. // Here we get the master CodeDownload obj to collate progress and report
  2079. // cumulative code download progress to client BSC::OnProgress.
  2080. // ---------------------------------------------------------------------------
  2081. STDMETHODIMP
  2082. CBindStatusCallback::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
  2083. {
  2084. DEBUG_ENTER((DBG_DOWNLOAD,
  2085. Hresult,
  2086. "CBindStatusCallback::IBindingStatusCallback::GetPriority",
  2087. "this=%#x, %#x, %#x, %#x, %.80wq",
  2088. this, ulProgress, ulProgressMax, ulStatusCode, szStatusText
  2089. ));
  2090. IBindStatusCallback *pClientBSC = m_pdl->GetCodeDownload()->GetClientBSC();
  2091. char szURL[INTERNET_MAX_URL_LENGTH];
  2092. FILEXTN extn;
  2093. char *pBaseFileName;
  2094. HRESULT hr = S_OK;
  2095. IMoniker *pmk = NULL;
  2096. CCodeDownload *pcdl = m_pdl->GetCodeDownload();
  2097. // if this a redirect set the context appropriately
  2098. // also use this URL to get the extension and base dest name for this
  2099. // component, if its a POST (Search Path)
  2100. if (m_pdl->DoPost() && (ulStatusCode == BINDSTATUS_REDIRECTING)) {
  2101. WideCharToMultiByte(CP_ACP, 0, szStatusText, -1, szURL,
  2102. INTERNET_MAX_URL_LENGTH, 0,0);
  2103. // BUGBUG: use mime type in response header to determine extn
  2104. extn = GetExtnAndBaseFileName( szURL, &pBaseFileName);
  2105. hr = m_pdl->SetURLAndExtn( szStatusText, extn);
  2106. if (SUCCEEDED(hr)) {
  2107. IBindHost *pBH = pcdl->GetClientBinding()->GetIBindHost();
  2108. if (pBH) {
  2109. hr = pBH->CreateMoniker((LPOLESTR)szStatusText, m_pdl->GetBindCtx(), &pmk, 0);
  2110. } else {
  2111. hr = CreateURLMoniker(NULL, szStatusText, &pmk);
  2112. }
  2113. if (SUCCEEDED(hr)) {
  2114. pcdl->SetContextMoniker(pmk);
  2115. pcdl->MarkNewContextMoniker();
  2116. }
  2117. }
  2118. if (FAILED(hr))
  2119. m_pdl->SetResponseHeaderStatus( hr );
  2120. }
  2121. // we are only interested in cumulative numbers for "downloading" status
  2122. // for all others progress is usually: "connecting: 0 of 0", so we
  2123. // pass these as is to our client
  2124. if ((ulStatusCode != BINDSTATUS_DOWNLOADINGDATA ) &&
  2125. (ulStatusCode != BINDSTATUS_ENDDOWNLOADDATA )) {
  2126. // pass on progress as is to our client
  2127. pClientBSC->OnProgress(ulProgress, ulProgressMax, ulStatusCode,
  2128. szStatusText);
  2129. DEBUG_LEAVE(S_OK);
  2130. return S_OK;
  2131. }
  2132. // here if Downloading Data progress
  2133. m_pdl->SetProgress(ulProgress, ulProgressMax); // update my dl-object's prog
  2134. // now summate stats and report to client
  2135. CDownload *pdl = m_pdl->GetCodeDownload()->GetDownloadHead();
  2136. ULONG ulSum = 0;
  2137. ULONG ulSumMax = 0;
  2138. // walk each dl object and make a sum of all ulProgress and ulProgressMax
  2139. do {
  2140. pdl->SumProgress(&ulSum, &ulSumMax);
  2141. } while ((pdl = pdl->GetNext()) != NULL);
  2142. // pass on cumulative downloading progress to our client
  2143. pClientBSC->OnProgress(ulSum, ulSumMax, BINDSTATUS_DOWNLOADINGDATA,
  2144. m_pdl->GetCodeDownload()->GetMainURL());
  2145. if (ulStatusCode == BINDSTATUS_ENDDOWNLOADDATA ) {
  2146. // pass on progress as is to our client
  2147. pClientBSC->OnProgress(ulProgress, ulProgressMax, ulStatusCode,
  2148. szStatusText);
  2149. }
  2150. DEBUG_LEAVE(NOERROR);
  2151. return(NOERROR);
  2152. } // CBindStatusCallback
  2153. // ---------------------------------------------------------------------------
  2154. // %%Function: CBindStatusCallback::OnDataAvailable
  2155. // At the last notification we get the filename URLmon has downloaded the
  2156. // m_url data to and rename it to a file in the temp dir.
  2157. // ---------------------------------------------------------------------------
  2158. STDMETHODIMP
  2159. CBindStatusCallback::OnDataAvailable(DWORD grfBSC, DWORD dwSize, FORMATETC *pFmtetc, STGMEDIUM __RPC_FAR *pstgmed)
  2160. {
  2161. DEBUG_ENTER((DBG_DOWNLOAD,
  2162. Hresult,
  2163. "CBindStatusCallback::IBindingStatusCallback::OnDataAvailable",
  2164. "this=%#x, %#x, %#x, %#x, %#x",
  2165. this, grfBSC, dwSize, pFmtetc, pstgmed
  2166. ));
  2167. HRESULT hr = NO_ERROR;
  2168. // never forward OnDataAvailable to code download's client BSC
  2169. if (grfBSC & BSCF_LASTDATANOTIFICATION)
  2170. {
  2171. // if this is the final notification then get the data and display it
  2172. // we asked for IUnknown, we should get back a filename
  2173. Assert((pFmtetc->tymed & TYMED_FILE));
  2174. if (pFmtetc->tymed & TYMED_FILE) {
  2175. char szFile[MAX_PATH];
  2176. DWORD dwLen = 0;
  2177. if (!(dwLen = WideCharToMultiByte(CP_ACP, 0 , pstgmed->lpszFileName , -1 , szFile, MAX_PATH, NULL, NULL))) {
  2178. hr = HRESULT_FROM_WIN32(GetLastError());
  2179. goto Exit;
  2180. } else {
  2181. LPSTR lpFileName = new char[dwLen + 1];
  2182. if (!lpFileName) {
  2183. hr = E_OUTOFMEMORY;
  2184. goto Exit;
  2185. } else {
  2186. lstrcpy(lpFileName, szFile);
  2187. m_pdl->SetFileName(lpFileName);
  2188. }
  2189. }
  2190. // check last modified date for file: URLs
  2191. // maybe we don't need the file
  2192. HRESULT hr1 = m_pdl->IsDownloadedVersionRequired();
  2193. if (FAILED(hr1)) {
  2194. m_pdl->SetResponseHeaderStatus(hr1);
  2195. goto Exit;
  2196. }
  2197. // ref count on the cache
  2198. // file.
  2199. pstgmed->pUnkForRelease->AddRef();
  2200. m_pdl->SetUnkForCacheFileRelease(pstgmed->pUnkForRelease);
  2201. }
  2202. }
  2203. Exit:
  2204. DEBUG_LEAVE(hr);
  2205. return hr;
  2206. } // CBindStatusCallback::OnDataAvailable
  2207. // ---------------------------------------------------------------------------
  2208. // %%Function: CBindStatusCallback::OnObjectAvailable
  2209. // ---------------------------------------------------------------------------
  2210. STDMETHODIMP
  2211. CBindStatusCallback::OnObjectAvailable( REFIID riid, IUnknown* punk)
  2212. {
  2213. DEBUG_ENTER((DBG_DOWNLOAD,
  2214. Hresult,
  2215. "CBindStatusCallback::IBindingStatusCallback::OnObjectAvailable",
  2216. "this=%#x, %#x, %#x",
  2217. this, &riid, punk
  2218. ));
  2219. // Not applicable: we call pmk->BTS not BTO
  2220. DEBUG_LEAVE(E_NOTIMPL);
  2221. return E_NOTIMPL;
  2222. } // CBindStatusCallback::OnObjectAvailable
  2223. // ---------------------------------------------------------------------------
  2224. // %%Function: CBindStatusCallback::OnLowResource
  2225. // ---------------------------------------------------------------------------
  2226. STDMETHODIMP
  2227. CBindStatusCallback::OnLowResource(DWORD dwReserved)
  2228. {
  2229. DEBUG_ENTER((DBG_DOWNLOAD,
  2230. Hresult,
  2231. "CBindStatusCallback::IBindingStatusCallback::OnObjectAvailable",
  2232. "this=%#x, %#x",
  2233. this, dwReserved
  2234. ));
  2235. DEBUG_LEAVE(E_NOTIMPL);
  2236. return E_NOTIMPL;
  2237. } // CBindStatusCallback::OnLoadResource
  2238. // ---------------------------------------------------------------------------
  2239. // %%Function: CBindStatusCallback::OnStopBinding
  2240. //
  2241. // we get here when we have fully downloaded 'this'.
  2242. // ---------------------------------------------------------------------------
  2243. STDMETHODIMP
  2244. CBindStatusCallback::OnStopBinding(HRESULT hrStatus, LPCWSTR szError)
  2245. {
  2246. DEBUG_ENTER((DBG_DOWNLOAD,
  2247. Hresult,
  2248. "CBindStatusCallback::IBindingStatusCallback::OnStopBinding",
  2249. "this=%#x, %#x, %.80wq",
  2250. this, hrStatus, szError
  2251. ));
  2252. CCodeDownload *pcdl = m_pdl->GetCodeDownload();
  2253. HRESULT hrResponseHdr = m_pdl->GetResponseHeaderStatus();
  2254. IBindHost *pBindHost = NULL;
  2255. HRESULT hr = S_OK; // assume all OK
  2256. if (pcdl) {
  2257. pcdl->CodeDownloadDebugOut(DEB_CODEDL, FALSE, ID_CDLDBG_DL_ON_STOP_BINDING, hrStatus, hrResponseHdr);
  2258. }
  2259. if ((FAILED(hrStatus) && (SCODE_FACILITY(hrStatus) == FACILITY_INTERNET)) ||
  2260. FAILED(hrResponseHdr) || SCODE_CODE(hrStatus) == ERROR_MOD_NOT_FOUND) {
  2261. hr = m_pdl->DownloadRedundantCodeBase();
  2262. if (hr == E_PENDING || hr == MK_S_ASYNCHRONOUS) {
  2263. goto Exit;
  2264. }
  2265. }
  2266. m_pdl->SetDLState(DLSTATE_DOWNLOADED);
  2267. pBindHost = pcdl->GetClientBinding()->GetIBindHost();
  2268. SAFERELEASE(m_pbinding);
  2269. if (!pBindHost) {
  2270. hr = RevokeBindStatusCallback(m_pdl->GetBindCtx(), m_pdl->GetBSC());
  2271. }
  2272. if (FAILED(hr)) {
  2273. goto OSB_Complete;
  2274. }
  2275. // if URLMON failed the download or if the response hdr indicated
  2276. // a failure that URLMON failed to detect properly
  2277. // pass the problem to pcdl->CompleteOne(). This will determine if it
  2278. // will query for the clsid with more urls in the CodeSearchPath
  2279. // in the registry.
  2280. if (FAILED(hrStatus) || FAILED(hrResponseHdr)) {
  2281. goto OSB_Complete;
  2282. }
  2283. // BUGBUG: also check here for Last Modified Date on the Cache Entry
  2284. // versus Last Modified if a previous version exists and we are doung
  2285. // GetLatest. If data is in the cache then wininet ignores our
  2286. // if-modified-since and so we will end up re-installing even though
  2287. // there is no version change.
  2288. if (m_pdl->GetFileName() != NULL) { // should be set by OnDataAvailable
  2289. // This takes us to the next state. VerifyTrust moves us when
  2290. // complete to the next state of processing the ProcessPiece.
  2291. CCDLPacket *pPkt= new CCDLPacket(CODE_DOWNLOAD_TRUST_PIECE, m_pdl, 0);
  2292. if (pPkt) {
  2293. hr = pPkt->Post();
  2294. } else {
  2295. hr = E_OUTOFMEMORY;
  2296. }
  2297. if (SUCCEEDED(hr))
  2298. goto Exit;
  2299. // else fall thru to OSB_Complete
  2300. } else if (!m_pdl->UsingCdlProtocol()) {
  2301. // In case of CDL protocol handler we don't need OnDataAvailable or
  2302. // Trust Verification done here.
  2303. // BindToStorage may have not detected the error
  2304. if (m_pdl->DoPost())
  2305. hrResponseHdr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
  2306. else
  2307. hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
  2308. }
  2309. OSB_Complete:
  2310. // does all the master state analysis
  2311. m_pdl->CompleteSignal(hr, hrStatus, hrResponseHdr, szError);
  2312. // This very BSC may already have been deleted if all done.
  2313. // Don't access any members. Just return !!!
  2314. Exit:
  2315. DEBUG_LEAVE(S_OK);
  2316. return S_OK; // always succeed to url mon.
  2317. } // CBindStatusCallback::OnStopBinding
  2318. // ---------------------------------------------------------------------------
  2319. // %%Function: CBindStatusCallback::BeginningTransaction
  2320. // ---------------------------------------------------------------------------
  2321. STDMETHODIMP
  2322. CBindStatusCallback::BeginningTransaction(
  2323. LPCWSTR szURL,
  2324. LPCWSTR szHeaders,
  2325. DWORD dwReserved,
  2326. LPWSTR *pszAdditionalHeaders)
  2327. {
  2328. DEBUG_ENTER((DBG_DOWNLOAD,
  2329. Hresult,
  2330. "CBindStatusCallback::IHttpNegotiate::BeginningTransaction",
  2331. "this=%#x, %.80wq, %.80wq, %#x, %#x",
  2332. this, szURL, szHeaders, dwReserved, pszAdditionalHeaders
  2333. ));
  2334. HRESULT hr = S_OK;
  2335. char szHttpDate[INTERNET_RFC1123_BUFSIZE+1];
  2336. DWORD dwLen = 0;
  2337. LPWSTR szAHdrs = NULL;
  2338. static const char cszHeaderFmt[] = "%s %s\r\n";
  2339. static const char szIfMod[] = "If-Modified-Since:";
  2340. static const char szNONEMATCH[] = "If-None-Match:";
  2341. static const WCHAR szFORM[] = L"Content-Type: application/x-www-form-urlencoded\r\n";
  2342. static const char szAcceptLanguageFmt[] = "Accept-Language: %s\r\n";
  2343. char szBuf[MAX_PATH];
  2344. WCHAR szAcceptLanguage[MAX_PATH];
  2345. char szLangBuf[10];
  2346. char *pszNoneMatch = NULL;
  2347. CCodeDownload *pcdl = m_pdl->GetCodeDownload();
  2348. LCID lcid = pcdl->GetLCID();
  2349. // BUGBUG: we currently only support primary lang or default
  2350. // it should really be "en-us, en", instead of just "en"
  2351. // waiting for note from TonyCi about some servers like Apache
  2352. // broken by this
  2353. lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(LANGIDFROMLCID(lcid)), SUBLANG_DEFAULT), SORT_DEFAULT);
  2354. DEBUG_PRINT(DOWNLOAD,
  2355. INFO,
  2356. ("this=%#x, m_lcid: %d (%#x), lcid: %d (%#x)\n",
  2357. this, pcdl->GetLCID(), pcdl->GetLCID(), lcid, lcid
  2358. ));
  2359. *szAcceptLanguage = L'\0';
  2360. if (pcdl->GetLangInfo()->GetAcceptLanguageString(lcid, szLangBuf, sizeof(szLangBuf))
  2361. && (*szLangBuf != '\0'))
  2362. {
  2363. wnsprintf(szBuf, sizeof(szBuf)-1, szAcceptLanguageFmt, szLangBuf);
  2364. dwLen = MultiByteToWideChar(CP_ACP, 0, szBuf, -1, szAcceptLanguage, MAX_PATH);
  2365. }
  2366. Assert((pszAdditionalHeaders != NULL));
  2367. FILETIME *pftLastMod = pcdl->GetLastModifiedTime();
  2368. SYSTEMTIME sSysTime;
  2369. BOOL bSendNoneMatch = !pcdl->ForceDownload() && ( pcdl->LocalVersionPresent() && (pcdl->GetLocalVersionEtag()) ) && pcdl->NeedLatestVersion();
  2370. BOOL bSendLastMod = !bSendNoneMatch && (!pcdl->ForceDownload() && ( pcdl->LocalVersionPresent() && (pftLastMod) ) && pcdl->NeedLatestVersion());
  2371. if ( bSendLastMod) {
  2372. Assert( (pftLastMod != NULL) ); // Check for bug#40696
  2373. // need to send If-Modified-Since
  2374. if (!FileTimeToSystemTime(pftLastMod, &sSysTime)) {
  2375. m_pdl->SetResponseHeaderStatus( HRESULT_FROM_WIN32(GetLastError()));
  2376. goto Exit;
  2377. }
  2378. if (!InternetTimeFromSystemTimeA(&sSysTime, INTERNET_RFC1123_FORMAT,
  2379. szHttpDate, INTERNET_RFC1123_BUFSIZE)) {
  2380. m_pdl->SetResponseHeaderStatus( HRESULT_FROM_WIN32(GetLastError()));
  2381. goto Exit;
  2382. }
  2383. dwLen += (INTERNET_RFC1123_BUFSIZE + 1 + sizeof(szIfMod) +
  2384. sizeof(cszHeaderFmt));
  2385. }
  2386. if (bSendNoneMatch) {
  2387. DWORD dwNoneMatch = lstrlen(pcdl->GetLocalVersionEtag()) + sizeof(szNONEMATCH) + sizeof(cszHeaderFmt);
  2388. pszNoneMatch = new char [dwNoneMatch+1];
  2389. wsprintf(pszNoneMatch, cszHeaderFmt, szNONEMATCH, pcdl->GetLocalVersionEtag());
  2390. dwLen += dwNoneMatch;
  2391. }
  2392. if (m_pdl->DoPost()) {
  2393. dwLen += sizeof(szFORM);
  2394. }
  2395. if (dwLen) {
  2396. szAHdrs = new WCHAR [dwLen + 1];
  2397. if (!szAHdrs) {
  2398. m_pdl->SetResponseHeaderStatus( E_OUTOFMEMORY );
  2399. // BUGBUG: Clean all this up to never return right away, and
  2400. // goto exit to cleanup
  2401. SAFEDELETE(pszNoneMatch);
  2402. DEBUG_LEAVE(hr);
  2403. return hr;
  2404. }
  2405. szAHdrs[0] = '\0';
  2406. }
  2407. if (bSendLastMod) {
  2408. char *szTemp = new char [dwLen + 1];
  2409. if (!szTemp) {
  2410. hr = E_OUTOFMEMORY;
  2411. delete szAHdrs;
  2412. goto Exit;
  2413. }
  2414. wsprintf(szTemp, cszHeaderFmt, szIfMod, szHttpDate);
  2415. MultiByteToWideChar(CP_ACP, 0, szTemp, -1, szAHdrs, dwLen);
  2416. delete szTemp;
  2417. }
  2418. if (bSendNoneMatch) {
  2419. MultiByteToWideChar(CP_ACP, 0, pszNoneMatch, -1, szAHdrs, dwLen);
  2420. }
  2421. if (m_pdl->DoPost()) {
  2422. StrCatW(szAHdrs, szFORM);
  2423. }
  2424. if (*szAcceptLanguage != L'\0')
  2425. {
  2426. StrCatW(szAHdrs, szAcceptLanguage);
  2427. }
  2428. Exit:
  2429. SAFEDELETE(pszNoneMatch);
  2430. *pszAdditionalHeaders = szAHdrs;
  2431. DEBUG_LEAVE(hr);
  2432. return hr;
  2433. }
  2434. // ---------------------------------------------------------------------------
  2435. // %%Function: CBindStatusCallback::OnResponse
  2436. // ---------------------------------------------------------------------------
  2437. STDMETHODIMP
  2438. CBindStatusCallback::OnResponse(
  2439. DWORD dwResponseCode,
  2440. LPCWSTR szResponseHeaders,
  2441. LPCWSTR szRequestHeaders,
  2442. LPWSTR *pszAdditionalRequestHeaders)
  2443. {
  2444. DEBUG_ENTER((DBG_DOWNLOAD,
  2445. Hresult,
  2446. "CBindStatusCallback::IHttpNegotiate::OnResponse",
  2447. "this=%#x, %#x, %.80wq, %.80wq, %#x",
  2448. this, dwResponseCode, szResponseHeaders, szRequestHeaders, pszAdditionalRequestHeaders
  2449. ));
  2450. HRESULT hr = S_OK;
  2451. // propogate errors here to CSBC::OnStopBinding
  2452. // we need this as urlmon might just convert any error returned here
  2453. // as user_cancelled
  2454. if (dwResponseCode != HTTP_STATUS_OK) {
  2455. if (dwResponseCode == HTTP_STATUS_NOT_MODIFIED) {
  2456. hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  2457. } else {
  2458. hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
  2459. }
  2460. m_pdl->SetResponseHeaderStatus( hr );
  2461. }
  2462. if (m_pdl->DoPost() ||
  2463. (m_pdl->GetMoniker() == m_pdl->GetCodeDownload()->GetContextMoniker())){
  2464. // Get the HttpQueryInfo wrapper object.
  2465. IWinInetHttpInfo *pHttpInfo = NULL;
  2466. HRESULT hr = GetBinding()->QueryInterface
  2467. (IID_IWinInetHttpInfo, (void **) &pHttpInfo);
  2468. if (SUCCEEDED(hr)) {
  2469. DWORD cbLen = INTERNET_RFC1123_BUFSIZE + 1;
  2470. char szHttpDate[INTERNET_RFC1123_BUFSIZE+1];
  2471. if ((pHttpInfo->QueryInfo (HTTP_QUERY_LAST_MODIFIED,
  2472. (LPVOID)szHttpDate, &cbLen, NULL, 0) == S_OK) && cbLen)
  2473. m_pdl->GetCodeDownload()->SetLastModifiedTime(szHttpDate);
  2474. cbLen = 0; // reset
  2475. if ( (pHttpInfo->QueryInfo (HTTP_QUERY_ETAG,
  2476. (LPVOID)NULL, &cbLen, NULL, 0) == S_OK) && cbLen) {
  2477. char *pbEtag = new char [cbLen +1];
  2478. if (pbEtag)
  2479. {
  2480. *pbEtag = '\0'; // clr
  2481. pHttpInfo->QueryInfo (HTTP_QUERY_ETAG,
  2482. (LPVOID)pbEtag, &cbLen, NULL, 0);
  2483. if (*pbEtag)
  2484. m_pdl->GetCodeDownload()->SetEtag(pbEtag);
  2485. }
  2486. }
  2487. pHttpInfo->Release();
  2488. }
  2489. }
  2490. DEBUG_LEAVE(S_OK);
  2491. return S_OK;
  2492. }
  2493. // ---------------------------------------------------------------------------
  2494. // %%Function: CBindStatusCallback::GetCatalogFile
  2495. // ---------------------------------------------------------------------------
  2496. STDMETHODIMP CBindStatusCallback::GetCatalogFile(LPSTR *ppszCatalogFile)
  2497. {
  2498. DEBUG_ENTER((DBG_DOWNLOAD,
  2499. Hresult,
  2500. "CBindStatusCallback::ICatalogFileInfo::GetCatalogFile",
  2501. "this=%#x, %#x",
  2502. this, ppszCatalogFile
  2503. ));
  2504. HRESULT hr = S_OK;
  2505. LPSTR pszCatFile = NULL;
  2506. if (ppszCatalogFile) {
  2507. pszCatFile = m_pdl->GetCodeDownload()->GetCatalogFile();
  2508. if (pszCatFile) {
  2509. *ppszCatalogFile = new char[lstrlen(pszCatFile) + 1];
  2510. if (*ppszCatalogFile == NULL) {
  2511. hr = E_OUTOFMEMORY;
  2512. }
  2513. else {
  2514. lstrcpy(*ppszCatalogFile, pszCatFile);
  2515. }
  2516. }
  2517. else {
  2518. *ppszCatalogFile = NULL;
  2519. }
  2520. }
  2521. else {
  2522. hr = E_INVALIDARG;
  2523. }
  2524. DEBUG_LEAVE(hr);
  2525. return hr;
  2526. }
  2527. // ---------------------------------------------------------------------------
  2528. // %%Function: CBindStatusCallback::GetJavaTrust
  2529. // ---------------------------------------------------------------------------
  2530. STDMETHODIMP CBindStatusCallback::GetJavaTrust(void **ppJavaTrust)
  2531. {
  2532. DEBUG_ENTER((DBG_DOWNLOAD,
  2533. Hresult,
  2534. "CBindStatusCallback::ICatalogFileInfo::GetJavaTrust",
  2535. "this=%#x, %#x",
  2536. this, ppJavaTrust
  2537. ));
  2538. HRESULT hr = S_OK;
  2539. if (ppJavaTrust) {
  2540. *ppJavaTrust = (void *)m_pdl->GetCodeDownload()->GetJavaTrust();
  2541. }
  2542. else {
  2543. hr = E_INVALIDARG;
  2544. }
  2545. DEBUG_LEAVE(hr);
  2546. return hr;
  2547. }