update for HEAD-2003091401
[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 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 */