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.

1361 lines
32 KiB

  1. #include "inspch.h"
  2. #include <regstr.h>
  3. #include "resource.h"
  4. #include "insobj.h"
  5. #define STR_FILELIST "filelist.dat"
  6. #define GENERAL_SECTION "General"
  7. #define MIN_SUPPORTED_FILELIST_VER 1
  8. #define CURRENT_FILELIST_VER "1"
  9. HRESULT GetICifFileFromFile(ICifFile **p, LPCSTR pszPath)
  10. {
  11. HRESULT hr;
  12. CCifFile *pcif;
  13. *p = 0;
  14. pcif = new CCifFile();
  15. if(pcif)
  16. {
  17. hr = pcif->SetCifFile(pszPath, FALSE); // FALSE: Read version
  18. if(FAILED(hr))
  19. delete pcif;
  20. else
  21. {
  22. pcif->AddRef();
  23. *p = (ICifFile *)pcif;
  24. }
  25. }
  26. else
  27. hr = E_OUTOFMEMORY;
  28. return hr;
  29. }
  30. HRESULT GetICifRWFileFromFile(ICifRWFile **p, LPCSTR pszPath)
  31. {
  32. HRESULT hr;
  33. CCifRWFile *pcifrw;
  34. *p = 0;
  35. pcifrw = new CCifRWFile();
  36. if(pcifrw)
  37. {
  38. hr = pcifrw->SetCifFile(pszPath, TRUE); // TRUE: ReadWrite version
  39. if(FAILED(hr))
  40. delete pcifrw;
  41. else
  42. {
  43. pcifrw->AddRef();
  44. *p = (ICifRWFile *)pcifrw;
  45. }
  46. }
  47. else
  48. hr = E_OUTOFMEMORY;
  49. return hr;
  50. }
  51. CCifFile::CCifFile()
  52. {
  53. _cRef = 0;
  54. _cComp = 0;
  55. _cGroup = 0;
  56. _cMode = 0;
  57. _rpGroup = 0;
  58. _rpComp = 0;
  59. _rpMode = 0;
  60. _rpRWGroup = 0;
  61. _rpRWComp = 0;
  62. _rpRWMode = 0;
  63. _fCleanDir = FALSE;
  64. _pLastCriticalComp = NULL;
  65. }
  66. CCifFile::~CCifFile()
  67. {
  68. UINT i;
  69. if(_rpGroup)
  70. {
  71. CCifGroup *pgrp;
  72. i = 0;
  73. for(pgrp = _rpGroup[i]; pgrp != 0; pgrp = _rpGroup[++i])
  74. delete pgrp;
  75. free(_rpGroup);
  76. }
  77. if(_rpComp)
  78. {
  79. CCifComponent *pcomp;
  80. i = 0;
  81. for(pcomp = _rpComp[i]; pcomp != 0; pcomp = _rpComp[++i])
  82. delete pcomp;
  83. free(_rpComp);
  84. }
  85. if(_rpMode)
  86. {
  87. CCifMode *pmode;
  88. i = 0;
  89. for(pmode = _rpMode[i]; pmode != 0; pmode = _rpMode[++i])
  90. delete pmode;
  91. free(_rpMode);
  92. }
  93. if(_fCleanDir)
  94. {
  95. GetParentDir(_szCifPath);
  96. CleanUpTempDir(_szCifPath);
  97. }
  98. }
  99. //************ IUnknown implementation ***************
  100. STDMETHODIMP_(ULONG) CCifFile::AddRef()
  101. {
  102. return(_cRef++);
  103. }
  104. STDMETHODIMP_(ULONG) CCifFile::Release()
  105. {
  106. ULONG temp = --_cRef;
  107. if(temp == 0)
  108. delete this;
  109. return temp;
  110. }
  111. STDMETHODIMP CCifFile::QueryInterface(REFIID riid, void **ppv)
  112. {
  113. *ppv = 0;
  114. if((riid == IID_IUnknown) || (riid == IID_ICifFile))
  115. *ppv = (ICifFile *)this;
  116. if(*ppv == NULL)
  117. return E_NOINTERFACE;
  118. AddRef();
  119. return NOERROR;
  120. }
  121. // ICifFile implementation
  122. STDMETHODIMP CCifFile::EnumComponents(IEnumCifComponents **pp, DWORD dwFilter, LPVOID pv)
  123. {
  124. CCifComponentEnum *pce;
  125. HRESULT hr = E_FAIL;
  126. *pp = 0;
  127. pce = new CCifComponentEnum(_rpComp, dwFilter, PARENTTYPE_CIF, NULL);
  128. if(pce)
  129. {
  130. *pp = (IEnumCifComponents *) pce;
  131. (*pp)->AddRef();
  132. hr = NOERROR;
  133. }
  134. return hr;
  135. }
  136. STDMETHODIMP CCifFile::FindComponent(LPCSTR pszID, ICifComponent **p)
  137. {
  138. CCifComponent *pcomp;
  139. UINT i = 0;
  140. *p = 0;
  141. if(_rpComp)
  142. {
  143. for(pcomp = _rpComp[i]; pcomp != 0; pcomp = _rpComp[++i])
  144. if(pcomp->IsID(pszID))
  145. {
  146. *p = (ICifComponent *) pcomp;
  147. return NOERROR;
  148. }
  149. }
  150. return E_FAIL;
  151. }
  152. STDMETHODIMP CCifFile::EnumGroups(IEnumCifGroups **pp, DWORD dwFilter, LPVOID pv)
  153. {
  154. CCifGroupEnum *pge;
  155. HRESULT hr = E_FAIL;
  156. *pp = 0;
  157. pge = new CCifGroupEnum(_rpGroup, dwFilter);
  158. if(pge)
  159. {
  160. *pp = (IEnumCifGroups *) pge;
  161. (*pp)->AddRef();
  162. hr = NOERROR;
  163. }
  164. return hr;
  165. }
  166. STDMETHODIMP CCifFile::FindGroup(LPCSTR pszID, ICifGroup **p)
  167. {
  168. CCifGroup *pgrp;
  169. UINT i = 0;
  170. *p = 0;
  171. if(_rpGroup)
  172. {
  173. for(pgrp = _rpGroup[i]; pgrp != 0; pgrp = _rpGroup[++i])
  174. if(pgrp->IsID(pszID))
  175. {
  176. *p = (ICifGroup *) pgrp;
  177. return NOERROR;
  178. }
  179. }
  180. return E_FAIL;
  181. }
  182. STDMETHODIMP CCifFile::EnumModes(IEnumCifModes **pp, DWORD dwFilter, LPVOID pv)
  183. {
  184. CCifModeEnum *pme;
  185. HRESULT hr = E_FAIL;
  186. *pp = 0;
  187. pme = new CCifModeEnum(_rpMode, dwFilter);
  188. if(pme)
  189. {
  190. *pp = (IEnumCifModes *) pme;
  191. (*pp)->AddRef();
  192. hr = NOERROR;
  193. }
  194. return hr;
  195. }
  196. STDMETHODIMP CCifFile::FindMode(LPCSTR pszID, ICifMode **p)
  197. {
  198. CCifMode *pmode;
  199. UINT i = 0;
  200. *p = 0;
  201. if(_rpMode)
  202. {
  203. for(pmode = _rpMode[i]; pmode != 0; pmode = _rpMode[++i])
  204. if(pmode->IsID(pszID))
  205. {
  206. *p = (ICifMode *) pmode;
  207. return NOERROR;
  208. }
  209. }
  210. return E_FAIL;
  211. }
  212. STDMETHODIMP CCifFile::GetDescription(LPSTR pszDesc, DWORD dwSize)
  213. {
  214. // Get display title out of version section
  215. if(FAILED(MyTranslateString(_szCifPath, "Version", DISPLAYNAME_KEY, pszDesc, dwSize)))
  216. LoadSz(IDS_DEFAULTTITLE, pszDesc, dwSize);
  217. return NOERROR;
  218. }
  219. STDMETHODIMP CCifFile::GetDetDlls(LPSTR pszDlls, DWORD dwSize)
  220. {
  221. return(GetPrivateProfileString("Version", DETDLLS_KEY, "", pszDlls, dwSize, _szCifPath)?NOERROR:E_FAIL);
  222. }
  223. //const char c_gszRegstrPathIExplore[] = REGSTR_PATH_APPPATHS "\\iexplore.exe";
  224. HRESULT CCifFile::SetCifFile(LPCSTR pszCifPath, BOOL bRWFlag)
  225. {
  226. HRESULT hr = NOERROR;
  227. UINT i;
  228. // if it is not quallified, start from ie
  229. if(PathIsFileSpec(pszCifPath))
  230. {
  231. DWORD dwSize, dwType;
  232. char szTmp[MAX_PATH];
  233. if ( SUCCEEDED(hr=GetIEPath(szTmp, sizeof(szTmp))))
  234. {
  235. lstrcpy(_szCifPath, szTmp);
  236. SafeAddPath(_szCifPath, pszCifPath, sizeof(_szCifPath));
  237. }
  238. }
  239. else // we were given a full path
  240. lstrcpyn(_szCifPath, pszCifPath, MAX_PATH);
  241. if(SUCCEEDED(hr))
  242. {
  243. if(_rpComp)
  244. {
  245. // we already have a cif, so just reset cached stuff, and pray...
  246. for(i = 0; i < _cComp; i++)
  247. {
  248. _rpComp[i]->ClearCachedInfo();
  249. }
  250. for(i = 0; i < _cGroup; i++)
  251. {
  252. _rpGroup[i]->ClearCachedInfo();
  253. }
  254. for(i = 0; i < _cMode; i++)
  255. {
  256. _rpMode[i]->ClearCachedInfo();
  257. }
  258. // Sort all again, in case priorities changed
  259. SortEntries();
  260. }
  261. else
  262. hr = _ParseCifFile(bRWFlag);
  263. }
  264. return(hr);
  265. }
  266. HRESULT CCifFile::_ParseCifFile(BOOL bRWFlag)
  267. {
  268. LPSTR pszSections;
  269. LPSTR pszSectionsPreFail = NULL;
  270. DWORD dwSize = ALLOC_CHUNK_SIZE;
  271. LPSTR pszTemp;
  272. char szEntryBuf[MAX_DISPLAYNAME_LENGTH];
  273. pszSections = (LPSTR) malloc(dwSize);
  274. // when the buffer is too small, GPPS returns bufsize - 2
  275. while(pszSections &&
  276. (GetPrivateProfileStringA(NULL, NULL, "", pszSections, dwSize, _szCifPath) == (dwSize - 2)))
  277. {
  278. dwSize += ALLOC_CHUNK_SIZE;
  279. pszSectionsPreFail = pszSections;
  280. #pragma prefast(suppress: 308, "PREfast noise - pointer was saved before")
  281. pszSections = (LPSTR) realloc(pszSections, dwSize);
  282. }
  283. if(!pszSections)
  284. {
  285. if(pszSectionsPreFail)
  286. free(pszSectionsPreFail);
  287. return E_OUTOFMEMORY;
  288. }
  289. if(lstrlen(pszSections) == 0)
  290. return E_FAIL;
  291. // whip thru the sections, and find counts for modes, groups, and components
  292. _cComp = _cGroup = _cMode = 0;
  293. for(pszTemp = pszSections; *pszTemp != 0; pszTemp += (lstrlen(pszTemp) + 1))
  294. {
  295. // skip String section and Version section
  296. if( (lstrcmpi(pszTemp, "Strings") != 0)
  297. && (lstrcmpi(pszTemp, "Version") != 0) )
  298. {
  299. GetPrivateProfileString(pszTemp, ENTRYTYPE_KEY, ENTRYTYPE_COMP, szEntryBuf, sizeof(szEntryBuf), _szCifPath);
  300. // see if this is a comp, group, or mode
  301. if(lstrcmpi(szEntryBuf, ENTRYTYPE_COMP) == 0)
  302. _cComp++;
  303. else if(lstrcmpi(szEntryBuf, ENTRYTYPE_GROUP) == 0)
  304. _cGroup++;
  305. else if(lstrcmpi(szEntryBuf, ENTRYTYPE_MODE) == 0)
  306. _cMode++;
  307. }
  308. }
  309. // alloc arrays to hold each type (1 more than count - last entry null)
  310. if (bRWFlag)
  311. {
  312. _rpRWComp = (CCifRWComponent **) calloc(sizeof(CCifRWComponent *), _cComp + 1);
  313. _rpRWGroup = (CCifRWGroup **) calloc(sizeof(CCifRWGroup *), _cGroup + 1);
  314. _rpRWMode = (CCifRWMode **) calloc(sizeof(CCifRWMode *), _cMode + 1);
  315. }
  316. else
  317. {
  318. _rpComp = (CCifComponent **) calloc(sizeof(CCifComponent *), _cComp + 1);
  319. _rpGroup = (CCifGroup **) calloc(sizeof(CCifGroup *), _cGroup + 1);
  320. _rpMode = (CCifMode **) calloc(sizeof(CCifMode *), _cMode + 1);
  321. }
  322. _cComp = _cGroup = _cMode = 0;
  323. if((!bRWFlag && _rpComp && _rpGroup && _rpMode) || (bRWFlag && _rpRWComp && _rpRWGroup && _rpRWMode))
  324. {
  325. // pass thru sections again, adding to lists
  326. for(pszTemp = pszSections; *pszTemp != 0; pszTemp += (lstrlen(pszTemp) + 1))
  327. {
  328. // skip String section and Version section
  329. if( (lstrcmpi(pszTemp, "Strings") != 0)
  330. && (lstrcmpi(pszTemp, "Version") != 0) )
  331. {
  332. GetPrivateProfileString(pszTemp, ENTRYTYPE_KEY, ENTRYTYPE_COMP, szEntryBuf, sizeof(szEntryBuf), _szCifPath);
  333. // see if this is a comp, group, or mode
  334. if(lstrcmpi(szEntryBuf, ENTRYTYPE_COMP) == 0)
  335. {
  336. if (bRWFlag)
  337. _rpRWComp[_cComp++] = new CCifRWComponent(pszTemp, this);
  338. else
  339. _rpComp[_cComp++] = new CCifComponent(pszTemp, this);
  340. }
  341. else if(lstrcmpi(szEntryBuf, ENTRYTYPE_GROUP) == 0)
  342. {
  343. if (bRWFlag)
  344. _rpRWGroup[_cGroup++] = new CCifRWGroup(pszTemp, _cGroup, this);
  345. else
  346. _rpGroup[_cGroup++] = new CCifGroup(pszTemp, _cGroup, this);
  347. }
  348. else if(lstrcmpi(szEntryBuf, ENTRYTYPE_MODE) == 0)
  349. {
  350. if (bRWFlag)
  351. _rpRWMode[_cMode++] = new CCifRWMode(pszTemp, this);
  352. else
  353. _rpMode[_cMode++] = new CCifMode(pszTemp, this);
  354. }
  355. }
  356. }
  357. }
  358. if(_cComp) _cComp--;
  359. if(_cGroup) _cGroup--;
  360. if(_cMode) _cMode--;
  361. if (!bRWFlag)
  362. SortEntries();
  363. free(pszSections);
  364. return NOERROR;
  365. }
  366. void CCifFile::ReinsertComponent(CCifComponent *pComp)
  367. {
  368. int i,j;
  369. // find it in list
  370. for(i = 0; i <= (int) _cComp; i++)
  371. {
  372. if(pComp == _rpComp[i])
  373. {
  374. // once found, move everything under it up
  375. for(j = i + 1; j <=(int) (_cComp + 1); j++)
  376. _rpComp[j-1] = _rpComp[j];
  377. break;
  378. }
  379. }
  380. // now find where we should insert it
  381. for(i = 0; _rpComp[i] != 0; i++)
  382. {
  383. if(_rpComp[i]->GetCurrentPriority() < pComp->GetCurrentPriority())
  384. break;
  385. }
  386. // we want to isert new guy at i
  387. // move everyone down first
  388. for(j = _cComp; j >= i; j--)
  389. _rpComp[j+1] = _rpComp[j];
  390. // reinsert at i
  391. _rpComp[i] = pComp;
  392. // Now check that the dependencies are maintained.
  393. _CheckDependencyPriority();
  394. }
  395. void CCifFile::SortEntries()
  396. {
  397. _SortComponents(_rpComp, 0, _cComp);
  398. _SortGroups(_rpGroup, 0, _cGroup);
  399. _CheckDependencyPriority();
  400. }
  401. void CCifFile::_CheckDependencyPriority()
  402. {
  403. char szCompBuf[MAX_ID_LENGTH];
  404. CCifComponent *pCompxkokr;
  405. CCifComponent *pCompxenus;
  406. DWORD ixkokr = 0xffffffff;
  407. DWORD ixenus = 0xffffffff;
  408. // this is a complete hack for Outlook 98 Korean, which has bugs
  409. // in prorities.
  410. for(int i = 0; _rpComp[i] != 0; i++)
  411. {
  412. if(_rpComp[i]->IsID("Outlook98_xkokr"))
  413. {
  414. pCompxkokr = _rpComp[i];
  415. ixkokr = i;
  416. }
  417. else if(_rpComp[i]->IsID("Outlook98_xenus"))
  418. {
  419. pCompxenus = _rpComp[i];
  420. ixenus = i;
  421. }
  422. }
  423. if(ixkokr != 0xffffffff && ixenus != 0xffffffff)
  424. {
  425. if(ixenus > ixkokr)
  426. {
  427. _rpComp[ixenus] = pCompxkokr;
  428. _rpComp[ixkokr] = pCompxenus;
  429. }
  430. }
  431. }
  432. void CCifFile::ClearQueueState()
  433. {
  434. for(int i = 0; _rpComp[i] != 0; i++)
  435. {
  436. _rpComp[i]->ClearQueueState();
  437. }
  438. }
  439. void CCifFile::_SortComponents(CCifComponent * a[], UINT p, UINT r)
  440. {
  441. UINT i, j, x;
  442. CCifComponent *t;
  443. if(p < r)
  444. {
  445. i = p - 1;
  446. j = r + 1;
  447. x = a[p]->GetCurrentPriority();
  448. for(;;)
  449. {
  450. while(a[++i]->GetCurrentPriority() > x);
  451. while(a[--j]->GetCurrentPriority() < x);
  452. if(i >= j) break;
  453. t = a[i]; a[i] = a[j]; a[j] = t;
  454. }
  455. _SortComponents(a, p, j);
  456. _SortComponents(a, j + 1, r);
  457. }
  458. }
  459. void CCifFile::_SortGroups(CCifGroup * a[], UINT p, UINT r)
  460. {
  461. UINT i, j, x;
  462. CCifGroup *t;
  463. if(p < r)
  464. {
  465. i = p - 1;
  466. j = r + 1;
  467. x = a[p]->GetCurrentPriority();
  468. for(;;)
  469. {
  470. while(a[++i]->GetCurrentPriority() > x);
  471. while(a[--j]->GetCurrentPriority() < x);
  472. if(i >= j) break;
  473. t = a[i]; a[i] = a[j]; a[j] = t;
  474. }
  475. _SortGroups(a, p, j);
  476. _SortGroups(a, j + 1, r);
  477. }
  478. }
  479. void CCifFile::SetDownloadDir(LPCSTR pszDownloadDir)
  480. {
  481. char szBuf[MAX_PATH];
  482. DWORD dwLen;
  483. DWORD dwVer;
  484. lstrcpyn(_szDLDir, pszDownloadDir, MAX_PATH);
  485. if(_szDLDir[0] >= 'a' && _szDLDir[0] <= 'z')
  486. _szDLDir[0] -= 32;
  487. lstrcpyn(_szFilelist, pszDownloadDir, MAX_PATH);
  488. SafeAddPath(_szFilelist, STR_FILELIST, MAX_PATH);
  489. // check to see if the download list has a version we like
  490. dwVer = GetPrivateProfileInt(GENERAL_SECTION, VERSION_KEY, 0, _szFilelist);
  491. if(dwVer < MIN_SUPPORTED_FILELIST_VER)
  492. DeleteFilelist(_szFilelist);
  493. WritePrivateProfileString(GENERAL_SECTION, VERSION_KEY, CURRENT_FILELIST_VER, _szFilelist);
  494. // flush due to wierd stacker bug
  495. WritePrivateProfileString(NULL, NULL, NULL, _szFilelist);
  496. }
  497. HRESULT CCifFile::Download()
  498. {
  499. CCifComponent *pcomp;
  500. UINT i = 0;
  501. HRESULT hr = NOERROR;
  502. for(pcomp = _rpComp[i]; pcomp != 0 && SUCCEEDED(hr); pcomp = _rpComp[++i])
  503. {
  504. // if it is queued up and not downloded, download it
  505. if((pcomp->GetInstallQueueState() == SETACTION_INSTALL) &&
  506. (pcomp->IsComponentDownloaded() == S_FALSE) )
  507. {
  508. hr = pcomp->Download();
  509. if(FAILED(hr) && _pInsEng->IgnoreDownloadError() && hr != E_ABORT)
  510. hr = NOERROR;
  511. if(SUCCEEDED(hr))
  512. hr = _pInsEng->CheckForContinue();
  513. }
  514. }
  515. return hr;
  516. }
  517. HRESULT CCifFile::Install(BOOL *pfOneInstalled)
  518. {
  519. CCifComponent *pcomp;
  520. UINT i = 0;
  521. *pfOneInstalled = FALSE;
  522. HRESULT hr = NOERROR;
  523. for(pcomp = _rpComp[i]; (pcomp != 0) && SUCCEEDED(hr); pcomp = _rpComp[++i])
  524. {
  525. // if it is queued up and not downloded, download it
  526. if(pcomp->GetInstallQueueState() == SETACTION_INSTALL)
  527. {
  528. hr = pcomp->Install();
  529. if(SUCCEEDED(hr))
  530. *pfOneInstalled = TRUE;
  531. if(hr != E_ABORT)
  532. hr = NOERROR;
  533. if(SUCCEEDED(hr))
  534. hr = _pInsEng->CheckForContinue();
  535. }
  536. }
  537. return hr;
  538. }
  539. HRESULT CCifFile::_ExtractDetDlls( LPCSTR pszCab, LPCSTR pszPath )
  540. {
  541. char szDetDlls[MAX_PATH];
  542. char szLogBuf[MAX_PATH*2];
  543. char szBuf[64];
  544. UINT i = 0;
  545. LPSTR pszTmp;
  546. HRESULT hr = NOERROR;
  547. // check if we need to extract & copy the detection dlls
  548. if (SUCCEEDED(GetDetDlls(szDetDlls, sizeof(szDetDlls))))
  549. {
  550. while(SUCCEEDED(hr) && GetStringField(szDetDlls, i++, szBuf, sizeof(szBuf)))
  551. {
  552. if(SUCCEEDED(ExtractFiles(pszCab, pszPath, 0, szBuf, NULL, 0)))
  553. {
  554. wsprintf(szLogBuf, "Extract DetDll path:%s file:%s\r\n",pszPath, szBuf );
  555. _pInsEng->WriteToLog(szLogBuf, TRUE);
  556. }
  557. else
  558. {
  559. wsprintf(szLogBuf, "Extract DetDll:%s from: %s\r\n", szBuf, pszCab);
  560. _pInsEng->WriteToLog(szLogBuf, TRUE);
  561. hr = E_FAIL;
  562. }
  563. }
  564. }
  565. return hr;
  566. }
  567. HRESULT CCifFile::_CopyDetDlls( LPCSTR pszPath )
  568. {
  569. char szDetDlls[MAX_PATH];
  570. char szSrcFile[MAX_PATH];
  571. char szDestFile[MAX_PATH];
  572. char szLogBuf[MAX_PATH*2];
  573. char szBuf[64];
  574. UINT i = 0;
  575. LPSTR pszTmp;
  576. // check if we need to extract & copy the detection dlls
  577. if (SUCCEEDED(GetDetDlls(szDetDlls, sizeof(szDetDlls))))
  578. {
  579. lstrcpy(szDestFile, _szCifPath);
  580. GetParentDir(szDestFile);
  581. pszTmp = szDestFile + lstrlen(szDestFile);
  582. while(GetStringField(szDetDlls, i++, szBuf, sizeof(szBuf)))
  583. {
  584. lstrcpy(szSrcFile, pszPath);
  585. AddPath(szSrcFile, szBuf);
  586. *pszTmp = 0;
  587. AddPath(szDestFile, szBuf);
  588. CopyFile(szSrcFile, szDestFile, FALSE);
  589. wsprintf(szLogBuf, "Copy DetDll fr:%s to:%s\r\n", szSrcFile, szDestFile);
  590. _pInsEng->WriteToLog(szLogBuf, TRUE);
  591. }
  592. return NOERROR;
  593. }
  594. else
  595. return E_FAIL;
  596. }
  597. HRESULT CCifFile::DownloadCifFile(LPCSTR pszUrl, LPCSTR pszCif)
  598. {
  599. HRESULT hr;
  600. char szTempfile[MAX_PATH];
  601. char szDownldfile[MAX_PATH];
  602. char szPath[MAX_PATH];
  603. _pInsEng->AddRef();
  604. _pInsEng->OnEngineStatusChange(ENGINESTATUS_LOADING, 0);
  605. CDownloader *pDL = _pInsEng->GetDownloader();
  606. if(!pDL)
  607. return E_UNEXPECTED;
  608. hr = pDL->SetupDownload(pszUrl, NULL, 0, NULL);
  609. szPath[0] = 0;
  610. if(SUCCEEDED(hr))
  611. hr = pDL->DoDownload(szDownldfile, sizeof(szDownldfile));
  612. if(SUCCEEDED(hr))
  613. {
  614. hr = ::CheckTrustEx(pszUrl, szDownldfile, _pInsEng->GetHWND(), FALSE, NULL);
  615. if (hr == S_FALSE)
  616. hr = TRUST_E_FAIL;
  617. // For compat reasons, we need to copy the cif cab into the download dir
  618. if(SUCCEEDED(hr))
  619. {
  620. lstrcpy(szPath, _szDLDir);
  621. SafeAddPath(szPath, ParseURLA(pszUrl), sizeof(szPath));
  622. CopyFile(szDownldfile, szPath, FALSE);
  623. }
  624. lstrcpy(szPath, szDownldfile);
  625. GetParentDir(szPath);
  626. }
  627. if(SUCCEEDED(hr))
  628. hr=ExtractFiles(szDownldfile, szPath, 0, pszCif, NULL, 0);
  629. if(SUCCEEDED(hr))
  630. {
  631. //BUGBUG: we should validate cif we got somehow!
  632. // if we already have a cif, copy what we need over old cif, delete temp now
  633. if(_rpComp)
  634. {
  635. // Dest
  636. lstrcpy(szTempfile, _szCifPath);
  637. GetParentDir(szTempfile);
  638. AddPath(szTempfile, pszCif);
  639. // source
  640. SafeAddPath(szPath, pszCif, sizeof(szPath));
  641. // copy to old one
  642. CopyFile(szPath, szTempfile, FALSE);
  643. hr = SetCifFile(szTempfile, FALSE); // read only version
  644. GetParentDir(szPath);
  645. // check if we need to extract & copy the detection dlls
  646. if (SUCCEEDED(hr))
  647. {
  648. if(SUCCEEDED(hr =_ExtractDetDlls(szDownldfile,szPath)))
  649. _CopyDetDlls(szPath);
  650. }
  651. DelNode(szPath, 0);
  652. }
  653. else
  654. {
  655. // new cif, use it in place in temp dir, mark temp dir to clean up
  656. _fCleanDir = TRUE;
  657. SafeAddPath(szPath, pszCif, sizeof(szPath));
  658. hr = SetCifFile(szPath, FALSE); // read only version
  659. if (SUCCEEDED(hr))
  660. {
  661. GetParentDir(szPath);
  662. hr =_ExtractDetDlls(szDownldfile,szPath);
  663. }
  664. }
  665. }
  666. else
  667. {
  668. // cleanup now
  669. if(szPath[0] != 0)
  670. DelNode(szPath, 0);
  671. }
  672. _pInsEng->OnEngineStatusChange(SUCCEEDED(hr) ? ENGINESTATUS_READY : ENGINESTATUS_NOTREADY, hr);
  673. // we are done; release the install engine
  674. _pInsEng->Release();
  675. return hr;
  676. }
  677. HRESULT CCifFile::_FindCifComponent(LPCSTR pszID, CCifComponent **p)
  678. {
  679. CCifComponent *pcomp;
  680. UINT i = 0;
  681. *p = 0;
  682. if(_rpComp)
  683. {
  684. for(pcomp = _rpComp[i]; pcomp != 0; pcomp = _rpComp[++i])
  685. if(pcomp->IsID(pszID))
  686. {
  687. *p = pcomp;
  688. return NOERROR;
  689. }
  690. }
  691. return E_FAIL;
  692. }
  693. void CCifFile::MarkCriticalComponents(CCifComponent *pOwner)
  694. {
  695. char szID[MAX_ID_LENGTH];
  696. UINT j;
  697. CCifComponent *pComp;
  698. for(j = 0;SUCCEEDED(pOwner->GetTreatAsOneComponents(j, szID, sizeof(szID))); j++)
  699. {
  700. if(SUCCEEDED(_FindCifComponent(szID, &pComp)))
  701. {
  702. if(pComp->GetInstallQueueState() == SETACTION_INSTALL)
  703. {
  704. if(_pLastCriticalComp == NULL)
  705. _pLastCriticalComp = pComp;
  706. else
  707. {
  708. UINT i = 0;
  709. CCifComponent *ptemp;
  710. for(ptemp = _rpComp[i]; ptemp != 0 && ptemp != _pLastCriticalComp && ptemp != pComp ; ptemp = _rpComp[++i]);
  711. if(ptemp == _pLastCriticalComp)
  712. _pLastCriticalComp = pComp;
  713. }
  714. }
  715. }
  716. }
  717. }
  718. void CCifFile::RemoveFromCriticalComponents(CCifComponent *pComp)
  719. {
  720. if(_pLastCriticalComp == pComp)
  721. _pLastCriticalComp = NULL;
  722. }
  723. DWORD WINAPI DownloadCifFile(LPVOID pv)
  724. {
  725. SETCIFARGS *p = (SETCIFARGS *) pv;
  726. p->pCif->DownloadCifFile(p->szUrl, p->szCif);
  727. delete p;
  728. return 0;
  729. }
  730. CCifRWFile::CCifRWFile() : CCifFile()
  731. {
  732. _cCompUnused = 0;
  733. _cGroupUnused = 0;
  734. _cModeUnused = 0;
  735. }
  736. CCifRWFile::~CCifRWFile()
  737. {
  738. // flus out the cif file
  739. WritePrivateProfileString( NULL, NULL, NULL, _szCifPath );
  740. if(_rpRWGroup)
  741. {
  742. for ( UINT i=0; i<=_cGroup; i++)
  743. delete(_rpRWGroup[i]);
  744. free(_rpRWGroup);
  745. }
  746. if(_rpRWComp)
  747. {
  748. for ( UINT i=0; i<=_cComp; i++)
  749. delete(_rpRWComp[i]);
  750. free(_rpRWComp);
  751. }
  752. if(_rpRWMode)
  753. {
  754. for ( UINT i=0; i<=_cMode; i++)
  755. delete(_rpRWMode[i]);
  756. free(_rpRWMode);
  757. }
  758. }
  759. // ICifRWFile implementation
  760. // wrapper of the CCifFile functions
  761. STDMETHODIMP CCifRWFile::QueryInterface(REFIID riid, LPVOID * ppvObj)
  762. {
  763. return (CCifFile::QueryInterface(riid, ppvObj));
  764. }
  765. STDMETHODIMP_(ULONG) CCifRWFile::AddRef()
  766. {
  767. return(_cRef++);
  768. }
  769. STDMETHODIMP_(ULONG) CCifRWFile::Release()
  770. {
  771. ULONG temp = --_cRef;
  772. if(temp == 0)
  773. delete this;
  774. return temp;
  775. }
  776. STDMETHODIMP CCifRWFile::EnumComponents(IEnumCifComponents **pp, DWORD dwFilter, LPVOID pv)
  777. {
  778. CCifComponentEnum *pce;
  779. HRESULT hr = E_FAIL;
  780. *pp = 0;
  781. pce = new CCifComponentEnum((CCifComponent **)_rpRWComp, dwFilter, PARENTTYPE_CIF, NULL);
  782. if(pce)
  783. {
  784. *pp = (IEnumCifComponents *) pce;
  785. (*pp)->AddRef();
  786. hr = NOERROR;
  787. }
  788. return hr;
  789. }
  790. STDMETHODIMP CCifRWFile::FindComponent(LPCSTR pszID, ICifComponent **p)
  791. {
  792. CCifRWComponent *pcomp;
  793. UINT i = 0;
  794. *p = 0;
  795. if(_rpRWComp)
  796. {
  797. for(pcomp = _rpRWComp[i]; pcomp != 0; pcomp = _rpRWComp[++i])
  798. if(pcomp->IsID(pszID))
  799. {
  800. CCifComponent *ptmp;
  801. ptmp = (CCifComponent *)pcomp;
  802. *p = (ICifComponent *) ptmp;
  803. return NOERROR;
  804. }
  805. }
  806. return E_FAIL;
  807. }
  808. STDMETHODIMP CCifRWFile::EnumGroups(IEnumCifGroups **pp, DWORD dwFilter, LPVOID pv)
  809. {
  810. CCifGroupEnum *pge;
  811. HRESULT hr = E_FAIL;
  812. *pp = 0;
  813. pge = new CCifGroupEnum((CCifGroup **)_rpRWGroup, dwFilter);
  814. if(pge)
  815. {
  816. *pp = (IEnumCifGroups *) pge;
  817. (*pp)->AddRef();
  818. hr = NOERROR;
  819. }
  820. return hr;
  821. }
  822. STDMETHODIMP CCifRWFile::FindGroup(LPCSTR pszID, ICifGroup **p)
  823. {
  824. CCifRWGroup *pgrp;
  825. UINT i = 0;
  826. *p = 0;
  827. if(_rpRWGroup)
  828. {
  829. for(pgrp = _rpRWGroup[i]; pgrp != 0; pgrp = _rpRWGroup[++i])
  830. if(pgrp->IsID(pszID))
  831. {
  832. CCifGroup *ptmp;
  833. ptmp = (CCifGroup *)pgrp;
  834. *p = (ICifGroup *) ptmp;
  835. return NOERROR;
  836. }
  837. }
  838. return E_FAIL;
  839. }
  840. STDMETHODIMP CCifRWFile::EnumModes(IEnumCifModes **pp, DWORD dwFilter, LPVOID pv)
  841. {
  842. CCifModeEnum *pme;
  843. HRESULT hr = E_FAIL;
  844. *pp = 0;
  845. pme = new CCifModeEnum((CCifMode **)_rpRWMode, dwFilter);
  846. if(pme)
  847. {
  848. *pp = (IEnumCifModes *) pme;
  849. (*pp)->AddRef();
  850. hr = NOERROR;
  851. }
  852. return hr;
  853. }
  854. STDMETHODIMP CCifRWFile::FindMode(LPCSTR pszID, ICifMode **p)
  855. {
  856. CCifRWMode *pmode;
  857. UINT i = 0;
  858. *p = 0;
  859. if(_rpRWMode)
  860. {
  861. for(pmode = _rpRWMode[i]; pmode != 0; pmode = _rpRWMode[++i])
  862. if(pmode->IsID(pszID))
  863. {
  864. CCifMode *ptmp;
  865. ptmp = (CCifMode *)pmode;
  866. *p = (ICifMode *) ptmp;
  867. return NOERROR;
  868. }
  869. }
  870. return E_FAIL;
  871. }
  872. STDMETHODIMP CCifRWFile::GetDescription(LPSTR pszDesc, DWORD dwSize)
  873. {
  874. return(CCifFile::GetDescription(pszDesc, dwSize));
  875. }
  876. STDMETHODIMP CCifRWFile::GetDetDlls(LPSTR pszDlls, DWORD dwSize)
  877. {
  878. return(CCifFile::GetDetDlls(pszDlls, dwSize));
  879. }
  880. STDMETHODIMP CCifRWFile::SetDescription(LPCSTR pszDesc)
  881. {
  882. return(WriteTokenizeString(_szCifPath, "Version", DISPLAYNAME_KEY, pszDesc));
  883. }
  884. STDMETHODIMP CCifRWFile::CreateComponent(LPCSTR pszID, ICifRWComponent **p)
  885. {
  886. CCifRWComponent *prwcomp;
  887. CCifRWComponent **ppRWCompPreFail;
  888. BOOL bFound = FALSE;
  889. UINT i = 0;
  890. *p = 0;
  891. for(prwcomp = _rpRWComp[i]; prwcomp != 0; prwcomp = _rpRWComp[++i])
  892. {
  893. if(prwcomp->IsID(pszID))
  894. {
  895. *p = (ICifRWComponent*)prwcomp;
  896. bFound = TRUE;
  897. break;
  898. }
  899. }
  900. // create the new component
  901. if (!bFound)
  902. {
  903. prwcomp = new CCifRWComponent(pszID, this);
  904. if (!prwcomp)
  905. return E_OUTOFMEMORY;
  906. // check to see if we need to grow the array size
  907. if (_cCompUnused <= 0)
  908. {
  909. // growing the array size to acomdate the new component
  910. ppRWCompPreFail = _rpRWComp;
  911. #pragma prefast(suppress: 308, "PREfast noise - pointer was saved before")
  912. _rpRWComp = (CCifRWComponent **) realloc(_rpRWComp, sizeof(CCifRWComponent **)*(i+10));
  913. if (_rpRWComp)
  914. {
  915. _cCompUnused = 9; // terminator used up one slot and the new comp use the one, s
  916. }
  917. else
  918. {
  919. if(ppRWCompPreFail)
  920. {
  921. for ( UINT i=0; i<=_cComp; i++)
  922. delete(ppRWCompPreFail[i]);
  923. free(ppRWCompPreFail);
  924. }
  925. return E_OUTOFMEMORY;
  926. }
  927. }
  928. _rpRWComp[i] = prwcomp;
  929. _rpRWComp[i+1] = 0;
  930. _cCompUnused--;
  931. _cComp++;
  932. *p = (ICifRWComponent*)prwcomp;
  933. WritePrivateProfileString(pszID, ENTRYTYPE_KEY, ENTRYTYPE_COMP, _szCifPath);
  934. }
  935. return NOERROR;
  936. }
  937. STDMETHODIMP CCifRWFile::CreateGroup(LPCSTR pszID, ICifRWGroup **p)
  938. {
  939. CCifRWGroup *prwgroup;
  940. CCifRWGroup **ppwgroupPreFail;
  941. BOOL bFound = FALSE;
  942. UINT i = 0;
  943. *p = 0;
  944. for(prwgroup = _rpRWGroup[i]; prwgroup != 0; prwgroup = _rpRWGroup[++i])
  945. {
  946. if(prwgroup->IsID(pszID))
  947. {
  948. *p = (ICifRWGroup *)prwgroup;
  949. bFound = TRUE;
  950. break;
  951. }
  952. }
  953. // create the new component
  954. if (!bFound)
  955. {
  956. prwgroup = new CCifRWGroup(pszID, i+1, this);
  957. if (!prwgroup)
  958. return E_OUTOFMEMORY;
  959. // check to see if we need to grow the array size
  960. if (_cGroupUnused <= 0)
  961. {
  962. ppwgroupPreFail = _rpRWGroup;
  963. // growing the array size to acomdate the new component
  964. #pragma prefast(suppress: 308, "PREfast noise - pointer was saved before")
  965. _rpRWGroup = (CCifRWGroup **) realloc(_rpRWGroup, sizeof(CCifRWGroup **)*(i+10));
  966. if (_rpRWGroup)
  967. {
  968. _cGroupUnused = 9;
  969. }
  970. else
  971. {
  972. if(ppwgroupPreFail)
  973. {
  974. for ( UINT i=0; i<=_cGroup; i++)
  975. delete(ppwgroupPreFail[i]);
  976. free(ppwgroupPreFail);
  977. }
  978. return E_OUTOFMEMORY;
  979. }
  980. }
  981. _rpRWGroup[i] = prwgroup;
  982. _rpRWGroup[i+1] = 0;
  983. _cGroupUnused--;
  984. _cGroup++;
  985. *p = (ICifRWGroup *)prwgroup;
  986. WritePrivateProfileString(pszID, ENTRYTYPE_KEY, ENTRYTYPE_GROUP, _szCifPath);
  987. }
  988. return NOERROR;
  989. }
  990. STDMETHODIMP CCifRWFile::CreateMode(LPCSTR pszID, ICifRWMode **p)
  991. {
  992. CCifRWMode *prwmode;
  993. CCifRWMode **prwmodePreFail;
  994. BOOL bFound = FALSE;
  995. UINT i = 0;
  996. *p = 0;
  997. for(prwmode = _rpRWMode[i]; prwmode != 0; prwmode = _rpRWMode[++i])
  998. {
  999. if(prwmode->IsID(pszID))
  1000. {
  1001. *p = (ICifRWMode *)prwmode;
  1002. bFound = TRUE;
  1003. break;
  1004. }
  1005. }
  1006. // create the new component
  1007. if (!bFound)
  1008. {
  1009. prwmode = new CCifRWMode(pszID, this);
  1010. if (!prwmode)
  1011. return E_OUTOFMEMORY;
  1012. // check to see if we need to grow the array size
  1013. if (_cModeUnused <= 0)
  1014. {
  1015. prwmodePreFail = _rpRWMode;
  1016. // growing the array size to acomdate the new component
  1017. #pragma prefast(suppress: 308, "PREfast noise - pointer was saved before")
  1018. _rpRWMode = (CCifRWMode **) realloc(_rpRWMode, sizeof(CCifRWMode **)*(i+10));
  1019. if (_rpRWMode)
  1020. {
  1021. _cModeUnused = 9;
  1022. }
  1023. else
  1024. {
  1025. if(prwmodePreFail)
  1026. {
  1027. for ( UINT i=0; i<=_cMode; i++)
  1028. delete(prwmodePreFail[i]);
  1029. free(prwmodePreFail);
  1030. }
  1031. return E_OUTOFMEMORY;
  1032. }
  1033. }
  1034. _rpRWMode[i] = prwmode;
  1035. _rpRWMode[i+1] = 0;
  1036. _cModeUnused--;
  1037. _cMode++;
  1038. *p = (ICifRWMode *)prwmode;
  1039. WritePrivateProfileString(pszID, ENTRYTYPE_KEY, ENTRYTYPE_MODE, _szCifPath);
  1040. }
  1041. return NOERROR;
  1042. }
  1043. STDMETHODIMP CCifRWFile::DeleteComponent(LPCSTR pszID)
  1044. {
  1045. CCifRWComponent *prwcomp;
  1046. BOOL bFound = FALSE;
  1047. UINT i = 0;
  1048. for(prwcomp = _rpRWComp[i]; prwcomp != 0; prwcomp = _rpRWComp[++i])
  1049. {
  1050. if(prwcomp->IsID(pszID))
  1051. {
  1052. bFound = TRUE;
  1053. break;
  1054. }
  1055. }
  1056. // Delete the component
  1057. if (bFound)
  1058. {
  1059. delete(prwcomp);
  1060. for ( UINT j=i+1; j<=_cComp; j++)
  1061. {
  1062. _rpRWComp[i] = _rpRWComp[j];
  1063. i= j;
  1064. }
  1065. _rpRWComp[i] = 0;
  1066. _cCompUnused++;
  1067. _cComp--;
  1068. }
  1069. return (WritePrivateProfileString(pszID, NULL, NULL, _szCifPath)?NOERROR:E_FAIL);
  1070. }
  1071. STDMETHODIMP CCifRWFile::DeleteGroup(LPCSTR pszID)
  1072. {
  1073. CCifRWGroup *prwgroup;
  1074. BOOL bFound = FALSE;
  1075. UINT i = 0;
  1076. for(prwgroup = _rpRWGroup[i]; prwgroup != 0; prwgroup = _rpRWGroup[++i])
  1077. {
  1078. if(prwgroup->IsID(pszID))
  1079. {
  1080. bFound = TRUE;
  1081. break;
  1082. }
  1083. }
  1084. // Delete the Group
  1085. if (bFound)
  1086. {
  1087. delete(prwgroup);
  1088. for (UINT j=i+1; j<=_cGroup; j++)
  1089. {
  1090. _rpRWGroup[i] = _rpRWGroup[j];
  1091. i= j;
  1092. }
  1093. _rpRWGroup[i] = 0;
  1094. _cGroupUnused++;
  1095. _cGroup--;
  1096. }
  1097. return (WritePrivateProfileString(pszID, NULL, NULL, _szCifPath)?NOERROR:E_FAIL);
  1098. }
  1099. STDMETHODIMP CCifRWFile::DeleteMode(LPCSTR pszID)
  1100. {
  1101. CCifRWMode *prwmode;
  1102. BOOL bFound = FALSE;
  1103. UINT i = 0;
  1104. for(prwmode = _rpRWMode[i]; prwmode != 0; prwmode = _rpRWMode[++i])
  1105. {
  1106. if(prwmode->IsID(pszID))
  1107. {
  1108. bFound = TRUE;
  1109. break;
  1110. }
  1111. }
  1112. // Delete the Mode
  1113. if (bFound)
  1114. {
  1115. delete(prwmode);
  1116. for (UINT j=i+1; j<=_cMode; j++)
  1117. {
  1118. _rpRWMode[i] = _rpRWMode[j];
  1119. i= j;
  1120. }
  1121. _rpRWMode[i] = 0;
  1122. _cModeUnused++;
  1123. _cMode--;
  1124. }
  1125. return (WritePrivateProfileString(pszID, NULL, NULL, _szCifPath)?NOERROR:E_FAIL);
  1126. }
  1127. STDMETHODIMP CCifRWFile::Flush()
  1128. {
  1129. WritePrivateProfileString(NULL, NULL, NULL, _szCifPath);
  1130. return NOERROR;
  1131. }