//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1999. // // File: P E R S I S T . C P P // // Contents: Module repsonsible for persistence of the network // configuration information. // // Notes: // // Author: shaunco 15 Jan 1999 // //---------------------------------------------------------------------------- #include #pragma hdrstop #include "persist.h" #include "ncreg.h" #if defined (_X86_) inline BOOL IsRunningOnWow64() { static DWORD dwCachedWow64 = DWORD_MAX; if (DWORD_MAX == dwCachedWow64) { BOOL fTempWow64; if (IsWow64Process(GetCurrentProcess(), &fTempWow64)) { dwCachedWow64 = fTempWow64; } else { AssertSz(FALSE, "Could not determine whether this is a WOW64 process."); return FALSE; } } return dwCachedWow64; } inline size_t ALIGNUP(size_t nSize) { // If we are a 32-bit app running on a 64-bit O/S we need to use 64-bit alignment when reading or writing from the registry. if (IsRunningOnWow64()) { return ((nSize + (sizeof(DWORD64) - 1)) & ~(sizeof(DWORD64) - 1)); } else { return nSize; } } #elif defined (_WIN64) #define ALIGNUP(x) ((x + (sizeof(PVOID) - 1)) & ~(sizeof(PVOID) - 1)) #else #error Please define an ALIGNUP implementation for this architecture. #endif #define alignedsizeof(x) ALIGNUP(sizeof(x)) const DWORD CURRENT_VERSION = 0; HRESULT HrLoadNetworkConfigurationFromBuffer ( IN const BYTE* pbBuf, IN ULONG cbBuf, OUT CNetConfig* pNetConfig) { HRESULT hr; DWORD dwVersion; ULONG cComponents; ULONG cStackEntries; ULONG cBindPaths; ULONG unUpperIndex; ULONG unLowerIndex; ULONG unComponentIndex; BOOL fRefByUser; BASIC_COMPONENT_DATA Data; CComponentList* pComponents; CComponent* pComponent; CStackEntry StackEntry; CBindPath BindPath; PCWSTR pszString; // We should be starting clean. // Assert (pNetConfig->Core.FIsEmpty()); hr = S_OK; // Load the version marker. // dwVersion = *(DWORD32*)pbBuf; pbBuf += alignedsizeof(DWORD32); if (dwVersion > CURRENT_VERSION) { hr = E_UNEXPECTED; goto finished; } // Load the component list. // cComponents = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); while (cComponents--) { ZeroMemory (&Data, sizeof(Data)); Data.InstanceGuid = *(GUID*)pbBuf; pbBuf += alignedsizeof(GUID); Data.Class = *(NETCLASS*)pbBuf; pbBuf += alignedsizeof(NETCLASS); Data.dwCharacter = *(DWORD32*)pbBuf; pbBuf += alignedsizeof(DWORD32); Data.pszInfId = (PCWSTR)pbBuf; Assert (*Data.pszInfId); pbBuf += ALIGNUP(CbOfSzAndTerm (Data.pszInfId)); pszString = (PCWSTR)pbBuf; pbBuf += ALIGNUP(CbOfSzAndTerm (pszString)); if (*pszString) { Data.pszPnpId = pszString; } hr = CComponent::HrCreateInstance ( &Data, CCI_DEFAULT, NULL, &pComponent); if (S_OK == hr) { hr = pNetConfig->Core.Components.HrInsertComponent ( pComponent, INS_ASSERT_IF_DUP | INS_NON_SORTED); } if (S_OK != hr) { goto finished; } } // Load the stack table. // pComponents = &pNetConfig->Core.Components; pNetConfig->Core.StackTable.m_fWanAdaptersFirst = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); cStackEntries = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); while (cStackEntries--) { ZeroMemory (&StackEntry, sizeof(StackEntry)); unUpperIndex = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); unLowerIndex = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); StackEntry.pUpper = pComponents->PGetComponentAtIndex ( unUpperIndex); StackEntry.pLower = pComponents->PGetComponentAtIndex ( unLowerIndex); // Insert in the order we persisted. If we used ISE_SORT here, we'd // blow away whatever bind order we saved. // hr = pNetConfig->Core.StackTable.HrInsertStackEntry ( &StackEntry, INS_NON_SORTED); if (S_OK != hr) { goto finished; } } // Load the disabled bindpaths. // cBindPaths = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); while (cBindPaths--) { cComponents = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); BindPath.Clear(); while (cComponents--) { unComponentIndex = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); pComponent = pComponents->PGetComponentAtIndex (unComponentIndex); Assert (pComponent); hr = BindPath.HrAppendComponent (pComponent); if (S_OK != hr) { goto finished; } } hr = pNetConfig->Core.DisabledBindings.HrAddBindPath ( &BindPath, INS_ASSERT_IF_DUP | INS_APPEND); if (S_OK != hr) { goto finished; } } // Load the component references. // cComponents = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); while (cComponents--) { unComponentIndex = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); pComponent = pComponents->PGetComponentAtIndex (unComponentIndex); Assert (pComponent); fRefByUser = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); if (fRefByUser) { hr = pComponent->Refs.HrAddReferenceByUser (); if (S_OK != hr) { goto finished; } } // Load the count of components that reference this component. // ULONG CountRefdBy = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); // Load the indicies of the components that reference this component. // for (UINT i = 0; i < CountRefdBy; i++) { unComponentIndex = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); CComponent* pRefdBy; pRefdBy = pComponents->PGetComponentAtIndex (unComponentIndex); Assert (pRefdBy); hr = pComponent->Refs.HrAddReferenceByComponent (pRefdBy); if (S_OK != hr) { goto finished; } } // Load the count of strings that represent external software // that reference this component. // CountRefdBy = *(ULONG32*)pbBuf; pbBuf += alignedsizeof(ULONG32); // Load the strings that represent external software that // references this component. // for (i = 0; i < CountRefdBy; i++) { pszString = (PCWSTR)pbBuf; pbBuf += ALIGNUP(CbOfSzAndTerm (pszString)); hr = pComponent->Refs.HrAddReferenceBySoftware (pszString); if (S_OK != hr) { goto finished; } } } finished: if (S_OK != hr) { pNetConfig->Core.DisabledBindings.Clear (); pNetConfig->Core.StackTable.Clear (); FreeCollectionAndItem (pNetConfig->Core.Components); } return hr; } HRESULT HrLoadNetworkConfigurationFromRegistry ( IN REGSAM samDesired, OUT CNetConfig* pNetConfig) { HRESULT hr; HKEY hkeyNetwork; Assert ((KEY_READ == samDesired) || (KEY_WRITE == samDesired)); hr = HrOpenNetworkKey (KEY_READ, &hkeyNetwork); if (S_OK == hr) { BYTE* pbBuf; ULONG cbBuf; hr = HrRegQueryBinaryWithAlloc ( hkeyNetwork, L"Config", &pbBuf, &cbBuf); // If we read the config binary, use it to initialize pNetConfig. // if (S_OK == hr) { hr = HrLoadNetworkConfigurationFromBuffer (pbBuf, cbBuf, pNetConfig); if (S_OK == hr) { pNetConfig->Core.DbgVerifyData (); } MemFree (pbBuf); } // Otherwise, if we couldn't read the config binary, we'll have // to construct what we can by grovelling the registry. // else { hr = HrLoadNetworkConfigurationFromLegacy (pNetConfig); if (S_OK == hr) { hr = HrSaveNetworkConfigurationToRegistry (pNetConfig); } } RegCloseKey (hkeyNetwork); } TraceHr (ttidError, FAL, hr, FALSE, "HrLoadNetworkConfigurationFromRegistry"); return hr; } ULONG CountComponentsReferencedByOthers ( IN CNetConfig* pNetConfig) { ULONG cComponents; CComponentList::iterator iter; CComponent* pComponent; cComponents = 0; for (iter = pNetConfig->Core.Components.begin(); iter != pNetConfig->Core.Components.end(); iter++) { pComponent = *iter; Assert (pComponent); if (pComponent->Refs.FIsReferencedByOthers ()) { cComponents++; } } return cComponents; } HRESULT HrSaveNetworkConfigurationToBuffer ( IN CNetConfig* pNetConfig, IN BYTE* pbBuf, IN OUT ULONG* pcbBuf) { HRESULT hr; ULONG cbBuf; ULONG cbBufIn; ULONG unIndex; ULONG Count; CComponentList* pComponents; CComponent* pComponent; CStackEntry* pStackEntry; CBindPath* pBindPath; PCWSTR pszString; Assert (pNetConfig); pNetConfig->Core.DbgVerifyData (); Assert (pcbBuf); cbBufIn = *pcbBuf; cbBuf = 0; pComponents = &pNetConfig->Core.Components; // Save the version number. // cbBuf += alignedsizeof(DWORD32); if (pbBuf && (cbBuf <= cbBufIn)) { *(DWORD32*)pbBuf = CURRENT_VERSION; pbBuf += alignedsizeof(DWORD32); } // Save the component list. // Count = pComponents->Count(); cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = Count; pbBuf += alignedsizeof(ULONG32); } for (unIndex = 0; unIndex < Count; unIndex++) { pComponent = pComponents->PGetComponentAtIndex (unIndex); Assert (pComponent); pszString = (pComponent->m_pszPnpId) ? pComponent->m_pszPnpId : L""; ULONG cbInfIdUnpad = CbOfSzAndTerm (pComponent->m_pszInfId); ULONG cbPnpIdUnpad = CbOfSzAndTerm (pszString); ULONG cbInfId = ALIGNUP(cbInfIdUnpad); ULONG cbPnpId = ALIGNUP(cbPnpIdUnpad); cbBuf += alignedsizeof(GUID) + alignedsizeof(NETCLASS) + alignedsizeof(DWORD32) + cbInfId + cbPnpId; if (pbBuf && (cbBuf <= cbBufIn)) { *(GUID*)pbBuf = pComponent->m_InstanceGuid; pbBuf += alignedsizeof(GUID); *(NETCLASS*)pbBuf = pComponent->Class(); pbBuf += alignedsizeof(NETCLASS); *(DWORD32*)pbBuf = pComponent->m_dwCharacter; pbBuf += alignedsizeof(DWORD32); CopyMemory(pbBuf, pComponent->m_pszInfId, cbInfIdUnpad); pbBuf += cbInfId; CopyMemory(pbBuf, pszString, cbPnpIdUnpad); pbBuf += cbPnpId; } } // Save the stack table. // cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = pNetConfig->Core.StackTable.m_fWanAdaptersFirst; pbBuf += alignedsizeof(ULONG32); } Count = pNetConfig->Core.StackTable.CountEntries(); cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = Count; pbBuf += alignedsizeof(ULONG32); } for (pStackEntry = pNetConfig->Core.StackTable.begin(); pStackEntry != pNetConfig->Core.StackTable.end(); pStackEntry++) { cbBuf += alignedsizeof(ULONG32) + alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = pComponents->UnGetIndexOfComponent (pStackEntry->pUpper); pbBuf += alignedsizeof(ULONG32); *(ULONG32*)pbBuf = pComponents->UnGetIndexOfComponent (pStackEntry->pLower); pbBuf += alignedsizeof(ULONG32); } } // Save the disabled bindpaths. // Count = pNetConfig->Core.DisabledBindings.CountBindPaths(); cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = Count; pbBuf += alignedsizeof(ULONG32); } for (pBindPath = pNetConfig->Core.DisabledBindings.begin(); pBindPath != pNetConfig->Core.DisabledBindings.end(); pBindPath++) { Count = pBindPath->CountComponents(); cbBuf += alignedsizeof(ULONG32) + (Count * alignedsizeof(ULONG32)); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = Count; pbBuf += alignedsizeof(ULONG32); CBindPath::iterator iter; for (iter = pBindPath->begin(); iter != pBindPath->end(); iter++) { pComponent = *iter; *(ULONG32*)pbBuf = pComponents->UnGetIndexOfComponent (pComponent); pbBuf += alignedsizeof(ULONG32); } } } // Save the component references. // Count = CountComponentsReferencedByOthers (pNetConfig); cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = Count; pbBuf += alignedsizeof(ULONG32); } for (unIndex = 0; unIndex < pComponents->Count(); unIndex++) { pComponent = pComponents->PGetComponentAtIndex (unIndex); Assert (pComponent); if (!pComponent->Refs.FIsReferencedByOthers ()) { continue; } // Index of component with the references. // cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = unIndex; pbBuf += alignedsizeof(ULONG32); } // Save whether the component is refernced by the user or not. // cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = pComponent->Refs.FIsReferencedByUser() ? 1 : 0; pbBuf += alignedsizeof(ULONG32); } // Save the count of components that reference this component. // ULONG CountRefdBy = pComponent->Refs.CountComponentsReferencedBy (); cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = CountRefdBy; pbBuf += alignedsizeof(ULONG32); } // Save the indicies of the components that reference this component. // for (UINT i = 0; i < CountRefdBy; i++) { CComponent* pRefdBy; pRefdBy = pComponent->Refs.PComponentReferencedByAtIndex(i); Assert (pRefdBy); cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = pComponents->UnGetIndexOfComponent (pRefdBy); pbBuf += alignedsizeof(ULONG32); } } // Save the count of strings that represent external software // that reference this component. // CountRefdBy = pComponent->Refs.CountSoftwareReferencedBy (); cbBuf += alignedsizeof(ULONG32); if (pbBuf && (cbBuf <= cbBufIn)) { *(ULONG32*)pbBuf = CountRefdBy; pbBuf += alignedsizeof(ULONG32); } // Save the strings that represent external software that // reference this component. // for (i = 0; i < CountRefdBy; i++) { const CWideString* pStr; pStr = pComponent->Refs.PSoftwareReferencedByAtIndex(i); Assert (pStr); ULONG cb = (pStr->length() + 1) * sizeof(WCHAR); cbBuf += ALIGNUP(cb); if (pbBuf && (cbBuf <= cbBufIn)) { CopyMemory (pbBuf, pStr->c_str(), cb); pbBuf += ALIGNUP(cb); } } } *pcbBuf = cbBuf; if (cbBuf <= cbBufIn) { hr = S_OK; } else { hr = (pbBuf) ? HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) : S_OK; } TraceHr (ttidError, FAL, hr, FALSE, "HrSaveNetworkConfigurationToBuffer"); return hr; } HRESULT HrSaveNetworkConfigurationToBufferWithAlloc ( IN CNetConfig* pNetConfig, OUT BYTE** ppbBuf, OUT ULONG* pcbBuf) { HRESULT hr; Assert (pNetConfig); Assert (ppbBuf); Assert (pcbBuf); *ppbBuf = NULL; *pcbBuf = 0; ULONG cbBuf; hr = HrSaveNetworkConfigurationToBuffer (pNetConfig, NULL, &cbBuf); if (S_OK == hr) { hr = E_OUTOFMEMORY; *ppbBuf = (BYTE*)MemAlloc (cbBuf); if (*ppbBuf) { hr = HrSaveNetworkConfigurationToBuffer ( pNetConfig, *ppbBuf, &cbBuf); if (S_OK == hr) { *pcbBuf = cbBuf; } } } TraceHr (ttidError, FAL, hr, FALSE, "HrSaveNetworkConfigurationToBufferWithAlloc"); return hr; } HRESULT HrSaveNetworkConfigurationToRegistry ( IN CNetConfig* pNetConfig) { HRESULT hr; HKEY hkeyNetwork; Assert (pNetConfig); pNetConfig->Core.DbgVerifyData (); hr = HrOpenNetworkKey (KEY_WRITE, &hkeyNetwork); if (S_OK == hr) { BYTE* pbBuf; ULONG cbBuf; hr = HrSaveNetworkConfigurationToBufferWithAlloc ( pNetConfig, &pbBuf, &cbBuf); if (S_OK == hr) { hr = HrRegSetBinary (hkeyNetwork, L"Config", pbBuf, cbBuf); MemFree (pbBuf); // Permission from the Perf team to call this. We need to ensure // that the configuration we just wrote will be available on // next boot in the case that we crash. // RegFlushKey (hkeyNetwork); } RegCloseKey (hkeyNetwork); } TraceHr (ttidError, FAL, hr, FALSE, "HrSaveNetworkConfigurationToRegistry"); return hr; }