/*++ Copyright (C) 1999 Microsoft Corporation --*/ #include "precomp.h" NTSTATUS DeviceIoCtrl( IN HANDLE fd, IN PVOID ReturnBuffer, IN ULONG BufferSize, IN ULONG Ioctl, IN PVOID pInput, IN ULONG SizeInput ); void DisplayInfo(int uNames, u_long ulValidAddr); LPWSTR ToWCS(LPCSTR szMBCSString) { int nResult = 0; LPWSTR lpWideString = NULL; // determone the size first nResult = MultiByteToWideChar( CP_ACP, 0, szMBCSString, -1, lpWideString, 0); lpWideString = WinsAllocateMemory((nResult+1)*sizeof(WCHAR)); if( lpWideString is NULL ) return NULL; nResult = MultiByteToWideChar( CP_ACP, MB_COMPOSITE, szMBCSString, -1, lpWideString, (nResult+1)*sizeof(WCHAR)); if( nResult is 0 ) { WinsFreeMemory(lpWideString); lpWideString = NULL; } else { lpWideString[nResult + 1] = '\0'; } return lpWideString; } //------------------------------------------------------------------------ NTSTATUS GetIpAddress( IN HANDLE fd, OUT PULONG pIpAddress ) /*++ Routine Description: This function calls into netbt to get the ip address. Arguments: fd - file handle to netbt pIpAddress - the ip address returned Return Value: ntstatus History: 27-Dec-1995 CDermody copied from nbtstat.c --*/ { NTSTATUS status; ULONG BufferSize=100; PVOID pBuffer; pBuffer = LocalAlloc(LMEM_FIXED,BufferSize); if (!pBuffer) { return(STATUS_INSUFFICIENT_RESOURCES); } status = DeviceIoCtrl(fd, pBuffer, BufferSize, IOCTL_NETBT_GET_IP_ADDRS, NULL, 0); if (NT_SUCCESS(status)) { *pIpAddress = *(ULONG *)pBuffer; } else { *pIpAddress = 0; } LocalFree(pBuffer); return(status); } //------------------------------------------------------------------------ NTSTATUS GetInterfaceList ( char pDeviceName[][MAX_NAME+1] ) { HANDLE StreamHandle; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; STRING name_string, AnsiString; UNICODE_STRING uc_name_string; NTSTATUS status; char pNbtWinsDeviceName[MAX_NAME] = "\\Device\\NetBt_Wins_Export"; PUCHAR SubKeyParms = "system\\currentcontrolset\\services\\netbt\\parameters"; PUCHAR Scope = "ScopeId"; CHAR pScopeBuffer[BUFF_SIZE]; HKEY Key; LONG Type; ULONG size; NETBT_INTERFACE_INFO *pInterfaceInfo; ULONG InterfaceInfoSize = 10 * sizeof(NETBT_ADAPTER_INDEX_MAP) + sizeof(ULONG); PVOID pInput = NULL; ULONG SizeInput = 0; LONG i, index = 0; pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize); if (!pInterfaceInfo) { return(STATUS_INSUFFICIENT_RESOURCES); } RtlInitString(&name_string, pNbtWinsDeviceName); RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE); InitializeObjectAttributes( &ObjectAttributes, &uc_name_string, OBJ_CASE_INSENSITIVE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL ); status = NtCreateFile (&StreamHandle, SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0); RtlFreeUnicodeString(&uc_name_string); if (NT_SUCCESS (status)) { do { status = DeviceIoCtrl(StreamHandle, pInterfaceInfo, InterfaceInfoSize, IOCTL_NETBT_GET_INTERFACE_INFO, pInput, SizeInput); if (status == STATUS_BUFFER_OVERFLOW) { LocalFree(pInterfaceInfo); InterfaceInfoSize *= 2; pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize); if (!pInterfaceInfo || (InterfaceInfoSize == 0xFFFF)) { NtClose(StreamHandle); //NlsPerror(COMMON_UNABLE_TO_ALLOCATE_PACKET,0); return(STATUS_INSUFFICIENT_RESOURCES); } } else if (!NT_SUCCESS (status)) { NtClose(StreamHandle); return(status); } } while (status == STATUS_BUFFER_OVERFLOW); NtClose (StreamHandle); for (i = 0; iNumAdapters; i++) { RtlInitString(&name_string, NULL); RtlInitUnicodeString(&uc_name_string, pInterfaceInfo->Adapter[i].Name); if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name_string, &uc_name_string, TRUE))) { size = (name_string.Length > MAX_NAME) ? MAX_NAME : name_string.Length; strncpy(pDeviceName[index], name_string.Buffer, size); pDeviceName[index][size] = '\0'; RtlFreeAnsiString (&name_string); index++; } } // // NULL out the next device string ptr // if (index < NBT_MAXIMUM_BINDINGS) { pDeviceName[index][0] = '\0'; } // // Read the ScopeId key! // size = BUFF_SIZE; *pScope = '\0'; // By default status = RegOpenKeyExA(HKEY_LOCAL_MACHINE, SubKeyParms, 0, KEY_READ, &Key); if (status == ERROR_SUCCESS) { // now read the Scope key status = RegQueryValueExA(Key, Scope, NULL, &Type, pScopeBuffer, &size); if (status == ERROR_SUCCESS) { strcpy(pScope,pScopeBuffer); } status = RegCloseKey(Key); } status = STATUS_SUCCESS; } return status; } //------------------------------------------------------------------------ NTSTATUS OpenNbt( IN char path[][MAX_NAME+1], OUT PHANDLE pHandle, int max_paths ) { HANDLE StreamHandle; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; STRING name_string; UNICODE_STRING uc_name_string; NTSTATUS status; LONG index=0; ASSERT ( max_paths <= NBT_MAXIMUM_BINDINGS ); while ((path[index][0] != '\0') && (index < max_paths)) { RtlInitString(&name_string, path[index]); RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE); InitializeObjectAttributes( &ObjectAttributes, &uc_name_string, OBJ_CASE_INSENSITIVE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL ); status = NtCreateFile( &StreamHandle, SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0); RtlFreeUnicodeString(&uc_name_string); if (NT_SUCCESS(status)) { *pHandle = StreamHandle; return(status); } ++index; } return (status); } // s_open //------------------------------------------------------------------------ NTSTATUS DeviceIoCtrl( IN HANDLE fd, IN PVOID ReturnBuffer, IN ULONG BufferSize, IN ULONG Ioctl, IN PVOID pInput, IN ULONG SizeInput ) /*++ Routine Description: This procedure performs an ioctl(I_STR) on a stream. Arguments: fd - NT file handle iocp - pointer to a strioctl structure Return Value: 0 if successful, non-zero otherwise. History: 27-Dec-1995 CDermody copied from nbtstat.c --*/ { NTSTATUS status; int retval; ULONG QueryType; IO_STATUS_BLOCK iosb; status = NtDeviceIoControlFile( fd, // Handle NULL, // Event NULL, // ApcRoutine NULL, // ApcContext &iosb, // IoStatusBlock Ioctl, // IoControlCode pInput, // InputBuffer SizeInput, // InputBufferSize (PVOID) ReturnBuffer, // OutputBuffer BufferSize); // OutputBufferSize if (status == STATUS_PENDING) { status = NtWaitForSingleObject( fd, // Handle TRUE, // Alertable NULL); // Timeout if (NT_SUCCESS(status)) { status = iosb.Status; } } return(status); } /****************************************************************************/ /* CheckRemoteTable */ /* */ /* This routine does an adapter status query to get the remote name table */ /* then checks to see if a netbios name is contained in it. */ /* */ /* Parameters: */ /* RemoteName, the IP address (asci nn.nn.nn.nn format) of a server to */ /* query. */ /* SearchName, a net bios name. */ /* */ /* Return: */ /* WINSTEST_VERIFIED The name exists in the remote name table */ /* WINSTEST_NOT_VERIFIED The name does not exist in the remote table */ /* WINSTEST_BAD_IP_ADDRESS inet_addr could not convert the ip address */ /* character string. */ /* WINSTEST_HOST_NOT_FOUND Could not reach ip address */ /* WINSTEST_OUT_OF_MEMORY Out of memory */ /* History: */ /* 27-Dec-1995 CDermody created following example of nbtstat.c */ /****************************************************************************/ int CheckRemoteTable( IN HANDLE fd, IN PCHAR RemoteName, IN PCHAR SearchName ) { LONG Count; LONG i; PVOID pBuffer; ULONG BufferSize=600; NTSTATUS status; tADAPTERSTATUS *pAdapterStatus; NAME_BUFFER *pNames; CHAR MacAddress[20]; tIPANDNAMEINFO *pIpAndNameInfo; ULONG SizeInput; ULONG IpAddress; USHORT BytesToCopy; pBuffer = LocalAlloc(LMEM_FIXED,BufferSize); if (!pBuffer) { return(WINSTEST_OUT_OF_MEMORY); } status = STATUS_BUFFER_OVERFLOW; pIpAndNameInfo = LocalAlloc(LMEM_FIXED,sizeof(tIPANDNAMEINFO)); if (!pIpAndNameInfo) { LocalFree(pBuffer); return(WINSTEST_OUT_OF_MEMORY); } RtlZeroMemory((PVOID)pIpAndNameInfo,sizeof(tIPANDNAMEINFO)); // // Convert the remote name which is really a dotted decimal ip address // into a ulong // IpAddress = inet_addr(RemoteName); // // Don't allow zero for the address since it sends a broadcast and // every one responds // if ((IpAddress == INADDR_NONE) || (IpAddress == 0)) { LocalFree(pBuffer); LocalFree(pIpAndNameInfo); return(WINSTEST_BAD_IP_ADDRESS); } pIpAndNameInfo->IpAddress = ntohl(IpAddress); pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosName[0] = '*'; pIpAndNameInfo->NetbiosAddress.TAAddressCount = 1; pIpAndNameInfo->NetbiosAddress.Address[0].AddressLength = sizeof(TDI_ADDRESS_NETBIOS); pIpAndNameInfo->NetbiosAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS; pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE; SizeInput = sizeof(tIPANDNAMEINFO); while (status == STATUS_BUFFER_OVERFLOW) { status = DeviceIoCtrl(fd, pBuffer, BufferSize, IOCTL_NETBT_ADAPTER_STATUS, pIpAndNameInfo, SizeInput); if (status == STATUS_BUFFER_OVERFLOW) { LocalFree(pBuffer); BufferSize *=2; pBuffer = LocalAlloc(LMEM_FIXED,BufferSize); if (!pBuffer || (BufferSize == 0xFFFF)) { LocalFree(pIpAndNameInfo); return(WINSTEST_OUT_OF_MEMORY); } } } pAdapterStatus = (tADAPTERSTATUS *)pBuffer; if ((pAdapterStatus->AdapterInfo.name_count == 0) || (status != STATUS_SUCCESS)) { LocalFree(pIpAndNameInfo); LocalFree(pBuffer); return(WINSTEST_HOST_NOT_FOUND); } pNames = pAdapterStatus->Names; Count = pAdapterStatus->AdapterInfo.name_count; status = 1; while (Count--) { if (0 == _strnicmp(SearchName, pNames->name, strlen(SearchName))) { LocalFree(pIpAndNameInfo); LocalFree(pBuffer); return WINSTEST_VERIFIED; // found } pNames++; } LocalFree(pIpAndNameInfo); LocalFree(pBuffer); return WINSTEST_NOT_VERIFIED; } /****************************************************************************/ /* VerifyRemote */ /* */ /* This routine checks to see if a netbios name is contained in the remote */ /* name table at a given IP address. */ /* */ /* Parameters: */ /* RemoteName, the IP address (asci nn.nn.nn.nn format) of a server to */ /* query. */ /* NBName, a net bios name. */ /* */ /* Return: */ /* WINSTEST_VERIFIED The name exists in the remote name table */ /* WINSTEST_NOT_VERIFIED The name does not exist in the remote table */ /* WINSTEST_BAD_IP_ADDRESS inet_addr could not convert the ip address */ /* character string. */ /* WINSTEST_OPEN_FAILED Could not open NBT driver or could not read */ /* the NBT driver info from the registry. */ /* WINSTEST_HOST_NOT_FOUND Could not reach ip address */ /* WINSTEST_OUT_OF_MEMORY Out of memory */ /* History: */ /* 27-Dec-1995 CDermody created following example of nbtstat.c */ /****************************************************************************/ int VerifyRemote(IN PCHAR RemoteName, IN PCHAR NBName) { NTSTATUS status; LONG interval=-1; HANDLE nbt = 0; int nStatus; int index; CHAR pDeviceName[NBT_MAXIMUM_BINDINGS+1][MAX_NAME+1]; status = GetInterfaceList(pDeviceName); if (!NT_SUCCESS(status)) { return WINSTEST_OPEN_FAILED; } for (index = 0; index < NBT_MAXIMUM_BINDINGS && pDeviceName[index][0]; index++) { // // Open the device of the appropriate streams module to start with. // status = OpenNbt(&pDeviceName[index], &nbt, NBT_MAXIMUM_BINDINGS-index); if (!NT_SUCCESS(status)) { // // Try the next binding! // continue; } GetIpAddress(nbt, &NetbtIpAddress); if (RemoteName[0] == '\0') return WINSTEST_INVALID_ARG; status = (NTSTATUS)CheckRemoteTable(nbt,RemoteName,NBName); if (status == WINSTEST_VERIFIED) break; } return status; } /*************************************************************/ /* NBEncode(name2,name) */ /* */ /* This routine code a netbios name from level1 to level2. */ /* name2 has to be NBT_NAMESIZE bytes long, remember that. */ /*************************************************************/ void NBEncode( unsigned char *name2, unsigned char *name ) { int i; name2[0] = 0x20; /* length of first block */ for (i = 0; i < NBT_NONCODED_NMSZ - 1; i++) { name2[ 2*i+1 ] = ((name[ i ] >> 4) & 0x0f) + 0x41; name2[ 2*i+2 ] = (name[ i ] & 0x0f) + 0x41; } name2[ NBT_NAMESIZE-1 ] = 0; /* length of next block */ } /*******************************************************************/ /* */ /* Send a Name Query to a WINS Server */ /* */ /* name is the name to query */ /* winsaddr is the ip address of the wins server to query */ /* TransID is the transaction ID to use for the query */ /* */ /*******************************************************************/ void SendNameQuery( unsigned char *name, u_long winsaddr, u_short TransID ) { struct sockaddr_in destad; char lpResults[MAX_SIZE] = {0}; char paddedname[NBT_NONCODED_NMSZ]; USHORT usEndPoint = 5005; int err = 0; struct { u_short TransactionID; u_short Flags; u_short QuestionCount; u_short AnswerCount; u_short NSCount; u_short AdditionalRec; u_char QuestionName[NBT_NAMESIZE]; u_short QuestionType; u_short QuestionClass; } NameQuery; memset(paddedname, 0x20, sizeof(paddedname)); memcpy(paddedname, name, strlen(name)); NBEncode(NameQuery.QuestionName, paddedname); NameQuery.TransactionID = htons(TransID); NameQuery.Flags = htons(0x0100); NameQuery.QuestionCount = htons(1); NameQuery.AnswerCount = 0; NameQuery.NSCount = 0; NameQuery.AdditionalRec = 0; NameQuery.QuestionType = htons(0x0020); NameQuery.QuestionClass = htons(1); destad.sin_family = AF_INET; destad.sin_port = htons(137); destad.sin_addr.s_addr = winsaddr; err = sendto(sd, (char *)&NameQuery, sizeof(NameQuery), 0, (struct sockaddr *)&destad, sizeof(myad)); if( err is SOCKET_ERROR ) { DisplayErrorMessage(EMSG_WINS_SENDTO_FAILED, WSAGetLastError()); return; } } /*******************************************************************/ /* */ /* Wait for a Name Response which matches the Transaction ID */ /* */ /* recvaddr is the ip address returned by the wins server */ /* */ /*******************************************************************/ int GetNameResponse( u_long * recvaddr, u_short TransactionID ) { char lpResults[100] = {0}; int i; int len; int rslt; u_long AnswerAddr; struct sockaddr_in addr; NameResponse * pNameResponse = NULL; BYTE Buf[NAME_RESPONSE_BUFFER_SIZE] = {0}; i = 0; while (i < 15) { addrlen = sizeof(addr); if ((len=recvfrom(sd, (char *) Buf, sizeof(Buf), 0, (struct sockaddr *)&addr, &addrlen)) < 0) { rslt = WSAGetLastError(); if (rslt == WSAEWOULDBLOCK) { Sleep(100); i++; continue; } else { DisplayErrorMessage(EMSG_WINS_GETRESPONSE_FAILED, rslt); return WINSTEST_NO_RESPONSE; } } pNameResponse = (NameResponse *) Buf; if (TransactionID == htons(pNameResponse->TransactionID)) { if (htons(pNameResponse->AnswerCount) == 0) { *recvaddr = 0; return(WINSTEST_NOT_FOUND); } AnswerAddr = (pNameResponse->AnswerAddr2 << 16) | pNameResponse->AnswerAddr1; *recvaddr = AnswerAddr; return(WINSTEST_FOUND); } } *recvaddr = 0; return(WINSTEST_NO_RESPONSE); } INT InitNameCheckSocket() { WCHAR lpResults[MAX_SIZE]; BOOL fBroadcast = TRUE; INT err = 0; /* Set up a socket to use for querys and responses */ WSAStartup( 0x0101, &WsaData ); // make sure winsock is happy - noop for now if ((sd = socket( AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) { DisplayErrorMessage(EMSG_WINS_NAMECHECK_FAILED, WSAGetLastError()); return WSAGetLastError(); } myad.sin_family = AF_INET; myad.sin_addr.s_addr = htonl(INADDR_ANY);//htonl(INADDR_BROADCAST);//INADDR_ANY; myad.sin_port = htons(0);//htons(usEndPoint); if (bind( sd, (struct sockaddr *)&myad, sizeof(myad) ) < 0) { DisplayErrorMessage(EMSG_WINS_NAMECHECK_FAILED, WSAGetLastError()); closesocket( sd ); return WSAGetLastError(); } if (ioctlsocket(sd, FIONBIO, &NonBlocking) < 0) { DisplayErrorMessage(EMSG_WINS_NAMECHECK_FAILED, WSAGetLastError()); return WSAGetLastError(); } return 0; } INT CloseNameCheckSocket() { closesocket(sd); WSACleanup(); return 0; } INT CheckNameConsistency() { int status = 0; int i, j; int Pass; int ServerInx, NameInx, Inx; struct in_addr retaddr; struct in_addr tempaddr; u_long temp; WINSERVERS * ServerTemp; int retry; FILE * nf; WCHAR szBuffer[MAX_SIZE] = {L'\0'}; WCHAR szNum[10]; WCHAR lpResults[200] = {L'\0'}; WCHAR wcName[21] = {L'\0'}; BOOL fDone = FALSE; LPWSTR pwszTempBuf = NULL; // initialize some things memset(VerifiedAddress, 0, sizeof(VerifiedAddress)); status = InitNameCheckSocket(); // if the query is sent to the local server, TranIDs less than 0x7fff are dropped by NetBT TranID = 0x8000; if( status ) return status; for (i = 0; i < MAX_SERVERS; i++) { WinServers[i].LastResponse = -1; WinServers[i].fQueried = FALSE; WinServers[i].Valid = 0; WinServers[i].Failed = 0; WinServers[i].Retries = 0; WinServers[i].Completed = 0; } /* We initially have no failed servers */ for (ServerInx = 0; ServerInx < NumWinServers; ServerInx++) { ServerTemp = &WinServers[ServerInx]; ServerTemp->Failed = 0; } for (NameInx = 0; NameInx < NumNBNames; NameInx++) { CHAR cchEnd = 0x00; cchEnd = NBNames[NameInx][15]; NBNames[NameInx][15] = 0x00; pwszTempBuf = WinsOemToUnicode(NBNames[NameInx], NULL); NBNames[NameInx][15] = cchEnd; if( pwszTempBuf is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_OUT_OF_MEMORY); return FALSE; } wcsncpy(wcName, pwszTempBuf, 15); WinsFreeMemory(pwszTempBuf); pwszTempBuf = NULL; for( j=wcslen(wcName); j<16; j++ ) { wcName[j] = L' '; } wcName[15] = L'['; WinsHexToString(wcName+16, (LPBYTE)&cchEnd, 1); wcName[18] = L'h'; wcName[19] = L']'; wcName[20] = L'\0'; for (ServerInx = 0; ServerInx < NumWinServers; ServerInx++) { ServerTemp = &WinServers[ServerInx]; if (ServerTemp->Completed) { continue; } retry = 0; TranID++; fDone = FALSE; while( !fDone ) { pwszTempBuf = WinsOemToUnicode(inet_ntoa(ServerTemp->Server), NULL); if( pwszTempBuf is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_OUT_OF_MEMORY); return FALSE; } DisplayMessage(g_hModule, MSG_WINS_SEND_NAMEQUERY, pwszTempBuf, wcName); WinsFreeMemory(pwszTempBuf); pwszTempBuf = NULL; SendNameQuery(NBNames[NameInx], ServerTemp->Server.s_addr, TranID); switch (GetNameResponse(&retaddr.s_addr, TranID)) { case WINSTEST_FOUND: // found ServerTemp->RetAddr.s_addr = retaddr.s_addr; ServerTemp->Valid = 1; ServerTemp->LastResponse = NameInx; if (retaddr.s_addr == VerifiedAddress[NameInx]) { // this address has already been verified... don't // do the checking again DisplayMessage(g_hModule, MSG_WINS_DISPLAY_STRING, wszOK); fDone = TRUE; break; } status = VerifyRemote(inet_ntoa(ServerTemp->RetAddr), NBNames[NameInx]); if (WINSTEST_VERIFIED == status) { DisplayMessage(g_hModule, MSG_WINS_DISPLAY_STRING, wszOK); VerifiedAddress[NameInx] = retaddr.s_addr; } else { DisplayMessage(g_hModule, MSG_WINS_DISPLAY_STRING, wszNameVerify);//wszFailure); } fDone = TRUE; break; case WINSTEST_NOT_FOUND: // responded -- name not found ServerTemp->RetAddr.s_addr = retaddr.s_addr; ServerTemp->Valid = 0; ServerTemp->LastResponse = NameInx; DisplayMessage(g_hModule, EMSG_WINS_NAME_NOT_FOUND); retry++; if (retry > 2) { ServerTemp->Failed = 1; fDone = TRUE; } break; case WINSTEST_NO_RESPONSE: // no response ServerTemp->RetAddr.s_addr = retaddr.s_addr; ServerTemp->Valid = 0; ServerTemp->Retries++; DisplayMessage(g_hModule, EMSG_WINS_NO_RESPONSE); retry++; if (retry > 2) { ServerTemp->Failed = 1; fDone = TRUE; } break; default: break; } // switch GetNameResponse } //while loop } // for ServerInx //Find a server address for this name for (ServerInx = 0; ServerInx < NumWinServers; ServerInx++) { ServerTemp = &WinServers[ServerInx]; if (ServerTemp->Valid) { DisplayMessage(g_hModule, MSG_WINS_RESULTS); DisplayInfo(NameInx, ServerTemp->RetAddr.s_addr); break; } } // for ServerInx } //Name for loop //Mark all successful servers as completed; for( ServerInx = 0; ServerInx < NumWinServers; ServerInx++ ) { ServerTemp = &WinServers[ServerInx]; if( !ServerTemp->Failed ) { ServerTemp->Completed = 1; } } DisplayMessage(g_hModule, MSG_WINS_FINAL_RESULTS); for (ServerInx = 0; ServerInx < NumWinServers; ServerInx++) { ServerTemp = &WinServers[ServerInx]; pwszTempBuf = WinsOemToUnicode(inet_ntoa(ServerTemp->Server), NULL); if( pwszTempBuf is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_OUT_OF_MEMORY); return FALSE; } if ((-1) == ServerTemp->LastResponse) { DisplayMessage(g_hModule, EMSG_WINS_WINS_NEVERRESPONDED, pwszTempBuf); } else if (0 == ServerTemp->Completed) { DisplayMessage(g_hModule, EMSG_WINS_WINS_INCOMPLETE, pwszTempBuf); } WinsFreeMemory(pwszTempBuf); pwszTempBuf = NULL; } // for ServerInx for (NameInx = 0; NameInx < NumNBNames; NameInx++) { CHAR cchEnd = NBNames[NameInx][15]; NBNames[NameInx][15] = '\0'; pwszTempBuf = WinsOemToUnicode(NBNames[NameInx], NULL); NBNames[NameInx][15] = cchEnd; if( pwszTempBuf is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_OUT_OF_MEMORY); return FALSE; } wcsncpy(wcName, pwszTempBuf, 15); WinsFreeMemory(pwszTempBuf); pwszTempBuf = NULL; for( j = wcslen(wcName); j < 16; j++ ) { wcName[j] = L' '; } wcName[15] = L'['; WinsHexToString(wcName+16, (LPBYTE)&cchEnd, 1); wcName[18] = L'h'; wcName[19] = L']'; wcName[20] = L'\0'; if (0 == VerifiedAddress[NameInx]) { DisplayMessage(g_hModule, EMSG_WINS_ADDRESS_VERIFY_FAILED, wcName); } } // for NameInx DisplayMessage(g_hModule, WINS_FORMAT_LINE); CloseNameCheckSocket(); return 1; // just to keep the compiler happy -- why do we have to? } void DisplayInfo(int uNames, u_long ulValidAddr) { int uServers; CHAR cchEnd = 0x00; LPWSTR pwszTemp = NULL; WINSERVERS * pCurrentServer; struct in_addr tempaddr; int i, j; BOOL fMismatchFound = FALSE; WCHAR wcName[21] = {L'\0'}; cchEnd = NBNames[uNames][15]; NBNames[uNames][15] = 0x00; pwszTemp = WinsOemToUnicode(NBNames[uNames], NULL); NBNames[uNames][15] = cchEnd; if( pwszTemp is NULL ) { DisplayMessage(g_hModule, EMSG_WINS_NOT_ENOUGH_MEMORY); return; } wcsncpy(wcName, pwszTemp, 15); for( j=wcslen(wcName); j<16; j++ ) { wcName[j] = L' '; } wcName[15] = L'['; WinsHexToString(wcName+16, (LPBYTE)&cchEnd, 1); wcName[18] = L'h'; wcName[19] = L']'; wcName[20] = L'\0'; WinsFreeMemory(pwszTemp); pwszTemp = NULL; // now check and see which WINS servers didn't match for (uServers = 0; uServers < NumWinServers; uServers++) { pCurrentServer = &WinServers[uServers]; if (pCurrentServer->Completed) { continue; } if ( (pCurrentServer->Valid) ) { if ( (pCurrentServer->RetAddr.s_addr != ulValidAddr) || (VerifiedAddress[uNames] != 0 && VerifiedAddress[uNames] != ulValidAddr) ) { // mismatch DisplayMessage(g_hModule, EMSG_WINS_NAME_INCONSISTENCY, wcName); if (VerifiedAddress[uNames] != 0) { tempaddr.s_addr = VerifiedAddress[uNames]; DisplayMessage(g_hModule, EMSG_WINS_VERIFIED_ADDRESS, IpAddressToString(ntohl(tempaddr.S_un.S_addr))); } // display the inconsistent name resolutions for (i = 0; i < NumWinServers; i++) { if (WinServers[i].Valid && VerifiedAddress[uNames] != WinServers[i].RetAddr.S_un.S_addr) { DisplayMessage(g_hModule, EMSG_WINS_NAMEQUERY_RESULT, IpAddressToString(ntohl(WinServers[i].Server.S_un.S_addr)), wcName, IpAddressToString(ntohl(WinServers[i].RetAddr.S_un.S_addr))); } } fMismatchFound = TRUE; break; } } } // end check for invalid addresses if (!fMismatchFound) { // display the correct info DisplayMessage(g_hModule, EMSG_WINS_NAME_VERIFIED, wcName, IpAddressToString(ntohl(ulValidAddr))); } }