211 lines
7.0 KiB
C
211 lines
7.0 KiB
C
/*++
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
lpcinit.c
|
|
|
|
Abstract:
|
|
Initialization module for the LPC subcomponent of NTOS
|
|
|
|
Author:
|
|
Steve Wood (stevewo) 15-May-1989
|
|
--*/
|
|
|
|
#include "lpcp.h"
|
|
|
|
// The following two object types are defined system wide to handle lpc ports
|
|
POBJECT_TYPE LpcPortObjectType;
|
|
POBJECT_TYPE LpcWaitablePortObjectType;
|
|
|
|
// This is the default access mask mapping for lpc port objects
|
|
GENERIC_MAPPING LpcpPortMapping = {
|
|
READ_CONTROL | PORT_CONNECT,
|
|
DELETE | PORT_CONNECT,
|
|
0,
|
|
PORT_ALL_ACCESS
|
|
};
|
|
|
|
|
|
LPC_MUTEX LpcpLock;// This lock is used to protect practically everything in lpc
|
|
|
|
// The following array of strings is used to debugger purposes and the values correspond to the Port message types defined in ntlpcapi.h
|
|
#if ENABLE_LPC_TRACING
|
|
char *LpcpMessageTypeName[] = {
|
|
"UNUSED_MSG_TYPE",
|
|
"LPC_REQUEST",
|
|
"LPC_REPLY",
|
|
"LPC_DATAGRAM",
|
|
"LPC_LOST_REPLY",
|
|
"LPC_PORT_CLOSED",
|
|
"LPC_CLIENT_DIED",
|
|
"LPC_EXCEPTION",
|
|
"LPC_DEBUG_EVENT",
|
|
"LPC_ERROR_EVENT",
|
|
"LPC_CONNECTION_REQUEST"
|
|
};
|
|
#endif // ENABLE_LPC_TRACING
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,LpcInitSystem)
|
|
#endif
|
|
|
|
|
|
BOOLEAN LpcInitSystem (VOID)
|
|
/*++
|
|
Routine Description:
|
|
This function performs the system initialization for the LPC package.
|
|
LPC stands for Local Inter-Process Communication.
|
|
Return Value:
|
|
TRUE if successful and FALSE if an error occurred.
|
|
The following errors can occur:
|
|
- insufficient memory
|
|
--*/
|
|
{
|
|
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
|
UNICODE_STRING PortTypeName;
|
|
ULONG ZoneElementSize;
|
|
NTSTATUS Status;
|
|
|
|
LpcpInitializeLpcpLock();// Initialize our global lpc lock
|
|
|
|
// Create the object type for the port object
|
|
RtlInitUnicodeString( &PortTypeName, L"Port" );
|
|
RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ));
|
|
ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer );
|
|
ObjectTypeInitializer.GenericMapping = LpcpPortMapping;
|
|
ObjectTypeInitializer.MaintainTypeList = TRUE;
|
|
ObjectTypeInitializer.PoolType = PagedPool;
|
|
ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof( LPCP_PORT_OBJECT );
|
|
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( LPCP_NONPAGED_PORT_QUEUE );
|
|
ObjectTypeInitializer.InvalidAttributes = OBJ_VALID_ATTRIBUTES ^ PORT_VALID_OBJECT_ATTRIBUTES;
|
|
ObjectTypeInitializer.ValidAccessMask = PORT_ALL_ACCESS;
|
|
ObjectTypeInitializer.CloseProcedure = LpcpClosePort;
|
|
ObjectTypeInitializer.DeleteProcedure = LpcpDeletePort;
|
|
ObjectTypeInitializer.UseDefaultObject = TRUE ;
|
|
ObCreateObjectType( &PortTypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &LpcPortObjectType );
|
|
|
|
// Create the object type for the waitable port object
|
|
RtlInitUnicodeString( &PortTypeName, L"WaitablePort" );
|
|
ObjectTypeInitializer.PoolType = NonPagedPool ;
|
|
ObjectTypeInitializer.UseDefaultObject = FALSE ;
|
|
ObCreateObjectType( &PortTypeName, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &LpcWaitablePortObjectType );
|
|
|
|
// Initialize the lpc message and callback id counters
|
|
LpcpNextMessageId = 1;
|
|
LpcpNextCallbackId = 1;
|
|
|
|
// Initialize the lpc port zone. Each element can contain a max message, plus an LPCP message structure, plus an LPCP connection message
|
|
ZoneElementSize = PORT_MAXIMUM_MESSAGE_LENGTH + sizeof( LPCP_MESSAGE ) + sizeof( LPCP_CONNECTION_MESSAGE );
|
|
ZoneElementSize = (ZoneElementSize + LPCP_ZONE_ALIGNMENT - 1) & LPCP_ZONE_ALIGNMENT_MASK;// Round up the size to the next 16 byte alignment
|
|
Status = LpcpInitializePortZone( ZoneElementSize, PAGE_SIZE, LPCP_ZONE_MAX_POOL_USAGE );// Initialize the zone
|
|
if (!NT_SUCCESS( Status )) {
|
|
return( FALSE );
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
char * LpcpGetCreatorName (PLPCP_PORT_OBJECT PortObject)
|
|
/*++
|
|
Routine Description:
|
|
This routine returns the name of the process that created the specified port object
|
|
Arguments:
|
|
PortObject - Supplies the port object being queried
|
|
Return Value:
|
|
char * - The image name of the process that created the port process
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
PEPROCESS Process;
|
|
|
|
Status = PsLookupProcessByProcessId( PortObject->Creator.UniqueProcess, &Process );// First find the process that created the port object
|
|
if (NT_SUCCESS( Status )) {// If we were able to get the process then return the name of the process to our caller
|
|
return Process->ImageFileName;
|
|
} else {
|
|
return "Unknown";// Otherwise tell our caller we don't know the name
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef LPCP_TRACE_SERVER_THREADS
|
|
VOID LpcpPortExtraDataCreate ( PLPCP_PORT_OBJECT PortObject )
|
|
/*++
|
|
Routine Description:
|
|
Allocate a LPCP_PORT_EXTRA_DATA structure and initializate it.
|
|
Arguments:
|
|
PortObject - The port object that will contains this structure
|
|
--*/
|
|
{
|
|
PLPCP_PORT_EXTRA_DATA PortData;
|
|
PortData = ExAllocatePoolWithTag(NonPagedPool, sizeof(LPCP_PORT_EXTRA_DATA), 'DEPL');
|
|
PortData->ThreadCount = 0;
|
|
PortData->PortObject = PortObject;
|
|
PortObject->Reserved = (ULONG)PortData;
|
|
}
|
|
|
|
VOID LpcpPortExtraDataDestroy (PLPCP_PORT_OBJECT PortObject)
|
|
/*++
|
|
Routine Description:
|
|
Free the memory alocated for the extra data structure
|
|
Arguments:
|
|
PortObject - The port object that will contains this structure
|
|
--*/
|
|
{
|
|
PLPCP_PORT_EXTRA_DATA PortData;
|
|
|
|
PortData = (PLPCP_PORT_EXTRA_DATA) PortObject->Reserved;
|
|
if ((PortData != NULL) && (PortData->PortObject == PortObject)) {
|
|
ExFreePoolWithTag( PortData, 'DEPL');
|
|
PortObject->Reserved = 0;
|
|
}
|
|
}
|
|
|
|
VOID LpcpPortExtraDataPush (PLPCP_PORT_EXTRA_DATA PortData, PVOID Thread)
|
|
/*++
|
|
Routine Description:
|
|
Push a new thread on the array. The opperation occurs only if the thread is first time using this port.
|
|
Arguments:
|
|
PortData - the pointer to the Extra data port structure
|
|
Thread - The thread that should be added to the thread array
|
|
--*/
|
|
{
|
|
ULONG Position;
|
|
ULONG EndSearch;
|
|
|
|
EndSearch = PortData->ThreadCount;
|
|
|
|
if ( EndSearch >= LPCP_SERVER_THREAD_ARRAY_SIZE) {
|
|
EndSearch = LPCP_SERVER_THREAD_ARRAY_SIZE - 1;
|
|
}
|
|
|
|
for (Position = 0; Position < EndSearch ; Position++) {
|
|
if ( PortData->Threads[Position] == Thread ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
PortData->Threads[PortData->ThreadCount % LPCP_SERVER_THREAD_ARRAY_SIZE] = Thread;
|
|
PortData->ThreadCount += 1;
|
|
// DbgPrint( "Port %lx : Threads: %ld (%lx)\n", PortData->PortObject, PortData->ThreadCount, Thread);
|
|
}
|
|
|
|
|
|
VOID LpcpSaveThread (PLPCP_PORT_OBJECT PortObject)
|
|
/*++
|
|
Routine Description:
|
|
This function is used to store the current thread to the PortObject.
|
|
If the port object does not have the extra-data structure allocated, this function will call LpcpPortExtraDataCreate to do this.
|
|
Arguments:
|
|
PortObject - The port object that will contains this structure
|
|
--*/
|
|
{
|
|
if (PortObject->Reserved == 0) {
|
|
LpcpPortExtraDataCreate( PortObject );
|
|
}
|
|
|
|
if ( ((PortObject->Flags & PORT_TYPE) == SERVER_COMMUNICATION_PORT) && (PortObject->Reserved != 0) ) {
|
|
LpcpPortExtraDataPush( (PLPCP_PORT_EXTRA_DATA)PortObject->Reserved, PsGetCurrentThread());
|
|
}
|
|
}
|
|
#endif |