//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1997 - 1999 // // File: csocm.cpp // // Contents: OCM component DLL for running the Certificate // Server setup. // // Functions: // // History: 12/13/96 TedM Created Original Version // 04/07/97 JerryK Rewrite for Cert Server // 04/??/97 JerryK Stopped updating these comments since // every other line changes every day. // 08/98 XTan Major structure change // // Notes: // // This sample OCM component DLL can be the component DLL // for multiple components. It assumes that a companion sample INF // is being used as the per-component INF, with private data in the // following form. // // [,] // Bitmap = // VerifySelect = 0/1 // VerifyDeselect = 0/1 // ; // ; follow this with install stuff such as CopyFiles= sections, etc. // //------------------------------------------------------------------------------ #include "pch.cpp" #pragma hdrstop #include "msg.h" #include "certmsg.h" #include "setuput.h" #include "setupids.h" #include "clibres.h" #include "csresstr.h" // defines #define cwcMESSAGETEXT 250 #define cwcINFVALUE 250 #define wszSMALLICON L"_SmallIcon" #define wszUNINSTALL L"_Uninstall" #define wszUPGRADE L"_Upgrade" #define wszINSTALL L"_Install" #define wszVERIFYSELECT L"_VerifySelect" #define wszVERIFYDESELECT L"_VerifyDeselect" #define wszCONFIGTITLE L"Title" #define wszCONFIGCOMMAND L"ConfigCommand" #define wszCONFIGARGS L"ConfigArgs" #define wszCONFIGTITLEVAL L"Certificate Services" #define wszCONFIGCOMMANDVAL L"sysocmgr.exe" #define wszCONFIGARGSVAL L"/i:certmast.inf /x" #define __dwFILE__ __dwFILE_OCMSETUP_CSOCM_CPP__ // globals PER_COMPONENT_DATA g_Comp; // Top Level component HINSTANCE g_hInstance; // get rid of it???? // find out if certsrv post setup is finished by checking // registry entries. ie. finish CYS? HRESULT CheckPostBaseInstallStatus( OUT BOOL *pfFinished) { HRESULT hr; HKEY hKey = NULL; DWORD dwSize = 0; DWORD dwType = REG_NONE; //init *pfFinished = TRUE; if (ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, wszREGKEYCERTSRVTODOLIST, 0, KEY_READ, &hKey)) { if (ERROR_SUCCESS == RegQueryValueEx( hKey, wszCONFIGCOMMAND, NULL, &dwType, NULL, // only query size &dwSize) && REG_SZ == dwType) { dwType = REG_NONE; if (ERROR_SUCCESS == RegQueryValueEx( hKey, wszCONFIGARGS, NULL, &dwType, NULL, // only query size &dwSize) && REG_SZ == dwType) { dwType = REG_NONE; if (ERROR_SUCCESS == RegQueryValueEx( hKey, wszCONFIGTITLE, NULL, &dwType, NULL, // only query size &dwSize) && REG_SZ == dwType) { //all entries exist *pfFinished = FALSE; } } } } hr = S_OK; //error: if (NULL != hKey) { RegCloseKey(hKey); } return hr; } HRESULT InitComponentAttributes( IN OUT PER_COMPONENT_DATA *pComp, IN HINSTANCE hDllHandle) { HRESULT hr; ZeroMemory(pComp, sizeof(PER_COMPONENT_DATA)); pComp->hInstance = hDllHandle; g_hInstance = hDllHandle; //get rid of it???? pComp->hrContinue = S_OK; pComp->pwszCustomMessage = NULL; pComp->fUnattended = FALSE; pComp->pwszUnattendedFile = NULL; pComp->pwszServerName = NULL; pComp->pwszServerNameOld = NULL; pComp->dwInstallStatus = 0x0; pComp->fPostBase = FALSE; (pComp->CA).pServer = NULL; (pComp->CA).pClient = NULL; hr = S_OK; //error: return hr; } //+------------------------------------------------------------------------ // // Function: DllMain( . . . . ) // // Synopsis: DLL Entry Point. // // Arguments: [DllHandle] DLL module handle. // [Reason] Reasons for entry into DLL. // [Reserved] Reserved. // // Returns: BOOL // // History: 04/07/97 JerryK Created (again) // //------------------------------------------------------------------------- BOOL WINAPI DllMain( IN HMODULE DllHandle, IN DWORD Reason, IN LPVOID Reserved) { BOOL b; UNREFERENCED_PARAMETER(Reserved); b = TRUE; switch(Reason) { case DLL_PROCESS_ATTACH: DBGPRINT((DBG_SS_CERTOCMI, "Process Attach\n")); // component initialization InitComponentAttributes(&g_Comp, DllHandle); // Fall through to process first thread case DLL_THREAD_ATTACH: b = TRUE; break; case DLL_PROCESS_DETACH: DBGPRINT((DBG_SS_CERTOCMI, "Process Detach\n")); myFreeResourceStrings("certocm.dll"); myFreeColumnDisplayNames(); myRegisterMemDump(); csiLogClose(); break; case DLL_THREAD_DETACH: break; } return b; } extern UNATTENDPARM aUnattendParmClient[]; extern UNATTENDPARM aUnattendParmServer[]; SUBCOMP g_aSubComp[] = { { L"certsrv", // pwszSubComponent cscTopLevel, // cscSubComponent 0, // InstallFlags 0, // UninstallFlags 0, // ChangeFlags 0, // UpgradeFlags 0, // EnabledFlags 0, // SetupStatusFlags FALSE, // fDefaultInstallUnattend FALSE, // fInstallUnattend NULL // aUnattendParm }, { wszSERVERSECTION, // pwszSubComponent cscServer, // cscSubComponent IS_SERVER_INSTALL, // InstallFlags IS_SERVER_REMOVE, // UninstallFlags IS_SERVER_CHANGE, // ChangeFlags IS_SERVER_UPGRADE, // UpgradeFlags IS_SERVER_ENABLED, // EnabledFlags SETUP_SERVER_FLAG, // SetupStatusFlags TRUE, // fDefaultInstallUnattend FALSE, // fInstallUnattend aUnattendParmServer // aUnattendParm }, { wszCLIENTSECTION, // pwszSubComponent cscClient, // cscSubComponent IS_CLIENT_INSTALL, // InstallFlags IS_CLIENT_REMOVE, // UninstallFlags IS_CLIENT_CHANGE, // ChangeFlags IS_CLIENT_UPGRADE, // UpgradeFlags IS_CLIENT_ENABLED, // EnabledFlags SETUP_CLIENT_FLAG, // SetupStatusFlags TRUE, // fDefaultInstallUnattend FALSE, // fInstallUnattend aUnattendParmClient // aUnattendParm }, { NULL, // pwszSubComponent } }; SUBCOMP * TranslateSubComponent( IN WCHAR const *pwszComponent, OPTIONAL IN WCHAR const *pwszSubComponent) { SUBCOMP *psc; if (NULL == pwszSubComponent) { pwszSubComponent = pwszComponent; } for (psc = g_aSubComp; NULL != psc->pwszSubComponent; psc++) { if (0 == lstrcmpi(psc->pwszSubComponent, pwszSubComponent)) { break; } } if (NULL == psc->pwszSubComponent) { psc = NULL; } return(psc); } SUBCOMP const * LookupSubComponent( IN CertSubComponent SubComp) { SUBCOMP const *psc; for (psc = g_aSubComp; NULL != psc->pwszSubComponent; psc++) { if (psc->cscSubComponent == SubComp) { break; } } CSASSERT(NULL != psc); return(psc); } BOOL fDebugSupress = TRUE; HRESULT UpdateSubComponentInstallStatus( IN WCHAR const *pwszComponent, IN WCHAR const *pwszSubComponent, IN OUT PER_COMPONENT_DATA *pComp) { HRESULT hr; BOOL fWasEnabled; BOOL fIsEnabled; DWORD InstallFlags; SUBCOMP const *psc; psc = TranslateSubComponent(pwszComponent, pwszSubComponent); if (NULL == psc) { hr = E_INVALIDARG; _JumpError(hr, error, "Internal error: unsupported component"); } fWasEnabled = certocmWasEnabled(pComp, psc->cscSubComponent); fIsEnabled = certocmIsEnabled(pComp, psc->cscSubComponent); CSILOGDWORD(IDS_LOG_WAS_ENABLED, fWasEnabled); CSILOGDWORD(IDS_LOG_IS_ENABLED, fIsEnabled); InstallFlags = psc->InstallFlags | psc->ChangeFlags | psc->EnabledFlags; if (!fWasEnabled) { if (fIsEnabled) { // install case pComp->dwInstallStatus |= InstallFlags; } else // !fIsEnabled { // this is from check then uncheck, should remove the bit // turn off both bits pComp->dwInstallStatus &= ~InstallFlags; } } else // fWasEnabled { if (pComp->fPostBase && (pComp->Flags & SETUPOP_STANDALONE) ) { // was installed, invoke from post setup // this is install case pComp->dwInstallStatus |= InstallFlags; } else if (pComp->Flags & SETUPOP_NTUPGRADE) { // if was installed and now in upgrade mode, upgrade case pComp->dwInstallStatus |= psc->UpgradeFlags | psc->EnabledFlags; } else if (!fIsEnabled) { // uninstall case pComp->dwInstallStatus &= ~psc->EnabledFlags; pComp->dwInstallStatus |= psc->UninstallFlags | psc->ChangeFlags; } else // fIsEnabled { pComp->dwInstallStatus |= psc->EnabledFlags; #if DBG_CERTSRV BOOL fUpgrade = FALSE; hr = myGetCertRegDWValue( NULL, NULL, NULL, L"EnforceUpgrade", (DWORD *) &fUpgrade); if (S_OK == hr && fUpgrade) { pComp->dwInstallStatus |= psc->UpgradeFlags; } #endif //DBG_CERTSRV } // end fIsEnabled else } // end fWasEnabled else // after all of this, change upgrade->uninstall if not supported // detect illegal upgrade if (pComp->dwInstallStatus & IS_SERVER_UPGRADE) { hr = DetermineServerUpgradePath(pComp); _JumpIfError(hr, error, "DetermineServerUpgradePath"); } else if (pComp->dwInstallStatus & IS_CLIENT_UPGRADE) { hr = DetermineClientUpgradePath(pComp); _JumpIfError(hr, error, "LoadAndDetermineClientUpgradeInfo"); } if ((pComp->dwInstallStatus & IS_SERVER_UPGRADE) || (pComp->dwInstallStatus & IS_CLIENT_UPGRADE)) { CSASSERT(pComp->UpgradeFlag != CS_UPGRADE_UNKNOWN); if (CS_UPGRADE_UNSUPPORTED == pComp->UpgradeFlag) { pComp->dwInstallStatus &= ~InstallFlags; pComp->dwInstallStatus |= psc->UninstallFlags | psc->ChangeFlags; } } CSILOG( S_OK, IDS_LOG_INSTALL_STATE, pwszSubComponent, NULL, &pComp->dwInstallStatus); hr = S_OK; error: return hr; } HRESULT certocmOcPreInitialize( IN WCHAR const *pwszComponent, IN UINT Flags, OUT ULONG_PTR *pulpRet) { HRESULT hr; *pulpRet = 0; DBGPRINT((DBG_SS_CERTOCMI, "OC_PREINITIALIZE(%ws, %x)\n", pwszComponent, Flags)); myVerifyResourceStrings(g_hInstance); // Return value is flag telling OCM which char width we want to run in. #ifdef UNICODE *pulpRet = OCFLAG_UNICODE & Flags; #else *pulpRet = OCFLAG_ANSI & Flags; #endif hr = S_OK; //error: return hr; } // Allocate and initialize a new component. // // Return code is Win32 error indicating outcome. ERROR_CANCELLED tells OCM to // cancel the installation. HRESULT certocmOcInitComponent( IN HWND hwnd, IN WCHAR const *pwszComponent, IN OUT SETUP_INIT_COMPONENT *pInitComponent, IN OUT PER_COMPONENT_DATA *pComp, OUT ULONG_PTR *pulpRet) { HRESULT hr; BOOL fCoInit = FALSE; HKEY hkey = NULL; WCHAR awc[30]; WCHAR *pwc; DBGPRINT(( DBG_SS_CERTOCMI, "OC_INIT_COMPONENT(%ws, %p)\n", pwszComponent, pInitComponent)); hr = CoInitialize(NULL); if (S_OK != hr && S_FALSE != hr) { _JumpError(hr, error, "CoInitialize"); } fCoInit = TRUE; *pulpRet = ERROR_CANCELLED; if (OCMANAGER_VERSION <= pInitComponent->OCManagerVersion) { pInitComponent->OCManagerVersion = OCMANAGER_VERSION; } // Allocate a new component string. pComp->pwszComponent = (WCHAR *) LocalAlloc(LPTR, (wcslen(pwszComponent) + 1) * sizeof(WCHAR)); _JumpIfOutOfMemory(hr, error, pComp->pwszComponent); wcscpy(pComp->pwszComponent, pwszComponent); // OCM passes in some information that we want to save, like the open // handle to our per-component INF. As long as we have a per-component INF, // append-open any layout file that is associated with it, in preparation // for later inf-based file queueing operations. // // We save away certain other stuff that gets passed to us now, since OCM // doesn't guarantee that the SETUP_INIT_COMPONENT will persist beyond the // processing of this one interface routine. if (INVALID_HANDLE_VALUE != pInitComponent->ComponentInfHandle && NULL != pInitComponent->ComponentInfHandle) { pComp->MyInfHandle = pInitComponent->ComponentInfHandle; } else { hr = E_INVALIDARG; _JumpError(hr, error, "invalid inf handle"); } if (NULL != pComp->MyInfHandle) { if (!SetupOpenAppendInfFile(NULL, pComp->MyInfHandle, NULL)) { // SetupOpenAppendInfFile: // If Filename (Param1) is NULL, the INF filename is // retrieved from the LayoutFile value of the Version // section in the existing INF file. // // If FileName was not specified and there was no // LayoutFile value in the Version section of the // existing INF File, GetLastError returns ERROR_INVALID_DATA. hr = myHLastError(); _PrintErrorStr(hr, "SetupOpenAppendInfFile", pwszComponent); } } pComp->HelperRoutines = pInitComponent->HelperRoutines; pComp->Flags = pInitComponent->SetupData.OperationFlags; pwc = awc; pwc += wsprintf(pwc, L"0x"); if (0 != (DWORD) (pComp->Flags >> 32)) { pwc += wsprintf(pwc, L"%x:", (DWORD) (pComp->Flags >> 32)); } wsprintf(pwc, L"%08x", (DWORD) pComp->Flags); CSILOG(S_OK, IDS_LOG_OPERATIONFLAGS, awc, NULL, NULL); CSILOGDWORD(IDS_LOG_POSTBASE, pComp->fPostBase); hr = RegOpenKey(HKEY_LOCAL_MACHINE, wszREGKEYOCMSUBCOMPONENTS, &hkey); if (S_OK == hr) { DWORD dwType; DWORD dwValue; DWORD cb; DWORD const *pdw; cb = sizeof(dwValue); hr = RegQueryValueEx( hkey, wszSERVERSECTION, 0, &dwType, (BYTE *) &dwValue, &cb); pdw = NULL; if (S_OK == hr && REG_DWORD == dwType && sizeof(dwValue) == cb) { pdw = &dwValue; } CSILOG(hr, IDS_LOG_REGSTATE, wszSERVERSECTION, NULL, pdw); cb = sizeof(dwValue); hr = RegQueryValueEx( hkey, wszCLIENTSECTION, 0, &dwType, (BYTE *) &dwValue, &cb); pdw = NULL; if (S_OK == hr && REG_DWORD == dwType && sizeof(dwValue) == cb) { pdw = &dwValue; } CSILOG(hr, IDS_LOG_REGSTATE, wszCLIENTSECTION, NULL, pdw); cb = sizeof(dwValue); hr = RegQueryValueEx( hkey, wszOLDDOCCOMPONENT, 0, &dwType, (BYTE *) &dwValue, &cb); pdw = NULL; if (S_OK == hr && REG_DWORD == dwType && sizeof(dwValue) == cb) { CSILOG(hr, IDS_LOG_REGSTATE, wszOLDDOCCOMPONENT, NULL, &dwValue); } } pComp->fUnattended = (pComp->Flags & SETUPOP_BATCH)? TRUE : FALSE; CSILOG( S_OK, IDS_LOG_UNATTENDED, pComp->fUnattended? pInitComponent->SetupData.UnattendFile : NULL, NULL, (DWORD const *) &pComp->fUnattended); if (pComp->fUnattended) { pComp->pwszUnattendedFile = (WCHAR *) LocalAlloc( LMEM_FIXED, (wcslen(pInitComponent->SetupData.UnattendFile) + 1) * sizeof(WCHAR)); _JumpIfOutOfMemory(hr, error, pComp->pwszUnattendedFile); wcscpy( pComp->pwszUnattendedFile, pInitComponent->SetupData.UnattendFile); } // initialize ca setup data hr = InitCASetup(hwnd, pComp); _JumpIfError(hr, error, "InitCASetup"); hr = S_OK; *pulpRet = NO_ERROR; error: if (NULL != hkey) { RegCloseKey(hkey); } if (fCoInit) { CoUninitialize(); } return(hr); } HRESULT certocmReadInfString( IN HINF hInf, OPTIONAL IN WCHAR const *pwszFile, IN WCHAR const *pwszSection, IN WCHAR const *pwszName, IN OUT WCHAR **ppwszValue) { INFCONTEXT InfContext; HRESULT hr; WCHAR wszBuffer[cwcINFVALUE]; WCHAR *pwsz; if (NULL != *ppwszValue) { // free old LocalFree(*ppwszValue); *ppwszValue = NULL; } if (!SetupFindFirstLine(hInf, pwszSection, pwszName, &InfContext)) { hr = myHLastError(); _JumpErrorStr(hr, error, "SetupFindFirstLine", pwszSection); } if (!SetupGetStringField( &InfContext, 1, wszBuffer, sizeof(wszBuffer)/sizeof(wszBuffer[0]), NULL)) { hr = myHLastError(); _JumpErrorStr(hr, error, "SetupGetStringField", pwszName); } pwsz = (WCHAR *) LocalAlloc( LMEM_FIXED, (wcslen(wszBuffer) + 1) * sizeof(WCHAR)); _JumpIfOutOfMemory(hr, error, pwsz); wcscpy(pwsz, wszBuffer); *ppwszValue = pwsz; hr = S_OK; error: return(hr); } HRESULT certocmReadInfInteger( IN HINF hInf, OPTIONAL IN WCHAR const *pwszFile, IN WCHAR const *pwszSection, IN WCHAR const *pwszName, OUT INT *pValue) { INFCONTEXT InfContext; HRESULT hr = S_OK; WCHAR wszBuffer[cwcINFVALUE]; *pValue = 0; if (!SetupFindFirstLine(hInf, pwszSection, pwszName, &InfContext)) { hr = myHLastError(); DBGPRINT(( DBG_SS_CERTOCMI, __FILE__ "(%u): %ws%wsSetupFindFirstLine([%ws] %ws) failed! -> %x\n", __LINE__, NULL != pwszFile? pwszFile : L"", NULL != pwszFile? L": " : L"", pwszSection, pwszName, hr)); goto error; } if (!SetupGetIntField(&InfContext, 1, pValue)) { hr = myHLastError(); DBGPRINT(( DBG_SS_CERTOCM, __FILE__ "(%u): %ws%wsSetupGetIntField([%ws] %ws) failed! -> %x\n", __LINE__, NULL != pwszFile? pwszFile : L"", NULL != pwszFile? L": " : L"", pwszSection, pwszName, hr)); goto error; } DBGPRINT(( DBG_SS_CERTOCMI, "%ws%ws[%ws] %ws = %u\n", NULL != pwszFile? pwszFile : L"", NULL != pwszFile? L": " : L"", pwszSection, pwszName, *pValue)); error: return(hr); } // Return the GDI handle of a small bitmap to be used. NULL means an error // occurred -- OCM will use a default bitmap. // // Demonstrates use of private data in a per-component inf. We will look in // our per-component inf to determine the resource name for the bitmap for this // component, and then go fetch it from the resources. // // Other possibilities would be to simply return the same hbitmap for all // cases, or to return NULL, in which case OCM uses a default. Note that we // ignore the requested width and height and our bitmaps are not language // dependent. HRESULT certocmOcQueryImage( IN WCHAR const *pwszComponent, OPTIONAL IN WCHAR const *pwszSubComponent, IN SubComponentInfo wSubComp, IN WORD wWidth, IN WORD wHeight, IN OUT PER_COMPONENT_DATA *pComp, OUT ULONG_PTR *pulpRet) { HANDLE hRet = NULL; HRESULT hr; DBGPRINT(( DBG_SS_CERTOCMI, "OC_QUERY_IMAGE(%ws, %ws, %hx, %hx, %hx)\n", pwszComponent, pwszSubComponent, wSubComp, wWidth, wHeight)); if (SubCompInfoSmallIcon != wSubComp) { goto done; } hRet = (HANDLE) LoadBitmap(pComp->hInstance, MAKEINTRESOURCE(IDB_APP)); if (NULL == hRet) { hr = myHLastError(); _JumpError(hr, error, "LoadBitmap"); } done: hr = S_OK; error: *pulpRet = (ULONG_PTR) hRet; return hr; } // Return the number of wizard pages the current component places in the // SETUP_REQUEST_PAGES structure. HRESULT certocmOcRequestPages( IN WCHAR const *pwszComponent, IN WizardPagesType WizPagesType, IN OUT SETUP_REQUEST_PAGES *pRequestPages, IN PER_COMPONENT_DATA *pComp, OUT ULONG_PTR *pulpRet) { HRESULT hr; *pulpRet = 0; DBGPRINT(( DBG_SS_CERTOCMI, "OC_REQUEST_PAGES(%ws, %x, %p)\n", pwszComponent, WizPagesType, pRequestPages)); // don't invoke wiz apge if unattended // or if running from base setup/upgrade setup if ((!pComp->fUnattended) && (SETUPOP_STANDALONE & pComp->Flags)) { *pulpRet = myDoPageRequest(pComp, WizPagesType, pRequestPages); } else { DBGPRINT(( DBG_SS_CERTOCMI, "Not adding wizard pages, %ws\n", pComp->fUnattended? L"Unattended" : L"GUI Setup")); } hr = S_OK; //error: return hr; } HRESULT IsIA5DnsMachineName() { WCHAR *pwszDnsName = NULL; CRL_DIST_POINTS_INFO CRLDistInfo; CRL_DIST_POINT DistPoint; CERT_ALT_NAME_ENTRY AltNameEntry; BYTE *pbEncoded = NULL; DWORD cbEncoded; static HRESULT s_hr = S_FALSE; if (S_FALSE != s_hr) { goto error; } s_hr = myGetMachineDnsName(&pwszDnsName); _JumpIfError(s_hr, error, "myGetMachineDnsName"); CRLDistInfo.cDistPoint = 1; CRLDistInfo.rgDistPoint = &DistPoint; ZeroMemory(&DistPoint, sizeof(DistPoint)); DistPoint.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME; DistPoint.DistPointName.FullName.cAltEntry = 1; DistPoint.DistPointName.FullName.rgAltEntry = &AltNameEntry; ZeroMemory(&AltNameEntry, sizeof(AltNameEntry)); AltNameEntry.dwAltNameChoice = CERT_ALT_NAME_URL; AltNameEntry.pwszURL = pwszDnsName; if (!myEncodeObject( X509_ASN_ENCODING, X509_CRL_DIST_POINTS, &CRLDistInfo, 0, CERTLIB_USE_LOCALALLOC, &pbEncoded, &cbEncoded)) { s_hr = myHLastError(); _JumpIfError(s_hr, error, "myEncodeObject"); } CSASSERT(S_OK == s_hr); error: if (NULL != pwszDnsName) { LocalFree(pwszDnsName); } if (NULL != pbEncoded) { LocalFree(pbEncoded); } return(s_hr); } // Return boolean to indicate whether to allow selection state change. As // demonstrated, again we'll go out to our per-component inf to see whether it // wants us to validate. Note that unattended mode must be respected. HRESULT certocmOcQueryChangeSelState( HWND hwnd, IN WCHAR const *pwszComponent, OPTIONAL IN WCHAR const *pwszSubComponent, IN BOOL fSelectedNew, IN DWORD Flags, IN OUT PER_COMPONENT_DATA *pComp, OUT ULONG_PTR *pulpRet) { INT fVerify; TCHAR wszText[cwcMESSAGETEXT]; const WCHAR* Args[2]; SUBCOMP const *psc; HRESULT hr; WCHAR awc[20]; WCHAR awc2[20]; DWORD fRet; BOOL fServerWasInstalled; BOOL fWebClientWasInstalled; BOOL fDisallow = FALSE; int iMsg; static BOOL s_fWarned = FALSE; *pulpRet = FALSE; DBGPRINT(( DBG_SS_CERTOCMI, "OC_QUERY_CHANGE_SEL_STATE(%ws, %ws, %x, %x)\n", pwszComponent, pwszSubComponent, fSelectedNew, Flags)); // disallow some selection changes fServerWasInstalled = certocmWasEnabled(pComp, cscServer); fWebClientWasInstalled = certocmWasEnabled(pComp, cscClient); if (fWebClientWasInstalled && (OCQ_ACTUAL_SELECTION & Flags)) { if (fSelectedNew) { // check if (!fServerWasInstalled && (0 == lstrcmpi(wszSERVERSECTION, pwszSubComponent) || 0 == lstrcmpi(wszCERTSRVSECTION, pwszSubComponent)) ) { // case: web client installed and try install server fDisallow = TRUE; iMsg = IDS_WRN_UNINSTALL_CLIENT; } if (fServerWasInstalled && 0 == lstrcmpi(wszCLIENTSECTION, pwszSubComponent)) { // case: uncheck both then check web client fDisallow = TRUE; iMsg = IDS_WRN_UNINSTALL_BOTH; } } else { // uncheck if (fServerWasInstalled && 0 == lstrcmpi(wszSERVERSECTION, pwszSubComponent)) { // case: full certsrv installed and try leave only web client fDisallow = TRUE; iMsg = IDS_WRN_UNINSTALL_BOTH; } } } // not a server sku if (!FIsServer()) { fDisallow = TRUE; iMsg = IDS_WRN_SERVER_ONLY; } if (fDisallow) { CertWarningMessageBox( pComp->hInstance, pComp->fUnattended, hwnd, iMsg, 0, NULL); goto done; } if (fSelectedNew) { hr = IsIA5DnsMachineName(); if (S_OK != hr) { CertMessageBox( pComp->hInstance, pComp->fUnattended, hwnd, IDS_ERR_NONIA5DNSNAME, hr, MB_OK | MB_ICONERROR, NULL); goto done; } if ((OCQ_ACTUAL_SELECTION & Flags) && 0 != lstrcmpi(wszCLIENTSECTION, pwszSubComponent)) { if (!s_fWarned) { DWORD dwSetupStatus; hr = GetSetupStatus(NULL, &dwSetupStatus); if (S_OK == hr) { if ((SETUP_CLIENT_FLAG | SETUP_SERVER_FLAG) & dwSetupStatus) { s_fWarned = TRUE; } CSILOG( hr, IDS_LOG_QUERYCHANGESELSTATE, NULL, NULL, &dwSetupStatus); } } if (!s_fWarned) { if (IDYES != CertMessageBox( pComp->hInstance, pComp->fUnattended, hwnd, IDS_WRN_NONAMECHANGE, S_OK, MB_YESNO | MB_ICONWARNING | CMB_NOERRFROMSYS, NULL)) { goto done; } s_fWarned = TRUE; } } } *pulpRet = TRUE; if (pComp->fUnattended) { goto done; } psc = TranslateSubComponent(pwszComponent, pwszSubComponent); if (NULL == psc) { hr = E_INVALIDARG; _JumpError(hr, error, "Internal error: unsupported component"); } hr = certocmReadInfInteger( pComp->MyInfHandle, NULL, psc->pwszSubComponent, fSelectedNew? wszVERIFYSELECT : wszVERIFYDESELECT, &fVerify); if (S_OK != hr || !fVerify) { goto done; } // Don't pass specific lang id to FormatMessage, as it fails if there's no // msg in that language. Instead, set the thread locale, which will get // FormatMessage to use a search algorithm to find a message of the // appropriate language, or use a reasonable fallback msg if there's none. Args[0] = pwszComponent; Args[1] = pwszSubComponent; FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, pComp->hInstance, fSelectedNew? MSG_SURE_SELECT : MSG_SURE_DESELECT, 0, wszText, sizeof(wszText)/sizeof(wszText[0]), (va_list *) Args); *pulpRet = (IDYES == CertMessageBox( pComp->hInstance, pComp->fUnattended, hwnd, 0, S_OK, MB_YESNO | MB_ICONWARNING | MB_TASKMODAL | CMB_NOERRFROMSYS, wszText)); done: hr = S_OK; error: wsprintf(awc, L"%u", fSelectedNew); wsprintf(awc2, L"0x%08x", Flags); fRet = (DWORD) *pulpRet; CSILOG(hr, IDS_LOG_QUERYCHANGESELSTATE, awc, awc2, &fRet); return hr; } // Calculate disk space for the component being added or removed. Return a // Win32 error code indicating outcome. In our case the private section for // this component/subcomponent pair is a simple standard inf install section, // so we can use high-level disk space list API to do what we want. HRESULT certocmOcCalcDiskSpace( IN WCHAR const *pwszComponent, OPTIONAL IN WCHAR const *pwszSubComponent, IN BOOL fAddComponent, IN HDSKSPC hDiskSpace, IN OUT PER_COMPONENT_DATA *pComp, OUT ULONG_PTR *pulpRet) { HRESULT hr; WCHAR *pwsz = NULL; SUBCOMP const *psc; static fServerFirstCall = TRUE; static fClientFirstCall = TRUE; DBGPRINT(( DBG_SS_CERTOCMI, "OC_CALC_DISK_SPACE(%ws, %ws, %x, %p)\n", pwszComponent, pwszSubComponent, fAddComponent, hDiskSpace)); psc = TranslateSubComponent(pwszComponent, pwszSubComponent); if (NULL == psc) { hr = E_INVALIDARG; _JumpError(hr, error, "Internal error: unsupported component"); } // Being installed or uninstalled. Fetch INSTALL section name, // so we can add or remove the files being INSTALLed from the disk // space list. hr = certocmReadInfString( pComp->MyInfHandle, NULL, psc->pwszSubComponent, wszINSTALL, &pwsz); _JumpIfError(hr, error, "certocmReadInfString"); if (fAddComponent) // Adding { if (!SetupAddInstallSectionToDiskSpaceList( hDiskSpace, pComp->MyInfHandle, NULL, pwsz, 0, 0)) { hr = myHLastError(); _JumpErrorStr(hr, error, "SetupAddInstallSectionToDiskSpaceList", pwsz); } } else // Removing { if (!SetupRemoveInstallSectionFromDiskSpaceList( hDiskSpace, pComp->MyInfHandle, NULL, pwsz, 0, 0)) { hr = myHLastError(); _JumpErrorStr(hr, error, "SetupRemoveInstallSectionFromDiskSpaceList", pwsz); } } hr = S_OK; error: if (NULL != pwsz) { LocalFree(pwsz); } *pulpRet = hr; return(hr); } // OCM calls this routine when ready for files to be copied to effect the // changes the user requested. The component DLL must figure out whether it is // being installed or uninstalled and take appropriate action. For this // sample, we look in the private data section for this component/subcomponent // pair, and get the name of an uninstall section for the uninstall case. // // Note that OCM calls us once for the *entire* component and then once per // subcomponent. We ignore the first call. // // Return value is Win32 error code indicating outcome. HRESULT certocmOcQueueFileOps( IN HWND hwnd, IN WCHAR const *pwszComponent, OPTIONAL IN WCHAR const *pwszSubComponent, IN HSPFILEQ hFileQueue, IN OUT PER_COMPONENT_DATA *pComp, OUT ULONG_PTR *pulpRet) { HRESULT hr; SUBCOMP const *psc; BOOL fRemoveFile = FALSE; // TRUE for uninstall; FALSE for install/upgrade WCHAR *pwszAction; WCHAR *pwsz = NULL; static BOOL s_fPreUninstall = FALSE; // preuninstall once DBGPRINT(( DBG_SS_CERTOCMI, "OC_QUEUE_FILE_OPS(%ws, %ws, %p)\n", pwszComponent, pwszSubComponent, hFileQueue)); if (NULL == pwszSubComponent) { // Do no work for top level component goto done; } psc = TranslateSubComponent(pwszComponent, pwszSubComponent); if (NULL == psc) { hr = E_INVALIDARG; _JumpError(hr, error, "Internal error: unsupported component"); } // if unattended, not upgrade, & not uninstall, load if (pComp->fUnattended && !(pComp->Flags & SETUPOP_NTUPGRADE) ) { // retrieve unattended attributes hr = certocmRetrieveUnattendedText( pwszComponent, pwszSubComponent, pComp); if (S_OK != hr && 0x0 != (pComp->Flags & SETUPOP_STANDALONE)) { // only error out if it is from add/remove or post because // it could fail regular ntbase in unattended mode without certsrv _JumpError(hr, error, "certocmRetrieveUnattendedText"); } // Init install status (must be done after retrieving unattended text) hr = UpdateSubComponentInstallStatus(pwszComponent, pwszSubComponent, pComp); _JumpIfError(hr, error, "UpdateSubComponentInstallStatus"); if (psc->fInstallUnattend) // make sure ON { if (certocmWasEnabled(pComp, psc->cscSubComponent) && !pComp->fPostBase) { // the case to run install with component ON twice or more hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE); _JumpError(hr, error, "You must uninstall before install"); } if (SETUPOP_STANDALONE & pComp->Flags) { // only prepare and validate unattende attr in standalone mode // in other word, don't call following if NT base hr = PrepareUnattendedAttributes( hwnd, pwszComponent, pwszSubComponent, pComp); _JumpIfError(hr, error, "PrepareUnattendedAttributes"); } } } else { // Initialize the install status hr = UpdateSubComponentInstallStatus(pwszComponent, pwszSubComponent, pComp); _JumpIfError(hr, error, "UpdateSubComponentInstallStatus"); } // If we're not doing base setup or an upgrade, check to see if we already // copied files during base setup, by checking to see if base setup // left an entry in the ToDo List. if(pComp->fPostBase) { DBGPRINT(( DBG_SS_CERTOCMI, "File Queueing Skipped, files already installed by GUI setup")); goto done; } /* //--- Talk with OCM guys and put this functionality into a notification routine //--- This will allow us to pop compatibility error to user before unattended upgrade begins // detect illegal upgrade if (pComp->dwInstallStatus & IS_SERVER_UPGRADE) { hr = DetermineServerUpgradePath(pComp); _JumpIfError(hr, error, "DetermineServerUpgradePath"); } else if (pComp->dwInstallStatus & IS_CLIENT_UPGRADE) { hr = DetermineClientUpgradePath(pComp); _JumpIfError(hr, error, "LoadAndDetermineClientUpgradeInfo"); } if ((pComp->dwInstallStatus & IS_SERVER_UPGRADE) || (pComp->dwInstallStatus & IS_CLIENT_UPGRADE)) { // block if attempting upgrade that is not Win2K or Whistler // lodge a complaint in the log; upgrade all bits and if ((CS_UPGRADE_NO != pComp->UpgradeFlag) && (CS_UPGRADE_WHISTLER != pComp->UpgradeFlag) && (CS_UPGRADE_WIN2000 != pComp->UpgradeFlag)) { hr = HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION); CertErrorMessageBox( pComp->hInstance, pComp->fUnattended, hwnd, IDS_ERR_UPGRADE_NOT_SUPPORTED, hr, NULL); // _JumpError(hr, error, "Unsupported upgrade"); // continue uninstall/reinstall } } */ if ((pComp->dwInstallStatus & psc->ChangeFlags) || (pComp->dwInstallStatus & psc->UpgradeFlags) ) { // for ChangeFlags, either install or uninstall // all cases, copy file or remove file if (pComp->dwInstallStatus & psc->UninstallFlags) { fRemoveFile = TRUE; } // Uninstall the core if: // this subcomponent is being uninstalled, and // this is a core subcomponent (client or server), and // this is the server subcomponent, or the server isn't being removed or // upgrade if (((pComp->dwInstallStatus & psc->UninstallFlags) || (pComp->dwInstallStatus & psc->UpgradeFlags) ) && (cscServer == psc->cscSubComponent || !(IS_SERVER_REMOVE & pComp->dwInstallStatus) ) ) { // if fall into here, either need to overwrite or // delete certsrv files so unreg all related dlls if (cscServer == psc->cscSubComponent && (pComp->dwInstallStatus & psc->UpgradeFlags) ) { // if this is server upgrade, determine upgrade path hr = DetermineServerUpgradePath(pComp); _JumpIfError(hr, error, "DetermineServerUpgradePath"); // determine custom policy module hr = DetermineServerCustomModule( pComp, TRUE); // policy _JumpIfError(hr, error, "DetermineServerCustomModule"); // determine custom exit module hr = DetermineServerCustomModule( pComp, FALSE); // exit _JumpIfError(hr, error, "DetermineServerCustomModule"); } if (!s_fPreUninstall) { hr = PreUninstallCore( hwnd, pComp, certocmPreserving(pComp, cscClient)); _JumpIfError(hr, error, "PreUninstallCore"); s_fPreUninstall = TRUE; } } if ((pComp->dwInstallStatus & psc->ChangeFlags) || (pComp->dwInstallStatus & psc->UpgradeFlags) ) { // Being installed or uninstalled. // Fetch [un]install/upgrade section name. if (pComp->dwInstallStatus & psc->InstallFlags) { pwszAction = wszINSTALL; } else if (pComp->dwInstallStatus & psc->UninstallFlags) { pwszAction = wszUNINSTALL; } else if (pComp->dwInstallStatus & psc->UpgradeFlags) { pwszAction = wszUPGRADE; } else { hr = E_INVALIDARG; _JumpError(hr, error, "Internal error"); } hr = certocmReadInfString( pComp->MyInfHandle, NULL, psc->pwszSubComponent, pwszAction, &pwsz); _JumpIfError(hr, error, "certocmReadInfString"); // If uninstalling, copy files without version checks. if (!SetupInstallFilesFromInfSection( pComp->MyInfHandle, NULL, hFileQueue, pwsz, NULL, fRemoveFile? 0 : SP_COPY_NEWER)) { hr = myHLastError(); _JumpIfError(hr, error, "SetupInstallFilesFromInfSection"); } } } done: hr = S_OK; error: if (NULL != pwsz) { LocalFree(pwsz); } if (S_OK != hr) { SetLastError(hr); } *pulpRet = hr; return(hr); } // OCM calls this routine when it wants to find out how much work the component // wants to perform for nonfile operations to install/uninstall a component or // subcomponent. It is called once for the *entire* component and then once // for each subcomponent in the component. One could get arbitrarily fancy // here but we simply return 1 step per subcomponent. We ignore the "entire // component" case. // // Return value is an arbitrary 'step' count or -1 if error. HRESULT certocmOcQueryStepCount( IN WCHAR const *pwszComponent, OPTIONAL IN WCHAR const *pwszSubComponent, OUT ULONG_PTR *pulpRet) { HRESULT hr; *pulpRet = 0; DBGPRINT(( DBG_SS_CERTOCMI, "OC_QUERY_STEP_COUNT(%ws, %ws)\n", pwszComponent, pwszSubComponent)); // Ignore all but "entire component" case. if (NULL != pwszSubComponent) { goto done; } *pulpRet = SERVERINSTALLTICKS; done: hr = S_OK; //error: return hr; } // OCM calls this routine when it wants the component dll to perform nonfile // ops to install/uninstall a component/subcomponent. It is called once for // the *entire* component and then once for each subcomponent in the component. // Our install and uninstall actions are based on simple standard inf install // sections. We ignore the "entire component" case. Note how similar this // code is to the OC_QUEUE_FILE_OPS case. HRESULT certocmOcCompleteInstallation( HWND hwnd, IN WCHAR const *pwszComponent, OPTIONAL IN WCHAR const *pwszSubComponent, IN OUT PER_COMPONENT_DATA *pComp, OUT ULONG_PTR *pulpRet) { HRESULT hr; TCHAR wszBuffer[cwcINFVALUE]; SUBCOMP const *psc; WCHAR *pwsz = NULL; DWORD dwSetupStatusFlags; CASERVERSETUPINFO *pServer = pComp->CA.pServer; WCHAR *pwszActiveCA = NULL; static BOOL fStoppedW3SVC = FALSE; *pulpRet = 0; DBGPRINT(( DBG_SS_CERTOCMI, "OC_COMPLETE_INSTALLATION(%ws, %ws)\n", pwszComponent, pwszSubComponent)); // Do no work for top level component if (NULL == pwszSubComponent) { goto done; } psc = TranslateSubComponent(pwszComponent, pwszSubComponent); if (NULL == psc) { hr = E_INVALIDARG; _JumpError(hr, error, "Internal error: unsupported component"); } if (pComp->dwInstallStatus & IS_SERVER_REMOVE) { // for uninstall, check if active ca use DS hr = myGetCertRegStrValue(NULL, NULL, NULL, wszREGACTIVE, &pwszActiveCA); if (S_OK == hr && NULL != pwszActiveCA) { hr = myGetCertRegDWValue(pwszActiveCA, NULL, NULL, wszREGCAUSEDS, (DWORD*)&pServer->fUseDS); _PrintIfError(hr, "myGetCertRegDWValue"); } } DBGPRINT(( DBG_SS_CERTOCMI, "certocmOcCompleteInstallation: pComp->dwInstallStatus: %lx, pComp->Flags: %lx\n", pComp->dwInstallStatus, pComp->Flags)); if ((pComp->dwInstallStatus & psc->ChangeFlags) || (pComp->dwInstallStatus & psc->UpgradeFlags) ) { // for unattended, make sure w3svc is stopped before file copy if (!fStoppedW3SVC && pComp->fUnattended && !(pComp->Flags & SETUPOP_NTUPGRADE) && !(pComp->dwInstallStatus & psc->UninstallFlags) ) { //fStoppedW3SVC makes stop only once //don't do this in upgrade // this happens for unattended // also not during uninstall hr = StartAndStopService(pComp->hInstance, pComp->fUnattended, hwnd, wszW3SVCNAME, TRUE, FALSE, 0, // doesn't matter since no confirmation &g_fW3SvcRunning); _PrintIfError(hr, "StartAndStopService"); fStoppedW3SVC = TRUE; } // certsrv file copy if (!SetupInstallFromInfSection( NULL, pComp->MyInfHandle, wszBuffer, SPINST_INIFILES | SPINST_REGISTRY, NULL, NULL, 0, NULL, NULL, NULL, NULL)) { hr = myHLastError(); _JumpError(hr, error, "SetupInstallFromInfSection"); } // Finish uninstalling the core if: // this subcomponent is being uninstalled, and // this is a core subcomponent (client or server), and // this is the server subcomponent, or the server isn't being removed. if ( (pComp->dwInstallStatus & psc->UninstallFlags) && (cscServer == psc->cscSubComponent || !(IS_SERVER_REMOVE & pComp->dwInstallStatus) ) ) { // Do uninstall work hr = UninstallCore( hwnd, pComp, 0, 100, certocmPreserving(pComp, cscClient), TRUE, FALSE); _JumpIfError(hr, error, "UninstallCore"); if (certocmPreserving(pComp, cscClient)) { hr = SetSetupStatus(NULL, SETUP_CLIENT_FLAG, TRUE); _JumpIfError(hr, error, "SetSetupStatus"); } else { // unmark all hr = SetSetupStatus(NULL, 0xFFFFFFFF, FALSE); _JumpIfError(hr, error, "SetSetupStatus"); } } // Finish installing the core if: // this subcomponent is being installed, and // this is a core subcomponent (client or server), and // this is the server subcomponent, or the server isn't being installed. // and this is not base setup (we'll do it later if it is) else if ((pComp->dwInstallStatus & psc->InstallFlags) && (cscServer == psc->cscSubComponent || !(IS_SERVER_INSTALL & pComp->dwInstallStatus)) && (0 != (pComp->Flags & SETUPOP_STANDALONE))) { DBGPRINT(( DBG_SS_CERTOCMI, "Performing standalone server installation\n")); hr = InstallCore(hwnd, pComp, cscServer == psc->cscSubComponent); _JumpIfError(hr, error, "InstallCore"); // last enough to mark complete if (pComp->dwInstallStatus & IS_SERVER_INSTALL) { // machine hr = SetSetupStatus(NULL, SETUP_SERVER_FLAG, TRUE); _JumpIfError(hr, error, "SetSetupStatus"); // ca hr = SetSetupStatus( pServer->pwszSanitizedName, SETUP_SERVER_FLAG, TRUE); _JumpIfError(hr, error, "SetSetupStatus"); if(IsEnterpriseCA(pServer->CAType)) { hr = SetSetupStatus( pServer->pwszSanitizedName, SETUP_UPDATE_CAOBJECT_SVRTYPE, TRUE); _JumpIfError(hr, error, "SetSetupStatus SETUP_UPDATE_CAOBJECT_SVRTYPE"); } hr = GetSetupStatus(pServer->pwszSanitizedName, &dwSetupStatusFlags); _JumpIfError(hr, error, "SetSetupStatus"); // Only start the server if: // 1: we're not waiting for the CA cert to be issued, and // 2: this is not base setup -- SETUP_STANDALONE means we're // running from the Control Panel or were manually invoked. // The server will not start during base setup due to an // access denied error from JetInit during base setup. if (0 == (SETUP_SUSPEND_FLAG & dwSetupStatusFlags) && (0 != (SETUPOP_STANDALONE & pComp->Flags))) { hr = StartCertsrvService(FALSE); _PrintIfError(hr, "failed in starting cert server service"); } // during base setup: f=0 sus=8 DBGPRINT(( DBG_SS_CERTOCMI, "InstallCore: f=%x sus=%x\n", pComp->Flags, dwSetupStatusFlags)); hr = EnableVRootsAndShares(FALSE, FALSE, TRUE, pComp); _PrintIfError(hr, "failed creating VRoots/shares"); } if (pComp->dwInstallStatus & IS_CLIENT_INSTALL) { hr = SetSetupStatus(NULL, SETUP_CLIENT_FLAG, TRUE); _JumpIfError(hr, error, "SetSetupStatus"); } if ((pComp->dwInstallStatus & IS_SERVER_INSTALL) && (pComp->dwInstallStatus & IS_CLIENT_INSTALL)) { hr = SetSetupStatus( pServer->pwszSanitizedName, SETUP_CLIENT_FLAG, TRUE); _JumpIfError(hr, error, "SetSetupStatus"); } // in case we're doing a post-base setup, // we always clear the post-base to-do list RegDeleteKey(HKEY_LOCAL_MACHINE, wszREGKEYCERTSRVTODOLIST); } else if ((pComp->dwInstallStatus & psc->InstallFlags) && (cscServer == psc->cscSubComponent || !(IS_SERVER_INSTALL & pComp->dwInstallStatus)) && (0 == (pComp->Flags & (SETUPOP_STANDALONE | SETUPOP_WIN31UPGRADE | SETUPOP_WIN95UPGRADE | SETUPOP_NTUPGRADE) ))) { HKEY hkToDoList = NULL; WCHAR *pwszConfigTitleVal = NULL; WCHAR *pwszArgsValTemp = NULL; WCHAR *pwszArgsVal = wszCONFIGARGSVAL; BOOL fFreeTitle = FALSE; DWORD disp; DWORD err; DBGPRINT(( DBG_SS_CERTOCMI, "Adding Certificate Services to ToDoList\n")); // We're installing base, so create // the ToDoList entry stating that we copied files. err = ::RegCreateKeyEx(HKEY_LOCAL_MACHINE, wszREGKEYCERTSRVTODOLIST, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkToDoList, &disp); hr = HRESULT_FROM_WIN32(err); _JumpIfError(hr, error, "RegCreateKeyEx"); hr = myLoadRCString( g_hInstance, IDS_TODO_TITLE, &pwszConfigTitleVal); if (S_OK == hr) { fFreeTitle = TRUE; } else { // If there was no resource, get something... pwszConfigTitleVal = wszCONFIGTITLEVAL; } // config title err = RegSetValueEx(hkToDoList, wszCONFIGTITLE, 0, REG_SZ, (PBYTE)pwszConfigTitleVal, sizeof(WCHAR)*(wcslen(pwszConfigTitleVal)+1)); hr = HRESULT_FROM_WIN32(err); _PrintIfErrorStr(hr, "RegSetValueEx", wszCONFIGTITLE); CSILOG(hr, IDS_LOG_TODOLIST, wszCONFIGTITLE, pwszConfigTitleVal, NULL); // config command err = RegSetValueEx(hkToDoList, wszCONFIGCOMMAND, 0, REG_SZ, (PBYTE)wszCONFIGCOMMANDVAL, sizeof(WCHAR)*(wcslen(wszCONFIGCOMMANDVAL)+1)); hr = HRESULT_FROM_WIN32(err); _PrintIfErrorStr(hr, "RegSetValueEx", wszCONFIGCOMMAND); CSILOG(hr, IDS_LOG_TODOLIST, wszCONFIGCOMMAND, wszCONFIGCOMMANDVAL, NULL); // config args if (pComp->fUnattended && NULL != pComp->pwszUnattendedFile) { // if nt base is in unattended mode, expand args with // unattended answer file name pwszArgsValTemp = (WCHAR*)LocalAlloc(LMEM_FIXED, (wcslen(pwszArgsVal) + wcslen(pComp->pwszUnattendedFile) + 5) * sizeof(WCHAR)); _JumpIfOutOfMemory(hr, error, pwszArgsValTemp); wcscpy(pwszArgsValTemp, pwszArgsVal); wcscat(pwszArgsValTemp, L" /u:"); wcscat(pwszArgsValTemp, pComp->pwszUnattendedFile); pwszArgsVal = pwszArgsValTemp; } err = RegSetValueEx(hkToDoList, wszCONFIGARGS, 0, REG_SZ, (PBYTE)pwszArgsVal, sizeof(WCHAR)*(wcslen(pwszArgsVal)+1)); hr = HRESULT_FROM_WIN32(err); _PrintIfErrorStr(hr, "RegSetValueEx", wszCONFIGARGS); CSILOG(hr, IDS_LOG_TODOLIST, wszCONFIGARGS, pwszArgsVal, NULL); // free stuff if (NULL != pwszConfigTitleVal && fFreeTitle) { LocalFree(pwszConfigTitleVal); } if (NULL != pwszArgsValTemp) { LocalFree(pwszArgsValTemp); } if (NULL != hkToDoList) { RegCloseKey(hkToDoList); } } else if (pComp->dwInstallStatus & psc->UpgradeFlags) { BOOL fFinishCYS; hr = CheckPostBaseInstallStatus(&fFinishCYS); _JumpIfError(hr, error, "CheckPostBaseInstallStatus"); // if post mode is true, don't execute setup upgrade path if (fFinishCYS) { BOOL fServer = FALSE; // upgrade if (cscServer == psc->cscSubComponent) { hr = UpgradeServer(hwnd, pComp); _JumpIfError(hr, error, "UpgradeServer"); fServer = TRUE; } else if (cscClient == psc->cscSubComponent) { hr = UpgradeClient(hwnd, pComp); _JumpIfError(hr, error, "UpgradeClient"); } // mark setup status hr = SetSetupStatus(NULL, psc->SetupStatusFlags, TRUE); _PrintIfError(hr, "SetSetupStatus"); if (fServer) { // ca level hr = SetSetupStatus( pServer->pwszSanitizedName, psc->SetupStatusFlags, TRUE); _PrintIfError(hr, "SetSetupStatus"); if(IsEnterpriseCA(pServer->CAType)) { hr = SetSetupStatus( pServer->pwszSanitizedName, SETUP_UPDATE_CAOBJECT_SVRTYPE, TRUE); _JumpIfError(hr, error, "SetSetupStatus SETUP_UPDATE_CAOBJECT_SVRTYPE"); } } if (fServer && pServer->fCertSrvWasRunning) { hr = StartCertsrvService(TRUE); _PrintIfError(hr, "failed in starting cert server service"); } } } } done: hr = S_OK; error: if (NULL != pwszActiveCA) { LocalFree(pwszActiveCA); } *pulpRet = hr; return(hr); } HRESULT certocmOcCommitQueue( IN HWND hwnd, IN WCHAR const *pwszComponent, IN WCHAR const *pwszSubComponent, IN PER_COMPONENT_DATA *pComp) { HRESULT hr; SUBCOMP *pSub; CASERVERSETUPINFO *pServer = pComp->CA.pServer; DBGPRINT(( DBG_SS_CERTOCMI, "OC_ABOUT_TO_COMMIT_QUEUE(%ws, %ws)\n", pwszComponent, pwszSubComponent)); pSub = TranslateSubComponent(pwszComponent, pwszSubComponent); if (NULL == pSub) { goto done; } // setup will satrt soon, mark it incomplete if ((pSub->InstallFlags & pComp->dwInstallStatus) && cscServer == pSub->cscSubComponent) { hr = SetSetupStatus(NULL, pSub->SetupStatusFlags, FALSE); _PrintIfError(hr, "SetSetupStatus"); hr = SetSetupStatus( pServer->pwszSanitizedName, pSub->SetupStatusFlags, FALSE); _PrintIfError(hr, "SetSetupStatus"); } if ((cscServer == pSub->cscSubComponent) && (pSub->UpgradeFlags & pComp->dwInstallStatus) ) { // upgrade case, no UI, stop existing certsrv hr = StartAndStopService(pComp->hInstance, pComp->fUnattended, hwnd, wszSERVICE_NAME, TRUE, // stop the service FALSE, // no confirm 0, //doesn't matter since no confirm &pServer->fCertSrvWasRunning); _PrintIfError(hr, "ServiceExists"); } done: hr = S_OK; //error: return hr; } // Component dll is being unloaded. VOID certocmOcCleanup( IN WCHAR const *pwszComponent, IN PER_COMPONENT_DATA *pComp) { DBGPRINT((DBG_SS_CERTOCMI, "OC_CLEANUP(%ws)\n", pwszComponent)); if (NULL != pComp->pwszComponent) { if (0 == lstrcmpi(pComp->pwszComponent, pwszComponent)) { FreeCAComponentInfo(pComp); } } // also free some globals FreeCAGlobals(); } ///////////////////////////////////////////////////////////////////////////// //++ // // certocmOcQueryState // // Routine Description: // This funcion sets the original, current, and final selection states of the // CertSrv service optional component. // // Return Value: // SubcompOn - indicates that the checkbox should be set // SubcompOff - indicates that the checkbox should be clear // SubcompUseOCManagerDefault - OC Manager should set the state of the checkbox // according to state information that is maintained // internally by OC Manager itself. // // Note: // By the time this function gets called OnOcInitComponent has already determined // that Terminal Services is not installed. It is only necessary to determine // whether Terminal Services is selected for installation. //-- ///////////////////////////////////////////////////////////////////////////// HRESULT certocmOcQueryState( IN WCHAR const *pwszComponent, OPTIONAL IN WCHAR const *pwszSubComponent, IN DWORD SelectionState, IN PER_COMPONENT_DATA *pComp, OUT ULONG_PTR *pulpRet) { HRESULT hr; SubComponentState stateRet = SubcompUseOcManagerDefault; DWORD status; WCHAR awc[20]; BOOL fFinished; DBGPRINT(( DBG_SS_CERTOCMI, "OC_QUERY_STATE(%ws, %ws, %x)\n", pwszComponent, pwszSubComponent, SelectionState)); if (NULL == pwszSubComponent) { goto done; } switch(SelectionState) { case OCSELSTATETYPE_ORIGINAL: { // check to see if the post link exist hr = CheckPostBaseInstallStatus(&fFinished); _JumpIfError(hr, error, "CheckPostBaseInstallStatus"); if (!pComp->fPostBase && (SETUPOP_STANDALONE & pComp->Flags) ) { // install through Components button if (!fFinished) { // don't honor local reg SetupStatus break; } } // Return the initial installation state of the subcomponent if (!pComp->fPostBase && ((SETUPOP_STANDALONE & pComp->Flags) || (SETUPOP_NTUPGRADE & pComp->Flags)) ) { //there is chance for user installed certsrv during base setup //and then upgrade without finishing CYS if (fFinished) { // If this is an upgrade or a standalone, query the registry to // get the current installation status // XTAN, 7/99 // currently certsrv_server has Needs relationship with // certsrv_client. OCM gathers success for certsrv_client before // certsrv_server is complete so we don't trust OCM state info // about certsrv_client and we check our reg SetupStatus here. // our certsrv_server Needs define is incorrect. If we take it // out, we probably don't need to reg SetupStatus at // Configuration level at all and we can trust OCM state info hr = GetSetupStatus(NULL, &status); if (S_OK == hr) { if ( (0 == lstrcmpi(wszSERVERSECTION, pwszSubComponent) && !(SETUP_SERVER_FLAG & status)) || (0 == lstrcmpi(wszCLIENTSECTION, pwszSubComponent) && !(SETUP_CLIENT_FLAG & status)) ) { // overwrite OCM default stateRet = SubcompOff; } } } } break; } case OCSELSTATETYPE_CURRENT: { break; } case OCSELSTATETYPE_FINAL: { SUBCOMP const *psc; BOOL fWasEnabled; if (S_OK != pComp->hrContinue && !pComp->fUnattended) { stateRet = SubcompOff; } //get component install info psc = TranslateSubComponent(pwszComponent, pwszSubComponent); if (NULL == psc) { hr = E_INVALIDARG; _JumpError(hr, error, "Internal error: unsupported component"); } fWasEnabled = certocmWasEnabled(pComp, psc->cscSubComponent); // after all of this, change upgrade->uninstall if not supported if ((SETUPOP_NTUPGRADE & pComp->Flags) && fWasEnabled) { CSASSERT(pComp->UpgradeFlag != CS_UPGRADE_UNKNOWN); if (CS_UPGRADE_UNSUPPORTED == pComp->UpgradeFlag) stateRet = SubcompOff; } break; } } done: hr = S_OK; error: wsprintf(awc, L"%u", SelectionState); CSILOG(S_OK, IDS_LOG_SELECTIONSTATE, awc, NULL, (DWORD const *) &stateRet); *pulpRet = stateRet; return(hr); } //+------------------------------------------------------------------------ // // Function: CertSrvOCProc( . . . . ) // // Synopsis: Service procedure for Cert Server OCM Setup. // // Arguments: [pwszComponent] // [pwszSubComponent] // [Function] // [Param1] // [Param2] // // Returns: DWORD // // History: 04/07/97 JerryK Created // //------------------------------------------------------------------------- ULONG_PTR CertSrvOCProc( IN WCHAR const *pwszComponent, IN WCHAR const *pwszSubComponent, IN UINT Function, IN UINT_PTR Param1, IN OUT VOID *Param2) { ULONG_PTR ulpRet = 0; WCHAR const *pwszFunction = NULL; BOOL fReturnErrCode = TRUE; __try { switch (Function) { // OC_PREINITIALIZE: // pwszComponent = WCHAR top level component string // pwszSubComponent = CHAR top level component string // Param1 = char width flags // Param2 = unused // // Return code is char width allowed flags case OC_PREINITIALIZE: csiLogOpen("+certocm.log"); pwszFunction = L"OC_PREINITIALIZE"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_PREINITIALIZE"); g_Comp.hrContinue = certocmOcPreInitialize( pwszComponent, (UINT)Param1, //cast to UINT, use as flags &ulpRet); break; // OC_INIT_COMPONENT: // pwszComponent = WCHAR top level component string // pwszSubComponent = unused // Param1 = unused // Param2 = points to IN OUT SETUP_INIT_COMPONENT structure // // Return code is Win32 error indicating outcome. case OC_INIT_COMPONENT: pwszFunction = L"OC_INIT_COMPONENT"; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_INIT_COMPONENT"); g_Comp.hrContinue = certocmOcInitComponent( NULL, // probably have to pass null hwnd pwszComponent, (SETUP_INIT_COMPONENT *) Param2, &g_Comp, &ulpRet); break; case OC_SET_LANGUAGE: pwszFunction = L"OC_SET_LANGUAGE"; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_SET_LANGUAGE"); DBGPRINT(( DBG_SS_CERTOCMI, "OC_SET_LANGUAGE(%ws, %ws, %x, %x)\n", pwszComponent, pwszSubComponent, Param1, Param2)); break; // OC_QUERY_IMAGE: // pwszComponent = WCHAR top level component string // pwszSubComponent = WCHAR sub-component string // Param1 = low 16 bits specify image; only small icon supported // Param2 = low 16 bits = desired width, high 16 bits = desired height // // Return value is the GDI handle of a small bitmap to be used. case OC_QUERY_IMAGE: pwszFunction = L"OC_QUERY_IMAGE"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_IMAGE"); g_Comp.hrContinue = certocmOcQueryImage( pwszComponent, pwszSubComponent, (SubComponentInfo) LOWORD(Param1), LOWORD((ULONG_PTR) Param2), HIWORD((ULONG_PTR) Param2), &g_Comp, &ulpRet); break; // OC_REQUEST_PAGES: // pwszComponent = WCHAR top level component string // pwszSubComponent = unused // Param1 = Type of wiz pages being requested (WizardPagesType enum) // Param2 = points to IN OUT SETUP_REQUEST_PAGES structure // // Return value is number of pages the component places in the // SETUP_REQUEST_PAGES structure. case OC_REQUEST_PAGES: pwszFunction = L"OC_REQUEST_PAGES"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_REQUEST_PAGES"); g_Comp.hrContinue = certocmOcRequestPages( pwszComponent, (WizardPagesType) Param1, (SETUP_REQUEST_PAGES *) Param2, &g_Comp, &ulpRet); break; // OC_QUERY_CHANGE_SEL_STATE: // pwszComponent = WCHAR top level component string // pwszSubComponent = WCHAR sub-component string // Param1 = proposed new sel state; 0 = unselected, non 0 = selected // Param2 = flags -- OCQ_ACTUAL_SELECTION // // Return boolean to indicate whether to allow selection state change case OC_QUERY_CHANGE_SEL_STATE: pwszFunction = L"OC_QUERY_CHANGE_SEL_STATE"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_CHANGE_SEL_STATE"); g_Comp.hrContinue = certocmOcQueryChangeSelState( g_Comp.HelperRoutines.QueryWizardDialogHandle(g_Comp.HelperRoutines.OcManagerContext), pwszComponent, pwszSubComponent, (BOOL) Param1, (DWORD) (ULONG_PTR) Param2, &g_Comp, &ulpRet); break; // OC_CALC_DISK_SPACE: // pwszComponent = WCHAR top level component string // pwszSubComponent = WCHAR sub-component string // Param1 = 0 for removing component or non 0 for adding component // Param2 = HDSKSPC to operate on // // Return value is Win32 error code indicating outcome. case OC_CALC_DISK_SPACE: pwszFunction = L"OC_CALC_DISK_SPACE"; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_CALC_DISK_SPACE"); g_Comp.hrContinue = certocmOcCalcDiskSpace( pwszComponent, pwszSubComponent, (BOOL) Param1, (HDSKSPC) Param2, &g_Comp, &ulpRet); break; // OC_QUEUE_FILE_OPS: // pwszComponent = WCHAR top level component string // pwszSubComponent = WCHAR sub-component string // Param1 = unused // Param2 = HSPFILEQ to operate on // // Return value is Win32 error code indicating outcome. case OC_QUEUE_FILE_OPS: pwszFunction = L"OC_QUEUE_FILE_OPS"; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_QUEUE_FILE_OPS"); g_Comp.hrContinue = certocmOcQueueFileOps( g_Comp.HelperRoutines.QueryWizardDialogHandle(g_Comp.HelperRoutines.OcManagerContext), pwszComponent, pwszSubComponent, (HSPFILEQ) Param2, &g_Comp, &ulpRet); break; // Params? xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // OC_NOTIFICATION_FROM_QUEUE: // pwszComponent = WCHAR top level component string // pwszSubComponent = unused // Param1 = unused // Param2 = unused // // Return value is ??? case OC_NOTIFICATION_FROM_QUEUE: pwszFunction = L"OC_NOTIFICATION_FROM_QUEUE"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); DBGPRINT(( DBG_SS_CERTOCMI, "OC_NOTIFICATION_FROM_QUEUE(%ws, %ws, %x, %x)\n", pwszComponent, pwszSubComponent, Param1, Param2)); break; // OC_QUERY_STEP_COUNT: // pwszComponent = WCHAR top level component string // pwszSubComponent = WCHAR sub-component string // Param1 = unused // Param2 = unused // // Return value is an arbitrary 'step' count or -1 if error. case OC_QUERY_STEP_COUNT: pwszFunction = L"OC_QUERY_STEP_COUNT"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_STEP_COUNT"); g_Comp.hrContinue = (DWORD) certocmOcQueryStepCount( pwszComponent, pwszSubComponent, &ulpRet); break; // OC_COMPLETE_INSTALLATION: // pwszComponent = WCHAR top level component string // pwszSubComponent = WCHAR sub-component string // Param1 = reserved for future expansion // Param2 = unused // // Return value is Win32 error code indicating outcome. case OC_COMPLETE_INSTALLATION: pwszFunction = L"OC_COMPLETE_INSTALLATION"; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_COMPLETE_INSTALLATION"); g_Comp.hrContinue = certocmOcCompleteInstallation( g_Comp.HelperRoutines.QueryWizardDialogHandle(g_Comp.HelperRoutines.OcManagerContext), pwszComponent, pwszSubComponent, &g_Comp, &ulpRet); break; // OC_CLEANUP: // pwszComponent = WCHAR top level component string // pwszSubComponent = unused // Param1 = unused // Param2 = unused // // Return value is ignored case OC_CLEANUP: // don't _LeaveIfError(g_Comp.hrContinue, "OC_CLEANUP"); // avoid memory leaks pwszFunction = L"OC_CLEANUP"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); certocmOcCleanup(pwszComponent, &g_Comp); break; // Params? xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // OC_QUERY_STATE: // pwszComponent = WCHAR top level component string // pwszSubComponent = WCHAR sub-component string // Param1 = unused? (but Index Server uses it for current state)! // Param2 = unused // // Return value is from the SubComponentState enumerated type case OC_QUERY_STATE: pwszFunction = L"OC_QUERY_STATE"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); //don't _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_STATE"); certocmOcQueryState( pwszComponent, pwszSubComponent, (DWORD)Param1, //cast to DWORD, use as flags &g_Comp, &ulpRet); break; // Params? xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // OC_NEED_MEDIA: // pwszComponent = WCHAR top level component string // pwszSubComponent = WCHAR sub-component string // Param1 = unused // Param2 = unused // // Return value is ??? case OC_NEED_MEDIA: pwszFunction = L"OC_NEED_MEDIA"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); DBGPRINT(( DBG_SS_CERTOCMI, "OC_NEED_MEDIA(%ws, %ws, %x, %x)\n", pwszComponent, pwszSubComponent, Param1, Param2)); break; // OC_ABOUT_TO_COMMIT_QUEUE: // pwszComponent = WCHAR top level component string // pwszSubComponent = WCHAR sub-component string // Param1 = reserved for future expansion // Param2 = unused // // Return value is Win32 error code indicating outcome. case OC_ABOUT_TO_COMMIT_QUEUE: pwszFunction = L"OC_ABOUT_TO_COMMIT_QUEUE"; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_ABOUT_TO_COMMIT_QUEUE"); g_Comp.hrContinue = certocmOcCommitQueue( g_Comp.HelperRoutines.QueryWizardDialogHandle(g_Comp.HelperRoutines.OcManagerContext), pwszComponent, pwszSubComponent, &g_Comp); break; // OC_QUERY_SKIP_PAGE: // pwszComponent = WCHAR top level component string // pwszSubComponent = unused // Param1 = OcManagerPage page indicator // Param2 = unused // // Return value is a boolean -- 0 for display or non 0 for skip case OC_QUERY_SKIP_PAGE: pwszFunction = L"OC_QUERY_SKIP_PAGE"; fReturnErrCode = FALSE; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); DBGPRINT(( DBG_SS_CERTOCMI, "OC_QUERY_SKIP_PAGE(%ws, %x)\n", pwszComponent, (OcManagerPage) Param1)); _LeaveIfError(g_Comp.hrContinue, "OC_QUERY_SKIP_PAGE"); if (g_Comp.fPostBase && (WizardPagesType) Param1 == WizPagesWelcome) { ulpRet = 1; // non 0 to skip wiz page } break; // OC_WIZARD_CREATED: // pwszComponent = WCHAR top level component string // pwszSubComponent = ??? // Param1 = ??? // Param2 = ??? // // Return value is ??? case OC_WIZARD_CREATED: pwszFunction = L"OC_WIZARD_CREATED"; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_WIZARD_CREATED"); break; // OC_EXTRA_ROUTINES: // pwszComponent = WCHAR top level component string // pwszSubComponent = ??? // Param1 = ??? // Param2 = ??? // // Return value is ??? case OC_EXTRA_ROUTINES: pwszFunction = L"OC_EXTRA_ROUTINES"; CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL); _LeaveIfError(g_Comp.hrContinue, "OC_EXTRA_ROUTINES"); break; // Some other notification: default: fReturnErrCode = FALSE; CSILOG( g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, (DWORD const *) &Function); DBGPRINT(( DBG_SS_CERTOCMI, "DEFAULT(0x%x: %ws, %ws, %x, %x)\n", Function, pwszComponent, pwszSubComponent, Param1, Param2)); break; } } __except(ulpRet = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { if (S_OK == g_Comp.hrContinue) { g_Comp.hrContinue = (HRESULT)ulpRet; } _PrintError((HRESULT)ulpRet, "Exception"); } DBGPRINT((DBG_SS_CERTOCMI, "return %p\n", ulpRet)); // make sure to get a pop up in case of fatal error if (S_OK != g_Comp.hrContinue) { if (!g_Comp.fShownErr) { int iMsgId = g_Comp.iErrMsg; if (0 == iMsgId) { // use generic one iMsgId = IDS_ERR_CERTSRV_SETUP_FAIL; } CertErrorMessageBox( g_Comp.hInstance, g_Comp.fUnattended, NULL, // null hwnd iMsgId, g_Comp.hrContinue, g_Comp.pwszCustomMessage); g_Comp.fShownErr = TRUE; } // anything fails, cancel install HRESULT hr2 = CancelCertsrvInstallation(NULL, &g_Comp); _PrintIfError(hr2, "CancelCertsrvInstallation"); } CSILOG( fReturnErrCode? (HRESULT) ulpRet : S_OK, IDS_LOG_END, pwszFunction, pwszSubComponent, fReturnErrCode? NULL : (DWORD const *) &ulpRet); return(ulpRet); } ULONG_PTR CertSrvOCPostProc( IN WCHAR const *pwszComponent, IN WCHAR const *pwszSubComponent, IN UINT Function, IN UINT Param1, IN OUT VOID *Param2) { // post setup entry point // by going through this path, we know it is invoked in post setup g_Comp.fPostBase = TRUE; return CertSrvOCProc( pwszComponent, pwszSubComponent, Function, Param1, Param2); } VOID certocmBumpGasGauge( OPTIONAL IN PER_COMPONENT_DATA *pComp, IN DWORD PerCentComplete DBGPARM(IN WCHAR const *pwszSource)) { static DWORD dwTickCount = 0; if (NULL != pComp) { DWORD NewCount; NewCount = (PerCentComplete * SERVERINSTALLTICKS)/100; DBGPRINT(( DBG_SS_CERTOCMI, "certocmBumpGasGauge(%ws, %u%%) %d ticks: %d --> %d\n", pwszSource, PerCentComplete, NewCount - dwTickCount, dwTickCount, NewCount)); if (SERVERINSTALLTICKS < NewCount) { NewCount = SERVERINSTALLTICKS; } while (dwTickCount < NewCount) { (*pComp->HelperRoutines.TickGauge)( pComp->HelperRoutines.OcManagerContext); dwTickCount++; } } } BOOL certocmEnabledSub( PER_COMPONENT_DATA *pComp, CertSubComponent SubComp, DWORD SelectionStateType) { SUBCOMP const *psc; BOOL bRet = FALSE; psc = LookupSubComponent(SubComp); if (NULL != psc->pwszSubComponent) { if (pComp->fUnattended && OCSELSTATETYPE_CURRENT == SelectionStateType && 0 == (pComp->Flags & SETUPOP_NTUPGRADE) ) { // unattended case, flags from unattended file // upgrade is automatically in unattended mode and make sure // to exclude it bRet = psc->fInstallUnattend; } else { bRet = (*pComp->HelperRoutines.QuerySelectionState)( pComp->HelperRoutines.OcManagerContext, psc->pwszSubComponent, SelectionStateType); } } return(bRet); } BOOL certocmIsEnabled( PER_COMPONENT_DATA *pComp, CertSubComponent SubComp) { BOOL bRet; bRet = certocmEnabledSub(pComp, SubComp, OCSELSTATETYPE_CURRENT); if (!fDebugSupress) { DBGPRINT(( DBG_SS_CERTOCMI, "certocmIsEnabled(%ws) Is %ws\n", LookupSubComponent(SubComp)->pwszSubComponent, bRet? L"Enabled" : L"Disabled")); } return(bRet); } BOOL certocmWasEnabled( PER_COMPONENT_DATA *pComp, CertSubComponent SubComp) { BOOL bRet; bRet = certocmEnabledSub(pComp, SubComp, OCSELSTATETYPE_ORIGINAL); if (!fDebugSupress) { DBGPRINT(( DBG_SS_CERTOCMI, "certocmWasEnabled(%ws) Was %ws\n", LookupSubComponent(SubComp)->pwszSubComponent, bRet? L"Enabled" : L"Disabled")); } return(bRet); } BOOL certocmUninstalling( PER_COMPONENT_DATA *pComp, CertSubComponent SubComp) { BOOL bRet; fDebugSupress++; bRet = certocmWasEnabled(pComp, SubComp) && !certocmIsEnabled(pComp, SubComp); fDebugSupress--; if (!fDebugSupress) { DBGPRINT(( DBG_SS_CERTOCMI, "certocmUninstalling(%ws) %ws\n", LookupSubComponent(SubComp)->pwszSubComponent, bRet? L"TRUE" : L"False")); } return(bRet); } BOOL certocmInstalling( PER_COMPONENT_DATA *pComp, CertSubComponent SubComp) { BOOL bRet; fDebugSupress++; bRet = !certocmWasEnabled(pComp, SubComp) && certocmIsEnabled(pComp, SubComp); fDebugSupress--; if (!fDebugSupress) { DBGPRINT(( DBG_SS_CERTOCMI, "certocmInstalling(%ws) %ws\n", LookupSubComponent(SubComp)->pwszSubComponent, bRet? L"TRUE" : L"False")); } return(bRet); } BOOL certocmPreserving( PER_COMPONENT_DATA *pComp, CertSubComponent SubComp) { BOOL bRet; fDebugSupress++; bRet = certocmWasEnabled(pComp, SubComp) && certocmIsEnabled(pComp, SubComp); fDebugSupress--; if (!fDebugSupress) { DBGPRINT(( DBG_SS_CERTOCMI, "certocmPreserving(%ws) %ws\n", LookupSubComponent(SubComp)->pwszSubComponent, bRet? L"TRUE" : L"False")); } return(bRet); }