/*++ 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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; } }