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.

945 lines
14 KiB

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