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.

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