- Check for the status after calling KeWaitForSingleObject in NtRequestWaitReplyPort.
[reactos.git] / reactos / ntoskrnl / lpc / send.c
1 /* $Id: send.c,v 1.12 2003/08/18 11:48:19 hbirr Exp $
2 *
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)
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 #include <internal/safe.h>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23
24 /**********************************************************************
25 * NAME
26 *
27 * DESCRIPTION
28 *
29 * ARGUMENTS
30 *
31 * RETURN VALUE
32 *
33 * REVISIONS
34 */
35 NTSTATUS STDCALL
36 LpcSendTerminationPort (IN PEPORT Port,
37 IN TIME CreationTime)
38 {
39 NTSTATUS Status;
40 LPC_TERMINATION_MESSAGE Msg;
41
42 Msg.CreationTime = CreationTime;
43 Status = LpcRequestPort (Port, &Msg.Header);
44 return(Status);
45 }
46
47
48 /**********************************************************************
49 * NAME
50 *
51 * DESCRIPTION
52 *
53 * ARGUMENTS
54 *
55 * RETURN VALUE
56 *
57 * REVISIONS
58 */
59 NTSTATUS STDCALL
60 LpcSendDebugMessagePort (IN PEPORT Port,
61 IN PLPC_DBG_MESSAGE Message,
62 OUT PLPC_DBG_MESSAGE Reply)
63 {
64 NTSTATUS Status;
65 KIRQL oldIrql;
66 PQUEUEDMESSAGE ReplyMessage;
67
68 Status = EiReplyOrRequestPort(Port,
69 &Message->Header,
70 LPC_REQUEST,
71 Port);
72 if (!NT_SUCCESS(Status))
73 {
74 ObDereferenceObject(Port);
75 return(Status);
76 }
77 KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);
78
79 /*
80 * Wait for a reply
81 */
82 KeWaitForSingleObject(&Port->Semaphore,
83 UserRequest,
84 UserMode,
85 FALSE,
86 NULL);
87
88 /*
89 * Dequeue the reply
90 */
91 KeAcquireSpinLock(&Port->Lock, &oldIrql);
92 ReplyMessage = EiDequeueMessagePort(Port);
93 KeReleaseSpinLock(&Port->Lock, oldIrql);
94 memcpy(Reply, &ReplyMessage->Message, ReplyMessage->Message.MessageSize);
95 ExFreePool(ReplyMessage);
96
97 return(STATUS_SUCCESS);
98 }
99
100
101 /**********************************************************************
102 * NAME
103 *
104 * DESCRIPTION
105 *
106 * ARGUMENTS
107 *
108 * RETURN VALUE
109 *
110 * REVISIONS
111 *
112 * @implemented
113 */
114 NTSTATUS STDCALL LpcRequestPort (IN PEPORT Port,
115 IN PLPC_MESSAGE LpcMessage)
116 {
117 NTSTATUS Status;
118
119 DPRINT("LpcRequestPort(PortHandle %x LpcMessage %x)\n", Port, LpcMessage);
120
121 Status = EiReplyOrRequestPort(Port,
122 LpcMessage,
123 LPC_DATAGRAM,
124 Port);
125 KeReleaseSemaphore( &Port->Semaphore, IO_NO_INCREMENT, 1, FALSE );
126
127 return(Status);
128 }
129
130
131 /**********************************************************************
132 * NAME
133 *
134 * DESCRIPTION
135 *
136 * ARGUMENTS
137 *
138 * RETURN VALUE
139 *
140 * REVISIONS
141 *
142 * @implemented
143 */
144 NTSTATUS STDCALL NtRequestPort (IN HANDLE PortHandle,
145 IN PLPC_MESSAGE LpcMessage)
146 {
147 NTSTATUS Status;
148 PEPORT Port;
149
150 DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle,
151 LpcMessage);
152
153 Status = ObReferenceObjectByHandle(PortHandle,
154 PORT_ALL_ACCESS,
155 ExPortType,
156 UserMode,
157 (PVOID*)&Port,
158 NULL);
159 if (!NT_SUCCESS(Status))
160 {
161 DPRINT("NtRequestPort() = %x\n", Status);
162 return(Status);
163 }
164
165 Status = LpcRequestPort(Port->OtherPort,
166 LpcMessage);
167
168 ObDereferenceObject(Port);
169 return(Status);
170 }
171
172
173 /**********************************************************************
174 * NAME
175 *
176 * DESCRIPTION
177 *
178 * ARGUMENTS
179 *
180 * RETURN VALUE
181 *
182 * REVISIONS
183 *
184 * @implemented
185 */
186 NTSTATUS STDCALL
187 NtRequestWaitReplyPort (IN HANDLE PortHandle,
188 PLPC_MESSAGE UnsafeLpcRequest,
189 PLPC_MESSAGE UnsafeLpcReply)
190 {
191 NTSTATUS Status;
192 PEPORT Port;
193 PQUEUEDMESSAGE Message;
194 KIRQL oldIrql;
195 PLPC_MESSAGE LpcRequest;
196 USHORT LpcRequestMessageSize;
197
198 DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, "
199 "LpcReply %x)\n", PortHandle, UnsafeLpcRequest, UnsafeLpcReply);
200
201 Status = ObReferenceObjectByHandle(PortHandle,
202 PORT_ALL_ACCESS,
203 ExPortType,
204 UserMode,
205 (PVOID*)&Port,
206 NULL);
207 if (!NT_SUCCESS(Status))
208 {
209 return(Status);
210 }
211
212 Status = MmCopyFromCaller(&LpcRequestMessageSize,
213 &UnsafeLpcRequest->MessageSize,
214 sizeof(USHORT));
215 if (!NT_SUCCESS(Status))
216 {
217 ObDereferenceObject(Port);
218 return(Status);
219 }
220 if (LpcRequestMessageSize > (sizeof(LPC_MESSAGE) + MAX_MESSAGE_DATA))
221 {
222 ObDereferenceObject(Port);
223 return(STATUS_PORT_MESSAGE_TOO_LONG);
224 }
225 LpcRequest = ExAllocatePool(NonPagedPool, LpcRequestMessageSize);
226 if (LpcRequest == NULL)
227 {
228 ObDereferenceObject(Port);
229 return(STATUS_NO_MEMORY);
230 }
231 Status = MmCopyFromCaller(LpcRequest, UnsafeLpcRequest,
232 LpcRequestMessageSize);
233 if (!NT_SUCCESS(Status))
234 {
235 ExFreePool(LpcRequest);
236 ObDereferenceObject(Port);
237 return(Status);
238 }
239 LpcRequestMessageSize = LpcRequest->MessageSize;
240 if (LpcRequestMessageSize > (sizeof(LPC_MESSAGE) + MAX_MESSAGE_DATA))
241 {
242 ExFreePool(LpcRequest);
243 ObDereferenceObject(Port);
244 return(STATUS_PORT_MESSAGE_TOO_LONG);
245 }
246 if (LpcRequest->DataSize != (LpcRequest->MessageSize - sizeof(LPC_MESSAGE)))
247 {
248 ExFreePool(LpcRequest);
249 ObDereferenceObject(Port);
250 return(STATUS_PORT_MESSAGE_TOO_LONG);
251 }
252
253 Status = EiReplyOrRequestPort(Port->OtherPort,
254 LpcRequest,
255 LPC_REQUEST,
256 Port);
257 if (!NT_SUCCESS(Status))
258 {
259 DbgPrint("Enqueue failed\n");
260 ExFreePool(LpcRequest);
261 ObDereferenceObject(Port);
262 return(Status);
263 }
264 ExFreePool(LpcRequest);
265 KeReleaseSemaphore (&Port->OtherPort->Semaphore, IO_NO_INCREMENT,
266 1, FALSE);
267
268 /*
269 * Wait for a reply
270 */
271 Status = KeWaitForSingleObject(&Port->Semaphore,
272 UserRequest,
273 UserMode,
274 FALSE,
275 NULL);
276 if (Status == STATUS_SUCCESS)
277 {
278
279 /*
280 * Dequeue the reply
281 */
282 KeAcquireSpinLock(&Port->Lock, &oldIrql);
283 Message = EiDequeueMessagePort(Port);
284 KeReleaseSpinLock(&Port->Lock, oldIrql);
285 if (Message)
286 {
287 DPRINT("Message->Message.MessageSize %d\n",
288 Message->Message.MessageSize);
289 Status = MmCopyToCaller(UnsafeLpcReply, &Message->Message,
290 Message->Message.MessageSize);
291 ExFreePool(Message);
292 }
293 else
294 Status = STATUS_UNSUCCESSFUL;
295 }
296 else
297 {
298 if (NT_SUCCESS(Status))
299 {
300 Status = STATUS_UNSUCCESSFUL;
301 }
302 }
303 ObDereferenceObject(Port);
304
305 return(Status);
306 }
307
308
309 /**********************************************************************
310 * NAME
311 *
312 * DESCRIPTION
313 *
314 * ARGUMENTS
315 *
316 * RETURN VALUE
317 *
318 * REVISIONS
319 */
320 NTSTATUS STDCALL NtWriteRequestData (HANDLE PortHandle,
321 PLPC_MESSAGE Message,
322 ULONG Index,
323 PVOID Buffer,
324 ULONG BufferLength,
325 PULONG ReturnLength)
326 {
327 UNIMPLEMENTED;
328 }
329
330
331 /* EOF */