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.

338 lines
7.3 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // resolver.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the class Resolver.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 02/28/2000 Original version.
  16. // 05/11/2000 Make OK button the default if name resolution succeeds.
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #include <proxypch.h>
  20. #include <resolver.h>
  21. #include <winsock2.h>
  22. #include <svcguid.h>
  23. /////////
  24. // Unicode version of gethostbyname. The caller must free the returned hostent
  25. // struct by calling LocalFree.
  26. /////////
  27. PHOSTENT
  28. WINAPI
  29. IASGetHostByName(
  30. IN PCWSTR name
  31. )
  32. {
  33. // We put these at function scope, so we can clean them up on the way out.
  34. DWORD error = NO_ERROR;
  35. HANDLE lookup = NULL;
  36. union
  37. {
  38. WSAQUERYSETW querySet;
  39. BYTE buffer[512];
  40. };
  41. PWSAQUERYSETW result = NULL;
  42. PHOSTENT retval = NULL;
  43. do
  44. {
  45. //////////
  46. // Create the query set
  47. //////////
  48. GUID hostAddrByNameGuid = SVCID_INET_HOSTADDRBYNAME;
  49. AFPROTOCOLS protocols[2] =
  50. {
  51. { AF_INET, IPPROTO_UDP },
  52. { AF_INET, IPPROTO_TCP }
  53. };
  54. memset(&querySet, 0, sizeof(querySet));
  55. querySet.dwSize = sizeof(querySet);
  56. querySet.lpszServiceInstanceName = (PWSTR)name;
  57. querySet.lpServiceClassId = &hostAddrByNameGuid;
  58. querySet.dwNameSpace = NS_ALL;
  59. querySet.dwNumberOfProtocols = 2;
  60. querySet.lpafpProtocols = protocols;
  61. //////////
  62. // Execute the query.
  63. //////////
  64. error = WSALookupServiceBeginW(
  65. &querySet,
  66. LUP_RETURN_ADDR,
  67. &lookup
  68. );
  69. if (error)
  70. {
  71. error = WSAGetLastError();
  72. break;
  73. }
  74. //////////
  75. // How much space do we need for the result?
  76. //////////
  77. DWORD length = sizeof(buffer);
  78. error = WSALookupServiceNextW(
  79. lookup,
  80. 0,
  81. &length,
  82. &querySet
  83. );
  84. if (!error)
  85. {
  86. result = &querySet;
  87. }
  88. else
  89. {
  90. error = WSAGetLastError();
  91. if (error != WSAEFAULT)
  92. {
  93. break;
  94. }
  95. /////////
  96. // Allocate memory to hold the result.
  97. /////////
  98. result = (PWSAQUERYSETW)LocalAlloc(0, length);
  99. if (!result)
  100. {
  101. error = WSA_NOT_ENOUGH_MEMORY;
  102. break;
  103. }
  104. /////////
  105. // Get the result.
  106. /////////
  107. error = WSALookupServiceNextW(
  108. lookup,
  109. 0,
  110. &length,
  111. result
  112. );
  113. if (error)
  114. {
  115. error = WSAGetLastError();
  116. break;
  117. }
  118. }
  119. if (result->dwNumberOfCsAddrs == 0)
  120. {
  121. error = WSANO_DATA;
  122. break;
  123. }
  124. ///////
  125. // Allocate memory to hold the hostent struct
  126. ///////
  127. DWORD naddr = result->dwNumberOfCsAddrs;
  128. SIZE_T nbyte = sizeof(hostent) +
  129. (naddr + 1) * sizeof(char*) +
  130. naddr * sizeof(in_addr);
  131. retval = (PHOSTENT)LocalAlloc(0, nbyte);
  132. if (!retval)
  133. {
  134. error = WSA_NOT_ENOUGH_MEMORY;
  135. break;
  136. }
  137. ///////
  138. // Initialize the hostent struct.
  139. ///////
  140. retval->h_name = NULL;
  141. retval->h_aliases = NULL;
  142. retval->h_addrtype = AF_INET;
  143. retval->h_length = sizeof(in_addr);
  144. retval->h_addr_list = (char**)(retval + 1);
  145. ///////
  146. // Store the addresses.
  147. ///////
  148. u_long* nextAddr = (u_long*)(retval->h_addr_list + naddr + 1);
  149. for (DWORD i = 0; i < naddr; ++i)
  150. {
  151. sockaddr_in* sin = (sockaddr_in*)
  152. result->lpcsaBuffer[i].RemoteAddr.lpSockaddr;
  153. retval->h_addr_list[i] = (char*)nextAddr;
  154. *nextAddr++ = sin->sin_addr.S_un.S_addr;
  155. }
  156. ///////
  157. // NULL terminate the address list.
  158. ///////
  159. retval->h_addr_list[i] = NULL;
  160. } while (FALSE);
  161. //////////
  162. // Clean up and return.
  163. //////////
  164. if (result && result != &querySet) { LocalFree(result); }
  165. if (lookup) { WSALookupServiceEnd(lookup); }
  166. if (error)
  167. {
  168. if (error == WSASERVICE_NOT_FOUND) { error = WSAHOST_NOT_FOUND; }
  169. WSASetLastError(error);
  170. }
  171. return retval;
  172. }
  173. Resolver::Resolver(PCWSTR dnsName, CWnd* pParent)
  174. : CHelpDialog(IDD_RESOLVE_ADDRESS, pParent),
  175. name(dnsName),
  176. choice(name)
  177. {
  178. WSADATA wsaData;
  179. WSAStartup(MAKEWORD(2, 0), &wsaData);
  180. }
  181. Resolver::~Resolver()
  182. {
  183. WSACleanup();
  184. }
  185. BOOL Resolver::OnInitDialog()
  186. {
  187. /////////
  188. // Subclass the list control.
  189. /////////
  190. if (!results.SubclassWindow(::GetDlgItem(m_hWnd, IDC_LIST_IPADDRS)))
  191. {
  192. AfxThrowNotSupportedException();
  193. }
  194. /////////
  195. // Set the column header.
  196. /////////
  197. RECT rect;
  198. results.GetClientRect(&rect);
  199. LONG width = rect.right - rect.left;
  200. ResourceString addrsCol(IDS_RESOLVER_COLUMN_ADDRS);
  201. results.InsertColumn(0, addrsCol, LVCFMT_LEFT, width);
  202. results.SetExtendedStyle(results.GetExtendedStyle() | LVS_EX_FULLROWSELECT);
  203. return CHelpDialog::OnInitDialog();
  204. }
  205. void Resolver::DoDataExchange(CDataExchange* pDX)
  206. {
  207. CHelpDialog::DoDataExchange(pDX);
  208. DDX_Text(pDX, IDC_EDIT_NAME, name);
  209. if (pDX->m_bSaveAndValidate)
  210. {
  211. int item = results.GetNextItem(-1, LVNI_SELECTED);
  212. choice = (item >= 0) ? results.GetItemText(item, 0) : name;
  213. }
  214. }
  215. void Resolver::OnResolve()
  216. {
  217. // Remove the existing result set.
  218. results.DeleteAllItems();
  219. // Get the name to resolve.
  220. UpdateData();
  221. // Change the cursor to busy signal since this will block.
  222. BeginWaitCursor();
  223. // Resolve the hostname.
  224. PHOSTENT he = IASGetHostByName(name);
  225. // The blocking part is over, so restore the cursor.
  226. EndWaitCursor();
  227. if (he)
  228. {
  229. // Add the IP addresses to the combo box.
  230. for (ULONG i = 0; he->h_addr_list[i] && i < 8; ++i)
  231. {
  232. PBYTE p = (PBYTE)he->h_addr_list[i];
  233. WCHAR szAddr[16];
  234. wsprintfW(szAddr, L"%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
  235. results.InsertItem(i, szAddr);
  236. }
  237. // Free the results.
  238. LocalFree(he);
  239. // Make the OK button the default ...
  240. setButtonStyle(IDOK, BS_DEFPUSHBUTTON, true);
  241. setButtonStyle(IDC_BUTTON_RESOLVE, BS_DEFPUSHBUTTON, false);
  242. // ... and give it the focus.
  243. setFocusControl(IDOK);
  244. }
  245. else
  246. {
  247. ResourceString text(IDS_SERVER_E_NO_RESOLVE);
  248. ResourceString caption(IDS_SERVER_E_CAPTION);
  249. MessageBox(text, caption, MB_ICONWARNING);
  250. }
  251. }
  252. BEGIN_MESSAGE_MAP(Resolver, CHelpDialog)
  253. ON_BN_CLICKED(IDC_BUTTON_RESOLVE, OnResolve)
  254. END_MESSAGE_MAP()
  255. void Resolver::setButtonStyle(int controlId, long flags, bool set)
  256. {
  257. // Get the button handle.
  258. HWND button = ::GetDlgItem(m_hWnd, controlId);
  259. // Retrieve the current style.
  260. long style = ::GetWindowLong(button, GWL_STYLE);
  261. // Update the flags.
  262. if (set)
  263. {
  264. style |= flags;
  265. }
  266. else
  267. {
  268. style &= ~flags;
  269. }
  270. // Set the new style.
  271. ::SendMessage(button, BM_SETSTYLE, LOWORD(style), MAKELPARAM(1,0));
  272. }
  273. void Resolver::setFocusControl(int controlId)
  274. {
  275. ::SetFocus(::GetDlgItem(m_hWnd, controlId));
  276. }