7afa196abe863b69003c37850f5757eeea2a23db
[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 = NULL;
254 ULONG ConnectDataLength = 0;
255 PSECTION_OBJECT SectionObject;
256 LARGE_INTEGER SectionOffset;
257 PEPORT ConnectedPort;
258 KPROCESSOR_MODE PreviousMode;
259 NTSTATUS Status = STATUS_SUCCESS;
260 PEPORT NamedPort;
261
262 PreviousMode = ExGetPreviousMode();
263
264 if (PreviousMode != KernelMode)
265 {
266 _SEH_TRY
267 {
268 ProbeForWrite(UnsafeConnectedPortHandle,
269 sizeof(HANDLE),
270 sizeof(ULONG));
271 if (UnsafeMaximumMessageSize != NULL)
272 {
273 ProbeForWrite(UnsafeMaximumMessageSize,
274 sizeof(ULONG),
275 sizeof(ULONG));
276 }
277 }
278 _SEH_HANDLE
279 {
280 Status = _SEH_GetExceptionCode();
281 }
282 _SEH_END;
283
284 if (!NT_SUCCESS(Status))
285 {
286 return Status;
287 }
288 }
289
290 /*
291 * Copy in write map and partially validate.
292 */
293 if (UnsafeWriteMap != NULL)
294 {
295 if (PreviousMode != KernelMode)
296 {
297 _SEH_TRY
298 {
299 ProbeForWrite(UnsafeWriteMap,
300 sizeof(LPC_SECTION_WRITE),
301 1);
302 RtlCopyMemory(&WriteMap,
303 UnsafeWriteMap,
304 sizeof(LPC_SECTION_WRITE));
305 }
306 _SEH_HANDLE
307 {
308 Status = _SEH_GetExceptionCode();
309 }
310 _SEH_END;
311
312 if (!NT_SUCCESS(Status))
313 {
314 return Status;
315 }
316 }
317 else
318 {
319 RtlCopyMemory(&WriteMap,
320 UnsafeWriteMap,
321 sizeof(LPC_SECTION_WRITE));
322 }
323
324 if (WriteMap.Length != sizeof(LPC_SECTION_WRITE))
325 {
326 return(STATUS_INVALID_PARAMETER_4);
327 }
328 SectionOffset.QuadPart = WriteMap.SectionOffset;
329 }
330 else
331 {
332 WriteMap.SectionHandle = INVALID_HANDLE_VALUE;
333 }
334
335 /*
336 * Handle connection data.
337 */
338 if (UnsafeConnectData)
339 {
340 if (PreviousMode != KernelMode)
341 {
342 _SEH_TRY
343 {
344 ProbeForRead(UnsafeConnectDataLength,
345 sizeof(ULONG),
346 1);
347 ConnectDataLength = *UnsafeConnectDataLength;
348 }
349 _SEH_HANDLE
350 {
351 Status = _SEH_GetExceptionCode();
352 }
353 _SEH_END;
354
355 if (!NT_SUCCESS(Status))
356 {
357 return Status;
358 }
359 }
360 else
361 {
362 ConnectDataLength = *UnsafeConnectDataLength;
363 }
364
365 if (ConnectDataLength != 0)
366 {
367 ConnectData = ExAllocatePool(NonPagedPool, ConnectDataLength);
368 if (ConnectData == NULL)
369 {
370 return(STATUS_NO_MEMORY);
371 }
372
373 if (PreviousMode != KernelMode)
374 {
375 _SEH_TRY
376 {
377 ProbeForWrite(UnsafeConnectData,
378 ConnectDataLength,
379 1);
380 RtlCopyMemory(ConnectData,
381 UnsafeConnectData,
382 ConnectDataLength);
383 }
384 _SEH_HANDLE
385 {
386 Status = _SEH_GetExceptionCode();
387 }
388 _SEH_END;
389
390 if (!NT_SUCCESS(Status))
391 {
392 ExFreePool(ConnectData);
393 return Status;
394 }
395 }
396 else
397 {
398 RtlCopyMemory(ConnectData,
399 UnsafeConnectData,
400 ConnectDataLength);
401 }
402 }
403 }
404
405 /*
406 * Reference the named port.
407 */
408 Status = ObReferenceObjectByName (PortName,
409 0,
410 NULL,
411 PORT_ALL_ACCESS, /* DesiredAccess */
412 LpcPortObjectType,
413 UserMode,
414 NULL,
415 (PVOID*)&NamedPort);
416 if (!NT_SUCCESS(Status))
417 {
418 if (KeGetPreviousMode() != KernelMode)
419 {
420 ExFreePool(ConnectData);
421 }
422 return(Status);
423 }
424
425 /*
426 * Reference the send section object.
427 */
428 if (WriteMap.SectionHandle != INVALID_HANDLE_VALUE)
429 {
430 Status = ObReferenceObjectByHandle(WriteMap.SectionHandle,
431 SECTION_MAP_READ | SECTION_MAP_WRITE,
432 MmSectionObjectType,
433 UserMode,
434 (PVOID*)&SectionObject,
435 NULL);
436 if (!NT_SUCCESS(Status))
437 {
438 ObDereferenceObject(NamedPort);
439 if (KeGetPreviousMode() != KernelMode)
440 {
441 ExFreePool(ConnectData);
442 }
443 return(Status);
444 }
445 }
446 else
447 {
448 SectionObject = NULL;
449 }
450
451 /*
452 * Do the connection establishment.
453 */
454 Status = EiConnectPort(&ConnectedPort,
455 NamedPort,
456 SectionObject,
457 SectionOffset,
458 WriteMap.ViewSize,
459 &WriteMap.ViewBase,
460 &WriteMap.TargetViewBase,
461 &ReadMap.ViewSize,
462 &ReadMap.ViewBase,
463 &MaximumMessageSize,
464 ConnectData,
465 &ConnectDataLength);
466 if (!NT_SUCCESS(Status))
467 {
468 /* FIXME: Again, check what NT does here. */
469 if (UnsafeConnectDataLength != NULL)
470 {
471 if (PreviousMode != KernelMode)
472 {
473 _SEH_TRY
474 {
475 RtlCopyMemory(UnsafeConnectData,
476 ConnectData,
477 ConnectDataLength);
478 *UnsafeConnectDataLength = ConnectDataLength;
479 }
480 _SEH_HANDLE
481 {
482 Status = _SEH_GetExceptionCode();
483 }
484 _SEH_END;
485 }
486 else
487 {
488 RtlCopyMemory(UnsafeConnectData,
489 ConnectData,
490 ConnectDataLength);
491 *UnsafeConnectDataLength = ConnectDataLength;
492 }
493
494 ExFreePool(ConnectData);
495 }
496 return(Status);
497 }
498
499 /*
500 * Do some initial cleanup.
501 */
502 if (SectionObject != NULL)
503 {
504 ObDereferenceObject(SectionObject);
505 SectionObject = NULL;
506 }
507 ObDereferenceObject(NamedPort);
508 NamedPort = NULL;
509
510 /*
511 * Copy the data back to the caller.
512 */
513
514 if (UnsafeConnectDataLength != NULL)
515 {
516 if (PreviousMode != KernelMode)
517 {
518 _SEH_TRY
519 {
520 *UnsafeConnectDataLength = ConnectDataLength;
521
522 if (ConnectData != NULL)
523 {
524 RtlCopyMemory(UnsafeConnectData,
525 ConnectData,
526 ConnectDataLength);
527 }
528 }
529 _SEH_HANDLE
530 {
531 Status = _SEH_GetExceptionCode();
532 }
533 _SEH_END;
534
535 if (!NT_SUCCESS(Status))
536 {
537 if (ConnectData != NULL)
538 {
539 ExFreePool(ConnectData);
540 }
541 return(Status);
542 }
543 }
544 else
545 {
546 *UnsafeConnectDataLength = ConnectDataLength;
547
548 if (ConnectData != NULL)
549 {
550 RtlCopyMemory(UnsafeConnectData,
551 ConnectData,
552 ConnectDataLength);
553 }
554 }
555
556 if (ConnectData != NULL)
557 {
558 ExFreePool(ConnectData);
559 }
560 }
561 Status = ObInsertObject(ConnectedPort,
562 NULL,
563 PORT_ALL_ACCESS,
564 0,
565 NULL,
566 &ConnectedPortHandle);
567 if (!NT_SUCCESS(Status))
568 {
569 return(Status);
570 }
571
572 if (PreviousMode != KernelMode)
573 {
574 _SEH_TRY
575 {
576 *UnsafeConnectedPortHandle = ConnectedPortHandle;
577
578 if (UnsafeWriteMap != NULL)
579 {
580 RtlCopyMemory(UnsafeWriteMap,
581 &WriteMap,
582 sizeof(LPC_SECTION_WRITE));
583 }
584
585 if (UnsafeReadMap != NULL)
586 {
587 RtlCopyMemory(UnsafeReadMap,
588 &ReadMap,
589 sizeof(LPC_SECTION_READ));
590 }
591
592 if (UnsafeMaximumMessageSize != NULL)
593 {
594 *UnsafeMaximumMessageSize = MaximumMessageSize;
595 }
596 }
597 _SEH_HANDLE
598 {
599 Status = _SEH_GetExceptionCode();
600 }
601 _SEH_END;
602
603 if (!NT_SUCCESS(Status))
604 {
605 return Status;
606 }
607 }
608 else
609 {
610 *UnsafeConnectedPortHandle = ConnectedPortHandle;
611
612 if (UnsafeWriteMap != NULL)
613 {
614 RtlCopyMemory(UnsafeWriteMap,
615 &WriteMap,
616 sizeof(LPC_SECTION_WRITE));
617 }
618
619 if (UnsafeReadMap != NULL)
620 {
621 RtlCopyMemory(UnsafeReadMap,
622 &ReadMap,
623 sizeof(LPC_SECTION_READ));
624 }
625
626 if (UnsafeMaximumMessageSize != NULL)
627 {
628 *UnsafeMaximumMessageSize = MaximumMessageSize;
629 }
630 }
631
632 /*
633 * All done.
634 */
635
636 return(STATUS_SUCCESS);
637 }
638
639
640 /**********************************************************************
641 * NAME EXPORTED
642 * NtAcceptConnectPort/6
643 *
644 * DESCRIPTION
645 *
646 * ARGUMENTS
647 * ServerPortHandle
648 * NamedPortHandle
649 * LpcMessage
650 * AcceptIt
651 * WriteMap
652 * ReadMap
653 *
654 * RETURN VALUE
655 */
656 /*EXPORTED*/ NTSTATUS STDCALL
657 NtAcceptConnectPort (PHANDLE ServerPortHandle,
658 HANDLE NamedPortHandle,
659 PLPC_MESSAGE LpcMessage,
660 BOOLEAN AcceptIt,
661 PLPC_SECTION_WRITE WriteMap,
662 PLPC_SECTION_READ ReadMap)
663 {
664 NTSTATUS Status;
665 PEPORT NamedPort;
666 PEPORT OurPort = NULL;
667 PQUEUEDMESSAGE ConnectionRequest;
668 KIRQL oldIrql;
669 PEPORT_CONNECT_REQUEST_MESSAGE CRequest;
670 PEPORT_CONNECT_REPLY_MESSAGE CReply;
671 ULONG Size;
672
673 Size = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
674 if (LpcMessage)
675 {
676 Size += LpcMessage->DataSize;
677 }
678
679 CReply = ExAllocatePool(NonPagedPool, Size);
680 if (CReply == NULL)
681 {
682 return(STATUS_NO_MEMORY);
683 }
684
685 Status = ObReferenceObjectByHandle(NamedPortHandle,
686 PORT_ALL_ACCESS,
687 LpcPortObjectType,
688 UserMode,
689 (PVOID*)&NamedPort,
690 NULL);
691 if (!NT_SUCCESS(Status))
692 {
693 ExFreePool(CReply);
694 return (Status);
695 }
696
697 /*
698 * Create a port object for our side of the connection
699 */
700 if (AcceptIt)
701 {
702 Status = ObCreateObject(ExGetPreviousMode(),
703 LpcPortObjectType,
704 NULL,
705 ExGetPreviousMode(),
706 NULL,
707 sizeof(EPORT),
708 0,
709 0,
710 (PVOID*)&OurPort);
711 if (!NT_SUCCESS(Status))
712 {
713 ExFreePool(CReply);
714 ObDereferenceObject(NamedPort);
715 return(Status);
716 }
717
718 Status = ObInsertObject ((PVOID)OurPort,
719 NULL,
720 PORT_ALL_ACCESS,
721 0,
722 NULL,
723 ServerPortHandle);
724 if (!NT_SUCCESS(Status))
725 {
726 ObDereferenceObject(OurPort);
727 ExFreePool(CReply);
728 ObDereferenceObject(NamedPort);
729 return(Status);
730 }
731
732 LpcpInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort);
733 }
734
735 /*
736 * Dequeue the connection request
737 */
738 KeAcquireSpinLock(&NamedPort->Lock, &oldIrql);
739 ConnectionRequest = EiDequeueConnectMessagePort (NamedPort);
740 KeReleaseSpinLock(&NamedPort->Lock, oldIrql);
741 CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)(&ConnectionRequest->Message);
742
743 /*
744 * Prepare the reply.
745 */
746 if (LpcMessage != NULL)
747 {
748 memcpy(&CReply->MessageHeader, LpcMessage, sizeof(LPC_MESSAGE));
749 memcpy(&CReply->ConnectData, (PVOID)(LpcMessage + 1),
750 LpcMessage->DataSize);
751 CReply->MessageHeader.MessageSize =
752 sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->DataSize;
753 CReply->MessageHeader.DataSize = CReply->MessageHeader.MessageSize -
754 sizeof(LPC_MESSAGE);
755 CReply->ConnectDataLength = LpcMessage->DataSize;
756 }
757 else
758 {
759 CReply->MessageHeader.MessageSize = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
760 CReply->MessageHeader.DataSize = sizeof(EPORT_CONNECT_REPLY_MESSAGE) -
761 sizeof(LPC_MESSAGE);
762 CReply->ConnectDataLength = 0;
763 }
764 if (!AcceptIt)
765 {
766 EiReplyOrRequestPort(ConnectionRequest->Sender,
767 &CReply->MessageHeader,
768 LPC_CONNECTION_REFUSED,
769 NamedPort);
770 KeReleaseSemaphore(&ConnectionRequest->Sender->Semaphore,
771 IO_NO_INCREMENT,
772 1,
773 FALSE);
774 ObDereferenceObject(ConnectionRequest->Sender);
775 ExFreePool(ConnectionRequest);
776 ExFreePool(CReply);
777 ObDereferenceObject(NamedPort);
778 return (STATUS_SUCCESS);
779 }
780
781 /*
782 * Prepare the connection.
783 */
784 if (WriteMap != NULL)
785 {
786 PSECTION_OBJECT SectionObject;
787 LARGE_INTEGER SectionOffset;
788
789 Status = ObReferenceObjectByHandle(WriteMap->SectionHandle,
790 SECTION_MAP_READ | SECTION_MAP_WRITE,
791 MmSectionObjectType,
792 UserMode,
793 (PVOID*)&SectionObject,
794 NULL);
795 if (!NT_SUCCESS(Status))
796 {
797 return(Status);
798 }
799
800 SectionOffset.QuadPart = WriteMap->SectionOffset;
801 WriteMap->TargetViewBase = 0;
802 CReply->ReceiveClientViewSize = WriteMap->ViewSize;
803 Status = MmMapViewOfSection(SectionObject,
804 CRequest->ConnectingProcess,
805 &WriteMap->TargetViewBase,
806 0,
807 CReply->ReceiveClientViewSize,
808 &SectionOffset,
809 &CReply->ReceiveClientViewSize,
810 ViewUnmap,
811 0 /* MEM_TOP_DOWN? */,
812 PAGE_READWRITE);
813 if (!NT_SUCCESS(Status))
814 {
815 return(Status);
816 }
817
818 WriteMap->ViewBase = 0;
819 Status = MmMapViewOfSection(SectionObject,
820 PsGetCurrentProcess(),
821 &WriteMap->ViewBase,
822 0,
823 WriteMap->ViewSize,
824 &SectionOffset,
825 &WriteMap->ViewSize,
826 ViewUnmap,
827 0 /* MEM_TOP_DOWN? */,
828 PAGE_READWRITE);
829 if (!NT_SUCCESS(Status))
830 {
831 return(Status);
832 }
833
834 ObDereferenceObject(SectionObject);
835 }
836 if (ReadMap != NULL && CRequest->SendSectionObject != NULL)
837 {
838 LARGE_INTEGER SectionOffset;
839
840 SectionOffset = CRequest->SendSectionOffset;
841 ReadMap->ViewSize = CRequest->SendViewSize;
842 ReadMap->ViewBase = 0;
843 Status = MmMapViewOfSection(CRequest->SendSectionObject,
844 PsGetCurrentProcess(),
845 &ReadMap->ViewBase,
846 0,
847 CRequest->SendViewSize,
848 &SectionOffset,
849 &CRequest->SendViewSize,
850 ViewUnmap,
851 0 /* MEM_TOP_DOWN? */,
852 PAGE_READWRITE);
853 if (!NT_SUCCESS(Status))
854 {
855 return(Status);
856 }
857 }
858
859 /*
860 * Finish the reply.
861 */
862 if (ReadMap != NULL)
863 {
864 CReply->SendServerViewBase = ReadMap->ViewBase;
865 }
866 else
867 {
868 CReply->SendServerViewBase = 0;
869 }
870 if (WriteMap != NULL)
871 {
872 CReply->ReceiveClientViewBase = WriteMap->TargetViewBase;
873 }
874 CReply->MaximumMessageSize = PORT_MAX_MESSAGE_LENGTH;
875
876
877 /*
878 * Connect the two ports
879 */
880 OurPort->OtherPort = ConnectionRequest->Sender;
881 OurPort->OtherPort->OtherPort = OurPort;
882 EiReplyOrRequestPort(ConnectionRequest->Sender,
883 (PLPC_MESSAGE)CReply,
884 LPC_REPLY,
885 OurPort);
886 ExFreePool(ConnectionRequest);
887 ExFreePool(CReply);
888
889 ObDereferenceObject(OurPort);
890 ObDereferenceObject(NamedPort);
891
892 return (STATUS_SUCCESS);
893 }
894
895 /**********************************************************************
896 * NAME EXPORTED
897 * NtSecureConnectPort/9
898 *
899 * DESCRIPTION
900 * Connect to a named port and wait for the other side to
901 * accept the connection. Possibly verify that the server
902 * matches the ServerSid (trusted server).
903 * Present in w2k+.
904 *
905 * ARGUMENTS
906 * ConnectedPort
907 * PortName: fully qualified name in the Ob name space;
908 * Qos
909 * WriteMap
910 * ServerSid
911 * ReadMap
912 * MaxMessageSize
913 * ConnectInfo
914 * UserConnectInfoLength
915 *
916 * RETURN VALUE
917 */
918 NTSTATUS STDCALL
919 NtSecureConnectPort (OUT PHANDLE ConnectedPort,
920 IN PUNICODE_STRING PortName,
921 IN PSECURITY_QUALITY_OF_SERVICE Qos,
922 IN OUT PLPC_SECTION_WRITE WriteMap OPTIONAL,
923 IN PSID ServerSid OPTIONAL,
924 IN OUT PLPC_SECTION_READ ReadMap OPTIONAL,
925 OUT PULONG MaxMessageSize OPTIONAL,
926 IN OUT PVOID ConnectInfo OPTIONAL,
927 IN OUT PULONG UserConnectInfoLength OPTIONAL)
928 {
929 /* TODO: implement a new object type: WaitablePort */
930 /* TODO: verify the process' SID that hosts the rendez-vous port equals ServerSid */
931 return NtConnectPort (ConnectedPort,
932 PortName,
933 Qos,
934 WriteMap,
935 ReadMap,
936 MaxMessageSize,
937 ConnectInfo,
938 UserConnectInfoLength);
939 }
940
941 /* EOF */