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>
18 /**********************************************************************
30 * I investigated this function a bit more in depth.
31 * It looks like the legal values for the MessageType field in the
32 * message to send are in the range LPC_NEW_MESSAGE .. LPC_CLIENT_DIED,
33 * but LPC_DATAGRAM is explicitly forbidden.
37 NTSTATUS STDCALL
LpcRequestPort (IN PVOID PortObject
,
38 IN PPORT_MESSAGE LpcMessage
)
41 PEPORT Port
= (PEPORT
)PortObject
;
43 DPRINT("LpcRequestPort(PortHandle %08x, LpcMessage %08x)\n", Port
, LpcMessage
);
46 /* Check the message's type */
47 if (LPC_NEW_MESSAGE
== LpcMessage
->u2
.s2
.Type
)
49 LpcMessage
->u2
.s2
.Type
= LPC_DATAGRAM
;
51 else if (LPC_DATAGRAM
== LpcMessage
->u2
.s2
.Type
)
53 return STATUS_INVALID_PARAMETER
;
55 else if (LpcMessage
->u2
.s2
.Type
> LPC_CLIENT_DIED
)
57 return STATUS_INVALID_PARAMETER
;
59 /* Check the range offset */
60 if (0 != LpcMessage
->VirtualRangesOffset
)
62 return STATUS_INVALID_PARAMETER
;
66 Status
= EiReplyOrRequestPort(Port
,
70 KeReleaseSemaphore( &Port
->Semaphore
, IO_NO_INCREMENT
, 1, FALSE
);
76 /**********************************************************************
90 NTSTATUS STDCALL
NtRequestPort (IN HANDLE PortHandle
,
91 IN PPORT_MESSAGE LpcMessage
)
96 DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle
,
99 Status
= ObReferenceObjectByHandle(PortHandle
,
105 if (!NT_SUCCESS(Status
))
107 DPRINT("NtRequestPort() = %x\n", Status
);
111 Status
= LpcRequestPort(Port
->OtherPort
,
114 ObDereferenceObject(Port
);
119 /**********************************************************************
121 * NtRequestWaitReplyPort/3
134 NtRequestWaitReplyPort (IN HANDLE PortHandle
,
135 PPORT_MESSAGE UnsafeLpcRequest
,
136 PPORT_MESSAGE UnsafeLpcReply
)
138 PETHREAD CurrentThread
;
139 struct _KPROCESS
*AttachedProcess
;
141 PQUEUEDMESSAGE Message
;
143 PPORT_MESSAGE LpcRequest
;
144 USHORT LpcRequestMessageSize
= 0, LpcRequestDataSize
= 0;
145 KPROCESSOR_MODE PreviousMode
;
146 NTSTATUS Status
= STATUS_SUCCESS
;
148 PreviousMode
= ExGetPreviousMode();
150 if (PreviousMode
!= KernelMode
)
154 ProbeForRead(UnsafeLpcRequest
,
155 sizeof(PORT_MESSAGE
),
157 ProbeForWrite(UnsafeLpcReply
,
158 sizeof(PORT_MESSAGE
),
160 LpcRequestMessageSize
= UnsafeLpcRequest
->u1
.s1
.TotalLength
;
164 Status
= _SEH_GetExceptionCode();
168 if (!NT_SUCCESS(Status
))
175 LpcRequestMessageSize
= UnsafeLpcRequest
->u1
.s1
.TotalLength
;
178 DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, "
179 "LpcReply %x)\n", PortHandle
, UnsafeLpcRequest
, UnsafeLpcReply
);
181 Status
= ObReferenceObjectByHandle(PortHandle
,
187 if (!NT_SUCCESS(Status
))
192 if (EPORT_DISCONNECTED
== Port
->State
)
194 ObDereferenceObject(Port
);
195 return STATUS_PORT_DISCONNECTED
;
198 /* win32k sometimes needs to KeAttach() the CSRSS process in order to make
199 the PortHandle valid. Now that we've got the EPORT structure from the
200 handle we can undo this, so everything is normal again. Need to
201 re-KeAttach() before returning though */
202 CurrentThread
= PsGetCurrentThread();
203 if (&CurrentThread
->ThreadsProcess
->Pcb
== CurrentThread
->Tcb
.ApcState
.Process
)
205 AttachedProcess
= NULL
;
209 AttachedProcess
= CurrentThread
->Tcb
.ApcState
.Process
;
213 if (LpcRequestMessageSize
> LPC_MAX_MESSAGE_LENGTH
)
215 if (NULL
!= AttachedProcess
)
217 KeAttachProcess(AttachedProcess
);
219 ObDereferenceObject(Port
);
220 return(STATUS_PORT_MESSAGE_TOO_LONG
);
222 LpcRequest
= ExAllocatePool(NonPagedPool
, LpcRequestMessageSize
);
223 if (LpcRequest
== NULL
)
225 if (NULL
!= AttachedProcess
)
227 KeAttachProcess(AttachedProcess
);
229 ObDereferenceObject(Port
);
230 return(STATUS_NO_MEMORY
);
232 if (PreviousMode
!= KernelMode
)
236 RtlCopyMemory(LpcRequest
,
238 LpcRequestMessageSize
);
239 LpcRequestMessageSize
= LpcRequest
->u1
.s1
.TotalLength
;
240 LpcRequestDataSize
= LpcRequest
->u1
.s1
.DataLength
;
244 Status
= _SEH_GetExceptionCode();
248 if (!NT_SUCCESS(Status
))
250 ExFreePool(LpcRequest
);
251 if (NULL
!= AttachedProcess
)
253 KeAttachProcess(AttachedProcess
);
255 ObDereferenceObject(Port
);
261 RtlCopyMemory(LpcRequest
,
263 LpcRequestMessageSize
);
264 LpcRequestMessageSize
= LpcRequest
->u1
.s1
.TotalLength
;
265 LpcRequestDataSize
= LpcRequest
->u1
.s1
.DataLength
;
268 if (LpcRequestMessageSize
> LPC_MAX_MESSAGE_LENGTH
)
270 ExFreePool(LpcRequest
);
271 if (NULL
!= AttachedProcess
)
273 KeAttachProcess(AttachedProcess
);
275 ObDereferenceObject(Port
);
276 return(STATUS_PORT_MESSAGE_TOO_LONG
);
278 if (LpcRequestDataSize
> LPC_MAX_DATA_LENGTH
)
280 ExFreePool(LpcRequest
);
281 if (NULL
!= AttachedProcess
)
283 KeAttachProcess(AttachedProcess
);
285 ObDereferenceObject(Port
);
286 return(STATUS_PORT_MESSAGE_TOO_LONG
);
289 Status
= EiReplyOrRequestPort(Port
->OtherPort
,
291 LpcRequest
->u2
.s2
.Type
== LPC_ERROR_EVENT
? LPC_ERROR_EVENT
: LPC_REQUEST
,
293 if (!NT_SUCCESS(Status
))
295 DPRINT1("Enqueue failed\n");
296 ExFreePool(LpcRequest
);
297 if (NULL
!= AttachedProcess
)
299 KeAttachProcess(AttachedProcess
);
301 ObDereferenceObject(Port
);
304 ExFreePool(LpcRequest
);
305 KeReleaseSemaphore (&Port
->OtherPort
->Semaphore
, IO_NO_INCREMENT
,
311 Status
= KeWaitForSingleObject(&Port
->Semaphore
,
316 if (Status
== STATUS_SUCCESS
)
322 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
323 Message
= EiDequeueMessagePort(Port
);
324 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
327 DPRINT("Message->Message.u1.s1.TotalLength %d\n",
328 Message
->Message
.u1
.s1
.TotalLength
);
329 if (PreviousMode
!= KernelMode
)
333 RtlCopyMemory(UnsafeLpcReply
,
335 Message
->Message
.u1
.s1
.TotalLength
);
339 Status
= _SEH_GetExceptionCode();
345 RtlCopyMemory(UnsafeLpcReply
,
347 Message
->Message
.u1
.s1
.TotalLength
);
352 Status
= STATUS_UNSUCCESSFUL
;
356 if (NT_SUCCESS(Status
))
358 Status
= STATUS_UNSUCCESSFUL
;
361 if (NULL
!= AttachedProcess
)
363 KeAttachProcess(AttachedProcess
);
365 ObDereferenceObject(Port
);
371 /**********************************************************************
373 * NtWriteRequestData/6
383 NTSTATUS STDCALL
NtWriteRequestData (HANDLE PortHandle
,
384 PPORT_MESSAGE Message
,
391 return(STATUS_NOT_IMPLEMENTED
);