Implemented /Device/PhysicalMemory
[reactos.git] / reactos / ntoskrnl / lpc / reply.c
1 /* $Id: reply.c,v 1.3 2000/12/28 03:38:07 dwelch Exp $
2 *
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)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/port.h>
17 #include <internal/dbg.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 /* FUNCTIONS *****************************************************************/
23
24 /**********************************************************************
25 * NAME
26 *
27 * DESCRIPTION
28 *
29 * ARGUMENTS
30 *
31 * RETURN VALUE
32 *
33 * REVISIONS
34 *
35 */
36 NTSTATUS STDCALL
37 EiReplyOrRequestPort (IN PEPORT Port,
38 IN PLPC_MESSAGE LpcReply,
39 IN ULONG MessageType,
40 IN PEPORT Sender)
41 {
42 KIRQL oldIrql;
43 PQUEUEDMESSAGE MessageReply;
44
45 MessageReply = ExAllocatePool(NonPagedPool, sizeof(QUEUEDMESSAGE));
46 MessageReply->Sender = Sender;
47
48 if (LpcReply != NULL)
49 {
50 memcpy(&MessageReply->Message, LpcReply, LpcReply->MessageSize);
51 }
52
53 MessageReply->Message.Cid.UniqueProcess = PsGetCurrentProcessId();
54 MessageReply->Message.Cid.UniqueThread = PsGetCurrentThreadId();
55 MessageReply->Message.MessageType = MessageType;
56 MessageReply->Message.MessageId = InterlockedIncrement(&EiNextLpcMessageId);
57
58 KeAcquireSpinLock(&Port->Lock, &oldIrql);
59 EiEnqueueMessagePort(Port, MessageReply);
60 KeReleaseSpinLock(&Port->Lock, oldIrql);
61
62 return(STATUS_SUCCESS);
63 }
64
65
66 /**********************************************************************
67 * NAME EXPORTED
68 *
69 * DESCRIPTION
70 *
71 * ARGUMENTS
72 *
73 * RETURN VALUE
74 *
75 * REVISIONS
76 *
77 */
78 NTSTATUS STDCALL
79 NtReplyPort (IN HANDLE PortHandle,
80 IN PLPC_MESSAGE LpcReply)
81 {
82 NTSTATUS Status;
83 PEPORT Port;
84
85 DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle, LpcReply);
86
87 Status = ObReferenceObjectByHandle(PortHandle,
88 PORT_ALL_ACCESS, /* AccessRequired */
89 ExPortType,
90 UserMode,
91 (PVOID*)&Port,
92 NULL);
93 if (!NT_SUCCESS(Status))
94 {
95 DPRINT("NtReplyPort() = %x\n", Status);
96 return(Status);
97 }
98
99 Status = EiReplyOrRequestPort(Port->OtherPort,
100 LpcReply,
101 LPC_REPLY,
102 Port);
103 KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE);
104
105 ObDereferenceObject(Port);
106
107 return(Status);
108 }
109
110
111 /**********************************************************************
112 * NAME EXPORTED
113 *
114 * DESCRIPTION
115 *
116 * ARGUMENTS
117 *
118 * RETURN VALUE
119 *
120 * REVISIONS
121 *
122 */
123 NTSTATUS STDCALL
124 NtReplyWaitReceivePort (HANDLE PortHandle,
125 PULONG PortId,
126 PLPC_MESSAGE LpcReply,
127 PLPC_MESSAGE LpcMessage)
128 {
129 NTSTATUS Status;
130 PEPORT Port;
131 KIRQL oldIrql;
132 PQUEUEDMESSAGE Request;
133
134 DPRINT("NtReplyWaitReceivePort(PortHandle %x, LpcReply %x, "
135 "LpcMessage %x)\n", PortHandle, LpcReply, LpcMessage);
136
137 Status = ObReferenceObjectByHandle(PortHandle,
138 PORT_ALL_ACCESS,
139 ExPortType,
140 UserMode,
141 (PVOID*)&Port,
142 NULL);
143 if (!NT_SUCCESS(Status))
144 {
145 DPRINT("NtReplyWaitReceivePort() = %x\n", Status);
146 return(Status);
147 }
148
149 /*
150 * Send the reply
151 */
152 if (LpcReply != NULL)
153 {
154 Status = EiReplyOrRequestPort(Port->OtherPort,
155 LpcReply,
156 LPC_REPLY,
157 Port);
158 KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE);
159
160 if (!NT_SUCCESS(Status))
161 {
162 ObDereferenceObject(Port);
163 return(Status);
164 }
165 }
166
167 /*
168 * Want for a message to be received
169 */
170 do
171 {
172 Status = KeWaitForSingleObject(&Port->Event,
173 UserRequest,
174 UserMode,
175 FALSE,
176 NULL);
177 if (!NT_SUCCESS(Status))
178 {
179 return(Status);
180 }
181
182 /*
183 * Dequeue the message
184 */
185 KeAcquireSpinLock(&Port->Lock, &oldIrql);
186 Request = EiDequeueMessagePort(Port);
187
188 /*
189 * There is a race between the event being set and the port being
190 * taken in which another thread may dequeue the same request so
191 * we may need to loop.
192 */
193 if (Request == NULL)
194 {
195 KeReleaseSpinLock(&Port->Lock, oldIrql);
196 }
197 } while(Request == NULL);
198
199 memcpy(LpcMessage, &Request->Message, Request->Message.MessageSize);
200 if (Request->Message.MessageType == LPC_CONNECTION_REQUEST)
201 {
202 EiEnqueueConnectMessagePort(Port, Request);
203 KeReleaseSpinLock(&Port->Lock, oldIrql);
204 }
205 else
206 {
207 KeReleaseSpinLock(&Port->Lock, oldIrql);
208 ExFreePool(Request);
209 }
210
211 /*
212 * Dereference the port
213 */
214 ObDereferenceObject(Port);
215 return(STATUS_SUCCESS);
216 }
217
218
219 /**********************************************************************
220 * NAME
221 *
222 * DESCRIPTION
223 *
224 * ARGUMENTS
225 *
226 * RETURN VALUE
227 *
228 * REVISIONS
229 *
230 */
231 NTSTATUS STDCALL
232 NtReplyWaitReplyPort (HANDLE PortHandle,
233 PLPC_MESSAGE ReplyMessage)
234 {
235 UNIMPLEMENTED;
236 }
237
238
239 /* EOF */