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.

2843 lines
82 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: csocm.cpp
  8. //
  9. // Contents: OCM component DLL for running the Certificate
  10. // Server setup.
  11. //
  12. // Functions:
  13. //
  14. // History: 12/13/96 TedM Created Original Version
  15. // 04/07/97 JerryK Rewrite for Cert Server
  16. // 04/??/97 JerryK Stopped updating these comments since
  17. // every other line changes every day.
  18. // 08/98 XTan Major structure change
  19. //
  20. // Notes:
  21. //
  22. // This sample OCM component DLL can be the component DLL
  23. // for multiple components. It assumes that a companion sample INF
  24. // is being used as the per-component INF, with private data in the
  25. // following form.
  26. //
  27. // [<pwszComponent>,<pwszSubComponent>]
  28. // Bitmap = <bitmapresourcename>
  29. // VerifySelect = 0/1
  30. // VerifyDeselect = 0/1
  31. // ;
  32. // ; follow this with install stuff such as CopyFiles= sections, etc.
  33. //
  34. //------------------------------------------------------------------------------
  35. #include "pch.cpp"
  36. #pragma hdrstop
  37. #include "msg.h"
  38. #include "certmsg.h"
  39. #include "setuput.h"
  40. #include "setupids.h"
  41. #include "clibres.h"
  42. #include "csresstr.h"
  43. // defines
  44. #define cwcMESSAGETEXT 250
  45. #define cwcINFVALUE 250
  46. #define wszSMALLICON L"_SmallIcon"
  47. #define wszUNINSTALL L"_Uninstall"
  48. #define wszUPGRADE L"_Upgrade"
  49. #define wszINSTALL L"_Install"
  50. #define wszVERIFYSELECT L"_VerifySelect"
  51. #define wszVERIFYDESELECT L"_VerifyDeselect"
  52. #define wszCONFIGTITLE L"Title"
  53. #define wszCONFIGCOMMAND L"ConfigCommand"
  54. #define wszCONFIGARGS L"ConfigArgs"
  55. #define wszCONFIGTITLEVAL L"Certificate Services"
  56. #define wszCONFIGCOMMANDVAL L"sysocmgr.exe"
  57. #define wszCONFIGARGSVAL L"/i:certmast.inf /x"
  58. #define __dwFILE__ __dwFILE_OCMSETUP_CSOCM_CPP__
  59. // globals
  60. PER_COMPONENT_DATA g_Comp; // Top Level component
  61. HINSTANCE g_hInstance; // get rid of it????
  62. // find out if certsrv post setup is finished by checking
  63. // registry entries. ie. finish CYS?
  64. HRESULT
  65. CheckPostBaseInstallStatus(
  66. OUT BOOL *pfFinished)
  67. {
  68. HRESULT hr;
  69. HKEY hKey = NULL;
  70. DWORD dwSize = 0;
  71. DWORD dwType = REG_NONE;
  72. //init
  73. *pfFinished = TRUE;
  74. if (ERROR_SUCCESS == RegOpenKeyEx(
  75. HKEY_LOCAL_MACHINE,
  76. wszREGKEYCERTSRVTODOLIST,
  77. 0,
  78. KEY_READ,
  79. &hKey))
  80. {
  81. if (ERROR_SUCCESS == RegQueryValueEx(
  82. hKey,
  83. wszCONFIGCOMMAND,
  84. NULL,
  85. &dwType,
  86. NULL, // only query size
  87. &dwSize) &&
  88. REG_SZ == dwType)
  89. {
  90. dwType = REG_NONE;
  91. if (ERROR_SUCCESS == RegQueryValueEx(
  92. hKey,
  93. wszCONFIGARGS,
  94. NULL,
  95. &dwType,
  96. NULL, // only query size
  97. &dwSize) &&
  98. REG_SZ == dwType)
  99. {
  100. dwType = REG_NONE;
  101. if (ERROR_SUCCESS == RegQueryValueEx(
  102. hKey,
  103. wszCONFIGTITLE,
  104. NULL,
  105. &dwType,
  106. NULL, // only query size
  107. &dwSize) &&
  108. REG_SZ == dwType)
  109. {
  110. //all entries exist
  111. *pfFinished = FALSE;
  112. }
  113. }
  114. }
  115. }
  116. hr = S_OK;
  117. //error:
  118. if (NULL != hKey)
  119. {
  120. RegCloseKey(hKey);
  121. }
  122. return hr;
  123. }
  124. HRESULT
  125. InitComponentAttributes(
  126. IN OUT PER_COMPONENT_DATA *pComp,
  127. IN HINSTANCE hDllHandle)
  128. {
  129. HRESULT hr;
  130. ZeroMemory(pComp, sizeof(PER_COMPONENT_DATA));
  131. pComp->hInstance = hDllHandle;
  132. g_hInstance = hDllHandle; //get rid of it????
  133. pComp->hrContinue = S_OK;
  134. pComp->pwszCustomMessage = NULL;
  135. pComp->fUnattended = FALSE;
  136. pComp->pwszUnattendedFile = NULL;
  137. pComp->pwszServerName = NULL;
  138. pComp->pwszServerNameOld = NULL;
  139. pComp->dwInstallStatus = 0x0;
  140. pComp->fPostBase = FALSE;
  141. (pComp->CA).pServer = NULL;
  142. (pComp->CA).pClient = NULL;
  143. hr = S_OK;
  144. //error:
  145. return hr;
  146. }
  147. //+------------------------------------------------------------------------
  148. //
  149. // Function: DllMain( . . . . )
  150. //
  151. // Synopsis: DLL Entry Point.
  152. //
  153. // Arguments: [DllHandle] DLL module handle.
  154. // [Reason] Reasons for entry into DLL.
  155. // [Reserved] Reserved.
  156. //
  157. // Returns: BOOL
  158. //
  159. // History: 04/07/97 JerryK Created (again)
  160. //
  161. //-------------------------------------------------------------------------
  162. BOOL WINAPI
  163. DllMain(
  164. IN HMODULE DllHandle,
  165. IN DWORD Reason,
  166. IN LPVOID Reserved)
  167. {
  168. BOOL b;
  169. UNREFERENCED_PARAMETER(Reserved);
  170. b = TRUE;
  171. switch(Reason)
  172. {
  173. case DLL_PROCESS_ATTACH:
  174. DBGPRINT((DBG_SS_CERTOCMI, "Process Attach\n"));
  175. // component initialization
  176. InitComponentAttributes(&g_Comp, DllHandle);
  177. // Fall through to process first thread
  178. case DLL_THREAD_ATTACH:
  179. b = TRUE;
  180. break;
  181. case DLL_PROCESS_DETACH:
  182. DBGPRINT((DBG_SS_CERTOCMI, "Process Detach\n"));
  183. myFreeResourceStrings("certocm.dll");
  184. myFreeColumnDisplayNames();
  185. myRegisterMemDump();
  186. csiLogClose();
  187. break;
  188. case DLL_THREAD_DETACH:
  189. break;
  190. }
  191. return b;
  192. }
  193. extern UNATTENDPARM aUnattendParmClient[];
  194. extern UNATTENDPARM aUnattendParmServer[];
  195. SUBCOMP g_aSubComp[] =
  196. {
  197. {
  198. L"certsrv", // pwszSubComponent
  199. cscTopLevel, // cscSubComponent
  200. 0, // InstallFlags
  201. 0, // UninstallFlags
  202. 0, // ChangeFlags
  203. 0, // UpgradeFlags
  204. 0, // EnabledFlags
  205. 0, // SetupStatusFlags
  206. FALSE, // fDefaultInstallUnattend
  207. FALSE, // fInstallUnattend
  208. NULL // aUnattendParm
  209. },
  210. {
  211. wszSERVERSECTION, // pwszSubComponent
  212. cscServer, // cscSubComponent
  213. IS_SERVER_INSTALL, // InstallFlags
  214. IS_SERVER_REMOVE, // UninstallFlags
  215. IS_SERVER_CHANGE, // ChangeFlags
  216. IS_SERVER_UPGRADE, // UpgradeFlags
  217. IS_SERVER_ENABLED, // EnabledFlags
  218. SETUP_SERVER_FLAG, // SetupStatusFlags
  219. TRUE, // fDefaultInstallUnattend
  220. FALSE, // fInstallUnattend
  221. aUnattendParmServer // aUnattendParm
  222. },
  223. {
  224. wszCLIENTSECTION, // pwszSubComponent
  225. cscClient, // cscSubComponent
  226. IS_CLIENT_INSTALL, // InstallFlags
  227. IS_CLIENT_REMOVE, // UninstallFlags
  228. IS_CLIENT_CHANGE, // ChangeFlags
  229. IS_CLIENT_UPGRADE, // UpgradeFlags
  230. IS_CLIENT_ENABLED, // EnabledFlags
  231. SETUP_CLIENT_FLAG, // SetupStatusFlags
  232. TRUE, // fDefaultInstallUnattend
  233. FALSE, // fInstallUnattend
  234. aUnattendParmClient // aUnattendParm
  235. },
  236. {
  237. NULL, // pwszSubComponent
  238. }
  239. };
  240. SUBCOMP *
  241. TranslateSubComponent(
  242. IN WCHAR const *pwszComponent,
  243. OPTIONAL IN WCHAR const *pwszSubComponent)
  244. {
  245. SUBCOMP *psc;
  246. if (NULL == pwszSubComponent)
  247. {
  248. pwszSubComponent = pwszComponent;
  249. }
  250. for (psc = g_aSubComp; NULL != psc->pwszSubComponent; psc++)
  251. {
  252. if (0 == lstrcmpi(psc->pwszSubComponent, pwszSubComponent))
  253. {
  254. break;
  255. }
  256. }
  257. if (NULL == psc->pwszSubComponent)
  258. {
  259. psc = NULL;
  260. }
  261. return(psc);
  262. }
  263. SUBCOMP const *
  264. LookupSubComponent(
  265. IN CertSubComponent SubComp)
  266. {
  267. SUBCOMP const *psc;
  268. for (psc = g_aSubComp; NULL != psc->pwszSubComponent; psc++)
  269. {
  270. if (psc->cscSubComponent == SubComp)
  271. {
  272. break;
  273. }
  274. }
  275. CSASSERT(NULL != psc);
  276. return(psc);
  277. }
  278. BOOL fDebugSupress = TRUE;
  279. HRESULT
  280. UpdateSubComponentInstallStatus(
  281. IN WCHAR const *pwszComponent,
  282. IN WCHAR const *pwszSubComponent,
  283. IN OUT PER_COMPONENT_DATA *pComp)
  284. {
  285. HRESULT hr;
  286. BOOL fWasEnabled;
  287. BOOL fIsEnabled;
  288. DWORD InstallFlags;
  289. SUBCOMP const *psc;
  290. psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
  291. if (NULL == psc)
  292. {
  293. hr = E_INVALIDARG;
  294. _JumpError(hr, error, "Internal error: unsupported component");
  295. }
  296. fWasEnabled = certocmWasEnabled(pComp, psc->cscSubComponent);
  297. fIsEnabled = certocmIsEnabled(pComp, psc->cscSubComponent);
  298. CSILOGDWORD(IDS_LOG_WAS_ENABLED, fWasEnabled);
  299. CSILOGDWORD(IDS_LOG_IS_ENABLED, fIsEnabled);
  300. InstallFlags = psc->InstallFlags | psc->ChangeFlags | psc->EnabledFlags;
  301. if (!fWasEnabled)
  302. {
  303. if (fIsEnabled)
  304. {
  305. // install case
  306. pComp->dwInstallStatus |= InstallFlags;
  307. }
  308. else // !fIsEnabled
  309. {
  310. // this is from check then uncheck, should remove the bit
  311. // turn off both bits
  312. pComp->dwInstallStatus &= ~InstallFlags;
  313. }
  314. }
  315. else // fWasEnabled
  316. {
  317. if (pComp->fPostBase &&
  318. (pComp->Flags & SETUPOP_STANDALONE) )
  319. {
  320. // was installed, invoke from post setup
  321. // this is install case
  322. pComp->dwInstallStatus |= InstallFlags;
  323. }
  324. else if (pComp->Flags & SETUPOP_NTUPGRADE)
  325. {
  326. // if was installed and now in upgrade mode, upgrade case
  327. pComp->dwInstallStatus |= psc->UpgradeFlags | psc->EnabledFlags;
  328. }
  329. else if (!fIsEnabled)
  330. {
  331. // uninstall case
  332. pComp->dwInstallStatus &= ~psc->EnabledFlags;
  333. pComp->dwInstallStatus |= psc->UninstallFlags | psc->ChangeFlags;
  334. }
  335. else // fIsEnabled
  336. {
  337. pComp->dwInstallStatus |= psc->EnabledFlags;
  338. #if DBG_CERTSRV
  339. BOOL fUpgrade = FALSE;
  340. hr = myGetCertRegDWValue(
  341. NULL,
  342. NULL,
  343. NULL,
  344. L"EnforceUpgrade",
  345. (DWORD *) &fUpgrade);
  346. if (S_OK == hr && fUpgrade)
  347. {
  348. pComp->dwInstallStatus |= psc->UpgradeFlags;
  349. }
  350. #endif //DBG_CERTSRV
  351. } // end fIsEnabled else
  352. } // end fWasEnabled else
  353. // after all of this, change upgrade->uninstall if not supported
  354. // detect illegal upgrade
  355. if (pComp->dwInstallStatus & IS_SERVER_UPGRADE)
  356. {
  357. hr = DetermineServerUpgradePath(pComp);
  358. _JumpIfError(hr, error, "DetermineServerUpgradePath");
  359. }
  360. else if (pComp->dwInstallStatus & IS_CLIENT_UPGRADE)
  361. {
  362. hr = DetermineClientUpgradePath(pComp);
  363. _JumpIfError(hr, error, "LoadAndDetermineClientUpgradeInfo");
  364. }
  365. if ((pComp->dwInstallStatus & IS_SERVER_UPGRADE) ||
  366. (pComp->dwInstallStatus & IS_CLIENT_UPGRADE))
  367. {
  368. CSASSERT(pComp->UpgradeFlag != CS_UPGRADE_UNKNOWN);
  369. if (CS_UPGRADE_UNSUPPORTED == pComp->UpgradeFlag)
  370. {
  371. pComp->dwInstallStatus &= ~InstallFlags;
  372. pComp->dwInstallStatus |= psc->UninstallFlags | psc->ChangeFlags;
  373. }
  374. }
  375. CSILOG(
  376. S_OK,
  377. IDS_LOG_INSTALL_STATE,
  378. pwszSubComponent,
  379. NULL,
  380. &pComp->dwInstallStatus);
  381. hr = S_OK;
  382. error:
  383. return hr;
  384. }
  385. HRESULT
  386. certocmOcPreInitialize(
  387. IN WCHAR const *pwszComponent,
  388. IN UINT Flags,
  389. OUT ULONG_PTR *pulpRet)
  390. {
  391. HRESULT hr;
  392. *pulpRet = 0;
  393. DBGPRINT((DBG_SS_CERTOCMI, "OC_PREINITIALIZE(%ws, %x)\n", pwszComponent, Flags));
  394. myVerifyResourceStrings(g_hInstance);
  395. // Return value is flag telling OCM which char width we want to run in.
  396. #ifdef UNICODE
  397. *pulpRet = OCFLAG_UNICODE & Flags;
  398. #else
  399. *pulpRet = OCFLAG_ANSI & Flags;
  400. #endif
  401. hr = S_OK;
  402. //error:
  403. return hr;
  404. }
  405. // Allocate and initialize a new component.
  406. //
  407. // Return code is Win32 error indicating outcome. ERROR_CANCELLED tells OCM to
  408. // cancel the installation.
  409. HRESULT
  410. certocmOcInitComponent(
  411. IN HWND hwnd,
  412. IN WCHAR const *pwszComponent,
  413. IN OUT SETUP_INIT_COMPONENT *pInitComponent,
  414. IN OUT PER_COMPONENT_DATA *pComp,
  415. OUT ULONG_PTR *pulpRet)
  416. {
  417. HRESULT hr;
  418. BOOL fCoInit = FALSE;
  419. HKEY hkey = NULL;
  420. WCHAR awc[30];
  421. WCHAR *pwc;
  422. DBGPRINT((
  423. DBG_SS_CERTOCMI,
  424. "OC_INIT_COMPONENT(%ws, %p)\n",
  425. pwszComponent,
  426. pInitComponent));
  427. hr = CoInitialize(NULL);
  428. if (S_OK != hr && S_FALSE != hr)
  429. {
  430. _JumpError(hr, error, "CoInitialize");
  431. }
  432. fCoInit = TRUE;
  433. *pulpRet = ERROR_CANCELLED;
  434. if (OCMANAGER_VERSION <= pInitComponent->OCManagerVersion)
  435. {
  436. pInitComponent->OCManagerVersion = OCMANAGER_VERSION;
  437. }
  438. // Allocate a new component string.
  439. pComp->pwszComponent = (WCHAR *) LocalAlloc(LPTR,
  440. (wcslen(pwszComponent) + 1) * sizeof(WCHAR));
  441. _JumpIfOutOfMemory(hr, error, pComp->pwszComponent);
  442. wcscpy(pComp->pwszComponent, pwszComponent);
  443. // OCM passes in some information that we want to save, like the open
  444. // handle to our per-component INF. As long as we have a per-component INF,
  445. // append-open any layout file that is associated with it, in preparation
  446. // for later inf-based file queueing operations.
  447. //
  448. // We save away certain other stuff that gets passed to us now, since OCM
  449. // doesn't guarantee that the SETUP_INIT_COMPONENT will persist beyond the
  450. // processing of this one interface routine.
  451. if (INVALID_HANDLE_VALUE != pInitComponent->ComponentInfHandle &&
  452. NULL != pInitComponent->ComponentInfHandle)
  453. {
  454. pComp->MyInfHandle = pInitComponent->ComponentInfHandle;
  455. }
  456. else
  457. {
  458. hr = E_INVALIDARG;
  459. _JumpError(hr, error, "invalid inf handle");
  460. }
  461. if (NULL != pComp->MyInfHandle)
  462. {
  463. if (!SetupOpenAppendInfFile(NULL, pComp->MyInfHandle, NULL))
  464. {
  465. // SetupOpenAppendInfFile:
  466. // If Filename (Param1) is NULL, the INF filename is
  467. // retrieved from the LayoutFile value of the Version
  468. // section in the existing INF file.
  469. //
  470. // If FileName was not specified and there was no
  471. // LayoutFile value in the Version section of the
  472. // existing INF File, GetLastError returns ERROR_INVALID_DATA.
  473. hr = myHLastError();
  474. _PrintErrorStr(hr, "SetupOpenAppendInfFile", pwszComponent);
  475. }
  476. }
  477. pComp->HelperRoutines = pInitComponent->HelperRoutines;
  478. pComp->Flags = pInitComponent->SetupData.OperationFlags;
  479. pwc = awc;
  480. pwc += wsprintf(pwc, L"0x");
  481. if (0 != (DWORD) (pComp->Flags >> 32))
  482. {
  483. pwc += wsprintf(pwc, L"%x:", (DWORD) (pComp->Flags >> 32));
  484. }
  485. wsprintf(pwc, L"%08x", (DWORD) pComp->Flags);
  486. CSILOG(S_OK, IDS_LOG_OPERATIONFLAGS, awc, NULL, NULL);
  487. CSILOGDWORD(IDS_LOG_POSTBASE, pComp->fPostBase);
  488. hr = RegOpenKey(HKEY_LOCAL_MACHINE, wszREGKEYOCMSUBCOMPONENTS, &hkey);
  489. if (S_OK == hr)
  490. {
  491. DWORD dwType;
  492. DWORD dwValue;
  493. DWORD cb;
  494. DWORD const *pdw;
  495. cb = sizeof(dwValue);
  496. hr = RegQueryValueEx(
  497. hkey,
  498. wszSERVERSECTION,
  499. 0,
  500. &dwType,
  501. (BYTE *) &dwValue,
  502. &cb);
  503. pdw = NULL;
  504. if (S_OK == hr && REG_DWORD == dwType && sizeof(dwValue) == cb)
  505. {
  506. pdw = &dwValue;
  507. }
  508. CSILOG(hr, IDS_LOG_REGSTATE, wszSERVERSECTION, NULL, pdw);
  509. cb = sizeof(dwValue);
  510. hr = RegQueryValueEx(
  511. hkey,
  512. wszCLIENTSECTION,
  513. 0,
  514. &dwType,
  515. (BYTE *) &dwValue,
  516. &cb);
  517. pdw = NULL;
  518. if (S_OK == hr && REG_DWORD == dwType && sizeof(dwValue) == cb)
  519. {
  520. pdw = &dwValue;
  521. }
  522. CSILOG(hr, IDS_LOG_REGSTATE, wszCLIENTSECTION, NULL, pdw);
  523. cb = sizeof(dwValue);
  524. hr = RegQueryValueEx(
  525. hkey,
  526. wszOLDDOCCOMPONENT,
  527. 0,
  528. &dwType,
  529. (BYTE *) &dwValue,
  530. &cb);
  531. pdw = NULL;
  532. if (S_OK == hr && REG_DWORD == dwType && sizeof(dwValue) == cb)
  533. {
  534. CSILOG(hr, IDS_LOG_REGSTATE, wszOLDDOCCOMPONENT, NULL, &dwValue);
  535. }
  536. }
  537. pComp->fUnattended = (pComp->Flags & SETUPOP_BATCH)? TRUE : FALSE;
  538. CSILOG(
  539. S_OK,
  540. IDS_LOG_UNATTENDED,
  541. pComp->fUnattended? pInitComponent->SetupData.UnattendFile : NULL,
  542. NULL,
  543. (DWORD const *) &pComp->fUnattended);
  544. if (pComp->fUnattended)
  545. {
  546. pComp->pwszUnattendedFile = (WCHAR *) LocalAlloc(
  547. LMEM_FIXED,
  548. (wcslen(pInitComponent->SetupData.UnattendFile) + 1) *
  549. sizeof(WCHAR));
  550. _JumpIfOutOfMemory(hr, error, pComp->pwszUnattendedFile);
  551. wcscpy(
  552. pComp->pwszUnattendedFile,
  553. pInitComponent->SetupData.UnattendFile);
  554. }
  555. // initialize ca setup data
  556. hr = InitCASetup(hwnd, pComp);
  557. _JumpIfError(hr, error, "InitCASetup");
  558. hr = S_OK;
  559. *pulpRet = NO_ERROR;
  560. error:
  561. if (NULL != hkey)
  562. {
  563. RegCloseKey(hkey);
  564. }
  565. if (fCoInit)
  566. {
  567. CoUninitialize();
  568. }
  569. return(hr);
  570. }
  571. HRESULT
  572. certocmReadInfString(
  573. IN HINF hInf,
  574. OPTIONAL IN WCHAR const *pwszFile,
  575. IN WCHAR const *pwszSection,
  576. IN WCHAR const *pwszName,
  577. IN OUT WCHAR **ppwszValue)
  578. {
  579. INFCONTEXT InfContext;
  580. HRESULT hr;
  581. WCHAR wszBuffer[cwcINFVALUE];
  582. WCHAR *pwsz;
  583. if (NULL != *ppwszValue)
  584. {
  585. // free old
  586. LocalFree(*ppwszValue);
  587. *ppwszValue = NULL;
  588. }
  589. if (!SetupFindFirstLine(hInf, pwszSection, pwszName, &InfContext))
  590. {
  591. hr = myHLastError();
  592. _JumpErrorStr(hr, error, "SetupFindFirstLine", pwszSection);
  593. }
  594. if (!SetupGetStringField(
  595. &InfContext,
  596. 1,
  597. wszBuffer,
  598. sizeof(wszBuffer)/sizeof(wszBuffer[0]),
  599. NULL))
  600. {
  601. hr = myHLastError();
  602. _JumpErrorStr(hr, error, "SetupGetStringField", pwszName);
  603. }
  604. pwsz = (WCHAR *) LocalAlloc(
  605. LMEM_FIXED,
  606. (wcslen(wszBuffer) + 1) * sizeof(WCHAR));
  607. _JumpIfOutOfMemory(hr, error, pwsz);
  608. wcscpy(pwsz, wszBuffer);
  609. *ppwszValue = pwsz;
  610. hr = S_OK;
  611. error:
  612. return(hr);
  613. }
  614. HRESULT
  615. certocmReadInfInteger(
  616. IN HINF hInf,
  617. OPTIONAL IN WCHAR const *pwszFile,
  618. IN WCHAR const *pwszSection,
  619. IN WCHAR const *pwszName,
  620. OUT INT *pValue)
  621. {
  622. INFCONTEXT InfContext;
  623. HRESULT hr = S_OK;
  624. WCHAR wszBuffer[cwcINFVALUE];
  625. *pValue = 0;
  626. if (!SetupFindFirstLine(hInf, pwszSection, pwszName, &InfContext))
  627. {
  628. hr = myHLastError();
  629. DBGPRINT((
  630. DBG_SS_CERTOCMI,
  631. __FILE__ "(%u): %ws%wsSetupFindFirstLine([%ws] %ws) failed! -> %x\n",
  632. __LINE__,
  633. NULL != pwszFile? pwszFile : L"",
  634. NULL != pwszFile? L": " : L"",
  635. pwszSection,
  636. pwszName,
  637. hr));
  638. goto error;
  639. }
  640. if (!SetupGetIntField(&InfContext, 1, pValue))
  641. {
  642. hr = myHLastError();
  643. DBGPRINT((
  644. DBG_SS_CERTOCM,
  645. __FILE__ "(%u): %ws%wsSetupGetIntField([%ws] %ws) failed! -> %x\n",
  646. __LINE__,
  647. NULL != pwszFile? pwszFile : L"",
  648. NULL != pwszFile? L": " : L"",
  649. pwszSection,
  650. pwszName,
  651. hr));
  652. goto error;
  653. }
  654. DBGPRINT((
  655. DBG_SS_CERTOCMI,
  656. "%ws%ws[%ws] %ws = %u\n",
  657. NULL != pwszFile? pwszFile : L"",
  658. NULL != pwszFile? L": " : L"",
  659. pwszSection,
  660. pwszName,
  661. *pValue));
  662. error:
  663. return(hr);
  664. }
  665. // Return the GDI handle of a small bitmap to be used. NULL means an error
  666. // occurred -- OCM will use a default bitmap.
  667. //
  668. // Demonstrates use of private data in a per-component inf. We will look in
  669. // our per-component inf to determine the resource name for the bitmap for this
  670. // component, and then go fetch it from the resources.
  671. //
  672. // Other possibilities would be to simply return the same hbitmap for all
  673. // cases, or to return NULL, in which case OCM uses a default. Note that we
  674. // ignore the requested width and height and our bitmaps are not language
  675. // dependent.
  676. HRESULT
  677. certocmOcQueryImage(
  678. IN WCHAR const *pwszComponent,
  679. OPTIONAL IN WCHAR const *pwszSubComponent,
  680. IN SubComponentInfo wSubComp,
  681. IN WORD wWidth,
  682. IN WORD wHeight,
  683. IN OUT PER_COMPONENT_DATA *pComp,
  684. OUT ULONG_PTR *pulpRet)
  685. {
  686. HANDLE hRet = NULL;
  687. HRESULT hr;
  688. DBGPRINT((
  689. DBG_SS_CERTOCMI,
  690. "OC_QUERY_IMAGE(%ws, %ws, %hx, %hx, %hx)\n",
  691. pwszComponent,
  692. pwszSubComponent,
  693. wSubComp,
  694. wWidth,
  695. wHeight));
  696. if (SubCompInfoSmallIcon != wSubComp)
  697. {
  698. goto done;
  699. }
  700. hRet = (HANDLE) LoadBitmap(pComp->hInstance, MAKEINTRESOURCE(IDB_APP));
  701. if (NULL == hRet)
  702. {
  703. hr = myHLastError();
  704. _JumpError(hr, error, "LoadBitmap");
  705. }
  706. done:
  707. hr = S_OK;
  708. error:
  709. *pulpRet = (ULONG_PTR) hRet;
  710. return hr;
  711. }
  712. // Return the number of wizard pages the current component places in the
  713. // SETUP_REQUEST_PAGES structure.
  714. HRESULT
  715. certocmOcRequestPages(
  716. IN WCHAR const *pwszComponent,
  717. IN WizardPagesType WizPagesType,
  718. IN OUT SETUP_REQUEST_PAGES *pRequestPages,
  719. IN PER_COMPONENT_DATA *pComp,
  720. OUT ULONG_PTR *pulpRet)
  721. {
  722. HRESULT hr;
  723. *pulpRet = 0;
  724. DBGPRINT((
  725. DBG_SS_CERTOCMI,
  726. "OC_REQUEST_PAGES(%ws, %x, %p)\n",
  727. pwszComponent,
  728. WizPagesType,
  729. pRequestPages));
  730. // don't invoke wiz apge if unattended
  731. // or if running from base setup/upgrade setup
  732. if ((!pComp->fUnattended) && (SETUPOP_STANDALONE & pComp->Flags))
  733. {
  734. *pulpRet = myDoPageRequest(pComp,
  735. WizPagesType, pRequestPages);
  736. }
  737. else
  738. {
  739. DBGPRINT((
  740. DBG_SS_CERTOCMI,
  741. "Not adding wizard pages, %ws\n",
  742. pComp->fUnattended? L"Unattended" : L"GUI Setup"));
  743. }
  744. hr = S_OK;
  745. //error:
  746. return hr;
  747. }
  748. HRESULT
  749. IsIA5DnsMachineName()
  750. {
  751. WCHAR *pwszDnsName = NULL;
  752. CRL_DIST_POINTS_INFO CRLDistInfo;
  753. CRL_DIST_POINT DistPoint;
  754. CERT_ALT_NAME_ENTRY AltNameEntry;
  755. BYTE *pbEncoded = NULL;
  756. DWORD cbEncoded;
  757. static HRESULT s_hr = S_FALSE;
  758. if (S_FALSE != s_hr)
  759. {
  760. goto error;
  761. }
  762. s_hr = myGetMachineDnsName(&pwszDnsName);
  763. _JumpIfError(s_hr, error, "myGetMachineDnsName");
  764. CRLDistInfo.cDistPoint = 1;
  765. CRLDistInfo.rgDistPoint = &DistPoint;
  766. ZeroMemory(&DistPoint, sizeof(DistPoint));
  767. DistPoint.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
  768. DistPoint.DistPointName.FullName.cAltEntry = 1;
  769. DistPoint.DistPointName.FullName.rgAltEntry = &AltNameEntry;
  770. ZeroMemory(&AltNameEntry, sizeof(AltNameEntry));
  771. AltNameEntry.dwAltNameChoice = CERT_ALT_NAME_URL;
  772. AltNameEntry.pwszURL = pwszDnsName;
  773. if (!myEncodeObject(
  774. X509_ASN_ENCODING,
  775. X509_CRL_DIST_POINTS,
  776. &CRLDistInfo,
  777. 0,
  778. CERTLIB_USE_LOCALALLOC,
  779. &pbEncoded,
  780. &cbEncoded))
  781. {
  782. s_hr = myHLastError();
  783. _JumpIfError(s_hr, error, "myEncodeObject");
  784. }
  785. CSASSERT(S_OK == s_hr);
  786. error:
  787. if (NULL != pwszDnsName)
  788. {
  789. LocalFree(pwszDnsName);
  790. }
  791. if (NULL != pbEncoded)
  792. {
  793. LocalFree(pbEncoded);
  794. }
  795. return(s_hr);
  796. }
  797. // Return boolean to indicate whether to allow selection state change. As
  798. // demonstrated, again we'll go out to our per-component inf to see whether it
  799. // wants us to validate. Note that unattended mode must be respected.
  800. HRESULT
  801. certocmOcQueryChangeSelState(
  802. HWND hwnd,
  803. IN WCHAR const *pwszComponent,
  804. OPTIONAL IN WCHAR const *pwszSubComponent,
  805. IN BOOL fSelectedNew,
  806. IN DWORD Flags,
  807. IN OUT PER_COMPONENT_DATA *pComp,
  808. OUT ULONG_PTR *pulpRet)
  809. {
  810. INT fVerify;
  811. TCHAR wszText[cwcMESSAGETEXT];
  812. const WCHAR* Args[2];
  813. SUBCOMP const *psc;
  814. HRESULT hr;
  815. WCHAR awc[20];
  816. WCHAR awc2[20];
  817. DWORD fRet;
  818. BOOL fServerWasInstalled;
  819. BOOL fWebClientWasInstalled;
  820. BOOL fDisallow = FALSE;
  821. int iMsg;
  822. static BOOL s_fWarned = FALSE;
  823. *pulpRet = FALSE;
  824. DBGPRINT((
  825. DBG_SS_CERTOCMI,
  826. "OC_QUERY_CHANGE_SEL_STATE(%ws, %ws, %x, %x)\n",
  827. pwszComponent,
  828. pwszSubComponent,
  829. fSelectedNew,
  830. Flags));
  831. // disallow some selection changes
  832. fServerWasInstalled = certocmWasEnabled(pComp, cscServer);
  833. fWebClientWasInstalled = certocmWasEnabled(pComp, cscClient);
  834. if (fWebClientWasInstalled &&
  835. (OCQ_ACTUAL_SELECTION & Flags))
  836. {
  837. if (fSelectedNew)
  838. {
  839. // check
  840. if (!fServerWasInstalled &&
  841. (0 == lstrcmpi(wszSERVERSECTION, pwszSubComponent) ||
  842. 0 == lstrcmpi(wszCERTSRVSECTION, pwszSubComponent)) )
  843. {
  844. // case: web client installed and try install server
  845. fDisallow = TRUE;
  846. iMsg = IDS_WRN_UNINSTALL_CLIENT;
  847. }
  848. if (fServerWasInstalled &&
  849. 0 == lstrcmpi(wszCLIENTSECTION, pwszSubComponent))
  850. {
  851. // case: uncheck both then check web client
  852. fDisallow = TRUE;
  853. iMsg = IDS_WRN_UNINSTALL_BOTH;
  854. }
  855. }
  856. else
  857. {
  858. // uncheck
  859. if (fServerWasInstalled &&
  860. 0 == lstrcmpi(wszSERVERSECTION, pwszSubComponent))
  861. {
  862. // case: full certsrv installed and try leave only web client
  863. fDisallow = TRUE;
  864. iMsg = IDS_WRN_UNINSTALL_BOTH;
  865. }
  866. }
  867. }
  868. // not a server sku
  869. if (!FIsServer())
  870. {
  871. fDisallow = TRUE;
  872. iMsg = IDS_WRN_SERVER_ONLY;
  873. }
  874. if (fDisallow)
  875. {
  876. CertWarningMessageBox(
  877. pComp->hInstance,
  878. pComp->fUnattended,
  879. hwnd,
  880. iMsg,
  881. 0,
  882. NULL);
  883. goto done;
  884. }
  885. if (fSelectedNew)
  886. {
  887. hr = IsIA5DnsMachineName();
  888. if (S_OK != hr)
  889. {
  890. CertMessageBox(
  891. pComp->hInstance,
  892. pComp->fUnattended,
  893. hwnd,
  894. IDS_ERR_NONIA5DNSNAME,
  895. hr,
  896. MB_OK | MB_ICONERROR,
  897. NULL);
  898. goto done;
  899. }
  900. if ((OCQ_ACTUAL_SELECTION & Flags) &&
  901. 0 != lstrcmpi(wszCLIENTSECTION, pwszSubComponent))
  902. {
  903. if (!s_fWarned)
  904. {
  905. DWORD dwSetupStatus;
  906. hr = GetSetupStatus(NULL, &dwSetupStatus);
  907. if (S_OK == hr)
  908. {
  909. if ((SETUP_CLIENT_FLAG | SETUP_SERVER_FLAG) & dwSetupStatus)
  910. {
  911. s_fWarned = TRUE;
  912. }
  913. CSILOG(
  914. hr,
  915. IDS_LOG_QUERYCHANGESELSTATE,
  916. NULL,
  917. NULL,
  918. &dwSetupStatus);
  919. }
  920. }
  921. if (!s_fWarned)
  922. {
  923. if (IDYES != CertMessageBox(
  924. pComp->hInstance,
  925. pComp->fUnattended,
  926. hwnd,
  927. IDS_WRN_NONAMECHANGE,
  928. S_OK,
  929. MB_YESNO | MB_ICONWARNING | CMB_NOERRFROMSYS,
  930. NULL))
  931. {
  932. goto done;
  933. }
  934. s_fWarned = TRUE;
  935. }
  936. }
  937. }
  938. *pulpRet = TRUE;
  939. if (pComp->fUnattended)
  940. {
  941. goto done;
  942. }
  943. psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
  944. if (NULL == psc)
  945. {
  946. hr = E_INVALIDARG;
  947. _JumpError(hr, error, "Internal error: unsupported component");
  948. }
  949. hr = certocmReadInfInteger(
  950. pComp->MyInfHandle,
  951. NULL,
  952. psc->pwszSubComponent,
  953. fSelectedNew? wszVERIFYSELECT : wszVERIFYDESELECT,
  954. &fVerify);
  955. if (S_OK != hr || !fVerify)
  956. {
  957. goto done;
  958. }
  959. // Don't pass specific lang id to FormatMessage, as it fails if there's no
  960. // msg in that language. Instead, set the thread locale, which will get
  961. // FormatMessage to use a search algorithm to find a message of the
  962. // appropriate language, or use a reasonable fallback msg if there's none.
  963. Args[0] = pwszComponent;
  964. Args[1] = pwszSubComponent;
  965. FormatMessage(
  966. FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  967. pComp->hInstance,
  968. fSelectedNew? MSG_SURE_SELECT : MSG_SURE_DESELECT,
  969. 0,
  970. wszText,
  971. sizeof(wszText)/sizeof(wszText[0]),
  972. (va_list *) Args);
  973. *pulpRet = (IDYES == CertMessageBox(
  974. pComp->hInstance,
  975. pComp->fUnattended,
  976. hwnd,
  977. 0,
  978. S_OK,
  979. MB_YESNO |
  980. MB_ICONWARNING |
  981. MB_TASKMODAL |
  982. CMB_NOERRFROMSYS,
  983. wszText));
  984. done:
  985. hr = S_OK;
  986. error:
  987. wsprintf(awc, L"%u", fSelectedNew);
  988. wsprintf(awc2, L"0x%08x", Flags);
  989. fRet = (DWORD) *pulpRet;
  990. CSILOG(hr, IDS_LOG_QUERYCHANGESELSTATE, awc, awc2, &fRet);
  991. return hr;
  992. }
  993. // Calculate disk space for the component being added or removed. Return a
  994. // Win32 error code indicating outcome. In our case the private section for
  995. // this component/subcomponent pair is a simple standard inf install section,
  996. // so we can use high-level disk space list API to do what we want.
  997. HRESULT
  998. certocmOcCalcDiskSpace(
  999. IN WCHAR const *pwszComponent,
  1000. OPTIONAL IN WCHAR const *pwszSubComponent,
  1001. IN BOOL fAddComponent,
  1002. IN HDSKSPC hDiskSpace,
  1003. IN OUT PER_COMPONENT_DATA *pComp,
  1004. OUT ULONG_PTR *pulpRet)
  1005. {
  1006. HRESULT hr;
  1007. WCHAR *pwsz = NULL;
  1008. SUBCOMP const *psc;
  1009. static fServerFirstCall = TRUE;
  1010. static fClientFirstCall = TRUE;
  1011. DBGPRINT((
  1012. DBG_SS_CERTOCMI,
  1013. "OC_CALC_DISK_SPACE(%ws, %ws, %x, %p)\n",
  1014. pwszComponent,
  1015. pwszSubComponent,
  1016. fAddComponent,
  1017. hDiskSpace));
  1018. psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
  1019. if (NULL == psc)
  1020. {
  1021. hr = E_INVALIDARG;
  1022. _JumpError(hr, error, "Internal error: unsupported component");
  1023. }
  1024. // Being installed or uninstalled. Fetch INSTALL section name,
  1025. // so we can add or remove the files being INSTALLed from the disk
  1026. // space list.
  1027. hr = certocmReadInfString(
  1028. pComp->MyInfHandle,
  1029. NULL,
  1030. psc->pwszSubComponent,
  1031. wszINSTALL,
  1032. &pwsz);
  1033. _JumpIfError(hr, error, "certocmReadInfString");
  1034. if (fAddComponent) // Adding
  1035. {
  1036. if (!SetupAddInstallSectionToDiskSpaceList(
  1037. hDiskSpace,
  1038. pComp->MyInfHandle,
  1039. NULL,
  1040. pwsz,
  1041. 0,
  1042. 0))
  1043. {
  1044. hr = myHLastError();
  1045. _JumpErrorStr(hr, error, "SetupAddInstallSectionToDiskSpaceList", pwsz);
  1046. }
  1047. }
  1048. else // Removing
  1049. {
  1050. if (!SetupRemoveInstallSectionFromDiskSpaceList(
  1051. hDiskSpace,
  1052. pComp->MyInfHandle,
  1053. NULL,
  1054. pwsz,
  1055. 0,
  1056. 0))
  1057. {
  1058. hr = myHLastError();
  1059. _JumpErrorStr(hr, error, "SetupRemoveInstallSectionFromDiskSpaceList", pwsz);
  1060. }
  1061. }
  1062. hr = S_OK;
  1063. error:
  1064. if (NULL != pwsz)
  1065. {
  1066. LocalFree(pwsz);
  1067. }
  1068. *pulpRet = hr;
  1069. return(hr);
  1070. }
  1071. // OCM calls this routine when ready for files to be copied to effect the
  1072. // changes the user requested. The component DLL must figure out whether it is
  1073. // being installed or uninstalled and take appropriate action. For this
  1074. // sample, we look in the private data section for this component/subcomponent
  1075. // pair, and get the name of an uninstall section for the uninstall case.
  1076. //
  1077. // Note that OCM calls us once for the *entire* component and then once per
  1078. // subcomponent. We ignore the first call.
  1079. //
  1080. // Return value is Win32 error code indicating outcome.
  1081. HRESULT
  1082. certocmOcQueueFileOps(
  1083. IN HWND hwnd,
  1084. IN WCHAR const *pwszComponent,
  1085. OPTIONAL IN WCHAR const *pwszSubComponent,
  1086. IN HSPFILEQ hFileQueue,
  1087. IN OUT PER_COMPONENT_DATA *pComp,
  1088. OUT ULONG_PTR *pulpRet)
  1089. {
  1090. HRESULT hr;
  1091. SUBCOMP const *psc;
  1092. BOOL fRemoveFile = FALSE; // TRUE for uninstall; FALSE for install/upgrade
  1093. WCHAR *pwszAction;
  1094. WCHAR *pwsz = NULL;
  1095. static BOOL s_fPreUninstall = FALSE; // preuninstall once
  1096. DBGPRINT((
  1097. DBG_SS_CERTOCMI,
  1098. "OC_QUEUE_FILE_OPS(%ws, %ws, %p)\n",
  1099. pwszComponent,
  1100. pwszSubComponent,
  1101. hFileQueue));
  1102. if (NULL == pwszSubComponent)
  1103. {
  1104. // Do no work for top level component
  1105. goto done;
  1106. }
  1107. psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
  1108. if (NULL == psc)
  1109. {
  1110. hr = E_INVALIDARG;
  1111. _JumpError(hr, error, "Internal error: unsupported component");
  1112. }
  1113. // if unattended, not upgrade, & not uninstall, load
  1114. if (pComp->fUnattended && !(pComp->Flags & SETUPOP_NTUPGRADE) )
  1115. {
  1116. // retrieve unattended attributes
  1117. hr = certocmRetrieveUnattendedText(
  1118. pwszComponent,
  1119. pwszSubComponent,
  1120. pComp);
  1121. if (S_OK != hr && 0x0 != (pComp->Flags & SETUPOP_STANDALONE))
  1122. {
  1123. // only error out if it is from add/remove or post because
  1124. // it could fail regular ntbase in unattended mode without certsrv
  1125. _JumpError(hr, error, "certocmRetrieveUnattendedText");
  1126. }
  1127. // Init install status (must be done after retrieving unattended text)
  1128. hr = UpdateSubComponentInstallStatus(pwszComponent,
  1129. pwszSubComponent,
  1130. pComp);
  1131. _JumpIfError(hr, error, "UpdateSubComponentInstallStatus");
  1132. if (psc->fInstallUnattend) // make sure ON
  1133. {
  1134. if (certocmWasEnabled(pComp, psc->cscSubComponent) &&
  1135. !pComp->fPostBase)
  1136. {
  1137. // the case to run install with component ON twice or more
  1138. hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
  1139. _JumpError(hr, error, "You must uninstall before install");
  1140. }
  1141. if (SETUPOP_STANDALONE & pComp->Flags)
  1142. {
  1143. // only prepare and validate unattende attr in standalone mode
  1144. // in other word, don't call following if NT base
  1145. hr = PrepareUnattendedAttributes(
  1146. hwnd,
  1147. pwszComponent,
  1148. pwszSubComponent,
  1149. pComp);
  1150. _JumpIfError(hr, error, "PrepareUnattendedAttributes");
  1151. }
  1152. }
  1153. }
  1154. else
  1155. {
  1156. // Initialize the install status
  1157. hr = UpdateSubComponentInstallStatus(pwszComponent,
  1158. pwszSubComponent,
  1159. pComp);
  1160. _JumpIfError(hr, error, "UpdateSubComponentInstallStatus");
  1161. }
  1162. // If we're not doing base setup or an upgrade, check to see if we already
  1163. // copied files during base setup, by checking to see if base setup
  1164. // left an entry in the ToDo List.
  1165. if(pComp->fPostBase)
  1166. {
  1167. DBGPRINT((
  1168. DBG_SS_CERTOCMI,
  1169. "File Queueing Skipped, files already installed by GUI setup"));
  1170. goto done;
  1171. }
  1172. /*
  1173. //--- Talk with OCM guys and put this functionality into a notification routine
  1174. //--- This will allow us to pop compatibility error to user before unattended upgrade begins
  1175. // detect illegal upgrade
  1176. if (pComp->dwInstallStatus & IS_SERVER_UPGRADE)
  1177. {
  1178. hr = DetermineServerUpgradePath(pComp);
  1179. _JumpIfError(hr, error, "DetermineServerUpgradePath");
  1180. }
  1181. else if (pComp->dwInstallStatus & IS_CLIENT_UPGRADE)
  1182. {
  1183. hr = DetermineClientUpgradePath(pComp);
  1184. _JumpIfError(hr, error, "LoadAndDetermineClientUpgradeInfo");
  1185. }
  1186. if ((pComp->dwInstallStatus & IS_SERVER_UPGRADE) ||
  1187. (pComp->dwInstallStatus & IS_CLIENT_UPGRADE))
  1188. {
  1189. // block if attempting upgrade that is not Win2K or Whistler
  1190. // lodge a complaint in the log; upgrade all bits and
  1191. if ((CS_UPGRADE_NO != pComp->UpgradeFlag) &&
  1192. (CS_UPGRADE_WHISTLER != pComp->UpgradeFlag) &&
  1193. (CS_UPGRADE_WIN2000 != pComp->UpgradeFlag))
  1194. {
  1195. hr = HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION);
  1196. CertErrorMessageBox(
  1197. pComp->hInstance,
  1198. pComp->fUnattended,
  1199. hwnd,
  1200. IDS_ERR_UPGRADE_NOT_SUPPORTED,
  1201. hr,
  1202. NULL);
  1203. // _JumpError(hr, error, "Unsupported upgrade");
  1204. // continue uninstall/reinstall
  1205. }
  1206. }
  1207. */
  1208. if ((pComp->dwInstallStatus & psc->ChangeFlags) ||
  1209. (pComp->dwInstallStatus & psc->UpgradeFlags) )
  1210. {
  1211. // for ChangeFlags, either install or uninstall
  1212. // all cases, copy file or remove file
  1213. if (pComp->dwInstallStatus & psc->UninstallFlags)
  1214. {
  1215. fRemoveFile = TRUE;
  1216. }
  1217. // Uninstall the core if:
  1218. // this subcomponent is being uninstalled, and
  1219. // this is a core subcomponent (client or server), and
  1220. // this is the server subcomponent, or the server isn't being removed or
  1221. // upgrade
  1222. if (((pComp->dwInstallStatus & psc->UninstallFlags) ||
  1223. (pComp->dwInstallStatus & psc->UpgradeFlags) ) &&
  1224. (cscServer == psc->cscSubComponent ||
  1225. !(IS_SERVER_REMOVE & pComp->dwInstallStatus) ) )
  1226. {
  1227. // if fall into here, either need to overwrite or
  1228. // delete certsrv files so unreg all related dlls
  1229. if (cscServer == psc->cscSubComponent &&
  1230. (pComp->dwInstallStatus & psc->UpgradeFlags) )
  1231. {
  1232. // if this is server upgrade, determine upgrade path
  1233. hr = DetermineServerUpgradePath(pComp);
  1234. _JumpIfError(hr, error, "DetermineServerUpgradePath");
  1235. // determine custom policy module
  1236. hr = DetermineServerCustomModule(
  1237. pComp,
  1238. TRUE); // policy
  1239. _JumpIfError(hr, error, "DetermineServerCustomModule");
  1240. // determine custom exit module
  1241. hr = DetermineServerCustomModule(
  1242. pComp,
  1243. FALSE); // exit
  1244. _JumpIfError(hr, error, "DetermineServerCustomModule");
  1245. }
  1246. if (!s_fPreUninstall)
  1247. {
  1248. hr = PreUninstallCore(
  1249. hwnd,
  1250. pComp,
  1251. certocmPreserving(pComp, cscClient));
  1252. _JumpIfError(hr, error, "PreUninstallCore");
  1253. s_fPreUninstall = TRUE;
  1254. }
  1255. }
  1256. if ((pComp->dwInstallStatus & psc->ChangeFlags) ||
  1257. (pComp->dwInstallStatus & psc->UpgradeFlags) )
  1258. {
  1259. // Being installed or uninstalled.
  1260. // Fetch [un]install/upgrade section name.
  1261. if (pComp->dwInstallStatus & psc->InstallFlags)
  1262. {
  1263. pwszAction = wszINSTALL;
  1264. }
  1265. else if (pComp->dwInstallStatus & psc->UninstallFlags)
  1266. {
  1267. pwszAction = wszUNINSTALL;
  1268. }
  1269. else if (pComp->dwInstallStatus & psc->UpgradeFlags)
  1270. {
  1271. pwszAction = wszUPGRADE;
  1272. }
  1273. else
  1274. {
  1275. hr = E_INVALIDARG;
  1276. _JumpError(hr, error, "Internal error");
  1277. }
  1278. hr = certocmReadInfString(
  1279. pComp->MyInfHandle,
  1280. NULL,
  1281. psc->pwszSubComponent,
  1282. pwszAction,
  1283. &pwsz);
  1284. _JumpIfError(hr, error, "certocmReadInfString");
  1285. // If uninstalling, copy files without version checks.
  1286. if (!SetupInstallFilesFromInfSection(
  1287. pComp->MyInfHandle,
  1288. NULL,
  1289. hFileQueue,
  1290. pwsz,
  1291. NULL,
  1292. fRemoveFile? 0 : SP_COPY_NEWER))
  1293. {
  1294. hr = myHLastError();
  1295. _JumpIfError(hr, error, "SetupInstallFilesFromInfSection");
  1296. }
  1297. }
  1298. }
  1299. done:
  1300. hr = S_OK;
  1301. error:
  1302. if (NULL != pwsz)
  1303. {
  1304. LocalFree(pwsz);
  1305. }
  1306. if (S_OK != hr)
  1307. {
  1308. SetLastError(hr);
  1309. }
  1310. *pulpRet = hr;
  1311. return(hr);
  1312. }
  1313. // OCM calls this routine when it wants to find out how much work the component
  1314. // wants to perform for nonfile operations to install/uninstall a component or
  1315. // subcomponent. It is called once for the *entire* component and then once
  1316. // for each subcomponent in the component. One could get arbitrarily fancy
  1317. // here but we simply return 1 step per subcomponent. We ignore the "entire
  1318. // component" case.
  1319. //
  1320. // Return value is an arbitrary 'step' count or -1 if error.
  1321. HRESULT
  1322. certocmOcQueryStepCount(
  1323. IN WCHAR const *pwszComponent,
  1324. OPTIONAL IN WCHAR const *pwszSubComponent,
  1325. OUT ULONG_PTR *pulpRet)
  1326. {
  1327. HRESULT hr;
  1328. *pulpRet = 0;
  1329. DBGPRINT((
  1330. DBG_SS_CERTOCMI,
  1331. "OC_QUERY_STEP_COUNT(%ws, %ws)\n",
  1332. pwszComponent,
  1333. pwszSubComponent));
  1334. // Ignore all but "entire component" case.
  1335. if (NULL != pwszSubComponent)
  1336. {
  1337. goto done;
  1338. }
  1339. *pulpRet = SERVERINSTALLTICKS;
  1340. done:
  1341. hr = S_OK;
  1342. //error:
  1343. return hr;
  1344. }
  1345. // OCM calls this routine when it wants the component dll to perform nonfile
  1346. // ops to install/uninstall a component/subcomponent. It is called once for
  1347. // the *entire* component and then once for each subcomponent in the component.
  1348. // Our install and uninstall actions are based on simple standard inf install
  1349. // sections. We ignore the "entire component" case. Note how similar this
  1350. // code is to the OC_QUEUE_FILE_OPS case.
  1351. HRESULT
  1352. certocmOcCompleteInstallation(
  1353. HWND hwnd,
  1354. IN WCHAR const *pwszComponent,
  1355. OPTIONAL IN WCHAR const *pwszSubComponent,
  1356. IN OUT PER_COMPONENT_DATA *pComp,
  1357. OUT ULONG_PTR *pulpRet)
  1358. {
  1359. HRESULT hr;
  1360. TCHAR wszBuffer[cwcINFVALUE];
  1361. SUBCOMP const *psc;
  1362. WCHAR *pwsz = NULL;
  1363. DWORD dwSetupStatusFlags;
  1364. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  1365. WCHAR *pwszActiveCA = NULL;
  1366. static BOOL fStoppedW3SVC = FALSE;
  1367. *pulpRet = 0;
  1368. DBGPRINT((
  1369. DBG_SS_CERTOCMI,
  1370. "OC_COMPLETE_INSTALLATION(%ws, %ws)\n",
  1371. pwszComponent,
  1372. pwszSubComponent));
  1373. // Do no work for top level component
  1374. if (NULL == pwszSubComponent)
  1375. {
  1376. goto done;
  1377. }
  1378. psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
  1379. if (NULL == psc)
  1380. {
  1381. hr = E_INVALIDARG;
  1382. _JumpError(hr, error, "Internal error: unsupported component");
  1383. }
  1384. if (pComp->dwInstallStatus & IS_SERVER_REMOVE)
  1385. {
  1386. // for uninstall, check if active ca use DS
  1387. hr = myGetCertRegStrValue(NULL, NULL, NULL,
  1388. wszREGACTIVE, &pwszActiveCA);
  1389. if (S_OK == hr && NULL != pwszActiveCA)
  1390. {
  1391. hr = myGetCertRegDWValue(pwszActiveCA, NULL, NULL,
  1392. wszREGCAUSEDS, (DWORD*)&pServer->fUseDS);
  1393. _PrintIfError(hr, "myGetCertRegDWValue");
  1394. }
  1395. }
  1396. DBGPRINT((
  1397. DBG_SS_CERTOCMI,
  1398. "certocmOcCompleteInstallation: pComp->dwInstallStatus: %lx, pComp->Flags: %lx\n",
  1399. pComp->dwInstallStatus,
  1400. pComp->Flags));
  1401. if ((pComp->dwInstallStatus & psc->ChangeFlags) ||
  1402. (pComp->dwInstallStatus & psc->UpgradeFlags) )
  1403. {
  1404. // for unattended, make sure w3svc is stopped before file copy
  1405. if (!fStoppedW3SVC &&
  1406. pComp->fUnattended &&
  1407. !(pComp->Flags & SETUPOP_NTUPGRADE) &&
  1408. !(pComp->dwInstallStatus & psc->UninstallFlags) )
  1409. {
  1410. //fStoppedW3SVC makes stop only once
  1411. //don't do this in upgrade
  1412. // this happens for unattended
  1413. // also not during uninstall
  1414. hr = StartAndStopService(pComp->hInstance,
  1415. pComp->fUnattended,
  1416. hwnd,
  1417. wszW3SVCNAME,
  1418. TRUE,
  1419. FALSE,
  1420. 0, // doesn't matter since no confirmation
  1421. &g_fW3SvcRunning);
  1422. _PrintIfError(hr, "StartAndStopService");
  1423. fStoppedW3SVC = TRUE;
  1424. }
  1425. // certsrv file copy
  1426. if (!SetupInstallFromInfSection(
  1427. NULL,
  1428. pComp->MyInfHandle,
  1429. wszBuffer,
  1430. SPINST_INIFILES | SPINST_REGISTRY,
  1431. NULL,
  1432. NULL,
  1433. 0,
  1434. NULL,
  1435. NULL,
  1436. NULL,
  1437. NULL))
  1438. {
  1439. hr = myHLastError();
  1440. _JumpError(hr, error, "SetupInstallFromInfSection");
  1441. }
  1442. // Finish uninstalling the core if:
  1443. // this subcomponent is being uninstalled, and
  1444. // this is a core subcomponent (client or server), and
  1445. // this is the server subcomponent, or the server isn't being removed.
  1446. if ( (pComp->dwInstallStatus & psc->UninstallFlags) &&
  1447. (cscServer == psc->cscSubComponent ||
  1448. !(IS_SERVER_REMOVE & pComp->dwInstallStatus) ) )
  1449. {
  1450. // Do uninstall work
  1451. hr = UninstallCore(
  1452. hwnd,
  1453. pComp,
  1454. 0,
  1455. 100,
  1456. certocmPreserving(pComp, cscClient),
  1457. TRUE,
  1458. FALSE);
  1459. _JumpIfError(hr, error, "UninstallCore");
  1460. if (certocmPreserving(pComp, cscClient))
  1461. {
  1462. hr = SetSetupStatus(NULL, SETUP_CLIENT_FLAG, TRUE);
  1463. _JumpIfError(hr, error, "SetSetupStatus");
  1464. }
  1465. else
  1466. {
  1467. // unmark all
  1468. hr = SetSetupStatus(NULL, 0xFFFFFFFF, FALSE);
  1469. _JumpIfError(hr, error, "SetSetupStatus");
  1470. }
  1471. }
  1472. // Finish installing the core if:
  1473. // this subcomponent is being installed, and
  1474. // this is a core subcomponent (client or server), and
  1475. // this is the server subcomponent, or the server isn't being installed.
  1476. // and this is not base setup (we'll do it later if it is)
  1477. else
  1478. if ((pComp->dwInstallStatus & psc->InstallFlags) &&
  1479. (cscServer == psc->cscSubComponent ||
  1480. !(IS_SERVER_INSTALL & pComp->dwInstallStatus)) &&
  1481. (0 != (pComp->Flags & SETUPOP_STANDALONE)))
  1482. {
  1483. DBGPRINT((
  1484. DBG_SS_CERTOCMI,
  1485. "Performing standalone server installation\n"));
  1486. hr = InstallCore(hwnd, pComp, cscServer == psc->cscSubComponent);
  1487. _JumpIfError(hr, error, "InstallCore");
  1488. // last enough to mark complete
  1489. if (pComp->dwInstallStatus & IS_SERVER_INSTALL)
  1490. {
  1491. // machine
  1492. hr = SetSetupStatus(NULL, SETUP_SERVER_FLAG, TRUE);
  1493. _JumpIfError(hr, error, "SetSetupStatus");
  1494. // ca
  1495. hr = SetSetupStatus(
  1496. pServer->pwszSanitizedName,
  1497. SETUP_SERVER_FLAG,
  1498. TRUE);
  1499. _JumpIfError(hr, error, "SetSetupStatus");
  1500. if(IsEnterpriseCA(pServer->CAType))
  1501. {
  1502. hr = SetSetupStatus(
  1503. pServer->pwszSanitizedName,
  1504. SETUP_UPDATE_CAOBJECT_SVRTYPE,
  1505. TRUE);
  1506. _JumpIfError(hr, error, "SetSetupStatus SETUP_UPDATE_CAOBJECT_SVRTYPE");
  1507. }
  1508. hr = GetSetupStatus(pServer->pwszSanitizedName, &dwSetupStatusFlags);
  1509. _JumpIfError(hr, error, "SetSetupStatus");
  1510. // Only start the server if:
  1511. // 1: we're not waiting for the CA cert to be issued, and
  1512. // 2: this is not base setup -- SETUP_STANDALONE means we're
  1513. // running from the Control Panel or were manually invoked.
  1514. // The server will not start during base setup due to an
  1515. // access denied error from JetInit during base setup.
  1516. if (0 == (SETUP_SUSPEND_FLAG & dwSetupStatusFlags) &&
  1517. (0 != (SETUPOP_STANDALONE & pComp->Flags)))
  1518. {
  1519. hr = StartCertsrvService(FALSE);
  1520. _PrintIfError(hr, "failed in starting cert server service");
  1521. }
  1522. // during base setup: f=0 sus=8
  1523. DBGPRINT((
  1524. DBG_SS_CERTOCMI,
  1525. "InstallCore: f=%x sus=%x\n",
  1526. pComp->Flags,
  1527. dwSetupStatusFlags));
  1528. hr = EnableVRootsAndShares(FALSE, FALSE, TRUE, pComp);
  1529. _PrintIfError(hr, "failed creating VRoots/shares");
  1530. }
  1531. if (pComp->dwInstallStatus & IS_CLIENT_INSTALL)
  1532. {
  1533. hr = SetSetupStatus(NULL, SETUP_CLIENT_FLAG, TRUE);
  1534. _JumpIfError(hr, error, "SetSetupStatus");
  1535. }
  1536. if ((pComp->dwInstallStatus & IS_SERVER_INSTALL) &&
  1537. (pComp->dwInstallStatus & IS_CLIENT_INSTALL))
  1538. {
  1539. hr = SetSetupStatus(
  1540. pServer->pwszSanitizedName,
  1541. SETUP_CLIENT_FLAG,
  1542. TRUE);
  1543. _JumpIfError(hr, error, "SetSetupStatus");
  1544. }
  1545. // in case we're doing a post-base setup,
  1546. // we always clear the post-base to-do list
  1547. RegDeleteKey(HKEY_LOCAL_MACHINE, wszREGKEYCERTSRVTODOLIST);
  1548. }
  1549. else
  1550. if ((pComp->dwInstallStatus & psc->InstallFlags) &&
  1551. (cscServer == psc->cscSubComponent ||
  1552. !(IS_SERVER_INSTALL & pComp->dwInstallStatus)) &&
  1553. (0 == (pComp->Flags & (SETUPOP_STANDALONE |
  1554. SETUPOP_WIN31UPGRADE |
  1555. SETUPOP_WIN95UPGRADE |
  1556. SETUPOP_NTUPGRADE) )))
  1557. {
  1558. HKEY hkToDoList = NULL;
  1559. WCHAR *pwszConfigTitleVal = NULL;
  1560. WCHAR *pwszArgsValTemp = NULL;
  1561. WCHAR *pwszArgsVal = wszCONFIGARGSVAL;
  1562. BOOL fFreeTitle = FALSE;
  1563. DWORD disp;
  1564. DWORD err;
  1565. DBGPRINT((
  1566. DBG_SS_CERTOCMI,
  1567. "Adding Certificate Services to ToDoList\n"));
  1568. // We're installing base, so create
  1569. // the ToDoList entry stating that we copied files.
  1570. err = ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  1571. wszREGKEYCERTSRVTODOLIST,
  1572. 0,
  1573. NULL,
  1574. 0,
  1575. KEY_ALL_ACCESS,
  1576. NULL,
  1577. &hkToDoList,
  1578. &disp);
  1579. hr = HRESULT_FROM_WIN32(err);
  1580. _JumpIfError(hr, error, "RegCreateKeyEx");
  1581. hr = myLoadRCString(
  1582. g_hInstance,
  1583. IDS_TODO_TITLE,
  1584. &pwszConfigTitleVal);
  1585. if (S_OK == hr)
  1586. {
  1587. fFreeTitle = TRUE;
  1588. }
  1589. else
  1590. {
  1591. // If there was no resource, get something...
  1592. pwszConfigTitleVal = wszCONFIGTITLEVAL;
  1593. }
  1594. // config title
  1595. err = RegSetValueEx(hkToDoList,
  1596. wszCONFIGTITLE,
  1597. 0,
  1598. REG_SZ,
  1599. (PBYTE)pwszConfigTitleVal,
  1600. sizeof(WCHAR)*(wcslen(pwszConfigTitleVal)+1));
  1601. hr = HRESULT_FROM_WIN32(err);
  1602. _PrintIfErrorStr(hr, "RegSetValueEx", wszCONFIGTITLE);
  1603. CSILOG(hr, IDS_LOG_TODOLIST, wszCONFIGTITLE, pwszConfigTitleVal, NULL);
  1604. // config command
  1605. err = RegSetValueEx(hkToDoList,
  1606. wszCONFIGCOMMAND,
  1607. 0,
  1608. REG_SZ,
  1609. (PBYTE)wszCONFIGCOMMANDVAL,
  1610. sizeof(WCHAR)*(wcslen(wszCONFIGCOMMANDVAL)+1));
  1611. hr = HRESULT_FROM_WIN32(err);
  1612. _PrintIfErrorStr(hr, "RegSetValueEx", wszCONFIGCOMMAND);
  1613. CSILOG(hr, IDS_LOG_TODOLIST, wszCONFIGCOMMAND, wszCONFIGCOMMANDVAL, NULL);
  1614. // config args
  1615. if (pComp->fUnattended && NULL != pComp->pwszUnattendedFile)
  1616. {
  1617. // if nt base is in unattended mode, expand args with
  1618. // unattended answer file name
  1619. pwszArgsValTemp = (WCHAR*)LocalAlloc(LMEM_FIXED,
  1620. (wcslen(pwszArgsVal) +
  1621. wcslen(pComp->pwszUnattendedFile) + 5) * sizeof(WCHAR));
  1622. _JumpIfOutOfMemory(hr, error, pwszArgsValTemp);
  1623. wcscpy(pwszArgsValTemp, pwszArgsVal);
  1624. wcscat(pwszArgsValTemp, L" /u:");
  1625. wcscat(pwszArgsValTemp, pComp->pwszUnattendedFile);
  1626. pwszArgsVal = pwszArgsValTemp;
  1627. }
  1628. err = RegSetValueEx(hkToDoList,
  1629. wszCONFIGARGS,
  1630. 0,
  1631. REG_SZ,
  1632. (PBYTE)pwszArgsVal,
  1633. sizeof(WCHAR)*(wcslen(pwszArgsVal)+1));
  1634. hr = HRESULT_FROM_WIN32(err);
  1635. _PrintIfErrorStr(hr, "RegSetValueEx", wszCONFIGARGS);
  1636. CSILOG(hr, IDS_LOG_TODOLIST, wszCONFIGARGS, pwszArgsVal, NULL);
  1637. // free stuff
  1638. if (NULL != pwszConfigTitleVal && fFreeTitle)
  1639. {
  1640. LocalFree(pwszConfigTitleVal);
  1641. }
  1642. if (NULL != pwszArgsValTemp)
  1643. {
  1644. LocalFree(pwszArgsValTemp);
  1645. }
  1646. if (NULL != hkToDoList)
  1647. {
  1648. RegCloseKey(hkToDoList);
  1649. }
  1650. }
  1651. else if (pComp->dwInstallStatus & psc->UpgradeFlags)
  1652. {
  1653. BOOL fFinishCYS;
  1654. hr = CheckPostBaseInstallStatus(&fFinishCYS);
  1655. _JumpIfError(hr, error, "CheckPostBaseInstallStatus");
  1656. // if post mode is true, don't execute setup upgrade path
  1657. if (fFinishCYS)
  1658. {
  1659. BOOL fServer = FALSE;
  1660. // upgrade
  1661. if (cscServer == psc->cscSubComponent)
  1662. {
  1663. hr = UpgradeServer(hwnd, pComp);
  1664. _JumpIfError(hr, error, "UpgradeServer");
  1665. fServer = TRUE;
  1666. }
  1667. else if (cscClient == psc->cscSubComponent)
  1668. {
  1669. hr = UpgradeClient(hwnd, pComp);
  1670. _JumpIfError(hr, error, "UpgradeClient");
  1671. }
  1672. // mark setup status
  1673. hr = SetSetupStatus(NULL, psc->SetupStatusFlags, TRUE);
  1674. _PrintIfError(hr, "SetSetupStatus");
  1675. if (fServer)
  1676. {
  1677. // ca level
  1678. hr = SetSetupStatus(
  1679. pServer->pwszSanitizedName,
  1680. psc->SetupStatusFlags, TRUE);
  1681. _PrintIfError(hr, "SetSetupStatus");
  1682. if(IsEnterpriseCA(pServer->CAType))
  1683. {
  1684. hr = SetSetupStatus(
  1685. pServer->pwszSanitizedName,
  1686. SETUP_UPDATE_CAOBJECT_SVRTYPE,
  1687. TRUE);
  1688. _JumpIfError(hr, error,
  1689. "SetSetupStatus SETUP_UPDATE_CAOBJECT_SVRTYPE");
  1690. }
  1691. }
  1692. if (fServer && pServer->fCertSrvWasRunning)
  1693. {
  1694. hr = StartCertsrvService(TRUE);
  1695. _PrintIfError(hr, "failed in starting cert server service");
  1696. }
  1697. }
  1698. }
  1699. }
  1700. done:
  1701. hr = S_OK;
  1702. error:
  1703. if (NULL != pwszActiveCA)
  1704. {
  1705. LocalFree(pwszActiveCA);
  1706. }
  1707. *pulpRet = hr;
  1708. return(hr);
  1709. }
  1710. HRESULT
  1711. certocmOcCommitQueue(
  1712. IN HWND hwnd,
  1713. IN WCHAR const *pwszComponent,
  1714. IN WCHAR const *pwszSubComponent,
  1715. IN PER_COMPONENT_DATA *pComp)
  1716. {
  1717. HRESULT hr;
  1718. SUBCOMP *pSub;
  1719. CASERVERSETUPINFO *pServer = pComp->CA.pServer;
  1720. DBGPRINT((
  1721. DBG_SS_CERTOCMI,
  1722. "OC_ABOUT_TO_COMMIT_QUEUE(%ws, %ws)\n",
  1723. pwszComponent,
  1724. pwszSubComponent));
  1725. pSub = TranslateSubComponent(pwszComponent, pwszSubComponent);
  1726. if (NULL == pSub)
  1727. {
  1728. goto done;
  1729. }
  1730. // setup will satrt soon, mark it incomplete
  1731. if ((pSub->InstallFlags & pComp->dwInstallStatus) &&
  1732. cscServer == pSub->cscSubComponent)
  1733. {
  1734. hr = SetSetupStatus(NULL, pSub->SetupStatusFlags, FALSE);
  1735. _PrintIfError(hr, "SetSetupStatus");
  1736. hr = SetSetupStatus(
  1737. pServer->pwszSanitizedName,
  1738. pSub->SetupStatusFlags,
  1739. FALSE);
  1740. _PrintIfError(hr, "SetSetupStatus");
  1741. }
  1742. if ((cscServer == pSub->cscSubComponent) &&
  1743. (pSub->UpgradeFlags & pComp->dwInstallStatus) )
  1744. {
  1745. // upgrade case, no UI, stop existing certsrv
  1746. hr = StartAndStopService(pComp->hInstance,
  1747. pComp->fUnattended,
  1748. hwnd,
  1749. wszSERVICE_NAME,
  1750. TRUE, // stop the service
  1751. FALSE, // no confirm
  1752. 0, //doesn't matter since no confirm
  1753. &pServer->fCertSrvWasRunning);
  1754. _PrintIfError(hr, "ServiceExists");
  1755. }
  1756. done:
  1757. hr = S_OK;
  1758. //error:
  1759. return hr;
  1760. }
  1761. // Component dll is being unloaded.
  1762. VOID
  1763. certocmOcCleanup(
  1764. IN WCHAR const *pwszComponent,
  1765. IN PER_COMPONENT_DATA *pComp)
  1766. {
  1767. DBGPRINT((DBG_SS_CERTOCMI, "OC_CLEANUP(%ws)\n", pwszComponent));
  1768. if (NULL != pComp->pwszComponent)
  1769. {
  1770. if (0 == lstrcmpi(pComp->pwszComponent, pwszComponent))
  1771. {
  1772. FreeCAComponentInfo(pComp);
  1773. }
  1774. }
  1775. // also free some globals
  1776. FreeCAGlobals();
  1777. }
  1778. /////////////////////////////////////////////////////////////////////////////
  1779. //++
  1780. //
  1781. // certocmOcQueryState
  1782. //
  1783. // Routine Description:
  1784. // This funcion sets the original, current, and final selection states of the
  1785. // CertSrv service optional component.
  1786. //
  1787. // Return Value:
  1788. // SubcompOn - indicates that the checkbox should be set
  1789. // SubcompOff - indicates that the checkbox should be clear
  1790. // SubcompUseOCManagerDefault - OC Manager should set the state of the checkbox
  1791. // according to state information that is maintained
  1792. // internally by OC Manager itself.
  1793. //
  1794. // Note:
  1795. // By the time this function gets called OnOcInitComponent has already determined
  1796. // that Terminal Services is not installed. It is only necessary to determine
  1797. // whether Terminal Services is selected for installation.
  1798. //--
  1799. /////////////////////////////////////////////////////////////////////////////
  1800. HRESULT
  1801. certocmOcQueryState(
  1802. IN WCHAR const *pwszComponent,
  1803. OPTIONAL IN WCHAR const *pwszSubComponent,
  1804. IN DWORD SelectionState,
  1805. IN PER_COMPONENT_DATA *pComp,
  1806. OUT ULONG_PTR *pulpRet)
  1807. {
  1808. HRESULT hr;
  1809. SubComponentState stateRet = SubcompUseOcManagerDefault;
  1810. DWORD status;
  1811. WCHAR awc[20];
  1812. BOOL fFinished;
  1813. DBGPRINT((
  1814. DBG_SS_CERTOCMI,
  1815. "OC_QUERY_STATE(%ws, %ws, %x)\n",
  1816. pwszComponent,
  1817. pwszSubComponent,
  1818. SelectionState));
  1819. if (NULL == pwszSubComponent)
  1820. {
  1821. goto done;
  1822. }
  1823. switch(SelectionState)
  1824. {
  1825. case OCSELSTATETYPE_ORIGINAL:
  1826. {
  1827. // check to see if the post link exist
  1828. hr = CheckPostBaseInstallStatus(&fFinished);
  1829. _JumpIfError(hr, error, "CheckPostBaseInstallStatus");
  1830. if (!pComp->fPostBase &&
  1831. (SETUPOP_STANDALONE & pComp->Flags) )
  1832. {
  1833. // install through Components button
  1834. if (!fFinished)
  1835. {
  1836. // don't honor local reg SetupStatus
  1837. break;
  1838. }
  1839. }
  1840. // Return the initial installation state of the subcomponent
  1841. if (!pComp->fPostBase &&
  1842. ((SETUPOP_STANDALONE & pComp->Flags) ||
  1843. (SETUPOP_NTUPGRADE & pComp->Flags)) )
  1844. {
  1845. //there is chance for user installed certsrv during base setup
  1846. //and then upgrade without finishing CYS
  1847. if (fFinished)
  1848. {
  1849. // If this is an upgrade or a standalone, query the registry to
  1850. // get the current installation status
  1851. // XTAN, 7/99
  1852. // currently certsrv_server has Needs relationship with
  1853. // certsrv_client. OCM gathers success for certsrv_client before
  1854. // certsrv_server is complete so we don't trust OCM state info
  1855. // about certsrv_client and we check our reg SetupStatus here.
  1856. // our certsrv_server Needs define is incorrect. If we take it
  1857. // out, we probably don't need to reg SetupStatus at
  1858. // Configuration level at all and we can trust OCM state info
  1859. hr = GetSetupStatus(NULL, &status);
  1860. if (S_OK == hr)
  1861. {
  1862. if (
  1863. (0 == lstrcmpi(wszSERVERSECTION, pwszSubComponent) &&
  1864. !(SETUP_SERVER_FLAG & status)) ||
  1865. (0 == lstrcmpi(wszCLIENTSECTION, pwszSubComponent) &&
  1866. !(SETUP_CLIENT_FLAG & status))
  1867. )
  1868. {
  1869. // overwrite OCM default
  1870. stateRet = SubcompOff;
  1871. }
  1872. }
  1873. }
  1874. }
  1875. break;
  1876. }
  1877. case OCSELSTATETYPE_CURRENT:
  1878. {
  1879. break;
  1880. }
  1881. case OCSELSTATETYPE_FINAL:
  1882. {
  1883. SUBCOMP const *psc;
  1884. BOOL fWasEnabled;
  1885. if (S_OK != pComp->hrContinue && !pComp->fUnattended)
  1886. {
  1887. stateRet = SubcompOff;
  1888. }
  1889. //get component install info
  1890. psc = TranslateSubComponent(pwszComponent, pwszSubComponent);
  1891. if (NULL == psc)
  1892. {
  1893. hr = E_INVALIDARG;
  1894. _JumpError(hr, error, "Internal error: unsupported component");
  1895. }
  1896. fWasEnabled = certocmWasEnabled(pComp, psc->cscSubComponent);
  1897. // after all of this, change upgrade->uninstall if not supported
  1898. if ((SETUPOP_NTUPGRADE & pComp->Flags) && fWasEnabled)
  1899. {
  1900. CSASSERT(pComp->UpgradeFlag != CS_UPGRADE_UNKNOWN);
  1901. if (CS_UPGRADE_UNSUPPORTED == pComp->UpgradeFlag)
  1902. stateRet = SubcompOff;
  1903. }
  1904. break;
  1905. }
  1906. }
  1907. done:
  1908. hr = S_OK;
  1909. error:
  1910. wsprintf(awc, L"%u", SelectionState);
  1911. CSILOG(S_OK, IDS_LOG_SELECTIONSTATE, awc, NULL, (DWORD const *) &stateRet);
  1912. *pulpRet = stateRet;
  1913. return(hr);
  1914. }
  1915. //+------------------------------------------------------------------------
  1916. //
  1917. // Function: CertSrvOCProc( . . . . )
  1918. //
  1919. // Synopsis: Service procedure for Cert Server OCM Setup.
  1920. //
  1921. // Arguments: [pwszComponent]
  1922. // [pwszSubComponent]
  1923. // [Function]
  1924. // [Param1]
  1925. // [Param2]
  1926. //
  1927. // Returns: DWORD
  1928. //
  1929. // History: 04/07/97 JerryK Created
  1930. //
  1931. //-------------------------------------------------------------------------
  1932. ULONG_PTR
  1933. CertSrvOCProc(
  1934. IN WCHAR const *pwszComponent,
  1935. IN WCHAR const *pwszSubComponent,
  1936. IN UINT Function,
  1937. IN UINT_PTR Param1,
  1938. IN OUT VOID *Param2)
  1939. {
  1940. ULONG_PTR ulpRet = 0;
  1941. WCHAR const *pwszFunction = NULL;
  1942. BOOL fReturnErrCode = TRUE;
  1943. __try
  1944. {
  1945. switch (Function)
  1946. {
  1947. // OC_PREINITIALIZE:
  1948. // pwszComponent = WCHAR top level component string
  1949. // pwszSubComponent = CHAR top level component string
  1950. // Param1 = char width flags
  1951. // Param2 = unused
  1952. //
  1953. // Return code is char width allowed flags
  1954. case OC_PREINITIALIZE:
  1955. csiLogOpen("+certocm.log");
  1956. pwszFunction = L"OC_PREINITIALIZE";
  1957. fReturnErrCode = FALSE;
  1958. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  1959. _LeaveIfError(g_Comp.hrContinue, "OC_PREINITIALIZE");
  1960. g_Comp.hrContinue = certocmOcPreInitialize(
  1961. pwszComponent,
  1962. (UINT)Param1, //cast to UINT, use as flags
  1963. &ulpRet);
  1964. break;
  1965. // OC_INIT_COMPONENT:
  1966. // pwszComponent = WCHAR top level component string
  1967. // pwszSubComponent = unused
  1968. // Param1 = unused
  1969. // Param2 = points to IN OUT SETUP_INIT_COMPONENT structure
  1970. //
  1971. // Return code is Win32 error indicating outcome.
  1972. case OC_INIT_COMPONENT:
  1973. pwszFunction = L"OC_INIT_COMPONENT";
  1974. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  1975. _LeaveIfError(g_Comp.hrContinue, "OC_INIT_COMPONENT");
  1976. g_Comp.hrContinue = certocmOcInitComponent(
  1977. NULL, // probably have to pass null hwnd
  1978. pwszComponent,
  1979. (SETUP_INIT_COMPONENT *) Param2,
  1980. &g_Comp,
  1981. &ulpRet);
  1982. break;
  1983. case OC_SET_LANGUAGE:
  1984. pwszFunction = L"OC_SET_LANGUAGE";
  1985. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  1986. _LeaveIfError(g_Comp.hrContinue, "OC_SET_LANGUAGE");
  1987. DBGPRINT((
  1988. DBG_SS_CERTOCMI,
  1989. "OC_SET_LANGUAGE(%ws, %ws, %x, %x)\n",
  1990. pwszComponent,
  1991. pwszSubComponent,
  1992. Param1,
  1993. Param2));
  1994. break;
  1995. // OC_QUERY_IMAGE:
  1996. // pwszComponent = WCHAR top level component string
  1997. // pwszSubComponent = WCHAR sub-component string
  1998. // Param1 = low 16 bits specify image; only small icon supported
  1999. // Param2 = low 16 bits = desired width, high 16 bits = desired height
  2000. //
  2001. // Return value is the GDI handle of a small bitmap to be used.
  2002. case OC_QUERY_IMAGE:
  2003. pwszFunction = L"OC_QUERY_IMAGE";
  2004. fReturnErrCode = FALSE;
  2005. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2006. _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_IMAGE");
  2007. g_Comp.hrContinue = certocmOcQueryImage(
  2008. pwszComponent,
  2009. pwszSubComponent,
  2010. (SubComponentInfo) LOWORD(Param1),
  2011. LOWORD((ULONG_PTR) Param2),
  2012. HIWORD((ULONG_PTR) Param2),
  2013. &g_Comp,
  2014. &ulpRet);
  2015. break;
  2016. // OC_REQUEST_PAGES:
  2017. // pwszComponent = WCHAR top level component string
  2018. // pwszSubComponent = unused
  2019. // Param1 = Type of wiz pages being requested (WizardPagesType enum)
  2020. // Param2 = points to IN OUT SETUP_REQUEST_PAGES structure
  2021. //
  2022. // Return value is number of pages the component places in the
  2023. // SETUP_REQUEST_PAGES structure.
  2024. case OC_REQUEST_PAGES:
  2025. pwszFunction = L"OC_REQUEST_PAGES";
  2026. fReturnErrCode = FALSE;
  2027. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2028. _LeaveIfError(g_Comp.hrContinue, "OC_REQUEST_PAGES");
  2029. g_Comp.hrContinue = certocmOcRequestPages(
  2030. pwszComponent,
  2031. (WizardPagesType) Param1,
  2032. (SETUP_REQUEST_PAGES *) Param2,
  2033. &g_Comp,
  2034. &ulpRet);
  2035. break;
  2036. // OC_QUERY_CHANGE_SEL_STATE:
  2037. // pwszComponent = WCHAR top level component string
  2038. // pwszSubComponent = WCHAR sub-component string
  2039. // Param1 = proposed new sel state; 0 = unselected, non 0 = selected
  2040. // Param2 = flags -- OCQ_ACTUAL_SELECTION
  2041. //
  2042. // Return boolean to indicate whether to allow selection state change
  2043. case OC_QUERY_CHANGE_SEL_STATE:
  2044. pwszFunction = L"OC_QUERY_CHANGE_SEL_STATE";
  2045. fReturnErrCode = FALSE;
  2046. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2047. _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_CHANGE_SEL_STATE");
  2048. g_Comp.hrContinue = certocmOcQueryChangeSelState(
  2049. g_Comp.HelperRoutines.QueryWizardDialogHandle(g_Comp.HelperRoutines.OcManagerContext),
  2050. pwszComponent,
  2051. pwszSubComponent,
  2052. (BOOL) Param1,
  2053. (DWORD) (ULONG_PTR) Param2,
  2054. &g_Comp,
  2055. &ulpRet);
  2056. break;
  2057. // OC_CALC_DISK_SPACE:
  2058. // pwszComponent = WCHAR top level component string
  2059. // pwszSubComponent = WCHAR sub-component string
  2060. // Param1 = 0 for removing component or non 0 for adding component
  2061. // Param2 = HDSKSPC to operate on
  2062. //
  2063. // Return value is Win32 error code indicating outcome.
  2064. case OC_CALC_DISK_SPACE:
  2065. pwszFunction = L"OC_CALC_DISK_SPACE";
  2066. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2067. _LeaveIfError(g_Comp.hrContinue, "OC_CALC_DISK_SPACE");
  2068. g_Comp.hrContinue = certocmOcCalcDiskSpace(
  2069. pwszComponent,
  2070. pwszSubComponent,
  2071. (BOOL) Param1,
  2072. (HDSKSPC) Param2,
  2073. &g_Comp,
  2074. &ulpRet);
  2075. break;
  2076. // OC_QUEUE_FILE_OPS:
  2077. // pwszComponent = WCHAR top level component string
  2078. // pwszSubComponent = WCHAR sub-component string
  2079. // Param1 = unused
  2080. // Param2 = HSPFILEQ to operate on
  2081. //
  2082. // Return value is Win32 error code indicating outcome.
  2083. case OC_QUEUE_FILE_OPS:
  2084. pwszFunction = L"OC_QUEUE_FILE_OPS";
  2085. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2086. _LeaveIfError(g_Comp.hrContinue, "OC_QUEUE_FILE_OPS");
  2087. g_Comp.hrContinue = certocmOcQueueFileOps(
  2088. g_Comp.HelperRoutines.QueryWizardDialogHandle(g_Comp.HelperRoutines.OcManagerContext),
  2089. pwszComponent,
  2090. pwszSubComponent,
  2091. (HSPFILEQ) Param2,
  2092. &g_Comp,
  2093. &ulpRet);
  2094. break;
  2095. // Params? xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  2096. // OC_NOTIFICATION_FROM_QUEUE:
  2097. // pwszComponent = WCHAR top level component string
  2098. // pwszSubComponent = unused
  2099. // Param1 = unused
  2100. // Param2 = unused
  2101. //
  2102. // Return value is ???
  2103. case OC_NOTIFICATION_FROM_QUEUE:
  2104. pwszFunction = L"OC_NOTIFICATION_FROM_QUEUE";
  2105. fReturnErrCode = FALSE;
  2106. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2107. DBGPRINT((
  2108. DBG_SS_CERTOCMI,
  2109. "OC_NOTIFICATION_FROM_QUEUE(%ws, %ws, %x, %x)\n",
  2110. pwszComponent,
  2111. pwszSubComponent,
  2112. Param1,
  2113. Param2));
  2114. break;
  2115. // OC_QUERY_STEP_COUNT:
  2116. // pwszComponent = WCHAR top level component string
  2117. // pwszSubComponent = WCHAR sub-component string
  2118. // Param1 = unused
  2119. // Param2 = unused
  2120. //
  2121. // Return value is an arbitrary 'step' count or -1 if error.
  2122. case OC_QUERY_STEP_COUNT:
  2123. pwszFunction = L"OC_QUERY_STEP_COUNT";
  2124. fReturnErrCode = FALSE;
  2125. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2126. _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_STEP_COUNT");
  2127. g_Comp.hrContinue = (DWORD) certocmOcQueryStepCount(
  2128. pwszComponent,
  2129. pwszSubComponent,
  2130. &ulpRet);
  2131. break;
  2132. // OC_COMPLETE_INSTALLATION:
  2133. // pwszComponent = WCHAR top level component string
  2134. // pwszSubComponent = WCHAR sub-component string
  2135. // Param1 = reserved for future expansion
  2136. // Param2 = unused
  2137. //
  2138. // Return value is Win32 error code indicating outcome.
  2139. case OC_COMPLETE_INSTALLATION:
  2140. pwszFunction = L"OC_COMPLETE_INSTALLATION";
  2141. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2142. _LeaveIfError(g_Comp.hrContinue, "OC_COMPLETE_INSTALLATION");
  2143. g_Comp.hrContinue = certocmOcCompleteInstallation(
  2144. g_Comp.HelperRoutines.QueryWizardDialogHandle(g_Comp.HelperRoutines.OcManagerContext),
  2145. pwszComponent,
  2146. pwszSubComponent,
  2147. &g_Comp,
  2148. &ulpRet);
  2149. break;
  2150. // OC_CLEANUP:
  2151. // pwszComponent = WCHAR top level component string
  2152. // pwszSubComponent = unused
  2153. // Param1 = unused
  2154. // Param2 = unused
  2155. //
  2156. // Return value is ignored
  2157. case OC_CLEANUP:
  2158. // don't _LeaveIfError(g_Comp.hrContinue, "OC_CLEANUP");
  2159. // avoid memory leaks
  2160. pwszFunction = L"OC_CLEANUP";
  2161. fReturnErrCode = FALSE;
  2162. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2163. certocmOcCleanup(pwszComponent, &g_Comp);
  2164. break;
  2165. // Params? xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  2166. // OC_QUERY_STATE:
  2167. // pwszComponent = WCHAR top level component string
  2168. // pwszSubComponent = WCHAR sub-component string
  2169. // Param1 = unused? (but Index Server uses it for current state)!
  2170. // Param2 = unused
  2171. //
  2172. // Return value is from the SubComponentState enumerated type
  2173. case OC_QUERY_STATE:
  2174. pwszFunction = L"OC_QUERY_STATE";
  2175. fReturnErrCode = FALSE;
  2176. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2177. //don't _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_STATE");
  2178. certocmOcQueryState(
  2179. pwszComponent,
  2180. pwszSubComponent,
  2181. (DWORD)Param1, //cast to DWORD, use as flags
  2182. &g_Comp,
  2183. &ulpRet);
  2184. break;
  2185. // Params? xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  2186. // OC_NEED_MEDIA:
  2187. // pwszComponent = WCHAR top level component string
  2188. // pwszSubComponent = WCHAR sub-component string
  2189. // Param1 = unused
  2190. // Param2 = unused
  2191. //
  2192. // Return value is ???
  2193. case OC_NEED_MEDIA:
  2194. pwszFunction = L"OC_NEED_MEDIA";
  2195. fReturnErrCode = FALSE;
  2196. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2197. DBGPRINT((
  2198. DBG_SS_CERTOCMI,
  2199. "OC_NEED_MEDIA(%ws, %ws, %x, %x)\n",
  2200. pwszComponent,
  2201. pwszSubComponent,
  2202. Param1,
  2203. Param2));
  2204. break;
  2205. // OC_ABOUT_TO_COMMIT_QUEUE:
  2206. // pwszComponent = WCHAR top level component string
  2207. // pwszSubComponent = WCHAR sub-component string
  2208. // Param1 = reserved for future expansion
  2209. // Param2 = unused
  2210. //
  2211. // Return value is Win32 error code indicating outcome.
  2212. case OC_ABOUT_TO_COMMIT_QUEUE:
  2213. pwszFunction = L"OC_ABOUT_TO_COMMIT_QUEUE";
  2214. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2215. _LeaveIfError(g_Comp.hrContinue, "OC_ABOUT_TO_COMMIT_QUEUE");
  2216. g_Comp.hrContinue = certocmOcCommitQueue(
  2217. g_Comp.HelperRoutines.QueryWizardDialogHandle(g_Comp.HelperRoutines.OcManagerContext),
  2218. pwszComponent,
  2219. pwszSubComponent,
  2220. &g_Comp);
  2221. break;
  2222. // OC_QUERY_SKIP_PAGE:
  2223. // pwszComponent = WCHAR top level component string
  2224. // pwszSubComponent = unused
  2225. // Param1 = OcManagerPage page indicator
  2226. // Param2 = unused
  2227. //
  2228. // Return value is a boolean -- 0 for display or non 0 for skip
  2229. case OC_QUERY_SKIP_PAGE:
  2230. pwszFunction = L"OC_QUERY_SKIP_PAGE";
  2231. fReturnErrCode = FALSE;
  2232. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2233. DBGPRINT((
  2234. DBG_SS_CERTOCMI,
  2235. "OC_QUERY_SKIP_PAGE(%ws, %x)\n",
  2236. pwszComponent,
  2237. (OcManagerPage) Param1));
  2238. _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_SKIP_PAGE");
  2239. if (g_Comp.fPostBase &&
  2240. (WizardPagesType) Param1 == WizPagesWelcome)
  2241. {
  2242. ulpRet = 1; // non 0 to skip wiz page
  2243. }
  2244. break;
  2245. // OC_WIZARD_CREATED:
  2246. // pwszComponent = WCHAR top level component string
  2247. // pwszSubComponent = ???
  2248. // Param1 = ???
  2249. // Param2 = ???
  2250. //
  2251. // Return value is ???
  2252. case OC_WIZARD_CREATED:
  2253. pwszFunction = L"OC_WIZARD_CREATED";
  2254. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2255. _LeaveIfError(g_Comp.hrContinue, "OC_WIZARD_CREATED");
  2256. break;
  2257. // OC_EXTRA_ROUTINES:
  2258. // pwszComponent = WCHAR top level component string
  2259. // pwszSubComponent = ???
  2260. // Param1 = ???
  2261. // Param2 = ???
  2262. //
  2263. // Return value is ???
  2264. case OC_EXTRA_ROUTINES:
  2265. pwszFunction = L"OC_EXTRA_ROUTINES";
  2266. CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
  2267. _LeaveIfError(g_Comp.hrContinue, "OC_EXTRA_ROUTINES");
  2268. break;
  2269. // Some other notification:
  2270. default:
  2271. fReturnErrCode = FALSE;
  2272. CSILOG(
  2273. g_Comp.hrContinue,
  2274. IDS_LOG_BEGIN,
  2275. pwszFunction,
  2276. pwszSubComponent,
  2277. (DWORD const *) &Function);
  2278. DBGPRINT((
  2279. DBG_SS_CERTOCMI,
  2280. "DEFAULT(0x%x: %ws, %ws, %x, %x)\n",
  2281. Function,
  2282. pwszComponent,
  2283. pwszSubComponent,
  2284. Param1,
  2285. Param2));
  2286. break;
  2287. }
  2288. }
  2289. __except(ulpRet = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  2290. {
  2291. if (S_OK == g_Comp.hrContinue)
  2292. {
  2293. g_Comp.hrContinue = (HRESULT)ulpRet;
  2294. }
  2295. _PrintError((HRESULT)ulpRet, "Exception");
  2296. }
  2297. DBGPRINT((DBG_SS_CERTOCMI, "return %p\n", ulpRet));
  2298. // make sure to get a pop up in case of fatal error
  2299. if (S_OK != g_Comp.hrContinue)
  2300. {
  2301. if (!g_Comp.fShownErr)
  2302. {
  2303. int iMsgId = g_Comp.iErrMsg;
  2304. if (0 == iMsgId)
  2305. {
  2306. // use generic one
  2307. iMsgId = IDS_ERR_CERTSRV_SETUP_FAIL;
  2308. }
  2309. CertErrorMessageBox(
  2310. g_Comp.hInstance,
  2311. g_Comp.fUnattended,
  2312. NULL, // null hwnd
  2313. iMsgId,
  2314. g_Comp.hrContinue,
  2315. g_Comp.pwszCustomMessage);
  2316. g_Comp.fShownErr = TRUE;
  2317. }
  2318. // anything fails, cancel install
  2319. HRESULT hr2 = CancelCertsrvInstallation(NULL, &g_Comp);
  2320. _PrintIfError(hr2, "CancelCertsrvInstallation");
  2321. }
  2322. CSILOG(
  2323. fReturnErrCode? (HRESULT) ulpRet : S_OK,
  2324. IDS_LOG_END,
  2325. pwszFunction,
  2326. pwszSubComponent,
  2327. fReturnErrCode? NULL : (DWORD const *) &ulpRet);
  2328. return(ulpRet);
  2329. }
  2330. ULONG_PTR
  2331. CertSrvOCPostProc(
  2332. IN WCHAR const *pwszComponent,
  2333. IN WCHAR const *pwszSubComponent,
  2334. IN UINT Function,
  2335. IN UINT Param1,
  2336. IN OUT VOID *Param2)
  2337. {
  2338. // post setup entry point
  2339. // by going through this path, we know it is invoked in post setup
  2340. g_Comp.fPostBase = TRUE;
  2341. return CertSrvOCProc(
  2342. pwszComponent,
  2343. pwszSubComponent,
  2344. Function,
  2345. Param1,
  2346. Param2);
  2347. }
  2348. VOID
  2349. certocmBumpGasGauge(
  2350. OPTIONAL IN PER_COMPONENT_DATA *pComp,
  2351. IN DWORD PerCentComplete
  2352. DBGPARM(IN WCHAR const *pwszSource))
  2353. {
  2354. static DWORD dwTickCount = 0;
  2355. if (NULL != pComp)
  2356. {
  2357. DWORD NewCount;
  2358. NewCount = (PerCentComplete * SERVERINSTALLTICKS)/100;
  2359. DBGPRINT((
  2360. DBG_SS_CERTOCMI,
  2361. "certocmBumpGasGauge(%ws, %u%%) %d ticks: %d --> %d\n",
  2362. pwszSource,
  2363. PerCentComplete,
  2364. NewCount - dwTickCount,
  2365. dwTickCount,
  2366. NewCount));
  2367. if (SERVERINSTALLTICKS < NewCount)
  2368. {
  2369. NewCount = SERVERINSTALLTICKS;
  2370. }
  2371. while (dwTickCount < NewCount)
  2372. {
  2373. (*pComp->HelperRoutines.TickGauge)(
  2374. pComp->HelperRoutines.OcManagerContext);
  2375. dwTickCount++;
  2376. }
  2377. }
  2378. }
  2379. BOOL
  2380. certocmEnabledSub(
  2381. PER_COMPONENT_DATA *pComp,
  2382. CertSubComponent SubComp,
  2383. DWORD SelectionStateType)
  2384. {
  2385. SUBCOMP const *psc;
  2386. BOOL bRet = FALSE;
  2387. psc = LookupSubComponent(SubComp);
  2388. if (NULL != psc->pwszSubComponent)
  2389. {
  2390. if (pComp->fUnattended &&
  2391. OCSELSTATETYPE_CURRENT == SelectionStateType &&
  2392. 0 == (pComp->Flags & SETUPOP_NTUPGRADE) )
  2393. {
  2394. // unattended case, flags from unattended file
  2395. // upgrade is automatically in unattended mode and make sure
  2396. // to exclude it
  2397. bRet = psc->fInstallUnattend;
  2398. }
  2399. else
  2400. {
  2401. bRet = (*pComp->HelperRoutines.QuerySelectionState)(
  2402. pComp->HelperRoutines.OcManagerContext,
  2403. psc->pwszSubComponent,
  2404. SelectionStateType);
  2405. }
  2406. }
  2407. return(bRet);
  2408. }
  2409. BOOL
  2410. certocmIsEnabled(
  2411. PER_COMPONENT_DATA *pComp,
  2412. CertSubComponent SubComp)
  2413. {
  2414. BOOL bRet;
  2415. bRet = certocmEnabledSub(pComp, SubComp, OCSELSTATETYPE_CURRENT);
  2416. if (!fDebugSupress)
  2417. {
  2418. DBGPRINT((
  2419. DBG_SS_CERTOCMI,
  2420. "certocmIsEnabled(%ws) Is %ws\n",
  2421. LookupSubComponent(SubComp)->pwszSubComponent,
  2422. bRet? L"Enabled" : L"Disabled"));
  2423. }
  2424. return(bRet);
  2425. }
  2426. BOOL
  2427. certocmWasEnabled(
  2428. PER_COMPONENT_DATA *pComp,
  2429. CertSubComponent SubComp)
  2430. {
  2431. BOOL bRet;
  2432. bRet = certocmEnabledSub(pComp, SubComp, OCSELSTATETYPE_ORIGINAL);
  2433. if (!fDebugSupress)
  2434. {
  2435. DBGPRINT((
  2436. DBG_SS_CERTOCMI,
  2437. "certocmWasEnabled(%ws) Was %ws\n",
  2438. LookupSubComponent(SubComp)->pwszSubComponent,
  2439. bRet? L"Enabled" : L"Disabled"));
  2440. }
  2441. return(bRet);
  2442. }
  2443. BOOL
  2444. certocmUninstalling(
  2445. PER_COMPONENT_DATA *pComp,
  2446. CertSubComponent SubComp)
  2447. {
  2448. BOOL bRet;
  2449. fDebugSupress++;
  2450. bRet = certocmWasEnabled(pComp, SubComp) && !certocmIsEnabled(pComp, SubComp);
  2451. fDebugSupress--;
  2452. if (!fDebugSupress)
  2453. {
  2454. DBGPRINT((
  2455. DBG_SS_CERTOCMI,
  2456. "certocmUninstalling(%ws) %ws\n",
  2457. LookupSubComponent(SubComp)->pwszSubComponent,
  2458. bRet? L"TRUE" : L"False"));
  2459. }
  2460. return(bRet);
  2461. }
  2462. BOOL
  2463. certocmInstalling(
  2464. PER_COMPONENT_DATA *pComp,
  2465. CertSubComponent SubComp)
  2466. {
  2467. BOOL bRet;
  2468. fDebugSupress++;
  2469. bRet = !certocmWasEnabled(pComp, SubComp) && certocmIsEnabled(pComp, SubComp);
  2470. fDebugSupress--;
  2471. if (!fDebugSupress)
  2472. {
  2473. DBGPRINT((
  2474. DBG_SS_CERTOCMI,
  2475. "certocmInstalling(%ws) %ws\n",
  2476. LookupSubComponent(SubComp)->pwszSubComponent,
  2477. bRet? L"TRUE" : L"False"));
  2478. }
  2479. return(bRet);
  2480. }
  2481. BOOL
  2482. certocmPreserving(
  2483. PER_COMPONENT_DATA *pComp,
  2484. CertSubComponent SubComp)
  2485. {
  2486. BOOL bRet;
  2487. fDebugSupress++;
  2488. bRet = certocmWasEnabled(pComp, SubComp) && certocmIsEnabled(pComp, SubComp);
  2489. fDebugSupress--;
  2490. if (!fDebugSupress)
  2491. {
  2492. DBGPRINT((
  2493. DBG_SS_CERTOCMI,
  2494. "certocmPreserving(%ws) %ws\n",
  2495. LookupSubComponent(SubComp)->pwszSubComponent,
  2496. bRet? L"TRUE" : L"False"));
  2497. }
  2498. return(bRet);
  2499. }