//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997. // // File: U P G R A D E . C P P // // Contents: functions related only to network upgrade // (i.e. not used when installing fresh) // // Notes: // // Author: kumarp // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "nsbase.h" #include "afileint.h" #include "afilestr.h" #include "afilexp.h" #include "kkreg.h" #include "kkutils.h" #include "ncatl.h" #include "nceh.h" #include "ncnetcfg.h" #include "ncreg.h" #include "ncsetup.h" #include "ncsvc.h" #include "resource.h" #include "upgrade.h" #include "nslog.h" #include "winsock2.h" // For WSCEnumProtocols #include "ws2spi.h" #include "sporder.h" // For WSCWriteProviderOrder // ---------------------------------------------------------------------- // String constants // ---------------------------------------------------------------------- extern const WCHAR c_szSvcRasAuto[]; extern const WCHAR c_szSvcRouter[]; extern const WCHAR c_szSvcRemoteAccess[]; extern const WCHAR c_szSvcRipForIp[]; extern const WCHAR c_szSvcRipForIpx[]; extern const WCHAR c_szSvcDhcpRelayAgent[]; extern const WCHAR c_szInfId_MS_RasSrv[]; // ---------------------------------------------------------------------- // forward declarations // ---------------------------------------------------------------------- // returns S_OK on success. typedef HRESULT (*HrOemComponentUpgradeFnPrototype) (IN DWORD dwUpgradeFlag, IN DWORD dwUpgradeFromBuildNumber, IN PCWSTR pszAnswerFileName, IN PCWSTR pszAnswerFileSectionName); BOOL InitWorkForWizIntro(); // ---------------------------------------------------------------------- static const WCHAR c_szCleanSection[] = L"Clean"; static const WCHAR c_szCleanServicesSection[]= L"Clean.Services"; const WCHAR c_szRouterUpgradeDll[] = L"rtrupg.dll"; const CHAR c_szRouterUpgradeFn[] = "RouterUpgrade"; // ---------------------------------------------------------------------- #define RGAS_SERVICES_HOME L"SYSTEM\\CurrentControlSet\\Services" // ---------------------------------------------------------------------- //+--------------------------------------------------------------------------- // // Function: HrRunAnswerFileCleanSection // // Purpose: Runs the [Clean] section of the answer file to remove old // registry entries and services. // // Arguments: // (none) // // Returns: S_OK if succeeded, SetupAPI error otherwise // // Author: danielwe 12 Jun 1997 // // Notes: // HRESULT HrRunAnswerFileCleanSection(IN PCWSTR pszAnswerFileName) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrRunAnswerFileCleanSection"); TraceFunctionEntry(ttidNetSetup); AssertValidReadPtr(pszAnswerFileName); TraceTag(ttidNetSetup, "%s: Cleaning services and registry keys based " "on params in the answer file %S.", __FUNCNAME__, pszAnswerFileName); HRESULT hr; HINF hinf; hr = HrSetupOpenInfFile(pszAnswerFileName, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinf); if (S_OK == hr) { BOOL frt; // It may say "Install" but this really deletes a bunch of // registry "leftovers" from previous installs frt = SetupInstallFromInfSection(NULL, hinf, c_szCleanSection, SPINST_ALL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (frt) { frt = SetupInstallServicesFromInfSection(hinf, c_szCleanServicesSection, 0); if (!frt) { hr = HrFromLastWin32Error(); TraceErrorOptional("SetupInstallServicesFromInfSection", hr, (hr == HRESULT_FROM_SETUPAPI(ERROR_SECTION_NOT_FOUND))); } } else { hr = HrFromLastWin32Error(); TraceErrorOptional("SetupInstallServicesFromInfSection", hr, (hr == HRESULT_FROM_SETUPAPI(ERROR_SECTION_NOT_FOUND))); } SetupCloseInfFile(hinf); } if (HRESULT_FROM_SETUPAPI(ERROR_SECTION_NOT_FOUND) == hr) { hr = S_OK; } TraceError("HrRunAnswerFileCleanSection", hr); return hr; } // ---------------------------------------------------------------------- // // Function: HrSaveInstanceGuid // // Purpose: Save instance guid of the specified component to the registry // // Arguments: // pszComponentName [in] name of // pguidInstance [in] pointer to // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 23-December-97 // // Notes: // HRESULT HrSaveInstanceGuid( IN PCWSTR pszComponentName, IN const GUID* pguidInstance) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrSaveInstanceGuid"); AssertValidReadPtr(pszComponentName); AssertValidReadPtr(pguidInstance); HRESULT hr; HKEY hkeyMap; hr = HrRegCreateKeyEx ( HKEY_LOCAL_MACHINE, c_szRegKeyAnswerFileMap, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyMap, NULL); if (S_OK == hr) { hr = HrRegSetGuidAsSz (hkeyMap, pszComponentName, *pguidInstance); RegCloseKey (hkeyMap); } TraceFunctionError(hr); return hr; } // ---------------------------------------------------------------------- // // Function: HrLoadInstanceGuid // // Purpose: Load instance guid of the specified component from registry // // Arguments: // pszComponentName [in] name of // pguidInstance [out] pointer to // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 23-December-97 // // Notes: // HRESULT HrLoadInstanceGuid( IN PCWSTR pszComponentName, OUT LPGUID pguidInstance) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrLoadInstanceGuid"); Assert (pszComponentName); Assert (pguidInstance); HRESULT hr; HKEY hkeyMap; ZeroMemory(pguidInstance, sizeof(GUID)); hr = HrRegOpenKeyEx ( HKEY_LOCAL_MACHINE, c_szRegKeyAnswerFileMap, KEY_READ, &hkeyMap); if (S_OK == hr) { WCHAR szGuid[c_cchGuidWithTerm]; DWORD cbGuid = sizeof(szGuid); hr = HrRegQuerySzBuffer ( hkeyMap, pszComponentName, szGuid, &cbGuid); if (S_OK == hr) { hr = IIDFromString (szGuid, pguidInstance); } RegCloseKey (hkeyMap); } TraceFunctionError(hr); return hr; } static const PCWSTR c_aszServicesToIgnore[] = { L"afd", L"asyncmac", L"atmarp", L"dhcp", L"nbf", // see bug 143346 L"ndistapi", L"ndiswan", L"nwlnkipx", L"nwlnknb", L"nwlnkspx", L"rpcss", L"wanarp", }; // ---------------------------------------------------------------------- // // Function: HrRestoreServiceStartValuesToPreUpgradeSetting // // Purpose: Restore start value of each network service to // what was before upgrade // // Arguments: // pwifAnswerFile [in] pointer to CWInfFile object // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 23-December-97 // // Notes: // HRESULT HrRestoreServiceStartValuesToPreUpgradeSetting(IN CWInfFile* pwifAnswerFile) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrRestoreServiceStartValuesToPreUpgradeSetting"); CWInfSection* pwisServiceStartTypes; pwisServiceStartTypes = pwifAnswerFile->FindSection(c_szAfServiceStartTypes); if (!pwisServiceStartTypes) { return S_OK; } HRESULT hr; CServiceManager scm; hr = scm.HrOpen(); if (SUCCEEDED(hr)) { DWORD dwPreUpgRouterStartType=0; DWORD dwPreUpgRemoteAccessStartType=0; DWORD dwRRASStartType=0; DWORD dwPreUpgRipForIpStartType=0; DWORD dwPreUpgRipForIpxStartType=0; DWORD dwPreUpgDhcpRelayAgentStartType=0; // In Windows2000, Router and RemoteAccess have merged. // If they have differing service start types before upgrade // we use the lower of the two start-type values to set // the start-type of "Routing and remote access" service. // // for more info see bug# 260253 // if (pwisServiceStartTypes->GetIntValue(c_szSvcRouter, &dwPreUpgRouterStartType) && pwisServiceStartTypes->GetIntValue(c_szSvcRemoteAccess, &dwPreUpgRemoteAccessStartType)) { dwRRASStartType = min(dwPreUpgRemoteAccessStartType, dwPreUpgRouterStartType); TraceTag(ttidNetSetup, "%s: pre-upg start-types:: Router: %d, RemoteAccess: %d", __FUNCNAME__, dwPreUpgRouterStartType, dwPreUpgRemoteAccessStartType); } // 306202: if IPRIP/IPXRIP/DHCPrelayagent were in use on NT4, set RRAS to Auto // if (pwisServiceStartTypes->GetIntValue(c_szSvcRipForIp, &dwPreUpgRipForIpStartType) && (SERVICE_AUTO_START == dwPreUpgRipForIpStartType)) { TraceTag(ttidNetSetup, "%s: pre-upg start-types:: IPRIP: %d, RemoteAccess: %d", __FUNCNAME__, dwPreUpgRipForIpStartType, dwPreUpgRemoteAccessStartType); dwRRASStartType = SERVICE_AUTO_START; } if (pwisServiceStartTypes->GetIntValue(c_szSvcRipForIpx, &dwPreUpgRipForIpxStartType) && (SERVICE_AUTO_START == dwPreUpgRipForIpxStartType)) { TraceTag(ttidNetSetup, "%s: pre-upg start-types:: RipForIpx: %d, RemoteAccess: %d", __FUNCNAME__, dwPreUpgRipForIpxStartType, dwPreUpgRemoteAccessStartType); dwRRASStartType = SERVICE_AUTO_START; } if (pwisServiceStartTypes->GetIntValue(c_szSvcDhcpRelayAgent, &dwPreUpgDhcpRelayAgentStartType) && (SERVICE_AUTO_START == dwPreUpgDhcpRelayAgentStartType)) { TraceTag(ttidNetSetup, "%s: pre-upg start-types:: DHCPRelayAgent: %d, RemoteAccess: %d", __FUNCNAME__, dwPreUpgDhcpRelayAgentStartType, dwPreUpgRemoteAccessStartType); dwRRASStartType = SERVICE_AUTO_START; } // end 306202 for (CWInfKey* pwik = pwisServiceStartTypes->FirstKey(); pwik; pwik = pwisServiceStartTypes->NextKey()) { PCWSTR pszServiceName; DWORD dwPreUpgradeStartValue; pszServiceName = pwik->Name(); AssertValidReadPtr(pszServiceName); dwPreUpgradeStartValue = pwik->GetIntValue(-1); if (dwPreUpgradeStartValue > SERVICE_DISABLED) { NetSetupLogStatusV( LogSevWarning, SzLoadIds (IDS_INVALID_PREUPGRADE_START), dwPreUpgradeStartValue, pszServiceName); continue; } // We do not want to restore the pre-upgrade start type if: // - it is one of c_aszServicesToIgnore AND // if (FIsInStringArray(c_aszServicesToIgnore, celems(c_aszServicesToIgnore), pszServiceName)) { NetSetupLogStatusV( LogSevInformation, SzLoadIds (IDS_IGNORED_SERVICE_PREUPGRADE), pszServiceName); continue; } // special case for RRAS, see the comment before the while loop if ((dwRRASStartType != 0) && !lstrcmpiW(pszServiceName, c_szSvcRemoteAccess)) { dwPreUpgradeStartValue = dwRRASStartType; } // 305065: if RasAuto was not disabled on NT4, make it demand-start on NT5 else if ((SERVICE_DISABLED != dwPreUpgradeStartValue) && !lstrcmpiW(pszServiceName, c_szSvcRasAuto)) { dwPreUpgradeStartValue = SERVICE_DEMAND_START; NetSetupLogStatusV( LogSevInformation, SzLoadIds (IDS_FORCING_DEMAND_START), pszServiceName); } CService service; hr = scm.HrOpenService(&service, pszServiceName); if (S_OK == hr) { DWORD dwStartValue; hr = service.HrQueryStartType(&dwStartValue); if ((S_OK == hr) && (dwStartValue != dwPreUpgradeStartValue)) { hr = service.HrSetStartType(dwPreUpgradeStartValue); NetSetupLogHrStatusV(hr, SzLoadIds (IDS_RESTORING_START_TYPE), pszServiceName, dwStartValue, dwPreUpgradeStartValue, hr); } } } // ignore any errors hr = S_OK; } TraceError(__FUNCNAME__, hr); return hr; } // GUIDs provided for the sole use of this function, which removes incompatible // Intel Winsock providers // const GUID GUID_INTEL_RSVP = { 0x0f1e5156L, 0xf07a, 0x11cf, 0x98, 0x0e, 0x00, 0xaa, 0x00, 0x58, 0x0a, 0x07 }; const GUID GUID_INTEL_GQOS1 = { 0xbca8a790L, 0xc186, 0x11d0, 0xb8, 0x69, 0x00, 0xa0, 0xc9, 0x08, 0x1e, 0x34 }; const GUID GUID_INTEL_GQOS2 = { 0xf80d1d20L, 0x8b7a, 0x11d0, 0xb8, 0x53, 0x00, 0xa0, 0xc9, 0x08, 0x1e, 0x34 }; //+--------------------------------------------------------------------------- // // Function: HrRemoveEvilIntelRSVPWinsockSPs // // Purpose: Remove the Intel RSVP Winsock SP's so they don't conflict // with the Windows 2000 RSVP provider. This is a complete hack // to cure RAID 332622, but it's all we can do this late in the // ship cycle. There's not a good general-case fix for this // problem. // // Arguments: // (none) // // Returns: // // Author: jeffspr 22 Aug 1999 // // Notes: // HRESULT HrRemoveEvilIntelWinsockSPs() { TraceFileFunc(ttidGuiModeSetup); HRESULT hr = S_OK; // Now read the new IDs and order them in memory // INT nErr = NO_ERROR; ULONG ulRes; DWORD cbInfo = 0; WSAPROTOCOL_INFO* pwpi = NULL; WSAPROTOCOL_INFO* pwpiInfo = NULL; // First get the size needed // ulRes = WSCEnumProtocols(NULL, NULL, &cbInfo, &nErr); if ((SOCKET_ERROR == ulRes) && (WSAENOBUFS == nErr)) { pwpi = reinterpret_cast(new BYTE[cbInfo]); if (pwpi) { // Find out all the protocols on the system // ulRes = WSCEnumProtocols(NULL, pwpi, &cbInfo, &nErr); if (SOCKET_ERROR != ulRes) { ULONG cProt = 0; for (pwpiInfo = pwpi, cProt = ulRes; cProt; cProt--, pwpiInfo++) { BOOL fDeleteMe = FALSE; if (IsEqualGUID(GUID_INTEL_RSVP, pwpiInfo->ProviderId)) { fDeleteMe = TRUE; } else if (IsEqualGUID(GUID_INTEL_GQOS1, pwpiInfo->ProviderId)) { fDeleteMe = TRUE; } else if (IsEqualGUID(GUID_INTEL_GQOS2, pwpiInfo->ProviderId)) { fDeleteMe = TRUE; } if (fDeleteMe) { int iErrNo = 0; int iReturn = WSCDeinstallProvider( &pwpiInfo->ProviderId, &iErrNo); TraceTag(ttidNetSetup, "SP Removal guid: %08x %04x %04x %02x%02x %02x%02x%02x%02x%02x%02x", pwpiInfo->ProviderId.Data1, pwpiInfo->ProviderId.Data2, pwpiInfo->ProviderId.Data3, pwpiInfo->ProviderId.Data4[0], pwpiInfo->ProviderId.Data4[1], pwpiInfo->ProviderId.Data4[2], pwpiInfo->ProviderId.Data4[3], pwpiInfo->ProviderId.Data4[4], pwpiInfo->ProviderId.Data4[5], pwpiInfo->ProviderId.Data4[6], pwpiInfo->ProviderId.Data4[7], pwpiInfo->ProviderId.Data4[8]); TraceTag(ttidNetSetup, "Removing incompatible RSVP WS provider: %S (%d, %04x), ret=%d, ierr=%d", pwpiInfo->szProtocol, pwpiInfo->dwCatalogEntryId, pwpiInfo->dwCatalogEntryId, iReturn, iErrNo); } } } else { TraceTag(ttidNetSetup, "Socket error in secondary WSCEnumProtocols"); } delete pwpi; } } else { TraceTag(ttidNetSetup, "Socket error in initial WSCEnumProtocols"); } TraceHr(ttidNetSetup, FAL, hr, FALSE, "HrRemoveEvilIntelWinsockSPs"); // Yes, we track hr for debugging purposes, but we don't ever want to // fail based on a failed removal of incompatible Winsock providers // return S_OK; } BOOL FIsValidCatalogId(WSAPROTOCOL_INFO *pwpi, ULONG cProt, DWORD dwCatId) { TraceFileFunc(ttidGuiModeSetup); for (; cProt; cProt--, pwpi++) { if (dwCatId == pwpi->dwCatalogEntryId) return TRUE; } return FALSE; } HRESULT HrRestoreWinsockProviderOrder(IN CWInfFile* pwifAnswerFile) { TraceFileFunc(ttidGuiModeSetup); HRESULT hr = S_OK; vector vecIds; CWInfSection * pwisWinsock; DefineFunctionName("HrRestoreWinsockProviderOrder"); // First get the old IDs into a vector of DWORDs // pwisWinsock = pwifAnswerFile->FindSection(c_szAfSectionWinsock); if (pwisWinsock) { tstring strOrder; PWSTR pszOrder; PWSTR pszId; pwisWinsock->GetStringValue(c_szAfKeyWinsockOrder, strOrder); if (!strOrder.empty()) { pszOrder = SzDupSz(strOrder.c_str()); pszId = wcstok(pszOrder, L"."); while (pszId) { DWORD dwId = wcstoul(pszId, NULL, 10); vecIds.push_back(dwId); pszId = wcstok(NULL, L"."); } delete pszOrder; // Now read the new IDs and order them in memory // INT nErr; ULONG ulRes; DWORD cbInfo = 0; WSAPROTOCOL_INFO* pwpi = NULL; WSAPROTOCOL_INFO* pwpiInfo = NULL; // First get the size needed // ulRes = WSCEnumProtocols(NULL, NULL, &cbInfo, &nErr); if ((SOCKET_ERROR == ulRes) && (WSAENOBUFS == nErr)) { pwpi = reinterpret_cast(new BYTE[cbInfo]); if (pwpi) { // Find out all the protocols on the system // ulRes = WSCEnumProtocols(NULL, pwpi, &cbInfo, &nErr); if (SOCKET_ERROR != ulRes) { ULONG cProt; vector::iterator iterLocation; iterLocation = vecIds.begin(); for (pwpiInfo = pwpi, cProt = ulRes; cProt; cProt--, pwpiInfo++) { if (vecIds.end() == find(vecIds.begin(), vecIds.end(), pwpiInfo->dwCatalogEntryId)) { // Not already in the list.. Add it after the last // entry we added (or the front if this is the first // addition) iterLocation = vecIds.insert(iterLocation, pwpiInfo->dwCatalogEntryId); } } DWORD * pdwIds = NULL; DWORD * pdwCurId; DWORD cdwIds = vecIds.size(); pdwIds = new DWORD[ulRes]; if (pdwIds) { #if DBG DWORD cValid = 0; #endif for (pdwCurId = pdwIds, iterLocation = vecIds.begin(); iterLocation != vecIds.end(); iterLocation++, pdwCurId++) { // Make sure we only re-order valid catalog // IDs if (FIsValidCatalogId(pwpi, ulRes, *iterLocation)) { #if DBG cValid++; #endif *pdwCurId = *iterLocation; } } AssertSz(ulRes == cValid, "Number of providers is" " different!"); // Restore the winsock provider order // nErr = WSCWriteProviderOrder(pdwIds, cdwIds); delete pdwIds; } } delete pwpi; } } } } TraceError(__FUNCNAME__, hr); return hr; } // ---------------------------------------------------------------------- // // Function: HrUpgradeOemComponent // // Purpose: Upgrade a component. This started as a generalized function // but currently it is being used only by HrUpgradeRouterIfPresent // // Arguments: // pszComponentToUpgrade [in] component to upgrade // pszDllName [in] name of DLL to load // psznEntryPoint [in] entry point to call // dwUpgradeFlag [in] upgrade flag // dwUpgradeFromBuildNumber [in] upgrade to build number // pszAnswerFileName [in] name of answerfile // pszAnswerFileSectionName [in] name of answerfile section name to use // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 23-December-97 // // Notes: // HRESULT HrUpgradeOemComponent ( IN PCWSTR pszComponentToUpgrade, IN PCWSTR pszDllName, IN PCSTR psznEntryPoint, IN DWORD dwUpgradeFlag, IN DWORD dwUpgradeFromBuildNumber, IN PCWSTR pszAnswerFileName, IN PCWSTR pszAnswerFileSectionName) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrUpgradeOemComponent"); HRESULT hr=E_FAIL; HrOemComponentUpgradeFnPrototype pfn; HMODULE hLib; TraceTag(ttidNetSetup, "%s: calling function '%s' in '%S' to upgrade component: %S...", __FUNCNAME__, psznEntryPoint, pszDllName, pszComponentToUpgrade); hr = HrLoadLibAndGetProc(pszDllName, psznEntryPoint, &hLib, (FARPROC*) &pfn); if (S_OK == hr) { NC_TRY { hr = pfn(dwUpgradeFlag, dwUpgradeFromBuildNumber, pszAnswerFileName, pszAnswerFileSectionName); } NC_CATCH_ALL { hr = E_UNEXPECTED; } FreeLibrary(hLib); } TraceError(__FUNCNAME__, hr); return hr; } // ---------------------------------------------------------------------- // // Function: HrUpgradeRouterIfPresent // // Purpose: Upgrade the Router service if present // // Arguments: // pnii [in] pointer to CNetInstallInfo object // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 23-December-97 // // Notes: // HRESULT HrUpgradeRouterIfPresent( IN INetCfg* pNetCfg, IN CNetInstallInfo* pnii) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrUpgradeRouterIfPresent"); HRESULT hr=S_FALSE; INFCONTEXT ic; PCWSTR pszRouterParamsSection=NULL; CNetComponent* pnc = pnii->FindFromInfID(L"ms_rasrtr"); if (pnc) { // Ensure RemoteAccess is installed. In the case of upgrade from // NT4 with Steelhead, we wouldn't have written a section to // the answerfile for RemoteAccess and consequently it would not // have been installed yet. We need to install it before we turn // the router upgrade DLL loose. In the case when RemoteAccess // is already installed, this is a no-op. // hr = HrInstallComponentOboUser (pNetCfg, NULL, GUID_DEVCLASS_NETSERVICE, c_szInfId_MS_RasSrv, NULL); if (SUCCEEDED(hr)) { // we call rtrupg.dll if atleast one of the following keys // is present in the params.MS_RasRtr section // - PreUpgradeRouter // - Sap.Parameters // - IpRip.Parameters // pszRouterParamsSection = pnc->ParamsSections().c_str(); hr = HrSetupFindFirstLine(pnii->m_hinfAnswerFile, pszRouterParamsSection, c_szAfPreUpgradeRouter, &ic); if (S_OK != hr) { hr = HrSetupFindFirstLine(pnii->m_hinfAnswerFile, pszRouterParamsSection, c_szAfNwSapAgentParams, &ic); } if (S_OK != hr) { hr = HrSetupFindFirstLine(pnii->m_hinfAnswerFile, pszRouterParamsSection, c_szAfIpRipParameters, &ic); } if (S_OK != hr) { hr = HrSetupFindFirstLine(pnii->m_hinfAnswerFile, pszRouterParamsSection, c_szAfDhcpRelayAgentParameters, &ic); } if (S_OK == hr) { hr = HrUpgradeOemComponent(L"ms_rasrtr", c_szRouterUpgradeDll, c_szRouterUpgradeFn, pnii->UpgradeFlag(), pnii->BuildNumber(), pnii->AnswerFileName(), pszRouterParamsSection); } } } if (!pnc || (SPAPI_E_LINE_NOT_FOUND == hr)) { TraceTag(ttidNetSetup, "%s: PreUpgradeRouter/Sap.Parameters/IpRip.Parameters key is not in answerfile, %S will not be called", __FUNCNAME__, c_szRouterUpgradeDll); } TraceErrorOptional(__FUNCNAME__, hr, ((hr == S_FALSE) || (SPAPI_E_LINE_NOT_FOUND == hr))); return hr; } //+--------------------------------------------------------------------------- // // Function: HrUpgradeTapiServer // // Purpose: Handle upgrade requirements of TAPI server // // Arguments: // hinfAnswerFile [in] handle of AnswerFile // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 28-January-99 // // Notes: // HRESULT HrUpgradeTapiServer(IN HINF hinfAnswerFile) { TraceFileFunc(ttidGuiModeSetup); Assert(hinfAnswerFile); DefineFunctionName("HrUpgradeTapiServer"); TraceFunctionEntry(ttidNetSetup); HRESULT hr=S_OK; BOOL fRunInSeparateInstance=FALSE; hr = HrSetupGetFirstStringAsBool(hinfAnswerFile, c_szAfMiscUpgradeData, c_szAfTapiSrvRunInSeparateInstance, &fRunInSeparateInstance); if ((S_OK == hr) && fRunInSeparateInstance) { static const WCHAR c_szTapisrv[] = L"Tapisrv"; static const CHAR c_szSvchostChangeSvchostGroup[] = "SvchostChangeSvchostGroup"; static const WCHAR c_szNetcfgxDll[] = L"netcfgx.dll"; TraceTag(ttidNetSetup, "%s: TapiSrvRunInSeparateInstance is TRUE...", __FUNCNAME__); typedef HRESULT (STDAPICALLTYPE *SvchostChangeSvchostGroupFn) (PCWSTR pszService, PCWSTR pszNewGroup); SvchostChangeSvchostGroupFn pfnSvchostChangeSvchostGroup; HMODULE hNetcfgx; hr = HrLoadLibAndGetProc(c_szNetcfgxDll, c_szSvchostChangeSvchostGroup, &hNetcfgx, (FARPROC*) &pfnSvchostChangeSvchostGroup); if (S_OK == hr) { hr = pfnSvchostChangeSvchostGroup(c_szTapisrv, c_szTapisrv); FreeLibrary(hNetcfgx); } } if ((SPAPI_E_LINE_NOT_FOUND == hr) || (SPAPI_E_SECTION_NOT_FOUND == hr)) { TraceTag(ttidNetSetup, "%s: %S not found in section [%S]", __FUNCNAME__, c_szAfTapiSrvRunInSeparateInstance, c_szAfMiscUpgradeData); hr = S_OK; } TraceError(__FUNCNAME__, hr); return hr; }