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
,
33 IN LARGE_INTEGER CreationTime
)
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 _KPROCESS
*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 if (EPORT_DISCONNECTED
== Port
->State
)
245 ObDereferenceObject(Port
);
246 return STATUS_PORT_DISCONNECTED
;
249 /* win32k sometimes needs to KeAttach() the CSRSS process in order to make
250 the PortHandle valid. Now that we've got the EPORT structure from the
251 handle we can undo this, so everything is normal again. Need to
252 re-KeAttach() before returning though */
253 CurrentThread
= PsGetCurrentThread();
254 if (&CurrentThread
->ThreadsProcess
->Pcb
== CurrentThread
->Tcb
.ApcState
.Process
)
256 AttachedProcess
= NULL
;
260 AttachedProcess
= CurrentThread
->Tcb
.ApcState
.Process
;
264 Status
= MmCopyFromCaller(&LpcRequestMessageSize
,
265 &UnsafeLpcRequest
->MessageSize
,
267 if (!NT_SUCCESS(Status
))
269 if (NULL
!= AttachedProcess
)
271 KeAttachProcess(AttachedProcess
);
273 ObDereferenceObject(Port
);
276 if (LpcRequestMessageSize
> (sizeof(LPC_MESSAGE
) + MAX_MESSAGE_DATA
))
278 if (NULL
!= AttachedProcess
)
280 KeAttachProcess(AttachedProcess
);
282 ObDereferenceObject(Port
);
283 return(STATUS_PORT_MESSAGE_TOO_LONG
);
285 LpcRequest
= ExAllocatePool(NonPagedPool
, LpcRequestMessageSize
);
286 if (LpcRequest
== NULL
)
288 if (NULL
!= AttachedProcess
)
290 KeAttachProcess(AttachedProcess
);
292 ObDereferenceObject(Port
);
293 return(STATUS_NO_MEMORY
);
295 Status
= MmCopyFromCaller(LpcRequest
, UnsafeLpcRequest
,
296 LpcRequestMessageSize
);
297 if (!NT_SUCCESS(Status
))
299 ExFreePool(LpcRequest
);
300 if (NULL
!= AttachedProcess
)
302 KeAttachProcess(AttachedProcess
);
304 ObDereferenceObject(Port
);
307 LpcRequestMessageSize
= LpcRequest
->MessageSize
;
308 if (LpcRequestMessageSize
> (sizeof(LPC_MESSAGE
) + MAX_MESSAGE_DATA
))
310 ExFreePool(LpcRequest
);
311 if (NULL
!= AttachedProcess
)
313 KeAttachProcess(AttachedProcess
);
315 ObDereferenceObject(Port
);
316 return(STATUS_PORT_MESSAGE_TOO_LONG
);
318 if (LpcRequest
->DataSize
!= (LpcRequest
->MessageSize
- sizeof(LPC_MESSAGE
)))
320 ExFreePool(LpcRequest
);
321 if (NULL
!= AttachedProcess
)
323 KeAttachProcess(AttachedProcess
);
325 ObDereferenceObject(Port
);
326 return(STATUS_PORT_MESSAGE_TOO_LONG
);
329 Status
= EiReplyOrRequestPort(Port
->OtherPort
,
333 if (!NT_SUCCESS(Status
))
335 DPRINT1("Enqueue failed\n");
336 ExFreePool(LpcRequest
);
337 if (NULL
!= AttachedProcess
)
339 KeAttachProcess(AttachedProcess
);
341 ObDereferenceObject(Port
);
344 ExFreePool(LpcRequest
);
345 KeReleaseSemaphore (&Port
->OtherPort
->Semaphore
, IO_NO_INCREMENT
,
351 Status
= KeWaitForSingleObject(&Port
->Semaphore
,
356 if (Status
== STATUS_SUCCESS
)
362 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
363 Message
= EiDequeueMessagePort(Port
);
364 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
367 DPRINT("Message->Message.MessageSize %d\n",
368 Message
->Message
.MessageSize
);
369 Status
= MmCopyToCaller(UnsafeLpcReply
, &Message
->Message
,
370 Message
->Message
.MessageSize
);
374 Status
= STATUS_UNSUCCESSFUL
;
378 if (NT_SUCCESS(Status
))
380 Status
= STATUS_UNSUCCESSFUL
;
383 if (NULL
!= AttachedProcess
)
385 KeAttachProcess(AttachedProcess
);
387 ObDereferenceObject(Port
);
393 /**********************************************************************
395 * NtWriteRequestData/6
405 NTSTATUS STDCALL
NtWriteRequestData (HANDLE PortHandle
,
406 PLPC_MESSAGE Message
,
413 return(STATUS_NOT_IMPLEMENTED
);