Windows NT 4.0 source code leak
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

/*++
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