diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/tdi/nbf/nbfdrvr.c | 2493 |
1 files changed, 2493 insertions, 0 deletions
diff --git a/private/ntos/tdi/nbf/nbfdrvr.c b/private/ntos/tdi/nbf/nbfdrvr.c new file mode 100644 index 000000000..2f42766ff --- /dev/null +++ b/private/ntos/tdi/nbf/nbfdrvr.c @@ -0,0 +1,2493 @@ +/*++ + +Copyright (c) 1989, 1990, 1991 Microsoft Corporation + +Module Name: + + nbfdrvr.c + +Abstract: + + This module contains code which defines the NetBIOS Frames Protocol + transport provider's device object. + +Author: + + David Beaver (dbeaver) 2-July-1991 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#include "precomp.h" +#pragma hdrstop +//#pragma warning(error:4101) // Unreferenced local variable + +// +// This is a list of all the device contexts that NBF owns, +// used while unloading. +// + +LIST_ENTRY NbfDeviceList = {0,0}; // initialized for real at runtime. + +#ifdef _PNP_POWER + +// +// Global variables this is a copy of the path in the registry for +// configuration data. +// + +UNICODE_STRING NbfRegistryPath; + +// +// We need the driver object to create device context structures. +// + +PDRIVER_OBJECT NbfDriverObject; + +#endif + + +#ifdef NBF_LOCKS // see spnlckdb.c + +extern KSPIN_LOCK NbfGlobalLock; + +#endif // def NBF_LOCKS + +// +// The debugging longword, containing a bitmask as defined in NBFCONST.H. +// If a bit is set, then debugging is turned on for that component. +// + +#if DBG + +ULONG NbfDebug = 0; +BOOLEAN NbfDisconnectDebug; + +NBF_SEND NbfSends[TRACK_TDI_LIMIT+1]; +LONG NbfSendsNext; + +NBF_SEND_COMPLETE NbfCompletedSends[TRACK_TDI_LIMIT+1]; +LONG NbfCompletedSendsNext; + +NBF_RECEIVE NbfReceives[TRACK_TDI_LIMIT+1]; +LONG NbfReceivesNext; + +NBF_RECEIVE_COMPLETE NbfCompletedReceives[TRACK_TDI_LIMIT+1]; +LONG NbfCompletedReceivesNext=0; + +PVOID * NbfConnectionTable; +PVOID * NbfRequestTable; +PVOID * NbfUiFrameTable; +PVOID * NbfSendPacketTable; +PVOID * NbfLinkTable; +PVOID * NbfAddressFileTable; +PVOID * NbfAddressTable; + + +LIST_ENTRY NbfGlobalRequestList; +LIST_ENTRY NbfGlobalLinkList; +LIST_ENTRY NbfGlobalConnectionList; +KSPIN_LOCK NbfGlobalInterlock; +KSPIN_LOCK NbfGlobalHistoryLock; + +PVOID +TtdiSend (); + +PVOID +TtdiReceive (); + +PVOID +TtdiServer (); + +KEVENT TdiSendEvent; +KEVENT TdiReceiveEvent; +KEVENT TdiServerEvent; + +#endif + +#if MAGIC + +BOOLEAN NbfEnableMagic = FALSE; // Controls sending of magic bullets. + +#endif // MAGIC + +// +// This prevents us from having a bss section +// + +ULONG _setjmpexused = 0; + +// +// Forward declaration of various routines used in this module. +// + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ); + +VOID +NbfUnload( + IN PDRIVER_OBJECT DriverObject + ); + +VOID +NbfFreeConfigurationInfo ( + IN PCONFIG_DATA ConfigurationInfo + ); + +NTSTATUS +NbfDispatchOpenClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +NTSTATUS +NbfDispatchInternal( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +NTSTATUS +NbfDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ); + +NTSTATUS +NbfDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ); + +VOID +NbfDeallocateResources( + IN PDEVICE_CONTEXT DeviceContext + ); + +#ifdef RASAUTODIAL +VOID +NbfAcdBind(); + +VOID +NbfAcdUnbind(); +#endif // RASAUTODIAL + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,DriverEntry) +#ifdef _PNP_POWER +#pragma alloc_text(PAGE,NbfInitializeOneDeviceContext) +#endif +#endif + + +NTSTATUS +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) + +/*++ + +Routine Description: + + This routine performs initialization of the NetBIOS Frames Protocol + transport driver. It creates the device objects for the transport + provider and performs other driver initialization. + +Arguments: + + DriverObject - Pointer to driver object created by the system. + + RegistryPath - The name of NBF's node in the registry. + +Return Value: + + The function value is the final status from the initialization operation. + +--*/ + +{ + ULONG j; + UNICODE_STRING nameString; + NTSTATUS status; + UINT SuccessfulOpens; + + PCONFIG_DATA NbfConfig = NULL; + + // + + ASSERT (sizeof (SHORT) == 2); + +#ifdef MEMPRINT + MemPrintInitialize (); +#endif + +#ifdef NBF_LOCKS + KeInitializeSpinLock( &NbfGlobalLock ); +#endif + +#if DBG + InitializeListHead (&NbfGlobalRequestList); + InitializeListHead (&NbfGlobalLinkList); + InitializeListHead (&NbfGlobalConnectionList); + KeInitializeSpinLock (&NbfGlobalInterlock); + KeInitializeSpinLock (&NbfGlobalHistoryLock); +#endif + +#ifdef _PNP_POWER + + NbfRegistryPath = *RegistryPath; + NbfRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, + RegistryPath->MaximumLength, + ' FBN'); + + if (NbfRegistryPath.Buffer == NULL) { + PANIC(" Failed to allocate Registry Path!\n"); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + RtlCopyMemory(NbfRegistryPath.Buffer, RegistryPath->Buffer, + RegistryPath->MaximumLength); + NbfDriverObject = DriverObject; + RtlInitUnicodeString( &nameString, NBF_NAME); + TdiInitialize(); + +#else // NOT _PNP_POWER + + // + // This allocates the CONFIG_DATA structure and returns + // it in NbfConfig. + // + + status = NbfConfigureTransport(RegistryPath, &NbfConfig); + + if (!NT_SUCCESS (status)) { + PANIC (" Failed to initialize transport, Nbf initialization failed.\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // make ourselves known to the NDIS wrapper. + // + + RtlInitUnicodeString( &nameString, NBF_DEVICE_NAME ); +#endif + + status = NbfRegisterProtocol (&nameString); + + if (!NT_SUCCESS (status)) { + +#ifdef _PNP_POWER + + // + // No configuration info read at startup when using PNP + // + + ExFreePool(NbfRegistryPath.Buffer); +#else + // + // Free up config info for non PNP mode operation. + // + + NbfFreeConfigurationInfo(NbfConfig); +#endif + PANIC ("NbfInitialize: RegisterProtocol failed!\n"); + + NbfWriteGeneralErrorLog( + (PVOID)DriverObject, + EVENT_TRANSPORT_REGISTER_FAILED, + 607, + status, + NULL, + 0, + NULL); + + return STATUS_INSUFFICIENT_RESOURCES; + + } + + + // + // Initialize the driver object with this driver's entry points. + // + + DriverObject->MajorFunction [IRP_MJ_CREATE] = NbfDispatchOpenClose; + DriverObject->MajorFunction [IRP_MJ_CLOSE] = NbfDispatchOpenClose; + DriverObject->MajorFunction [IRP_MJ_CLEANUP] = NbfDispatchOpenClose; + DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] = NbfDispatchInternal; + DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = NbfDispatch; + + DriverObject->DriverUnload = NbfUnload; + + // + // Initialize the global list of devices. + // + + InitializeListHead (&NbfDeviceList); + +#ifndef _PNP_POWER + +#if DBG + + // + // Allocate the debugging tables. In the PNP case we don't need these + // until we are activated by ProtocolBindAdapter + // + + NbfConnectionTable = (PVOID *)ExAllocatePoolWithTag(NonPagedPool, + sizeof(PVOID) * + (NbfConfig->InitConnections + 2 + + NbfConfig->InitRequests + 2 + + NbfConfig->InitUIFrames + 2 + + NbfConfig->InitPackets + 2 + + NbfConfig->InitLinks + 2 + + NbfConfig->InitAddressFiles + 2 + + NbfConfig->InitAddresses + 2), + ' FBN'); + + ASSERT (NbfConnectionTable); + + NbfRequestTable = NbfConnectionTable + (NbfConfig->InitConnections + 2); + NbfUiFrameTable = NbfRequestTable + (NbfConfig->InitRequests + 2); + NbfSendPacketTable = NbfUiFrameTable + (NbfConfig->InitUIFrames + 2); + NbfLinkTable = NbfSendPacketTable + (NbfConfig->InitPackets + 2); + NbfAddressFileTable = NbfLinkTable + (NbfConfig->InitLinks + 2); + NbfAddressTable = NbfAddressFileTable + (NbfConfig->InitAddressFiles + 2); +#endif + + + SuccessfulOpens = 0; + + for (j=0;j<NbfConfig->NumAdapters;j++ ) { + + // + // Loop through all the adapters that are in the configuration + // information structure. Allocate a device object for each + // one that we find. + // + SuccessfulOpens += NbfInitializeOneDeviceContext(&status, + DriverObject, + NbfConfig, j + ); + + } + + NbfFreeConfigurationInfo(NbfConfig); + +#ifdef RASAUTODIAL + // + // Get the automatic connection + // driver entry points. + // + if (SuccessfulOpens > 0) + NbfAcdBind(); +#endif // RASAUTODIAL + + return ((SuccessfulOpens>0) ? STATUS_SUCCESS :STATUS_DEVICE_DOES_NOT_EXIST); +#else // _PNP_POWER + return(status); +#endif + +} + +VOID +NbfUnload( + IN PDRIVER_OBJECT DriverObject + ) + +/*++ + +Routine Description: + + This routine unloads the NetBIOS Frames Protocol transport driver. + It unbinds from any NDIS drivers that are open and frees all resources + associated with the transport. The I/O system will not call us until + nobody above has NBF open. + +Arguments: + + DriverObject - Pointer to driver object created by the system. + +Return Value: + + None. When the function returns, the driver is unloaded. + +--*/ + +{ + + PDEVICE_CONTEXT DeviceContext; + PLIST_ENTRY p; + + + UNREFERENCED_PARAMETER (DriverObject); + + +#ifdef RASAUTODIAL + // + // Unbind from the + // automatic connection driver. + // + NbfAcdUnbind(); +#endif // RASAUTODIAL + + // + // Walk the list of device contexts. + // + + while (!IsListEmpty (&NbfDeviceList)) { + + p = RemoveHeadList (&NbfDeviceList); + DeviceContext = CONTAINING_RECORD (p, DEVICE_CONTEXT, Linkage); + + DeviceContext->State = DEVICECONTEXT_STATE_STOPPING; + + // + // Remove all the storage associated with the device. + // + + NbfFreeResources (DeviceContext); + + // + // Free the packet pools, etc. and close the + // adapter. + // + + NbfCloseNdis (DeviceContext); + + // + // And remove the creation reference from the device + // context. + // + + NbfDereferenceDeviceContext ("Unload", DeviceContext, DCREF_CREATION); + + } + + // + // Finally, remove ourselves as an NDIS protocol. + // + + NbfDeregisterProtocol(); + + return; + +} + + +VOID +NbfFreeResources ( + IN PDEVICE_CONTEXT DeviceContext + ) +/*++ + +Routine Description: + + This routine is called by NBF to clean up the data structures associated + with a given DeviceContext. When this routine exits, the DeviceContext + should be deleted as it no longer has any assocaited resources. + +Arguments: + + DeviceContext - Pointer to the DeviceContext we wish to clean up. + +Return Value: + + None. + +--*/ +{ + PLIST_ENTRY p; + PSINGLE_LIST_ENTRY s; + PTP_PACKET packet; + PTP_UI_FRAME uiFrame; + PTP_ADDRESS address; + PTP_CONNECTION connection; + PTP_REQUEST request; + PTP_LINK link; + PTP_ADDRESS_FILE addressFile; + PNDIS_PACKET ndisPacket; + PBUFFER_TAG BufferTag; + + + // + // Stop the timers. + // + + NbfStopTimerSystem (DeviceContext); + + + // + // Clean up packet pool. + // + + while ( DeviceContext->PacketPool.Next != NULL ) { + s = PopEntryList( &DeviceContext->PacketPool ); + packet = CONTAINING_RECORD( s, TP_PACKET, Linkage ); + + NbfDeallocateSendPacket (DeviceContext, packet); + } + + // + // Clean up UI frame pool. + // + + while ( !IsListEmpty( &DeviceContext->UIFramePool ) ) { + p = RemoveHeadList( &DeviceContext->UIFramePool ); + uiFrame = CONTAINING_RECORD (p, TP_UI_FRAME, Linkage ); + + NbfDeallocateUIFrame (DeviceContext, uiFrame); + } + + // + // Clean up address pool. + // + + while ( !IsListEmpty (&DeviceContext->AddressPool) ) { + p = RemoveHeadList (&DeviceContext->AddressPool); + address = CONTAINING_RECORD (p, TP_ADDRESS, Linkage); + + NbfDeallocateAddress (DeviceContext, address); + } + + // + // Clean up address file pool. + // + + while ( !IsListEmpty (&DeviceContext->AddressFilePool) ) { + p = RemoveHeadList (&DeviceContext->AddressFilePool); + addressFile = CONTAINING_RECORD (p, TP_ADDRESS_FILE, Linkage); + + NbfDeallocateAddressFile (DeviceContext, addressFile); + } + + // + // Clean up connection pool. + // + + while ( !IsListEmpty (&DeviceContext->ConnectionPool) ) { + p = RemoveHeadList (&DeviceContext->ConnectionPool); + connection = CONTAINING_RECORD (p, TP_CONNECTION, LinkList); + + NbfDeallocateConnection (DeviceContext, connection); + } + + // + // Clean up link pool. + // + + while ( !IsListEmpty (&DeviceContext->LinkPool) ) { + p = RemoveHeadList (&DeviceContext->LinkPool); + link = CONTAINING_RECORD (p, TP_LINK, Linkage); + + NbfDeallocateLink (DeviceContext, link); + } + + // + // Clean up request pool. + // + + while ( !IsListEmpty( &DeviceContext->RequestPool ) ) { + p = RemoveHeadList( &DeviceContext->RequestPool ); + request = CONTAINING_RECORD (p, TP_REQUEST, Linkage ); + + NbfDeallocateRequest (DeviceContext, request); + } + + // + // Clean up receive packet pool + // + + while ( DeviceContext->ReceivePacketPool.Next != NULL) { + s = PopEntryList (&DeviceContext->ReceivePacketPool); + + // + // HACK: This works because Linkage is the first field in + // ProtocolReserved for a receive packet. + // + + ndisPacket = CONTAINING_RECORD (s, NDIS_PACKET, ProtocolReserved[0]); + + NbfDeallocateReceivePacket (DeviceContext, ndisPacket); + } + + + // + // Clean up receive buffer pool. + // + + while ( DeviceContext->ReceiveBufferPool.Next != NULL ) { + s = PopEntryList( &DeviceContext->ReceiveBufferPool ); + BufferTag = CONTAINING_RECORD (s, BUFFER_TAG, Linkage ); + + NbfDeallocateReceiveBuffer (DeviceContext, BufferTag); + } + + + return; + +} /* NbfFreeResources */ + + +NTSTATUS +NbfDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + +/*++ + +Routine Description: + + This routine is the main dispatch routine for the NBF device driver. + It accepts an I/O Request Packet, performs the request, and then + returns with the appropriate status. + +Arguments: + + DeviceObject - Pointer to the device object for this driver. + + Irp - Pointer to the request packet representing the I/O request. + +Return Value: + + The function value is the status of the operation. + +--*/ + +{ + NTSTATUS Status; + PIO_STACK_LOCATION IrpSp; + PDEVICE_CONTEXT DeviceContext; + + ENTER_NBF; + + // + // Check to see if NBF has been initialized; if not, don't allow any use. + // Note that this only covers any user mode code use; kernel TDI clients + // will fail on their creation of an endpoint. + // + + DeviceContext = (PDEVICE_CONTEXT)DeviceObject; + if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) { + LEAVE_NBF; + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; + IoCompleteRequest (Irp, IO_NETWORK_INCREMENT); + return STATUS_INVALID_DEVICE_STATE; + } + + // + // Make sure status information is consistent every time. + // + + IoMarkIrpPending (Irp); + Irp->IoStatus.Status = STATUS_PENDING; + Irp->IoStatus.Information = 0; + + // + // Get a pointer to the current stack location in the IRP. This is where + // the function codes and parameters are stored. + // + + IrpSp = IoGetCurrentIrpStackLocation (Irp); + + // + // Case on the function that is being performed by the requestor. If the + // operation is a valid one for this device, then make it look like it was + // successfully completed, where possible. + // + + + switch (IrpSp->MajorFunction) { + + case IRP_MJ_DEVICE_CONTROL: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: IRP_MJ_DEVICE_CONTROL.\n"); + } + + Status = NbfDeviceControl (DeviceObject, Irp, IrpSp); + break; + + default: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: OTHER (DEFAULT).\n"); + } + Status = STATUS_INVALID_DEVICE_REQUEST; + + } /* major function switch */ + + if (Status == STATUS_PENDING) { + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: request PENDING from handler.\n"); + } + } else { + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: request COMPLETED by handler.\n"); + } + + LEAVE_NBF; + IrpSp->Control &= ~SL_PENDING_RETURNED; + Irp->IoStatus.Status = Status; + IoCompleteRequest (Irp, IO_NETWORK_INCREMENT); + ENTER_NBF; + } + + // + // Return the immediate status code to the caller. + // + + LEAVE_NBF; + return Status; +} /* NbfDispatch */ + + +NTSTATUS +NbfDispatchOpenClose( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + +/*++ + +Routine Description: + + This routine is the main dispatch routine for the NBF device driver. + It accepts an I/O Request Packet, performs the request, and then + returns with the appropriate status. + +Arguments: + + DeviceObject - Pointer to the device object for this driver. + + Irp - Pointer to the request packet representing the I/O request. + +Return Value: + + The function value is the status of the operation. + +--*/ + +{ + KIRQL oldirql; + PDEVICE_CONTEXT DeviceContext; + NTSTATUS Status; + PIO_STACK_LOCATION IrpSp; + PFILE_FULL_EA_INFORMATION openType; + USHORT i; + BOOLEAN found; + PTP_ADDRESS_FILE AddressFile; + PTP_CONNECTION Connection; + + ENTER_NBF; + + // + // Check to see if NBF has been initialized; if not, don't allow any use. + // Note that this only covers any user mode code use; kernel TDI clients + // will fail on their creation of an endpoint. + // + + DeviceContext = (PDEVICE_CONTEXT)DeviceObject; + if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) { + LEAVE_NBF; + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; + IoCompleteRequest (Irp, IO_NETWORK_INCREMENT); + return STATUS_INVALID_DEVICE_STATE; + } + + // + // Make sure status information is consistent every time. + // + + IoMarkIrpPending (Irp); + Irp->IoStatus.Status = STATUS_PENDING; + Irp->IoStatus.Information = 0; + + // + // Get a pointer to the current stack location in the IRP. This is where + // the function codes and parameters are stored. + // + + IrpSp = IoGetCurrentIrpStackLocation (Irp); + + // + // Case on the function that is being performed by the requestor. If the + // operation is a valid one for this device, then make it look like it was + // successfully completed, where possible. + // + + + switch (IrpSp->MajorFunction) { + + // + // The Create function opens a transport object (either address or + // connection). Access checking is performed on the specified + // address to ensure security of transport-layer addresses. + // + + case IRP_MJ_CREATE: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: IRP_MJ_CREATE.\n"); + } + + openType = + (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer; + + if (openType != NULL) { + + found = TRUE; + + for (i=0;i<(USHORT)openType->EaNameLength;i++) { + if (openType->EaName[i] == TdiTransportAddress[i]) { + continue; + } else { + found = FALSE; + break; + } + } + + if (found) { + Status = NbfOpenAddress (DeviceObject, Irp, IrpSp); + break; + } + + // + // Connection? + // + + found = TRUE; + + for (i=0;i<(USHORT)openType->EaNameLength;i++) { + if (openType->EaName[i] == TdiConnectionContext[i]) { + continue; + } else { + found = FALSE; + break; + } + } + + if (found) { + Status = NbfOpenConnection (DeviceObject, Irp, IrpSp); + break; + } + + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint1 ("NbfDispatchOpenClose: IRP_MJ_CREATE on invalid type, type was: %s\n", + openType->EaName); + } + + } else { + + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchOpenClose: IRP_MJ_CREATE on control channel!\n"); + } + + ACQUIRE_SPIN_LOCK (&DeviceContext->SpinLock, &oldirql); + + IrpSp->FileObject->FsContext = (PVOID)(DeviceContext->ControlChannelIdentifier); + ++DeviceContext->ControlChannelIdentifier; + if (DeviceContext->ControlChannelIdentifier == 0) { + DeviceContext->ControlChannelIdentifier = 1; + } + + RELEASE_SPIN_LOCK (&DeviceContext->SpinLock, oldirql); + + IrpSp->FileObject->FsContext2 = (PVOID)NBF_FILE_TYPE_CONTROL; + Status = STATUS_SUCCESS; + } + + break; + + case IRP_MJ_CLOSE: + + // + // The Close function closes a transport endpoint, terminates + // all outstanding transport activity on the endpoint, and unbinds + // the endpoint from its transport address, if any. If this + // is the last transport endpoint bound to the address, then + // the address is removed from the provider. + // + + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: IRP_MJ_CLOSE.\n"); + } + + switch ((ULONG)IrpSp->FileObject->FsContext2) { + case TDI_TRANSPORT_ADDRESS_FILE: + AddressFile = (PTP_ADDRESS_FILE)IrpSp->FileObject->FsContext; + + // + // This creates a reference to AddressFile->Address + // which is removed by NbfCloseAddress. + // + + Status = NbfVerifyAddressObject(AddressFile); + + if (!NT_SUCCESS (Status)) { + Status = STATUS_INVALID_HANDLE; + } else { + Status = NbfCloseAddress (DeviceObject, Irp, IrpSp); + } + + break; + + case TDI_CONNECTION_FILE: + + // + // This is a connection + // + + Connection = (PTP_CONNECTION)IrpSp->FileObject->FsContext; + Status = NbfVerifyConnectionObject (Connection); + if (NT_SUCCESS (Status)) { + + Status = NbfCloseConnection (DeviceObject, Irp, IrpSp); + NbfDereferenceConnection ("Temporary Use",Connection, CREF_BY_ID); + + } + + break; + + case NBF_FILE_TYPE_CONTROL: + + // + // this always succeeds + // + + Status = STATUS_SUCCESS; + break; + + default: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint1 ("NbfDispatch: IRP_MJ_CLOSE on unknown file type %lx.\n", + IrpSp->FileObject->FsContext2); + } + + Status = STATUS_INVALID_HANDLE; + } + + break; + + case IRP_MJ_CLEANUP: + + // + // Handle the two stage IRP for a file close operation. When the first + // stage hits, run down all activity on the object of interest. This + // do everything to it but remove the creation hold. Then, when the + // CLOSE irp hits, actually close the object. + // + + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: IRP_MJ_CLEANUP.\n"); + } + + switch ((ULONG)IrpSp->FileObject->FsContext2) { + case TDI_TRANSPORT_ADDRESS_FILE: + AddressFile = (PTP_ADDRESS_FILE)IrpSp->FileObject->FsContext; + Status = NbfVerifyAddressObject(AddressFile); + if (!NT_SUCCESS (Status)) { + + Status = STATUS_INVALID_HANDLE; + + } else { + + NbfStopAddressFile (AddressFile, AddressFile->Address); + NbfDereferenceAddress ("IRP_MJ_CLEANUP", AddressFile->Address, AREF_VERIFY); + Status = STATUS_SUCCESS; + } + + break; + + case TDI_CONNECTION_FILE: + + Connection = (PTP_CONNECTION)IrpSp->FileObject->FsContext; + Status = NbfVerifyConnectionObject (Connection); + if (NT_SUCCESS (Status)) { + KeRaiseIrql (DISPATCH_LEVEL, &oldirql); + NbfStopConnection (Connection, STATUS_LOCAL_DISCONNECT); + KeLowerIrql (oldirql); + Status = STATUS_SUCCESS; + NbfDereferenceConnection ("Temporary Use",Connection, CREF_BY_ID); + } + + break; + + case NBF_FILE_TYPE_CONTROL: + + NbfStopControlChannel( + (PDEVICE_CONTEXT)DeviceObject, + (USHORT)IrpSp->FileObject->FsContext + ); + + Status = STATUS_SUCCESS; + break; + + default: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint1 ("NbfDispatch: IRP_MJ_CLEANUP on unknown file type %lx.\n", + IrpSp->FileObject->FsContext2); + } + + Status = STATUS_INVALID_HANDLE; + } + + break; + + default: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: OTHER (DEFAULT).\n"); + } + + Status = STATUS_INVALID_DEVICE_REQUEST; + + } /* major function switch */ + + if (Status == STATUS_PENDING) { + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: request PENDING from handler.\n"); + } + } else { + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatch: request COMPLETED by handler.\n"); + } + + LEAVE_NBF; + IrpSp->Control &= ~SL_PENDING_RETURNED; + Irp->IoStatus.Status = Status; + IoCompleteRequest (Irp, IO_NETWORK_INCREMENT); + ENTER_NBF; + } + + + // + // Return the immediate status code to the caller. + // + + LEAVE_NBF; + return Status; +} /* NbfDispatchOpenClose */ + + +NTSTATUS +NbfDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ) + +/*++ + +Routine Description: + + This routine dispatches TDI request types to different handlers based + on the minor IOCTL function code in the IRP's current stack location. + In addition to cracking the minor function code, this routine also + reaches into the IRP and passes the packetized parameters stored there + as parameters to the various TDI request handlers so that they are + not IRP-dependent. + +Arguments: + + DeviceObject - Pointer to the device object for this driver. + + 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. + +--*/ + +{ + NTSTATUS Status; + PDEVICE_CONTEXT DeviceContext = (PDEVICE_CONTEXT)DeviceObject; + + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDeviceControl: Entered.\n"); + } + + + // + // Branch to the appropriate request handler. Preliminary checking of + // the size of the request block is performed here so that it is known + // in the handlers that the minimum input parameters are readable. It + // is *not* determined here whether variable length input fields are + // passed correctly; this is a check which must be made within each routine. + // + + switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) { + +#if MAGIC + case IOCTL_TDI_MAGIC_BULLET: + + // + // Special: send the magic bullet (to trigger the Sniffer). + // + + NbfPrint1 ("NBF: Sending user MagicBullet on %lx\n", DeviceContext); + { + extern VOID NbfSendMagicBullet (PDEVICE_CONTEXT, PTP_LINK); + NbfSendMagicBullet (DeviceContext, NULL); + } + + if (IrpSp->Parameters.DeviceIoControl.Type3InputBuffer != NULL) { + NbfPrint0 ("NBF: DbgBreakPoint after MagicBullet\n"); + DbgBreakPoint(); + } + + Status = STATUS_SUCCESS; + break; +#endif + +#if DBG + case IOCTL_TDI_SEND_TEST: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDeviceControl: Internal IOCTL: start send side test\n"); + } + + (VOID) KeSetEvent( &TdiSendEvent, 0, FALSE ); + + break; + + case IOCTL_TDI_RECEIVE_TEST: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDeviceControl: Internal IOCTL: start receive side test\n"); + } + + (VOID) KeSetEvent( &TdiReceiveEvent, 0, FALSE ); + + break; + + case IOCTL_TDI_SERVER_TEST: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDeviceControl: Internal IOCTL: start receive side test\n"); + } + + (VOID) KeSetEvent( &TdiServerEvent, 0, FALSE ); + + break; +#endif + + default: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDeviceControl: invalid request type.\n"); + } + + // + // Convert the user call to the proper internal device call. + // + + Status = TdiMapUserRequest (DeviceObject, Irp, IrpSp); + + if (Status == STATUS_SUCCESS) { + + // + // If TdiMapUserRequest returns SUCCESS then the IRP + // has been converted into an IRP_MJ_INTERNAL_DEVICE_CONTROL + // IRP, so we dispatch it as usual. The IRP will + // be completed by this call. + // + // NbfDispatchInternal expects to complete the IRP, + // so we change Status to PENDING so we don't. + // + + (VOID)NbfDispatchInternal (DeviceObject, Irp); + Status = STATUS_PENDING; + + } + } + + return Status; +} /* NbfDeviceControl */ + + +NTSTATUS +NbfDispatchInternal ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + +/*++ + +Routine Description: + + This routine dispatches TDI request types to different handlers based + on the minor IOCTL function code in the IRP's current stack location. + In addition to cracking the minor function code, this routine also + reaches into the IRP and passes the packetized parameters stored there + as parameters to the various TDI request handlers so that they are + not IRP-dependent. + +Arguments: + + DeviceObject - Pointer to the device object for this driver. + + Irp - Pointer to the request packet representing the I/O request. + +Return Value: + + The function value is the status of the operation. + +--*/ + +{ + NTSTATUS Status; + PDEVICE_CONTEXT DeviceContext; + PIO_STACK_LOCATION IrpSp; +#if DBG + KIRQL IrqlOnEnter = KeGetCurrentIrql(); +#endif + + ENTER_NBF; + + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfInternalDeviceControl: Entered.\n"); + } + + // + // Get a pointer to the current stack location in the IRP. This is where + // the function codes and parameters are stored. + // + + IrpSp = IoGetCurrentIrpStackLocation (Irp); + + DeviceContext = (PDEVICE_CONTEXT)DeviceObject; + + + if (DeviceContext->State != DEVICECONTEXT_STATE_OPEN) { + LEAVE_NBF; + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; + IoCompleteRequest (Irp, IO_NETWORK_INCREMENT); + return STATUS_INVALID_DEVICE_STATE; + } + + + // + // Make sure status information is consistent every time. + // + + IoMarkIrpPending (Irp); + Irp->IoStatus.Status = STATUS_PENDING; + Irp->IoStatus.Information = 0; + + + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + { + PULONG Temp=(PULONG)&IrpSp->Parameters; + NbfPrint5 ("Got IrpSp %lx %lx %lx %lx %lx\n", Temp++, Temp++, + Temp++, Temp++, Temp++); + } + } + + // + // Branch to the appropriate request handler. Preliminary checking of + // the size of the request block is performed here so that it is known + // in the handlers that the minimum input parameters are readable. It + // is *not* determined here whether variable length input fields are + // passed correctly; this is a check which must be made within each routine. + // + + switch (IrpSp->MinorFunction) { + + case TDI_ACCEPT: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiAccept request.\n"); + } + + Status = NbfTdiAccept (Irp); + break; + + case TDI_ACTION: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiAction request.\n"); + } + + Status = NbfTdiAction (DeviceContext, Irp); + break; + + case TDI_ASSOCIATE_ADDRESS: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiAccept request.\n"); + } + + Status = NbfTdiAssociateAddress (Irp); + break; + + case TDI_DISASSOCIATE_ADDRESS: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiDisassociateAddress request.\n"); + } + + Status = NbfTdiDisassociateAddress (Irp); + break; + + case TDI_CONNECT: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiConnect request\n"); + } + + Status = NbfTdiConnect (Irp); + + break; + + case TDI_DISCONNECT: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiDisconnect request.\n"); + } + + Status = NbfTdiDisconnect (Irp); + break; + + case TDI_LISTEN: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiListen request.\n"); + } + + Status = NbfTdiListen (Irp); + break; + + case TDI_QUERY_INFORMATION: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiQueryInformation request.\n"); + } + + Status = NbfTdiQueryInformation (DeviceContext, Irp); + break; + + case TDI_RECEIVE: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiReceive request.\n"); + } + + Status = NbfTdiReceive (Irp); + break; + + case TDI_RECEIVE_DATAGRAM: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiReceiveDatagram request.\n"); + } + + Status = NbfTdiReceiveDatagram (Irp); + break; + + case TDI_SEND: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiSend request.\n"); + } + + Status = NbfTdiSend (Irp); + break; + + case TDI_SEND_DATAGRAM: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiSendDatagram request.\n"); + } + + Status = NbfTdiSendDatagram (Irp); + break; + + case TDI_SET_EVENT_HANDLER: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiSetEventHandler request.\n"); + } + + // + // Because this request will enable direct callouts from the + // transport provider at DISPATCH_LEVEL to a client-specified + // routine, this request is only valid in kernel mode, denying + // access to this request in user mode. + // + + Status = NbfTdiSetEventHandler (Irp); + break; + + case TDI_SET_INFORMATION: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: TdiSetInformation request.\n"); + } + + Status = NbfTdiSetInformation (Irp); + break; + +#if DBG + case 0x7f: + + // + // Special: send the magic bullet (to trigger the Sniffer). + // + + NbfPrint1 ("NBF: Sending MagicBullet on %lx\n", DeviceContext); + { + extern VOID NbfSendMagicBullet (PDEVICE_CONTEXT, PTP_LINK); + NbfSendMagicBullet (DeviceContext, NULL); + } + + Status = STATUS_SUCCESS; + break; +#endif + + // + // Something we don't know about was submitted. + // + + default: + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint1 ("NbfDispatchInternal: invalid request type %lx\n", + IrpSp->MinorFunction); + } + Status = STATUS_INVALID_DEVICE_REQUEST; + } + + if (Status == STATUS_PENDING) { + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: request PENDING from handler.\n"); + } + } else { + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint0 ("NbfDispatchInternal: request COMPLETED by handler.\n"); + } + + LEAVE_NBF; + IrpSp->Control &= ~SL_PENDING_RETURNED; + Irp->IoStatus.Status = Status; + IoCompleteRequest (Irp, IO_NETWORK_INCREMENT); + ENTER_NBF; + } + + + IF_NBFDBG (NBF_DEBUG_DISPATCH) { + NbfPrint1 ("NbfDispatchInternal: exiting, status: %lx\n",Status); + } + + // + // Return the immediate status code to the caller. + // + + LEAVE_NBF; +#if DBG + ASSERT (KeGetCurrentIrql() == IrqlOnEnter); +#endif + + return Status; + +} /* NbfDispatchInternal */ + + +VOID +NbfWriteResourceErrorLog( + IN PDEVICE_CONTEXT DeviceContext, + IN NTSTATUS ErrorCode, + IN ULONG UniqueErrorValue, + IN ULONG BytesNeeded, + IN ULONG ResourceId + ) + +/*++ + +Routine Description: + + This routine allocates and writes an error log entry indicating + an out of resources condition. It will handle event codes + RESOURCE_POOL, RESOURCE_LIMIT, and RESOURCE_SPECIFIC. + +Arguments: + + DeviceContext - Pointer to the device context. + + ErrorCode - The transport event code. + + UniqueErrorValue - Used as the UniqueErrorValue in the error log + packet. + + BytesNeeded - If applicable, the number of bytes that could not + be allocated. + + ResourceId - The resource ID of the allocated structure. + +Return Value: + + None. + +--*/ + +{ + PIO_ERROR_LOG_PACKET errorLogEntry; + UCHAR EntrySize; + PWSTR SecondString; + ULONG SecondStringSize; + PUCHAR StringLoc; + WCHAR ResourceIdBuffer[3]; + WCHAR SizeBuffer[2]; + WCHAR SpecificMaxBuffer[11]; + ULONG SpecificMax; + INT i; + + switch (ErrorCode) { + + case EVENT_TRANSPORT_RESOURCE_POOL: + SecondString = NULL; + SecondStringSize = 0; + break; + + case EVENT_TRANSPORT_RESOURCE_LIMIT: + SecondString = SizeBuffer; + SecondStringSize = sizeof(SizeBuffer); + + switch (DeviceContext->MemoryLimit) { + case 100000: SizeBuffer[0] = L'1'; break; + case 250000: SizeBuffer[0] = L'2'; break; + case 0: SizeBuffer[0] = L'3'; break; + default: SizeBuffer[0] = L'0'; break; + } + SizeBuffer[1] = 0; + break; + + case EVENT_TRANSPORT_RESOURCE_SPECIFIC: + switch (ResourceId) { + case UI_FRAME_RESOURCE_ID: SpecificMax = DeviceContext->SendPacketPoolSize; break; + case PACKET_RESOURCE_ID: SpecificMax = DeviceContext->SendPacketPoolSize; break; + case RECEIVE_PACKET_RESOURCE_ID: SpecificMax = DeviceContext->ReceivePacketPoolSize; break; + case RECEIVE_BUFFER_RESOURCE_ID: SpecificMax = DeviceContext->SendPacketPoolSize+DeviceContext->ReceivePacketPoolSize; break; + case ADDRESS_RESOURCE_ID: SpecificMax = DeviceContext->MaxAddresses; break; + case ADDRESS_FILE_RESOURCE_ID: SpecificMax = DeviceContext->MaxAddressFiles; break; + case CONNECTION_RESOURCE_ID: SpecificMax = DeviceContext->MaxConnections; break; + case LINK_RESOURCE_ID: SpecificMax = DeviceContext->MaxLinks; break; + case REQUEST_RESOURCE_ID: SpecificMax = DeviceContext->MaxRequests; break; + } + + for (i=9; i>=0; i--) { + SpecificMaxBuffer[i] = (WCHAR)((SpecificMax % 10) + L'0'); + SpecificMax /= 10; + if (SpecificMax == 0) { + break; + } + } + SecondString = SpecificMaxBuffer + i; + SecondStringSize = sizeof(SpecificMaxBuffer) - (i * sizeof(WCHAR)); + SpecificMaxBuffer[10] = 0; + break; + + default: + ASSERT (FALSE); + break; + } + + + EntrySize = sizeof(IO_ERROR_LOG_PACKET) + + DeviceContext->DeviceNameLength + + sizeof(ResourceIdBuffer) + + SecondStringSize; + + errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( + (PDEVICE_OBJECT)DeviceContext, + EntrySize + ); + + // + // Convert the resource ID into a buffer. + // + + ResourceIdBuffer[1] = (WCHAR)((ResourceId % 10) + L'0'); + ResourceId /= 10; + ASSERT(ResourceId <= 9); + ResourceIdBuffer[0] = (WCHAR)((ResourceId % 10) + L'0'); + ResourceIdBuffer[2] = 0; + + if (errorLogEntry != NULL) { + + errorLogEntry->MajorFunctionCode = (UCHAR)-1; + errorLogEntry->RetryCount = (UCHAR)-1; + errorLogEntry->DumpDataSize = sizeof(ULONG); + errorLogEntry->NumberOfStrings = (SecondString == NULL) ? 2 : 3; + errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET); + errorLogEntry->EventCategory = 0; + errorLogEntry->ErrorCode = ErrorCode; + errorLogEntry->UniqueErrorValue = 0; + errorLogEntry->FinalStatus = STATUS_INSUFFICIENT_RESOURCES; + errorLogEntry->SequenceNumber = (ULONG)-1; + errorLogEntry->IoControlCode = 0; + errorLogEntry->DumpData[0] = BytesNeeded; + + StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset; + RtlCopyMemory (StringLoc, DeviceContext->DeviceName, DeviceContext->DeviceNameLength); + StringLoc += DeviceContext->DeviceNameLength; + + RtlCopyMemory (StringLoc, ResourceIdBuffer, sizeof(ResourceIdBuffer)); + StringLoc += sizeof(ResourceIdBuffer); + + if (SecondString) { + RtlCopyMemory (StringLoc, SecondString, SecondStringSize); + } + + IoWriteErrorLogEntry(errorLogEntry); + + } + +} /* NbfWriteResourceErrorLog */ + + +VOID +NbfWriteGeneralErrorLog( + IN PDEVICE_CONTEXT DeviceContext, + IN NTSTATUS ErrorCode, + IN ULONG UniqueErrorValue, + IN NTSTATUS FinalStatus, + IN PWSTR SecondString, + IN ULONG DumpDataCount, + IN ULONG DumpData[] + ) + +/*++ + +Routine Description: + + This routine allocates and writes an error log entry indicating + a general problem as indicated by the parameters. It handles + event codes REGISTER_FAILED, BINDING_FAILED, ADAPTER_NOT_FOUND, + TRANSFER_DATA, TOO_MANY_LINKS, and BAD_PROTOCOL. All these + events have messages with one or two strings in them. + +Arguments: + + DeviceContext - Pointer to the device context, or this may be + a driver object instead. + + ErrorCode - The transport event code. + + UniqueErrorValue - Used as the UniqueErrorValue in the error log + packet. + + FinalStatus - Used as the FinalStatus in the error log packet. + + SecondString - If not NULL, the string to use as the %3 + value in the error log packet. + + DumpDataCount - The number of ULONGs of dump data. + + DumpData - Dump data for the packet. + +Return Value: + + None. + +--*/ + +{ + PIO_ERROR_LOG_PACKET errorLogEntry; + UCHAR EntrySize; + ULONG SecondStringSize; + PUCHAR StringLoc; + PWSTR DriverName; + + EntrySize = sizeof(IO_ERROR_LOG_PACKET) + + (DumpDataCount * sizeof(ULONG)); + + if (DeviceContext->Type == IO_TYPE_DEVICE) { + EntrySize += (UCHAR)DeviceContext->DeviceNameLength; + } else { + DriverName = L"Nbf"; + EntrySize += 4 * sizeof(WCHAR); + } + + if (SecondString) { + SecondStringSize = (wcslen(SecondString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL); + EntrySize += (UCHAR)SecondStringSize; + } + + errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( + (PDEVICE_OBJECT)DeviceContext, + EntrySize + ); + + if (errorLogEntry != NULL) { + + errorLogEntry->MajorFunctionCode = (UCHAR)-1; + errorLogEntry->RetryCount = (UCHAR)-1; + errorLogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG)); + errorLogEntry->NumberOfStrings = (SecondString == NULL) ? 1 : 2; + errorLogEntry->StringOffset = + sizeof(IO_ERROR_LOG_PACKET) + ((DumpDataCount-1) * sizeof(ULONG)); + errorLogEntry->EventCategory = 0; + errorLogEntry->ErrorCode = ErrorCode; + errorLogEntry->UniqueErrorValue = UniqueErrorValue; + errorLogEntry->FinalStatus = FinalStatus; + errorLogEntry->SequenceNumber = (ULONG)-1; + errorLogEntry->IoControlCode = 0; + + if (DumpDataCount) { + RtlCopyMemory(errorLogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG)); + } + + StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset; + if (DeviceContext->Type == IO_TYPE_DEVICE) { + RtlCopyMemory (StringLoc, DeviceContext->DeviceName, DeviceContext->DeviceNameLength); + StringLoc += DeviceContext->DeviceNameLength; + } else { + RtlCopyMemory (StringLoc, DriverName, 4 * sizeof(WCHAR)); + StringLoc += 4 * sizeof(WCHAR); + } + if (SecondString) { + RtlCopyMemory (StringLoc, SecondString, SecondStringSize); + } + + IoWriteErrorLogEntry(errorLogEntry); + + } + +} /* NbfWriteGeneralErrorLog */ + + +VOID +NbfWriteOidErrorLog( + IN PDEVICE_CONTEXT DeviceContext, + IN NTSTATUS ErrorCode, + IN NTSTATUS FinalStatus, + IN PWSTR AdapterString, + IN ULONG OidValue + ) + +/*++ + +Routine Description: + + This routine allocates and writes an error log entry indicating + a problem querying or setting an OID on an adapter. It handles + event codes SET_OID_FAILED and QUERY_OID_FAILED. + +Arguments: + + DeviceContext - Pointer to the device context. + + ErrorCode - Used as the ErrorCode in the error log packet. + + FinalStatus - Used as the FinalStatus in the error log packet. + + AdapterString - The name of the adapter we were bound to. + + OidValue - The OID which could not be set or queried. + +Return Value: + + None. + +--*/ + +{ + PIO_ERROR_LOG_PACKET errorLogEntry; + UCHAR EntrySize; + ULONG AdapterStringSize; + PUCHAR StringLoc; + WCHAR OidBuffer[9]; + INT i; + UINT CurrentDigit; + + AdapterStringSize = (wcslen(AdapterString)*sizeof(WCHAR)) + sizeof(UNICODE_NULL); + EntrySize = sizeof(IO_ERROR_LOG_PACKET) - + sizeof(ULONG) + + DeviceContext->DeviceNameLength + + AdapterStringSize + + sizeof(OidBuffer); + + errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry( + (PDEVICE_OBJECT)DeviceContext, + EntrySize + ); + + // + // Convert the OID into a buffer. + // + + for (i=7; i>=0; i--) { + CurrentDigit = OidValue & 0xf; + OidValue >>= 4; + if (CurrentDigit >= 0xa) { + OidBuffer[i] = (WCHAR)(CurrentDigit - 0xa + L'A'); + } else { + OidBuffer[i] = (WCHAR)(CurrentDigit + L'0'); + } + } + OidBuffer[8] = 0; + + if (errorLogEntry != NULL) { + + errorLogEntry->MajorFunctionCode = (UCHAR)-1; + errorLogEntry->RetryCount = (UCHAR)-1; + errorLogEntry->DumpDataSize = 0; + errorLogEntry->NumberOfStrings = 3; + errorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) - sizeof(ULONG); + errorLogEntry->EventCategory = 0; + errorLogEntry->ErrorCode = ErrorCode; + errorLogEntry->UniqueErrorValue = 0; + errorLogEntry->FinalStatus = FinalStatus; + errorLogEntry->SequenceNumber = (ULONG)-1; + errorLogEntry->IoControlCode = 0; + + StringLoc = ((PUCHAR)errorLogEntry) + errorLogEntry->StringOffset; + RtlCopyMemory (StringLoc, DeviceContext->DeviceName, DeviceContext->DeviceNameLength); + StringLoc += DeviceContext->DeviceNameLength; + + RtlCopyMemory (StringLoc, OidBuffer, sizeof(OidBuffer)); + StringLoc += sizeof(OidBuffer); + + RtlCopyMemory (StringLoc, AdapterString, AdapterStringSize); + + IoWriteErrorLogEntry(errorLogEntry); + + } + +} /* NbfWriteOidErrorLog */ + +ULONG +NbfInitializeOneDeviceContext( + OUT PNDIS_STATUS NdisStatus, + IN PDRIVER_OBJECT DriverObject, + IN PCONFIG_DATA NbfConfig, + IN INT AdapterIndex + ) +/*++ + +Routine Description: + + This routine creates and initializes one nbf device context. In order to + do this it must successfully open and bind to the adapter described by + nbfconfig->names[adapterindex]. + +Arguments: + + NdisStatus - The outputted status of the operations. + + DriverObject - the nbf driver object. + + NbfConfig - the transport configuration information from the registry. + + AdapterIndex - which adapter to bind with. + +Return Value: + + The number of successful binds. + +--*/ + +{ + ULONG i, j; + PDEVICE_CONTEXT DeviceContext; + PTP_REQUEST Request; + PTP_LINK Link; + PTP_CONNECTION Connection; + PTP_ADDRESS_FILE AddressFile; + PTP_ADDRESS Address; + PTP_UI_FRAME UIFrame; + PTP_PACKET Packet; + PNDIS_PACKET NdisPacket; + PRECEIVE_PACKET_TAG ReceiveTag; + PBUFFER_TAG BufferTag; + NTSTATUS status; + UINT SuccessfulOpens; + UINT MaxUserData; + ULONG InitReceivePackets; + BOOLEAN UniProcessor; +#ifdef _PNP_POWER + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING DeviceString; + UCHAR PermAddr[sizeof(TA_ADDRESS)+TDI_ADDRESS_LENGTH_NETBIOS]; + PTA_ADDRESS pAddress = (PTA_ADDRESS)PermAddr; + PTDI_ADDRESS_NETBIOS NetBIOSAddress = + (PTDI_ADDRESS_NETBIOS)pAddress->Address; + + pAddress->AddressLength = TDI_ADDRESS_LENGTH_NETBIOS; + pAddress->AddressType = TDI_ADDRESS_TYPE_NETBIOS; + NetBIOSAddress->NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE; +#endif + // + // Determine if we are on a uniprocessor. + // + + if (*KeNumberProcessors == 1) { + UniProcessor = TRUE; + } else { + UniProcessor = FALSE; + } + + { + j = AdapterIndex; + // + // Loop through all the adapters that are in the configuration + // information structure. Allocate a device object for each + // one that we find. + // + + status = NbfCreateDeviceContext( + DriverObject, + &NbfConfig->Names[NbfConfig->DevicesOffset+j], + &DeviceContext + ); + + if (!NT_SUCCESS (status)) { + NbfWriteGeneralErrorLog( + (PVOID)DriverObject, + EVENT_TRANSPORT_BINDING_FAILED, + 707, + status, + NbfConfig->Names[j].Buffer, + 0, + NULL); + *NdisStatus = status; + return(0); + } + + DeviceContext->UniProcessor = UniProcessor; + + // + // Initialize the timer and retry values (note that the link timeouts + // are converted from NT ticks to NBF ticks). These values may + // be modified by NbfInitializeNdis. + // + + DeviceContext->DefaultT1Timeout = NbfConfig->DefaultT1Timeout / SHORT_TIMER_DELTA; + DeviceContext->DefaultT2Timeout = NbfConfig->DefaultT2Timeout / SHORT_TIMER_DELTA; + DeviceContext->DefaultTiTimeout = NbfConfig->DefaultTiTimeout / LONG_TIMER_DELTA; + DeviceContext->LlcRetries = NbfConfig->LlcRetries; + DeviceContext->LlcMaxWindowSize = NbfConfig->LlcMaxWindowSize; + DeviceContext->MaxConsecutiveIFrames = (UCHAR)NbfConfig->MaximumIncomingFrames; + DeviceContext->NameQueryRetries = NbfConfig->NameQueryRetries; + DeviceContext->NameQueryTimeout = NbfConfig->NameQueryTimeout; + DeviceContext->AddNameQueryRetries = NbfConfig->AddNameQueryRetries; + DeviceContext->AddNameQueryTimeout = NbfConfig->AddNameQueryTimeout; + DeviceContext->GeneralRetries = NbfConfig->GeneralRetries; + DeviceContext->GeneralTimeout = NbfConfig->GeneralTimeout; + DeviceContext->MinimumSendWindowLimit = NbfConfig->MinimumSendWindowLimit; + + // + // Initialize our counter that records memory usage. + // + + DeviceContext->MemoryUsage = 0; + DeviceContext->MemoryLimit = NbfConfig->MaxMemoryUsage; + + DeviceContext->MaxRequests = NbfConfig->MaxRequests; + DeviceContext->MaxLinks = NbfConfig->MaxLinks; + DeviceContext->MaxConnections = NbfConfig->MaxConnections; + DeviceContext->MaxAddressFiles = NbfConfig->MaxAddressFiles; + DeviceContext->MaxAddresses = NbfConfig->MaxAddresses; + + // + // Now fire up NDIS so this adapter talks + // + + status = NbfInitializeNdis (DeviceContext, + NbfConfig, + j); + + if (!NT_SUCCESS (status)) { + + // + // Log an error if we were failed to + // open this adapter. + // + + NbfWriteGeneralErrorLog( + DeviceContext, + EVENT_TRANSPORT_BINDING_FAILED, + 601, + status, + NbfConfig->Names[j].Buffer, + 0, + NULL); + + NbfDereferenceDeviceContext ("Initialize NDIS failed", DeviceContext, DCREF_CREATION); + *NdisStatus = status; + return(0); + + } + +#if 0 + DbgPrint("Opened %S as %S\n", &NbfConfig->Names[j], &nameString); +#endif + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint6 ("NbfInitialize: NDIS returned: %x %x %x %x %x %x as local address.\n", + DeviceContext->LocalAddress.Address[0], + DeviceContext->LocalAddress.Address[1], + DeviceContext->LocalAddress.Address[2], + DeviceContext->LocalAddress.Address[3], + DeviceContext->LocalAddress.Address[4], + DeviceContext->LocalAddress.Address[5]); + } + + // + // Initialize our provider information structure; since it + // doesn't change, we just keep it around and copy it to + // whoever requests it. + // + + + MacReturnMaxDataSize( + &DeviceContext->MacInfo, + NULL, + 0, + DeviceContext->MaxSendPacketSize, + TRUE, + &MaxUserData); + + DeviceContext->Information.Version = 0x0100; + DeviceContext->Information.MaxSendSize = 0x1fffe; // 128k - 2 + DeviceContext->Information.MaxConnectionUserData = 0; + DeviceContext->Information.MaxDatagramSize = + MaxUserData - (sizeof(DLC_FRAME) + sizeof(NBF_HDR_CONNECTIONLESS)); + DeviceContext->Information.ServiceFlags = NBF_SERVICE_FLAGS; + if (DeviceContext->MacInfo.MediumAsync) { + DeviceContext->Information.ServiceFlags |= TDI_SERVICE_POINT_TO_POINT; + } + DeviceContext->Information.MinimumLookaheadData = + 240 - (sizeof(DLC_FRAME) + sizeof(NBF_HDR_CONNECTIONLESS)); + DeviceContext->Information.MaximumLookaheadData = + DeviceContext->MaxReceivePacketSize - (sizeof(DLC_I_FRAME) + sizeof(NBF_HDR_CONNECTION)); + DeviceContext->Information.NumberOfResources = NBF_TDI_RESOURCES; + KeQuerySystemTime (&DeviceContext->Information.StartTime); + + + // + // Allocate various structures we will need. + // + + ENTER_NBF; + + // + // The TP_UI_FRAME structure has a CHAR[1] field at the end + // which we expand upon to include all the headers needed; + // the size of the MAC header depends on what the adapter + // told us about its max header size. + // + + DeviceContext->UIFrameHeaderLength = + DeviceContext->MacInfo.MaxHeaderLength + + sizeof(DLC_FRAME) + + sizeof(NBF_HDR_CONNECTIONLESS); + + DeviceContext->UIFrameLength = + FIELD_OFFSET(TP_UI_FRAME, Header[0]) + + DeviceContext->UIFrameHeaderLength; + + + // + // The TP_PACKET structure has a CHAR[1] field at the end + // which we expand upon to include all the headers needed; + // the size of the MAC header depends on what the adapter + // told us about its max header size. TP_PACKETs are used + // for connection-oriented frame as well as for + // control frames, but since DLC_I_FRAME and DLC_S_FRAME + // are the same size, the header is the same size. + // + + ASSERT (sizeof(DLC_I_FRAME) == sizeof(DLC_S_FRAME)); + + DeviceContext->PacketHeaderLength = + DeviceContext->MacInfo.MaxHeaderLength + + sizeof(DLC_I_FRAME) + + sizeof(NBF_HDR_CONNECTION); + + DeviceContext->PacketLength = + FIELD_OFFSET(TP_PACKET, Header[0]) + + DeviceContext->PacketHeaderLength; + + + // + // The BUFFER_TAG structure has a CHAR[1] field at the end + // which we expand upong to include all the frame data. + // + + DeviceContext->ReceiveBufferLength = + DeviceContext->MaxReceivePacketSize + + FIELD_OFFSET(BUFFER_TAG, Buffer[0]); + + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: pre-allocating requests.\n"); + } + for (i=0; i<NbfConfig->InitRequests; i++) { + + NbfAllocateRequest (DeviceContext, &Request); + + if (Request == NULL) { + PANIC ("NbfInitialize: insufficient memory to allocate requests.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + InsertTailList (&DeviceContext->RequestPool, &Request->Linkage); +#if DBG + NbfRequestTable[i+1] = (PVOID)Request; +#endif + } +#if DBG + NbfRequestTable[0] = (PVOID)NbfConfig->InitRequests; + NbfRequestTable[NbfConfig->InitRequests + 1] = (PVOID) + ((NBF_REQUEST_SIGNATURE << 16) | sizeof (TP_REQUEST)); + InitializeListHead (&NbfGlobalRequestList); +#endif + + DeviceContext->RequestInitAllocated = NbfConfig->InitRequests; + DeviceContext->RequestMaxAllocated = NbfConfig->MaxRequests; + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d requests, %ld\n", NbfConfig->InitRequests, DeviceContext->MemoryUsage); + } + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: allocating links.\n"); + } + for (i=0; i<NbfConfig->InitLinks; i++) { + + NbfAllocateLink (DeviceContext, &Link); + + if (Link == NULL) { + PANIC ("NbfInitialize: insufficient memory to allocate links.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + InsertTailList (&DeviceContext->LinkPool, &Link->Linkage); +#if DBG + NbfLinkTable[i+1] = (PVOID)Link; +#endif + } +#if DBG + NbfLinkTable[0] = (PVOID)NbfConfig->InitLinks; + NbfLinkTable[NbfConfig->InitLinks+1] = (PVOID) + ((NBF_LINK_SIGNATURE << 16) | sizeof (TP_LINK)); +#endif + + DeviceContext->LinkInitAllocated = NbfConfig->InitLinks; + DeviceContext->LinkMaxAllocated = NbfConfig->MaxLinks; + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d links, %ld\n", NbfConfig->InitLinks, DeviceContext->MemoryUsage); + } + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: allocating connections.\n"); + } + for (i=0; i<NbfConfig->InitConnections; i++) { + + NbfAllocateConnection (DeviceContext, &Connection); + + if (Connection == NULL) { + PANIC ("NbfInitialize: insufficient memory to allocate connections.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + InsertTailList (&DeviceContext->ConnectionPool, &Connection->LinkList); +#if DBG + NbfConnectionTable[i+1] = (PVOID)Connection; +#endif + } +#if DBG + NbfConnectionTable[0] = (PVOID)NbfConfig->InitConnections; + NbfConnectionTable[NbfConfig->InitConnections+1] = (PVOID) + ((NBF_CONNECTION_SIGNATURE << 16) | sizeof (TP_CONNECTION)); +#endif + + DeviceContext->ConnectionInitAllocated = NbfConfig->InitConnections; + DeviceContext->ConnectionMaxAllocated = NbfConfig->MaxConnections; + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d connections, %ld\n", NbfConfig->InitConnections, DeviceContext->MemoryUsage); + } + + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: allocating AddressFiles.\n"); + } + for (i=0; i<NbfConfig->InitAddressFiles; i++) { + + NbfAllocateAddressFile (DeviceContext, &AddressFile); + + if (AddressFile == NULL) { + PANIC ("NbfInitialize: insufficient memory to allocate Address Files.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + InsertTailList (&DeviceContext->AddressFilePool, &AddressFile->Linkage); +#if DBG + NbfAddressFileTable[i+1] = (PVOID)AddressFile; +#endif + } +#if DBG + NbfAddressFileTable[0] = (PVOID)NbfConfig->InitAddressFiles; + NbfAddressFileTable[NbfConfig->InitAddressFiles + 1] = (PVOID) + ((NBF_ADDRESSFILE_SIGNATURE << 16) | + sizeof (TP_ADDRESS_FILE)); +#endif + + DeviceContext->AddressFileInitAllocated = NbfConfig->InitAddressFiles; + DeviceContext->AddressFileMaxAllocated = NbfConfig->MaxAddressFiles; + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d address files, %ld\n", NbfConfig->InitAddressFiles, DeviceContext->MemoryUsage); + } + + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: allocating addresses.\n"); + } + for (i=0; i<NbfConfig->InitAddresses; i++) { + + NbfAllocateAddress (DeviceContext, &Address); + if (Address == NULL) { + PANIC ("NbfInitialize: insufficient memory to allocate addresses.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + InsertTailList (&DeviceContext->AddressPool, &Address->Linkage); +#if DBG + NbfAddressTable[i+1] = (PVOID)Address; +#endif + } +#if DBG + NbfAddressTable[0] = (PVOID)NbfConfig->InitAddresses; + NbfAddressTable[NbfConfig->InitAddresses + 1] = (PVOID) + ((NBF_ADDRESS_SIGNATURE << 16) | sizeof (TP_ADDRESS)); +#endif + + DeviceContext->AddressInitAllocated = NbfConfig->InitAddresses; + DeviceContext->AddressMaxAllocated = NbfConfig->MaxAddresses; + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d addresses, %ld\n", NbfConfig->InitAddresses, DeviceContext->MemoryUsage); + } + + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: allocating UI frames.\n"); + } + + for (i=0; i<NbfConfig->InitUIFrames; i++) { + + NbfAllocateUIFrame (DeviceContext, &UIFrame); + + if (UIFrame == NULL) { + PANIC ("NbfInitialize: insufficient memory to allocate UI frames.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + InsertTailList (&(DeviceContext->UIFramePool), &UIFrame->Linkage); +#if DBG + NbfUiFrameTable[i+1] = UIFrame; +#endif + } +#if DBG + NbfUiFrameTable[0] = (PVOID)NbfConfig->InitUIFrames; +#endif + + DeviceContext->UIFrameInitAllocated = NbfConfig->InitUIFrames; + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d UI frames, %ld\n", NbfConfig->InitUIFrames, DeviceContext->MemoryUsage); + } + + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: allocating I frames.\n"); + NbfPrint1 ("NBFDRVR: Packet pool header: %lx\n",&DeviceContext->PacketPool); + } + + for (i=0; i<NbfConfig->InitPackets; i++) { + + NbfAllocateSendPacket (DeviceContext, &Packet); + if (Packet == NULL) { + PANIC ("NbfInitialize: insufficient memory to allocate packets.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + PushEntryList (&DeviceContext->PacketPool, (PSINGLE_LIST_ENTRY)&Packet->Linkage); +#if DBG + NbfSendPacketTable[i+1] = Packet; +#endif + } +#if DBG + NbfSendPacketTable[0] = (PVOID)NbfConfig->InitPackets; + NbfSendPacketTable[NbfConfig->InitPackets+1] = (PVOID) + ((NBF_PACKET_SIGNATURE << 16) | sizeof (TP_PACKET)); +#endif + + DeviceContext->PacketInitAllocated = NbfConfig->InitPackets; + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d send packets, %ld\n", NbfConfig->InitPackets, DeviceContext->MemoryUsage); + } + + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: allocating RR frames.\n"); + NbfPrint1 ("NBFDRVR: Packet pool header: %lx\n",&DeviceContext->RrPacketPool); + } + + for (i=0; i<10; i++) { + + NbfAllocateSendPacket (DeviceContext, &Packet); + if (Packet == NULL) { + PANIC ("NbfInitialize: insufficient memory to allocate packets.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + Packet->Action = PACKET_ACTION_RR; + PushEntryList (&DeviceContext->RrPacketPool, (PSINGLE_LIST_ENTRY)&Packet->Linkage); + } + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d send packets, %ld\n", 10, DeviceContext->MemoryUsage); + } + + + // Allocate receive Ndis packets + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: allocating Ndis Receive packets.\n"); + } + if (DeviceContext->MacInfo.SingleReceive) { + InitReceivePackets = 2; + } else { + InitReceivePackets = NbfConfig->InitReceivePackets; + } + for (i=0; i<InitReceivePackets; i++) { + + NbfAllocateReceivePacket (DeviceContext, &NdisPacket); + + if (NdisPacket == NULL) { + PANIC ("NbfInitialize: insufficient memory to allocate packet MDLs.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + ReceiveTag = (PRECEIVE_PACKET_TAG)NdisPacket->ProtocolReserved; + PushEntryList (&DeviceContext->ReceivePacketPool, &ReceiveTag->Linkage); + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + PNDIS_BUFFER NdisBuffer; + NdisQueryPacket(NdisPacket, NULL, NULL, &NdisBuffer, NULL); + NbfPrint2 ("NbfInitialize: Created NDIS Pkt: %x Buffer: %x\n", + NdisPacket, NdisBuffer); + } + } + + DeviceContext->ReceivePacketInitAllocated = InitReceivePackets; + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d receive packets, %ld\n", InitReceivePackets, DeviceContext->MemoryUsage); + } + + IF_NBFDBG (NBF_DEBUG_RESOURCE) { + NbfPrint0 ("NBFDRVR: allocating Ndis Receive buffers.\n"); + } + + for (i=0; i<NbfConfig->InitReceiveBuffers; i++) { + + NbfAllocateReceiveBuffer (DeviceContext, &BufferTag); + + if (BufferTag == NULL) { + PANIC ("NbfInitialize: Unable to allocate receive packet.\n"); + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + PushEntryList (&DeviceContext->ReceiveBufferPool, (PSINGLE_LIST_ENTRY)&BufferTag->Linkage); + + } + + DeviceContext->ReceiveBufferInitAllocated = NbfConfig->InitReceiveBuffers; + + IF_NBFDBG (NBF_DEBUG_DYNAMIC) { + NbfPrint2 ("%d receive buffers, %ld\n", NbfConfig->InitReceiveBuffers, DeviceContext->MemoryUsage); + } + + DeviceContext->State = DEVICECONTEXT_STATE_OPEN; + + // + // Start the link-level timers running. + // + + NbfInitializeTimerSystem (DeviceContext); + + + // + // Now link the device into the global list. + // + + InsertTailList (&NbfDeviceList, &DeviceContext->Linkage); + + ++SuccessfulOpens; + +#ifdef _PNP_POWER + DeviceObject = (PDEVICE_OBJECT) DeviceContext; + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + RtlInitUnicodeString(&DeviceString, DeviceContext->DeviceName); + status = TdiRegisterDeviceObject(&DeviceString, + &DeviceContext->TdiDeviceHandle); + + if (!NT_SUCCESS (status)) { + --SuccessfulOpens; + RemoveEntryList(&DeviceContext->Linkage); + goto cleanup; + } + + RtlCopyMemory(NetBIOSAddress->NetbiosName, + DeviceContext->ReservedNetBIOSAddress, 16); + + + status = TdiRegisterNetAddress(pAddress, + &DeviceContext->ReservedAddressHandle); + + if (!NT_SUCCESS (status)) { + --SuccessfulOpens; + RemoveEntryList(&DeviceContext->Linkage); + goto cleanup; + } +#endif + + LEAVE_NBF; + *NdisStatus = NDIS_STATUS_SUCCESS; + + return(1);; + +cleanup: + + NbfWriteResourceErrorLog( + DeviceContext, + EVENT_TRANSPORT_RESOURCE_POOL, + 501, + DeviceContext->MemoryUsage, + 0); + + // + // Cleanup whatever device context we were initializing + // when we failed. + // + *NdisStatus = status; + ASSERT(status != STATUS_SUCCESS); + + NbfFreeResources (DeviceContext); + NbfCloseNdis (DeviceContext); + NbfDereferenceDeviceContext ("Load failed", DeviceContext, DCREF_CREATION); + + + LEAVE_NBF; + } + return(0); +} |