|
|
/*++
Copyright(c) 1995 Microsoft Corporation
MODULE NAME access.c
ABSTRACT Address accessibility routines for automatic connections
AUTHOR Anthony Discolo (adiscolo) 26-Jul-1995
REVISION HISTORY
--*/
#define UNICODE
#define _UNICODE
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdlib.h>
#include <windows.h>
#include <tdi.h>
#include <nb30.h>
#include <nbtioctl.h>
#include <stdio.h>
#include <npapi.h>
#include <ctype.h>
#include <winsock.h>
#include <acd.h>
#include <ras.h>
#include <raserror.h>
#include <rasman.h>
#include <debug.h>
#include <ipexport.h>
#include <icmpapi.h>
#include "reg.h"
#include "rasprocs.h"
#include "misc.h"
#include "table.h"
#include "addrmap.h"
#include "imperson.h"
//
// The format of Adapter Status responses.
//
typedef struct _ADAPTERSTATUS { ADAPTER_STATUS AdapterInfo; NAME_BUFFER Names[32]; } ADAPTERSTATUS, *PADAPTERSTATUS;
//
// Icmp.dll library entrypoints.
//
#define ICMP_MODULE L"icmp"
HANDLE hIcmpG;
#define ICMPCREATEFILE "IcmpCreateFile"
FARPROC lpfnIcmpCreateFileG;
#define ICMPSENDECHO "IcmpSendEcho"
FARPROC lpfnIcmpSendEchoG;
#define ICMPCLOSEHANDLE "IcmpCloseHandle"
FARPROC lpfnIcmpCloseHandleG;
//
// PingIpAddress constants
//
#define PING_SEND_SIZE 32
#define PING_RECV_SIZE (0x2000 - 8)
#define PING_TTL 32
#define PING_TIMEOUT 2000L // needs to be long enough to succeed over slow links
//
// External variables
//
extern HANDLE hTerminatingG;
BOOLEAN CopyNetbiosName( IN NAME_BUFFER *pNames, IN DWORD dwcNames, OUT LPSTR pszNetbiosName ) { BOOLEAN fFound = FALSE; DWORD i, iWks = 0; CHAR szWks[NCBNAMSZ]; PCHAR p = pszNetbiosName;
//
// Find the unique workstation name.
//
again: szWks[0] = '\0'; for (i = iWks; i < dwcNames; i++) { RASAUTO_TRACE2( "CopyNetbiosName: wks %15.15s (0x%x)", pNames[i].name, pNames[i].name[NCBNAMSZ - 1]); if (pNames[i].name[NCBNAMSZ - 1] == 0x0 && !(pNames[i].name_flags & GROUP_NAME)) { RASAUTO_TRACE1("CopyNetbiosName: iWks=%d\n", iWks); iWks = i; memcpy(szWks, pNames[i].name, NCBNAMSZ - 1); break; } } //
// Check to make sure we found one.
//
if (szWks[0] == '\0') return FALSE; //
// Find the unique server name and make
// sure it matches the workstation name.
//
for (i = 0; i < dwcNames; i++) { RASAUTO_TRACE3( "CopyNetbiosName: srv %15.15s (0x%x), cmp=%d", pNames[i].name, pNames[i].name[NCBNAMSZ - 1], memcmp(szWks, pNames[i].name, NCBNAMSZ - 1)); if (pNames[i].name[NCBNAMSZ - 1] == 0x20 && !(pNames[i].name_flags & GROUP_NAME) && !memcmp(szWks, pNames[i].name, NCBNAMSZ - 1)) { DWORD j;
//
// Copy up to a null or a space.
//
for (j = 0; j < NCBNAMSZ - 1; j++) { if (pNames[i].name[j] == '\0' || pNames[i].name[j] == ' ') break; *p++ = pNames[i].name[j]; } *p++ = '\0'; return TRUE; } } //
// No match found. Look for another unique workstation
// name and try again if we haven't exhausted the list.
//
if (++iWks >= dwcNames) return FALSE; goto again; } // CopyNetbiosName
LPTSTR IpAddressToNetbiosName( IN LPTSTR pszIpAddress, IN HPORT hPort ) { BOOLEAN fFound; RAS_PROTOCOLS Protocols; DWORD i, dwcProtocols; RASMAN_ROUTEINFO *pRoute; WCHAR szAdapterName[MAX_PATH]; NTSTATUS status; HANDLE fd; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; UNICODE_STRING unicodeString; ULONG ipaddr; CHAR szIpAddress[17]; tIPANDNAMEINFO ipAndNameInfo; PVOID pBuffer; DWORD dwSize; PADAPTERSTATUS pAdapterStatus; NAME_BUFFER *pNames; DWORD dwcNames; LPTSTR pszNetbiosName = NULL;
//
// Enumerate the bindings for the port to
// try to find the Netbt device.
//
GetPortProtocols(hPort, &Protocols, &dwcProtocols); fFound = FALSE; for (i = 0; i < dwcProtocols; i++) { pRoute = &Protocols.RP_ProtocolInfo[i]; RASAUTO_TRACE3( "IpAddressToNetbiosName: adapter type=%d, name=%S, xport=%S", pRoute->RI_Type, pRoute->RI_AdapterName, pRoute->RI_XportName); if (pRoute->RI_Type == IP) { wcscpy(szAdapterName, L"\\Device\\Netbt_Tcpip_"); wcscat(szAdapterName, &pRoute->RI_AdapterName[8]); fFound = TRUE; break; } } if (!fFound) return NULL; //
// Open the device and issue a remote
// adapter status command.
//
RtlInitUnicodeString(&unicodeString, szAdapterName); InitializeObjectAttributes( &objectAttributes, &unicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); status = NtCreateFile( &fd, 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); if (!NT_SUCCESS(status)) { RASAUTO_TRACE1( "IpAddressToNetbiosName: NtCreateFile failed (status=0x%x)\n", status); return NULL; }
UnicodeStringToAnsiString(pszIpAddress, szIpAddress, sizeof (szIpAddress)); ipaddr = inet_addr(szIpAddress); if (ipaddr == INADDR_ANY) return NULL;
RtlZeroMemory(&ipAndNameInfo, sizeof (ipAndNameInfo)); ipAndNameInfo.IpAddress = ntohl(ipaddr); ipAndNameInfo.NetbiosAddress.Address[0].Address[0].NetbiosName[0] = '*'; ipAndNameInfo.NetbiosAddress.TAAddressCount = 1; ipAndNameInfo.NetbiosAddress.Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS); ipAndNameInfo.NetbiosAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS; ipAndNameInfo.NetbiosAddress.Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
dwSize = 2048; for (;;) { pBuffer = LocalAlloc(LPTR, dwSize); if (pBuffer == NULL) { RASAUTO_TRACE("IpAddressToNetbiosName: LocalAlloc failed"); return NULL; } status = NtDeviceIoControlFile( fd, NULL, NULL, NULL, &ioStatusBlock, IOCTL_NETBT_ADAPTER_STATUS, &ipAndNameInfo, sizeof (tIPANDNAMEINFO), pBuffer, dwSize); if (status != STATUS_BUFFER_OVERFLOW) break;
LocalFree(pBuffer); dwSize *= 2; if (dwSize >= 0xffff) { RASAUTO_TRACE("IpAddressToNetbiosName: Unable to allocate packet"); return NULL; } } if (status == STATUS_PENDING) { status = NtWaitForSingleObject(fd, TRUE, NULL); if (status == STATUS_SUCCESS) status = ioStatusBlock.Status; } NtClose(fd);
pAdapterStatus = (PADAPTERSTATUS)pBuffer; dwcNames = pAdapterStatus->AdapterInfo.name_count; RASAUTO_TRACE2( "IpAddressToNetbiosName: results (status=0x%x, dwcNames=%d)\n", status, dwcNames); if (status == STATUS_SUCCESS && dwcNames) { CHAR szNetbiosName[NCBNAMSZ + 1];
pNames = pAdapterStatus->Names; if (CopyNetbiosName(pNames, dwcNames, szNetbiosName)) pszNetbiosName = AnsiStringToUnicodeString(szNetbiosName, NULL, 0); } LocalFree(pBuffer);
return pszNetbiosName; } // IpAddressToNetbiosName
UCHAR HexByte( IN PCHAR p ) { UCHAR c;
c = *(UCHAR *)p; if (c >= '0' && c <= '9') return c - '0'; if ((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) { return c - ('A' - 10); } return 0xff; } // HexByte
VOID StringToNodeNumber( IN PCHAR pszString, OUT PCHAR pszNode ) { UCHAR c1, c2; INT i;
if (strlen(pszString) != 12) { RASAUTO_TRACE("StringToNodeNumber: bad node number length\n"); return; } for (i = 0; i < 6; i++) { c1 = HexByte(pszString++); c2 = HexByte(pszString++); if (c1 == 0xff || c2 == 0xff) { RASAUTO_TRACE("StringToNodeNumber: bad digit"); return; } *pszNode++ = (c1 << 4) + c2; } } // StringToNodeNumber
VOID NodeNumberToString( IN PCHAR pszNode, OUT PCHAR pszString ) { UCHAR c1, c2; INT i;
sprintf( pszString, "%02x:%02x:%02x:%02x:%02x:%02x", pszNode[0], pszNode[1], pszNode[2], pszNode[3], pszNode[4], pszNode[5]); } // NodeNumberToString
LPTSTR IpxAddressToNetbiosName( IN LPTSTR pszIpxAddress ) { NTSTATUS status; HANDLE fd; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; UNICODE_STRING unicodeString; PTDI_REQUEST_QUERY_INFORMATION pQuery; PTDI_CONNECTION_INFORMATION pConnectionInformation; PTA_NETBIOS_ADDRESS pRemoteAddress; CHAR szIpxAddress[13]; PVOID pBuffer; DWORD dwQuerySize, dwBufferSize; PADAPTERSTATUS pAdapterStatus; NAME_BUFFER *pNames; DWORD dwcNames; LPTSTR pszNetbiosName = NULL;
RtlInitUnicodeString(&unicodeString, L"\\Device\\Nwlnknb"); InitializeObjectAttributes( &objectAttributes, &unicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); status = NtCreateFile( &fd, 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); if (!NT_SUCCESS(status)) { RASAUTO_TRACE1("IpxAddressToNetbiosName: NtCreateFile failed (status=0x%x)", status); return NULL; }
dwQuerySize = sizeof (TDI_REQUEST_QUERY_INFORMATION) + sizeof (TDI_CONNECTION_INFORMATION) + sizeof (TA_NETBIOS_ADDRESS); pQuery = LocalAlloc(LPTR, dwQuerySize); if (pQuery == NULL) { RASAUTO_TRACE("IpxAddressToNetbiosName: LocalAlloc failed"); return NULL; } pQuery->QueryType = TDI_QUERY_ADAPTER_STATUS; (PTDI_CONNECTION_INFORMATION)&pQuery->RequestConnectionInformation; pQuery->RequestConnectionInformation = (PTDI_CONNECTION_INFORMATION)(pQuery + 1); pConnectionInformation = pQuery->RequestConnectionInformation; pConnectionInformation->UserDataLength = 0; pConnectionInformation->UserData = NULL; pConnectionInformation->OptionsLength = 0; pConnectionInformation->Options = NULL; pConnectionInformation->RemoteAddressLength = sizeof (TDI_ADDRESS_NETBIOS); pConnectionInformation->RemoteAddress = (PTA_NETBIOS_ADDRESS)(pConnectionInformation + 1); pRemoteAddress = pConnectionInformation->RemoteAddress; pRemoteAddress->TAAddressCount = 1; pRemoteAddress->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS); pRemoteAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS; pRemoteAddress->Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE; UnicodeStringToAnsiString( pszIpxAddress, szIpxAddress, sizeof (szIpxAddress)); RtlZeroMemory((PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName, 10); StringToNodeNumber( (PCHAR)szIpxAddress, (PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName[10]); RASAUTO_TRACE6("IpxAddressToNetbiosName: Node=%02x:%02x:%02x:%02x:%02x:%02x\n", pRemoteAddress->Address[0].Address[0].NetbiosName[10], pRemoteAddress->Address[0].Address[0].NetbiosName[11], pRemoteAddress->Address[0].Address[0].NetbiosName[12], pRemoteAddress->Address[0].Address[0].NetbiosName[13], pRemoteAddress->Address[0].Address[0].NetbiosName[14], pRemoteAddress->Address[0].Address[0].NetbiosName[15]);
dwBufferSize = 2048; for (;;) { pBuffer = LocalAlloc(LPTR, dwBufferSize); if (pBuffer == NULL) { RASAUTO_TRACE("IpxAddressToNetbiosName: LocalAlloc failed"); LocalFree(pQuery); return NULL; } status = NtDeviceIoControlFile( fd, NULL, NULL, NULL, &ioStatusBlock, IOCTL_TDI_QUERY_INFORMATION, pQuery, dwQuerySize, pBuffer, dwBufferSize); if (status != STATUS_BUFFER_OVERFLOW) break;
LocalFree(pBuffer); dwBufferSize *= 2; if (dwBufferSize >= 0xffff) { RASAUTO_TRACE("IpxAddressToNetbiosName: Unable to allocate packet"); LocalFree(pQuery); return NULL; } } if (status == STATUS_PENDING) { status = NtWaitForSingleObject(fd, TRUE, NULL); if (status == STATUS_SUCCESS) status = ioStatusBlock.Status; } NtClose(fd);
pAdapterStatus = (PADAPTERSTATUS)pBuffer; dwcNames = pAdapterStatus->AdapterInfo.name_count; RASAUTO_TRACE2( "IpxAddressToNetbiosName: results (status=0x%x, dwcNames=%d)", status, dwcNames); if (status == STATUS_SUCCESS && dwcNames) { CHAR szNetbiosName[NCBNAMSZ + 1];
pNames = pAdapterStatus->Names; if (CopyNetbiosName(pNames, dwcNames, szNetbiosName)) pszNetbiosName = AnsiStringToUnicodeString(pNames->name, NULL, 0); } LocalFree(pBuffer); LocalFree(pQuery);
return pszNetbiosName; } // IpxAddressToNetbiosName
BOOLEAN NetbiosFindName( IN LPTSTR *pszDevices, IN DWORD dwcDevices, IN LPTSTR pszAddress ) { NTSTATUS *pStatus; PHANDLE pfd; PHANDLE pEvent; POBJECT_ATTRIBUTES pObjectAttributes; PIO_STATUS_BLOCK pIoStatusBlock; PUNICODE_STRING pUnicodeString; PTDI_REQUEST_QUERY_INFORMATION pQuery; PTDI_CONNECTION_INFORMATION pConnectionInformation; PTA_NETBIOS_ADDRESS pRemoteAddress; CHAR szAddress[NCBNAMSZ]; PVOID *pBuffer; DWORD i, dwQuerySize, dwBufferSize; PADAPTERSTATUS pAdapterStatus; NAME_BUFFER *pNames; DWORD dwcWait, dwcNames; BOOLEAN bFound = FALSE;
//
// If there are no Netbios devices, then we're done.
//
if (pszDevices == NULL || !dwcDevices) return FALSE; //
// Allocate our arrays up front.
//
pStatus = (NTSTATUS *)LocalAlloc(LPTR, dwcDevices * sizeof (NTSTATUS)); if (pStatus == NULL) { RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed"); return FALSE; } pfd = (PHANDLE)LocalAlloc(LPTR, dwcDevices * sizeof (HANDLE)); if (pfd == NULL) { RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed"); LocalFree(pStatus); return FALSE; } pUnicodeString = (PUNICODE_STRING)LocalAlloc(LPTR, dwcDevices * sizeof (UNICODE_STRING)); if (pUnicodeString == NULL) { RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed"); LocalFree(pStatus); LocalFree(pfd); return FALSE; } pEvent = (PHANDLE)LocalAlloc( LPTR, dwcDevices * sizeof (HANDLE)); if (pEvent == NULL) { RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed"); LocalFree(pStatus); LocalFree(pfd); LocalFree(pUnicodeString); return FALSE; } pObjectAttributes = (POBJECT_ATTRIBUTES)LocalAlloc( LPTR, dwcDevices * sizeof (OBJECT_ATTRIBUTES)); if (pObjectAttributes == NULL) { RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed"); LocalFree(pStatus); LocalFree(pfd); LocalFree(pUnicodeString); LocalFree(pEvent); return FALSE; } pIoStatusBlock = (PIO_STATUS_BLOCK)LocalAlloc( LPTR, dwcDevices * sizeof (IO_STATUS_BLOCK)); if (pIoStatusBlock == NULL) { RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed"); LocalFree(pStatus); LocalFree(pfd); LocalFree(pUnicodeString); LocalFree(pEvent); LocalFree(pObjectAttributes); return FALSE; } pBuffer = LocalAlloc(LPTR, dwcDevices * sizeof (PVOID)); if (pBuffer == NULL) { RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed"); LocalFree(pStatus); LocalFree(pfd); LocalFree(pUnicodeString); LocalFree(pEvent); LocalFree(pObjectAttributes); LocalFree(pIoStatusBlock); return FALSE; } //
// Allocate and initialize our query structure.
// We will give the same query to all the devices.
//
dwQuerySize = sizeof (TDI_REQUEST_QUERY_INFORMATION) + sizeof (TDI_CONNECTION_INFORMATION) + sizeof (TA_NETBIOS_ADDRESS); pQuery = LocalAlloc(LPTR, dwQuerySize); if (pQuery == NULL) { RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed"); LocalFree(pStatus); LocalFree(pfd); LocalFree(pUnicodeString); LocalFree(pEvent); LocalFree(pObjectAttributes); LocalFree(pIoStatusBlock); return FALSE; } pQuery->QueryType = TDI_QUERY_ADAPTER_STATUS; (PTDI_CONNECTION_INFORMATION)&pQuery->RequestConnectionInformation; pQuery->RequestConnectionInformation = (PTDI_CONNECTION_INFORMATION)(pQuery + 1); pConnectionInformation = pQuery->RequestConnectionInformation; pConnectionInformation->UserDataLength = 0; pConnectionInformation->UserData = NULL; pConnectionInformation->OptionsLength = 0; pConnectionInformation->Options = NULL; pConnectionInformation->RemoteAddressLength = sizeof (TA_NETBIOS_ADDRESS); pConnectionInformation->RemoteAddress = (PTA_NETBIOS_ADDRESS)(pConnectionInformation + 1); pRemoteAddress = pConnectionInformation->RemoteAddress; pRemoteAddress->TAAddressCount = 1; pRemoteAddress->Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS); pRemoteAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS; pRemoteAddress->Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE; UnicodeStringToAnsiString( pszAddress, szAddress, sizeof (szAddress)); RtlFillMemory( (PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName, NCBNAMSZ, ' '); //
// Make sure the Netbios name is in uppercase!
//
_strupr(szAddress); RtlCopyMemory( (PCHAR)&pRemoteAddress->Address[0].Address[0].NetbiosName, szAddress, strlen(szAddress)); pRemoteAddress->Address[0].Address[0].NetbiosName[NCBNAMSZ - 1] = '\0'; RASAUTO_TRACE1("NetbiosFindName: address=%s", szAddress); //
// Initialize the OBJECT_ATTRIBUTES structure,
// open the device, and start the query
// for each device.
//
for (i = 0; i < dwcDevices; i++) { pBuffer[i] = NULL;
RtlInitUnicodeString(&pUnicodeString[i], pszDevices[i]); InitializeObjectAttributes( &pObjectAttributes[i], &pUnicodeString[i], OBJ_CASE_INSENSITIVE, NULL, NULL); pEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL); if (pEvent[i] == NULL) { RASAUTO_TRACE("NetbiosFindName: CreateEvent failed"); goto done; } pStatus[i] = NtCreateFile( &pfd[i], FILE_READ_DATA|FILE_WRITE_DATA, &pObjectAttributes[i], &pIoStatusBlock[i], NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0); if (!NT_SUCCESS(pStatus[i])) { RASAUTO_TRACE1("NetbiosFindName: NtCreateFile failed (status=0x%x)", pStatus[i]); continue; } //
// Allocate the results buffer.
//
dwBufferSize = 2048; for (;;) { pBuffer[i] = LocalAlloc(LPTR, dwBufferSize); if (pBuffer[i] == NULL) { RASAUTO_TRACE("NetbiosFindName: LocalAlloc failed"); goto done; } pStatus[i] = NtDeviceIoControlFile( pfd[i], pEvent[i], NULL, NULL, &pIoStatusBlock[i], IOCTL_TDI_QUERY_INFORMATION, pQuery, dwQuerySize, pBuffer[i], dwBufferSize); if (pStatus[i] != STATUS_BUFFER_OVERFLOW) break;
LocalFree(pBuffer[i]); pBuffer[i] = NULL; dwBufferSize *= 2; if (dwBufferSize >= 0xffff) { RASAUTO_TRACE("NetbiosFindName: Unable to allocate packet"); break; } } } //
// Determine whether any of the
// requests returned STATUS_SUCCESS.
//
RASAUTO_TRACE("NetbiosFindName: checking for STATUS_SUCCESS"); dwcWait = 0; for (i = 0; i < dwcDevices; i++) { RASAUTO_TRACE2("NetbiosFindName: %S: status=%d", pszDevices[i], pStatus[i]); if (pStatus[i] == STATUS_SUCCESS) { pAdapterStatus = (PADAPTERSTATUS)pBuffer[i]; dwcNames = pAdapterStatus->AdapterInfo.name_count; RASAUTO_TRACE2( "NetbiosFindName: %S: dwcNames=%d", pszDevices[i], dwcNames); if (dwcNames) { bFound = TRUE; goto done; } } else if (pStatus[i] == STATUS_PENDING) dwcWait++; } //
// If we didn't find a successful return,
// then wait for the others to complete.
//
RASAUTO_TRACE1("NetbiosFindName: dwcWait=%d", dwcWait); for (i = 0; i < dwcWait; i++) { NTSTATUS status; DWORD dwiDevice;
status = WaitForMultipleObjects(dwcDevices, pEvent, FALSE, INFINITE); RASAUTO_TRACE1("NetbiosFindName: WaitForMultipleObjects returned 0x%x", status); if (status == WAIT_FAILED) { RASAUTO_TRACE1( "NetbiosFindName: WaitForMultipleObjects failed (status=0x%x)", GetLastError()); goto done; } dwiDevice = (DWORD)status - WAIT_OBJECT_0; if (dwiDevice >= dwcDevices) { RASAUTO_TRACE( "NetbiosFindName: WaitForMultipleObjects returned STATUS_ABANDONED?"); goto done; } pStatus[dwiDevice] = pIoStatusBlock[dwiDevice].Status; RASAUTO_TRACE2( "NetbiosFindName: %S returned status 0x%x from wait", pszDevices[dwiDevice], pStatus[dwiDevice]); if (pStatus[dwiDevice] == STATUS_SUCCESS) { pAdapterStatus = (PADAPTERSTATUS)pBuffer[dwiDevice]; dwcNames = pAdapterStatus->AdapterInfo.name_count; RASAUTO_TRACE2( "NetbiosFindName: %S: dwcNames=%d", pszDevices[dwiDevice], dwcNames); if (dwcNames) { bFound = TRUE; goto done; } } } done: //
// Free the resources associated with
// each device.
//
for (i = 0; i < dwcDevices; i++) { RASAUTO_TRACE4( "NetbiosFindName: pIoStatusBlock[%d]=0x%x, pBuffer[%d]=0x%x", i, &pIoStatusBlock[i], i, pBuffer[i]); if (pfd[i] != NULL) { (void)NtCancelIoFile(pfd[i], &pIoStatusBlock[i]); NtClose(pfd[i]); } if (pEvent[i] != NULL) CloseHandle(pEvent[i]); if (pBuffer[i] != NULL) LocalFree(pBuffer[i]); } //
// Free the buffers we allocated above.
//
LocalFree(pStatus); LocalFree(pfd); LocalFree(pUnicodeString); LocalFree(pEvent); LocalFree(pObjectAttributes); LocalFree(pIoStatusBlock); LocalFree(pBuffer);
return bFound; } // NetbiosFindName
struct hostent * IpAddressToHostent( IN LPTSTR pszInetAddress ) { CHAR szInetAddress[ACD_ADDR_INET_LEN]; ULONG inaddr; struct hostent *hp;
UnicodeStringToAnsiString( pszInetAddress, szInetAddress, sizeof (szInetAddress)); inaddr = inet_addr(szInetAddress); //
// Disable the address so when we call gethostbyname(),
// we won't cause an autodial attempt. Enable it after
// we're done.
//
SetAddressDisabled(pszInetAddress, TRUE); hp = gethostbyaddr((char *)&inaddr, 4, PF_INET); SetAddressDisabled(pszInetAddress, FALSE);
return hp; } // InetAddressToHostent
struct hostent * InetAddressToHostent( IN LPTSTR pszInetAddress ) { CHAR szInetAddress[ACD_ADDR_INET_LEN]; struct hostent *hp;
UnicodeStringToAnsiString( pszInetAddress, szInetAddress, sizeof (szInetAddress)); //
// Disable the address so when we call gethostbyname(),
// we won't cause an autodial attempt. Enable it after
// we're done.
//
SetAddressDisabled(pszInetAddress, TRUE); hp = gethostbyname(szInetAddress); SetAddressDisabled(pszInetAddress, FALSE);
return hp; } // InetAddressToHostEnt
BOOLEAN PingIpAddress( IN LPTSTR pszIpAddress )
/*++
DESCRIPTION Determine whether an IP address is accessible by pinging it.
ARGUMENTS lpszAddress: the IP address
RETURN VALUE TRUE if lpszAddress is accessible, FALSE otherwise.
--*/
{ BOOLEAN fSuccess = FALSE; LONG inaddr; char szIpAddress[17]; int i, nReplies, nTry; char *lpSendBuf = NULL, *lpRecvBuf = NULL; HANDLE hIcmp = NULL; IP_OPTION_INFORMATION SendOpts; PICMP_ECHO_REPLY lpReply;
UnicodeStringToAnsiString(pszIpAddress, szIpAddress, sizeof (szIpAddress)); inaddr = inet_addr(szIpAddress); RASAUTO_TRACE2("PingIpAddress: IP address=(%s, 0x%x)", szIpAddress, inaddr); //
// Check to make sure we loaded icmp.dll.
//
if (hIcmpG == NULL) { RASAUTO_TRACE("PingIpAddress: icmp.dll not loaded!"); return FALSE; } //
// Open the icmp device.
//
hIcmp = (HANDLE)(*lpfnIcmpCreateFileG)(); if (hIcmp == INVALID_HANDLE_VALUE) { RASAUTO_TRACE("PingIpAddress: IcmpCreateFile failed"); return FALSE; } //
// Allocate the send and receive buffers.
//
lpSendBuf = LocalAlloc(LMEM_FIXED, PING_SEND_SIZE); if (lpSendBuf == NULL) { RASAUTO_TRACE("PingIpAddress: LocalAlloc failed"); goto done; } lpRecvBuf = LocalAlloc(LMEM_FIXED, PING_RECV_SIZE); if (lpRecvBuf == NULL) { RASAUTO_TRACE("PingIpAddress: LocalAlloc failed"); goto done; } //
// Initialize the send buffer pattern.
//
for (i = 0; i < PING_SEND_SIZE; i++) lpSendBuf[i] = 'a' + (i % 23); //
// Initialize the send options.
//
SendOpts.OptionsData = (unsigned char FAR *)0; SendOpts.OptionsSize = 0; SendOpts.Ttl = PING_TTL; SendOpts.Tos = 0; SendOpts.Flags = 0; //
// Ping the host.
//
for (nTry = 0; nTry < 3; nTry++) { DWORD dwTimeout = 750;
#ifdef notdef
if (nTry < 2) dwTimeout = 750; else dwTimeout = 2000; #endif
//
// Check to make sure the service isn't shutting
// down before we start on our next iteration.
//
if (WaitForSingleObject(hTerminatingG, 0) != WAIT_TIMEOUT) { RASAUTO_TRACE("PingIpAddress: shutting down"); LocalFree(lpRecvBuf); LocalFree(lpSendBuf); return FALSE; } nReplies = (int) (*lpfnIcmpSendEchoG)( hIcmp, inaddr, lpSendBuf, (unsigned short)PING_SEND_SIZE, &SendOpts, lpRecvBuf, PING_RECV_SIZE, dwTimeout); //
// Look at the responses to see
// if any are successful.
//
for (lpReply = (PICMP_ECHO_REPLY)lpRecvBuf, i = 0; i < nReplies; lpReply++, i++) { RASAUTO_TRACE2( "PingIpAddress: ping reply status[%d]=%d", i, lpReply->Status); //
// Unless the status is IP_REQ_TIMED_OUT,
// we're done.
//
fSuccess = (lpReply->Status == IP_SUCCESS); if (lpReply->Status != IP_REQ_TIMED_OUT) goto done; } } //
// Clean up.
//
done: if (lpRecvBuf != NULL) LocalFree(lpRecvBuf); if (lpSendBuf != NULL) LocalFree(lpSendBuf); if (hIcmp != NULL) (*lpfnIcmpCloseHandleG)(hIcmp);
return fSuccess; } // PingIpAddress
VOID LoadIcmpDll(VOID) { hIcmpG = LoadLibrary(ICMP_MODULE); if (hIcmpG == NULL) return; lpfnIcmpCreateFileG = GetProcAddress(hIcmpG, ICMPCREATEFILE); lpfnIcmpSendEchoG = GetProcAddress(hIcmpG, ICMPSENDECHO); lpfnIcmpCloseHandleG = GetProcAddress(hIcmpG, ICMPCLOSEHANDLE); if (lpfnIcmpCreateFileG == NULL || lpfnIcmpSendEchoG == NULL || lpfnIcmpCloseHandleG == NULL) { FreeLibrary(hIcmpG); hIcmpG = NULL; return; } } // LoadIcmpDll
VOID UnloadIcmpDll(VOID) { if (hIcmpG != NULL) { FreeLibrary(hIcmpG); hIcmpG = NULL; } }
|