503 lines
11 KiB
C
503 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989, 1990, 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
autodial.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains code that interacts with the
|
|||
|
automatic connection driver (rasacd.sys):
|
|||
|
|
|||
|
o NbfNoteNewConnection
|
|||
|
o NbfAcdBind
|
|||
|
o NbfAcdUnbind
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Anthony Discolo (adiscolo) 6 September 1995
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
#ifdef RASAUTODIAL
|
|||
|
|
|||
|
#include <acd.h>
|
|||
|
#include <acdapi.h>
|
|||
|
|
|||
|
//
|
|||
|
// Global variables.
|
|||
|
//
|
|||
|
BOOLEAN fAcdLoadedG;
|
|||
|
ACD_DRIVER AcdDriverG;
|
|||
|
ULONG ulDriverIdG = 'Nbf ';
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
NbfCancelAutoDialRequest(
|
|||
|
IN PVOID pArg,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN ACD_CONNECT_CALLBACK pProc,
|
|||
|
IN USHORT nArgs,
|
|||
|
IN PVOID *pArgs
|
|||
|
)
|
|||
|
{
|
|||
|
if (nArgs != 1)
|
|||
|
return FALSE;
|
|||
|
|
|||
|
return (pArgs[0] == pArg);
|
|||
|
} // NbfCancelAutoDialRequest
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NbfRetryTdiConnect(
|
|||
|
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;
|
|||
|
PTP_CONNECTION pConnection = pArgs[0];
|
|||
|
KIRQL irql;
|
|||
|
BOOL fStopping;
|
|||
|
|
|||
|
//
|
|||
|
// Check for a destroyed connection.
|
|||
|
//
|
|||
|
if (pConnection == NULL)
|
|||
|
return;
|
|||
|
status = NbfVerifyConnectionObject(pConnection);
|
|||
|
if (status != STATUS_SUCCESS) {
|
|||
|
DbgPrint(
|
|||
|
"NbfRetryTdiConnect: NbfVerifyConnectionObject failed (status=0x%x)\n",
|
|||
|
status);
|
|||
|
return;
|
|||
|
}
|
|||
|
#ifdef notdef // DBG
|
|||
|
DbgPrint(
|
|||
|
"NbfRetryTdiConnect: fSuccess=%d, pConnection=0x%x, STOPPING=%d\n",
|
|||
|
fSuccess,
|
|||
|
pConnection,
|
|||
|
pConnection->Flags2 & CONNECTION_FLAGS2_STOPPING);
|
|||
|
#endif
|
|||
|
KeRaiseIrql(DISPATCH_LEVEL, &irql);
|
|||
|
//
|
|||
|
// Check to see if the connection
|
|||
|
// is closing.
|
|||
|
//
|
|||
|
ACQUIRE_DPC_SPIN_LOCK(&pConnection->SpinLock);
|
|||
|
fStopping = (pConnection->Flags2 & CONNECTION_FLAGS2_STOPPING);
|
|||
|
//
|
|||
|
// Clear the automatic connection
|
|||
|
// in-progress flag, and set the
|
|||
|
// autoconnected flag.
|
|||
|
//
|
|||
|
pConnection->Flags2 &= ~CONNECTION_FLAGS2_AUTOCONNECTING;
|
|||
|
pConnection->Flags2 |= CONNECTION_FLAGS2_AUTOCONNECTED;
|
|||
|
RELEASE_DPC_SPIN_LOCK(&pConnection->SpinLock);
|
|||
|
if (!fStopping) {
|
|||
|
if (fSuccess) {
|
|||
|
//
|
|||
|
// Restart the name query.
|
|||
|
//
|
|||
|
pConnection->Retries =
|
|||
|
(USHORT)pConnection->Provider->NameQueryRetries;
|
|||
|
NbfSendNameQuery (
|
|||
|
pConnection,
|
|||
|
TRUE);
|
|||
|
NbfStartConnectionTimer (
|
|||
|
pConnection,
|
|||
|
ConnectionEstablishmentTimeout,
|
|||
|
pConnection->Provider->NameQueryTimeout);
|
|||
|
}
|
|||
|
else {
|
|||
|
//
|
|||
|
// Terminate the connection with an error.
|
|||
|
//
|
|||
|
NbfStopConnection(pConnection, STATUS_BAD_NETWORK_PATH);
|
|||
|
}
|
|||
|
}
|
|||
|
KeLowerIrql(irql);
|
|||
|
NbfDereferenceConnection ("NbfRetryTdiConnect", pConnection, CREF_BY_ID);
|
|||
|
} /* NbfRetryTdiConnect */
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
NbfCancelTdiConnect(
|
|||
|
IN PDEVICE_OBJECT pDeviceObject,
|
|||
|
IN PIRP pIrp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
DESCRIPTION
|
|||
|
This routine is called by the I/O system to cancel a connection
|
|||
|
when we are attempting to restore an automatic connection.
|
|||
|
|
|||
|
ARGUMENTS
|
|||
|
pDeviceObject: a pointer to the device object for this driver
|
|||
|
|
|||
|
pIrp: a pointer to the irp to be cancelled
|
|||
|
|
|||
|
RETURN VALUE
|
|||
|
TRUE if the request was canceled; FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PIO_STACK_LOCATION pIrpSp;
|
|||
|
PTP_CONNECTION pConnection;
|
|||
|
ACD_ADDR addr;
|
|||
|
|
|||
|
UNREFERENCED_PARAMETER(pDeviceObject);
|
|||
|
//
|
|||
|
// Get a pointer to the current stack location in the IRP. This is where
|
|||
|
// the function codes and parameters are stored.
|
|||
|
//
|
|||
|
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
|
|||
|
pConnection = pIrpSp->FileObject->FsContext;
|
|||
|
if (pConnection == NULL)
|
|||
|
return FALSE;
|
|||
|
#ifdef notdef // DBG
|
|||
|
DbgPrint(
|
|||
|
"NbfCancelTdiConnect: pIrp=0x%x, pConnection=0x%x\n",
|
|||
|
pIrp,
|
|||
|
pConnection);
|
|||
|
#endif
|
|||
|
//
|
|||
|
// Get the address of the connection.
|
|||
|
//
|
|||
|
addr.fType = ACD_ADDR_NB;
|
|||
|
RtlCopyMemory(&addr.cNetbios, pConnection->CalledAddress.NetbiosName, 15);
|
|||
|
//
|
|||
|
// Cancel the autodial request.
|
|||
|
//
|
|||
|
return (*AcdDriverG.lpfnCancelConnection)(
|
|||
|
ulDriverIdG,
|
|||
|
&addr,
|
|||
|
NbfCancelAutoDialRequest,
|
|||
|
pConnection);
|
|||
|
} // NbfCancelTdiConnect
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
NbfAttemptAutoDial(
|
|||
|
IN PTP_CONNECTION pConnection,
|
|||
|
IN ULONG ulFlags,
|
|||
|
IN ACD_CONNECT_CALLBACK pProc,
|
|||
|
IN PVOID pArg
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Call the automatic connection driver to attempt an
|
|||
|
automatic connection.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pConnection - a pointer to the TP_CONNECTION block for this connection
|
|||
|
|
|||
|
ulFlags - connection flags to pass to the automatic
|
|||
|
connection driver
|
|||
|
|
|||
|
pProc - a callback procedure when the automatic connection completes
|
|||
|
|
|||
|
pArg - the single parameter to the callback procedure
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if the automatic connection was started successfully,
|
|||
|
FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ACD_ADDR addr;
|
|||
|
PVOID pArgs[1];
|
|||
|
BOOLEAN bSuccess;
|
|||
|
|
|||
|
//
|
|||
|
// If we've already attempted an automatic
|
|||
|
// connection on this connection, then
|
|||
|
// don't try again.
|
|||
|
//
|
|||
|
if (pConnection->Flags2 & CONNECTION_FLAGS2_AUTOCONNECTED)
|
|||
|
return FALSE;
|
|||
|
//
|
|||
|
// Get the address of the connection.
|
|||
|
//
|
|||
|
addr.fType = ACD_ADDR_NB;
|
|||
|
RtlCopyMemory(&addr.cNetbios, pConnection->CalledAddress.NetbiosName, 15);
|
|||
|
#ifdef notdef // DBG
|
|||
|
DbgPrint("NbfAttemptAutoDial: szAddr=%15.15s\n", addr.cNetbios);
|
|||
|
#endif
|
|||
|
//
|
|||
|
// Attempt to start the connection.
|
|||
|
// NbfRetryTdiConnect() will be called
|
|||
|
// when the connection process has completed.
|
|||
|
//
|
|||
|
pArgs[0] = pArg;
|
|||
|
bSuccess = (*AcdDriverG.lpfnStartConnection)(
|
|||
|
ulDriverIdG,
|
|||
|
&addr,
|
|||
|
ulFlags,
|
|||
|
pProc,
|
|||
|
1,
|
|||
|
pArgs);
|
|||
|
if (bSuccess) {
|
|||
|
//
|
|||
|
// Set the CONNECTION_FLAGS2_AUTOCONNECTING flag on
|
|||
|
// the connection. This will prevent it from being
|
|||
|
// aborted during the automatic connection process.
|
|||
|
//
|
|||
|
pConnection->Flags2 |= CONNECTION_FLAGS2_AUTOCONNECTING;
|
|||
|
}
|
|||
|
|
|||
|
return bSuccess;
|
|||
|
} // NbfAttemptAutoDial
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NbfNoteNewConnection(
|
|||
|
PTP_CONNECTION pConnection,
|
|||
|
PDEVICE_CONTEXT DeviceContext
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
Inform the automatic connection driver of a successful
|
|||
|
new connection.
|
|||
|
|
|||
|
Arguments:
|
|||
|
Connection - a pointer to a connection object
|
|||
|
|
|||
|
DeviceContext - a pointer to the device context
|
|||
|
|
|||
|
Return Value:
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
KIRQL irql;
|
|||
|
ACD_ADDR addr;
|
|||
|
ACD_ADAPTER adapter;
|
|||
|
ULONG ulcChars;
|
|||
|
|
|||
|
addr.fType = ACD_ADDR_NB;
|
|||
|
RtlCopyMemory(&addr.cNetbios, pConnection->CalledAddress.NetbiosName, 15);
|
|||
|
#ifdef notdef // DBG
|
|||
|
DbgPrint("NbfNoteNewConnection: szAddr=%15.15s\n", addr.cNetbios);
|
|||
|
#endif
|
|||
|
//
|
|||
|
// Eliminate the "/Device/Nbf_" prefix when
|
|||
|
// copying the adapter name.
|
|||
|
//
|
|||
|
adapter.fType = ACD_ADAPTER_NAME;
|
|||
|
ulcChars = DeviceContext->DeviceNameLength / sizeof(WCHAR) - 1 - 12;
|
|||
|
if (ulcChars >= ACD_ADAPTER_NAME_LEN)
|
|||
|
ulcChars = ACD_ADAPTER_NAME_LEN - 1;
|
|||
|
RtlCopyMemory(
|
|||
|
adapter.szName,
|
|||
|
&DeviceContext->DeviceName[12],
|
|||
|
ulcChars * sizeof (WCHAR));
|
|||
|
adapter.szName[ulcChars] = L'\0';
|
|||
|
//
|
|||
|
// Simply notify the automatic connection driver
|
|||
|
// that a successful connection has been made.
|
|||
|
//
|
|||
|
(*AcdDriverG.lpfnNewConnection)(
|
|||
|
&addr,
|
|||
|
&adapter);
|
|||
|
} // NbfNoteNewConnection
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NbfAcdBind()
|
|||
|
{
|
|||
|
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);
|
|||
|
} // NbfAcdBind
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NbfAcdUnbind()
|
|||
|
{
|
|||
|
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);
|
|||
|
} // NbfAcdUnbind
|
|||
|
|
|||
|
#endif // RASAUTODIAL
|
|||
|
|
|||
|
|