1 /* $Id: reply.c,v 1.4 2001/01/18 15:00:09 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>
20 #include <internal/debug.h>
22 /* FUNCTIONS *****************************************************************/
24 /**********************************************************************
37 EiReplyOrRequestPort (IN PEPORT Port
,
38 IN PLPC_MESSAGE LpcReply
,
43 PQUEUEDMESSAGE MessageReply
;
50 MessageReply
= ExAllocatePool(NonPagedPool
, sizeof(QUEUEDMESSAGE
));
51 MessageReply
->Sender
= Sender
;
55 memcpy(&MessageReply
->Message
, LpcReply
, LpcReply
->MessageSize
);
58 MessageReply
->Message
.Cid
.UniqueProcess
= PsGetCurrentProcessId();
59 MessageReply
->Message
.Cid
.UniqueThread
= PsGetCurrentThreadId();
60 MessageReply
->Message
.MessageType
= MessageType
;
61 MessageReply
->Message
.MessageId
= InterlockedIncrement(&EiNextLpcMessageId
);
63 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
64 EiEnqueueMessagePort(Port
, MessageReply
);
65 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
67 return(STATUS_SUCCESS
);
71 /**********************************************************************
84 NtReplyPort (IN HANDLE PortHandle
,
85 IN PLPC_MESSAGE LpcReply
)
90 DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle
, LpcReply
);
92 Status
= ObReferenceObjectByHandle(PortHandle
,
93 PORT_ALL_ACCESS
, /* AccessRequired */
98 if (!NT_SUCCESS(Status
))
100 DPRINT("NtReplyPort() = %x\n", Status
);
104 Status
= EiReplyOrRequestPort(Port
->OtherPort
,
108 KeSetEvent(&Port
->OtherPort
->Event
, IO_NO_INCREMENT
, FALSE
);
110 ObDereferenceObject(Port
);
116 /**********************************************************************
129 NtReplyWaitReceivePort (HANDLE PortHandle
,
131 PLPC_MESSAGE LpcReply
,
132 PLPC_MESSAGE LpcMessage
)
137 PQUEUEDMESSAGE Request
;
139 DPRINT("NtReplyWaitReceivePort(PortHandle %x, LpcReply %x, "
140 "LpcMessage %x)\n", PortHandle
, LpcReply
, LpcMessage
);
142 Status
= ObReferenceObjectByHandle(PortHandle
,
148 if (!NT_SUCCESS(Status
))
150 DPRINT1("NtReplyWaitReceivePort() = %x\n", Status
);
154 if (Port
->State
!= EPORT_CONNECTED_CLIENT
&&
155 Port
->State
!= EPORT_CONNECTED_SERVER
&&
158 DPRINT1("NtReplyWaitReceivePort() = %x (State was %x)\n",
159 STATUS_PORT_DISCONNECTED
, Port
->State
);
160 return(STATUS_PORT_DISCONNECTED
);
166 if (LpcReply
!= NULL
)
168 Status
= EiReplyOrRequestPort(Port
->OtherPort
,
172 KeSetEvent(&Port
->OtherPort
->Event
, IO_NO_INCREMENT
, FALSE
);
174 if (!NT_SUCCESS(Status
))
176 ObDereferenceObject(Port
);
177 DPRINT1("NtReplyWaitReceivePort() = %x\n", Status
);
183 * Want for a message to be received
187 Status
= KeWaitForSingleObject(&Port
->Event
,
192 if (!NT_SUCCESS(Status
))
194 DPRINT1("NtReplyWaitReceivePort() = %x\n", Status
);
199 * Dequeue the message
201 KeAcquireSpinLock(&Port
->Lock
, &oldIrql
);
202 Request
= EiDequeueMessagePort(Port
);
205 * There is a race between the event being set and the port lock being
206 * taken in which another thread may dequeue the same request so
207 * we may need to loop.
211 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
213 } while(Request
== NULL
);
215 memcpy(LpcMessage
, &Request
->Message
, Request
->Message
.MessageSize
);
216 if (Request
->Message
.MessageType
== LPC_CONNECTION_REQUEST
)
218 EiEnqueueConnectMessagePort(Port
, Request
);
219 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
223 KeReleaseSpinLock(&Port
->Lock
, oldIrql
);
228 * Dereference the port
230 ObDereferenceObject(Port
);
231 return(STATUS_SUCCESS
);
235 /**********************************************************************
248 NtReplyWaitReplyPort (HANDLE PortHandle
,
249 PLPC_MESSAGE ReplyMessage
)