[NTOS:LPC] Add a number of DPRINTs on failure
[reactos.git] / ntoskrnl / lpc / connect.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/lpc/connect.c
5 * PURPOSE: Local Procedure Call: Connection Management
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* PRIVATE FUNCTIONS *********************************************************/
16
17 PVOID
18 NTAPI
19 LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message,
20 IN OUT PLPCP_CONNECTION_MESSAGE *ConnectMessage,
21 IN PETHREAD CurrentThread)
22 {
23 PVOID SectionToMap;
24 PLPCP_MESSAGE ReplyMessage;
25
26 /* Acquire the LPC lock */
27 KeAcquireGuardedMutex(&LpcpLock);
28
29 /* Check if the reply chain is not empty */
30 if (!IsListEmpty(&CurrentThread->LpcReplyChain))
31 {
32 /* Remove this entry and re-initialize it */
33 RemoveEntryList(&CurrentThread->LpcReplyChain);
34 InitializeListHead(&CurrentThread->LpcReplyChain);
35 }
36
37 /* Check if there's a reply message */
38 ReplyMessage = LpcpGetMessageFromThread(CurrentThread);
39 if (ReplyMessage)
40 {
41 /* Get the message */
42 *Message = ReplyMessage;
43
44 /* Check if it's got messages */
45 if (!IsListEmpty(&ReplyMessage->Entry))
46 {
47 /* Clear the list */
48 RemoveEntryList(&ReplyMessage->Entry);
49 InitializeListHead(&ReplyMessage->Entry);
50 }
51
52 /* Clear message data */
53 CurrentThread->LpcReceivedMessageId = 0;
54 CurrentThread->LpcReplyMessage = NULL;
55
56 /* Get the connection message and clear the section */
57 *ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(ReplyMessage + 1);
58 SectionToMap = (*ConnectMessage)->SectionToMap;
59 (*ConnectMessage)->SectionToMap = NULL;
60 }
61 else
62 {
63 /* No message to return */
64 *Message = NULL;
65 SectionToMap = NULL;
66 }
67
68 /* Release the lock and return the section */
69 KeReleaseGuardedMutex(&LpcpLock);
70 return SectionToMap;
71 }
72
73 /* PUBLIC FUNCTIONS **********************************************************/
74
75 /*
76 * @implemented
77 */
78 NTSTATUS
79 NTAPI
80 NtSecureConnectPort(OUT PHANDLE PortHandle,
81 IN PUNICODE_STRING PortName,
82 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
83 IN OUT PPORT_VIEW ClientView OPTIONAL,
84 IN PSID ServerSid OPTIONAL,
85 IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL,
86 OUT PULONG MaxMessageLength OPTIONAL,
87 IN OUT PVOID ConnectionInformation OPTIONAL,
88 IN OUT PULONG ConnectionInformationLength OPTIONAL)
89 {
90 NTSTATUS Status = STATUS_SUCCESS;
91 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
92 PETHREAD Thread = PsGetCurrentThread();
93 SECURITY_QUALITY_OF_SERVICE CapturedQos;
94 PORT_VIEW CapturedClientView;
95 PSID CapturedServerSid;
96 ULONG ConnectionInfoLength = 0;
97 PLPCP_PORT_OBJECT Port, ClientPort;
98 PLPCP_MESSAGE Message;
99 PLPCP_CONNECTION_MESSAGE ConnectMessage;
100 ULONG PortMessageLength;
101 HANDLE Handle;
102 PVOID SectionToMap;
103 LARGE_INTEGER SectionOffset;
104 PTOKEN Token;
105 PTOKEN_USER TokenUserInfo;
106
107 PAGED_CODE();
108 LPCTRACE(LPC_CONNECT_DEBUG,
109 "Name: %wZ. SecurityQos: %p. Views: %p/%p. Sid: %p\n",
110 PortName,
111 SecurityQos,
112 ClientView,
113 ServerView,
114 ServerSid);
115
116 /* Check if the call comes from user mode */
117 if (PreviousMode != KernelMode)
118 {
119 /* Enter SEH for probing the parameters */
120 _SEH2_TRY
121 {
122 /* Probe the PortHandle */
123 ProbeForWriteHandle(PortHandle);
124
125 /* Probe and capture the QoS */
126 ProbeForRead(SecurityQos, sizeof(*SecurityQos), sizeof(ULONG));
127 CapturedQos = *(volatile SECURITY_QUALITY_OF_SERVICE*)SecurityQos;
128 /* NOTE: Do not care about CapturedQos.Length */
129
130 /* The following parameters are optional */
131
132 /* Capture the client view */
133 if (ClientView)
134 {
135 ProbeForWrite(ClientView, sizeof(*ClientView), sizeof(ULONG));
136 CapturedClientView = *(volatile PORT_VIEW*)ClientView;
137
138 /* Validate the size of the client view */
139 if (CapturedClientView.Length != sizeof(CapturedClientView))
140 {
141 /* Invalid size */
142 _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
143 }
144
145 }
146
147 /* Capture the server view */
148 if (ServerView)
149 {
150 ProbeForWrite(ServerView, sizeof(*ServerView), sizeof(ULONG));
151
152 /* Validate the size of the server view */
153 if (((volatile REMOTE_PORT_VIEW*)ServerView)->Length != sizeof(*ServerView))
154 {
155 /* Invalid size */
156 _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
157 }
158 }
159
160 if (MaxMessageLength)
161 ProbeForWriteUlong(MaxMessageLength);
162
163 /* Capture connection information length */
164 if (ConnectionInformationLength)
165 {
166 ProbeForWriteUlong(ConnectionInformationLength);
167 ConnectionInfoLength = *(volatile ULONG*)ConnectionInformationLength;
168 }
169
170 /* Probe the ConnectionInformation */
171 if (ConnectionInformation)
172 ProbeForWrite(ConnectionInformation, ConnectionInfoLength, sizeof(ULONG));
173
174 CapturedServerSid = ServerSid;
175 if (ServerSid != NULL)
176 {
177 /* Capture it */
178 Status = SepCaptureSid(ServerSid,
179 PreviousMode,
180 PagedPool,
181 TRUE,
182 &CapturedServerSid);
183 if (!NT_SUCCESS(Status))
184 {
185 DPRINT1("Failed to capture ServerSid!\n");
186 _SEH2_YIELD(return Status);
187 }
188 }
189 }
190 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
191 {
192 /* There was an exception, return the exception code */
193 _SEH2_YIELD(return _SEH2_GetExceptionCode());
194 }
195 _SEH2_END;
196 }
197 else
198 {
199 CapturedQos = *SecurityQos;
200 /* NOTE: Do not care about CapturedQos.Length */
201
202 /* The following parameters are optional */
203
204 /* Capture the client view */
205 if (ClientView)
206 {
207 /* Validate the size of the client view */
208 if (ClientView->Length != sizeof(*ClientView))
209 {
210 /* Invalid size */
211 return STATUS_INVALID_PARAMETER;
212 }
213 CapturedClientView = *ClientView;
214 }
215
216 /* Capture the server view */
217 if (ServerView)
218 {
219 /* Validate the size of the server view */
220 if (ServerView->Length != sizeof(*ServerView))
221 {
222 /* Invalid size */
223 return STATUS_INVALID_PARAMETER;
224 }
225 }
226
227 /* Capture connection information length */
228 if (ConnectionInformationLength)
229 ConnectionInfoLength = *ConnectionInformationLength;
230
231 CapturedServerSid = ServerSid;
232 }
233
234 /* Get the port */
235 Status = ObReferenceObjectByName(PortName,
236 0,
237 NULL,
238 PORT_CONNECT,
239 LpcPortObjectType,
240 PreviousMode,
241 NULL,
242 (PVOID*)&Port);
243 if (!NT_SUCCESS(Status))
244 {
245 DPRINT1("Failed to reference port '%wZ': 0x%lx\n", PortName, Status);
246
247 if (CapturedServerSid != ServerSid)
248 SepReleaseSid(CapturedServerSid, PreviousMode, TRUE);
249
250 return Status;
251 }
252
253 /* This has to be a connection port */
254 if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT)
255 {
256 DPRINT1("Port '%wZ' is not a connection port (Flags: 0x%lx)\n", PortName, Port->Flags);
257
258 /* It isn't, so fail */
259 ObDereferenceObject(Port);
260
261 if (CapturedServerSid != ServerSid)
262 SepReleaseSid(CapturedServerSid, PreviousMode, TRUE);
263
264 return STATUS_INVALID_PORT_HANDLE;
265 }
266
267 /* Check if we have a (captured) SID */
268 if (ServerSid)
269 {
270 /* Make sure that we have a server */
271 if (Port->ServerProcess)
272 {
273 /* Get its token and query user information */
274 Token = PsReferencePrimaryToken(Port->ServerProcess);
275 Status = SeQueryInformationToken(Token, TokenUser, (PVOID*)&TokenUserInfo);
276 PsDereferencePrimaryToken(Token);
277
278 /* Check for success */
279 if (NT_SUCCESS(Status))
280 {
281 /* Compare the SIDs */
282 if (!RtlEqualSid(CapturedServerSid, TokenUserInfo->User.Sid))
283 {
284 /* Fail */
285 DPRINT1("Port '%wZ': server SID mismatch\n", PortName);
286 Status = STATUS_SERVER_SID_MISMATCH;
287 }
288
289 /* Free token information */
290 ExFreePoolWithTag(TokenUserInfo, TAG_SE);
291 }
292 }
293 else
294 {
295 /* Invalid SID */
296 DPRINT1("Port '%wZ': server SID mismatch\n", PortName);
297 Status = STATUS_SERVER_SID_MISMATCH;
298 }
299
300 /* Finally release the captured SID, we don't need it anymore */
301 if (CapturedServerSid != ServerSid)
302 SepReleaseSid(CapturedServerSid, PreviousMode, TRUE);
303
304 /* Check if SID failed */
305 if (!NT_SUCCESS(Status))
306 {
307 /* Quit */
308 ObDereferenceObject(Port);
309 return Status;
310 }
311 }
312
313 /* Create the client port */
314 Status = ObCreateObject(PreviousMode,
315 LpcPortObjectType,
316 NULL,
317 PreviousMode,
318 NULL,
319 sizeof(LPCP_PORT_OBJECT),
320 0,
321 0,
322 (PVOID*)&ClientPort);
323 if (!NT_SUCCESS(Status))
324 {
325 /* Failed, dereference the server port and return */
326 DPRINT1("Failed to create Port object: 0x%lx\n", Status);
327 ObDereferenceObject(Port);
328 return Status;
329 }
330
331 /*
332 * Setup the client port -- From now on, dereferencing the client port
333 * will automatically dereference the connection port too.
334 */
335 RtlZeroMemory(ClientPort, sizeof(LPCP_PORT_OBJECT));
336 ClientPort->Flags = LPCP_CLIENT_PORT;
337 ClientPort->ConnectionPort = Port;
338 ClientPort->MaxMessageLength = Port->MaxMessageLength;
339 ClientPort->SecurityQos = CapturedQos;
340 InitializeListHead(&ClientPort->LpcReplyChainHead);
341 InitializeListHead(&ClientPort->LpcDataInfoChainHead);
342
343 /* Check if we have dynamic security */
344 if (CapturedQos.ContextTrackingMode == SECURITY_DYNAMIC_TRACKING)
345 {
346 /* Remember that */
347 ClientPort->Flags |= LPCP_SECURITY_DYNAMIC;
348 }
349 else
350 {
351 /* Create our own client security */
352 Status = SeCreateClientSecurity(Thread,
353 &CapturedQos,
354 FALSE,
355 &ClientPort->StaticSecurity);
356 if (!NT_SUCCESS(Status))
357 {
358 /* Security failed, dereference and return */
359 DPRINT1("SeCreateClientSecurity failed: 0x%lx\n", Status);
360 ObDereferenceObject(ClientPort);
361 return Status;
362 }
363 }
364
365 /* Initialize the port queue */
366 Status = LpcpInitializePortQueue(ClientPort);
367 if (!NT_SUCCESS(Status))
368 {
369 /* Failed */
370 DPRINT1("LpcpInitializePortQueue failed: 0x%lx\n", Status);
371 ObDereferenceObject(ClientPort);
372 return Status;
373 }
374
375 /* Check if we have a client view */
376 if (ClientView)
377 {
378 /* Get the section handle */
379 Status = ObReferenceObjectByHandle(CapturedClientView.SectionHandle,
380 SECTION_MAP_READ |
381 SECTION_MAP_WRITE,
382 MmSectionObjectType,
383 PreviousMode,
384 (PVOID*)&SectionToMap,
385 NULL);
386 if (!NT_SUCCESS(Status))
387 {
388 /* Fail */
389 DPRINT1("Failed to reference port section handle: 0x%lx\n", Status);
390 ObDereferenceObject(ClientPort);
391 return Status;
392 }
393
394 /* Set the section offset */
395 SectionOffset.QuadPart = CapturedClientView.SectionOffset;
396
397 /* Map it */
398 Status = MmMapViewOfSection(SectionToMap,
399 PsGetCurrentProcess(),
400 &ClientPort->ClientSectionBase,
401 0,
402 0,
403 &SectionOffset,
404 &CapturedClientView.ViewSize,
405 ViewUnmap,
406 0,
407 PAGE_READWRITE);
408
409 /* Update the offset */
410 CapturedClientView.SectionOffset = SectionOffset.LowPart;
411
412 /* Check for failure */
413 if (!NT_SUCCESS(Status))
414 {
415 /* Fail */
416 DPRINT1("Failed to map port section: 0x%lx\n", Status);
417 ObDereferenceObject(SectionToMap);
418 ObDereferenceObject(ClientPort);
419 return Status;
420 }
421
422 /* Update the base */
423 CapturedClientView.ViewBase = ClientPort->ClientSectionBase;
424
425 /* Reference and remember the process */
426 ClientPort->MappingProcess = PsGetCurrentProcess();
427 ObReferenceObject(ClientPort->MappingProcess);
428 }
429 else
430 {
431 /* No section */
432 SectionToMap = NULL;
433 }
434
435 /* Normalize connection information */
436 if (ConnectionInfoLength > Port->MaxConnectionInfoLength)
437 {
438 /* Use the port's maximum allowed value */
439 ConnectionInfoLength = Port->MaxConnectionInfoLength;
440 }
441
442 /* Allocate a message from the port zone */
443 Message = LpcpAllocateFromPortZone();
444 if (!Message)
445 {
446 /* Fail if we couldn't allocate a message */
447 DPRINT1("LpcpAllocateFromPortZone failed\n");
448 if (SectionToMap) ObDereferenceObject(SectionToMap);
449 ObDereferenceObject(ClientPort);
450 return STATUS_NO_MEMORY;
451 }
452
453 /* Set pointer to the connection message and fill in the CID */
454 ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
455 Message->Request.ClientId = Thread->Cid;
456
457 /* Check if we have a client view */
458 if (ClientView)
459 {
460 /* Set the view size */
461 Message->Request.ClientViewSize = CapturedClientView.ViewSize;
462
463 /* Copy the client view and clear the server view */
464 RtlCopyMemory(&ConnectMessage->ClientView,
465 &CapturedClientView,
466 sizeof(CapturedClientView));
467 RtlZeroMemory(&ConnectMessage->ServerView, sizeof(REMOTE_PORT_VIEW));
468 }
469 else
470 {
471 /* Set the size to 0 and clear the connect message */
472 Message->Request.ClientViewSize = 0;
473 RtlZeroMemory(ConnectMessage, sizeof(LPCP_CONNECTION_MESSAGE));
474 }
475
476 /* Set the section and client port. Port is NULL for now */
477 ConnectMessage->ClientPort = NULL;
478 ConnectMessage->SectionToMap = SectionToMap;
479
480 /* Set the data for the connection request message */
481 Message->Request.u1.s1.DataLength = (CSHORT)ConnectionInfoLength +
482 sizeof(LPCP_CONNECTION_MESSAGE);
483 Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
484 Message->Request.u1.s1.DataLength;
485 Message->Request.u2.s2.Type = LPC_CONNECTION_REQUEST;
486
487 /* Check if we have connection information */
488 if (ConnectionInformation)
489 {
490 _SEH2_TRY
491 {
492 /* Copy it in */
493 RtlCopyMemory(ConnectMessage + 1,
494 ConnectionInformation,
495 ConnectionInfoLength);
496 }
497 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
498 {
499 DPRINT1("Exception 0x%lx when copying connection info to user mode\n",
500 _SEH2_GetExceptionCode());
501
502 /* Cleanup and return the exception code */
503
504 /* Free the message we have */
505 LpcpFreeToPortZone(Message, 0);
506
507 /* Dereference other objects */
508 if (SectionToMap) ObDereferenceObject(SectionToMap);
509 ObDereferenceObject(ClientPort);
510
511 /* Return status */
512 _SEH2_YIELD(return _SEH2_GetExceptionCode());
513 }
514 _SEH2_END;
515 }
516
517 /* Reset the status code */
518 Status = STATUS_SUCCESS;
519
520 /* Acquire the port lock */
521 KeAcquireGuardedMutex(&LpcpLock);
522
523 /* Check if someone already deleted the port name */
524 if (Port->Flags & LPCP_NAME_DELETED)
525 {
526 /* Fail the request */
527 Status = STATUS_OBJECT_NAME_NOT_FOUND;
528 }
529 else
530 {
531 /* Associate no thread yet */
532 Message->RepliedToThread = NULL;
533
534 /* Generate the Message ID and set it */
535 Message->Request.MessageId = LpcpNextMessageId++;
536 if (!LpcpNextMessageId) LpcpNextMessageId = 1;
537 Thread->LpcReplyMessageId = Message->Request.MessageId;
538
539 /* Insert the message into the queue and thread chain */
540 InsertTailList(&Port->MsgQueue.ReceiveHead, &Message->Entry);
541 InsertTailList(&Port->LpcReplyChainHead, &Thread->LpcReplyChain);
542 Thread->LpcReplyMessage = Message;
543
544 /* Now we can finally reference the client port and link it */
545 ObReferenceObject(ClientPort);
546 ConnectMessage->ClientPort = ClientPort;
547
548 /* Enter a critical region */
549 KeEnterCriticalRegion();
550 }
551
552 /* Add another reference to the port */
553 ObReferenceObject(Port);
554
555 /* Release the lock */
556 KeReleaseGuardedMutex(&LpcpLock);
557
558 /* Check for success */
559 if (NT_SUCCESS(Status))
560 {
561 LPCTRACE(LPC_CONNECT_DEBUG,
562 "Messages: %p/%p. Ports: %p/%p. Status: %lx\n",
563 Message,
564 ConnectMessage,
565 Port,
566 ClientPort,
567 Status);
568
569 /* If this is a waitable port, set the event */
570 if (Port->Flags & LPCP_WAITABLE_PORT)
571 KeSetEvent(&Port->WaitEvent, 1, FALSE);
572
573 /* Release the queue semaphore and leave the critical region */
574 LpcpCompleteWait(Port->MsgQueue.Semaphore);
575 KeLeaveCriticalRegion();
576
577 /* Now wait for a reply and set 'Status' */
578 LpcpConnectWait(&Thread->LpcReplySemaphore, PreviousMode);
579 }
580
581 /* Now, always free the connection message */
582 SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread);
583
584 /* Check for failure */
585 if (!NT_SUCCESS(Status))
586 {
587 /* Check if the semaphore got signaled in the meantime */
588 if (KeReadStateSemaphore(&Thread->LpcReplySemaphore))
589 {
590 /* Wait on it */
591 KeWaitForSingleObject(&Thread->LpcReplySemaphore,
592 WrExecutive,
593 KernelMode,
594 FALSE,
595 NULL);
596 }
597
598 goto Failure;
599 }
600
601 /* Check if we got a message back */
602 if (Message)
603 {
604 /* Check for new return length */
605 if ((Message->Request.u1.s1.DataLength -
606 sizeof(LPCP_CONNECTION_MESSAGE)) < ConnectionInfoLength)
607 {
608 /* Set new normalized connection length */
609 ConnectionInfoLength = Message->Request.u1.s1.DataLength -
610 sizeof(LPCP_CONNECTION_MESSAGE);
611 }
612
613 /* Check if the caller had connection information */
614 if (ConnectionInformation)
615 {
616 _SEH2_TRY
617 {
618 /* Return the connection information length if needed */
619 if (ConnectionInformationLength)
620 *ConnectionInformationLength = ConnectionInfoLength;
621
622 /* Return the connection information */
623 RtlCopyMemory(ConnectionInformation,
624 ConnectMessage + 1,
625 ConnectionInfoLength);
626 }
627 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
628 {
629 /* Cleanup and return the exception code */
630 Status = _SEH2_GetExceptionCode();
631 _SEH2_YIELD(goto Failure);
632 }
633 _SEH2_END;
634 }
635
636 /* Make sure we had a connected port */
637 if (ClientPort->ConnectedPort)
638 {
639 /* Get the message length before the port might get killed */
640 PortMessageLength = Port->MaxMessageLength;
641
642 /* Insert the client port */
643 Status = ObInsertObject(ClientPort,
644 NULL,
645 PORT_ALL_ACCESS,
646 0,
647 NULL,
648 &Handle);
649 if (NT_SUCCESS(Status))
650 {
651 LPCTRACE(LPC_CONNECT_DEBUG,
652 "Handle: %p. Length: %lx\n",
653 Handle,
654 PortMessageLength);
655
656 _SEH2_TRY
657 {
658 /* Return the handle */
659 *PortHandle = Handle;
660
661 /* Check if maximum length was requested */
662 if (MaxMessageLength)
663 *MaxMessageLength = PortMessageLength;
664
665 /* Check if we had a client view */
666 if (ClientView)
667 {
668 /* Copy it back */
669 RtlCopyMemory(ClientView,
670 &ConnectMessage->ClientView,
671 sizeof(*ClientView));
672 }
673
674 /* Check if we had a server view */
675 if (ServerView)
676 {
677 /* Copy it back */
678 RtlCopyMemory(ServerView,
679 &ConnectMessage->ServerView,
680 sizeof(*ServerView));
681 }
682 }
683 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
684 {
685 /* An exception happened, close the opened handle */
686 ObCloseHandle(Handle, PreviousMode);
687 Status = _SEH2_GetExceptionCode();
688 }
689 _SEH2_END;
690 }
691 }
692 else
693 {
694 /* No connection port, we failed */
695 if (SectionToMap) ObDereferenceObject(SectionToMap);
696
697 /* Acquire the lock */
698 KeAcquireGuardedMutex(&LpcpLock);
699
700 /* Check if it's because the name got deleted */
701 if (!(ClientPort->ConnectionPort) ||
702 (Port->Flags & LPCP_NAME_DELETED))
703 {
704 /* Set the correct status */
705 Status = STATUS_OBJECT_NAME_NOT_FOUND;
706 }
707 else
708 {
709 /* Otherwise, the caller refused us */
710 Status = STATUS_PORT_CONNECTION_REFUSED;
711 }
712
713 /* Release the lock */
714 KeReleaseGuardedMutex(&LpcpLock);
715
716 /* Kill the port */
717 ObDereferenceObject(ClientPort);
718 }
719
720 /* Free the message */
721 LpcpFreeToPortZone(Message, 0);
722 }
723 else
724 {
725 /* No reply message, fail */
726 Status = STATUS_PORT_CONNECTION_REFUSED;
727 goto Failure;
728 }
729
730 ObDereferenceObject(Port);
731
732 /* Return status */
733 return Status;
734
735 Failure:
736 /* Check if we had a message and free it */
737 if (Message) LpcpFreeToPortZone(Message, 0);
738
739 /* Dereference other objects */
740 if (SectionToMap) ObDereferenceObject(SectionToMap);
741 ObDereferenceObject(ClientPort);
742 ObDereferenceObject(Port);
743
744 /* Return status */
745 return Status;
746 }
747
748 /*
749 * @implemented
750 */
751 NTSTATUS
752 NTAPI
753 NtConnectPort(OUT PHANDLE PortHandle,
754 IN PUNICODE_STRING PortName,
755 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
756 IN OUT PPORT_VIEW ClientView OPTIONAL,
757 IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL,
758 OUT PULONG MaxMessageLength OPTIONAL,
759 IN OUT PVOID ConnectionInformation OPTIONAL,
760 IN OUT PULONG ConnectionInformationLength OPTIONAL)
761 {
762 /* Call the newer API */
763 return NtSecureConnectPort(PortHandle,
764 PortName,
765 SecurityQos,
766 ClientView,
767 NULL,
768 ServerView,
769 MaxMessageLength,
770 ConnectionInformation,
771 ConnectionInformationLength);
772 }
773
774 /* EOF */