Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

862 lines
17 KiB

  1. //=======================================================================
  2. //
  3. // Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: detect.cpp
  6. //
  7. // Purpose: Component Detection
  8. //
  9. // History: 3/9/99 YAsmi Created
  10. //
  11. //=======================================================================
  12. #include "stdafx.h"
  13. #include "detect.h"
  14. #include "debug.h"
  15. #include <wustl.h>
  16. #include "log.h"
  17. LPCSTR ParseField(LPCSTR pszStr, LPSTR pszTokOut, int cTokSize);
  18. BOOL UninstallKeyExists(LPCSTR pszUninstallKey);
  19. static int CompareLocales(LPCSTR pszLoc1, LPCSTR pszLoc2);
  20. //
  21. // CComponentDetection
  22. //
  23. CComponentDetection::CComponentDetection() :
  24. m_dwDetectStatus(ICI_NOTINITIALIZED),
  25. m_dwDLLReturnValue(0),
  26. m_dwInstalledVer(0),
  27. m_dwInstalledBuild(0)
  28. {
  29. int i;
  30. for (i = 0; i < (int)ccValueCount; i++)
  31. {
  32. m_ppValue[i] = (char*)malloc(ccMaxSize);
  33. }
  34. // custom data has its own size and can be longer than MaxSize
  35. m_dwCustomDataSize = ccMaxSize;
  36. for (i = 0; i < (int)ccDLLCount; i++)
  37. {
  38. m_pDLLs[i].bUsed = FALSE;
  39. }
  40. ClearValues();
  41. }
  42. CComponentDetection::~CComponentDetection()
  43. {
  44. int i;
  45. //
  46. // free cached libraries
  47. //
  48. for (i = 0; i < (int)ccDLLCount; i++)
  49. {
  50. if (m_pDLLs[i].bUsed)
  51. FreeLibrary(m_pDLLs[i].hLib);
  52. }
  53. for (i = 0; i < (int)ccValueCount; i++)
  54. {
  55. free(m_ppValue[i]);
  56. }
  57. }
  58. void CComponentDetection::ClearValues()
  59. {
  60. for (int i = 0; i < (int)ccValueCount; i++)
  61. {
  62. m_ppValue[i][0] = '\0';
  63. }
  64. }
  65. BOOL CComponentDetection::SetValue(enumCCValue cc, LPCSTR pszValue)
  66. {
  67. if (cc <= ccLastValue)
  68. {
  69. if (cc == ccCustomData)
  70. {
  71. // we allow custom data to be as long as possible so we will reallocate if neccessory
  72. DWORD l = strlen(pszValue) + 1;
  73. if (l > m_dwCustomDataSize)
  74. {
  75. free(m_ppValue[cc]);
  76. m_ppValue[cc] = _strdup(pszValue);
  77. m_dwCustomDataSize = l;
  78. }
  79. else
  80. {
  81. strncpy(m_ppValue[cc], pszValue, m_dwCustomDataSize);
  82. }
  83. return TRUE;
  84. }
  85. else
  86. {
  87. // we don't copy more than ccMaxSize
  88. strncpy(m_ppValue[cc], pszValue, ccMaxSize - 1);
  89. return TRUE;
  90. }
  91. }
  92. return FALSE;
  93. }
  94. BOOL CComponentDetection::GetValue(enumCCValue cc, LPSTR pszValue, DWORD dwSize)
  95. {
  96. if (cc <= ccLastValue)
  97. {
  98. strncpy(pszValue, m_ppValue[cc], dwSize);
  99. if (pszValue[0] != '\0')
  100. return TRUE;
  101. }
  102. return FALSE;
  103. }
  104. // detects using the current values specified by SetValue
  105. // clears all the values after detection but we can still retrieve the
  106. // status of last detection using GetLastDetectStatus
  107. //
  108. // Returns the status of detection ICI_INSTALLED etc
  109. DWORD CComponentDetection::Detect()
  110. {
  111. DWORD dwDetStat;
  112. m_dwDLLReturnValue = 0;
  113. dwDetStat = IsComponentInstalled();
  114. ClearValues();
  115. return dwDetStat;
  116. }
  117. DWORD CComponentDetection::GetLastDetectStatus()
  118. {
  119. return m_dwDetectStatus;
  120. }
  121. DWORD CComponentDetection::GetLastDLLReturnValue()
  122. {
  123. return m_dwDLLReturnValue;
  124. }
  125. void CComponentDetection::GetInstalledVersion(LPDWORD pdwVer, LPDWORD pdwBuild)
  126. {
  127. *pdwVer = m_dwInstalledVer;
  128. *pdwBuild = m_dwInstalledBuild;
  129. }
  130. HINSTANCE CComponentDetection::CacheLoadLibrary(LPCSTR pszDLLName, LPCTSTR pszDLLFullPath)
  131. {
  132. int iAvailable = -1;
  133. int iFound = -1;
  134. //
  135. // check the cache to see if we already have loaded it
  136. //
  137. for (int i = 0; i < (int)ccDLLCount; i++)
  138. {
  139. if (m_pDLLs[i].bUsed)
  140. {
  141. if (_stricmp(pszDLLName, m_pDLLs[i].szDLLName) == 0)
  142. {
  143. iFound = i;
  144. break;
  145. }
  146. }
  147. else
  148. {
  149. if (iAvailable == -1)
  150. iAvailable = i;
  151. }
  152. }
  153. if (iFound != -1)
  154. {
  155. //
  156. // returned the cached libary instance
  157. //
  158. return m_pDLLs[iFound].hLib;
  159. }
  160. else
  161. {
  162. //
  163. // load and cache the libary
  164. //
  165. if (iAvailable == -1)
  166. {
  167. iAvailable = 0;
  168. if (m_pDLLs[iAvailable].bUsed)
  169. {
  170. FreeLibrary(m_pDLLs[iAvailable].hLib);
  171. m_pDLLs[iAvailable].bUsed = FALSE;
  172. }
  173. }
  174. m_pDLLs[iAvailable].hLib = LoadLibrary(pszDLLFullPath);
  175. if (m_pDLLs[iAvailable].hLib != NULL)
  176. {
  177. strcpy(m_pDLLs[iAvailable].szDLLName, pszDLLName);
  178. m_pDLLs[iAvailable].bUsed = TRUE;
  179. }
  180. else
  181. {
  182. TRACE_HR(HRESULT_FROM_WIN32(GetLastError()), "Could not load %s (%d)", pszDLLFullPath, HRESULT_FROM_WIN32(GetLastError()));
  183. }
  184. return m_pDLLs[iAvailable].hLib;
  185. }
  186. }
  187. HRESULT CComponentDetection::CallDetectDLL(LPCSTR pszDll, LPCSTR pszEntry)
  188. {
  189. USES_CONVERSION;
  190. HRESULT hr = E_FAIL;
  191. HINSTANCE hLib;
  192. DETECTION_STRUCT Det;
  193. DWORD dwCifVer, dwCifBuild;
  194. char szLocale[8];
  195. char szGUID[128];
  196. m_dwDetectStatus = ICI_NOTINSTALLED;
  197. GetValue(ccGUID, szGUID, sizeof(szGUID));
  198. GetLocale(szLocale, sizeof(szLocale));
  199. GetVersion(&dwCifVer, &dwCifBuild);
  200. //
  201. // init the Detection structure
  202. //
  203. Det.dwSize = sizeof(DETECTION_STRUCT);
  204. Det.pdwInstalledVer = &m_dwInstalledVer;
  205. Det.pdwInstalledBuild = &m_dwInstalledBuild;
  206. Det.pszLocale = szLocale;
  207. Det.pszGUID = szGUID;
  208. Det.dwAskVer = dwCifVer;
  209. Det.dwAskBuild = dwCifBuild;
  210. Det.pCifFile = NULL;
  211. Det.pCifComp = (ICifComponent*)this;
  212. TCHAR szDllFile[MAX_PATH];
  213. GetWindowsUpdateDirectory(szDllFile);
  214. lstrcat(szDllFile, A2T(pszDll));
  215. //
  216. // load the detection dll
  217. //
  218. hLib = CacheLoadLibrary(pszDll, szDllFile);
  219. if (hLib)
  220. {
  221. DETECTVERSION fpDetVer = (DETECTVERSION)GetProcAddress(hLib, pszEntry);
  222. if (fpDetVer)
  223. {
  224. //
  225. // call the entry point
  226. //
  227. m_dwDLLReturnValue = fpDetVer(&Det);
  228. switch(m_dwDLLReturnValue)
  229. {
  230. case DET_NOTINSTALLED:
  231. m_dwDetectStatus = ICI_NOTINSTALLED;
  232. break;
  233. case DET_INSTALLED:
  234. m_dwDetectStatus = ICI_INSTALLED;
  235. break;
  236. case DET_NEWVERSIONINSTALLED:
  237. m_dwDetectStatus = ICI_OLDVERSIONAVAILABLE;
  238. break;
  239. case DET_OLDVERSIONINSTALLED:
  240. m_dwDetectStatus = ICI_NEWVERSIONAVAILABLE;
  241. break;
  242. }
  243. hr = NOERROR;
  244. }
  245. else
  246. {
  247. TRACE_HR(HRESULT_FROM_WIN32(GetLastError()), "Detection DLL call failed %s %s", pszDll, pszEntry);
  248. }
  249. }
  250. return hr;
  251. }
  252. STDMETHODIMP_(DWORD) CComponentDetection::IsComponentInstalled()
  253. {
  254. USES_CONVERSION;
  255. char szDllName[32];
  256. char szDllEntry[32];
  257. DWORD dwUnused;
  258. DWORD dwIsInstalled;
  259. char szGUID[128];
  260. HKEY hComponentKey = NULL;
  261. m_dwDetectStatus = ICI_NOTINSTALLED;
  262. //
  263. // if we need to call detection dll, call it
  264. //
  265. if (SUCCEEDED(GetDetVersion(szDllName, sizeof(szDllName), szDllEntry, sizeof(szDllEntry))))
  266. {
  267. if (SUCCEEDED(CallDetectDLL(szDllName, szDllEntry)))
  268. {
  269. if (m_dwDetectStatus == ICI_OLDVERSIONAVAILABLE)
  270. m_dwDetectStatus = ICI_INSTALLED;
  271. return m_dwDetectStatus;
  272. }
  273. }
  274. //
  275. // build GUID registry key
  276. //
  277. GetValue(ccGUID, szGUID, sizeof(szGUID));
  278. TCHAR szKeyName[MAX_PATH];
  279. lstrcpy(szKeyName, COMPONENT_KEY);
  280. lstrcat(szKeyName, _T("\\"));
  281. lstrcat(szKeyName, A2T(szGUID));
  282. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_READ, &hComponentKey) == ERROR_SUCCESS)
  283. {
  284. //
  285. // first check for the IsInstalled valuename
  286. // if the valuename is there AND equals zero, we say not installed.
  287. // otherwise continue.
  288. //
  289. // NOTE: We default to ISINSTALLED_YES if valuename not present to be Back-compatible
  290. //
  291. dwUnused = sizeof(dwIsInstalled);
  292. if (RegQueryValueEx(hComponentKey, ISINSTALLED_KEY, 0, NULL, (LPBYTE) (&dwIsInstalled), &dwUnused) != ERROR_SUCCESS)
  293. dwIsInstalled = ISINSTALLED_YES;
  294. if (dwIsInstalled == ISINSTALLED_YES)
  295. {
  296. //
  297. // next check for a locale match (no locale entry uses default)
  298. //
  299. DWORD dwType;
  300. TCHAR szRegLocale[8];
  301. dwUnused = sizeof(szRegLocale);
  302. if (RegQueryValueEx(hComponentKey, LOCALE_KEY, 0, NULL, (LPBYTE)szRegLocale, &dwUnused) != ERROR_SUCCESS)
  303. lstrcpy(szRegLocale, DEFAULT_LOCALE);
  304. char szAskLocale[8];
  305. GetValue(ccLocale, szAskLocale, sizeof(szAskLocale));
  306. if (CompareLocales(T2A(szRegLocale), szAskLocale) == 0)
  307. {
  308. //
  309. // locales match so go check the QFEversio, version in that order
  310. //
  311. BOOL bVersionFound = FALSE;
  312. TCHAR szRegVer[128];
  313. DWORD dwCifVer, dwCifBuild;
  314. dwUnused = sizeof(szRegVer);
  315. bVersionFound = (RegQueryValueEx(hComponentKey, QFE_VERSION_KEY, 0, &dwType, (LPBYTE)szRegVer, &dwUnused) == ERROR_SUCCESS);
  316. if (!bVersionFound)
  317. {
  318. dwUnused = sizeof(szRegVer);
  319. bVersionFound = (RegQueryValueEx(hComponentKey, VERSION_KEY, 0, &dwType, (LPBYTE)szRegVer, &dwUnused) == ERROR_SUCCESS);
  320. }
  321. if (bVersionFound)
  322. {
  323. if (dwType == REG_SZ)
  324. {
  325. ConvertVersionStrToDwords(szRegVer, &m_dwInstalledVer, &m_dwInstalledBuild);
  326. GetVersion(&dwCifVer, &dwCifBuild);
  327. if ((m_dwInstalledVer > dwCifVer) ||
  328. ((m_dwInstalledVer == dwCifVer) && (m_dwInstalledBuild >= dwCifBuild)))
  329. {
  330. m_dwDetectStatus = ICI_INSTALLED;
  331. }
  332. else
  333. {
  334. m_dwDetectStatus = ICI_NEWVERSIONAVAILABLE;
  335. }
  336. }
  337. else
  338. {
  339. // if a string field is not found assume we have a newer version
  340. m_dwDetectStatus = ICI_NEWVERSIONAVAILABLE;
  341. }
  342. } //version found
  343. } //locales match
  344. } // installed key
  345. }
  346. if (hComponentKey)
  347. RegCloseKey(hComponentKey);
  348. //
  349. // we think its installed, now try to verify using uninstall key
  350. //
  351. if (m_dwDetectStatus != ICI_NOTINSTALLED)
  352. {
  353. char szUninstallKey[ccMaxSize];
  354. if (GetValue(ccUninstallKey, szUninstallKey, sizeof(szUninstallKey)))
  355. {
  356. if (!UninstallKeyExists(szUninstallKey))
  357. {
  358. m_dwDetectStatus = ICI_NOTINSTALLED;
  359. }
  360. }
  361. }
  362. return m_dwDetectStatus;
  363. }
  364. STDMETHODIMP CComponentDetection::GetDetVersion(LPSTR pszDll, DWORD dwdllSize, LPSTR pszEntry, DWORD dwentSize)
  365. {
  366. char szBuf[ccMaxSize];
  367. if (pszDll && pszEntry)
  368. *pszDll = *pszEntry = '\0';
  369. else
  370. return E_FAIL;
  371. if (GetValue(ccDetectVersion, szBuf, sizeof(szBuf)))
  372. {
  373. LPCSTR pszParse = szBuf;
  374. pszParse = ParseField(pszParse, pszDll, dwdllSize);
  375. pszParse = ParseField(pszParse, pszEntry, dwentSize);
  376. }
  377. if (pszDll[0] == '\0' || pszEntry[0] == '\0')
  378. return E_FAIL;
  379. else
  380. return NOERROR;
  381. }
  382. STDMETHODIMP CComponentDetection::GetCustomData(LPSTR pszKey, LPSTR pszData, DWORD dwSize)
  383. {
  384. USES_CONVERSION;
  385. if (_stricmp(pszKey, "DetectVersion") == 0)
  386. {
  387. strncpy(pszData, m_ppValue[ccDetectVersion], dwSize);
  388. return NOERROR;
  389. }
  390. char szKeyName[128];
  391. LPCSTR pCus = m_ppValue[ccCustomData];
  392. LPCSTR pBeg = pCus;
  393. LPCSTR pEq;
  394. strcpy(szKeyName, "_");
  395. strcat(szKeyName, pszKey);
  396. // look for the _ key name
  397. pBeg = stristr(pBeg, szKeyName);
  398. while (pBeg != NULL)
  399. {
  400. // we found a match ensure that its at the begining of a line
  401. if ((pBeg == pCus) || (*(pBeg - 1) == '\n'))
  402. {
  403. // point to equal sign
  404. pEq = pBeg + strlen(szKeyName);
  405. // skip spaces
  406. while (*pEq == ' ')
  407. pEq++;
  408. if (*pEq == '=')
  409. {
  410. // skip the equal sign
  411. pEq++;
  412. // copy the value into pszData
  413. LPSTR p = pszData;
  414. int i = dwSize - 1;
  415. while ((*pEq != '\n') && (i > 0))
  416. {
  417. *p++ = *pEq++;
  418. i--;
  419. }
  420. *p = '\0';
  421. TRACE("Detect GetCustomData %s returns %s", A2T(pszKey), A2T(pszData));
  422. return NOERROR;
  423. }
  424. } // not the begining of the line
  425. }
  426. TRACE("Detect GetCustomData %s not found", A2T(pszKey));
  427. return E_FAIL;
  428. }
  429. STDMETHODIMP CComponentDetection::GetVersion(LPDWORD pdwVersion, LPDWORD pdwBuild)
  430. {
  431. USES_CONVERSION;
  432. char szBuf[ccMaxSize];
  433. if (GetValue(ccVersion, szBuf, sizeof(szBuf)))
  434. {
  435. ConvertVersionStrToDwords(A2T(szBuf), pdwVersion, pdwBuild);
  436. return NOERROR;
  437. }
  438. else
  439. return E_FAIL;
  440. }
  441. STDMETHODIMP CComponentDetection::GetGUID(LPSTR pszGUID, DWORD dwSize)
  442. {
  443. if (GetValue(ccGUID, pszGUID, dwSize))
  444. return NOERROR;
  445. else
  446. return E_FAIL;
  447. }
  448. STDMETHODIMP CComponentDetection::GetLocale(LPSTR pszLocale, DWORD dwSize)
  449. {
  450. if (GetValue(ccLocale, pszLocale, dwSize))
  451. return NOERROR;
  452. else
  453. return E_FAIL;
  454. }
  455. STDMETHODIMP CComponentDetection::GetUninstallKey(LPSTR pszKey, DWORD dwSize)
  456. {
  457. if (GetValue(ccUninstallKey, pszKey, dwSize))
  458. return NOERROR;
  459. else
  460. return E_FAIL;
  461. }
  462. STDMETHODIMP CComponentDetection::GetID(LPSTR pszID, DWORD dwSize)
  463. {
  464. return E_NOTIMPL;
  465. }
  466. STDMETHODIMP CComponentDetection::GetDescription(LPSTR pszDesc, DWORD dwSize)
  467. {
  468. return E_NOTIMPL;
  469. }
  470. STDMETHODIMP CComponentDetection::GetDetails(LPSTR pszDetails, DWORD dwSize)
  471. {
  472. return E_NOTIMPL;
  473. }
  474. STDMETHODIMP CComponentDetection::GetUrl(UINT uUrlNum, LPSTR pszUrl, DWORD dwSize, LPDWORD pdwUrlFlags)
  475. {
  476. return E_NOTIMPL;
  477. }
  478. STDMETHODIMP CComponentDetection::GetFileExtractList(UINT uUrlNum, LPSTR pszExtract, DWORD dwSize)
  479. {
  480. return E_NOTIMPL;
  481. }
  482. STDMETHODIMP CComponentDetection::GetUrlCheckRange(UINT uUrlNum, LPDWORD pdwMin, LPDWORD pdwMax)
  483. {
  484. return E_NOTIMPL;
  485. }
  486. STDMETHODIMP CComponentDetection::GetCommand(UINT uCmdNum, LPSTR pszCmd, DWORD dwCmdSize,
  487. LPSTR pszSwitches, DWORD dwSwitchSize, LPDWORD pdwType)
  488. {
  489. return E_NOTIMPL;
  490. }
  491. STDMETHODIMP CComponentDetection::GetInstalledSize(LPDWORD pdwWin, LPDWORD pdwApp)
  492. {
  493. return E_NOTIMPL;
  494. }
  495. STDMETHODIMP_(DWORD) CComponentDetection::GetDownloadSize()
  496. {
  497. return E_NOTIMPL;
  498. }
  499. STDMETHODIMP_(DWORD) CComponentDetection::GetExtractSize()
  500. {
  501. return E_NOTIMPL;
  502. }
  503. STDMETHODIMP CComponentDetection::GetSuccessKey(LPSTR pszKey, DWORD dwSize)
  504. {
  505. return E_NOTIMPL;
  506. }
  507. STDMETHODIMP CComponentDetection::GetProgressKeys(LPSTR pszProgress, DWORD dwProgSize, LPSTR pszCancel, DWORD dwCancelSize)
  508. {
  509. return E_NOTIMPL;
  510. }
  511. STDMETHODIMP CComponentDetection::IsActiveSetupAware()
  512. {
  513. return E_NOTIMPL;
  514. }
  515. STDMETHODIMP CComponentDetection::IsRebootRequired()
  516. {
  517. return E_NOTIMPL;
  518. }
  519. STDMETHODIMP CComponentDetection::RequiresAdminRights()
  520. {
  521. return E_NOTIMPL;
  522. }
  523. STDMETHODIMP_(DWORD) CComponentDetection::GetPriority()
  524. {
  525. return E_NOTIMPL;
  526. }
  527. STDMETHODIMP CComponentDetection::GetDependency(UINT uDepNum, LPSTR pszID, DWORD dwBuf, char *pchType, LPDWORD pdwVer, LPDWORD pdwBuild)
  528. {
  529. return E_NOTIMPL;
  530. }
  531. STDMETHODIMP_(DWORD) CComponentDetection::GetPlatform()
  532. {
  533. return E_NOTIMPL;
  534. }
  535. STDMETHODIMP_(BOOL) CComponentDetection::DisableComponent()
  536. {
  537. return E_NOTIMPL;
  538. }
  539. STDMETHODIMP CComponentDetection::GetMode(UINT uModeNum, LPSTR pszMode, DWORD dwSize)
  540. {
  541. return E_NOTIMPL;
  542. }
  543. STDMETHODIMP CComponentDetection::GetGroup(LPSTR pszID, DWORD dwSize)
  544. {
  545. return E_NOTIMPL;
  546. }
  547. STDMETHODIMP CComponentDetection::IsUIVisible()
  548. {
  549. return E_NOTIMPL;
  550. }
  551. STDMETHODIMP CComponentDetection::GetPatchID(LPSTR pszID, DWORD dwSize)
  552. {
  553. return E_NOTIMPL;
  554. }
  555. STDMETHODIMP CComponentDetection::GetTreatAsOneComponents(UINT uNum, LPSTR pszID, DWORD dwBuf)
  556. {
  557. return E_NOTIMPL;
  558. }
  559. STDMETHODIMP_(DWORD) CComponentDetection::GetCurrentPriority()
  560. {
  561. return E_NOTIMPL;
  562. }
  563. STDMETHODIMP CComponentDetection::SetCurrentPriority(DWORD dwPriority)
  564. {
  565. return E_NOTIMPL;
  566. }
  567. STDMETHODIMP_(DWORD) CComponentDetection::GetActualDownloadSize()
  568. {
  569. return E_NOTIMPL;
  570. }
  571. STDMETHODIMP CComponentDetection::IsComponentDownloaded()
  572. {
  573. return E_NOTIMPL;
  574. }
  575. STDMETHODIMP_(DWORD) CComponentDetection::IsThisVersionInstalled(DWORD dwAskVer, DWORD dwAskBld, LPDWORD pdwVersion, LPDWORD pdwBuild)
  576. {
  577. return E_NOTIMPL;
  578. }
  579. STDMETHODIMP_(DWORD) CComponentDetection::GetInstallQueueState()
  580. {
  581. return E_NOTIMPL;
  582. }
  583. STDMETHODIMP CComponentDetection::SetInstallQueueState(DWORD dwState)
  584. {
  585. return E_NOTIMPL;
  586. }
  587. LPCSTR ParseField(LPCSTR pszStr, LPSTR pszTokOut, int cTokSize)
  588. {
  589. LPCSTR pszRetVal = NULL;
  590. LPSTR p;
  591. LPSTR p2;
  592. if (pszStr == NULL || *pszStr == '\0')
  593. {
  594. pszTokOut[0] = '\0';
  595. return NULL;
  596. }
  597. // look for a comma separator
  598. p = strstr(pszStr, ",");
  599. if (p != NULL)
  600. {
  601. int l = p - pszStr;
  602. if (l >= cTokSize)
  603. l = cTokSize - 1;
  604. strncpy(pszTokOut, pszStr, l);
  605. pszTokOut[l] = '\0';
  606. pszRetVal = p + 1;
  607. }
  608. else
  609. {
  610. strncpy(pszTokOut, pszStr, cTokSize - 1);
  611. }
  612. //strip spaces
  613. p = pszTokOut;
  614. p2 = pszTokOut;
  615. while (*p2)
  616. {
  617. if (*p2 != ' ')
  618. *p++ = *p2++;
  619. else
  620. p2++;
  621. }
  622. *p = '\0';
  623. return pszRetVal;
  624. }
  625. static int CompareLocales(LPCSTR pszLoc1, LPCSTR pszLoc2)
  626. {
  627. if (pszLoc1[0] == '*' || pszLoc2[0] == '*')
  628. return 0;
  629. else
  630. return _stricmp(pszLoc1, pszLoc2);
  631. }
  632. void ConvertVersionStrToDwords(LPCTSTR pszVer, LPDWORD pdwVer, LPDWORD pdwBuild)
  633. {
  634. USES_CONVERSION;
  635. DWORD dwTemp1,dwTemp2;
  636. LPCSTR pszParse = T2A(pszVer);
  637. char szBuf[20];
  638. pszParse = ParseField(pszParse, szBuf, sizeof(szBuf));
  639. dwTemp1 = atoi(szBuf);
  640. pszParse = ParseField(pszParse, szBuf, sizeof(szBuf));
  641. dwTemp2 = atoi(szBuf);
  642. *pdwVer = (dwTemp1 << 16) + dwTemp2;
  643. pszParse = ParseField(pszParse, szBuf, sizeof(szBuf));
  644. dwTemp1 = atoi(szBuf);
  645. pszParse = ParseField(pszParse, szBuf, sizeof(szBuf));
  646. dwTemp2 = atoi(szBuf);
  647. *pdwBuild = (dwTemp1 << 16) + dwTemp2;
  648. }
  649. BOOL UninstallKeyExists(LPCSTR pszUninstallKey)
  650. {
  651. USES_CONVERSION;
  652. HKEY hUninstallKey = NULL;
  653. TCHAR szUninstallKey[MAX_PATH];
  654. if (!pszUninstallKey) //if the pointer is NULL, assume installed
  655. return TRUE;
  656. lstrcpy(szUninstallKey, UNINSTALL_BRANCH);
  657. lstrcat(szUninstallKey, _T("\\"));
  658. lstrcat(szUninstallKey, A2T(pszUninstallKey));
  659. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, szUninstallKey, 0, KEY_READ, &hUninstallKey) == ERROR_SUCCESS)
  660. {
  661. RegCloseKey(hUninstallKey);
  662. return TRUE;
  663. }
  664. else
  665. return FALSE;
  666. }
  667. //reterives file version
  668. BOOL GetFileVersionDwords(LPCTSTR pszFilename, LPDWORD pdwMSVer, LPDWORD pdwLSVer)
  669. {
  670. BOOL bRetVal = FALSE;
  671. DWORD dwHandle;
  672. DWORD dwVerInfoSize = GetFileVersionInfoSize((LPTSTR)pszFilename, &dwHandle);
  673. if (dwVerInfoSize)
  674. {
  675. LPVOID lpBuffer = LocalAlloc(LPTR, dwVerInfoSize);
  676. if (lpBuffer)
  677. {
  678. // Read version stamping info
  679. if (GetFileVersionInfo((LPTSTR)pszFilename, dwHandle, dwVerInfoSize, lpBuffer))
  680. {
  681. // Get the value for Translation
  682. UINT uiSize;
  683. VS_FIXEDFILEINFO* lpVSFixedFileInfo;
  684. if (VerQueryValue(lpBuffer, _T("\\"), (LPVOID*)&lpVSFixedFileInfo, &uiSize) && (uiSize))
  685. {
  686. *pdwMSVer = lpVSFixedFileInfo->dwFileVersionMS;
  687. *pdwLSVer = lpVSFixedFileInfo->dwFileVersionLS;
  688. bRetVal = TRUE;
  689. }
  690. }
  691. LocalFree(lpBuffer);
  692. }
  693. }
  694. if (!bRetVal)
  695. {
  696. *pdwMSVer = *pdwLSVer = 0L;
  697. }
  698. return bRetVal;
  699. }