//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997. // // File: A F I L E X P . C P P // // Contents: Functions exported from netsetup for answerfile related work. // // Author: kumarp 25-November-97 // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "afileint.h" #include "afilexp.h" #include "compid.h" #include "kkenet.h" #include "kkutils.h" #include "ncerror.h" #include "ncnetcfg.h" #include "ncsetup.h" #include "nsbase.h" #include "oemupgrd.h" #include "resource.h" #include "upgrade.h" #include #include "nslog.h" //+--------------------------------------------------------------------------- // Global variables // CNetInstallInfo* g_pnii; CNetInstallInfo* g_pniiTemp; DWORD g_dwOperationFlags = 0; //+--------------------------------------------------------------------------- // // Function: HrDoUnattend // // Purpose: call member function of CNetInstallInfo to perform // answerfile based install/upgrade work // // Arguments: // hwndParent [in] handle of parent window // punk [in] pointer to an interface // idPage [in] id indicating which section to run // ppdm [out] pointer to page display mode // pfAllowChanges [out] pointer to flag controlling read/write behavior // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 26-November-97 // EXTERN_C HRESULT WINAPI HrDoUnattend ( IN HWND hwndParent, IN IUnknown* punk, IN EUnattendWorkType uawType, OUT EPageDisplayMode* ppdm, OUT BOOL* pfAllowChanges) { TraceFileFunc(ttidGuiModeSetup); Assert(punk); Assert(ppdm); Assert(pfAllowChanges); Assert(g_pnii); HRESULT hr = S_OK; #if DBG if (FIsDebugFlagSet (dfidBreakOnDoUnattend)) { AssertSz(FALSE, "THIS IS NOT A BUG! The debug flag " "\"BreakOnDoUnattend\" has been set. Set your breakpoints now."); } #endif //_DEBUG hr = g_pnii->HrDoUnattended(hwndParent, punk, uawType, ppdm, pfAllowChanges); TraceHr(ttidError, FAL, hr, FALSE, "HrDoUnattend"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrInitForRepair // // Purpose: Initialize in repair mode. // // Arguments: // // Returns: S_OK on success, otherwise an error code // // Author: asinha 17-October-2001 // HRESULT HrInitForRepair (VOID) { TraceFileFunc(ttidGuiModeSetup); HRESULT hr = S_OK; g_pnii = NULL; hr = CNetInstallInfo::HrCreateInstance ( NULL, &g_pnii); TraceHr(ttidError, FAL, hr, FALSE, "HrInitForRepair"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrInitForUnattendedNetSetup // // Purpose: Initialize net setup for answerfile processing // // Arguments: // pnc [in] pointer to INetCfg object // pisd [in] pointer to private data supplied by base setup // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 26-November-97 // HRESULT HrInitForUnattendedNetSetup ( IN INetCfg* pnc, IN PINTERNAL_SETUP_DATA pisd) { TraceFileFunc(ttidGuiModeSetup); Assert(pnc); Assert(pisd); HRESULT hr = S_OK; g_dwOperationFlags = pisd->OperationFlags; if (pisd->OperationFlags & SETUPOPER_BATCH) { Assert(pisd->UnattendFile); AssertSz(!g_pnii, "who initialized g_pnii ??"); hr = HrInitAnswerFileProcessing(pisd->UnattendFile, &g_pnii); } TraceHr(ttidError, FAL, hr, (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) || (hr == NETSETUP_E_NO_ANSWERFILE), "HrInitNetSetup"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrCleanupNetSetup // // Purpose: Do cleanup work in NetSetup // // Arguments: None // // Returns: Nothing // // Author: kumarp 26-November-97 // VOID HrCleanupNetSetup() { TraceFileFunc(ttidGuiModeSetup); DeleteIfNotNull(g_pnii); DeleteIfNotNull(g_pniiTemp); } //+--------------------------------------------------------------------------- // // Function: HrGetAnswerFileName // // Purpose: Generate full path to the answerfile // // Arguments: // pstrAnswerFileName [out] pointer to name of answerfile // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 26-November-97 // // Notes: !!!This function has a dependency on the base setup.!!! // If base setup changes name of the answerfile, this fn // function will break. // HRESULT HrGetAnswerFileName( OUT tstring* pstrAnswerFileName) { TraceFileFunc(ttidGuiModeSetup); static const WCHAR c_szAfSubDirAndName[] = L"\\system32\\$winnt$.inf"; HRESULT hr=S_OK; WCHAR szWinDir[MAX_PATH+1]; DWORD cNumCharsReturned = GetSystemWindowsDirectory(szWinDir, MAX_PATH); if (cNumCharsReturned) { *pstrAnswerFileName = szWinDir; *pstrAnswerFileName += c_szAfSubDirAndName; } else { hr = HrFromLastWin32Error(); } TraceHr(ttidError, FAL, hr, FALSE, "HrGetAnswerFileName"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrInitAnswerFileProcessing // // Purpose: Initialize answerfile processing // // Arguments: // szAnswerFileName [in] name of answerfile // ppnii [out] pointer to pointer to CNetInstallInfo object // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 26-November-97 // HRESULT HrInitAnswerFileProcessing ( IN PCWSTR szAnswerFileName, OUT CNetInstallInfo** ppnii) { TraceFileFunc(ttidGuiModeSetup); Assert(ppnii); HRESULT hr = S_OK; tstring strAnswerFileName; *ppnii = NULL; if (!szAnswerFileName) { hr = HrGetAnswerFileName(&strAnswerFileName); } else { strAnswerFileName = szAnswerFileName; } if (S_OK == hr) { hr = CNetInstallInfo::HrCreateInstance ( strAnswerFileName.c_str(), ppnii); } TraceHr(ttidError, FAL, hr, (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) || (hr == NETSETUP_E_NO_ANSWERFILE), "HrInitAnswerFileProcessing"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrOemUpgrade // // Purpose: Process special OEM upgrades by running an inf section // // Arguments: // hkeyDriver [in] the driver key // pszAnswerFile [in] pointer to answer filename string. // pszAnswerSection [in] pointer to answer filname sections string // // Returns: S_OK on success, otherwise an error code // // Date: 30 Mar 1998 // EXTERN_C HRESULT WINAPI HrOemUpgrade( IN HKEY hkeyDriver, IN PCWSTR pszAnswerFile, IN PCWSTR pszAnswerSection) { TraceFileFunc(ttidGuiModeSetup); Assert(hkeyDriver); Assert(pszAnswerFile); Assert(pszAnswerSection); // Open the answer file. HINF hinf; HRESULT hr = HrSetupOpenInfFile(pszAnswerFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinf); if (SUCCEEDED(hr)) { tstring strInfToRun; tstring strSectionToRun; tstring strInfToRunType; // Get the file and section to run for upgrade hr = HrAfGetInfToRunValue(hinf, pszAnswerFile, pszAnswerSection, I2R_AfterInstall, &strInfToRun, &strSectionToRun, &strInfToRunType); if (S_OK == hr) { HINF hinfToRun; // Open the inf file containing the section to run hr = HrSetupOpenInfFile(strInfToRun.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL, &hinfToRun); if (SUCCEEDED(hr)) { TraceTag(ttidNetSetup, "Running section %S in %S", strSectionToRun.c_str(), strInfToRun.c_str()); // Run the section against the key hr = HrSetupInstallFromInfSection (NULL, hinfToRun, strSectionToRun.c_str(), SPINST_REGISTRY, hkeyDriver, NULL, 0, NULL, NULL, NULL, NULL); NetSetupLogHrStatusV(hr, SzLoadIds (IDS_STATUS_OF_APPLYING), pszAnswerSection, strInfToRunType.c_str(), strSectionToRun.c_str(), strInfToRun.c_str()); SetupCloseInfFile(hinfToRun); } } else if (SPAPI_E_LINE_NOT_FOUND == hr) { // Nothing to run. hr = S_FALSE; } SetupCloseInfFile(hinf); } TraceHr(ttidError, FAL, hr, FALSE, "HrOemUpgrade"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrGetAnswerFileParametersForComponent // // Purpose: Search in answerfile for a component whose InfId matches // the one specified. // // Arguments: // pszInfId [in] inf id of component // ppszAnswerFile [out] pointer to answer filename string. // ppszAnswerSection [out] pointer to answer filename section string // // Returns: S_OK on success, otherwise an error code // // Author: billbe 12 July 1999 // // Notes: This fcn is not for adapters. If you need the answerfile // parameters for an adapter, use // HrGetAnswerFileParametersForNetCard. // HRESULT HrGetAnswerFileParametersForComponent ( IN PCWSTR pszInfId, OUT PWSTR* ppszAnswerFile, OUT PWSTR* ppszAnswerSection) { TraceFileFunc(ttidGuiModeSetup); Assert(pszInfId); Assert(ppszAnswerFile); Assert(ppszAnswerSection); HRESULT hr = S_OK; TraceTag (ttidNetSetup, "In HrGetAnswerFileParametersForComponent"); *ppszAnswerFile = NULL; *ppszAnswerSection = NULL; // If we don't already have a cached pointer... if (!g_pniiTemp) { // Initialize our net install info. hr = HrInitAnswerFileProcessing(NULL, &g_pniiTemp); } if (S_OK == hr) { Assert(g_pniiTemp); if (!g_pniiTemp->AnswerFileInitialized()) { hr = NETSETUP_E_NO_ANSWERFILE; TraceTag (ttidNetSetup, "No answerfile"); } if (S_OK == hr) { // Find the component in the list of component's with // answer file sections. CNetComponent* pnetcomp; pnetcomp = g_pniiTemp->FindFromInfID (pszInfId); if (!pnetcomp) { // The component doesn't have a section. Return // no answer file. hr = NETSETUP_E_NO_ANSWERFILE; TraceTag (ttidNetSetup, "Component not found"); } else { if (NCT_Adapter == pnetcomp->Type()) { // We don't support getting answerfile parameters // for adapters. HrGetAnswerFileParametersForNetCard // is the fcn for adapters. hr = NETSETUP_E_NO_ANSWERFILE; } else { // Allocate and save the answerfile name and the // component's section. hr = HrCoTaskMemAllocAndDupSz (g_pniiTemp->AnswerFileName(), ppszAnswerFile, MAX_PATH); if (S_OK == hr) { hr = HrCoTaskMemAllocAndDupSz ( pnetcomp->ParamsSections().c_str(), ppszAnswerSection, MAX_PATH); } } } } } else { TraceTag (ttidNetSetup, "Answerfile could not be initialized"); } TraceHr (ttidError, FAL, hr, (NETSETUP_E_NO_ANSWERFILE == hr) || (HRESULT_FROM_WIN32 (ERROR_FILE_NOT_FOUND) == hr), "HrGetAnswerFileParametersForComponent"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrGetAnswerFileParametersForNetCard // // Purpose: Search in answerfile for a net card whose InfID matches // at least one in the supplied multi-sz list. // // Arguments: // mszInfIDs [in] list of InfIDs // pszDeviceName [in] exported device name of the card to search // pguidNetCardInstance [in] pointer to instance guid of the card // pszAnswerFile [out] pointer to answer filename string. // pszAnswerSection [out] pointer to answer filname sections string // // Returns: S_OK on success, otherwise an error code // // Author: kumarp 26-November-97 // // Notes: If more than one such card is found in the answerfile, then // resolve between the cards by finding out the net-card-address // of the pszServiceInstance and matching it against that // stored in the answerfile. // EXTERN_C HRESULT WINAPI HrGetAnswerFileParametersForNetCard( IN HDEVINFO hdi, IN PSP_DEVINFO_DATA pdeid, IN PCWSTR pszDeviceName, IN const GUID* pguidNetCardInstance, OUT PWSTR* ppszwAnswerFile, OUT PWSTR* ppszwAnswerSections) { TraceFileFunc(ttidGuiModeSetup); Assert(IsValidHandle(hdi)); Assert(pdeid); Assert(pguidNetCardInstance); Assert(ppszwAnswerFile); Assert(ppszwAnswerSections); HRESULT hr=E_FAIL; CNetAdapter* pna=NULL; WORD wNumAdapters=0; QWORD qwNetCardAddr=0; *ppszwAnswerFile = NULL; *ppszwAnswerSections = NULL; if (!g_pniiTemp) { hr = HrInitAnswerFileProcessing(NULL, &g_pniiTemp); #if DBG if (S_OK == hr) { Assert(g_pniiTemp); } #endif if (FAILED(hr) || !g_pniiTemp->AnswerFileInitialized()) { TraceHr (ttidNetSetup, FAL, hr, (hr == NETSETUP_E_NO_ANSWERFILE) || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "HrGetAnswerFileParametersForNetCard"); return hr; } } // the defs of HIDWORD and LODWORD are wrong in byteorder.hxx # define LODWORD(a) (DWORD)( (a) & ( (DWORD)~0 )) # define HIDWORD(a) (DWORD)( (a) >> (sizeof(DWORD)*8) ) hr = HrGetNetCardAddr(pszDeviceName, &qwNetCardAddr); if ((S_OK == hr) && qwNetCardAddr) { // there is a bug in wvsprintfA (used in trace.cpp) which does not // handle %I64x therefore we need to show the QWORD addr as follows // TraceTag(ttidNetSetup, "net card address of %S is 0x%x%x", pszDeviceName, HIDWORD(qwNetCardAddr), LODWORD(qwNetCardAddr)); hr = g_pniiTemp->FindAdapter(qwNetCardAddr, &pna); if (NETSETUP_E_NO_EXACT_MATCH == hr) { TraceTag(ttidError, "there is no card with this netcard address in the answer-file"); } } else { TraceTag(ttidError, "error getting netcard address of %S", pszDeviceName); // if we either (a) failed to get the NetCard address, or // (b) if the netcard address was 0 (ISDN adapters), we try other means // hr = NETSETUP_E_AMBIGUOUS_MATCH; } if (NETSETUP_E_AMBIGUOUS_MATCH == hr) { // could not match netcard using the mac addr. If this device is // PCI, try to match using location info. // TraceTag (ttidNetSetup, "Did not find a match for netcard address. " "But there was at least one section that did not specify an " "address.\nChecking bus type of installed adapter."); GUID BusTypeGuid; hr = HrSetupDiGetDeviceRegistryProperty (hdi, pdeid, SPDRP_BUSTYPEGUID, NULL, (BYTE*)&BusTypeGuid, sizeof (BusTypeGuid), NULL); if (S_OK == hr) { if (GUID_BUS_TYPE_PCI == BusTypeGuid) { TraceTag (ttidNetSetup, "Installed adapter is PCI. " "Retrieving its location info."); DWORD BusNumber; hr = HrSetupDiGetDeviceRegistryProperty (hdi, pdeid, SPDRP_BUSNUMBER, NULL, (BYTE*)&BusNumber, sizeof (BusNumber), NULL); if (S_OK == hr) { DWORD Address; hr = HrSetupDiGetDeviceRegistryProperty (hdi, pdeid, SPDRP_ADDRESS, NULL, (BYTE*)&Address, sizeof (Address), NULL); if (S_OK == hr) { TraceTag (ttidNetSetup, "Installed device location: " "Bus: %X, Device %x, Function %x\n Will try to " "use location info to find a match with the " "remaining ambiguous sections.", BusNumber, HIWORD(Address), LOWORD(Address)); hr = g_pniiTemp->FindAdapter (BusNumber, Address, &pna); #ifdef ENABLETRACE if (NETSETUP_E_NO_EXACT_MATCH == hr) { TraceTag (ttidNetSetup, "No match was found " "using PCI location info."); } else if (NETSETUP_E_AMBIGUOUS_MATCH == hr) { TraceTag (ttidNetSetup, "Location info did not " "match but some sections did not specify " "location info."); } #endif // ENABLETRACE } } } else { hr = NETSETUP_E_AMBIGUOUS_MATCH; } } if (FAILED(hr) && (NETSETUP_E_AMBIGUOUS_MATCH != hr) && (NETSETUP_E_NO_EXACT_MATCH != hr)) { TraceHr(ttidNetSetup, FAL, hr, FALSE, "Trying to retrieve/use " "PCI location info."); hr = NETSETUP_E_AMBIGUOUS_MATCH; } if (NETSETUP_E_AMBIGUOUS_MATCH == hr) { // could not match netcard using the mac addr. try to match // using the PnP ID TraceTag (ttidNetSetup, "Will try to use pnp id to find a match " "with the remaining ambiguous sections."); PWSTR mszInfIds; hr = HrGetCompatibleIds (hdi, pdeid, &mszInfIds); if (S_OK == hr) { #ifdef ENABLETRACE TStringList slInfIds; tstring strInfIds; MultiSzToColString(mszInfIds, &slInfIds); ConvertStringListToCommaList(slInfIds, strInfIds); TraceTag(ttidNetSetup, "(InfIDs (%d): %S\tDeviceName: %S)", slInfIds.size(), strInfIds.c_str(), pszDeviceName); #endif // find out how many adapters have this InfID wNumAdapters = (WORD)g_pniiTemp->AdaptersPage()->GetNumCompatibleAdapters(mszInfIds); TraceTag(ttidNetSetup, "%d adapters of type '%S' found in the answer-file", wNumAdapters, mszInfIds); if (wNumAdapters == 1) { // a definite match found pna = (CNetAdapter*) g_pniiTemp->AdaptersPage()->FindCompatibleAdapter(mszInfIds); Assert(pna); // Since matching by inf id can cause one section to be // matched to multiple adapters, we pass on sections that // have already been give to an adapter. // GUID guid = GUID_NULL; pna->GetInstanceGuid(&guid); if (GUID_NULL == guid) { // The section is still available. hr = S_OK; } else { // This section was given to another adapter. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); } } else { // either there are no adapters of this type in the answerfile // or there are multiple adapters of the same type. // we couldn't match the card using the mac addr earlier. // must return error // hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); } MemFree (mszInfIds); } } } if (S_OK == hr) { Assert(pna); pna->SetInstanceGuid(pguidNetCardInstance); hr = HrCoTaskMemAllocAndDupSz(g_pniiTemp->AnswerFileName(), (PWSTR*) ppszwAnswerFile, MAX_PATH); if (S_OK == hr) { hr = HrCoTaskMemAllocAndDupSz(pna->ParamsSections().c_str(), (PWSTR*) ppszwAnswerSections, MAX_PATH); } } if (S_OK != hr && (NETSETUP_E_NO_ANSWERFILE != hr)) { // add log so that we know why adapter specific params // are lost after upgrade // if (g_dwOperationFlags & SETUPOPER_NTUPGRADE) { // bug 124805 - We only want to see this during upgradres WCHAR szGuid[c_cchGuidWithTerm]; StringFromGUID2(*pguidNetCardInstance, szGuid, c_cchGuidWithTerm); NetSetupLogStatusV(LogSevWarning, SzLoadIds (IDS_ANSWERFILE_SECTION_NOT_FOUND), szGuid); } } if ((NETSETUP_E_AMBIGUOUS_MATCH == hr) || (NETSETUP_E_NO_EXACT_MATCH == hr)) { hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); } TraceHr(ttidError, FAL, hr, (hr == NETSETUP_E_NO_ANSWERFILE) || (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)), "HrGetAnswerFileParametersForNetCard"); return hr; } //+--------------------------------------------------------------------------- // // Function: HrGetInstanceGuidOfPreNT5NetCardInstance // // Purpose: Finds the instance guid of a component specified in the answerfile // or an already installed component // // Arguments: // szPreNT5NetCardInstance [in] pre-NT5 net card instance name e.g. "ieepro2" // pguid [out] instance guid of the same card // // Returns: S_OK if found, S_FALSE if not, or an error code. // // Author: kumarp 12-AUG-97 // // Notes: // EXTERN_C HRESULT WINAPI HrGetInstanceGuidOfPreNT5NetCardInstance ( IN PCWSTR szPreNT5NetCardInstance, OUT LPGUID pguid) { TraceFileFunc(ttidGuiModeSetup); Assert(szPreNT5NetCardInstance); Assert(pguid); HRESULT hr = E_FAIL; if (IsBadStringPtr(szPreNT5NetCardInstance, 64) || IsBadWritePtr(pguid, sizeof(GUID))) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } else if (g_pnii) { hr = g_pnii->HrGetInstanceGuidOfPreNT5NetCardInstance ( szPreNT5NetCardInstance, pguid); } TraceHr(ttidError, FAL, hr, FALSE, "HrGetInstanceGuidOfPreNT5NetCardInstance"); return hr; } HRESULT HrResolveAnswerFileAdapters ( IN INetCfg* pnc) { TraceFileFunc(ttidGuiModeSetup); Assert(g_pnii); HRESULT hr = S_OK; if (g_pnii) { hr = g_pnii->AdaptersPage()->HrResolveNetAdapters(pnc); } TraceHr(ttidError, FAL, hr, FALSE, "HrResolveAnswerFileAdapters"); return hr; }