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