//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997. // // File: S R V R O B J . C P P // // Contents: Implementation of CSrvrcfg and helper functions. // // Notes: // // Author: danielwe 5 Mar 1997 // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "srvrobj.h" #include "ncerror.h" #include "ncperms.h" #include "ncreg.h" #include "ncsetup.h" #include "ncsvc.h" #include "afilestr.h" static const WCHAR c_szRegKeyServerParams[] = L"System\\CurrentControlSet\\Services\\LanmanServer\\Parameters"; static const WCHAR c_szRegKeyServerShares[] = L"System\\CurrentControlSet\\Services\\LanmanServer\\Shares"; static const WCHAR c_szRegKeyServerAutoTuned[] = L"System\\CurrentControlSet\\Services\\LanmanServer\\AutotunedParameters"; //+--------------------------------------------------------------------------- // // Member: CSrvrcfg::CSrvrcfg // // Purpose: Constructs the CSrvrcfg object. // // Arguments: // (none) // // Returns: Nothing. // // Author: danielwe 5 Mar 1997 // // Notes: // CSrvrcfg::CSrvrcfg() : m_hkeyMM(NULL), m_fDirty(FALSE), m_pncc(NULL), m_fOneTimeInstall(FALSE), m_fRestoredRegistry(FALSE), m_fUpgradeFromWks(FALSE), m_fUpgrade(FALSE) { ZeroMemory(&m_apspObj, sizeof(m_apspObj)); ZeroMemory(&m_sdd, sizeof(m_sdd)); } // // INetCfgComponentControl // //+--------------------------------------------------------------------------- // // Member: CSrvrcfg::Initialize // // Purpose: Called when we are initialized. // // Arguments: // pnccItem [in] Component we belong to. // pnc [in] INetCfg master object if we need it. // fInstalling [in] TRUE if we are being installed, FALSE otherwise. // // Returns: HRESULT, Error code. // // Author: danielwe 22 Mar 1997 // // Notes: // STDMETHODIMP CSrvrcfg::Initialize(INetCfgComponent* pnccItem, INetCfg *pnc, BOOL fInstalling) { Validate_INetCfgNotify_Initialize(pnccItem, pnc, fInstalling); m_pncc = pnccItem; AddRefObj(m_pncc); GetProductFlavor(NULL, &m_pf); HRESULT hr = HrOpenRegKeys(pnc); if (SUCCEEDED(hr)) { hr = HrGetRegistryInfo(fInstalling); } Validate_INetCfgNotify_Initialize_Return(hr); TraceError("CSrvrcfg::Initialize", hr); return hr; } STDMETHODIMP CSrvrcfg::Validate() { return S_OK; } STDMETHODIMP CSrvrcfg::CancelChanges() { return S_OK; } //+--------------------------------------------------------------------------- // // Member: CSrvrcfg::Apply // // Purpose: Called when changes to this component should be applied. // // Arguments: // (none) // // Returns: HRESULT, Error code. // // Author: danielwe 5 Mar 1997 // // Notes: // STDMETHODIMP CSrvrcfg::ApplyRegistryChanges() { HRESULT hr = S_OK; static const WCHAR c_szLicenseSvc[] = L"LicenseService"; if (m_fUpgrade) { TraceTag(ttidSrvrCfg, "Upgrading MS_SERVER"); if (!m_fRestoredRegistry) { TraceTag(ttidSrvrCfg, "Restoring registry"); hr = HrRestoreRegistry(); if (FAILED(hr)) { TraceError("CSrvrcfg::ApplyRegistryChanges - HrRestoreRegistry - non-fatal", hr); hr = S_OK; } } } if (SUCCEEDED(hr)) { if (m_fDirty) { hr = HrSetRegistryInfo(); } if (SUCCEEDED(hr)) { if (m_fOneTimeInstall) { /* hr = HrChangeServiceStartTypeOptional(c_szLicenseSvc, SERVICE_AUTO_START); if (SUCCEEDED(hr)) { hr = S_OK; m_fDirty = FALSE; m_fOneTimeInstall = FALSE; } */ } } } Validate_INetCfgNotify_Apply_Return(hr); TraceError("CSrvrcfg::ApplyRegistryChanges", (hr == S_FALSE) ? S_OK : hr); return hr; } // // INetCfgComponentSetup // //+--------------------------------------------------------------------------- // // Member: CSrvrcfg::Install // // Purpose: Called when this component is being installed // // Arguments: // dwSetupFlags [in] Flags that describe the type of setup // // Returns: HRESULT, Error code. // // Author: danielwe 5 Mar 1997 // // Notes: // STDMETHODIMP CSrvrcfg::Install(DWORD dwSetupFlags) { m_fDirty = TRUE; m_fOneTimeInstall = TRUE; if (dwSetupFlags & NSF_WINNT_WKS_UPGRADE) { m_fUpgrade = TRUE; m_fUpgradeFromWks = TRUE; } else if ((dwSetupFlags & NSF_WINNT_SVR_UPGRADE) || (dwSetupFlags & NSF_WINNT_SBS_UPGRADE)) { m_fUpgrade = TRUE; } return S_OK; } STDMETHODIMP CSrvrcfg::Upgrade(DWORD dwSetupFlags, DWORD dwUpgradeFomBuildNo) { return S_FALSE; } //+--------------------------------------------------------------------------- // // Member: CSrvrcfg::ReadAnswerFile // // Purpose: Reads the appropriate fields from the given answer file into // our in-memory state. // // Arguments: // pszAnswerFile [in] File name of answer file // pszAnswerSection [in] Section of answer file to look in // // Returns: S_OK if successful, OLE or Win32 error otherwise // // Author: danielwe 30 Oct 1997 // // Notes: // STDMETHODIMP CSrvrcfg::ReadAnswerFile(PCWSTR pszAnswerFile, PCWSTR pszAnswerSection) { HRESULT hr = S_OK; if (pszAnswerSection && pszAnswerFile) { // There's an answer file. We must process it now. hr = HrProcessAnswerFile(pszAnswerFile, pszAnswerSection); if (FAILED(hr)) { TraceError("CSrvrcfg::ReadAnswerFile- Answer file has " "errors. Defaulting all information as if " "answer file did not exist.", NETSETUP_E_ANS_FILE_ERROR); hr = S_OK; } } TraceError("CSrvrcfg::ReadAnswerFile", hr); return hr; } STDMETHODIMP CSrvrcfg::Removing() { return S_OK; } //+--------------------------------------------------------------------------- // // Member: CSrvrcfg::HrRestoreRegistry // // Purpose: Restores the contents of the registry for this component // // Arguments: // (none) // // Returns: Win32 error if failed, otherwise S_OK // // Author: danielwe 8 Aug 1997 // // Notes: // HRESULT CSrvrcfg::HrRestoreRegistry() { HRESULT hr = S_OK; HKEY hkey; TOKEN_PRIVILEGES * ptpRestore = NULL; BOOL fRestoreSucceeded = FALSE; if (!m_strParamsRestoreFile.empty() || !m_strSharesRestoreFile.empty() || !m_strAutoTunedRestoreFile.empty()) { hr = HrEnableAllPrivileges(&ptpRestore); if (SUCCEEDED(hr)) { if (!m_strParamsRestoreFile.empty()) { hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyServerParams, KEY_ALL_ACCESS, &hkey); if (SUCCEEDED(hr)) { hr = HrRegRestoreKey(hkey, m_strParamsRestoreFile.c_str(), 0); if (FAILED(hr)) { TraceError("CSrvrcfg::HrRestoreRegistry - HrRestoreRegistry for " "Parameters", hr); hr = S_OK; } else { fRestoreSucceeded = TRUE; } RegCloseKey(hkey); } } if (fRestoreSucceeded) { // if the restore succeeded, rewrite the values that were blown // away by the restore static const WCHAR c_szSvcDLLName[] = L"%SystemRoot%\\System32\\srvsvc.dll"; static const WCHAR c_szServiceDll[] = L"ServiceDll"; HKEY hkResult = NULL; hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyServerParams, KEY_ALL_ACCESS, &hkResult); if SUCCEEDED(hr) { hr = HrRegSetValueEx(hkResult, c_szServiceDll, REG_EXPAND_SZ, (const BYTE *)c_szSvcDLLName, CbOfMultiSzAndTermSafe(c_szSvcDLLName)); } if FAILED(hr) { TraceError("CSrvrcfg::HrRestoreRegistry - HrRestoreRegistry for " "ServiceDll", hr); hr = S_OK; } // // The following key has to be set here because of new changes introduced // by SCE (Security Configuration Engine). SCE runs early in GUI mode setup to // set out-of-the-box security by setting some registry values. During NT4 // upgrades we don't see those registry values set because during NT4 upgrades, // some services including Lanmanserver and Netlogon gets deleted and reinstalled // for PnP requirements. To maintain the services configuration between deleting // and reinstalling, some of their Keys including the "Parameters" keys for // LanManServer and Netlogon get backed up early during upgrade and restored // later with the service installation. This backing up and restoring action // happens through the services own notify objects (like this one). The problem // is, backing up of the Keys happens before SCE sets the values in those keys and // they get restored after SCE sets the values. So we lose the values set. So, we // are setting those keys here separately to the secure values. // See Windows Raid bug #691952 for more details. // static const WCHAR c_szRestrictNullSessAccess[] = L"RestrictNullSessAccess"; DWORD value = 1; hr = HrRegSetValueEx(hkey, c_szRestrictNullSessAccess, REG_DWORD, (const BYTE *)&value, 4); if (FAILED(hr)) { TraceError("CSrvrcfg::HrRestoreRegistry - setting RestrictNullSessAccess to DWORD 1 failed", hr); hr = S_OK; } RegSafeCloseKey(hkResult); static const WCHAR c_szTrkWks[] = L"TrkWks"; static const WCHAR c_szTrkSrv[] = L"TrkSrv"; static const WCHAR c_szNullSession[] = L"NullSessionPipes"; hr = HrRegAddStringToMultiSz(c_szTrkWks, HKEY_LOCAL_MACHINE, c_szRegKeyServerParams, c_szNullSession, STRING_FLAG_ENSURE_AT_END, 0); if (SUCCEEDED(hr)) { hr = HrRegAddStringToMultiSz(c_szTrkSrv, HKEY_LOCAL_MACHINE, c_szRegKeyServerParams, c_szNullSession, STRING_FLAG_ENSURE_AT_END, 0); } if (FAILED(hr)) { TraceError("CSrvrcfg::HrRestoreRegistry - Error replacing " "values for Parameters", hr); hr = S_OK; } } if (!m_strSharesRestoreFile.empty()) { hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyServerShares, KEY_ALL_ACCESS, &hkey); if (SUCCEEDED(hr)) { hr = HrRegRestoreKey(hkey, m_strSharesRestoreFile.c_str(), 0); if (FAILED(hr)) { TraceError("CSrvrcfg::HrRestoreRegistry - HrRestoreRegistry for " "Shares", hr); hr = S_OK; } RegCloseKey(hkey); } } if (!m_strAutoTunedRestoreFile.empty()) { hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyServerAutoTuned, KEY_ALL_ACCESS, &hkey); if (SUCCEEDED(hr)) { hr = HrRegRestoreKey(hkey, m_strAutoTunedRestoreFile.c_str(), 0); if (FAILED(hr)) { TraceError("CSrvrcfg::HrRestoreRegistry - HrRestoreRegistry for " "AutotunedParameters", hr); hr = S_OK; } RegCloseKey(hkey); } } hr = HrRestorePrivileges(ptpRestore); delete [] reinterpret_cast(ptpRestore); // Set a flag so we don't do this again if we are applied again m_fRestoredRegistry = TRUE; } } else { TraceTag(ttidSrvrCfg, "WARNING: HrRestoreRegistry() was called without" " ReadAnswerFile() being called!"); } TraceError("CSrvrcfg::HrRestoreRegistry", hr); return hr; } //+--------------------------------------------------------------------------- // // Member: CSrvrcfg::HrProcessAnswerFile // // Purpose: Handles necessary processing of contents of the answer file. // // Arguments: // pszAnswerFile [in] Filename of answer file for upgrade. // pszAnswerSection [in] Comma-separated list of sections in the // file appropriate to this component. // // Returns: S_OK if successful, setup API error otherwise. // // Author: danielwe 8 May 1997 // // Notes: // HRESULT CSrvrcfg::HrProcessAnswerFile(PCWSTR pszAnswerFile, PCWSTR pszAnswerSection) { HRESULT hr = S_OK; tstring strOpt; PCWSTR szOptDefault; CSetupInfFile csif; if (m_pf == PF_SERVER) { szOptDefault = c_szAfMaxthroughputforfilesharing; } else { szOptDefault = c_szAfMinmemoryused; } // Open the answer file. hr = csif.HrOpen(pszAnswerFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); if (FAILED(hr)) { hr = S_OK; goto err; } if (m_fUpgrade) { // Restore portions of the registry based on file names from the answer // file // Get restore file for "Parameters" key hr = csif.HrGetString(pszAnswerSection, c_szAfLmServerParameters, &m_strParamsRestoreFile); if (FAILED(hr)) { TraceError("CSrvrcfg::HrProcessAnswerFile - Error restoring " "Parameters key", hr); // oh well, just continue hr = S_OK; } // Get restore file for "Shares" key hr = csif.HrGetString(pszAnswerSection, c_szAfLmServerShares, &m_strSharesRestoreFile); if (FAILED(hr)) { TraceError("CSrvrcfg::HrProcessAnswerFile - Error restoring " "Shares key", hr); // oh well, just continue hr = S_OK; } // Get restore file for "AutotunedParameters" key hr = csif.HrGetString(pszAnswerSection, c_szAfLmServerAutotunedParameters, &m_strAutoTunedRestoreFile); if (FAILED(hr)) { TraceError("CSrvrcfg::HrProcessAnswerFile - Error restoring " "AutotunedParameters key", hr); // oh well, just continue hr = S_OK; } } // Read contents Opimitzation key hr = csif.HrGetString(pszAnswerSection, c_szAfLmServerOptimization, &strOpt); if (SUCCEEDED(hr)) { m_fDirty = TRUE; if (!lstrcmpiW(strOpt.c_str(), c_szAfMinmemoryused)) { m_sdd.dwSize = 1; } else if (!lstrcmpiW(strOpt.c_str(), c_szAfBalance)) { m_sdd.dwSize = 2; } else if (!lstrcmpiW(strOpt.c_str(), c_szAfMaxthroughputforfilesharing)) { m_sdd.dwSize = 3; m_sdd.fLargeCache = TRUE; } else if (!lstrcmpiW(strOpt.c_str(), c_szAfMaxthrouputfornetworkapps)) { m_sdd.dwSize = 3; m_sdd.fLargeCache = FALSE; } #ifdef DBG else { // NOTE: Default values for dwSize and fLargeCache will have been set // already by registry reading function. TraceTag(ttidSrvrCfg, "Unknown Optimization value '%S'. Using default " "'%S'.", strOpt.c_str(), szOptDefault); } #endif } // Read contents of BroadcastsToLanman2Clients key. hr = csif.HrGetStringAsBool(pszAnswerSection, c_szAfBroadcastToClients, &m_sdd.fAnnounce); if (FAILED(hr)) { TraceError("CSrvrcfg::HrProcessAnswerFile - Error restoring " "BroadcastsToLanman2Clients key. Using default value" " of FALSE.", hr); // oh well, just continue hr = S_OK; } err: TraceError("CSrvrcfg::HrProcessAnswerFile", hr); return hr; } // // INetCfgProperties // //+--------------------------------------------------------------------------- // // Member: CSrvrcfg::MergePropPages // // Purpose: Called when this component's properties are about to be // brought up. // // Arguments: // pdwDefPages [out] Number of default pages to show. // pahpspPrivate [out] Array of property sheet handles to pages that this // component will show. // pcPrivate [out] Number of pages in array. // hwndParent [in] Parent window for any UI. // pszStartPage [out] Pointer to start page. // // Returns: HRESULT, Error code. // // Author: danielwe 22 Feb 1997 // // Notes: // STDMETHODIMP CSrvrcfg::MergePropPages(DWORD *pdwDefPages, LPBYTE *pahpspPrivate, UINT *pcPrivate, HWND hwndParent, PCWSTR *pszStartPage) { HRESULT hr = S_OK; HPROPSHEETPAGE *ahpsp = NULL; Validate_INetCfgProperties_MergePropPages(pdwDefPages, pahpspPrivate, pcPrivate, hwndParent, pszStartPage); // We don't want any default pages to be shown *pdwDefPages = 0; if (m_pf == PF_WORKSTATION) { // On workstation product, UI is not shown. *pcPrivate = 0; } else { hr = HrSetupPropSheets(&ahpsp, c_cPages); if (SUCCEEDED(hr)) { *pahpspPrivate = (LPBYTE)ahpsp; *pcPrivate = c_cPages; } } Validate_INetCfgProperties_MergePropPages_Return(hr); TraceError("CSrvrcfg::MergePropPages", hr); return hr; } STDMETHODIMP CSrvrcfg::ValidateProperties(HWND hwndSheet) { return S_OK; } STDMETHODIMP CSrvrcfg::CancelProperties() { return S_OK; } STDMETHODIMP CSrvrcfg::ApplyProperties() { return S_OK; } //+--------------------------------------------------------------------------- // // Member: CSrvrcfg::~CSrvrcfg // // Purpose: Destroys the CSrvrcfg object. // // Arguments: // (none) // // Returns: Nothing. // // Author: danielwe 5 Mar 1997 // // Notes: // CSrvrcfg::~CSrvrcfg() { ReleaseObj(m_pncc); RegSafeCloseKey(m_hkeyMM); CleanupPropPages(); #ifdef DBG { INT ipage; for (ipage = 0; ipage < c_cPages; ipage++) { AssertSz(!m_apspObj[ipage], "Prop page object should be NULL!"); } } #endif }