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.

860 lines
13 KiB

  1. /*++
  2. Copyright (c) 1994-1998 Microsoft Corporation
  3. Module Name :
  4. ipa.cpp
  5. Abstract:
  6. IP Address value and helper functions
  7. Author:
  8. Ronald Meijer (ronaldm)
  9. Project:
  10. Internet Services Manager
  11. Revision History:
  12. --*/
  13. //
  14. // Include Files
  15. //
  16. #include "stdafx.h"
  17. #include "comprop.h"
  18. #include <winsock2.h>
  19. /* static */
  20. DWORD
  21. CIPAddress::StringToLong(
  22. IN LPCTSTR lpstr,
  23. IN int nLength
  24. )
  25. /*++
  26. Routine Description:
  27. Static function to convert an ip address string of the form "1.2.3.4"
  28. to a a single 32 bit number.
  29. Arguments:
  30. LPCTSTR lpstr : String ip address
  31. int nLength : Length of string
  32. Return Value:
  33. 32 bit ip address.
  34. --*/
  35. {
  36. DWORD dwIPValue = 0L;
  37. if (nLength > 0)
  38. {
  39. u_long ul;
  40. #ifdef UNICODE
  41. try
  42. {
  43. //
  44. // Convert to ANSI
  45. //
  46. LPSTR pszDest = AllocAnsiString(lpstr);
  47. ul = ::inet_addr(pszDest);
  48. FreeMem(pszDest);
  49. }
  50. catch(CException * e)
  51. {
  52. TRACEEOLID("!!!Exception converting string to ip address");
  53. e->ReportError();
  54. e->Delete();
  55. }
  56. #else
  57. ul = ::inet_addr(lpstr);
  58. #endif // UNICODE
  59. //
  60. // Convert to host byte order.
  61. //
  62. dwIPValue = (DWORD)::ntohl(ul);
  63. }
  64. return dwIPValue;
  65. }
  66. /* static */
  67. LPTSTR
  68. CIPAddress::LongToString(
  69. IN const DWORD dwIPAddress,
  70. OUT LPTSTR lpStr,
  71. IN int cbSize
  72. )
  73. /*++
  74. Routine Description:
  75. Static function to convert a 32 bit number to a CString of the format
  76. "1.2.3.4"
  77. Arguments:
  78. const DWORD dwIPAddress : 32 bit ip address to be converted to string
  79. LPTSTR lpStr : Destination string
  80. int cbSize : Size of destination string
  81. Return Value:
  82. Pointer to string buffer
  83. --*/
  84. {
  85. struct in_addr ipaddr;
  86. //
  87. // Convert the unsigned long to network byte order
  88. //
  89. ipaddr.s_addr = ::htonl((u_long)dwIPAddress);
  90. //
  91. // Convert the IP address value to a string
  92. //
  93. LPCSTR pchAddr = ::inet_ntoa(ipaddr);
  94. #ifdef UNICODE
  95. VERIFY(::MultiByteToWideChar(CP_ACP, 0L, pchAddr, -1, lpStr, cbSize));
  96. #else
  97. ::lstrcpy(lpStr, pchAddr);
  98. #endif // UNICODE
  99. return lpStr;
  100. }
  101. /* static */
  102. LPCTSTR
  103. CIPAddress::LongToString(
  104. IN const DWORD dwIPAddress,
  105. OUT CString & str
  106. )
  107. /*++
  108. Routine Description:
  109. Static function to convert a 32 bit number to a CString of the format
  110. "1.2.3.4"
  111. Arguments:
  112. const DWORD dwIPAddress : 32 bit ip address to be converted to string
  113. CString & str : Destination string
  114. Return Value:
  115. Pointer to string buffer
  116. --*/
  117. {
  118. struct in_addr ipaddr;
  119. //
  120. // Convert the unsigned long to network byte order
  121. //
  122. ipaddr.s_addr = ::htonl((u_long)dwIPAddress);
  123. //
  124. // Convert the IP address value to a string
  125. //
  126. LPCSTR pchAddr = ::inet_ntoa(ipaddr);
  127. try
  128. {
  129. str = pchAddr;
  130. }
  131. catch(CMemoryException * e)
  132. {
  133. TRACEEOLID("!!!Exception converting ip address to string");
  134. e->ReportError();
  135. e->Delete();
  136. }
  137. return (LPCTSTR)str;
  138. }
  139. /* static */
  140. LPBYTE
  141. CIPAddress::DWORDtoLPBYTE(
  142. IN DWORD dw,
  143. OUT LPBYTE lpBytes
  144. )
  145. /*++
  146. Routine Description:
  147. Convert a DWORD to a byte array of 4 bytes. No size
  148. checking is performed.
  149. Arguments:
  150. DWORD dw : 32 bit ip address
  151. LPBYTE lpBytes : Byte stream
  152. Return Value:
  153. Pointer to the input buffer.
  154. --*/
  155. {
  156. lpBytes[0] = (BYTE)GETIP_FIRST(dw);
  157. lpBytes[1] = (BYTE)GETIP_SECOND(dw);
  158. lpBytes[2] = (BYTE)GETIP_THIRD(dw);
  159. lpBytes[3] = (BYTE)GETIP_FOURTH(dw);
  160. return lpBytes;
  161. }
  162. CIPAddress::CIPAddress()
  163. /*++
  164. Routine Description:
  165. Constructor
  166. Arguments:
  167. None
  168. Return Value:
  169. N/A
  170. --*/
  171. : m_dwIPAddress(0L)
  172. {
  173. }
  174. CIPAddress::CIPAddress(
  175. IN DWORD dwIPAddress,
  176. IN BOOL fNetworkByteOrder
  177. )
  178. /*++
  179. Routine Description:
  180. Constructor.
  181. Arguments:
  182. DWORD dwIPAddress : IP address value
  183. BOOL fNetworkByteOrder : if TRUE, value must be converted to host byte
  184. order, otherwise is assumed to already be in
  185. host byte order.
  186. Return Value:
  187. N/A
  188. --*/
  189. {
  190. if (fNetworkByteOrder)
  191. {
  192. //
  193. // Convert to host byte order
  194. //
  195. dwIPAddress = (DWORD)::ntohl((u_long)dwIPAddress);
  196. }
  197. m_dwIPAddress = dwIPAddress;
  198. }
  199. CIPAddress::CIPAddress(
  200. IN BYTE b1,
  201. IN BYTE b2,
  202. IN BYTE b3,
  203. IN BYTE b4
  204. )
  205. /*++
  206. Routine Description:
  207. Constructor.
  208. Arguments:
  209. BYTE b1 : First octet
  210. BYTE b2 : Second octet
  211. BYTE b3 : Third octet
  212. BYTE b4 : Fourth octet
  213. Return Value:
  214. N/A
  215. Notes:
  216. This is already assumed to be in host order
  217. --*/
  218. : m_dwIPAddress(MAKEIPADDRESS(b1, b2, b3, b4))
  219. {
  220. }
  221. CIPAddress::CIPAddress(
  222. IN LPBYTE lpBytes,
  223. IN BOOL fNetworkByteOrder OPTIONAL
  224. )
  225. /*++
  226. Routine Description:
  227. Construct from byte stream
  228. Arguments:
  229. LPBYTE lpBytes : Byte stream
  230. BOOL fNetworkByteOrder : TRUE if the byte stream is in network byte order
  231. Return Value:
  232. N/A
  233. --*/
  234. {
  235. }
  236. CIPAddress::CIPAddress(
  237. IN const CIPAddress & ia
  238. )
  239. /*++
  240. Routine Description:
  241. Copy Constructor.
  242. Arguments:
  243. const CIPAddress & ia
  244. Return Value:
  245. N/A
  246. --*/
  247. : m_dwIPAddress(ia.m_dwIPAddress)
  248. {
  249. }
  250. CIPAddress::CIPAddress(
  251. IN LPCTSTR lpstr,
  252. IN int nLength
  253. )
  254. /*++
  255. Routine Description:
  256. Constructor.
  257. Arguments:
  258. LPCTSTR lpstr : string ip value
  259. int nLength : length of string
  260. Return Value:
  261. N/A
  262. --*/
  263. {
  264. m_dwIPAddress = CIPAddress::StringToLong(lpstr, nLength);
  265. }
  266. CIPAddress::CIPAddress(
  267. const CString & str
  268. )
  269. /*++
  270. Routine Description:
  271. Constructor.
  272. Arguments:
  273. const CString & str : IP Address string
  274. Return Value:
  275. N/A
  276. --*/
  277. {
  278. m_dwIPAddress = CIPAddress::StringToLong(str);
  279. }
  280. const CIPAddress &
  281. CIPAddress::operator =(
  282. IN const CIPAddress & ia
  283. )
  284. /*++
  285. Routine Description:
  286. Assignment operator
  287. Arguments:
  288. const CIPAddress & ia : Source ip address
  289. Return Value:
  290. Current object
  291. --*/
  292. {
  293. m_dwIPAddress = ia.m_dwIPAddress;
  294. return *this;
  295. }
  296. const CIPAddress &
  297. CIPAddress::operator =(
  298. IN const DWORD dwIPAddress
  299. )
  300. /*++
  301. Routine Description:
  302. Assignment operator
  303. Arguments:
  304. const DWORD dwIPAddress : Source ip address
  305. Return Value:
  306. Current object
  307. --*/
  308. {
  309. m_dwIPAddress = dwIPAddress;
  310. return *this;
  311. }
  312. const CIPAddress &
  313. CIPAddress::operator =(
  314. IN LPCTSTR lpstr
  315. )
  316. /*++
  317. Routine Description:
  318. Assignment operator
  319. Arguments:
  320. LPCTSTR lpstr : Source string
  321. Return Value:
  322. Current object
  323. --*/
  324. {
  325. m_dwIPAddress = CIPAddress::StringToLong(lpstr, ::lstrlen(lpstr));
  326. return *this;
  327. }
  328. const CIPAddress &
  329. CIPAddress::operator =(
  330. IN const CString & str
  331. )
  332. /*++
  333. Routine Description:
  334. Assignment operator
  335. Arguments:
  336. const CString & str : Source string
  337. Return Value:
  338. Current object
  339. --*/
  340. {
  341. m_dwIPAddress = CIPAddress::StringToLong(str);
  342. return *this;
  343. }
  344. int
  345. CIPAddress::CompareItem(
  346. IN const CIPAddress & ia
  347. ) const
  348. /*++
  349. Routine Description:
  350. Compare two ip addresses
  351. Arguments:
  352. const CIPAddress & ia : IP Address to compare this to
  353. Return Value:
  354. +1 if the current ip address is greater,
  355. 0 if the two ip addresses are the same
  356. -1 if the current ip address is less,
  357. --*/
  358. {
  359. return (DWORD)ia < m_dwIPAddress
  360. ? +1
  361. : (DWORD)ia == m_dwIPAddress
  362. ? 0
  363. : -1;
  364. }
  365. CIPAddress::operator LPCTSTR() const
  366. /*++
  367. Routine Description:
  368. Conversion operator
  369. Arguments:
  370. N/A
  371. Return Value:
  372. Pointer to converted string
  373. --*/
  374. {
  375. static TCHAR szIPAddress[] = _T("xxx.xxx.xxx.xxx");
  376. return CIPAddress::LongToString(
  377. m_dwIPAddress,
  378. szIPAddress,
  379. ARRAY_SIZE(szIPAddress)
  380. );
  381. }
  382. CIPAddress::operator CString() const
  383. /*++
  384. Routine Description:
  385. Conversion operator
  386. Arguments:
  387. N/A
  388. Return Value:
  389. Converted string
  390. --*/
  391. {
  392. CString str;
  393. CIPAddress::LongToString(m_dwIPAddress, str);
  394. return str;
  395. }
  396. DWORD
  397. CIPAddress::QueryIPAddress(
  398. IN BOOL fNetworkByteOrder
  399. ) const
  400. /*++
  401. Routine Description:
  402. Get the ip address as a 32 bit number
  403. Arguments:
  404. BOOL fNetworkByteOrder : If TRUE, convert to network byte order
  405. Return Value:
  406. 32 bit ip address
  407. --*/
  408. {
  409. return fNetworkByteOrder
  410. ? ::htonl((u_long)m_dwIPAddress)
  411. : m_dwIPAddress;
  412. }
  413. //
  414. // IP Address helper functions
  415. //
  416. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  417. DWORD
  418. PopulateComboWithKnownIpAddresses(
  419. IN LPCTSTR lpszServer,
  420. IN CComboBox & combo,
  421. IN CIPAddress & iaIpAddress,
  422. OUT CObListPlus & oblIpAddresses,
  423. OUT int & nIpAddressSel
  424. )
  425. /*++
  426. Routine Description:
  427. Fill a combo box with known ip addresses
  428. Arguments:
  429. LPCTSTR lpszServer : Server whose ip addresses to obtain
  430. (can be computer name or ip address)
  431. CComboBox & combo : Combo box to populate
  432. CIPAddress & iaIpAddress : IP Address to select
  433. CObListPlus & oblIpAddresses : Returns an oblist of CIPAddress objects
  434. int & nIpAddressSel : Returns selected IP address
  435. Return Value:
  436. Error return code
  437. --*/
  438. {
  439. //
  440. // Start clean
  441. //
  442. oblIpAddresses.RemoveAll();
  443. combo.ResetContent();
  444. //
  445. // Don't like \\names
  446. //
  447. lpszServer = PURE_COMPUTER_NAME(lpszServer);
  448. struct hostent * pHostEntry = NULL;
  449. if (_istdigit(*lpszServer))
  450. {
  451. //
  452. // Get by ip address
  453. //
  454. u_long ul = (DWORD)CIPAddress(lpszServer);
  455. ul = ::htonl(ul); // convert to network order.
  456. pHostEntry = ::gethostbyaddr((CHAR *)&ul, sizeof(ul), PF_INET);
  457. }
  458. else
  459. {
  460. //
  461. // Get by domain name
  462. //
  463. const char FAR * lpszAnsiServer = NULL;
  464. #ifdef UNICODE
  465. CHAR szAnsi[255];
  466. if (::WideCharToMultiByte(CP_ACP, 0L, lpszServer, -1, szAnsi,
  467. sizeof(szAnsi), NULL, NULL) > 0)
  468. {
  469. lpszAnsiServer = szAnsi;
  470. }
  471. #else
  472. lpszAnsiServer = lpszServer;
  473. #endif // UNICODE
  474. if (lpszAnsiServer)
  475. {
  476. pHostEntry = ::gethostbyname(lpszAnsiServer);
  477. }
  478. }
  479. //
  480. // We'll always have the 'default' server id
  481. // selected
  482. //
  483. CString strDefault, str;
  484. VERIFY(strDefault.LoadString(IDS_DEFAULT));
  485. nIpAddressSel = -1;
  486. CIPAddress * pia = new CIPAddress;
  487. if (pia == NULL) {
  488. return ERROR_NOT_ENOUGH_MEMORY;
  489. }
  490. oblIpAddresses.AddTail(pia);
  491. int nNewSel = combo.AddString(strDefault);
  492. if (iaIpAddress == *pia)
  493. {
  494. //
  495. // Remember selection
  496. //
  497. nIpAddressSel = nNewSel;
  498. }
  499. if (pHostEntry != NULL)
  500. {
  501. int n = 0;
  502. while (((DWORD *)pHostEntry->h_addr_list[n]) != NULL)
  503. {
  504. //
  505. // Convert from network byte order
  506. //
  507. pia = new CIPAddress(
  508. *((DWORD *)(pHostEntry->h_addr_list[n++])), TRUE);
  509. nNewSel = combo.AddString(pia->QueryIPAddress(str));
  510. oblIpAddresses.AddTail(pia);
  511. if (iaIpAddress == *pia)
  512. {
  513. //
  514. // This is our current ip address, save index
  515. // for selection
  516. //
  517. nIpAddressSel = nNewSel;
  518. }
  519. }
  520. }
  521. if (nIpAddressSel < 0)
  522. {
  523. //
  524. // Ok, the IP address selected is not part of the
  525. // list. Add it to the list, and select it.
  526. //
  527. pia = new CIPAddress(iaIpAddress);
  528. nIpAddressSel = combo.AddString(pia->QueryIPAddress(str));
  529. oblIpAddresses.AddTail(pia);
  530. }
  531. combo.SetCurSel(nIpAddressSel);
  532. return ERROR_SUCCESS;
  533. }
  534. BOOL
  535. FetchIpAddressFromCombo(
  536. IN CComboBox & combo,
  537. IN CObListPlus & oblIpAddresses,
  538. OUT CIPAddress & ia
  539. )
  540. /*++
  541. Routine Description:
  542. Helper function to fetch an ip address from the combo box.
  543. The combo box may not have a selection, in which case whatever
  544. is in the edit box is used
  545. Arguments:
  546. CComboBox & combo : Combo box
  547. CObListPlus & oblIpAddresses : Oblist of ip addresses
  548. CIPAddress & ia : Returns the ip address
  549. Return Value:
  550. TRUE if a valid IP address is found, FALSE otherwise.
  551. --*/
  552. {
  553. int nSel = combo.GetCurSel();
  554. if (nSel >= 0)
  555. {
  556. //
  557. // Fetch selected item
  558. //
  559. CIPAddress * pia = (CIPAddress *)oblIpAddresses.Index(nSel);
  560. ASSERT(pia != NULL);
  561. if (pia != NULL)
  562. ia = *pia;
  563. return TRUE;
  564. }
  565. //
  566. // Try to make an ip address out of what's in the editbox
  567. //
  568. CString str;
  569. combo.GetWindowText(str);
  570. if (!str.IsEmpty())
  571. {
  572. ia = str;
  573. if (!ia.IsZeroValue() && !ia.IsBadValue())
  574. {
  575. return TRUE;
  576. }
  577. }
  578. //
  579. // No good
  580. //
  581. ::AfxMessageBox(IDS_IP_INVALID);
  582. return FALSE;
  583. }