Fixed LPC port implementation to use an internal semaphore, rather than an
[reactos.git] / reactos / ntoskrnl / lpc / send.c
1 /* $Id: send.c,v 1.5 2001/06/23 19:13:33 phreak 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
19 #define NDEBUG
20 #include <internal/debug.h>
21
22
23 /**********************************************************************
24 * NAME
25 *
26 * DESCRIPTION
27 *
28 * ARGUMENTS
29 *
30 * RETURN VALUE
31 *
32 * REVISIONS
33 *
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 */
60 NTSTATUS STDCALL
61 LpcSendDebugMessagePort (IN PEPORT Port,
62 IN PLPC_DBG_MESSAGE Message,
63 OUT PLPC_DBG_MESSAGE Reply)
64 {
65 NTSTATUS Status;
66 KIRQL oldIrql;
67 PQUEUEDMESSAGE ReplyMessage;
68
69 Status = EiReplyOrRequestPort(Port,
70 &Message->Header,
71 LPC_REQUEST,
72 Port);
73 if (!NT_SUCCESS(Status))
74 {
75 ObDereferenceObject(Port);
76 return(Status);
77 }
78 KeReleaseSemaphore( &Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE );
79
80 /*
81 * Wait for a reply
82 */
83 KeWaitForSingleObject(&Port->Semaphore,
84 UserRequest,
85 UserMode,
86 FALSE,
87 NULL);
88
89 /*
90 * Dequeue the reply
91 */
92 KeAcquireSpinLock(&Port->Lock, &oldIrql);
93 ReplyMessage = EiDequeueMessagePort(Port);
94 KeReleaseSpinLock(&Port->Lock, oldIrql);
95 memcpy(Reply, &ReplyMessage->Message, ReplyMessage->Message.MessageSize);
96 ExFreePool(ReplyMessage);
97
98 return(STATUS_SUCCESS);
99 }
100
101
102 /**********************************************************************
103 * NAME
104 *
105 * DESCRIPTION
106 *
107 * ARGUMENTS
108 *
109 * RETURN VALUE
110 *
111 * REVISIONS
112 *
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 */
143 NTSTATUS STDCALL NtRequestPort (IN HANDLE PortHandle,
144 IN PLPC_MESSAGE LpcMessage)
145 {
146 NTSTATUS Status;
147 PEPORT Port;
148
149 DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle,
150 LpcMessage);
151
152 Status = ObReferenceObjectByHandle(PortHandle,
153 PORT_ALL_ACCESS,
154 ExPortType,
155 UserMode,
156 (PVOID*)&Port,
157 NULL);
158 if (!NT_SUCCESS(Status))
159 {
160 DPRINT("NtRequestPort() = %x\n", Status);
161 return(Status);
162 }
163
164 Status = LpcRequestPort(Port->OtherPort,
165 LpcMessage);
166
167 ObDereferenceObject(Port);
168 return(Status);
169 }
170
171
172 /**********************************************************************
173 * NAME
174 *
175 * DESCRIPTION
176 *
177 * ARGUMENTS
178 *
179 * RETURN VALUE
180 *
181 * REVISIONS
182 *
183 */
184 NTSTATUS STDCALL
185 NtRequestWaitReplyPort (IN HANDLE PortHandle,
186 PLPC_MESSAGE LpcRequest,
187 PLPC_MESSAGE LpcReply)
188 {
189 NTSTATUS Status;
190 PEPORT Port;
191 PQUEUEDMESSAGE Message;
192 KIRQL oldIrql;
193
194 DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, "
195 "LpcReply %x)\n", PortHandle, LpcRequest, LpcReply);
196
197 Status = ObReferenceObjectByHandle(PortHandle,
198 PORT_ALL_ACCESS,
199 ExPortType,
200 UserMode,
201 (PVOID*)&Port,
202 NULL);
203 if (!NT_SUCCESS(Status))
204 {
205 return(Status);
206 }
207
208
209 Status = EiReplyOrRequestPort(Port->OtherPort,
210 LpcRequest,
211 LPC_REQUEST,
212 Port);
213 if (!NT_SUCCESS(Status))
214 {
215 DbgPrint("Enqueue failed\n");
216 ObDereferenceObject(Port);
217 return(Status);
218 }
219 KeReleaseSemaphore( &Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);
220
221 /*
222 * Wait for a reply
223 */
224 KeWaitForSingleObject(&Port->Semaphore,
225 UserRequest,
226 UserMode,
227 FALSE,
228 NULL);
229
230 /*
231 * Dequeue the reply
232 */
233 KeAcquireSpinLock(&Port->Lock, &oldIrql);
234 Message = EiDequeueMessagePort(Port);
235 KeReleaseSpinLock(&Port->Lock, oldIrql);
236 DPRINT("Message->Message.MessageSize %d\n",
237 Message->Message.MessageSize);
238 memcpy(LpcReply, &Message->Message, Message->Message.MessageSize);
239 ExFreePool(Message);
240
241 ObDereferenceObject(Port);
242
243 return(STATUS_SUCCESS);
244 }
245
246
247 /**********************************************************************
248 * NAME
249 *
250 * DESCRIPTION
251 *
252 * ARGUMENTS
253 *
254 * RETURN VALUE
255 *
256 * REVISIONS
257 *
258 */
259 NTSTATUS STDCALL NtWriteRequestData (HANDLE PortHandle,
260 PLPC_MESSAGE Message,
261 ULONG Index,
262 PVOID Buffer,
263 ULONG BufferLength,
264 PULONG ReturnLength)
265 {
266 UNIMPLEMENTED;
267 }
268
269
270 /* EOF */