NT4/private/ntos/lpc/lpcclose.c
2020-09-30 17:12:29 +02:00

184 lines
4.8 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
lpcclose.c
Abstract:
Local Inter-Process Communication close procedures that are called when
a connection port or a communications port is closed.
Author:
Steve Wood (stevewo) 15-May-1989
Revision History:
--*/
#include "lpcp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,LpcpDeletePort)
#pragma alloc_text(PAGE,LpcExitThread)
#endif
VOID
LpcpClosePort(
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG ProcessHandleCount,
IN ULONG SystemHandleCount
)
{
PLPCP_PORT_OBJECT Port = Object;
if ( (Port->Flags & PORT_TYPE) == SERVER_CONNECTION_PORT ) {
if ( SystemHandleCount == 0 ) {
LpcpDestroyPortQueue( Port, TRUE );
}
else if ( SystemHandleCount == 1 ) {
LpcpDestroyPortQueue( Port, FALSE );
}
}
return;
}
VOID
LpcpDeletePort(
IN PVOID Object
)
{
PLPCP_PORT_OBJECT Port = Object;
PLPCP_PORT_OBJECT ConnectionPort;
LPC_CLIENT_DIED_MSG ClientPortClosedDatagram;
PLPCP_MESSAGE Msg;
PLIST_ENTRY Head, Next;
HANDLE CurrentProcessId;
PAGED_CODE();
//
// Send an LPC_PORT_CLOSED datagram to whoever is connected
// to this port so they know they are no longer connected.
//
if ((Port->Flags & PORT_TYPE) == CLIENT_COMMUNICATION_PORT) {
ClientPortClosedDatagram.PortMsg.u1.s1.TotalLength = sizeof( ClientPortClosedDatagram );
ClientPortClosedDatagram.PortMsg.u1.s1.DataLength = sizeof( ClientPortClosedDatagram.CreateTime );
ClientPortClosedDatagram.PortMsg.u2.s2.Type = LPC_PORT_CLOSED;
ClientPortClosedDatagram.PortMsg.u2.s2.DataInfoOffset = 0;
ClientPortClosedDatagram.CreateTime = PsGetCurrentProcess()->CreateTime;
LpcRequestPort( Port, (PPORT_MESSAGE)&ClientPortClosedDatagram );
}
//
// If connected, disconnect the port, and then scan the message queue
// for this port and dereference any messages in the queue.
//
LpcpDestroyPortQueue( Port, TRUE );
//
// If the client has a port memory view, then unmap it
//
if (Port->ClientSectionBase != NULL) {
ZwUnmapViewOfSection( NtCurrentProcess(),
Port->ClientSectionBase
);
}
//
// If the server has a port memory view, then unmap it
//
if (Port->ServerSectionBase != NULL) {
ZwUnmapViewOfSection( NtCurrentProcess(),
Port->ServerSectionBase
);
}
//
// Dereference the pointer to the connection port if it is not
// this port.
//
if (ConnectionPort = Port->ConnectionPort) {
CurrentProcessId = PsGetCurrentThread()->Cid.UniqueProcess;
ExAcquireFastMutex( &LpcpLock );
Head = &ConnectionPort->LpcDataInfoChainHead;
Next = Head->Flink;
while (Next != Head) {
Msg = CONTAINING_RECORD( Next, LPCP_MESSAGE, Entry );
Next = Next->Flink;
if (Msg->Request.ClientId.UniqueProcess == CurrentProcessId) {
LpcpTrace(( "%s Freeing DataInfo Message %lx (%u.%u) Port: %lx\n",
PsGetCurrentProcess()->ImageFileName,
Msg,
Msg->Request.MessageId,
Msg->Request.CallbackId,
ConnectionPort
));
RemoveEntryList( &Msg->Entry );
LpcpFreeToPortZone( Msg, TRUE );
}
}
ExReleaseFastMutex( &LpcpLock );
if (ConnectionPort != Port) {
ObDereferenceObject( ConnectionPort );
}
}
//
// Free any static client security context
//
LpcpFreePortClientSecurity( Port );
}
VOID
LpcExitThread(
PETHREAD Thread
)
{
PLPCP_MESSAGE Msg;
//
// Acquire the mutex that protects the LpcReplyMessage field of
// the thread. Zero the field so nobody else tries to process it
// when we release the lock.
//
ExAcquireFastMutex( &LpcpLock );
if (!IsListEmpty( &Thread->LpcReplyChain )) {
RemoveEntryList( &Thread->LpcReplyChain );
}
Thread->LpcExitThreadCalled = TRUE;
Thread->LpcReplyMessageId = 0;
Msg = Thread->LpcReplyMessage;
if (Msg != NULL) {
Thread->LpcReplyMessage = NULL;
if (Msg->RepliedToThread != NULL) {
ObDereferenceObject( Msg->RepliedToThread );
Msg->RepliedToThread = NULL;
}
LpcpTrace(( "Cleanup Msg %lx (%d) for Thread %lx allocated\n", Msg, IsListEmpty( &Msg->Entry ), Thread ));
LpcpFreeToPortZone( Msg, TRUE );
}
ExReleaseFastMutex( &LpcpLock );
}