windows-nt/Source/XPSP1/NT/net/homenet/netsh/bridge.cpp
2020-09-26 16:20:57 +08:00

1096 lines
33 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998 - 2001
//
// File : bridge.cpp
//
// Contents : bridge context specific code
//
// Notes :
//
// Author : Raghu Gatta (rgatta) 11 May 2001
//
//----------------------------------------------------------------------------
#include "precomp.h"
#pragma hdrstop
const TCHAR c_stRegKeyBridgeAdapters[] =
_T("SYSTEM\\CurrentControlSet\\Services\\Bridge\\Parameters\\Adapters");
const TCHAR c_stFCMode[] = _T("ForceCompatibilityMode");
CMD_ENTRY g_BridgeSetCmdTable[] = {
CREATE_CMD_ENTRY(BRIDGE_SET_ADAPTER, HandleBridgeSetAdapter),
};
CMD_ENTRY g_BridgeShowCmdTable[] = {
CREATE_CMD_ENTRY(BRIDGE_SHOW_ADAPTER, HandleBridgeShowAdapter),
};
CMD_GROUP_ENTRY g_BridgeCmdGroups[] =
{
CREATE_CMD_GROUP_ENTRY(GROUP_SET, g_BridgeSetCmdTable),
CREATE_CMD_GROUP_ENTRY(GROUP_SHOW, g_BridgeShowCmdTable),
};
ULONG g_ulBridgeNumGroups = sizeof(g_BridgeCmdGroups)/sizeof(CMD_GROUP_ENTRY);
CMD_ENTRY g_BridgeCmds[] =
{
CREATE_CMD_ENTRY(INSTALL, HandleBridgeInstall),
CREATE_CMD_ENTRY(UNINSTALL, HandleBridgeUninstall),
};
ULONG g_ulBridgeNumTopCmds = sizeof(g_BridgeCmds)/sizeof(CMD_ENTRY);
DWORD WINAPI
BridgeDump(
IN LPCWSTR pwszRouter,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwArgCount,
IN LPCVOID pvData
)
{
//
// Output the string that shows our settings.
// The idea here is to spit out a script that,
// when run from the command line (netsh -f script)
// will cause your component to be configured
// exactly as it is when this dump command was run.
//
PrintMessageFromModule(
g_hModule,
DMP_BRIDGE_HEADER
);
PrintMessageFromModule(
g_hModule,
DMP_BRIDGE_FOOTER
);
return NO_ERROR;
}
HRESULT
HrCycleBridge(
IHNetBridge *pIHNetBridge
)
{
HRESULT hr = S_OK;
//
// Check to see if the bridge is up and running.
// If it is, then disable and reenable
//
do
{
//
// Get the pointer to IID_IHNetConnection interface of this
// bridged connection
//
CComPtr<IHNetConnection> spIHNConn;
hr = pIHNetBridge->QueryInterface(
IID_PPV_ARG(IHNetConnection, &spIHNConn)
);
assert(SUCCEEDED(hr));
if (FAILED(hr))
{
break;
}
INetConnection *pINetConn;
hr = spIHNConn->GetINetConnection(&pINetConn);
if (SUCCEEDED(hr))
{
NETCON_PROPERTIES* pNCProps;
hr = pINetConn->GetProperties(&pNCProps);
if(SUCCEEDED(hr))
{
//
// check status - restart only if already running
//
if (pNCProps->Status == NCS_CONNECTED ||
pNCProps->Status == NCS_CONNECTING)
{
pINetConn->Disconnect();
pINetConn->Connect();
}
NcFreeNetconProperties(pNCProps);
}
ReleaseObj(pINetConn);
}
} while(FALSE);
return hr;
}
DWORD
SetBridgeAdapterInfo(
DWORD adapterId,
BOOL bFlag
)
{
DWORD dwErr = NO_ERROR;
IHNetCfgMgr* pIHNetCfgMgr = NULL;
HRESULT hr = S_OK;
hr = HrInitializeHomenetConfig(
&g_fInitCom,
&pIHNetCfgMgr
);
if (SUCCEEDED(hr))
{
//
// Get the IHNetBridgeSettings
//
CComPtr<IHNetBridgeSettings> spIHNetBridgeSettings;
hr = pIHNetCfgMgr->QueryInterface(
IID_PPV_ARG(IHNetBridgeSettings, &spIHNetBridgeSettings)
);
if (SUCCEEDED(hr))
{
//
// Get the IEnumHNetBridges
//
CComPtr<IEnumHNetBridges> spehBridges;
if ((hr = spIHNetBridgeSettings->EnumBridges(&spehBridges)) == S_OK)
{
//
// Get the first IHNetBridge
//
CComPtr<IHNetBridge> spIHNetBridge;
if ((hr = spehBridges->Next(1, &spIHNetBridge, NULL)) == S_OK)
{
{
//
// We currently should have only one bridge;
// this may change in the future. The
// code here is just to catch future instances
// where this function would have to change in case
// there is more than one bridge.
//
CComPtr<IHNetBridge> spIHNetBridge2;
if ((hr = spehBridges->Next(1, &spIHNetBridge2, NULL)) == S_OK)
{
assert(FALSE);
}
}
//
// Get the IEnumHNetBridgedConnections
//
CComPtr<IEnumHNetBridgedConnections> spehBrdgConns;
if ((hr = spIHNetBridge->EnumMembers(&spehBrdgConns)) == S_OK)
{
//
// enumerate all the IHNetBridgedConnections
//
DWORD id = 0;
IHNetBridgedConnection* pIHNetBConn;
spehBrdgConns->Reset();
while (S_OK == spehBrdgConns->Next(1, &pIHNetBConn, NULL))
{
id++;
if (id != adapterId)
{
//
// release the IHNetBridgedConnection
//
ReleaseObj(pIHNetBConn);
continue;
}
//
// Get the pointer to IID_IHNetConnection interface of this
// bridged connection
//
CComPtr<IHNetConnection> spIHNConn;
hr = pIHNetBConn->QueryInterface(
IID_PPV_ARG(IHNetConnection, &spIHNConn)
);
assert(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
GUID *pGuid = NULL;
hr = spIHNConn->GetGuid(&pGuid);
if (SUCCEEDED(hr) && (NULL != pGuid))
{
PTCHAR pwszKey = NULL;
int keyLen;
TCHAR wszGuid[128];
HKEY hKey = NULL;
DWORD dwDisp = 0;
BOOL bCycleBridge = TRUE;
DWORD dwOldValue;
DWORD dwNewValue = (bFlag) ? 1 : 0;
do
{
ZeroMemory(wszGuid, sizeof(wszGuid));
StringFromGUID2(
*pGuid,
wszGuid,
ARRAYSIZE(wszGuid)
);
keyLen = _tcslen(c_stRegKeyBridgeAdapters) +
_tcslen(_T("\\")) +
_tcslen(wszGuid) +
1;
pwszKey = (TCHAR *) HeapAlloc(
GetProcessHeap(),
0,
keyLen * sizeof(TCHAR)
);
if (!pwszKey)
{
break;
}
ZeroMemory(pwszKey, sizeof(pwszKey));
_tcscpy(pwszKey, c_stRegKeyBridgeAdapters);
_tcscat(pwszKey, _T("\\"));
_tcscat(pwszKey, wszGuid);
dwErr = RegCreateKeyEx(
HKEY_LOCAL_MACHINE,
pwszKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&dwDisp
);
if (ERROR_SUCCESS != dwErr)
{
break;
}
//
// if the key was old, get its value
// and compare to see if we need to
// cycle the bridge
//
if (dwDisp &&
dwDisp == REG_OPENED_EXISTING_KEY)
{
DWORD dwSize = sizeof(dwOldValue);
if (ERROR_SUCCESS == RegQueryValueEx(
hKey,
c_stFCMode,
NULL,
NULL,
(LPBYTE)&dwOldValue,
&dwSize))
{
if (dwOldValue == dwNewValue)
{
//
// no need to cycle the bridge
//
bCycleBridge = FALSE;
}
}
}
dwErr = RegSetValueEx(
hKey,
c_stFCMode,
0,
REG_DWORD,
(LPBYTE) &dwNewValue,
sizeof(dwNewValue)
);
if (ERROR_SUCCESS != dwErr)
{
break;
}
if (bCycleBridge)
{
//
// cycle the (respective) bridge
//
hr = HrCycleBridge(
spIHNetBridge
);
}
} while(FALSE);
//
// cleanup
//
if (hKey)
{
RegCloseKey(hKey);
}
if (pwszKey)
{
HeapFree(GetProcessHeap(), 0, pwszKey);
}
CoTaskMemFree(pGuid);
}
}
//
// release the IHNetBridgedConnection
//
ReleaseObj(pIHNetBConn);
break;
} //while
}
}
}
}
//
// we are done completely
//
hr = HrUninitializeHomenetConfig(
g_fInitCom,
pIHNetCfgMgr
);
}
return (hr==S_OK) ? dwErr : hr;
}
DWORD
WINAPI
HandleBridgeSetAdapter(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwRet = NO_ERROR;
PDWORD pdwTagType = NULL;
DWORD dwNumOpt;
DWORD dwNumArg;
DWORD dwRes;
DWORD dwErrIndex =-1,
i;
//
// default values
//
DWORD id = 0;
DWORD bFCMode = FALSE;
TAG_TYPE pttTags[] =
{
{TOKEN_OPT_ID, NS_REQ_PRESENT, FALSE},
{TOKEN_OPT_FCMODE, NS_REQ_ZERO, FALSE} // not required to allow for
// addition of future flags
};
if (dwCurrentIndex >= dwArgCount)
{
// No arguments specified. At least interface name should be specified.
return ERROR_INVALID_SYNTAX;
}
dwNumArg = dwArgCount - dwCurrentIndex;
pdwTagType = (DWORD *) HeapAlloc(
GetProcessHeap(),
0,
dwNumArg * sizeof(DWORD)
);
if (NULL == pdwTagType)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
dwRet = PreprocessCommand(
g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
ARRAYSIZE(pttTags),
1, // min args
2, // max args
pdwTagType
);
if (NO_ERROR != dwRet)
{
HeapFree(GetProcessHeap(), 0, pdwTagType);
if (ERROR_INVALID_OPTION_TAG == dwRet)
{
return ERROR_INVALID_SYNTAX;
}
return dwRet;
}
for ( i = 0; i < dwNumArg; i++)
{
switch (pdwTagType[i])
{
case 0:
{
//
// refers to the 'id' field
//
id = _tcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
break;
}
case 1:
{
//
// refers to the 'forcecompatmode' field
// possible values are : enable or disable
//
TOKEN_VALUE rgEnums[] =
{
{TOKEN_OPT_VALUE_ENABLE, TRUE},
{TOKEN_OPT_VALUE_DISABLE, FALSE}
};
dwRet = MatchEnumTag(
g_hModule,
ppwcArguments[i + dwCurrentIndex],
ARRAYSIZE(rgEnums),
rgEnums,
&dwRes
);
if (dwRet != NO_ERROR)
{
dwErrIndex = i;
i = dwNumArg;
dwRet = ERROR_INVALID_PARAMETER;
break;
}
switch (dwRes)
{
case 0:
bFCMode = FALSE;
break;
case 1:
bFCMode = TRUE;
break;
}
break;
}
default:
{
i = dwNumArg;
dwRet = ERROR_INVALID_PARAMETER;
break;
}
} //switch
if (dwRet != NO_ERROR)
{
break ;
}
} //for
//
// adapter id MUST be present
//
if (!pttTags[0].bPresent)
{
dwRet = ERROR_INVALID_SYNTAX;
}
switch(dwRet)
{
case NO_ERROR:
break;
case ERROR_INVALID_PARAMETER:
if (dwErrIndex != -1)
{
PrintError(
g_hModule,
EMSG_BAD_OPTION_VALUE,
ppwcArguments[dwErrIndex + dwCurrentIndex],
pttTags[pdwTagType[dwErrIndex]].pwszTag
);
}
dwRet = ERROR_SUPPRESS_OUTPUT;
break;
default:
//
// error message already printed
//
break;
}
if (pdwTagType)
{
HeapFree(GetProcessHeap(), 0, pdwTagType);
}
if (NO_ERROR != dwRet)
{
return dwRet;
}
//
// we have the requisite info - process them
//
//
// since we may or may not have flag info, check for it
//
if (pttTags[1].bPresent)
{
dwRet = SetBridgeAdapterInfo(
id,
bFCMode
);
}
return dwRet;
}
DWORD
ShowBridgeAdapterInfo(
DWORD id,
IHNetConnection *pIHNConn
)
{
HRESULT hr;
//
// print out the bridged connections details
//
PWSTR pwszName = NULL;
PWSTR pwszState = NULL;
hr = pIHNConn->GetName(&pwszName);
if (SUCCEEDED(hr) && (NULL != pwszName))
{
GUID *pGuid = NULL;
hr = pIHNConn->GetGuid(&pGuid);
if (SUCCEEDED(hr) && (NULL != pGuid))
{
WCHAR wszGuid[128];
ZeroMemory(wszGuid, sizeof(wszGuid));
StringFromGUID2(*pGuid, wszGuid, ARRAYSIZE(wszGuid));
//
// check to see if registry settings present
//
// for forcecompatmode:
// + if key is not present --> disabled
// + if key is present
// 0x1 --> enabled
// 0x0 --> disabled
// + all other errors --> unknown
//
{
HKEY hBAKey;
DWORD msgState = STRING_UNKNOWN;
if (ERROR_SUCCESS == RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
c_stRegKeyBridgeAdapters,
0,
KEY_READ,
&hBAKey))
{
HKEY hBCKey;
if (ERROR_SUCCESS == RegOpenKeyEx(
hBAKey,
wszGuid,
0,
KEY_READ,
&hBCKey))
{
DWORD dwFCModeState = 0;
DWORD dwSize = sizeof(dwFCModeState);
if (ERROR_SUCCESS == RegQueryValueEx(
hBCKey,
c_stFCMode,
NULL,
NULL,
(LPBYTE)&dwFCModeState,
&dwSize))
{
switch (dwFCModeState)
{
case 0:
msgState = STRING_DISABLED;
break;
case 1:
msgState = STRING_ENABLED;
break;
default:
msgState = STRING_UNKNOWN;
}
}
else
{
//
// value not present
//
msgState = STRING_DISABLED;
}
RegCloseKey(hBCKey);
}
else
{
//
// bridged connection guid key not present
//
msgState = STRING_DISABLED;
}
RegCloseKey(hBAKey);
}
pwszState = MakeString(g_hModule, msgState);
}
PrintMessage(
L" %1!2d! %2!-27s! %3!s!%n",
id,
pwszName,
pwszState
);
if (pwszState)
{
FreeString(pwszState);
}
CoTaskMemFree(pGuid);
}
CoTaskMemFree(pwszName);
}
return NO_ERROR;
}
DWORD
ShowBridgeAllAdapterInfo(
BOOL bShowAll, // TRUE to show all
DWORD adapterId // valid only if bShowAll is FALSE
)
{
IHNetCfgMgr* pIHNetCfgMgr = NULL;
HRESULT hr = S_OK;
hr = HrInitializeHomenetConfig(
&g_fInitCom,
&pIHNetCfgMgr
);
if (SUCCEEDED(hr))
{
//
// Get the IHNetBridgeSettings
//
CComPtr<IHNetBridgeSettings> spIHNetBridgeSettings;
hr = pIHNetCfgMgr->QueryInterface(
IID_PPV_ARG(IHNetBridgeSettings, &spIHNetBridgeSettings)
);
if (SUCCEEDED(hr))
{
//
// Get the IEnumHNetBridges
//
CComPtr<IEnumHNetBridges> spehBridges;
if ((hr = spIHNetBridgeSettings->EnumBridges(&spehBridges)) == S_OK)
{
//
// Get the first IHNetBridge
//
CComPtr<IHNetBridge> spIHNetBridge;
if ((hr = spehBridges->Next(1, &spIHNetBridge, NULL)) == S_OK)
{
{
//
// We currently should have only one bridge;
// this may change in the future. The
// code here is just to catch future instances
// where this function would have to change in case
// there is more than one bridge.
//
CComPtr<IHNetBridge> spIHNetBridge2;
if ((hr = spehBridges->Next(1, &spIHNetBridge2, NULL)) == S_OK)
{
assert(FALSE);
}
}
//
// Get the IEnumHNetBridgedConnections
//
CComPtr<IEnumHNetBridgedConnections> spehBrdgConns;
if ((hr = spIHNetBridge->EnumMembers(&spehBrdgConns)) == S_OK)
{
//
// spit out header for displaying the list
//
PrintMessageFromModule(
g_hModule,
MSG_BRIDGE_ADAPTER_INFO_HDR
);
//
// enumerate all the IHNetBridgedConnections
//
DWORD id = 0;
IHNetBridgedConnection* pIHNetBConn;
spehBrdgConns->Reset();
while (S_OK == spehBrdgConns->Next(1, &pIHNetBConn, NULL))
{
id++;
//
// check if we are looking for a specific id
//
if (FALSE == bShowAll && id != adapterId)
{
//
// release the IHNetBridgedConnection
//
ReleaseObj(pIHNetBConn);
continue;
}
//
// Get the pointer to IID_IHNetConnection interface of this
// bridged connection
//
CComPtr<IHNetConnection> spIHNConn;
hr = pIHNetBConn->QueryInterface(
IID_PPV_ARG(IHNetConnection, &spIHNConn)
);
assert(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
ShowBridgeAdapterInfo(
id,
spIHNConn
);
}
//
// release the IHNetBridgedConnection
//
ReleaseObj(pIHNetBConn);
//
// if we reached here and we were looking for a
// specific id, our work is done - break out
//
if (FALSE == bShowAll)
{
break;
}
}
//
// spit out footer for displaying the list
//
PrintMessageFromModule(
g_hModule,
TABLE_SEPARATOR
);
}
}
}
}
//
// we are done completely
//
hr = HrUninitializeHomenetConfig(
g_fInitCom,
pIHNetCfgMgr
);
}
return (hr==S_OK) ? NO_ERROR : hr;
}
DWORD
WINAPI
HandleBridgeShowAdapter(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Gets options for showing bridge adapter info
Arguements:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
IHNetCfgMgr* pIHNetCfgMgr = NULL;
HRESULT hr = S_OK;
BOOL bShowAll = FALSE;
DWORD id = 0,
i,
dwRet = NO_ERROR,
dwNumOpt,
dwNumArg,
dwSize,
dwRes;
PDWORD pdwTagType = NULL;
TAG_TYPE pttTags[] =
{
{TOKEN_OPT_ID, NS_REQ_ZERO, FALSE}
};
if (dwCurrentIndex > dwArgCount)
{
//
// No arguments specified
//
return ERROR_INVALID_SYNTAX;
}
if (dwCurrentIndex == dwArgCount)
{
bShowAll = TRUE;
}
dwNumArg = dwArgCount - dwCurrentIndex;
pdwTagType = (DWORD *) HeapAlloc(
GetProcessHeap(),
0,
dwNumArg * sizeof(DWORD)
);
if (dwNumArg && NULL == pdwTagType)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
dwRet = PreprocessCommand(
g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
ARRAYSIZE(pttTags),
0, // min args
1, // max args
pdwTagType
);
if (NO_ERROR == dwRet)
{
//
// process each argument...
//
for (i = 0; i < (dwArgCount - dwCurrentIndex); i++)
{
//
// Check its corresponding value in the pdwTagType array.
//
switch (pdwTagType[i])
{
case 0:
//
// refers to the 'id' field
//
id = _tcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
break;
default:
//
// Since there is only one valid value, means the arg
// wasn't recognized. Shouldn't reach this point because
// PreprocessCommand wouldn't have returned NO_ERROR if
// this was the case.
//
dwRet = ERROR_INVALID_SYNTAX;
break;
}
}
dwRet = ShowBridgeAllAdapterInfo(
bShowAll,
id
) ;
}
else
{
dwRet = ERROR_SHOW_USAGE;
}
//
// cleanup
//
if (pdwTagType)
{
HeapFree(GetProcessHeap(), 0, pdwTagType);
}
return dwRet;
}
DWORD
WINAPI
HandleBridgeInstall(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
PrintMessageFromModule(
g_hModule,
HLP_BRIDGE_USE_GUI,
CMD_INSTALL
);
return NO_ERROR;
}
DWORD
WINAPI
HandleBridgeUninstall(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
PrintMessageFromModule(
g_hModule,
HLP_BRIDGE_USE_GUI,
CMD_UNINSTALL
);
return NO_ERROR;
}