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

503 lines
11 KiB
C
Raw Permalink 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) 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