373 lines
15 KiB
C
373 lines
15 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1989 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
nb.h
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Private include file for the NB (NetBIOS) component of the NTOS project.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Colin Watson (ColinW) 13-Mar-1991
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#ifndef _NB_
|
||
|
#define _NB_
|
||
|
|
||
|
#include <ntifs.h>
|
||
|
|
||
|
//#include <ntos.h>
|
||
|
#include <windef.h>
|
||
|
#include <status.h>
|
||
|
#include <tdikrnl.h> // Transport Driver Interface.
|
||
|
#include <nb30.h>
|
||
|
#include <nb30p.h>
|
||
|
#include <netpnp.h>
|
||
|
|
||
|
#include "nbconst.h" // private NETBEUI constants.
|
||
|
#include "nbtypes.h" // private NETBEUI types.
|
||
|
#include "nbdebug.h" // private NETBEUI debug defines.
|
||
|
#include "nbprocs.h" // private NETBEUI function prototypes.
|
||
|
|
||
|
#ifdef MEMPRINT
|
||
|
#include "memprint.h" // drt's memory debug print
|
||
|
#endif
|
||
|
|
||
|
extern PEPROCESS NbFspProcess;
|
||
|
|
||
|
|
||
|
extern ULONG g_ulMaxLana;
|
||
|
|
||
|
extern LANA_ENUM g_leLanaEnum;
|
||
|
|
||
|
extern PUNICODE_STRING g_pusActiveDeviceList;
|
||
|
|
||
|
extern HANDLE g_hBindHandle;
|
||
|
|
||
|
extern UNICODE_STRING g_usRegistryPath;
|
||
|
|
||
|
extern LIST_ENTRY g_leFCBList;
|
||
|
|
||
|
extern ERESOURCE g_erGlobalLock;
|
||
|
|
||
|
|
||
|
|
||
|
#if DBG
|
||
|
#define PAGED_DBG 1
|
||
|
#endif
|
||
|
#ifdef PAGED_DBG
|
||
|
#undef PAGED_CODE
|
||
|
#define PAGED_CODE() \
|
||
|
struct { ULONG bogus; } ThisCodeCantBePaged; \
|
||
|
ThisCodeCantBePaged; \
|
||
|
if (KeGetCurrentIrql() > APC_LEVEL) { \
|
||
|
KdPrint(( "NETBIOS: Pageable code called at IRQL %d. File %s, Line %d\n", KeGetCurrentIrql(), __FILE__, __LINE__ )); \
|
||
|
ASSERT(FALSE); \
|
||
|
}
|
||
|
#define PAGED_CODE_CHECK() if (ThisCodeCantBePaged) ;
|
||
|
extern ULONG ThisCodeCantBePaged;
|
||
|
#else
|
||
|
#define PAGED_CODE_CHECK()
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#if PAGED_DBG
|
||
|
#define ACQUIRE_SPIN_LOCK(a, b) { \
|
||
|
PAGED_CODE_CHECK(); \
|
||
|
KeAcquireSpinLock(a, b); \
|
||
|
}
|
||
|
#define RELEASE_SPIN_LOCK(a, b) { \
|
||
|
PAGED_CODE_CHECK(); \
|
||
|
KeReleaseSpinLock(a, b); \
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
#define ACQUIRE_SPIN_LOCK(a, b) KeAcquireSpinLock(a, b)
|
||
|
#define RELEASE_SPIN_LOCK(a, b) KeReleaseSpinLock(a, b)
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Macro for filling in the status for an NCB.
|
||
|
//
|
||
|
|
||
|
#define NCB_COMPLETE( _pdncb, _code ) { \
|
||
|
UCHAR _internal_copy = _code; \
|
||
|
IF_NBDBG (NB_DEBUG_COMPLETE) { \
|
||
|
NbPrint (("%s %d NCB_COMPLETE: %lx, %lx\n" , \
|
||
|
__FILE__, __LINE__, _pdncb, _internal_copy )); \
|
||
|
} \
|
||
|
if (((PDNCB)_pdncb)->ncb_retcode == NRC_PENDING) { \
|
||
|
((PDNCB)_pdncb)->ncb_retcode = _internal_copy; \
|
||
|
} else { \
|
||
|
IF_NBDBG (NB_DEBUG_NCBS) { \
|
||
|
NbPrint((" Status already set!!!!!!!!\n")); \
|
||
|
IF_NBDBG (NB_DEBUG_NCBSBRK) { \
|
||
|
DbgBreakPoint(); \
|
||
|
} \
|
||
|
} \
|
||
|
} \
|
||
|
IF_NBDBG (NB_DEBUG_NCBS) { \
|
||
|
NbDisplayNcb( (PDNCB)_pdncb ); \
|
||
|
} \
|
||
|
IF_NBDBG (NB_DEBUG_COMPLETE) \
|
||
|
{ \
|
||
|
if ( ( (_code) == NRC_BRIDGE ) || \
|
||
|
( (_code) == NRC_ENVNOTDEF ) ) \
|
||
|
{ \
|
||
|
DbgPrint("\n[NETBIOS]: NCB_COMPLETE : File %s," \
|
||
|
" line %d\n", __FILE__, __LINE__); \
|
||
|
DbgPrint("LANA %x, Command %x ", \
|
||
|
((PDNCB)_pdncb)->ncb_lana_num, \
|
||
|
((PDNCB)_pdncb)->ncb_command ); \
|
||
|
DbgPrint("Return %x, Cmplt %x\n", \
|
||
|
((PDNCB)_pdncb)->ncb_retcode, \
|
||
|
((PDNCB)_pdncb)->ncb_cmd_cplt ); \
|
||
|
NbFormattedDump( ((PDNCB)_pdncb)->ncb_name, 16 ); \
|
||
|
NbFormattedDump( ((PDNCB)_pdncb)->ncb_callname, 16 ); \
|
||
|
} \
|
||
|
else if ( ( ( (_code) == NRC_DUPNAME ) || \
|
||
|
( (_code) == NRC_INUSE ) ) && \
|
||
|
( ((PDNCB)_pdncb)-> ncb_command != NCBADDGRNAME ) ) \
|
||
|
{ \
|
||
|
DbgPrint("\n[NETBIOS]: NCB_COMPLETE : DUPNAME : File %s," \
|
||
|
"line %d\n", __FILE__, __LINE__); \
|
||
|
DbgPrint("LANA %x, Command %x ", \
|
||
|
((PDNCB)_pdncb)->ncb_lana_num, \
|
||
|
((PDNCB)_pdncb)->ncb_command ); \
|
||
|
DbgPrint("Return %x, Cmplt %x\n", \
|
||
|
((PDNCB)_pdncb)->ncb_retcode, \
|
||
|
((PDNCB)_pdncb)->ncb_cmd_cplt ); \
|
||
|
NbFormattedDump( ((PDNCB)_pdncb)->ncb_name, 16 ); \
|
||
|
if ( ((PDNCB)_pdncb)->ncb_name[15] == 0x3) \
|
||
|
{ \
|
||
|
DbgPrint("Messenger Name, dup ok\n"); \
|
||
|
} \
|
||
|
else \
|
||
|
{ \
|
||
|
IF_NBDBG(NB_DEBUG_NCBSBRK) DbgBreakPoint(); \
|
||
|
} \
|
||
|
} \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
|
||
|
//++
|
||
|
//
|
||
|
// VOID
|
||
|
// NbCompleteRequest (
|
||
|
// IN PIRP Irp,
|
||
|
// IN NTSTATUS Status
|
||
|
// );
|
||
|
//
|
||
|
// Routine Description:
|
||
|
//
|
||
|
// This routine is used to complete an IRP with the indicated
|
||
|
// status. It does the necessary raise and lower of IRQL.
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Irp - Supplies a pointer to the Irp to complete
|
||
|
//
|
||
|
// Status - Supplies the completion status for the Irp
|
||
|
//
|
||
|
// Return Value:
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
//--
|
||
|
#define NbCompleteRequest(IRP,STATUS) { \
|
||
|
(IRP)->IoStatus.Status = (STATUS); \
|
||
|
IoCompleteRequest( (IRP), IO_NETWORK_INCREMENT ); \
|
||
|
}
|
||
|
|
||
|
|
||
|
#if defined(_WIN64)
|
||
|
#define NbCheckAndCompleteIrp32(Irp) \
|
||
|
{ \
|
||
|
if (IoIs32bitProcess(Irp) == TRUE) \
|
||
|
{ \
|
||
|
NbCompleteIrp32(Irp); \
|
||
|
} \
|
||
|
}
|
||
|
#else
|
||
|
#define NbCheckAndCompleteIrp32(Irp)
|
||
|
#endif
|
||
|
//
|
||
|
// Normally the driver wants to prohibit other threads making
|
||
|
// requests (using a resource) and also prevent indication routines
|
||
|
// being called (using a spinlock).
|
||
|
//
|
||
|
// To do this LOCK and UNLOCK are used. IO system calls cannot
|
||
|
// be called with a spinlock held so sometimes the ordering becomes
|
||
|
// LOCK, UNLOCK_SPINLOCK <do IO calls> UNLOCK_RESOURCE.
|
||
|
//
|
||
|
|
||
|
#define LOCK(PFCB, OLDIRQL) { \
|
||
|
IF_NBDBG (NB_DEBUG_LOCKS) { \
|
||
|
NbPrint (("%s %d LOCK: %lx %lx %lx\n" , \
|
||
|
__FILE__, __LINE__, (PFCB) )); \
|
||
|
} \
|
||
|
KeEnterCriticalRegion(); \
|
||
|
ExAcquireResourceExclusiveLite( &(PFCB)->Resource, TRUE); \
|
||
|
ACQUIRE_SPIN_LOCK( &(PFCB)->SpinLock, &(OLDIRQL)); \
|
||
|
}
|
||
|
|
||
|
#define LOCK_RESOURCE(PFCB) { \
|
||
|
IF_NBDBG (NB_DEBUG_LOCKS) { \
|
||
|
NbPrint(("%s %d LOCK_RESOURCE: %lx, %lx %lx\n" , \
|
||
|
__FILE__, __LINE__, (PFCB))); \
|
||
|
} \
|
||
|
KeEnterCriticalRegion(); \
|
||
|
ExAcquireResourceExclusiveLite( &(PFCB)->Resource, TRUE); \
|
||
|
}
|
||
|
|
||
|
#define LOCK_GLOBAL() { \
|
||
|
IF_NBDBG (NB_DEBUG_LOCKS) { \
|
||
|
NbPrint(("%s %d LOCK_GLOBAL: %lx, %lx\n" , \
|
||
|
__FILE__, __LINE__)); \
|
||
|
} \
|
||
|
KeEnterCriticalRegion(); \
|
||
|
ExAcquireResourceExclusiveLite( &g_erGlobalLock, TRUE); \
|
||
|
}
|
||
|
|
||
|
#define LOCK_STOP() { \
|
||
|
IF_NBDBG (NB_DEBUG_LOCKS) { \
|
||
|
NbPrint(("%s %d LOCK_STOP: %lx, %lx\n" , \
|
||
|
__FILE__, __LINE__)); \
|
||
|
} \
|
||
|
KeEnterCriticalRegion(); \
|
||
|
ExAcquireResourceExclusiveLite( &g_erStopLock, TRUE); \
|
||
|
}
|
||
|
|
||
|
|
||
|
#define LOCK_SPINLOCK(PFCB, OLDIRQL) { \
|
||
|
IF_NBDBG (NB_DEBUG_LOCKS) { \
|
||
|
NbPrint( ("%s %d LOCK_SPINLOCK: %lx %lx %lx\n" , \
|
||
|
__FILE__, __LINE__, (PFCB))); \
|
||
|
} \
|
||
|
ACQUIRE_SPIN_LOCK( &(PFCB)->SpinLock, &(OLDIRQL)); \
|
||
|
}
|
||
|
|
||
|
#define UNLOCK(PFCB, OLDIRQL) { \
|
||
|
UNLOCK_SPINLOCK( PFCB, OLDIRQL ); \
|
||
|
UNLOCK_RESOURCE( PFCB ); \
|
||
|
}
|
||
|
|
||
|
#define UNLOCK_GLOBAL() { \
|
||
|
IF_NBDBG (NB_DEBUG_LOCKS) { \
|
||
|
NbPrint(("%s %d UNLOCK_GLOBAL: %lx, %lx\n" , \
|
||
|
__FILE__, __LINE__)); \
|
||
|
} \
|
||
|
ExReleaseResourceLite( &g_erGlobalLock ); \
|
||
|
KeLeaveCriticalRegion(); \
|
||
|
}
|
||
|
|
||
|
|
||
|
#define UNLOCK_STOP() { \
|
||
|
IF_NBDBG (NB_DEBUG_LOCKS) { \
|
||
|
NbPrint(("%s %d UNLOCK_STOP: %lx, %lx\n" , \
|
||
|
__FILE__, __LINE__)); \
|
||
|
} \
|
||
|
ExReleaseResourceLite( &g_erStopLock ); \
|
||
|
KeLeaveCriticalRegion(); \
|
||
|
}
|
||
|
|
||
|
#define UNLOCK_RESOURCE(PFCB) { \
|
||
|
IF_NBDBG (NB_DEBUG_LOCKS) { \
|
||
|
NbPrint( ("%s %d RESOURCE: %lx, %lx %lx\n" , \
|
||
|
__FILE__, __LINE__, (PFCB) )); \
|
||
|
} \
|
||
|
ExReleaseResourceLite( &(PFCB)->Resource ); \
|
||
|
KeLeaveCriticalRegion(); \
|
||
|
}
|
||
|
|
||
|
#define UNLOCK_SPINLOCK(PFCB, OLDIRQL) { \
|
||
|
IF_NBDBG (NB_DEBUG_LOCKS) { \
|
||
|
NbPrint( ("%s %d SPINLOCK: %lx, %lx %lx %lx\n" , \
|
||
|
__FILE__, __LINE__, (PFCB), (OLDIRQL))); \
|
||
|
} \
|
||
|
RELEASE_SPIN_LOCK( &(PFCB)->SpinLock, (OLDIRQL) ); \
|
||
|
}
|
||
|
|
||
|
|
||
|
// Assume resource held when modifying CurrentUsers
|
||
|
#define REFERENCE_AB(PAB) { \
|
||
|
(PAB)->CurrentUsers++; \
|
||
|
IF_NBDBG (NB_DEBUG_ADDRESS) { \
|
||
|
NbPrint( ("ReferenceAb %s %d: %lx, NewCount:%lx\n", \
|
||
|
__FILE__, __LINE__, \
|
||
|
PAB, \
|
||
|
(PAB)->CurrentUsers)); \
|
||
|
NbFormattedDump( (PUCHAR)&(PAB)->Name, sizeof(NAME) ); \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
// Resource must be held before dereferencing the address block
|
||
|
|
||
|
#define DEREFERENCE_AB(PPAB) { \
|
||
|
IF_NBDBG (NB_DEBUG_ADDRESS) { \
|
||
|
NbPrint( ("DereferenceAb %s %d: %lx, OldCount:%lx\n", \
|
||
|
__FILE__, __LINE__, *PPAB, (*PPAB)->CurrentUsers)); \
|
||
|
NbFormattedDump( (PUCHAR)&(*PPAB)->Name, sizeof(NAME) );\
|
||
|
} \
|
||
|
(*PPAB)->CurrentUsers--; \
|
||
|
if ( (*PPAB)->CurrentUsers == 0 ) { \
|
||
|
if ( (*PPAB)->AddressHandle != NULL ) { \
|
||
|
IF_NBDBG (NB_DEBUG_ADDRESS) { \
|
||
|
NbPrint( ("DereferenceAb: Closing: %lx\n", \
|
||
|
(*PPAB)->AddressHandle)); \
|
||
|
} \
|
||
|
NbAddressClose( (*PPAB)->AddressHandle, \
|
||
|
(*PPAB)->AddressObject ); \
|
||
|
(*PPAB)->AddressHandle = NULL; \
|
||
|
} \
|
||
|
(*PPAB)->pLana->AddressCount--; \
|
||
|
ExFreePool( *PPAB ); \
|
||
|
*PPAB = NULL; \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// The following macros are used to establish the semantics needed
|
||
|
// to do a return from within a try-finally clause. As a rule every
|
||
|
// try clause must end with a label call try_exit. For example,
|
||
|
//
|
||
|
// try {
|
||
|
// :
|
||
|
// :
|
||
|
//
|
||
|
// try_exit: NOTHING;
|
||
|
// } finally {
|
||
|
//
|
||
|
// :
|
||
|
// :
|
||
|
// }
|
||
|
//
|
||
|
// Every return statement executed inside of a try clause should use the
|
||
|
// try_return macro. If the compiler fully supports the try-finally construct
|
||
|
// then the macro should be
|
||
|
//
|
||
|
// #define try_return(S) { return(S); }
|
||
|
//
|
||
|
// If the compiler does not support the try-finally construct then the macro
|
||
|
// should be
|
||
|
//
|
||
|
#define try_return(S) { S; goto try_exit; }
|
||
|
|
||
|
#define NETBIOS_STOPPING 1
|
||
|
#define NETBIOS_RUNNING 2;
|
||
|
|
||
|
|
||
|
#endif // def _NB_
|