You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2908 lines
88 KiB
2908 lines
88 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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 <common.ver>
|
|
#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;
|
|
pComp->hinfCAPolicy = INVALID_HANDLE_VALUE;
|
|
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"));
|
|
|
|
if(INVALID_HANDLE_VALUE != g_Comp.hinfCAPolicy)
|
|
myInfCloseFile(g_Comp.hinfCAPolicy);
|
|
|
|
myInfClearError();
|
|
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 == mylstrcmpiL(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 *DBGPARMREFERENCED(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,
|
|
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 *DBGPARMREFERENCED(pwszFile),
|
|
IN WCHAR const *pwszSection,
|
|
IN WCHAR const *pwszName,
|
|
OUT INT *pValue)
|
|
{
|
|
INFCONTEXT InfContext;
|
|
HRESULT hr = S_OK;
|
|
|
|
*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 *DBGPARMREFERENCED(pwszComponent),
|
|
OPTIONAL IN WCHAR const *DBGPARMREFERENCED(pwszSubComponent),
|
|
IN SubComponentInfo wSubComp,
|
|
IN UINT DBGPARMREFERENCED(wWidth),
|
|
IN UINT DBGPARMREFERENCED(wHeight),
|
|
IN OUT PER_COMPONENT_DATA *pComp,
|
|
OUT HBITMAP *pulpRet)
|
|
{
|
|
HBITMAP hRet = NULL;
|
|
HRESULT hr;
|
|
|
|
DBGPRINT((
|
|
DBG_SS_CERTOCMI,
|
|
"OC_QUERY_IMAGE(%ws, %ws, %hx, %x, %x)\n",
|
|
pwszComponent,
|
|
pwszSubComponent,
|
|
wSubComp,
|
|
wWidth,
|
|
wHeight));
|
|
|
|
if (SubCompInfoSmallIcon != wSubComp)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
hRet = LoadBitmap(pComp->hInstance, MAKEINTRESOURCE(IDB_APP));
|
|
if (NULL == hRet)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, error, "LoadBitmap");
|
|
}
|
|
|
|
done:
|
|
hr = S_OK;
|
|
|
|
error:
|
|
*pulpRet = hRet;
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Return the number of wizard pages the current component places in the
|
|
// SETUP_REQUEST_PAGES structure.
|
|
|
|
HRESULT
|
|
certocmOcRequestPages(
|
|
IN WCHAR const *DBGPARMREFERENCED(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[cwcDWORDSPRINTF];
|
|
WCHAR awc2[cwcDWORDSPRINTF];
|
|
DWORD fRet;
|
|
BOOL fServerWasInstalled;
|
|
BOOL fWebClientWasInstalled;
|
|
int iMsg = 0;
|
|
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 == LSTRCMPIS(pwszSubComponent, wszSERVERSECTION) ||
|
|
0 == LSTRCMPIS(pwszSubComponent, wszCERTSRVSECTION)) )
|
|
{
|
|
// case: web client installed and try install server
|
|
iMsg = IDS_WRN_UNINSTALL_CLIENT;
|
|
}
|
|
if (fServerWasInstalled &&
|
|
0 == LSTRCMPIS(pwszSubComponent, wszCLIENTSECTION))
|
|
{
|
|
// case: uncheck both then check web client
|
|
iMsg = IDS_WRN_UNINSTALL_BOTH;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// uncheck
|
|
if (fServerWasInstalled &&
|
|
0 == LSTRCMPIS(pwszSubComponent, wszSERVERSECTION))
|
|
{
|
|
// case: full certsrv installed and try leave only web client
|
|
iMsg = IDS_WRN_UNINSTALL_BOTH;
|
|
}
|
|
}
|
|
}
|
|
|
|
// not a server sku
|
|
if (!FIsServer())
|
|
{
|
|
iMsg = IDS_WRN_SERVER_ONLY;
|
|
}
|
|
|
|
if (0 != iMsg)
|
|
{
|
|
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 != LSTRCMPIS(pwszSubComponent, wszCLIENTSECTION))
|
|
{
|
|
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,
|
|
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);
|
|
_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,
|
|
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 *DBGPARMREFERENCED(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(
|
|
IN 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;
|
|
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, hwnd);
|
|
|
|
if(REGDB_E_CLASSNOTREG == hr ||
|
|
HRESULT_FROM_WIN32(ERROR_SERVICE_DOES_NOT_EXIST) == hr ||
|
|
HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr)
|
|
{
|
|
CertWarningMessageBox(
|
|
pComp->hInstance,
|
|
pComp->fUnattended,
|
|
hwnd,
|
|
IDS_WRN_IIS_NOT_INSTALLED,
|
|
0,
|
|
NULL);
|
|
hr = S_OK;
|
|
}
|
|
_JumpIfError(hr, error, "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 == mylstrcmpiL(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[cwcDWORDSPRINTF];
|
|
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 == LSTRCMPIS(pwszSubComponent, wszSERVERSECTION) &&
|
|
!(SETUP_SERVER_FLAG & status)) ||
|
|
(0 == LSTRCMPIS(pwszSubComponent, wszCLIENTSECTION) &&
|
|
!(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;
|
|
DWORD ErrorLine;
|
|
|
|
__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");
|
|
CSILOGFILEVERSION(0, L"certocm.dll", szCSVER_STR);
|
|
|
|
pwszFunction = L"OC_PREINITIALIZE";
|
|
fReturnErrCode = FALSE;
|
|
|
|
// Make sure IDS_LOG_BEGIN & IDS_LOG_END see a Unicode string:
|
|
|
|
pwszSubComponent = pwszComponent;
|
|
|
|
CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
|
|
_LeaveIfError(g_Comp.hrContinue, "OC_PREINITIALIZE");
|
|
|
|
g_Comp.hrContinue = myInfOpenFile(NULL, &g_Comp.hinfCAPolicy, &ErrorLine);
|
|
if(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == g_Comp.hrContinue)
|
|
{
|
|
g_Comp.hrContinue = S_OK;
|
|
}
|
|
_LeaveIfError(g_Comp.hrContinue, "myInfOpenFile");
|
|
|
|
g_Comp.hrContinue = certocmOcPreInitialize(
|
|
pwszComponent,
|
|
(UINT)Param1, //cast to UINT, use as flags
|
|
&ulpRet);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcPreInitialize");
|
|
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);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcInitComponent");
|
|
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:
|
|
//
|
|
// obsolete (only called on x86 if IMAGE_EX fails)
|
|
// use OC_QUERY_IMAGE_EX instead
|
|
//
|
|
// 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,
|
|
(HBITMAP*)&ulpRet);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcQueryImage");
|
|
break;
|
|
|
|
// OC_QUERY_IMAGE_EX:
|
|
//
|
|
// pwszComponent = WCHAR top level component string
|
|
// pwszSubComponent = WCHAR sub-component string
|
|
// Param1 = [in] OC_QUERY_IMAGE_INFO*
|
|
// Param2 = [in,out] HBITMAP*
|
|
//
|
|
// Return value is S_OK or ERROR_CALL_COMPONENT
|
|
|
|
case OC_QUERY_IMAGE_EX:
|
|
pwszFunction = L"OC_QUERY_IMAGE_EX";
|
|
fReturnErrCode = FALSE;
|
|
CSILOG(g_Comp.hrContinue, IDS_LOG_BEGIN, pwszFunction, pwszSubComponent, NULL);
|
|
{
|
|
OC_QUERY_IMAGE_INFO *pocQueryImageInfo = (OC_QUERY_IMAGE_INFO *) Param1;
|
|
g_Comp.hrContinue = certocmOcQueryImage(
|
|
pwszComponent,
|
|
pwszSubComponent,
|
|
pocQueryImageInfo->ComponentInfo,
|
|
pocQueryImageInfo->DesiredWidth,
|
|
pocQueryImageInfo->DesiredHeight,
|
|
&g_Comp,
|
|
(HBITMAP *) Param2);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcQueryImage");
|
|
ulpRet = (S_OK == g_Comp.hrContinue)? TRUE:FALSE;
|
|
}
|
|
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);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcRequestPages");
|
|
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);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcQueryChangeSelState");
|
|
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);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcCalcDiskSpace");
|
|
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);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcQueueFileOps");
|
|
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);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcQueryStepCount");
|
|
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);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcCompleteInstallation");
|
|
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);
|
|
_PrintIfError(g_Comp.hrContinue, "certocmOcCommitQueue");
|
|
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);
|
|
}
|