1 /* $Id: reply.c,v 1.6 2001/03/07 16:48:43 dwelch Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/lpc/reply.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/pool.h>
21 #include <internal/debug.h>
23 /* GLOBALS *******************************************************************/
25 #define TAG_LPC_MESSAGE TAG('L', 'P', 'C', 'M')
27 /* FUNCTIONS *****************************************************************/
29 /**********************************************************************
42 EiReplyOrRequestPort (IN PEPORT Port
,
43 IN PLPC_MESSAGE LpcReply
,
48 PQUEUEDMESSAGE MessageReply
;
55 MessageReply
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(QUEUEDMESSAGE
),
57 MessageReply
->Sender
= Sender
;
61 memcpy(&MessageReply
->Message
, LpcReply
, LpcReply
->MessageSize
);
64 MessageReply
->Message
.Cid
.UniqueProcess
= PsGetCurrentProcessId();
65 MessageReply
->Message
.Cid
.UniqueThread
= PsGetCurrentThreadId();
66 MessageReply
->Message
.MessageType
= MessageType
;
67 MessageReply
->Message
.MessageId
= InterlockedIncrement(&EiNextLpcMessageId
);
69 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
70 EiEnqueueMessagePort(Port
, MessageReply
);
71 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
73 return(STATUS_SUCCESS
);
77 /**********************************************************************
90 NtReplyPort (IN HANDLE PortHandle
,
91 IN PLPC_MESSAGE LpcReply
)
96 DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle
, LpcReply
);
98 Status
= ObReferenceObjectByHandle(PortHandle
,
99 PORT_ALL_ACCESS
, /* AccessRequired */
104 if (!NT_SUCCESS(Status
))
106 DPRINT("NtReplyPort() = %x\n", Status
);
110 Status
= EiReplyOrRequestPort(Port
->OtherPort
,
114 KeSetEvent(&Port
->OtherPort
->Event
, IO_NO_INCREMENT
, FALSE
);
116 ObDereferenceObject(Port
);
122 /**********************************************************************
124 * NtReplyWaitReceivePortEx
127 * Can be used with waitable ports.
128 * Present only in w2k+.
143 NtReplyWaitReceivePortEx(IN HANDLE PortHandle
,
145 IN PLPC_MESSAGE LpcReply
,
146 OUT PLPC_MESSAGE LpcMessage
,
147 IN PLARGE_INTEGER Timeout
)
152 PQUEUEDMESSAGE Request
;
154 DPRINT("NtReplyWaitReceivePortEx(PortHandle %x, LpcReply %x, "
155 "LpcMessage %x)\n", PortHandle
, LpcReply
, LpcMessage
);
157 Status
= ObReferenceObjectByHandle(PortHandle
,
163 if (!NT_SUCCESS(Status
))
165 DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status
);
169 if (Port
->State
!= EPORT_CONNECTED_CLIENT
&&
170 Port
->State
!= EPORT_CONNECTED_SERVER
&&
173 DPRINT1("NtReplyWaitReceivePortEx() = %x (State was %x)\n",
174 STATUS_PORT_DISCONNECTED
, Port
->State
);
175 return(STATUS_PORT_DISCONNECTED
);
181 if (LpcReply
!= NULL
)
183 Status
= EiReplyOrRequestPort(Port
->OtherPort
,
187 KeSetEvent(&Port
->OtherPort
->Event
, IO_NO_INCREMENT
, FALSE
);
189 if (!NT_SUCCESS(Status
))
191 ObDereferenceObject(Port
);
192 DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status
);
198 * Want for a message to be received
202 Status
= KeWaitForSingleObject(&Port
->Event
,
207 if (!NT_SUCCESS(Status
))
209 DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status
);
214 * Dequeue the message
216 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
217 Request
= EiDequeueMessagePort(Port
);
220 * There is a race between the event being set and the port lock being
221 * taken in which another thread may dequeue the same request so
222 * we may need to loop.
226 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
228 } while(Request
== NULL
);
230 memcpy(LpcMessage
, &Request
->Message
, Request
->Message
.MessageSize
);
231 if (Request
->Message
.MessageType
== LPC_CONNECTION_REQUEST
)
233 EiEnqueueConnectMessagePort(Port
, Request
);
234 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
238 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
243 * Dereference the port
245 ObDereferenceObject(Port
);
246 return(STATUS_SUCCESS
);
250 /**********************************************************************
252 * NtReplyWaitReceivePort
255 * Can be used with waitable ports.
269 NtReplyWaitReceivePort (IN HANDLE PortHandle
,
271 IN PLPC_MESSAGE LpcReply
,
272 OUT PLPC_MESSAGE LpcMessage
)
274 return NtReplyWaitReceivePortEx (
283 /**********************************************************************
296 NtReplyWaitReplyPort (HANDLE PortHandle
,
297 PLPC_MESSAGE ReplyMessage
)