windows-nt/Source/XPSP1/NT/net/config/netcfg/engine/persist.cpp

717 lines
18 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// 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 <pch.h>
#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;
}