mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
594 lines
15 KiB
594 lines
15 KiB
/*++
|
|
|
|
Copyright (c) 1989-1993 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
driver.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the DriverEntry and other initialization
|
|
code for the Netbios module of the ISN transport.
|
|
|
|
Author:
|
|
|
|
Adam Barr (adamba) 16-November-1993
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,NbiBind)
|
|
#endif
|
|
|
|
#if defined(_PNP_POWER)
|
|
//
|
|
// local functions.
|
|
//
|
|
VOID
|
|
NbiPnPNotification(
|
|
IN IPX_PNP_OPCODE OpCode,
|
|
IN PVOID PnPData
|
|
);
|
|
#endif _PNP_POWER
|
|
|
|
|
|
NTSTATUS
|
|
NbiBind(
|
|
IN PDEVICE Device,
|
|
IN PCONFIG Config
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine binds the Netbios module of ISN to the IPX
|
|
module, which provides the NDIS binding services.
|
|
|
|
Arguments:
|
|
|
|
Device - Pointer to the Netbios device.
|
|
|
|
Config - Pointer to the configuration information.
|
|
|
|
Return Value:
|
|
|
|
The function value is the final status from the initialization operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
/* union {
|
|
IPX_INTERNAL_BIND_INPUT Input;
|
|
IPX_INTERNAL_BIND_OUTPUT Output;
|
|
} Bind;
|
|
*/
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&Config->BindName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = ZwCreateFile(
|
|
&Device->BindHandle,
|
|
SYNCHRONIZE | GENERIC_READ,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN,
|
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL,
|
|
0L);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
NB_DEBUG (BIND, ("Could not open IPX (%ws) %lx\n",
|
|
Config->BindName.Buffer, Status));
|
|
NbiWriteGeneralErrorLog(
|
|
Device,
|
|
EVENT_TRANSPORT_ADAPTER_NOT_FOUND,
|
|
1,
|
|
Status,
|
|
Config->BindName.Buffer,
|
|
0,
|
|
NULL);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Fill in our bind data.
|
|
//
|
|
|
|
#if defined(_PNP_POWER)
|
|
Device->BindInput.Version = ISN_VERSION;
|
|
#else
|
|
Device->BindInput.Version = 1;
|
|
#endif _PNP_POWER
|
|
Device->BindInput.Identifier = IDENTIFIER_NB;
|
|
Device->BindInput.BroadcastEnable = TRUE;
|
|
Device->BindInput.LookaheadRequired = 192;
|
|
Device->BindInput.ProtocolOptions = 0;
|
|
Device->BindInput.ReceiveHandler = NbiReceive;
|
|
Device->BindInput.ReceiveCompleteHandler = NbiReceiveComplete;
|
|
Device->BindInput.StatusHandler = NbiStatus;
|
|
Device->BindInput.SendCompleteHandler = NbiSendComplete;
|
|
Device->BindInput.TransferDataCompleteHandler = NbiTransferDataComplete;
|
|
Device->BindInput.FindRouteCompleteHandler = NbiFindRouteComplete;
|
|
Device->BindInput.LineUpHandler = NbiLineUp;
|
|
Device->BindInput.LineDownHandler = NbiLineDown;
|
|
Device->BindInput.ScheduleRouteHandler = NULL;
|
|
#if defined(_PNP_POWER)
|
|
Device->BindInput.PnPHandler = NbiPnPNotification;
|
|
#endif _PNP_POWER
|
|
|
|
|
|
Status = ZwDeviceIoControlFile(
|
|
Device->BindHandle, // HANDLE to File
|
|
NULL, // HANDLE to Event
|
|
NULL, // ApcRoutine
|
|
NULL, // ApcContext
|
|
&IoStatusBlock, // IO_STATUS_BLOCK
|
|
IOCTL_IPX_INTERNAL_BIND, // IoControlCode
|
|
&Device->BindInput, // Input Buffer
|
|
sizeof(Device->BindInput), // Input Buffer Length
|
|
&Device->Bind, // OutputBuffer
|
|
sizeof(Device->Bind)); // OutputBufferLength
|
|
|
|
//
|
|
// We open synchronous, so this shouldn't happen.
|
|
//
|
|
|
|
CTEAssert (Status != STATUS_PENDING);
|
|
|
|
//
|
|
// Save the bind data.
|
|
//
|
|
|
|
if (Status == STATUS_SUCCESS) {
|
|
|
|
NB_DEBUG2 (BIND, ("Successfully bound to IPX (%ws)\n",
|
|
Config->BindName.Buffer));
|
|
// RtlCopyMemory (&Device->Bind, &Bind.Output, sizeof(IPX_INTERNAL_BIND_OUTPUT));
|
|
|
|
#if !defined(_PNP_POWER)
|
|
RtlZeroMemory (Device->ReservedNetbiosName, 16);
|
|
RtlCopyMemory (&Device->ReservedNetbiosName[10], Device->Bind.Node, 6);
|
|
|
|
Status = (*Device->Bind.QueryHandler)( // BUGBUG: Check return code
|
|
IPX_QUERY_MAXIMUM_NIC_ID,
|
|
(USHORT)0,
|
|
&Device->MaximumNicId,
|
|
sizeof(Device->MaximumNicId),
|
|
NULL);
|
|
CTEAssert (Status == STATUS_SUCCESS);
|
|
#endif !_PNP_POWER
|
|
|
|
} else {
|
|
|
|
NB_DEBUG (BIND, ("Could not bind to IPX (%ws) %lx\n",
|
|
Config->BindName.Buffer, Status));
|
|
NbiWriteGeneralErrorLog(
|
|
Device,
|
|
EVENT_TRANSPORT_BINDING_FAILED,
|
|
1,
|
|
Status,
|
|
Config->BindName.Buffer,
|
|
0,
|
|
NULL);
|
|
ZwClose(Device->BindHandle);
|
|
}
|
|
|
|
return Status;
|
|
|
|
} /* NbiBind */
|
|
|
|
|
|
VOID
|
|
NbiUnbind(
|
|
IN PDEVICE Device
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function closes the binding between the Netbios over
|
|
IPX module and the IPX module previously established by
|
|
NbiBind.
|
|
|
|
Arguments:
|
|
|
|
Device - The netbios device object.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ZwClose (Device->BindHandle);
|
|
|
|
} /* NbiUnbind */
|
|
|
|
|
|
VOID
|
|
NbiStatus(
|
|
IN USHORT NicId,
|
|
IN NDIS_STATUS GeneralStatus,
|
|
IN PVOID StatusBuffer,
|
|
IN UINT StatusBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function receives a status indication from IPX,
|
|
corresponding to a status indication from an underlying
|
|
NDIS driver.
|
|
|
|
Arguments:
|
|
|
|
NicId - The NIC ID of the underlying adapter.
|
|
|
|
GeneralStatus - The general status code.
|
|
|
|
StatusBuffer - The status buffer.
|
|
|
|
StatusBufferLength - The length of the status buffer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
} /* NbiStatus */
|
|
|
|
|
|
VOID
|
|
NbiLineUp(
|
|
IN USHORT NicId,
|
|
IN PIPX_LINE_INFO LineInfo,
|
|
IN NDIS_MEDIUM DeviceType,
|
|
IN PVOID ConfigurationData
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function receives line up indications from IPX,
|
|
indicating that the specified adapter is now up with
|
|
the characteristics shown.
|
|
|
|
Arguments:
|
|
|
|
NicId - The NIC ID of the underlying adapter.
|
|
|
|
LineInfo - Information about the adapter's medium.
|
|
|
|
DeviceType - The type of the adapter.
|
|
|
|
ConfigurationData - IPX-specific configuration data.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIPXCP_CONFIGURATION Configuration = (PIPXCP_CONFIGURATION)ConfigurationData;
|
|
|
|
//
|
|
// Update queries have NULL as the ConfigurationData. These
|
|
// only indicate changes in LineInfo. BUGBUG Ignore these
|
|
// for the moment.
|
|
//
|
|
|
|
if (Configuration == NULL) {
|
|
return;
|
|
}
|
|
|
|
#if !defined(_PNP_POWER)
|
|
//
|
|
// Since Netbios outgoing queries only go out on network 1,
|
|
// we ignore this (BUGBUG for the moment) unless that is
|
|
// the NIC it is on.
|
|
//
|
|
|
|
if (NicId == 1) {
|
|
|
|
RtlCopyMemory(NbiDevice->ConnectionlessHeader.SourceNetwork, Configuration->Network, 4);
|
|
RtlCopyMemory(NbiDevice->ConnectionlessHeader.SourceNode, Configuration->LocalNode, 6);
|
|
|
|
}
|
|
#endif !_PNP_POWER
|
|
} /* NbiLineUp */
|
|
|
|
|
|
VOID
|
|
NbiLineDown(
|
|
IN USHORT NicId,
|
|
IN ULONG FwdAdapterContext
|
|
)
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function receives line down indications from IPX,
|
|
indicating that the specified adapter is no longer
|
|
up.
|
|
|
|
Arguments:
|
|
|
|
NicId - The NIC ID of the underlying adapter.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
} /* NbiLineDown */
|
|
|
|
#if defined(_PNP_POWER)
|
|
|
|
VOID
|
|
NbiPnPNotification(
|
|
IN IPX_PNP_OPCODE OpCode,
|
|
IN PVOID PnPData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function receives the notification about PnP events from IPX.
|
|
|
|
Arguments:
|
|
|
|
OpCode - Type of the PnP event
|
|
|
|
PnPData - Data associated with this event.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PDEVICE Device = NbiDevice;
|
|
USHORT MaximumNicId = 0;
|
|
CTELockHandle LockHandle;
|
|
UCHAR PrevReservedName[NB_NETBIOS_NAME_SIZE];
|
|
UNICODE_STRING UnicodeDeviceName;
|
|
|
|
|
|
NB_DEBUG2( DEVICE, ("Received a pnp notification, opcode %d\n",OpCode ));
|
|
|
|
switch( OpCode ) {
|
|
case IPX_PNP_ADD_DEVICE : {
|
|
IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;
|
|
BOOLEAN ReallocReceiveBuffers = FALSE;
|
|
|
|
NB_GET_LOCK( &Device->Lock, &LockHandle );
|
|
|
|
if ( PnPInfo->NewReservedAddress ) {
|
|
|
|
*(UNALIGNED ULONG *)Device->Bind.Network = PnPInfo->NetworkAddress;
|
|
RtlCopyMemory( Device->Bind.Node, PnPInfo->NodeAddress, 6);
|
|
|
|
// RtlZeroMemory(Device->ReservedNetbiosName, NB_NETBIOS_NAME_SIZE);
|
|
// RtlCopyMemory(&Device->ReservedNetbiosName[10], Device->Bind.Node, 6);
|
|
|
|
*(UNALIGNED ULONG *)Device->ConnectionlessHeader.SourceNetwork = *(UNALIGNED ULONG *)Device->Bind.Network;
|
|
RtlCopyMemory(Device->ConnectionlessHeader.SourceNode, Device->Bind.Node, 6);
|
|
}
|
|
|
|
if ( PnPInfo->FirstORLastDevice ) {
|
|
CTEAssert( PnPInfo->NewReservedAddress );
|
|
CTEAssert( Device->State != DEVICE_STATE_OPEN );
|
|
|
|
|
|
//
|
|
// we must do this while we still have the device lock.
|
|
//
|
|
if ( !Device->LongTimerRunning ) {
|
|
Device->LongTimerRunning = TRUE;
|
|
NbiReferenceDevice (Device, DREF_LONG_TIMER);
|
|
|
|
CTEStartTimer(
|
|
&Device->LongTimer,
|
|
LONG_TIMER_DELTA,
|
|
NbiLongTimeout,
|
|
(PVOID)Device);
|
|
|
|
}
|
|
|
|
Device->State = DEVICE_STATE_OPEN;
|
|
|
|
CTEAssert( !Device->MaximumNicId );
|
|
|
|
Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
|
|
Device->Bind.LineInfo.MaximumPacketSize = PnPInfo->LineInfo.MaximumSendSize;
|
|
ReallocReceiveBuffers = TRUE;
|
|
} else {
|
|
if ( PnPInfo->LineInfo.MaximumPacketSize > Device->CurMaxReceiveBufferSize ) {
|
|
ReallocReceiveBuffers = TRUE;
|
|
}
|
|
//
|
|
// MaxSendSize could become smaller.
|
|
//
|
|
Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
|
|
}
|
|
|
|
Device->MaximumNicId++;
|
|
|
|
|
|
//
|
|
//
|
|
NbiCreateAdapterAddress( PnPInfo->NodeAddress );
|
|
|
|
//
|
|
// And finally remove all the failed cache entries since we might
|
|
// find those routes using this new adapter
|
|
//
|
|
FlushFailedNetbiosCacheEntries(Device->NameCache);
|
|
|
|
NB_FREE_LOCK( &Device->Lock, LockHandle );
|
|
|
|
|
|
if ( ReallocReceiveBuffers ) {
|
|
PWORK_QUEUE_ITEM WorkItem;
|
|
|
|
WorkItem = NbiAllocateMemory( sizeof(WORK_QUEUE_ITEM), MEMORY_WORK_ITEM, "Alloc Rcv Buffer work item");
|
|
|
|
if ( WorkItem ) {
|
|
ExInitializeWorkItem( WorkItem, NbiReAllocateReceiveBufferPool, (PVOID) WorkItem );
|
|
ExQueueWorkItem( WorkItem, DelayedWorkQueue );
|
|
} else {
|
|
NB_DEBUG( DEVICE, ("Cannt schdule work item to realloc receive buffer pool\n"));
|
|
}
|
|
}
|
|
//
|
|
// Notify the TDI clients about the device creation
|
|
//
|
|
if ( PnPInfo->FirstORLastDevice ) {
|
|
UnicodeDeviceName.Buffer = Device->DeviceName;
|
|
UnicodeDeviceName.MaximumLength = Device->DeviceNameLength;
|
|
UnicodeDeviceName.Length = Device->DeviceNameLength - sizeof(WCHAR);
|
|
|
|
if ( !NT_SUCCESS( TdiRegisterDeviceObject(
|
|
&UnicodeDeviceName,
|
|
&Device->TdiRegistrationHandle ) )) {
|
|
NB_DEBUG( DEVICE, ("Failed to register nwlnknb with TDI\n"));
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IPX_PNP_DELETE_DEVICE : {
|
|
|
|
IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;
|
|
|
|
PLIST_ENTRY p;
|
|
PNETBIOS_CACHE CacheName;
|
|
USHORT i,j,NetworksRemoved;
|
|
|
|
NB_GET_LOCK( &Device->Lock, &LockHandle );
|
|
|
|
CTEAssert( Device->MaximumNicId );
|
|
Device->MaximumNicId--;
|
|
|
|
if ( PnPInfo->FirstORLastDevice ) {
|
|
Device->State = DEVICE_STATE_LOADED;
|
|
Device->MaximumNicId = 0;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// MaximumSendSize could change if the card with the smallest send size just
|
|
// got removed. MaximumPacketSize could only become smaller and we ignore that
|
|
// since we dont need to(want to) realloc ReceiveBuffers.
|
|
//
|
|
|
|
Device->Bind.LineInfo.MaximumSendSize = PnPInfo->LineInfo.MaximumSendSize;
|
|
|
|
//
|
|
// Flush all the cache entries that are using this NicId in the local
|
|
// target.
|
|
//
|
|
RemoveInvalidRoutesFromNetbiosCacheTable( Device->NameCache, &PnPInfo->NicHandle );
|
|
|
|
NbiDestroyAdapterAddress( NULL, PnPInfo->NodeAddress );
|
|
|
|
NB_FREE_LOCK( &Device->Lock, LockHandle );
|
|
|
|
/* //
|
|
// Now mark the previous reserved name in conflict if it has
|
|
// been registered by any of our client
|
|
//
|
|
if ( Address = NbiFindAddress( Device, PrevReservedName ) ) {
|
|
NB_GET_LOCK( &Address->Lock, &LockHandle );
|
|
Address->Flags |= ADDRESS_FLAGS_CONFLICT;
|
|
NB_FREE_LOCK( &Address->Lock, LockHandle );
|
|
|
|
NB_DEBUG( ADDRESS, ("Reserved Address %lx<%.16s> is marked CONFLICT\n",Address,Address->NetbiosAddress.NetbiosName));
|
|
//
|
|
// nbifindaddress added a reference, so deref
|
|
//
|
|
NbiDereferenceAddress( Address, AREF_FIND );
|
|
}
|
|
*/
|
|
|
|
//
|
|
// inform tdi clients about the device deletion
|
|
//
|
|
if ( PnPInfo->FirstORLastDevice ) {
|
|
if ( !NT_SUCCESS( TdiDeregisterDeviceObject(
|
|
Device->TdiRegistrationHandle ) )) {
|
|
NB_DEBUG( DEVICE, ("Failed to Deregister nwlnknb with TDI\n"));
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
case IPX_PNP_ADDRESS_CHANGE: {
|
|
IPX_PNP_INFO UNALIGNED *PnPInfo = (IPX_PNP_INFO UNALIGNED *)PnPData;
|
|
PADDRESS Address;
|
|
BOOLEAN ReservedNameClosing = FALSE;
|
|
|
|
CTEAssert( PnPInfo->NewReservedAddress );
|
|
|
|
NB_GET_LOCK( &Device->Lock, &LockHandle );
|
|
*(UNALIGNED ULONG *)Device->Bind.Network = PnPInfo->NetworkAddress;
|
|
RtlCopyMemory( Device->Bind.Node, PnPInfo->NodeAddress, 6);
|
|
|
|
*(UNALIGNED ULONG *)Device->ConnectionlessHeader.SourceNetwork = *(UNALIGNED ULONG *)Device->Bind.Network;
|
|
RtlCopyMemory(Device->ConnectionlessHeader.SourceNode, Device->Bind.Node, 6);
|
|
|
|
NB_FREE_LOCK( &Device->Lock, LockHandle );
|
|
|
|
|
|
break;
|
|
}
|
|
case IPX_PNP_TRANSLATE_DEVICE:
|
|
break;
|
|
case IPX_PNP_TRANSLATE_ADDRESS:
|
|
break;
|
|
default:
|
|
CTEAssert( FALSE );
|
|
}
|
|
} /* NbiPnPNotification */
|
|
|
|
#endif _PNP_POWER
|