|
|
/*++
Copyright (c) 1989-1993 Microsoft Corporation
Module Name:
Driver.c
Abstract:
This module implements the DRIVER_INITIALIZATION routine for the NBT Transport and other routines that are specific to the NT implementation of a driver.
Author:
Jim Stewart (Jimst) 10-2-92
Revision History:
--*/
#include "precomp.h"
#include <nbtioctl.h>
#include "driver.tmh"
#if DBG
// allocate storage for the global debug flag NbtDebug
//ULONG NbtDebug = NBT_DEBUG_KDPRINTS| NBT_DEBUG_NETBIOS_EX;
ULONG NbtDebug = 0; #endif // DBG
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );
NTSTATUS NbtDispatchCleanup( IN PDEVICE_OBJECT Device, IN PIRP pIrp );
NTSTATUS NbtDispatchClose( IN PDEVICE_OBJECT device, IN PIRP pIrp );
NTSTATUS NbtDispatchCreate( IN PDEVICE_OBJECT Device, IN PIRP pIrp );
NTSTATUS NbtDispatchDevCtrl( IN PDEVICE_OBJECT device, IN PIRP pIrp );
NTSTATUS NbtDispatchInternalCtrl( IN PDEVICE_OBJECT device, IN PIRP pIrp );
#ifdef _PNP_POWER_
VOID NbtUnload( IN PDRIVER_OBJECT device ); #endif // _PNP_POWER_
NTSTATUS NbtDispatchPnP( IN PDEVICE_OBJECT Device, IN PIRP pIrp );
PFILE_FULL_EA_INFORMATION FindInEA( IN PFILE_FULL_EA_INFORMATION start, IN PCHAR wanted );
VOID ReturnIrp( IN PIRP pIrp, IN int status );
VOID MakePending( IN PIRP pIrp );
NTSTATUS NbtCreateAdminSecurityDescriptor( IN PDEVICE_OBJECT dev );
#ifdef _PNP_POWER_DBG_
//
//Debug Stuff for DbgBreakPoint -- REMOVE
//
NTSTATUS NbtOpenRegistry( IN HANDLE NbConfigHandle, IN PWSTR String, OUT PHANDLE pHandle ); #endif // _PNP_POWER_DBG_
#ifdef _PNP_POWER_
HANDLE TdiClientHandle = NULL; HANDLE TdiProviderHandle = NULL; extern tTIMERQ TimerQ; #endif // _PNP_POWER_
#ifdef _NETBIOSLESS
tDEVICECONTEXT *pNbtSmbDevice = NULL; #endif // _NETBIOSLESS
//******************* Pageable Routine Declarations ****************
#ifdef ALLOC_PRAGMA
#pragma CTEMakePageable(INIT, DriverEntry)
#pragma CTEMakePageable(PAGE, NbtDispatchCleanup)
#pragma CTEMakePageable(PAGE, NbtDispatchClose)
#pragma CTEMakePageable(PAGE, NbtDispatchCreate)
#pragma CTEMakePageable(PAGE, NbtDispatchDevCtrl)
#pragma CTEMakePageable(PAGE, FindInEA)
#pragma CTEMakePageable(PAGE, NbtUnload)
#endif
//******************* Pageable Routine Declarations ****************
//----------------------------------------------------------------------------
VOID CleanupDriverEntry( ULONG CleanupStage ) { PSINGLE_LIST_ENTRY pSingleListEntry; PMDL pMdl; PVOID pBuffer; LIST_ENTRY *pListEntry; tDGRAM_SEND_TRACKING *pTracker;
switch (CleanupStage) { case (6): NbtDestroyDevice (pWinsDeviceContext, FALSE);
#ifdef RASAUTODIAL
//
// Unbind fron the RAS driver if we were bound
//
NbtAcdUnbind (); #endif // RASAUTODIAL
// Fall through
case (5): if (pNbtSmbDevice) { NbtDestroyDevice (pNbtSmbDevice, FALSE); pNbtSmbDevice = NULL; }
if (NbtConfig.OutOfRsrc.pDpc) { CTEMemFree (NbtConfig.OutOfRsrc.pDpc); } if (NbtConfig.OutOfRsrc.pIrp) { IoFreeIrp (NbtConfig.OutOfRsrc.pIrp); }
// Fall through
case (4): while (NbtConfig.SessionMdlFreeSingleList.Next) { pSingleListEntry = PopEntryList(&NbtConfig.SessionMdlFreeSingleList); pMdl = CONTAINING_RECORD(pSingleListEntry,MDL,Next); pBuffer = MmGetMdlVirtualAddress (pMdl); CTEMemFree (pBuffer); IoFreeMdl (pMdl); }
while (NbtConfig.DgramMdlFreeSingleList.Next) { pSingleListEntry = PopEntryList(&NbtConfig.DgramMdlFreeSingleList); pMdl = CONTAINING_RECORD(pSingleListEntry,MDL,Next); pBuffer = MmGetMdlVirtualAddress (pMdl); CTEMemFree (pBuffer); IoFreeMdl (pMdl); }
// Fall through
case (3): //
// InitNotOs has been called
//
DestroyTimerQ();
while (!IsListEmpty(&NbtConfig.DgramTrackerFreeQ)) { pListEntry = RemoveHeadList(&NbtConfig.DgramTrackerFreeQ); pTracker = CONTAINING_RECORD(pListEntry,tDGRAM_SEND_TRACKING,Linkage); CTEMemFree (pTracker); }
DestroyHashTables (); ExDeleteResourceLite (&NbtConfig.Resource); // Delete the resource
// Fall through
case (2): //
// Read registry has been called!
//
CTEMemFree (NbtConfig.pLmHosts); CTEMemFree (NbtConfig.pScope); if (NbtConfig.pTcpBindName) { CTEMemFree (NbtConfig.pTcpBindName); }
// Fall through
case (1): CTEMemFree (NbtConfig.pRegistry.Buffer);
default: break; } }
//----------------------------------------------------------------------------
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
/*++
Routine Description:
This is the initialization routine for the NBT device driver. This routine creates the device object for the NBT device and calls a routine to perform other driver initialization.
Arguments:
DriverObject - Pointer to driver object created by the system.
Return Value:
NTSTATUS - The function value is the final status from the initialization operation.
--*/
{ NTSTATUS status; tDEVICES *pBindDevices=NULL; tDEVICES *pExportDevices=NULL; tADDRARRAY *pAddrArray=NULL; PMDL pMdl; PSINGLE_LIST_ENTRY pSingleListEntry;
UNICODE_STRING ucWinsDeviceBindName; UNICODE_STRING ucWinsDeviceExportName; UNICODE_STRING ucSmbDeviceBindName; UNICODE_STRING ucSmbDeviceExportName; UNICODE_STRING ucNetBTClientName; UNICODE_STRING ucNetBTProviderName;
TDI_CLIENT_INTERFACE_INFO TdiClientInterface;
#ifdef _PNP_POWER_DBG_
//
//Debug Stuff for DbgBreakPoint
//
OBJECT_ATTRIBUTES TmpObjectAttributes; HANDLE NbtConfigHandle; ULONG Disposition; PWSTR ParametersString = L"Parameters"; HANDLE ParametersHandle; #endif // _PNP_POWER_DBG_
CTEPagedCode();
#ifdef _NBT_WMI_SOFTWARE_TRACING_
WPP_INIT_TRACING(DriverObject, RegistryPath); #endif
#ifdef _PNP_POWER_DBG_
InitializeObjectAttributes (&TmpObjectAttributes, RegistryPath, // name
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // attributes
NULL, // root
NULL); // security descriptor
status = ZwCreateKey (&NbtConfigHandle, KEY_READ, &TmpObjectAttributes, 0, // title index
NULL, // class
0, // create options
&Disposition); // disposition
if (!NT_SUCCESS(status)) { NbtLogEvent (EVENT_NBT_CREATE_DRIVER, status, 0x109); return STATUS_UNSUCCESSFUL; }
status = NbtOpenRegistry (NbtConfigHandle, ParametersString, &ParametersHandle); if (!NT_SUCCESS(status)) { ZwClose(NbtConfigHandle); return (status); }
if (CTEReadSingleIntParameter(ParametersHandle, ANSI_IF_VXD("Break"), 0, 0)) // disabled by default
{ KdPrint (("Nbt.DriverEntry: Registry-set Break!\n")); DbgBreakPoint(); }
ZwClose(ParametersHandle); ZwClose(NbtConfigHandle); #endif // _PNP_POWER_DBG_
TdiInitialize();
//
// get the file system process for NBT since we need to know this for
// allocating and freeing handles
//
NbtFspProcess =(PEPROCESS)PsGetCurrentProcess();
//
// Initialize the Configuration data structure
//
CTEZeroMemory(&NbtConfig,sizeof(tNBTCONFIG));
NbtConfig.LoopbackIfContext = 0xffff;
// save the driver object for event logging purposes
//
NbtConfig.DriverObject = DriverObject;
// save the registry path for later use when DHCP asks us
// to re-read the registry.
//
NbtConfig.pRegistry.MaximumLength = (USHORT) RegistryPath->MaximumLength; if (NbtConfig.pRegistry.Buffer = NbtAllocMem (RegistryPath->MaximumLength, NBT_TAG2('17'))) { RtlCopyUnicodeString(&NbtConfig.pRegistry,RegistryPath); } else { return (STATUS_INSUFFICIENT_RESOURCES); }
//
// Initialize the driver object with this driver's entry points.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)NbtDispatchCreate; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)NbtDispatchDevCtrl; DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)NbtDispatchInternalCtrl; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)NbtDispatchCleanup; DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)NbtDispatchClose; DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH)NbtDispatchPnP; DriverObject->DriverUnload = NbtUnload;
//
// read in registry configuration data
//
status = NbtReadRegistry (&pBindDevices, &pExportDevices, &pAddrArray); if (!NT_SUCCESS(status)) { //
// There must have been some major problems with the registry, so
// we will not load!
//
DbgPrint ("Nbt.DriverEntry[1]: Not loading because of failure to read registry = <%x>\n", status);
CleanupDriverEntry (1); return(status); }
//
// Cleanup Allocated memory
//
NbtReadRegistryCleanup (&pBindDevices, &pExportDevices, &pAddrArray);
//
// Initialize NBT global data.
//
status = InitNotOs(); if (!NT_SUCCESS(status)) { NbtLogEvent (EVENT_NBT_NON_OS_INIT, status, 0x110);
DbgPrint ("Nbt.DriverEntry[3]: Not loading because of failure to Initialize = <%x>\n",status); CleanupDriverEntry (3); // We may have done some partial initialization!
return (status); }
// create some MDLs, for session sends to speed up the sends.
status = NbtInitMdlQ (&NbtConfig.SessionMdlFreeSingleList, eNBT_FREE_SESSION_MDLS); if (!NT_SUCCESS(status)) { DbgPrint ("Nbt.DriverEntry[4]: Not loading because of failure to init Session MDL Q = <%x>\n",status); CleanupDriverEntry (4); return (status); }
// create some MDLs for datagram sends
status = NbtInitMdlQ( &NbtConfig.DgramMdlFreeSingleList, eNBT_DGRAM_MDLS); if (!NT_SUCCESS(status)) { DbgPrint ("Nbt.DriverEntry[4]: Not loading because of failure to init Dgram MDL Q = <%x>\n", status); CleanupDriverEntry (4); return (status); }
//---------------------------------------------------------------------------------------
//
// Create the SmbDevice object for Rdr/Srv
//
if ((NbtConfig.SMBDeviceEnabled) && (!(pNbtSmbDevice = NbtCreateSmbDevice()))) { KdPrint (("Nbt.DriverEntry: Failed to create SmbDevice!\n")); //
// Allow the initialization to succeed even if this fails!
//
}
//---------------------------------------------------------------------------------------
//
// Create the NBT device object for WINS to use
//
RtlInitUnicodeString (&ucWinsDeviceBindName, WC_WINS_DEVICE_BIND_NAME); ucWinsDeviceBindName.MaximumLength = sizeof (WC_WINS_DEVICE_BIND_NAME); RtlInitUnicodeString (&ucWinsDeviceExportName, WC_WINS_DEVICE_EXPORT_NAME); ucWinsDeviceExportName.MaximumLength = sizeof (WC_WINS_DEVICE_EXPORT_NAME);
//
// Try to export a DeviceObject for Wins, but do not add it to the list
// of devices which we notify TDI about
// Do not care about status because we want to continue even if we fail
//
status = NbtAllocAndInitDevice (&ucWinsDeviceBindName, &ucWinsDeviceExportName, &pWinsDeviceContext, NBT_DEVICE_WINS);
if (!NT_SUCCESS(status)) { DbgPrint ("Nbt.DriverEntry[5]: Not loading because of failure to create pWinsDevContext = <%x>\n", status); CleanupDriverEntry (5); return (status); } status = NbtCreateAdminSecurityDescriptor(&pWinsDeviceContext->DeviceObject); ASSERT(NT_SUCCESS(status));
pWinsDeviceContext->IpAddress = 0; pWinsDeviceContext->DeviceRegistrationHandle = NULL; pWinsDeviceContext->NetAddressRegistrationHandle = NULL; pWinsDeviceContext->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
//---------------------------------------------------------------------------------------
#ifdef RASAUTODIAL
//
// Get the automatic connection driver
// entry points.
//
NbtAcdBind(); #endif
//---------------------------------------------------------------------------------------
//
// Register ourselves as a Provider with Tdi
//
RtlInitUnicodeString(&ucNetBTProviderName, WC_NETBT_PROVIDER_NAME); ucNetBTProviderName.MaximumLength = sizeof (WC_NETBT_PROVIDER_NAME); status = TdiRegisterProvider (&ucNetBTProviderName, &TdiProviderHandle); if (NT_SUCCESS (status)) { //
// Register our Handlers with TDI
//
RtlInitUnicodeString(&ucNetBTClientName, WC_NETBT_CLIENT_NAME); ucNetBTClientName.MaximumLength = sizeof (WC_NETBT_CLIENT_NAME); RtlZeroMemory(&TdiClientInterface, sizeof(TdiClientInterface));
TdiClientInterface.MajorTdiVersion = MAJOR_TDI_VERSION; TdiClientInterface.MinorTdiVersion = MINOR_TDI_VERSION; TdiClientInterface.ClientName = &ucNetBTClientName; TdiClientInterface.AddAddressHandlerV2 = TdiAddressArrival; TdiClientInterface.DelAddressHandlerV2 = TdiAddressDeletion; TdiClientInterface.BindingHandler = TdiBindHandler; TdiClientInterface.PnPPowerHandler = TdiPnPPowerHandler;
status = TdiRegisterPnPHandlers (&TdiClientInterface, sizeof(TdiClientInterface), &TdiClientHandle); if (!NT_SUCCESS (status)) { TdiDeregisterProvider (TdiProviderHandle); TdiProviderHandle = NULL; } } else { TdiProviderHandle = NULL; }
if (!NT_SUCCESS (status)) { DbgPrint ("Nbt.DriverEntry[6]: Not loading because of error = <%x>\n", status); CleanupDriverEntry (6); }
//
// Return to the caller.
//
return (status); }
//----------------------------------------------------------------------------
NTSTATUS NbtDispatchCleanup( IN PDEVICE_OBJECT Device, IN PIRP pIrp )
/*++
Routine Description:
This is the NBT driver's dispatch function for IRP_MJ_CLEANUP requests.
This function is called when the last reference to the handle is closed. Hence, an NtClose() results in an IRP_MJ_CLEANUP first, and then an IRP_MJ_CLOSE. This function runs down all activity on the object, and when the close comes in the object is actually deleted.
Arguments:
device - ptr to device object for target device pIrp - ptr to I/O request packet
Return Value:
STATUS_SUCCESS
--*/
{ NTSTATUS status; PIO_STACK_LOCATION pIrpSp; tDEVICECONTEXT *pDeviceContext;
CTEPagedCode();
pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp->MajorFunction == IRP_MJ_CLEANUP);
pDeviceContext = (tDEVICECONTEXT *)Device; if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE)) { // IF_DBG(NBT_DEBUG_DRIVER)
KdPrint(("Nbt.NbtDispatchCleanup: Short-Ckt request --Device=<%x>, Context=<%x>, Context2=<%x>\n", pDeviceContext, pIrpSp->FileObject->FsContext, pIrpSp->FileObject->FsContext2));
status = STATUS_SUCCESS;
pIrp->IoStatus.Status = status; IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT); return (status); }
// look at the context value that NBT put into the FSContext2 value to
// decide what to do
switch ((USHORT)pIrpSp->FileObject->FsContext2) { case NBT_ADDRESS_TYPE: // the client is closing the address file, so we must cleanup
// and memory blocks associated with it.
status = NTCleanUpAddress(pDeviceContext,pIrp); break;
case NBT_CONNECTION_TYPE: // the client is closing a connection, so we must clean up any
// memory blocks associated with it.
status = NTCleanUpConnection(pDeviceContext,pIrp); break;
case NBT_WINS_TYPE: //
// This is synchronous with the Wins NtClose operation
//
status = NTCleanUpWinsAddr (pDeviceContext, pIrp); break;
case NBT_CONTROL_TYPE: // there is nothing to do here....
status = STATUS_SUCCESS; break;
default: /*
* complete the i/o successfully. */ status = STATUS_SUCCESS; break; }
//
// Complete the Irp
//
ReturnIrp(pIrp, status);
NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(status); } // DispatchCleanup
//----------------------------------------------------------------------------
NTSTATUS NbtDispatchClose( IN PDEVICE_OBJECT Device, IN PIRP pIrp )
/*++
Routine Description:
This is the NBT driver's dispatch function for IRP_MJ_CLOSE requests. This is called after Cleanup (above) is called.
Arguments:
device - ptr to device object for target device pIrp - ptr to I/O request packet
Return Value:
an NT status code.
--*/
{ NTSTATUS status; PIO_STACK_LOCATION pIrpSp; tDEVICECONTEXT *pDeviceContext;
CTEPagedCode();
pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp->MajorFunction == IRP_MJ_CLOSE);
pDeviceContext = (tDEVICECONTEXT *)Device; if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE)) { // IF_DBG(NBT_DEBUG_DRIVER)
KdPrint(("Nbt.NbtDispatchClose: Short-Ckt request -- Device=<%x>, Context=<%x>, Context2=<%x>\n", pDeviceContext, pIrpSp->FileObject->FsContext, pIrpSp->FileObject->FsContext2));
status = STATUS_SUCCESS;
pIrp->IoStatus.Status = status; IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT); return (status); }
//
// close operations are synchronous.
//
pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0;
switch (PtrToUlong(pIrpSp->FileObject->FsContext2)) { case NBT_ADDRESS_TYPE: status = NTCloseAddress(pDeviceContext,pIrp); break;
case NBT_CONNECTION_TYPE: status = NTCloseConnection(pDeviceContext,pIrp); break;
case NBT_WINS_TYPE: //
// We don't need to set the DeviceContext here since we had
// already saved it in pWinsInfo
// This is an Asynchronous operation wrt the Wins server, hence
// we should do only minimal work in this routine -- the
// major cleanup should be in the DispatchCleanup routine
//
status = NTCloseWinsAddr(pDeviceContext,pIrp); break;
case NBT_CONTROL_TYPE: // the client is closing the Control Object...
// there is nothing to do here....
status = STATUS_SUCCESS; break;
default: KdPrint(("Nbt:Close Received for unknown object type = %X\n", pIrpSp->FileObject->FsContext2)); status = STATUS_SUCCESS; break; }
// NTCloseAddress can return Pending until the ref count actually gets
// to zero.
//
if (status != STATUS_PENDING) { ReturnIrp(pIrp, status); }
NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(status); } // DispatchClose
//----------------------------------------------------------------------------
NTSTATUS NbtDispatchCreate( IN PDEVICE_OBJECT Device, IN PIRP pIrp )
/*++
Routine Description:
This is the NBT driver's dispatch function for IRP_MJ_CREATE requests. It is called as a consequence of one of the following:
a. TdiOpenConnection("\Device\Nbt_Elnkii0"), b. TdiOpenAddress("\Device\Nbt_Elnkii0"),
Arguments:
Device - ptr to device object being opened pIrp - ptr to I/O request packet pIrp->Status => return status pIrp->MajorFunction => IRP_MD_CREATE pIrp->MinorFunction => not used pIpr->FileObject => ptr to file obj created by I/O system. NBT fills in FsContext pIrp->AssociatedIrp.SystemBuffer => ptr to EA buffer with address of obj to open(Netbios Name) pIrp->Parameters.Create.EaLength => length of buffer specifying the Xport Addr.
Return Value:
STATUS_SUCCESS or STATUS_PENDING
--*/
{ NTSTATUS status; PIO_STACK_LOCATION pIrpSp; PFILE_FULL_EA_INFORMATION ea, eabuf; tDEVICECONTEXT *pDeviceContext; UCHAR IrpFlags; tIPADDRESS UNALIGNED *pIpAddressU; tIPADDRESS IpAddress;
CTEPagedCode();
pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp->MajorFunction == IRP_MJ_CREATE);
//
// If this device was destroyed, then reject all opens on it.
// Ideally we would like the IO sub-system to guarantee that no
// requests come down on IoDeleted devices, but.....
//
pDeviceContext = (tDEVICECONTEXT *)Device; if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE)) { // IF_DBG(NBT_DEBUG_DRIVER)
KdPrint(("Nbt.NbtDispatchCreate: Short-Ckt request -- Device=<%x>, CtrlCode=<%x>\n", pDeviceContext, pIrpSp->Parameters.DeviceIoControl.IoControlCode)); pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT); return (STATUS_INVALID_DEVICE_STATE); }
IrpFlags = pIrpSp->Control;
//
// set the pending flag here so that it is sure to be set BEFORE the
// completion routine gets hit.
//
pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_PENDING; IoMarkIrpPending(pIrp);
/*
* was this a TdiOpenConnection() or TdiOpenAddress()? * Get the Extended Attribute pointer and look at the text * value passed in for a match with "TransportAddress" or * "ConnectionContext" (in FindEa) */ ea = (PFILE_FULL_EA_INFORMATION) pIrp->AssociatedIrp.SystemBuffer;
IF_DBG(NBT_DEBUG_DRIVER) KdPrint(("Nbt.NbtDispatchCreate: Major:Minor=<%x:%x>, PFILE_FULL_EA_INFORMATION = <%x>\n", pIrpSp->MajorFunction, pIrpSp->MinorFunction, ea));
if (!ea) { // a null ea means open the control object
status = NTOpenControl(pDeviceContext,pIrp); } else if (eabuf = FindInEA(ea, TdiConnectionContext)) { // not allowed to pass in both a Connect Request and a Transport Address
ASSERT(!FindInEA(ea, TdiTransportAddress)); status = NTOpenConnection(pDeviceContext, pIrp, eabuf); } else if (eabuf = FindInEA(ea, TdiTransportAddress)) { status = NTOpenAddr(pDeviceContext, pIrp, eabuf); } else if (eabuf = FindInEA(ea, WINS_INTERFACE_NAME)) { pIpAddressU = (tIPADDRESS UNALIGNED *) &ea->EaName[ea->EaNameLength+1]; if (IpAddress = *pIpAddressU) { status = NTOpenWinsAddr(pDeviceContext, pIrp, IpAddress); } else { status = STATUS_INVALID_ADDRESS; } } else { status = STATUS_INVALID_EA_NAME; }
// complete the irp if the status is anything EXCEPT status_pending
// since the name query completion routine NTCompletIO completes pending
// open addresses
if (status != STATUS_PENDING) {
#if DBG
if (!NT_SUCCESS(status)) { IF_DBG(NBT_DEBUG_NAMESRV) KdPrint(("Nbt.NbtDispatchCreate: Returning Error status = %X\n",status)); } #endif
// reset the pending returned bit, since we are NOT returning pending
pIrpSp->Control = IrpFlags; ReturnIrp(pIrp,status);
}
NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(status); }
//----------------------------------------------------------------------------
NTSTATUS NbtDispatchDevCtrl( IN PDEVICE_OBJECT Device, IN PIRP pIrp )
/*++
Routine Description:
This is the NBT driver's dispatch function for all IRP_MJ_DEVICE_CONTROL requests.
Arguments:
device - ptr to device object for target device pIrp - ptr to I/O request packet
Return Value:
NTSTATUS -- Indicates whether the request was successfully queued.
--*/
{ NTSTATUS status = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION pIrpSp; tDEVICECONTEXT *pDeviceContext; ULONG IoControlCode; PULONG_PTR pEntryPoint;
pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
//
// If this device was destroyed, then reject all requests on it.
// Ideally we would like the IO sub-system to guarantee that no
// requests come down on IoDeleted devices, but.....
//
pDeviceContext = (tDEVICECONTEXT *)Device; if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE)) { // IF_DBG(NBT_DEBUG_DRIVER)
KdPrint(("Nbt.NbtDispatchDevCtrl: Short-Ckt request -- Device=<%x>, CtrlCode=<%x>\n", pDeviceContext, pIrpSp->Parameters.DeviceIoControl.IoControlCode)); pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT); return (STATUS_INVALID_DEVICE_STATE); }
/*
* Initialize the I/O status block. */ pIrp->IoStatus.Status = STATUS_PENDING; pIrp->IoStatus.Information = 0; IoControlCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode; // Save the IoControl code
IF_DBG(NBT_DEBUG_DRIVER) KdPrint(("Nbt.NbtDispatchDevCtrl: IoControlCode = <%x>\n", pIrpSp->Parameters.DeviceIoControl.IoControlCode));
/*
* if possible, convert the (external) device control into internal * format, then treat it as if it had arrived that way. */ if (STATUS_SUCCESS == TdiMapUserRequest(Device, pIrp, pIrpSp)) { status = NbtDispatchInternalCtrl (Device, pIrp); } #if FAST_DISP
// Check if upper layer is querying for fast send path
else if (pIrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER) { if (pEntryPoint = pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer) { if (pIrp->RequestorMode != KernelMode) // Bug# 120649: Make sure data + the Address type are good
{ try { ProbeForWrite (pEntryPoint, sizeof(PVOID *), sizeof(BYTE)); *pEntryPoint = (ULONG_PTR) NTSend; status = STATUS_SUCCESS; } except(EXCEPTION_EXECUTE_HANDLER) { // status = STATUS_UNSUCCESSFUL by default
} } else { *pEntryPoint = (ULONG_PTR) NTSend; status = STATUS_SUCCESS; } }
IF_DBG(NBT_DEBUG_DRIVER) KdPrint(("Nbt.NbtDispatchDevCtrl: direct send handler query %x\n", pEntryPoint));
ReturnIrp(pIrp, status); } #endif
else { status = DispatchIoctls (pDeviceContext, pIrp, pIrpSp); }
//
// Dereference this DeviceContext, unless it was to destroy the Device!
//
if (IoControlCode != IOCTL_NETBT_DELETE_INTERFACE) { NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); }
return (status); } // NbtDispatchDevCtrl
//----------------------------------------------------------------------------
NTSTATUS NbtDispatchInternalCtrl( IN PDEVICE_OBJECT Device, IN PIRP pIrp )
/*++
Routine Description:
This is the driver's dispatch function for all IRP_MJ_INTERNAL_DEVICE_CONTROL requests.
Arguments:
device - ptr to device object for target device pIrp - ptr to I/O request packet
Return Value:
NTSTATUS -- Indicates whether the request was successfully queued.
--*/
{ tDEVICECONTEXT *pDeviceContext; PIO_STACK_LOCATION pIrpSp; NTSTATUS status; UCHAR IrpFlags;
pDeviceContext = (tDEVICECONTEXT *)Device;
pIrpSp = IoGetCurrentIrpStackLocation(pIrp); ASSERT(pIrpSp->MajorFunction == IRP_MJ_INTERNAL_DEVICE_CONTROL);
//
// this check is first to optimize the Send path
//
if (pIrpSp->MinorFunction ==TDI_SEND) { //
// this routine decides if it should complete the pIrp or not
// It never returns status pending, so we can turn off the
// pending bit
//
status = NTSend (pDeviceContext,pIrp); return status; }
//
// If this device was destroyed, then reject all operations on it.
// Ideally we would like the IO sub-system to guarantee that no
// requests come down on IoDeleted devices, but.....
//
if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE)) { // IF_DBG(NBT_DEBUG_DRIVER)
KdPrint(("Nbt.NbtDispatchInternalCtrl: Short-Ckt request -- Device=<%x>, CtrlCode=<%x>\n", pDeviceContext, pIrpSp->Parameters.DeviceIoControl.IoControlCode)); pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT); return (STATUS_INVALID_DEVICE_STATE); }
IrpFlags = pIrpSp->Control;
IF_DBG(NBT_DEBUG_DRIVER) KdPrint(("Nbt.NbtDispatchInternalCtrl: MajorFunction:MinorFunction = <%x:%x>\n", pIrpSp->MajorFunction, pIrpSp->MinorFunction));
switch (pIrpSp->MinorFunction) { case TDI_ACCEPT: MakePending(pIrp); status = NTAccept(pDeviceContext,pIrp); break;
case TDI_ASSOCIATE_ADDRESS: MakePending(pIrp); status = NTAssocAddress(pDeviceContext,pIrp); break;
case TDI_DISASSOCIATE_ADDRESS: MakePending(pIrp); status = NTDisAssociateAddress(pDeviceContext,pIrp); break;
case TDI_CONNECT: MakePending(pIrp); status = NTConnect(pDeviceContext,pIrp); break;
case TDI_DISCONNECT: MakePending(pIrp); status = NTDisconnect(pDeviceContext,pIrp); break;
case TDI_LISTEN: status = NTListen(pDeviceContext,pIrp); NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(status); break;
case TDI_QUERY_INFORMATION: status = NTQueryInformation(pDeviceContext,pIrp); #if DBG
if (!NT_SUCCESS(status)) { IF_DBG(NBT_DEBUG_NAMESRV) KdPrint(("Nbt.NbtDispatchInternalCtrl: Bad status from NTQueryInformation = %x\n",status)); } #endif
NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(status); break;
case TDI_RECEIVE: status = NTReceive(pDeviceContext,pIrp); NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(status);
break;
case TDI_RECEIVE_DATAGRAM: status = NTReceiveDatagram(pDeviceContext,pIrp); NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(status); break;
case TDI_SEND_DATAGRAM:
status = NTSendDatagram(pDeviceContext,pIrp); #if DBG
if (!NT_SUCCESS(status)) { IF_DBG(NBT_DEBUG_NAMESRV) KdPrint(("Nbt.NbtDispatchInternalCtrl: Bad status from NTSendDatagram = %x\n",status)); } #endif
NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(status); break;
case TDI_SET_EVENT_HANDLER: MakePending(pIrp); status = NTSetEventHandler(pDeviceContext,pIrp); break;
case TDI_SET_INFORMATION: MakePending(pIrp); status = NTSetInformation(pDeviceContext,pIrp); break;
#if DBG
//
// 0x7f is a request by the redirector to put a "magic bullet" out on
// the wire, to trigger the Network General Sniffer.
//
case 0x7f: KdPrint(("NBT.DispatchInternalCtrl: - 07f minor function code\n")); ReturnIrp(pIrp, STATUS_NOT_SUPPORTED); NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(STATUS_NOT_SUPPORTED);
#endif /* DBG */
default: KdPrint(("Nbt.DispatchInternalCtrl: Invalid minor function %X\n", pIrpSp->MinorFunction)); ReturnIrp(pIrp, STATUS_INVALID_DEVICE_REQUEST); NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(STATUS_INVALID_DEVICE_REQUEST); }
// if the returned status is pending, then we do not complete the IRP
// here since it will be completed elsewhere in the code...
//
if (status != STATUS_PENDING) { #if DBG
// *TODO* for debug...
if (!NT_SUCCESS(status)) { IF_DBG(NBT_DEBUG_NAMESRV) KdPrint(("Nbt.NbtDispatchInternalCtrl: Returning Error status = %X,MinorFunc = %X\n", status,pIrpSp->MinorFunction)); // ASSERTMSG("An error Status reported from NBT",0L);
} #endif
pIrpSp->Control = IrpFlags; ReturnIrp(pIrp,status); }
NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return(status); } // NbtDispatchInternalCtrl
//----------------------------------------------------------------------------
ULONG CompleteTimerAndWorkerRequests( ) { CTELockHandle OldIrq; tDEVICECONTEXT *pDeviceContext; LIST_ENTRY *pTimerQEntry; tTIMERQENTRY *pTimer; LIST_ENTRY *pWorkerQEntry; NBT_WORK_ITEM_CONTEXT *pContext; PNBT_WORKER_THREAD_ROUTINE pCompletionRoutine; ULONG NumTimerRequests = 0; ULONG NumDelayedRequests = 0; NTSTATUS status;
//
// First remove any active Device Contexts if they are still present
//
CTESpinLock(&NbtConfig.JointLock,OldIrq); while (!IsListEmpty(&NbtConfig.DeviceContexts)) { pDeviceContext = CONTAINING_RECORD(NbtConfig.DeviceContexts.Flink, tDEVICECONTEXT, Linkage); NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, TRUE); CTESpinFree(&NbtConfig.JointLock,OldIrq); NbtDestroyDevice (pDeviceContext, FALSE); // Don't wait since the Worker threads will not fire
CTESpinLock(&NbtConfig.JointLock,OldIrq); NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_FIND_REF, TRUE); } CTESpinFree(&NbtConfig.JointLock,OldIrq);
if (pNbtSmbDevice) { NbtDestroyDevice (pNbtSmbDevice, FALSE); // Don't wait since the Worker threads will not fire
pNbtSmbDevice = NULL; }
NbtDestroyDevice (pWinsDeviceContext, FALSE); // Don't wait since the Worker threads will not fire
StopInitTimers(); KeClearEvent (&NbtConfig.TimerQLastEvent);
//
// if any other timers are active, stop them
//
CTESpinLock(&NbtConfig.JointLock,OldIrq); while (!IsListEmpty(&TimerQ.ActiveHead)) { pTimerQEntry = RemoveHeadList(&TimerQ.ActiveHead); pTimer = CONTAINING_RECORD(pTimerQEntry,tTIMERQENTRY,Linkage); InitializeListHead (&pTimer->Linkage); // in case the Linkage is touched again
IF_DBG(NBT_DEBUG_PNP_POWER) KdPrint (("CompleteTimerAndWorkerRequests[%d]: Completing request <%x>\n", NumTimerRequests, pTimer));
StopTimer (pTimer, NULL, NULL);
NumTimerRequests++; }
//
// See if there are any Timers currently executing, and if so, wait for
// them to complete
//
if (NbtConfig.NumTimersRunning) { CTESpinFree(&NbtConfig.JointLock,OldIrq); status = KeWaitForSingleObject(&NbtConfig.TimerQLastEvent, // Object to wait on.
Executive, // Reason for waiting
KernelMode, // Processor mode
FALSE, // Alertable
NULL); // Timeout
ASSERT(status == STATUS_SUCCESS); } else { CTESpinFree(&NbtConfig.JointLock,OldIrq); }
//
// See if there are any worker threads currently executing, and if so, wait for
// them to complete
//
KeClearEvent (&NbtConfig.WorkerQLastEvent); CTESpinLock(&NbtConfig.WorkerQLock,OldIrq); if (NbtConfig.NumWorkerThreadsQueued) { CTESpinFree(&NbtConfig.WorkerQLock,OldIrq);
status = KeWaitForSingleObject(&NbtConfig.WorkerQLastEvent, // Object to wait on.
Executive, // Reason for waiting
KernelMode, // Processor mode
FALSE, // Alertable
NULL); // Timeout
ASSERT(status == STATUS_SUCCESS); } else { CTESpinFree(&NbtConfig.WorkerQLock,OldIrq); }
//
// Dequeue each of the requests in the Worker Queue and complete them
//
CTESpinLock(&NbtConfig.WorkerQLock,OldIrq); while (!IsListEmpty(&NbtConfig.WorkerQList)) { pWorkerQEntry = RemoveHeadList(&NbtConfig.WorkerQList); pContext = CONTAINING_RECORD(pWorkerQEntry, NBT_WORK_ITEM_CONTEXT, NbtConfigLinkage); CTESpinFree(&NbtConfig.WorkerQLock,OldIrq); // To get back to non-raised Irql!
pCompletionRoutine = pContext->WorkerRoutine;
IF_DBG(NBT_DEBUG_PNP_POWER) KdPrint (("CompleteTimerAndWorkerRequests[%d]: Completing request <%x>\n", NumDelayedRequests, pCompletionRoutine));
(*pCompletionRoutine) (pContext->pTracker, pContext->pClientContext, pContext->ClientCompletion, pContext->pDeviceContext);
CTEMemFree ((PVOID) pContext);
NumDelayedRequests++; //
// Acquire Lock again to check if we have completed all the requests
//
CTESpinLock(&NbtConfig.WorkerQLock,OldIrq); } CTESpinFree(&NbtConfig.WorkerQLock,OldIrq);
//
// Now destroy the Devices queued on the Free'ed list since there are no more Worker threads or
// Timers pending!
//
while (!IsListEmpty(&NbtConfig.DevicesAwaitingDeletion)) { pDeviceContext = CONTAINING_RECORD(NbtConfig.DevicesAwaitingDeletion.Flink, tDEVICECONTEXT, Linkage); ASSERT (pDeviceContext->RefCount == 0);
KdPrint(("Nbt.CompleteTimerAndWorkerRequests: *** Destroying Device *** \n\t%wZ\n", &pDeviceContext->ExportName));
RemoveEntryList (&pDeviceContext->Linkage); // Remove the Device from the to-be-free'ed list
CTEMemFree (pDeviceContext->ExportName.Buffer); IoDeleteDevice((PDEVICE_OBJECT)pDeviceContext); }
ASSERT (IsListEmpty(&NbtConfig.AddressHead)); KdPrint(("Nbt.CompleteTimerAndWorkerRequests: Completed <%d> Timer and <%d> Delayed requests\n", NumTimerRequests, NumDelayedRequests));
return (NumTimerRequests + NumDelayedRequests); }
//----------------------------------------------------------------------------
VOID NbtUnload( IN PDRIVER_OBJECT DriverObject )
/*++
Routine Description:
This is the NBT driver's dispatch function for Unload requests
Arguments:
DriverObject - Pointer to driver object created by the system.
Return Value:
None
--*/
{ NTSTATUS status;
CTEPagedCode();
KdPrint(("Nbt.NbtUnload: Unloading ...\n"));
//
// After setting the following flag, no new requests should be queued on to
// the WorkerQ NbtConfig.WorkerQLastEvent will be set when all the current
// requests have finished executing
//
NbtConfig.Unloading = TRUE;
//
// Unbind fron the RAS driver if we were bound
//
NbtAcdUnbind ();
status = TdiDeregisterPnPHandlers(TdiClientHandle); IF_DBG(NBT_DEBUG_PNP_POWER) KdPrint (("NbtUnload: TdiDeregisterPnPHandlers returned <%x>\n", status));
status = TdiDeregisterProvider (TdiProviderHandle); IF_DBG(NBT_DEBUG_PNP_POWER) KdPrint (("NbtUnload: TdiDeregisterProvider returned <%x>\n", status));
//
// Dequeue each of the requests in the Timer and NbtConfigWorker Queues and complete them
//
CompleteTimerAndWorkerRequests();
//
// Now cleanup the rest of the static allocations
//
CleanupDriverEntry (5);
ASSERT (IsListEmpty (&NbtConfig.PendingNameQueries));
if (NbtConfig.pServerBindings) { CTEFreeMem (NbtConfig.pServerBindings); NbtConfig.pServerBindings = NULL; }
if (NbtConfig.pClientBindings) { CTEFreeMem (NbtConfig.pClientBindings); NbtConfig.pClientBindings = NULL; }
#ifdef _NBT_WMI_SOFTWARE_TRACING_
WPP_CLEANUP(DriverObject); #endif
}
//----------------------------------------------------------------------------
NTSTATUS NbtDispatchPnP( IN PDEVICE_OBJECT Device, IN PIRP pIrp ) { tDEVICECONTEXT *pDeviceContext; PIO_STACK_LOCATION pIrpSp, pIrpSpNext; NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; tCONNECTELE *pConnectEle; tLOWERCONNECTION *pLowerConn; KIRQL OldIrq1, OldIrq2; PDEVICE_OBJECT pTcpDeviceObject; PFILE_OBJECT pTcpFileObject; tFILE_OBJECTS *pFileObjectsContext;
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
//
// If this device was destroyed, then reject all operations on it.
// Ideally we would like the IO sub-system to guarantee that no
// requests come down on IoDeleted devices, but.....
//
pDeviceContext = (tDEVICECONTEXT *)Device; if (!NBT_REFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE)) { IF_DBG(NBT_DEBUG_DRIVER) KdPrint(("Nbt.NbtDispatchPnP: Short-Ckt request -- Device=<%x>\n", pDeviceContext)); pIrp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT); return (STATUS_INVALID_DEVICE_STATE); }
switch (pIrpSp->MinorFunction) { case IRP_MN_QUERY_DEVICE_RELATIONS: { if (pIrpSp->Parameters.QueryDeviceRelations.Type==TargetDeviceRelation) { if (PtrToUlong(pIrpSp->FileObject->FsContext2) == NBT_CONNECTION_TYPE) { // pass to transport to get the PDO
//
pConnectEle = (tCONNECTELE *)pIrpSp->FileObject->FsContext; if (NBT_VERIFY_HANDLE2 (pConnectEle, NBT_VERIFY_CONNECTION, NBT_VERIFY_CONNECTION_DOWN)) { CTESpinLock(pConnectEle, OldIrq1);
pLowerConn = (tLOWERCONNECTION *)pConnectEle->pLowerConnId; if (NBT_VERIFY_HANDLE (pLowerConn, NBT_VERIFY_LOWERCONN)) { CTESpinLock(pLowerConn, OldIrq2); NBT_REFERENCE_LOWERCONN (pLowerConn, REF_LOWC_QUERY_DEVICE_REL); CTESpinFree(pLowerConn, OldIrq2); CTESpinFree(pConnectEle, OldIrq1);
if ((pTcpFileObject = pLowerConn->pFileObject) && (pTcpDeviceObject = IoGetRelatedDeviceObject (pLowerConn->pFileObject))) { //
// Simply pass the Irp on by to the Transport, and let it
// fill in the info
//
pIrpSpNext = IoGetNextIrpStackLocation (pIrp); *pIrpSpNext = *pIrpSp;
IoSetCompletionRoutine (pIrp, NULL, NULL, FALSE, FALSE, FALSE); pIrpSpNext->FileObject = pTcpFileObject; pIrpSpNext->DeviceObject = pTcpDeviceObject;
status = IoCallDriver(pTcpDeviceObject, pIrp);
NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE); return status; } else { status = STATUS_INVALID_HANDLE; } NBT_DEREFERENCE_LOWERCONN (pLowerConn, REF_LOWC_QUERY_DEVICE_REL, FALSE); } else { status = STATUS_CONNECTION_INVALID; CTESpinFree(pConnectEle, OldIrq1); } } else { status = STATUS_INVALID_HANDLE; } } else if ( PtrToUlong(pIrpSp->FileObject->FsContext2) == NBT_ADDRESS_TYPE) { CTESpinLock(&NbtConfig.JointLock,OldIrq1);
if ((pDeviceContext->IpAddress) && (pFileObjectsContext = pDeviceContext->pFileObjects) && (pTcpFileObject = pFileObjectsContext->pDgramFileObject) && (pTcpDeviceObject = pFileObjectsContext->pDgramDeviceObject)) { pFileObjectsContext->RefCount++; // Dereferenced after the Query has completed
//
// pass the Irp to transport to get the PDO
//
pIrpSpNext = IoGetNextIrpStackLocation (pIrp); *pIrpSpNext = *pIrpSp;
IoSetCompletionRoutine (pIrp, NULL, NULL, FALSE, FALSE, FALSE); pIrpSpNext->FileObject = pTcpFileObject; pIrpSpNext->DeviceObject = pTcpDeviceObject;
CTESpinFree(&NbtConfig.JointLock,OldIrq1); status = IoCallDriver(pTcpDeviceObject, pIrp);
CTESpinLock(&NbtConfig.JointLock,OldIrq1); if (--pFileObjectsContext->RefCount == 0) { CTEQueueForNonDispProcessing(DelayedNbtCloseFileHandles, NULL, pFileObjectsContext, NULL, NULL, TRUE); }
NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, TRUE); CTESpinFree(&NbtConfig.JointLock,OldIrq1);
return status; } else { CTESpinFree(&NbtConfig.JointLock,OldIrq1); status = STATUS_INVALID_DEVICE_REQUEST; } } else { ASSERT (0); } }
break; }
default: { break; } }
ReturnIrp(pIrp, status); NBT_DEREFERENCE_DEVICE (pDeviceContext, REF_DEV_DISPATCH, FALSE);
return status; }
//----------------------------------------------------------------------------
PFILE_FULL_EA_INFORMATION FindInEA( IN PFILE_FULL_EA_INFORMATION start, IN PCHAR wanted )
/*++
Routine Description:
This function check for the "Wanted" string in the Ea structure and returns a pointer to the extended attribute structure representing the given extended attribute name.
Arguments:
device - ptr to device object for target device pIrp - ptr to I/O request packet
Return Value:
pointer to the extended attribute structure, or NULL if not found.
--*/
{ PFILE_FULL_EA_INFORMATION eabuf;
CTEPagedCode();
//
// Bug # 225668: advance eabug ptr by typecasting it to UCHAR
//
for (eabuf = start; eabuf; eabuf = (PFILE_FULL_EA_INFORMATION) ((PUCHAR)eabuf + eabuf->NextEntryOffset)) { if (strncmp(eabuf->EaName,wanted,eabuf->EaNameLength) == 0) { return eabuf; }
if (eabuf->NextEntryOffset == 0) { return((PFILE_FULL_EA_INFORMATION) NULL); } } return((PFILE_FULL_EA_INFORMATION) NULL);
} // FindEA
//----------------------------------------------------------------------------
VOID ReturnIrp( IN PIRP pIrp, IN int status )
/*++
Routine Description:
This function completes an IRP, and arranges for return parameters, if any, to be copied.
Although somewhat a misnomer, this function is named after a similar function in the SpiderSTREAMS emulator.
Arguments:
pIrp - pointer to the IRP to complete status - completion status of the IRP
Return Value:
number of bytes copied back to the user.
--*/
{ KIRQL oldlevel; CCHAR priboost;
//
// pIrp->IoStatus.Information is meaningful only for STATUS_SUCCESS
//
// set the Irps cancel routine to null or the system may bugcheck
// with a bug code of CANCEL_STATE_IN_COMPLETED_IRP
//
// refer to IoCancelIrp() ..\ntos\io\iosubs.c
//
IoAcquireCancelSpinLock(&oldlevel); IoSetCancelRoutine(pIrp,NULL); IoReleaseCancelSpinLock(oldlevel);
pIrp->IoStatus.Status = status;
priboost = (CCHAR) ((status == STATUS_SUCCESS) ? IO_NETWORK_INCREMENT : IO_NO_INCREMENT);
IoCompleteRequest(pIrp, priboost);
return;
} //----------------------------------------------------------------------------
VOID MakePending( IN PIRP pIrp )
/*++
Routine Description:
This function marks an irp pending and sets the correct status.
Arguments:
pIrp - pointer to the IRP to complete status - completion status of the IRP
Return Value:
--*/
{ IoMarkIrpPending(pIrp); pIrp->IoStatus.Status = STATUS_PENDING; pIrp->IoStatus.Information = 0;
}
#ifdef _NBT_WMI_SOFTWARE_TRACING_
int nbtlog_strnlen(char *p, int n) { int i;
for (i = 0; (i < n) && *p; i++, p++) { }
return i; } #endif
|