1 /* $Id: send.c,v 1.17 2004/08/31 20:17:18 hbirr Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/lpc/send.c
6 * PURPOSE: Communication mechanism
7 * PROGRAMMER: David Welch (welch@cwcom.net)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
19 /**********************************************************************
21 * LpcSendTerminationPort/2
32 LpcSendTerminationPort (IN PEPORT Port
,
36 LPC_TERMINATION_MESSAGE Msg
;
39 Msg
.Header
.MessageType
= LPC_NEW_MESSAGE
;
41 Msg
.CreationTime
= CreationTime
;
42 Status
= LpcRequestPort (Port
, &Msg
.Header
);
47 /**********************************************************************
49 * LpcSendDebugMessagePort/3
60 LpcSendDebugMessagePort (IN PEPORT Port
,
61 IN PLPC_DBG_MESSAGE Message
,
62 OUT PLPC_DBG_MESSAGE Reply
)
66 PQUEUEDMESSAGE ReplyMessage
;
68 Status
= EiReplyOrRequestPort(Port
,
72 if (!NT_SUCCESS(Status
))
74 ObDereferenceObject(Port
);
77 KeReleaseSemaphore(&Port
->OtherPort
->Semaphore
, IO_NO_INCREMENT
, 1, FALSE
);
82 KeWaitForSingleObject(&Port
->Semaphore
,
91 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
92 ReplyMessage
= EiDequeueMessagePort(Port
);
93 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
94 memcpy(Reply
, &ReplyMessage
->Message
, ReplyMessage
->Message
.MessageSize
);
95 ExFreePool(ReplyMessage
);
97 return(STATUS_SUCCESS
);
101 /**********************************************************************
113 * I investigated this function a bit more in depth.
114 * It looks like the legal values for the MessageType field in the
115 * message to send are in the range LPC_NEW_MESSAGE .. LPC_CLIENT_DIED,
116 * but LPC_DATAGRAM is explicitly forbidden.
120 NTSTATUS STDCALL
LpcRequestPort (IN PEPORT Port
,
121 IN PLPC_MESSAGE LpcMessage
)
125 DPRINT("LpcRequestPort(PortHandle %08x, LpcMessage %08x)\n", Port
, LpcMessage
);
127 #ifdef __USE_NT_LPC__
128 /* Check the message's type */
129 if (LPC_NEW_MESSAGE
== LpcMessage
->MessageType
)
131 LpcMessage
->MessageType
= LPC_DATAGRAM
;
133 else if (LPC_DATAGRAM
== LpcMessage
->MessageType
)
135 return STATUS_INVALID_PARAMETER
;
137 else if (LpcMessage
->MessageType
> LPC_CLIENT_DIED
)
139 return STATUS_INVALID_PARAMETER
;
141 /* Check the range offset */
142 if (0 != LpcMessage
->VirtualRangesOffset
)
144 return STATUS_INVALID_PARAMETER
;
148 Status
= EiReplyOrRequestPort(Port
,
152 KeReleaseSemaphore( &Port
->Semaphore
, IO_NO_INCREMENT
, 1, FALSE
);
158 /**********************************************************************
172 NTSTATUS STDCALL
NtRequestPort (IN HANDLE PortHandle
,
173 IN PLPC_MESSAGE LpcMessage
)
178 DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle
,
181 Status
= ObReferenceObjectByHandle(PortHandle
,
187 if (!NT_SUCCESS(Status
))
189 DPRINT("NtRequestPort() = %x\n", Status
);
193 Status
= LpcRequestPort(Port
->OtherPort
,
196 ObDereferenceObject(Port
);
201 /**********************************************************************
203 * NtRequestWaitReplyPort/3
216 NtRequestWaitReplyPort (IN HANDLE PortHandle
,
217 PLPC_MESSAGE UnsafeLpcRequest
,
218 PLPC_MESSAGE UnsafeLpcReply
)
220 PETHREAD CurrentThread
;
221 struct _EPROCESS
*AttachedProcess
;
224 PQUEUEDMESSAGE Message
;
226 PLPC_MESSAGE LpcRequest
;
227 USHORT LpcRequestMessageSize
;
229 DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, "
230 "LpcReply %x)\n", PortHandle
, UnsafeLpcRequest
, UnsafeLpcReply
);
232 Status
= ObReferenceObjectByHandle(PortHandle
,
238 if (!NT_SUCCESS(Status
))
243 /* win32k sometimes needs to KeAttach() the CSRSS process in order to make
244 the PortHandle valid. Now that we've got the EPORT structure from the
245 handle we can undo this, so everything is normal again. Need to
246 re-KeAttach() before returning though */
247 CurrentThread
= PsGetCurrentThread();
248 if (&CurrentThread
->ThreadsProcess
->Pcb
== CurrentThread
->Tcb
.ApcState
.Process
)
250 AttachedProcess
= NULL
;
254 AttachedProcess
= (PEPROCESS
)CurrentThread
->Tcb
.ApcState
.Process
;
258 Status
= MmCopyFromCaller(&LpcRequestMessageSize
,
259 &UnsafeLpcRequest
->MessageSize
,
261 if (!NT_SUCCESS(Status
))
263 if (NULL
!= AttachedProcess
)
265 KeAttachProcess(AttachedProcess
);
267 ObDereferenceObject(Port
);
270 if (LpcRequestMessageSize
> (sizeof(LPC_MESSAGE
) + MAX_MESSAGE_DATA
))
272 if (NULL
!= AttachedProcess
)
274 KeAttachProcess(AttachedProcess
);
276 ObDereferenceObject(Port
);
277 return(STATUS_PORT_MESSAGE_TOO_LONG
);
279 LpcRequest
= ExAllocatePool(NonPagedPool
, LpcRequestMessageSize
);
280 if (LpcRequest
== NULL
)
282 if (NULL
!= AttachedProcess
)
284 KeAttachProcess(AttachedProcess
);
286 ObDereferenceObject(Port
);
287 return(STATUS_NO_MEMORY
);
289 Status
= MmCopyFromCaller(LpcRequest
, UnsafeLpcRequest
,
290 LpcRequestMessageSize
);
291 if (!NT_SUCCESS(Status
))
293 ExFreePool(LpcRequest
);
294 if (NULL
!= AttachedProcess
)
296 KeAttachProcess(AttachedProcess
);
298 ObDereferenceObject(Port
);
301 LpcRequestMessageSize
= LpcRequest
->MessageSize
;
302 if (LpcRequestMessageSize
> (sizeof(LPC_MESSAGE
) + MAX_MESSAGE_DATA
))
304 ExFreePool(LpcRequest
);
305 if (NULL
!= AttachedProcess
)
307 KeAttachProcess(AttachedProcess
);
309 ObDereferenceObject(Port
);
310 return(STATUS_PORT_MESSAGE_TOO_LONG
);
312 if (LpcRequest
->DataSize
!= (LpcRequest
->MessageSize
- sizeof(LPC_MESSAGE
)))
314 ExFreePool(LpcRequest
);
315 if (NULL
!= AttachedProcess
)
317 KeAttachProcess(AttachedProcess
);
319 ObDereferenceObject(Port
);
320 return(STATUS_PORT_MESSAGE_TOO_LONG
);
323 Status
= EiReplyOrRequestPort(Port
->OtherPort
,
327 if (!NT_SUCCESS(Status
))
329 DPRINT1("Enqueue failed\n");
330 ExFreePool(LpcRequest
);
331 if (NULL
!= AttachedProcess
)
333 KeAttachProcess(AttachedProcess
);
335 ObDereferenceObject(Port
);
338 ExFreePool(LpcRequest
);
339 KeReleaseSemaphore (&Port
->OtherPort
->Semaphore
, IO_NO_INCREMENT
,
345 Status
= KeWaitForSingleObject(&Port
->Semaphore
,
350 if (Status
== STATUS_SUCCESS
)
356 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
357 Message
= EiDequeueMessagePort(Port
);
358 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
361 DPRINT("Message->Message.MessageSize %d\n",
362 Message
->Message
.MessageSize
);
363 Status
= MmCopyToCaller(UnsafeLpcReply
, &Message
->Message
,
364 Message
->Message
.MessageSize
);
368 Status
= STATUS_UNSUCCESSFUL
;
372 if (NT_SUCCESS(Status
))
374 Status
= STATUS_UNSUCCESSFUL
;
377 if (NULL
!= AttachedProcess
)
379 KeAttachProcess(AttachedProcess
);
381 ObDereferenceObject(Port
);
387 /**********************************************************************
389 * NtWriteRequestData/6
399 NTSTATUS STDCALL
NtWriteRequestData (HANDLE PortHandle
,
400 PLPC_MESSAGE Message
,
407 return(STATUS_NOT_IMPLEMENTED
);