Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

581 lines
10 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1999 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. compinfo.cpp
  7. Computer info class plus helper functions
  8. FILE HISTORY:
  9. */
  10. #include <stdafx.h>
  11. #include <winsock.h>
  12. #include "compinfo.h"
  13. #define STRING_MAX 256
  14. //
  15. //
  16. //
  17. BOOL
  18. CIpInfoArray::FIsInList(DWORD dwIp)
  19. {
  20. BOOL fFound = FALSE;
  21. for (int i = 0; i < GetSize(); i++)
  22. {
  23. if (GetAt(i).dwIp == dwIp)
  24. {
  25. fFound = TRUE;
  26. break;
  27. }
  28. }
  29. return fFound;
  30. }
  31. //
  32. //
  33. //
  34. CComputerInfo::CComputerInfo(LPCTSTR pszNameOrIp)
  35. {
  36. m_strNameOrIp = pszNameOrIp;
  37. m_nIndex = -1;
  38. }
  39. CComputerInfo::~CComputerInfo()
  40. {
  41. }
  42. HRESULT
  43. CComputerInfo::GetIp(DWORD * pdwIp, int nIndex)
  44. {
  45. HRESULT hr = hrOK;
  46. if (m_nIndex == -1)
  47. {
  48. hr = InitializeData();
  49. }
  50. if (SUCCEEDED(hr))
  51. {
  52. if (pdwIp)
  53. *pdwIp = m_arrayIps[nIndex].dwIp;
  54. }
  55. else
  56. {
  57. if (pdwIp)
  58. *pdwIp = 0xFFFFFFFF;
  59. }
  60. return hr;
  61. }
  62. HRESULT
  63. CComputerInfo::GetIpStr(CString & strIp, int nIndex)
  64. {
  65. HRESULT hr = hrOK;
  66. if (m_nIndex == -1)
  67. {
  68. hr = InitializeData();
  69. }
  70. if (SUCCEEDED(hr))
  71. {
  72. struct in_addr ipaddr ;
  73. //
  74. // Convert the unsigned long to network byte order
  75. //
  76. ipaddr.s_addr = ::htonl( (u_long) m_arrayIps[nIndex].dwIp ) ;
  77. CHAR * pszAddr = inet_ntoa( ipaddr ) ;
  78. ::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszAddr, -1, strIp.GetBuffer(IP_ADDDRESS_LENGTH_MAX), IP_ADDDRESS_LENGTH_MAX);
  79. strIp.ReleaseBuffer();
  80. }
  81. else
  82. {
  83. strIp.Empty();
  84. }
  85. return hr;
  86. }
  87. HRESULT
  88. CComputerInfo::GetHostName(CString & strHostName)
  89. {
  90. HRESULT hr = hrOK;
  91. if (m_nIndex == -1)
  92. {
  93. hr = InitializeData();
  94. }
  95. if (SUCCEEDED(hr))
  96. {
  97. strHostName = m_strHostname;
  98. }
  99. else
  100. {
  101. strHostName.Empty();
  102. }
  103. return hr;
  104. }
  105. HRESULT
  106. CComputerInfo::GetFqdn(CString & strFqdn, int nIndex)
  107. {
  108. HRESULT hr = hrOK;
  109. if (m_nIndex == -1)
  110. {
  111. hr = InitializeData();
  112. }
  113. if (SUCCEEDED(hr))
  114. {
  115. strFqdn = m_arrayIps[nIndex].strFqdn;
  116. }
  117. else
  118. {
  119. strFqdn.Empty();
  120. }
  121. return hr;
  122. }
  123. int
  124. CComputerInfo::GetCount()
  125. {
  126. return m_nIndex;
  127. }
  128. //
  129. // Call this function to reset the internal data so that on the next query
  130. // we will rebuild our data.
  131. //
  132. void
  133. CComputerInfo::Reset()
  134. {
  135. // set this to -1 so that we will get the data again on the next call
  136. m_nIndex = -1;
  137. m_arrayIps.RemoveAll();
  138. m_strHostname.Empty();
  139. }
  140. HRESULT
  141. CComputerInfo::GetDomain(CString & strDomain)
  142. {
  143. // not supported right now
  144. strDomain.Empty();
  145. return E_NOTIMPL;
  146. }
  147. HRESULT
  148. CComputerInfo::IsLocalMachine(BOOL * pfIsLocal)
  149. {
  150. HRESULT hr = hrOK;
  151. if (m_nIndex == -1)
  152. {
  153. hr = InitializeData();
  154. }
  155. if (pfIsLocal)
  156. {
  157. if (SUCCEEDED(hr))
  158. {
  159. CString strLocal;
  160. DWORD dwSize = STRING_MAX;
  161. BOOL fSuccess = GetComputerName(strLocal.GetBuffer(dwSize), &dwSize);
  162. strLocal.ReleaseBuffer();
  163. if (fSuccess)
  164. {
  165. *pfIsLocal = (strLocal.CompareNoCase(m_strHostname) == 0) ? TRUE : FALSE;
  166. }
  167. }
  168. else
  169. {
  170. *pfIsLocal = FALSE;
  171. }
  172. }
  173. return hr;
  174. }
  175. COMPUTER_INFO_TYPE
  176. CComputerInfo::GetInputType()
  177. {
  178. // assume a NetBios name
  179. COMPUTER_INFO_TYPE enResult = COMPUTER_INFO_TYPE_NB ;
  180. const TCHAR chDash = '-';
  181. const TCHAR chDot = '.' ;
  182. const TCHAR chSlash = '\\' ;
  183. CString strName( m_strNameOrIp ) ;
  184. int cch = strName.GetLength() ;
  185. // Does the name begin with two slashes??
  186. if ( cch > 2
  187. && strName.GetAt(0) == chSlash
  188. && strName.GetAt(1) == chSlash )
  189. {
  190. enResult = COMPUTER_INFO_TYPE_NB ;
  191. }
  192. else
  193. {
  194. //
  195. // Scan the name looking for DNS name or IP address
  196. //
  197. int i = 0,
  198. cDots = 0,
  199. cAlpha = 0,
  200. cDash = 0;
  201. TCHAR ch ;
  202. BOOL bOk = TRUE ;
  203. for ( ; i < cch ; i++ )
  204. {
  205. switch ( ch = strName.GetAt( i ) )
  206. {
  207. case chDot:
  208. if ( ++cDots > 3 )
  209. {
  210. // we keep track of the number of dots,
  211. // but we need to be able to handle fully
  212. // qualified domain names (FQDN) so more than
  213. // 3 dots is ok.
  214. //bOk = FALSE ;
  215. }
  216. break;
  217. default:
  218. if ( _istalpha( ch ) )
  219. {
  220. cAlpha++;
  221. }
  222. else if ( ch == chDash )
  223. {
  224. cDash++;
  225. }
  226. else if ( !_istdigit(ch) )
  227. {
  228. bOk = FALSE;
  229. }
  230. break;
  231. }
  232. if ( ! bOk )
  233. {
  234. break ;
  235. }
  236. }
  237. if ( bOk )
  238. {
  239. if ( cAlpha )
  240. {
  241. enResult = COMPUTER_INFO_TYPE_DNS ;
  242. }
  243. else if ( cDots == 3 )
  244. {
  245. enResult = COMPUTER_INFO_TYPE_IP ;
  246. }
  247. }
  248. }
  249. return enResult ;
  250. }
  251. // internal functions
  252. HRESULT
  253. CComputerInfo::InitializeData()
  254. {
  255. HRESULT hr = hrOK;
  256. switch (GetInputType())
  257. {
  258. case COMPUTER_INFO_TYPE_NB:
  259. case COMPUTER_INFO_TYPE_DNS:
  260. {
  261. DWORD dwIp;
  262. GetHostAddress(m_strNameOrIp, &dwIp);
  263. GetHostInfo(dwIp);
  264. }
  265. break;
  266. case COMPUTER_INFO_TYPE_IP:
  267. {
  268. // convert the string to ansi
  269. CHAR szString [ STRING_MAX ] = {0};
  270. ::WideCharToMultiByte(CP_ACP, 0, m_strNameOrIp, -1, szString, sizeof(szString), NULL, NULL);
  271. // get the host info after converting the IP string to a DWORD
  272. GetHostInfo(::ntohl( ::inet_addr( szString ) ) );
  273. }
  274. break;
  275. }
  276. return hr;
  277. }
  278. HRESULT
  279. CComputerInfo::GetHostInfo
  280. (
  281. DWORD dhipa
  282. )
  283. {
  284. CString strFQDN;
  285. CString strHostname;
  286. CString strTemp;
  287. CIpInfo ipInfo;
  288. //
  289. // Call the Winsock API to get host name and alias information.
  290. //
  291. u_long ulAddrInNetOrder = ::htonl( (u_long) dhipa ) ;
  292. HOSTENT * pHostEnt = ::gethostbyaddr( (CHAR *) & ulAddrInNetOrder,
  293. sizeof ulAddrInNetOrder,
  294. PF_INET ) ;
  295. if ( pHostEnt == NULL )
  296. {
  297. return HRESULT_FROM_WIN32(::WSAGetLastError());
  298. }
  299. CHAR * * ppchAlias = pHostEnt->h_aliases ;
  300. //
  301. // Check and copy the host name.
  302. //
  303. ::MultiByteToWideChar(CP_ACP,
  304. MB_PRECOMPOSED,
  305. pHostEnt->h_name,
  306. lstrlenA(pHostEnt->h_name),
  307. strTemp.GetBuffer(STRING_MAX * 2),
  308. STRING_MAX * 2);
  309. strTemp.ReleaseBuffer();
  310. // remove any periods at the end
  311. while (strTemp[strTemp.GetLength() - 1] == '.')
  312. {
  313. strTemp = strTemp.Left(strTemp.GetLength() - 1);
  314. }
  315. // gethostbyaddr is returning the hostname only in some cases.
  316. // Make another call to get the fqdn
  317. if (strTemp.Find('.') == -1)
  318. {
  319. // this is not a FQDN
  320. GetHostAddressFQDN(strTemp, &strFQDN, &dhipa);
  321. }
  322. else
  323. {
  324. strFQDN = strTemp;
  325. }
  326. // copy the data into the buffer
  327. strFQDN.MakeLower();
  328. int nDot = strFQDN.Find('.');
  329. m_strHostname = strFQDN.Left(nDot);
  330. // add the primary entry to the array
  331. ipInfo.dwIp = dhipa;
  332. ipInfo.strFqdn = strFQDN;
  333. m_arrayIps.Add(ipInfo);
  334. // now loop through the h_addr_list
  335. int iCount = 0;
  336. while ( (LPDWORD)(pHostEnt->h_addr_list[iCount] ) )
  337. {
  338. if (!m_arrayIps.FIsInList(addrFromHostent(pHostEnt, iCount)))
  339. {
  340. ipInfo.dwIp = addrFromHostent(pHostEnt, iCount);
  341. ipInfo.strFqdn.Empty();
  342. m_arrayIps.Add(ipInfo);
  343. }
  344. iCount++;
  345. }
  346. m_nIndex = m_arrayIps.GetSize();
  347. //
  348. // Find the first acceptable NetBIOS name among the aliases;
  349. // i.e., the first name without a period
  350. //
  351. /*
  352. for ( ; *ppchAlias ; ppchAlias++ )
  353. {
  354. if ( validateNetbiosName( *ppchAlias ) )
  355. {
  356. break ;
  357. }
  358. }
  359. //
  360. // Empty the NetBIOS name in case we didn't get one.
  361. //
  362. pdhsrvi->_chNetbiosName[0] = 0 ;
  363. if ( *ppchAlias )
  364. {
  365. //
  366. // We found a usable name; copy it to output structure.
  367. //
  368. ::MultiByteToWideChar(CP_ACP,
  369. MB_PRECOMPOSED,
  370. *ppchAlias,
  371. lstrlenA(*ppchAlias),
  372. pdhsrvi->_chNetbiosName,
  373. sizeof(pdhsrvi->_chNetbiosName));
  374. }
  375. */
  376. return hrOK ;
  377. }
  378. HRESULT
  379. CComputerInfo::GetHostAddressFQDN
  380. (
  381. LPCTSTR pszHostName,
  382. CString * pstrFQDN,
  383. DWORD * pdhipa
  384. )
  385. {
  386. HRESULT hr = hrOK;
  387. CHAR szString [ MAX_PATH ] = {0};
  388. ::WideCharToMultiByte(CP_ACP, 0, pszHostName, -1, szString, sizeof(szString), NULL, NULL);
  389. HOSTENT * pHostent = ::gethostbyname( szString ) ;
  390. if ( pHostent )
  391. {
  392. *pdhipa = addrFromHostent( pHostent ) ;
  393. LPTSTR pName = pstrFQDN->GetBuffer(STRING_MAX * 2);
  394. ZeroMemory(pName, STRING_MAX * 2);
  395. ::MultiByteToWideChar(CP_ACP,
  396. MB_PRECOMPOSED,
  397. pHostent->h_name,
  398. strlen(pHostent->h_name),
  399. pName,
  400. STRING_MAX * 2);
  401. pstrFQDN->ReleaseBuffer();
  402. }
  403. else
  404. {
  405. hr = HRESULT_FROM_WIN32(::WSAGetLastError());
  406. }
  407. return hr;
  408. }
  409. DWORD
  410. CComputerInfo::addrFromHostent
  411. (
  412. const HOSTENT * pHostent,
  413. INT index
  414. )
  415. {
  416. return (DWORD) ::ntohl( *((u_long *) pHostent->h_addr_list[index]) );
  417. }
  418. HRESULT
  419. CComputerInfo::GetHostAddress
  420. (
  421. LPCTSTR pszHostName,
  422. DWORD * pdhipa
  423. )
  424. {
  425. HRESULT hr = hrOK;
  426. CHAR szString [ MAX_PATH ] = {0};
  427. ::WideCharToMultiByte(CP_ACP, 0, pszHostName, -1, szString, sizeof(szString), NULL, NULL);
  428. HOSTENT * pHostent = ::gethostbyname( szString ) ;
  429. if ( pHostent )
  430. {
  431. *pdhipa = addrFromHostent( pHostent ) ;
  432. }
  433. else
  434. {
  435. hr = HRESULT_FROM_WIN32(::WSAGetLastError());
  436. }
  437. return hr ;
  438. }
  439. HRESULT
  440. CComputerInfo::GetLocalHostAddress
  441. (
  442. DWORD * pdhipa
  443. )
  444. {
  445. HRESULT hr = hrOK;
  446. CHAR chHostName [ STRING_MAX * 2 ];
  447. if ( ::gethostname( chHostName, sizeof(chHostName) ) == 0 )
  448. {
  449. CString strTemp = chHostName;
  450. hr = GetHostAddress( strTemp, pdhipa ) ;
  451. }
  452. else
  453. {
  454. hr = HRESULT_FROM_WIN32(::WSAGetLastError()) ;
  455. }
  456. return hr;
  457. }
  458. HRESULT
  459. CComputerInfo::GetLocalHostName
  460. (
  461. CString * pstrName
  462. )
  463. {
  464. HRESULT hr = hrOK;
  465. CHAR chHostName [ STRING_MAX * 2 ] ;
  466. if ( ::gethostname( chHostName, sizeof (chHostName) ) == 0 )
  467. {
  468. LPTSTR pName = pstrName->GetBuffer(STRING_MAX * 2);
  469. ZeroMemory(pName, STRING_MAX * 2);
  470. ::MultiByteToWideChar(CP_ACP,
  471. MB_PRECOMPOSED,
  472. chHostName,
  473. strlen(chHostName),
  474. pName,
  475. STRING_MAX * 2);
  476. pstrName->ReleaseBuffer();
  477. }
  478. else
  479. {
  480. hr = HRESULT_FROM_WIN32(::WSAGetLastError()) ;
  481. }
  482. return hr;
  483. }