1210 lines
32 KiB
C
1210 lines
32 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
address.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains code which defines the NetBIOS driver's
|
|||
|
address object.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Colin Watson (ColinW) 13-Mar-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "nb.h"
|
|||
|
//nclude <zwapi.h>
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, NbAddName)
|
|||
|
#pragma alloc_text(PAGE, NbOpenAddress)
|
|||
|
#pragma alloc_text(PAGE, NbAddressClose)
|
|||
|
#pragma alloc_text(PAGE, NbSetEventHandler)
|
|||
|
#pragma alloc_text(PAGE, SubmitTdiRequest)
|
|||
|
#pragma alloc_text(PAGE, NewAb)
|
|||
|
#endif
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NbAddName(
|
|||
|
IN PDNCB pdncb,
|
|||
|
IN PIO_STACK_LOCATION IrpSp
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called to add a name to the name table so that the
|
|||
|
name is available for listens etc. If the name is already in the table
|
|||
|
then reject the request. If an error is found by NewAb then it is
|
|||
|
recorded directly in the NCB.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pdncb - Pointer to the NCB.
|
|||
|
|
|||
|
Irp - Pointer to the request packet representing the I/O request.
|
|||
|
|
|||
|
IrpSp - Pointer to current IRP stack frame.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The function value is the status of the operation. This is always
|
|||
|
STATUS_SUCCESS because the operations called by this routine are all
|
|||
|
synchronous. We must never return an error status since this would
|
|||
|
prevent the ncb from being copied back.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
PFCB pfcb = IrpSp->FileObject->FsContext2;
|
|||
|
PSZ Name = pdncb->ncb_name;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint(( "\n****** Start of AddName ****** pdncb %lx\n", pdncb ));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// NewAb is used in file.c to add the reserved name. Check here
|
|||
|
// for an application using a special name.
|
|||
|
//
|
|||
|
|
|||
|
if (( pdncb->ncb_name[0] == '*' ) ||
|
|||
|
( pdncb->ncb_name[0] == '\0' )) {
|
|||
|
NCB_COMPLETE( pdncb, NRC_NOWILD );
|
|||
|
} else {
|
|||
|
NewAb( IrpSp, pdncb );
|
|||
|
}
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NbDeleteName(
|
|||
|
IN PDNCB pdncb,
|
|||
|
IN PIO_STACK_LOCATION IrpSp
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called to delete a name. To perform this operation
|
|||
|
the AddressHandle to the transport is closed and the Address Block
|
|||
|
is deleted.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pdncb - Pointer to the NCB.
|
|||
|
|
|||
|
Irp - Pointer to the request packet representing the I/O request.
|
|||
|
|
|||
|
IrpSp - Pointer to current IRP stack frame.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The function value is the status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFCB pfcb = IrpSp->FileObject->FsContext2;
|
|||
|
PPAB ppab;
|
|||
|
KIRQL OldIrql; // Used when SpinLock held.
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint(( "\n****** Start of NbDeleteName ****** pdncb %lx\n", pdncb ));
|
|||
|
}
|
|||
|
|
|||
|
if (( pdncb->ncb_name[0] == '*' ) ||
|
|||
|
( pdncb->ncb_name[0] == '\0' )) {
|
|||
|
NCB_COMPLETE( pdncb, NRC_NOWILD );
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
LOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
ppab = FindAb( pfcb, pdncb, FALSE );
|
|||
|
|
|||
|
if ( ppab != NULL ) {
|
|||
|
|
|||
|
if (( (*ppab)->NameNumber == 0) ||
|
|||
|
( (*ppab)->NameNumber == MAXIMUM_ADDRESS)) {
|
|||
|
UNLOCK( pfcb, OldIrql );
|
|||
|
NCB_COMPLETE( pdncb, NRC_NAMERR );
|
|||
|
} else {
|
|||
|
|
|||
|
if ( ((*ppab)->Status & 0x7) != REGISTERED) {
|
|||
|
UNLOCK( pfcb, OldIrql );
|
|||
|
NCB_COMPLETE( pdncb, NRC_TOOMANY ); // Try later.
|
|||
|
} else {
|
|||
|
if ( FindActiveSession( pfcb, pdncb, ppab ) == TRUE ) {
|
|||
|
// When all the sessions close, the name will be deleted.
|
|||
|
UNLOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
CleanupAb( ppab, FALSE );
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
NCB_COMPLETE( pdncb, NRC_ACTSES );
|
|||
|
} else {
|
|||
|
UNLOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
CleanupAb( ppab, TRUE );
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
NCB_COMPLETE( pdncb, NRC_GOODRET );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
UNLOCK( pfcb, OldIrql );
|
|||
|
// FindAb has already set the completion code.
|
|||
|
}
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NbOpenAddress (
|
|||
|
OUT PHANDLE FileHandle,
|
|||
|
OUT PVOID *Object,
|
|||
|
IN PFCB pfcb,
|
|||
|
IN UCHAR LanNumber,
|
|||
|
IN PDNCB pdncb OPTIONAL
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine uses the transport to create an entry in the NetBIOS
|
|||
|
table with the value of "Name". It will re-use an existing entry if
|
|||
|
"Name" already exists.
|
|||
|
|
|||
|
Note: This synchronous call may take a number of seconds. If this matters
|
|||
|
then the caller should specify ASYNCH and a post routine so that it is
|
|||
|
performed by the thread created by the netbios dll routines.
|
|||
|
|
|||
|
If pdncb == NULL then a special handle is returned that is capable of
|
|||
|
administering the transport. For example to execute an ASTAT.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileHandle - Pointer to where the filehandle is to be returned.
|
|||
|
|
|||
|
*Object - Pointer to where the file object pointer is to be stored
|
|||
|
|
|||
|
pfcb - supplies the device names for the lana number.
|
|||
|
|
|||
|
LanNumber - supplies the network adapter to be opened.
|
|||
|
|
|||
|
pdncb - Pointer to either an NCB or NULL.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The function value is the status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
IO_STATUS_BLOCK IoStatusBlock;
|
|||
|
NTSTATUS Status;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
PFILE_FULL_EA_INFORMATION EaBuffer;
|
|||
|
ULONG EaLength;
|
|||
|
TA_NETBIOS_ADDRESS Address;
|
|||
|
ULONG ShareAccess;
|
|||
|
BOOLEAN ProcessAttached = FALSE;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
if ( pdncb ) {
|
|||
|
NbPrint( ("NbOpenAddress: Opening lana: %lx, Address:\n",
|
|||
|
LanNumber ));
|
|||
|
NbFormattedDump( pdncb->ncb_name, NCBNAMSZ );
|
|||
|
if ( pdncb->ncb_command == NCBADDBROADCAST ) {
|
|||
|
NbPrint (("NbOpenAddress: Opening Broadcast Address length: %x\n",
|
|||
|
pdncb->ncb_length));
|
|||
|
}
|
|||
|
} else {
|
|||
|
NbPrint( ("NbOpenAddress: Opening lana: %lx Control Channel\n",
|
|||
|
LanNumber));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
InitializeObjectAttributes (
|
|||
|
&ObjectAttributes,
|
|||
|
&pfcb->pDriverName[LanNumber],
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
NULL);
|
|||
|
|
|||
|
if ( ARGUMENT_PRESENT( pdncb ) ) {
|
|||
|
|
|||
|
EaLength = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +
|
|||
|
TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
|
|||
|
sizeof(TA_NETBIOS_ADDRESS); // EA length
|
|||
|
|
|||
|
EaBuffer = (PFILE_FULL_EA_INFORMATION)
|
|||
|
ExAllocatePoolWithTag( NonPagedPool, EaLength, 'eSBN' );
|
|||
|
|
|||
|
if (EaBuffer == NULL) {
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
EaBuffer->NextEntryOffset = 0;
|
|||
|
EaBuffer->Flags = 0;
|
|||
|
EaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
|
|||
|
|
|||
|
EaBuffer->EaValueLength = sizeof (TA_NETBIOS_ADDRESS);
|
|||
|
|
|||
|
RtlMoveMemory( EaBuffer->EaName, TdiTransportAddress, EaBuffer->EaNameLength + 1 );
|
|||
|
|
|||
|
//
|
|||
|
// Create a copy of the NETBIOS address descriptor in a local
|
|||
|
// first, in order to avoid alignment problems.
|
|||
|
//
|
|||
|
|
|||
|
Address.TAAddressCount = 1;
|
|||
|
Address.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
|
|||
|
|
|||
|
if ( pdncb->ncb_command == NCBADDBROADCAST ) {
|
|||
|
Address.Address[0].AddressLength = pdncb->ncb_length;
|
|||
|
} else {
|
|||
|
Address.Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
|
|||
|
}
|
|||
|
|
|||
|
if (((pdncb->ncb_command & ~ASYNCH) == NCBADDNAME) ||
|
|||
|
((pdncb->ncb_command & ~ASYNCH) == NCBQUICKADDNAME)) {
|
|||
|
|
|||
|
ShareAccess = 0; // Exclusive access
|
|||
|
|
|||
|
|
|||
|
if ((pdncb->ncb_command & ~ASYNCH) == NCBQUICKADDNAME) {
|
|||
|
Address.Address[0].Address[0].NetbiosNameType =
|
|||
|
TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE;
|
|||
|
} else {
|
|||
|
Address.Address[0].Address[0].NetbiosNameType =
|
|||
|
TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
if ((pdncb->ncb_command & ~ASYNCH) == NCBADDRESERVED) {
|
|||
|
//
|
|||
|
// NB30 non-conformance!
|
|||
|
// We allow multiple applications to use name number 1. This is so that we can
|
|||
|
// conveniently run multiple dos applications which all have address 1.
|
|||
|
//
|
|||
|
|
|||
|
ShareAccess = FILE_SHARE_WRITE; // Non-exclusive access
|
|||
|
Address.Address[0].Address[0].NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE;
|
|||
|
} else {
|
|||
|
// Group names and Broadcast addresses.
|
|||
|
ShareAccess = FILE_SHARE_WRITE; // Non-exclusive access
|
|||
|
|
|||
|
if ((pdncb->ncb_command & ~ASYNCH) == NCBQUICKADDGRNAME) {
|
|||
|
Address.Address[0].Address[0].NetbiosNameType =
|
|||
|
TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP;
|
|||
|
} else {
|
|||
|
Address.Address[0].Address[0].NetbiosNameType =
|
|||
|
TDI_ADDRESS_NETBIOS_TYPE_GROUP;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
Address.Address[0].Address[0].NetbiosName,
|
|||
|
pdncb->ncb_name,
|
|||
|
NCBNAMSZ
|
|||
|
);
|
|||
|
|
|||
|
RtlMoveMemory (
|
|||
|
&EaBuffer->EaName[EaBuffer->EaNameLength + 1],
|
|||
|
&Address,
|
|||
|
sizeof(TA_NETBIOS_ADDRESS)
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
ShareAccess = FILE_SHARE_WRITE; // Non-exclusive access
|
|||
|
EaBuffer = NULL;
|
|||
|
EaLength = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (PsGetCurrentProcess() != NbFspProcess) {
|
|||
|
KeAttachProcess(NbFspProcess);
|
|||
|
|
|||
|
ProcessAttached = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
Status = ZwCreateFile (
|
|||
|
FileHandle,
|
|||
|
GENERIC_READ | GENERIC_WRITE, // desired access.
|
|||
|
&ObjectAttributes, // object attributes.
|
|||
|
&IoStatusBlock, // returned status information.
|
|||
|
NULL, // Allocation size (unused).
|
|||
|
FILE_ATTRIBUTE_NORMAL, // file attributes.
|
|||
|
ShareAccess,
|
|||
|
FILE_CREATE,
|
|||
|
0, // create options.
|
|||
|
EaBuffer,
|
|||
|
EaLength
|
|||
|
);
|
|||
|
|
|||
|
if ( NT_SUCCESS( Status )) {
|
|||
|
Status = IoStatusBlock.Status;
|
|||
|
}
|
|||
|
|
|||
|
// Obtain a referenced pointer to the file object.
|
|||
|
if (NT_SUCCESS( Status )) {
|
|||
|
Status = ObReferenceObjectByHandle (
|
|||
|
*FileHandle,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
KernelMode,
|
|||
|
Object,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
NTSTATUS localstatus;
|
|||
|
|
|||
|
localstatus = ZwClose( *FileHandle);
|
|||
|
|
|||
|
ASSERT(NT_SUCCESS(localstatus));
|
|||
|
|
|||
|
*FileHandle = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (ProcessAttached) {
|
|||
|
KeDetachProcess();
|
|||
|
}
|
|||
|
|
|||
|
if ( EaBuffer ) {
|
|||
|
ExFreePool( EaBuffer );
|
|||
|
}
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("NbOpenAddress Status:%X, IoStatus:%X.\n", Status, IoStatusBlock.Status));
|
|||
|
}
|
|||
|
|
|||
|
if ( NT_SUCCESS( Status )) {
|
|||
|
Status = IoStatusBlock.Status;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS( Status )) {
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("NbOpenAddress: FAILURE, status code=%X.\n", Status));
|
|||
|
}
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
PAB
|
|||
|
NewAb(
|
|||
|
IN PIO_STACK_LOCATION IrpSp,
|
|||
|
IN OUT PDNCB pdncb
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Arguments:
|
|||
|
`
|
|||
|
IrpSp - Pointer to current IRP stack frame.
|
|||
|
|
|||
|
pdncb - Pointer to the ncb being processed.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The new Cb.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
|||
|
PAB pab;
|
|||
|
PFCB pfcb = FileObject->FsContext2;
|
|||
|
PLANA_INFO plana;
|
|||
|
int index;
|
|||
|
ULONG NameLength;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
// Prevent resets while we add the name
|
|||
|
ExAcquireResourceShared ( &pfcb->AddResource, TRUE );
|
|||
|
|
|||
|
LOCK_RESOURCE( pfcb );
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("NewAb: lana: %lx Address:\n", pdncb->ncb_lana_num ));
|
|||
|
NbFormattedDump( (PUCHAR) pdncb->ncb_name, sizeof(NAME) );
|
|||
|
}
|
|||
|
|
|||
|
if ( pdncb->ncb_lana_num > pfcb->MaxLana ) {
|
|||
|
// no such adapter
|
|||
|
NCB_COMPLETE( pdncb, NRC_BRIDGE );
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
ExReleaseResource( &pfcb->AddResource );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (( pfcb == NULL ) ||
|
|||
|
( pfcb->ppLana[pdncb->ncb_lana_num] == NULL )) {
|
|||
|
// adapter not installed
|
|||
|
NCB_COMPLETE( pdncb, NRC_ENVNOTDEF );
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
ExReleaseResource( &pfcb->AddResource );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
plana = pfcb->ppLana[pdncb->ncb_lana_num];
|
|||
|
|
|||
|
if ( pdncb->ncb_command == NCBADDRESERVED ) {
|
|||
|
index = 1;
|
|||
|
NameLength = NCBNAMSZ;
|
|||
|
} else {
|
|||
|
if ( pdncb->ncb_command == NCBADDBROADCAST ) {
|
|||
|
index = MAXIMUM_ADDRESS;
|
|||
|
NameLength = pdncb->ncb_length;
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Ensure that the user has not added too many names or attempted to
|
|||
|
// add the same name twice. If not then scan the address table looking
|
|||
|
// for the next available slot.
|
|||
|
//
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("NewAb: AddressCount: %lx, MaximumAddress %lx\n",
|
|||
|
plana->AddressCount,
|
|||
|
plana->MaximumAddresses ));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the application has added the number of names requested
|
|||
|
// or has filled the table, refuse the request.
|
|||
|
//
|
|||
|
|
|||
|
if ( plana->MaximumAddresses == plana->AddressCount) {
|
|||
|
|
|||
|
NCB_COMPLETE( pdncb, NRC_NAMTFUL );
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
ExReleaseResource( &pfcb->AddResource );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Scan the name table and ensure that the name isn't already
|
|||
|
// there.
|
|||
|
//
|
|||
|
|
|||
|
if (( FindAb(pfcb, pdncb, FALSE) != NULL) ||
|
|||
|
( pdncb->ncb_retcode != NRC_NOWILD)) {
|
|||
|
|
|||
|
//
|
|||
|
// error is set to DUPNAME iff FindAb found the name
|
|||
|
// in all other cases FindAb sets the error code and sets
|
|||
|
// returns the address block.
|
|||
|
//
|
|||
|
|
|||
|
NCB_COMPLETE( pdncb, NRC_DUPNAME );
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
ExReleaseResource( &pfcb->AddResource );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Find the appropriate name number to use.
|
|||
|
//
|
|||
|
|
|||
|
index = plana->NextAddress;
|
|||
|
while ( plana->AddressBlocks[index] != NULL ) {
|
|||
|
index++;
|
|||
|
if ( index == MAXIMUM_ADDRESS ) {
|
|||
|
index = 2;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// reset retcode so that NCB_COMPLETE will process the NCB.
|
|||
|
pdncb->ncb_retcode = NRC_PENDING;
|
|||
|
|
|||
|
NameLength = NCBNAMSZ;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( plana->AddressBlocks[index] != NULL ) {
|
|||
|
NCB_COMPLETE( pdncb, NRC_DUPNAME );
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
ExReleaseResource( &pfcb->AddResource );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
pab = ExAllocatePoolWithTag (NonPagedPool, sizeof(AB), 'aSBN');
|
|||
|
|
|||
|
if (pab==NULL) {
|
|||
|
NCB_COMPLETE( pdncb, NbMakeNbError( STATUS_INSUFFICIENT_RESOURCES ) );
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
ExReleaseResource( &pfcb->AddResource );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
pab->AddressHandle = NULL;
|
|||
|
pab->AddressObject = NULL;
|
|||
|
pab->DeviceObject = NULL;
|
|||
|
pab->NameNumber = (UCHAR)index;
|
|||
|
pab->pLana = plana;
|
|||
|
InitializeListHead(&pab->ReceiveAnyList);
|
|||
|
InitializeListHead(&pab->ReceiveDatagramList);
|
|||
|
InitializeListHead(&pab->ReceiveBroadcastDatagramList);
|
|||
|
pab->NameLength = (UCHAR)NameLength;
|
|||
|
RtlMoveMemory( &pab->Name, pdncb->ncb_name, NCBNAMSZ);
|
|||
|
|
|||
|
if (((pdncb->ncb_command & ~ASYNCH) == NCBADDNAME) ||
|
|||
|
((pdncb->ncb_command & ~ASYNCH) == NCBQUICKADDNAME)) {
|
|||
|
|
|||
|
pab->Status = REGISTERING | UNIQUE_NAME;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
pab->Status = REGISTERING | GROUP_NAME;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
pab->CurrentUsers = 1;
|
|||
|
plana->AddressBlocks[index] = pab;
|
|||
|
pab->Signature = AB_SIGNATURE;
|
|||
|
|
|||
|
|
|||
|
if (( pdncb->ncb_command != NCBADDRESERVED ) &&
|
|||
|
( pdncb->ncb_command != NCBADDBROADCAST )) {
|
|||
|
plana->AddressCount++;
|
|||
|
plana->NextAddress = index + 1;
|
|||
|
if ( plana->NextAddress == MAXIMUM_ADDRESS ) {
|
|||
|
plana->NextAddress = 2;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Unlock so other Ncb's can be processed while adding the name.
|
|||
|
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
|
|||
|
Status = NbOpenAddress (&pab->AddressHandle,
|
|||
|
(PVOID *)&pab->AddressObject,
|
|||
|
pfcb,
|
|||
|
pdncb->ncb_lana_num,
|
|||
|
pdncb);
|
|||
|
|
|||
|
LOCK_RESOURCE( pfcb );
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint(( "\n FAILED on open of %s %X ******\n",
|
|||
|
pdncb->ncb_name,
|
|||
|
Status ));
|
|||
|
}
|
|||
|
NCB_COMPLETE( pdncb, NbMakeNbError( Status ) );
|
|||
|
ExFreePool( pab );
|
|||
|
plana->AddressBlocks[index] = NULL;
|
|||
|
|
|||
|
if (( pdncb->ncb_command != NCBADDRESERVED ) &&
|
|||
|
( pdncb->ncb_command != NCBADDBROADCAST )) {
|
|||
|
|
|||
|
plana->AddressCount--;
|
|||
|
}
|
|||
|
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
ExReleaseResource( &pfcb->AddResource );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
// Inform the application of the address number.
|
|||
|
pdncb->ncb_num = (UCHAR) index;
|
|||
|
|
|||
|
//
|
|||
|
// Register the event handlers for this address.
|
|||
|
//
|
|||
|
|
|||
|
// Get the address of the device object for the endpoint.
|
|||
|
|
|||
|
pab->DeviceObject = IoGetRelatedDeviceObject(pab->AddressObject);
|
|||
|
|
|||
|
//
|
|||
|
// No connections are made using the broadcast address so don't register disconnect or
|
|||
|
// receive indication handlers. The ReceiveDatagram handler will get registered if the
|
|||
|
// application requests a receive broadcast datagram. This will cut down the cpu load
|
|||
|
// when the application is not interested in broadcasts. We always register the error
|
|||
|
// indication handler on the broadcast address because it is the only address which is
|
|||
|
// always open to the transport.
|
|||
|
//
|
|||
|
|
|||
|
if ( pdncb->ncb_command != NCBADDBROADCAST ) {
|
|||
|
Status = NbSetEventHandler( pab->DeviceObject,
|
|||
|
pab->AddressObject,
|
|||
|
TDI_EVENT_RECEIVE,
|
|||
|
(PVOID)NbTdiReceiveHandler,
|
|||
|
pab);
|
|||
|
|
|||
|
ASSERT( NT_SUCCESS(Status) );
|
|||
|
|
|||
|
Status = NbSetEventHandler( pab->DeviceObject,
|
|||
|
pab->AddressObject,
|
|||
|
TDI_EVENT_DISCONNECT,
|
|||
|
(PVOID)NbTdiDisconnectHandler,
|
|||
|
pab);
|
|||
|
|
|||
|
ASSERT( NT_SUCCESS(Status) );
|
|||
|
|
|||
|
Status = NbSetEventHandler( pab->DeviceObject,
|
|||
|
pab->AddressObject,
|
|||
|
TDI_EVENT_RECEIVE_DATAGRAM,
|
|||
|
(PVOID)NbTdiDatagramHandler,
|
|||
|
pab);
|
|||
|
|
|||
|
ASSERT( NT_SUCCESS(Status) );
|
|||
|
pab->ReceiveDatagramRegistered = TRUE;
|
|||
|
} else {
|
|||
|
Status = NbSetEventHandler( pab->DeviceObject,
|
|||
|
pab->AddressObject,
|
|||
|
TDI_EVENT_ERROR,
|
|||
|
(PVOID)NbTdiErrorHandler,
|
|||
|
plana);
|
|||
|
|
|||
|
ASSERT( NT_SUCCESS(Status) );
|
|||
|
pab->ReceiveDatagramRegistered = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
pab->Status |= REGISTERED;
|
|||
|
|
|||
|
UNLOCK_RESOURCE( pfcb );
|
|||
|
|
|||
|
ExReleaseResource( &pfcb->AddResource );
|
|||
|
|
|||
|
NCB_COMPLETE( pdncb, NRC_GOODRET );
|
|||
|
|
|||
|
return pab;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
CleanupAb(
|
|||
|
IN PPAB ppab,
|
|||
|
IN BOOLEAN CloseAddress
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This closes the handles in the Ab and deletes the Address Block.
|
|||
|
|
|||
|
During this routine we need the spinlock held to prevent an indication accessing
|
|||
|
a Receive while we are cancelling it.
|
|||
|
|
|||
|
Note: Resource must be held before calling this routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pab - Address of the pointer to the Ab to be destroyed.
|
|||
|
|
|||
|
CloseAddress - TRUE if Address block is to be destroyed immediately.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
nothing.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
PAB pab = *ppab;
|
|||
|
PAB pab255;
|
|||
|
PFCB pfcb = (*ppab)->pLana->pFcb;
|
|||
|
PLANA_INFO plana = (*ppab)->pLana;
|
|||
|
KIRQL OldIrql; // Used when SpinLock held.
|
|||
|
PLIST_ENTRY ReceiveEntry;
|
|||
|
|
|||
|
LOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
ASSERT( pab->Signature == AB_SIGNATURE );
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("CleanupAb ppab: %lx, pab: %lx, CurrentUsers: %lx, State: %x\n",
|
|||
|
ppab,
|
|||
|
pab,
|
|||
|
pab->CurrentUsers,
|
|||
|
pab->Status));
|
|||
|
|
|||
|
NbFormattedDump( (PUCHAR)&pab->Name, sizeof(NAME) );
|
|||
|
}
|
|||
|
|
|||
|
if ( (pab->Status & 0x7) != DEREGISTERED ) {
|
|||
|
PDNCB pdncb;
|
|||
|
|
|||
|
pab->Status |= DEREGISTERED;
|
|||
|
|
|||
|
//
|
|||
|
// This is the first time through so cancel all the receive datagram
|
|||
|
// requests for this address.
|
|||
|
|
|||
|
|
|||
|
while ( (pdncb = DequeueRequest( &pab->ReceiveDatagramList)) != NULL ) {
|
|||
|
|
|||
|
UNLOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
NCB_COMPLETE( pdncb, NRC_NAMERR );
|
|||
|
|
|||
|
pdncb->irp->IoStatus.Information = FIELD_OFFSET( DNCB, ncb_cmd_cplt );
|
|||
|
NbCompleteRequest( pdncb->irp, STATUS_SUCCESS );
|
|||
|
LOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
}
|
|||
|
|
|||
|
while ( (pdncb = DequeueRequest( &pab->ReceiveBroadcastDatagramList)) != NULL ) {
|
|||
|
|
|||
|
UNLOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
NCB_COMPLETE( pdncb, NRC_NAMERR );
|
|||
|
|
|||
|
pdncb->irp->IoStatus.Information = FIELD_OFFSET( DNCB, ncb_cmd_cplt );
|
|||
|
NbCompleteRequest( pdncb->irp, STATUS_SUCCESS );
|
|||
|
LOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
}
|
|||
|
|
|||
|
while ( (pdncb = DequeueRequest( &pab->ReceiveAnyList)) != NULL ) {
|
|||
|
|
|||
|
UNLOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
NCB_COMPLETE( pdncb, NRC_NAMERR );
|
|||
|
|
|||
|
pdncb->irp->IoStatus.Information = FIELD_OFFSET( DNCB, ncb_cmd_cplt );
|
|||
|
NbCompleteRequest( pdncb->irp, STATUS_SUCCESS );
|
|||
|
LOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
}
|
|||
|
|
|||
|
// The IBM Mif081 test requires ReceiveBroadcast Any with this name to be cancelled.
|
|||
|
|
|||
|
pab255 = plana->AddressBlocks[MAXIMUM_ADDRESS];
|
|||
|
|
|||
|
//
|
|||
|
// check for null pointer. Added to fix stress bug
|
|||
|
//
|
|||
|
// V Raman
|
|||
|
//
|
|||
|
|
|||
|
if ( pab255 != NULL )
|
|||
|
{
|
|||
|
ReceiveEntry = pab255->ReceiveBroadcastDatagramList.Flink;
|
|||
|
|
|||
|
while ( ReceiveEntry != &pab255->ReceiveBroadcastDatagramList ) {
|
|||
|
|
|||
|
PLIST_ENTRY NextReceiveEntry = ReceiveEntry->Flink;
|
|||
|
|
|||
|
PDNCB pdncb = CONTAINING_RECORD( ReceiveEntry, DNCB, ncb_next);
|
|||
|
|
|||
|
if ( pab->NameNumber == pdncb->ncb_num ) {
|
|||
|
PIRP Irp;
|
|||
|
|
|||
|
RemoveEntryList( &pdncb->ncb_next );
|
|||
|
|
|||
|
Irp = pdncb->irp;
|
|||
|
|
|||
|
IoAcquireCancelSpinLock(&Irp->CancelIrql);
|
|||
|
|
|||
|
//
|
|||
|
// Remove the cancel request for this IRP. If its cancelled then its
|
|||
|
// ok to just process it because we will be returning it to the caller.
|
|||
|
//
|
|||
|
|
|||
|
Irp->Cancel = FALSE;
|
|||
|
|
|||
|
IoSetCancelRoutine(Irp, NULL);
|
|||
|
|
|||
|
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
|||
|
|
|||
|
UNLOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
NCB_COMPLETE( pdncb, NRC_NAMERR );
|
|||
|
|
|||
|
pdncb->irp->IoStatus.Information = FIELD_OFFSET( DNCB, ncb_cmd_cplt );
|
|||
|
|
|||
|
NbCompleteRequest( pdncb->irp, STATUS_SUCCESS );
|
|||
|
|
|||
|
LOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
ReceiveEntry = NextReceiveEntry;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
UNLOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
CloseListens( pfcb, ppab );
|
|||
|
LOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
}
|
|||
|
|
|||
|
UNLOCK_SPINLOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
if ( ( pab->AddressHandle != NULL ) &&
|
|||
|
(( CloseAddress == TRUE ) || ( pab->CurrentUsers == 1 )) ){
|
|||
|
|
|||
|
NbAddressClose( pab->AddressHandle, pab->AddressObject );
|
|||
|
|
|||
|
pab->AddressHandle = NULL;
|
|||
|
}
|
|||
|
|
|||
|
DEREFERENCE_AB(ppab);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
NbAddressClose(
|
|||
|
IN HANDLE AddressHandle,
|
|||
|
IN PVOID Object
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Remove close the handle and dereference the address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AddressHandle
|
|||
|
|
|||
|
Object
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS localstatus;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
ObDereferenceObject( Object );
|
|||
|
if (PsGetCurrentProcess() != NbFspProcess) {
|
|||
|
KeAttachProcess(NbFspProcess);
|
|||
|
localstatus = ZwClose( AddressHandle);
|
|||
|
ASSERT(NT_SUCCESS(localstatus));
|
|||
|
KeDetachProcess();
|
|||
|
} else {
|
|||
|
localstatus = ZwClose( AddressHandle);
|
|||
|
ASSERT(NT_SUCCESS(localstatus));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
PPAB
|
|||
|
FindAb(
|
|||
|
IN PFCB pfcb,
|
|||
|
IN PDNCB pdncb,
|
|||
|
IN BOOLEAN IncrementUsers
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine uses the callers lana number and Name to find the Address
|
|||
|
Block that corresponds to the Ncb. Note, it returns the address of the
|
|||
|
relevant plana->AddressBlocks entry so that deletion of the address
|
|||
|
block is simpler.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pfcb - Supplies a pointer to the Fcb that Ab is chained onto.
|
|||
|
|
|||
|
pdncb - Supplies the connection id from the applications point of view.
|
|||
|
|
|||
|
IncrementUsers - TRUE iff performing a listen or call so increment CurrentUsers
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Address of the pointer to the address block or NULL.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PLANA_INFO plana;
|
|||
|
PAB pab;
|
|||
|
int index;
|
|||
|
|
|||
|
if (( pdncb->ncb_lana_num > pfcb->MaxLana ) ||
|
|||
|
( pfcb == NULL ) ||
|
|||
|
( pfcb->ppLana[pdncb->ncb_lana_num] == NULL) ||
|
|||
|
( pfcb->ppLana[pdncb->ncb_lana_num]->Status != NB_INITIALIZED) ) {
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("FindAb pfcb: %lx, lana: %lx Failed, returning NULL\n",
|
|||
|
pfcb,
|
|||
|
pdncb->ncb_lana_num));
|
|||
|
}
|
|||
|
NCB_COMPLETE( pdncb, NRC_BRIDGE );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT( pfcb->Signature == FCB_SIGNATURE );
|
|||
|
|
|||
|
plana = pfcb->ppLana[pdncb->ncb_lana_num];
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("FindAb pfcb: %lx, lana: %lx, lsn: %lx ",
|
|||
|
pfcb,
|
|||
|
pdncb->ncb_lana_num,
|
|||
|
pdncb->ncb_lsn));
|
|||
|
}
|
|||
|
|
|||
|
for ( index = 0; index <= MAXIMUM_ADDRESS; index++ ) {
|
|||
|
pab = plana->AddressBlocks[index];
|
|||
|
if (( pab != NULL ) &&
|
|||
|
(RtlEqualMemory( &pab->Name, pdncb->ncb_name, NCBNAMSZ))) {
|
|||
|
|
|||
|
ASSERT( pab->Signature == AB_SIGNATURE );
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("ppab %lx, pab: %lx, state:%x\n",
|
|||
|
&plana->AddressBlocks[index],
|
|||
|
plana->AddressBlocks[index],
|
|||
|
pab->Status));
|
|||
|
|
|||
|
NbFormattedDump( (PUCHAR)&pab->Name, sizeof(NAME) );
|
|||
|
}
|
|||
|
|
|||
|
if ( (pab->Status & 0x07) != REGISTERED ) {
|
|||
|
NCB_COMPLETE( pdncb, NRC_NOWILD );
|
|||
|
//
|
|||
|
// The name is in a bad state. Tell NewAb not to add the name by
|
|||
|
// returning non-null. Don't reference the AB.
|
|||
|
//
|
|||
|
if (( (pdncb->ncb_command & ~ ASYNCH) == NCBADDNAME ) ||
|
|||
|
( (pdncb->ncb_command & ~ ASYNCH) == NCBQUICKADDNAME ) ||
|
|||
|
( (pdncb->ncb_command & ~ ASYNCH) == NCBQUICKADDGRNAME ) ||
|
|||
|
( (pdncb->ncb_command & ~ ASYNCH) == NCBADDGRNAME )) {
|
|||
|
return &plana->AddressBlocks[index];
|
|||
|
} else {
|
|||
|
// Not NewAb so return Null as usual.
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( IncrementUsers == TRUE ) {
|
|||
|
REFERENCE_AB(pab);
|
|||
|
}
|
|||
|
return &plana->AddressBlocks[index];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("Failed return NULL\n"));
|
|||
|
}
|
|||
|
|
|||
|
NCB_COMPLETE( pdncb, NRC_NOWILD );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
PPAB
|
|||
|
FindAbUsingNum(
|
|||
|
IN PFCB pfcb,
|
|||
|
IN PDNCB pdncb,
|
|||
|
IN UCHAR NameNumber
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine uses the callers lana number and name number to find the
|
|||
|
Address Block that corresponds to the Ncb.
|
|||
|
Note, it returns the address of the relevant plana->AddressBlocks entry
|
|||
|
so that deletion of the address block is simpler.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pfcb - Supplies a pointer to the Fcb that Ab is chained onto.
|
|||
|
|
|||
|
pdncb - Supplies the applications NCB.
|
|||
|
|
|||
|
NameNumber - Supplies the name number to look for. This is not equal to pdncb->ncb_num
|
|||
|
when manipulating broadcast datagrams.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Address of the pointer to the address block or NULL.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PLANA_INFO plana;
|
|||
|
|
|||
|
if (( pdncb->ncb_lana_num > pfcb->MaxLana ) ||
|
|||
|
( pfcb == NULL ) ||
|
|||
|
( pfcb->ppLana[pdncb->ncb_lana_num] == NULL) ||
|
|||
|
( pfcb->ppLana[pdncb->ncb_lana_num]->Status != NB_INITIALIZED) ) {
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("FindAbUsingNum pfcb: %lx, lana: %lx Failed, returning NULL\n",
|
|||
|
pfcb,
|
|||
|
pdncb->ncb_lana_num));
|
|||
|
}
|
|||
|
NCB_COMPLETE( pdncb, NRC_BRIDGE );
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT( pfcb->Signature == FCB_SIGNATURE );
|
|||
|
|
|||
|
plana = pfcb->ppLana[pdncb->ncb_lana_num];
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("FindAbUsingNum pfcb: %lx, lana: %lx, num: %lx\n",
|
|||
|
pfcb,
|
|||
|
pdncb->ncb_lana_num,
|
|||
|
NameNumber));
|
|||
|
}
|
|||
|
|
|||
|
if (( NameNumber < (UCHAR)MAXIMUM_ADDRESS ) &&
|
|||
|
( plana->AddressBlocks[NameNumber] != NULL) &&
|
|||
|
(( plana->AddressBlocks[NameNumber]->Status & 0x7) == REGISTERED )) {
|
|||
|
return &plana->AddressBlocks[NameNumber];
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The user is allowed to receive any and receive broadcast
|
|||
|
// datagrams on address 255.
|
|||
|
//
|
|||
|
|
|||
|
if ((( NameNumber == MAXIMUM_ADDRESS ) &&
|
|||
|
( plana->AddressBlocks[NameNumber] != NULL)) &&
|
|||
|
(( (pdncb->ncb_command & ~ASYNCH) == NCBRECVANY ) ||
|
|||
|
( (pdncb->ncb_command & ~ASYNCH) == NCBDGRECVBC ) ||
|
|||
|
( (pdncb->ncb_command & ~ASYNCH) == NCBDGSENDBC ) ||
|
|||
|
( (pdncb->ncb_command & ~ASYNCH) == NCBDGRECV ))) {
|
|||
|
return &plana->AddressBlocks[NameNumber];
|
|||
|
}
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_ADDRESS) {
|
|||
|
NbPrint( ("Failed return NULL\n"));
|
|||
|
}
|
|||
|
NCB_COMPLETE( pdncb, NRC_ILLNN );
|
|||
|
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NbSetEventHandler (
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN ULONG EventType,
|
|||
|
IN PVOID EventHandler,
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine registers an event handler with a TDI transport provider.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PDEVICE_OBJECT DeviceObject - Supplies the device object of the transport provider.
|
|||
|
IN PFILE_OBJECT FileObject - Supplies the address object's file object.
|
|||
|
IN ULONG EventType, - Supplies the type of event.
|
|||
|
IN PVOID EventHandler - Supplies the event handler.
|
|||
|
IN PVOID Context - Supplies the PAB or PLANA_INFO associated with this event.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of the set event operation
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PIRP Irp;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
Irp = IoAllocateIrp(IoGetRelatedDeviceObject(FileObject)->StackSize, FALSE);
|
|||
|
|
|||
|
if (Irp == NULL) {
|
|||
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|||
|
}
|
|||
|
|
|||
|
TdiBuildSetEventHandler(Irp, DeviceObject, FileObject,
|
|||
|
NULL, NULL,
|
|||
|
EventType, EventHandler, Context);
|
|||
|
|
|||
|
Status = SubmitTdiRequest(FileObject, Irp);
|
|||
|
|
|||
|
IoFreeIrp(Irp);
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SubmitTdiRequest (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine submits a request to TDI and waits for it to complete.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN PFILE_OBJECT FileObject - Connection or Address handle for TDI request
|
|||
|
IN PIRP Irp - TDI request to submit.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of request.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
KEVENT Event;
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
KeInitializeEvent (&Event, NotificationEvent, FALSE);
|
|||
|
|
|||
|
IoSetCompletionRoutine(Irp, NbCompletionEvent, &Event, TRUE, TRUE, TRUE);
|
|||
|
|
|||
|
Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp);
|
|||
|
|
|||
|
//
|
|||
|
// If it failed immediately, return now, otherwise wait.
|
|||
|
//
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
if (Status == STATUS_PENDING) {
|
|||
|
|
|||
|
Status = KeWaitForSingleObject(&Event, // Object to wait on.
|
|||
|
Executive, // Reason for waiting
|
|||
|
KernelMode, // Processor mode
|
|||
|
FALSE, // Alertable
|
|||
|
NULL); // Timeout
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
IoFreeIrp ( Irp );
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
Status = Irp->IoStatus.Status;
|
|||
|
}
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|