1 /* $Id: send.c,v 1.14 2004/01/07 21:13:22 ea 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 *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/port.h>
17 #include <internal/dbg.h>
18 #include <internal/safe.h>
21 #include <internal/debug.h>
24 /**********************************************************************
26 * LpcSendTerminationPort/2
37 LpcSendTerminationPort (IN PEPORT Port
,
41 LPC_TERMINATION_MESSAGE Msg
;
44 Msg
.Header
.MessageType
= LPC_NEW_MESSAGE
;
46 Msg
.CreationTime
= CreationTime
;
47 Status
= LpcRequestPort (Port
, &Msg
.Header
);
52 /**********************************************************************
54 * LpcSendDebugMessagePort/3
65 LpcSendDebugMessagePort (IN PEPORT Port
,
66 IN PLPC_DBG_MESSAGE Message
,
67 OUT PLPC_DBG_MESSAGE Reply
)
71 PQUEUEDMESSAGE ReplyMessage
;
73 Status
= EiReplyOrRequestPort(Port
,
77 if (!NT_SUCCESS(Status
))
79 ObDereferenceObject(Port
);
82 KeReleaseSemaphore(&Port
->OtherPort
->Semaphore
, IO_NO_INCREMENT
, 1, FALSE
);
87 KeWaitForSingleObject(&Port
->Semaphore
,
96 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
97 ReplyMessage
= EiDequeueMessagePort(Port
);
98 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
99 memcpy(Reply
, &ReplyMessage
->Message
, ReplyMessage
->Message
.MessageSize
);
100 ExFreePool(ReplyMessage
);
102 return(STATUS_SUCCESS
);
106 /**********************************************************************
118 * I investigated this function a bit more in depth.
119 * It looks like the legal values for the MessageType field in the
120 * message to send are in the range LPC_NEW_MESSAGE .. LPC_CLIENT_DIED,
121 * but LPC_DATAGRAM is explicitly forbidden.
125 NTSTATUS STDCALL
LpcRequestPort (IN PEPORT Port
,
126 IN PLPC_MESSAGE LpcMessage
)
130 DPRINT("LpcRequestPort(PortHandle %08x, LpcMessage %08x)\n", Port
, LpcMessage
);
132 #ifdef __USE_NT_LPC__
133 /* Check the message's type */
134 if (LPC_NEW_MESSAGE
== LpcMessage
->MessageType
)
136 LpcMessage
->MessageType
= LPC_DATAGRAM
;
138 else if (LPC_DATAGRAM
== LpcMessage
->MessageType
)
140 return STATUS_INVALID_PARAMETER
;
142 else if (LpcMessage
->MessageType
> LPC_CLIENT_DIED
)
144 return STATUS_INVALID_PARAMETER
;
146 /* Check the range offset */
147 if (0 != LpcMessage
->VirtualRangesOffset
)
149 return STATUS_INVALID_PARAMETER
;
153 Status
= EiReplyOrRequestPort(Port
,
157 KeReleaseSemaphore( &Port
->Semaphore
, IO_NO_INCREMENT
, 1, FALSE
);
163 /**********************************************************************
177 NTSTATUS STDCALL
NtRequestPort (IN HANDLE PortHandle
,
178 IN PLPC_MESSAGE LpcMessage
)
183 DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle
,
186 Status
= ObReferenceObjectByHandle(PortHandle
,
192 if (!NT_SUCCESS(Status
))
194 DPRINT("NtRequestPort() = %x\n", Status
);
198 Status
= LpcRequestPort(Port
->OtherPort
,
201 ObDereferenceObject(Port
);
206 /**********************************************************************
208 * NtRequestWaitReplyPort/3
221 NtRequestWaitReplyPort (IN HANDLE PortHandle
,
222 PLPC_MESSAGE UnsafeLpcRequest
,
223 PLPC_MESSAGE UnsafeLpcReply
)
227 PQUEUEDMESSAGE Message
;
229 PLPC_MESSAGE LpcRequest
;
230 USHORT LpcRequestMessageSize
;
232 DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, "
233 "LpcReply %x)\n", PortHandle
, UnsafeLpcRequest
, UnsafeLpcReply
);
235 Status
= ObReferenceObjectByHandle(PortHandle
,
241 if (!NT_SUCCESS(Status
))
246 Status
= MmCopyFromCaller(&LpcRequestMessageSize
,
247 &UnsafeLpcRequest
->MessageSize
,
249 if (!NT_SUCCESS(Status
))
251 ObDereferenceObject(Port
);
254 if (LpcRequestMessageSize
> (sizeof(LPC_MESSAGE
) + MAX_MESSAGE_DATA
))
256 ObDereferenceObject(Port
);
257 return(STATUS_PORT_MESSAGE_TOO_LONG
);
259 LpcRequest
= ExAllocatePool(NonPagedPool
, LpcRequestMessageSize
);
260 if (LpcRequest
== NULL
)
262 ObDereferenceObject(Port
);
263 return(STATUS_NO_MEMORY
);
265 Status
= MmCopyFromCaller(LpcRequest
, UnsafeLpcRequest
,
266 LpcRequestMessageSize
);
267 if (!NT_SUCCESS(Status
))
269 ExFreePool(LpcRequest
);
270 ObDereferenceObject(Port
);
273 LpcRequestMessageSize
= LpcRequest
->MessageSize
;
274 if (LpcRequestMessageSize
> (sizeof(LPC_MESSAGE
) + MAX_MESSAGE_DATA
))
276 ExFreePool(LpcRequest
);
277 ObDereferenceObject(Port
);
278 return(STATUS_PORT_MESSAGE_TOO_LONG
);
280 if (LpcRequest
->DataSize
!= (LpcRequest
->MessageSize
- sizeof(LPC_MESSAGE
)))
282 ExFreePool(LpcRequest
);
283 ObDereferenceObject(Port
);
284 return(STATUS_PORT_MESSAGE_TOO_LONG
);
287 Status
= EiReplyOrRequestPort(Port
->OtherPort
,
291 if (!NT_SUCCESS(Status
))
293 DbgPrint("Enqueue failed\n");
294 ExFreePool(LpcRequest
);
295 ObDereferenceObject(Port
);
298 ExFreePool(LpcRequest
);
299 KeReleaseSemaphore (&Port
->OtherPort
->Semaphore
, IO_NO_INCREMENT
,
305 Status
= KeWaitForSingleObject(&Port
->Semaphore
,
310 if (Status
== STATUS_SUCCESS
)
316 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
317 Message
= EiDequeueMessagePort(Port
);
318 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
321 DPRINT("Message->Message.MessageSize %d\n",
322 Message
->Message
.MessageSize
);
323 Status
= MmCopyToCaller(UnsafeLpcReply
, &Message
->Message
,
324 Message
->Message
.MessageSize
);
328 Status
= STATUS_UNSUCCESSFUL
;
332 if (NT_SUCCESS(Status
))
334 Status
= STATUS_UNSUCCESSFUL
;
337 ObDereferenceObject(Port
);
343 /**********************************************************************
345 * NtWriteRequestData/6
355 NTSTATUS STDCALL
NtWriteRequestData (HANDLE PortHandle
,
356 PLPC_MESSAGE Message
,
363 return(STATUS_NOT_IMPLEMENTED
);