8d002a770f0301ab8bfe267e94c7a69cd5027ffa
[reactos.git] / reactos / ntoskrnl / lpc / reply.c
1 /* $Id: reply.c,v 1.2 2000/10/22 16:36:51 ekohl 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
19 #define NDEBUG
20 #include <internal/debug.h>
21
22
23
24 /**********************************************************************
25 * NAME
26 *
27 * DESCRIPTION
28 *
29 * ARGUMENTS
30 *
31 * RETURN VALUE
32 *
33 * REVISIONS
34 *
35 */
36 NTSTATUS
37 STDCALL
38 EiReplyOrRequestPort (
39 IN PEPORT Port,
40 IN PLPC_MESSAGE LpcReply,
41 IN ULONG MessageType,
42 IN PEPORT Sender
43 )
44 {
45 KIRQL oldIrql;
46 PQUEUEDMESSAGE MessageReply;
47
48 MessageReply = ExAllocatePool(NonPagedPool, sizeof(QUEUEDMESSAGE));
49 MessageReply->Sender = Sender;
50
51 if (LpcReply != NULL)
52 {
53 memcpy(&MessageReply->Message, LpcReply, LpcReply->MessageSize);
54 }
55
56 MessageReply->Message.Cid.UniqueProcess = PsGetCurrentProcessId();
57 MessageReply->Message.Cid.UniqueThread = PsGetCurrentThreadId();
58 MessageReply->Message.MessageType = MessageType;
59 MessageReply->Message.MessageId = InterlockedIncrement(&EiNextLpcMessageId);
60
61 KeAcquireSpinLock(&Port->Lock, &oldIrql);
62 EiEnqueueMessagePort(Port, MessageReply);
63 KeReleaseSpinLock(&Port->Lock, oldIrql);
64
65 return(STATUS_SUCCESS);
66 }
67
68
69 /**********************************************************************
70 * NAME EXPORTED
71 *
72 * DESCRIPTION
73 *
74 * ARGUMENTS
75 *
76 * RETURN VALUE
77 *
78 * REVISIONS
79 *
80 */
81 NTSTATUS
82 STDCALL
83 NtReplyPort (
84 IN HANDLE PortHandle,
85 IN PLPC_MESSAGE LpcReply
86 )
87 {
88 NTSTATUS Status;
89 PEPORT Port;
90
91 DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle, LpcReply);
92
93 Status = ObReferenceObjectByHandle(PortHandle,
94 PORT_ALL_ACCESS, /* AccessRequired */
95 ExPortType,
96 UserMode,
97 (PVOID*)&Port,
98 NULL);
99 if (!NT_SUCCESS(Status))
100 {
101 DPRINT("NtReplyPort() = %x\n", Status);
102 return(Status);
103 }
104
105 Status = EiReplyOrRequestPort(Port->OtherPort,
106 LpcReply,
107 LPC_REPLY,
108 Port);
109 KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE);
110
111 ObDereferenceObject(Port);
112
113 return(Status);
114 }
115
116
117 /**********************************************************************
118 * NAME EXPORTED
119 *
120 * DESCRIPTION
121 *
122 * ARGUMENTS
123 *
124 * RETURN VALUE
125 *
126 * REVISIONS
127 *
128 */
129 NTSTATUS
130 STDCALL
131 NtReplyWaitReceivePort (
132 HANDLE PortHandle,
133 PULONG PortId,
134 PLPC_MESSAGE LpcReply,
135 PLPC_MESSAGE LpcMessage
136 )
137 {
138 NTSTATUS Status;
139 PEPORT Port;
140 KIRQL oldIrql;
141 PQUEUEDMESSAGE Request;
142
143 DPRINT("NtReplyWaitReceivePort(PortHandle %x, LpcReply %x, "
144 "LpcMessage %x)\n", PortHandle, LpcReply, LpcMessage);
145
146 Status = ObReferenceObjectByHandle(PortHandle,
147 PORT_ALL_ACCESS,
148 ExPortType,
149 UserMode,
150 (PVOID*)&Port,
151 NULL);
152 if (!NT_SUCCESS(Status))
153 {
154 DPRINT("NtReplyWaitReceivePort() = %x\n", Status);
155 return(Status);
156 }
157
158 /*
159 * Send the reply
160 */
161 if (LpcReply != NULL)
162 {
163 Status = EiReplyOrRequestPort(Port->OtherPort,
164 LpcReply,
165 LPC_REPLY,
166 Port);
167 KeSetEvent(&Port->OtherPort->Event, IO_NO_INCREMENT, FALSE);
168
169 if (!NT_SUCCESS(Status))
170 {
171 ObDereferenceObject(Port);
172 return(Status);
173 }
174 }
175
176 /*
177 * Want for a message to be received
178 */
179 DPRINT("Entering wait for message\n");
180 KeWaitForSingleObject(&Port->Event,
181 UserRequest,
182 UserMode,
183 FALSE,
184 NULL);
185 DPRINT("Woke from wait for message\n");
186
187 /*
188 * Dequeue the message
189 */
190 KeAcquireSpinLock(&Port->Lock, &oldIrql);
191 Request = EiDequeueMessagePort(Port);
192 memcpy(LpcMessage, &Request->Message, Request->Message.MessageSize);
193 if (Request->Message.MessageType == LPC_CONNECTION_REQUEST)
194 {
195 EiEnqueueConnectMessagePort(Port, Request);
196 KeReleaseSpinLock(&Port->Lock, oldIrql);
197 }
198 else
199 {
200 KeReleaseSpinLock(&Port->Lock, oldIrql);
201 ExFreePool(Request);
202 }
203
204 /*
205 *
206 */
207 ObDereferenceObject(Port);
208 return(STATUS_SUCCESS);
209 }
210
211
212 /**********************************************************************
213 * NAME
214 *
215 * DESCRIPTION
216 *
217 * ARGUMENTS
218 *
219 * RETURN VALUE
220 *
221 * REVISIONS
222 *
223 */
224 NTSTATUS
225 STDCALL
226 NtReplyWaitReplyPort (
227 HANDLE PortHandle,
228 PLPC_MESSAGE ReplyMessage
229 )
230 {
231 UNIMPLEMENTED;
232 }
233
234
235 /* EOF */