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

531 lines
12 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) 1995 Microsoft Corporation
Module Name:
autodial.c
Abstract:
NT specific routines for interfacing with the
RAS AutoDial driver (rasacd.sys).
Author:
Anthony Discolo (adiscolo) Aug 30, 1995
Revision History:
Who When What
-------- -------- ----------------------------------------------
adiscolo 08-30-95 created
Notes:
--*/
#include "precomp.h"
#pragma hdrstop
#ifdef RASAUTODIAL
#include <acd.h>
#include <acdapi.h>
//
// Global variables
//
BOOLEAN fAcdLoadedG;
ACD_DRIVER AcdDriverG;
ULONG ulDriverIdG = 'Nbi ';
VOID
NbiRetryTdiConnect(
IN BOOLEAN fSuccess,
IN PVOID *pArgs
)
/*++
Routine Description:
This routine is called indirectly by the automatic
connection driver to continue the connection process
after an automatic connection has been made.
Arguments:
fSuccess - TRUE if the connection attempt was successful.
pArgs - a pointer to the argument vector
Return Value:
None.
--*/
{
NTSTATUS status;
PDEVICE pDevice = pArgs[0];
PCONNECTION pConnection = pArgs[1];
PREQUEST pRequest = pArgs[2];
CTELockHandle ConnectionLH, DeviceLH;
CTELockHandle CancelLH;
BOOLEAN bLockFreed = FALSE;
//
// Check that the connection is valid. This references
// the connection.
//
#if notdef // DBG
DbgPrint("NbiRetryTdiConnect: fSuccess=%d, pConnection=0x%x\n", fSuccess, pConnection);
#endif
status = NbiVerifyConnection(pConnection);
if (!NT_SUCCESS(status)) {
DbgPrint(
"NbiRetryTdiConnect: NbiVerifyConnection failed on connection 0x%x (status=0x%x)\n",
pConnection,
status);
return;
}
NB_GET_CANCEL_LOCK( &CancelLH );
NB_GET_LOCK (&pConnection->Lock, &ConnectionLH);
NB_GET_LOCK (&pDevice->Lock, &DeviceLH);
#if notdef // DBG
DbgPrint(
"NbiRetryTdiConnect: AddressFile=0x%x, DisassociatePending=0x%x, ClosePending=0x%x\n",
pConnection->AddressFile,
pConnection->DisassociatePending,
pConnection->ClosePending);
#endif
if ((pConnection->AddressFile != NULL) &&
(pConnection->AddressFile != (PVOID)-1) &&
(pConnection->DisassociatePending == NULL) &&
(pConnection->ClosePending == NULL))
{
NbiReferenceConnectionLock(pConnection, CREF_CONNECT);
//
// Clear the AUTOCONNECTING flag since we
// done with the automatic connection attempt.
// Set the AUTOCONNECTED flag to prevent us
// from attempting an automatic connection
// for this connection again.
//
pConnection->Flags &= ~CONNECTION_FLAGS_AUTOCONNECTING;
pConnection->Flags |= CONNECTION_FLAGS_AUTOCONNECTED;
pConnection->State = CONNECTION_STATE_CONNECTING;
pConnection->Retries = pDevice->ConnectionCount;
status = NbiTdiConnectFindName(
pDevice,
pRequest,
pConnection,
CancelLH,
ConnectionLH,
DeviceLH,
&bLockFreed);
}
else {
DbgPrint("NbiRetryTdiConnect: Connect on invalid connection 0x%x\n", pConnection);
pConnection->SubState = CONNECTION_SUBSTATE_C_DISCONN;
NB_FREE_LOCK (&pDevice->Lock, DeviceLH);
status = STATUS_INVALID_CONNECTION;
}
if (!bLockFreed) {
NB_FREE_LOCK (&pConnection->Lock, ConnectionLH);
NB_FREE_CANCEL_LOCK(CancelLH);
}
//
// Complete the irp if necessary.
//
if (status != STATUS_PENDING) {
REQUEST_INFORMATION(pRequest) = 0;
REQUEST_STATUS(pRequest) = status;
NbiCompleteRequest(pRequest);
NbiFreeRequest(pDevice, pRequest);
}
NbiDereferenceConnection(pConnection, CREF_VERIFY);
} /* NbiRetryTdiConnect */
BOOLEAN
NbiCancelAutoDialRequest(
IN PVOID pArg,
IN ULONG ulFlags,
IN ACD_CONNECT_CALLBACK pProc,
IN USHORT nArgs,
IN PVOID *pArgs
)
{
#if notdef // DBG
DbgPrint("NbiCancelAutodialRequest: pArg=0x%x\n", pArg);
#endif
if (nArgs != 2)
return FALSE;
return (pArgs[1] == pArg);
} // NbiCancelAutoDialRequest
BOOLEAN
NbiCancelTdiConnect(
IN PDEVICE pDevice,
IN PREQUEST pRequest,
IN PCONNECTION pConnection
)
/*++
DESCRIPTION
This routine is called by the I/O system to cancel a connection
when we are attempting to restore an automatic connection.
ARGUMENTS
pDevice: a pointer to the device object for this driver
pRequest: a pointer to the irp to be cancelled
pConnection: a pointer to the connnection to be cancelled
RETURN VALUE
TRUE if the request was canceled; FALSE otherwise.
--*/
{
ACD_ADDR addr;
//
// Get the address of the connection.
//
addr.fType = ACD_ADDR_NB;
RtlCopyMemory(&addr.cNetbios, pConnection->RemoteName, 16);
#ifdef notdef // DBG
DbgPrint(
"NbiCancelTdiConnect: pIrp=0x%x, RemoteName=%-15.15s, pConnection=0x%x\n",
pRequest,
addr.cNetbios,
pConnection);
#endif
//
// Cancel the autodial request.
//
return (*AcdDriverG.lpfnCancelConnection)(
ulDriverIdG,
&addr,
NbiCancelAutoDialRequest,
pConnection);
} // NbiCancelTdiConnect
BOOLEAN
NbiAttemptAutoDial(
IN PDEVICE pDevice,
IN PCONNECTION pConnection,
IN ULONG ulFlags,
IN ACD_CONNECT_CALLBACK pProc,
IN PREQUEST pRequest
)
/*++
Routine Description:
Call the automatic connection driver to attempt an
automatic connection.
Arguments:
pDevice - a pointer to the DEVICE structure for this connection
pConnection - a pointer to the CONNECTION block for this connection
ulFlags - connection flags to pass to the automatic
connection driver
pProc - a callback procedure when the automatic connection completes
pRequest - a pointer to the request irp
Return Value:
TRUE if the automatic connection was started successfully,
FALSE otherwise.
--*/
{
ACD_ADDR addr;
PVOID pArgs[3];
BOOLEAN bSuccess;
//
// If we've already attempted an automatic connection
// on this connection, don't try it again.
//
if (pConnection->Flags & CONNECTION_FLAGS_AUTOCONNECTED)
return FALSE;
//
// Get the address of the connection.
//
addr.fType = ACD_ADDR_NB;
RtlCopyMemory(&addr.cNetbios, pConnection->RemoteName, 16);
#ifdef notdef // DBG
DbgPrint("NbiAttemptAutoDial: szAddr=%15.15s\n", addr.cNetbios);
#endif
//
// Attempt to start the connection.
// NbiRetryTdiConnect() will be called
// when the connection process has completed.
//
pArgs[0] = pDevice;
pArgs[1] = pConnection;
pArgs[2] = pRequest;
bSuccess = (*AcdDriverG.lpfnStartConnection)(
ulDriverIdG,
&addr,
ulFlags,
pProc,
3,
pArgs);
if (bSuccess) {
//
// Set the AUTOCONNECTING flag so we know
// to also cancel the connection in the
// automatic connection driver if this
// request gets canceled.
//
pConnection->Flags |= CONNECTION_FLAGS_AUTOCONNECTING;
}
return bSuccess;
} // NbiAttemptAutoDial
VOID
NbiNoteNewConnection(
IN PCONNECTION pConnection
)
{
NTSTATUS status;
ACD_ADDR addr;
ACD_ADAPTER adapter;
ULONG i;
TDI_ADDRESS_IPX tdiIpxAddress;
addr.fType = ACD_ADDR_NB;
RtlCopyMemory(&addr.cNetbios, pConnection->RemoteName, 16);
//
// Determine the mac address of the adapter
// over which the connection has been made.
//
status = (pConnection->Device->Bind.QueryHandler)(
IPX_QUERY_IPX_ADDRESS,
#if defined(_PNP_POWER)
&pConnection->LocalTarget.NicHandle,
#else
pConnection->LocalTarget.NicId,
#endif _PNP_POWER
&tdiIpxAddress,
sizeof(TDI_ADDRESS_IPX),
NULL);
if (status != STATUS_SUCCESS) {
#if notdef // DBG
DbgPrint("NbiNoteNewConnection: QueryHandler(IPX_QUERY_IPX_ADDRESS) failed (status=0x%x)\n", status);
return;
#endif
}
//
// Copy the source mac address to identify
// the adapter.
//
adapter.fType = ACD_ADAPTER_MAC;
for (i = 0; i < 6; i++)
adapter.cMac[i] = tdiIpxAddress.NodeAddress[i];
#if notdef // DBG
DbgPrint(
"NbiNoteNewConnection: address=%-15.15s, remote mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
addr.cNetbios,
adapter.cMac[0],
adapter.cMac[1],
adapter.cMac[2],
adapter.cMac[3],
adapter.cMac[4],
adapter.cMac[5]);
#endif
//
// Simply notify the automatic connection driver
// that a successful connection has been made.
//
(*AcdDriverG.lpfnNewConnection)(
&addr,
&adapter);
} // NbiNoteNewConnection
VOID
NbiAcdBind()
{
NTSTATUS status;
UNICODE_STRING nameString;
IO_STATUS_BLOCK ioStatusBlock;
PIRP pIrp;
PFILE_OBJECT pAcdFileObject;
PDEVICE_OBJECT pAcdDeviceObject;
PACD_DRIVER pDriver = &AcdDriverG;
//
// Initialize the name of the automatic
// connection device.
//
RtlInitUnicodeString(&nameString, ACD_DEVICE_NAME);
//
// Get the file and device objects for the
// device.
//
status = IoGetDeviceObjectPointer(
&nameString,
SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
&pAcdFileObject,
&pAcdDeviceObject);
if (status != STATUS_SUCCESS)
return;
//
// Reference the device object.
//
ObReferenceObject(pAcdDeviceObject);
//
// Remove the reference IoGetDeviceObjectPointer()
// put on the file object.
//
ObDereferenceObject(pAcdFileObject);
//
// Initialize our part of the ACD_DRIVER
// structure.
//
KeInitializeSpinLock(&AcdDriverG.SpinLock);
AcdDriverG.ulDriverId = ulDriverIdG;
AcdDriverG.fEnabled = FALSE;
//
// Build a request to get the automatic
// connection driver entry points.
//
pIrp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_ACD_BIND,
pAcdDeviceObject,
(PVOID)&pDriver,
sizeof (pDriver),
NULL,
0,
TRUE,
NULL,
&ioStatusBlock);
if (pIrp == NULL) {
ObDereferenceObject(pAcdDeviceObject);
return;
}
//
// Submit the request to the
// automatic connection driver.
//
status = IoCallDriver(pAcdDeviceObject, pIrp);
fAcdLoadedG = (status == STATUS_SUCCESS);
//
// Close the device.
//
ObDereferenceObject(pAcdDeviceObject);
} // NbiAcdBind
VOID
NbiAcdUnbind()
{
NTSTATUS status;
UNICODE_STRING nameString;
IO_STATUS_BLOCK ioStatusBlock;
PIRP pIrp;
PFILE_OBJECT pAcdFileObject;
PDEVICE_OBJECT pAcdDeviceObject;
PACD_DRIVER pDriver = &AcdDriverG;
//
// Don't bother to unbind if we
// didn't successfully bind in the
// first place.
//
if (!fAcdLoadedG)
return;
//
// Initialize the name of the automatic
// connection device.
//
RtlInitUnicodeString(&nameString, ACD_DEVICE_NAME);
//
// Get the file and device objects for the
// device.
//
status = IoGetDeviceObjectPointer(
&nameString,
SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
&pAcdFileObject,
&pAcdDeviceObject);
if (status != STATUS_SUCCESS)
return;
//
// Reference the device object.
//
ObReferenceObject(pAcdDeviceObject);
//
// Remove the reference IoGetDeviceObjectPointer()
// put on the file object.
//
ObDereferenceObject(pAcdFileObject);
//
// Build a request to unbind from
// the automatic connection driver.
//
pIrp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_ACD_UNBIND,
pAcdDeviceObject,
(PVOID)&pDriver,
sizeof (pDriver),
NULL,
0,
TRUE,
NULL,
&ioStatusBlock);
if (pIrp == NULL) {
ObDereferenceObject(pAcdDeviceObject);
return;
}
//
// Submit the request to the
// automatic connection driver.
//
status = IoCallDriver(pAcdDeviceObject, pIrp);
//
// Close the device.
//
ObDereferenceObject(pAcdDeviceObject);
} // NbiAcdUnbind
#endif // RASAUTODIAL