//+--------------------------------------------------------------------------- // // Microsoft Windows NT5.0 // Copyright (C) Microsoft Corporation, 1997. // // File: O E M U P G R D . H // // Contents: Functions for OEM upgrade // // Notes: // // Author: kumarp 13-November-97 // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include #include "nsbase.h" #include "afileint.h" #include "afilestr.h" #include "kkutils.h" #include "ncatl.h" #include "nceh.h" #include "ncsetup.h" #include "netcfgn.h" #include "oemupgrd.h" #include "nslog.h" #include "resource.h" static const PCWSTR c_aszComponentSections[] = { c_szAfSectionNetAdapters, c_szAfSectionNetProtocols, c_szAfSectionNetClients, c_szAfSectionNetServices }; // ---------------------------------------------------------------------- // // Function: COemInfo::COemInfo // // Purpose: constructor for class COemInfo // // Arguments: None // // Returns: None // // Author: kumarp 24-December-97 // // Notes: // COemInfo::COemInfo() { TraceFileFunc(ttidGuiModeSetup); m_hOemDll = 0; m_dwError = ERROR_SUCCESS; m_pfnPostUpgradeInitialize = 0; m_pfnDoPostUpgradeProcessing = 0; } // ---------------------------------------------------------------------- // // Function: COemInfo::~COemInfo // // Purpose: destructor for class COemInfo // // Arguments: None // // Returns: None // // Author: kumarp 24-December-97 // // Notes: // COemInfo::~COemInfo() { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("COemInfo::~COemInfo"); if (m_hOemDll) { TraceTag(ttidNetSetup, "%s: unloading OEM DLL: %S\\%S", __FUNCNAME__, m_strOemDir.c_str(), m_strOemDll.c_str()); ::FreeLibrary(m_hOemDll); } } // ---------------------------------------------------------------------- // // Function: HrLoadAndVerifyOemDll // // Purpose: Load OEM upgrade DLL and verify that it has // correct exported functions // // Arguments: // poi [in/out] pointer to COemInfo object // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 19-February-98 // // Notes: // HRESULT HrLoadAndVerifyOemDll(IN OUT COemInfo* poi) { TraceFileFunc(ttidGuiModeSetup); AssertValidWritePtr(poi); DefineFunctionName("HrLoadAndVerifyOemDll"); HRESULT hr=S_OK; if (!poi->m_hOemDll) { tstring strOemDllFullPath; strOemDllFullPath = poi->m_strOemDir; AppendToPath(&strOemDllFullPath, poi->m_strOemDll.c_str()); TraceTag(ttidNetSetup, "%s: loading OEM DLL: %S", __FUNCNAME__, strOemDllFullPath.c_str()); hr = HrLoadLibAndGetProcsV(strOemDllFullPath.c_str(), &poi->m_hOemDll, c_szPostUpgradeInitialize, (FARPROC*) &poi->m_pfnPostUpgradeInitialize, c_szDoPostUpgradeProcessing, (FARPROC*) &poi->m_pfnDoPostUpgradeProcessing, NULL); if (S_OK != hr) { FreeLibrary(poi->m_hOemDll); poi->m_hOemDll = NULL; poi->m_pfnPostUpgradeInitialize = NULL; poi->m_pfnDoPostUpgradeProcessing = NULL; poi->m_dwError = ERROR_DLL_INIT_FAILED; } NetSetupLogComponentStatus(poi->m_strOemDll.c_str(), SzLoadIds (IDS_LOADING), hr); } TraceError(__FUNCNAME__, hr); return hr; } // ---------------------------------------------------------------------- // // Function: HrLoadAndInitOemDll // // Purpose: Load OEM DLL, verify that it exports correct functions // and call DoPostUpgradeInitialize // // Arguments: // poi [in] pointer to COemInfo object // pNetUpgradeInfo [in] pointer to NetUpgradeInfo // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 04-March-98 // // Notes: // HRESULT HrLoadAndInitOemDll(IN COemInfo* poi, IN NetUpgradeInfo* pNetUpgradeInfo) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrLoadAndInitOemDll"); HRESULT hr=S_OK; DWORD dwError=ERROR_SUCCESS; hr = HrLoadAndVerifyOemDll(poi); VENDORINFO vi; if (S_OK == hr) { if ((ERROR_SUCCESS == poi->m_dwError) && poi->m_pfnPostUpgradeInitialize) { NC_TRY { TraceTag(ttidNetSetup, "%s: initializing OEM DLL: %S\\%S", __FUNCNAME__, poi->m_strOemDir.c_str(), poi->m_strOemDll.c_str()); dwError = poi->m_pfnPostUpgradeInitialize(poi->m_strOemDir.c_str(), pNetUpgradeInfo, &vi, NULL); // ensure that this function gets called only once // poi->m_pfnPostUpgradeInitialize = NULL; if (ERROR_SUCCESS == dwError) { hr = S_OK; } } NC_CATCH_ALL { dwError = ERROR_DLL_INIT_FAILED; NetSetupLogHrStatusV(S_FALSE, SzLoadIds (IDS_POSTUPGRADEINIT_EXCEPTION), poi->m_strOemDll.c_str()); } poi->m_dwError = dwError; NetSetupLogComponentStatus(poi->m_strOemDll.c_str(), SzLoadIds (IDS_POSTUPGRADE_INIT), dwError); } else { hr = S_FALSE; } } TraceError(__FUNCNAME__, hr); return hr; } typedef list TOemInfoList; typedef TOemInfoList::iterator TOemInfoListIter; static TOemInfoList* g_plOemInfo; // ---------------------------------------------------------------------- // // Function: HrGetOemInfo // // Purpose: Locate (create if not found) and return COemInfo // for the given dir & dll // // Arguments: // pszOemDir [in] full path to OEM temp dir // pszOemDll [in] full path to OEM DLL // ppoi [out] pointer to pointer to COemInfo object // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 04-March-98 // // Notes: // HRESULT HrGetOemInfo(IN PCWSTR pszOemDir, IN PCWSTR pszOemDll, OUT COemInfo** ppoi) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrGetOemInfo"); HRESULT hr=E_OUTOFMEMORY; *ppoi = NULL; if (!g_plOemInfo) { g_plOemInfo = new TOemInfoList; } if (g_plOemInfo) { TOemInfoListIter pos; COemInfo* poi; for (pos=g_plOemInfo->begin(); pos != g_plOemInfo->end(); pos++) { poi = (COemInfo*) *pos; if (!lstrcmpiW(pszOemDir, poi->m_strOemDir.c_str()) && !lstrcmpiW(pszOemDll, poi->m_strOemDll.c_str())) { *ppoi = poi; hr = S_OK; break; } } if (!*ppoi) { hr = E_OUTOFMEMORY; *ppoi = new COemInfo; if (*ppoi) { (*ppoi)->m_strOemDir = pszOemDir; (*ppoi)->m_strOemDll = pszOemDll; g_plOemInfo->push_back(*ppoi); hr = S_OK; } } } TraceError(__FUNCNAME__, hr); return hr; } // ---------------------------------------------------------------------- // // Function: CleanupOemInfo // // Purpose: Cleanup OEM data // // Arguments: None // // Returns: None // // Author: kumarp 04-March-98 // // Notes: // void CleanupOemInfo() { TraceFileFunc(ttidGuiModeSetup); if (g_plOemInfo) { FreeCollectionAndItem(*g_plOemInfo); g_plOemInfo = 0; } } // ---------------------------------------------------------------------- // // Function: HrProcessOemComponent // // Purpose: Process upgrade an OEM component in the following steps // - if OEM upgrade DLL is not loaded, load it and // verify that it exports the required functions // - call DoPostUpgradeInitialize only once // - call DoPostUpgradeProcessing // // Arguments: // hwndParent [in] handle of parent window // pszOemDir [in] OEM working temp dir // pszOemDll [in] full path to OEM DLL // pNetUpgradeInfo [in] pointer to NetUpgradeInfo // hkeyParams [in] handle of Parameters regkey // pszPreNT5Instance [in] pre-NT5 instance e.g. IEEPRO3 // pszNT5InfId [in] NT5 InfID/PnpID // hinfAnswerFile [in] handle of AnswerFile // pszSectionName [in] name of OEM Section // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 04-March-98 // // Notes: // HRESULT HrProcessOemComponent(IN HWND hwndParent, IN PCWSTR pszOemDir, IN PCWSTR pszOemDll, IN NetUpgradeInfo* pNetUpgradeInfo, IN HKEY hkeyParams, IN PCWSTR pszPreNT5Instance, IN PCWSTR pszNT5InfId, IN HINF hinfAnswerFile, IN PCWSTR pszSectionName) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrProcessOemComponent"); VENDORINFO vi; TraceTag(ttidNetSetup, "%s: Processing OEM component: %S, instance: %S", __FUNCNAME__, pszNT5InfId, pszPreNT5Instance); HRESULT hr=S_OK; COemInfo* poi; hr = HrGetOemInfo(pszOemDir, pszOemDll, &poi); DWORD dwError; DWORD dwErrorMessageId=0; if (S_OK == hr) { hr = HrLoadAndInitOemDll(poi, pNetUpgradeInfo); } if ((S_OK == hr) && (ERROR_SUCCESS == poi->m_dwError)) { Assert(poi->m_pfnDoPostUpgradeProcessing); NC_TRY { TraceTag(ttidNetSetup, "%s: calling DoPostUpgradeProcessing in %S\\%S for %S", __FUNCNAME__, poi->m_strOemDll.c_str(), poi->m_strOemDir.c_str(), pszNT5InfId); dwError = poi->m_pfnDoPostUpgradeProcessing(hwndParent, hkeyParams, pszPreNT5Instance, pszNT5InfId, hinfAnswerFile, pszSectionName, &vi, NULL); NetSetupLogComponentStatus(pszNT5InfId, SzLoadIds (IDS_POSTUPGRADE_PROCESSING), dwError); } NC_CATCH_ALL { dwError = ERROR_OPERATION_ABORTED; NetSetupLogHrStatusV(S_FALSE, SzLoadIds (IDS_POSTUPGRADEPROC_EXCEPTION), pszOemDll, pszNT5InfId); } if (dwError == ERROR_SUCCESS) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32(dwError); } poi->m_dwError = dwError; NetSetupLogComponentStatus(pszOemDll, SzLoadIds (IDS_POSTUPGRADE_PROCESSING), hr); } else { hr = HRESULT_FROM_WIN32(poi->m_dwError); } TraceError(__FUNCNAME__, hr); return hr; } // ---------------------------------------------------------------------- // // Function: MapProductFlagToProductType // // Purpose: Map Product flag (NSF_*) to PRODUCTTYPE // // Arguments: // dwUpgradeFromProductFlag [in] product flag // // Returns: PRODUCTTYPE // // Author: kumarp 04-March-98 // // Notes: // PRODUCTTYPE MapProductFlagToProductType(IN DWORD dwUpgradeFromProductFlag) { TraceFileFunc(ttidGuiModeSetup); PRODUCTTYPE pt; switch (dwUpgradeFromProductFlag) { case NSF_WINNT_SVR_UPGRADE: case NSF_WINNT_SBS_UPGRADE: pt = NT_SERVER; break; case NSF_WINNT_WKS_UPGRADE: pt = NT_WORKSTATION; break; default: pt = UNKNOWN; break; } return pt; } // ---------------------------------------------------------------------- // // Function: GetCurrentProductBuildNumber // // Purpose: Get build number of NT on which we are running // // Arguments: None // // Returns: build number // // Author: kumarp 04-March-98 // // Notes: // DWORD GetCurrentProductBuildNumber() { TraceFileFunc(ttidGuiModeSetup); OSVERSIONINFO osv; osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osv); return osv.dwBuildNumber; } // ---------------------------------------------------------------------- // // Function: MapProductFlavorToProductType // // Purpose: Map from PRODUCT_FLAVOR to PRODUCTTYPE // // Arguments: // pf [in] product flavor // // Returns: product type // // Author: kumarp 04-March-98 // // Notes: // PRODUCTTYPE MapProductFlavorToProductType(IN PRODUCT_FLAVOR pf) { TraceFileFunc(ttidGuiModeSetup); PRODUCTTYPE pt; switch (pf) { case PF_WORKSTATION: pt = NT_WORKSTATION; break; case PF_SERVER: pt = NT_SERVER; break; } return pt; } // ---------------------------------------------------------------------- // // Function: GetCurrentProductInfo // // Purpose: Get info. on the product on which we are running // // Arguments: None // // Returns: pointer to // // Author: kumarp 04-March-98 // // Notes: // ProductInfo GetCurrentProductInfo() { TraceFileFunc(ttidGuiModeSetup); ProductInfo pi; pi.dwBuildNumber = GetCurrentProductBuildNumber(); PRODUCT_FLAVOR pf; GetProductFlavor(NULL, &pf); pi.ProductType = MapProductFlavorToProductType(pf); return pi; } // ---------------------------------------------------------------------- // // Function: HrSetupGetFieldCount // // Purpose: Wrapper for SetupGetFieldCount // // Arguments: // pic [in] pointer to INFCONTEXT // pcNumFields [out] pointer to number of fields // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 04-March-98 // // Notes: // HRESULT HrSetupGetFieldCount(IN INFCONTEXT* pic, OUT UINT* pcNumFields) { TraceFileFunc(ttidGuiModeSetup); HRESULT hr=S_OK; if (!(*pcNumFields = SetupGetFieldCount(pic))) { hr = HrFromLastWin32Error(); } return hr; } // ---------------------------------------------------------------------- // // Function: HrAfGetInfToRunValue // // Purpose: Helper fn. to parse and locate the INF/section to run // Before/After installing an OEM component // // Arguments: // hinfAnswerFile [in] handle of AnswerFile // szAnswerFileName [in] name of AnswerFile // szParamsSection [in] name of Params section // itrType [in] type of InfToRun key (Before/After) // pstrInfToRun [out] pointer to the name of INF to run // pstrSectionToRun [out] pointer to the name of section to run // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 04-March-98 // // Notes: // HRESULT HrAfGetInfToRunValue(IN HINF hinfAnswerFile, IN PCWSTR szAnswerFileName, IN PCWSTR szParamsSection, IN EInfToRunValueType itrType, OUT tstring* pstrInfToRun, OUT tstring* pstrSectionToRun, OUT tstring* pstrInfToRunType) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrAfGetInfToRunValue"); HRESULT hr=S_OK; INFCONTEXT ic, ic2; PCWSTR szInfToRunKey; if (itrType == I2R_BeforeInstall) { szInfToRunKey = c_szInfToRunBeforeInstall; } else { szInfToRunKey = c_szInfToRunAfterInstall; } *pstrInfToRunType = szInfToRunKey; hr = HrSetupFindFirstLine(hinfAnswerFile, szParamsSection, c_szAfOemSection, &ic); if (S_OK == hr) { tstring strOemSection; hr = HrSetupGetStringField(ic, 1, &strOemSection); if (S_OK == hr) { hr = HrSetupFindFirstLine(hinfAnswerFile, strOemSection.c_str(), szInfToRunKey, &ic2); if (S_OK == hr) { UINT cNumFields=0; hr = HrSetupGetFieldCount(&ic2, &cNumFields); if (S_OK == hr) { if (2 == cNumFields) { hr = HrSetupGetStringField(ic2, 1, pstrInfToRun); if (S_OK == hr) { if (pstrInfToRun->empty()) { if (itrType == I2R_AfterInstall) { *pstrInfToRun = szAnswerFileName; } else { hr = SPAPI_E_LINE_NOT_FOUND; } } if (S_OK == hr) { hr = HrSetupGetStringField(ic2, 2, pstrSectionToRun); } } } else { hr = SPAPI_E_LINE_NOT_FOUND; } } } else { hr = S_FALSE; } } } TraceErrorOptional(__FUNCNAME__, hr, ((SPAPI_E_LINE_NOT_FOUND == hr) || (S_FALSE == hr))); return hr; } // ---------------------------------------------------------------------- // // Function: HrProcessInfToRunForComponent // // Purpose: Run INF/section indicated by InfToRunBefore/AfterInstall // key of a given OEM component // // Arguments: // hinfAnswerFile [in] handle of AnswerFile // szAnswerFileName [in] name of AnswerFile // szParamsSection [in] parameters section of a component // itrType [in] type of InfToRun key (Before/After) // hwndParent [in] handle of parent window // hkeyParams [in] handle of Parameters regkey // fQuietInstall [in] TRUE if we do not want any UI to popup // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 04-March-98 // // Notes: // HRESULT HrProcessInfToRunForComponent(IN HINF hinfAnswerFile, IN PCWSTR szAnswerFileName, IN PCWSTR szParamsSection, IN EInfToRunValueType itrType, IN HWND hwndParent, IN HKEY hkeyParams, IN BOOL fQuietInstall) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrProcessInfToRunForComponent"); HRESULT hr=S_OK; tstring strInfToRun; tstring strSectionToRun; tstring strInfToRunType; hr = HrAfGetInfToRunValue(hinfAnswerFile, szAnswerFileName, szParamsSection, itrType, &strInfToRun, &strSectionToRun, &strInfToRunType); if (S_OK == hr) { hr = HrInstallFromInfSectionInFile(hwndParent, strInfToRun.c_str(), strSectionToRun.c_str(), hkeyParams, fQuietInstall); NetSetupLogHrStatusV(hr, SzLoadIds (IDS_STATUS_OF_APPLYING), szParamsSection, strInfToRunType.c_str(), strSectionToRun.c_str(), strInfToRun.c_str()); } else if (SPAPI_E_LINE_NOT_FOUND == hr) { hr = S_FALSE; } TraceErrorOptional(__FUNCNAME__, hr, (S_FALSE == hr)); return hr; } // ---------------------------------------------------------------------- // // Function: HrProcessInfToRunBeforeInstall // // Purpose: Process the answerfile and run any INFs/sections // indicated by InfToRunBeforeInstall keys // // Arguments: // hwndParent [in] handle of parent window // szAnswerFileName [in] name of AnswerFile // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 04-March-98 // // Notes: // HRESULT HrProcessInfToRunBeforeInstall(IN HWND hwndParent, IN PCWSTR szAnswerFileName) { TraceFileFunc(ttidGuiModeSetup); AssertValidReadPtr(szAnswerFileName); DefineFunctionName("HrRunInfToRunBeforeInstall"); HRESULT hr; HINF hinf; hr = HrSetupOpenInfFile(szAnswerFileName, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinf); if (S_OK == hr) { PCWSTR szSection; INFCONTEXT ic; tstring strParamsSection; for (int iSection=0; iSection < celems(c_aszComponentSections); iSection++) { szSection = c_aszComponentSections[iSection]; TraceTag(ttidNetSetup, "%s: Processing section [%S]", __FUNCNAME__, szSection); hr = HrSetupFindFirstLine(hinf, szSection, NULL, &ic); if (S_OK == hr) { do { hr = HrSetupGetStringField(ic, 1, &strParamsSection); if (S_OK == hr) { hr = HrProcessInfToRunForComponent(hinf, szAnswerFileName, strParamsSection.c_str(), I2R_BeforeInstall, hwndParent, NULL, // HKR TRUE); // fQuietInstall if (SUCCEEDED(hr)) { hr = HrSetupFindNextLine(ic, &ic); } } } while (S_OK == hr); } else if ((SPAPI_E_SECTION_NOT_FOUND == hr) || (SPAPI_E_LINE_NOT_FOUND == hr)) { hr = S_OK; } } SetupCloseInfFile(hinf); } if (S_FALSE == hr) { hr = S_OK; } TraceError(__FUNCNAME__, hr); return hr; } // ---------------------------------------------------------------------- // // Function: HrNetSetupCopyOemInfs // // Purpose: Copies all OEM INF files using SetupCopyOemInf // // Arguments: // szAnswerFileName [in] name of AnswerFile // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 12-May-98 // // Notes: // HRESULT HrNetSetupCopyOemInfs(IN PCWSTR szAnswerFileName) { TraceFileFunc(ttidGuiModeSetup); DefineFunctionName("HrNetSetupCopyOemInfs"); TraceTag(ttidNetSetup, "----> entering %s", __FUNCNAME__); AssertValidReadPtr(szAnswerFileName); HRESULT hr=S_OK; HINF hinf=NULL; INFCONTEXT ic; tstring strParamsSection; tstring strOemDir; tstring strOemInf; WCHAR szInfNameAfterCopy[MAX_PATH+1]; hr = HrSetupOpenInfFile(szAnswerFileName, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinf); if (S_OK == hr) { PCWSTR szSection; for (int iSection=0; iSection < celems(c_aszComponentSections); iSection++) { szSection = c_aszComponentSections[iSection]; TraceTag(ttidNetSetup, "%s: Processing section [%S]", __FUNCNAME__, szSection); hr = HrSetupFindFirstLine(hinf, szSection, NULL, &ic); if (S_OK == hr) { do { hr = HrSetupGetStringField(ic, 1, &strParamsSection); if (S_OK == hr) { hr = HrSetupGetFirstString(hinf, strParamsSection.c_str(), c_szAfOemInf, &strOemInf); if (S_OK == hr) { hr = HrSetupGetFirstString(hinf, strParamsSection.c_str(), c_szAfOemDir, &strOemDir); if (S_OK == hr) { AppendToPath(&strOemDir, strOemInf.c_str()); TraceTag(ttidNetSetup, "%s: calling SetupCopyOemInf for %S", __FUNCNAME__, strOemDir.c_str()); if (SetupCopyOEMInf(strOemDir.c_str(), NULL, SPOST_PATH, 0, szInfNameAfterCopy, MAX_PATH, NULL, NULL)) { ShowProgressMessage( L"...%s was copied as %s", strOemDir.c_str(), szInfNameAfterCopy); NetSetupLogHrStatusV(S_OK, SzLoadIds (IDS_OEMINF_COPY), strOemDir.c_str(), szInfNameAfterCopy); } else { hr = HrFromLastWin32Error(); ShowProgressMessage( L"...SetupCopyOemInf failed for %s: error code: 0x%08x", strOemDir.c_str(), hr); NetSetupLogComponentStatus(strOemDir.c_str(), SzLoadIds (IDS_CALLING_COPY_OEM_INF), hr); } } else if (SPAPI_E_LINE_NOT_FOUND == hr) { TraceTag(ttidNetSetup, "%s: Found %S but not %S!!", __FUNCNAME__, c_szAfOemInf, c_szAfOemDir); hr = S_OK; } } else { if (SPAPI_E_LINE_NOT_FOUND == hr) { hr = S_OK; } } } // ignore all earlier errors, see if we can do the // next item right // hr = HrSetupFindNextLine(ic, &ic); } while (S_OK == hr); } else if ((SPAPI_E_SECTION_NOT_FOUND == hr) || (SPAPI_E_LINE_NOT_FOUND == hr)) { hr = S_OK; } } SetupCloseInfFile(hinf); } if (S_FALSE == hr) { hr = S_OK; } TraceError(__FUNCNAME__, hr); return hr; }