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 */ 775