Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262/* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/lpc/create.c * PURPOSE: Local Procedure Call: Port/Queue/Message Creation * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>#define NDEBUG#include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
NTSTATUSNTAPILpcpInitializePortQueue(IN PLPCP_PORT_OBJECT Port){ PLPCP_NONPAGED_PORT_QUEUE MessageQueue;
PAGED_CODE();
/* Allocate the queue */ MessageQueue = ExAllocatePoolWithTag(NonPagedPool, sizeof(*MessageQueue), 'troP'); if (!MessageQueue) return STATUS_INSUFFICIENT_RESOURCES;
/* Set it up */ KeInitializeSemaphore(&MessageQueue->Semaphore, 0, MAXLONG); MessageQueue->BackPointer = Port;
/* And link it with the Paged Pool part */ Port->MsgQueue.Semaphore = &MessageQueue->Semaphore; InitializeListHead(&Port->MsgQueue.ReceiveHead); return STATUS_SUCCESS;}
NTSTATUSNTAPILpcpCreatePort(OUT PHANDLE PortHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG MaxConnectionInfoLength, IN ULONG MaxMessageLength, IN ULONG MaxPoolUsage, IN BOOLEAN Waitable){ NTSTATUS Status; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); UNICODE_STRING CapturedObjectName, *ObjectName;#if DBG UNICODE_STRING CapturedPortName;#endif PLPCP_PORT_OBJECT Port; HANDLE Handle;
PAGED_CODE();
RtlInitEmptyUnicodeString(&CapturedObjectName, NULL, 0);
/* Check if the call comes from user mode */ if (PreviousMode != KernelMode) { _SEH2_TRY { /* Probe the PortHandle */ ProbeForWriteHandle(PortHandle);
/* Probe the ObjectAttributes and its object name (not the buffer) */ ProbeForRead(ObjectAttributes, sizeof(*ObjectAttributes), sizeof(ULONG)); ObjectName = ((volatile OBJECT_ATTRIBUTES*)ObjectAttributes)->ObjectName; if (ObjectName) CapturedObjectName = ProbeForReadUnicodeString(ObjectName); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Return the exception code */ _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; } else { ObjectName = ObjectAttributes->ObjectName; if (ObjectName) CapturedObjectName = *ObjectName; }
/* Normalize the buffer pointer in case we don't have * a name, for initializing an unconnected port. */ if (CapturedObjectName.Length == 0) CapturedObjectName.Buffer = NULL;
#if DBG /* Capture the port name for DPRINT only - ObCreateObject does its * own capture. As it is used only for debugging, ignore any failure; * the string is zeroed out in such case. */ ProbeAndCaptureUnicodeString(&CapturedPortName, PreviousMode, ObjectName); LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", &CapturedPortName); ReleaseCapturedUnicodeString(&CapturedPortName, PreviousMode);#endif
/* Create the Object */ Status = ObCreateObject(PreviousMode, LpcPortObjectType, ObjectAttributes, PreviousMode, NULL, sizeof(LPCP_PORT_OBJECT), 0, 0, (PVOID*)&Port); if (!NT_SUCCESS(Status)) return Status;
/* Set up the Object */ RtlZeroMemory(Port, sizeof(LPCP_PORT_OBJECT)); Port->ConnectionPort = Port; Port->Creator = PsGetCurrentThread()->Cid; InitializeListHead(&Port->LpcDataInfoChainHead); InitializeListHead(&Port->LpcReplyChainHead);
/* Check if we don't have a name */ if (CapturedObjectName.Buffer == NULL) { /* Set up for an unconnected port */ Port->Flags = LPCP_UNCONNECTED_PORT; Port->ConnectedPort = Port; Port->ServerProcess = NULL; } else { /* Set up for a named connection port */ Port->Flags = LPCP_CONNECTION_PORT; Port->ServerProcess = PsGetCurrentProcess();
/* Don't let the process die on us */ ObReferenceObject(Port->ServerProcess); }
/* Check if this is a waitable port */ if (Waitable) Port->Flags |= LPCP_WAITABLE_PORT;
/* Setup the port queue */ Status = LpcpInitializePortQueue(Port); if (!NT_SUCCESS(Status)) { /* Fail */ ObDereferenceObject(Port); return Status; }
/* Check if this is a waitable port */ if (Port->Flags & LPCP_WAITABLE_PORT) { /* Setup the wait event */ KeInitializeEvent(&Port->WaitEvent, NotificationEvent, FALSE); }
/* Set the maximum message size allowed */ Port->MaxMessageLength = LpcpMaxMessageSize - FIELD_OFFSET(LPCP_MESSAGE, Request);
/* Now subtract the actual message structures and get the data size */ Port->MaxConnectionInfoLength = Port->MaxMessageLength - sizeof(PORT_MESSAGE) - sizeof(LPCP_CONNECTION_MESSAGE);
/* Validate the sizes */ if (Port->MaxConnectionInfoLength < MaxConnectionInfoLength) { /* Not enough space for your request */ ObDereferenceObject(Port); return STATUS_INVALID_PARAMETER_3; } else if (Port->MaxMessageLength < MaxMessageLength) { /* Not enough space for your request */ ObDereferenceObject(Port); return STATUS_INVALID_PARAMETER_4; }
/* Now set the custom setting */ Port->MaxMessageLength = MaxMessageLength;
/* Insert it now */ Status = ObInsertObject(Port, NULL, PORT_ALL_ACCESS, 0, NULL, &Handle); if (NT_SUCCESS(Status)) { _SEH2_TRY { /* Write back the handle, pointer was already probed */ *PortHandle = Handle; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* An exception happened, close the opened handle */ ObCloseHandle(Handle, PreviousMode); Status = _SEH2_GetExceptionCode(); } _SEH2_END; }
/* Return success or the error */ LPCTRACE(LPC_CREATE_DEBUG, "Port: %p. Handle: %p\n", Port, Handle); return Status;}
/* PUBLIC FUNCTIONS **********************************************************/
/* * @implemented */NTSTATUSNTAPINtCreatePort(OUT PHANDLE PortHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG MaxConnectInfoLength, IN ULONG MaxDataLength, IN ULONG MaxPoolUsage){ PAGED_CODE();
/* Call the internal API */ return LpcpCreatePort(PortHandle, ObjectAttributes, MaxConnectInfoLength, MaxDataLength, MaxPoolUsage, FALSE);}
/* * @implemented */NTSTATUSNTAPINtCreateWaitablePort(OUT PHANDLE PortHandle, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG MaxConnectInfoLength, IN ULONG MaxDataLength, IN ULONG MaxPoolUsage){ PAGED_CODE();
/* Call the internal API */ return LpcpCreatePort(PortHandle, ObjectAttributes, MaxConnectInfoLength, MaxDataLength, MaxPoolUsage, TRUE);}
/* EOF */