b8eb952d405f26d29e1e47d0f43830e032237596
[reactos.git] / reactos / ntoskrnl / lpc / connect.c
1 /* $Id: connect.c,v 1.3 2001/01/18 15:00:09 dwelch Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/lpc/connect.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 EXPORTED
25 * NtConnectPort@32
26 *
27 * DESCRIPTION
28 * Connect to a named port and wait for the other side to
29 * accept the connection.
30 *
31 * ARGUMENTS
32 * ConnectedPort
33 * PortName
34 * Qos
35 * WriteMap
36 * ReadMap
37 * MaxMessageSize
38 * ConnectInfo
39 * UserConnectInfoLength
40 *
41 * RETURN VALUE
42 *
43 */
44 NTSTATUS STDCALL
45 NtConnectPort (PHANDLE ConnectedPort,
46 PUNICODE_STRING PortName,
47 PSECURITY_QUALITY_OF_SERVICE Qos,
48 PLPC_SECTION_WRITE WriteMap,
49 PLPC_SECTION_READ ReadMap,
50 PULONG MaxMessageSize,
51 PVOID ConnectInfo,
52 PULONG UserConnectInfoLength)
53 {
54 NTSTATUS Status;
55 PEPORT NamedPort;
56 PEPORT OurPort;
57 HANDLE OurPortHandle;
58 PLPC_MESSAGE Request;
59 PQUEUEDMESSAGE Reply;
60 ULONG ConnectInfoLength;
61 KIRQL oldIrql;
62
63 DPRINT("PortName %x\n", PortName);
64 DPRINT("NtConnectPort(PortName %S)\n", PortName->Buffer);
65
66 /*
67 * Copy in user parameters
68 */
69 memcpy (&ConnectInfoLength, UserConnectInfoLength,
70 sizeof (*UserConnectInfoLength));
71
72 /*
73 * Get access to the port
74 */
75 Status = ObReferenceObjectByName (PortName,
76 0,
77 NULL,
78 PORT_ALL_ACCESS, /* DesiredAccess */
79 ExPortType,
80 UserMode,
81 NULL,
82 (PVOID*)&NamedPort);
83 if (!NT_SUCCESS(Status))
84 {
85 DPRINT("Failed to reference named port (status %x)\n", Status);
86 return (Status);
87 }
88 /*
89 * Create a port to represent our side of the connection
90 */
91 OurPort = ObCreateObject (&OurPortHandle,
92 PORT_ALL_ACCESS,
93 NULL,
94 ExPortType);
95 NiInitializePort(OurPort);
96 /*
97 * Create a request message
98 */
99 DPRINT("Creating request message\n");
100
101 Request = ExAllocatePool (NonPagedPool,
102 (sizeof (LPC_MESSAGE) + ConnectInfoLength));
103
104 Request->DataSize = ConnectInfoLength;
105 Request->MessageSize = sizeof(LPC_MESSAGE) + ConnectInfoLength;
106 Request->SharedSectionSize = 0;
107 if ((ConnectInfo != NULL) && (ConnectInfoLength > 0))
108 {
109 memcpy ((PVOID) (Request + 1), ConnectInfo, ConnectInfoLength);
110 }
111 /*
112 * Queue the message to the named port
113 */
114 DPRINT("Queuing message\n");
115
116 EiReplyOrRequestPort (NamedPort,
117 Request,
118 LPC_CONNECTION_REQUEST,
119 OurPort);
120 KeSetEvent (&NamedPort->Event, IO_NO_INCREMENT, FALSE);
121
122 DPRINT("Waiting for connection completion\n");
123
124 /*
125 * Wait for them to accept our connection
126 */
127 KeWaitForSingleObject (&OurPort->Event,
128 UserRequest,
129 UserMode,
130 FALSE,
131 NULL);
132
133 DPRINT("Received connection completion\n");
134 KeAcquireSpinLock (&OurPort->Lock, &oldIrql);
135 Reply = EiDequeueMessagePort (OurPort);
136 KeReleaseSpinLock (&OurPort->Lock, oldIrql);
137 memcpy (ConnectInfo, Reply->MessageData, Reply->Message.DataSize);
138 *UserConnectInfoLength = Reply->Message.DataSize;
139
140 if (Reply->Message.MessageType == LPC_CONNECTION_REFUSED)
141 {
142 ObDereferenceObject (NamedPort);
143 ObDereferenceObject (OurPort);
144 ZwClose (OurPortHandle);
145 ExFreePool (Request);
146 ExFreePool (Reply);
147 return (STATUS_UNSUCCESSFUL);
148 }
149
150 OurPort->State = EPORT_CONNECTED_CLIENT;
151 *ConnectedPort = OurPortHandle;
152 ExFreePool (Reply);
153 ExFreePool (Request);
154
155 DPRINT("Exited successfully\n");
156
157 return (STATUS_SUCCESS);
158 }
159
160
161 /**********************************************************************
162 * NAME EXPORTED
163 * NtAcceptConnectPort@24
164 *
165 * DESCRIPTION
166 *
167 * ARGUMENTS
168 * ServerPortHandle
169 * NamedPortHandle
170 * LpcMessage
171 * AcceptIt
172 * WriteMap
173 * ReadMap
174 *
175 * RETURN VALUE
176 *
177 */
178 EXPORTED NTSTATUS STDCALL
179 NtAcceptConnectPort (PHANDLE ServerPortHandle,
180 HANDLE NamedPortHandle,
181 PLPC_MESSAGE LpcMessage,
182 BOOLEAN AcceptIt,
183 PLPC_SECTION_WRITE WriteMap,
184 PLPC_SECTION_READ ReadMap)
185 {
186 NTSTATUS Status;
187 PEPORT NamedPort;
188 PEPORT OurPort = NULL;
189 PQUEUEDMESSAGE ConnectionRequest;
190 KIRQL oldIrql;
191
192 Status = ObReferenceObjectByHandle (NamedPortHandle,
193 PORT_ALL_ACCESS,
194 ExPortType,
195 UserMode,
196 (PVOID*)&NamedPort,
197 NULL);
198 if (!NT_SUCCESS(Status))
199 {
200 return (Status);
201 }
202 /*
203 * Create a port object for our side of the connection
204 */
205 if (AcceptIt == 1)
206 {
207 OurPort = ObCreateObject (ServerPortHandle,
208 PORT_ALL_ACCESS,
209 NULL,
210 ExPortType);
211 NiInitializePort(OurPort);
212 }
213 /*
214 * Dequeue the connection request
215 */
216 KeAcquireSpinLock (&NamedPort->Lock, & oldIrql);
217 ConnectionRequest = EiDequeueConnectMessagePort (NamedPort);
218 KeReleaseSpinLock (&NamedPort->Lock, oldIrql);
219
220 if (AcceptIt != 1)
221 {
222 EiReplyOrRequestPort (ConnectionRequest->Sender,
223 LpcMessage,
224 LPC_CONNECTION_REFUSED,
225 NamedPort);
226 KeSetEvent (&ConnectionRequest->Sender->Event,
227 IO_NO_INCREMENT,
228 FALSE);
229 ObDereferenceObject (ConnectionRequest->Sender);
230 ExFreePool (ConnectionRequest);
231 ObDereferenceObject (NamedPort);
232 return (STATUS_SUCCESS);
233 }
234 /*
235 * Connect the two ports
236 */
237 OurPort->OtherPort = ConnectionRequest->Sender;
238 OurPort->OtherPort->OtherPort = OurPort;
239 EiReplyOrRequestPort (ConnectionRequest->Sender,
240 LpcMessage,
241 LPC_REPLY,
242 OurPort);
243 ExFreePool (ConnectionRequest);
244
245 ObDereferenceObject (OurPort);
246 ObDereferenceObject (NamedPort);
247
248 return (STATUS_SUCCESS);
249 }
250
251
252 /* EOF */