windows-nt/Source/XPSP1/NT/ds/security/services/ca/ocmsetup/csocm.cpp

2844 lines
82 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+-------------------------------------------------------------------------
//
// 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.
//
// [<pwszComponent>,<pwszSubComponent>]
// Bitmap = <bitmapresourcename>
// 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);
}