Added tagging of most allocates
[reactos.git] / reactos / ntoskrnl / lpc / reply.c
1 /* $Id: reply.c,v 1.6 2001/03/07 16:48:43 dwelch Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/lpc/reply.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/pool.h>
19
20 #define NDEBUG
21 #include <internal/debug.h>
22
23 /* GLOBALS *******************************************************************/
24
25 #define TAG_LPC_MESSAGE TAG('L', 'P', 'C', 'M')
26
27 /* FUNCTIONS *****************************************************************/
28
29 /**********************************************************************
30 * NAME
31 *
32 * DESCRIPTION
33 *
34 * ARGUMENTS
35 *
36 * RETURN VALUE
37 *
38 * REVISIONS
39 *
40 */
41 NTSTATUS STDCALL
42 EiReplyOrRequestPort (IN PEPORT Port,
43 IN PLPC_MESSAGE LpcReply,
44 IN ULONG MessageType,
45 IN PEPORT Sender)
46 {
47 KIRQL oldIrql;
48 PQUEUEDMESSAGE MessageReply;
49
50 if (Port == NULL)
51 {
52 KeBugCheck(0);
53 }
54
55 MessageReply = ExAllocatePoolWithTag(NonPagedPool, sizeof(QUEUEDMESSAGE),
56 TAG_LPC_MESSAGE);
57 MessageReply->Sender = Sender;
58
59 if (LpcReply != NULL)
60 {
61 memcpy(&MessageReply->Message, LpcReply, LpcReply->MessageSize);
62 }
63
64 MessageReply->Message.Cid.UniqueProcess = PsGetCurrentProcessId();
65 MessageReply->Message.Cid.UniqueThread = PsGetCurrentThreadId();
66 MessageReply->Message.MessageType = MessageType;
67 MessageReply->Message.MessageId = InterlockedIncrement(&EiNextLpcMessageId);
68
69 KeAcquireSpinLock(&Port->Lock, &oldIrql);
70 EiEnqueueMessagePort(Port, MessageReply);
71 KeReleaseSpinLock(&Port->Lock, oldIrql);
72
73 return(STATUS_SUCCESS);
74 }
75
76
77 /**********************************************************************
78 * NAME EXPORTED
79 *
80 * DESCRIPTION
81 *
82 * ARGUMENTS
83 *
84 * RETURN VALUE
85 *
86 * REVISIONS
87 *
88 */
89 NTSTATUS STDCALL
90 NtReplyPort (IN HANDLE PortHandle,
91 IN PLPC_MESSAGE LpcReply)
92 {
93 NTSTATUS Status;
94 PEPORT Port;
95
96 DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle, LpcReply);
97
98 Status = ObReferenceObjectByHandle(PortHandle,
99 PORT_ALL_ACCESS, /* AccessRequired */
100 ExPortType,
101 UserMode,
102 (PVOID*)&Port,
103 NULL);
104 if (!NT_SUCCESS(Status))
105 {
106 DPRINT("NtReplyPort() = %x\n", Status);
107 return(Status);
108 }
109
110 Status = EiReplyOrRequestPort(Port->OtherPort,
111 LpcReply,
112 LPC_REPLY,
113 Port);
114 KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE);
115
116 ObDereferenceObject(Port);
117
118 return(Status);
119 }
120
121
122 /**********************************************************************
123 * NAME EXPORTED
124 * NtReplyWaitReceivePortEx
125 *
126 * DESCRIPTION
127 * Can be used with waitable ports.
128 * Present only in w2k+.
129 *
130 * ARGUMENTS
131 * PortHandle
132 * PortId
133 * LpcReply
134 * LpcMessage
135 * Timeout
136 *
137 * RETURN VALUE
138 *
139 * REVISIONS
140 *
141 */
142 NTSTATUS STDCALL
143 NtReplyWaitReceivePortEx(IN HANDLE PortHandle,
144 OUT PULONG PortId,
145 IN PLPC_MESSAGE LpcReply,
146 OUT PLPC_MESSAGE LpcMessage,
147 IN PLARGE_INTEGER Timeout)
148 {
149 NTSTATUS Status;
150 PEPORT Port;
151 KIRQL oldIrql;
152 PQUEUEDMESSAGE Request;
153
154 DPRINT("NtReplyWaitReceivePortEx(PortHandle %x, LpcReply %x, "
155 "LpcMessage %x)\n", PortHandle, LpcReply, LpcMessage);
156
157 Status = ObReferenceObjectByHandle(PortHandle,
158 PORT_ALL_ACCESS,
159 ExPortType,
160 UserMode,
161 (PVOID*)&Port,
162 NULL);
163 if (!NT_SUCCESS(Status))
164 {
165 DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status);
166 return(Status);
167 }
168
169 if (Port->State != EPORT_CONNECTED_CLIENT &&
170 Port->State != EPORT_CONNECTED_SERVER &&
171 LpcReply != NULL)
172 {
173 DPRINT1("NtReplyWaitReceivePortEx() = %x (State was %x)\n",
174 STATUS_PORT_DISCONNECTED, Port->State);
175 return(STATUS_PORT_DISCONNECTED);
176 }
177
178 /*
179 * Send the reply
180 */
181 if (LpcReply != NULL)
182 {
183 Status = EiReplyOrRequestPort(Port->OtherPort,
184 LpcReply,
185 LPC_REPLY,
186 Port);
187 KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE);
188
189 if (!NT_SUCCESS(Status))
190 {
191 ObDereferenceObject(Port);
192 DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status);
193 return(Status);
194 }
195 }
196
197 /*
198 * Want for a message to be received
199 */
200 do
201 {
202 Status = KeWaitForSingleObject(&Port->Event,
203 UserRequest,
204 UserMode,
205 FALSE,
206 NULL);
207 if (!NT_SUCCESS(Status))
208 {
209 DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status);
210 return(Status);
211 }
212
213 /*
214 * Dequeue the message
215 */
216 KeAcquireSpinLock(&Port->Lock, &oldIrql);
217 Request = EiDequeueMessagePort(Port);
218
219 /*
220 * There is a race between the event being set and the port lock being
221 * taken in which another thread may dequeue the same request so
222 * we may need to loop.
223 */
224 if (Request == NULL)
225 {
226 KeReleaseSpinLock(&Port->Lock, oldIrql);
227 }
228 } while(Request == NULL);
229
230 memcpy(LpcMessage, &Request->Message, Request->Message.MessageSize);
231 if (Request->Message.MessageType == LPC_CONNECTION_REQUEST)
232 {
233 EiEnqueueConnectMessagePort(Port, Request);
234 KeReleaseSpinLock(&Port->Lock, oldIrql);
235 }
236 else
237 {
238 KeReleaseSpinLock(&Port->Lock, oldIrql);
239 ExFreePool(Request);
240 }
241
242 /*
243 * Dereference the port
244 */
245 ObDereferenceObject(Port);
246 return(STATUS_SUCCESS);
247 }
248
249
250 /**********************************************************************
251 * NAME EXPORTED
252 * NtReplyWaitReceivePort
253 *
254 * DESCRIPTION
255 * Can be used with waitable ports.
256 *
257 * ARGUMENTS
258 * PortHandle
259 * PortId
260 * LpcReply
261 * LpcMessage
262 *
263 * RETURN VALUE
264 *
265 * REVISIONS
266 *
267 */
268 NTSTATUS STDCALL
269 NtReplyWaitReceivePort (IN HANDLE PortHandle,
270 OUT PULONG PortId,
271 IN PLPC_MESSAGE LpcReply,
272 OUT PLPC_MESSAGE LpcMessage)
273 {
274 return NtReplyWaitReceivePortEx (
275 PortHandle,
276 PortId,
277 LpcReply,
278 LpcMessage,
279 NULL
280 );
281 }
282
283 /**********************************************************************
284 * NAME
285 *
286 * DESCRIPTION
287 *
288 * ARGUMENTS
289 *
290 * RETURN VALUE
291 *
292 * REVISIONS
293 *
294 */
295 NTSTATUS STDCALL
296 NtReplyWaitReplyPort (HANDLE PortHandle,
297 PLPC_MESSAGE ReplyMessage)
298 {
299 UNIMPLEMENTED;
300 }
301
302
303 /* EOF */