1068 lines
30 KiB
C
1068 lines
30 KiB
C
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
}
|