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.

1058 lines
26 KiB

  1. // ClientCaps.cpp : Implementation of CClientCaps
  2. #include "headers.h"
  3. #pragma MARK_DATA(__FILE__)
  4. #pragma MARK_CODE(__FILE__)
  5. #pragma MARK_CONST(__FILE__)
  6. #include "iextag.h"
  7. #include "ccaps.h"
  8. typedef HRESULT STDAPICALLTYPE SHOWHTMLDIALOGFN (HWND hwndParent, IMoniker *pmk,
  9. VARIANT *pvarArgIn, WCHAR* pchOptions,
  10. VARIANT *pvArgOut);
  11. #define REGKEY_ACTIVESETUP "Software\\Microsoft\\Active Setup"
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CClientCaps
  14. STDMETHODIMP CClientCaps::get_javaEnabled(VARIANT_BOOL * pVal)
  15. {
  16. IOmNavigator *pClientInformation;
  17. HRESULT hr = GetClientInformation(&pClientInformation);
  18. if (SUCCEEDED(hr))
  19. {
  20. hr = pClientInformation->javaEnabled(pVal);
  21. pClientInformation->Release();
  22. }
  23. return hr;
  24. }
  25. STDMETHODIMP CClientCaps::get_cookieEnabled(VARIANT_BOOL * pVal)
  26. {
  27. IOmNavigator *pClientInformation;
  28. HRESULT hr = GetClientInformation(&pClientInformation);
  29. if (SUCCEEDED(hr))
  30. {
  31. hr = pClientInformation->get_cookieEnabled(pVal);
  32. pClientInformation->Release();
  33. }
  34. return hr;
  35. }
  36. STDMETHODIMP CClientCaps::get_cpuClass(BSTR * p)
  37. {
  38. IOmNavigator *pClientInformation;
  39. HRESULT hr = GetClientInformation(&pClientInformation);
  40. if (SUCCEEDED(hr))
  41. {
  42. hr = pClientInformation->get_cpuClass(p);
  43. pClientInformation->Release();
  44. }
  45. return hr;
  46. }
  47. STDMETHODIMP CClientCaps::get_systemLanguage(BSTR * p)
  48. {
  49. IOmNavigator *pClientInformation;
  50. HRESULT hr = GetClientInformation(&pClientInformation);
  51. if (SUCCEEDED(hr))
  52. {
  53. hr = pClientInformation->get_systemLanguage(p);
  54. pClientInformation->Release();
  55. }
  56. return hr;
  57. }
  58. STDMETHODIMP CClientCaps::get_userLanguage(BSTR * p)
  59. {
  60. IOmNavigator *pClientInformation;
  61. HRESULT hr = GetClientInformation(&pClientInformation);
  62. if (SUCCEEDED(hr))
  63. {
  64. hr = pClientInformation->get_userLanguage(p);
  65. pClientInformation->Release();
  66. }
  67. return hr;
  68. }
  69. STDMETHODIMP CClientCaps::get_platform(BSTR * p)
  70. {
  71. IOmNavigator *pClientInformation;
  72. HRESULT hr = GetClientInformation(&pClientInformation);
  73. if (SUCCEEDED(hr))
  74. {
  75. hr = pClientInformation->get_platform(p);
  76. pClientInformation->Release();
  77. }
  78. return hr;
  79. }
  80. STDMETHODIMP CClientCaps::get_connectionSpeed(long * p)
  81. {
  82. IOmNavigator *pClientInformation;
  83. HRESULT hr = GetClientInformation(&pClientInformation);
  84. if (SUCCEEDED(hr))
  85. {
  86. hr = pClientInformation->get_connectionSpeed(p);
  87. pClientInformation->Release();
  88. }
  89. return hr;
  90. }
  91. STDMETHODIMP CClientCaps::get_onLine(VARIANT_BOOL *p)
  92. {
  93. IOmNavigator *pClientInformation;
  94. HRESULT hr = GetClientInformation(&pClientInformation);
  95. if (SUCCEEDED(hr))
  96. {
  97. hr = pClientInformation->get_onLine(p);
  98. pClientInformation->Release();
  99. }
  100. return hr;
  101. }
  102. STDMETHODIMP CClientCaps::get_colorDepth(long * p)
  103. {
  104. IHTMLScreen *pScreen;
  105. HRESULT hr = GetScreen(&pScreen);
  106. if (SUCCEEDED(hr))
  107. {
  108. hr = pScreen->get_colorDepth(p);
  109. pScreen->Release();
  110. }
  111. return hr;
  112. }
  113. STDMETHODIMP CClientCaps::get_bufferDepth(long * p)
  114. {
  115. IHTMLScreen *pScreen;
  116. HRESULT hr = GetScreen(&pScreen);
  117. if (SUCCEEDED(hr))
  118. {
  119. hr = pScreen->get_bufferDepth(p);
  120. pScreen->Release();
  121. }
  122. return hr;
  123. }
  124. STDMETHODIMP CClientCaps::get_width(long * p)
  125. {
  126. IHTMLScreen *pScreen;
  127. HRESULT hr = GetScreen(&pScreen);
  128. if (SUCCEEDED(hr))
  129. {
  130. hr = pScreen->get_width(p);
  131. pScreen->Release();
  132. }
  133. return hr;
  134. }
  135. STDMETHODIMP CClientCaps::get_height(long * p)
  136. {
  137. IHTMLScreen *pScreen;
  138. HRESULT hr = GetScreen(&pScreen);
  139. if (SUCCEEDED(hr))
  140. {
  141. hr = pScreen->get_height(p);
  142. pScreen->Release();
  143. }
  144. return hr;
  145. }
  146. STDMETHODIMP CClientCaps::get_availHeight(long * p)
  147. {
  148. IHTMLScreen *pScreen;
  149. HRESULT hr = GetScreen(&pScreen);
  150. if (SUCCEEDED(hr))
  151. {
  152. hr = pScreen->get_availHeight(p);
  153. pScreen->Release();
  154. }
  155. return hr;
  156. }
  157. STDMETHODIMP CClientCaps::get_availWidth(long * p)
  158. {
  159. IHTMLScreen *pScreen;
  160. HRESULT hr = GetScreen(&pScreen);
  161. if (SUCCEEDED(hr))
  162. {
  163. hr = pScreen->get_availWidth(p);
  164. pScreen->Release();
  165. }
  166. return hr;
  167. }
  168. STDMETHODIMP CClientCaps::get_connectionType(BSTR *pbstr)
  169. {
  170. DWORD dwFlags = 0;
  171. BOOL bConnected;
  172. HRESULT hr = S_OK;
  173. DWORD dwState = 0;
  174. DWORD dwSize = sizeof(dwState);
  175. BOOL bGlobalOffline = FALSE ; // Has the user gone into offline mode, inspite of having a connection.
  176. if (InternetQueryOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState, &dwSize))
  177. {
  178. if (dwState & INTERNET_STATE_DISCONNECTED_BY_USER)
  179. bGlobalOffline = TRUE;
  180. }
  181. bConnected = InternetGetConnectedStateEx(&dwFlags, NULL, 0, 0);
  182. // NOTE: We use literal strings in code and resources so these don't get localized.
  183. if (bConnected && !bGlobalOffline)
  184. {
  185. // If we are connected figure out how.
  186. if (dwFlags & INTERNET_CONNECTION_MODEM )
  187. {
  188. *pbstr = SysAllocString(L"modem");
  189. }
  190. else if (dwFlags & INTERNET_CONNECTION_LAN )
  191. {
  192. *pbstr = SysAllocString(L"lan");
  193. }
  194. else
  195. {
  196. // Don't know what to do here.
  197. *pbstr = SysAllocString(L"");
  198. hr = S_FALSE;
  199. }
  200. }
  201. else
  202. {
  203. *pbstr = SysAllocString(L"offline");
  204. }
  205. if (!*pbstr)
  206. hr = E_OUTOFMEMORY;
  207. return hr;
  208. }
  209. STDMETHODIMP CClientCaps::isComponentInstalled(BSTR bstrName, BSTR bstrType, BSTR bstrVersion, VARIANT_BOOL *pVal)
  210. {
  211. if (pVal == NULL)
  212. {
  213. return E_POINTER;
  214. }
  215. DWORD dwVersionMS;
  216. DWORD dwVersionLS;
  217. HRESULT hr = GetVersion(bstrName, bstrType, &dwVersionMS, &dwVersionLS);
  218. HRESULT hrRet;
  219. if (hr == S_OK)
  220. {
  221. if (bstrVersion && bstrVersion[0] != L'\0')
  222. {
  223. // User wants us to check for minimum version number.
  224. DWORD dwVersionReqdMS;
  225. DWORD dwVersionReqdLS;
  226. hr = GetVersionFromString(bstrVersion, &dwVersionReqdMS, &dwVersionReqdLS);
  227. if (SUCCEEDED(hr))
  228. {
  229. if ( (dwVersionMS > dwVersionReqdMS) ||
  230. (dwVersionMS == dwVersionReqdMS && dwVersionLS >= dwVersionReqdLS)
  231. )
  232. {
  233. *pVal = TRUE;
  234. }
  235. else
  236. {
  237. *pVal = FALSE;
  238. }
  239. hrRet = S_OK;
  240. }
  241. else
  242. {
  243. *pVal = FALSE;
  244. hrRet = S_FALSE;
  245. }
  246. }
  247. else
  248. {
  249. *pVal = TRUE;
  250. hrRet = S_OK;
  251. }
  252. }
  253. else if (hr == S_FALSE)
  254. {
  255. *pVal = FALSE;
  256. hrRet = S_OK;
  257. }
  258. else
  259. {
  260. // This is really an error, but to avoid script error dialogs we still return a success
  261. // code, but indicate that the component is not installed.
  262. *pVal = FALSE;
  263. hrRet = S_FALSE;
  264. }
  265. return hrRet;
  266. }
  267. STDMETHODIMP CClientCaps::getComponentVersion(BSTR bstrName, BSTR bstrType, BSTR* pbstrVersion)
  268. {
  269. if (pbstrVersion == NULL)
  270. return E_POINTER;
  271. DWORD dwVersionMS;
  272. DWORD dwVersionLS;
  273. HRESULT hr = GetVersion(bstrName, bstrType, &dwVersionMS, &dwVersionLS);
  274. if (hr == S_OK)
  275. {
  276. hr = GetStringFromVersion(dwVersionMS, dwVersionLS, pbstrVersion);
  277. }
  278. else
  279. {
  280. *pbstrVersion = SysAllocString(L"");
  281. hr = S_OK;
  282. }
  283. return hr;
  284. }
  285. STDMETHODIMP CClientCaps::compareVersions(BSTR bstrVer1, BSTR bstrVer2, long *p)
  286. {
  287. if ( p == NULL)
  288. return E_POINTER;
  289. HRESULT hr = S_OK;
  290. if (bstrVer1 == NULL || bstrVer2 == NULL)
  291. {
  292. hr = E_INVALIDARG;
  293. }
  294. else
  295. {
  296. DWORD dwMS1 = 0 , dwLS1 = 0, dwMS2 = 0, dwLS2 = 0;
  297. HRESULT hr1 = GetVersionFromString(bstrVer1, &dwMS1, &dwLS1);
  298. HRESULT hr2 = GetVersionFromString(bstrVer2, &dwMS2, &dwLS2);
  299. if (SUCCEEDED(hr1) && SUCCEEDED(hr2))
  300. {
  301. if (dwMS1 > dwMS2)
  302. *p = 1;
  303. else if (dwMS1 < dwMS2)
  304. *p = -1;
  305. else /* dwMS1 == dwMS2 */
  306. {
  307. if (dwLS1 > dwLS2)
  308. *p = 1;
  309. else if (dwLS1 < dwLS2)
  310. *p = -1;
  311. else
  312. *p = 0;
  313. }
  314. hr = S_OK;
  315. }
  316. else
  317. {
  318. *p = 1; // ISSUE: what is the right thing to do here.
  319. hr = S_FALSE;
  320. }
  321. }
  322. return hr;
  323. }
  324. STDMETHODIMP CClientCaps::addComponentRequest(BSTR bstrName, BSTR bstrType, BSTR bstrVer)
  325. // Checks if the passed component is installed (optionally at or above the passed version)
  326. // and if not, adds it to a list of components to be added at a call to DoComponentRequest
  327. {
  328. HRESULT hr = 0;
  329. VARIANT_BOOL bInstalled;
  330. uCLSSPEC classspec;
  331. int iLength;
  332. int iRes;
  333. LPWSTR pwszComponentID = NULL;
  334. LPSTR pszComponentID = NULL;
  335. hr = isComponentInstalled(bstrName, bstrType, bstrVer, &bInstalled);
  336. // Unknown Error
  337. if(! SUCCEEDED(hr))
  338. {
  339. goto Exit;
  340. }
  341. // Component is already installed
  342. if(bInstalled)
  343. {
  344. hr = S_OK;
  345. goto Exit;
  346. }
  347. // otherwise, add the comnponent to the list of components to be installed
  348. // First figure out the type of the component and populate the CLSSPEC appropriately.
  349. if (0 == StrCmpICW(bstrType, L"mimetype"))
  350. {
  351. classspec.tyspec = TYSPEC_MIMETYPE;
  352. classspec.tagged_union.pMimeType = bstrName;
  353. }
  354. else if (0 == StrCmpICW(bstrType, L"progid"))
  355. {
  356. classspec.tyspec = TYSPEC_PROGID;
  357. classspec.tagged_union.pProgId = bstrName;
  358. }
  359. else if (0 == StrCmpICW(bstrType, L"clsid"))
  360. {
  361. classspec.tyspec = TYSPEC_CLSID;
  362. // Convert class-id string to GUID.
  363. hr = CLSIDFromString(bstrName, &classspec.tagged_union.clsid);
  364. if (FAILED(hr))
  365. goto Exit;
  366. }
  367. else if (0 == StrCmpICW(bstrType, L"componentid")) //internally called a FeatureID
  368. {
  369. classspec.tyspec = TYSPEC_FILENAME;
  370. classspec.tagged_union.pFileName = bstrName;
  371. }
  372. else
  373. {
  374. hr = E_INVALIDARG;
  375. goto Exit;
  376. }
  377. // Get a ComponentID from the uCLSSPEC
  378. hr = GetComponentIDFromCLSSPEC(&classspec, &pszComponentID);
  379. if(FAILED(hr))
  380. {
  381. goto Exit;
  382. }
  383. // Convert the ComponentID to a wide character string (wide expected by ShowHTMLDialog)
  384. iLength = lstrlenA(pszComponentID) + 1;
  385. pwszComponentID = new WCHAR[iLength];
  386. if(pwszComponentID == NULL)
  387. {
  388. hr = E_OUTOFMEMORY;
  389. goto Exit;
  390. }
  391. iRes = MultiByteToWideChar(CP_ACP,0,pszComponentID, iLength,
  392. pwszComponentID, iLength);
  393. if(iRes == 0)
  394. {
  395. hr = HRESULT_FROM_WIN32(GetLastError());
  396. if(pwszComponentID)
  397. {
  398. delete [] pwszComponentID;
  399. pwszComponentID = NULL;
  400. }
  401. goto Exit;
  402. }
  403. // initialize array for first time
  404. if(ppwszComponents == NULL)
  405. {
  406. // Hard coded initial size of 10; It's in the right order of magnitude
  407. // Maybe this should be in a constant, but that seems a lot of overhead
  408. // for such a small feature
  409. ppwszComponents = new LPWSTR[10];
  410. iComponentNum = 0;
  411. iComponentCap = 10;
  412. }
  413. // Resizing the array of Components
  414. if(iComponentNum >= iComponentCap)
  415. {
  416. iComponentCap *= 2;
  417. LPWSTR * ppwszOldComponents = ppwszComponents;
  418. ppwszComponents = NULL;
  419. ppwszComponents = new LPWSTR[iComponentCap];
  420. if(ppwszComponents == NULL)
  421. {
  422. hr = E_OUTOFMEMORY;
  423. ppwszComponents = ppwszOldComponents;
  424. if(pwszComponentID)
  425. {
  426. delete [] pwszComponentID;
  427. pwszComponentID = NULL;
  428. }
  429. goto Exit;
  430. }
  431. for(int i = 0; i < iComponentNum; i++)
  432. {
  433. ppwszComponents[i] = ppwszOldComponents[i];
  434. }
  435. delete [] ppwszOldComponents;
  436. }
  437. ppwszComponents[iComponentNum++] = pwszComponentID;
  438. hr = S_OK;
  439. Exit:
  440. if(pszComponentID)
  441. {
  442. CoTaskMemFree(pszComponentID);
  443. }
  444. return hr;
  445. }
  446. STDMETHODIMP CClientCaps::doComponentRequest(VARIANT_BOOL * pVal)
  447. // Uses the url in HKLM\Software\Microsoft\Active Setup\JITSetupPage
  448. // to add the list of components logged using AddComponentRequest
  449. {
  450. SHOWHTMLDIALOGFN *pfnShowHTMLDialog = NULL;
  451. HINSTANCE hInst = 0;
  452. HRESULT hr = 0;
  453. LPWSTR pwszFeatures = NULL;
  454. IMoniker *pMk = NULL;
  455. VARIANT vtDialogArg;
  456. VariantInit(&vtDialogArg);
  457. VARIANT vtRetVal;
  458. VariantInit(&vtRetVal);
  459. int i,j,k,iFeatureArgLength;
  460. TCHAR *pszSETUPPAGE = _T("JITSetupPage");
  461. WCHAR wszDownLoadPage[MAX_PATH];
  462. WCHAR wszDownLoadPageReg[MAX_PATH];
  463. // LPWSTR pwszDownLoadPage = NULL;
  464. HKEY hkeyActiveSetup = 0;
  465. LONG lResult = 0;
  466. DWORD dwType;
  467. DWORD dwSize = INTERNET_MAX_URL_LENGTH;
  468. int iLength = 0;
  469. int iRes = 0;
  470. OSVERSIONINFO osvi;
  471. // NT5 should never show JIT dialog.
  472. osvi.dwOSVersionInfoSize = sizeof(osvi);
  473. GetVersionEx(&osvi);
  474. if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  475. osvi.dwMajorVersion >= 5) {
  476. hr = E_ACCESSDENIED;
  477. goto Exit;
  478. }
  479. // No Component Requests to process. Return success and exit
  480. if(iComponentNum <= 0)
  481. {
  482. if(pVal)
  483. *pVal = TRUE;
  484. hr = S_OK;
  485. goto Exit;
  486. }
  487. // calculate space needed
  488. iFeatureArgLength = 0;
  489. // Length for the characters in the ComponentIDs
  490. for(k = 0; k < iComponentNum; k++)
  491. {
  492. iFeatureArgLength += lstrlenW(ppwszComponents[k]);
  493. }
  494. iFeatureArgLength += 9*iComponentNum - 1; // "Feature="s and &'s
  495. iFeatureArgLength += 10; // breathing room
  496. pwszFeatures = new WCHAR[iFeatureArgLength];
  497. if(!pwszFeatures)
  498. {
  499. hr = E_OUTOFMEMORY;
  500. goto Exit;
  501. }
  502. // copy the individual strings to one big string, seperated by "&feature="
  503. // i.e. "feature=JavaVM&feature=MOBILEPKx86"
  504. // i is the position in the full string
  505. // k is the current substring
  506. for(i = k = 0; k < iComponentNum; k++)
  507. {
  508. // "feature="
  509. StrCpyW(pwszFeatures + i, L"feature=");
  510. i += 8;
  511. iLength = lstrlenW(ppwszComponents[k]);
  512. // componentID
  513. StrCpyW(pwszFeatures + i, ppwszComponents[k]);
  514. i += iLength;
  515. // "&" || '\0'
  516. if(k + 1 < iComponentNum)
  517. {
  518. pwszFeatures[i] = L'&';
  519. i++;
  520. }
  521. else
  522. {
  523. pwszFeatures[i] = L'\0';
  524. i++;
  525. }
  526. }
  527. // Change string to variant
  528. vtDialogArg.vt = VT_BSTR;
  529. vtDialogArg.bstrVal = SysAllocString(pwszFeatures);
  530. if(! vtDialogArg.bstrVal)
  531. {
  532. hr = E_OUTOFMEMORY;
  533. goto Exit;
  534. }
  535. // get the download dialog page from the registry
  536. if ((lResult = RegOpenKeyExA( HKEY_LOCAL_MACHINE,
  537. REGKEY_ACTIVESETUP, 0, KEY_READ,
  538. &hkeyActiveSetup)) != ERROR_SUCCESS)
  539. {
  540. hr = HRESULT_FROM_WIN32(lResult);
  541. goto Exit;
  542. }
  543. if (lResult = SHQueryValueEx(hkeyActiveSetup, pszSETUPPAGE, NULL,
  544. &dwType, wszDownLoadPageReg, &dwSize) != ERROR_SUCCESS)
  545. {
  546. hr = HRESULT_FROM_WIN32(lResult);
  547. goto Exit;
  548. }
  549. if (wszDownLoadPageReg) {
  550. WCHAR *wszDownLoadPageFile = NULL;
  551. wszDownLoadPageFile = PathFindFileNameW(wszDownLoadPageReg);
  552. hr = SHGetWebFolderFilePathW(wszDownLoadPageFile, wszDownLoadPage, MAX_PATH);
  553. if (FAILED(hr)) {
  554. goto Exit;
  555. }
  556. }
  557. /* iLength = lstrlenA(szDownLoadPage) + 1;
  558. pwszDownLoadPage = new WCHAR[iLength];
  559. iRes = MultiByteToWideChar(CP_ACP,0,szDownLoadPage, iLength,
  560. pwszDownLoadPage, iLength);
  561. if(iRes == 0)
  562. {
  563. hr = HRESULT_FROM_WIN32(GetLastError());
  564. goto Exit;
  565. }
  566. */
  567. // Get Moniker to The JIT Dialog page
  568. hr = CreateURLMoniker(NULL, wszDownLoadPage, &pMk);
  569. if (FAILED(hr))
  570. goto Exit;
  571. // Get the ShowHTMLDialog function from the mshtml dll
  572. hInst = LoadLibraryEx(TEXT("MSHTML.DLL"), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  573. if (!hInst)
  574. {
  575. hr = HRESULT_FROM_WIN32(GetLastError());
  576. goto Exit;
  577. }
  578. pfnShowHTMLDialog = (SHOWHTMLDIALOGFN *)GetProcAddress(hInst, "ShowHTMLDialog");
  579. if (!pfnShowHTMLDialog)
  580. {
  581. hr = HRESULT_FROM_WIN32(GetLastError());
  582. goto Exit;
  583. }
  584. // Show the JIT download page; the rest of the work is accomplished there
  585. hr = (*pfnShowHTMLDialog)(NULL, pMk, &vtDialogArg, NULL, &vtRetVal);
  586. if(FAILED(hr))
  587. {
  588. goto Exit;
  589. }
  590. // Process the return value
  591. if ((vtRetVal.vt == VT_I4) && vtRetVal.lVal != S_OK )
  592. {
  593. hr = S_FALSE;
  594. if(pVal)
  595. *pVal = FALSE;
  596. }
  597. else if(vtRetVal.vt != VT_I4)
  598. {
  599. hr = S_FALSE;
  600. if(pVal)
  601. *pVal = FALSE;
  602. }
  603. else
  604. {
  605. hr = S_OK;
  606. if(pVal)
  607. *pVal = TRUE;
  608. }
  609. // Since everything was successful, clear the component list
  610. clearComponentRequest();
  611. Exit: // Goto needed because these resources must be cleaned up on all errors and successes
  612. // clear string
  613. if(pwszFeatures)
  614. delete [] pwszFeatures;
  615. if(pMk)
  616. {
  617. pMk->Release();
  618. }
  619. // if(pwszDownLoadPage)
  620. // {
  621. // delete [] pwszDownLoadPage;
  622. // pwszDownLoadPage = NULL;
  623. // }
  624. VariantClear(&vtRetVal);
  625. VariantClear(&vtDialogArg);
  626. if(hInst)
  627. {
  628. FreeLibrary(hInst);
  629. }
  630. return hr;
  631. }
  632. STDMETHODIMP CClientCaps::clearComponentRequest()
  633. // Clears the list of components logged using AddComponentRequest
  634. {
  635. int i;
  636. for(i = 0; i < iComponentNum; i++)
  637. {
  638. if(ppwszComponents[i] != NULL)
  639. {
  640. // delete the wide string
  641. delete [] ppwszComponents[i];
  642. ppwszComponents[i] = NULL;
  643. }
  644. }
  645. iComponentNum = 0;
  646. return S_OK;
  647. }
  648. // IElementBehavior methods
  649. STDMETHODIMP CClientCaps::Init(IElementBehaviorSite *pSite)
  650. {
  651. HRESULT hr = E_INVALIDARG;
  652. if (pSite != NULL)
  653. {
  654. m_pSite = pSite;
  655. m_pSite->AddRef();
  656. hr = S_OK;
  657. }
  658. return hr;
  659. }
  660. STDMETHODIMP CClientCaps::Notify(LONG lNotify, VARIANT * pVarNotify)
  661. {
  662. return S_OK;
  663. }
  664. // Helper functions for internal use only
  665. STDMETHODIMP CClientCaps::GetHTMLDocument(IHTMLDocument2 **ppDoc)
  666. {
  667. HRESULT hr = E_FAIL;
  668. if (m_pSite != NULL)
  669. {
  670. IHTMLElement *pElement = NULL;
  671. hr = m_pSite->GetElement(&pElement);
  672. if (SUCCEEDED(hr))
  673. {
  674. IDispatch * pDispDoc = NULL;
  675. hr = pElement->get_document(&pDispDoc);
  676. if (SUCCEEDED(hr))
  677. {
  678. hr = pDispDoc->QueryInterface(IID_IHTMLDocument2, (void **)ppDoc);
  679. pDispDoc->Release();
  680. }
  681. pElement->Release();
  682. }
  683. }
  684. return hr;
  685. }
  686. STDMETHODIMP CClientCaps::GetHTMLWindow(IHTMLWindow2 **ppWindow)
  687. {
  688. HRESULT hr = E_FAIL;
  689. IHTMLDocument2 *pDoc = NULL;
  690. hr = GetHTMLDocument(&pDoc);
  691. if (SUCCEEDED(hr))
  692. {
  693. hr = pDoc->get_parentWindow(ppWindow);
  694. pDoc->Release();
  695. }
  696. return hr;
  697. }
  698. STDMETHODIMP CClientCaps::GetClientInformation(IOmNavigator **ppNav)
  699. {
  700. HRESULT hr = E_FAIL;
  701. IHTMLWindow2 *pWindow = NULL;
  702. hr = GetHTMLWindow(&pWindow);
  703. if (SUCCEEDED(hr))
  704. {
  705. hr = pWindow->get_clientInformation(ppNav);
  706. pWindow->Release();
  707. }
  708. return hr ;
  709. }
  710. STDMETHODIMP CClientCaps::GetScreen(IHTMLScreen **ppScreen)
  711. {
  712. HRESULT hr = E_FAIL;
  713. IHTMLWindow2 *pWindow = NULL;
  714. hr = GetHTMLWindow(&pWindow);
  715. if (SUCCEEDED(hr))
  716. {
  717. hr = pWindow->get_screen(ppScreen);
  718. pWindow->Release();
  719. }
  720. return hr ;
  721. }
  722. // Returns S_OK if component is installed and the version # in pbstrVersion.
  723. // Returns S_FALSE if component is not installed.
  724. // E_INVALIDARG if the input args are ill-formed or not an IE component.
  725. // E_* if it encounters an error.
  726. STDMETHODIMP CClientCaps::GetVersion(BSTR bstrName, BSTR bstrType, LPDWORD pdwFileVersionMS, LPDWORD pdwFileVersionLS)
  727. {
  728. if (bstrName == NULL || bstrType == NULL)
  729. return E_INVALIDARG;
  730. uCLSSPEC classspec;
  731. HRESULT hr = E_FAIL;
  732. QUERYCONTEXT qc = {0};
  733. // First figure out the type of the component and populate the CLSSPEC appropriately.
  734. if (0 == StrCmpICW(bstrType, L"mimetype"))
  735. {
  736. classspec.tyspec = TYSPEC_MIMETYPE;
  737. classspec.tagged_union.pMimeType = bstrName;
  738. }
  739. else if (0 == StrCmpICW(bstrType, L"progid"))
  740. {
  741. classspec.tyspec = TYSPEC_PROGID;
  742. classspec.tagged_union.pProgId = bstrName;
  743. }
  744. else if (0 == StrCmpICW(bstrType, L"clsid"))
  745. {
  746. classspec.tyspec = TYSPEC_CLSID;
  747. // Convert class-id string to GUID.
  748. hr = CLSIDFromString(bstrName, &classspec.tagged_union.clsid);
  749. if (FAILED(hr))
  750. goto Exit;
  751. }
  752. else if (0 == StrCmpICW(bstrType, L"componentid"))
  753. {
  754. classspec.tyspec = TYSPEC_FILENAME;
  755. classspec.tagged_union.pFileName = bstrName;
  756. }
  757. else
  758. {
  759. hr = E_INVALIDARG;
  760. goto Exit;
  761. }
  762. hr = FaultInIEFeature(NULL, &classspec, &qc, FIEF_FLAG_PEEK);
  763. if (hr == S_OK || (qc.dwVersionHi != 0 || qc.dwVersionLo != 0))
  764. {
  765. // Put the version #'s that we found in the out args.
  766. if (pdwFileVersionMS != NULL)
  767. *pdwFileVersionMS = qc.dwVersionHi;
  768. if (pdwFileVersionLS != NULL)
  769. *pdwFileVersionLS = qc.dwVersionLo;
  770. hr = S_OK;
  771. }
  772. else if ( hr == S_FALSE)
  773. {
  774. // this implies the component is not recognized as an IE component.
  775. // The input argument must be incorrect in this case.
  776. hr = E_INVALIDARG;
  777. }
  778. else if ( hr == HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED))
  779. {
  780. hr = S_FALSE;
  781. }
  782. Exit:
  783. return hr;
  784. }
  785. // ---------------------------------------------------------------------------
  786. // %%Function: GetVersionFromString
  787. //
  788. // converts version in text format (a,b,c,d) into two dwords (a,b), (c,d)
  789. // The printed version number is of format a.b.d (but, we don't care)
  790. // ---------------------------------------------------------------------------
  791. HRESULT
  792. CClientCaps::GetVersionFromString(LPCOLESTR szBuf, LPDWORD pdwFileVersionMS, LPDWORD pdwFileVersionLS)
  793. {
  794. LPCOLESTR pch = szBuf;
  795. OLECHAR ch;
  796. *pdwFileVersionMS = 0;
  797. *pdwFileVersionLS = 0;
  798. if (!pch) // default to zero if none provided
  799. return S_OK;
  800. if (StrCmpCW(pch, L"-1,-1,-1,-1") == 0) {
  801. *pdwFileVersionMS = 0xffffffff;
  802. *pdwFileVersionLS = 0xffffffff;
  803. return S_OK;
  804. }
  805. USHORT n = 0;
  806. USHORT a = 0;
  807. USHORT b = 0;
  808. USHORT c = 0;
  809. USHORT d = 0;
  810. enum HAVE { HAVE_NONE, HAVE_A, HAVE_B, HAVE_C, HAVE_D } have = HAVE_NONE;
  811. for (ch = *pch++;;ch = *pch++) {
  812. if ((ch == L',') || (ch == L'\0')) {
  813. switch (have) {
  814. case HAVE_NONE:
  815. a = n;
  816. have = HAVE_A;
  817. break;
  818. case HAVE_A:
  819. b = n;
  820. have = HAVE_B;
  821. break;
  822. case HAVE_B:
  823. c = n;
  824. have = HAVE_C;
  825. break;
  826. case HAVE_C:
  827. d = n;
  828. have = HAVE_D;
  829. break;
  830. case HAVE_D:
  831. return E_INVALIDARG; // invalid arg
  832. }
  833. if (ch == L'\0') {
  834. // all done convert a,b,c,d into two dwords of version
  835. *pdwFileVersionMS = ((a << 16)|b);
  836. *pdwFileVersionLS = ((c << 16)|d);
  837. return S_OK;
  838. }
  839. n = 0; // reset
  840. } else if ( (ch < L'0') || (ch > L'9'))
  841. return E_INVALIDARG; // invalid arg
  842. else
  843. n = n*10 + (ch - L'0');
  844. } /* end forever */
  845. // NEVERREACHED
  846. }
  847. // ---------------------------------------------------------------------------
  848. // %%Function: GetStringFromVersion
  849. //
  850. // converts version from two DWORD's to the string format a,b,c,d
  851. // ---------------------------------------------------------------------------
  852. HRESULT CClientCaps::GetStringFromVersion(DWORD dwVersionMS, DWORD dwVersionLS, BSTR *pbstrVersion)
  853. {
  854. if (pbstrVersion == NULL)
  855. return E_POINTER;
  856. // 16-bits is a max of 5 decimal digits * 4 + 3 ','s + null terminator
  857. const int maxStringSize = 5 * 4 + 3 * 1 + 1;
  858. OLECHAR rgch[maxStringSize];
  859. USHORT a = (USHORT)(dwVersionMS >> 16);
  860. USHORT b = (USHORT)(dwVersionMS & 0xffff);
  861. USHORT c = (USHORT)(dwVersionLS >> 16);
  862. USHORT d = (USHORT)(dwVersionLS & 0xffff);
  863. OLECHAR rgchFormat[] = L"%hu,%hu,%hu,%hu";
  864. int nRet = wnsprintfW(rgch, maxStringSize, rgchFormat, a, b, c, d);
  865. HRESULT hr;
  866. if (nRet < 7 ) // 0,0,0,0
  867. {
  868. hr = E_FAIL;
  869. }
  870. else
  871. {
  872. *pbstrVersion = SysAllocString(rgch);
  873. if (*pbstrVersion == NULL)
  874. hr = E_OUTOFMEMORY;
  875. else
  876. hr = S_OK;
  877. }
  878. return hr;
  879. }