windows-nt/Source/XPSP1/NT/net/rras/ras/autodial/rasadhlp/autodial.c
2020-09-26 16:20:57 +08:00

445 lines
9.1 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1996 Microsoft Corporation
MODULE NAME
autodial.c
ABSTRACT
This module contains support for RAS AutoDial system service.
AUTHOR
Anthony Discolo (adiscolo) 22-Apr-1996
REVISION HISTORY
--*/
#define UNICODE
#define _UNICODE
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <stdlib.h>
#include <windows.h>
#include <acd.h>
#include <debug.h>
#include <winsock2.h>
#include <dnsapi.h>
#define NEW_TRANSPORT_INTERVAL 0
BOOLEAN
AcsHlpSendCommand(
IN PACD_NOTIFICATION pRequest
)
/*++
DESCRIPTION
Take an automatic connection driver command block
and send it to the driver.
ARGUMENTS
pRequest: a pointer to the command block
RETURN VALUE
TRUE if successful; FALSE otherwise.
--*/
{
NTSTATUS status;
HANDLE hAcd;
HANDLE hNotif = NULL;
UNICODE_STRING nameString;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
//
// Initialize the name of the automatic
// connection device.
//
RtlInitUnicodeString(&nameString, ACD_DEVICE_NAME);
//
// Initialize the object attributes.
//
InitializeObjectAttributes(
&objectAttributes,
&nameString,
OBJ_CASE_INSENSITIVE,
(HANDLE)NULL,
(PSECURITY_DESCRIPTOR)NULL);
//
// Open the automatic connection device.
//
status = NtCreateFile(
&hAcd,
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 (status != STATUS_SUCCESS)
return FALSE;
//
// Create an event to wait on.
//
hNotif = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hNotif == NULL) {
CloseHandle(hAcd);
return FALSE;
}
status = NtDeviceIoControlFile(
hAcd,
hNotif,
NULL,
NULL,
&ioStatusBlock,
IOCTL_ACD_CONNECT_ADDRESS,
pRequest,
sizeof (ACD_NOTIFICATION),
NULL,
0);
if (status == STATUS_PENDING) {
status = WaitForSingleObject(hNotif, INFINITE);
//
// If WaitForSingleObject() returns successfully,
// return the status from the status block,
// otherwise return the wait status.
//
if (status == WAIT_OBJECT_0)
status = ioStatusBlock.Status;
}
//
// Free resources.
//
CloseHandle(hNotif);
CloseHandle(hAcd);
return (status == STATUS_SUCCESS);
} // AcsHlpSendCommand
BOOLEAN
AcsHlpAttemptConnection(
IN PACD_ADDR pAddr
)
/*++
DESCRIPTION
Construct an automatic connection driver command block
to attempt to create an autodial connection for
the specified address.
ARGUMENTS
pAddr: a pointer to the address
RETURN VALUE
TRUE if successful; FALSE otherwise.
--*/
{
ACD_NOTIFICATION request;
//
// Initialize the request with
// the address.
//
RtlCopyMemory(&request.addr, pAddr, sizeof (ACD_ADDR));
request.ulFlags = 0;
RtlZeroMemory(&request.adapter, sizeof (ACD_ADAPTER));
//
// Give this request to the automatic
// connection driver.
//
return AcsHlpSendCommand(&request);
} // AcsHlpAttemptConnection
BOOLEAN
AcsHlpNoteNewConnection(
IN PACD_ADDR pAddr,
IN PACD_ADAPTER pAdapter
)
/*++
DESCRIPTION
Construct an automatic connection driver command block
to notify the automatic connection service of a new connection.
ARGUMENTS
pAddr: a pointer to the address
pAdapter: a pointer to the adapter over which the new
connection was made
RETURN VALUE
TRUE if successful; FALSE otherwise.
--*/
{
ULONG cbAddress;
ACD_NOTIFICATION request;
//
// Initialize the request with
// the address.
//
RtlCopyMemory(&request.addr, pAddr, sizeof (ACD_ADDR));
request.ulFlags = ACD_NOTIFICATION_SUCCESS;
RtlCopyMemory(&request.adapter, pAdapter, sizeof (ACD_ADAPTER));
//
// Give this request to the automatic
// connection driver.
//
return AcsHlpSendCommand(&request);
} // AcsHlpNoteNewConnection
CHAR *
pszDupWtoA(
IN LPCWSTR psz
)
{
CHAR* pszNew = NULL;
if (NULL != psz)
{
DWORD cb;
cb = WideCharToMultiByte(CP_ACP,
0,
psz,
-1,
NULL,
0,
NULL,
NULL);
pszNew = (CHAR*) LocalAlloc(LPTR, cb);
if (NULL == pszNew)
{
goto done;
}
cb = WideCharToMultiByte(CP_ACP,
0,
psz,
-1,
pszNew,
cb,
NULL,
NULL);
if (!cb)
{
LocalFree(pszNew);
pszNew = NULL;
goto done;
}
}
done:
return pszNew;
}
BOOL
fIsDnsName(LPCWSTR pszName)
{
HINSTANCE hInst = NULL;
BOOL fRet = FALSE;
FARPROC pfnDnsValidateName = NULL;
if( (NULL == (hInst = LoadLibrary(TEXT("dnsapi.dll"))))
|| (NULL == (pfnDnsValidateName = GetProcAddress(
hInst,
"DnsValidateName_W")
)))
{
DWORD retcode = GetLastError();
goto done;
}
fRet = (ERROR_SUCCESS == pfnDnsValidateName(pszName, DnsNameDomain));
done:
if(NULL != hInst)
{
FreeLibrary(hInst);
}
return fRet;
}
ULONG
ulGetAutodialSleepInterval()
{
DWORD dwSleepInterval = NEW_TRANSPORT_INTERVAL;
HKEY hkey = NULL;
DWORD dwType;
DWORD dwSize = sizeof(DWORD);
TCHAR *pszAutodialParam =
TEXT("SYSTEM\\CurrentControlSet\\Services\\RasAuto\\Parameters");
if (ERROR_SUCCESS != RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
pszAutodialParam,
0, KEY_READ,
&hkey))
{
goto done;
}
if(ERROR_SUCCESS != RegQueryValueEx(
hkey,
TEXT("NewTransportWaitInterval"),
NULL,
&dwType,
(LPBYTE) &dwSleepInterval,
&dwSize))
{
goto done;
}
done:
if(NULL != hkey)
{
RegCloseKey(hkey);
}
return (ULONG) dwSleepInterval;
}
DWORD
DwGetAcdAddr(ACD_ADDR *paddr, LPCWSTR pszName)
{
CHAR *pszNameA = NULL;
CHAR *pszNameAt = NULL;
DWORD retcode = ERROR_SUCCESS;
ULONG ulIpAddr = 0;
if( (NULL == pszName)
|| (NULL == paddr))
{
retcode = E_INVALIDARG;
goto done;
}
pszNameA = pszDupWtoA(pszName);
if(NULL == pszNameA)
{
retcode = E_FAIL;
goto done;
}
if(INADDR_NONE != (ulIpAddr = inet_addr(pszNameA)))
{
paddr->fType = ACD_ADDR_IP;
paddr->ulIpaddr = ulIpAddr;
goto done;
}
if(fIsDnsName(pszName))
{
paddr->fType = ACD_ADDR_INET;
RtlCopyMemory((PBYTE) paddr->szInet,
(PBYTE) pszNameA,
strlen(pszNameA) + 1);
goto done;
}
pszNameAt = pszNameA;
//
// Skip '\\' if required
//
if( (TEXT('\0') != pszName[0])
&& (TEXT('\\') == pszName[0])
&& (TEXT('\\') == pszName[1]))
{
pszNameA += 2;
}
//
// Default to a netbios name if its neither an ip address
// or a dns name
//
paddr->fType = ACD_ADDR_NB;
RtlCopyMemory((PBYTE) paddr->cNetbios,
(PBYTE) pszNameA,
strlen(pszNameA) + 1);
done:
if(NULL != pszNameAt)
{
LocalFree(pszNameAt);
}
return retcode;
}
BOOL
AcsHlpNbConnection(LPCWSTR pszName)
{
ACD_ADDR addr = {0};
BOOL fRet;
if(!(fRet = (ERROR_SUCCESS == DwGetAcdAddr(&addr, pszName))))
{
goto done;
}
fRet = AcsHlpAttemptConnection(&addr);
//
// Temporary solution for beta2. We may need to wait till redir gets
// a new transport notification. Currently There is no way to
// guarantee that redir is bound to some transport before returning
// from this api.
//
if(fRet)
{
ULONG ulSleepInterval = ulGetAutodialSleepInterval();
if(ulSleepInterval > 0)
{
Sleep(ulSleepInterval);
}
}
done:
return fRet;
}