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.

1067 lines
31 KiB

  1. /*++
  2. Copyright(c) 1995 Microsoft Corporation
  3. MODULE NAME
  4. access.c
  5. ABSTRACT
  6. Address accessibility routines for automatic connections
  7. AUTHOR
  8. Anthony Discolo (adiscolo) 26-Jul-1995
  9. REVISION HISTORY
  10. --*/
  11. #define UNICODE
  12. #define _UNICODE
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <stdlib.h>
  17. #include <windows.h>
  18. #include <tdi.h>
  19. #include <nb30.h>
  20. #include <nbtioctl.h>
  21. #include <stdio.h>
  22. #include <npapi.h>
  23. #include <ctype.h>
  24. #include <winsock.h>
  25. #include <acd.h>
  26. #include <ras.h>
  27. #include <raserror.h>
  28. #include <rasman.h>
  29. #include <debug.h>
  30. #include <ipexport.h>
  31. #include <icmpapi.h>
  32. #include "reg.h"
  33. #include "rasprocs.h"
  34. #include "misc.h"
  35. #include "table.h"
  36. #include "addrmap.h"
  37. #include "imperson.h"
  38. //
  39. // The format of Adapter Status responses.
  40. //
  41. typedef struct _ADAPTERSTATUS
  42. {
  43. ADAPTER_STATUS AdapterInfo;
  44. NAME_BUFFER Names[32];
  45. } ADAPTERSTATUS, *PADAPTERSTATUS;
  46. //
  47. // Icmp.dll library entrypoints.
  48. //
  49. #define ICMP_MODULE L"icmp"
  50. HANDLE hIcmpG;
  51. #define ICMPCREATEFILE "IcmpCreateFile"
  52. FARPROC lpfnIcmpCreateFileG;
  53. #define ICMPSENDECHO "IcmpSendEcho"
  54. FARPROC lpfnIcmpSendEchoG;
  55. #define ICMPCLOSEHANDLE "IcmpCloseHandle"
  56. FARPROC lpfnIcmpCloseHandleG;
  57. //
  58. // PingIpAddress constants
  59. //
  60. #define PING_SEND_SIZE 32
  61. #define PING_RECV_SIZE (0x2000 - 8)
  62. #define PING_TTL 32
  63. #define PING_TIMEOUT 2000L // needs to be long enough to succeed over slow links
  64. //
  65. // External variables
  66. //
  67. extern HANDLE hTerminatingG;
  68. BOOLEAN
  69. CopyNetbiosName(
  70. IN NAME_BUFFER *pNames,
  71. IN DWORD dwcNames,
  72. OUT LPSTR pszNetbiosName
  73. )
  74. {
  75. BOOLEAN fFound = FALSE;
  76. DWORD i, iWks = 0;
  77. CHAR szWks[NCBNAMSZ];
  78. PCHAR p = pszNetbiosName;
  79. //
  80. // Find the unique workstation name.
  81. //
  82. again:
  83. szWks[0] = '\0';
  84. for (i = iWks; i < dwcNames; i++) {
  85. RASAUTO_TRACE2(
  86. "CopyNetbiosName: wks %15.15s (0x%x)",
  87. pNames[i].name,
  88. pNames[i].name[NCBNAMSZ - 1]);
  89. if (pNames[i].name[NCBNAMSZ - 1] == 0x0 &&
  90. !(pNames[i].name_flags & GROUP_NAME))
  91. {
  92. RASAUTO_TRACE1("CopyNetbiosName: iWks=%d\n", iWks);
  93. iWks = i;
  94. memcpy(szWks, pNames[i].name, NCBNAMSZ - 1);
  95. break;
  96. }
  97. }
  98. //
  99. // Check to make sure we found one.
  100. //
  101. if (szWks[0] == '\0')
  102. return FALSE;
  103. //
  104. // Find the unique server name and make
  105. // sure it matches the workstation name.
  106. //
  107. for (i = 0; i < dwcNames; i++) {
  108. RASAUTO_TRACE3(
  109. "CopyNetbiosName: srv %15.15s (0x%x), cmp=%d",
  110. pNames[i].name,
  111. pNames[i].name[NCBNAMSZ - 1],
  112. memcmp(szWks, pNames[i].name, NCBNAMSZ - 1));
  113. if (pNames[i].name[NCBNAMSZ - 1] == 0x20 &&
  114. !(pNames[i].name_flags & GROUP_NAME) &&
  115. !memcmp(szWks, pNames[i].name, NCBNAMSZ - 1))
  116. {
  117. DWORD j;
  118. //
  119. // Copy up to a null or a space.
  120. //
  121. for (j = 0; j < NCBNAMSZ - 1; j++) {
  122. if (pNames[i].name[j] == '\0' || pNames[i].name[j] == ' ')
  123. break;
  124. *p++ = pNames[i].name[j];
  125. }
  126. *p++ = '\0';
  127. return TRUE;
  128. }
  129. }
  130. //
  131. // No match found. Look for another unique workstation
  132. // name and try again if we haven't exhausted the list.
  133. //
  134. if (++iWks >= dwcNames)
  135. return FALSE;
  136. goto again;
  137. } // CopyNetbiosName
  138. LPTSTR
  139. IpAddressToNetbiosName(
  140. IN LPTSTR pszIpAddress,
  141. IN HPORT hPort
  142. )
  143. {
  144. BOOLEAN fFound;
  145. RAS_PROTOCOLS Protocols;
  146. DWORD i, dwcProtocols;
  147. RASMAN_ROUTEINFO *pRoute;
  148. WCHAR szAdapterName[MAX_PATH];
  149. NTSTATUS status;
  150. HANDLE fd;
  151. OBJECT_ATTRIBUTES objectAttributes;
  152. IO_STATUS_BLOCK ioStatusBlock;
  153. UNICODE_STRING unicodeString;
  154. ULONG ipaddr;
  155. CHAR szIpAddress[17];
  156. tIPANDNAMEINFO ipAndNameInfo;
  157. PVOID pBuffer;
  158. DWORD dwSize;
  159. PADAPTERSTATUS pAdapterStatus;
  160. NAME_BUFFER *pNames;
  161. DWORD dwcNames;
  162. LPTSTR pszNetbiosName = NULL;
  163. //
  164. // Enumerate the bindings for the port to
  165. // try to find the Netbt device.
  166. //
  167. GetPortProtocols(hPort, &Protocols, &dwcProtocols);
  168. fFound = FALSE;
  169. for (i = 0; i < dwcProtocols; i++) {
  170. pRoute = &Protocols.RP_ProtocolInfo[i];
  171. RASAUTO_TRACE3(
  172. "IpAddressToNetbiosName: adapter type=%d, name=%S, xport=%S",
  173. pRoute->RI_Type,
  174. pRoute->RI_AdapterName,
  175. pRoute->RI_XportName);
  176. if (pRoute->RI_Type == IP) {
  177. wcscpy(szAdapterName, L"\\Device\\Netbt_Tcpip_");
  178. wcscat(szAdapterName, &pRoute->RI_AdapterName[8]);
  179. fFound = TRUE;
  180. break;
  181. }
  182. }
  183. if (!fFound)
  184. return NULL;
  185. //
  186. // Open the device and issue a remote
  187. // adapter status command.
  188. //
  189. RtlInitUnicodeString(&unicodeString, szAdapterName);
  190. InitializeObjectAttributes(
  191. &objectAttributes,
  192. &unicodeString,
  193. OBJ_CASE_INSENSITIVE,
  194. NULL,
  195. NULL);
  196. status = NtCreateFile(
  197. &fd,
  198. SYNCHRONIZE|FILE_READ_DATA|FILE_WRITE_DATA,
  199. &objectAttributes,
  200. &ioStatusBlock,
  201. NULL,
  202. FILE_ATTRIBUTE_NORMAL,
  203. FILE_SHARE_READ|FILE_SHARE_WRITE,
  204. FILE_OPEN_IF,
  205. 0,
  206. NULL,
  207. 0);
  208. if (!NT_SUCCESS(status)) {
  209. RASAUTO_TRACE1(
  210. "IpAddressToNetbiosName: NtCreateFile failed (status=0x%x)\n",
  211. status);
  212. return NULL;
  213. }
  214. UnicodeStringToAnsiString(pszIpAddress, szIpAddress, sizeof (szIpAddress));
  215. ipaddr = inet_addr(szIpAddress);
  216. if (ipaddr == INADDR_ANY)
  217. return NULL;
  218. RtlZeroMemory(&ipAndNameInfo, sizeof (ipAndNameInfo));
  219. ipAndNameInfo.IpAddress = ntohl(ipaddr);
  220. ipAndNameInfo.NetbiosAddress.Address[0].Address[0].NetbiosName[0] = '*';
  221. ipAndNameInfo.NetbiosAddress.TAAddressCount = 1;
  222. ipAndNameInfo.NetbiosAddress.Address[0].AddressLength =
  223. sizeof (TDI_ADDRESS_NETBIOS);
  224. ipAndNameInfo.NetbiosAddress.Address[0].AddressType =
  225. TDI_ADDRESS_TYPE_NETBIOS;
  226. ipAndNameInfo.NetbiosAddress.Address[0].Address[0].NetbiosNameType =
  227. TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  228. dwSize = 2048;
  229. for (;;) {
  230. pBuffer = LocalAlloc(LPTR, dwSize);
  231. if (pBuffer == NULL) {
  232. RASAUTO_TRACE("IpAddressToNetbiosName: LocalAlloc failed");
  233. return NULL;
  234. }
  235. status = NtDeviceIoControlFile(
  236. fd,
  237. NULL,
  238. NULL,
  239. NULL,
  240. &ioStatusBlock,
  241. IOCTL_NETBT_ADAPTER_STATUS,
  242. &ipAndNameInfo,
  243. sizeof (tIPANDNAMEINFO),
  244. pBuffer,
  245. dwSize);
  246. if (status != STATUS_BUFFER_OVERFLOW)
  247. break;
  248. LocalFree(pBuffer);
  249. dwSize *= 2;
  250. if (dwSize >= 0xffff) {
  251. RASAUTO_TRACE("IpAddressToNetbiosName: Unable to allocate packet");
  252. return NULL;
  253. }
  254. }
  255. if (status == STATUS_PENDING) {
  256. status = NtWaitForSingleObject(fd, TRUE, NULL);
  257. if (status == STATUS_SUCCESS)
  258. status = ioStatusBlock.Status;
  259. }
  260. NtClose(fd);
  261. pAdapterStatus = (PADAPTERSTATUS)pBuffer;
  262. dwcNames = pAdapterStatus->AdapterInfo.name_count;
  263. RASAUTO_TRACE2(
  264. "IpAddressToNetbiosName: results (status=0x%x, dwcNames=%d)\n",
  265. status,
  266. dwcNames);
  267. if (status == STATUS_SUCCESS && dwcNames) {
  268. CHAR szNetbiosName[NCBNAMSZ + 1];
  269. pNames = pAdapterStatus->Names;
  270. if (CopyNetbiosName(pNames, dwcNames, szNetbiosName))
  271. pszNetbiosName = AnsiStringToUnicodeString(szNetbiosName, NULL, 0);
  272. }
  273. LocalFree(pBuffer);
  274. return pszNetbiosName;
  275. } // IpAddressToNetbiosName
  276. UCHAR
  277. HexByte(
  278. IN PCHAR p
  279. )
  280. {
  281. UCHAR c;
  282. c = *(UCHAR *)p;
  283. if (c >= '0' && c <= '9')
  284. return c - '0';
  285. if ((c >= 'A' && c <= 'F') ||
  286. (c >= 'a' && c <= 'f'))
  287. {
  288. return c - ('A' - 10);
  289. }
  290. return 0xff;
  291. } // HexByte
  292. VOID
  293. StringToNodeNumber(
  294. IN PCHAR pszString,
  295. OUT PCHAR pszNode
  296. )
  297. {
  298. UCHAR c1, c2;
  299. INT i;
  300. if (strlen(pszString) != 12) {
  301. RASAUTO_TRACE("StringToNodeNumber: bad node number length\n");
  302. return;
  303. }
  304. for (i = 0; i < 6; i++) {
  305. c1 = HexByte(pszString++);
  306. c2 = HexByte(pszString++);
  307. if (c1 == 0xff || c2 == 0xff) {
  308. RASAUTO_TRACE("StringToNodeNumber: bad digit");
  309. return;
  310. }
  311. *pszNode++ = (c1 << 4) + c2;
  312. }
  313. } // StringToNodeNumber
  314. VOID
  315. NodeNumberToString(
  316. IN PCHAR pszNode,
  317. OUT PCHAR pszString
  318. )
  319. {
  320. UCHAR c1, c2;
  321. INT i;
  322. sprintf(
  323. pszString,
  324. "%02x:%02x:%02x:%02x:%02x:%02x",
  325. pszNode[0],
  326. pszNode[1],
  327. pszNode[2],
  328. pszNode[3],
  329. pszNode[4],
  330. pszNode[5]);
  331. } // NodeNumberToString
  332. LPTSTR
  333. IpxAddressToNetbiosName(
  334. IN LPTSTR pszIpxAddress
  335. )
  336. {
  337. NTSTATUS status;
  338. HANDLE fd;
  339. OBJECT_ATTRIBUTES objectAttributes;
  340. IO_STATUS_BLOCK ioStatusBlock;
  341. UNICODE_STRING unicodeString;
  342. PTDI_REQUEST_QUERY_INFORMATION pQuery;
  343. PTDI_CONNECTION_INFORMATION pConnectionInformation;
  344. PTA_NETBIOS_ADDRESS pRemoteAddress;
  345. CHAR szIpxAddress[13];
  346. PVOID pBuffer;
  347. DWORD dwQuerySize, dwBufferSize;
  348. PADAPTERSTATUS pAdapterStatus;
  349. NAME_BUFFER *pNames;
  350. DWORD dwcNames;
  351. LPTSTR pszNetbiosName = NULL;
  352. RtlInitUnicodeString(&unicodeString, L"\\Device\\Nwlnknb");
  353. InitializeObjectAttributes(
  354. &objectAttributes,
  355. &unicodeString,
  356. OBJ_CASE_INSENSITIVE,
  357. NULL,
  358. NULL);
  359. status = NtCreateFile(
  360. &fd,
  361. SYNCHRONIZE|FILE_READ_DATA|FILE_WRITE_DATA,
  362. &objectAttributes,
  363. &ioStatusBlock,
  364. NULL,
  365. FILE_ATTRIBUTE_NORMAL,
  366. FILE_SHARE_READ|FILE_SHARE_WRITE,
  367. FILE_OPEN_IF,
  368. 0,
  369. NULL,
  370. 0);
  371. if (!NT_SUCCESS(status)) {
  372. RASAUTO_TRACE1("IpxAddressToNetbiosName: NtCreateFile failed (status=0x%x)", status);
  373. return NULL;
  374. }
  375. dwQuerySize = sizeof (TDI_REQUEST_QUERY_INFORMATION) +
  376. sizeof (TDI_CONNECTION_INFORMATION) +
  377. sizeof (TA_NETBIOS_ADDRESS);
  378. pQuery = LocalAlloc(LPTR, dwQuerySize);
  379. if (pQuery == NULL) {
  380. RASAUTO_TRACE("IpxAddressToNetbiosName: LocalAlloc failed");
  381. return NULL;
  382. }
  383. pQuery->QueryType = TDI_QUERY_ADAPTER_STATUS;
  384. (PTDI_CONNECTION_INFORMATION)&pQuery->RequestConnectionInformation;
  385. pQuery->RequestConnectionInformation =
  386. (PTDI_CONNECTION_INFORMATION)(pQuery + 1);
  387. pConnectionInformation = pQuery->RequestConnectionInformation;
  388. pConnectionInformation->UserDataLength = 0;
  389. pConnectionInformation->UserData = NULL;
  390. pConnectionInformation->OptionsLength = 0;
  391. pConnectionInformation->Options = NULL;
  392. pConnectionInformation->RemoteAddressLength = sizeof (TDI_ADDRESS_NETBIOS);
  393. pConnectionInformation->RemoteAddress =
  394. (PTA_NETBIOS_ADDRESS)(pConnectionInformation + 1);
  395. pRemoteAddress = pConnectionInformation->RemoteAddress;
  396. pRemoteAddress->TAAddressCount = 1;
  397. pRemoteAddress->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
  398. pRemoteAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  399. pRemoteAddress->Address[0].Address[0].NetbiosNameType =
  400. TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  401. UnicodeStringToAnsiString(
  402. pszIpxAddress,
  403. szIpxAddress,
  404. sizeof (szIpxAddress));
  405. RtlZeroMemory((PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName, 10);
  406. StringToNodeNumber(
  407. (PCHAR)szIpxAddress,
  408. (PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName[10]);
  409. RASAUTO_TRACE6("IpxAddressToNetbiosName: Node=%02x:%02x:%02x:%02x:%02x:%02x\n",
  410. pRemoteAddress->Address[0].Address[0].NetbiosName[10],
  411. pRemoteAddress->Address[0].Address[0].NetbiosName[11],
  412. pRemoteAddress->Address[0].Address[0].NetbiosName[12],
  413. pRemoteAddress->Address[0].Address[0].NetbiosName[13],
  414. pRemoteAddress->Address[0].Address[0].NetbiosName[14],
  415. pRemoteAddress->Address[0].Address[0].NetbiosName[15]);
  416. dwBufferSize = 2048;
  417. for (;;) {
  418. pBuffer = LocalAlloc(LPTR, dwBufferSize);
  419. if (pBuffer == NULL) {
  420. RASAUTO_TRACE("IpxAddressToNetbiosName: LocalAlloc failed");
  421. LocalFree(pQuery);
  422. return NULL;
  423. }
  424. status = NtDeviceIoControlFile(
  425. fd,
  426. NULL,
  427. NULL,
  428. NULL,
  429. &ioStatusBlock,
  430. IOCTL_TDI_QUERY_INFORMATION,
  431. pQuery,
  432. dwQuerySize,
  433. pBuffer,
  434. dwBufferSize);
  435. if (status != STATUS_BUFFER_OVERFLOW)
  436. break;
  437. LocalFree(pBuffer);
  438. dwBufferSize *= 2;
  439. if (dwBufferSize >= 0xffff) {
  440. RASAUTO_TRACE("IpxAddressToNetbiosName: Unable to allocate packet");
  441. LocalFree(pQuery);
  442. return NULL;
  443. }
  444. }
  445. if (status == STATUS_PENDING) {
  446. status = NtWaitForSingleObject(fd, TRUE, NULL);
  447. if (status == STATUS_SUCCESS)
  448. status = ioStatusBlock.Status;
  449. }
  450. NtClose(fd);
  451. pAdapterStatus = (PADAPTERSTATUS)pBuffer;
  452. dwcNames = pAdapterStatus->AdapterInfo.name_count;
  453. RASAUTO_TRACE2(
  454. "IpxAddressToNetbiosName: results (status=0x%x, dwcNames=%d)",
  455. status,
  456. dwcNames);
  457. if (status == STATUS_SUCCESS && dwcNames) {
  458. CHAR szNetbiosName[NCBNAMSZ + 1];
  459. pNames = pAdapterStatus->Names;
  460. if (CopyNetbiosName(pNames, dwcNames, szNetbiosName))
  461. pszNetbiosName = AnsiStringToUnicodeString(pNames->name, NULL, 0);
  462. }
  463. LocalFree(pBuffer);
  464. LocalFree(pQuery);
  465. return pszNetbiosName;
  466. } // IpxAddressToNetbiosName
  467. BOOLEAN
  468. NetbiosFindName(
  469. IN LPTSTR *pszDevices,
  470. IN DWORD dwcDevices,
  471. IN LPTSTR pszAddress
  472. )
  473. {
  474. NTSTATUS *pStatus;
  475. PHANDLE pfd;
  476. PHANDLE pEvent;
  477. POBJECT_ATTRIBUTES pObjectAttributes;
  478. PIO_STATUS_BLOCK pIoStatusBlock;
  479. PUNICODE_STRING pUnicodeString;
  480. PTDI_REQUEST_QUERY_INFORMATION pQuery;
  481. PTDI_CONNECTION_INFORMATION pConnectionInformation;
  482. PTA_NETBIOS_ADDRESS pRemoteAddress;
  483. CHAR szAddress[NCBNAMSZ];
  484. PVOID *pBuffer;
  485. DWORD i, dwQuerySize, dwBufferSize;
  486. PADAPTERSTATUS pAdapterStatus;
  487. NAME_BUFFER *pNames;
  488. DWORD dwcWait, dwcNames;
  489. BOOLEAN bFound = FALSE;
  490. //
  491. // If there are no Netbios devices, then we're done.
  492. //
  493. if (pszDevices == NULL || !dwcDevices)
  494. return FALSE;
  495. //
  496. // Allocate our arrays up front.
  497. //
  498. pStatus = (NTSTATUS *)LocalAlloc(LPTR, dwcDevices * sizeof (NTSTATUS));
  499. if (pStatus == NULL) {
  500. RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
  501. return FALSE;
  502. }
  503. pfd = (PHANDLE)LocalAlloc(LPTR, dwcDevices * sizeof (HANDLE));
  504. if (pfd == NULL) {
  505. RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
  506. LocalFree(pStatus);
  507. return FALSE;
  508. }
  509. pUnicodeString = (PUNICODE_STRING)LocalAlloc(LPTR, dwcDevices * sizeof (UNICODE_STRING));
  510. if (pUnicodeString == NULL) {
  511. RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
  512. LocalFree(pStatus);
  513. LocalFree(pfd);
  514. return FALSE;
  515. }
  516. pEvent = (PHANDLE)LocalAlloc(
  517. LPTR,
  518. dwcDevices * sizeof (HANDLE));
  519. if (pEvent == NULL) {
  520. RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
  521. LocalFree(pStatus);
  522. LocalFree(pfd);
  523. LocalFree(pUnicodeString);
  524. return FALSE;
  525. }
  526. pObjectAttributes = (POBJECT_ATTRIBUTES)LocalAlloc(
  527. LPTR,
  528. dwcDevices * sizeof (OBJECT_ATTRIBUTES));
  529. if (pObjectAttributes == NULL) {
  530. RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
  531. LocalFree(pStatus);
  532. LocalFree(pfd);
  533. LocalFree(pUnicodeString);
  534. LocalFree(pEvent);
  535. return FALSE;
  536. }
  537. pIoStatusBlock = (PIO_STATUS_BLOCK)LocalAlloc(
  538. LPTR,
  539. dwcDevices * sizeof (IO_STATUS_BLOCK));
  540. if (pIoStatusBlock == NULL) {
  541. RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
  542. LocalFree(pStatus);
  543. LocalFree(pfd);
  544. LocalFree(pUnicodeString);
  545. LocalFree(pEvent);
  546. LocalFree(pObjectAttributes);
  547. return FALSE;
  548. }
  549. pBuffer = LocalAlloc(LPTR, dwcDevices * sizeof (PVOID));
  550. if (pBuffer == NULL) {
  551. RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
  552. LocalFree(pStatus);
  553. LocalFree(pfd);
  554. LocalFree(pUnicodeString);
  555. LocalFree(pEvent);
  556. LocalFree(pObjectAttributes);
  557. LocalFree(pIoStatusBlock);
  558. return FALSE;
  559. }
  560. //
  561. // Allocate and initialize our query structure.
  562. // We will give the same query to all the devices.
  563. //
  564. dwQuerySize = sizeof (TDI_REQUEST_QUERY_INFORMATION) +
  565. sizeof (TDI_CONNECTION_INFORMATION) +
  566. sizeof (TA_NETBIOS_ADDRESS);
  567. pQuery = LocalAlloc(LPTR, dwQuerySize);
  568. if (pQuery == NULL) {
  569. RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
  570. LocalFree(pStatus);
  571. LocalFree(pfd);
  572. LocalFree(pUnicodeString);
  573. LocalFree(pEvent);
  574. LocalFree(pObjectAttributes);
  575. LocalFree(pIoStatusBlock);
  576. return FALSE;
  577. }
  578. pQuery->QueryType = TDI_QUERY_ADAPTER_STATUS;
  579. (PTDI_CONNECTION_INFORMATION)&pQuery->RequestConnectionInformation;
  580. pQuery->RequestConnectionInformation =
  581. (PTDI_CONNECTION_INFORMATION)(pQuery + 1);
  582. pConnectionInformation = pQuery->RequestConnectionInformation;
  583. pConnectionInformation->UserDataLength = 0;
  584. pConnectionInformation->UserData = NULL;
  585. pConnectionInformation->OptionsLength = 0;
  586. pConnectionInformation->Options = NULL;
  587. pConnectionInformation->RemoteAddressLength = sizeof (TA_NETBIOS_ADDRESS);
  588. pConnectionInformation->RemoteAddress =
  589. (PTA_NETBIOS_ADDRESS)(pConnectionInformation + 1);
  590. pRemoteAddress = pConnectionInformation->RemoteAddress;
  591. pRemoteAddress->TAAddressCount = 1;
  592. pRemoteAddress->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
  593. pRemoteAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
  594. pRemoteAddress->Address[0].Address[0].NetbiosNameType =
  595. TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  596. UnicodeStringToAnsiString(
  597. pszAddress,
  598. szAddress,
  599. sizeof (szAddress));
  600. RtlFillMemory(
  601. (PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName,
  602. NCBNAMSZ,
  603. ' ');
  604. //
  605. // Make sure the Netbios name is in uppercase!
  606. //
  607. _strupr(szAddress);
  608. RtlCopyMemory(
  609. (PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName,
  610. szAddress,
  611. strlen(szAddress));
  612. pRemoteAddress->Address[0].Address[0].NetbiosName[NCBNAMSZ - 1] = '\0';
  613. RASAUTO_TRACE1("NetbiosFindName: address=%s", szAddress);
  614. //
  615. // Initialize the OBJECT_ATTRIBUTES structure,
  616. // open the device, and start the query
  617. // for each device.
  618. //
  619. for (i = 0; i < dwcDevices; i++) {
  620. pBuffer[i] = NULL;
  621. RtlInitUnicodeString(&pUnicodeString[i], pszDevices[i]);
  622. InitializeObjectAttributes(
  623. &pObjectAttributes[i],
  624. &pUnicodeString[i],
  625. OBJ_CASE_INSENSITIVE,
  626. NULL,
  627. NULL);
  628. pEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
  629. if (pEvent[i] == NULL) {
  630. RASAUTO_TRACE("NetbiosFindName: CreateEvent failed");
  631. goto done;
  632. }
  633. pStatus[i] = NtCreateFile(
  634. &pfd[i],
  635. FILE_READ_DATA|FILE_WRITE_DATA,
  636. &pObjectAttributes[i],
  637. &pIoStatusBlock[i],
  638. NULL,
  639. FILE_ATTRIBUTE_NORMAL,
  640. FILE_SHARE_READ|FILE_SHARE_WRITE,
  641. FILE_OPEN_IF,
  642. 0,
  643. NULL,
  644. 0);
  645. if (!NT_SUCCESS(pStatus[i])) {
  646. RASAUTO_TRACE1("NetbiosFindName: NtCreateFile failed (status=0x%x)", pStatus[i]);
  647. continue;
  648. }
  649. //
  650. // Allocate the results buffer.
  651. //
  652. dwBufferSize = 2048;
  653. for (;;) {
  654. pBuffer[i] = LocalAlloc(LPTR, dwBufferSize);
  655. if (pBuffer[i] == NULL) {
  656. RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed");
  657. goto done;
  658. }
  659. pStatus[i] = NtDeviceIoControlFile(
  660. pfd[i],
  661. pEvent[i],
  662. NULL,
  663. NULL,
  664. &pIoStatusBlock[i],
  665. IOCTL_TDI_QUERY_INFORMATION,
  666. pQuery,
  667. dwQuerySize,
  668. pBuffer[i],
  669. dwBufferSize);
  670. if (pStatus[i] != STATUS_BUFFER_OVERFLOW)
  671. break;
  672. LocalFree(pBuffer[i]);
  673. pBuffer[i] = NULL;
  674. dwBufferSize *= 2;
  675. if (dwBufferSize >= 0xffff) {
  676. RASAUTO_TRACE("NetbiosFindName: Unable to allocate packet");
  677. break;
  678. }
  679. }
  680. }
  681. //
  682. // Determine whether any of the
  683. // requests returned STATUS_SUCCESS.
  684. //
  685. RASAUTO_TRACE("NetbiosFindName: checking for STATUS_SUCCESS");
  686. dwcWait = 0;
  687. for (i = 0; i < dwcDevices; i++) {
  688. RASAUTO_TRACE2("NetbiosFindName: %S: status=%d", pszDevices[i], pStatus[i]);
  689. if (pStatus[i] == STATUS_SUCCESS) {
  690. pAdapterStatus = (PADAPTERSTATUS)pBuffer[i];
  691. dwcNames = pAdapterStatus->AdapterInfo.name_count;
  692. RASAUTO_TRACE2(
  693. "NetbiosFindName: %S: dwcNames=%d",
  694. pszDevices[i],
  695. dwcNames);
  696. if (dwcNames) {
  697. bFound = TRUE;
  698. goto done;
  699. }
  700. }
  701. else if (pStatus[i] == STATUS_PENDING)
  702. dwcWait++;
  703. }
  704. //
  705. // If we didn't find a successful return,
  706. // then wait for the others to complete.
  707. //
  708. RASAUTO_TRACE1("NetbiosFindName: dwcWait=%d", dwcWait);
  709. for (i = 0; i < dwcWait; i++) {
  710. NTSTATUS status;
  711. DWORD dwiDevice;
  712. status = WaitForMultipleObjects(dwcDevices, pEvent, FALSE, INFINITE);
  713. RASAUTO_TRACE1("NetbiosFindName: WaitForMultipleObjects returned 0x%x", status);
  714. if (status == WAIT_FAILED) {
  715. RASAUTO_TRACE1(
  716. "NetbiosFindName: WaitForMultipleObjects failed (status=0x%x)",
  717. GetLastError());
  718. goto done;
  719. }
  720. dwiDevice = (DWORD)status - WAIT_OBJECT_0;
  721. if (dwiDevice >= dwcDevices) {
  722. RASAUTO_TRACE(
  723. "NetbiosFindName: WaitForMultipleObjects returned STATUS_ABANDONED?");
  724. goto done;
  725. }
  726. pStatus[dwiDevice] = pIoStatusBlock[dwiDevice].Status;
  727. RASAUTO_TRACE2(
  728. "NetbiosFindName: %S returned status 0x%x from wait",
  729. pszDevices[dwiDevice],
  730. pStatus[dwiDevice]);
  731. if (pStatus[dwiDevice] == STATUS_SUCCESS) {
  732. pAdapterStatus = (PADAPTERSTATUS)pBuffer[dwiDevice];
  733. dwcNames = pAdapterStatus->AdapterInfo.name_count;
  734. RASAUTO_TRACE2(
  735. "NetbiosFindName: %S: dwcNames=%d",
  736. pszDevices[dwiDevice],
  737. dwcNames);
  738. if (dwcNames) {
  739. bFound = TRUE;
  740. goto done;
  741. }
  742. }
  743. }
  744. done:
  745. //
  746. // Free the resources associated with
  747. // each device.
  748. //
  749. for (i = 0; i < dwcDevices; i++) {
  750. RASAUTO_TRACE4(
  751. "NetbiosFindName: pIoStatusBlock[%d]=0x%x, pBuffer[%d]=0x%x",
  752. i,
  753. &pIoStatusBlock[i],
  754. i,
  755. pBuffer[i]);
  756. if (pfd[i] != NULL)
  757. {
  758. (void)NtCancelIoFile(pfd[i], &pIoStatusBlock[i]);
  759. NtClose(pfd[i]);
  760. }
  761. if (pEvent[i] != NULL)
  762. CloseHandle(pEvent[i]);
  763. if (pBuffer[i] != NULL)
  764. LocalFree(pBuffer[i]);
  765. }
  766. //
  767. // Free the buffers we allocated above.
  768. //
  769. LocalFree(pStatus);
  770. LocalFree(pfd);
  771. LocalFree(pUnicodeString);
  772. LocalFree(pEvent);
  773. LocalFree(pObjectAttributes);
  774. LocalFree(pIoStatusBlock);
  775. LocalFree(pBuffer);
  776. return bFound;
  777. } // NetbiosFindName
  778. struct hostent *
  779. IpAddressToHostent(
  780. IN LPTSTR pszInetAddress
  781. )
  782. {
  783. CHAR szInetAddress[ACD_ADDR_INET_LEN];
  784. ULONG inaddr;
  785. struct hostent *hp;
  786. UnicodeStringToAnsiString(
  787. pszInetAddress,
  788. szInetAddress,
  789. sizeof (szInetAddress));
  790. inaddr = inet_addr(szInetAddress);
  791. //
  792. // Disable the address so when we call gethostbyname(),
  793. // we won't cause an autodial attempt. Enable it after
  794. // we're done.
  795. //
  796. SetAddressDisabled(pszInetAddress, TRUE);
  797. hp = gethostbyaddr((char *)&inaddr, 4, PF_INET);
  798. SetAddressDisabled(pszInetAddress, FALSE);
  799. return hp;
  800. } // InetAddressToHostent
  801. struct hostent *
  802. InetAddressToHostent(
  803. IN LPTSTR pszInetAddress
  804. )
  805. {
  806. CHAR szInetAddress[ACD_ADDR_INET_LEN];
  807. struct hostent *hp;
  808. UnicodeStringToAnsiString(
  809. pszInetAddress,
  810. szInetAddress,
  811. sizeof (szInetAddress));
  812. //
  813. // Disable the address so when we call gethostbyname(),
  814. // we won't cause an autodial attempt. Enable it after
  815. // we're done.
  816. //
  817. SetAddressDisabled(pszInetAddress, TRUE);
  818. hp = gethostbyname(szInetAddress);
  819. SetAddressDisabled(pszInetAddress, FALSE);
  820. return hp;
  821. } // InetAddressToHostEnt
  822. BOOLEAN
  823. PingIpAddress(
  824. IN LPTSTR pszIpAddress
  825. )
  826. /*++
  827. DESCRIPTION
  828. Determine whether an IP address is accessible by pinging it.
  829. ARGUMENTS
  830. lpszAddress: the IP address
  831. RETURN VALUE
  832. TRUE if lpszAddress is accessible, FALSE otherwise.
  833. --*/
  834. {
  835. BOOLEAN fSuccess = FALSE;
  836. LONG inaddr;
  837. char szIpAddress[17];
  838. int i, nReplies, nTry;
  839. char *lpSendBuf = NULL, *lpRecvBuf = NULL;
  840. HANDLE hIcmp = NULL;
  841. IP_OPTION_INFORMATION SendOpts;
  842. PICMP_ECHO_REPLY lpReply;
  843. UnicodeStringToAnsiString(pszIpAddress, szIpAddress, sizeof (szIpAddress));
  844. inaddr = inet_addr(szIpAddress);
  845. RASAUTO_TRACE2("PingIpAddress: IP address=(%s, 0x%x)", szIpAddress, inaddr);
  846. //
  847. // Check to make sure we loaded icmp.dll.
  848. //
  849. if (hIcmpG == NULL) {
  850. RASAUTO_TRACE("PingIpAddress: icmp.dll not loaded!");
  851. return FALSE;
  852. }
  853. //
  854. // Open the icmp device.
  855. //
  856. hIcmp = (HANDLE)(*lpfnIcmpCreateFileG)();
  857. if (hIcmp == INVALID_HANDLE_VALUE) {
  858. RASAUTO_TRACE("PingIpAddress: IcmpCreateFile failed");
  859. return FALSE;
  860. }
  861. //
  862. // Allocate the send and receive buffers.
  863. //
  864. lpSendBuf = LocalAlloc(LMEM_FIXED, PING_SEND_SIZE);
  865. if (lpSendBuf == NULL) {
  866. RASAUTO_TRACE("PingIpAddress: LocalAlloc failed");
  867. goto done;
  868. }
  869. lpRecvBuf = LocalAlloc(LMEM_FIXED, PING_RECV_SIZE);
  870. if (lpRecvBuf == NULL) {
  871. RASAUTO_TRACE("PingIpAddress: LocalAlloc failed");
  872. goto done;
  873. }
  874. //
  875. // Initialize the send buffer pattern.
  876. //
  877. for (i = 0; i < PING_SEND_SIZE; i++)
  878. lpSendBuf[i] = 'a' + (i % 23);
  879. //
  880. // Initialize the send options.
  881. //
  882. SendOpts.OptionsData = (unsigned char FAR *)0;
  883. SendOpts.OptionsSize = 0;
  884. SendOpts.Ttl = PING_TTL;
  885. SendOpts.Tos = 0;
  886. SendOpts.Flags = 0;
  887. //
  888. // Ping the host.
  889. //
  890. for (nTry = 0; nTry < 3; nTry++) {
  891. DWORD dwTimeout = 750;
  892. #ifdef notdef
  893. if (nTry < 2)
  894. dwTimeout = 750;
  895. else
  896. dwTimeout = 2000;
  897. #endif
  898. //
  899. // Check to make sure the service isn't shutting
  900. // down before we start on our next iteration.
  901. //
  902. if (WaitForSingleObject(hTerminatingG, 0) != WAIT_TIMEOUT) {
  903. RASAUTO_TRACE("PingIpAddress: shutting down");
  904. LocalFree(lpRecvBuf);
  905. LocalFree(lpSendBuf);
  906. return FALSE;
  907. }
  908. nReplies = (int) (*lpfnIcmpSendEchoG)(
  909. hIcmp,
  910. inaddr,
  911. lpSendBuf,
  912. (unsigned short)PING_SEND_SIZE,
  913. &SendOpts,
  914. lpRecvBuf,
  915. PING_RECV_SIZE,
  916. dwTimeout);
  917. //
  918. // Look at the responses to see
  919. // if any are successful.
  920. //
  921. for (lpReply = (PICMP_ECHO_REPLY)lpRecvBuf, i = 0;
  922. i < nReplies;
  923. lpReply++, i++)
  924. {
  925. RASAUTO_TRACE2(
  926. "PingIpAddress: ping reply status[%d]=%d",
  927. i,
  928. lpReply->Status);
  929. //
  930. // Unless the status is IP_REQ_TIMED_OUT,
  931. // we're done.
  932. //
  933. fSuccess = (lpReply->Status == IP_SUCCESS);
  934. if (lpReply->Status != IP_REQ_TIMED_OUT)
  935. goto done;
  936. }
  937. }
  938. //
  939. // Clean up.
  940. //
  941. done:
  942. if (lpRecvBuf != NULL)
  943. LocalFree(lpRecvBuf);
  944. if (lpSendBuf != NULL)
  945. LocalFree(lpSendBuf);
  946. if (hIcmp != NULL)
  947. (*lpfnIcmpCloseHandleG)(hIcmp);
  948. return fSuccess;
  949. } // PingIpAddress
  950. VOID
  951. LoadIcmpDll(VOID)
  952. {
  953. hIcmpG = LoadLibrary(ICMP_MODULE);
  954. if (hIcmpG == NULL)
  955. return;
  956. lpfnIcmpCreateFileG = GetProcAddress(hIcmpG, ICMPCREATEFILE);
  957. lpfnIcmpSendEchoG = GetProcAddress(hIcmpG, ICMPSENDECHO);
  958. lpfnIcmpCloseHandleG = GetProcAddress(hIcmpG, ICMPCLOSEHANDLE);
  959. if (lpfnIcmpCreateFileG == NULL ||
  960. lpfnIcmpSendEchoG == NULL ||
  961. lpfnIcmpCloseHandleG == NULL)
  962. {
  963. FreeLibrary(hIcmpG);
  964. hIcmpG = NULL;
  965. return;
  966. }
  967. } // LoadIcmpDll
  968. VOID
  969. UnloadIcmpDll(VOID)
  970. {
  971. if (hIcmpG != NULL) {
  972. FreeLibrary(hIcmpG);
  973. hIcmpG = NULL;
  974. }
  975. }