Reverted latest changes.
[reactos.git] / reactos / ntoskrnl / lpc / send.c
1 /* $Id: send.c,v 1.9 2002/09/08 10:23:32 chorns 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 */
36 NTSTATUS STDCALL
37 LpcSendTerminationPort (IN PEPORT Port,
38 IN TIME CreationTime)
39 {
40 NTSTATUS Status;
41 LPC_TERMINATION_MESSAGE Msg;
42
43 Msg.CreationTime = CreationTime;
44 Status = LpcRequestPort (Port, &Msg.Header);
45 return(Status);
46 }
47
48
49 /**********************************************************************
50 * NAME
51 *
52 * DESCRIPTION
53 *
54 * ARGUMENTS
55 *
56 * RETURN VALUE
57 *
58 * REVISIONS
59 *
60 */
61 NTSTATUS STDCALL
62 LpcSendDebugMessagePort (IN PEPORT Port,
63 IN PLPC_DBG_MESSAGE Message,
64 OUT PLPC_DBG_MESSAGE Reply)
65 {
66 NTSTATUS Status;
67 KIRQL oldIrql;
68 PQUEUEDMESSAGE ReplyMessage;
69
70 Status = EiReplyOrRequestPort(Port,
71 &Message->Header,
72 LPC_REQUEST,
73 Port);
74 if (!NT_SUCCESS(Status))
75 {
76 ObDereferenceObject(Port);
77 return(Status);
78 }
79 KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);
80
81 /*
82 * Wait for a reply
83 */
84 KeWaitForSingleObject(&Port->Semaphore,
85 UserRequest,
86 UserMode,
87 FALSE,
88 NULL);
89
90 /*
91 * Dequeue the reply
92 */
93 KeAcquireSpinLock(&Port->Lock, &oldIrql);
94 ReplyMessage = EiDequeueMessagePort(Port);
95 KeReleaseSpinLock(&Port->Lock, oldIrql);
96 memcpy(Reply, &ReplyMessage->Message, ReplyMessage->Message.MessageSize);
97 ExFreePool(ReplyMessage);
98
99 return(STATUS_SUCCESS);
100 }
101
102
103 /**********************************************************************
104 * NAME
105 *
106 * DESCRIPTION
107 *
108 * ARGUMENTS
109 *
110 * RETURN VALUE
111 *
112 * REVISIONS
113 *
114 */
115 NTSTATUS STDCALL LpcRequestPort (IN PEPORT Port,
116 IN PLPC_MESSAGE LpcMessage)
117 {
118 NTSTATUS Status;
119
120 DPRINT("LpcRequestPort(PortHandle %x LpcMessage %x)\n", Port, LpcMessage);
121
122 Status = EiReplyOrRequestPort(Port,
123 LpcMessage,
124 LPC_DATAGRAM,
125 Port);
126 KeReleaseSemaphore( &Port->Semaphore, IO_NO_INCREMENT, 1, FALSE );
127
128 return(Status);
129 }
130
131
132 /**********************************************************************
133 * NAME
134 *
135 * DESCRIPTION
136 *
137 * ARGUMENTS
138 *
139 * RETURN VALUE
140 *
141 * REVISIONS
142 *
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 */
185 NTSTATUS STDCALL
186 NtRequestWaitReplyPort (IN HANDLE PortHandle,
187 PLPC_MESSAGE UnsafeLpcRequest,
188 PLPC_MESSAGE UnsafeLpcReply)
189 {
190 NTSTATUS Status;
191 PEPORT Port;
192 PQUEUEDMESSAGE Message;
193 KIRQL oldIrql;
194 PLPC_MESSAGE LpcRequest;
195 USHORT LpcRequestMessageSize;
196
197 DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, "
198 "LpcReply %x)\n", PortHandle, UnsafeLpcRequest, UnsafeLpcReply);
199
200 Status = ObReferenceObjectByHandle(PortHandle,
201 PORT_ALL_ACCESS,
202 ExPortType,
203 UserMode,
204 (PVOID*)&Port,
205 NULL);
206 if (!NT_SUCCESS(Status))
207 {
208 return(Status);
209 }
210
211 Status = MmCopyFromCaller(&LpcRequestMessageSize,
212 &UnsafeLpcRequest->MessageSize,
213 sizeof(USHORT));
214 if (!NT_SUCCESS(Status))
215 {
216 ObDereferenceObject(Port);
217 return(Status);
218 }
219 if (LpcRequestMessageSize > (sizeof(LPC_MESSAGE) + MAX_MESSAGE_DATA))
220 {
221 ObDereferenceObject(Port);
222 return(STATUS_PORT_MESSAGE_TOO_LONG);
223 }
224 LpcRequest = ExAllocatePool(NonPagedPool, LpcRequestMessageSize);
225 if (LpcRequest == NULL)
226 {
227 ObDereferenceObject(Port);
228 return(STATUS_NO_MEMORY);
229 }
230 Status = MmCopyFromCaller(LpcRequest, UnsafeLpcRequest,
231 LpcRequestMessageSize);
232 if (!NT_SUCCESS(Status))
233 {
234 ExFreePool(LpcRequest);
235 ObDereferenceObject(Port);
236 return(Status);
237 }
238 LpcRequestMessageSize = LpcRequest->MessageSize;
239 if (LpcRequestMessageSize > (sizeof(LPC_MESSAGE) + MAX_MESSAGE_DATA))
240 {
241 ExFreePool(LpcRequest);
242 ObDereferenceObject(Port);
243 return(STATUS_PORT_MESSAGE_TOO_LONG);
244 }
245 if (LpcRequest->DataSize != (LpcRequest->MessageSize - sizeof(LPC_MESSAGE)))
246 {
247 ExFreePool(LpcRequest);
248 ObDereferenceObject(Port);
249 return(STATUS_PORT_MESSAGE_TOO_LONG);
250 }
251
252 Status = EiReplyOrRequestPort(Port->OtherPort,
253 LpcRequest,
254 LPC_REQUEST,
255 Port);
256 if (!NT_SUCCESS(Status))
257 {
258 DbgPrint("Enqueue failed\n");
259 ExFreePool(LpcRequest);
260 ObDereferenceObject(Port);
261 return(Status);
262 }
263 ExFreePool(LpcRequest);
264 KeReleaseSemaphore (&Port->OtherPort->Semaphore, IO_NO_INCREMENT,
265 1, FALSE);
266
267 /*
268 * Wait for a reply
269 */
270 KeWaitForSingleObject(&Port->Semaphore,
271 UserRequest,
272 UserMode,
273 FALSE,
274 NULL);
275
276 /*
277 * Dequeue the reply
278 */
279 KeAcquireSpinLock(&Port->Lock, &oldIrql);
280 Message = EiDequeueMessagePort(Port);
281 KeReleaseSpinLock(&Port->Lock, oldIrql);
282 DPRINT("Message->Message.MessageSize %d\n",
283 Message->Message.MessageSize);
284 Status = MmCopyToCaller(UnsafeLpcReply, &Message->Message,
285 Message->Message.MessageSize);
286 ExFreePool(Message);
287
288 ObDereferenceObject(Port);
289
290 return(Status);
291 }
292
293
294 /**********************************************************************
295 * NAME
296 *
297 * DESCRIPTION
298 *
299 * ARGUMENTS
300 *
301 * RETURN VALUE
302 *
303 * REVISIONS
304 *
305 */
306 NTSTATUS STDCALL NtWriteRequestData (HANDLE PortHandle,
307 PLPC_MESSAGE Message,
308 ULONG Index,
309 PVOID Buffer,
310 ULONG BufferLength,
311 PULONG ReturnLength)
312 {
313 UNIMPLEMENTED;
314 }
315
316
317 /* EOF */