Merge 15329:15546 from trunk
[reactos.git] / reactos / ntoskrnl / lpc / connect.c
1 /* $Id$
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 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* FUNCTIONS *****************************************************************/
18
19 /**********************************************************************
20 * NAME EXPORTED
21 * EiConnectPort/12
22 *
23 * DESCRIPTION
24 *
25 * ARGUMENTS
26 *
27 * RETURN VALUE
28 */
29 NTSTATUS STDCALL
30 EiConnectPort(IN PEPORT* ConnectedPort,
31 IN PEPORT NamedPort,
32 IN PSECTION_OBJECT Section,
33 IN LARGE_INTEGER SectionOffset,
34 IN ULONG ViewSize,
35 OUT PVOID* ClientSendViewBase,
36 OUT PVOID* ServerSendViewBase,
37 OUT PULONG ReceiveViewSize,
38 OUT PVOID* ReceiveViewBase,
39 OUT PULONG MaximumMessageSize,
40 IN OUT PVOID ConnectData,
41 IN OUT PULONG ConnectDataLength)
42 {
43 PEPORT_CONNECT_REQUEST_MESSAGE RequestMessage;
44 ULONG RequestConnectDataLength;
45 PEPORT OurPort;
46 PQUEUEDMESSAGE Reply;
47 PEPORT_CONNECT_REPLY_MESSAGE CReply;
48 NTSTATUS Status;
49 KIRQL oldIrql;
50
51 if (ConnectDataLength == NULL)
52 {
53 RequestConnectDataLength = 0;
54 }
55 else
56 {
57 RequestConnectDataLength = *ConnectDataLength;
58 }
59
60 /*
61 * Create a port to represent our side of the connection
62 */
63 Status = ObCreateObject (KernelMode,
64 LpcPortObjectType,
65 NULL,
66 KernelMode,
67 NULL,
68 sizeof(EPORT),
69 0,
70 0,
71 (PVOID*)&OurPort);
72 if (!NT_SUCCESS(Status))
73 {
74 return (Status);
75 }
76 LpcpInitializePort(OurPort, EPORT_TYPE_CLIENT_COMM_PORT, NamedPort);
77
78 /*
79 * Allocate a request message.
80 */
81 RequestMessage = ExAllocatePool(NonPagedPool,
82 sizeof(EPORT_CONNECT_REQUEST_MESSAGE) +
83 RequestConnectDataLength);
84 if (RequestMessage == NULL)
85 {
86 ObDereferenceObject(OurPort);
87 return(STATUS_NO_MEMORY);
88 }
89
90 /*
91 * Initialize the request message.
92 */
93 RequestMessage->MessageHeader.DataSize =
94 sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength -
95 sizeof(LPC_MESSAGE);
96 RequestMessage->MessageHeader.MessageSize =
97 sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength;
98 DPRINT("RequestMessageSize %d\n",
99 RequestMessage->MessageHeader.MessageSize);
100 RequestMessage->MessageHeader.SectionSize = 0;
101 RequestMessage->ConnectingProcess = PsGetCurrentProcess();
102 ObReferenceObjectByPointer(RequestMessage->ConnectingProcess,
103 PROCESS_VM_OPERATION,
104 NULL,
105 KernelMode);
106 RequestMessage->SendSectionObject = (struct _SECTION_OBJECT*)Section;
107 RequestMessage->SendSectionOffset = SectionOffset;
108 RequestMessage->SendViewSize = ViewSize;
109 RequestMessage->ConnectDataLength = RequestConnectDataLength;
110 if (RequestConnectDataLength > 0)
111 {
112 memcpy(RequestMessage->ConnectData, ConnectData,
113 RequestConnectDataLength);
114 }
115
116 /*
117 * Queue the message to the named port
118 */
119 EiReplyOrRequestPort(NamedPort,
120 &RequestMessage->MessageHeader,
121 LPC_CONNECTION_REQUEST,
122 OurPort);
123 KeReleaseSemaphore(&NamedPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);
124 ExFreePool(RequestMessage);
125
126 /*
127 * Wait for them to accept our connection
128 */
129 KeWaitForSingleObject(&OurPort->Semaphore,
130 UserRequest,
131 UserMode,
132 FALSE,
133 NULL);
134
135 /*
136 * Dequeue the response
137 */
138 KeAcquireSpinLock (&OurPort->Lock, &oldIrql);
139 Reply = EiDequeueMessagePort (OurPort);
140 KeReleaseSpinLock (&OurPort->Lock, oldIrql);
141 CReply = (PEPORT_CONNECT_REPLY_MESSAGE)&Reply->Message;
142
143 /*
144 * Do some initial cleanup.
145 */
146 ObDereferenceObject(PsGetCurrentProcess());
147
148 /*
149 * Check for connection refusal.
150 */
151 if (CReply->MessageHeader.MessageType == LPC_CONNECTION_REFUSED)
152 {
153 ObDereferenceObject(OurPort);
154 ExFreePool(Reply);
155 /*
156 * FIXME: Check what NT does here. Giving the user data back on
157 * connect failure sounds reasonable; it probably wouldn't break
158 * anything anyway.
159 */
160 if (ConnectDataLength != NULL)
161 {
162 *ConnectDataLength = CReply->ConnectDataLength;
163 memcpy(ConnectData, CReply->ConnectData, CReply->ConnectDataLength);
164 }
165 return(STATUS_PORT_CONNECTION_REFUSED);
166 }
167
168 /*
169 * Otherwise we are connected. Copy data back to the client.
170 */
171 *ServerSendViewBase = CReply->SendServerViewBase;
172 *ReceiveViewSize = CReply->ReceiveClientViewSize;
173 *ReceiveViewBase = CReply->ReceiveClientViewBase;
174 *MaximumMessageSize = CReply->MaximumMessageSize;
175 if (ConnectDataLength != NULL)
176 {
177 *ConnectDataLength = CReply->ConnectDataLength;
178 memcpy(ConnectData, CReply->ConnectData, CReply->ConnectDataLength);
179 }
180
181 /*
182 * Create our view of the send section object.
183 */
184 if (Section != NULL)
185 {
186 *ClientSendViewBase = 0;
187 Status = MmMapViewOfSection(Section,
188 PsGetCurrentProcess(),
189 ClientSendViewBase,
190 0,
191 ViewSize,
192 &SectionOffset,
193 &ViewSize,
194 ViewUnmap,
195 0 /* MEM_TOP_DOWN? */,
196 PAGE_READWRITE);
197 if (!NT_SUCCESS(Status))
198 {
199 /* FIXME: Cleanup here. */
200 return(Status);
201 }
202 }
203
204 /*
205 * Do the final initialization of our port.
206 */
207 OurPort->State = EPORT_CONNECTED_CLIENT;
208
209 /*
210 * Cleanup.
211 */
212 ExFreePool(Reply);
213 *ConnectedPort = OurPort;
214 return(STATUS_SUCCESS);
215 }
216
217 /**********************************************************************
218 * NAME EXPORTED
219 * NtConnectPort/8
220 *
221 * DESCRIPTION
222 * Connect to a named port and wait for the other side to
223 * accept or reject the connection request.
224 *
225 * ARGUMENTS
226 * ConnectedPort
227 * PortName
228 * Qos
229 * WriteMap
230 * ReadMap
231 * MaxMessageSize
232 * ConnectInfo
233 * UserConnectInfoLength
234 *
235 * RETURN VALUE
236 *
237 * @unimplemented
238 */
239 NTSTATUS STDCALL
240 NtConnectPort (PHANDLE UnsafeConnectedPortHandle,
241 PUNICODE_STRING PortName,
242 PSECURITY_QUALITY_OF_SERVICE Qos,
243 PLPC_SECTION_WRITE UnsafeWriteMap,
244 PLPC_SECTION_READ UnsafeReadMap,
245 PULONG UnsafeMaximumMessageSize,
246 PVOID UnsafeConnectData,
247 PULONG UnsafeConnectDataLength)
248 {
249 HANDLE ConnectedPortHandle;
250 LPC_SECTION_WRITE WriteMap;
251 LPC_SECTION_READ ReadMap;
252 ULONG MaximumMessageSize;
253 PVOID ConnectData;
254 ULONG ConnectDataLength;
255 PSECTION_OBJECT SectionObject;
256 LARGE_INTEGER SectionOffset;
257 PEPORT ConnectedPort;
258 NTSTATUS Status;
259 PEPORT NamedPort;
260
261 /*
262 * Copy in write map and partially validate.
263 */
264 if (UnsafeWriteMap != NULL)
265 {
266 Status = MmCopyFromCaller(&WriteMap,
267 UnsafeWriteMap,
268 sizeof(LPC_SECTION_WRITE));
269 if (!NT_SUCCESS(Status))
270 {
271 return(Status);
272 }
273 if (WriteMap.Length != sizeof(LPC_SECTION_WRITE))
274 {
275 return(STATUS_INVALID_PARAMETER_4);
276 }
277 SectionOffset.QuadPart = WriteMap.SectionOffset;
278 }
279 else
280 {
281 WriteMap.SectionHandle = INVALID_HANDLE_VALUE;
282 }
283
284 /*
285 * Handle connection data.
286 */
287 if (UnsafeConnectData == NULL)
288 {
289 ConnectDataLength = 0;
290 ConnectData = NULL;
291 }
292 else
293 {
294 if (ExGetPreviousMode() == KernelMode)
295 {
296 ConnectDataLength = *UnsafeConnectDataLength;
297 ConnectData = UnsafeConnectData;
298 }
299 else
300 {
301 Status = MmCopyFromCaller(&ConnectDataLength,
302 UnsafeConnectDataLength,
303 sizeof(ULONG));
304 if (!NT_SUCCESS(Status))
305 {
306 return(Status);
307 }
308 ConnectData = ExAllocatePool(NonPagedPool, ConnectDataLength);
309 if (ConnectData == NULL && ConnectDataLength != 0)
310 {
311 return(STATUS_NO_MEMORY);
312 }
313 Status = MmCopyFromCaller(ConnectData,
314 UnsafeConnectData,
315 ConnectDataLength);
316 if (!NT_SUCCESS(Status))
317 {
318 ExFreePool(ConnectData);
319 return(Status);
320 }
321 }
322 }
323
324 /*
325 * Reference the named port.
326 */
327 Status = ObReferenceObjectByName (PortName,
328 0,
329 NULL,
330 PORT_ALL_ACCESS, /* DesiredAccess */
331 LpcPortObjectType,
332 UserMode,
333 NULL,
334 (PVOID*)&NamedPort);
335 if (!NT_SUCCESS(Status))
336 {
337 if (KeGetPreviousMode() != KernelMode)
338 {
339 ExFreePool(ConnectData);
340 }
341 return(Status);
342 }
343
344 /*
345 * Reference the send section object.
346 */
347 if (WriteMap.SectionHandle != INVALID_HANDLE_VALUE)
348 {
349 Status = ObReferenceObjectByHandle(WriteMap.SectionHandle,
350 SECTION_MAP_READ | SECTION_MAP_WRITE,
351 MmSectionObjectType,
352 UserMode,
353 (PVOID*)&SectionObject,
354 NULL);
355 if (!NT_SUCCESS(Status))
356 {
357 ObDereferenceObject(NamedPort);
358 if (KeGetPreviousMode() != KernelMode)
359 {
360 ExFreePool(ConnectData);
361 }
362 return(Status);
363 }
364 }
365 else
366 {
367 SectionObject = NULL;
368 }
369
370 /*
371 * Do the connection establishment.
372 */
373 Status = EiConnectPort(&ConnectedPort,
374 NamedPort,
375 SectionObject,
376 SectionOffset,
377 WriteMap.ViewSize,
378 &WriteMap.ViewBase,
379 &WriteMap.TargetViewBase,
380 &ReadMap.ViewSize,
381 &ReadMap.ViewBase,
382 &MaximumMessageSize,
383 ConnectData,
384 &ConnectDataLength);
385 if (!NT_SUCCESS(Status))
386 {
387 /* FIXME: Again, check what NT does here. */
388 if (UnsafeConnectDataLength != NULL)
389 {
390 if (ExGetPreviousMode() != KernelMode)
391 {
392 MmCopyToCaller(UnsafeConnectData,
393 ConnectData,
394 ConnectDataLength);
395 ExFreePool(ConnectData);
396 }
397 MmCopyToCaller(UnsafeConnectDataLength,
398 &ConnectDataLength,
399 sizeof(ULONG));
400 }
401 return(Status);
402 }
403
404 /*
405 * Do some initial cleanup.
406 */
407 if (SectionObject != NULL)
408 {
409 ObDereferenceObject(SectionObject);
410 SectionObject = NULL;
411 }
412 ObDereferenceObject(NamedPort);
413 NamedPort = NULL;
414
415 /*
416 * Copy the data back to the caller.
417 */
418 if (ExGetPreviousMode() != KernelMode)
419 {
420 if (UnsafeConnectDataLength != NULL)
421 {
422 Status = MmCopyToCaller(UnsafeConnectDataLength,
423 &ConnectDataLength,
424 sizeof(ULONG));
425 if (!NT_SUCCESS(Status))
426 {
427 return(Status);
428 }
429 }
430 if (UnsafeConnectData != NULL && ConnectData != NULL)
431 {
432 Status = MmCopyToCaller(UnsafeConnectData,
433 ConnectData,
434 ConnectDataLength);
435 ExFreePool(ConnectData);
436 if (!NT_SUCCESS(Status))
437 {
438 return(Status);
439 }
440 }
441 }
442 Status = ObInsertObject(ConnectedPort,
443 NULL,
444 PORT_ALL_ACCESS,
445 0,
446 NULL,
447 &ConnectedPortHandle);
448 if (!NT_SUCCESS(Status))
449 {
450 return(Status);
451 }
452 Status = MmCopyToCaller(UnsafeConnectedPortHandle,
453 &ConnectedPortHandle,
454 sizeof(HANDLE));
455 if (!NT_SUCCESS(Status))
456 {
457 return(Status);
458 }
459 if (UnsafeWriteMap != NULL)
460 {
461 Status = MmCopyToCaller(UnsafeWriteMap,
462 &WriteMap,
463 sizeof(LPC_SECTION_WRITE));
464 if (!NT_SUCCESS(Status))
465 {
466 return(Status);
467 }
468 }
469 if (UnsafeReadMap != NULL)
470 {
471 Status = MmCopyToCaller(UnsafeReadMap,
472 &ReadMap,
473 sizeof(LPC_SECTION_READ));
474 if (!NT_SUCCESS(Status))
475 {
476 return(Status);
477 }
478 }
479 if (UnsafeMaximumMessageSize != NULL)
480 {
481 Status = MmCopyToCaller(UnsafeMaximumMessageSize,
482 &MaximumMessageSize,
483 sizeof(ULONG));
484 if (!NT_SUCCESS(Status))
485 {
486 return(Status);
487 }
488 }
489
490 /*
491 * All done.
492 */
493
494 return(STATUS_SUCCESS);
495 }
496
497
498 /**********************************************************************
499 * NAME EXPORTED
500 * NtAcceptConnectPort/6
501 *
502 * DESCRIPTION
503 *
504 * ARGUMENTS
505 * ServerPortHandle
506 * NamedPortHandle
507 * LpcMessage
508 * AcceptIt
509 * WriteMap
510 * ReadMap
511 *
512 * RETURN VALUE
513 */
514 /*EXPORTED*/ NTSTATUS STDCALL
515 NtAcceptConnectPort (PHANDLE ServerPortHandle,
516 HANDLE NamedPortHandle,
517 PLPC_MESSAGE LpcMessage,
518 BOOLEAN AcceptIt,
519 PLPC_SECTION_WRITE WriteMap,
520 PLPC_SECTION_READ ReadMap)
521 {
522 NTSTATUS Status;
523 PEPORT NamedPort;
524 PEPORT OurPort = NULL;
525 PQUEUEDMESSAGE ConnectionRequest;
526 KIRQL oldIrql;
527 PEPORT_CONNECT_REQUEST_MESSAGE CRequest;
528 PEPORT_CONNECT_REPLY_MESSAGE CReply;
529 ULONG Size;
530
531 Size = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
532 if (LpcMessage)
533 {
534 Size += LpcMessage->DataSize;
535 }
536
537 CReply = ExAllocatePool(NonPagedPool, Size);
538 if (CReply == NULL)
539 {
540 return(STATUS_NO_MEMORY);
541 }
542
543 Status = ObReferenceObjectByHandle(NamedPortHandle,
544 PORT_ALL_ACCESS,
545 LpcPortObjectType,
546 UserMode,
547 (PVOID*)&NamedPort,
548 NULL);
549 if (!NT_SUCCESS(Status))
550 {
551 ExFreePool(CReply);
552 return (Status);
553 }
554
555 /*
556 * Create a port object for our side of the connection
557 */
558 if (AcceptIt)
559 {
560 Status = ObCreateObject(ExGetPreviousMode(),
561 LpcPortObjectType,
562 NULL,
563 ExGetPreviousMode(),
564 NULL,
565 sizeof(EPORT),
566 0,
567 0,
568 (PVOID*)&OurPort);
569 if (!NT_SUCCESS(Status))
570 {
571 ExFreePool(CReply);
572 ObDereferenceObject(NamedPort);
573 return(Status);
574 }
575
576 Status = ObInsertObject ((PVOID)OurPort,
577 NULL,
578 PORT_ALL_ACCESS,
579 0,
580 NULL,
581 ServerPortHandle);
582 if (!NT_SUCCESS(Status))
583 {
584 ObDereferenceObject(OurPort);
585 ExFreePool(CReply);
586 ObDereferenceObject(NamedPort);
587 return(Status);
588 }
589
590 LpcpInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort);
591 }
592
593 /*
594 * Dequeue the connection request
595 */
596 KeAcquireSpinLock(&NamedPort->Lock, &oldIrql);
597 ConnectionRequest = EiDequeueConnectMessagePort (NamedPort);
598 KeReleaseSpinLock(&NamedPort->Lock, oldIrql);
599 CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)(&ConnectionRequest->Message);
600
601 /*
602 * Prepare the reply.
603 */
604 if (LpcMessage != NULL)
605 {
606 memcpy(&CReply->MessageHeader, LpcMessage, sizeof(LPC_MESSAGE));
607 memcpy(&CReply->ConnectData, (PVOID)(LpcMessage + 1),
608 LpcMessage->DataSize);
609 CReply->MessageHeader.MessageSize =
610 sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->DataSize;
611 CReply->MessageHeader.DataSize = CReply->MessageHeader.MessageSize -
612 sizeof(LPC_MESSAGE);
613 CReply->ConnectDataLength = LpcMessage->DataSize;
614 }
615 else
616 {
617 CReply->MessageHeader.MessageSize = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
618 CReply->MessageHeader.DataSize = sizeof(EPORT_CONNECT_REPLY_MESSAGE) -
619 sizeof(LPC_MESSAGE);
620 CReply->ConnectDataLength = 0;
621 }
622 if (!AcceptIt)
623 {
624 EiReplyOrRequestPort(ConnectionRequest->Sender,
625 &CReply->MessageHeader,
626 LPC_CONNECTION_REFUSED,
627 NamedPort);
628 KeReleaseSemaphore(&ConnectionRequest->Sender->Semaphore,
629 IO_NO_INCREMENT,
630 1,
631 FALSE);
632 ObDereferenceObject(ConnectionRequest->Sender);
633 ExFreePool(ConnectionRequest);
634 ExFreePool(CReply);
635 ObDereferenceObject(NamedPort);
636 return (STATUS_SUCCESS);
637 }
638
639 /*
640 * Prepare the connection.
641 */
642 if (WriteMap != NULL)
643 {
644 PSECTION_OBJECT SectionObject;
645 LARGE_INTEGER SectionOffset;
646
647 Status = ObReferenceObjectByHandle(WriteMap->SectionHandle,
648 SECTION_MAP_READ | SECTION_MAP_WRITE,
649 MmSectionObjectType,
650 UserMode,
651 (PVOID*)&SectionObject,
652 NULL);
653 if (!NT_SUCCESS(Status))
654 {
655 return(Status);
656 }
657
658 SectionOffset.QuadPart = WriteMap->SectionOffset;
659 WriteMap->TargetViewBase = 0;
660 CReply->ReceiveClientViewSize = WriteMap->ViewSize;
661 Status = MmMapViewOfSection(SectionObject,
662 CRequest->ConnectingProcess,
663 &WriteMap->TargetViewBase,
664 0,
665 CReply->ReceiveClientViewSize,
666 &SectionOffset,
667 &CReply->ReceiveClientViewSize,
668 ViewUnmap,
669 0 /* MEM_TOP_DOWN? */,
670 PAGE_READWRITE);
671 if (!NT_SUCCESS(Status))
672 {
673 return(Status);
674 }
675
676 WriteMap->ViewBase = 0;
677 Status = MmMapViewOfSection(SectionObject,
678 PsGetCurrentProcess(),
679 &WriteMap->ViewBase,
680 0,
681 WriteMap->ViewSize,
682 &SectionOffset,
683 &WriteMap->ViewSize,
684 ViewUnmap,
685 0 /* MEM_TOP_DOWN? */,
686 PAGE_READWRITE);
687 if (!NT_SUCCESS(Status))
688 {
689 return(Status);
690 }
691
692 ObDereferenceObject(SectionObject);
693 }
694 if (ReadMap != NULL && CRequest->SendSectionObject != NULL)
695 {
696 LARGE_INTEGER SectionOffset;
697
698 SectionOffset = CRequest->SendSectionOffset;
699 ReadMap->ViewSize = CRequest->SendViewSize;
700 ReadMap->ViewBase = 0;
701 Status = MmMapViewOfSection(CRequest->SendSectionObject,
702 PsGetCurrentProcess(),
703 &ReadMap->ViewBase,
704 0,
705 CRequest->SendViewSize,
706 &SectionOffset,
707 &CRequest->SendViewSize,
708 ViewUnmap,
709 0 /* MEM_TOP_DOWN? */,
710 PAGE_READWRITE);
711 if (!NT_SUCCESS(Status))
712 {
713 return(Status);
714 }
715 }
716
717 /*
718 * Finish the reply.
719 */
720 if (ReadMap != NULL)
721 {
722 CReply->SendServerViewBase = ReadMap->ViewBase;
723 }
724 else
725 {
726 CReply->SendServerViewBase = 0;
727 }
728 if (WriteMap != NULL)
729 {
730 CReply->ReceiveClientViewBase = WriteMap->TargetViewBase;
731 }
732 CReply->MaximumMessageSize = PORT_MAX_MESSAGE_LENGTH;
733
734
735 /*
736 * Connect the two ports
737 */
738 OurPort->OtherPort = ConnectionRequest->Sender;
739 OurPort->OtherPort->OtherPort = OurPort;
740 EiReplyOrRequestPort(ConnectionRequest->Sender,
741 (PLPC_MESSAGE)CReply,
742 LPC_REPLY,
743 OurPort);
744 ExFreePool(ConnectionRequest);
745 ExFreePool(CReply);
746
747 ObDereferenceObject(OurPort);
748 ObDereferenceObject(NamedPort);
749
750 return (STATUS_SUCCESS);
751 }
752
753 /**********************************************************************
754 * NAME EXPORTED
755 * NtSecureConnectPort/9
756 *
757 * DESCRIPTION
758 * Connect to a named port and wait for the other side to
759 * accept the connection. Possibly verify that the server
760 * matches the ServerSid (trusted server).
761 * Present in w2k+.
762 *
763 * ARGUMENTS
764 * ConnectedPort
765 * PortName: fully qualified name in the Ob name space;
766 * Qos
767 * WriteMap
768 * ServerSid
769 * ReadMap
770 * MaxMessageSize
771 * ConnectInfo
772 * UserConnectInfoLength
773 *
774 * RETURN VALUE
775 */
776 NTSTATUS STDCALL
777 NtSecureConnectPort (OUT PHANDLE ConnectedPort,
778 IN PUNICODE_STRING PortName,
779 IN PSECURITY_QUALITY_OF_SERVICE Qos,
780 IN OUT PLPC_SECTION_WRITE WriteMap OPTIONAL,
781 IN PSID ServerSid OPTIONAL,
782 IN OUT PLPC_SECTION_READ ReadMap OPTIONAL,
783 OUT PULONG MaxMessageSize OPTIONAL,
784 IN OUT PVOID ConnectInfo OPTIONAL,
785 IN OUT PULONG UserConnectInfoLength OPTIONAL)
786 {
787 /* TODO: implement a new object type: WaitablePort */
788 /* TODO: verify the process' SID that hosts the rendez-vous port equals ServerSid */
789 return NtConnectPort (ConnectedPort,
790 PortName,
791 Qos,
792 WriteMap,
793 ReadMap,
794 MaxMessageSize,
795 ConnectInfo,
796 UserConnectInfoLength);
797 }
798
799 /* EOF */