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.

1209 lines
35 KiB

  1. /*++
  2. Copyright (C) 1999 Microsoft Corporation
  3. --*/
  4. #include "precomp.h"
  5. NTSTATUS
  6. DeviceIoCtrl(
  7. IN HANDLE fd,
  8. IN PVOID ReturnBuffer,
  9. IN ULONG BufferSize,
  10. IN ULONG Ioctl,
  11. IN PVOID pInput,
  12. IN ULONG SizeInput
  13. );
  14. void DisplayInfo(int uNames, u_long ulValidAddr);
  15. LPWSTR ToWCS(LPCSTR szMBCSString)
  16. {
  17. int nResult = 0;
  18. LPWSTR lpWideString = NULL;
  19. // determone the size first
  20. nResult = MultiByteToWideChar(
  21. CP_ACP,
  22. 0,
  23. szMBCSString,
  24. -1,
  25. lpWideString,
  26. 0);
  27. lpWideString = WinsAllocateMemory((nResult+1)*sizeof(WCHAR));
  28. if( lpWideString is NULL )
  29. return NULL;
  30. nResult = MultiByteToWideChar(
  31. CP_ACP,
  32. MB_COMPOSITE,
  33. szMBCSString,
  34. -1,
  35. lpWideString,
  36. (nResult+1)*sizeof(WCHAR));
  37. if( nResult is 0 )
  38. {
  39. WinsFreeMemory(lpWideString);
  40. lpWideString = NULL;
  41. }
  42. else
  43. {
  44. lpWideString[nResult + 1] = '\0';
  45. }
  46. return lpWideString;
  47. }
  48. //------------------------------------------------------------------------
  49. NTSTATUS
  50. GetIpAddress(
  51. IN HANDLE fd,
  52. OUT PULONG pIpAddress
  53. )
  54. /*++
  55. Routine Description:
  56. This function calls into netbt to get the ip address.
  57. Arguments:
  58. fd - file handle to netbt
  59. pIpAddress - the ip address returned
  60. Return Value:
  61. ntstatus
  62. History:
  63. 27-Dec-1995 CDermody copied from nbtstat.c
  64. --*/
  65. {
  66. NTSTATUS status;
  67. ULONG BufferSize=100;
  68. PVOID pBuffer;
  69. pBuffer = LocalAlloc(LMEM_FIXED,BufferSize);
  70. if (!pBuffer)
  71. {
  72. return(STATUS_INSUFFICIENT_RESOURCES);
  73. }
  74. status = DeviceIoCtrl(fd,
  75. pBuffer,
  76. BufferSize,
  77. IOCTL_NETBT_GET_IP_ADDRS,
  78. NULL,
  79. 0);
  80. if (NT_SUCCESS(status))
  81. {
  82. *pIpAddress = *(ULONG *)pBuffer;
  83. }
  84. else
  85. {
  86. *pIpAddress = 0;
  87. }
  88. LocalFree(pBuffer);
  89. return(status);
  90. }
  91. //------------------------------------------------------------------------
  92. NTSTATUS
  93. GetInterfaceList
  94. (
  95. char pDeviceName[][MAX_NAME+1]
  96. )
  97. {
  98. HANDLE StreamHandle;
  99. OBJECT_ATTRIBUTES ObjectAttributes;
  100. IO_STATUS_BLOCK IoStatusBlock;
  101. STRING name_string, AnsiString;
  102. UNICODE_STRING uc_name_string;
  103. NTSTATUS status;
  104. char pNbtWinsDeviceName[MAX_NAME] = "\\Device\\NetBt_Wins_Export";
  105. PUCHAR SubKeyParms = "system\\currentcontrolset\\services\\netbt\\parameters";
  106. PUCHAR Scope = "ScopeId";
  107. CHAR pScopeBuffer[BUFF_SIZE];
  108. HKEY Key;
  109. LONG Type;
  110. ULONG size;
  111. NETBT_INTERFACE_INFO *pInterfaceInfo;
  112. ULONG InterfaceInfoSize = 10 * sizeof(NETBT_ADAPTER_INDEX_MAP) + sizeof(ULONG);
  113. PVOID pInput = NULL;
  114. ULONG SizeInput = 0;
  115. LONG i, index = 0;
  116. pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize);
  117. if (!pInterfaceInfo)
  118. {
  119. return(STATUS_INSUFFICIENT_RESOURCES);
  120. }
  121. RtlInitString(&name_string, pNbtWinsDeviceName);
  122. RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE);
  123. InitializeObjectAttributes(
  124. &ObjectAttributes,
  125. &uc_name_string,
  126. OBJ_CASE_INSENSITIVE,
  127. (HANDLE) NULL,
  128. (PSECURITY_DESCRIPTOR) NULL
  129. );
  130. status = NtCreateFile (&StreamHandle,
  131. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  132. &ObjectAttributes,
  133. &IoStatusBlock,
  134. NULL,
  135. FILE_ATTRIBUTE_NORMAL,
  136. FILE_SHARE_READ | FILE_SHARE_WRITE,
  137. FILE_OPEN_IF,
  138. 0,
  139. NULL,
  140. 0);
  141. RtlFreeUnicodeString(&uc_name_string);
  142. if (NT_SUCCESS (status))
  143. {
  144. do
  145. {
  146. status = DeviceIoCtrl(StreamHandle,
  147. pInterfaceInfo,
  148. InterfaceInfoSize,
  149. IOCTL_NETBT_GET_INTERFACE_INFO,
  150. pInput,
  151. SizeInput);
  152. if (status == STATUS_BUFFER_OVERFLOW)
  153. {
  154. LocalFree(pInterfaceInfo);
  155. InterfaceInfoSize *= 2;
  156. pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize);
  157. if (!pInterfaceInfo || (InterfaceInfoSize == 0xFFFF))
  158. {
  159. NtClose(StreamHandle);
  160. //NlsPerror(COMMON_UNABLE_TO_ALLOCATE_PACKET,0);
  161. return(STATUS_INSUFFICIENT_RESOURCES);
  162. }
  163. }
  164. else if (!NT_SUCCESS (status))
  165. {
  166. NtClose(StreamHandle);
  167. return(status);
  168. }
  169. } while (status == STATUS_BUFFER_OVERFLOW);
  170. NtClose (StreamHandle);
  171. for (i = 0; i<pInterfaceInfo->NumAdapters; i++)
  172. {
  173. RtlInitString(&name_string, NULL);
  174. RtlInitUnicodeString(&uc_name_string, pInterfaceInfo->Adapter[i].Name);
  175. if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name_string, &uc_name_string, TRUE)))
  176. {
  177. size = (name_string.Length > MAX_NAME) ? MAX_NAME : name_string.Length;
  178. strncpy(pDeviceName[index], name_string.Buffer, size);
  179. pDeviceName[index][size] = '\0';
  180. RtlFreeAnsiString (&name_string);
  181. index++;
  182. }
  183. }
  184. //
  185. // NULL out the next device string ptr
  186. //
  187. if (index < NBT_MAXIMUM_BINDINGS)
  188. {
  189. pDeviceName[index][0] = '\0';
  190. }
  191. //
  192. // Read the ScopeId key!
  193. //
  194. size = BUFF_SIZE;
  195. *pScope = '\0'; // By default
  196. status = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
  197. SubKeyParms,
  198. 0,
  199. KEY_READ,
  200. &Key);
  201. if (status == ERROR_SUCCESS)
  202. {
  203. // now read the Scope key
  204. status = RegQueryValueExA(Key, Scope, NULL, &Type, pScopeBuffer, &size);
  205. if (status == ERROR_SUCCESS)
  206. {
  207. strcpy(pScope,pScopeBuffer);
  208. }
  209. status = RegCloseKey(Key);
  210. }
  211. status = STATUS_SUCCESS;
  212. }
  213. return status;
  214. }
  215. //------------------------------------------------------------------------
  216. NTSTATUS
  217. OpenNbt(
  218. IN char path[][MAX_NAME+1],
  219. OUT PHANDLE pHandle,
  220. int max_paths
  221. )
  222. {
  223. HANDLE StreamHandle;
  224. OBJECT_ATTRIBUTES ObjectAttributes;
  225. IO_STATUS_BLOCK IoStatusBlock;
  226. STRING name_string;
  227. UNICODE_STRING uc_name_string;
  228. NTSTATUS status;
  229. LONG index=0;
  230. ASSERT ( max_paths <= NBT_MAXIMUM_BINDINGS );
  231. while ((path[index][0] != '\0') && (index < max_paths))
  232. {
  233. RtlInitString(&name_string, path[index]);
  234. RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE);
  235. InitializeObjectAttributes(
  236. &ObjectAttributes,
  237. &uc_name_string,
  238. OBJ_CASE_INSENSITIVE,
  239. (HANDLE) NULL,
  240. (PSECURITY_DESCRIPTOR) NULL
  241. );
  242. status =
  243. NtCreateFile(
  244. &StreamHandle,
  245. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  246. &ObjectAttributes,
  247. &IoStatusBlock,
  248. NULL,
  249. FILE_ATTRIBUTE_NORMAL,
  250. FILE_SHARE_READ | FILE_SHARE_WRITE,
  251. FILE_OPEN_IF,
  252. 0,
  253. NULL,
  254. 0);
  255. RtlFreeUnicodeString(&uc_name_string);
  256. if (NT_SUCCESS(status))
  257. {
  258. *pHandle = StreamHandle;
  259. return(status);
  260. }
  261. ++index;
  262. }
  263. return (status);
  264. } // s_open
  265. //------------------------------------------------------------------------
  266. NTSTATUS
  267. DeviceIoCtrl(
  268. IN HANDLE fd,
  269. IN PVOID ReturnBuffer,
  270. IN ULONG BufferSize,
  271. IN ULONG Ioctl,
  272. IN PVOID pInput,
  273. IN ULONG SizeInput
  274. )
  275. /*++
  276. Routine Description:
  277. This procedure performs an ioctl(I_STR) on a stream.
  278. Arguments:
  279. fd - NT file handle
  280. iocp - pointer to a strioctl structure
  281. Return Value:
  282. 0 if successful, non-zero otherwise.
  283. History:
  284. 27-Dec-1995 CDermody copied from nbtstat.c
  285. --*/
  286. {
  287. NTSTATUS status;
  288. int retval;
  289. ULONG QueryType;
  290. IO_STATUS_BLOCK iosb;
  291. status = NtDeviceIoControlFile(
  292. fd, // Handle
  293. NULL, // Event
  294. NULL, // ApcRoutine
  295. NULL, // ApcContext
  296. &iosb, // IoStatusBlock
  297. Ioctl, // IoControlCode
  298. pInput, // InputBuffer
  299. SizeInput, // InputBufferSize
  300. (PVOID) ReturnBuffer, // OutputBuffer
  301. BufferSize); // OutputBufferSize
  302. if (status == STATUS_PENDING)
  303. {
  304. status = NtWaitForSingleObject(
  305. fd, // Handle
  306. TRUE, // Alertable
  307. NULL); // Timeout
  308. if (NT_SUCCESS(status))
  309. {
  310. status = iosb.Status;
  311. }
  312. }
  313. return(status);
  314. }
  315. /****************************************************************************/
  316. /* CheckRemoteTable */
  317. /* */
  318. /* This routine does an adapter status query to get the remote name table */
  319. /* then checks to see if a netbios name is contained in it. */
  320. /* */
  321. /* Parameters: */
  322. /* RemoteName, the IP address (asci nn.nn.nn.nn format) of a server to */
  323. /* query. */
  324. /* SearchName, a net bios name. */
  325. /* */
  326. /* Return: */
  327. /* WINSTEST_VERIFIED The name exists in the remote name table */
  328. /* WINSTEST_NOT_VERIFIED The name does not exist in the remote table */
  329. /* WINSTEST_BAD_IP_ADDRESS inet_addr could not convert the ip address */
  330. /* character string. */
  331. /* WINSTEST_HOST_NOT_FOUND Could not reach ip address */
  332. /* WINSTEST_OUT_OF_MEMORY Out of memory */
  333. /* History: */
  334. /* 27-Dec-1995 CDermody created following example of nbtstat.c */
  335. /****************************************************************************/
  336. int
  337. CheckRemoteTable(
  338. IN HANDLE fd,
  339. IN PCHAR RemoteName,
  340. IN PCHAR SearchName
  341. )
  342. {
  343. LONG Count;
  344. LONG i;
  345. PVOID pBuffer;
  346. ULONG BufferSize=600;
  347. NTSTATUS status;
  348. tADAPTERSTATUS *pAdapterStatus;
  349. NAME_BUFFER *pNames;
  350. CHAR MacAddress[20];
  351. tIPANDNAMEINFO *pIpAndNameInfo;
  352. ULONG SizeInput;
  353. ULONG IpAddress;
  354. USHORT BytesToCopy;
  355. pBuffer = LocalAlloc(LMEM_FIXED,BufferSize);
  356. if (!pBuffer)
  357. {
  358. return(WINSTEST_OUT_OF_MEMORY);
  359. }
  360. status = STATUS_BUFFER_OVERFLOW;
  361. pIpAndNameInfo = LocalAlloc(LMEM_FIXED,sizeof(tIPANDNAMEINFO));
  362. if (!pIpAndNameInfo)
  363. {
  364. LocalFree(pBuffer);
  365. return(WINSTEST_OUT_OF_MEMORY);
  366. }
  367. RtlZeroMemory((PVOID)pIpAndNameInfo,sizeof(tIPANDNAMEINFO));
  368. //
  369. // Convert the remote name which is really a dotted decimal ip address
  370. // into a ulong
  371. //
  372. IpAddress = inet_addr(RemoteName);
  373. //
  374. // Don't allow zero for the address since it sends a broadcast and
  375. // every one responds
  376. //
  377. if ((IpAddress == INADDR_NONE) || (IpAddress == 0))
  378. {
  379. LocalFree(pBuffer);
  380. LocalFree(pIpAndNameInfo);
  381. return(WINSTEST_BAD_IP_ADDRESS);
  382. }
  383. pIpAndNameInfo->IpAddress = ntohl(IpAddress);
  384. pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosName[0] = '*';
  385. pIpAndNameInfo->NetbiosAddress.TAAddressCount = 1;
  386. pIpAndNameInfo->NetbiosAddress.Address[0].AddressLength
  387. = sizeof(TDI_ADDRESS_NETBIOS);
  388. pIpAndNameInfo->NetbiosAddress.Address[0].AddressType
  389. = TDI_ADDRESS_TYPE_NETBIOS;
  390. pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosNameType
  391. = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
  392. SizeInput = sizeof(tIPANDNAMEINFO);
  393. while (status == STATUS_BUFFER_OVERFLOW)
  394. {
  395. status = DeviceIoCtrl(fd,
  396. pBuffer,
  397. BufferSize,
  398. IOCTL_NETBT_ADAPTER_STATUS,
  399. pIpAndNameInfo,
  400. SizeInput);
  401. if (status == STATUS_BUFFER_OVERFLOW)
  402. {
  403. LocalFree(pBuffer);
  404. BufferSize *=2;
  405. pBuffer = LocalAlloc(LMEM_FIXED,BufferSize);
  406. if (!pBuffer || (BufferSize == 0xFFFF))
  407. {
  408. LocalFree(pIpAndNameInfo);
  409. return(WINSTEST_OUT_OF_MEMORY);
  410. }
  411. }
  412. }
  413. pAdapterStatus = (tADAPTERSTATUS *)pBuffer;
  414. if ((pAdapterStatus->AdapterInfo.name_count == 0) ||
  415. (status != STATUS_SUCCESS))
  416. {
  417. LocalFree(pIpAndNameInfo);
  418. LocalFree(pBuffer);
  419. return(WINSTEST_HOST_NOT_FOUND);
  420. }
  421. pNames = pAdapterStatus->Names;
  422. Count = pAdapterStatus->AdapterInfo.name_count;
  423. status = 1;
  424. while (Count--)
  425. {
  426. if (0 == _strnicmp(SearchName, pNames->name, strlen(SearchName)))
  427. {
  428. LocalFree(pIpAndNameInfo);
  429. LocalFree(pBuffer);
  430. return WINSTEST_VERIFIED; // found
  431. }
  432. pNames++;
  433. }
  434. LocalFree(pIpAndNameInfo);
  435. LocalFree(pBuffer);
  436. return WINSTEST_NOT_VERIFIED;
  437. }
  438. /****************************************************************************/
  439. /* VerifyRemote */
  440. /* */
  441. /* This routine checks to see if a netbios name is contained in the remote */
  442. /* name table at a given IP address. */
  443. /* */
  444. /* Parameters: */
  445. /* RemoteName, the IP address (asci nn.nn.nn.nn format) of a server to */
  446. /* query. */
  447. /* NBName, a net bios name. */
  448. /* */
  449. /* Return: */
  450. /* WINSTEST_VERIFIED The name exists in the remote name table */
  451. /* WINSTEST_NOT_VERIFIED The name does not exist in the remote table */
  452. /* WINSTEST_BAD_IP_ADDRESS inet_addr could not convert the ip address */
  453. /* character string. */
  454. /* WINSTEST_OPEN_FAILED Could not open NBT driver or could not read */
  455. /* the NBT driver info from the registry. */
  456. /* WINSTEST_HOST_NOT_FOUND Could not reach ip address */
  457. /* WINSTEST_OUT_OF_MEMORY Out of memory */
  458. /* History: */
  459. /* 27-Dec-1995 CDermody created following example of nbtstat.c */
  460. /****************************************************************************/
  461. int VerifyRemote(IN PCHAR RemoteName, IN PCHAR NBName)
  462. {
  463. NTSTATUS status;
  464. LONG interval=-1;
  465. HANDLE nbt = 0;
  466. int nStatus;
  467. int index;
  468. CHAR pDeviceName[NBT_MAXIMUM_BINDINGS+1][MAX_NAME+1];
  469. status = GetInterfaceList(pDeviceName);
  470. if (!NT_SUCCESS(status))
  471. {
  472. return WINSTEST_OPEN_FAILED;
  473. }
  474. for (index = 0; index < NBT_MAXIMUM_BINDINGS && pDeviceName[index][0]; index++)
  475. {
  476. //
  477. // Open the device of the appropriate streams module to start with.
  478. //
  479. status = OpenNbt(&pDeviceName[index], &nbt, NBT_MAXIMUM_BINDINGS-index);
  480. if (!NT_SUCCESS(status))
  481. {
  482. //
  483. // Try the next binding!
  484. //
  485. continue;
  486. }
  487. GetIpAddress(nbt, &NetbtIpAddress);
  488. if (RemoteName[0] == '\0')
  489. return WINSTEST_INVALID_ARG;
  490. status = (NTSTATUS)CheckRemoteTable(nbt,RemoteName,NBName);
  491. if (status == WINSTEST_VERIFIED)
  492. break;
  493. }
  494. return status;
  495. }
  496. /*************************************************************/
  497. /* NBEncode(name2,name) */
  498. /* */
  499. /* This routine code a netbios name from level1 to level2. */
  500. /* name2 has to be NBT_NAMESIZE bytes long, remember that. */
  501. /*************************************************************/
  502. void
  503. NBEncode(
  504. unsigned char *name2,
  505. unsigned char *name
  506. )
  507. {
  508. int i;
  509. name2[0] = 0x20; /* length of first block */
  510. for (i = 0; i < NBT_NONCODED_NMSZ - 1; i++)
  511. {
  512. name2[ 2*i+1 ] = ((name[ i ] >> 4) & 0x0f) + 0x41;
  513. name2[ 2*i+2 ] = (name[ i ] & 0x0f) + 0x41;
  514. }
  515. name2[ NBT_NAMESIZE-1 ] = 0; /* length of next block */
  516. }
  517. /*******************************************************************/
  518. /* */
  519. /* Send a Name Query to a WINS Server */
  520. /* */
  521. /* name is the name to query */
  522. /* winsaddr is the ip address of the wins server to query */
  523. /* TransID is the transaction ID to use for the query */
  524. /* */
  525. /*******************************************************************/
  526. void
  527. SendNameQuery(
  528. unsigned char *name,
  529. u_long winsaddr,
  530. u_short TransID
  531. )
  532. {
  533. struct sockaddr_in destad;
  534. char lpResults[MAX_SIZE] = {0};
  535. char paddedname[NBT_NONCODED_NMSZ];
  536. USHORT usEndPoint = 5005;
  537. int err = 0;
  538. struct
  539. {
  540. u_short TransactionID;
  541. u_short Flags;
  542. u_short QuestionCount;
  543. u_short AnswerCount;
  544. u_short NSCount;
  545. u_short AdditionalRec;
  546. u_char QuestionName[NBT_NAMESIZE];
  547. u_short QuestionType;
  548. u_short QuestionClass;
  549. } NameQuery;
  550. memset(paddedname, 0x20, sizeof(paddedname));
  551. memcpy(paddedname, name, strlen(name));
  552. NBEncode(NameQuery.QuestionName, paddedname);
  553. NameQuery.TransactionID = htons(TransID);
  554. NameQuery.Flags = htons(0x0100);
  555. NameQuery.QuestionCount = htons(1);
  556. NameQuery.AnswerCount = 0;
  557. NameQuery.NSCount = 0;
  558. NameQuery.AdditionalRec = 0;
  559. NameQuery.QuestionType = htons(0x0020);
  560. NameQuery.QuestionClass = htons(1);
  561. destad.sin_family = AF_INET;
  562. destad.sin_port = htons(137);
  563. destad.sin_addr.s_addr = winsaddr;
  564. err = sendto(sd, (char *)&NameQuery, sizeof(NameQuery), 0,
  565. (struct sockaddr *)&destad, sizeof(myad));
  566. if( err is SOCKET_ERROR )
  567. {
  568. DisplayErrorMessage(EMSG_WINS_SENDTO_FAILED, WSAGetLastError());
  569. return;
  570. }
  571. }
  572. /*******************************************************************/
  573. /* */
  574. /* Wait for a Name Response which matches the Transaction ID */
  575. /* */
  576. /* recvaddr is the ip address returned by the wins server */
  577. /* */
  578. /*******************************************************************/
  579. int
  580. GetNameResponse(
  581. u_long * recvaddr,
  582. u_short TransactionID
  583. )
  584. {
  585. char lpResults[100] = {0};
  586. int i;
  587. int len;
  588. int rslt;
  589. u_long AnswerAddr;
  590. struct sockaddr_in addr;
  591. NameResponse * pNameResponse = NULL;
  592. BYTE Buf[NAME_RESPONSE_BUFFER_SIZE] = {0};
  593. i = 0;
  594. while (i < 15)
  595. {
  596. addrlen = sizeof(addr);
  597. if ((len=recvfrom(sd, (char *) Buf, sizeof(Buf), 0,
  598. (struct sockaddr *)&addr, &addrlen)) < 0)
  599. {
  600. rslt = WSAGetLastError();
  601. if (rslt == WSAEWOULDBLOCK)
  602. {
  603. Sleep(100);
  604. i++;
  605. continue;
  606. }
  607. else
  608. {
  609. DisplayErrorMessage(EMSG_WINS_GETRESPONSE_FAILED,
  610. rslt);
  611. return WINSTEST_NO_RESPONSE;
  612. }
  613. }
  614. pNameResponse = (NameResponse *) Buf;
  615. if (TransactionID == htons(pNameResponse->TransactionID))
  616. {
  617. if (htons(pNameResponse->AnswerCount) == 0)
  618. {
  619. *recvaddr = 0;
  620. return(WINSTEST_NOT_FOUND);
  621. }
  622. AnswerAddr = (pNameResponse->AnswerAddr2 << 16) | pNameResponse->AnswerAddr1;
  623. *recvaddr = AnswerAddr;
  624. return(WINSTEST_FOUND);
  625. }
  626. }
  627. *recvaddr = 0;
  628. return(WINSTEST_NO_RESPONSE);
  629. }
  630. INT
  631. InitNameCheckSocket()
  632. {
  633. WCHAR lpResults[MAX_SIZE];
  634. BOOL fBroadcast = TRUE;
  635. INT err = 0;
  636. /* Set up a socket to use for querys and responses */
  637. WSAStartup( 0x0101, &WsaData ); // make sure winsock is happy - noop for now
  638. if ((sd = socket( AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
  639. {
  640. DisplayErrorMessage(EMSG_WINS_NAMECHECK_FAILED,
  641. WSAGetLastError());
  642. return WSAGetLastError();
  643. }
  644. myad.sin_family = AF_INET;
  645. myad.sin_addr.s_addr = htonl(INADDR_ANY);//htonl(INADDR_BROADCAST);//INADDR_ANY;
  646. myad.sin_port = htons(0);//htons(usEndPoint);
  647. if (bind( sd, (struct sockaddr *)&myad, sizeof(myad) ) < 0)
  648. {
  649. DisplayErrorMessage(EMSG_WINS_NAMECHECK_FAILED,
  650. WSAGetLastError());
  651. closesocket( sd );
  652. return WSAGetLastError();
  653. }
  654. if (ioctlsocket(sd, FIONBIO, &NonBlocking) < 0)
  655. {
  656. DisplayErrorMessage(EMSG_WINS_NAMECHECK_FAILED,
  657. WSAGetLastError());
  658. return WSAGetLastError();
  659. }
  660. return 0;
  661. }
  662. INT
  663. CloseNameCheckSocket()
  664. {
  665. closesocket(sd);
  666. WSACleanup();
  667. return 0;
  668. }
  669. INT
  670. CheckNameConsistency()
  671. {
  672. int status = 0;
  673. int i, j;
  674. int Pass;
  675. int ServerInx, NameInx, Inx;
  676. struct in_addr retaddr;
  677. struct in_addr tempaddr;
  678. u_long temp;
  679. WINSERVERS * ServerTemp;
  680. int retry;
  681. FILE * nf;
  682. WCHAR szBuffer[MAX_SIZE] = {L'\0'};
  683. WCHAR szNum[10];
  684. WCHAR lpResults[200] = {L'\0'};
  685. WCHAR wcName[21] = {L'\0'};
  686. BOOL fDone = FALSE;
  687. LPWSTR pwszTempBuf = NULL;
  688. // initialize some things
  689. memset(VerifiedAddress, 0, sizeof(VerifiedAddress));
  690. status = InitNameCheckSocket();
  691. // if the query is sent to the local server, TranIDs less than 0x7fff are dropped by NetBT
  692. TranID = 0x8000;
  693. if( status )
  694. return status;
  695. for (i = 0; i < MAX_SERVERS; i++)
  696. {
  697. WinServers[i].LastResponse = -1;
  698. WinServers[i].fQueried = FALSE;
  699. WinServers[i].Valid = 0;
  700. WinServers[i].Failed = 0;
  701. WinServers[i].Retries = 0;
  702. WinServers[i].Completed = 0;
  703. }
  704. /* We initially have no failed servers */
  705. for (ServerInx = 0; ServerInx < NumWinServers; ServerInx++)
  706. {
  707. ServerTemp = &WinServers[ServerInx];
  708. ServerTemp->Failed = 0;
  709. }
  710. for (NameInx = 0; NameInx < NumNBNames; NameInx++)
  711. {
  712. CHAR cchEnd = 0x00;
  713. cchEnd = NBNames[NameInx][15];
  714. NBNames[NameInx][15] = 0x00;
  715. pwszTempBuf = WinsOemToUnicode(NBNames[NameInx], NULL);
  716. NBNames[NameInx][15] = cchEnd;
  717. if( pwszTempBuf is NULL )
  718. {
  719. DisplayMessage(g_hModule,
  720. EMSG_WINS_OUT_OF_MEMORY);
  721. return FALSE;
  722. }
  723. wcsncpy(wcName, pwszTempBuf, 15);
  724. WinsFreeMemory(pwszTempBuf);
  725. pwszTempBuf = NULL;
  726. for( j=wcslen(wcName); j<16; j++ )
  727. {
  728. wcName[j] = L' ';
  729. }
  730. wcName[15] = L'[';
  731. WinsHexToString(wcName+16, (LPBYTE)&cchEnd, 1);
  732. wcName[18] = L'h';
  733. wcName[19] = L']';
  734. wcName[20] = L'\0';
  735. for (ServerInx = 0; ServerInx < NumWinServers; ServerInx++)
  736. {
  737. ServerTemp = &WinServers[ServerInx];
  738. if (ServerTemp->Completed)
  739. {
  740. continue;
  741. }
  742. retry = 0;
  743. TranID++;
  744. fDone = FALSE;
  745. while( !fDone )
  746. {
  747. pwszTempBuf = WinsOemToUnicode(inet_ntoa(ServerTemp->Server), NULL);
  748. if( pwszTempBuf is NULL )
  749. {
  750. DisplayMessage(g_hModule,
  751. EMSG_WINS_OUT_OF_MEMORY);
  752. return FALSE;
  753. }
  754. DisplayMessage(g_hModule,
  755. MSG_WINS_SEND_NAMEQUERY,
  756. pwszTempBuf,
  757. wcName);
  758. WinsFreeMemory(pwszTempBuf);
  759. pwszTempBuf = NULL;
  760. SendNameQuery(NBNames[NameInx],
  761. ServerTemp->Server.s_addr,
  762. TranID);
  763. switch (GetNameResponse(&retaddr.s_addr, TranID))
  764. {
  765. case WINSTEST_FOUND: // found
  766. ServerTemp->RetAddr.s_addr = retaddr.s_addr;
  767. ServerTemp->Valid = 1;
  768. ServerTemp->LastResponse = NameInx;
  769. if (retaddr.s_addr == VerifiedAddress[NameInx])
  770. {
  771. // this address has already been verified... don't
  772. // do the checking again
  773. DisplayMessage(g_hModule,
  774. MSG_WINS_DISPLAY_STRING,
  775. wszOK);
  776. fDone = TRUE;
  777. break;
  778. }
  779. status = VerifyRemote(inet_ntoa(ServerTemp->RetAddr),
  780. NBNames[NameInx]);
  781. if (WINSTEST_VERIFIED == status)
  782. {
  783. DisplayMessage(g_hModule,
  784. MSG_WINS_DISPLAY_STRING,
  785. wszOK);
  786. VerifiedAddress[NameInx] = retaddr.s_addr;
  787. }
  788. else
  789. {
  790. DisplayMessage(g_hModule,
  791. MSG_WINS_DISPLAY_STRING,
  792. wszNameVerify);//wszFailure);
  793. }
  794. fDone = TRUE;
  795. break;
  796. case WINSTEST_NOT_FOUND: // responded -- name not found
  797. ServerTemp->RetAddr.s_addr = retaddr.s_addr;
  798. ServerTemp->Valid = 0;
  799. ServerTemp->LastResponse = NameInx;
  800. DisplayMessage(g_hModule, EMSG_WINS_NAME_NOT_FOUND);
  801. retry++;
  802. if (retry > 2)
  803. {
  804. ServerTemp->Failed = 1;
  805. fDone = TRUE;
  806. }
  807. break;
  808. case WINSTEST_NO_RESPONSE: // no response
  809. ServerTemp->RetAddr.s_addr = retaddr.s_addr;
  810. ServerTemp->Valid = 0;
  811. ServerTemp->Retries++;
  812. DisplayMessage(g_hModule, EMSG_WINS_NO_RESPONSE);
  813. retry++;
  814. if (retry > 2)
  815. {
  816. ServerTemp->Failed = 1;
  817. fDone = TRUE;
  818. }
  819. break;
  820. default:
  821. break;
  822. } // switch GetNameResponse
  823. } //while loop
  824. } // for ServerInx
  825. //Find a server address for this name
  826. for (ServerInx = 0; ServerInx < NumWinServers; ServerInx++)
  827. {
  828. ServerTemp = &WinServers[ServerInx];
  829. if (ServerTemp->Valid)
  830. {
  831. DisplayMessage(g_hModule,
  832. MSG_WINS_RESULTS);
  833. DisplayInfo(NameInx, ServerTemp->RetAddr.s_addr);
  834. break;
  835. }
  836. } // for ServerInx
  837. } //Name for loop
  838. //Mark all successful servers as completed;
  839. for( ServerInx = 0; ServerInx < NumWinServers; ServerInx++ )
  840. {
  841. ServerTemp = &WinServers[ServerInx];
  842. if( !ServerTemp->Failed )
  843. {
  844. ServerTemp->Completed = 1;
  845. }
  846. }
  847. DisplayMessage(g_hModule,
  848. MSG_WINS_FINAL_RESULTS);
  849. for (ServerInx = 0; ServerInx < NumWinServers; ServerInx++)
  850. {
  851. ServerTemp = &WinServers[ServerInx];
  852. pwszTempBuf = WinsOemToUnicode(inet_ntoa(ServerTemp->Server), NULL);
  853. if( pwszTempBuf is NULL )
  854. {
  855. DisplayMessage(g_hModule,
  856. EMSG_WINS_OUT_OF_MEMORY);
  857. return FALSE;
  858. }
  859. if ((-1) == ServerTemp->LastResponse)
  860. {
  861. DisplayMessage(g_hModule,
  862. EMSG_WINS_WINS_NEVERRESPONDED,
  863. pwszTempBuf);
  864. }
  865. else if (0 == ServerTemp->Completed)
  866. {
  867. DisplayMessage(g_hModule,
  868. EMSG_WINS_WINS_INCOMPLETE,
  869. pwszTempBuf);
  870. }
  871. WinsFreeMemory(pwszTempBuf);
  872. pwszTempBuf = NULL;
  873. } // for ServerInx
  874. for (NameInx = 0; NameInx < NumNBNames; NameInx++)
  875. {
  876. CHAR cchEnd = NBNames[NameInx][15];
  877. NBNames[NameInx][15] = '\0';
  878. pwszTempBuf = WinsOemToUnicode(NBNames[NameInx], NULL);
  879. NBNames[NameInx][15] = cchEnd;
  880. if( pwszTempBuf is NULL )
  881. {
  882. DisplayMessage(g_hModule,
  883. EMSG_WINS_OUT_OF_MEMORY);
  884. return FALSE;
  885. }
  886. wcsncpy(wcName, pwszTempBuf, 15);
  887. WinsFreeMemory(pwszTempBuf);
  888. pwszTempBuf = NULL;
  889. for( j = wcslen(wcName); j < 16; j++ )
  890. {
  891. wcName[j] = L' ';
  892. }
  893. wcName[15] = L'[';
  894. WinsHexToString(wcName+16, (LPBYTE)&cchEnd, 1);
  895. wcName[18] = L'h';
  896. wcName[19] = L']';
  897. wcName[20] = L'\0';
  898. if (0 == VerifiedAddress[NameInx])
  899. {
  900. DisplayMessage(g_hModule,
  901. EMSG_WINS_ADDRESS_VERIFY_FAILED,
  902. wcName);
  903. }
  904. } // for NameInx
  905. DisplayMessage(g_hModule,
  906. WINS_FORMAT_LINE);
  907. CloseNameCheckSocket();
  908. return 1; // just to keep the compiler happy -- why do we have to?
  909. }
  910. void DisplayInfo(int uNames, u_long ulValidAddr)
  911. {
  912. int uServers;
  913. CHAR cchEnd = 0x00;
  914. LPWSTR pwszTemp = NULL;
  915. WINSERVERS * pCurrentServer;
  916. struct in_addr tempaddr;
  917. int i, j;
  918. BOOL fMismatchFound = FALSE;
  919. WCHAR wcName[21] = {L'\0'};
  920. cchEnd = NBNames[uNames][15];
  921. NBNames[uNames][15] = 0x00;
  922. pwszTemp = WinsOemToUnicode(NBNames[uNames], NULL);
  923. NBNames[uNames][15] = cchEnd;
  924. if( pwszTemp is NULL )
  925. {
  926. DisplayMessage(g_hModule,
  927. EMSG_WINS_NOT_ENOUGH_MEMORY);
  928. return;
  929. }
  930. wcsncpy(wcName, pwszTemp, 15);
  931. for( j=wcslen(wcName); j<16; j++ )
  932. {
  933. wcName[j] = L' ';
  934. }
  935. wcName[15] = L'[';
  936. WinsHexToString(wcName+16, (LPBYTE)&cchEnd, 1);
  937. wcName[18] = L'h';
  938. wcName[19] = L']';
  939. wcName[20] = L'\0';
  940. WinsFreeMemory(pwszTemp);
  941. pwszTemp = NULL;
  942. // now check and see which WINS servers didn't match
  943. for (uServers = 0; uServers < NumWinServers; uServers++)
  944. {
  945. pCurrentServer = &WinServers[uServers];
  946. if (pCurrentServer->Completed)
  947. {
  948. continue;
  949. }
  950. if ( (pCurrentServer->Valid) )
  951. {
  952. if ( (pCurrentServer->RetAddr.s_addr != ulValidAddr) ||
  953. (VerifiedAddress[uNames] != 0 &&
  954. VerifiedAddress[uNames] != ulValidAddr) )
  955. {
  956. // mismatch
  957. DisplayMessage(g_hModule,
  958. EMSG_WINS_NAME_INCONSISTENCY,
  959. wcName);
  960. if (VerifiedAddress[uNames] != 0)
  961. {
  962. tempaddr.s_addr = VerifiedAddress[uNames];
  963. DisplayMessage(g_hModule,
  964. EMSG_WINS_VERIFIED_ADDRESS,
  965. IpAddressToString(ntohl(tempaddr.S_un.S_addr)));
  966. }
  967. // display the inconsistent name resolutions
  968. for (i = 0; i < NumWinServers; i++)
  969. {
  970. if (WinServers[i].Valid &&
  971. VerifiedAddress[uNames] != WinServers[i].RetAddr.S_un.S_addr)
  972. {
  973. DisplayMessage(g_hModule,
  974. EMSG_WINS_NAMEQUERY_RESULT,
  975. IpAddressToString(ntohl(WinServers[i].Server.S_un.S_addr)),
  976. wcName,
  977. IpAddressToString(ntohl(WinServers[i].RetAddr.S_un.S_addr)));
  978. }
  979. }
  980. fMismatchFound = TRUE;
  981. break;
  982. }
  983. }
  984. } // end check for invalid addresses
  985. if (!fMismatchFound)
  986. {
  987. // display the correct info
  988. DisplayMessage(g_hModule,
  989. EMSG_WINS_NAME_VERIFIED,
  990. wcName,
  991. IpAddressToString(ntohl(ulValidAddr)));
  992. }
  993. }