You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
5.9 KiB
225 lines
5.9 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1999.
|
|
//
|
|
// File: L O C K D O W N . C P P
|
|
//
|
|
// Contents: Routines to get and set components that are in a lockdown
|
|
// state. A component goes into lockdown when it requires a
|
|
// reboot on removal. When a component is locked down, it
|
|
// cannot be installed until after the next reboot.
|
|
//
|
|
// Notes: Because a component comes out of lockdown after a reboot,
|
|
// a natural choice for implementation is to use a volatile
|
|
// registry key to keep track of the state. Each component
|
|
// that is locked down is represented by a volatile registry
|
|
// key the name of which is the same as the INF ID of the
|
|
// component. These keys exist under
|
|
// SYSTEM\CurrentControlSet\Control\Network\Lockdown.
|
|
//
|
|
// Author: shaunco 24 May 1999
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
#include "diagctx.h"
|
|
#include "lockdown.h"
|
|
#include "ncreg.h"
|
|
|
|
#define REGSTR_KEY_LOCKDOWN \
|
|
L"SYSTEM\\CurrentControlSet\\Control\\Network\\Lockdown"
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: EnumLockedDownComponents
|
|
//
|
|
// Purpose: Enumerate the currently locked down components via a
|
|
// caller-supplied callback.
|
|
//
|
|
// Arguments:
|
|
// pfnCallback [in] pointer to callback function
|
|
// OPTIONAL [in] optional caller-supplied data to pass back
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
// Author: shaunco 24 May 1999
|
|
//
|
|
VOID
|
|
EnumLockedDownComponents (
|
|
IN PFN_ELDC_CALLBACK pfnCallback,
|
|
IN PVOID pvCallerData OPTIONAL)
|
|
{
|
|
HRESULT hr;
|
|
HKEY hkey;
|
|
|
|
hr = HrRegOpenKeyEx (
|
|
HKEY_LOCAL_MACHINE,
|
|
REGSTR_KEY_LOCKDOWN,
|
|
KEY_READ,
|
|
&hkey);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
WCHAR szInfId [_MAX_PATH];
|
|
FILETIME ft;
|
|
DWORD dwSize;
|
|
DWORD dwRegIndex;
|
|
|
|
for (dwRegIndex = 0, dwSize = celems(szInfId);
|
|
S_OK == HrRegEnumKeyEx(hkey, dwRegIndex, szInfId,
|
|
&dwSize, NULL, NULL, &ft);
|
|
dwRegIndex++, dwSize = celems(szInfId))
|
|
{
|
|
pfnCallback (szInfId, pvCallerData);
|
|
}
|
|
|
|
RegCloseKey (hkey);;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FGetOrSetComponentLockDown
|
|
//
|
|
// Purpose: Gets or sets the state of whether a component is locked down.
|
|
//
|
|
// Arguments:
|
|
// fSet [in] TRUE to set into the lockdown state, FALSE to get.
|
|
// pszInfId [in] the INF ID of the component in question.
|
|
//
|
|
// Returns: TRUE if non-zero fSet and component is locked down.
|
|
// FALSE otherwise.
|
|
//
|
|
// Author: shaunco 24 May 1999
|
|
//
|
|
BOOL
|
|
FGetOrSetComponentLockDown (
|
|
IN BOOL fSet,
|
|
IN PCWSTR pszInfId)
|
|
{
|
|
Assert (pszInfId);
|
|
|
|
//ensure that the infid passed in is within required limits.
|
|
Assert (wcslen (pszInfId) < MAX_DEVICE_ID_LEN);
|
|
|
|
HRESULT hr;
|
|
HKEY hkey;
|
|
BOOL fRet;
|
|
WCHAR szKey [_MAX_PATH];
|
|
|
|
fRet = FALSE;
|
|
hkey = NULL;
|
|
|
|
wcscpy (szKey, REGSTR_KEY_LOCKDOWN);
|
|
wcscat (szKey, L"\\");
|
|
wcscat (szKey, pszInfId);
|
|
|
|
if (fSet)
|
|
{
|
|
g_pDiagCtx->Printf (ttidBeDiag, " %S is being locked "
|
|
"down to prevent re-install until the next reboot\n",
|
|
pszInfId);
|
|
|
|
hr = HrRegCreateKeyEx (
|
|
HKEY_LOCAL_MACHINE,
|
|
szKey,
|
|
REG_OPTION_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&hkey,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
hr = HrRegOpenKeyEx (
|
|
HKEY_LOCAL_MACHINE,
|
|
szKey,
|
|
KEY_READ,
|
|
&hkey);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
|
|
RegSafeCloseKey (hkey);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL
|
|
FIsComponentLockedDown (
|
|
IN PCWSTR pszInfId)
|
|
{
|
|
return FGetOrSetComponentLockDown (FALSE, pszInfId);
|
|
}
|
|
|
|
|
|
struct LOCKDOWN_DEPENDENCY_ENTRY
|
|
{
|
|
PCWSTR pszInfId;
|
|
const PCWSTR* ppszDependentInfIds;
|
|
};
|
|
|
|
extern const WCHAR c_szInfId_MS_NWIPX[];
|
|
extern const WCHAR c_szInfId_MS_FPNW[];
|
|
extern const WCHAR c_szInfId_MS_NWClient[];
|
|
extern const WCHAR c_szInfId_MS_NwSapAgent[];
|
|
|
|
static const PCWSTR c_apszNwlnkIpxDependentInfIds [] =
|
|
{
|
|
c_szInfId_MS_FPNW,
|
|
c_szInfId_MS_NWClient,
|
|
c_szInfId_MS_NwSapAgent,
|
|
NULL,
|
|
};
|
|
|
|
static const LOCKDOWN_DEPENDENCY_ENTRY c_LockdownDependencyMap [] =
|
|
{
|
|
{ c_szInfId_MS_NWIPX, c_apszNwlnkIpxDependentInfIds },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
VOID
|
|
LockdownComponentUntilNextReboot (
|
|
IN PCWSTR pszInfId)
|
|
{
|
|
(VOID) FGetOrSetComponentLockDown (TRUE, pszInfId);
|
|
|
|
// Lock down dependents of the component as well.
|
|
//
|
|
const LOCKDOWN_DEPENDENCY_ENTRY* pEntry;
|
|
UINT ipsz;
|
|
|
|
// Search for the matching entry in c_LockdownDependencyMap.
|
|
//
|
|
for (pEntry = c_LockdownDependencyMap;
|
|
pEntry->pszInfId;
|
|
pEntry++)
|
|
{
|
|
if (0 != _wcsicmp (pEntry->pszInfId, pszInfId))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Found a matching entry. Now lock down all of its
|
|
// dependent INF ids. The array of const PCWSTR pointers is
|
|
// terminated with a NULL pointer.
|
|
//
|
|
Assert (pEntry->ppszDependentInfIds);
|
|
|
|
for (ipsz = 0;
|
|
pEntry->ppszDependentInfIds [ipsz];
|
|
ipsz++)
|
|
{
|
|
(VOID) FGetOrSetComponentLockDown (
|
|
TRUE, pEntry->ppszDependentInfIds [ipsz]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|