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.

4136 lines
121 KiB

  1. // ===========================================================================
  2. // File: SOFTDIST.CXX
  3. // Channel Software Distribution Unit Tag handler
  4. //
  5. #include <cdlpch.h>
  6. #include <winineti.h>
  7. #include <shlwapip.h>
  8. #include <msxml.h>
  9. LPCSTR szWinNT = "WinNT";
  10. LPCSTR szWin95 = "Win95";
  11. LPCSTR szPlatform = "Win32";
  12. LPCOLESTR szMSInstallProgID = L"MSInstall.SoftDistExt";
  13. const TCHAR c_szTrayUI[] = TEXT("MS_WebcheckMonitor"); // Do not change this string. LoadWC relies on it.
  14. const TCHAR c_szTrayMenu[] = TEXT("TrayMenu");
  15. const LPTSTR szControlSetup = _T("Status");
  16. const DWORD dwStatusOK = 0;
  17. const DWORD dwStatusSuspend = 1;
  18. const DWORD dwStatusResume = 2;
  19. const DWORD dwStatusAbort = 3;
  20. const UM_NEEDREBOOT = WM_USER + 16;
  21. extern char *g_szProcessorTypes[];
  22. extern char g_szBrowserLang[];
  23. extern int g_lenBrowserLang;
  24. extern char g_szBrowserPrimaryLang[];
  25. extern int g_lenBrowserPrimaryLang;
  26. extern LCID g_lcidBrowser;
  27. #define ERROR_EXIT(cond) if (!(cond)) { \
  28. goto Exit;}
  29. extern COleAutDll g_OleAutDll;
  30. //REVIEW: This is located in cdl.cxx for page swapping reasons. (OSD's are processed
  31. // more than CDF/<SoftDist>'s?
  32. HRESULT ProcessImplementation(IXMLElement *pConfig,
  33. CList<CCodeBaseHold *, CCodeBaseHold *> *pcbhList,
  34. LCID lcidOverride,
  35. #ifdef WX86
  36. CMultiArch *MultiArch,
  37. #endif
  38. LPWSTR szBaseURL);
  39. HRESULT
  40. GetAbstract(HKEY hkeyAv, LPSTR *ppszAbstract)
  41. {
  42. DEBUG_ENTER((DBG_DOWNLOAD,
  43. Hresult,
  44. "GetAbstract",
  45. "%#x, %#x",
  46. hkeyAv, ppszAbstract
  47. ));
  48. HRESULT hr = S_OK;
  49. DWORD Size,dwType;
  50. LONG lResult;
  51. if (ppszAbstract) {
  52. *ppszAbstract = NULL;
  53. if (RegQueryValueEx(hkeyAv, REGVAL_ABSTRACT_AVAILABLE, NULL, &dwType,
  54. NULL, &Size) == ERROR_SUCCESS) {
  55. *ppszAbstract = new char[Size];
  56. if (!*ppszAbstract) {
  57. hr = E_OUTOFMEMORY;
  58. goto Exit;
  59. }
  60. if ((lResult = RegQueryValueEx(hkeyAv, REGVAL_ABSTRACT_AVAILABLE, NULL, &dwType,
  61. (unsigned char *)*ppszAbstract, &Size) != ERROR_SUCCESS)) {
  62. hr = HRESULT_FROM_WIN32(lResult);
  63. }
  64. }
  65. }
  66. Exit:
  67. DEBUG_LEAVE(hr);
  68. return hr;
  69. }
  70. BOOL
  71. IsAbstractDifferent(HKEY hkeyAv, LPSTR szNewAbstract)
  72. {
  73. DEBUG_ENTER((DBG_DOWNLOAD,
  74. Bool,
  75. "IsAbstractDifferent",
  76. "%#x, %.80q",
  77. hkeyAv, szNewAbstract
  78. ));
  79. LPSTR pszOldAbstract = NULL;
  80. BOOL bDifferent = TRUE;
  81. if ((GetAbstract(hkeyAv, &pszOldAbstract) == S_OK) && pszOldAbstract) {
  82. if (szNewAbstract)
  83. bDifferent = lstrcmp(pszOldAbstract, szNewAbstract) != 0;
  84. delete pszOldAbstract;
  85. }
  86. DEBUG_LEAVE(bDifferent);
  87. return bDifferent;
  88. }
  89. /******************************************************************************
  90. Constructor, Destructor and helper methods
  91. ******************************************************************************/
  92. CSoftDist::CSoftDist()
  93. {
  94. DEBUG_ENTER((DBG_DOWNLOAD,
  95. None,
  96. "CSoftDist::CSoftDist",
  97. "this=%#x",
  98. this
  99. ));
  100. DllAddRef();
  101. m_cRef = 1;
  102. m_szDistUnit = NULL;
  103. m_szCDFURL = NULL;
  104. m_szTitle = NULL;
  105. m_szAbstract = NULL;
  106. m_szHREF = NULL;
  107. m_szLanguages = NULL;
  108. m_dwVersionMS = m_dwVersionLS = 0;
  109. m_dwVersionAdvertisedMS = m_dwVersionAdvertisedLS = 0;
  110. m_dwAdState = SOFTDIST_ADSTATE_NONE;
  111. m_Style = STYLE_MSICD;
  112. m_sdMSInstall = NULL;
  113. m_pClientBSC = NULL;
  114. m_szBaseURL = NULL;
  115. memset(&m_distunitinst, 0, sizeof(DISTUNITINST));
  116. DetermineOSAndCPUVersion();
  117. DEBUG_LEAVE(0);
  118. }
  119. CSoftDist::~CSoftDist()
  120. {
  121. DEBUG_ENTER((DBG_DOWNLOAD,
  122. None,
  123. "CSoftDist::~CSoftDist",
  124. "this=%#x",
  125. this
  126. ));
  127. Assert(m_cRef == 0);
  128. SAFERELEASE(m_sdMSInstall);
  129. SAFEDELETE(m_szDistUnit);
  130. SAFEDELETE(m_szCDFURL);
  131. SAFEDELETE(m_szTitle);
  132. SAFEDELETE(m_szAbstract);
  133. SAFEDELETE(m_szHREF);
  134. SAFEDELETE(m_szLanguages);
  135. SAFEDELETE(m_pClientBSC);
  136. SAFEDELETE(m_szBaseURL);
  137. DllRelease();
  138. DEBUG_LEAVE(0);
  139. }
  140. /******************************************************************************
  141. IUnknown Methods
  142. ******************************************************************************/
  143. STDMETHODIMP CSoftDist::QueryInterface(
  144. REFIID iid,
  145. void** ppvObject)
  146. {
  147. DEBUG_ENTER((DBG_DOWNLOAD,
  148. Hresult,
  149. "CSoftDist::IUnknown::QueryInterface",
  150. "this=%#x, %#x, %#x",
  151. this, &iid, ppvObject
  152. ));
  153. *ppvObject = NULL;
  154. if (iid == IID_IUnknown)
  155. {
  156. *ppvObject = (void*)this;
  157. }
  158. else if (iid == IID_ISoftDistExt)
  159. {
  160. *ppvObject = (void*)(ISoftDistExt*)this;
  161. }
  162. if (*ppvObject)
  163. {
  164. ((LPUNKNOWN)*ppvObject)->AddRef();
  165. DEBUG_LEAVE(S_OK);
  166. return S_OK;
  167. }
  168. DEBUG_LEAVE(E_NOINTERFACE);
  169. return E_NOINTERFACE;
  170. }
  171. STDMETHODIMP_(ULONG) CSoftDist::AddRef()
  172. {
  173. DEBUG_ENTER((DBG_DOWNLOAD,
  174. Dword,
  175. "CSoftDist::IUnknown::AddRef",
  176. "this=%#x",
  177. this
  178. ));
  179. ULONG ulRet = ++m_cRef;
  180. DEBUG_LEAVE(ulRet);
  181. return ulRet;
  182. }
  183. STDMETHODIMP_(ULONG) CSoftDist::Release()
  184. {
  185. DEBUG_ENTER((DBG_DOWNLOAD,
  186. Dword,
  187. "CSoftDist::IUnknown::Release",
  188. "this=%#x",
  189. this
  190. ));
  191. if (--m_cRef)
  192. {
  193. DEBUG_LEAVE(m_cRef);
  194. return m_cRef;
  195. }
  196. delete this;
  197. DEBUG_LEAVE(0);
  198. return 0;
  199. }
  200. /******************************************************************************
  201. ISoftDistExt Methods
  202. ******************************************************************************/
  203. /*
  204. * return values:
  205. * All success codes indicate user should be notified through channel UI.
  206. *
  207. * S_OK: Locally not available, Send Email (Show in channel UI)
  208. * S_FALSE: Locally not available. Don't send Email. (But show in channel UI)
  209. *
  210. * ERROR_ALREADY_EXISTS:Locally already installed. Don't send email/advertise.
  211. * ERROR: Processing error, fail.
  212. *
  213. * For additional information on usage flags, set dwReserved to a valid pointer
  214. * and it will set appropriate bit fields
  215. *
  216. */
  217. STDMETHODIMP
  218. CSoftDist::ProcessSoftDist(LPCWSTR szCDFURL, IXMLElement *pSoftDist, LPSOFTDISTINFO psdi)
  219. {
  220. DEBUG_ENTER((DBG_DOWNLOAD,
  221. Hresult,
  222. "CSoftDist::ProcessSoftDist",
  223. "this=%#x, %.80wq, %#x, %#x",
  224. this, szCDFURL, pSoftDist, psdi
  225. ));
  226. HRESULT hr = S_FALSE; // default: send email, no precache
  227. char szVersion[MAX_PATH];
  228. char szStyle[MAX_PATH];
  229. LPSTR szThisOS = NULL;
  230. LPWSTR szTitle = NULL;
  231. IXMLElement *pTitle = NULL, *pConfig = NULL, *pLang = NULL,
  232. *pAbstract = NULL, *pUsage = NULL, *pDeleteOnInstall = NULL;
  233. IXMLElement *pParent = NULL;
  234. BOOL bPrecache = FALSE, bChannelUIOnly = FALSE, bAutoInstall = FALSE,
  235. bIsPrecached = FALSE, bDeleteOnInstall = FALSE;
  236. BOOL fFoundConfig = FALSE;
  237. LPDWORD lpFlags = NULL;
  238. BOOL bIsValidCDF = FALSE;
  239. if (psdi) {
  240. if (psdi->cbSize < sizeof(SOFTDISTINFO))
  241. {
  242. DEBUG_LEAVE(E_INVALIDARG);
  243. return E_INVALIDARG;
  244. }
  245. psdi->dwFlags = 0;
  246. }
  247. if (szCDFURL && FAILED((hr=::Unicode2Ansi(szCDFURL, &m_szCDFURL))))
  248. {
  249. goto Exit;
  250. }
  251. // Try to use the BASE tag from the channel.
  252. // BUGBUG: This is a really convoluted way to get at the channel
  253. // BASE URL, but there is no way for webcheck to pass this
  254. // information to us w/o changing the ISoftDistExt interface.
  255. pSoftDist->get_parent(&pParent);
  256. if (pParent) {
  257. DupAttribute(pParent, CHANNEL_ATTRIB_BASE, &m_szBaseURL);
  258. SAFERELEASE(pParent);
  259. }
  260. hr = DupAttribute(pSoftDist, DU_ATTRIB_NAME, &m_szDistUnit);
  261. ERROR_EXIT(SUCCEEDED(hr));
  262. // code around assumes that MAX_PATH is MAX size of dist unit
  263. // we try to make a key name with the distunit and that limit is
  264. // now MAX_PATH. Hence the reasoning to limit this to MAX_PATH
  265. if (lstrlenW(m_szDistUnit) >= MAX_PATH) {
  266. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  267. goto Exit;
  268. }
  269. hr = DupAttributeA(pSoftDist, DU_ATTRIB_HREF, &m_szHREF);
  270. ERROR_EXIT(SUCCEEDED(hr));
  271. if (psdi) {
  272. hr = Ansi2Unicode( m_szHREF, &psdi->szHREF );
  273. if ( FAILED(hr) )
  274. goto Exit;
  275. }
  276. hr = GetAttributeA(pSoftDist, DU_ATTRIB_VERSION, szVersion, MAX_PATH);
  277. ERROR_EXIT(SUCCEEDED(hr));
  278. if ( FAILED(GetVersionFromString(szVersion, &m_dwVersionMS, &m_dwVersionLS))){
  279. hr = HRESULT_FROM_WIN32(GetLastError());
  280. goto Exit;
  281. }
  282. if (!(m_dwVersionMS | m_dwVersionLS)) { // zero is invalid advt version
  283. hr = E_INVALIDARG;
  284. goto Exit;
  285. }
  286. if (psdi) {
  287. CHAR szTemp[MAX_PATH];
  288. psdi->dwFlags = 0;
  289. psdi->dwUpdateVersionMS = m_dwVersionMS;
  290. psdi->dwUpdateVersionLS = m_dwVersionLS;
  291. psdi->dwAdvertisedVersionMS = m_dwVersionAdvertisedMS;
  292. psdi->dwAdvertisedVersionLS = m_dwVersionAdvertisedLS;
  293. if (GetFirstChildTag(pSoftDist, DU_TAG_USAGE, &pUsage) == S_OK) {
  294. VARIANT vtVal;
  295. VariantInit(&vtVal);
  296. if (SUCCEEDED(pUsage->getAttribute(DU_ATTRIB_VALUE, &vtVal)) && (vtVal.vt == VT_BSTR)) {
  297. if (!StrCmpIW(vtVal.bstrVal, DU_ATTRIB_EMAIL))
  298. psdi->dwFlags |= SOFTDIST_FLAG_USAGE_EMAIL;
  299. // SAFESYSFREESTRING(vtVal.bstrVal);
  300. }
  301. VariantClear(&vtVal);
  302. SAFERELEASE(pUsage);
  303. }
  304. if (SUCCEEDED(GetAttributeA(pSoftDist, DU_ATTRIB_PRECACHE, szTemp, MAX_PATH))) {
  305. if (szTemp[0] == 'Y' || szTemp[0] == 'y') {
  306. psdi->dwFlags |= SOFTDIST_FLAG_USAGE_PRECACHE;
  307. bPrecache = TRUE;
  308. }
  309. }
  310. if (SUCCEEDED(GetAttributeA(pSoftDist, DU_ATTRIB_AUTOINSTALL, szTemp, MAX_PATH))) {
  311. if (szTemp[0] == 'Y' || szTemp[0] == 'y') {
  312. psdi->dwFlags |= SOFTDIST_FLAG_USAGE_AUTOINSTALL;
  313. bPrecache = TRUE;
  314. bAutoInstall = TRUE;
  315. }
  316. }
  317. }
  318. // get abstract
  319. if(GetFirstChildTag(pSoftDist,DU_TAG_ABSTRACT, &pAbstract) == S_OK) {
  320. BSTR bstrAbstract = NULL;
  321. hr = pAbstract->get_text(&bstrAbstract);
  322. ERROR_EXIT(SUCCEEDED(hr));
  323. if (FAILED(Unicode2Ansi(bstrAbstract, &m_szAbstract))) {
  324. hr = E_OUTOFMEMORY;
  325. SAFESYSFREESTRING(bstrAbstract);
  326. goto Exit;
  327. }
  328. if (psdi) {
  329. psdi->szAbstract = new WCHAR[lstrlenW(bstrAbstract)+1];
  330. if (!psdi->szAbstract) {
  331. hr = E_OUTOFMEMORY;
  332. SAFESYSFREESTRING(bstrAbstract);
  333. goto Exit;
  334. } else {
  335. StrCpyW(psdi->szAbstract, bstrAbstract);
  336. }
  337. }
  338. SAFESYSFREESTRING(bstrAbstract);
  339. }
  340. // get title
  341. if(GetFirstChildTag(pSoftDist,DU_TAG_TITLE, &pTitle) == S_OK) {
  342. BSTR bstrTitle = NULL;
  343. hr = pTitle->get_text(&bstrTitle);
  344. ERROR_EXIT(SUCCEEDED(hr));
  345. if (FAILED(Unicode2Ansi(bstrTitle, &m_szTitle))) {
  346. hr = E_OUTOFMEMORY;
  347. SAFESYSFREESTRING(bstrTitle);
  348. goto Exit;
  349. }
  350. if (psdi) {
  351. psdi->szTitle = new WCHAR[lstrlenW(bstrTitle)+1];
  352. if (!psdi->szTitle) {
  353. hr = E_OUTOFMEMORY;
  354. SAFESYSFREESTRING(bstrTitle);
  355. goto Exit;
  356. } else {
  357. StrCpyW(psdi->szTitle, bstrTitle);
  358. }
  359. }
  360. SAFESYSFREESTRING(bstrTitle);
  361. }
  362. // get langs available
  363. if(GetFirstChildTag(pSoftDist,DU_TAG_LANG, &pLang) == S_OK) {
  364. BSTR bstrLang = NULL;
  365. hr = pLang->get_text(&bstrLang);
  366. ERROR_EXIT(SUCCEEDED(hr));
  367. DWORD len = lstrlenW(bstrLang);
  368. m_szLanguages = new char [len+1];
  369. if (!m_szLanguages) {
  370. hr = E_OUTOFMEMORY;
  371. SAFESYSFREESTRING(bstrLang);
  372. goto Exit;
  373. }
  374. WideCharToMultiByte(CP_ACP, 0, bstrLang , -1, m_szLanguages,
  375. len, NULL, NULL);
  376. SAFESYSFREESTRING(bstrLang);
  377. }
  378. // <deleteoninstall />
  379. if (GetFirstChildTag(pSoftDist, DU_TAG_DELETEONINSTALL, &pDeleteOnInstall) == S_OK) {
  380. SAFERELEASE(pDeleteOnInstall);
  381. bDeleteOnInstall = TRUE;
  382. }
  383. // style tells us who to ask
  384. // accomodate Darwin here
  385. if(SUCCEEDED(GetAttributeA(pSoftDist, DU_ATTRIB_STYLE, szStyle, MAX_PATH))){
  386. (void) GetStyleFromString(szStyle, &m_Style);
  387. if (m_Style == STYLE_UNKNOWN) {
  388. if (m_sdMSInstall == NULL) {
  389. CLSID clsidOther;
  390. LPWSTR wszStyle = NULL;
  391. if (FAILED(DupAttribute(pSoftDist, DU_ATTRIB_STYLE, &wszStyle)))
  392. goto Exit;
  393. if (SUCCEEDED(CLSIDFromProgID(wszStyle, &clsidOther))) {
  394. if (FAILED(hr = CoCreateInstance(clsidOther, NULL, CLSCTX_INPROC_SERVER,
  395. IID_ISoftDistExt, (void **)&m_sdMSInstall)))
  396. goto Exit;
  397. m_Style = STYLE_OTHER;
  398. }
  399. // If failed, continue as normal.
  400. }
  401. }
  402. if (m_Style == STYLE_MSINSTALL) {
  403. if (m_sdMSInstall == NULL) {
  404. CLSID clsidMSInstall;
  405. if (FAILED(hr = CLSIDFromProgID(szMSInstallProgID, &clsidMSInstall)))
  406. goto Exit;
  407. if (FAILED(hr = CoCreateInstance(clsidMSInstall, NULL, CLSCTX_INPROC_SERVER,
  408. IID_ISoftDistExt, (void **)&m_sdMSInstall)))
  409. goto Exit;
  410. }
  411. }
  412. if (m_sdMSInstall != NULL) {
  413. hr = m_sdMSInstall->ProcessSoftDist(szCDFURL, pSoftDist, psdi);
  414. goto Exit;
  415. }
  416. }
  417. // get list of available languages here
  418. hr = InitBrowserLangStrings();
  419. if (FAILED(hr))
  420. goto Exit;
  421. // check if software already locally installed
  422. hr = IsLocallyInstalled(m_szDistUnit, m_dwVersionMS, m_dwVersionLS, m_szLanguages, m_Style);
  423. if ( psdi != NULL )
  424. {
  425. if ( SUCCEEDED(hr) )
  426. {
  427. psdi->dwInstalledVersionMS = m_distunitinst.dwInstalledVersionMS;
  428. psdi->dwInstalledVersionLS = m_distunitinst.dwInstalledVersionLS;
  429. }
  430. else
  431. {
  432. // No version.
  433. psdi->dwInstalledVersionMS = 0xFFFFFFFF;
  434. psdi->dwInstalledVersionLS = 0xFFFFFFFF;
  435. }
  436. }
  437. if (hr != S_FALSE) {
  438. if (hr == S_OK) {
  439. if (psdi && bDeleteOnInstall) {
  440. psdi->dwFlags |= SOFTDIST_FLAG_DELETE_SUBSCRIPTION;
  441. }
  442. hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  443. }
  444. goto Exit;
  445. }
  446. // check here to see if Advertised already to avoid
  447. // processing filters?
  448. if (FAILED(hr = IsAdvertised(&bIsPrecached, &bIsValidCDF)))
  449. goto Exit;
  450. // If already advertised then only precache once.
  451. if (hr == S_OK) {
  452. if ((!bPrecache) || (!bAutoInstall && bPrecache && bIsPrecached)) {
  453. bChannelUIOnly = TRUE;
  454. }
  455. }
  456. // version doesn't already exist
  457. // process filters to see if we can Advertise this
  458. // look for dependency & config filters. If either fails, then we don't do Channel UI or
  459. // email notification.
  460. if (FAILED(hr = CheckDependency(pSoftDist)))
  461. goto Exit;
  462. if (FAILED(hr = CheckConfig(pSoftDist)))
  463. goto Exit;
  464. if (bChannelUIOnly)
  465. {
  466. // we record advertise again to stomp the title & abstract
  467. if (bIsValidCDF) {
  468. hr = Advertise(/*bFullAdvt*/FALSE);
  469. }
  470. // We are already advertised, we want Channel UI but not email notification.
  471. hr = S_FALSE;
  472. }
  473. else
  474. {
  475. if (bIsValidCDF) {
  476. // Advertise software, mark as Advertised
  477. hr = Advertise(/*bFullAdvt*/TRUE);
  478. // We advertise in Channel UI and email notification.
  479. hr = S_OK;
  480. } else {
  481. // if not an authorized CDF then we can't trigger email notification or download
  482. hr = S_FALSE;
  483. }
  484. }
  485. Exit:
  486. SAFERELEASE(pLang);
  487. SAFERELEASE(pAbstract);
  488. SAFERELEASE(pTitle);
  489. DEBUG_LEAVE(hr);
  490. return hr;
  491. }
  492. STDMETHODIMP
  493. CSoftDist::GetFirstCodeBase(LPWSTR *szCodeBase, LPDWORD lpdwSize)
  494. {
  495. DEBUG_ENTER((DBG_DOWNLOAD,
  496. Hresult,
  497. "CSoftDist::GetFirstCodeBase",
  498. "this=%#x, %#x, %#x",
  499. this, szCodeBase, lpdwSize
  500. ));
  501. HRESULT hr;
  502. if (m_sdMSInstall != NULL)
  503. {
  504. hr = m_sdMSInstall->GetFirstCodeBase(szCodeBase, lpdwSize);
  505. DEBUG_LEAVE(hr);
  506. return hr;
  507. }
  508. m_curPos = m_cbh.GetHeadPosition();
  509. hr = GetNextCodeBase(szCodeBase, lpdwSize);
  510. DEBUG_LEAVE(hr);
  511. return hr;
  512. }
  513. STDMETHODIMP
  514. CSoftDist::GetNextCodeBase(LPWSTR *szCodeBase, LPDWORD lpdwSize)
  515. {
  516. DEBUG_ENTER((DBG_DOWNLOAD,
  517. Hresult,
  518. "CSoftDist::GetNextCodeBase",
  519. "this=%#x, %#x, %#x",
  520. this, szCodeBase, lpdwSize
  521. ));
  522. HRESULT hr = S_OK;
  523. CCodeBaseHold *cbh = NULL;
  524. if (m_sdMSInstall != NULL)
  525. {
  526. hr = m_sdMSInstall->GetNextCodeBase(szCodeBase, lpdwSize);
  527. DEBUG_LEAVE(hr);
  528. return hr;
  529. }
  530. if (szCodeBase == NULL || lpdwSize == NULL) {
  531. hr = E_INVALIDARG;
  532. goto Exit;
  533. }
  534. *szCodeBase = NULL;
  535. *lpdwSize = 0;
  536. if (m_curPos == NULL) {
  537. hr = E_FAIL;
  538. goto Exit;
  539. }
  540. cbh = m_cbh.GetNext(m_curPos);
  541. hr = CDLDupWStr( szCodeBase, cbh->wszCodeBase );
  542. *lpdwSize = cbh->dwSize;
  543. Exit:
  544. DEBUG_LEAVE(hr);
  545. return hr;
  546. }
  547. STDMETHODIMP
  548. CSoftDist::AsyncInstallDistributionUnit(IBindCtx *pbc, LPVOID pvReserved, DWORD dwFlags, LPCODEBASEHOLD lpcbh)
  549. {
  550. DEBUG_ENTER((DBG_DOWNLOAD,
  551. Hresult,
  552. "CSoftDist::AsyncInstallDistributionUnit",
  553. "this=%#x, %#x, %#x, %#x, %#x",
  554. this, pbc, pvReserved, dwFlags, lpcbh
  555. ));
  556. HRESULT hr = S_OK;
  557. LPWSTR szCodeBase = NULL;
  558. DWORD dwSize;
  559. if ((lpcbh) && (lpcbh->cbSize == sizeof(CODEBASEHOLD)))
  560. {
  561. hr = ::AsyncInstallDistributionUnit(
  562. lpcbh->szDistUnit,
  563. NULL,
  564. NULL,
  565. lpcbh->dwVersionMS,
  566. lpcbh->dwVersionLS,
  567. lpcbh->szCodeBase, // URL of code base
  568. pbc,
  569. NULL,
  570. 0);
  571. } else if (m_Style == STYLE_MSICD) {
  572. if (SUCCEEDED(GetFirstCodeBase(&szCodeBase, &dwSize))) {
  573. CCodeBaseHold *pcbh;
  574. pcbh = m_cbh.GetHead();
  575. pcbh->dwFlags |= CBH_FLAGS_DOWNLOADED;
  576. hr = ::AsyncInstallDistributionUnit(
  577. m_szDistUnit,
  578. NULL,
  579. NULL,
  580. m_dwVersionMS,
  581. m_dwVersionLS,
  582. szCodeBase, // URL of code base
  583. pbc,
  584. NULL,
  585. 0);
  586. // NOTE: EAX should be MK_S_ASYNC (0x401E8)
  587. } else
  588. hr = E_FAIL;
  589. // Return successful no matter what
  590. } else if (m_Style == STYLE_MSINSTALL || m_Style == STYLE_OTHER) {
  591. if (m_sdMSInstall == NULL) {
  592. hr = E_FAIL; // Interfaces should be here but aren't.
  593. } else {
  594. hr = m_sdMSInstall->AsyncInstallDistributionUnit(pbc, pvReserved, dwFlags, lpcbh);
  595. }
  596. } else if (m_Style == STYLE_ACTIVE_SETUP) {
  597. if (SUCCEEDED(GetFirstCodeBase(&szCodeBase, &dwSize))) {
  598. CActiveSetupBinding *pasb = NULL;
  599. IBindStatusCallback *pbsc = NULL;
  600. if (SUCCEEDED(pbc->GetObjectParam(REG_BSCB_HOLDER, (IUnknown **)&pbsc))) {
  601. pasb = new CActiveSetupBinding(pbc, pbsc, szCodeBase, m_szDistUnit, &hr);
  602. if (pasb && FAILED(hr)) {
  603. SAFERELEASE(pasb); // deletes itself
  604. }
  605. SAFERELEASE(pbsc);
  606. // NOTE: This is not a memory leak, the object will clean itself up when it
  607. // is done the binding operation.
  608. }
  609. else
  610. hr = E_FAIL;
  611. }
  612. else
  613. hr = E_FAIL;
  614. } else if (m_Style == STYLE_LOGO3) {
  615. CCodeBaseHold *pcbhCur = NULL;
  616. m_curPos = m_cbh.GetHeadPosition();
  617. if (m_curPos == 0) {
  618. goto Exit;
  619. }
  620. pcbhCur = m_cbh.GetAt(m_curPos);
  621. if (pcbhCur == NULL) {
  622. goto Exit;
  623. }
  624. CDLDupWStr(&szCodeBase, pcbhCur->wszCodeBase);
  625. dwSize = pcbhCur->dwSize;
  626. pcbhCur->dwFlags |= CBH_FLAGS_DOWNLOADED;
  627. if (pbc != NULL) {
  628. pbc->GetObjectParam(REG_BSCB_HOLDER, (IUnknown **)&m_pClientBSC);
  629. }
  630. hr = Logo3Download(szCodeBase);
  631. } else {
  632. hr = E_NOTIMPL;
  633. }
  634. Exit:
  635. SAFEDELETE(szCodeBase);
  636. DEBUG_LEAVE(hr);
  637. return hr;
  638. }
  639. /******************************************************************************
  640. CheckDependency
  641. ******************************************************************************/
  642. /* This checks for filter criteria in <Config> tags.
  643. *
  644. * <!ELEMENT Dependency (SoftDist)* | Language | Processor | Platform>
  645. *
  646. * Returns: E_ERROR code if Dependency check fails or badly formatted.
  647. *
  648. */
  649. HRESULT
  650. CSoftDist::CheckDependency(IXMLElement *pSoftDist)
  651. {
  652. DEBUG_ENTER((DBG_DOWNLOAD,
  653. Hresult,
  654. "CSoftDist::CheckDependency",
  655. "this=%#x, %#x",
  656. this, pSoftDist
  657. ));
  658. int nLastChildTag = -1;
  659. LPSTR szLanguages = NULL;
  660. LPWSTR szCoreDist = NULL;
  661. IXMLElement *pDepend = NULL, *pCoreDist = NULL;
  662. IXMLElement *pProcessor = NULL, *pPlatform = NULL, *pLang = NULL;
  663. HRESULT hr = S_OK;
  664. DWORD style;
  665. while (GetNextChildTag(pSoftDist, DU_TAG_DEPENDENCY, &pDepend, nLastChildTag) == S_OK) {
  666. LPWSTR szCoreDist = NULL;
  667. union {
  668. char szVersion[MAX_PATH];
  669. char szStyle[MAX_PATH];
  670. char szProcessor[MAX_PATH];
  671. char szPlatformAttr[MAX_PATH];
  672. };
  673. // check for 'softdist' tag and version info.
  674. int nLastSoftDist = -1;
  675. while (GetNextChildTag(pDepend, DU_TAG_SOFTDIST, &pCoreDist, nLastSoftDist) == S_OK) {
  676. // default values if attributes are not specified.
  677. DWORD dwVersionMS = 0, dwVersionLS = 0, style = m_Style;
  678. // look for language tag (if present), otherwise NULL.
  679. SAFEDELETE(szLanguages);
  680. if (GetFirstChildTag(pCoreDist, DU_TAG_LANG, &pLang) == S_OK) {
  681. BSTR bstrLang = NULL;
  682. pLang->get_text(&bstrLang);
  683. DWORD len = lstrlenW(bstrLang);
  684. szLanguages = new char[len+1];
  685. if (!szLanguages) {
  686. hr = E_OUTOFMEMORY;
  687. SAFESYSFREESTRING(bstrLang);
  688. goto Exit;
  689. }
  690. WideCharToMultiByte(CP_ACP, 0, bstrLang , -1, szLanguages,
  691. len, NULL, NULL);
  692. SAFESYSFREESTRING(bstrLang);
  693. }
  694. if (FAILED(hr = DupAttribute(pCoreDist, DU_ATTRIB_NAME, &szCoreDist)))
  695. goto Exit;
  696. if (SUCCEEDED(GetAttributeA(pCoreDist, DU_ATTRIB_VERSION, szVersion, MAX_PATH))) {
  697. if (FAILED(GetVersionFromString(szVersion, &dwVersionMS, &dwVersionLS))) {
  698. hr = HRESULT_FROM_WIN32(GetLastError());
  699. goto Exit;
  700. }
  701. }
  702. if (SUCCEEDED(GetAttributeA(pCoreDist, DU_ATTRIB_STYLE, szStyle, MAX_PATH))) {
  703. // return is not required
  704. (void) GetStyleFromString(szStyle, &style);
  705. }
  706. hr = IsLocallyInstalled(szCoreDist, dwVersionMS, dwVersionLS,
  707. szLanguages != NULL ? szLanguages : m_szLanguages, style);
  708. SAFEDELETE(szCoreDist);
  709. // core product doesn't exist, or version is lower than required.
  710. if (hr != S_OK) {
  711. hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
  712. goto Exit;
  713. }
  714. SAFERELEASE(pCoreDist);
  715. } // while for softdist
  716. // check processor
  717. if (GetFirstChildTag(pDepend, DU_TAG_PROCESSOR, &pProcessor) == S_OK) {
  718. if (FAILED(hr = GetAttributeA(pProcessor, DU_ATTRIB_VALUE, szProcessor, MAX_PATH)))
  719. goto Exit;
  720. #ifdef WX86
  721. char *szPreferredArch;
  722. char *szAlternateArch;
  723. HRESULT hrArch;
  724. GetMultiArch()->SelectArchitecturePreferences(
  725. g_szProcessorTypes[g_CPUType],
  726. g_szProcessorTypes[PROCESSOR_ARCHITECTURE_INTEL],
  727. &szPreferredArch,
  728. &szAlternateArch);
  729. if (lstrcmpi(szPreferredArch, szProcessor) == 0) {
  730. hrArch = GetMultiArch()->RequirePrimaryArch();
  731. Assert(SUCCEEDED(hrArch));
  732. } else if (szAlternateArch && lstrcmpi(szAlternateArch, szProcessor) == 0) {
  733. hrArch = GetMultiArch()->RequireAlternateArch();
  734. Assert(SUCCEEDED(hrArch));
  735. } else {
  736. //
  737. // Processor type is neither perferred nor alternate.
  738. //
  739. hr = HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH);
  740. goto Exit;
  741. }
  742. #else
  743. if (lstrcmpi(g_szProcessorTypes[g_CPUType],szProcessor) != 0) {
  744. hr = HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH);
  745. goto Exit;
  746. }
  747. #endif
  748. }
  749. // check platform
  750. if (GetFirstChildTag(pDepend, DU_TAG_PLATFORM, &pPlatform) == S_OK) {
  751. if (FAILED(hr = GetAttributeA(pPlatform, DU_ATTRIB_VALUE, szPlatformAttr, MAX_PATH)))
  752. goto Exit;
  753. if (lstrcmpi(szPlatform, szPlatformAttr) != 0) {
  754. hr = HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH);
  755. goto Exit;
  756. }
  757. }
  758. SAFERELEASE(pDepend);
  759. } // dependency check loop
  760. Exit:
  761. SAFERELEASE(pDepend);
  762. SAFERELEASE(pCoreDist);
  763. SAFERELEASE(pProcessor);
  764. SAFERELEASE(pPlatform);
  765. SAFERELEASE(pLang);
  766. SAFEDELETE(szLanguages);
  767. SAFEDELETE(szCoreDist);
  768. DEBUG_LEAVE(hr);
  769. return hr;
  770. }
  771. /******************************************************************************
  772. CheckConfig
  773. ******************************************************************************/
  774. /* This checks for filter criteria in <Config> tags.
  775. *
  776. * <!ELEMENT Config (CodeBase)*>
  777. * <!ATTLIST Config Language CDATA #IMPLIED>
  778. * <!ATTLIST Config (OS OSVersion) CDATA #IMPLIED>
  779. * <!ATTLIST Config Processor CDATA #IMPLIED>
  780. */
  781. HRESULT
  782. CSoftDist::CheckConfig(IXMLElement *pSoftDist)
  783. {
  784. DEBUG_ENTER((DBG_DOWNLOAD,
  785. Hresult,
  786. "CSoftDist::CheckConfig",
  787. "this=%#x, %#x",
  788. this, pSoftDist
  789. ));
  790. IXMLElement *pConfig = NULL;
  791. IXMLElement *pCodeBase = NULL;
  792. BOOL fFoundMatchingConfig = FALSE;
  793. BOOL fFoundAnyConfig = FALSE;
  794. HRESULT hr = S_OK;
  795. int nLastChildTag = -1;
  796. int nLastChildCodeBase = -1;
  797. WCHAR szResult[INTERNET_MAX_URL_LENGTH];
  798. DWORD dwSize = 0;
  799. // Process CONFIG tags
  800. while (GetNextChildTag(pSoftDist, DU_TAG_CONFIG, &pConfig, nLastChildTag) == S_OK) {
  801. fFoundAnyConfig = TRUE;
  802. if (ProcessImplementation(pConfig, &m_cbh, GetThreadLocale(),
  803. #ifdef WX86
  804. GetMultiArch(),
  805. #endif
  806. m_szBaseURL) == S_OK) {
  807. fFoundMatchingConfig = TRUE;
  808. break;
  809. }
  810. SAFERELEASE(pConfig);
  811. }
  812. // if at least one config and none match, return with error.
  813. if (fFoundAnyConfig && !fFoundMatchingConfig) {
  814. hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
  815. goto Exit;
  816. }
  817. Exit:
  818. SAFERELEASE(pConfig);
  819. SAFERELEASE(pCodeBase);
  820. DEBUG_LEAVE(hr);
  821. return hr;
  822. }
  823. typedef HRESULT (STDAPICALLTYPE *PFNLCIDTORFC1766)(LCID, LPSTR, DWORD);
  824. HRESULT
  825. GetLangStringMod(HMODULE hMod, LCID localeID, char *szThisLang, int iLen)
  826. {
  827. DEBUG_ENTER((DBG_DOWNLOAD,
  828. Hresult,
  829. "GetLangStringMod",
  830. "%#x, %#x, %.80q",
  831. hMod, localeID, szThisLang
  832. ));
  833. PFNLCIDTORFC1766 pfnLCIDToRFC1766 = NULL;
  834. HRESULT hr = S_OK;
  835. #ifdef UNICODE
  836. pfnLCIDToRFC1766 = (PFNLCIDTORFC1766)GetProcAddress(hMod, "LcidToRfc1766W");
  837. #else
  838. pfnLCIDToRFC1766 = (PFNLCIDTORFC1766)GetProcAddress(hMod, "LcidToRfc1766A");
  839. #endif
  840. if (pfnLCIDToRFC1766) {
  841. hr = pfnLCIDToRFC1766(localeID, szThisLang, iLen);
  842. } else {
  843. hr = E_UNEXPECTED;
  844. }
  845. DEBUG_LEAVE(hr);
  846. return hr;
  847. }
  848. HRESULT
  849. GetLangString(LCID localeID, char *szThisLang, int iLen)
  850. {
  851. DEBUG_ENTER((DBG_DOWNLOAD,
  852. Hresult,
  853. "GetLangString",
  854. "%#x, %.80q",
  855. localeID, szThisLang
  856. ));
  857. HRESULT hr = S_OK;
  858. HMODULE hMod = 0;
  859. LCID lcidPrimaryBrowser = PRIMARYLANGID(LANGIDFROMLCID(g_lcidBrowser));
  860. // use cached copies of browser lang string
  861. if ( (localeID == g_lcidBrowser) && g_szBrowserLang[0] ) {
  862. StrNCpy(szThisLang, g_szBrowserLang, iLen);
  863. goto Exit;
  864. }
  865. if ( (localeID == lcidPrimaryBrowser) && g_szBrowserPrimaryLang[0] ) {
  866. StrNCpy(szThisLang, g_szBrowserPrimaryLang, iLen);
  867. goto Exit;
  868. }
  869. hMod = LoadLibrary("mlang.dll");
  870. if (!hMod) {
  871. hr = HRESULT_FROM_WIN32(GetLastError());
  872. goto Exit;
  873. }
  874. hr = GetLangStringMod(hMod, localeID, szThisLang, iLen);
  875. Exit:
  876. if (hMod)
  877. FreeLibrary(hMod);
  878. DEBUG_LEAVE(hr);
  879. return hr;
  880. }
  881. // globals for code downloader
  882. extern CMutexSem g_mxsCodeDownloadGlobals;
  883. BOOL g_bLangInit = FALSE;
  884. HRESULT
  885. InitBrowserLangStrings()
  886. {
  887. DEBUG_ENTER((DBG_DOWNLOAD,
  888. Hresult,
  889. "InitBrowserLangStrings",
  890. NULL
  891. ));
  892. HRESULT hr = S_OK;
  893. CLock lck(g_mxsCodeDownloadGlobals);
  894. static const char *cszSHDOCVW = "\\shdocvw.dll";
  895. if (g_bLangInit)
  896. {
  897. DEBUG_LEAVE(hr);
  898. return hr;
  899. }
  900. g_bLangInit = TRUE;
  901. CLocalComponentInfo lci;
  902. DWORD dwVerMS, dwVerLS;
  903. GetSystemDirectory(lci.szExistingFileName, MAX_PATH);
  904. StrCatBuff(lci.szExistingFileName, cszSHDOCVW, sizeof(lci.szExistingFileName));
  905. if (SUCCEEDED(GetFileVersion(&lci, &dwVerMS, &dwVerLS))) {
  906. if (lci.lcid) {
  907. g_lcidBrowser = lci.lcid;
  908. }
  909. }
  910. HMODULE hMod = LoadLibrary("mlang.dll");
  911. LCID lcidPrimaryBrowser = PRIMARYLANGID(LANGIDFROMLCID(g_lcidBrowser));
  912. if (hMod) {
  913. hr = GetLangStringMod(hMod, g_lcidBrowser, g_szBrowserLang, g_lenBrowserLang);
  914. hr = GetLangStringMod(hMod, lcidPrimaryBrowser, g_szBrowserPrimaryLang, g_lenBrowserPrimaryLang);
  915. FreeLibrary(hMod);
  916. } else {
  917. hr = HRESULT_FROM_WIN32(GetLastError());
  918. }
  919. DEBUG_LEAVE(hr);
  920. return hr;
  921. }
  922. /******************************************************************************
  923. CheckLanguage
  924. ******************************************************************************/
  925. /* The languages string is of the form,
  926. * lang1;lang2;lang3;...
  927. *
  928. * OR = '*' (the first character is an asterick).
  929. *
  930. * This routine will scan the LocaleID string (as saved from registry, GetLocaleInfo)
  931. * for an occurrence in the szLanguage string. If found, it returns true. If '*'
  932. * is specified, the result is always true. Regular expressions are otherwise
  933. * not supported.
  934. *
  935. */
  936. HRESULT CheckLanguage(LCID localeID, LPTSTR szLanguage)
  937. {
  938. DEBUG_ENTER((DBG_DOWNLOAD,
  939. Hresult,
  940. "CheckLanguage",
  941. "%#x, %.80q",
  942. localeID, szLanguage
  943. ));
  944. LCID lcidPrimaryBrowser = PRIMARYLANGID(LANGIDFROMLCID(g_lcidBrowser));
  945. CHAR szThisLang[MAX_PATH];
  946. int i;
  947. HRESULT hr = S_OK;
  948. if (szLanguage == NULL)
  949. {
  950. DEBUG_LEAVE(S_OK);
  951. return S_OK;
  952. }
  953. if (*szLanguage == '*')
  954. {
  955. DEBUG_LEAVE(S_OK);
  956. return S_OK;
  957. }
  958. hr = GetLangString(localeID, (char *)szThisLang, sizeof(szThisLang));
  959. if (FAILED(hr)) {
  960. DEBUG_LEAVE(hr);
  961. return hr;
  962. }
  963. if (AreAllLanguagesPresent((char *)szThisLang, szLanguage)) {
  964. DEBUG_LEAVE(S_OK);
  965. return S_OK;
  966. }
  967. // check with primary language
  968. localeID = PRIMARYLANGID(LANGIDFROMLCID(localeID));
  969. hr = GetLangString(localeID, (char *)szThisLang, sizeof(szThisLang));
  970. if (FAILED(hr)) {
  971. DEBUG_LEAVE(hr);
  972. return hr;
  973. }
  974. if (AreAllLanguagesPresent((char *)szThisLang, szLanguage)) {
  975. DEBUG_LEAVE(S_OK);
  976. return S_OK;
  977. }
  978. hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_LANG_NOT_FOUND);
  979. DEBUG_LEAVE(hr);
  980. return hr;
  981. }
  982. HRESULT
  983. CSoftDist::IsLocallyInstalled(LPCWSTR szDistUnit, DWORD dwVersionMS, DWORD dwVersionLS, LPCSTR szLanguages, DWORD Style)
  984. {
  985. DEBUG_ENTER((DBG_DOWNLOAD,
  986. Hresult,
  987. "CSoftDist::IsLocallyInstalled",
  988. "this=%#x, %.80wq, %#x, %#x, %.80q, %#x",
  989. this, szDistUnit, dwVersionMS, dwVersionLS, szLanguages, Style
  990. ));
  991. Assert(szDistUnit);
  992. HRESULT hr = S_OK;
  993. if (Style == STYLE_MSICD)
  994. hr = IsICDLocallyInstalled(szDistUnit, dwVersionMS, dwVersionLS, szLanguages);
  995. else if (Style == STYLE_ACTIVE_SETUP)
  996. hr = IsActSetupLocallyInstalled(szDistUnit, dwVersionMS, dwVersionLS, szLanguages);
  997. else if (Style == STYLE_LOGO3)
  998. hr = IsLogo3LocallyInstalled(szDistUnit, dwVersionMS, dwVersionLS, szLanguages);
  999. else
  1000. hr = E_UNEXPECTED;
  1001. DEBUG_LEAVE(hr);
  1002. return hr;
  1003. }
  1004. HRESULT
  1005. CSoftDist::IsLogo3LocallyInstalled(LPCWSTR szDistUnit, DWORD dwVersionMS, DWORD dwVersionLS, LPCSTR szLanguages)
  1006. {
  1007. DEBUG_ENTER((DBG_DOWNLOAD,
  1008. Hresult,
  1009. "CSoftDist::IsLogo3LocallyInstalled",
  1010. "this=%#x, %.80wq, %#x, %#x, %.80q",
  1011. this, szDistUnit, dwVersionMS, dwVersionLS, szLanguages
  1012. ));
  1013. HRESULT hr = S_OK;
  1014. DWORD dwInstVersionMS = 0;
  1015. DWORD dwInstVersionLS = 0;
  1016. DWORD dwType = 0;
  1017. DWORD dwLen = 0;
  1018. LPSTR szDU = NULL;
  1019. HKEY hkeyLogo3 = 0;
  1020. HKEY hkeyDist = 0;
  1021. // No LOGO3 language information is stored, so language checking is not
  1022. // possible yet.
  1023. Assert(szDistUnit);
  1024. if (!szDistUnit) {
  1025. hr = E_INVALIDARG;
  1026. goto Exit;
  1027. }
  1028. dwLen = WideCharToMultiByte(CP_ACP,0, szDistUnit, -1, NULL, 0, NULL, NULL);
  1029. szDU = new char [dwLen];
  1030. if (szDU == NULL) {
  1031. hr = E_OUTOFMEMORY;
  1032. goto Exit;
  1033. }
  1034. WideCharToMultiByte(CP_ACP, 0, szDistUnit , -1, szDU,
  1035. dwLen, NULL, NULL);
  1036. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_LOGO3_SETTINGS,
  1037. 0, KEY_READ, &hkeyLogo3) != ERROR_SUCCESS) {
  1038. hr = E_FAIL;
  1039. goto Exit;
  1040. }
  1041. if (RegOpenKeyEx(hkeyLogo3, szDU, 0, KEY_READ, &hkeyDist) != ERROR_SUCCESS) {
  1042. hr = S_FALSE;
  1043. goto Exit;
  1044. }
  1045. dwLen = sizeof(DWORD);
  1046. if (RegQueryValueEx(hkeyDist, REGVAL_LOGO3_MAJORVERSION, 0, &dwType,
  1047. (LPBYTE)&dwInstVersionMS, &dwLen) != ERROR_SUCCESS) {
  1048. hr = S_FALSE;
  1049. goto Exit;
  1050. }
  1051. dwLen = sizeof(DWORD);
  1052. if (RegQueryValueEx(hkeyDist, REGVAL_LOGO3_MINORVERSION, 0, &dwType,
  1053. (LPBYTE)&dwInstVersionLS, &dwLen) != ERROR_SUCCESS) {
  1054. hr = S_FALSE;
  1055. goto Exit;
  1056. }
  1057. m_distunitinst.dwInstalledVersionMS = dwInstVersionMS;
  1058. m_distunitinst.dwInstalledVersionLS = dwInstVersionLS;
  1059. if (dwInstVersionMS > dwVersionMS ||
  1060. (dwInstVersionMS == dwVersionMS && dwInstVersionLS >= dwVersionLS)) {
  1061. hr = S_OK;
  1062. } else {
  1063. hr = S_FALSE;
  1064. }
  1065. Exit:
  1066. if (hkeyLogo3) {
  1067. RegCloseKey(hkeyLogo3);
  1068. }
  1069. if (hkeyDist) {
  1070. RegCloseKey(hkeyDist);
  1071. }
  1072. if (szDU) {
  1073. delete [] szDU;
  1074. }
  1075. DEBUG_LEAVE(hr);
  1076. return hr;
  1077. }
  1078. HRESULT
  1079. CSoftDist::IsICDLocallyInstalled(LPCWSTR szDistUnit, DWORD dwVersionMS, DWORD dwVersionLS, LPCSTR szLanguages)
  1080. {
  1081. DEBUG_ENTER((DBG_DOWNLOAD,
  1082. Hresult,
  1083. "CSoftDist::IsICDLocallyInstalled",
  1084. "this=%#x, %.80wq, %#x, %#x, %.80q",
  1085. this, szDistUnit, dwVersionMS, dwVersionLS, szLanguages
  1086. ));
  1087. Assert(szDistUnit);
  1088. CLSID inclsid = CLSID_NULL;
  1089. HRESULT hr = S_OK;
  1090. CLocalComponentInfo* plci = NULL;
  1091. plci = new CLocalComponentInfo();
  1092. if(!plci) {
  1093. hr = E_OUTOFMEMORY;
  1094. goto Exit;
  1095. }
  1096. // if fails szDistUnit is not clsid
  1097. CLSIDFromString((LPOLESTR)szDistUnit, &inclsid);
  1098. // check to see if locally installed.
  1099. if ((hr = IsControlLocallyInstalled(NULL,
  1100. (LPCLSID)&inclsid, szDistUnit,
  1101. dwVersionMS, dwVersionLS, plci, NULL)) != S_FALSE) {
  1102. // S_OK if local version OK
  1103. // ERROR, fail
  1104. goto Exit;
  1105. }
  1106. // check for other hooks like Active Setup, Add/Remove Programs here
  1107. Exit:
  1108. if (plci)
  1109. {
  1110. m_distunitinst.dwInstalledVersionMS = plci->dwLocFVMS;
  1111. m_distunitinst.dwInstalledVersionLS = plci->dwLocFVLS;
  1112. }
  1113. SAFEDELETE(plci);
  1114. DEBUG_LEAVE(hr);
  1115. return hr;
  1116. }
  1117. HRESULT
  1118. CSoftDist::IsAdvertised(LPBOOL lpfIsPrecached, LPBOOL lpfIsAuthorizedCDF)
  1119. {
  1120. DEBUG_ENTER((DBG_DOWNLOAD,
  1121. Hresult,
  1122. "CSoftDist::IsAdvertised",
  1123. "this=%#x, %#x, %#x",
  1124. this, lpfIsPrecached, lpfIsAuthorizedCDF
  1125. ));
  1126. HRESULT hr = S_OK;
  1127. if (m_Style == STYLE_MSICD)
  1128. hr = IsICDAdvertised(lpfIsPrecached, lpfIsAuthorizedCDF);
  1129. else if (m_Style == STYLE_ACTIVE_SETUP)
  1130. hr = IsActSetupAdvertised(lpfIsPrecached, lpfIsAuthorizedCDF);
  1131. else if (m_Style == STYLE_LOGO3)
  1132. hr = IsLogo3Advertised(lpfIsPrecached, lpfIsAuthorizedCDF);
  1133. else
  1134. hr = E_UNEXPECTED;
  1135. DEBUG_LEAVE(hr);
  1136. return hr;
  1137. }
  1138. HRESULT
  1139. CSoftDist::IsLogo3Advertised(LPBOOL lpfIsPrecached, LPBOOL lpfIsAuthorizedCDF)
  1140. {
  1141. DEBUG_ENTER((DBG_DOWNLOAD,
  1142. Hresult,
  1143. "CSoftDist::IsLogo3Advertised",
  1144. "this=%#x, %#x, %#x",
  1145. this, lpfIsPrecached, lpfIsAuthorizedCDF
  1146. ));
  1147. HRESULT hr = S_OK;
  1148. HKEY hkeyDistInfo = 0;
  1149. HKEY hkeyAdvertisedVersion = 0;
  1150. HKEY hkeyAuthCDF = 0;
  1151. HKEY hkeyLogo3 = 0;
  1152. DWORD lResult = 0;
  1153. DWORD dwSize = 0;
  1154. DWORD dwType;
  1155. LPSTR szDU = NULL;
  1156. DWORD dwLen = 0;
  1157. DWORD dwCurAdvMS = 0;
  1158. DWORD dwCurAdvLS = 0;
  1159. char szBuffer[MAX_REGSTR_LEN];
  1160. char szVersionBuf[MAX_PATH];
  1161. static const char *szPrecache = "Precache";
  1162. static const char *szAbstract = "Abstract";
  1163. static const char *szAuthorizedCDF = "AuthorizedCDFPrefix";
  1164. static const char *szHREF = "HREF";
  1165. static const char *szTITLE = "TITLE";
  1166. ASSERT(lpfIsPrecached && lpfIsAuthorizedCDF);
  1167. if (!lpfIsPrecached || !lpfIsAuthorizedCDF) {
  1168. hr = E_INVALIDARG;
  1169. goto Exit;
  1170. }
  1171. *lpfIsPrecached = FALSE;
  1172. *lpfIsAuthorizedCDF = FALSE;
  1173. if (m_szDistUnit) {
  1174. if (FAILED(Unicode2Ansi(m_szDistUnit, &szDU))) {
  1175. hr = E_OUTOFMEMORY;
  1176. goto Exit;
  1177. }
  1178. }
  1179. else {
  1180. hr = E_INVALIDARG;
  1181. goto Exit;
  1182. }
  1183. wnsprintf(szBuffer, sizeof(szBuffer)-1, "%s\\%s", REGSTR_PATH_LOGO3_SETTINGS, szDU);
  1184. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ,
  1185. &hkeyLogo3) != ERROR_SUCCESS) {
  1186. hr = S_FALSE;
  1187. goto Exit;
  1188. }
  1189. *lpfIsAuthorizedCDF = IsAuthorizedCDF(hkeyLogo3);
  1190. if (RegOpenKeyEx(hkeyLogo3, "AvailableVersion", 0, KEY_READ,
  1191. &hkeyDistInfo) != ERROR_SUCCESS) {
  1192. hr = S_FALSE;
  1193. goto Exit;
  1194. }
  1195. dwSize = sizeof(DWORD);
  1196. if (RegQueryValueEx(hkeyDistInfo, szPrecache, 0, &dwType,
  1197. (unsigned char *)&lResult, &dwSize) == ERROR_SUCCESS) {
  1198. // Precached value was the code download HR
  1199. *lpfIsPrecached = (SUCCEEDED(lResult)) ? (TRUE) : (FALSE);
  1200. }
  1201. // This key is optionally present.
  1202. dwSize = MAX_PATH;
  1203. if (RegQueryValueEx(hkeyDistInfo, REGSTR_LOGO3_ADVERTISED_VERSION, NULL, &dwType,
  1204. (unsigned char *)szVersionBuf, &dwSize) == ERROR_SUCCESS)
  1205. {
  1206. GetVersionFromString(szVersionBuf, &m_dwVersionAdvertisedMS, &m_dwVersionAdvertisedLS);
  1207. }
  1208. // Get the AdState, if any
  1209. dwSize = sizeof(DWORD);
  1210. RegQueryValueEx(hkeyDistInfo, REGVAL_ADSTATE, NULL, NULL, (LPBYTE)&m_dwAdState, &dwSize);
  1211. if (!m_szAbstract) {
  1212. if (RegQueryValueEx(hkeyDistInfo, szAbstract, NULL, &dwType,
  1213. NULL, &dwSize) == ERROR_SUCCESS) {
  1214. m_szAbstract = new char[dwSize];
  1215. if (!m_szAbstract) {
  1216. hr = E_OUTOFMEMORY;
  1217. goto Exit;
  1218. }
  1219. if (RegQueryValueEx(hkeyDistInfo, szAbstract, NULL, &dwType,
  1220. (unsigned char *)m_szAbstract, &dwSize) != ERROR_SUCCESS) {
  1221. hr = HRESULT_FROM_WIN32(GetLastError());
  1222. goto Exit;
  1223. }
  1224. }
  1225. }
  1226. if (!m_szHREF) {
  1227. if (RegQueryValueEx(hkeyDistInfo, szHREF, NULL, &dwType,
  1228. NULL, &dwSize) == ERROR_SUCCESS) {
  1229. m_szHREF = new char[dwSize];
  1230. if (!m_szHREF) {
  1231. hr = E_OUTOFMEMORY;
  1232. goto Exit;
  1233. }
  1234. if (RegQueryValueEx(hkeyDistInfo, szHREF, NULL, &dwType,
  1235. (unsigned char *)m_szHREF, &dwSize) != ERROR_SUCCESS) {
  1236. hr = HRESULT_FROM_WIN32(GetLastError());
  1237. goto Exit;
  1238. }
  1239. }
  1240. }
  1241. if (!m_szTitle) {
  1242. if (RegQueryValueEx(hkeyDistInfo, szTITLE, NULL, &dwType,
  1243. NULL, &dwSize) == ERROR_SUCCESS) {
  1244. m_szTitle = new char[dwSize];
  1245. if (!m_szHREF) {
  1246. hr = E_OUTOFMEMORY;
  1247. goto Exit;
  1248. }
  1249. if (RegQueryValueEx(hkeyDistInfo, szTITLE, NULL, &dwType,
  1250. (unsigned char *)m_szTitle, &dwSize) != ERROR_SUCCESS) {
  1251. hr = HRESULT_FROM_WIN32(GetLastError());
  1252. goto Exit;
  1253. }
  1254. }
  1255. }
  1256. dwSize = MAX_PATH;
  1257. if (RegQueryValueEx(hkeyDistInfo, NULL, NULL, &dwType,
  1258. (unsigned char *)szVersionBuf, &dwSize) != ERROR_SUCCESS) {
  1259. hr = S_FALSE;
  1260. goto Exit;
  1261. }
  1262. if ( FAILED(GetVersionFromString(szVersionBuf, &dwCurAdvMS, &dwCurAdvLS))){
  1263. hr = S_FALSE;
  1264. goto Exit;
  1265. }
  1266. if (!(m_dwVersionMS|m_dwVersionLS)) {
  1267. m_dwVersionMS = dwCurAdvMS;
  1268. m_dwVersionLS = dwCurAdvLS;
  1269. }
  1270. if (IsCDFNewerVersion(dwCurAdvMS, dwCurAdvLS)) {
  1271. hr = S_FALSE;
  1272. }
  1273. else {
  1274. hr = S_OK;
  1275. }
  1276. Exit:
  1277. if (hkeyDistInfo) {
  1278. RegCloseKey(hkeyDistInfo);
  1279. }
  1280. if (hkeyAdvertisedVersion) {
  1281. RegCloseKey(hkeyAdvertisedVersion);
  1282. }
  1283. if (hkeyLogo3) {
  1284. RegCloseKey(hkeyLogo3);
  1285. }
  1286. if (hkeyAuthCDF) {
  1287. RegCloseKey(hkeyAuthCDF);
  1288. }
  1289. SAFEDELETE(szDU);
  1290. DEBUG_LEAVE(hr);
  1291. return hr;
  1292. }
  1293. // **** IsICDAdvertised ****
  1294. // returns: S_FALSE for not advertised (or newest version not advertised)
  1295. // S_OK for advertised
  1296. HRESULT
  1297. CSoftDist::IsICDAdvertised(LPBOOL lpfIsPrecached, LPBOOL lpfIsAuthorizedCDF)
  1298. {
  1299. DEBUG_ENTER((DBG_DOWNLOAD,
  1300. Hresult,
  1301. "CSoftDist::IsICDAdvertised",
  1302. "this=%#x, %#x, %#x",
  1303. this, lpfIsPrecached, lpfIsAuthorizedCDF
  1304. ));
  1305. HRESULT hr = S_OK;
  1306. LONG lResult = ERROR_SUCCESS;
  1307. HKEY hkeyDist =0;
  1308. HKEY hkeyThisDist = 0;
  1309. HKEY hkeyVersion = 0;
  1310. HKEY hkeyAdvertisedVersion = 0;
  1311. DWORD Size = MAX_PATH;
  1312. DWORD SizeDword = sizeof(DWORD);
  1313. DWORD dwType;
  1314. DWORD dwCurAdvMS = 0;
  1315. DWORD dwCurAdvLS = 0;
  1316. const static char * szAvailableVersion = "AvailableVersion";
  1317. const static char * szHREF = "HREF";
  1318. const static char * szABSTRACT = "Abstract";
  1319. const static char * szPrecache = "Precache";
  1320. const static char * szAuthorizedCDF = "AuthorizedCDFPrefix";
  1321. LPSTR pszDist = NULL;
  1322. char szVersionBuf[MAX_PATH];
  1323. ASSERT(lpfIsPrecached && lpfIsAuthorizedCDF);
  1324. if (!lpfIsPrecached || !lpfIsAuthorizedCDF) {
  1325. hr = E_INVALIDARG;
  1326. goto Exit;
  1327. }
  1328. *lpfIsPrecached = FALSE;
  1329. *lpfIsAuthorizedCDF = TRUE;
  1330. if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGSTR_PATH_DIST_UNITS,
  1331. 0, KEY_ALL_ACCESS, &hkeyDist)) != ERROR_SUCCESS) {
  1332. hr = S_FALSE;
  1333. goto Exit;
  1334. }
  1335. if (FAILED((hr=::Unicode2Ansi(m_szDistUnit, &pszDist))))
  1336. {
  1337. goto Exit;
  1338. }
  1339. // open the dist unit key for this dist unit.
  1340. if (RegOpenKeyEx( hkeyDist, pszDist,
  1341. 0, KEY_ALL_ACCESS, &hkeyThisDist) != ERROR_SUCCESS) {
  1342. hr = S_FALSE;
  1343. goto Exit;
  1344. }
  1345. *lpfIsAuthorizedCDF = IsAuthorizedCDF(hkeyThisDist, /*bOptional*/TRUE);
  1346. if (RegOpenKeyEx( hkeyThisDist, szAvailableVersion,
  1347. 0, KEY_ALL_ACCESS, &hkeyVersion) != ERROR_SUCCESS) {
  1348. hr = S_FALSE;
  1349. goto Exit;
  1350. }
  1351. if (RegQueryValueEx(hkeyVersion, szPrecache, 0, &dwType,
  1352. (unsigned char *)&lResult, &SizeDword) == ERROR_SUCCESS) {
  1353. // check for success or common error conditions which indicate we have bits.
  1354. if (SUCCEEDED(lResult)) {
  1355. *lpfIsPrecached = TRUE;
  1356. } else {
  1357. *lpfIsPrecached = FALSE;
  1358. }
  1359. }
  1360. // This key is optionally present.
  1361. if ( RegOpenKeyEx( hkeyThisDist, REGKEY_MSICD_ADVERTISED_VERSION,
  1362. 0, KEY_ALL_ACCESS, &hkeyAdvertisedVersion) == ERROR_SUCCESS )
  1363. {
  1364. Size = MAX_PATH;
  1365. if (RegQueryValueEx(hkeyAdvertisedVersion, NULL, NULL, &dwType,
  1366. (unsigned char *)szVersionBuf, &Size) == ERROR_SUCCESS)
  1367. GetVersionFromString(szVersionBuf, &m_dwVersionAdvertisedMS, &m_dwVersionAdvertisedLS);
  1368. // Get the AdState, if any
  1369. SizeDword = sizeof(DWORD);
  1370. RegQueryValueEx( hkeyAdvertisedVersion, REGVAL_ADSTATE, NULL, NULL, (LPBYTE)&m_dwAdState, &SizeDword);
  1371. }
  1372. // save away the advt info like Title, href, abstract
  1373. // if called from GetDistributionUnitAdvt()
  1374. if (!m_szTitle) {
  1375. if (RegQueryValueEx(hkeyThisDist, NULL, NULL, &dwType,
  1376. NULL, &Size) == ERROR_SUCCESS) {
  1377. m_szTitle = new char[Size];
  1378. if (!m_szTitle) {
  1379. hr = E_OUTOFMEMORY;
  1380. goto Exit;
  1381. }
  1382. if (RegQueryValueEx(hkeyThisDist, NULL, NULL, &dwType,
  1383. (unsigned char *)m_szTitle, &Size) != ERROR_SUCCESS) {
  1384. hr = HRESULT_FROM_WIN32(GetLastError());
  1385. goto Exit;
  1386. }
  1387. }
  1388. }
  1389. if (!m_szAbstract) {
  1390. if (RegQueryValueEx(hkeyVersion, szABSTRACT, NULL, &dwType,
  1391. NULL, &Size) == ERROR_SUCCESS) {
  1392. m_szAbstract = new char[Size];
  1393. if (!m_szAbstract) {
  1394. hr = E_OUTOFMEMORY;
  1395. goto Exit;
  1396. }
  1397. if (RegQueryValueEx(hkeyVersion, szABSTRACT, NULL, &dwType,
  1398. (unsigned char *)m_szAbstract, &Size) != ERROR_SUCCESS) {
  1399. hr = HRESULT_FROM_WIN32(GetLastError());
  1400. goto Exit;
  1401. }
  1402. }
  1403. }
  1404. if (!m_szHREF) {
  1405. if (RegQueryValueEx(hkeyVersion, szHREF, NULL, &dwType,
  1406. NULL, &Size) == ERROR_SUCCESS) {
  1407. m_szHREF = new char[Size];
  1408. if (!m_szHREF) {
  1409. hr = E_OUTOFMEMORY;
  1410. goto Exit;
  1411. }
  1412. if (RegQueryValueEx(hkeyVersion, szHREF, NULL, &dwType,
  1413. (unsigned char *)m_szHREF, &Size) != ERROR_SUCCESS) {
  1414. hr = HRESULT_FROM_WIN32(GetLastError());
  1415. goto Exit;
  1416. }
  1417. }
  1418. }
  1419. if (RegQueryValueEx(hkeyVersion, NULL, NULL, &dwType,
  1420. (unsigned char *)szVersionBuf, &Size) != ERROR_SUCCESS) {
  1421. hr = S_FALSE;
  1422. goto Exit;
  1423. }
  1424. if ( FAILED(GetVersionFromString(szVersionBuf, &dwCurAdvMS, &dwCurAdvLS))){
  1425. hr = S_FALSE;
  1426. goto Exit;
  1427. }
  1428. if (!(m_dwVersionMS|m_dwVersionLS)) {
  1429. m_dwVersionMS = dwCurAdvMS;
  1430. m_dwVersionLS = dwCurAdvLS;
  1431. }
  1432. if (IsCDFNewerVersion(dwCurAdvMS, dwCurAdvLS))
  1433. hr = S_FALSE;
  1434. else
  1435. hr = S_OK;
  1436. Exit:
  1437. SAFEDELETE(pszDist);
  1438. SAFEREGCLOSEKEY(hkeyVersion);
  1439. SAFEREGCLOSEKEY(hkeyAdvertisedVersion);
  1440. SAFEREGCLOSEKEY(hkeyDist);
  1441. SAFEREGCLOSEKEY(hkeyThisDist);
  1442. DEBUG_LEAVE(hr);
  1443. return hr;
  1444. }
  1445. HRESULT
  1446. CSoftDist::Advertise(BOOL bFullAdvt)
  1447. {
  1448. DEBUG_ENTER((DBG_DOWNLOAD,
  1449. Hresult,
  1450. "CSoftDist::Advertise",
  1451. "this=%#x, %B",
  1452. this, bFullAdvt
  1453. ));
  1454. HRESULT hr = S_OK;
  1455. if (m_Style == STYLE_MSICD)
  1456. hr = ICDAdvertise(bFullAdvt);
  1457. else if (m_Style == STYLE_ACTIVE_SETUP)
  1458. hr = ActSetupAdvertise(bFullAdvt);
  1459. else if (m_Style == STYLE_LOGO3)
  1460. hr = Logo3Advertise(bFullAdvt);
  1461. else
  1462. hr = E_UNEXPECTED;
  1463. DEBUG_LEAVE(hr);
  1464. return hr;
  1465. }
  1466. HRESULT
  1467. CSoftDist::Logo3Advertise(BOOL bFullAdvt)
  1468. {
  1469. DEBUG_ENTER((DBG_DOWNLOAD,
  1470. Hresult,
  1471. "CSoftDist::Logo3Advertise",
  1472. "this=%#x, %B",
  1473. this, bFullAdvt
  1474. ));
  1475. HRESULT hr = S_OK;
  1476. DWORD dwLen = 0;
  1477. DWORD lResult = 0;
  1478. LPSTR szDU = NULL;
  1479. HKEY hkeyLogo3 = 0;
  1480. HKEY hkeyDist = 0;
  1481. HKEY hkeyAvailVersion = 0;
  1482. DWORD dwAdState;
  1483. static const char *szAvailableVersion = "AvailableVersion";
  1484. static const char *szPrecache = "Precache";
  1485. static const char *szHREF = "HREF";
  1486. static const char *szTitle = "Title";
  1487. char szVersionBuf[MAX_PATH];
  1488. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_LOGO3_SETTINGS,
  1489. 0, KEY_ALL_ACCESS, &hkeyLogo3) != ERROR_SUCCESS) {
  1490. hr = E_FAIL;
  1491. goto Exit;
  1492. }
  1493. dwLen = WideCharToMultiByte(CP_ACP,0, m_szDistUnit, -1, NULL, 0, NULL, NULL);
  1494. szDU = new char [dwLen];
  1495. if (szDU == NULL) {
  1496. hr = E_OUTOFMEMORY;
  1497. goto Exit;
  1498. }
  1499. WideCharToMultiByte(CP_ACP, 0, m_szDistUnit , -1, szDU, dwLen, NULL, NULL);
  1500. if (RegOpenKeyEx(hkeyLogo3, szDU, 0, KEY_ALL_ACCESS, &hkeyDist) != ERROR_SUCCESS) {
  1501. // Create key if it doesn't exist
  1502. if ((lResult = RegCreateKey(hkeyLogo3, szDU, &hkeyDist)) != ERROR_SUCCESS) {
  1503. hr = HRESULT_FROM_WIN32(lResult);
  1504. goto Exit;
  1505. }
  1506. }
  1507. if (RegOpenKeyEx(hkeyDist, szAvailableVersion, 0, KEY_ALL_ACCESS,
  1508. &hkeyAvailVersion) != ERROR_SUCCESS) {
  1509. if ((lResult = RegCreateKey(hkeyDist, szAvailableVersion, &hkeyAvailVersion)) != ERROR_SUCCESS) {
  1510. hr = HRESULT_FROM_WIN32(lResult);
  1511. goto Exit;
  1512. }
  1513. }
  1514. wsprintf(szVersionBuf, "%d,%d,%d,%d",
  1515. (m_dwVersionMS & 0xffff0000)>>16,
  1516. (m_dwVersionMS & 0xffff),
  1517. (m_dwVersionLS & 0xffff0000)>>16,
  1518. (m_dwVersionLS & 0xffff));
  1519. lResult = ::RegSetValueEx(hkeyAvailVersion, NULL, NULL, REG_SZ,
  1520. (unsigned char *)szVersionBuf,
  1521. lstrlen(szVersionBuf) + 1);
  1522. if (bFullAdvt || IsAbstractDifferent(hkeyAvailVersion, m_szAbstract)) {
  1523. // Clear previous AdState, if any
  1524. dwAdState = SOFTDIST_ADSTATE_NONE;
  1525. // Don't panic if this fails
  1526. lResult = ::RegSetValueEx(hkeyAvailVersion, REGVAL_ADSTATE, NULL,
  1527. REG_DWORD, (unsigned char *)&dwAdState, sizeof(DWORD));
  1528. // save HREF
  1529. if ((lResult == ERROR_SUCCESS) && m_szHREF) {
  1530. lResult = ::RegSetValueEx(hkeyAvailVersion, szHREF, NULL, REG_SZ,
  1531. (unsigned char *)m_szHREF,
  1532. lstrlen(m_szHREF) + 1);
  1533. }
  1534. // save Abstract
  1535. if ((lResult == ERROR_SUCCESS) && m_szAbstract) {
  1536. lResult = RegSetValueEx(hkeyAvailVersion, REGVAL_ABSTRACT_AVAILABLE,
  1537. NULL, REG_SZ, (unsigned char *)m_szAbstract,
  1538. lstrlen(m_szAbstract) + 1);
  1539. }
  1540. // save Title
  1541. if ((lResult == ERROR_SUCCESS) && m_szTitle) {
  1542. lResult = ::RegSetValueEx(hkeyAvailVersion, szTitle, NULL, REG_SZ,
  1543. (unsigned char *)m_szTitle,
  1544. lstrlen(m_szTitle) + 1);
  1545. }
  1546. }
  1547. if (lResult != ERROR_SUCCESS) {
  1548. hr = HRESULT_FROM_WIN32(lResult);
  1549. goto Exit;
  1550. }
  1551. // new advertisement, remove old precache
  1552. if (bFullAdvt)
  1553. ::RegDeleteValue(hkeyAvailVersion, szPrecache);
  1554. Exit:
  1555. if (hkeyLogo3) {
  1556. RegCloseKey(hkeyLogo3);
  1557. }
  1558. if (hkeyDist) {
  1559. RegCloseKey(hkeyDist);
  1560. }
  1561. if (hkeyAvailVersion) {
  1562. RegCloseKey(hkeyAvailVersion);
  1563. }
  1564. if (szDU) {
  1565. delete [] szDU;
  1566. }
  1567. DEBUG_LEAVE(hr);
  1568. return hr;
  1569. }
  1570. HRESULT
  1571. CSoftDist::ICDAdvertise(BOOL bFullAdvt)
  1572. {
  1573. DEBUG_ENTER((DBG_DOWNLOAD,
  1574. Hresult,
  1575. "CSoftDist::ICDAdvertise",
  1576. "this=%#x, %B",
  1577. this, bFullAdvt
  1578. ));
  1579. HRESULT hr = S_OK;
  1580. LONG lResult = ERROR_SUCCESS;
  1581. HKEY hkeyDist =0;
  1582. HKEY hkeyThisDist = 0;
  1583. HKEY hkeyDownloadInfo = 0;
  1584. HKEY hkeyVersion = 0;
  1585. HKEY hkeyAdvertisedVersion = 0;
  1586. const static char * szAvailableVersion = "AvailableVersion";
  1587. const static char * szDownloadInfo = "DownloadInformation";
  1588. const static char * szCODEBASE = "CODEBASE";
  1589. const static char * szLOCALCDF = "CDF";
  1590. const static char * szINSTALLER = "Installer";
  1591. const static char * szMSICD = "MSICD";
  1592. const static char * szHREF = "HREF";
  1593. const static char * szPrecache = "Precache";
  1594. char szTmpCodeBase[MAX_PATH+sizeof(szCODEBASE)+5];
  1595. LPSTR pszCodeBase = NULL;
  1596. int numCodeBase;
  1597. POSITION pos;
  1598. LPSTR pszDist = NULL;
  1599. char szVersionBuf[MAX_PATH];
  1600. if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGSTR_PATH_DIST_UNITS,
  1601. 0, KEY_ALL_ACCESS, &hkeyDist)) != ERROR_SUCCESS) {
  1602. if ((lResult = RegCreateKey( HKEY_LOCAL_MACHINE,
  1603. REGSTR_PATH_DIST_UNITS, &hkeyDist)) != ERROR_SUCCESS) {
  1604. hr = HRESULT_FROM_WIN32(lResult);
  1605. goto Exit;
  1606. }
  1607. }
  1608. if (FAILED((hr=::Unicode2Ansi(m_szDistUnit, &pszDist))))
  1609. {
  1610. goto Exit;
  1611. }
  1612. // open/create the dist unit key for this dist unit.
  1613. if (RegOpenKeyEx( hkeyDist, pszDist,
  1614. 0, KEY_ALL_ACCESS, &hkeyThisDist) != ERROR_SUCCESS) {
  1615. if ((lResult = RegCreateKey( hkeyDist,
  1616. pszDist, &hkeyThisDist)) != ERROR_SUCCESS) {
  1617. hr = HRESULT_FROM_WIN32(lResult);
  1618. goto Exit;
  1619. }
  1620. }
  1621. if (m_szTitle &&
  1622. ((lResult = ::RegSetValueEx(hkeyThisDist, NULL, NULL, REG_SZ,
  1623. (unsigned char *)m_szTitle,
  1624. lstrlen(m_szTitle)+1)) != ERROR_SUCCESS)){
  1625. hr = HRESULT_FROM_WIN32(lResult);
  1626. goto Exit;
  1627. }
  1628. lResult = ::RegSetValueEx(hkeyThisDist, szINSTALLER, NULL, REG_SZ,
  1629. (unsigned char *)szMSICD, sizeof(szMSICD)+1);
  1630. if (lResult != ERROR_SUCCESS) {
  1631. hr = HRESULT_FROM_WIN32(lResult);
  1632. goto Exit;
  1633. }
  1634. // open/create the download info key for this dist unit.
  1635. if (RegOpenKeyEx( hkeyThisDist, szDownloadInfo,
  1636. 0, KEY_ALL_ACCESS, &hkeyDownloadInfo) != ERROR_SUCCESS) {
  1637. if ((lResult = RegCreateKey( hkeyThisDist,
  1638. szDownloadInfo, &hkeyDownloadInfo)) != ERROR_SUCCESS) {
  1639. hr = HRESULT_FROM_WIN32(lResult);
  1640. goto Exit;
  1641. }
  1642. }
  1643. // set download info params
  1644. if (GetCDF() && (lResult = ::RegSetValueEx(hkeyDownloadInfo,
  1645. szLOCALCDF, NULL, REG_SZ, (unsigned char *)GetCDF(), lstrlen(GetCDF())+1)) != ERROR_SUCCESS) {
  1646. hr = HRESULT_FROM_WIN32(lResult);
  1647. goto Exit;
  1648. }
  1649. pos = m_cbh.GetHeadPosition();
  1650. numCodeBase = 1;
  1651. while (pos != NULL) {
  1652. CCodeBaseHold *cbh = m_cbh.GetNext(pos);
  1653. if (numCodeBase <= 1)
  1654. lstrcpy((char *)szTmpCodeBase, szCODEBASE);
  1655. else
  1656. wsprintf(szTmpCodeBase, "%s%d", szCODEBASE, numCodeBase);
  1657. if (FAILED(::Unicode2Ansi(cbh->wszCodeBase,&pszCodeBase))) {
  1658. hr = E_OUTOFMEMORY;
  1659. goto Exit;
  1660. }
  1661. if ((lResult = ::RegSetValueEx(hkeyDownloadInfo, szTmpCodeBase,
  1662. NULL, REG_SZ, (unsigned char *)pszCodeBase, strlen(pszCodeBase))) != ERROR_SUCCESS) {
  1663. SAFEDELETE(pszCodeBase);
  1664. hr = HRESULT_FROM_WIN32(lResult);
  1665. goto Exit;
  1666. }
  1667. SAFEDELETE(pszCodeBase);
  1668. numCodeBase ++;
  1669. }
  1670. // Note Version
  1671. wsprintf(szVersionBuf, "%d,%d,%d,%d",
  1672. (m_dwVersionMS & 0xffff0000)>>16,
  1673. (m_dwVersionMS & 0xffff),
  1674. (m_dwVersionLS & 0xffff0000)>>16,
  1675. (m_dwVersionLS & 0xffff));
  1676. if (RegOpenKeyEx( hkeyThisDist, szAvailableVersion,
  1677. 0, KEY_ALL_ACCESS, &hkeyVersion) != ERROR_SUCCESS) {
  1678. if ((lResult = RegCreateKey( hkeyThisDist,
  1679. szAvailableVersion, &hkeyVersion)) != ERROR_SUCCESS) {
  1680. hr = HRESULT_FROM_WIN32(lResult);
  1681. goto Exit;
  1682. }
  1683. }
  1684. if (bFullAdvt || IsAbstractDifferent(hkeyVersion, m_szAbstract)) {
  1685. // Clear previous AdState, if any
  1686. if (RegOpenKey(hkeyThisDist, REGKEY_MSICD_ADVERTISED_VERSION, &hkeyAdvertisedVersion) == ERROR_SUCCESS)
  1687. {
  1688. DWORD dwAdState = SOFTDIST_ADSTATE_NONE;
  1689. // Don't panic if this fails
  1690. lResult = ::RegSetValueEx(hkeyAdvertisedVersion, REGVAL_ADSTATE, NULL, REG_DWORD,
  1691. (unsigned char *)&dwAdState, sizeof(DWORD) );
  1692. }
  1693. }
  1694. // new advertisement, remove old precache
  1695. if (bFullAdvt)
  1696. ::RegDeleteValue(hkeyVersion, szPrecache);
  1697. lResult = ::RegSetValueEx(hkeyVersion, NULL, NULL, REG_SZ,
  1698. (unsigned char *)szVersionBuf, lstrlen(szVersionBuf)+1);
  1699. // save HREF
  1700. if ( (lResult == ERROR_SUCCESS) && m_szHREF)
  1701. lResult = ::RegSetValueEx(hkeyVersion, szHREF, NULL, REG_SZ,
  1702. (unsigned char *)m_szHREF, lstrlen(m_szHREF)+1);
  1703. // save Abstract
  1704. if ( (lResult == ERROR_SUCCESS) && m_szAbstract)
  1705. lResult = ::RegSetValueEx(hkeyVersion, REGVAL_ABSTRACT_AVAILABLE, NULL, REG_SZ,
  1706. (unsigned char *)m_szAbstract, lstrlen(m_szAbstract)+1);
  1707. if (lResult != ERROR_SUCCESS) {
  1708. hr = HRESULT_FROM_WIN32(lResult);
  1709. goto Exit;
  1710. }
  1711. Exit:
  1712. SAFEDELETE(pszDist);
  1713. SAFEDELETE(pszCodeBase);
  1714. SAFEREGCLOSEKEY(hkeyDownloadInfo);
  1715. SAFEREGCLOSEKEY(hkeyVersion);
  1716. SAFEREGCLOSEKEY(hkeyDist);
  1717. SAFEREGCLOSEKEY(hkeyThisDist);
  1718. SAFEREGCLOSEKEY(hkeyAdvertisedVersion);
  1719. DEBUG_LEAVE(hr);
  1720. return hr;
  1721. }
  1722. BOOL
  1723. CSoftDist::IsAuthorizedCDF(HKEY hkeyRootDU, BOOL bOptional)
  1724. {
  1725. DEBUG_ENTER((DBG_DOWNLOAD,
  1726. Bool,
  1727. "CSoftDist::IsAuthorizedCDF",
  1728. "this=%#x, %#x, %B",
  1729. this, hkeyRootDU, bOptional
  1730. ));
  1731. const static char *szAuthorizedCDF="AuthorizedCDFPrefix";
  1732. BOOL fResult = FALSE;
  1733. HRESULT hr;
  1734. int iValue = 0;
  1735. CHAR szEnumCDF[MAX_PATH];
  1736. DWORD dwValueSize = MAX_PATH;
  1737. LPWSTR wzCDFURL = 0;
  1738. IInternetSecurityManager *pism = 0;
  1739. DWORD dwZone = 0, dwType = 0;
  1740. HKEY hkeyAuthCDF = 0;
  1741. DWORD dwPolicy = 0;
  1742. DWORD dwContext = 0;
  1743. if (!hkeyRootDU) {
  1744. goto Exit;
  1745. }
  1746. if (!m_szCDFURL) {
  1747. goto Exit;
  1748. }
  1749. if (FAILED(CoInternetCreateSecurityManager(NULL, &pism, 0)) || !pism) {
  1750. goto Exit;
  1751. }
  1752. if (FAILED(Ansi2Unicode(m_szCDFURL, &wzCDFURL))) {
  1753. goto Exit;
  1754. }
  1755. pism->ProcessUrlAction(wzCDFURL, URLACTION_CHANNEL_SOFTDIST_PERMISSIONS,
  1756. (BYTE *)&dwPolicy, sizeof(dwPolicy),
  1757. (BYTE *)&dwContext, sizeof(dwContext),
  1758. PUAF_NOUI, 0);
  1759. if (dwPolicy == URLPOLICY_CHANNEL_SOFTDIST_AUTOINSTALL)
  1760. {
  1761. fResult = TRUE;
  1762. goto Exit;
  1763. }
  1764. // if no "AuthorizedCDF" key exists we don't do any prefix checking
  1765. if (RegOpenKeyEx( hkeyRootDU, szAuthorizedCDF,
  1766. 0, KEY_READ, &hkeyAuthCDF) != ERROR_SUCCESS) {
  1767. if (bOptional)
  1768. fResult = TRUE;
  1769. goto Exit;
  1770. }
  1771. iValue = 0;
  1772. while (RegEnumValue(hkeyAuthCDF, iValue++,
  1773. szEnumCDF, &dwValueSize, 0, &dwType, NULL, NULL) == ERROR_SUCCESS) {
  1774. dwValueSize = MAX_PATH; // reset
  1775. // check for partial match, if found return true.
  1776. if (StrCmpNI(szEnumCDF, m_szCDFURL, min(lstrlenA(szEnumCDF), lstrlenA(m_szCDFURL))) == 0) {
  1777. fResult = TRUE;
  1778. goto Exit;
  1779. }
  1780. }
  1781. Exit:
  1782. SAFERELEASE(pism);
  1783. SAFEDELETE(wzCDFURL);
  1784. if (hkeyAuthCDF)
  1785. RegCloseKey(hkeyAuthCDF);
  1786. DEBUG_LEAVE(fResult);
  1787. return fResult;
  1788. }
  1789. BOOL
  1790. CSoftDist::IsCDFNewerVersion(DWORD dwLocFVMS, DWORD dwLocFVLS)
  1791. {
  1792. DEBUG_ENTER((DBG_DOWNLOAD,
  1793. Bool,
  1794. "CSoftDist::IsCDFNewerVersion",
  1795. "this=%#x, %#x, %#x",
  1796. this, dwLocFVMS, dwLocFVLS
  1797. ));
  1798. BOOL fRet = ((m_dwVersionMS > dwLocFVMS) ||
  1799. ((m_dwVersionMS == dwLocFVMS) &&
  1800. (m_dwVersionLS > dwLocFVLS)));
  1801. DEBUG_LEAVE(fRet);
  1802. return fRet;
  1803. }
  1804. HRESULT
  1805. CSoftDist::IsActSetupLocallyInstalled(LPCWSTR szDistUnit, DWORD dwVersionMS, DWORD dwVersionLS, LPCSTR szLanguages)
  1806. {
  1807. DEBUG_ENTER((DBG_DOWNLOAD,
  1808. Hresult,
  1809. "CSoftDist::IsActSetupLocallyInstalled",
  1810. "this=%#x, %.80wq, %#x, %#x, %.80q",
  1811. this, szDistUnit, dwVersionMS, dwVersionLS, szLanguages
  1812. ));
  1813. Assert(szDistUnit);
  1814. HRESULT hr = S_FALSE, hr2; // Not installed by active setup.
  1815. LONG lResult = ERROR_SUCCESS;
  1816. LPSTR pszKey = NULL;
  1817. BOOL bAllocedKey = FALSE;
  1818. int nKey;
  1819. //we've done this at THREE other places in the code, so let's raise this from 1 to 2 *MAX_PATH
  1820. char szKey[2*MAX_PATH];
  1821. char szVersion[MAX_PATH];
  1822. HKEY hKey = NULL;
  1823. DWORD dwSize;
  1824. DWORD dwValue;
  1825. DWORD dwType;
  1826. BOOL fIsInstalled = FALSE;
  1827. WORD wVersion[4];
  1828. LPSTR pszDist = NULL;
  1829. DWORD dwCurMS = 0;
  1830. DWORD dwCurLS = 0;
  1831. const static char * szLocale = "Locale";
  1832. const static char * szIsInstalled = "IsInstalled";
  1833. const static char * szActVersion = "Version";
  1834. if (FAILED((hr2=::Unicode2Ansi(szDistUnit, &pszDist))))
  1835. {
  1836. hr = hr2;
  1837. goto Exit;
  1838. }
  1839. ULONG ulenDist = lstrlenA(pszDist);
  1840. //sizeof counts terminating NULL also, so subtract 2, and add 1 for the final NULL
  1841. ULONG ulenConst = sizeof(REGKEY_ACTIVESETUP_COMPONENTS)/sizeof(CHAR) + sizeof("\\")/sizeof(CHAR) - 2 + 1;
  1842. if ((ulenDist+ulenConst) > sizeof(szKey))
  1843. {
  1844. pszKey = new CHAR[ulenDist+ulenConst];
  1845. }
  1846. if (pszKey)
  1847. {
  1848. bAllocedKey = TRUE;
  1849. nKey = ulenDist+ulenConst;
  1850. }
  1851. else
  1852. {
  1853. pszKey = szKey;
  1854. nKey = sizeof(szKey);
  1855. }
  1856. StrNCpy(pszKey, REGKEY_ACTIVESETUP_COMPONENTS, nKey);
  1857. StrCatBuff(pszKey, "\\", nKey);
  1858. StrCatBuff(pszKey, pszDist, nKey);
  1859. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  1860. {
  1861. // Check for the installed language. And see if it fits the availabel szLanguages
  1862. dwSize = sizeof(szVersion);
  1863. if (RegQueryValueEx( hKey, szLocale, NULL, NULL, (LPBYTE)szVersion, &dwSize) == ERROR_SUCCESS)
  1864. {
  1865. if (szLanguages && !AreAllLanguagesPresent(szVersion, szLanguages))
  1866. goto Exit;
  1867. }
  1868. dwSize = sizeof(dwValue);
  1869. // Old format of the Installed components did not have the IsInstalled value.
  1870. if (RegQueryValueEx( hKey, szIsInstalled, NULL, NULL, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS)
  1871. {
  1872. dwValue = 0;
  1873. }
  1874. fIsInstalled = (dwValue != 0);
  1875. if (fIsInstalled)
  1876. {
  1877. dwSize = sizeof(szVersion);
  1878. if ( (lResult = RegQueryValueEx(hKey, szActVersion, NULL, &dwType, (LPBYTE)szVersion, &dwSize)) == ERROR_SUCCESS )
  1879. {
  1880. if (dwType == REG_SZ)
  1881. {
  1882. if ( SUCCEEDED(GetVersionFromString(szVersion, &dwCurMS, &dwCurLS)))
  1883. {
  1884. m_distunitinst.dwInstalledVersionMS = dwCurMS;
  1885. m_distunitinst.dwInstalledVersionLS = dwCurLS;
  1886. if (dwCurMS > dwVersionMS ||
  1887. (dwCurMS == dwVersionMS && dwCurLS >= dwVersionLS)) {
  1888. hr = S_OK;
  1889. } else {
  1890. hr = S_FALSE;
  1891. }
  1892. }
  1893. }
  1894. else
  1895. {
  1896. dwSize = 4 * sizeof(WORD);
  1897. if ( (lResult = RegQueryValueEx(hKey, szActVersion, NULL, NULL, (LPBYTE)wVersion, &dwSize)) == ERROR_SUCCESS )
  1898. {
  1899. // The registry version number is saved hi-word MS lo-word MS hi-word LS lo-word LS
  1900. // therefore we need to put the data manualy into the DWORDs
  1901. dwCurMS = (DWORD)wVersion[0] << 16; // Make hi word of MS version
  1902. dwCurMS += (DWORD)wVersion[1]; // Make lo word of MS version
  1903. dwCurLS = (DWORD)wVersion[2] << 16; // Make hi word of LS version
  1904. dwCurLS += (DWORD)wVersion[3]; // Make lo word of LS version
  1905. if (dwCurMS > dwVersionMS ||
  1906. (dwCurMS == dwVersionMS && dwCurLS >= dwVersionLS)) {
  1907. hr = S_OK;
  1908. } else {
  1909. hr = S_FALSE;
  1910. }
  1911. }
  1912. else
  1913. hr = HRESULT_FROM_WIN32(lResult);
  1914. }
  1915. }
  1916. // If "Version" doesn't exist we assume its been advertised
  1917. // but not locally installed.
  1918. }
  1919. }
  1920. Exit:
  1921. if (bAllocedKey)
  1922. {
  1923. delete [] pszKey;
  1924. }
  1925. SAFEREGCLOSEKEY(hKey);
  1926. SAFEDELETE(pszDist);
  1927. DEBUG_LEAVE(hr);
  1928. return hr;
  1929. }
  1930. HRESULT CSoftDist::ActSetupAdvertise(BOOL bFullAdvt)
  1931. {
  1932. DEBUG_ENTER((DBG_DOWNLOAD,
  1933. Hresult,
  1934. "CSoftDist::ActSetupAdvertise",
  1935. "this=%#x, %B",
  1936. this, bFullAdvt
  1937. ));
  1938. LPSTR pszKey = NULL;
  1939. BOOL bAllocedKey = FALSE;
  1940. int nKey;
  1941. char szKey[2*MAX_PATH];
  1942. HKEY hKey;
  1943. HRESULT hr = S_OK;
  1944. LPSTR pszDist = NULL;
  1945. LONG lResult = ERROR_SUCCESS;
  1946. static const char *szPrecache = "Precache";
  1947. if (FAILED((hr=::Unicode2Ansi(m_szDistUnit, &pszDist))))
  1948. {
  1949. goto Exit;
  1950. }
  1951. ULONG ulenDist = lstrlenA(pszDist);
  1952. //sizeof counts terminating NULL also, so subtract 2, and add 1 for the final NULL
  1953. ULONG ulenConst = sizeof(REGKEY_ACTIVESETUP_COMPONENTS)/sizeof(CHAR) + sizeof("\\")/sizeof(CHAR) - 2 + 1;
  1954. if ((ulenDist+ulenConst) > sizeof(szKey))
  1955. {
  1956. pszKey = new CHAR[ulenDist+ulenConst];
  1957. }
  1958. if (pszKey)
  1959. {
  1960. bAllocedKey = TRUE;
  1961. nKey = ulenDist + ulenConst;
  1962. }
  1963. else
  1964. {
  1965. pszKey = szKey;
  1966. nKey = sizeof(szKey);
  1967. }
  1968. StrNCpy(pszKey, REGKEY_ACTIVESETUP_COMPONENTS, nKey);
  1969. StrCatBuff(pszKey, "\\", nKey);
  1970. StrCatBuff(pszKey, pszDist, nKey);
  1971. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE,
  1972. KEY_READ|KEY_SET_VALUE, NULL, &hKey, NULL) == ERROR_SUCCESS)
  1973. {
  1974. DWORD dwAdStateInit = SOFTDIST_ADSTATE_NONE;
  1975. // Note Version
  1976. wsprintf(pszKey, "%d,%d,%d,%d",
  1977. (m_dwVersionMS & 0xffff0000)>>16,
  1978. (m_dwVersionMS & 0xffff),
  1979. (m_dwVersionLS & 0xffff0000)>>16,
  1980. (m_dwVersionLS & 0xffff));
  1981. lResult = ::RegSetValueEx(hKey, REGVAL_VERSION_AVAILABLE, NULL, REG_SZ,
  1982. (unsigned char *)pszKey, lstrlen(pszKey)+1);
  1983. if (bFullAdvt || IsAbstractDifferent(hKey, m_szAbstract)) {
  1984. // (re)set the ad state
  1985. lResult = ::RegSetValueEx(hKey, REGVAL_ADSTATE, NULL, REG_DWORD,
  1986. (unsigned char *)&dwAdStateInit, sizeof(DWORD) );
  1987. if( (lResult == ERROR_SUCCESS) && m_szTitle)
  1988. lResult=RegSetValueEx(hKey,REGVAL_TITLE_AVAILABLE, NULL, REG_SZ,
  1989. (unsigned char *)m_szTitle, lstrlen(m_szTitle)+1);
  1990. if( (lResult == ERROR_SUCCESS) && m_szAbstract)
  1991. lResult=RegSetValueEx(hKey,REGVAL_ABSTRACT_AVAILABLE, NULL,
  1992. REG_SZ, (unsigned char *)m_szAbstract, lstrlen(m_szAbstract)+1);
  1993. if( (lResult == ERROR_SUCCESS) && m_szHREF) {
  1994. //
  1995. // Check if this is the IE4 GUID. If so, change IE's
  1996. // First Home Page to point to this HREF.
  1997. /*
  1998. // This is no longer being used because we pop up a dialog instead
  1999. if (lstrcmpi(pszDist, DISTUNIT_NAME_IE4) == 0) {
  2000. HKEY hKeyIE = 0;
  2001. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_IE_MAIN, 0, KEY_SET_VALUE, &hKeyIE) == ERROR_SUCCESS) {
  2002. RegSetValueEx(hKeyIE,REGVAL_FIRST_HOME_PAGE, NULL,
  2003. REG_SZ, (unsigned char *)m_szHREF, lstrlen(m_szHREF)+1);
  2004. RegCloseKey(hKeyIE);
  2005. }
  2006. }
  2007. */
  2008. lResult =RegSetValueEx(hKey,REGVAL_HREF_AVAILABLE, NULL, REG_SZ,
  2009. (unsigned char *)m_szHREF, lstrlen(m_szHREF)+1);
  2010. }
  2011. }
  2012. if (lResult != ERROR_SUCCESS)
  2013. {
  2014. hr = HRESULT_FROM_WIN32(lResult);
  2015. }
  2016. // new advertisement, remove old precache
  2017. if (bFullAdvt)
  2018. ::RegDeleteValue(hKey, szPrecache);
  2019. RegCloseKey(hKey);
  2020. }
  2021. Exit:
  2022. if (bAllocedKey)
  2023. {
  2024. delete [] pszKey;
  2025. }
  2026. SAFEDELETE(pszDist);
  2027. DEBUG_LEAVE(hr);
  2028. return hr;
  2029. }
  2030. HRESULT CSoftDist::IsActSetupAdvertised(LPBOOL lpfIsPrecached, LPBOOL lpfIsAuthorized)
  2031. {
  2032. DEBUG_ENTER((DBG_DOWNLOAD,
  2033. Hresult,
  2034. "CSoftDist::IsActSetupAdvertised",
  2035. "this=%#x, %#x, %#x",
  2036. this, lpfIsPrecached, lpfIsAuthorized
  2037. ));
  2038. HKEY hKey;
  2039. LPSTR pszTmp = NULL;
  2040. BOOL bAllocedTmp = FALSE;
  2041. int nTmp;
  2042. char szTmp[2*MAX_PATH];
  2043. DWORD dwSize;
  2044. DWORD dwCurAdvMS = 0;
  2045. DWORD dwCurAdvLS = 0;
  2046. HRESULT hr = S_FALSE, hr2;
  2047. LPSTR pszDist = NULL;
  2048. LONG lResult = ERROR_SUCCESS;
  2049. const static char * szPrecache = "Precache";
  2050. ASSERT(lpfIsPrecached && lpfIsAuthorized);
  2051. if (!lpfIsPrecached || !lpfIsAuthorized) {
  2052. hr = E_INVALIDARG;
  2053. goto Exit;
  2054. }
  2055. *lpfIsPrecached = FALSE;
  2056. *lpfIsAuthorized = TRUE;
  2057. if (FAILED((hr2=::Unicode2Ansi(m_szDistUnit, &pszDist))))
  2058. {
  2059. hr = hr2;
  2060. goto Exit;
  2061. }
  2062. hr = S_FALSE; // reset: assume not advertised
  2063. ULONG ulenDist = lstrlenA(pszDist);
  2064. //sizeof counts terminating NULL also, so subtract 2, and add 1 for the final NULL
  2065. ULONG ulenConst = sizeof(REGKEY_ACTIVESETUP_COMPONENTS)/sizeof(CHAR) + sizeof("\\")/sizeof(CHAR) - 2 + 1;
  2066. if ((ulenDist+ulenConst) > sizeof(szTmp))
  2067. {
  2068. pszTmp = new CHAR[ulenDist+ulenConst];
  2069. }
  2070. if (pszTmp)
  2071. {
  2072. bAllocedTmp = TRUE;
  2073. nTmp = ulenDist + ulenConst;
  2074. }
  2075. else
  2076. {
  2077. pszTmp = szTmp;
  2078. nTmp = sizeof(szTmp);
  2079. }
  2080. StrNCpy(pszTmp, REGKEY_ACTIVESETUP_COMPONENTS, nTmp);
  2081. StrCatBuff(pszTmp, "\\", nTmp);
  2082. StrCatBuff(pszTmp, pszDist, nTmp);
  2083. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszTmp, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  2084. {
  2085. *lpfIsAuthorized = IsAuthorizedCDF(hKey);
  2086. dwSize = sizeof(szTmp);
  2087. if (RegQueryValueEx( hKey, REGVAL_VERSION_AVAILABLE, NULL, NULL, (LPBYTE)szTmp, &dwSize) == ERROR_SUCCESS)
  2088. {
  2089. DWORD Size;
  2090. DWORD dwType;
  2091. char szVersionAdvertised[MAX_PATH];
  2092. DWORD SizeDword = sizeof(DWORD);
  2093. // check for precache registry key
  2094. if (RegQueryValueEx(hKey, szPrecache, 0, &dwType,
  2095. (unsigned char *)&lResult, &SizeDword) == ERROR_SUCCESS) {
  2096. // check for success or common error conditions which indicate we have bits.
  2097. if (SUCCEEDED(lResult)) {
  2098. *lpfIsPrecached = TRUE;
  2099. } else {
  2100. *lpfIsPrecached = FALSE;
  2101. }
  2102. }
  2103. dwSize = sizeof(szVersionAdvertised);
  2104. m_dwVersionAdvertisedMS = 0;
  2105. m_dwVersionAdvertisedLS = 0;
  2106. // read in the advertised version, if any
  2107. if (RegQueryValueEx( hKey, REGVAL_VERSION_ADVERTISED, NULL, NULL,
  2108. (LPBYTE)szVersionAdvertised, &dwSize) == ERROR_SUCCESS)
  2109. {
  2110. if ( SUCCEEDED(GetVersionFromString(szTmp, &dwCurAdvMS, &dwCurAdvLS)))
  2111. {
  2112. m_dwVersionAdvertisedMS = dwCurAdvMS;
  2113. m_dwVersionAdvertisedLS = dwCurAdvLS;
  2114. }
  2115. SizeDword = sizeof(DWORD);
  2116. RegQueryValueEx( hKey, REGVAL_ADSTATE, NULL, NULL, (LPBYTE)&m_dwAdState, &SizeDword);
  2117. }
  2118. dwCurAdvMS = 0;
  2119. dwCurAdvLS = 0;
  2120. // save away the advt info like Title, href, abstract
  2121. // if called from GetDistributionUnitAdvt()
  2122. if (!m_szHREF) {
  2123. if (RegQueryValueEx(hKey, REGVAL_HREF_AVAILABLE, NULL, &dwType,
  2124. NULL, &Size) == ERROR_SUCCESS) {
  2125. m_szHREF = new char[Size];
  2126. if (!m_szHREF) {
  2127. hr = E_OUTOFMEMORY;
  2128. goto Exit;
  2129. }
  2130. if (RegQueryValueEx(hKey, REGVAL_HREF_AVAILABLE, NULL, &dwType,
  2131. (unsigned char *)m_szHREF, &Size) != ERROR_SUCCESS) {
  2132. hr = HRESULT_FROM_WIN32(GetLastError());
  2133. goto Exit;
  2134. }
  2135. }
  2136. }
  2137. if (!m_szTitle) {
  2138. if (RegQueryValueEx(hKey, REGVAL_TITLE_AVAILABLE, NULL, &dwType,
  2139. NULL, &Size) == ERROR_SUCCESS) {
  2140. m_szTitle = new char[Size];
  2141. if (!m_szTitle) {
  2142. hr = E_OUTOFMEMORY;
  2143. goto Exit;
  2144. }
  2145. if (RegQueryValueEx(hKey, REGVAL_TITLE_AVAILABLE, NULL, &dwType,
  2146. (unsigned char *)m_szTitle, &Size) != ERROR_SUCCESS) {
  2147. hr = HRESULT_FROM_WIN32(GetLastError());
  2148. goto Exit;
  2149. }
  2150. }
  2151. }
  2152. if (!m_szAbstract) {
  2153. if (RegQueryValueEx(hKey, REGVAL_ABSTRACT_AVAILABLE, NULL, &dwType,
  2154. NULL, &Size) == ERROR_SUCCESS) {
  2155. m_szAbstract = new char[Size];
  2156. if (!m_szAbstract) {
  2157. hr = E_OUTOFMEMORY;
  2158. goto Exit;
  2159. }
  2160. if (RegQueryValueEx(hKey, REGVAL_ABSTRACT_AVAILABLE, NULL, &dwType,
  2161. (unsigned char *)m_szAbstract, &Size) != ERROR_SUCCESS) {
  2162. hr = HRESULT_FROM_WIN32(GetLastError());
  2163. goto Exit;
  2164. }
  2165. }
  2166. }
  2167. // If we have a Version available, we are done.
  2168. if ( SUCCEEDED(GetVersionFromString(szTmp, &dwCurAdvMS, &dwCurAdvLS)))
  2169. {
  2170. if (!(m_dwVersionMS|m_dwVersionLS)) {
  2171. m_dwVersionMS = dwCurAdvMS;
  2172. m_dwVersionLS = dwCurAdvLS;
  2173. }
  2174. if (IsCDFNewerVersion(dwCurAdvMS, dwCurAdvLS)) {
  2175. hr = S_FALSE;
  2176. } else {
  2177. hr = S_OK;
  2178. }
  2179. }
  2180. }
  2181. }
  2182. Exit:
  2183. if (bAllocedTmp)
  2184. {
  2185. delete [] pszTmp;
  2186. }
  2187. SAFEDELETE(pszDist);
  2188. DEBUG_LEAVE(hr);
  2189. return hr;
  2190. }
  2191. HRESULT
  2192. CSoftDist::GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi )
  2193. {
  2194. DEBUG_ENTER((DBG_DOWNLOAD,
  2195. Hresult,
  2196. "CSoftDist::GetSoftwareUpdateInfo",
  2197. "this=%#x, %.80wq, %#x",
  2198. this, szDistUnit, psdi
  2199. ));
  2200. HRESULT hr = S_OK;
  2201. DWORD dwStyle = STYLE_MSICD;
  2202. BOOL bIsPrecached = FALSE;
  2203. BOOL bIsAuthorized = FALSE;
  2204. if ( psdi != NULL )
  2205. {
  2206. psdi->szTitle = NULL;
  2207. psdi->szAbstract = NULL;
  2208. psdi->szHREF = NULL;
  2209. }
  2210. hr = PrepSoftwareUpdate( szDistUnit, &dwStyle );
  2211. if ( FAILED(hr) )
  2212. goto Exit;
  2213. if (dwStyle == STYLE_MSICD) {
  2214. hr = IsICDAdvertised(&bIsPrecached, &bIsAuthorized);
  2215. } else if (dwStyle == STYLE_LOGO3) {
  2216. hr = IsLogo3Advertised(&bIsPrecached, &bIsAuthorized);
  2217. } else {
  2218. hr = IsActSetupAdvertised(&bIsPrecached, &bIsAuthorized);
  2219. }
  2220. if ( hr == S_OK ) {
  2221. BOOL bUpdateIsNewer = IsCDFNewerVersion(m_distunitinst.dwInstalledVersionMS, m_distunitinst.dwInstalledVersionLS);
  2222. if ( psdi != NULL )
  2223. {
  2224. psdi->dwFlags = 0;
  2225. psdi->dwInstalledVersionMS = m_distunitinst.dwInstalledVersionMS;
  2226. psdi->dwInstalledVersionLS = m_distunitinst.dwInstalledVersionLS;
  2227. psdi->dwUpdateVersionMS = m_dwVersionMS;
  2228. psdi->dwUpdateVersionLS = m_dwVersionLS;
  2229. psdi->dwAdvertisedVersionMS = m_dwVersionAdvertisedMS;
  2230. psdi->dwAdvertisedVersionLS = m_dwVersionAdvertisedLS;
  2231. psdi->dwAdState = m_dwAdState;
  2232. // conjure up the flags
  2233. // Note: we never set the e-mail flag.
  2234. if ( bIsPrecached )
  2235. psdi->dwFlags |= SOFTDIST_FLAG_USAGE_PRECACHE;
  2236. // REVIEW: Is this true?
  2237. // If we're precached and the update version matches the installed version,
  2238. // then we've already auto-installed, or close enough for the purposes of
  2239. // advertisement.
  2240. if ( psdi->dwInstalledVersionMS == psdi->dwUpdateVersionMS &&
  2241. psdi->dwInstalledVersionLS == psdi->dwUpdateVersionLS )
  2242. psdi->dwFlags |= SOFTDIST_FLAG_USAGE_AUTOINSTALL;
  2243. if (m_szTitle)
  2244. {
  2245. hr = Ansi2Unicode( m_szTitle, &psdi->szTitle );
  2246. if (FAILED(hr))
  2247. goto Exit;
  2248. }
  2249. if (m_szAbstract)
  2250. {
  2251. hr = Ansi2Unicode( m_szAbstract, &psdi->szAbstract );
  2252. if (FAILED(hr))
  2253. goto Exit;
  2254. }
  2255. if (m_szHREF)
  2256. {
  2257. hr = Ansi2Unicode( m_szHREF, &psdi->szHREF );
  2258. if (FAILED(hr))
  2259. goto Exit;
  2260. }
  2261. } // if caller wants SOFTDISTINFO
  2262. if ( bUpdateIsNewer )
  2263. hr = S_OK;
  2264. else
  2265. hr = S_FALSE;
  2266. }
  2267. else
  2268. {
  2269. // return at least the current version in this situation
  2270. if ( psdi != NULL )
  2271. {
  2272. psdi->dwFlags = 0;
  2273. psdi->dwInstalledVersionMS = m_distunitinst.dwInstalledVersionMS;
  2274. psdi->dwInstalledVersionLS = m_distunitinst.dwInstalledVersionLS;
  2275. psdi->dwUpdateVersionMS = 0;
  2276. psdi->dwUpdateVersionLS = 0;
  2277. psdi->dwAdvertisedVersionMS = 0;
  2278. psdi->dwAdvertisedVersionLS = 0;
  2279. psdi->dwAdState = 0;
  2280. }
  2281. hr = E_INVALIDARG; // szDistUnit has no advertising data, not subscribed?
  2282. // BUGBUG: we want to be able to populate the SOFTDISTINFO before the first
  2283. // advertised update, but this class won't scoop up the necessary goo
  2284. // prior.
  2285. }
  2286. Exit:
  2287. if ( FAILED(hr) && psdi != NULL )
  2288. {
  2289. SAFEDELETE(psdi->szTitle);
  2290. SAFEDELETE(psdi->szAbstract);
  2291. SAFEDELETE(psdi->szHREF);
  2292. }
  2293. DEBUG_LEAVE(hr);
  2294. return hr;
  2295. }
  2296. HRESULT
  2297. CSoftDist::SetSoftwareUpdateAdvertisementState( LPCWSTR szDistUnit,
  2298. DWORD dwAdState,
  2299. DWORD dwAdvertisedVersionMS,
  2300. DWORD dwAdvertisedVersionLS )
  2301. {
  2302. DEBUG_ENTER((DBG_DOWNLOAD,
  2303. Hresult,
  2304. "CSoftDist::SetSoftwareUpdateAdvertisementState",
  2305. "this=%#x, %.80wq, %#x, %#x, %#x",
  2306. this, szDistUnit, dwAdState, dwAdvertisedVersionMS, dwAdvertisedVersionLS
  2307. ));
  2308. HRESULT hr = S_OK;
  2309. DWORD dwStyle;
  2310. TCHAR *pszDU = NULL;
  2311. hr = Unicode2Ansi( szDistUnit, &pszDU );
  2312. // code around assumes that MAX_PATH is MAX size of dist unit
  2313. // we try to make a key name with the distunit and that limit is
  2314. // now MAX_PATH. Hence the reasoning to limit this to MAX_PATH
  2315. if (FAILED(hr) || (lstrlenW(szDistUnit) > MAX_PATH)) {
  2316. if (SUCCEEDED(hr)) {
  2317. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  2318. }
  2319. goto Exit;
  2320. }
  2321. // BUFFER OVERRUN : limit size in of distunit
  2322. hr = PrepSoftwareUpdate( szDistUnit, &dwStyle );
  2323. if ( SUCCEEDED(hr) )
  2324. {
  2325. if (dwStyle == STYLE_MSICD)
  2326. {
  2327. LONG lResult = ERROR_SUCCESS;
  2328. HKEY hkeyDist =0;
  2329. HKEY hkeyThisDist = 0;
  2330. HKEY hkeyAdvertisedVersion = 0;
  2331. char szTmp[2*MAX_PATH];
  2332. wnsprintf( szTmp, sizeof(szTmp)-1, "%s\\%s\\%s", REGSTR_PATH_DIST_UNITS, pszDU, REGKEY_MSICD_ADVERTISED_VERSION );
  2333. if (RegCreateKey(HKEY_LOCAL_MACHINE, szTmp, &hkeyAdvertisedVersion) == ERROR_SUCCESS)
  2334. {
  2335. // Note Version
  2336. wsprintf(szTmp, "%d,%d,%d,%d",
  2337. (dwAdvertisedVersionMS & 0xffff0000)>>16,
  2338. (dwAdvertisedVersionMS & 0xffff),
  2339. (dwAdvertisedVersionLS & 0xffff0000)>>16,
  2340. (dwAdvertisedVersionLS & 0xffff));
  2341. lResult = ::RegSetValueEx(hkeyAdvertisedVersion, NULL, NULL, REG_SZ,
  2342. (unsigned char *)szTmp, lstrlen(szTmp)+1);
  2343. if ( lResult == ERROR_SUCCESS )
  2344. {
  2345. lResult = ::RegSetValueEx(hkeyAdvertisedVersion, REGVAL_ADSTATE, NULL, REG_DWORD,
  2346. (unsigned char *)&dwAdState, sizeof(DWORD) );
  2347. if ( lResult != ERROR_SUCCESS )
  2348. hr = HRESULT_FROM_WIN32( lResult );
  2349. }
  2350. else
  2351. hr = HRESULT_FROM_WIN32( lResult );
  2352. RegCloseKey( hkeyAdvertisedVersion );
  2353. }
  2354. }
  2355. else if (dwStyle == STYLE_LOGO3)
  2356. {
  2357. LONG lResult = ERROR_SUCCESS;
  2358. HKEY hkeyDist =0;
  2359. HKEY hkeyThisDist = 0;
  2360. HKEY hkeyAvailableVersion = 0;
  2361. char szTmp[2*MAX_PATH];
  2362. wnsprintf( szTmp, sizeof(szTmp)-1, "%s\\%s\\%s", REGSTR_PATH_LOGO3_SETTINGS, pszDU, REGKEY_LOGO3_AVAILABLE_VERSION );
  2363. if (RegCreateKey(HKEY_LOCAL_MACHINE, szTmp, &hkeyAvailableVersion) == ERROR_SUCCESS)
  2364. {
  2365. // Note Version
  2366. wsprintf(szTmp, "%d,%d,%d,%d",
  2367. (dwAdvertisedVersionMS & 0xffff0000)>>16,
  2368. (dwAdvertisedVersionMS & 0xffff),
  2369. (dwAdvertisedVersionLS & 0xffff0000)>>16,
  2370. (dwAdvertisedVersionLS & 0xffff));
  2371. lResult = ::RegSetValueEx(hkeyAvailableVersion, REGSTR_LOGO3_ADVERTISED_VERSION, NULL, REG_SZ,
  2372. (unsigned char *)szTmp, lstrlen(szTmp)+1);
  2373. if ( lResult == ERROR_SUCCESS )
  2374. {
  2375. lResult = ::RegSetValueEx(hkeyAvailableVersion, REGVAL_ADSTATE, NULL, REG_DWORD,
  2376. (unsigned char *)&dwAdState, sizeof(DWORD) );
  2377. if ( lResult != ERROR_SUCCESS )
  2378. hr = HRESULT_FROM_WIN32( lResult );
  2379. }
  2380. else
  2381. hr = HRESULT_FROM_WIN32( lResult );
  2382. RegCloseKey( hkeyAvailableVersion );
  2383. }
  2384. }
  2385. else
  2386. {
  2387. LPSTR pszKey = NULL;
  2388. BOOL bAllocedKey = FALSE;
  2389. int nKey;
  2390. CHAR szKey[2*MAX_PATH];
  2391. HKEY hKey;
  2392. LONG lResult = ERROR_SUCCESS;
  2393. ULONG ulenDist = lstrlenA(pszDU);
  2394. //sizeof counts terminating NULL also, so subtract 2, and add 1 for the final NULL
  2395. ULONG ulenConst = sizeof(REGKEY_ACTIVESETUP_COMPONENTS)/sizeof(CHAR) + sizeof("\\")/sizeof(CHAR) - 2 + 1;
  2396. if ((ulenDist+ulenConst) > sizeof(szKey))
  2397. {
  2398. pszKey = new CHAR[ulenDist+ulenConst];
  2399. }
  2400. if (pszKey)
  2401. {
  2402. bAllocedKey = TRUE;
  2403. nKey = ulenDist + ulenConst;
  2404. }
  2405. else
  2406. {
  2407. pszKey = szKey;
  2408. nKey = sizeof(szKey);
  2409. }
  2410. StrNCpy(pszKey, REGKEY_ACTIVESETUP_COMPONENTS, nKey);
  2411. StrCatBuff(pszKey, "\\", nKey);
  2412. StrCatBuff(pszKey, pszDU, nKey);
  2413. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, pszKey, 0, KEY_WRITE , &hKey ) == ERROR_SUCCESS)
  2414. {
  2415. // Note Version
  2416. wsprintf(pszKey, "%d,%d,%d,%d",
  2417. (dwAdvertisedVersionMS & 0xffff0000)>>16,
  2418. (dwAdvertisedVersionMS & 0xffff),
  2419. (dwAdvertisedVersionLS & 0xffff0000)>>16,
  2420. (dwAdvertisedVersionLS & 0xffff));
  2421. lResult = ::RegSetValueEx(hKey, REGVAL_VERSION_ADVERTISED, NULL, REG_SZ,
  2422. (unsigned char *)pszKey, lstrlen(pszKey)+1);
  2423. if ( lResult == ERROR_SUCCESS )
  2424. {
  2425. lResult = ::RegSetValueEx(hKey, REGVAL_ADSTATE, NULL, REG_DWORD,
  2426. (unsigned char *)&dwAdState, sizeof(DWORD) );
  2427. if ( lResult != ERROR_SUCCESS )
  2428. hr = HRESULT_FROM_WIN32( lResult );
  2429. }
  2430. else
  2431. hr = HRESULT_FROM_WIN32( lResult );
  2432. RegCloseKey( hKey );
  2433. }
  2434. if (bAllocedKey)
  2435. {
  2436. delete [] pszKey;
  2437. }
  2438. }
  2439. }
  2440. Exit:
  2441. SAFEDELETE(pszDU);
  2442. DEBUG_LEAVE(hr);
  2443. return hr;
  2444. }
  2445. HRESULT
  2446. CSoftDist::PrepSoftwareUpdate( LPCWSTR szDistUnit, DWORD *pdwStyle )
  2447. {
  2448. DEBUG_ENTER((DBG_DOWNLOAD,
  2449. Hresult,
  2450. "CSoftDist::PrepSoftwareUpdate",
  2451. "this=%#x, %.80wq, %#x",
  2452. this, szDistUnit, pdwStyle
  2453. ));
  2454. HRESULT hr = S_OK;
  2455. *pdwStyle = STYLE_MSICD;
  2456. hr = CDLDupWStr( &m_szDistUnit, szDistUnit );
  2457. if ( FAILED(hr) )
  2458. goto Exit;
  2459. hr = IsICDLocallyInstalled(m_szDistUnit, m_dwVersionMS, m_dwVersionLS, m_szLanguages);
  2460. if (FAILED(hr))
  2461. goto Exit;
  2462. if (!IsAnyInstalled()) {
  2463. hr = IsActSetupLocallyInstalled(m_szDistUnit, m_dwVersionMS, m_dwVersionLS, m_szLanguages);
  2464. if (FAILED(hr))
  2465. {
  2466. goto Exit;
  2467. }
  2468. else if (hr == S_OK)
  2469. {
  2470. *pdwStyle = STYLE_ACTIVE_SETUP;
  2471. goto Exit;
  2472. }
  2473. if (!IsAnyInstalled()) {
  2474. hr = IsLogo3LocallyInstalled(m_szDistUnit, m_dwVersionMS, m_dwVersionLS, m_szLanguages);
  2475. if (FAILED(hr))
  2476. {
  2477. if (!IsAnyInstalled()) {
  2478. // some prev version must be installed for this to succeed
  2479. hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
  2480. goto Exit;
  2481. }
  2482. }
  2483. else if (hr == S_OK)
  2484. {
  2485. *pdwStyle = STYLE_LOGO3;
  2486. }
  2487. }
  2488. }
  2489. Exit:
  2490. DEBUG_LEAVE(hr);
  2491. return hr;
  2492. }
  2493. STDMETHODIMP CSoftDist::Logo3DownloadNext()
  2494. {
  2495. DEBUG_ENTER((DBG_DOWNLOAD,
  2496. Hresult,
  2497. "CSoftDist::Logo3DownloadNext",
  2498. "this=%#x",
  2499. this
  2500. ));
  2501. HRESULT hr = S_FALSE;
  2502. FILETIME ftExpireTime;
  2503. FILETIME ftTime;
  2504. LPWSTR wszCodeBase = NULL;
  2505. LPSTR szDownloadedCodeBase = NULL;
  2506. LPSTR szMainCodeBase = NULL;
  2507. LPSTR szDownloadedFile = NULL;
  2508. LPSTR pszExtn = NULL;
  2509. DWORD dwSize = 0;
  2510. DWORD dwBytes;
  2511. CCodeBaseHold *pcbhPrev = NULL;
  2512. CCodeBaseHold *pcbhCur = NULL;
  2513. LISTPOSITION lpos = 0, lposOld = 0;
  2514. BOOL bFound = FALSE;
  2515. BOOL bFakeCacheEntry;
  2516. TCHAR achFileName[MAX_PATH];
  2517. LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo = NULL;
  2518. char achBuffer[MAX_CACHE_ENTRY_INFO_SIZE];
  2519. pcbhPrev = m_cbh.GetAt(m_curPos);
  2520. Assert(pcbhPrev);
  2521. if (FAILED(hr = Unicode2Ansi(pcbhPrev->wszCodeBase, &szDownloadedCodeBase))) {
  2522. goto Exit;
  2523. }
  2524. lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFO)achBuffer;
  2525. dwSize = MAX_CACHE_ENTRY_INFO_SIZE;
  2526. if (!GetUrlCacheEntryInfo(szDownloadedCodeBase, lpCacheEntryInfo, &dwSize)) {
  2527. // this should never happen
  2528. hr = E_FAIL;
  2529. goto Exit;
  2530. }
  2531. szDownloadedFile = new char[lstrlen(lpCacheEntryInfo->lpszLocalFileName) + 1];
  2532. if (szDownloadedFile == NULL) {
  2533. hr = E_OUTOFMEMORY;
  2534. goto Exit;
  2535. }
  2536. lstrcpy(szDownloadedFile, lpCacheEntryInfo->lpszLocalFileName);
  2537. GetSystemTimeAsFileTime(&ftTime);
  2538. ftExpireTime.dwLowDateTime = (DWORD)0;
  2539. ftExpireTime.dwHighDateTime = (DWORD)0;
  2540. // Mark all CCodeBaseHold's with same group as downloaded and find
  2541. // main codebase
  2542. bFakeCacheEntry = TRUE;
  2543. szMainCodeBase = NULL;
  2544. lpos = m_cbh.GetHeadPosition();
  2545. while (lpos) {
  2546. pcbhCur = m_cbh.GetNext(lpos);
  2547. if (pcbhCur->dwFlags & CBH_FLAGS_MAIN_CODEBASE) {
  2548. Assert(szMainCodeBase == NULL); // we should only get here once
  2549. if (FAILED(Unicode2Ansi(pcbhCur->wszCodeBase, &szMainCodeBase))) {
  2550. hr = E_FAIL;
  2551. goto Exit;
  2552. }
  2553. if (pcbhCur == pcbhPrev || StrCmpW(pcbhCur->wszDLGroup, pcbhPrev->wszDLGroup)) {
  2554. bFakeCacheEntry = FALSE;
  2555. }
  2556. }
  2557. if (pcbhCur == pcbhPrev) {
  2558. continue;
  2559. }
  2560. if (!StrCmpW(pcbhPrev->wszDLGroup, pcbhCur->wszDLGroup)) {
  2561. pcbhCur->dwFlags |= CBH_FLAGS_DOWNLOADED;
  2562. }
  2563. }
  2564. // Fake a cache entry for this
  2565. if (bFakeCacheEntry) {
  2566. Assert(szMainCodeBase != NULL);
  2567. lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFO)achBuffer;
  2568. dwSize = MAX_CACHE_ENTRY_INFO_SIZE;
  2569. if (!GetUrlCacheEntryInfo(szMainCodeBase, lpCacheEntryInfo, &dwSize)) {
  2570. pszExtn = PathFindExtension(szMainCodeBase) + 1;
  2571. if (CreateUrlCacheEntry((LPCSTR)szMainCodeBase, 0, pszExtn,
  2572. achFileName, 0)) {
  2573. CopyFile(szDownloadedFile, achFileName, FALSE);
  2574. CommitUrlCacheEntry(szMainCodeBase, achFileName, ftExpireTime,
  2575. ftTime, NORMAL_CACHE_ENTRY, NULL, 0,
  2576. pszExtn, szDownloadedCodeBase);
  2577. }
  2578. }
  2579. }
  2580. // Iterate list until we get a new group
  2581. pcbhCur = NULL;
  2582. lpos = m_cbh.GetHeadPosition();
  2583. while (lpos) {
  2584. lposOld = lpos;
  2585. pcbhCur = m_cbh.GetNext(lpos);
  2586. if (!(pcbhCur->dwFlags & CBH_FLAGS_DOWNLOADED)) {
  2587. m_curPos = lposOld;
  2588. bFound = TRUE;
  2589. pcbhCur->dwFlags |= CBH_FLAGS_DOWNLOADED;
  2590. hr = CDLDupWStr(&wszCodeBase, pcbhCur->wszCodeBase);
  2591. break;
  2592. }
  2593. }
  2594. hr = (bFound) ? (Logo3Download(wszCodeBase)) : (S_FALSE);
  2595. Exit:
  2596. SAFEDELETE(szDownloadedCodeBase);
  2597. SAFEDELETE(szDownloadedFile);
  2598. SAFEDELETE(szMainCodeBase);
  2599. DEBUG_LEAVE(hr);
  2600. return hr;
  2601. }
  2602. STDMETHODIMP CSoftDist::Logo3DownloadRedundant()
  2603. {
  2604. DEBUG_ENTER((DBG_DOWNLOAD,
  2605. Hresult,
  2606. "CSoftDist::Logo3DownloadRedundant",
  2607. "this=%#x",
  2608. this
  2609. ));
  2610. HRESULT hr = S_FALSE;
  2611. LPWSTR szCodeBase = NULL;
  2612. DWORD dwSize = 0;
  2613. CCodeBaseHold *pcbhPrev = NULL;
  2614. CCodeBaseHold *pcbhCur = NULL;
  2615. LISTPOSITION lpos = 0, lposOld = 0;
  2616. BOOL bFound = FALSE;
  2617. pcbhPrev = m_cbh.GetAt(m_curPos);
  2618. Assert(pcbhPrev);
  2619. // Find first undownloaded codebase of the same group
  2620. lpos = m_cbh.GetHeadPosition();
  2621. while (lpos) {
  2622. lposOld = lpos;
  2623. pcbhCur = m_cbh.GetNext(lpos);
  2624. if (!(pcbhCur->dwFlags & CBH_FLAGS_DOWNLOADED) &&
  2625. !StrCmpW(pcbhCur->wszDLGroup, pcbhPrev->wszDLGroup)) {
  2626. bFound = TRUE;
  2627. m_curPos = lposOld;
  2628. pcbhCur->dwFlags |= CBH_FLAGS_DOWNLOADED;
  2629. hr = CDLDupWStr(&szCodeBase, pcbhCur->wszCodeBase);
  2630. dwSize = pcbhCur->dwSize;
  2631. break;
  2632. }
  2633. }
  2634. hr = (bFound) ? (Logo3Download(szCodeBase)) : (S_FALSE);
  2635. DEBUG_LEAVE(hr);
  2636. return hr;
  2637. }
  2638. STDMETHODIMP CSoftDist::Logo3Download(LPWSTR szCodeBase)
  2639. {
  2640. DEBUG_ENTER((DBG_DOWNLOAD,
  2641. Hresult,
  2642. "CSoftDist::Logo3Download",
  2643. "this=%#x, %.80wq",
  2644. szCodeBase
  2645. ));
  2646. HRESULT hr = S_OK;
  2647. DWORD dwLen = 0;
  2648. char achCodeBase[INTERNET_MAX_PATH_LENGTH];
  2649. IMoniker *pmk = NULL;
  2650. Logo3CodeDLBSC *pCDLBSC = NULL;
  2651. IBindCtx *pabc = NULL;
  2652. IBindStatusCallback *pbscOld = NULL;
  2653. IUnknown *pUnk = NULL;
  2654. hr = CreateURLMoniker(NULL, szCodeBase, &pmk);
  2655. if (SUCCEEDED(hr))
  2656. {
  2657. dwLen = INTERNET_MAX_PATH_LENGTH;
  2658. WideCharToMultiByte(CP_ACP, 0, szCodeBase , -1, achCodeBase,
  2659. dwLen, NULL, NULL);
  2660. Assert(m_pClientBSC);
  2661. pCDLBSC = new Logo3CodeDLBSC(this, m_pClientBSC, achCodeBase,
  2662. m_szDistUnit);
  2663. if (pCDLBSC == NULL)
  2664. {
  2665. hr = E_OUTOFMEMORY;
  2666. SAFERELEASE(pmk);
  2667. m_pClientBSC->Release();
  2668. goto Exit;
  2669. }
  2670. hr = CreateBindCtx(0, &pabc);
  2671. if (SUCCEEDED(hr))
  2672. {
  2673. hr = RegisterBindStatusCallback(pabc, pCDLBSC, &pbscOld, 0);
  2674. }
  2675. if (SUCCEEDED(hr))
  2676. {
  2677. pCDLBSC->SetBindCtx(pabc);
  2678. hr = pmk->BindToStorage(pabc, NULL, IID_IUnknown, (void **)&pUnk);
  2679. if (FAILED(hr) && hr != E_PENDING)
  2680. {
  2681. RevokeBindStatusCallback(pabc, pCDLBSC);
  2682. }
  2683. }
  2684. if (pUnk) {
  2685. pUnk->Release();
  2686. }
  2687. }
  2688. Exit:
  2689. SAFERELEASE(pCDLBSC);
  2690. SAFERELEASE(pabc);
  2691. SAFERELEASE(pbscOld);
  2692. SAFERELEASE(pmk);
  2693. DEBUG_LEAVE(hr);
  2694. return hr;
  2695. }
  2696. // Replace the ';' separator with '\0' and count the number of languages in the string.
  2697. void PrepareLanguage(LPSTR lpLang)
  2698. {
  2699. DEBUG_ENTER((DBG_DOWNLOAD,
  2700. None,
  2701. "PrepareLanguage",
  2702. "%.80q",
  2703. lpLang
  2704. ));
  2705. LPSTR lpTmp;
  2706. int index = 0;
  2707. if (lpLang)
  2708. {
  2709. index = 1;
  2710. lpTmp = lpLang;
  2711. while (*lpTmp)
  2712. {
  2713. if (*lpTmp == ';')
  2714. {
  2715. *lpTmp = '\0';
  2716. index++;
  2717. }
  2718. lpTmp = CharNext(lpTmp);
  2719. }
  2720. }
  2721. DEBUG_LEAVE(0);
  2722. return;
  2723. }
  2724. // Checks if all languages in the semicolon separated list of lpszLang1 are also in lpszLang2
  2725. BOOL AreAllLanguagesPresent(LPCSTR lpszLang1, LPCSTR lpszLang2)
  2726. {
  2727. DEBUG_ENTER((DBG_DOWNLOAD,
  2728. Bool,
  2729. "AreAllLanguagesPresent",
  2730. "%.80q, %.80q",
  2731. lpszLang1, lpszLang2
  2732. ));
  2733. LPSTR lpLang1 = NULL;
  2734. LPSTR lpLang2 = NULL;
  2735. LPSTR lpTmp1; // Pointer into lpLang1
  2736. LPSTR lpTmp2; // pointer into lpLang2
  2737. BOOL bAllPresent = FALSE;
  2738. BOOL bFoundOne = TRUE;
  2739. if (lpszLang2 == NULL) // No language in the CDF, assume all languages are OK
  2740. {
  2741. DEBUG_LEAVE(TRUE);
  2742. return TRUE;
  2743. }
  2744. // Make a copy of the language strings
  2745. lpLang1 = new char[lstrlen(lpszLang1) + 2];
  2746. lpLang2 = new char[lstrlen(lpszLang2) + 2];
  2747. if ((lpLang1) && (lpLang2))
  2748. {
  2749. strcpy(lpLang1, lpszLang1);
  2750. strcpy(lpLang2, lpszLang2);
  2751. PrepareLanguage(lpLang1);
  2752. PrepareLanguage(lpLang2);
  2753. lpTmp1 = lpLang1;
  2754. while ((*lpTmp1) && (bFoundOne))
  2755. {
  2756. lpTmp2 = lpLang2;
  2757. bFoundOne = FALSE;
  2758. while ((*lpTmp2) && !bFoundOne)
  2759. {
  2760. bFoundOne = (lstrcmpi(lpTmp1, lpTmp2) == 0);
  2761. lpTmp2 += lstrlen(lpTmp2) + 1;
  2762. }
  2763. lpTmp1 += lstrlen(lpTmp1) + 1;
  2764. }
  2765. bAllPresent = bFoundOne;
  2766. }
  2767. SAFEDELETE(lpLang1);
  2768. SAFEDELETE(lpLang2);
  2769. DEBUG_LEAVE(bAllPresent);
  2770. return bAllPresent;
  2771. }
  2772. STDAPI GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi )
  2773. {
  2774. DEBUG_ENTER_API((DBG_DOWNLOAD,
  2775. Hresult,
  2776. "GetSoftwareUpdateInfo",
  2777. "%.80wq, %#x",
  2778. szDistUnit, psdi
  2779. ));
  2780. HRESULT hr = S_OK;
  2781. if ( psdi == NULL ||
  2782. (psdi->cbSize == sizeof(SOFTDISTINFO) && psdi->dwReserved == 0) )
  2783. {
  2784. CSoftDist *pSoftDist = new CSoftDist();
  2785. if (!pSoftDist) {
  2786. hr = E_OUTOFMEMORY;
  2787. goto Exit;
  2788. }
  2789. hr = pSoftDist->GetSoftwareUpdateInfo(szDistUnit, psdi);
  2790. SAFERELEASE(pSoftDist);
  2791. }
  2792. else
  2793. hr = E_INVALIDARG;
  2794. Exit:
  2795. DEBUG_LEAVE_API(hr);
  2796. return hr;
  2797. }
  2798. STDAPI SetSoftwareUpdateAdvertisementState( LPCWSTR szDistUnit,
  2799. DWORD dwAdState,
  2800. DWORD dwAdvertisedVersionMS,
  2801. DWORD dwAdvertisedVersionLS )
  2802. {
  2803. DEBUG_ENTER((DBG_DOWNLOAD,
  2804. Hresult,
  2805. "SetSoftwareUpdateAdvertisementState",
  2806. "%.80wq, %#x, %#x, %#x",
  2807. szDistUnit, dwAdState, dwAdvertisedVersionMS, dwAdvertisedVersionLS
  2808. ));
  2809. HRESULT hr = S_OK;
  2810. CSoftDist *pSoftDist = new CSoftDist();
  2811. if (!pSoftDist) {
  2812. hr = E_OUTOFMEMORY;
  2813. goto Exit;
  2814. }
  2815. hr = pSoftDist->SetSoftwareUpdateAdvertisementState( szDistUnit,
  2816. dwAdState,
  2817. dwAdvertisedVersionMS,
  2818. dwAdvertisedVersionLS );
  2819. SAFERELEASE(pSoftDist);
  2820. Exit:
  2821. DEBUG_LEAVE(hr);
  2822. return hr;
  2823. }
  2824. HRESULT GetStyleFromString(LPSTR szStyle, LPDWORD lpdwStyle)
  2825. {
  2826. DEBUG_ENTER((DBG_DOWNLOAD,
  2827. Hresult,
  2828. "GetStyleFromString",
  2829. "%.80q, %#x",
  2830. szStyle, lpdwStyle
  2831. ));
  2832. HRESULT hr = S_OK;
  2833. if (szStyle == NULL || lpdwStyle == NULL) {
  2834. hr = E_INVALIDARG;
  2835. } else if (lstrcmpi(szStyle,DU_STYLE_MSICD) == 0) {
  2836. *lpdwStyle = STYLE_MSICD;
  2837. } else if (lstrcmpi(szStyle,DU_STYLE_ACTIVE_SETUP) == 0) {
  2838. *lpdwStyle = STYLE_ACTIVE_SETUP;
  2839. } else if (lstrcmpi(szStyle,DU_STYLE_MSINSTALL) == 0) {
  2840. *lpdwStyle = STYLE_MSINSTALL;
  2841. } else if (lstrcmpi(szStyle,DU_STYLE_LOGO3) == 0 ) {
  2842. *lpdwStyle = STYLE_LOGO3;
  2843. } else {
  2844. *lpdwStyle = STYLE_UNKNOWN;
  2845. hr = E_UNEXPECTED;
  2846. }
  2847. DEBUG_LEAVE(hr);
  2848. return hr;
  2849. }
  2850. //*******************************************************************************************
  2851. // CActiveSetupBinding : Wrapper class to simulate control over client binding operation when
  2852. // we are actually dealing with an EXE.
  2853. //*******************************************************************************************
  2854. DWORD WINAPI StartActiveSetup(void *dwArg)
  2855. {
  2856. DEBUG_ENTER((DBG_DOWNLOAD,
  2857. Dword,
  2858. "StartActiveSetup",
  2859. "%#x",
  2860. dwArg
  2861. ));
  2862. CActiveSetupBinding *pasb = (CActiveSetupBinding *)dwArg;
  2863. ASSERT(pasb);
  2864. pasb->StartActiveSetup();
  2865. // Should never return.
  2866. ASSERT(FALSE);
  2867. DEBUG_LEAVE(-1);
  2868. return -1;
  2869. }
  2870. CActiveSetupBinding::CActiveSetupBinding(IBindCtx *pbc,
  2871. IBindStatusCallback *pbsc, LPWSTR szCodeBase,
  2872. LPWSTR szDistUnit, HRESULT *phr)
  2873. {
  2874. DEBUG_ENTER((DBG_DOWNLOAD,
  2875. None,
  2876. "CActiveSetupBinding::CActiveSetupBinding",
  2877. "this=%#x, %#x, %#x, %.80wq, %.80wq, %#x",
  2878. this, pbc, pbsc, szCodeBase, szDistUnit, phr
  2879. ));
  2880. HKEY hkAppPath = NULL;
  2881. ASSERT(pbc);
  2882. ASSERT(pbsc);
  2883. ASSERT(phr);
  2884. *phr = S_OK;
  2885. fSilent = FALSE;
  2886. m_pbc = pbc;
  2887. m_pbc->AddRef();
  2888. m_pbsc = pbsc;
  2889. m_pbsc->AddRef();
  2890. m_dwRef = 1;
  2891. m_hWaitThread = NULL;
  2892. memset(&m_piChild, 0, sizeof(m_piChild));
  2893. if (FAILED(Unicode2Ansi(szCodeBase, &m_szCodeBase)))
  2894. goto Exit;
  2895. if (FAILED(Unicode2Ansi(szDistUnit, &m_szDistUnit)))
  2896. goto Exit;
  2897. ASSERT(m_szCodeBase);
  2898. // Get actsetup.exe path.
  2899. if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  2900. "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE",
  2901. 0, KEY_READ, &hkAppPath) == ERROR_SUCCESS) {
  2902. long dwSize = MAX_PATH;
  2903. m_szActSetupPath[0] = '\0';
  2904. if (RegQueryValueA(hkAppPath, NULL, (LPSTR)m_szActSetupPath, &dwSize) == ERROR_SUCCESS) {
  2905. if ((dwSize <= 1) || (m_szActSetupPath[0] == '\0'))
  2906. goto Exit;
  2907. LPSTR szCur = &m_szActSetupPath[dwSize-2]; // points to last character
  2908. while (szCur>m_szActSetupPath) {
  2909. if (*szCur == '\\')
  2910. break;
  2911. szCur--;
  2912. }
  2913. *(++szCur) = '\0'; // Prematurely truncate string (chop off IEXPLORE.EXE)
  2914. } else
  2915. goto Exit;
  2916. } else
  2917. goto Exit;
  2918. // Create thread to monitor status of Active Setup executable.
  2919. m_hWaitThread = CreateThread(NULL, 0, &(::StartActiveSetup), (LPVOID)this, 0, &dwThreadID);
  2920. Exit:
  2921. *phr = (m_hWaitThread != NULL) ? S_OK : E_FAIL;
  2922. SAFEREGCLOSEKEY(hkAppPath);
  2923. DEBUG_LEAVE(0);
  2924. }
  2925. CActiveSetupBinding::~CActiveSetupBinding()
  2926. {
  2927. DEBUG_ENTER((DBG_DOWNLOAD,
  2928. None,
  2929. "CActiveSetupBinding::~CActiveSetupBinding",
  2930. "this=%#x",
  2931. this
  2932. ));
  2933. ASSERT(m_dwRef == 0);
  2934. SAFERELEASE(m_pbsc);
  2935. SAFERELEASE(m_pbc);
  2936. SAFEDELETE(m_szCodeBase);
  2937. SAFEDELETE(m_szDistUnit);
  2938. if (m_hWaitThread)
  2939. CloseHandle(m_hWaitThread);
  2940. if (m_piChild.hProcess)
  2941. CloseHandle(m_piChild.hProcess);
  2942. if (m_piChild.hThread)
  2943. CloseHandle(m_piChild.hThread);
  2944. DEBUG_LEAVE(0);
  2945. }
  2946. void CActiveSetupBinding::StartActiveSetup(void)
  2947. {
  2948. DEBUG_ENTER((DBG_DOWNLOAD,
  2949. None,
  2950. "CActiveSetupBinding::StartActiveSetup",
  2951. "this=%#x",
  2952. this
  2953. ));
  2954. CHAR szCmdLine[2*MAX_PATH];
  2955. STARTUPINFO si;
  2956. DWORD dwResult;
  2957. LPSTR szSite;
  2958. //REVIEW: Change to some other suitable value?
  2959. const DWORD dwTimeOut = 100*60*5; // every 5 minutes
  2960. memset(&si, 0, sizeof(si));
  2961. si.cb = sizeof(STARTUPINFO); // ActSetup.Exe can take care of itself.
  2962. BINDINFO bi;
  2963. DWORD dwBindf = 0;
  2964. memset(&bi, 0, sizeof(BINDINFO));
  2965. bi.cbSize = sizeof(BINDINFO);
  2966. m_pbsc->GetBindInfo(&dwBindf, &bi);
  2967. fSilent = (dwBindf & BINDF_SILENTOPERATION) ? TRUE : FALSE;
  2968. szSite = StrChr(m_szCodeBase, ';');
  2969. if (szSite) {
  2970. *szSite = '\0';
  2971. szSite++;
  2972. SetDefaultDownloadSite(szSite);
  2973. }
  2974. // compose the pathname for actsetup.exe and then check for
  2975. // file existence before spawning process
  2976. wnsprintfA(szCmdLine, sizeof(szCmdLine)-1, "%sactsetup.exe", m_szActSetupPath);
  2977. if (GetFileAttributes(szCmdLine) == -1) {
  2978. DoCleanUp(E_NOTIMPL); // auto install or pre download not impl
  2979. delete this;
  2980. goto Exit;
  2981. }
  2982. // Create proper command line
  2983. // /r:n - no reboot
  2984. // /d - download only
  2985. // /q - silent mode (does not require user input)
  2986. wnsprintfA(szCmdLine, sizeof(szCmdLine)-1, "\"%sactsetup.exe\" /J:job.ie4 /r:n /q %s /s:\"%s\" ",
  2987. m_szActSetupPath, fSilent ? "/d" : "", m_szCodeBase);
  2988. // Use ansi version since Win95 doesn't support unicode version.
  2989. if (!CreateProcessA(NULL, // lpApplicationName
  2990. szCmdLine, // lpCommandLine
  2991. NULL, // lpProcessAttributes
  2992. NULL, // lpThreadAttributes
  2993. FALSE, // Inherit Handles
  2994. 0, // dwCreationFlags
  2995. NULL, // Environment block (inherit callers)
  2996. NULL, // Current directory
  2997. &si, // STARTUPINFO record
  2998. &m_piChild)) { // PROCESSINFOMRATION record
  2999. delete this;
  3000. goto Exit;
  3001. }
  3002. // REVIEW: Localize status messages? Messages aren't currently used for anything useful.
  3003. if (FAILED(m_pbsc->OnStartBinding(0,(IBinding *)this)))
  3004. goto Exit;
  3005. while ((dwResult = WaitForSingleObject(m_piChild.hProcess, dwTimeOut)) == WAIT_TIMEOUT) {
  3006. (void) m_pbsc->OnProgress(0,0,BINDSTATUS_DOWNLOADINGDATA, L"ActiveSetup Running");
  3007. }
  3008. ASSERT(dwResult == WAIT_OBJECT_O);
  3009. if (GetExitCodeProcess(m_piChild.hProcess, &dwResult)) {
  3010. //REVIEW: Check for partial return codes.
  3011. SaveHresult(dwResult);
  3012. if (SUCCEEDED(dwResult)) {
  3013. (void) m_pbsc->OnStopBinding(S_OK, NULL);
  3014. } else {
  3015. DoCleanUp(dwResult);
  3016. goto Exit;
  3017. }
  3018. } else {
  3019. // Install failed, abort process.
  3020. DoCleanUp(E_FAIL);
  3021. goto Exit;
  3022. }
  3023. delete this;
  3024. Exit:
  3025. // BINDINFO_FIX(LaszloG) 8/15/96
  3026. ReleaseBindInfo(&bi);
  3027. DEBUG_LEAVE(0);
  3028. ExitThread(-1);
  3029. }
  3030. STDMETHODIMP CActiveSetupBinding::QueryInterface(REFIID riid,void ** ppv)
  3031. {
  3032. DEBUG_ENTER((DBG_DOWNLOAD,
  3033. Hresult,
  3034. "CActiveSetupBinding::IUnknown::QueryInterface",
  3035. "this=%#x, %#x, %#x",
  3036. this, &riid, ppv
  3037. ));
  3038. if ((riid == IID_IUnknown) || (riid == IID_IBinding))
  3039. {
  3040. *ppv = (IBinding *) this;
  3041. AddRef();
  3042. DEBUG_LEAVE(S_OK);
  3043. return S_OK;
  3044. }
  3045. else
  3046. {
  3047. DEBUG_LEAVE(E_NOINTERFACE);
  3048. return E_NOINTERFACE;
  3049. }
  3050. }
  3051. STDMETHODIMP_(ULONG) CActiveSetupBinding::AddRef()
  3052. {
  3053. DEBUG_ENTER((DBG_DOWNLOAD,
  3054. Dword,
  3055. "CActiveSetupBinding::IUnknown::AddRef",
  3056. "this=%#x",
  3057. this
  3058. ));
  3059. ULONG ulRet = m_dwRef++;
  3060. DEBUG_LEAVE(ulRet);
  3061. return ulRet;
  3062. }
  3063. STDMETHODIMP_(ULONG) CActiveSetupBinding::Release()
  3064. {
  3065. DEBUG_ENTER((DBG_DOWNLOAD,
  3066. Dword,
  3067. "CActiveSetupBinding::IUnknown::Release",
  3068. "this=%#x",
  3069. this
  3070. ));
  3071. if (--m_dwRef == 0) {
  3072. delete this;
  3073. DEBUG_LEAVE(0);
  3074. return 0;
  3075. }
  3076. DEBUG_LEAVE(m_dwRef);
  3077. return m_dwRef;
  3078. }
  3079. HRESULT CActiveSetupBinding::SetDefaultDownloadSite(LPSTR szSite)
  3080. {
  3081. DEBUG_ENTER((DBG_DOWNLOAD,
  3082. Hresult,
  3083. "CActiveSetupBinding::SetDefaultDownloadSite",
  3084. "this=%#x, %.80q",
  3085. this, szSite
  3086. ));
  3087. HRESULT hr = S_OK;
  3088. const static char * szRegion = "DownloadSiteRegion";
  3089. CHAR szTmp[MAX_PATH];
  3090. DWORD dwSize = 0, dwType = REG_SZ, dwResult;
  3091. HKEY hKey = 0;
  3092. //static known sizes of buffers.
  3093. lstrcpy(szTmp, REGKEY_ACTIVESETUP);
  3094. lstrcat(szTmp, "\\Jobs\\Job.IE4");
  3095. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTmp, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  3096. {
  3097. if (RegQueryValueEx(hKey, szRegion, 0, &dwType, NULL, &dwSize) != ERROR_SUCCESS)
  3098. {
  3099. hr = RegSetValueEx(hKey, szRegion, 0, REG_SZ, (LPBYTE)szSite, strlen(szSite));
  3100. }
  3101. ::RegCloseKey(hKey);
  3102. }
  3103. DEBUG_LEAVE(hr);
  3104. return hr;
  3105. }
  3106. STDMETHODIMP CActiveSetupBinding::Abort(void)
  3107. {
  3108. DEBUG_ENTER((DBG_DOWNLOAD,
  3109. Hresult,
  3110. "CActiveSetupBinding::IBinding::Abort",
  3111. "this=%#x",
  3112. this
  3113. ));
  3114. HRESULT hr = E_FAIL;
  3115. DWORD dwSize, dwResult;
  3116. HKEY hKey = 0;
  3117. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_ACTIVESETUP, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  3118. {
  3119. hr = RegSetValueEx(hKey, szControlSetup, 0, REG_DWORD, (LPBYTE)&dwStatusAbort, sizeof(DWORD));
  3120. ::RegCloseKey(hKey);
  3121. }
  3122. if (SUCCEEDED(hr) && m_hWaitThread)
  3123. {
  3124. // The child thread will terminate when Active Setup finishes and post message
  3125. // to tray agent to terminate.
  3126. }
  3127. else
  3128. {
  3129. // terminate waiting thread
  3130. TerminateThread(m_hWaitThread, E_ABORT);
  3131. // terminate active setup process
  3132. TerminateProcess(m_piChild.hProcess, E_ABORT);
  3133. DoCleanUp(E_ABORT);
  3134. }
  3135. DEBUG_LEAVE(hr);
  3136. return hr;
  3137. }
  3138. HRESULT CActiveSetupBinding::SaveHresult(HRESULT hrResult)
  3139. {
  3140. DEBUG_ENTER((DBG_DOWNLOAD,
  3141. Hresult,
  3142. "CActiveSetupBinding::SaveHresult",
  3143. "this=%#x, %#x",
  3144. this, hrResult
  3145. ));
  3146. HRESULT hr = S_OK;
  3147. const static char * szPrecache = "Precache";
  3148. HKEY hKey = 0;
  3149. LPSTR pszTmp = NULL;
  3150. BOOL bAllocedTmp = FALSE;
  3151. int nTmp;
  3152. CHAR szTmp[2*MAX_PATH];
  3153. DWORD dwSize;
  3154. HWND hwnd = 0;
  3155. ULONG ulenDist = lstrlenA(m_szDistUnit);
  3156. //sizeof counts terminating NULL also, so subtract 2, and add 1 for the final NULL
  3157. ULONG ulenConst = sizeof(REGKEY_ACTIVESETUP_COMPONENTS)/sizeof(CHAR) + sizeof("\\")/sizeof(CHAR) - 2 + 1;
  3158. if ((ulenDist+ulenConst) > sizeof(szTmp))
  3159. {
  3160. pszTmp = new CHAR[ulenDist+ulenConst];
  3161. }
  3162. if (pszTmp)
  3163. {
  3164. bAllocedTmp = TRUE;
  3165. nTmp = ulenDist + ulenConst;
  3166. }
  3167. else
  3168. {
  3169. pszTmp = szTmp;
  3170. nTmp = sizeof(szTmp);
  3171. }
  3172. StrNCpy(pszTmp, REGKEY_ACTIVESETUP_COMPONENTS, nTmp);
  3173. StrCatBuff(pszTmp, "\\", nTmp);
  3174. StrCatBuff(pszTmp, m_szDistUnit, nTmp);
  3175. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszTmp, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  3176. {
  3177. // if silent mode or autoinstall / failed then record as precache attempt
  3178. if (fSilent || (!fSilent && FAILED(hrResult)))
  3179. {
  3180. // for silent (download only), record precache result
  3181. hr = RegSetValueEx(hKey, szPrecache, 0, REG_DWORD, (LPBYTE)&hrResult, sizeof(HRESULT));
  3182. }
  3183. else
  3184. {
  3185. // for non-silent (autoinstall), kill the precache key
  3186. hr = RegDeleteValue(hKey, szPrecache);
  3187. }
  3188. ::RegCloseKey(hKey);
  3189. }
  3190. // if reboot required, post a message to tray agent message pump if we can find it.
  3191. if (hrResult == ERROR_SUCCESS_REBOOT_REQUIRED)
  3192. {
  3193. hwnd = FindWindow(c_szTrayUI, NULL);
  3194. if (hwnd)
  3195. {
  3196. (void) SendNotifyMessage(hwnd, WM_USER, 0, UM_NEEDREBOOT);
  3197. }
  3198. }
  3199. if (bAllocedTmp)
  3200. {
  3201. delete [] pszTmp;
  3202. }
  3203. DEBUG_LEAVE(hr);
  3204. return hr;
  3205. }
  3206. void CActiveSetupBinding::DoCleanUp(DWORD dwExitCode)
  3207. {
  3208. DEBUG_ENTER((DBG_DOWNLOAD,
  3209. None,
  3210. "CActiveSetupBinding::DoCleanUp",
  3211. "this=%#x, %#x",
  3212. this, dwExitCode
  3213. ));
  3214. m_pbsc->OnStopBinding(dwExitCode, NULL);
  3215. SAFERELEASE(m_pbsc);
  3216. SAFERELEASE(m_pbc);
  3217. // at this point, BindCtx loses all references, deletes itself and
  3218. // its reference to BindStatusCallback. BSC loses all references are
  3219. // deletes its reference to us, so we have no more references &
  3220. // this invokes our destructor which cleans up by closing handles,
  3221. // then do returns on stack to calling point.
  3222. // we should be implicitly history at this point.
  3223. DEBUG_LEAVE(0);
  3224. }
  3225. STDMETHODIMP CActiveSetupBinding::Suspend(void)
  3226. {
  3227. DEBUG_ENTER((DBG_DOWNLOAD,
  3228. Hresult,
  3229. "CActiveSetupBinding::IBinding::Suspend",
  3230. "this=%#x",
  3231. this
  3232. ));
  3233. HRESULT hr = S_OK;
  3234. DWORD dwSize;
  3235. HKEY hKey = 0;
  3236. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_ACTIVESETUP, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  3237. {
  3238. hr = RegSetValueEx(hKey, szControlSetup, 0, REG_DWORD, (LPBYTE)&dwStatusSuspend, sizeof(DWORD));
  3239. ::RegCloseKey(hKey);
  3240. }
  3241. DEBUG_LEAVE(hr);
  3242. return hr;
  3243. }
  3244. STDMETHODIMP CActiveSetupBinding::Resume(void)
  3245. {
  3246. DEBUG_ENTER((DBG_DOWNLOAD,
  3247. Hresult,
  3248. "CActiveSetupBinding::IBinding::Resume",
  3249. "this=%#x",
  3250. this
  3251. ));
  3252. HRESULT hr = S_OK;
  3253. DWORD dwSize;
  3254. HKEY hKey = 0;
  3255. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_ACTIVESETUP, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
  3256. {
  3257. hr = RegSetValueEx(hKey, szControlSetup, 0, REG_DWORD, (LPBYTE)&dwStatusResume, sizeof(DWORD));
  3258. ::RegCloseKey(hKey);
  3259. }
  3260. DEBUG_LEAVE(hr);
  3261. return hr;
  3262. }
  3263. STDMETHODIMP CActiveSetupBinding::SetPriority(LONG nPriority)
  3264. {
  3265. DEBUG_ENTER((DBG_DOWNLOAD,
  3266. Hresult,
  3267. "CActiveSetupBinding::IBinding::SetPriority",
  3268. "this=%#x, %#x",
  3269. this, nPriority
  3270. ));
  3271. DEBUG_LEAVE(E_NOTIMPL);
  3272. return E_NOTIMPL;
  3273. }
  3274. STDMETHODIMP CActiveSetupBinding::GetPriority(LONG *pnPriority)
  3275. {
  3276. DEBUG_ENTER((DBG_DOWNLOAD,
  3277. Hresult,
  3278. "CActiveSetupBinding::IBinding::GetPriority",
  3279. "this=%#x, %#x",
  3280. this, pnPriority
  3281. ));
  3282. DEBUG_LEAVE(E_NOTIMPL);
  3283. return E_NOTIMPL;
  3284. }
  3285. STDMETHODIMP CActiveSetupBinding::GetBindResult(CLSID *pclsidProtocol,
  3286. DWORD *pdwResult, LPWSTR *pszResult,DWORD *pdwReserved)
  3287. {
  3288. DEBUG_ENTER((DBG_DOWNLOAD,
  3289. Hresult,
  3290. "CActiveSetupBinding::IBinding::GetBindResult",
  3291. "this=%#x, %#x, %#x, %#x, %#x",
  3292. this, pclsidProtocol, pdwResult, pszResult, pdwReserved
  3293. ));
  3294. HRESULT hr = NOERROR;
  3295. if (!pdwResult || !pszResult || pdwReserved)
  3296. {
  3297. hr = E_INVALIDARG;
  3298. }
  3299. else
  3300. {
  3301. *pdwResult = NOERROR;
  3302. *pszResult = NULL;
  3303. }
  3304. DEBUG_LEAVE(hr);
  3305. return hr;
  3306. }