NT4/private/nw/rdr/pid.c
2020-09-30 17:12:29 +02:00

455 lines
9.5 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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 );
}