Leaked source code of windows server 2003
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.

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