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.

1892 lines
54 KiB

  1. // ===========================================================================
  2. // File: JIT.CXX
  3. // The Just In Time setup of IE addon components
  4. //
  5. #include <cdlpch.h>
  6. #include <mshtmhst.h>
  7. #include <shlwapi.h>
  8. #include <shlwapip.h>
  9. #include <commctrl.h>
  10. #include <shfusion.h>
  11. #include <inseng.h>
  12. #include "webjit.h"
  13. #include "webjitres.h"
  14. #include "mluisupp.h"
  15. #include "shellapi.h"
  16. #define IDD_JAVAVMJITDIALOG 20001
  17. #define IDC_NOMOREDIALOG 20002
  18. #define IDC_MOREINFO 20003
  19. #define IDC_STATIC -1
  20. #define IDS_JAVAVMFAQURL 20005
  21. const CLSID CLSID_AppletOCX = { 0x08B0e5c0, 0x4FCB, 0x11CF, 0xAA, 0xA5, 0x00, 0x40, 0x1C, 0x60, 0x85, 0x01 };
  22. const char *g_pszCLSID_AppletOCX = "{08B0e5c0-4FCB-11CF-AAA5-00401C608501}";
  23. const WCHAR *g_pwszCLSID_AppletOCX = L"{08B0e5c0-4FCB-11CF-AAA5-00401C608501}";
  24. #ifdef UNIX
  25. #include <unixfile.h>
  26. #endif /* UNIX */
  27. extern HINSTANCE g_hInst;
  28. HRESULT
  29. GetComponentIDFromIEFeature(LPCSTR pszIEFeature, LPSTR *ppszComponentID)
  30. {
  31. DEBUG_ENTER((DBG_DOWNLOAD,
  32. Hresult,
  33. "GetComponentIDFromIEFeature",
  34. "%.80q, %#x",
  35. pszIEFeature, ppszComponentID
  36. ));
  37. HRESULT hr = S_OK;
  38. HKEY hkeyFeatureComponentID =0;
  39. DWORD lResult;
  40. char szComponentID[MAX_PATH];
  41. DWORD dwSize = MAX_PATH;
  42. DWORD dwType;
  43. *ppszComponentID = NULL;
  44. if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  45. REGKEY_ACTIVESETUP_FEATURECOMPID, 0, KEY_READ,
  46. &hkeyFeatureComponentID)) != ERROR_SUCCESS) {
  47. hr = HRESULT_FROM_WIN32(lResult);
  48. goto Exit;
  49. }
  50. szComponentID[0] = '\0';
  51. if (SHQueryValueEx(hkeyFeatureComponentID, pszIEFeature, NULL, &dwType,
  52. (unsigned char *)szComponentID, &dwSize) == ERROR_SUCCESS) {
  53. *ppszComponentID = new char [dwSize+1];
  54. if (*ppszComponentID == NULL) {
  55. hr = E_OUTOFMEMORY;
  56. goto Exit;
  57. }
  58. lstrcpy(*ppszComponentID, szComponentID);
  59. // FALLTHROUGH to exit
  60. } else {
  61. hr = E_UNEXPECTED;
  62. // FALLTHROUGH to exit
  63. }
  64. Exit:
  65. if (hkeyFeatureComponentID)
  66. ::RegCloseKey(hkeyFeatureComponentID);
  67. DEBUG_LEAVE(hr);
  68. return hr;
  69. }
  70. HRESULT GetComponentIDFromCLSSPEC(uCLSSPEC *pClassspec, LPSTR * ppszComponentID)
  71. {
  72. DEBUG_ENTER((DBG_DOWNLOAD,
  73. Hresult,
  74. "GetComponentIDFromCLSSPEC",
  75. "%#x, %#x",
  76. pClassspec, ppszComponentID
  77. ));
  78. HRESULT hr = S_OK;
  79. *ppszComponentID = NULL;
  80. LPWSTR pwszIEFeature = NULL;
  81. LPSTR pszIEFeature = NULL;
  82. LPCWSTR pwszMimeType = NULL;
  83. CLSID inclsid = CLSID_NULL;
  84. QUERYCONTEXT qcInternal;
  85. memset(&qcInternal, 0, sizeof(QUERYCONTEXT));
  86. BOOL bUnknown = FALSE;
  87. int iRes = 0;
  88. int length = 0;
  89. switch(pClassspec->tyspec)
  90. {
  91. case TYSPEC_PROGID:
  92. // BUGBUG: we don't have JIT tables for progid to feature id
  93. // so this will only work for PEEK for installed versions
  94. if (FAILED((hr=CLSIDFromProgID(pClassspec->tagged_union.pProgId,
  95. &inclsid))))
  96. goto Exit;
  97. hr = GetIEFeatureFromClass(&pwszIEFeature, inclsid, &qcInternal);
  98. if (hr != S_OK)
  99. goto Exit;
  100. break;
  101. case TYSPEC_CLSID:
  102. inclsid = pClassspec->tagged_union.clsid;
  103. hr = GetIEFeatureFromClass(&pwszIEFeature, inclsid, &qcInternal);
  104. if (hr != S_OK)
  105. goto Exit;
  106. break;
  107. case TYSPEC_MIMETYPE:
  108. pwszMimeType = (LPCWSTR) pClassspec->tagged_union.pMimeType;
  109. hr = GetIEFeatureFromMime(&pwszIEFeature, pwszMimeType, &qcInternal);
  110. if (hr != S_OK)
  111. goto Exit;
  112. break;
  113. case TYSPEC_FILENAME:
  114. // overload filename to be Active Setup feature ID
  115. hr = CDLDupWStr( &pwszIEFeature, pClassspec->tagged_union.pFileName);
  116. if (hr != S_OK)
  117. goto Exit;
  118. break;
  119. default:
  120. hr = E_INVALIDARG;
  121. goto Exit;
  122. }
  123. if(pwszIEFeature == NULL)
  124. {
  125. hr = E_UNEXPECTED;
  126. goto Exit;
  127. }
  128. // Change the wide character IEFeature to a multibyte string
  129. length = lstrlenW(pwszIEFeature) + 1;
  130. pszIEFeature = new CHAR[length];
  131. if(pszIEFeature == NULL)
  132. {
  133. hr = E_OUTOFMEMORY;
  134. goto Exit;
  135. }
  136. bUnknown = FALSE;
  137. iRes = WideCharToMultiByte(CP_ACP, 0, pwszIEFeature,length,
  138. pszIEFeature, length,NULL,&bUnknown);
  139. // unknown multibyte character
  140. if(bUnknown == TRUE)
  141. {
  142. hr = E_INVALIDARG;
  143. goto Exit;
  144. }
  145. // failed for other reason
  146. if(iRes == 0)
  147. {
  148. hr = HRESULT_FROM_WIN32(GetLastError());
  149. goto Exit;
  150. }
  151. // Get a ComponentID from the FeatureID
  152. hr = GetComponentIDFromIEFeature(pszIEFeature, ppszComponentID);
  153. if(FAILED(hr))
  154. {
  155. goto Exit;
  156. }
  157. hr = S_OK;
  158. Exit:
  159. SAFEDELETE(pszIEFeature);
  160. SAFEDELETE(pwszIEFeature);
  161. DEBUG_LEAVE(hr);
  162. return hr;
  163. }
  164. #define FEATURE_VERSION_SEPARATOR ';'
  165. #define ALT_FEATURE_VERSION_SEPARATOR '!'
  166. // if the IE Feature for this mime/clsid has an IE recommended version
  167. // then modify the querycontext to reflect this as if the caller wanted this
  168. // version. If the caller already has specifies a version that overrides
  169. // the recommnedation.
  170. // format: featurename;a,b,c,d
  171. HRESULT
  172. ParseIEFeature(LPSTR pszIEFeatureWithVersion,
  173. QUERYCONTEXT *pQuery,
  174. LPWSTR *ppwszIEFeature,
  175. QUERYCONTEXT *pQueryRec)
  176. {
  177. DEBUG_ENTER((DBG_DOWNLOAD,
  178. Hresult,
  179. "ParseIEFeature",
  180. "%.80q, %#x, %#x, %#x",
  181. pszIEFeatureWithVersion, pQuery, ppwszIEFeature, pQueryRec
  182. ));
  183. HRESULT hr = S_OK;
  184. DWORD dwIERecommendedVersionHi = 0;
  185. DWORD dwIERecommendedVersionLo = 0;
  186. LPSTR pchVersion = StrChr(pszIEFeatureWithVersion, FEATURE_VERSION_SEPARATOR);
  187. if (!pchVersion)
  188. {
  189. pchVersion = StrChr(pszIEFeatureWithVersion, ALT_FEATURE_VERSION_SEPARATOR);
  190. }
  191. if (pchVersion)
  192. {
  193. *pchVersion = '\0'; // stomp version separator so
  194. // pszIEFetaureWithVersion has just the feature name
  195. pchVersion++;
  196. if (*pchVersion
  197. && ((!(pQuery->dwVersionHi|pQuery->dwVersionLo))
  198. || pQueryRec))
  199. {
  200. // now pointing at version string
  201. // of format a,b,c,d
  202. hr = GetVersionFromString(pchVersion,
  203. &dwIERecommendedVersionHi, &dwIERecommendedVersionLo);
  204. if ( SUCCEEDED(hr))
  205. {
  206. if (!(pQuery->dwVersionHi|pQuery->dwVersionLo))
  207. {
  208. pQuery->dwVersionHi = dwIERecommendedVersionHi;
  209. pQuery->dwVersionLo = dwIERecommendedVersionLo;
  210. }
  211. if (pQueryRec)
  212. {
  213. pQueryRec->dwVersionHi = dwIERecommendedVersionHi;
  214. pQueryRec->dwVersionLo = dwIERecommendedVersionLo;
  215. }
  216. }
  217. else if (pQuery->dwVersionHi|pQuery->dwVersionLo)
  218. {
  219. hr = S_OK; //don't introduce new error codes into path if query already has version (COMPAT)
  220. }
  221. }
  222. }
  223. if ( SUCCEEDED(hr) && ppwszIEFeature)
  224. hr=Ansi2Unicode(pszIEFeatureWithVersion, ppwszIEFeature);
  225. DEBUG_LEAVE(hr);
  226. return hr;
  227. }
  228. HRESULT
  229. GetIEFeatureFromMime(LPWSTR *ppwszIEFeature, LPCWSTR pwszMimeType, QUERYCONTEXT *pQuery, QUERYCONTEXT* pQueryRec)
  230. {
  231. DEBUG_ENTER((DBG_DOWNLOAD,
  232. Hresult,
  233. "GetIEFeatureFromMime",
  234. "%#x, %.80wq, %#x, %#x",
  235. ppwszIEFeature, pwszMimeType, pQuery, pQueryRec
  236. ));
  237. HRESULT hr = S_OK;
  238. HKEY hkeyMimeFeature =0;
  239. LPSTR pszMime = NULL;
  240. DWORD lResult;
  241. char szFeature[MAX_PATH];
  242. DWORD dwSize = MAX_PATH;
  243. DWORD dwType;
  244. if (FAILED((hr=::Unicode2Ansi(pwszMimeType, &pszMime))))
  245. {
  246. goto Exit;
  247. }
  248. if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  249. REGKEY_ACTIVESETUP_MIMEFEATURE, 0, KEY_READ,
  250. &hkeyMimeFeature)) != ERROR_SUCCESS)
  251. {
  252. #if JIT_IN_BUILD
  253. hr = HRESULT_FROM_WIN32(lResult);
  254. #else
  255. hr = S_FALSE;
  256. #endif
  257. goto Exit;
  258. }
  259. szFeature[0] = '\0';
  260. if (SHQueryValueEx(hkeyMimeFeature, pszMime, NULL, &dwType,
  261. (unsigned char *)szFeature, &dwSize) == ERROR_SUCCESS)
  262. {
  263. if (dwSize > MAX_PATH)
  264. {
  265. // limit the feature name to MAX_PATH as buffer overrun protection
  266. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  267. goto Exit;
  268. }
  269. hr = ParseIEFeature(szFeature, pQuery, ppwszIEFeature, pQueryRec);
  270. // FALLTHROUGH to exit
  271. }
  272. else
  273. {
  274. hr = S_FALSE;
  275. // FALLTHROUGH to exit
  276. }
  277. Exit:
  278. if (hkeyMimeFeature)
  279. ::RegCloseKey(hkeyMimeFeature);
  280. delete[] pszMime;
  281. DEBUG_LEAVE(hr);
  282. return hr;
  283. }
  284. HRESULT
  285. GetIEFeatureFromClass(LPWSTR *ppwszIEFeature, REFCLSID clsid, QUERYCONTEXT *pQuery, QUERYCONTEXT *pQueryRec)
  286. {
  287. DEBUG_ENTER((DBG_DOWNLOAD,
  288. Hresult,
  289. "GetIEFeatureFromClass",
  290. "%#x, %#x, %#x",
  291. ppwszIEFeature, &clsid, pQuery, pQueryRec
  292. ));
  293. HRESULT hr = S_OK;
  294. LPOLESTR pwcsClsid = NULL;
  295. LPSTR pszClsid = NULL;
  296. HKEY hkeyClsidFeature =0;
  297. DWORD lResult;
  298. char szFeature[MAX_PATH];
  299. DWORD dwSize = MAX_PATH;
  300. DWORD dwType;
  301. // return if we can't get a valid string representation of the CLSID
  302. if (FAILED((hr=StringFromCLSID(clsid, &pwcsClsid))))
  303. goto Exit;
  304. if (FAILED((hr=::Unicode2Ansi(pwcsClsid, &pszClsid))))
  305. {
  306. goto Exit;
  307. }
  308. if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  309. REGKEY_ACTIVESETUP_CLSIDFEATURE, 0, KEY_READ,
  310. &hkeyClsidFeature)) != ERROR_SUCCESS)
  311. {
  312. #if JIT_IN_BUILD
  313. hr = HRESULT_FROM_WIN32(lResult);
  314. #else
  315. hr = S_FALSE;
  316. #endif
  317. goto Exit;
  318. }
  319. szFeature[0] = '\0';
  320. if (SHQueryValueEx(hkeyClsidFeature, pszClsid, NULL, &dwType,
  321. (unsigned char *)szFeature, &dwSize) == ERROR_SUCCESS)
  322. {
  323. if (dwSize > MAX_PATH)
  324. {
  325. // limit the feature name to MAX_PATH as buffer overrun protection
  326. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  327. goto Exit;
  328. }
  329. hr = ParseIEFeature(szFeature, pQuery, ppwszIEFeature, pQueryRec);
  330. // FALLTHROUGH to exit
  331. }
  332. else
  333. {
  334. hr = S_FALSE;
  335. // FALLTHROUGH to exit
  336. }
  337. Exit:
  338. if (hkeyClsidFeature)
  339. ::RegCloseKey(hkeyClsidFeature);
  340. SAFEDELETE(pwcsClsid);
  341. SAFEDELETE(pszClsid);
  342. DEBUG_LEAVE(hr);
  343. return hr;
  344. }
  345. HRESULT
  346. IsActiveSetupFeatureLocallyInstalled(
  347. LPCSTR pszDist,
  348. QUERYCONTEXT *pQuery,
  349. LPSTR *ppszComponentID,
  350. DWORD *pdwVersionHi,
  351. DWORD *pdwVersionLo,
  352. DWORD dwFlags)
  353. {
  354. DEBUG_ENTER((DBG_DOWNLOAD,
  355. Hresult,
  356. "IsActiveSetupFeatureLocallyInstalled",
  357. "%.80q, %#x, %#x, %#x, %#x, %#x",
  358. pszDist, pQuery, ppszComponentID, pdwVersionHi, pdwVersionLo, dwFlags
  359. ));
  360. HRESULT hr = S_FALSE; // Not installed by active setup.
  361. LONG lResult = ERROR_SUCCESS;
  362. CHAR* pszKey = NULL;
  363. BOOL bAllocedKey = FALSE;
  364. int nKey;
  365. char szKey[2*MAX_PATH];
  366. char szVersion[MAX_PATH];
  367. HKEY hKey = NULL;
  368. DWORD dwSize;
  369. DWORD dwValue;
  370. DWORD dwType;
  371. BOOL fIsInstalled = FALSE;
  372. WORD wVersion[4];
  373. DWORD dwCurMS = 0;
  374. DWORD dwCurLS = 0;
  375. const static char * szLocale = "Locale";
  376. const static char * szIsInstalled = "IsInstalled";
  377. const static char * szActVersion = "Version";
  378. const static char * szCOMPONENTID = "ComponentID";
  379. const static char * szKEYFILENAME = "KeyFileName";
  380. if (pdwVersionHi && pdwVersionLo)
  381. {
  382. *pdwVersionHi = 0;
  383. *pdwVersionLo = 0;
  384. }
  385. if (ppszComponentID)
  386. {
  387. // if we need a componentID
  388. GetComponentIDFromIEFeature(pszDist, ppszComponentID);
  389. }
  390. ULONG ulenDist = lstrlenA(pszDist);
  391. //sizeof counts terminating NULL also, so subtract 2, and add 1 for the final NULL
  392. ULONG ulenConst = sizeof(REGKEY_ACTIVESETUP_COMPONENTS)/sizeof(CHAR) + sizeof("\\")/sizeof(CHAR) - 2 + 1;
  393. if ((ulenDist+ulenConst) > sizeof(szKey))
  394. {
  395. pszKey = new CHAR[ulenDist+ulenConst];
  396. }
  397. if (pszKey)
  398. {
  399. bAllocedKey = TRUE;
  400. nKey = ulenDist+ulenConst;
  401. }
  402. else
  403. {
  404. pszKey = szKey;
  405. nKey = sizeof(szKey);
  406. }
  407. StrNCpy(pszKey, REGKEY_ACTIVESETUP_COMPONENTS, nKey);
  408. StrCatBuff(pszKey, "\\", nKey);
  409. StrCatBuff(pszKey, pszDist, nKey);
  410. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  411. {
  412. dwSize = sizeof(dwValue);
  413. // Old format of the Installed components did not have the IsInstalled value.
  414. if (RegQueryValueEx( hKey, szIsInstalled, NULL, NULL, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS)
  415. {
  416. dwValue = 0;
  417. }
  418. fIsInstalled = (dwValue != 0);
  419. if (fIsInstalled)
  420. {
  421. hr = S_OK;
  422. }
  423. else
  424. {
  425. // hr is S_FALSE;
  426. goto Exit;
  427. }
  428. if (pQuery && ((pQuery->dwVersionHi|pQuery->dwVersionLo) ||
  429. (dwFlags & FIEF_FLAG_PEEK)) )
  430. {
  431. dwSize = sizeof(szVersion);
  432. if ( (lResult = RegQueryValueEx(hKey, szActVersion, NULL, &dwType, (LPBYTE)szVersion, &dwSize)) == ERROR_SUCCESS )
  433. {
  434. Assert(dwType == REG_SZ);
  435. if ( SUCCEEDED(GetVersionFromString(szVersion, &dwCurMS, &dwCurLS)))
  436. {
  437. if (dwCurMS > pQuery->dwVersionHi ||
  438. (dwCurMS == pQuery->dwVersionHi && dwCurLS >= pQuery->dwVersionLo))
  439. {
  440. hr = S_OK;
  441. }
  442. else
  443. {
  444. hr = S_FALSE;
  445. }
  446. if (pdwVersionHi && pdwVersionLo)
  447. {
  448. *pdwVersionHi = dwCurMS;
  449. *pdwVersionLo = dwCurLS;
  450. }
  451. }
  452. else
  453. {
  454. hr = S_FALSE;
  455. }
  456. }
  457. else
  458. {
  459. hr = S_FALSE;
  460. }
  461. }
  462. if (hr == S_OK)
  463. {
  464. // we think it is installed
  465. // robustify with key file presence check
  466. dwSize = sizeof(szVersion);
  467. dwType = REG_SZ;
  468. if ( SHQueryValueEx(hKey, szKEYFILENAME, NULL, &dwType, (LPBYTE)szVersion, &dwSize) == ERROR_SUCCESS )
  469. {
  470. // value present, check if file is present
  471. if (GetFileAttributes(szVersion) == -1)
  472. hr = S_FALSE;
  473. }
  474. }
  475. }
  476. Exit:
  477. if (bAllocedKey)
  478. {
  479. delete [] pszKey;
  480. }
  481. SAFEREGCLOSEKEY(hKey);
  482. DEBUG_LEAVE(hr);
  483. return hr;
  484. }
  485. HRESULT
  486. GetInstalledVersion(
  487. LPCWSTR pwszIEFeature,
  488. QUERYCONTEXT *pQuery)
  489. {
  490. DEBUG_ENTER((DBG_DOWNLOAD,
  491. Hresult,
  492. "GetInstalledVersion",
  493. "%.100wq, %#x",
  494. pwszIEFeature, pQuery
  495. ));
  496. HRESULT hr = E_FAIL;
  497. LPSTR pszIEFeature = NULL;
  498. HKEY hKey = NULL;
  499. LONG lResult = ERROR_SUCCESS;
  500. CHAR* pszKey = NULL;
  501. BOOL bAllocedKey = FALSE;
  502. int nKey;
  503. char szKey[2*MAX_PATH];
  504. char szVersion[MAX_PATH];
  505. DWORD dwSize, dwType;
  506. DWORD dwCurMS, dwCurLS;
  507. const static char * szActVersion = "Version";
  508. if (FAILED((hr=::Unicode2Ansi(pwszIEFeature, &pszIEFeature))))
  509. {
  510. goto Exit;
  511. }
  512. ULONG ulenDist = lstrlenA(pszIEFeature);
  513. //sizeof counts terminating NULL also, so subtract 2, and add 1 for the final NULL
  514. ULONG ulenConst = sizeof(REGKEY_ACTIVESETUP_COMPONENTS)/sizeof(CHAR) + sizeof("\\")/sizeof(CHAR) - 2 + 1;
  515. if ((ulenDist+ulenConst) > sizeof(szKey))
  516. {
  517. pszKey = new CHAR[ulenDist+ulenConst];
  518. }
  519. if (pszKey)
  520. {
  521. bAllocedKey = TRUE;
  522. nKey = ulenDist + ulenConst;
  523. }
  524. else
  525. {
  526. pszKey = szKey;
  527. nKey = sizeof(szKey);
  528. }
  529. StrNCpy(pszKey, REGKEY_ACTIVESETUP_COMPONENTS, nKey);
  530. StrCatBuff(pszKey, "\\", nKey);
  531. StrCatBuff(pszKey, pszIEFeature, nKey);
  532. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
  533. {
  534. dwSize = sizeof(szVersion);
  535. if ( (lResult = RegQueryValueEx(hKey, szActVersion, NULL, &dwType, (LPBYTE)szVersion, &dwSize)) == ERROR_SUCCESS )
  536. {
  537. Assert(dwType == REG_SZ);
  538. if ( SUCCEEDED(GetVersionFromString(szVersion, &dwCurMS, &dwCurLS)))
  539. {
  540. if (pQuery)
  541. {
  542. pQuery->dwVersionHi = dwCurMS;
  543. pQuery->dwVersionLo = dwCurLS;
  544. hr = S_OK;
  545. }
  546. }
  547. }
  548. }
  549. Exit:
  550. if (bAllocedKey)
  551. {
  552. delete [] pszKey;
  553. }
  554. if (pszIEFeature)
  555. {
  556. delete [] pszIEFeature;
  557. }
  558. SAFEREGCLOSEKEY(hKey);
  559. DEBUG_LEAVE(hr);
  560. return hr;
  561. }
  562. typedef HRESULT (*PFNGETICIFFILEFROMFILE)(ICifFile **, LPCSTR pszFile);
  563. HRESULT
  564. IsCIFVersionGoodEnough(
  565. QUERYCONTEXT *pQuery,
  566. LPCSTR pszID)
  567. {
  568. DEBUG_ENTER((DBG_DOWNLOAD,
  569. Hresult,
  570. "IsCIFVersionGoodEnough",
  571. "%#x, %.80q",
  572. pQuery, pszID
  573. ));
  574. // BUGBUG: not side by side aware!!!
  575. const static char * szCIFPATH = "iesetup.cif";
  576. HRESULT hr = S_OK;
  577. ICifFile *pcif;
  578. ICifComponent *pcomp;
  579. DWORD dwVersionHi = 0;
  580. DWORD dwVersionLo = 0;
  581. PFNGETICIFFILEFROMFILE pfnGetICifFileFromFile = NULL;
  582. HMODULE hMod = LoadLibrary("inseng.dll");
  583. if ( !hMod ||
  584. (!(pfnGetICifFileFromFile = (PFNGETICIFFILEFROMFILE)GetProcAddress(hMod,
  585. "GetICifFileFromFile")))) {
  586. DEBUG_LEAVE(E_UNEXPECTED);
  587. return E_UNEXPECTED;
  588. }
  589. if(SUCCEEDED(pfnGetICifFileFromFile(&pcif, szCIFPATH))) // szCifPath is full path to cif, or 8.3 and it defaults to look in ie dir for it
  590. {
  591. if(SUCCEEDED(pcif->FindComponent(pszID, &pcomp))) // pszID is id of what you are interested in
  592. {
  593. pcomp->GetVersion(&dwVersionHi, &dwVersionLo);
  594. // BUGBUG: ?
  595. // pcomp->Release();
  596. if (pQuery->dwVersionHi > dwVersionHi ||
  597. (dwVersionHi == pQuery->dwVersionHi && pQuery->dwVersionLo > dwVersionLo)) {
  598. hr = HRESULT_FROM_WIN32(ERROR_UNKNOWN_REVISION);
  599. }
  600. }
  601. pcif->Release();
  602. }
  603. if (hMod)
  604. FreeLibrary(hMod);
  605. DEBUG_LEAVE(hr);
  606. return hr;
  607. }
  608. /* Returns:
  609. *
  610. * S_OK: Is Installed
  611. * S_FALSE: Is Available, Needs to be faulted in.
  612. * ERROR
  613. *
  614. */
  615. HRESULT
  616. IsIEFeatureInstalled(
  617. LPCWSTR pwszIEFeature,
  618. QUERYCONTEXT *pQuery,
  619. LPWSTR *ppwszSetupPage,
  620. LPWSTR *ppwszCompID,
  621. DWORD dwFlags,
  622. BOOL *pbWebJit,
  623. LPSTR *ppszWebJitUrl,
  624. BOOL fOnlyCheckInstall
  625. )
  626. {
  627. DEBUG_ENTER((DBG_DOWNLOAD,
  628. Hresult,
  629. "IsIEFeatureInstalled",
  630. "%.80wq, %#x, %#x, %#x, %#x, %B",
  631. pwszIEFeature, pQuery, ppwszSetupPage, ppwszCompID, dwFlags, fOnlyCheckInstall
  632. ));
  633. HRESULT hr = S_FALSE; // assume need to fault in
  634. LPSTR pszIEFeature = NULL;
  635. LPSTR pszComponentID = NULL;
  636. const static char * szSETUPPAGE = "JITSetupPage";
  637. const static char * szQUERYFEATURE = "feature=";
  638. LONG lResult;
  639. HKEY hkeyActiveSetup = 0;
  640. HKEY hkeyWebJitUrls = 0;
  641. char szJITPage[INTERNET_MAX_URL_LENGTH];
  642. DWORD dwType;
  643. DWORD dwSize = INTERNET_MAX_URL_LENGTH;
  644. DWORD dwInstalledVersionHi =0;
  645. DWORD dwInstalledVersionLo =0;
  646. BOOL bComponentDeclined = FALSE;
  647. #ifdef UNIX
  648. {
  649. /* Unix special handling for features like java VM
  650. * For instance, libmsjava.so will always be installed.
  651. * But, is the Sun VM installed?
  652. */
  653. hr = CheckIEFeatureOnUnix(pwszIEFeature, &dwInstalledVersionHi, &dwInstalledVersionLo, dwFlags);
  654. if (hr == S_OK || hr == ERROR_PRODUCT_UNINSTALLED)
  655. goto Exit; /* Found on Unix and Handled */
  656. }
  657. #endif /* UNIX */
  658. if (FAILED((hr=::Unicode2Ansi(pwszIEFeature, &pszIEFeature))))
  659. {
  660. goto Exit;
  661. }
  662. hr = IsActiveSetupFeatureLocallyInstalled(pszIEFeature, pQuery, fOnlyCheckInstall ? NULL : &pszComponentID, &dwInstalledVersionHi, &dwInstalledVersionLo, dwFlags);
  663. if (fOnlyCheckInstall)
  664. {
  665. goto Exit;
  666. }
  667. if (hr == S_FALSE)
  668. {
  669. // not installed, need to JIT
  670. // find out if this is JITDeclined
  671. if (SHRegGetUSValue( REGKEY_DECLINED_IOD, pszIEFeature, NULL, NULL, NULL, 0,NULL,0) == ERROR_SUCCESS)
  672. {
  673. bComponentDeclined = TRUE;
  674. }
  675. }
  676. if (((hr != S_OK) || dwFlags & FIEF_FLAG_SKIP_INSTALLED_VERSION_CHECK)
  677. && ppwszSetupPage && ppwszCompID)
  678. {
  679. if (pszComponentID && ppszWebJitUrl && pbWebJit)
  680. {
  681. if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  682. REGKEY_WEBJITURLS, 0, KEY_READ,
  683. &hkeyWebJitUrls)) == ERROR_SUCCESS)
  684. {
  685. //reuse temporary array for WebJITURL
  686. szJITPage[0] = '\0';
  687. if (SHQueryValueEx(hkeyWebJitUrls, pszComponentID, NULL, &dwType,
  688. (unsigned char *)szJITPage, &dwSize) == ERROR_SUCCESS)
  689. {
  690. LPSTR pszWebJitUrl = new CHAR[dwSize+1];
  691. if (!pszWebJitUrl)
  692. {
  693. hr = E_OUTOFMEMORY;
  694. goto Exit;
  695. }
  696. lstrcpy(pszWebJitUrl, szJITPage);
  697. *ppszWebJitUrl = pszWebJitUrl;
  698. *pbWebJit = TRUE;
  699. HRESULT hr1 = ::Ansi2Unicode(pszComponentID, ppwszCompID);
  700. if (FAILED(hr1))
  701. {
  702. hr = hr1;
  703. }
  704. goto Exit;
  705. }
  706. }
  707. *pbWebJit = FALSE;
  708. }
  709. if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  710. REGKEY_ACTIVESETUP, 0, KEY_READ,
  711. &hkeyActiveSetup)) != ERROR_SUCCESS)
  712. {
  713. hr = HRESULT_FROM_WIN32(lResult);
  714. goto Exit;
  715. }
  716. szJITPage[0] = '\0';
  717. if (SHQueryValueEx(hkeyActiveSetup, szSETUPPAGE, NULL, &dwType,
  718. (unsigned char *)szJITPage, &dwSize) == ERROR_SUCCESS)
  719. {
  720. HRESULT hr1 = ::Ansi2Unicode(szJITPage, ppwszSetupPage);
  721. if(FAILED(hr1))
  722. hr = hr1; // else hr still = S_FALSE;
  723. if (pszComponentID)
  724. {
  725. if ((sizeof(szQUERYFEATURE) + lstrlen(pszComponentID) +1)
  726. < INTERNET_MAX_URL_LENGTH)
  727. {
  728. lstrcpy(szJITPage, szQUERYFEATURE);
  729. lstrcat(szJITPage, pszComponentID);
  730. if ( (dwFlags & FIEF_FLAG_CHECK_CIFVERSION) &&
  731. pQuery &&
  732. (pQuery->dwVersionHi|pQuery->dwVersionLo))
  733. {
  734. hr1=IsCIFVersionGoodEnough(pQuery, pszComponentID);
  735. if (FAILED(hr1))
  736. {
  737. hr = hr1;
  738. goto Exit;
  739. }
  740. }
  741. HRESULT hr1 = ::Ansi2Unicode(szJITPage, ppwszCompID);
  742. if(FAILED(hr1))
  743. hr = hr1; // else hr still = S_FALSE;
  744. }
  745. else
  746. {
  747. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  748. }
  749. }
  750. }
  751. }
  752. Exit:
  753. if (pQuery && (dwFlags & FIEF_FLAG_PEEK))
  754. {
  755. pQuery->dwVersionHi = dwInstalledVersionHi;
  756. pQuery->dwVersionLo = dwInstalledVersionLo;
  757. }
  758. SAFEDELETE(pszIEFeature);
  759. SAFEDELETE(pszComponentID);
  760. if (hkeyActiveSetup)
  761. RegCloseKey(hkeyActiveSetup);
  762. if (hkeyWebJitUrls)
  763. RegCloseKey(hkeyWebJitUrls);
  764. if (bComponentDeclined)
  765. {
  766. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  767. }
  768. DEBUG_LEAVE(hr);
  769. return hr;
  770. }
  771. HRESULT
  772. IsJITRestricted(BOOL bWebJit)
  773. {
  774. DEBUG_ENTER((DBG_DOWNLOAD,
  775. Hresult,
  776. "IsJITRestricted",
  777. "%B",
  778. bWebJit
  779. ));
  780. HKEY hkeyRest = 0;
  781. BOOL bJITRest = FALSE;
  782. DWORD dwValue = 0;
  783. DWORD dwLen = sizeof(DWORD);
  784. HRESULT hr = S_OK;
  785. OSVERSIONINFO osvi;
  786. // BUGBUG: NT RAID #216898--when you install IE5 and the shell cabs
  787. // on NT5, the NoJITSetup reg value is blown away, but we can't figure
  788. // out who is doing this. JIT should not occur for NT5. This hack
  789. // is a work-around so JIT does not occur under NT5 and above.
  790. if (!bWebJit)
  791. {
  792. osvi.dwOSVersionInfoSize = sizeof(osvi);
  793. GetVersionEx(&osvi);
  794. if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  795. osvi.dwMajorVersion >= 5) {
  796. hr = E_ACCESSDENIED;
  797. goto Exit;
  798. }
  799. }
  800. // per-machine JIT off policy
  801. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_INFODEL_REST, 0, KEY_READ, &hkeyRest) == ERROR_SUCCESS)
  802. {
  803. if (!bWebJit)
  804. {
  805. if (RegQueryValueEx( hkeyRest, REGVAL_JIT_REST, NULL, NULL,
  806. (LPBYTE)&dwValue, &dwLen) == ERROR_SUCCESS && dwValue)
  807. hr = E_ACCESSDENIED;
  808. }
  809. else
  810. {
  811. if (RegQueryValueEx( hkeyRest, REGVAL_WEBJIT_REST, NULL, NULL,
  812. (LPBYTE)&dwValue, &dwLen) == ERROR_SUCCESS && dwValue)
  813. hr = E_ACCESSDENIED;
  814. }
  815. RegCloseKey(hkeyRest);
  816. }
  817. if (SUCCEEDED(hr))
  818. {
  819. // Check to see if the user has turned it off under advanced options
  820. // make this appear in UI similar to the admin restricted case
  821. // hence the return value of access_denied
  822. dwValue = 0;
  823. dwLen = sizeof(DWORD);
  824. if (!bWebJit)
  825. {
  826. if (SHRegGetUSValue( REGSTR_PATH_IE_MAIN, REGVAL_JIT_REST, NULL, (LPBYTE)&dwValue, &dwLen, 0,NULL,0) == ERROR_SUCCESS && dwValue)
  827. hr = E_ACCESSDENIED;
  828. }
  829. else
  830. {
  831. if (SHRegGetUSValue( REGSTR_PATH_IE_MAIN, REGVAL_WEBJIT_REST, NULL, (LPBYTE)&dwValue, &dwLen, 0,NULL,0) == ERROR_SUCCESS && dwValue)
  832. hr = E_ACCESSDENIED;
  833. }
  834. }
  835. Exit:
  836. DEBUG_LEAVE(hr);
  837. return hr;
  838. }
  839. HRESULT
  840. SetJITDeclined(
  841. LPCWSTR pwszIEFeature)
  842. {
  843. DEBUG_ENTER((DBG_DOWNLOAD,
  844. Hresult,
  845. "SetJITDeclined",
  846. "%.80wq",
  847. pwszIEFeature
  848. ));
  849. HRESULT hr = S_FALSE; // assume need to fault in
  850. LPSTR pszIEFeature = NULL;
  851. LONG lResult = ERROR_SUCCESS;
  852. HKEY hKey = NULL;
  853. DWORD dwSize;
  854. DWORD dwValue;
  855. LPSTR szNull = "";
  856. if (FAILED((hr=::Unicode2Ansi(pwszIEFeature, &pszIEFeature))))
  857. {
  858. goto Exit;
  859. }
  860. if (RegOpenKeyEx(HKEY_CURRENT_USER, REGKEY_DECLINED_IOD, 0, KEY_WRITE, &hKey) != ERROR_SUCCESS)
  861. {
  862. if ((lResult = RegCreateKey( HKEY_CURRENT_USER,
  863. REGKEY_DECLINED_IOD, &hKey)) != ERROR_SUCCESS) {
  864. hr = HRESULT_FROM_WIN32(lResult);
  865. goto Exit;
  866. }
  867. }
  868. if (((lResult = RegSetValueEx (hKey, pszIEFeature, 0, REG_SZ,
  869. (unsigned char *)szNull, 1))) != ERROR_SUCCESS) {
  870. hr = HRESULT_FROM_WIN32(lResult);
  871. }
  872. Exit:
  873. if (hKey)
  874. RegCloseKey(hKey);
  875. SAFEDELETE(pszIEFeature);
  876. DEBUG_LEAVE(hr);
  877. return hr;
  878. }
  879. HRESULT
  880. HasFeatureAlreadyBeenRejected(
  881. LPCWSTR szDistUnit)
  882. {
  883. DEBUG_ENTER((DBG_DOWNLOAD,
  884. Hresult,
  885. "HasFeatureAlreadyBeenRejected",
  886. "%.80wq",
  887. szDistUnit
  888. ));
  889. HRESULT hr = S_OK;
  890. LISTPOSITION curpos;
  891. LPCWSTR pwszRejectedFeature = NULL;
  892. int iNumRejected;
  893. int i;
  894. CUrlMkTls tls(hr); // hr passed by reference!
  895. if (FAILED(hr))
  896. goto Exit;
  897. iNumRejected = tls->pRejectedFeaturesList->GetCount();
  898. curpos = tls->pRejectedFeaturesList->GetHeadPosition();
  899. // walk thru all the rejected features in the thread and check for match
  900. for (i=0; i < iNumRejected; i++) {
  901. pwszRejectedFeature = tls->pRejectedFeaturesList->GetNext(curpos);
  902. if (StrCmpIW(szDistUnit, pwszRejectedFeature) == 0) {
  903. hr = S_FALSE;
  904. break;
  905. }
  906. }
  907. Exit:
  908. DEBUG_LEAVE(hr);
  909. return hr;
  910. }
  911. HRESULT
  912. RelinquishCodeDownloadCookies()
  913. {
  914. DEBUG_ENTER((DBG_DOWNLOAD,
  915. Hresult,
  916. "RelinquishCodeDownloadCookies",
  917. NULL
  918. ));
  919. HRESULT hr = S_OK;
  920. CUrlMkTls tls(hr); // hr passed by reference!
  921. if (FAILED(hr))
  922. goto Exit;
  923. Assert(tls->pTrustCookie);
  924. Assert(tls->pSetupCookie);
  925. if (!tls->pTrustCookie || !tls->pSetupCookie) {
  926. hr = E_UNEXPECTED;
  927. goto Exit;
  928. }
  929. tls->pSetupCookie->JITRelinquish();
  930. tls->pTrustCookie->JITRelinquish();
  931. Exit:
  932. DEBUG_LEAVE(hr);
  933. return hr;
  934. }
  935. HRESULT
  936. AcquireCodeDownloadCookies()
  937. {
  938. DEBUG_ENTER((DBG_DOWNLOAD,
  939. Hresult,
  940. "AcquireCodeDownloadCookies",
  941. NULL
  942. ));
  943. HRESULT hr = S_OK;
  944. HRESULT hrJITTrustCookie = E_FAIL;
  945. HRESULT hrJITSetupCookie = E_FAIL;
  946. CUrlMkTls tls(hr); // hr passed by reference!
  947. if (FAILED(hr))
  948. goto Exit;
  949. // are both cookies free?
  950. if (!(tls->pTrustCookie->IsFree() && tls->pSetupCookie->IsFree())) {
  951. hr = E_FAIL;
  952. goto Exit;
  953. }
  954. // if both cookies are free, grab them
  955. // thius will ensure that code downloads are
  956. // frozen or pended to the point JIT completes
  957. hrJITTrustCookie = tls->pTrustCookie->JITAcquire();
  958. if (FAILED(hrJITTrustCookie)) {
  959. Assert(TRUE);
  960. hr = hrJITTrustCookie;
  961. goto Exit;
  962. }
  963. hrJITSetupCookie = tls->pSetupCookie->JITAcquire();
  964. if (FAILED(hrJITSetupCookie)) {
  965. Assert(TRUE);
  966. hr = hrJITSetupCookie;
  967. goto Exit;
  968. }
  969. // taken both the cookies
  970. Exit:
  971. if (FAILED(hr)) {
  972. if (SUCCEEDED(hrJITSetupCookie))
  973. tls->pSetupCookie->JITRelinquish();
  974. if (SUCCEEDED(hrJITTrustCookie))
  975. tls->pTrustCookie->JITRelinquish();
  976. }
  977. DEBUG_LEAVE(hr);
  978. return hr;
  979. }
  980. HRESULT
  981. GetDialogArgs(LPCWSTR pwszCompID, DWORD dwFlags, VARIANT& vtDialogArg)
  982. {
  983. DEBUG_ENTER((DBG_DOWNLOAD,
  984. Hresult,
  985. "GetDialogArgs",
  986. "%.80wq, %#x, %#x",
  987. pwszCompID, dwFlags, &vtDialogArg
  988. ));
  989. HRESULT hr = S_OK;
  990. WCHAR pwszFLAGS[] = L"&flag=forceUI";
  991. WCHAR pwszArgs[INTERNET_MAX_URL_LENGTH];// large buffer
  992. StrCpyNW(pwszArgs, pwszCompID, INTERNET_MAX_URL_LENGTH);
  993. if (dwFlags & FIEF_FLAG_FORCE_JITUI) {
  994. StrCatBuffW(pwszArgs, pwszFLAGS, INTERNET_MAX_URL_LENGTH);
  995. }
  996. vtDialogArg.bstrVal = SysAllocString(pwszArgs);
  997. ASSERT(vtDialogArg.bstrVal);
  998. if(vtDialogArg.bstrVal)
  999. {
  1000. vtDialogArg.vt = VT_BSTR;
  1001. }
  1002. else
  1003. {
  1004. hr = E_OUTOFMEMORY;
  1005. goto Exit;
  1006. }
  1007. Exit:
  1008. DEBUG_LEAVE(hr);
  1009. return hr;
  1010. }
  1011. //for WebJit
  1012. #define MAX_URL_STRING INTERNET_MAX_URL_LENGTH
  1013. VOID URLSubstitution(LPCSTR pszUrlIn, LPSTR pszUrlOut, DWORD cchSize, DWORD dwSubstitutions);
  1014. #define URLSUB_OLCID 0x00000040 // The hexadecimal Locale ID (LCID) or Language ID (LID) of the operating system.
  1015. #define URLSUB_CLCID 0x00000080 // The hexadecimal Locale ID (LCID) or Language ID (LID) of the current user?s Regional Setting (as in Control Panel).
  1016. #define URLSUB_ALL 0xFFFFFFFF
  1017. BOOL CALLBACK JavaVMJitProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1018. {
  1019. switch (message)
  1020. {
  1021. case WM_COMMAND:
  1022. switch (LOWORD(wParam))
  1023. {
  1024. case IDOK:
  1025. if (SendDlgItemMessage(hwndDlg, IDC_NOMOREDIALOG, BM_GETSTATE, 0, 0) == BST_CHECKED)
  1026. {
  1027. //Never ask again
  1028. SetJITDeclined(g_pwszCLSID_AppletOCX);
  1029. }
  1030. EndDialog(hwndDlg, wParam);
  1031. return TRUE;
  1032. case IDC_MOREINFO:
  1033. if (HIWORD(wParam) == BN_CLICKED)
  1034. {
  1035. TCHAR szJavaFAQRegUrl[1024], szJavaFAQUrl[1024];
  1036. if (0 < LoadString(g_hInst, IDS_JAVAVMFAQURL, szJavaFAQRegUrl, sizeof(szJavaFAQRegUrl)/sizeof(szJavaFAQRegUrl[0])))
  1037. {
  1038. URLSubstitution(szJavaFAQRegUrl, szJavaFAQUrl, sizeof(szJavaFAQRegUrl)/sizeof(szJavaFAQRegUrl[0]), URLSUB_OLCID|URLSUB_CLCID);
  1039. ShellExecute(hwndDlg, NULL, szJavaFAQUrl, NULL, NULL, SW_SHOWDEFAULT);
  1040. }
  1041. }
  1042. break;
  1043. }
  1044. }
  1045. return FALSE;
  1046. }
  1047. /*
  1048. * FaultInIEFeature
  1049. *
  1050. * Description:
  1051. *
  1052. * Synchronous API that is to be invoked by client of an IE feature before
  1053. * accessing the feature. If the feature is already installed then it
  1054. * succeeds and the client should attempt to access the feature. Success
  1055. * return by the API does not guarantee that the feature is fully installed
  1056. * or will work. The client should still robustify access to the feature
  1057. * with proper error checking.
  1058. * If the API detects that the feature is missing on the client then it
  1059. * maps the feature identified by a clsid or mimetype (in the classspec)
  1060. * into a feature name/id and then invokes a HTML dialog with the feature
  1061. * name in the form of http://...../setuppage.htm?FeatureName=<featurename>
  1062. * The page can communicate back a return value thru
  1063. * window.external.returnValue. The following are recognized now:
  1064. *
  1065. * #define JITPAGE_RETVAL_SUCCESS 0x0 // successfully installed
  1066. * #define JITPAGE_RETVAL_CANCELLED 0x1 // was cancelled by user
  1067. * #define JITPAGE_RETVAL_DONTASK_THISWINDOW 0x2 // don't ask again in this
  1068. *
  1069. * Parameters:
  1070. *
  1071. * hWnd: parent hwnd for htmldialog
  1072. * pClassSpec: ptr to union {clsid, mimetype ...}
  1073. * querycontext: to specify version, lcid of feature(lcid not impl)
  1074. * This is an IN/OUT param. The installed version
  1075. * number is returned is FIEF_FLAG_PEEK is passed in
  1076. * dwFlags: control behaviour such as UI/no UI, peek versus faultin
  1077. * FIEF_FLAG_PEEK
  1078. *
  1079. * FIEF_FLAG_FORCE_JITUI
  1080. * Force JIT even if user has cancelled a previous JIT in
  1081. * the same session or even asked to Never JIT this feature.
  1082. *
  1083. * FIEF_FLAG_PEEK
  1084. * Don't fault in just peek. Peek has the side effect of
  1085. * returning currently installed version in the querycontext
  1086. *
  1087. * FIEF_FLAG_SKIP_INSTALLED_VERSION_CHECK
  1088. * Ignore local version being satisfactory and force JIT
  1089. * download. Typically called by code download or other caller
  1090. * after a CoCreateInstance call has failed with
  1091. * REGDB_E_CLASSNOTREG or ERROR_MOD_NOT_FOUND (missing
  1092. * dependency dll). The registry probably still looks like
  1093. * this feature is installed, but really isn't or is damaged.
  1094. *
  1095. *
  1096. * Returns:
  1097. *
  1098. * S_OK: Is Installed. Caller needs to CoCreate or BindToObject or some
  1099. * other system service to invoke the class or mime handler.
  1100. * S_FALSE: Class or Mime is not part of an IE feature. Caller needs to
  1101. * CoCreate or BindToObject or some other system service to
  1102. * invoke the class or mime handler.
  1103. * E_ACCESSDENIED
  1104. * Admin has turned off JIT feature.
  1105. * HRESULT_FROM_WIN32(ERROR_CANCELLED):
  1106. * Could have been cancelled by the user or has been requested
  1107. * by user not to bother again in this browser window.
  1108. * HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED):
  1109. * Returned if the feature is not installed, but FIEF_FLAG_PEEK
  1110. * was specified
  1111. * HRESULT_FROM_WIN32(ERROR_REVISION_UNKNOWN);
  1112. * Returned when dwFlag FIEF_FLAG_CHECK_CIFVERSION is passed and
  1113. * the local version is not good enough AND the version in the CIF
  1114. * that would get JIT installed is also less then the version
  1115. * requested by the caller. This flag is typically passed by a
  1116. * caller such as code download in URLMON that has the means to
  1117. * get the requested version by installing the CODEBASE object.
  1118. *
  1119. * ERROR:
  1120. * Other error.
  1121. *
  1122. */
  1123. #define HELP_CLSID L"{45ea75a0-a269-11d1-b5bf-0000f8051515}"
  1124. BOOL IsWin32X86();
  1125. STDAPI
  1126. FaultInIEFeature(
  1127. HWND hWnd,
  1128. uCLSSPEC *pClassSpec,
  1129. QUERYCONTEXT *pQuery,
  1130. DWORD dwFlags
  1131. )
  1132. {
  1133. DEBUG_ENTER_API((DBG_DOWNLOAD,
  1134. Hresult,
  1135. "FaultInIEFeature",
  1136. "%#x, %#x, %#x, %#x",
  1137. hWnd, pClassSpec, pQuery, dwFlags
  1138. ));
  1139. HRESULT hr = S_OK;
  1140. HRESULT hrCDLCookies=E_FAIL;
  1141. WCHAR *pwszMUISetupFile = NULL;
  1142. WCHAR pwszMUISetupPage[MAX_PATH];
  1143. CLSID inclsid = CLSID_NULL;
  1144. LPCWSTR pwszDistUnit=NULL;
  1145. LPCWSTR pwszFileExt=NULL;
  1146. LPCWSTR pwszMimeType=NULL;
  1147. LPWSTR pwszIEFeature=NULL;
  1148. LPWSTR pwszSetupPage=NULL;
  1149. LPWSTR pwszCompID=NULL;
  1150. HINSTANCE hInst = 0;
  1151. IMoniker *pMk = NULL;
  1152. SHOWHTMLDIALOGFN *pfnShowHTMLDialog = NULL;
  1153. VARIANT vtRetVal;
  1154. VARIANT vtDialogArg;
  1155. VariantInit(&vtRetVal);
  1156. VariantInit(&vtDialogArg);
  1157. QUERYCONTEXT qcInternal;
  1158. BOOL bShowHelp = FALSE;
  1159. LPWSTR pwszHelpFeature=NULL;
  1160. LPWSTR pwszHelpSetupPage=NULL;
  1161. LPWSTR pwszHelpCompID=NULL;
  1162. CLSID HelpCLSID = CLSID_NULL;
  1163. QUERYCONTEXT qcHelp;
  1164. LPSTR pszWebJitRegUrl = 0;
  1165. LPSTR pszWebJitUrl = 0;
  1166. BOOL bWebJit = FALSE;
  1167. QUERYCONTEXT qcRequested;
  1168. QUERYCONTEXT qcRecommended;
  1169. QUERYCONTEXT* pQueryInstalled = NULL;
  1170. ULONG_PTR uCookie = 0;
  1171. // setup the per thread tls list for rejected features, so we
  1172. // don't bother the user multiple times for the same feature
  1173. // needs review on whether this is per thread or per process
  1174. CUrlMkTls tls(hr); // hr passed by reference!
  1175. if (FAILED(hr))
  1176. goto Exit;
  1177. hr = SetCodeDownloadTLSVars();
  1178. if (FAILED(hr))
  1179. goto Exit;
  1180. if (pQuery)
  1181. {
  1182. memcpy(&qcInternal, pQuery, sizeof(QUERYCONTEXT));
  1183. }
  1184. else
  1185. {
  1186. memset(&qcInternal, 0, sizeof(QUERYCONTEXT));
  1187. }
  1188. memset(&qcRecommended, 0, sizeof(QUERYCONTEXT));
  1189. // Get the class spec.
  1190. if(pClassSpec != NULL)
  1191. {
  1192. switch(pClassSpec->tyspec)
  1193. {
  1194. case TYSPEC_PROGID:
  1195. // BUGBUG: we don't have JIT tables for progid to feature id
  1196. // so this will only work for PEEK for installed versions
  1197. if (FAILED((hr=CLSIDFromProgID(pClassSpec->tagged_union.pProgId,
  1198. &inclsid))))
  1199. goto Exit;
  1200. hr = GetIEFeatureFromClass(&pwszIEFeature, inclsid, &qcInternal, &qcRecommended);
  1201. if (hr != S_OK)
  1202. goto Exit;
  1203. break;
  1204. case TYSPEC_CLSID:
  1205. inclsid = pClassSpec->tagged_union.clsid;
  1206. hr = GetIEFeatureFromClass(&pwszIEFeature, inclsid, &qcInternal, &qcRecommended);
  1207. if (hr != S_OK)
  1208. goto Exit;
  1209. break;
  1210. case TYSPEC_MIMETYPE:
  1211. pwszMimeType = (LPCWSTR) pClassSpec->tagged_union.pMimeType;
  1212. hr = GetIEFeatureFromMime(&pwszIEFeature, pwszMimeType, &qcInternal, &qcRecommended);
  1213. if (hr != S_OK)
  1214. goto Exit;
  1215. break;
  1216. case TYSPEC_FILENAME:
  1217. // overload filename to be Active Setup feature ID
  1218. hr = CDLDupWStr( &pwszIEFeature, pClassSpec->tagged_union.pFileName);
  1219. if (hr != S_OK)
  1220. goto Exit;
  1221. break;
  1222. default:
  1223. hr = E_INVALIDARG;
  1224. goto Exit;
  1225. }
  1226. }
  1227. else
  1228. {
  1229. hr = E_INVALIDARG;
  1230. goto Exit;
  1231. }
  1232. // We have a feature now
  1233. ASSERT(pwszIEFeature);
  1234. if (!pwszIEFeature)
  1235. {
  1236. hr = E_UNEXPECTED;
  1237. goto Exit;
  1238. }
  1239. // copy over the recommended or the user-desired version, before it may be stomped by IsIEFeatureInstalled.
  1240. memcpy(&qcRequested, &qcInternal, sizeof(QUERYCONTEXT));
  1241. hr = IsIEFeatureInstalled(pwszIEFeature, &qcInternal, &pwszSetupPage, &pwszCompID, dwFlags, &bWebJit, &pszWebJitRegUrl, FALSE);
  1242. if ((dwFlags & FIEF_FLAG_PEEK) && pQuery)
  1243. {
  1244. memcpy(pQuery, &qcInternal, sizeof(QUERYCONTEXT));
  1245. }
  1246. if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
  1247. {
  1248. if (!(dwFlags & FIEF_FLAG_FORCE_JITUI))
  1249. goto Exit;
  1250. else
  1251. hr = S_FALSE;
  1252. }
  1253. if (bWebJit
  1254. && (hr == S_FALSE)
  1255. && (qcRecommended.dwVersionHi || qcRecommended.dwVersionLo)
  1256. && ((qcRequested.dwVersionHi > qcRecommended.dwVersionHi)
  1257. || ((qcRequested.dwVersionLo > qcRecommended.dwVersionLo)
  1258. && (qcRequested.dwVersionHi == qcRecommended.dwVersionHi))))
  1259. {
  1260. //Don't WEBJIT if the requested version < recommeded version.
  1261. hr = HRESULT_FROM_WIN32(ERROR_UNKNOWN_REVISION);
  1262. }
  1263. if (FAILED(hr) || (hr == S_OK && !(dwFlags & FIEF_FLAG_SKIP_INSTALLED_VERSION_CHECK)))
  1264. goto Exit;
  1265. if (SUCCEEDED(hr) && pwszSetupPage && !bWebJit)
  1266. {
  1267. pwszMUISetupFile = PathFindFileNameW(pwszSetupPage);
  1268. hr = SHGetWebFolderFilePathW(pwszMUISetupFile, pwszMUISetupPage, MAX_PATH);
  1269. }
  1270. hr = IsJITRestricted(bWebJit);
  1271. if (hr == E_ACCESSDENIED
  1272. || ((hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
  1273. && (!(dwFlags & FIEF_FLAG_FORCE_JITUI))
  1274. )
  1275. )
  1276. {
  1277. goto Exit;
  1278. }
  1279. if (!(dwFlags & FIEF_FLAG_FORCE_JITUI))
  1280. {
  1281. hr = HasFeatureAlreadyBeenRejected(pwszIEFeature);
  1282. if (hr == S_FALSE)
  1283. {
  1284. // already been rejected
  1285. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  1286. goto Exit;
  1287. }
  1288. }
  1289. // We have a setup page for the feature now
  1290. // need to faultin feature
  1291. if (dwFlags & FIEF_FLAG_PEEK)
  1292. {
  1293. hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED);
  1294. goto Exit;
  1295. }
  1296. if (!pwszCompID)
  1297. {
  1298. hr = E_UNEXPECTED;
  1299. goto Exit;
  1300. }
  1301. // faultin feature
  1302. // now we need to acuire some code download cookies
  1303. // trust and setup. This is to make sure that we don't
  1304. // have a JIT and WVT dialog up at the same time
  1305. // we aslo want to avoid having to do a JIT and a code download
  1306. // restart machine dialog come up in the middle
  1307. hrCDLCookies = AcquireCodeDownloadCookies();
  1308. //if (FAILED(hrCDLCookies))
  1309. {
  1310. // Just try and make the new JIT dialog plaster on top of the
  1311. // WVT dialog, but make the WVT dialog disabled while JIT is up
  1312. // this can be done by hopefully just parenting the JIT with the
  1313. // trust dialog instead of the one passed in.
  1314. HWND hWndParent = hWnd;
  1315. HWND hWndTop = hWnd;
  1316. while ( (hWndParent = GetParent(hWndParent)) != NULL)
  1317. {
  1318. hWndTop = hWndParent;
  1319. }
  1320. hWnd = GetLastActivePopup(hWndTop);
  1321. }
  1322. //VENKATK
  1323. DWORD dwRetVal;
  1324. if (!bWebJit)
  1325. {
  1326. hr = GetDialogArgs(pwszCompID, dwFlags, vtDialogArg);
  1327. if (FAILED(hr))
  1328. goto Exit;
  1329. //#81608: Do not show the "?" help icon if Help is not installed
  1330. CLSIDFromString(HELP_CLSID, &HelpCLSID);
  1331. memset(&qcHelp, 0, sizeof(QUERYCONTEXT));
  1332. GetIEFeatureFromClass(&pwszHelpFeature, HelpCLSID, &qcHelp);
  1333. if (pwszHelpFeature && *pwszHelpFeature)
  1334. {
  1335. if (IsIEFeatureInstalled(pwszHelpFeature, &qcHelp, &pwszHelpSetupPage, &pwszHelpCompID, 0, NULL, NULL, FALSE) == S_OK)
  1336. {
  1337. // Help Feature is installed. Turn on the "?" flag.
  1338. bShowHelp = TRUE;
  1339. }
  1340. }
  1341. hr = CreateURLMoniker(NULL, pwszMUISetupPage, &pMk);
  1342. if (FAILED(hr))
  1343. goto Exit;
  1344. hInst = LoadLibraryEx(TEXT("MSHTML.DLL"), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  1345. if (!hInst)
  1346. {
  1347. hr = HRESULT_FROM_WIN32(GetLastError());
  1348. goto Exit;
  1349. }
  1350. pfnShowHTMLDialog = (SHOWHTMLDIALOGFN *)GetProcAddress(hInst, "ShowHTMLDialog");
  1351. if (!pfnShowHTMLDialog) {
  1352. hr = HRESULT_FROM_WIN32(GetLastError());
  1353. goto Exit;
  1354. }
  1355. DEBUG_ENTER((DBG_DOWNLOAD,
  1356. Dword,
  1357. "EXTERNAL::ShowHTMLDialog",
  1358. "%#x, %#x, %.200wq",
  1359. hWnd, pMk, pwszMUISetupPage
  1360. ));
  1361. if (bShowHelp)
  1362. (*pfnShowHTMLDialog)(hWnd, pMk, &vtDialogArg, NULL, &vtRetVal);
  1363. else
  1364. (*pfnShowHTMLDialog)(hWnd, pMk, &vtDialogArg, L"help:no;", &vtRetVal);
  1365. // below to release inseng.dll and asctrls.ocx the setup helper and
  1366. // control used in the JIT setup page. This is to help people
  1367. // running iesetup for the next build after they have had a JIT
  1368. // to not require a reboot
  1369. dwRetVal = (vtRetVal.vt == VT_I4) ? vtRetVal.lVal : 0;
  1370. DEBUG_LEAVE(dwRetVal);
  1371. CoFreeUnusedLibraries();
  1372. }
  1373. else
  1374. {
  1375. //WEBJIT
  1376. WEBJIT_PARAM sWebJitParam;
  1377. if (!IsWin32X86())
  1378. {
  1379. hr = HRESULT_FROM_WIN32(ERROR_INSTALL_PLATFORM_UNSUPPORTED);
  1380. goto Exit;
  1381. }
  1382. //KV-should we do this? Is a NULL handle value being used to indicate no UI? - Verify.
  1383. if (!hWnd)
  1384. {
  1385. hWnd = GetActiveWindow();
  1386. }
  1387. //We do not want to jit Java VM
  1388. if (IsEqualIID(inclsid, CLSID_AppletOCX))
  1389. {
  1390. if (ERROR_SUCCESS != SHRegGetUSValue( REGKEY_DECLINED_IOD, g_pszCLSID_AppletOCX, NULL, NULL, NULL, 0, NULL, 0))
  1391. {
  1392. //Pop up the dialog box if this has not been declined;
  1393. DialogBox(g_hInst, MAKEINTRESOURCE(IDD_JAVAVMJITDIALOG), hWnd, (DLGPROC)JavaVMJitProc);
  1394. }
  1395. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  1396. goto Exit;
  1397. }
  1398. pszWebJitUrl = new CHAR[MAX_URL_STRING];
  1399. if (!pszWebJitUrl)
  1400. {
  1401. hr = E_OUTOFMEMORY;
  1402. goto Exit;
  1403. }
  1404. pQueryInstalled = new QUERYCONTEXT;
  1405. if (pQueryInstalled
  1406. && (SUCCEEDED(GetInstalledVersion(pwszIEFeature, pQueryInstalled))))
  1407. {
  1408. sWebJitParam.pQueryInstalled = pQueryInstalled;
  1409. }
  1410. else
  1411. {
  1412. sWebJitParam.pQueryInstalled = NULL;
  1413. }
  1414. URLSubstitution(pszWebJitRegUrl, pszWebJitUrl, MAX_URL_STRING, URLSUB_OLCID|URLSUB_CLCID);
  1415. sWebJitParam.lpszResource = pszWebJitUrl;
  1416. sWebJitParam.dwFlags = dwFlags;
  1417. sWebJitParam.pwszComponentId = pwszCompID;
  1418. sWebJitParam.hWndParent = hWnd;
  1419. CWebJit* pWebJit = new CWebJit(&sWebJitParam);
  1420. if (!pWebJit)
  1421. {
  1422. hr = E_OUTOFMEMORY;
  1423. goto Exit;
  1424. }
  1425. if (!pWebJit->InitCommonControlsForWebJit())
  1426. {
  1427. hr = HRESULT_FROM_WIN32(GetLastError());
  1428. goto Exit;
  1429. }
  1430. DEBUG_ENTER((DBG_DOWNLOAD,
  1431. Dword,
  1432. "EXTERNAL::DialogBoxParamA",
  1433. "%#x, %.200wq, %.200q, %.200q, %#x",
  1434. hWnd, pwszCompID, pszWebJitRegUrl, pszWebJitUrl, dwFlags
  1435. ));
  1436. SHActivateContext(&uCookie);
  1437. sWebJitParam.pWebJit = pWebJit;
  1438. DialogBoxParamA(MLGetHinst(), MAKEINTRESOURCE(IDD_WEBJIT), hWnd, WebJitProc, (LPARAM)&sWebJitParam);
  1439. dwRetVal = pWebJit->GetResult();
  1440. if (uCookie)
  1441. {
  1442. SHDeactivateContext(uCookie);
  1443. }
  1444. DEBUG_LEAVE(dwRetVal);
  1445. //Need to set hr to SUCCESS if install succeeded.
  1446. if (dwRetVal == S_OK)
  1447. {
  1448. QUERYCONTEXT qcInternal2;
  1449. memcpy(&qcInternal2, &qcRequested, sizeof(QUERYCONTEXT));
  1450. hr = IsIEFeatureInstalled(pwszIEFeature, &qcInternal2, NULL, NULL, 0, NULL, NULL, TRUE);
  1451. //hr now has either S_OK or S_FALSE from IsIEFeatureInstalled
  1452. }
  1453. pWebJit->Release();
  1454. }
  1455. if (dwRetVal == JITPAGE_RETVAL_CANCELLED)
  1456. {
  1457. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  1458. }
  1459. else if (dwRetVal == JITPAGE_RETVAL_NEED_REBOOT)
  1460. {
  1461. hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
  1462. }
  1463. else if (dwRetVal == JITPAGE_RETVAL_DONTASK_THISWINDOW)
  1464. {
  1465. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  1466. tls->pRejectedFeaturesList->AddHead(pwszIEFeature);
  1467. pwszIEFeature = NULL;
  1468. }
  1469. else if (dwRetVal == JITPAGE_RETVAL_DONTASK_EVER)
  1470. {
  1471. SetJITDeclined(pwszIEFeature);
  1472. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  1473. }
  1474. else if (FAILED(dwRetVal))
  1475. {
  1476. hr = (HRESULT)dwRetVal;
  1477. }
  1478. Exit:
  1479. if (SUCCEEDED(hrCDLCookies))
  1480. {
  1481. HRESULT hr1 = RelinquishCodeDownloadCookies();
  1482. if (FAILED(hr1) && SUCCEEDED(hr))
  1483. hr = hr1;
  1484. }
  1485. SAFERELEASE(pMk);
  1486. SAFEDELETE(pwszIEFeature);
  1487. SAFEDELETE(pwszSetupPage);
  1488. SAFEDELETE(pwszCompID);
  1489. VariantClear(&vtDialogArg);
  1490. SAFEDELETE(pwszHelpFeature);
  1491. SAFEDELETE(pwszHelpSetupPage);
  1492. SAFEDELETE(pwszHelpCompID);
  1493. SAFEDELETE(pszWebJitRegUrl);
  1494. SAFEDELETE(pszWebJitUrl);
  1495. SAFEDELETE(pQueryInstalled);
  1496. if (hInst)
  1497. FreeLibrary(hInst);
  1498. DEBUG_LEAVE_API(hr);
  1499. return hr;
  1500. }
  1501. //This won't work for WebJit but nobody seems to call this anywhere in the codebase.
  1502. STDAPI_(BOOL) IsJITInProgress()
  1503. {
  1504. DEBUG_ENTER((DBG_DOWNLOAD,
  1505. Bool,
  1506. "IsJITInProgress",
  1507. NULL
  1508. ));
  1509. HWND hwnd;
  1510. hwnd = FindWindow(JIT_DIALOG_CLASS_NAME, JIT_DIALOG_CAPTION);
  1511. DEBUG_LEAVE(hwnd != NULL);
  1512. return (hwnd != NULL); // not a typo (FindWindow returns NULL for unfound)
  1513. }
  1514. //This is an abbreviated part of the code in shdocvw.
  1515. #define MAX_SUBSTR_SIZE 100
  1516. typedef struct tagURLSub
  1517. {
  1518. LPCTSTR szTag;
  1519. DWORD dwType;
  1520. }
  1521. URLSUB;
  1522. const static URLSUB c_UrlSub[] =
  1523. {
  1524. {TEXT("{SUB_OLCID}"), URLSUB_OLCID},
  1525. {TEXT("{SUB_CLCID}"), URLSUB_CLCID},
  1526. };
  1527. VOID URLSubstitution(LPCSTR pszUrlIn, LPSTR pszUrlOut, DWORD cchSize, DWORD dwSubstitutions)
  1528. {
  1529. DWORD dwIndex;
  1530. CHAR szTempUrl[MAX_URL_STRING];
  1531. ASSERT(cchSize <= ARRAYSIZE(szTempUrl)); // We will truncate anything longer than MAX_URL_STRING
  1532. StrCpyN(szTempUrl, pszUrlIn, ARRAYSIZE(szTempUrl));
  1533. for (dwIndex = 0; dwIndex < ARRAYSIZE(c_UrlSub); dwIndex++)
  1534. {
  1535. while (dwSubstitutions & c_UrlSub[dwIndex].dwType)
  1536. {
  1537. LPSTR pszTag = StrStr(szTempUrl, c_UrlSub[dwIndex].szTag);
  1538. if (pszTag)
  1539. {
  1540. CHAR szCopyUrl[MAX_URL_STRING];
  1541. CHAR szSubStr[MAX_SUBSTR_SIZE]; // The Substitution
  1542. // Copy URL Before Substitution.
  1543. StrCpyN(szCopyUrl, szTempUrl, (int)(pszTag-szTempUrl+1));
  1544. pszTag += lstrlen(c_UrlSub[dwIndex].szTag);
  1545. switch (c_UrlSub[dwIndex].dwType)
  1546. {
  1547. case URLSUB_OLCID:
  1548. wnsprintf(szSubStr, ARRAYSIZE(szSubStr), _T("%#04lx"), GetSystemDefaultLCID());
  1549. break;
  1550. case URLSUB_CLCID:
  1551. wnsprintf(szSubStr, ARRAYSIZE(szSubStr), _T("%#04lx"), GetUserDefaultLCID());
  1552. break;
  1553. }
  1554. // Add the Substitution String to the end (will become the middle)
  1555. StrCatBuff(szCopyUrl, szSubStr, ARRAYSIZE(szCopyUrl));
  1556. // Add the rest of the URL after the substitution substring.
  1557. StrCatBuff(szCopyUrl, pszTag, ARRAYSIZE(szCopyUrl));
  1558. StrCpyN(szTempUrl, szCopyUrl, ARRAYSIZE(szTempUrl));
  1559. }
  1560. else
  1561. break; // This will allow us to replace all the occurances of this string.
  1562. }
  1563. }
  1564. StrCpyN(pszUrlOut, szTempUrl, cchSize);
  1565. return;
  1566. }