summaryrefslogtreecommitdiffstats
path: root/private/nw/rdr/pid.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/rdr/pid.c')
-rw-r--r--private/nw/rdr/pid.c454
1 files changed, 454 insertions, 0 deletions
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-<initial entries>. 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 );
+}
+