- Use the actual previous mode (spotted by Thomas)
[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 PreviousMode,
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 PreviousMode,
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 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
673
674 Size = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
675 if (LpcMessage)
676 {
677 Size += LpcMessage->DataSize;
678 }
679
680 CReply = ExAllocatePool(NonPagedPool, Size);
681 if (CReply == NULL)
682 {
683 return(STATUS_NO_MEMORY);
684 }
685
686 Status = ObReferenceObjectByHandle(NamedPortHandle,
687 PORT_ALL_ACCESS,
688 LpcPortObjectType,
689 PreviousMode,
690 (PVOID*)&NamedPort,
691 NULL);
692 if (!NT_SUCCESS(Status))
693 {
694 ExFreePool(CReply);
695 return (Status);
696 }
697
698 /*
699 * Create a port object for our side of the connection
700 */
701 if (AcceptIt)
702 {
703 Status = ObCreateObject(PreviousMode,
704 LpcPortObjectType,
705 NULL,
706 PreviousMode,
707 NULL,
708 sizeof(EPORT),
709 0,
710 0,
711 (PVOID*)&OurPort);
712 if (!NT_SUCCESS(Status))
713 {
714 ExFreePool(CReply);
715 ObDereferenceObject(NamedPort);
716 return(Status);
717 }
718
719 Status = ObInsertObject ((PVOID)OurPort,
720 NULL,
721 PORT_ALL_ACCESS,
722 0,
723 NULL,
724 ServerPortHandle);
725 if (!NT_SUCCESS(Status))
726 {
727 ObDereferenceObject(OurPort);
728 ExFreePool(CReply);
729 ObDereferenceObject(NamedPort);
730 return(Status);
731 }
732
733 LpcpInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort);
734 }
735
736 /*
737 * Dequeue the connection request
738 */
739 KeAcquireSpinLock(&NamedPort->Lock, &oldIrql);
740 ConnectionRequest = EiDequeueConnectMessagePort (NamedPort);
741 KeReleaseSpinLock(&NamedPort->Lock, oldIrql);
742 CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)(&ConnectionRequest->Message);
743
744 /*
745 * Prepare the reply.
746 */
747 if (LpcMessage != NULL)
748 {
749 memcpy(&CReply->MessageHeader, LpcMessage, sizeof(LPC_MESSAGE));
750 memcpy(&CReply->ConnectData, (PVOID)(LpcMessage + 1),
751 LpcMessage->DataSize);
752 CReply->MessageHeader.MessageSize =
753 sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->DataSize;
754 CReply->MessageHeader.DataSize = CReply->MessageHeader.MessageSize -
755 sizeof(LPC_MESSAGE);
756 CReply->ConnectDataLength = LpcMessage->DataSize;
757 }
758 else
759 {
760 CReply->MessageHeader.MessageSize = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
761 CReply->MessageHeader.DataSize = sizeof(EPORT_CONNECT_REPLY_MESSAGE) -
762 sizeof(LPC_MESSAGE);
763 CReply->ConnectDataLength = 0;
764 }
765 if (!AcceptIt)
766 {
767 EiReplyOrRequestPort(ConnectionRequest->Sender,
768 &CReply->MessageHeader,
769 LPC_CONNECTION_REFUSED,
770 NamedPort);
771 KeReleaseSemaphore(&ConnectionRequest->Sender->Semaphore,
772 IO_NO_INCREMENT,
773 1,
774 FALSE);
775 ObDereferenceObject(ConnectionRequest->Sender);
776 ExFreePool(ConnectionRequest);
777 ExFreePool(CReply);
778 ObDereferenceObject(NamedPort);
779 return (STATUS_SUCCESS);
780 }
781
782 /*
783 * Prepare the connection.
784 */
785 if (WriteMap != NULL)
786 {
787 PSECTION_OBJECT SectionObject;
788 LARGE_INTEGER SectionOffset;
789
790 Status = ObReferenceObjectByHandle(WriteMap->SectionHandle,
791 SECTION_MAP_READ | SECTION_MAP_WRITE,
792 MmSectionObjectType,
793 PreviousMode,
794 (PVOID*)&SectionObject,
795 NULL);
796 if (!NT_SUCCESS(Status))
797 {
798 return(Status);
799 }
800
801 SectionOffset.QuadPart = WriteMap->SectionOffset;
802 WriteMap->TargetViewBase = 0;
803 CReply->ReceiveClientViewSize = WriteMap->ViewSize;
804 Status = MmMapViewOfSection(SectionObject,
805 CRequest->ConnectingProcess,
806 &WriteMap->TargetViewBase,
807 0,
808 CReply->ReceiveClientViewSize,
809 &SectionOffset,
810 &CReply->ReceiveClientViewSize,
811 ViewUnmap,
812 0 /* MEM_TOP_DOWN? */,
813 PAGE_READWRITE);
814 if (!NT_SUCCESS(Status))
815 {
816 return(Status);
817 }
818
819 WriteMap->ViewBase = 0;
820 Status = MmMapViewOfSection(SectionObject,
821 PsGetCurrentProcess(),
822 &WriteMap->ViewBase,
823 0,
824 WriteMap->ViewSize,
825 &SectionOffset,
826 &WriteMap->ViewSize,
827 ViewUnmap,
828 0 /* MEM_TOP_DOWN? */,
829 PAGE_READWRITE);
830 if (!NT_SUCCESS(Status))
831 {
832 return(Status);
833 }
834
835 ObDereferenceObject(SectionObject);
836 }
837 if (ReadMap != NULL && CRequest->SendSectionObject != NULL)
838 {
839 LARGE_INTEGER SectionOffset;
840
841 SectionOffset = CRequest->SendSectionOffset;
842 ReadMap->ViewSize = CRequest->SendViewSize;
843 ReadMap->ViewBase = 0;
844 Status = MmMapViewOfSection(CRequest->SendSectionObject,
845 PsGetCurrentProcess(),
846 &ReadMap->ViewBase,
847 0,
848 CRequest->SendViewSize,
849 &SectionOffset,
850 &CRequest->SendViewSize,
851 ViewUnmap,
852 0 /* MEM_TOP_DOWN? */,
853 PAGE_READWRITE);
854 if (!NT_SUCCESS(Status))
855 {
856 return(Status);
857 }
858 }
859
860 /*
861 * Finish the reply.
862 */
863 if (ReadMap != NULL)
864 {
865 CReply->SendServerViewBase = ReadMap->ViewBase;
866 }
867 else
868 {
869 CReply->SendServerViewBase = 0;
870 }
871 if (WriteMap != NULL)
872 {
873 CReply->ReceiveClientViewBase = WriteMap->TargetViewBase;
874 }
875 CReply->MaximumMessageSize = PORT_MAX_MESSAGE_LENGTH;
876
877
878 /*
879 * Connect the two ports
880 */
881 OurPort->OtherPort = ConnectionRequest->Sender;
882 OurPort->OtherPort->OtherPort = OurPort;
883 EiReplyOrRequestPort(ConnectionRequest->Sender,
884 (PLPC_MESSAGE)CReply,
885 LPC_REPLY,
886 OurPort);
887 ExFreePool(ConnectionRequest);
888 ExFreePool(CReply);
889
890 ObDereferenceObject(OurPort);
891 ObDereferenceObject(NamedPort);
892
893 return (STATUS_SUCCESS);
894 }
895
896 /**********************************************************************
897 * NAME EXPORTED
898 * NtSecureConnectPort/9
899 *
900 * DESCRIPTION
901 * Connect to a named port and wait for the other side to
902 * accept the connection. Possibly verify that the server
903 * matches the ServerSid (trusted server).
904 * Present in w2k+.
905 *
906 * ARGUMENTS
907 * ConnectedPort
908 * PortName: fully qualified name in the Ob name space;
909 * Qos
910 * WriteMap
911 * ServerSid
912 * ReadMap
913 * MaxMessageSize
914 * ConnectInfo
915 * UserConnectInfoLength
916 *
917 * RETURN VALUE
918 */
919 NTSTATUS STDCALL
920 NtSecureConnectPort (OUT PHANDLE ConnectedPort,
921 IN PUNICODE_STRING PortName,
922 IN PSECURITY_QUALITY_OF_SERVICE Qos,
923 IN OUT PLPC_SECTION_WRITE WriteMap OPTIONAL,
924 IN PSID ServerSid OPTIONAL,
925 IN OUT PLPC_SECTION_READ ReadMap OPTIONAL,
926 OUT PULONG MaxMessageSize OPTIONAL,
927 IN OUT PVOID ConnectInfo OPTIONAL,
928 IN OUT PULONG UserConnectInfoLength OPTIONAL)
929 {
930 /* TODO: implement a new object type: WaitablePort */
931 /* TODO: verify the process' SID that hosts the rendez-vous port equals ServerSid */
932 return NtConnectPort (ConnectedPort,
933 PortName,
934 Qos,
935 WriteMap,
936 ReadMap,
937 MaxMessageSize,
938 ConnectInfo,
939 UserConnectInfoLength);
940 }
941
942 /* EOF */