:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / ntoskrnl / lpc / send.c
1 /* $Id$
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 */