//+--------------------------------------------------------------------------- // // 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 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 spIHNetBridgeSettings; hr = pIHNetCfgMgr->QueryInterface( IID_PPV_ARG(IHNetBridgeSettings, &spIHNetBridgeSettings) ); if (SUCCEEDED(hr)) { // // Get the IEnumHNetBridges // CComPtr spehBridges; if ((hr = spIHNetBridgeSettings->EnumBridges(&spehBridges)) == S_OK) { // // Get the first IHNetBridge // CComPtr 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 spIHNetBridge2; if ((hr = spehBridges->Next(1, &spIHNetBridge2, NULL)) == S_OK) { assert(FALSE); } } // // Get the IEnumHNetBridgedConnections // CComPtr 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 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 spIHNetBridgeSettings; hr = pIHNetCfgMgr->QueryInterface( IID_PPV_ARG(IHNetBridgeSettings, &spIHNetBridgeSettings) ); if (SUCCEEDED(hr)) { // // Get the IEnumHNetBridges // CComPtr spehBridges; if ((hr = spIHNetBridgeSettings->EnumBridges(&spehBridges)) == S_OK) { // // Get the first IHNetBridge // CComPtr 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 spIHNetBridge2; if ((hr = spehBridges->Next(1, &spIHNetBridge2, NULL)) == S_OK) { assert(FALSE); } } // // Get the IEnumHNetBridgedConnections // CComPtr 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 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; }