/* Copyright (c) 1998, Microsoft Corporation, all rights reserved Description: The old code is in SaveRegistry and LoadRegistry functions in ncpa1.1\tcpip\tcpipcpl.cxx History: Dec 1997: Vijay Baliga created original version. */ #include "tcpreg_.h" /* Returns: Number of bytes in the mwsz including the two terminating NULLs. Notes: */ #define RAS_LOOPBACK_ADDRESS 0x100007f DWORD MwszLength( IN WCHAR* mwsz ) { DWORD dwLength = 2; RTASSERT(NULL != mwsz); while (mwsz[0] != 0 || mwsz[1] != 0) { dwLength++; mwsz++; } return(dwLength); } /* Returns: VOID Notes: There should be atleast two zeros at the end */ VOID ConvertSzToMultiSz( IN CHAR* sz ) { while (TRUE) { if ( (0 == sz[0]) && (0 == sz[1])) { break; } if ( (' ' == sz[0]) || (',' == sz[0])) { sz[0] = 0; } sz++; } } /* Returns: Win32 error code Notes: */ DWORD RegQueryValueWithAllocA( IN HKEY hKey, IN CHAR* szValueName, IN DWORD dwTypeRequired, IN BYTE** ppbData ) { DWORD dwType = 0; DWORD dwSize = 0; DWORD dwErr = ERROR_SUCCESS; RTASSERT(NULL != szValueName); RTASSERT(NULL != ppbData); *ppbData = NULL; dwErr = RegQueryValueExA(hKey, szValueName, NULL, &dwType, NULL, &dwSize); if (ERROR_SUCCESS != dwErr) { // TraceHlp("RegQueryValueEx(%s) failed and returned %d.", // szValueName, dwErr); goto LDone; } if (dwTypeRequired != dwType) { dwErr = E_FAIL; TraceHlp("The type of the value %s should be %d, not %d", szValueName, dwTypeRequired, dwType); goto LDone; } // For an empty MULTI-SZ, dwSize will be sizeof(CHAR) instead of // 2 * sizeof(CHAR). We also want to make sure that no matter what // the type, there will be 2 zeros at the end. dwSize += 2 * sizeof(CHAR); *ppbData = LocalAlloc(LPTR, dwSize); if (NULL == *ppbData) { dwErr = GetLastError(); TraceHlp("LocalAlloc failed and returned %d", dwErr); goto LDone; } dwErr = RegQueryValueExA(hKey, szValueName, NULL, &dwType, *ppbData, &dwSize); if (ERROR_SUCCESS != dwErr) { // TraceHlp("RegQueryValueEx(%s) failed and returned %d.", // szValueName, dwErr); goto LDone; } LDone: if (NO_ERROR != dwErr) { LocalFree(*ppbData); *ppbData = NULL; } return(dwErr); } /* Returns: Win32 error code Notes: */ DWORD RegQueryValueWithAllocW( IN HKEY hKey, IN WCHAR* wszValueName, IN DWORD dwTypeRequired, IN BYTE** ppbData ) { DWORD dwType; DWORD dwSize = 0; DWORD dwErr = ERROR_SUCCESS; RTASSERT(NULL != wszValueName); RTASSERT(NULL != ppbData); *ppbData = NULL; dwErr = RegQueryValueExW(hKey, wszValueName, NULL, &dwType, NULL, &dwSize); if (ERROR_SUCCESS != dwErr) { // TraceHlp("RegQueryValueEx(%ws) failed and returned %d.", // wszValueName, dwErr); goto LDone; } if (dwTypeRequired != dwType) { dwErr = E_FAIL; TraceHlp("The type of the value %ws should be %d, not %d", wszValueName, dwTypeRequired, dwType); goto LDone; } // For an empty MULTI-SZ, dwSize will be sizeof(WCHAR) instead of // 2 * sizeof(WCHAR). We also want to make sure that no matter what // the type, there will be 2 zeros at the end. dwSize += sizeof(WCHAR); *ppbData = LocalAlloc(LPTR, dwSize); if (NULL == *ppbData) { dwErr = GetLastError(); TraceHlp("LocalAlloc failed and returned %d", dwErr); goto LDone; } dwErr = RegQueryValueExW(hKey, wszValueName, NULL, &dwType, *ppbData, &dwSize); if (ERROR_SUCCESS != dwErr) { // TraceHlp("RegQueryValueEx(%ws) failed and returned %d.", // wszValueName, dwErr); goto LDone; } LDone: if (NO_ERROR != dwErr) { LocalFree(*ppbData); *ppbData = NULL; } return(dwErr); } /* Returns: IP address Notes: Converts caller's a.b.c.d IP address string to a network byte order IP address. 0 if formatted incorrectly. */ IPADDR IpAddressFromAbcdWsz( IN WCHAR* wszIpAddress ) { CHAR szIpAddress[MAXIPSTRLEN + 1]; IPADDR nboIpAddr; if (0 == WideCharToMultiByte( CP_UTF8, 0, wszIpAddress, -1, szIpAddress, MAXIPSTRLEN + 1, NULL, NULL)) { return(0); } nboIpAddr = inet_addr(szIpAddress); if (INADDR_NONE == nboIpAddr) { nboIpAddr = 0; } return(nboIpAddr); } /* Returns: VOID Description: Converts nboIpAddr to a string in the a.b.c.d form and returns same in caller's szIpAddress buffer. The buffer should be at least MAXIPSTRLEN + 1 characters long. */ VOID AbcdSzFromIpAddress( IN IPADDR nboIpAddr, OUT CHAR* szIpAddress ) { struct in_addr in_addr; CHAR* sz; in_addr.s_addr = nboIpAddr; sz = inet_ntoa(in_addr); strcpy(szIpAddress, sz ? sz : ""); } /* Returns: VOID Description: Converts nboIpAddr to a string in the a.b.c.d form and returns same in caller's wszIpAddress buffer. The buffer should be at least MAXIPSTRLEN + 1 characters long. */ VOID AbcdWszFromIpAddress( IN IPADDR nboIpAddr, OUT WCHAR* wszIpAddress ) { CHAR szIpAddress[MAXIPSTRLEN + 1]; AbcdSzFromIpAddress(nboIpAddr, szIpAddress); if (0 == MultiByteToWideChar( CP_UTF8, 0, szIpAddress, -1, wszIpAddress, MAXIPSTRLEN + 1)) { wszIpAddress[0] = 0; } } /* Returns: ERROR_SUCCESS: Success (including not finding a.b.c.d) ERROR_NOT_ENOUGH_MEMORY: Failure Notes: Remove the a.b.c.d string wszIpAddress from the space-separated LocalAlloc'ed list *pwsz. *pwsz is LocalFree'ed and a new string LocalAlloc'ed and stored in *pwsz. */ DWORD RemoveWszIpAddress( IN WCHAR** pwsz, IN WCHAR* wszIpAddress ) { DWORD cwchIpAddress; DWORD cwchNew; WCHAR* wszFound; WCHAR* wszNew; DWORD nFoundOffset; if (NULL == *pwsz) { return(ERROR_SUCCESS); } cwchIpAddress = wcslen(wszIpAddress); wszFound = wcsstr(*pwsz, wszIpAddress); if (!wszFound) { return(ERROR_SUCCESS); } if (wszFound[cwchIpAddress] == L' ') { ++cwchIpAddress; } cwchNew = wcslen(*pwsz) - cwchIpAddress + 1; wszNew = LocalAlloc(LPTR, cwchNew * sizeof(WCHAR)); if (!wszNew) { TraceHlp("RemoveWszIpAddress: LocalAlloc returned NULL"); return(ERROR_NOT_ENOUGH_MEMORY); } nFoundOffset = (ULONG) (wszFound - *pwsz); wcsncpy(wszNew, *pwsz, nFoundOffset); wcscpy(wszNew + nFoundOffset, *pwsz + nFoundOffset + cwchIpAddress); LocalFree(*pwsz); *pwsz = wszNew; return(ERROR_SUCCESS); } /* Returns: Win32 error code Notes: Add the a.b.c.d string wszIpAddress to the front of the space-separated LocalAlloc'ed list *pwsz. *pwsz is LocalFree'ed and a new string LocalAlloc'ed and stored in *pwsz. */ DWORD PrependWszIpAddress( IN WCHAR** pwsz, IN WCHAR* wszIpAddress ) { DWORD cwchOld; DWORD cwchNew; WCHAR* wszNew; if (0 == IpAddressFromAbcdWsz(wszIpAddress)) { TraceHlp("PrependWszIpAddress: Not prepending %ws", wszIpAddress); return(ERROR_SUCCESS); } cwchOld = *pwsz ? wcslen(*pwsz) : 0; cwchNew = cwchOld + wcslen(wszIpAddress) + 6; wszNew = LocalAlloc(LPTR, cwchNew * sizeof(WCHAR)); if (!wszNew) { TraceHlp("PrependWszIpAddress: LocalAlloc returned NULL"); return(ERROR_NOT_ENOUGH_MEMORY); } wcscpy(wszNew, wszIpAddress); if (cwchOld) { wcscat(wszNew, L" "); wcscat(wszNew, *pwsz); } if(NULL != *pwsz) { LocalFree(*pwsz); } wcscat(wszNew, L"\0"); *pwsz = wszNew; return(ERROR_SUCCESS); } /* Returns: ERROR_SUCCESS: Success (including not finding a.b.c.d) ERROR_NOT_ENOUGH_MEMORY: Failure Notes: Remove the a.b.c.d string wszIpAddress from the LocalAlloc'ed MULTI_SZ *pmwsz. *pmwsz is LocalFree'ed and a new string LocalAlloc'ed and stored in *pmwsz. */ DWORD RemoveWszIpAddressFromMwsz( IN WCHAR** pmwsz, IN WCHAR* wszIpAddress ) { DWORD cwchIpAddress; DWORD cwchNew; WCHAR* wszFound; WCHAR* mwszNew; DWORD nFoundOffset; if (NULL == *pmwsz) { return(ERROR_SUCCESS); } cwchIpAddress = wcslen(wszIpAddress); for (wszFound = *pmwsz; wszFound[0] != 0; wszFound += wcslen(wszFound) + 1) { if (!wcscmp(wszFound, wszIpAddress)) { break; } } if (!wszFound[0]) { return(ERROR_SUCCESS); } if (wszFound[cwchIpAddress + 1] != 0) { ++cwchIpAddress; } cwchNew = MwszLength(*pmwsz) - cwchIpAddress; mwszNew = LocalAlloc(LPTR, cwchNew * sizeof(WCHAR)); if (!mwszNew) { TraceHlp("RemoveWszIpAddress: LocalAlloc returned NULL"); return(ERROR_NOT_ENOUGH_MEMORY); } nFoundOffset = (ULONG) (wszFound - *pmwsz); CopyMemory(mwszNew, *pmwsz, nFoundOffset * sizeof(WCHAR)); CopyMemory(mwszNew + nFoundOffset, *pmwsz + nFoundOffset + cwchIpAddress, (cwchNew - nFoundOffset) * sizeof(WCHAR)); LocalFree(*pmwsz); *pmwsz = mwszNew; return(ERROR_SUCCESS); } /* Returns: Win32 error code Notes: Add the a.b.c.d string wszIpAddress to the front of the LocalAlloc'ed MULTI_SZ *pmwsz. *pmwsz is LocalFree'ed and a new string LocalAlloc'ed and stored in *pmwsz. */ DWORD PrependWszIpAddressToMwsz( IN WCHAR** pmwsz, IN WCHAR* wszIpAddress ) { DWORD cwchIpAddress; DWORD cwchOld; DWORD cwchNew; WCHAR* mwszNew; cwchIpAddress = wcslen(wszIpAddress); cwchOld = *pmwsz ? MwszLength(*pmwsz) : 0; cwchNew = cwchOld + cwchIpAddress + 6; mwszNew = LocalAlloc(LPTR, cwchNew * sizeof(WCHAR)); if (!mwszNew) { TraceHlp("PrependWszIpAddress: LocalAlloc returned NULL"); return(ERROR_NOT_ENOUGH_MEMORY); } wcscpy(mwszNew, wszIpAddress); if (cwchOld) { CopyMemory(mwszNew + cwchIpAddress + 1, *pmwsz, cwchOld *sizeof(WCHAR)); LocalFree(*pmwsz); } *pmwsz = mwszNew; return(ERROR_SUCCESS); } /* Returns: Win32 error code Notes: Add the address nboIpAddr to the front of the space-separated LocalAlloc'ed list *pwsz. *pwsz is LocalFree'ed and a new string LocalAlloc'ed and stored in *pwsz. */ DWORD PrependDwIpAddress( IN WCHAR** pwsz, IN IPADDR nboIpAddr ) { WCHAR wszIpAddress[MAXIPSTRLEN + 1]; AbcdWszFromIpAddress(nboIpAddr, wszIpAddress); return(PrependWszIpAddress(pwsz, wszIpAddress)); } /* Returns: Win32 error code Notes: Add the address nboIpAddr to the front of the LocalAlloc'ed MULTI_SZ *pmwsz. *pmwsz is LocalFree'ed and a new string LocalAlloc'ed and stored in *pmwsz. */ DWORD PrependDwIpAddressToMwsz( IN WCHAR** pmwsz, IN IPADDR nboIpAddr ) { WCHAR wszIpAddress[MAXIPSTRLEN + 1]; AbcdWszFromIpAddress(nboIpAddr, wszIpAddress); return(PrependWszIpAddressToMwsz(pmwsz, wszIpAddress)); } /* Returns: BOOL Description: Returns TRUE if there is any non zero value in pTcpipInfo. It also zeroes the value. */ BOOL FJunkExists( TCPIP_INFO* pTcpipInfo ) { BOOL fRet = FALSE; if ( 0 != pTcpipInfo->wszIPAddress[0] && wcscmp(pTcpipInfo->wszIPAddress, WCH_ZEROADDRESS)) { fRet = TRUE; pTcpipInfo->fChanged = TRUE; pTcpipInfo->wszIPAddress[0] = 0; } if ( 0 != pTcpipInfo->wszSubnetMask[0] && wcscmp(pTcpipInfo->wszSubnetMask, WCH_ZEROADDRESS)) { fRet = TRUE; pTcpipInfo->fChanged = TRUE; pTcpipInfo->wszSubnetMask[0] = 0; } if ( NULL != pTcpipInfo->wszDNSNameServers && 0 != pTcpipInfo->wszDNSNameServers[0]) { fRet = TRUE; LocalFree(pTcpipInfo->wszDNSNameServers); pTcpipInfo->wszDNSNameServers = NULL; } if ( NULL != pTcpipInfo->mwszNetBIOSNameServers && 0 != pTcpipInfo->mwszNetBIOSNameServers[0] && 0 != pTcpipInfo->mwszNetBIOSNameServers[1]) { fRet = TRUE; LocalFree(pTcpipInfo->mwszNetBIOSNameServers); pTcpipInfo->mwszNetBIOSNameServers = NULL; } if ( NULL != pTcpipInfo->wszDNSDomainName && 0 != pTcpipInfo->wszDNSDomainName[0]) { fRet = TRUE; LocalFree(pTcpipInfo->wszDNSDomainName); pTcpipInfo->wszDNSDomainName = NULL; } return(fRet); } /* Returns: VOID Description: Clears up the stale information left in the regsitry when we AV or the machine BS's. */ VOID ClearTcpipInfo( VOID ) { LONG lRet; DWORD dwErr; HKEY hKeyNdisWanIp = NULL; WCHAR* mwszAdapters = NULL; WCHAR* mwszTemp; WCHAR* wszAdapterName; TCPIP_INFO* pTcpipInfo = NULL; DWORD dwPrefixLen = wcslen(WCH_TCPIP_PARAM_INT_W); DWORD dwStrLen; lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGKEY_TCPIP_NDISWANIP_W, 0, KEY_READ, &hKeyNdisWanIp); if (ERROR_SUCCESS != lRet) { goto LDone; } dwErr = RegQueryValueWithAllocW(hKeyNdisWanIp, REGVAL_IPCONFIG_W, REG_MULTI_SZ, (BYTE**)&mwszAdapters); if (NO_ERROR != dwErr) { goto LDone; } mwszTemp = mwszAdapters; while (mwszTemp[0] != 0) { pTcpipInfo = NULL; dwStrLen = wcslen(mwszTemp); if (dwPrefixLen >= dwStrLen) { goto LWhileEnd; } wszAdapterName = mwszTemp + dwPrefixLen; RTASSERT('{' == wszAdapterName[0]); dwErr = LoadTcpipInfo(&pTcpipInfo, wszAdapterName, FALSE); if (NO_ERROR != dwErr) { goto LWhileEnd; } if (!FJunkExists(pTcpipInfo)) { goto LWhileEnd; } dwErr = SaveTcpipInfo(pTcpipInfo); if (NO_ERROR != dwErr) { goto LWhileEnd; } TraceHlp("Clearing Tcpip info for adapter %ws", wszAdapterName); dwErr = PDhcpNotifyConfigChange(NULL, wszAdapterName, TRUE, 0, 0, 0, IgnoreFlag); LWhileEnd: if (NULL != pTcpipInfo) { FreeTcpipInfo(&pTcpipInfo); } mwszTemp = mwszTemp + dwStrLen + 1; } LDone: if (NULL != hKeyNdisWanIp) { RegCloseKey(hKeyNdisWanIp); } LocalFree(mwszAdapters); } /* Returns: Win32 error code Description: Frees the TCPIP_INFO buffer. */ DWORD FreeTcpipInfo( IN TCPIP_INFO** ppTcpipInfo ) { if (NULL == *ppTcpipInfo) { return(NO_ERROR); } TraceHlp("Freeing Tcpip info for adapter %ws", (*ppTcpipInfo)->wszAdapterName); LocalFree((*ppTcpipInfo)->wszAdapterName); LocalFree((*ppTcpipInfo)->mwszNetBIOSNameServers); LocalFree((*ppTcpipInfo)->wszDNSDomainName); LocalFree((*ppTcpipInfo)->wszDNSNameServers); LocalFree(*ppTcpipInfo); *ppTcpipInfo = NULL; return(NO_ERROR); } /* Returns: Win32 error code Description: Reads NETBT information for the adapter pTcpipInfo->wszAdapterName from the registry. */ DWORD LoadWinsParam( IN HKEY hKeyWinsParam, IN TCPIP_INFO* pTcpipInfo ) { HKEY hKeyInterfaces = NULL; HKEY hKeyInterfaceParam = NULL; WCHAR* wszNetBtBindPath = NULL; DWORD dwStrLenTcpip_; DWORD dwStrLenTcpipBindPath; DWORD dwErr = ERROR_SUCCESS; RTASSERT(NULL != pTcpipInfo); RTASSERT(NULL != pTcpipInfo->wszAdapterName); RTASSERT(NULL == pTcpipInfo->mwszNetBIOSNameServers); dwErr = RegOpenKeyExW(hKeyWinsParam, REGKEY_INTERFACES_W, 0, KEY_READ, &hKeyInterfaces); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", REGKEY_INTERFACES_W, dwErr); goto LDone; } dwStrLenTcpip_ = wcslen(WCH_TCPIP_); dwStrLenTcpipBindPath = wcslen(pTcpipInfo->wszAdapterName); wszNetBtBindPath = LocalAlloc( LPTR, (dwStrLenTcpip_ + dwStrLenTcpipBindPath + 1) * sizeof(WCHAR)); if (NULL == wszNetBtBindPath) { dwErr = GetLastError(); TraceHlp("LocalAlloc failed and returned %d", dwErr); goto LDone; } wcscpy(wszNetBtBindPath, WCH_TCPIP_); wcscat(wszNetBtBindPath, pTcpipInfo->wszAdapterName); dwErr = RegOpenKeyExW(hKeyInterfaces, wszNetBtBindPath, 0, KEY_READ, &hKeyInterfaceParam); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", wszNetBtBindPath, dwErr); goto LDone; } // Its OK if we cannot find the value. Ignore the error. RegQueryValueWithAllocW(hKeyInterfaceParam, REGVAL_NAMESERVERLIST_W, REG_MULTI_SZ, (BYTE**)&(pTcpipInfo->mwszNetBIOSNameServers)); LDone: LocalFree(wszNetBtBindPath); if (NULL != hKeyInterfaces) { RegCloseKey(hKeyInterfaces); } if (NULL != hKeyInterfaceParam) { RegCloseKey(hKeyInterfaceParam); } if (NO_ERROR != dwErr) { LocalFree(pTcpipInfo->mwszNetBIOSNameServers); pTcpipInfo->mwszNetBIOSNameServers = NULL; } return(dwErr); } /* Returns: Win32 error code Description: Reads TCPIP information for the adapter pTcpipInfo->wszAdapterName from the registry. */ DWORD LoadTcpipParam( IN HKEY hKeyTcpipParam, IN TCPIP_INFO* pTcpipInfo ) { HKEY hKeyInterfaces = NULL; HKEY hKeyInterfaceParam = NULL; DWORD dwType; DWORD dwSize; DWORD dwErr = ERROR_SUCCESS; RTASSERT(NULL != pTcpipInfo); RTASSERT(NULL != pTcpipInfo->wszAdapterName); _wcslwr(pTcpipInfo->wszAdapterName); RTASSERT(0 == pTcpipInfo->wszIPAddress[0]); RTASSERT(0 == pTcpipInfo->wszSubnetMask[0]); RTASSERT(NULL == pTcpipInfo->wszDNSDomainName); RTASSERT(NULL == pTcpipInfo->wszDNSNameServers); dwErr = RegOpenKeyExW(hKeyTcpipParam, REGKEY_INTERFACES_W, 0, KEY_READ, &hKeyInterfaces); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", REGKEY_INTERFACES_W, dwErr); goto LDone; } // Open subkey for this adapter under "Interfaces" dwErr = RegOpenKeyExW(hKeyInterfaces, pTcpipInfo->wszAdapterName, 0, KEY_READ, &hKeyInterfaceParam); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", pTcpipInfo->wszAdapterName, dwErr); goto LDone; } dwSize = sizeof(pTcpipInfo->wszIPAddress); // Its OK if we cannot find the value. Ignore the error. dwErr = RegQueryValueExW(hKeyInterfaceParam, REGVAL_DHCPIPADDRESS_W, NULL, &dwType, (BYTE*)pTcpipInfo->wszIPAddress, &dwSize); if (ERROR_SUCCESS != dwErr || REG_SZ != dwType) { dwErr = ERROR_SUCCESS; RTASSERT(0 == pTcpipInfo->wszIPAddress[0]); pTcpipInfo->wszIPAddress[0] = 0; } dwSize = sizeof(pTcpipInfo->wszSubnetMask); // Its OK if we cannot find the value. Ignore the error. dwErr = RegQueryValueExW(hKeyInterfaceParam, REGVAL_DHCPSUBNETMASK_W, NULL, &dwType, (BYTE*)pTcpipInfo->wszSubnetMask, &dwSize); if (ERROR_SUCCESS != dwErr || REG_SZ != dwType) { dwErr = ERROR_SUCCESS; RTASSERT(0 == pTcpipInfo->wszSubnetMask[0]); pTcpipInfo->wszSubnetMask[0] = 0; // No point in having a valid IP address with an invalid mask. pTcpipInfo->wszIPAddress[0] = 0; } // Its OK if we cannot find the value. Ignore the error. RegQueryValueWithAllocW(hKeyInterfaceParam, REGVAL_DOMAIN_W, REG_SZ, (BYTE**)&(pTcpipInfo->wszDNSDomainName)); // Its OK if we cannot find the value. Ignore the error. RegQueryValueWithAllocW(hKeyInterfaceParam, REGVAL_NAMESERVER_W, REG_SZ, (BYTE**)&(pTcpipInfo->wszDNSNameServers)); LDone: if (NULL != hKeyInterfaces) { RegCloseKey(hKeyInterfaces); } if (NULL != hKeyInterfaceParam) { RegCloseKey(hKeyInterfaceParam); } if (ERROR_SUCCESS != dwErr) { LocalFree(pTcpipInfo->wszDNSDomainName); pTcpipInfo->wszDNSDomainName = NULL; LocalFree(pTcpipInfo->wszDNSNameServers); pTcpipInfo->wszDNSNameServers = NULL; } return(dwErr); } /* Returns: Win32 error code Description: If fAdapterOnly is FALSE, reads NETBT and TCPIP information for the adapter wszAdapterName from the registry. *ppTcpipInfo must ultimately be freed by calling FreeTcpipInfo(). */ DWORD LoadTcpipInfo( IN TCPIP_INFO** ppTcpipInfo, IN WCHAR* wszAdapterName, IN BOOL fAdapterOnly ) { HKEY hKeyTcpipParam = NULL; HKEY hKeyWinsParam = NULL; DWORD dwErr = ERROR_SUCCESS; RTASSERT(NULL != wszAdapterName); if (NULL == wszAdapterName) { dwErr = E_FAIL; TraceHlp("wszAdapterName is NULL"); goto LDone; } *ppTcpipInfo = NULL; *ppTcpipInfo = LocalAlloc(LPTR, sizeof(TCPIP_INFO)); if (NULL == *ppTcpipInfo) { dwErr = GetLastError(); TraceHlp("LocalAlloc failed and returned %d", dwErr); goto LDone; } (*ppTcpipInfo)->wszAdapterName = LocalAlloc( LPTR, (wcslen(wszAdapterName) + 1) * sizeof(WCHAR)); if (NULL == (*ppTcpipInfo)->wszAdapterName) { dwErr = GetLastError(); TraceHlp("LocalAlloc failed and returned %d", dwErr); goto LDone; } wcscpy((*ppTcpipInfo)->wszAdapterName, wszAdapterName); if (fAdapterOnly) { goto LDone; } dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGKEY_TCPIP_PARAM_W, 0, KEY_READ, &hKeyTcpipParam); if (ERROR_SUCCESS != dwErr) { if (ERROR_FILE_NOT_FOUND == dwErr) { // Mask the error dwErr = ERROR_SUCCESS; } else { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", REGKEY_TCPIP_PARAM_W, dwErr); goto LDone; } } else { dwErr = LoadTcpipParam(hKeyTcpipParam, *ppTcpipInfo); if (ERROR_SUCCESS != dwErr) { goto LDone; } } // Open NETBT's parameters key dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGKEY_NETBT_PARAM_W, 0, KEY_READ, &hKeyWinsParam); if (ERROR_SUCCESS != dwErr) { if (ERROR_FILE_NOT_FOUND == dwErr) { // Mask the error dwErr = ERROR_SUCCESS; } else { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", REGKEY_NETBT_PARAM_W, dwErr); goto LDone; } } else { dwErr = LoadWinsParam(hKeyWinsParam, *ppTcpipInfo); if (ERROR_SUCCESS != dwErr) { goto LDone; } } LDone: if (NULL != hKeyTcpipParam) { RegCloseKey(hKeyTcpipParam); } if (NULL != hKeyWinsParam) { RegCloseKey(hKeyWinsParam); } if (ERROR_SUCCESS != dwErr) { FreeTcpipInfo(ppTcpipInfo); } return(dwErr); } /* Returns: Win32 error code Description: Saves NETBT information for the adapter pTcpipInfo->wszAdapterName to the registry. */ DWORD SaveWinsParam( IN HKEY hKeyWinsParam, IN TCPIP_INFO* pTcpipInfo ) { HKEY hKeyInterfaces = NULL; HKEY hKeyInterfaceParam = NULL; WCHAR* wszNetBtBindPath = NULL; DWORD dwStrLenTcpip_; DWORD dwStrLenAdapterName; WCHAR* mwszData = NULL; WCHAR mwszBlank[2]; DWORD dw; DWORD dwErr = ERROR_SUCCESS; RTASSERT(NULL != pTcpipInfo); RTASSERT(NULL != pTcpipInfo->wszAdapterName); dwErr = RegOpenKeyExW(hKeyWinsParam, REGKEY_INTERFACES_W, 0, KEY_WRITE, &hKeyInterfaces); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", REGKEY_INTERFACES_W, dwErr); goto LDone; } dwStrLenTcpip_ = wcslen(WCH_TCPIP_); dwStrLenAdapterName = wcslen(pTcpipInfo->wszAdapterName); wszNetBtBindPath = LocalAlloc( LPTR, (dwStrLenTcpip_ + dwStrLenAdapterName + 1) * sizeof(WCHAR)); if (NULL == wszNetBtBindPath) { dwErr = GetLastError(); TraceHlp("LocalAlloc failed and returned %d", dwErr); goto LDone; } wcscpy(wszNetBtBindPath, WCH_TCPIP_); wcscat(wszNetBtBindPath, pTcpipInfo->wszAdapterName); dwErr = RegOpenKeyExW(hKeyInterfaces, wszNetBtBindPath, 0, KEY_WRITE, &hKeyInterfaceParam); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", wszNetBtBindPath, dwErr); goto LDone; } if (pTcpipInfo->fDisableNetBIOSoverTcpip) { dw = REGVAL_DISABLE_NETBT; dwErr = RegSetValueExW(hKeyInterfaceParam, REGVAL_NETBIOSOPTIONS_W, 0, REG_DWORD, (BYTE*)&dw, sizeof(DWORD)); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegSetValueEx(%ws) failed: %d", REGVAL_NETBIOSOPTIONS_W, dwErr); dwErr = NO_ERROR; // Ignore this error } } else { dwErr = RegDeleteValueW(hKeyInterfaceParam, REGVAL_NETBIOSOPTIONS_W); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegDeleteValue(%ws) failed: %d", REGVAL_NETBIOSOPTIONS_W, dwErr); dwErr = NO_ERROR; // Ignore this error } } if (NULL == pTcpipInfo->mwszNetBIOSNameServers) { ZeroMemory(mwszBlank, sizeof(mwszBlank)); mwszData = mwszBlank; } else { mwszData = pTcpipInfo->mwszNetBIOSNameServers; } dwErr = RegSetValueExW(hKeyInterfaceParam, REGVAL_NAMESERVERLIST_W, 0, REG_MULTI_SZ, (BYTE*)mwszData, sizeof(WCHAR) * MwszLength(mwszData)); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegSetValueEx(%ws) failed and returned %d", REGVAL_NAMESERVERLIST_W, dwErr); goto LDone; } LDone: LocalFree(wszNetBtBindPath); if (NULL != hKeyInterfaceParam) { RegCloseKey(hKeyInterfaceParam); } if (NULL != hKeyInterfaces) { RegCloseKey(hKeyInterfaces); } return(dwErr); } /* Returns: Win32 error code Description: Saves TCPIP information for the adapter pTcpipInfo->wszAdapterName to the registry. */ DWORD SaveTcpipParam( IN HKEY hKeyTcpipParam, IN TCPIP_INFO* pTcpipInfo ) { HKEY hKeyInterfaces = NULL; HKEY hKeyInterfaceParam = NULL; DWORD dwLength; WCHAR mwszZeroAddress[MAXIPSTRLEN + 1]; WCHAR* wszData = NULL; WCHAR wszBlank[2]; DWORD dwErr = ERROR_SUCCESS; RTASSERT(NULL != pTcpipInfo); RTASSERT(NULL != pTcpipInfo->wszAdapterName); _wcslwr(pTcpipInfo->wszAdapterName); dwErr = RegOpenKeyExW(hKeyTcpipParam, REGKEY_INTERFACES_W, 0, KEY_WRITE, &hKeyInterfaces); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", REGKEY_INTERFACES_W, dwErr); goto LDone; } // Open subkey for this adapter under "Interfaces" dwErr = RegOpenKeyExW(hKeyInterfaces, pTcpipInfo->wszAdapterName, 0, KEY_WRITE, &hKeyInterfaceParam); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", pTcpipInfo->wszAdapterName, dwErr); goto LDone; } // If fChanged is set if (pTcpipInfo->fChanged == TRUE) { if ( 0 == pTcpipInfo->wszIPAddress[0] || 0 == pTcpipInfo->wszSubnetMask[0]) { RTASSERT(wcslen(WCH_ZEROADDRESS) <= MAXIPSTRLEN); wcscpy(pTcpipInfo->wszIPAddress, WCH_ZEROADDRESS); wcscpy(pTcpipInfo->wszSubnetMask, WCH_ZEROADDRESS); } dwErr = RegSetValueExW(hKeyInterfaceParam, REGVAL_DHCPIPADDRESS_W, 0, REG_SZ, (BYTE*)pTcpipInfo->wszIPAddress, sizeof(WCHAR) * wcslen(pTcpipInfo->wszIPAddress)); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegSetValueEx(%ws) failed and returned %d", REGVAL_DHCPIPADDRESS_W, dwErr); goto LDone; } dwErr = RegSetValueExW(hKeyInterfaceParam, REGVAL_DHCPSUBNETMASK_W, 0, REG_SZ, (BYTE*)pTcpipInfo->wszSubnetMask, sizeof(WCHAR) * wcslen(pTcpipInfo->wszSubnetMask)); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegSetValueEx(%ws) failed and returned %d", REGVAL_DHCPSUBNETMASK_W, dwErr); goto LDone; } } // if fChanged = TRUE ZeroMemory(wszBlank, sizeof(wszBlank)); if (NULL == pTcpipInfo->wszDNSDomainName) { wszData = wszBlank; } else { wszData = pTcpipInfo->wszDNSDomainName; } dwErr = RegSetValueExW(hKeyInterfaceParam, REGVAL_DOMAIN_W, 0, REG_SZ, (BYTE*)wszData, sizeof(WCHAR) * (wcslen(wszData) + 1)); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegSetValueEx(%ws) failed and returned %d", REGVAL_DOMAIN_W, dwErr); goto LDone; } if (NULL == pTcpipInfo->wszDNSNameServers) { wszData = wszBlank; } else { wszData = pTcpipInfo->wszDNSNameServers; } // Check whether the value starts with a space. // If so, delete the key. Otherwise save the value. if (WCH_SPACE != wszData[0]) { dwErr = RegSetValueExW(hKeyInterfaceParam, REGVAL_NAMESERVER_W, 0, REG_SZ, (BYTE*)wszData, sizeof(WCHAR) * (wcslen(wszData) + 1)); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegSetValueEx(%ws) failed and returned %d", REGVAL_NAMESERVER_W, dwErr); goto LDone; } } else { dwErr = RegDeleteValueW(hKeyInterfaceParam, REGVAL_NAMESERVER_W); if (ERROR_SUCCESS != dwErr) { TraceHlp("RegDeleteValue(%ws) failed and returned %d", REGVAL_NAMESERVER_W, dwErr); goto LDone; } } LDone: if (NULL != hKeyInterfaceParam) { RegCloseKey(hKeyInterfaceParam); } if (NULL != hKeyInterfaces) { RegCloseKey(hKeyInterfaces); } return(dwErr); } /* Returns: Win32 error code Description: Saves NETBT and TCPIP information for the adapter pTcpipInfo->wszAdapterName to the registry. */ DWORD SaveTcpipInfo( IN TCPIP_INFO* pTcpipInfo ) { HKEY hKeyTcpipParam = NULL; HKEY hKeyWinsParam = NULL; DWORD dwErr = ERROR_SUCCESS; RTASSERT(NULL != pTcpipInfo); if ( (NULL == pTcpipInfo) || (NULL == pTcpipInfo->wszAdapterName)) { dwErr = E_FAIL; TraceHlp("pTcpipInfo or wszAdapterName is NULL"); goto LDone; } dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGKEY_TCPIP_PARAM_W, 0, KEY_WRITE, &hKeyTcpipParam); if (ERROR_SUCCESS != dwErr) { if (ERROR_FILE_NOT_FOUND == dwErr) { // Mask the error dwErr = ERROR_SUCCESS; } else { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", REGKEY_TCPIP_PARAM_W, dwErr); goto LDone; } } else { dwErr = SaveTcpipParam(hKeyTcpipParam, pTcpipInfo); if (ERROR_SUCCESS != dwErr) { goto LDone; } } // Open NETBT's parameters key dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGKEY_NETBT_PARAM_W, 0, KEY_WRITE, &hKeyWinsParam); if (ERROR_SUCCESS != dwErr) { if (ERROR_FILE_NOT_FOUND == dwErr) { // Mask the error dwErr = ERROR_SUCCESS; } else { TraceHlp("RegOpenKeyEx(%ws) failed and returned %d", REGKEY_NETBT_PARAM_W, dwErr); goto LDone; } } else { dwErr = SaveWinsParam(hKeyWinsParam, pTcpipInfo); if (ERROR_SUCCESS != dwErr) { goto LDone; } } LDone: if (NULL != hKeyTcpipParam) { RegCloseKey(hKeyTcpipParam); } if (NULL != hKeyWinsParam) { RegCloseKey(hKeyWinsParam); } return(dwErr); } /* Returns: Win32 error code Notes: */ DWORD GetAdapterInfo( IN DWORD dwIndex, OUT IPADDR* pnboIpAddress, OUT IPADDR* pnboDNS1, OUT IPADDR* pnboDNS2, OUT IPADDR* pnboWINS1, OUT IPADDR* pnboWINS2, OUT IPADDR* pnboGateway, OUT BYTE* pbAddress ) { IP_ADAPTER_INFO* pAdapterInfo = NULL; IP_ADAPTER_INFO* pAdapter; IP_PER_ADAPTER_INFO* pPerAdapterInfo = NULL; DWORD dwSize; DWORD dw; IPADDR nboIpAddress = 0; IPADDR nboDNS1 = 0; IPADDR nboDNS2 = 0; IPADDR nboWINS1 = 0; IPADDR nboWINS2 = 0; IPADDR nboGateway = 0; BYTE bAddress[MAX_ADAPTER_ADDRESS_LENGTH]; DWORD dwErr = NO_ERROR; TraceHlp("GetAdapterInfo"); dwSize = 0; dwErr = PGetAdaptersInfo(NULL, &dwSize); if (ERROR_BUFFER_OVERFLOW != dwErr && NO_ERROR != dwErr ) { TraceHlp("GetAdaptersInfo failed and returned %d", dwErr); goto LDone; } pAdapterInfo = LocalAlloc(LPTR, dwSize); if (NULL == pAdapterInfo) { dwErr = GetLastError(); TraceHlp("LocalAlloc failed and returned %d", dwErr); goto LDone; } dwErr = PGetAdaptersInfo(pAdapterInfo, &dwSize); if (NO_ERROR != dwErr) { TraceHlp("GetAdaptersInfo failed and returned %d", dwErr); goto LDone; } pAdapter = pAdapterInfo; while (pAdapter) { if (pAdapter->Index != dwIndex) { pAdapter = pAdapter->Next; continue; } break; } if (NULL == pAdapter) { TraceHlp("Couldn't get info for the adapter"); dwErr = ERROR_NOT_FOUND; goto LDone; } nboIpAddress = inet_addr(pAdapter->IpAddressList.IpAddress.String); nboGateway = inet_addr(pAdapter->GatewayList.IpAddress.String); if (pAdapter->HaveWins) { nboWINS1 = inet_addr(pAdapter->PrimaryWinsServer.IpAddress.String); nboWINS2 = inet_addr(pAdapter->SecondaryWinsServer.IpAddress.String); } // // Check to see if the address is a loopback address and replace it // with adapter's ip address if it is - bug. 377807 in .net server // database. // if(nboWINS1 == RAS_LOOPBACK_ADDRESS) { TraceHlp("GetAdapterInfo: replacing WINS1 with" " 0x%x since its loopback", nboIpAddress); nboWINS1 = nboIpAddress; } if(nboWINS2 == RAS_LOOPBACK_ADDRESS) { TraceHlp("GetAdapterInfo: replacing WINS2 with" " 0x%x since its loopback", nboIpAddress); nboWINS2 = nboIpAddress; } for (dw = 0; dw < pAdapter->AddressLength && dw < MAX_ADAPTER_ADDRESS_LENGTH; dw++) { bAddress[dw] = pAdapter->Address[dw]; } dwSize = 0; dwErr = PGetPerAdapterInfo(dwIndex, NULL, &dwSize); if (ERROR_BUFFER_OVERFLOW != dwErr) { TraceHlp("GetPerAdapterInfo failed and returned %d", dwErr); goto LDone; } pPerAdapterInfo = LocalAlloc(LPTR, dwSize); if (NULL == pPerAdapterInfo) { dwErr = GetLastError(); TraceHlp("LocalAlloc failed and returned %d", dwErr); goto LDone; } dwErr = PGetPerAdapterInfo(dwIndex, pPerAdapterInfo, &dwSize); if (NO_ERROR != dwErr) { TraceHlp("GetPerAdapterInfo failed and returned %d", dwErr); goto LDone; } if (NULL == pPerAdapterInfo) { TraceHlp("Couldn't get per adapter info for the adapter"); dwErr = ERROR_NOT_FOUND; goto LDone; } nboDNS1 = inet_addr(pPerAdapterInfo->DnsServerList.IpAddress.String); // // Check to see if the address is a loopback address and replace it // with adapter's ip address if it is - bug. 377807 in .net server // database. // if(nboDNS1 == RAS_LOOPBACK_ADDRESS) { TraceHlp("GetAdapterInfo: replacing DNS1 with" " 0x%x since its loopback", nboIpAddress); nboDNS1 = nboIpAddress; } if (NULL != pPerAdapterInfo->DnsServerList.Next) { nboDNS2 = inet_addr(pPerAdapterInfo->DnsServerList.Next->IpAddress.String); // // If this is the loop back address, replace the address with // the adapters ip address. // if(nboDNS2 == RAS_LOOPBACK_ADDRESS) { TraceHlp("GetAdapterInfo: replacing DNS2 with" " 0x%x since its loopback", nboIpAddress); nboDNS2 = nboIpAddress; } } if ( (0 == nboIpAddress) || (INADDR_NONE == nboIpAddress)) { TraceHlp("Couldn't get IpAddress for the adapter"); dwErr = ERROR_NOT_FOUND; goto LDone; } if(INADDR_NONE == nboGateway) { nboGateway = 0; } if (INADDR_NONE == nboDNS1) { nboDNS1 = 0; } if (INADDR_NONE == nboDNS2) { nboDNS2 = 0; } if (INADDR_NONE == nboWINS1) { nboWINS1 = 0; } if (INADDR_NONE == nboWINS2) { nboWINS2 = 0; } LDone: if (NO_ERROR != dwErr) { nboIpAddress = nboGateway = nboDNS1 = nboDNS2 = nboWINS1 = nboWINS2 = 0; ZeroMemory(bAddress, MAX_ADAPTER_ADDRESS_LENGTH); } if (pnboIpAddress) { *pnboIpAddress = nboIpAddress; } if (pnboDNS1) { *pnboDNS1 = nboDNS1; } if (pnboDNS2) { *pnboDNS2 = nboDNS2; } if (pnboWINS1) { *pnboWINS1 = nboWINS1; } if (pnboWINS2) { *pnboWINS2 = nboWINS2; } if (pbAddress) { CopyMemory(pbAddress, bAddress, MAX_ADAPTER_ADDRESS_LENGTH); } if(pnboGateway) { *pnboGateway = nboGateway; } LocalFree(pAdapterInfo); LocalFree(pPerAdapterInfo); return(dwErr); } /* Returns: Win32 error code Description: Don't cache these values because DHCP leases may have expired, etc */ DWORD GetPreferredAdapterInfo( OUT IPADDR* pnboIpAddress, OUT IPADDR* pnboDNS1, OUT IPADDR* pnboDNS2, OUT IPADDR* pnboWINS1, OUT IPADDR* pnboWINS2, OUT BYTE* pbAddress ) { HANDLE hHeap = NULL; IP_INTERFACE_NAME_INFO* pTable = NULL; DWORD dw; DWORD dwCount; DWORD dwIndex = (DWORD)-1; DWORD dwErr = NO_ERROR; TraceHlp("GetPreferredAdapterInfo"); hHeap = GetProcessHeap(); if (NULL == hHeap) { dwErr = GetLastError(); TraceHlp("GetProcessHeap failed and returned %d", dwErr); goto LDone; } dwErr = PNhpAllocateAndGetInterfaceInfoFromStack(&pTable, &dwCount, FALSE /* bOrder */, hHeap, LPTR); if (NO_ERROR != dwErr) { TraceHlp("NhpAllocateAndGetInterfaceInfoFromStack failed and " "returned %d", dwErr); goto LDone; } for (dw = 0; dw < dwCount; dw++) { // Only interested in NICs if (IF_CONNECTION_DEDICATED != pTable[dw].ConnectionType) { continue; } // If the admin wants to use a particular NIC if ( HelperRegVal.fNICChosen && (!IsEqualGUID(&(HelperRegVal.guidChosenNIC), &(pTable[dw].DeviceGuid)))) { continue; } dwIndex = pTable[dw].Index; break; } if ((DWORD)-1 == dwIndex) { if (HelperRegVal.fNICChosen) { // The chosen NIC is not available. Let us choose another one. for (dw = 0; dw < dwCount; dw++) { // Only interested in NICs if (IF_CONNECTION_DEDICATED != pTable[dw].ConnectionType) { continue; } dwIndex = pTable[dw].Index; break; } } if ((DWORD)-1 == dwIndex) { TraceHlp("Couldn't find an appropriate NIC"); dwErr = ERROR_NOT_FOUND; goto LDone; } HelperRegVal.fNICChosen = FALSE; TraceHlp("The network adapter chosen by the administrator is not " "available. Some other adapter will be used."); } dwErr = GetAdapterInfo( dwIndex, pnboIpAddress, pnboDNS1, pnboDNS2, pnboWINS1, pnboWINS2, NULL, pbAddress); LDone: if (NULL != pTable) { HeapFree(hHeap, 0, pTable); } return(dwErr); }