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