3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/lpc/send.c
6 * PURPOSE: Communication mechanism
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
11 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
19 /**********************************************************************
21 * LpcSendTerminationPort/2
32 LpcSendTerminationPort (IN PEPORT Port
,
33 IN LARGE_INTEGER CreateTime
)
39 Msg
.h
.u2
.s2
.Type
= LPC_CLIENT_DIED
;
41 Msg
.h
.u1
.s1
.TotalLength
= sizeof(Msg
);
42 Msg
.h
.u1
.s1
.DataLength
= sizeof(Msg
) - sizeof(PORT_MESSAGE
);
43 Msg
.CreateTime
= CreateTime
;
44 Status
= LpcRequestPort (Port
, &Msg
.h
);
49 /**********************************************************************
51 * LpcSendDebugMessagePort/3
62 LpcSendDebugMessagePort (IN PEPORT Port
,
63 IN PDBGKM_MSG Message
,
68 PQUEUEDMESSAGE ReplyMessage
;
70 Status
= EiReplyOrRequestPort(Port
,
74 if (!NT_SUCCESS(Status
))
76 ObDereferenceObject(Port
);
79 KeReleaseSemaphore(&Port
->OtherPort
->Semaphore
, IO_NO_INCREMENT
, 1, FALSE
);
84 KeWaitForSingleObject(&Port
->Semaphore
,
93 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
94 ReplyMessage
= EiDequeueMessagePort(Port
);
95 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
96 memcpy(Reply
, &ReplyMessage
->Message
, ReplyMessage
->Message
.u1
.s1
.TotalLength
);
97 ExFreePool(ReplyMessage
);
99 return(STATUS_SUCCESS
);
103 /**********************************************************************
115 * I investigated this function a bit more in depth.
116 * It looks like the legal values for the MessageType field in the
117 * message to send are in the range LPC_NEW_MESSAGE .. LPC_CLIENT_DIED,
118 * but LPC_DATAGRAM is explicitly forbidden.
122 NTSTATUS STDCALL
LpcRequestPort (IN PEPORT Port
,
123 IN PPORT_MESSAGE LpcMessage
)
127 DPRINT("LpcRequestPort(PortHandle %08x, LpcMessage %08x)\n", Port
, LpcMessage
);
129 #ifdef __USE_NT_LPC__
130 /* Check the message's type */
131 if (LPC_NEW_MESSAGE
== LpcMessage
->u2
.s2
.Type
)
133 LpcMessage
->u2
.s2
.Type
= LPC_DATAGRAM
;
135 else if (LPC_DATAGRAM
== LpcMessage
->u2
.s2
.Type
)
137 return STATUS_INVALID_PARAMETER
;
139 else if (LpcMessage
->u2
.s2
.Type
> LPC_CLIENT_DIED
)
141 return STATUS_INVALID_PARAMETER
;
143 /* Check the range offset */
144 if (0 != LpcMessage
->VirtualRangesOffset
)
146 return STATUS_INVALID_PARAMETER
;
150 Status
= EiReplyOrRequestPort(Port
,
154 KeReleaseSemaphore( &Port
->Semaphore
, IO_NO_INCREMENT
, 1, FALSE
);
160 /**********************************************************************
174 NTSTATUS STDCALL
NtRequestPort (IN HANDLE PortHandle
,
175 IN PPORT_MESSAGE LpcMessage
)
180 DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle
,
183 Status
= ObReferenceObjectByHandle(PortHandle
,
189 if (!NT_SUCCESS(Status
))
191 DPRINT("NtRequestPort() = %x\n", Status
);
195 Status
= LpcRequestPort(Port
->OtherPort
,
198 ObDereferenceObject(Port
);
203 /**********************************************************************
205 * NtRequestWaitReplyPort/3
218 NtRequestWaitReplyPort (IN HANDLE PortHandle
,
219 PPORT_MESSAGE UnsafeLpcRequest
,
220 PPORT_MESSAGE UnsafeLpcReply
)
222 PETHREAD CurrentThread
;
223 struct _KPROCESS
*AttachedProcess
;
225 PQUEUEDMESSAGE Message
;
227 PPORT_MESSAGE LpcRequest
;
228 USHORT LpcRequestMessageSize
= 0, LpcRequestDataSize
= 0;
229 KPROCESSOR_MODE PreviousMode
;
230 NTSTATUS Status
= STATUS_SUCCESS
;
232 PreviousMode
= ExGetPreviousMode();
234 if (PreviousMode
!= KernelMode
)
238 ProbeForRead(UnsafeLpcRequest
,
239 sizeof(PORT_MESSAGE
),
241 ProbeForWrite(UnsafeLpcReply
,
242 sizeof(PORT_MESSAGE
),
244 LpcRequestMessageSize
= UnsafeLpcRequest
->u1
.s1
.TotalLength
;
248 Status
= _SEH_GetExceptionCode();
252 if (!NT_SUCCESS(Status
))
259 LpcRequestMessageSize
= UnsafeLpcRequest
->u1
.s1
.TotalLength
;
262 DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, "
263 "LpcReply %x)\n", PortHandle
, UnsafeLpcRequest
, UnsafeLpcReply
);
265 Status
= ObReferenceObjectByHandle(PortHandle
,
271 if (!NT_SUCCESS(Status
))
276 if (EPORT_DISCONNECTED
== Port
->State
)
278 ObDereferenceObject(Port
);
279 return STATUS_PORT_DISCONNECTED
;
282 /* win32k sometimes needs to KeAttach() the CSRSS process in order to make
283 the PortHandle valid. Now that we've got the EPORT structure from the
284 handle we can undo this, so everything is normal again. Need to
285 re-KeAttach() before returning though */
286 CurrentThread
= PsGetCurrentThread();
287 if (&CurrentThread
->ThreadsProcess
->Pcb
== CurrentThread
->Tcb
.ApcState
.Process
)
289 AttachedProcess
= NULL
;
293 AttachedProcess
= CurrentThread
->Tcb
.ApcState
.Process
;
297 if (LpcRequestMessageSize
> LPC_MAX_MESSAGE_LENGTH
)
299 if (NULL
!= AttachedProcess
)
301 KeAttachProcess(AttachedProcess
);
303 ObDereferenceObject(Port
);
304 return(STATUS_PORT_MESSAGE_TOO_LONG
);
306 LpcRequest
= ExAllocatePool(NonPagedPool
, LpcRequestMessageSize
);
307 if (LpcRequest
== NULL
)
309 if (NULL
!= AttachedProcess
)
311 KeAttachProcess(AttachedProcess
);
313 ObDereferenceObject(Port
);
314 return(STATUS_NO_MEMORY
);
316 if (PreviousMode
!= KernelMode
)
320 RtlCopyMemory(LpcRequest
,
322 LpcRequestMessageSize
);
323 LpcRequestMessageSize
= LpcRequest
->u1
.s1
.TotalLength
;
324 LpcRequestDataSize
= LpcRequest
->u1
.s1
.DataLength
;
328 Status
= _SEH_GetExceptionCode();
332 if (!NT_SUCCESS(Status
))
334 ExFreePool(LpcRequest
);
335 if (NULL
!= AttachedProcess
)
337 KeAttachProcess(AttachedProcess
);
339 ObDereferenceObject(Port
);
345 RtlCopyMemory(LpcRequest
,
347 LpcRequestMessageSize
);
348 LpcRequestMessageSize
= LpcRequest
->u1
.s1
.TotalLength
;
349 LpcRequestDataSize
= LpcRequest
->u1
.s1
.DataLength
;
352 if (LpcRequestMessageSize
> LPC_MAX_MESSAGE_LENGTH
)
354 ExFreePool(LpcRequest
);
355 if (NULL
!= AttachedProcess
)
357 KeAttachProcess(AttachedProcess
);
359 ObDereferenceObject(Port
);
360 return(STATUS_PORT_MESSAGE_TOO_LONG
);
362 if (LpcRequestDataSize
> LPC_MAX_DATA_LENGTH
)
364 ExFreePool(LpcRequest
);
365 if (NULL
!= AttachedProcess
)
367 KeAttachProcess(AttachedProcess
);
369 ObDereferenceObject(Port
);
370 return(STATUS_PORT_MESSAGE_TOO_LONG
);
373 Status
= EiReplyOrRequestPort(Port
->OtherPort
,
377 if (!NT_SUCCESS(Status
))
379 DPRINT1("Enqueue failed\n");
380 ExFreePool(LpcRequest
);
381 if (NULL
!= AttachedProcess
)
383 KeAttachProcess(AttachedProcess
);
385 ObDereferenceObject(Port
);
388 ExFreePool(LpcRequest
);
389 KeReleaseSemaphore (&Port
->OtherPort
->Semaphore
, IO_NO_INCREMENT
,
395 Status
= KeWaitForSingleObject(&Port
->Semaphore
,
400 if (Status
== STATUS_SUCCESS
)
406 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
407 Message
= EiDequeueMessagePort(Port
);
408 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
411 DPRINT("Message->Message.u1.s1.TotalLength %d\n",
412 Message
->Message
.u1
.s1
.TotalLength
);
413 if (PreviousMode
!= KernelMode
)
417 RtlCopyMemory(UnsafeLpcReply
,
419 Message
->Message
.u1
.s1
.TotalLength
);
423 Status
= _SEH_GetExceptionCode();
429 RtlCopyMemory(UnsafeLpcReply
,
431 Message
->Message
.u1
.s1
.TotalLength
);
436 Status
= STATUS_UNSUCCESSFUL
;
440 if (NT_SUCCESS(Status
))
442 Status
= STATUS_UNSUCCESSFUL
;
445 if (NULL
!= AttachedProcess
)
447 KeAttachProcess(AttachedProcess
);
449 ObDereferenceObject(Port
);
455 /**********************************************************************
457 * NtWriteRequestData/6
467 NTSTATUS STDCALL
NtWriteRequestData (HANDLE PortHandle
,
468 PPORT_MESSAGE Message
,
475 return(STATUS_NOT_IMPLEMENTED
);