//============================================================================= // Copyright (c) 1999 Microsoft Corporation // File: ifip1.c // Abstract: // This module implements the helpers for if/ip apis // // Author: K.S.Lokesh (lokeshs@) 8-1-99 //============================================================================= #include "precomp.h" #include #include #include #include "ifip.h" #include "ifstring.h" const WCHAR c_wszListSeparatorComma[] = L","; const WCHAR c_wListSeparatorComma = L','; const WCHAR c_wListSeparatorSC = L';'; const WCHAR c_wszListSeparatorSC[] = L";"; const WCHAR c_wcsDefGateway[] = L"DefGw="; const WCHAR c_wcsGwMetric[] = L"GwMetric="; const WCHAR c_wcsIfMetric[] = L"IfMetric="; const WCHAR c_wcsDns[] = L"DNS="; const WCHAR c_wcsDdns[] = L"DynamicUpdate="; const WCHAR c_wcsDdnsSuffix[] = L"NameRegistration="; const WCHAR c_wcsWins[] = L"WINS="; const WCHAR c_wEqual = L'='; BOOL g_fInitCom = TRUE; HRESULT HrUninitializeAndUnlockINetCfg ( INetCfg* pnc ) /*++ Routine Description Uninitializes and unlocks the INetCfg object Arguments pnc [in] INetCfg to uninitialize and unlock Return Value S_OK if success, OLE or Win32 error otherwise Author: danielwe 13 Nov 1997 --*/ { HRESULT hr = S_OK; hr = pnc->lpVtbl->Uninitialize(pnc); if (SUCCEEDED(hr)) { INetCfgLock * pnclock; // Get the locking interface hr = pnc->lpVtbl->QueryInterface(pnc, &IID_INetCfgLock, (LPVOID *)(&pnclock)); if (SUCCEEDED(hr)) { // Attempt to lock the INetCfg for read/write hr = pnclock->lpVtbl->ReleaseWriteLock(pnclock); if (pnclock) { pnclock->lpVtbl->Release(pnclock); } pnclock = NULL; } } // TraceResult("HrUninitializeAndUnlockINetCfg", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrUninitializeAndReleaseINetCfg // // Purpose: Unintialize and release an INetCfg object. This will // optionally uninitialize COM for the caller too. // // Arguments: // fUninitCom [in] TRUE to uninitialize COM after the INetCfg is // uninitialized and released. // pnc [in] The INetCfg object. // fHasLock [in] TRUE if the INetCfg was locked for write and // must be unlocked. // // Returns: S_OK or an error code. // // Author: shaunco 7 May 1997 // // Notes: The return value is the value returned from // INetCfg::Uninitialize. Even if this fails, the INetCfg // is still released. Therefore, the return value is for // informational purposes only. You can't touch the INetCfg // object after this call returns. // HRESULT HrUninitializeAndReleaseINetCfg ( BOOL fUninitCom, INetCfg* pnc, BOOL fHasLock ) /*++ Routine Description Arguments Return Value --*/ { // Assert (pnc); HRESULT hr = S_OK; if (fHasLock) { hr = HrUninitializeAndUnlockINetCfg(pnc); } else { hr = pnc->lpVtbl->Uninitialize (pnc); } if (pnc) { pnc->lpVtbl->Release(pnc); } pnc = NULL; if (fUninitCom) { CoUninitialize (); } // TraceResult("HrUninitializeAndReleaseINetCfg", hr); return hr; } /*!-------------------------------------------------------------------------- HrGetIpPrivateInterface - Author: TongLu, KennT ---------------------------------------------------------------------------*/ HRESULT HrGetIpPrivateInterface(INetCfg* pNetCfg, ITcpipProperties **ppTcpProperties ) /*++ Routine Description Arguments Return Value --*/ { HRESULT hr; INetCfgClass* pncclass = NULL; if ((pNetCfg == NULL) || (ppTcpProperties == NULL)) return E_INVALIDARG; hr = pNetCfg->lpVtbl->QueryNetCfgClass (pNetCfg, &GUID_DEVCLASS_NETTRANS, &IID_INetCfgClass, (void**)(&pncclass)); if (SUCCEEDED(hr)) { INetCfgComponent * pnccItem = NULL; // Find the component. hr = pncclass->lpVtbl->FindComponent(pncclass, TEXT("MS_TCPIP"), &pnccItem); //AssertSz (SUCCEEDED(hr), "pncclass->Find failed."); if (S_OK == hr) { INetCfgComponentPrivate* pinccp = NULL; hr = pnccItem->lpVtbl->QueryInterface(pnccItem, &IID_INetCfgComponentPrivate, (void**)(&pinccp)); if (SUCCEEDED(hr)) { hr = pinccp->lpVtbl->QueryNotifyObject(pinccp, &IID_ITcpipProperties, (void**)(ppTcpProperties)); pinccp->lpVtbl->Release(pinccp); } } if (pnccItem) pnccItem->lpVtbl->Release(pnccItem); } if (pncclass) pncclass->lpVtbl->Release(pncclass); // S_OK indicates success (interface returned) // S_FALSE indicates Ipx not installed // other values are errors // TraceResult("HrGetIpPrivateInterface", hr); return hr; } HRESULT HrCreateAndInitializeINetCfg ( BOOL* pfInitCom, INetCfg** ppnc, BOOL fGetWriteLock, DWORD cmsTimeout, LPCWSTR szwClientDesc, LPWSTR * ppszwClientDesc ) /*++ Routine Description Cocreate and initialize the root INetCfg object. This will optionally initialize COM for the caller too. Arguments pfInitCom [in,out] TRUE to call CoInitialize before creating. returns TRUE if COM was successfully initialized FALSE if not. If NULL, means don't initialize COM. ppnc [out] The returned INetCfg object. fGetWriteLock [in] TRUE if a writable INetCfg is needed cmsTimeout [in] See INetCfg::LockForWrite szwClientDesc [in] See INetCfg::LockForWrite ppszwClientDesc [out] See INetCfg::LockForWrite Return Value S_OK or an error code. --*/ { HRESULT hr; // Initialize the output parameter. *ppnc = NULL; if (ppszwClientDesc) *ppszwClientDesc = NULL; // Initialize COM if the caller requested. hr = S_OK; if (pfInitCom && *pfInitCom) { hr = CoInitializeEx( NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED ); if (RPC_E_CHANGED_MODE == hr) { hr = S_OK; if (pfInitCom) { *pfInitCom = FALSE; } } } if (SUCCEEDED(hr)) { // Create the object implementing INetCfg. // INetCfg* pnc; hr = CoCreateInstance(&CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, &IID_INetCfg, (void**)(&pnc)); // TraceResult("HrCreateAndInitializeINetCfg - CoCreateInstance(CLSID_CNetCfg)", hr); if (SUCCEEDED(hr)) { INetCfgLock* pnclock = NULL; if (fGetWriteLock) { // Get the locking interface hr = pnc->lpVtbl->QueryInterface(pnc, &IID_INetCfgLock, (LPVOID *)(&pnclock)); // TraceResult("HrCreateAndInitializeINetCfg - QueryInterface(IID_INetCfgLock", hr); if (SUCCEEDED(hr)) { // Attempt to lock the INetCfg for read/write hr = pnclock->lpVtbl->AcquireWriteLock(pnclock, cmsTimeout, szwClientDesc, ppszwClientDesc); // TraceResult("HrCreateAndInitializeINetCfg - INetCfgLock::LockForWrite", hr); if (S_FALSE == hr) { // Couldn't acquire the lock hr = NETCFG_E_NO_WRITE_LOCK; } } } if (SUCCEEDED(hr)) { // Initialize the INetCfg object. // hr = pnc->lpVtbl->Initialize (pnc, NULL); // TraceResult("HrCreateAndInitializeINetCfg - Initialize", hr); if (SUCCEEDED(hr)) { *ppnc = pnc; if (pnc) pnc->lpVtbl->AddRef(pnc); } else { if (pnclock) { pnclock->lpVtbl->ReleaseWriteLock(pnclock); } } // Transfer reference to caller. } if (pnclock) { pnclock->lpVtbl->Release(pnclock); } pnclock = NULL; if (pnc) { pnc->lpVtbl->Release(pnc); } pnc = NULL; } // If we failed anything above, and we've initialized COM, // be sure an uninitialize it. // if (FAILED(hr) && pfInitCom && *pfInitCom) { CoUninitialize (); } } return hr; } DWORD GetTransportConfig( INetCfg ** pNetCfg, ITcpipProperties ** pTcpipProperties, REMOTE_IPINFO **pRemoteIpInfo, GUID *pGuid, LPCWSTR pwszIfFriendlyName ) /*++ Routine Description Arguments Return Value --*/ { WCHAR wszDesc[] = L"Test of Change IP settings"; HRESULT hr; // Create the INetCfg, we get the write lock because we need read and write hr = HrCreateAndInitializeINetCfg(&g_fInitCom, /* &g_fInitCom, */ pNetCfg, TRUE /* fGetWriteLock */, 500 /* cmsTimeout */, wszDesc/* swzClientDesc */, NULL /* ppszwClientDesc */); if (hr == S_OK) { hr = HrGetIpPrivateInterface(*pNetCfg, pTcpipProperties); } if (hr == NETCFG_E_NO_WRITE_LOCK) { DisplayMessage( g_hModule, EMSG_NETCFG_WRITE_LOCK ); return ERROR_SUPPRESS_OUTPUT; } if (hr == S_OK) { hr = (*pTcpipProperties)->lpVtbl->GetIpInfoForAdapter(*pTcpipProperties, pGuid, pRemoteIpInfo); if (hr != S_OK) { DisplayMessage(g_hModule, EMSG_PROPERTIES, pwszIfFriendlyName); hr = ERROR_SUPPRESS_OUTPUT; } } return (hr==S_OK) ? NO_ERROR : hr; } VOID UninitializeTransportConfig( INetCfg * pNetCfg, ITcpipProperties * pTcpipProperties, REMOTE_IPINFO *pRemoteIpInfo ) /*++ Routine Description Arguments Return Value --*/ { if (pTcpipProperties) pTcpipProperties->lpVtbl->Release(pTcpipProperties); if (pNetCfg) { HrUninitializeAndReleaseINetCfg(FALSE, pNetCfg, TRUE /* fHasLock */); } if (pRemoteIpInfo) CoTaskMemFree(pRemoteIpInfo); return; } DWORD IfIpAddSetAddress( LPCWSTR pwszIfFriendlyName, GUID *pGuid, LPCWSTR wszIp, LPCWSTR wszMask, DWORD Flags ) /*++ Routine Description Arguments Return Value --*/ { INetCfg * pNetCfg = NULL; ITcpipProperties * pTcpipProperties = NULL; DWORD dwNetwork; DWORD dwErr = NO_ERROR; REMOTE_IPINFO *pRemoteIpInfo = NULL; REMOTE_IPINFO newIPInfo; if (pGuid == NULL) return E_INVALIDARG; dwErr = HRESULT_CODE(GetTransportConfig( &pNetCfg, &pTcpipProperties, &pRemoteIpInfo, pGuid, pwszIfFriendlyName )); while (dwErr == NO_ERROR) { //breakout block PWCHAR ptrAddr, ptrMask; DWORD Found = FALSE; PWCHAR pszwRemoteIpAddrList=NULL, pszwRemoteIpSubnetMaskList=NULL, pszwRemoteOptionList=pRemoteIpInfo->pszwOptionList;//i copy options list PWCHAR IpAddrListEnd; ULONG Length = wcslen(wszIp); // currently in static mode if (pRemoteIpInfo->dwEnableDhcp == FALSE) { pszwRemoteIpAddrList = pRemoteIpInfo->pszwIpAddrList; pszwRemoteIpSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList; IpAddrListEnd = pszwRemoteIpAddrList + wcslen(pszwRemoteIpAddrList); } // // if adding ipaddr, check if the IpAddr and Mask is already present // if (Flags & ADD_FLAG) { // // make sure it is in static mode // if (pRemoteIpInfo->dwEnableDhcp == TRUE) { DisplayMessage(g_hModule, EMSG_ADD_IPADDR_DHCP); dwErr = ERROR_SUPPRESS_OUTPUT; break; } ptrAddr = pszwRemoteIpAddrList; ptrMask = pszwRemoteIpSubnetMaskList; while (ptrAddr && (ptrAddr + Length <= IpAddrListEnd) ){ if (wcsncmp(ptrAddr, wszIp, Length) == 0) { if ( *(ptrAddr+Length)==0 || *(ptrAddr+Length)==c_wListSeparatorComma){ Found = TRUE; break; } } ptrAddr = wcschr(ptrAddr, c_wListSeparatorComma); ptrMask = wcschr(ptrMask, c_wListSeparatorComma); if (ptrAddr){ ptrAddr++; ptrMask++; } } if (Found) { PWCHAR MaskEnd; MaskEnd = wcschr(ptrMask, c_wListSeparatorComma); if (MaskEnd) *MaskEnd = 0; DisplayMessage(g_hModule, EMSG_IPADDR_PRESENT, wszIp, ptrMask); if (MaskEnd) *MaskEnd = c_wListSeparatorComma; dwErr = ERROR_SUPPRESS_OUTPUT; break; } } memcpy(&newIPInfo, pRemoteIpInfo, sizeof(newIPInfo)); newIPInfo.dwEnableDhcp = FALSE; // // copy ip addr list // if (Flags & ADD_FLAG) { ULONG IpAddrListLength = 0; if (pszwRemoteIpAddrList) IpAddrListLength = wcslen(pszwRemoteIpAddrList); newIPInfo.pszwIpAddrList = IfutlAlloc (sizeof(WCHAR) * (IpAddrListLength + Length + 2), TRUE); if (!newIPInfo.pszwIpAddrList) return ERROR_NOT_ENOUGH_MEMORY; newIPInfo.pszwIpAddrList[0] = 0; if (pszwRemoteIpAddrList) { wcscat(newIPInfo.pszwIpAddrList, pszwRemoteIpAddrList); wcscat(newIPInfo.pszwIpAddrList, c_wszListSeparatorComma); } wcscat(newIPInfo.pszwIpAddrList, wszIp); } else { newIPInfo.pszwIpAddrList = IfutlAlloc (sizeof(WCHAR) * (Length + 1), FALSE); if (!newIPInfo.pszwIpAddrList) return ERROR_NOT_ENOUGH_MEMORY; wcscpy(newIPInfo.pszwIpAddrList, wszIp); } // // copy subnet mask list // if (Flags & ADD_FLAG) { ULONG RemoteIpSubnetMaskListLen = 0; if (pszwRemoteIpSubnetMaskList) RemoteIpSubnetMaskListLen = wcslen(pszwRemoteIpSubnetMaskList); newIPInfo.pszwSubnetMaskList = IfutlAlloc (sizeof(WCHAR) * (RemoteIpSubnetMaskListLen + wcslen(wszMask) + 2), TRUE); if (!newIPInfo.pszwSubnetMaskList) return ERROR_NOT_ENOUGH_MEMORY; newIPInfo.pszwSubnetMaskList[0]= 0; if (pszwRemoteIpSubnetMaskList) { wcscpy(newIPInfo.pszwSubnetMaskList, pszwRemoteIpSubnetMaskList); wcscat(newIPInfo.pszwSubnetMaskList, c_wszListSeparatorComma); } wcscat(newIPInfo.pszwSubnetMaskList, wszMask); } else { newIPInfo.pszwSubnetMaskList = IfutlAlloc (sizeof(WCHAR) * (wcslen(wszMask) + 1), FALSE); if (!newIPInfo.pszwSubnetMaskList) return ERROR_NOT_ENOUGH_MEMORY; wcscpy(newIPInfo.pszwSubnetMaskList, wszMask); } // copy old options list newIPInfo.pszwOptionList = _wcsdup(pszwRemoteOptionList); DEBUG_PRINT_CONFIG(&newIPInfo); // // set the ip address // dwErr = HRESULT_CODE(pTcpipProperties->lpVtbl->SetIpInfoForAdapter( pTcpipProperties, pGuid, &newIPInfo)); if (dwErr == NO_ERROR) dwErr = HRESULT_CODE(pNetCfg->lpVtbl->Apply(pNetCfg)); if (newIPInfo.pszwIpAddrList) IfutlFree(newIPInfo.pszwIpAddrList); if (newIPInfo.pszwSubnetMaskList) IfutlFree(newIPInfo.pszwSubnetMaskList); if (newIPInfo.pszwOptionList) free(newIPInfo.pszwOptionList); break; //breakout block } //breakout block UninitializeTransportConfig( pNetCfg, pTcpipProperties, pRemoteIpInfo ); return dwErr; } VOID AppendDdnsOptions( PWCHAR ptrDstn, PWCHAR ptrOptionList, DWORD Flags, DWORD dwRegisterMode ) /*++ Routine Description Adds the appropriate "DynamicUpdate=...;NameRegistration=...;" string to a net config option list. Arguments ptrDstn [in] Buffer to which to append DDNS options. ptrOptionList [in] Old option list. Flags [in] Used to tell whether this is in a SET or ADD. dwRegisterMode [in] New mode to convert to options values. Return Value None. --*/ { PWCHAR ptrBegin, ptrEnd; // // Insert DynamicUpdate=...; // wcscat(ptrDstn, c_wcsDdns); if ((Flags & SET_FLAG) && (dwRegisterMode != REGISTER_UNCHANGED)) { // // Insert the new value. // if (dwRegisterMode == REGISTER_NONE) { wcscat(ptrDstn, L"0"); } else { wcscat(ptrDstn, L"1"); } } else { // // Copy the previous value. // ptrBegin = wcsstr(ptrOptionList, c_wcsDdns) + wcslen(c_wcsDdns); ptrEnd = wcschr(ptrBegin, c_wListSeparatorSC); ptrDstn += wcslen(ptrDstn); wcsncpy(ptrDstn, ptrBegin, (DWORD)(ptrEnd - ptrBegin)); ptrDstn += (ULONG)(ptrEnd - ptrBegin); *ptrDstn = 0; } wcscat(ptrDstn, c_wszListSeparatorSC); // // Insert NameRegistration=...; // wcscat(ptrDstn, c_wcsDdnsSuffix); if ((Flags & SET_FLAG) && (dwRegisterMode != REGISTER_UNCHANGED)) { // // Insert the new value. // if (dwRegisterMode == REGISTER_BOTH) { wcscat(ptrDstn, L"1"); } else { wcscat(ptrDstn, L"0"); } } else { // // Copy the previous value. // ptrBegin = wcsstr(ptrOptionList, c_wcsDdnsSuffix) + wcslen(c_wcsDdnsSuffix); ptrEnd = wcschr(ptrBegin, c_wListSeparatorSC); ptrDstn += wcslen(ptrDstn); wcsncpy(ptrDstn, ptrBegin, (DWORD)(ptrEnd - ptrBegin)); ptrDstn += (ULONG)(ptrEnd - ptrBegin); *ptrDstn = 0; } wcscat(ptrDstn, c_wszListSeparatorSC); } DWORD IfIpSetDhcpModeMany( LPCWSTR pwszIfFriendlyName, GUID *pGuid, DWORD dwRegisterMode, DISPLAY_TYPE Type ) /*++ Routine Description Arguments Return Value --*/ { INetCfg * pNetCfg = NULL; ITcpipProperties * pTcpipProperties = NULL; DWORD dwNetwork; HRESULT hr = S_OK; REMOTE_IPINFO *pRemoteIpInfo = NULL; REMOTE_IPINFO newIPInfo; if (pGuid == NULL) return E_INVALIDARG; hr = GetTransportConfig( &pNetCfg, &pTcpipProperties, &pRemoteIpInfo, pGuid, pwszIfFriendlyName ); while (hr == NO_ERROR) { //breakout block PWCHAR pszwBuffer; PWCHAR ptr, newPtr; PWCHAR pszwRemoteOptionList=pRemoteIpInfo->pszwOptionList; try { #pragma prefast(suppress:263, "This is a breakout block, not while loop") pszwBuffer = (PWCHAR) _alloca(sizeof(WCHAR) * (wcslen(pszwRemoteOptionList) + 100)) ; } except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; } // if setting ipaddr, check if dhcp already enabled. return. if (Type==TYPE_IPADDR && pRemoteIpInfo->dwEnableDhcp) { DisplayMessage(g_hModule, EMSG_DHCP_MODE); hr = ERROR_SUPPRESS_OUTPUT; break; } memcpy(&newIPInfo, pRemoteIpInfo, sizeof(REMOTE_IPINFO)); newIPInfo.dwEnableDhcp = pRemoteIpInfo->dwEnableDhcp; newIPInfo.pszwOptionList = pszwBuffer; pszwBuffer[0] = 0; switch(Type) { case TYPE_DNS: wcscpy(pszwBuffer, c_wcsDns); wcscat(pszwBuffer, c_wszListSeparatorSC); AppendDdnsOptions(pszwBuffer + wcslen(pszwBuffer), pRemoteIpInfo->pszwOptionList, SET_FLAG, dwRegisterMode); break; case TYPE_WINS: wcscpy(pszwBuffer, c_wcsWins); wcscat(pszwBuffer, c_wszListSeparatorSC); break; case TYPE_IPADDR: newIPInfo.dwEnableDhcp = TRUE; newIPInfo.pszwIpAddrList = NULL; newIPInfo.pszwSubnetMaskList = NULL; wcscpy(pszwBuffer, c_wcsDefGateway); wcscat(pszwBuffer, c_wszListSeparatorSC); wcscat(pszwBuffer, c_wcsGwMetric); wcscat(pszwBuffer, c_wszListSeparatorSC); break; } DEBUG_PRINT_CONFIG(&newIPInfo); // // set the ip address // hr = pTcpipProperties->lpVtbl->SetIpInfoForAdapter(pTcpipProperties, pGuid, &newIPInfo); if (hr == S_OK) hr = pNetCfg->lpVtbl->Apply(pNetCfg); break; } //breakout block UninitializeTransportConfig( pNetCfg, pTcpipProperties, pRemoteIpInfo ); return (hr == S_OK) ? NO_ERROR : hr; } DWORD IfIpAddSetDelMany( PWCHAR wszIfFriendlyName, GUID *pGuid, PWCHAR pwszAddress, DWORD dwIndex, DWORD dwRegisterMode, DISPLAY_TYPE Type, DWORD Flags ) /*++ Routine Description Arguments Return Value --*/ { INetCfg * pNetCfg = NULL; ITcpipProperties * pTcpipProperties = NULL; DWORD dwNetwork; HRESULT hr = S_OK; REMOTE_IPINFO * pRemoteIpInfo = NULL; REMOTE_IPINFO newIPInfo; if (pGuid == NULL) return E_INVALIDARG; hr = GetTransportConfig( &pNetCfg, &pTcpipProperties, &pRemoteIpInfo, pGuid, wszIfFriendlyName ); while (hr==NO_ERROR) { //breakout block PWCHAR ptrBegin, ptrEnd, ptrTmp, ptrDstn, ptrDel=NULL; const WCHAR * Token; switch (Type) { case TYPE_DNS: Token = c_wcsDns; break; case TYPE_WINS: Token = c_wcsWins; break; } ptrBegin = wcsstr(pRemoteIpInfo->pszwOptionList, Token) + wcslen(Token); ptrEnd = wcschr(ptrBegin, c_wListSeparatorSC); // // check if the address is already present // if ( (Flags & (ADD_FLAG | DEL_FLAG)) && (pwszAddress)) { ULONG Length = wcslen(pwszAddress), Found = FALSE; ptrTmp = ptrBegin; while (ptrTmp && (ptrTmp+Length <= ptrEnd) ){ if (ptrTmp = wcsstr(ptrTmp, pwszAddress)) { if ( ((*(ptrTmp+Length)==c_wListSeparatorComma) || (*(ptrTmp+Length)==c_wListSeparatorSC) ) && ( (*(ptrTmp-1)==c_wListSeparatorComma) || (*(ptrTmp-1)==c_wEqual)) ) { Found = TRUE; ptrDel = ptrTmp; break; } else { ptrTmp = wcschr(ptrTmp, c_wListSeparatorComma); } } } if (Found && (Flags & ADD_FLAG)) { DisplayMessage(g_hModule, EMSG_SERVER_PRESENT, pwszAddress); hr = ERROR_SUPPRESS_OUTPUT; break; //from breakout block } else if (!Found && (Flags & DEL_FLAG)) { DisplayMessage(g_hModule, EMSG_SERVER_ABSENT, pwszAddress); hr = ERROR_SUPPRESS_OUTPUT; break; //from breakout block } } // breakout block memcpy(&newIPInfo, pRemoteIpInfo, sizeof(newIPInfo)); // copy ip addr list { newIPInfo.pszwIpAddrList = pRemoteIpInfo->pszwIpAddrList; } // copy subnet mask list { newIPInfo.pszwSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList; } try { #pragma prefast(suppress:263, "This is a breakout block, not while loop") newIPInfo.pszwOptionList = (PWCHAR) _alloca(sizeof(PWCHAR) * (wcslen(pRemoteIpInfo->pszwOptionList)+ (pwszAddress?wcslen(pwszAddress):0) + 1)); } except (EXCEPTION_EXECUTE_HANDLER) { return ERROR_NOT_ENOUGH_MEMORY; } // copy token in all cases ptrDstn = newIPInfo.pszwOptionList; ptrDstn[0] = 0; wcscpy(ptrDstn, Token); ptrDstn += wcslen(Token); if (Flags & ADD_FLAG) { DWORD i; ptrTmp = ptrBegin; for (i=0; i ptrEnd)) { ptrTmp = ptrEnd; } if (*(ptrTmp-1) == c_wListSeparatorComma) ptrTmp--; // copy addresses before index if (ptrTmp>ptrBegin) { wcsncpy(ptrDstn, ptrBegin, (DWORD)(ptrTmp-ptrBegin)); ptrDstn += (ULONG) (ptrTmp - ptrBegin); ptrTmp++; *ptrDstn++ = c_wListSeparatorComma; *ptrDstn = 0; } } // copy new address if (Flags & (ADD_FLAG|SET_FLAG) ) { if (pwszAddress) { wcscat(ptrDstn, pwszAddress); ptrDstn += wcslen(pwszAddress); } } // copy addresses after index if (Flags & ADD_FLAG) { if (ptrTmp < ptrEnd) { *ptrDstn++ = c_wListSeparatorComma; *ptrDstn = 0; wcsncpy(ptrDstn, ptrTmp, (DWORD)(ptrEnd - ptrTmp)); ptrDstn += (ULONG)(ptrEnd - ptrTmp); *ptrDstn = 0; } } if (Flags & (ADD_FLAG|SET_FLAG) ) { wcscat(ptrDstn, c_wszListSeparatorSC); } if (Flags & DEL_FLAG) { if (pwszAddress && ptrDel) {//ptrDel to make prefast happy //if ptrDel not set, then I would have //got out of breakout block. BOOL AddrPrepend = FALSE; if (ptrDel > ptrBegin) { wcsncat(ptrDstn, ptrBegin, (DWORD)(ptrDel-ptrBegin)); ptrDstn += (ULONG)(ptrDel-ptrBegin); AddrPrepend = TRUE; if ( *(ptrDstn-1) == c_wListSeparatorComma) { *(--ptrDstn) = 0; } } ptrTmp = ptrDel + wcslen(pwszAddress); if (*ptrTmp == c_wListSeparatorComma) ptrTmp++; if (AddrPrepend && *ptrTmp!=c_wListSeparatorSC) *ptrDstn++ = c_wListSeparatorComma; wcsncat(ptrDstn, ptrTmp, (DWORD)(ptrEnd - ptrTmp)); ptrDstn += (ULONG)(ptrEnd - ptrTmp); *ptrDstn = 0; } wcscat(ptrDstn, c_wszListSeparatorSC); } if (Type == TYPE_DNS) { AppendDdnsOptions(ptrDstn, pRemoteIpInfo->pszwOptionList, Flags, dwRegisterMode); } DEBUG_PRINT_CONFIG(&newIPInfo); // // set the ip address // hr = pTcpipProperties->lpVtbl->SetIpInfoForAdapter(pTcpipProperties, pGuid, &newIPInfo); if (hr == S_OK) hr = pNetCfg->lpVtbl->Apply(pNetCfg); break; } //breakout block UninitializeTransportConfig( pNetCfg, pTcpipProperties, pRemoteIpInfo ); return (hr == S_OK) ? NO_ERROR : hr; } DWORD IfIpAddSetGateway( LPCWSTR pwszIfFriendlyName, GUID *pGuid, LPCWSTR pwszGateway, LPCWSTR pwszGwMetric, DWORD Flags ) /*++ Routine Description Arguments Return Value --*/ { INetCfg * pNetCfg = NULL; ITcpipProperties * pTcpipProperties = NULL; DWORD dwNetwork; HRESULT hr = S_OK; REMOTE_IPINFO *pRemoteIpInfo = NULL; REMOTE_IPINFO newIPInfo; PWCHAR Gateways, GatewaysEnd, GwMetrics, GwMetricsEnd; if (pGuid == NULL) return E_INVALIDARG; hr = GetTransportConfig( &pNetCfg, &pTcpipProperties, &pRemoteIpInfo, pGuid, pwszIfFriendlyName ); while (hr==NO_ERROR) { //breakout block PWCHAR ptrAddr, ptrMask; DWORD bFound = FALSE; PWCHAR pszwRemoteIpAddrList=NULL, pszwRemoteIpSubnetMaskList=NULL, pszwRemoteOptionList=NULL; pszwRemoteIpAddrList = pRemoteIpInfo->pszwIpAddrList; pszwRemoteIpSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList; pszwRemoteOptionList = pRemoteIpInfo->pszwOptionList; Gateways = wcsstr(pszwRemoteOptionList, c_wcsDefGateway) + wcslen(c_wcsDefGateway); GatewaysEnd = wcschr(Gateways, c_wListSeparatorSC); GwMetrics = wcsstr(pszwRemoteOptionList, c_wcsGwMetric) + wcslen(c_wcsGwMetric); GwMetricsEnd = wcschr(GwMetrics, c_wListSeparatorSC); // // check if the gateway is already present // if (Flags & ADD_FLAG) { ULONG Length = wcslen(pwszGateway), Found = FALSE; PWCHAR TmpPtr; TmpPtr = Gateways; while (TmpPtr && (TmpPtr+Length <= GatewaysEnd) ){ if (TmpPtr = wcsstr(TmpPtr, pwszGateway)) { if ( ((*(TmpPtr+Length)==c_wListSeparatorComma) || (*(TmpPtr+Length)==c_wListSeparatorSC) ) && ( (*(TmpPtr-1)==c_wListSeparatorComma) || (*(TmpPtr-1)==c_wEqual)) ) { Found = TRUE; break; } else { TmpPtr = wcschr(TmpPtr, c_wListSeparatorComma); } } } if (Found) { DisplayMessage(g_hModule, EMSG_DEFGATEWAY_PRESENT, pwszGateway); hr = ERROR_SUPPRESS_OUTPUT; break; //from breakout block } } memcpy(&newIPInfo, pRemoteIpInfo, sizeof(newIPInfo)); // copy ip addr list newIPInfo.pszwIpAddrList = pRemoteIpInfo->pszwIpAddrList; // copy subnet mask list newIPInfo.pszwSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList; // copy old options list if (Flags & ADD_FLAG) { newIPInfo.pszwOptionList = IfutlAlloc (sizeof(WCHAR) * (wcslen(pszwRemoteOptionList) + wcslen(pwszGateway) + wcslen(pwszGwMetric) + 3), TRUE); if (!newIPInfo.pszwOptionList) { hr = ERROR_NOT_ENOUGH_MEMORY; break; //from breakout block } wcsncpy(newIPInfo.pszwOptionList, pszwRemoteOptionList, (DWORD)(GatewaysEnd - pszwRemoteOptionList)); *(newIPInfo.pszwOptionList + (GatewaysEnd - pszwRemoteOptionList)) = 0; if (*(GatewaysEnd-1) != c_wEqual) { wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorComma); } wcscat(newIPInfo.pszwOptionList, pwszGateway); wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorSC); { ULONG Length; Length = wcslen(newIPInfo.pszwOptionList); wcsncat(newIPInfo.pszwOptionList, GatewaysEnd+1, (DWORD)(GwMetricsEnd - (GatewaysEnd+1))); Length += (DWORD) (GwMetricsEnd - (GatewaysEnd+1)); newIPInfo.pszwOptionList[Length] = 0; } if (*(GwMetricsEnd-1) != c_wEqual) { wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorComma); } wcscat(newIPInfo.pszwOptionList, pwszGwMetric); wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorSC); wcscat(newIPInfo.pszwOptionList, GwMetricsEnd+1); } else { ULONG Length; Length = sizeof(WCHAR) * (wcslen(c_wcsDefGateway) + wcslen(c_wcsGwMetric) + 3); if (pwszGateway) Length += sizeof(WCHAR) * (wcslen(pwszGateway) + wcslen(pwszGwMetric)); newIPInfo.pszwOptionList = (PWCHAR) IfutlAlloc (Length, FALSE); if (newIPInfo.pszwOptionList == NULL) { hr = ERROR_NOT_ENOUGH_MEMORY; break; //from breakout block } newIPInfo.pszwOptionList[0] = 0; // cat gateway wcscat(newIPInfo.pszwOptionList, c_wcsDefGateway); if (pwszGateway) wcscat(newIPInfo.pszwOptionList, pwszGateway); wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorSC); // cat gwmetric wcscat(newIPInfo.pszwOptionList, c_wcsGwMetric); if (pwszGateway) wcscat(newIPInfo.pszwOptionList, pwszGwMetric); wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorSC); } DEBUG_PRINT_CONFIG(&newIPInfo); // // set the ip address // hr = pTcpipProperties->lpVtbl->SetIpInfoForAdapter(pTcpipProperties, pGuid, &newIPInfo); if (hr == S_OK) hr = pNetCfg->lpVtbl->Apply(pNetCfg); if (newIPInfo.pszwOptionList) IfutlFree(newIPInfo.pszwOptionList); break; } //breakout block UninitializeTransportConfig( pNetCfg, pTcpipProperties, pRemoteIpInfo ); return (hr == S_OK) ? NO_ERROR : hr; } // // Display an IP address in Unicode form. If First is false, // a string of spaces will first be printed so that the list lines up. // For the first address, the caller is responsible for printing the // header before calling this function. // VOID ShowUnicodeAddress( BOOL *pFirst, PWCHAR pwszAddress) { if (*pFirst) { *pFirst = FALSE; } else { DisplayMessage(g_hModule, MSG_ADDR2); } DisplayMessage(g_hModule, MSG_ADDR1, pwszAddress); } // Same as ShowUnicodeAddress, except that the address is passed // in multibyte form, such as is used by IPHLPAPI VOID ShowCharAddress( BOOL *pFirst, char *chAddress) { WCHAR pwszBuffer[16]; if (!chAddress[0]) { return; } MultiByteToWideChar(GetConsoleOutputCP(), 0, chAddress, strlen(chAddress)+1, pwszBuffer, 16); ShowUnicodeAddress(pFirst, pwszBuffer); } DWORD IfIpShowManyExEx( LPCWSTR pwszMachineName, ULONG IfIndex, PWCHAR pFriendlyIfName, GUID *pGuid, ULONG Flags, HANDLE hFile ) /*++ Routine Description Arguments Return Value --*/ { INetCfg * pNetCfg = NULL; ITcpipProperties * pTcpipProperties = NULL; DWORD dwNetwork, dwSize = 0, dwErr; HRESULT hr = S_OK; REMOTE_IPINFO *pRemoteIpInfo = NULL; REMOTE_IPINFO newIPInfo; PWCHAR pQuotedFriendlyIfName = NULL; PIP_PER_ADAPTER_INFO pPerAdapterInfo = NULL; PIP_ADAPTER_INFO pAdaptersInfo = NULL, pAdapterInfo = NULL; DWORD dwRegisterMode; if (pGuid == NULL) return E_INVALIDARG; if (hFile && pwszMachineName) { // not currently remotable return NO_ERROR; } if (!hFile && !pwszMachineName) { // // If we're not doing a "dump", and we're looking at the local // machine, then get active per-adapter information such as the // current DNS and WINS server addresses // GetPerAdapterInfo(IfIndex, NULL, &dwSize); pPerAdapterInfo = (PIP_PER_ADAPTER_INFO)IfutlAlloc(dwSize,FALSE); if (!pPerAdapterInfo) { return ERROR_NOT_ENOUGH_MEMORY; } dwErr = GetPerAdapterInfo(IfIndex, pPerAdapterInfo, &dwSize); if (dwErr != NO_ERROR) { IfutlFree(pPerAdapterInfo); pPerAdapterInfo = NULL; } dwSize = 0; GetAdaptersInfo(NULL, &dwSize); pAdaptersInfo = (PIP_ADAPTER_INFO)IfutlAlloc(dwSize,FALSE); if (!pAdaptersInfo) { IfutlFree(pPerAdapterInfo); return ERROR_NOT_ENOUGH_MEMORY; } dwErr = GetAdaptersInfo(pAdaptersInfo, &dwSize); if (dwErr != NO_ERROR) { IfutlFree(pAdaptersInfo); pAdaptersInfo = NULL; } if (pAdaptersInfo) { for (pAdapterInfo = pAdaptersInfo; pAdapterInfo && pAdapterInfo->Index != IfIndex; pAdapterInfo = pAdapterInfo->Next); } } hr = GetTransportConfig( &pNetCfg, &pTcpipProperties, &pRemoteIpInfo, pGuid, pFriendlyIfName ); while (hr==NO_ERROR) { //breakout block PWCHAR ptrAddr, ptrMask, ptrAddrNew, ptrMaskNew; if (hr != NO_ERROR) break; pQuotedFriendlyIfName = MakeQuotedString( pFriendlyIfName ); if ( pQuotedFriendlyIfName == NULL ) { hr = ERROR_NOT_ENOUGH_MEMORY; break; } DEBUG_PRINT_CONFIG(pRemoteIpInfo); if (hFile) { DisplayMessage(g_hModule, DMP_IFIP_INTERFACE_HEADER, pQuotedFriendlyIfName); } else { DisplayMessage(g_hModule, MSG_IFIP_HEADER, pQuotedFriendlyIfName); } // // display ipaddress list // if (Flags & TYPE_IPADDR) { if (hFile) { DisplayMessageT( (pRemoteIpInfo->dwEnableDhcp) ? DMP_DHCP : DMP_STATIC, pQuotedFriendlyIfName ); } else { DisplayMessage(g_hModule, (pRemoteIpInfo->dwEnableDhcp) ? MSG_DHCP : MSG_STATIC); } if (!pRemoteIpInfo->dwEnableDhcp) { ptrAddr = pRemoteIpInfo->pszwIpAddrList; ptrMask = pRemoteIpInfo->pszwSubnetMaskList; } else if (!pwszMachineName) { // If on the local machine, get the active list ptrAddr = NULL; ptrMask = NULL; } if (ptrAddr && ptrMask) { DWORD First = TRUE; while (ptrAddr && ptrMask && *ptrAddr!=0 && *ptrMask != 0) { ptrAddrNew = wcschr(ptrAddr, c_wListSeparatorComma); ptrMaskNew = wcschr(ptrMask, c_wListSeparatorComma); if (ptrAddrNew) *ptrAddrNew = 0; if (ptrMaskNew) *ptrMaskNew = 0; if (hFile) { if (First) { DisplayMessageT( DMP_IPADDR1, ptrAddr, ptrMask ); First = FALSE; } else { DisplayMessageT( DMP_IPADDR2, pQuotedFriendlyIfName, ptrAddr, ptrMask ); } } else { DisplayMessage(g_hModule, MSG_IPADDR_LIST1, ptrAddr, ptrMask); } ptrAddr = ptrAddrNew ? ++ptrAddrNew : NULL; ptrMask = ptrMaskNew ? ++ptrMaskNew : NULL; } } } // end display ipaddr // // display options list // { PWCHAR IfMetric1, Gateways1, GwMetrics1, Dns1, Wins1, Ptr1, Ptr2, Equal, SemiColon, Ddns1, DdnsSuffix1, End1; if (hr != NO_ERROR) break; Ptr1 = pRemoteIpInfo->pszwOptionList; IfMetric1 = wcsstr(Ptr1, c_wcsIfMetric); Gateways1 = wcsstr(Ptr1, c_wcsDefGateway); GwMetrics1 = wcsstr(Ptr1, c_wcsGwMetric); Dns1 = wcsstr(Ptr1, c_wcsDns); Wins1 = wcsstr(Ptr1, c_wcsWins); Ddns1 = wcsstr(Ptr1, c_wcsDdns); DdnsSuffix1 = wcsstr(Ptr1, c_wcsDdnsSuffix); while (*Ptr1) { Equal = wcschr(Ptr1, c_wEqual); SemiColon = wcschr(Ptr1, c_wListSeparatorSC); if (!Equal || !SemiColon) break; Ptr2 = Ptr1; Ptr1 = SemiColon + 1; *SemiColon = 0; // display IfMetric if (Ptr2 == IfMetric1) { if (! (Flags & TYPE_IPADDR)) continue; if (hFile) { } else { DisplayMessage(g_hModule, MSG_IFMETRIC, Equal+1); } } // display Gateways else if (Ptr2 == Gateways1) { PWCHAR Gateway, GwMetric, GatewayEnd, GwMetricEnd, Comma1, Comma2; BOOL First = TRUE; if (! (Flags & TYPE_IPADDR)) continue; // gateways list null if (SemiColon == (Ptr2 + wcslen(c_wcsDefGateway))) continue; Gateway = Equal + 1; GatewayEnd = SemiColon; GwMetric = wcschr(GwMetrics1, c_wEqual) + 1; GwMetricEnd = wcschr(GwMetrics1, c_wListSeparatorSC); *GwMetricEnd = 0; do { Comma1 = wcschr(Gateway, c_wListSeparatorComma); if (Comma1) *Comma1 = 0; Comma2 = wcschr(GwMetric, c_wListSeparatorComma); if (Comma2) *Comma2 = 0; if (hFile) { if (First) { DisplayMessageT( DMP_GATEWAY2, pQuotedFriendlyIfName, Gateway, GwMetric ); First = FALSE; } else { DisplayMessageT( DMP_GATEWAY3, pQuotedFriendlyIfName, Gateway, GwMetric ); } } else { DisplayMessage(g_hModule, MSG_GATEWAY, Gateway, GwMetric); } if (Comma1) *Comma1 = c_wListSeparatorComma; if (Comma2) *Comma2 = c_wListSeparatorComma; Gateway = Comma1 + 1; GwMetric = Comma2 + 1; } while (Comma1 && GatewaydwEnableDhcp ? (bDns?DMP_DNS_DHCP:DMP_WINS_DHCP) : (bDns?DMP_DNS_STATIC_NONE:DMP_WINS_STATIC_NONE), pQuotedFriendlyIfName ); if (bDns) { // // When generating a DNS (not WINS) line, // also include the REGISTER=... argument. // We need to look ahead in the option list // since the DDNS info may occur after the // WINS info, but we have to output it before. // if (!wcstol(Ddns1+wcslen(c_wcsDdns), &End1, 10)) { DisplayMessageT(DMP_STRING_ARG, TOKEN_REGISTER, TOKEN_VALUE_NONE); } else if (!wcstol(DdnsSuffix1+wcslen( c_wcsDdnsSuffix), &End1, 10)) { DisplayMessageT(DMP_STRING_ARG, TOKEN_REGISTER, TOKEN_VALUE_PRIMARY); } else { DisplayMessageT(DMP_STRING_ARG, TOKEN_REGISTER, TOKEN_VALUE_BOTH); } } } else { if (pRemoteIpInfo->dwEnableDhcp) { IP_ADDR_STRING *pAddr; BOOL First = TRUE; if (!pwszMachineName) { DisplayMessage(g_hModule, (bDns?MSG_DNS_DHCP_HDR:MSG_WINS_DHCP_HDR) ); // Display active list if (bDns && pPerAdapterInfo) { for (pAddr = &pPerAdapterInfo->DnsServerList; pAddr; pAddr = pAddr->Next) { ShowCharAddress(&First, pAddr->IpAddress.String); } } else if (!bDns && pAdapterInfo) { if (strcmp(pAdapterInfo->PrimaryWinsServer.IpAddress.String, "0.0.0.0")) { ShowCharAddress(&First, pAdapterInfo->PrimaryWinsServer.IpAddress.String); } if (strcmp(pAdapterInfo->SecondaryWinsServer.IpAddress.String, "0.0.0.0")) { ShowCharAddress(&First, pAdapterInfo->SecondaryWinsServer.IpAddress.String); } } if (First) { DisplayMessage(g_hModule, MSG_NONE); } } else { DisplayMessage(g_hModule, (bDns?MSG_DNS_DHCP:MSG_WINS_DHCP) ); } } else { DisplayMessage(g_hModule, bDns?MSG_DNS_HDR:MSG_WINS_HDR); DisplayMessage(g_hModule, MSG_NONE); } // // For show commands, we output either DNS or WINS // information but not both, so we can wait until // we process the DDNS information normally, // before outputting the DDNS state. // } continue; } { PWCHAR Comma1; BOOL First = TRUE; DWORD Index = 0; if (!hFile) { DisplayMessage(g_hModule, bDns?MSG_DNS_HDR:MSG_WINS_HDR); } do { Index++; Comma1 = wcschr(BeginPtr, c_wListSeparatorComma); if (Comma1) *Comma1 = 0; if (hFile) { DisplayMessageT( First ? (First=FALSE,(bDns?DMP_DNS_STATIC_ADDR1:DMP_WINS_STATIC_ADDR1)) : (bDns?DMP_DNS_STATIC_ADDR2:DMP_WINS_STATIC_ADDR2), pQuotedFriendlyIfName, BeginPtr); if (bDns && (Index == 1)) { // // When generating a DNS (not WINS) line, // also include the REGISTER=... argument. // We need to look ahead in the option list // since the DDNS info may occur after the // WINS info, but we have to output it // before. // if (!wcstol(Ddns1+wcslen(c_wcsDdns), &End1, 10)) { DisplayMessageT(DMP_STRING_ARG, TOKEN_REGISTER, TOKEN_VALUE_NONE); } else if (!wcstol(DdnsSuffix1+wcslen( c_wcsDdnsSuffix), &End1, 10)) { DisplayMessageT(DMP_STRING_ARG, TOKEN_REGISTER, TOKEN_VALUE_PRIMARY); } else { DisplayMessageT(DMP_STRING_ARG, TOKEN_REGISTER, TOKEN_VALUE_BOTH); } } else if (Index > 1) { DisplayMessageT(DMP_INTEGER_ARG, TOKEN_INDEX, Index); } } else { ShowUnicodeAddress(&First, BeginPtr); } if (Comma1) *Comma1 = c_wListSeparatorComma; BeginPtr = Comma1 + 1; } while (Comma1 && BeginPtrpszwIpAddrList; PWCHAR pszwRemoteSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList; PWCHAR EndIpAddrList = pszwRemoteIpAddrList + wcslen(pszwRemoteIpAddrList); BOOL Found = FALSE; ULONG Length = wcslen(pwszIpAddr); IpAddr = pszwRemoteIpAddrList; Mask = pszwRemoteSubnetMaskList; while (IpAddr && (IpAddr + Length <= EndIpAddrList) ){ if (wcsncmp(IpAddr, pwszIpAddr, Length) == 0) { if ( *(IpAddr+Length)==0 || *(IpAddr+Length)==c_wListSeparatorComma){ Found = TRUE; break; } } IpAddr = wcschr(IpAddr, c_wListSeparatorComma); Mask = wcschr(Mask, c_wListSeparatorComma); if (IpAddr){ IpAddr++; Mask++; } } // IpAddr not present if (!Found) { DisplayMessage(g_hModule, EMSG_ADDRESS_NOT_PRESENT); hr = ERROR_SUPPRESS_OUTPUT; break; } // cannot delete addr in dhcp mode if (pRemoteIpInfo->dwEnableDhcp == TRUE) { DisplayMessage(g_hModule, EMSG_DHCP_DELETEADDR); hr = ERROR_SUPPRESS_OUTPUT; break; } IpAddrEnd = wcschr(IpAddr, c_wListSeparatorComma); MaskEnd = wcschr(Mask, c_wListSeparatorComma); if (*(IpAddr-1) == c_wListSeparatorComma) { IpAddr --; Mask --; } else if (IpAddrEnd) { IpAddrEnd++; MaskEnd++; } pszwRemoteIpAddrList[IpAddr - pszwRemoteIpAddrList] = 0; pszwRemoteSubnetMaskList[Mask - pszwRemoteSubnetMaskList] = 0; if (IpAddrEnd) { wcscat(pszwRemoteIpAddrList, IpAddrEnd); wcscat(pszwRemoteSubnetMaskList, MaskEnd); } // should have at least one addr in static mode if (wcslen(pszwRemoteIpAddrList)==0 && pRemoteIpInfo->dwEnableDhcp == FALSE) { DisplayMessage(g_hModule, EMSG_MIN_ONE_ADDR); hr = ERROR_SUPPRESS_OUTPUT; break; } } //end delete ipaddr if (Flags & TYPE_GATEWAY) { PWCHAR pszwRemoteOptionList = pRemoteIpInfo->pszwOptionList; PWCHAR Gateways, GatewaysEnd, GwMetrics, GwMetricsEnd, GwMetrics1; BOOL Found = FALSE; Gateways = wcsstr(pszwRemoteOptionList, c_wcsDefGateway) + wcslen(c_wcsDefGateway); GwMetrics1 = GwMetrics = wcsstr(pszwRemoteOptionList, c_wcsGwMetric) + wcslen(c_wcsGwMetric); GatewaysEnd = wcschr(Gateways, c_wListSeparatorSC); // check if the gateway is present if (pwszGateway) { ULONG Length = wcslen(pwszGateway); while ((Gateways+Length) <= GatewaysEnd) { if ( (wcsncmp(pwszGateway, Gateways, Length)==0) && ( (*(Gateways+Length)==c_wListSeparatorComma) || (*(Gateways+Length)==c_wListSeparatorSC)) ) { Found = TRUE; break; } else { if (Gateways = wcschr(Gateways, c_wListSeparatorComma)) { Gateways++; GwMetrics = wcschr(GwMetrics, c_wListSeparatorComma) + 1; } else { break; } } } if (!Found) { DisplayMessage(g_hModule, EMSG_GATEWAY_NOT_PRESENT); hr = ERROR_SUPPRESS_OUTPUT; break; //from breakout block } } if (!pwszGateway) { wcscpy(pszwRemoteOptionList, c_wcsDefGateway); wcscat(pszwRemoteOptionList, c_wszListSeparatorSC); wcscat(pszwRemoteOptionList, c_wcsGwMetric); wcscat(pszwRemoteOptionList, c_wszListSeparatorSC); } else { PWCHAR GatewaysListEnd, GwMetricsListEnd, TmpPtr; GatewaysListEnd = wcschr(Gateways, c_wListSeparatorSC); GwMetricsListEnd = wcschr(GwMetrics, c_wListSeparatorSC); GatewaysEnd = Gateways + wcslen(pwszGateway); GwMetricsEnd = wcschr(GwMetrics, c_wListSeparatorComma); if (!GwMetricsEnd || GwMetricsEnd>GwMetricsListEnd) GwMetricsEnd = wcschr(GwMetrics, c_wListSeparatorSC); if (*(Gateways-1)==c_wListSeparatorComma) { Gateways--; GwMetrics--; } else if (*GatewaysEnd==c_wListSeparatorComma) { GatewaysEnd++; GwMetricsEnd++; } wcsncpy(Gateways, GatewaysEnd, (DWORD)(GwMetrics - GatewaysEnd)); TmpPtr = Gateways + (GwMetrics - GatewaysEnd); *TmpPtr = 0; wcscat(TmpPtr, GwMetricsEnd); } } //end delete gateway // // set the config // if (hr == S_OK) hr = pTcpipProperties->lpVtbl->SetIpInfoForAdapter(pTcpipProperties, pGuid, pRemoteIpInfo); if (hr == S_OK) hr = pNetCfg->lpVtbl->Apply(pNetCfg); break; }//end breakout block UninitializeTransportConfig( pNetCfg, pTcpipProperties, pRemoteIpInfo ); return (hr == S_OK) ? NO_ERROR : hr; } DWORD OpenDriver( HANDLE *Handle, LPWSTR DriverName ) /*++ Routine Description: This function opens a specified IO drivers. Arguments: Handle - pointer to location where the opened drivers handle is returned. DriverName - name of the driver to be opened. Return Value: Windows Error Code. Notes: copied from net\sockets\tcpcmd\ipcfgapi\ipcfgapi.c --*/ { OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; UNICODE_STRING nameString; NTSTATUS status; *Handle = NULL; // // Open a Handle to the IP driver. // RtlInitUnicodeString(&nameString, DriverName); InitializeObjectAttributes( &objectAttributes, &nameString, OBJ_CASE_INSENSITIVE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL ); status = NtCreateFile( Handle, SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0 ); return( RtlNtStatusToDosError( status ) ); } NTSTATUS DoIoctl( HANDLE Handle, DWORD IoctlCode, PVOID Request, DWORD RequestSize, PVOID Response, PDWORD ResponseSize ) /*++ Routine Description: Utility routine used to issue a filtering ioctl to the tcpip driver. Arguments: Handle - An open file handle on which to issue the request. IoctlCode - The IOCTL opcode. Request - A pointer to the input buffer. RequestSize - Size of the input buffer. Response - A pointer to the output buffer. ResponseSize - On input, the size in bytes of the output buffer. On output, the number of bytes returned in the output buffer. Return Value: NT Status Code. Notes: copied from net\sockets\tcpcmd\ipcfgapi\ipcfgapi.c --*/ { IO_STATUS_BLOCK ioStatusBlock; NTSTATUS status; ioStatusBlock.Information = 0; status = NtDeviceIoControlFile( Handle, // Driver handle NULL, // Event NULL, // APC Routine NULL, // APC context &ioStatusBlock, // Status block IoctlCode, // Control code Request, // Input buffer RequestSize, // Input buffer size Response, // Output buffer *ResponseSize // Output buffer size ); if (status == STATUS_PENDING) { status = NtWaitForSingleObject( Handle, TRUE, NULL ); } if (status == STATUS_SUCCESS) { status = ioStatusBlock.Status; *ResponseSize = (ULONG)ioStatusBlock.Information; } else { *ResponseSize = 0; } return(status); } DWORD IfIpGetInfoOffload( ULONG IfIndex, IFOffloadCapability* IFOC ) /*++ Routine Description Arguments Return Value --*/ { NTSTATUS Status; HANDLE Handle; ULONG ResponseBufferSize = sizeof(*IFOC); Status = OpenDriver(&Handle, L"\\Device\\Ip"); if (!NT_SUCCESS(Status)) { return(RtlNtStatusToDosError(Status)); } Status = DoIoctl( Handle, IOCTL_IP_GET_OFFLOAD_CAPABILITY, &IfIndex, sizeof(IfIndex), IFOC, &ResponseBufferSize ); CloseHandle(Handle); if (!NT_SUCCESS(Status)) { return(RtlNtStatusToDosError(Status)); } return NO_ERROR; } DWORD IfIpShowManyEx( LPCWSTR pwszMachineName, ULONG IfIndex, PWCHAR wszIfFriendlyName, GUID *guid, DISPLAY_TYPE dtType, HANDLE hFile ) /*++ Routine Description Arguments Return Value --*/ { switch (dtType) { case TYPE_IPADDR: case TYPE_DNS: case TYPE_WINS: case TYPE_IP_ALL: return IfIpShowManyExEx(pwszMachineName, IfIndex, wszIfFriendlyName, guid, dtType, hFile); case TYPE_OFFLOAD: return IfIpShowInfoOffload(IfIndex, wszIfFriendlyName); } return NO_ERROR; } DWORD IfIpShowInfoOffload( ULONG IfIndex, PWCHAR wszIfFriendlyName ) /*++ Routine Description Arguments Return Value --*/ { IFOffloadCapability IFOC; DWORD dwErr; PWCHAR pQuotedFriendlyIfName = NULL; pQuotedFriendlyIfName = MakeQuotedString( wszIfFriendlyName ); if ( pQuotedFriendlyIfName == NULL ) { return ERROR_NOT_ENOUGH_MEMORY; } dwErr = IfIpGetInfoOffload(IfIndex, &IFOC); if (dwErr != NO_ERROR) return dwErr; DisplayMessage(g_hModule, MSG_OFFLOAD_HDR, pQuotedFriendlyIfName, IfIndex); if (IFOC.ifoc_OffloadFlags & TCP_XMT_CHECKSUM_OFFLOAD) { DisplayMessage(g_hModule, MSG_TCP_XMT_CHECKSUM_OFFLOAD); } if (IFOC.ifoc_OffloadFlags & IP_XMT_CHECKSUM_OFFLOAD) { DisplayMessage(g_hModule, MSG_IP_XMT_CHECKSUM_OFFLOAD); } if (IFOC.ifoc_OffloadFlags & TCP_RCV_CHECKSUM_OFFLOAD) { DisplayMessage(g_hModule, MSG_TCP_RCV_CHECKSUM_OFFLOAD); } if (IFOC.ifoc_OffloadFlags & IP_RCV_CHECKSUM_OFFLOAD) { DisplayMessage(g_hModule, MSG_IP_RCV_CHECKSUM_OFFLOAD); } if (IFOC.ifoc_OffloadFlags & TCP_LARGE_SEND_OFFLOAD) { DisplayMessage(g_hModule, MSG_TCP_LARGE_SEND_OFFLOAD); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_CRYPTO_ONLY) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_CRYPTO_ONLY); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_ESP) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_AH_ESP); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_TPT_TUNNEL) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_TPT_TUNNEL); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_V4_OPTIONS) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_V4_OPTIONS); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_QUERY_SPI) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_QUERY_SPI); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_XMT) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_AH_XMT); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_RCV) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_AH_RCV); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_TPT) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_AH_TPT); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_TUNNEL) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_AH_TUNNEL); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_MD5) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_AH_MD5); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_SHA_1) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_AH_SHA_1); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_XMT) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_ESP_XMT); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_RCV) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_ESP_RCV); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_TPT) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_ESP_TPT); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_TUNNEL) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_ESP_TUNNEL); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_DES) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_ESP_DES); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_DES_40) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_ESP_DES_40); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_3_DES) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_ESP_3_DES); } if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_NONE) { DisplayMessage(g_hModule, MSG_IPSEC_OFFLOAD_ESP_NONE); } if ( pQuotedFriendlyIfName ) { FreeQuotedString( pQuotedFriendlyIfName ); } return dwErr; }