From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/nw/rdr/pid.c | 454 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 454 insertions(+) create mode 100644 private/nw/rdr/pid.c (limited to 'private/nw/rdr/pid.c') diff --git a/private/nw/rdr/pid.c b/private/nw/rdr/pid.c new file mode 100644 index 000000000..375fba553 --- /dev/null +++ b/private/nw/rdr/pid.c @@ -0,0 +1,454 @@ +/*++ + +Copyright (c) 1993 Microsoft Corporation + +Module Name: + + Pid.c + +Abstract: + + This module implements the routines for the NetWare + redirector to map 32 bit NT pid values to unique 8 bit + NetWare values. + + The technique used is to maintain a table of up to 256 entries. + The index of each entry corresponds directly to the 8 bit pid + values. Each table entry contains the 32 bit pid of the process + that has obtained exclusive access to the pid and the number of + handles opened by that process to this server. + + This architecture limits the number of processes on the NT machine + communicating with any one server to 256. + + Note: This package assumes that the size that the PidTable grows is + a factor of 256-. This ensures that running out of + valid entries in the table will occur when 256 entries have been + allocated. + +Author: + + Colin Watson [ColinW] 02-Mar-1993 + +Revision History: + +--*/ + +#include "Procs.h" + + +// +// The debug trace level +// + +#define Dbg (DEBUG_TRACE_CREATE) + +#define INITIAL_MAPPID_ENTRIES 8 +#define MAPPID_INCREASE 8 +#define MAX_PIDS 256 + +#define PID_FLAG_EOJ_REQUIRED 0x00000001 // EOJ required for this PID + +typedef struct _NW_PID_TABLE_ENTRY { + ULONG Pid32; + ULONG ReferenceCount; + ULONG Flags; +} NW_PID_TABLE_ENTRY, *PNW_PID_TABLE_ENTRY; + +typedef struct _NW_PID_TABLE { + + // + // Type and size of this record (must be NW_NTC_PID) + // + + NODE_TYPE_CODE NodeTypeCode; + NODE_BYTE_SIZE NodeByteSize; + + int ValidEntries; + NW_PID_TABLE_ENTRY PidTable[0]; +} NW_PID_TABLE, *PNW_PID_TABLE; + + + +PNW_PID_TABLE PidTable; +ERESOURCE PidResource; + +#ifdef ALLOC_PRAGMA +#pragma alloc_text( PAGE, NwInitializePidTable ) +#pragma alloc_text( PAGE, NwUninitializePidTable ) +#pragma alloc_text( PAGE, NwMapPid ) +#pragma alloc_text( PAGE, NwSetEndOfJobRequired ) +#pragma alloc_text( PAGE, NwUnmapPid ) +#endif + + +BOOLEAN +NwInitializePidTable( + VOID + ) +/*++ + +Routine Description: + + Creates a table for the MapPid package. The initial table has room for + INITIAL_MAPPID_ENTRIES entries. + +Arguments: + + +Return Value: + + NTSTATUS of result. + +--*/ + +{ + int i; + PNW_PID_TABLE TempPid = + ALLOCATE_POOL( PagedPool, + FIELD_OFFSET( NW_PID_TABLE, PidTable[0] ) + + (sizeof(NW_PID_TABLE_ENTRY) * INITIAL_MAPPID_ENTRIES )); + + PAGED_CODE(); + + if (TempPid == NULL) { + return( FALSE ); + } + + TempPid->NodeByteSize = FIELD_OFFSET( NW_PID_TABLE, PidTable[0] ) + + (sizeof(NW_PID_TABLE_ENTRY) * INITIAL_MAPPID_ENTRIES ); + + TempPid->NodeTypeCode = NW_NTC_PID; + + TempPid->ValidEntries = INITIAL_MAPPID_ENTRIES; + + // + // Set the ref count for all PIDs to 0, except for pid 0. We + // do this so that we don't allocate PID 0. + // + + TempPid->PidTable[0].ReferenceCount = 1; + for (i = 1; i < INITIAL_MAPPID_ENTRIES ; i++ ) { + TempPid->PidTable[i].ReferenceCount = 0; + } + + PidTable = TempPid; + ExInitializeResource( &PidResource ); +} + +VOID +NwUninitializePidTable( + VOID + ) +/*++ + +Routine Description: + + Deletes a table created by the MapPid package. + +Arguments: + + Pid - Supplies the table to be deleted. + +Return Value: + +--*/ + +{ +#ifdef NWDBG + int i; +#endif + + PAGED_CODE(); + +#ifdef NWDBG + ASSERT(PidTable->NodeTypeCode == NW_NTC_PID); + ASSERT(PidTable->PidTable[0].ReferenceCount == 1); + + for (i = 1; i < PidTable->ValidEntries; i++ ) { + ASSERT(PidTable->PidTable[i].ReferenceCount == 0); + } +#endif + + FREE_POOL( PidTable ); + + ExDeleteResource( &PidResource ); + return; + +} + +NTSTATUS +NwMapPid( + IN ULONG Pid32, + OUT PUCHAR Pid8 + ) +/*++ + +Routine Description: + + Obtain an 8 bit unique pid for this process. Either use a previosly + assigned pid for this process or assign an unused value. + +Arguments: + + Pid - Supplies the datastructure used by MapPid to assign pids for + this server. + + Pid32 - Supplies the NT pid to be mapped. + + Pid8 - Returns the 8 bit Pid. + +Return Value: + + NTSTATUS of result. + +--*/ +{ + int i; + int FirstFree = -1; + int NewEntries; + PNW_PID_TABLE TempPid; + + PAGED_CODE(); + + ExAcquireResourceExclusive( &PidResource, TRUE ); + + // DebugTrace(0, Dbg, "NwMapPid for %08lx\n", Pid32); + + for (i=0; i < (PidTable)->ValidEntries ; i++ ) { + + if ((PidTable)->PidTable[i].Pid32 == Pid32) { + + // + // This process already has an 8 bit pid value assigned. + // Increment the reference and return. + // + + (PidTable)->PidTable[i].ReferenceCount++; + *Pid8 = i; + + // DebugTrace(0, Dbg, "NwMapPid found %08lx\n", (DWORD)i); + + ExReleaseResource( &PidResource ); + ASSERT( *Pid8 != 0 ); + return( STATUS_SUCCESS ); + } + + if ((FirstFree == -1) && + ((PidTable)->PidTable[i].ReferenceCount == 0)) { + + // + // i is the lowest free 8 bit Pid. + // + + FirstFree = i; + } + } + + // + // This process does not have a pid assigned. + // + + if ( FirstFree != -1 ) { + + // + // We had an empty slot so assign it to this process. + // + + (PidTable)->PidTable[FirstFree].ReferenceCount++; + (PidTable)->PidTable[FirstFree].Pid32 = Pid32; + *Pid8 = FirstFree; + + DebugTrace(0, DEBUG_TRACE_ICBS, "NwMapPid maps %08lx\n", (DWORD)FirstFree); + + ExReleaseResource( &PidResource ); + ASSERT( *Pid8 != 0 ); + return( STATUS_SUCCESS ); + } + + if ( (PidTable)->ValidEntries == MAX_PIDS ) { + + // + // We've run out of 8 bit pids. + // + + ExReleaseResource( &PidResource ); + +#ifdef NWDBG + // + // temporary code to find the PID leak. BUGBUG + // + DumpIcbs() ; + ASSERT(FALSE) ; +#endif + + return(STATUS_TOO_MANY_OPENED_FILES); + } + + // + // Grow the table by MAPPID_INCREASE entries. + // + + NewEntries = (PidTable)->ValidEntries + MAPPID_INCREASE; + + TempPid = + ALLOCATE_POOL( PagedPool, + FIELD_OFFSET( NW_PID_TABLE, PidTable[0] ) + + (sizeof(NW_PID_TABLE_ENTRY) * NewEntries )); + + if (TempPid == NULL) { + ExReleaseResource( &PidResource ); + return( STATUS_INSUFFICIENT_RESOURCES ); + } + + RtlMoveMemory( + TempPid, + (PidTable), + FIELD_OFFSET( NW_PID_TABLE, PidTable[0] ) + + (sizeof(NW_PID_TABLE_ENTRY) * (PidTable)->ValidEntries )); + + TempPid->NodeByteSize = FIELD_OFFSET( NW_PID_TABLE, PidTable[0] ) + + (sizeof(NW_PID_TABLE_ENTRY) * NewEntries ); + + for ( i = (PidTable)->ValidEntries; i < NewEntries ; i++ ) { + TempPid->PidTable[i].ReferenceCount = 0; + } + + TempPid->ValidEntries = NewEntries; + + // + // Save the index of the first free entry. + // + + i = (PidTable)->ValidEntries; + + // + // The new table is initialized. Free up the old table and return + // the first of the new entries. + // + + FREE_POOL(PidTable); + PidTable = TempPid; + + (PidTable)->PidTable[i].ReferenceCount = 1; + (PidTable)->PidTable[i].Pid32 = Pid32; + *Pid8 = i; + + DebugTrace(0, DEBUG_TRACE_ICBS, "NwMapPid grows & maps %08lx\n", (DWORD)i); + + ExReleaseResource( &PidResource ); + return( STATUS_SUCCESS ); +} + +VOID +NwSetEndOfJobRequired( + IN UCHAR Pid8 + ) +/*++ + +Routine Description: + + Mark a PID as must send End Of Job when the pid reference count + reaches zero. + +Arguments: + + Pid8 - The 8 bit Pid to mark. + +Return Value: + + None. + +--*/ +{ + PAGED_CODE(); + + ASSERT( Pid8 != 0 ); + + // DebugTrace(0, Dbg, "NwSetEndofJob for %08lx\n", (DWORD)Pid8); + SetFlag( PidTable->PidTable[Pid8].Flags, PID_FLAG_EOJ_REQUIRED ); + return; +} + + +VOID +NwUnmapPid( + IN UCHAR Pid8, + IN PIRP_CONTEXT IrpContext OPTIONAL + ) +/*++ + +Routine Description: + + This routine dereference an 8 bit PID. If the reference count reaches + zero and this PID is marked End Of Job required, this routine will + also send an EOJ NCP for this PID. + +Arguments: + + Pid8 - The 8 bit Pid to mark. + + IrpContext - The IrpContext for the IRP in progress. + +Return Value: + + None. + +--*/ +{ + BOOLEAN EndOfJob; + + PAGED_CODE(); + + ASSERT( Pid8 != 0 ); + + // DebugTrace(0, Dbg, "NwUnmapPid %08lx\n", (DWORD)Pid8); + if ( BooleanFlagOn( PidTable->PidTable[Pid8].Flags, PID_FLAG_EOJ_REQUIRED ) && + IrpContext != NULL ) { + + // + // The End of job flag is set. Obtain a position at the front of + // the SCB queue, so that if we need to set an EOJ NCP, we needn't + // wait for the SCB queue while holding the PID table lock. + // + + EndOfJob = TRUE; + NwAppendToQueueAndWait( IrpContext ); + } else { + EndOfJob = FALSE; + } + + // + // The PidResource lock controls the reference counts. + // + + ExAcquireResourceExclusive( &PidResource, TRUE ); + + if ( --(PidTable)->PidTable[Pid8].ReferenceCount == 0 ) { + + // + // Done with this PID, send an EOJ if necessary. + // + + // DebugTrace(0, Dbg, "NwUnmapPid (ref=0) %08lx\n", (DWORD)Pid8); + (PidTable)->PidTable[Pid8].Flags = 0; + (PidTable)->PidTable[Pid8].Pid32 = 0; + + if ( EndOfJob ) { + (VOID) ExchangeWithWait( + IrpContext, + SynchronousResponseCallback, + "F-", + NCP_END_OF_JOB ); + } + } + + if ( EndOfJob ) { + NwDequeueIrpContext( IrpContext, FALSE ); + } + + ASSERT((PidTable)->PidTable[Pid8].ReferenceCount>=0); + + ExReleaseResource( &PidResource ); +} + -- cgit v1.2.3