-/* $Id: connect.c,v 1.25 2004/02/02 23:48:42 ea Exp $
- *
+/* $Id$
+ *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/lpc/connect.c
* PURPOSE: Communication mechanism
- * PROGRAMMER: David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- * Created 22/05/98
+ *
+ * PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
-#define NTOS_MODE_KERNEL
-#include <ntos.h>
-#include <internal/ob.h>
-#include <internal/port.h>
-#include <internal/dbg.h>
-#include <internal/pool.h>
-#include <internal/safe.h>
-#include <internal/mm.h>
-
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
-/* GLOBALS *******************************************************************/
-
-#define TAG_LPC_CONNECT_MESSAGE TAG('L', 'P', 'C', 'C')
-
/* FUNCTIONS *****************************************************************/
/**********************************************************************
* Create a port to represent our side of the connection
*/
Status = ObCreateObject (KernelMode,
- ExPortType,
+ LpcPortObjectType,
NULL,
KernelMode,
NULL,
{
return (Status);
}
- NiInitializePort(OurPort, EPORT_TYPE_CLIENT_COMM_PORT, NamedPort);
+ LpcpInitializePort(OurPort, EPORT_TYPE_CLIENT_COMM_PORT, NamedPort);
/*
* Allocate a request message.
*/
- RequestMessage = ExAllocatePool(NonPagedPool,
- sizeof(EPORT_CONNECT_REQUEST_MESSAGE) +
+ RequestMessage = ExAllocatePool(NonPagedPool,
+ sizeof(EPORT_CONNECT_REQUEST_MESSAGE) +
RequestConnectDataLength);
if (RequestMessage == NULL)
{
/*
* Initialize the request message.
*/
- RequestMessage->MessageHeader.DataSize =
+ RequestMessage->MessageHeader.DataSize =
sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength -
sizeof(LPC_MESSAGE);
- RequestMessage->MessageHeader.MessageSize =
+ RequestMessage->MessageHeader.MessageSize =
sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength;
DPRINT("RequestMessageSize %d\n",
RequestMessage->MessageHeader.MessageSize);
memcpy(RequestMessage->ConnectData, ConnectData,
RequestConnectDataLength);
}
-
+
/*
* Queue the message to the named port
*/
OurPort);
KeReleaseSemaphore(&NamedPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);
ExFreePool(RequestMessage);
-
+
/*
* Wait for them to accept our connection
*/
FALSE,
NULL);
- /*
+ /*
* Dequeue the response
*/
KeAcquireSpinLock (&OurPort->Lock, &oldIrql);
/**********************************************************************
* NAME EXPORTED
* NtConnectPort/8
- *
+ *
* DESCRIPTION
- * Connect to a named port and wait for the other side to
+ * Connect to a named port and wait for the other side to
* accept or reject the connection request.
*
* ARGUMENTS
* MaxMessageSize
* ConnectInfo
* UserConnectInfoLength
- *
+ *
* RETURN VALUE
- *
+ *
* @unimplemented
*/
NTSTATUS STDCALL
LPC_SECTION_WRITE WriteMap;
LPC_SECTION_READ ReadMap;
ULONG MaximumMessageSize;
- PVOID ConnectData;
- ULONG ConnectDataLength;
+ PVOID ConnectData = NULL;
+ ULONG ConnectDataLength = 0;
PSECTION_OBJECT SectionObject;
LARGE_INTEGER SectionOffset;
PEPORT ConnectedPort;
- NTSTATUS Status;
+ KPROCESSOR_MODE PreviousMode;
+ NTSTATUS Status = STATUS_SUCCESS;
PEPORT NamedPort;
+ PreviousMode = ExGetPreviousMode();
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(UnsafeConnectedPortHandle,
+ sizeof(HANDLE),
+ sizeof(ULONG));
+ if (UnsafeMaximumMessageSize != NULL)
+ {
+ ProbeForWrite(UnsafeMaximumMessageSize,
+ sizeof(ULONG),
+ sizeof(ULONG));
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+
/*
* Copy in write map and partially validate.
*/
if (UnsafeWriteMap != NULL)
{
- Status = MmCopyFromCaller(&WriteMap,
- UnsafeWriteMap,
- sizeof(LPC_SECTION_WRITE));
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(UnsafeWriteMap,
+ sizeof(LPC_SECTION_WRITE),
+ 1);
+ RtlCopyMemory(&WriteMap,
+ UnsafeWriteMap,
+ sizeof(LPC_SECTION_WRITE));
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ else
+ {
+ RtlCopyMemory(&WriteMap,
+ UnsafeWriteMap,
+ sizeof(LPC_SECTION_WRITE));
+ }
+
if (WriteMap.Length != sizeof(LPC_SECTION_WRITE))
{
return(STATUS_INVALID_PARAMETER_4);
/*
* Handle connection data.
*/
- if (UnsafeConnectData == NULL)
- {
- ConnectDataLength = 0;
- ConnectData = NULL;
- }
- else
- {
- if (ExGetPreviousMode() == KernelMode)
- {
- ConnectDataLength = *UnsafeConnectDataLength;
- ConnectData = UnsafeConnectData;
- }
+ if (UnsafeConnectData)
+ {
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForRead(UnsafeConnectDataLength,
+ sizeof(ULONG),
+ 1);
+ ConnectDataLength = *UnsafeConnectDataLength;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
else
- {
- Status = MmCopyFromCaller(&ConnectDataLength,
- UnsafeConnectDataLength,
- sizeof(ULONG));
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- ConnectData = ExAllocatePool(NonPagedPool, ConnectDataLength);
- if (ConnectData == NULL && ConnectDataLength != 0)
- {
- return(STATUS_NO_MEMORY);
- }
- Status = MmCopyFromCaller(ConnectData,
- UnsafeConnectData,
- ConnectDataLength);
- if (!NT_SUCCESS(Status))
- {
- ExFreePool(ConnectData);
- return(Status);
- }
- }
+ {
+ ConnectDataLength = *UnsafeConnectDataLength;
+ }
+
+ if (ConnectDataLength != 0)
+ {
+ ConnectData = ExAllocatePool(NonPagedPool, ConnectDataLength);
+ if (ConnectData == NULL)
+ {
+ return(STATUS_NO_MEMORY);
+ }
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ ProbeForWrite(UnsafeConnectData,
+ ConnectDataLength,
+ 1);
+ RtlCopyMemory(ConnectData,
+ UnsafeConnectData,
+ ConnectDataLength);
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(ConnectData);
+ return Status;
+ }
+ }
+ else
+ {
+ RtlCopyMemory(ConnectData,
+ UnsafeConnectData,
+ ConnectDataLength);
+ }
+ }
}
/*
0,
NULL,
PORT_ALL_ACCESS, /* DesiredAccess */
- ExPortType,
- UserMode,
+ LpcPortObjectType,
+ PreviousMode,
NULL,
(PVOID*)&NamedPort);
if (!NT_SUCCESS(Status))
Status = ObReferenceObjectByHandle(WriteMap.SectionHandle,
SECTION_MAP_READ | SECTION_MAP_WRITE,
MmSectionObjectType,
- UserMode,
+ PreviousMode,
(PVOID*)&SectionObject,
NULL);
if (!NT_SUCCESS(Status))
/* FIXME: Again, check what NT does here. */
if (UnsafeConnectDataLength != NULL)
{
- if (ExGetPreviousMode() != KernelMode)
+ if (PreviousMode != KernelMode)
{
- MmCopyToCaller(UnsafeConnectData,
- ConnectData,
- ConnectDataLength);
- ExFreePool(ConnectData);
+ _SEH_TRY
+ {
+ RtlCopyMemory(UnsafeConnectData,
+ ConnectData,
+ ConnectDataLength);
+ *UnsafeConnectDataLength = ConnectDataLength;
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
}
- MmCopyToCaller(UnsafeConnectDataLength,
- &ConnectDataLength,
- sizeof(ULONG));
+ else
+ {
+ RtlCopyMemory(UnsafeConnectData,
+ ConnectData,
+ ConnectDataLength);
+ *UnsafeConnectDataLength = ConnectDataLength;
+ }
+
+ ExFreePool(ConnectData);
}
return(Status);
}
}
ObDereferenceObject(NamedPort);
NamedPort = NULL;
-
+
/*
* Copy the data back to the caller.
*/
- if (ExGetPreviousMode() != KernelMode)
+
+ if (UnsafeConnectDataLength != NULL)
{
- if (UnsafeConnectDataLength != NULL)
+ if (PreviousMode != KernelMode)
{
- if (ExGetPreviousMode() != KernelMode)
- {
- Status = MmCopyToCaller(UnsafeConnectData,
- ConnectData,
- ConnectDataLength);
- ExFreePool(ConnectData);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- }
- Status = MmCopyToCaller(UnsafeConnectDataLength,
- &ConnectDataLength,
- sizeof(ULONG));
+ _SEH_TRY
+ {
+ *UnsafeConnectDataLength = ConnectDataLength;
+
+ if (ConnectData != NULL)
+ {
+ RtlCopyMemory(UnsafeConnectData,
+ ConnectData,
+ ConnectDataLength);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
if (!NT_SUCCESS(Status))
{
- return(Status);
+ if (ConnectData != NULL)
+ {
+ ExFreePool(ConnectData);
+ }
+ return(Status);
}
}
+ else
+ {
+ *UnsafeConnectDataLength = ConnectDataLength;
+
+ if (ConnectData != NULL)
+ {
+ RtlCopyMemory(UnsafeConnectData,
+ ConnectData,
+ ConnectDataLength);
+ }
+ }
+
+ if (ConnectData != NULL)
+ {
+ ExFreePool(ConnectData);
+ }
}
Status = ObInsertObject(ConnectedPort,
NULL,
{
return(Status);
}
- Status = MmCopyToCaller(UnsafeConnectedPortHandle,
- &ConnectedPortHandle,
- sizeof(HANDLE));
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- if (UnsafeWriteMap != NULL)
- {
- Status = MmCopyToCaller(UnsafeWriteMap,
- &WriteMap,
- sizeof(LPC_SECTION_WRITE));
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- }
- if (UnsafeReadMap != NULL)
- {
- Status = MmCopyToCaller(UnsafeReadMap,
- &ReadMap,
- sizeof(LPC_SECTION_READ));
+
+ if (PreviousMode != KernelMode)
+ {
+ _SEH_TRY
+ {
+ *UnsafeConnectedPortHandle = ConnectedPortHandle;
+
+ if (UnsafeWriteMap != NULL)
+ {
+ RtlCopyMemory(UnsafeWriteMap,
+ &WriteMap,
+ sizeof(LPC_SECTION_WRITE));
+ }
+
+ if (UnsafeReadMap != NULL)
+ {
+ RtlCopyMemory(UnsafeReadMap,
+ &ReadMap,
+ sizeof(LPC_SECTION_READ));
+ }
+
+ if (UnsafeMaximumMessageSize != NULL)
+ {
+ *UnsafeMaximumMessageSize = MaximumMessageSize;
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
+ {
+ return Status;
+ }
}
- if (UnsafeMaximumMessageSize != NULL)
+ else
{
- Status = MmCopyToCaller(UnsafeMaximumMessageSize,
- &MaximumMessageSize,
- sizeof(ULONG));
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
+ *UnsafeConnectedPortHandle = ConnectedPortHandle;
+
+ if (UnsafeWriteMap != NULL)
+ {
+ RtlCopyMemory(UnsafeWriteMap,
+ &WriteMap,
+ sizeof(LPC_SECTION_WRITE));
+ }
+
+ if (UnsafeReadMap != NULL)
+ {
+ RtlCopyMemory(UnsafeReadMap,
+ &ReadMap,
+ sizeof(LPC_SECTION_READ));
+ }
+
+ if (UnsafeMaximumMessageSize != NULL)
+ {
+ *UnsafeMaximumMessageSize = MaximumMessageSize;
+ }
}
/*
PEPORT_CONNECT_REQUEST_MESSAGE CRequest;
PEPORT_CONNECT_REPLY_MESSAGE CReply;
ULONG Size;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
Size = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
if (LpcMessage)
{
return(STATUS_NO_MEMORY);
}
-
+
Status = ObReferenceObjectByHandle(NamedPortHandle,
PORT_ALL_ACCESS,
- ExPortType,
- UserMode,
+ LpcPortObjectType,
+ PreviousMode,
(PVOID*)&NamedPort,
NULL);
if (!NT_SUCCESS(Status))
*/
if (AcceptIt)
{
- Status = ObCreateObject(ExGetPreviousMode(),
- ExPortType,
+ Status = ObCreateObject(PreviousMode,
+ LpcPortObjectType,
NULL,
- ExGetPreviousMode(),
+ PreviousMode,
NULL,
sizeof(EPORT),
0,
return(Status);
}
- NiInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort);
+ LpcpInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort);
}
/*
ConnectionRequest = EiDequeueConnectMessagePort (NamedPort);
KeReleaseSpinLock(&NamedPort->Lock, oldIrql);
CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)(&ConnectionRequest->Message);
-
+
/*
* Prepare the reply.
*/
if (LpcMessage != NULL)
{
memcpy(&CReply->MessageHeader, LpcMessage, sizeof(LPC_MESSAGE));
- memcpy(&CReply->ConnectData, (PVOID)(LpcMessage + 1),
+ memcpy(&CReply->ConnectData, (PVOID)(LpcMessage + 1),
LpcMessage->DataSize);
CReply->MessageHeader.MessageSize =
sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->DataSize;
CReply->ConnectDataLength = 0;
}
if (!AcceptIt)
- {
+ {
EiReplyOrRequestPort(ConnectionRequest->Sender,
&CReply->MessageHeader,
LPC_CONNECTION_REFUSED,
1,
FALSE);
ObDereferenceObject(ConnectionRequest->Sender);
- ExFreePool(ConnectionRequest);
+ ExFreePool(ConnectionRequest);
ExFreePool(CReply);
ObDereferenceObject(NamedPort);
return (STATUS_SUCCESS);
}
-
+
/*
* Prepare the connection.
*/
Status = ObReferenceObjectByHandle(WriteMap->SectionHandle,
SECTION_MAP_READ | SECTION_MAP_WRITE,
MmSectionObjectType,
- UserMode,
+ PreviousMode,
(PVOID*)&SectionObject,
NULL);
if (!NT_SUCCESS(Status))
if (!NT_SUCCESS(Status))
{
return(Status);
- }
+ }
WriteMap->ViewBase = 0;
Status = MmMapViewOfSection(SectionObject,
if (!NT_SUCCESS(Status))
{
return(Status);
- }
-
+ }
+
ObDereferenceObject(SectionObject);
}
if (ReadMap != NULL && CRequest->SendSectionObject != NULL)
OurPort);
ExFreePool(ConnectionRequest);
ExFreePool(CReply);
-
+
ObDereferenceObject(OurPort);
ObDereferenceObject(NamedPort);
-
+
return (STATUS_SUCCESS);
}
/**********************************************************************
* NAME EXPORTED
* NtSecureConnectPort/9
- *
+ *
* DESCRIPTION
- * Connect to a named port and wait for the other side to
+ * Connect to a named port and wait for the other side to
* accept the connection. Possibly verify that the server
* matches the ServerSid (trusted server).
* Present in w2k+.
* MaxMessageSize
* ConnectInfo
* UserConnectInfoLength
- *
+ *
* RETURN VALUE
*/
NTSTATUS STDCALL