1259 lines
32 KiB
C
1259 lines
32 KiB
C
/*
|
|
File Steelhead.c
|
|
|
|
Implementation of functions to update the registry when an
|
|
NT 4.0 Steelhead to NT 5.0 upgrade takes place.
|
|
|
|
Paul Mayfield, 8/11/97
|
|
|
|
Copyright 1997 Microsoft.
|
|
*/
|
|
|
|
#include "upgrade.h"
|
|
#include <wchar.h>
|
|
#include <rtcfg.h>
|
|
|
|
//
|
|
// Macro for convenience
|
|
//
|
|
#define BREAK_ON_ERROR(_err) if ((_err)) break
|
|
|
|
//
|
|
// Defines a function to get nt4.0 interface name from a
|
|
// guid.
|
|
//
|
|
typedef HRESULT (*GetGuidFromInterfaceNameProc)(PWCHAR,LPGUID);
|
|
|
|
//
|
|
// The following define what is needed to infer guids from 4.0
|
|
// interface names.
|
|
//
|
|
WCHAR NetCfgLibName[] = L"netshell.dll";
|
|
CHAR GuidProcName[] = "HrGetInstanceGuidOfPreNT5NetCardInstance";
|
|
static const WCHAR c_szwInternalAdapter [] = L"Internal";
|
|
static const WCHAR c_szwLoopbackAdapter [] = L"Loopback";
|
|
|
|
GetGuidFromInterfaceNameProc GetGuid = NULL;
|
|
|
|
// Function uses the application defined parameter to initialize the
|
|
// system of mapping old interface names to new ones.
|
|
//
|
|
DWORD SeedInterfaceNameMapper(
|
|
OUT PHANDLE phParam)
|
|
{
|
|
HINSTANCE hLibModule;
|
|
|
|
// Load the library
|
|
hLibModule = LoadLibraryW(NetCfgLibName);
|
|
if (hLibModule == NULL) {
|
|
PrintMessage(L"Unable to load NetCfgLibName\n");
|
|
return GetLastError();
|
|
}
|
|
|
|
// Get the appropriate function pointers
|
|
GetGuid = (GetGuidFromInterfaceNameProc)
|
|
GetProcAddress(hLibModule, GuidProcName);
|
|
if (GetGuid == NULL) {
|
|
PrintMessage(L"Unable to get GuidProcName\n");
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
// Assign the return value
|
|
*phParam = (HANDLE)hLibModule;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Cleans up the interface name mapper.
|
|
//
|
|
DWORD CleanupInterfaceNameMapper(HANDLE hParam) {
|
|
HINSTANCE hLibModule = (HINSTANCE)hParam;
|
|
|
|
if (hLibModule) {
|
|
if (! FreeLibrary(hLibModule))
|
|
PrintMessage(L"Unable to free library\n");
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Determines whether the type of interface being examined
|
|
// should have its name changed.
|
|
//
|
|
BOOL IfNeedsNameUpdate(
|
|
IN MPR_INTERFACE_0 * If)
|
|
{
|
|
// Validate parameters
|
|
if (!If) {
|
|
PrintMessage(L"Null interface passed to IfNeedsNameUpdate.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// Only lan interfaces can have their names updated
|
|
if (If->dwIfType == ROUTER_IF_TYPE_DEDICATED)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Returns a pointer to the packet name portion of the
|
|
// interface name if it exists.
|
|
//
|
|
PWCHAR FindPacketName(
|
|
IN PWCHAR IfName)
|
|
{
|
|
PWCHAR res;
|
|
|
|
if ((res = wcsstr(IfName,L"/Ethernet_SNAP")) != NULL)
|
|
return res;
|
|
|
|
if ((res = wcsstr(IfName,L"/Ethernet_II")) != NULL)
|
|
return res;
|
|
|
|
if ((res = wcsstr(IfName,L"/Ethernet_802.2")) != NULL)
|
|
return res;
|
|
|
|
if ((res = wcsstr(IfName,L"/Ethernet_802.3")) != NULL)
|
|
return res;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Upgrades a packet name from the 4.0 convention to
|
|
// the nt5 convention.
|
|
//
|
|
PWCHAR UpgradePktName(
|
|
IN PWCHAR PacketName)
|
|
{
|
|
PWCHAR res;
|
|
|
|
if ((res = wcsstr(PacketName,L"/Ethernet_SNAP")) != NULL)
|
|
return L"/SNAP";
|
|
|
|
if ((res = wcsstr(PacketName,L"/Ethernet_II")) != NULL)
|
|
return L"/EthII";
|
|
|
|
if ((res = wcsstr(PacketName,L"/Ethernet_802.2")) != NULL)
|
|
return L"/802.2";
|
|
|
|
if ((res = wcsstr(PacketName,L"/Ethernet_802.3")) != NULL)
|
|
return L"/802.3";
|
|
|
|
return L"";
|
|
}
|
|
|
|
|
|
//
|
|
// Provides the mapping between old interface names and new guid
|
|
// interface names.
|
|
//
|
|
DWORD UpdateInterfaceName(
|
|
IN PWCHAR IName)
|
|
{
|
|
HRESULT hResult;
|
|
GUID Guid;
|
|
PWCHAR GuidName=NULL;
|
|
PWCHAR PacketName=NULL;
|
|
WCHAR SavedPacketName[MAX_INTEFACE_NAME_LEN];
|
|
WCHAR SavedIName[MAX_INTEFACE_NAME_LEN];
|
|
PWCHAR ptr;
|
|
|
|
// Validate parameters
|
|
if (! IName) {
|
|
PrintMessage(L"Invalid parameter to UpdateInterfaceName.\n");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Save off the packet name if it exists and remove if from the
|
|
// interface name
|
|
wcscpy(SavedIName, IName);
|
|
PacketName = FindPacketName(SavedIName);
|
|
if (PacketName) {
|
|
wcscpy(SavedPacketName, PacketName);
|
|
*PacketName = 0;
|
|
}
|
|
|
|
// Get the guid of the interface name
|
|
hResult = (*GetGuid)(SavedIName,&Guid);
|
|
if (hResult != S_OK) {
|
|
PrintMessage(L"Unable to get guid function.\n");
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
// Format the guid as a string
|
|
if (UuidToStringW(&Guid, &GuidName) != RPC_S_OK) {
|
|
PrintMessage(L"Not enough memory to create guid string.\n");
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
// Capitalize the guid string (all letters are hexidecimal
|
|
// string characters)
|
|
ptr = GuidName;
|
|
while (ptr && *ptr) {
|
|
if ((*ptr <= L'z') && (*ptr >= L'a'))
|
|
*ptr = towupper(*ptr);
|
|
ptr++;
|
|
}
|
|
|
|
// Change the interface name according to the new mapping
|
|
if (PacketName) {
|
|
wsprintf(IName, L"{%s}%s", GuidName, UpgradePktName(SavedPacketName));
|
|
}
|
|
else
|
|
wsprintfW(IName,L"{%s}", GuidName);
|
|
|
|
// Cleanup
|
|
if (GuidName)
|
|
RpcStringFreeW(&GuidName);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Provides the mapping between old interface names and new guid
|
|
// interface names.
|
|
//
|
|
DWORD UpdateIpxAdapterName(PWCHAR AName) {
|
|
HRESULT hResult;
|
|
GUID Guid;
|
|
PWCHAR GuidName = NULL;
|
|
PWCHAR PacketName = NULL;
|
|
WCHAR SavedAName[MAX_INTEFACE_NAME_LEN];
|
|
PWCHAR ptr = NULL;
|
|
|
|
// Validate parameters
|
|
if (!AName) {
|
|
PrintMessage(L"Invalid parameter to UpdateIpxAdapterName.\n");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Adapter names do not have packet types associated with them
|
|
if (FindPacketName(AName))
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
|
|
// Get the guid of the interface name
|
|
hResult = (*GetGuid)(AName,&Guid);
|
|
if (hResult!=S_OK) {
|
|
PrintMessage(L"GetGuid function returned failure.\n");
|
|
return ERROR_CAN_NOT_COMPLETE;
|
|
}
|
|
|
|
// Format the guid as a string
|
|
if (UuidToStringW(&Guid,&GuidName) != RPC_S_OK) {
|
|
PrintMessage(L"Uuid to string failed.\n");
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
// Capitalize the guid string
|
|
ptr = GuidName;
|
|
while (ptr && *ptr) {
|
|
if ((*ptr <= L'z') && (*ptr >= L'a'))
|
|
*ptr = towupper(*ptr);
|
|
ptr++;
|
|
}
|
|
|
|
// Change the adapter name according to the new mapping
|
|
wsprintfW(AName, L"{%s}", GuidName);
|
|
|
|
// Cleanup
|
|
if (GuidName)
|
|
RpcStringFreeW(&GuidName);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Update the interface name stored in the adapter info blob
|
|
//
|
|
DWORD UpdateIpxAdapterInfo(
|
|
IN PIPX_ADAPTER_INFO AdapterInfop,
|
|
OUT PIPX_ADAPTER_INFO * NewAdapterInfop,
|
|
OUT DWORD * NewSize)
|
|
{
|
|
DWORD dwErr;
|
|
|
|
// Validate parameters
|
|
if (! (AdapterInfop && NewAdapterInfop && NewSize)) {
|
|
PrintMessage(L"Invalid params to UpdateIpxAdapterInfo.\n");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Allocate a new adapter
|
|
*NewAdapterInfop = (PIPX_ADAPTER_INFO)
|
|
UtlAlloc(sizeof(IPX_ADAPTER_INFO));
|
|
if (! (*NewAdapterInfop)) {
|
|
PrintMessage(L"Unable to allocate NewAdapterInfo.\n");
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
// Copy into the new interface name
|
|
(*NewAdapterInfop)->PacketType = AdapterInfop->PacketType;
|
|
wcscpy(
|
|
(*NewAdapterInfop)->AdapterName,
|
|
AdapterInfop->AdapterName);
|
|
|
|
// Update the interface name
|
|
dwErr = UpdateIpxAdapterName((*NewAdapterInfop)->AdapterName);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"UpdateIpxAdapterName failed.\n");
|
|
return dwErr;
|
|
}
|
|
*NewSize = sizeof(IPX_ADAPTER_INFO);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Update all of the ipx related interface
|
|
// information in the router configuration
|
|
//
|
|
DWORD UpdateIpxIfData(
|
|
IN HANDLE hConfig,
|
|
IN HANDLE hInterface)
|
|
{
|
|
PIPX_ADAPTER_INFO AdapterInfop;
|
|
PIPX_ADAPTER_INFO NewAdapterInfop;
|
|
DWORD dwErr, dwCount, dwSize, dwNewSize, dwTransSize;
|
|
HANDLE hTransport;
|
|
LPBYTE pTransInfo = NULL, pNewInfo = NULL;
|
|
|
|
// Validate parameters
|
|
if (!hConfig || !hInterface)
|
|
{
|
|
PrintMessage(L"Invalid params passed to UpdateIpxIfData.\n");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
do {
|
|
// Update the ipx interface info since this protocol
|
|
// stores interface specific info in the transport
|
|
// info blob (shame shame).
|
|
dwErr = MprConfigInterfaceTransportGetHandle(
|
|
hConfig,
|
|
hInterface,
|
|
PID_IPX,
|
|
&hTransport);
|
|
if (dwErr != NO_ERROR)
|
|
break;
|
|
|
|
// Update the adapter info blob
|
|
dwErr = MprConfigInterfaceTransportGetInfo(
|
|
hConfig,
|
|
hInterface,
|
|
hTransport,
|
|
&pTransInfo,
|
|
&dwTransSize);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"Unable to get transport info for ipx.\n");
|
|
break;
|
|
}
|
|
|
|
// Get the adapter info associated with this interface
|
|
dwErr = MprInfoBlockFind(
|
|
pTransInfo,
|
|
IPX_ADAPTER_INFO_TYPE,
|
|
&dwSize,
|
|
&dwCount,
|
|
(LPBYTE*)&AdapterInfop);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"ERROR - null adapter information.\n");
|
|
break;
|
|
}
|
|
|
|
// Change the name of the referenced adapter
|
|
dwErr = UpdateIpxAdapterInfo(AdapterInfop, &NewAdapterInfop, &dwNewSize);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"UpdateIpxAdapterInfo failed.\n");
|
|
break;
|
|
}
|
|
|
|
dwErr = MprInfoBlockSet(
|
|
pTransInfo,
|
|
IPX_ADAPTER_INFO_TYPE,
|
|
dwNewSize,
|
|
1,
|
|
(LPVOID)NewAdapterInfop,
|
|
&pNewInfo);
|
|
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"MprInfoBlockSet failed.\n");
|
|
break;
|
|
}
|
|
|
|
dwNewSize = ((PRTR_INFO_BLOCK_HEADER)pNewInfo)->Size;
|
|
|
|
// Commit the change
|
|
dwErr = MprConfigInterfaceTransportSetInfo(
|
|
hConfig,
|
|
hInterface,
|
|
hTransport,
|
|
pNewInfo,
|
|
dwNewSize);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"Unable to set ipx transport info.\n");
|
|
break;
|
|
}
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
if (pTransInfo)
|
|
MprConfigBufferFree(pTransInfo);
|
|
if (pNewInfo)
|
|
MprConfigBufferFree(pNewInfo);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Updates the ip interface info
|
|
//
|
|
DWORD
|
|
UpdateIpIfData(
|
|
IN HANDLE hConfig,
|
|
IN HANDLE hInterface)
|
|
{
|
|
PMIB_IPFORWARDROW pRoutes;
|
|
DWORD dwErr, dwCount, dwSize, dwNewSize, dwTransSize, dwInd;
|
|
HANDLE hTransport;
|
|
LPBYTE pTransInfo = NULL, pNewInfo = NULL;
|
|
|
|
pRoutes = NULL;
|
|
|
|
// Validate parameters
|
|
if (!hConfig || !hInterface)
|
|
{
|
|
PrintMessage(L"Invalid params passed to UpdateIpIfData.\n");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
do {
|
|
// Update the ipx interface info since this protocol
|
|
// stores interface specific info in the transport
|
|
// info blob (shame shame).
|
|
dwErr = MprConfigInterfaceTransportGetHandle(
|
|
hConfig,
|
|
hInterface,
|
|
PID_IP,
|
|
&hTransport);
|
|
if (dwErr != NO_ERROR)
|
|
break;
|
|
|
|
// Update the adapter info blob
|
|
dwErr = MprConfigInterfaceTransportGetInfo(
|
|
hConfig,
|
|
hInterface,
|
|
hTransport,
|
|
&pTransInfo,
|
|
&dwTransSize);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"Unable to get transport info for ip.\n");
|
|
break;
|
|
}
|
|
|
|
// Get the adapter info associated with this interface
|
|
dwErr = MprInfoBlockFind(
|
|
pTransInfo,
|
|
IP_ROUTE_INFO,
|
|
&dwSize,
|
|
&dwCount,
|
|
(LPBYTE*)&pRoutes);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"Unable to find ip route info.\n");
|
|
break;
|
|
}
|
|
|
|
// Update the protocol id's
|
|
for(dwInd = 0; dwInd < dwCount; dwInd++)
|
|
{
|
|
if((pRoutes[dwInd].dwForwardProto == MIB_IPPROTO_LOCAL) ||
|
|
(pRoutes[dwInd].dwForwardProto == MIB_IPPROTO_NETMGMT))
|
|
{
|
|
pRoutes[dwInd].dwForwardProto = MIB_IPPROTO_NT_STATIC;
|
|
}
|
|
}
|
|
|
|
// Commit the info
|
|
dwErr = MprInfoBlockSet(
|
|
pTransInfo,
|
|
IP_ROUTE_INFO,
|
|
dwSize,
|
|
dwCount,
|
|
(LPVOID)pRoutes,
|
|
&pNewInfo);
|
|
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"MprInfoBlockSet failed.\n");
|
|
break;
|
|
}
|
|
|
|
dwNewSize = ((PRTR_INFO_BLOCK_HEADER)pNewInfo)->Size;
|
|
|
|
// Commit the change
|
|
dwErr = MprConfigInterfaceTransportSetInfo(
|
|
hConfig,
|
|
hInterface,
|
|
hTransport,
|
|
pNewInfo,
|
|
dwNewSize);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"Unable to set ip transport info.\n");
|
|
break;
|
|
}
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
if (pTransInfo)
|
|
MprConfigBufferFree(pTransInfo);
|
|
if (pNewInfo)
|
|
MprConfigBufferFree(pNewInfo);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Flushes the name in given interface name to the registry.
|
|
//
|
|
DWORD CommitInterfaceNameChange(
|
|
IN MPR_INTERFACE_0 * If)
|
|
{
|
|
DWORD dwErr;
|
|
WCHAR c_szInterfaceName[] = L"InterfaceName";
|
|
INTERFACECB* pinterface;
|
|
|
|
// Validate parameters
|
|
if (!If) {
|
|
PrintMessage(L"Invalid param to CommitInterfaceNameChange.\n");
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Set the name
|
|
pinterface = (INTERFACECB*)If->hInterface;
|
|
dwErr = RegSetValueExW(
|
|
pinterface->hkey,
|
|
c_szInterfaceName,
|
|
0,
|
|
REG_SZ,
|
|
(LPCSTR)(If->wszInterfaceName),
|
|
(lstrlen(If->wszInterfaceName)+1)*sizeof(WCHAR));
|
|
|
|
if (dwErr != ERROR_SUCCESS)
|
|
PrintMessage(L"RegSetValueEx err in CommitIfNameChange.\n");
|
|
|
|
if (dwErr == ERROR_SUCCESS)
|
|
return NO_ERROR;
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Creates a default ip interface blob
|
|
//
|
|
DWORD
|
|
IpCreateDefaultInterfaceInfo(
|
|
OUT LPBYTE* ppInfo,
|
|
OUT LPDWORD lpdwSize)
|
|
{
|
|
PBYTE pInfo = NULL, pNewInfo = NULL;
|
|
DWORD dwErr = NO_ERROR;
|
|
//MIB_IPFORWARDROW RouteInfo;
|
|
INTERFACE_STATUS_INFO StatusInfo;
|
|
RTR_DISC_INFO DiscInfo;
|
|
|
|
do
|
|
{
|
|
// Create the blob
|
|
//
|
|
dwErr = MprInfoCreate(RTR_INFO_BLOCK_VERSION, &pInfo);
|
|
BREAK_ON_ERROR(dwErr);
|
|
|
|
// Add an the route info
|
|
//
|
|
//ZeroMemory(&RouteInfo, sizeof(RouteInfo));
|
|
//dwErr = MprInfoBlockAdd(
|
|
// pInfo,
|
|
// IP_ROUTE_INFO,
|
|
// sizeof(MIB_IPFORWARDROW),
|
|
// 1,
|
|
// (LPBYTE)&RouteInfo,
|
|
// &pNewInfo);
|
|
//MprConfigBufferFree(pInfo);
|
|
//pInfo = pNewInfo;
|
|
//pNewInfo = NULL;
|
|
//BREAK_ON_ERROR(dwErr);
|
|
|
|
// Add an the status info
|
|
//
|
|
ZeroMemory(&StatusInfo, sizeof(StatusInfo));
|
|
StatusInfo.dwAdminStatus = MIB_IF_ADMIN_STATUS_UP;
|
|
dwErr = MprInfoBlockAdd(
|
|
pInfo,
|
|
IP_INTERFACE_STATUS_INFO,
|
|
sizeof(INTERFACE_STATUS_INFO),
|
|
1,
|
|
(LPBYTE)&StatusInfo,
|
|
&pNewInfo);
|
|
MprConfigBufferFree(pInfo);
|
|
pInfo = pNewInfo;
|
|
pNewInfo = NULL;
|
|
BREAK_ON_ERROR(dwErr);
|
|
|
|
// Add an the disc info
|
|
//
|
|
ZeroMemory(&DiscInfo, sizeof(DiscInfo));
|
|
DiscInfo.bAdvertise = FALSE;
|
|
DiscInfo.wMaxAdvtInterval = DEFAULT_MAX_ADVT_INTERVAL;
|
|
DiscInfo.wMinAdvtInterval = (WORD)
|
|
(DEFAULT_MIN_ADVT_INTERVAL_RATIO * DEFAULT_MAX_ADVT_INTERVAL);
|
|
DiscInfo.wAdvtLifetime = (WORD)
|
|
(DEFAULT_ADVT_LIFETIME_RATIO * DEFAULT_MAX_ADVT_INTERVAL);
|
|
DiscInfo.lPrefLevel = DEFAULT_PREF_LEVEL;
|
|
dwErr = MprInfoBlockAdd(
|
|
pInfo,
|
|
IP_ROUTER_DISC_INFO,
|
|
sizeof(PRTR_DISC_INFO),
|
|
1,
|
|
(LPBYTE)&DiscInfo,
|
|
&pNewInfo);
|
|
MprConfigBufferFree(pInfo);
|
|
pInfo = pNewInfo;
|
|
pNewInfo = NULL;
|
|
BREAK_ON_ERROR(dwErr);
|
|
|
|
// Assign the return value
|
|
//
|
|
*ppInfo = pInfo;
|
|
*lpdwSize = ((PRTR_INFO_BLOCK_HEADER)pInfo)->Size;
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Adds an ip interface blob to the given interface
|
|
//
|
|
DWORD
|
|
IpAddDefaultInfoToInterface(
|
|
IN HANDLE hConfig,
|
|
IN HANDLE hIf)
|
|
{
|
|
HANDLE hIfTrans = NULL;
|
|
LPBYTE pInfo = NULL;
|
|
DWORD dwErr = 0, dwSize = 0;
|
|
|
|
do
|
|
{
|
|
// If the transport blob already exists, there's
|
|
// nothing to do.
|
|
//
|
|
dwErr = MprConfigInterfaceTransportGetHandle(
|
|
hConfig,
|
|
hIf,
|
|
PID_IP,
|
|
&hIfTrans);
|
|
if ((dwErr == NO_ERROR) || (hIfTrans != NULL))
|
|
{
|
|
dwErr = NO_ERROR;
|
|
break;
|
|
}
|
|
|
|
// Create the info blob
|
|
//
|
|
dwErr = IpCreateDefaultInterfaceInfo(&pInfo, &dwSize);
|
|
BREAK_ON_ERROR(dwErr);
|
|
|
|
// Add the ip transport to the interface
|
|
//
|
|
dwErr = MprConfigInterfaceTransportAdd(
|
|
hConfig,
|
|
hIf,
|
|
PID_IP,
|
|
NULL,
|
|
pInfo,
|
|
dwSize,
|
|
&hIfTrans);
|
|
BREAK_ON_ERROR(dwErr);
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
if (pInfo)
|
|
{
|
|
MprConfigBufferFree(pInfo);
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Function called to add the loopback and internal interfaces which
|
|
// are required if IP was installed and which wouldn't be installed
|
|
// in nt4.
|
|
//
|
|
DWORD
|
|
IpCreateLoopbackAndInternalIfs(
|
|
IN HANDLE hConfig)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
MPR_INTERFACE_0 If0, *pIf0 = &If0;
|
|
HANDLE hIf = NULL;
|
|
|
|
do
|
|
{
|
|
// If the loopback interface is not already installed,
|
|
// go ahead and create it
|
|
//
|
|
dwErr = MprConfigInterfaceGetHandle(
|
|
hConfig,
|
|
(PWCHAR)c_szwLoopbackAdapter,
|
|
&hIf);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
// Initialize the loopback interface info
|
|
//
|
|
ZeroMemory(pIf0, sizeof(MPR_INTERFACE_0));
|
|
wcscpy(pIf0->wszInterfaceName, c_szwLoopbackAdapter);
|
|
pIf0->hInterface = INVALID_HANDLE_VALUE;
|
|
pIf0->fEnabled = TRUE;
|
|
pIf0->dwIfType = ROUTER_IF_TYPE_LOOPBACK;
|
|
|
|
// Create the loopback interface
|
|
dwErr = MprConfigInterfaceCreate(hConfig, 0, (LPBYTE)pIf0, &hIf);
|
|
BREAK_ON_ERROR(dwErr);
|
|
}
|
|
|
|
// Add an ip interface blob to the interface if not already there
|
|
//
|
|
dwErr = IpAddDefaultInfoToInterface(hConfig, hIf);
|
|
BREAK_ON_ERROR(dwErr);
|
|
hIf = NULL;
|
|
|
|
// Make sure internal interface gets installed
|
|
// (will be there if IPX was installed)
|
|
//
|
|
dwErr = MprConfigInterfaceGetHandle(
|
|
hConfig,
|
|
(PWCHAR)c_szwInternalAdapter,
|
|
&hIf);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
// Initialize the internal interface info
|
|
//
|
|
ZeroMemory(pIf0, sizeof(MPR_INTERFACE_0));
|
|
wcscpy(pIf0->wszInterfaceName, c_szwInternalAdapter);
|
|
pIf0->hInterface = INVALID_HANDLE_VALUE;
|
|
pIf0->fEnabled = TRUE;
|
|
pIf0->dwIfType = ROUTER_IF_TYPE_INTERNAL;
|
|
|
|
// Create the internal interface
|
|
dwErr = MprConfigInterfaceCreate(hConfig, 0, (LPBYTE)pIf0, &hIf);
|
|
BREAK_ON_ERROR(dwErr);
|
|
}
|
|
|
|
// Add an ip interface blob to the interface if not already there
|
|
//
|
|
dwErr = IpAddDefaultInfoToInterface(hConfig, hIf);
|
|
BREAK_ON_ERROR(dwErr);
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Callback to interface enumeration function that upgrades
|
|
// the interface names.
|
|
//
|
|
// Returns TRUE to continue the enumeration, FALSE to stop
|
|
// it.
|
|
//
|
|
BOOL SteelHeadUpgradeInterface (
|
|
IN HANDLE hConfig,
|
|
IN MPR_INTERFACE_0 * pIf,
|
|
IN HANDLE hUserData)
|
|
{
|
|
DWORD dwErr;
|
|
|
|
do {
|
|
if (IfNeedsNameUpdate(pIf))
|
|
{
|
|
// Update the interface name
|
|
dwErr = UpdateInterfaceName(pIf->wszInterfaceName);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"UpdateIfName failed -- returning error.\n");
|
|
UtlPrintErr(GetLastError());
|
|
break;
|
|
}
|
|
|
|
// Commit the changed interface name
|
|
dwErr = CommitInterfaceNameChange(pIf);
|
|
if (dwErr != NO_ERROR) {
|
|
PrintMessage(L"CommitInterfaceNameChange failed.\n");
|
|
break;
|
|
}
|
|
|
|
// Update the ipx data
|
|
UpdateIpxIfData(
|
|
hConfig,
|
|
pIf->hInterface);
|
|
}
|
|
|
|
// Update the ip data
|
|
UpdateIpIfData(
|
|
hConfig,
|
|
pIf->hInterface);
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Function UpdateIpxInterfaces
|
|
//
|
|
// Updates all of the interfaces as needed to
|
|
// upgrade the router from steelhead to nt5
|
|
//
|
|
DWORD UpdateInterfaces() {
|
|
DWORD dwErr = NO_ERROR;
|
|
HANDLE hConfig = NULL;
|
|
|
|
do
|
|
{
|
|
// Enumerate the interfaces, upgrading the interface
|
|
// names, etc as we go.
|
|
//
|
|
dwErr = UtlEnumerateInterfaces(
|
|
SteelHeadUpgradeInterface,
|
|
NULL);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
// If ip is installed, we need to add the loopback and
|
|
// internal interface for ip.
|
|
dwErr = MprConfigServerConnect(NULL, &hConfig);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwErr = IpCreateLoopbackAndInternalIfs(hConfig);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
if (hConfig)
|
|
{
|
|
MprConfigServerDisconnect(hConfig);
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
// Copy any values that are in hkSrc but not in hkDst into hkDst.
|
|
DWORD MergeRegistryValues(HKEY hkDst, HKEY hkSrc) {
|
|
DWORD dwErr, dwCount, dwNameSize, dwDataSize;
|
|
DWORD dwType, i, dwCurNameSize, dwCurValSize;
|
|
PWCHAR pszNameBuf, pszDataBuf;
|
|
|
|
// Find out how many values there are in the source
|
|
dwErr = RegQueryInfoKey (hkSrc,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&dwCount,
|
|
&dwNameSize,
|
|
&dwDataSize,
|
|
NULL,
|
|
NULL);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
return dwErr;
|
|
|
|
dwNameSize++;
|
|
dwDataSize++;
|
|
|
|
__try {
|
|
// Allocate the buffers
|
|
pszNameBuf = (PWCHAR) UtlAlloc(dwNameSize * sizeof(WCHAR));
|
|
pszDataBuf = (PWCHAR) UtlAlloc(dwDataSize * sizeof(WCHAR));
|
|
if (!pszNameBuf || !pszDataBuf)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
// Loop through the values
|
|
for (i = 0; i < dwCount; i++) {
|
|
dwCurNameSize = dwNameSize;
|
|
dwCurValSize = dwDataSize;
|
|
|
|
// Get the current source value
|
|
dwErr = RegEnumValueW(
|
|
hkSrc,
|
|
i,
|
|
pszNameBuf,
|
|
&dwCurNameSize,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)pszDataBuf,
|
|
&dwCurValSize);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
continue;
|
|
|
|
// Find out if a value of the same name exists
|
|
// in the destination key. If it does, we don't
|
|
// overwrite it.
|
|
dwErr = RegQueryValueExW(
|
|
hkDst,
|
|
pszNameBuf,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if (dwErr == ERROR_SUCCESS)
|
|
continue;
|
|
|
|
// Copy the value over
|
|
RegSetValueExW(
|
|
hkDst,
|
|
pszNameBuf,
|
|
0,
|
|
dwType,
|
|
(LPBYTE)pszDataBuf,
|
|
dwCurValSize);
|
|
}
|
|
}
|
|
__finally {
|
|
if (pszNameBuf)
|
|
UtlFree(pszNameBuf);
|
|
if (pszDataBuf)
|
|
UtlFree(pszDataBuf);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Recursively copies all of the subkeys of the given registry source to the
|
|
// given registry destination.
|
|
DWORD CopyRegistryKey(
|
|
IN HKEY hkDst,
|
|
IN HKEY hkSrc,
|
|
IN PWCHAR pszSubKey,
|
|
IN LPSTR pszTempFile)
|
|
{
|
|
DWORD dwErr;
|
|
HKEY hkSrcTemp;
|
|
|
|
// Open the subkey in the source
|
|
dwErr = RegOpenKeyExW(hkSrc, pszSubKey, 0, KEY_ALL_ACCESS, &hkSrcTemp);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
return dwErr;
|
|
|
|
// Save off that subkey in a temporary file
|
|
if ((dwErr = RegSaveKeyA(hkSrcTemp, pszTempFile, NULL)) != ERROR_SUCCESS)
|
|
return dwErr;
|
|
|
|
// Copy the saved information into the new key
|
|
RegRestoreKeyA(hkDst, pszTempFile, 0);
|
|
|
|
// Close off the temporary source key
|
|
RegCloseKey(hkSrcTemp);
|
|
|
|
// Delete the temp file
|
|
DeleteFileA(pszTempFile);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Filters which subkeys in the router registry hive should be
|
|
// overwritten with saved off values during upgrade.
|
|
BOOL OverwriteThisSubkey(PWCHAR pszSubKey) {
|
|
if (_wcsicmp(pszSubKey, L"Interfaces") == 0)
|
|
return TRUE;
|
|
|
|
if (_wcsicmp(pszSubKey, L"RouterManagers") == 0)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// Copy all keys that are in hkSrc but not in hkDst into hkDst.
|
|
// By copy we mean all subkeys and values are propagated over.
|
|
DWORD MergeRegistryKeys(HKEY hkDst, HKEY hkSrc) {
|
|
DWORD dwErr, dwCount, dwNameSize, dwType, i;
|
|
DWORD dwCurNameSize, dwDisposition;
|
|
char pszTempFile[512], pszTempPath[512];
|
|
PWCHAR pszNameBuf;
|
|
HKEY hkTemp;
|
|
|
|
// Create the path to the temp file directory
|
|
if (!GetTempPathA(512, pszTempPath))
|
|
return GetLastError();
|
|
|
|
// Create the temp file name
|
|
if (!GetTempFileNameA(pszTempPath, "rtr", 0, pszTempFile))
|
|
return GetLastError();
|
|
|
|
// Delete the temp file created with GetTempFileName(...)
|
|
DeleteFileA(pszTempFile);
|
|
|
|
// Find out how many keys there are in the source
|
|
dwErr = RegQueryInfoKey (
|
|
hkSrc,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&dwCount,
|
|
&dwNameSize,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
return dwErr;
|
|
|
|
dwNameSize++;
|
|
|
|
__try {
|
|
// Allocate the buffers
|
|
pszNameBuf = (PWCHAR) UtlAlloc(dwNameSize * sizeof(WCHAR));
|
|
if (!pszNameBuf)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
// Loop through the keys
|
|
for (i = 0; i < dwCount; i++) {
|
|
dwCurNameSize = dwNameSize;
|
|
|
|
// Get the current source key
|
|
dwErr = RegEnumKeyExW(
|
|
hkSrc,
|
|
i,
|
|
pszNameBuf,
|
|
&dwCurNameSize,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
continue;
|
|
|
|
// Create the new subkey in the destination
|
|
dwErr = RegCreateKeyExW(
|
|
hkDst,
|
|
pszNameBuf,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hkTemp,
|
|
&dwDisposition);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
continue;
|
|
|
|
// If the subkey was created (not opened),
|
|
// copy over the key from hkSrc
|
|
if (dwDisposition == REG_CREATED_NEW_KEY) {
|
|
CopyRegistryKey(
|
|
hkTemp,
|
|
hkSrc,
|
|
pszNameBuf,
|
|
pszTempFile);
|
|
}
|
|
|
|
// Otherwise, if this is one of the keys that we
|
|
// should overwrite, do so now.
|
|
else {
|
|
if (OverwriteThisSubkey(pszNameBuf)) {
|
|
CopyRegistryKey(
|
|
hkTemp,
|
|
hkSrc,
|
|
pszNameBuf,
|
|
pszTempFile);
|
|
}
|
|
}
|
|
|
|
// Close up the temporary handles
|
|
RegCloseKey(hkTemp);
|
|
hkTemp = NULL;
|
|
}
|
|
}
|
|
__finally {
|
|
if (pszNameBuf)
|
|
UtlFree(pszNameBuf);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Restore the registry from from backup
|
|
//
|
|
DWORD
|
|
RestoreRegistrySteelhead(
|
|
IN PWCHAR pszBackup)
|
|
{
|
|
HKEY hkRouter = NULL, hkRestore = NULL;
|
|
DWORD dwErr = NO_ERROR, dwDisposition;
|
|
PWCHAR pszRestore = L"Temp";
|
|
|
|
// Merge the router key values and sub keys with the
|
|
// remote access key
|
|
do
|
|
{
|
|
// Get access to the router registry key
|
|
//
|
|
dwErr = UtlAccessRouterKey(&hkRouter);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
PrintMessage(L"Unable to access router key.\n");
|
|
break;
|
|
}
|
|
|
|
// Load in the saved router settings
|
|
//
|
|
dwErr = UtlLoadSavedSettings(
|
|
hkRouter,
|
|
pszRestore,
|
|
pszBackup,
|
|
&hkRestore);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Merge all of the values in the restored key
|
|
//
|
|
dwErr = MergeRegistryValues(hkRouter, hkRestore);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Give yourself backup and restore privilege
|
|
//
|
|
UtlSetupBackupPrivelege (TRUE);
|
|
UtlSetupRestorePrivilege(TRUE);
|
|
|
|
// Merge all of the keys in the restored key
|
|
//
|
|
dwErr = MergeRegistryKeys(hkRouter, hkRestore);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
if (hkRestore)
|
|
{
|
|
UtlDeleteRegistryTree(hkRestore);
|
|
RegCloseKey(hkRestore);
|
|
RegDeleteKey(hkRouter, pszRestore);
|
|
}
|
|
if (hkRouter)
|
|
{
|
|
RegCloseKey(hkRouter);
|
|
}
|
|
UtlSetupBackupPrivelege (FALSE);
|
|
UtlSetupRestorePrivilege(FALSE);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Upgrades the remoteaccess registry with the router
|
|
// configuration from nt4.
|
|
//
|
|
DWORD SteelheadToNt5Upgrade (PWCHAR BackupFileName) {
|
|
DWORD dwErr = NO_ERROR;
|
|
HANDLE hMapperParam;
|
|
|
|
do
|
|
{
|
|
// Prepare the old interface name -> new if name mapper
|
|
dwErr = SeedInterfaceNameMapper(&hMapperParam);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
PrintMessage(L"Unable to seed if name mapper.\n");
|
|
}
|
|
else
|
|
{
|
|
// Copy all of registry data that has been backed up.
|
|
dwErr = RestoreRegistrySteelhead(BackupFileName);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
PrintMessage(L"Unable to restore registry.\n");
|
|
}
|
|
else
|
|
{
|
|
// Update all of the interfaces accordingly
|
|
dwErr = UpdateInterfaces();
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
PrintMessage(L"Unable to update interfaces.\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add 'router' usage to all ports
|
|
//
|
|
dwErr = MprPortSetUsage(MPRFLAG_PORT_Router);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
PrintMessage(L"Unable to update interfaces.\n");
|
|
}
|
|
|
|
// Mark the computer as having been configured
|
|
//
|
|
dwErr = UtlMarkRouterConfigured();
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
PrintMessage(L"Unable to mark router as configured.\n");
|
|
}
|
|
|
|
} while (FALSE);
|
|
|
|
// Cleanup
|
|
{
|
|
CleanupInterfaceNameMapper(hMapperParam);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|