diff options
author | Rob Mensching <rob@firegiant.com> | 2024-07-14 23:58:39 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2024-10-04 12:53:32 -0700 |
commit | a04c8d7d821bdea2832f04d19e05f9560da65603 (patch) | |
tree | 485e88a9586082786f4390e7d43a52e608753a2c | |
parent | 123c7f022b5a5acd1a0ddcc8b38e21fe2e128462 (diff) | |
download | wix-a04c8d7d821bdea2832f04d19e05f9560da65603.tar.gz wix-a04c8d7d821bdea2832f04d19e05f9560da65603.tar.bz2 wix-a04c8d7d821bdea2832f04d19e05f9560da65603.zip |
Fix faulty memory access in Util's User custom actions
Generally, clean up the handling of getting the domain from a server name by
centralizing and simplifying it behind an improved GetDomainFromServerName()
based on the buggy GetServerName().
Fixes 8576
-rw-r--r-- | src/ext/Util/ca/precomp.h | 3 | ||||
-rw-r--r-- | src/ext/Util/ca/scaexec.cpp | 100 | ||||
-rw-r--r-- | src/ext/Util/ca/scauser.cpp | 48 | ||||
-rw-r--r-- | src/ext/Util/ca/utilca.cpp | 56 | ||||
-rw-r--r-- | src/ext/Util/ca/utilca.h | 8 |
5 files changed, 95 insertions, 120 deletions
diff --git a/src/ext/Util/ca/precomp.h b/src/ext/Util/ca/precomp.h index efde32a6..9456c691 100644 --- a/src/ext/Util/ca/precomp.h +++ b/src/ext/Util/ca/precomp.h | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #include <msxml2.h> | 16 | #include <msxml2.h> |
17 | #include <Iads.h> | 17 | #include <Iads.h> |
18 | #include <activeds.h> | 18 | #include <activeds.h> |
19 | #include <lm.h> // NetApi32.lib | 19 | #include <lm.h> // NetApi32.lib |
20 | #include <Ntsecapi.h> | 20 | #include <Ntsecapi.h> |
21 | #include <Dsgetdc.h> | 21 | #include <Dsgetdc.h> |
@@ -50,5 +50,6 @@ | |||
50 | #include "scauser.h" | 50 | #include "scauser.h" |
51 | #include "scasmb.h" | 51 | #include "scasmb.h" |
52 | #include "scasmbexec.h" | 52 | #include "scasmbexec.h" |
53 | #include "utilca.h" | ||
53 | 54 | ||
54 | #include "..\..\caDecor.h" | 55 | #include "..\..\caDecor.h" |
diff --git a/src/ext/Util/ca/scaexec.cpp b/src/ext/Util/ca/scaexec.cpp index 5119bc11..8579b8bb 100644 --- a/src/ext/Util/ca/scaexec.cpp +++ b/src/ext/Util/ca/scaexec.cpp | |||
@@ -613,8 +613,7 @@ static HRESULT RemoveUserInternal( | |||
613 | LPWSTR pwz = NULL; | 613 | LPWSTR pwz = NULL; |
614 | LPWSTR pwzGroup = NULL; | 614 | LPWSTR pwzGroup = NULL; |
615 | LPWSTR pwzGroupDomain = NULL; | 615 | LPWSTR pwzGroupDomain = NULL; |
616 | LPCWSTR wz = NULL; | 616 | LPWSTR pwzDomainName = NULL; |
617 | PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; | ||
618 | 617 | ||
619 | // | 618 | // |
620 | // Remove the logon as service privilege. | 619 | // Remove the logon as service privilege. |
@@ -644,30 +643,10 @@ static HRESULT RemoveUserInternal( | |||
644 | // | 643 | // |
645 | if (!(SCAU_DONT_CREATE_USER & iAttributes)) | 644 | if (!(SCAU_DONT_CREATE_USER & iAttributes)) |
646 | { | 645 | { |
647 | if (wzDomain && *wzDomain) | 646 | hr = GetDomainFromServerName(&pwzDomainName, wzDomain, 0); |
648 | { | 647 | ExitOnFailure(hr, "Failed to get domain to remove user from server name: %ls", wzDomain); |
649 | er = ::DsGetDcNameW(NULL, (LPCWSTR)wzDomain, NULL, NULL, NULL, &pDomainControllerInfo); | ||
650 | if (RPC_S_SERVER_UNAVAILABLE == er) | ||
651 | { | ||
652 | // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag | ||
653 | er = ::DsGetDcNameW(NULL, (LPCWSTR)wzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo); | ||
654 | } | ||
655 | if (ERROR_SUCCESS == er) | ||
656 | { | ||
657 | if (2 <= wcslen(pDomainControllerInfo->DomainControllerName)) | ||
658 | { | ||
659 | wz = pDomainControllerInfo->DomainControllerName + 2; // Add 2 so that we don't get the \\ prefix. | ||
660 | // Pass the entire string if it is too short | ||
661 | // to have a \\ prefix. | ||
662 | } | ||
663 | } | ||
664 | else | ||
665 | { | ||
666 | wz = wzDomain; | ||
667 | } | ||
668 | } | ||
669 | 648 | ||
670 | er = ::NetUserDel(wz, wzName); | 649 | er = ::NetUserDel(pwzDomainName, wzName); |
671 | if (NERR_UserNotFound == er) | 650 | if (NERR_UserNotFound == er) |
672 | { | 651 | { |
673 | er = NERR_Success; | 652 | er = NERR_Success; |
@@ -707,52 +686,13 @@ static HRESULT RemoveUserInternal( | |||
707 | } | 686 | } |
708 | 687 | ||
709 | LExit: | 688 | LExit: |
710 | if (pDomainControllerInfo) | 689 | ReleaseStr(pwzDomainName); |
711 | { | 690 | ReleaseStr(pwzGroupDomain); |
712 | ::NetApiBufferFree(static_cast<LPVOID>(pDomainControllerInfo)); | 691 | ReleaseStr(pwzGroup); |
713 | } | ||
714 | 692 | ||
715 | return hr; | 693 | return hr; |
716 | } | 694 | } |
717 | 695 | ||
718 | static void GetServerName(LPWSTR pwzDomain, LPWSTR* ppwzServerName) | ||
719 | { | ||
720 | DWORD er = ERROR_SUCCESS; | ||
721 | PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; | ||
722 | |||
723 | if (pwzDomain && *pwzDomain) | ||
724 | { | ||
725 | er = ::DsGetDcNameW(NULL, (LPCWSTR)pwzDomain, NULL, NULL, NULL, &pDomainControllerInfo); | ||
726 | if (RPC_S_SERVER_UNAVAILABLE == er) | ||
727 | { | ||
728 | // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag | ||
729 | er = ::DsGetDcNameW(NULL, (LPCWSTR)pwzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo); | ||
730 | } | ||
731 | |||
732 | if (ERROR_SUCCESS == er && pDomainControllerInfo->DomainControllerName) | ||
733 | { | ||
734 | // Skip the \\ prefix if present. | ||
735 | if ('\\' == *pDomainControllerInfo->DomainControllerName && '\\' == *pDomainControllerInfo->DomainControllerName + 1) | ||
736 | { | ||
737 | *ppwzServerName = pDomainControllerInfo->DomainControllerName + 2; | ||
738 | } | ||
739 | else | ||
740 | { | ||
741 | *ppwzServerName = pDomainControllerInfo->DomainControllerName; | ||
742 | } | ||
743 | } | ||
744 | else | ||
745 | { | ||
746 | *ppwzServerName = pwzDomain; | ||
747 | } | ||
748 | } | ||
749 | |||
750 | if (pDomainControllerInfo) | ||
751 | { | ||
752 | ::NetApiBufferFree((LPVOID)pDomainControllerInfo); | ||
753 | } | ||
754 | } | ||
755 | |||
756 | /******************************************************************** | 696 | /******************************************************************** |
757 | CreateUser - CUSTOM ACTION ENTRY POINT for creating users | 697 | CreateUser - CUSTOM ACTION ENTRY POINT for creating users |
758 | 698 | ||
@@ -776,6 +716,7 @@ extern "C" UINT __stdcall CreateUser( | |||
776 | LPWSTR pwzPassword = NULL; | 716 | LPWSTR pwzPassword = NULL; |
777 | LPWSTR pwzGroup = NULL; | 717 | LPWSTR pwzGroup = NULL; |
778 | LPWSTR pwzGroupDomain = NULL; | 718 | LPWSTR pwzGroupDomain = NULL; |
719 | LPWSTR pwzDomainName = NULL; | ||
779 | int iAttributes = 0; | 720 | int iAttributes = 0; |
780 | BOOL fInitializedCom = FALSE; | 721 | BOOL fInitializedCom = FALSE; |
781 | 722 | ||
@@ -786,7 +727,6 @@ extern "C" UINT __stdcall CreateUser( | |||
786 | USER_INFO_1 userInfo1; | 727 | USER_INFO_1 userInfo1; |
787 | USER_INFO_1* pUserInfo1 = NULL; | 728 | USER_INFO_1* pUserInfo1 = NULL; |
788 | DWORD dw; | 729 | DWORD dw; |
789 | LPWSTR pwzServerName = NULL; | ||
790 | 730 | ||
791 | hr = WcaInitialize(hInstall, "CreateUser"); | 731 | hr = WcaInitialize(hInstall, "CreateUser"); |
792 | ExitOnFailure(hr, "failed to initialize"); | 732 | ExitOnFailure(hr, "failed to initialize"); |
@@ -845,9 +785,10 @@ extern "C" UINT __stdcall CreateUser( | |||
845 | // | 785 | // |
846 | // Create the User | 786 | // Create the User |
847 | // | 787 | // |
848 | GetServerName(pwzDomain, &pwzServerName); | 788 | hr = GetDomainFromServerName(&pwzDomainName, pwzDomain, 0); |
789 | ExitOnFailure(hr, "Failed to get domain from server name: %ls", pwzDomain); | ||
849 | 790 | ||
850 | er = ::NetUserAdd(pwzServerName, 1, reinterpret_cast<LPBYTE>(pUserInfo1), &dw); | 791 | er = ::NetUserAdd(pwzDomainName, 1, reinterpret_cast<LPBYTE>(pUserInfo1), &dw); |
851 | if (NERR_UserExists == er) | 792 | if (NERR_UserExists == er) |
852 | { | 793 | { |
853 | if (SCAU_FAIL_IF_EXISTS & iAttributes) | 794 | if (SCAU_FAIL_IF_EXISTS & iAttributes) |
@@ -862,7 +803,7 @@ extern "C" UINT __stdcall CreateUser( | |||
862 | if (SCAU_UPDATE_IF_EXISTS & iAttributes) | 803 | if (SCAU_UPDATE_IF_EXISTS & iAttributes) |
863 | { | 804 | { |
864 | pUserInfo1 = NULL; | 805 | pUserInfo1 = NULL; |
865 | er = ::NetUserGetInfo(pwzServerName, pwzName, 1, reinterpret_cast<LPBYTE*>(&pUserInfo1)); | 806 | er = ::NetUserGetInfo(pwzDomainName, pwzName, 1, reinterpret_cast<LPBYTE*>(&pUserInfo1)); |
866 | if (ERROR_SUCCESS == er) | 807 | if (ERROR_SUCCESS == er) |
867 | { | 808 | { |
868 | // There is no rollback scheduled if the key is empty. | 809 | // There is no rollback scheduled if the key is empty. |
@@ -922,28 +863,28 @@ extern "C" UINT __stdcall CreateUser( | |||
922 | 863 | ||
923 | if (ERROR_SUCCESS == er) | 864 | if (ERROR_SUCCESS == er) |
924 | { | 865 | { |
925 | hr = SetUserPassword(pwzServerName, pwzName, pwzPassword); | 866 | hr = SetUserPassword(pwzDomainName, pwzName, pwzPassword); |
926 | if (FAILED(hr)) | 867 | if (FAILED(hr)) |
927 | { | 868 | { |
928 | WcaLogError(hr, "failed to set user password for user %ls\\%ls, continuing anyway.", pwzServerName, pwzName); | 869 | WcaLogError(hr, "failed to set user password for user %ls\\%ls, continuing anyway.", pwzDomainName, pwzName); |
929 | hr = S_OK; | 870 | hr = S_OK; |
930 | } | 871 | } |
931 | 872 | ||
932 | if (SCAU_REMOVE_COMMENT & iAttributes) | 873 | if (SCAU_REMOVE_COMMENT & iAttributes) |
933 | { | 874 | { |
934 | hr = SetUserComment(pwzServerName, pwzName, L""); | 875 | hr = SetUserComment(pwzDomainName, pwzName, L""); |
935 | if (FAILED(hr)) | 876 | if (FAILED(hr)) |
936 | { | 877 | { |
937 | WcaLogError(hr, "failed to clear user comment for user %ls\\%ls, continuing anyway.", pwzServerName, pwzName); | 878 | WcaLogError(hr, "failed to clear user comment for user %ls\\%ls, continuing anyway.", pwzDomainName, pwzName); |
938 | hr = S_OK; | 879 | hr = S_OK; |
939 | } | 880 | } |
940 | } | 881 | } |
941 | else if (pwzComment && *pwzComment) | 882 | else if (pwzComment && *pwzComment) |
942 | { | 883 | { |
943 | hr = SetUserComment(pwzServerName, pwzName, pwzComment); | 884 | hr = SetUserComment(pwzDomainName, pwzName, pwzComment); |
944 | if (FAILED(hr)) | 885 | if (FAILED(hr)) |
945 | { | 886 | { |
946 | WcaLogError(hr, "failed to set user comment to %ls for user %ls\\%ls, continuing anyway.", pwzComment, pwzServerName, pwzName); | 887 | WcaLogError(hr, "failed to set user comment to %ls for user %ls\\%ls, continuing anyway.", pwzComment, pwzDomainName, pwzName); |
947 | hr = S_OK; | 888 | hr = S_OK; |
948 | } | 889 | } |
949 | } | 890 | } |
@@ -952,10 +893,10 @@ extern "C" UINT __stdcall CreateUser( | |||
952 | 893 | ||
953 | ApplyAttributes(iAttributes, &flags); | 894 | ApplyAttributes(iAttributes, &flags); |
954 | 895 | ||
955 | hr = SetUserFlags(pwzServerName, pwzName, flags); | 896 | hr = SetUserFlags(pwzDomainName, pwzName, flags); |
956 | if (FAILED(hr)) | 897 | if (FAILED(hr)) |
957 | { | 898 | { |
958 | WcaLogError(hr, "failed to set user flags for user %ls\\%ls, continuing anyway.", pwzServerName, pwzName); | 899 | WcaLogError(hr, "failed to set user flags for user %ls\\%ls, continuing anyway.", pwzDomainName, pwzName); |
959 | hr = S_OK; | 900 | hr = S_OK; |
960 | } | 901 | } |
961 | } | 902 | } |
@@ -1018,6 +959,7 @@ LExit: | |||
1018 | ReleaseStr(pwzPassword); | 959 | ReleaseStr(pwzPassword); |
1019 | ReleaseStr(pwzGroup); | 960 | ReleaseStr(pwzGroup); |
1020 | ReleaseStr(pwzGroupDomain); | 961 | ReleaseStr(pwzGroupDomain); |
962 | ReleaseStr(pwzDomainName) | ||
1021 | 963 | ||
1022 | if (fInitializedCom) | 964 | if (fInitializedCom) |
1023 | { | 965 | { |
diff --git a/src/ext/Util/ca/scauser.cpp b/src/ext/Util/ca/scauser.cpp index b643a842..79da155f 100644 --- a/src/ext/Util/ca/scauser.cpp +++ b/src/ext/Util/ca/scauser.cpp | |||
@@ -487,7 +487,7 @@ HRESULT ScaUserExecute( | |||
487 | { | 487 | { |
488 | HRESULT hr = S_OK; | 488 | HRESULT hr = S_OK; |
489 | DWORD er = 0; | 489 | DWORD er = 0; |
490 | PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; | 490 | LPWSTR pwzDomainName = NULL; |
491 | 491 | ||
492 | LPWSTR pwzBaseScriptKey = NULL; | 492 | LPWSTR pwzBaseScriptKey = NULL; |
493 | DWORD cScriptKey = 0; | 493 | DWORD cScriptKey = 0; |
@@ -518,36 +518,11 @@ HRESULT ScaUserExecute( | |||
518 | ExitOnFailure(hr, "Failed to add user comment to custom action data: %ls", psu->wzComment); | 518 | ExitOnFailure(hr, "Failed to add user comment to custom action data: %ls", psu->wzComment); |
519 | 519 | ||
520 | // Check to see if the user already exists since we have to be very careful when adding | 520 | // Check to see if the user already exists since we have to be very careful when adding |
521 | // and removing users. Note: MSDN says that it is safe to call these APIs from any | 521 | // and removing users. |
522 | // user, so we should be safe calling it during immediate mode. | 522 | hr = GetDomainFromServerName(&pwzDomainName, psu->wzDomain, 0); |
523 | er = ::NetApiBufferAllocate(sizeof(USER_INFO_0), reinterpret_cast<LPVOID*>(&pUserInfo)); | 523 | ExitOnFailure(hr, "Failed to get domain from server name: %ls", psu->wzDomain); |
524 | hr = HRESULT_FROM_WIN32(er); | ||
525 | ExitOnFailure(hr, "Failed to allocate memory to check existence of user: %ls", psu->wzName); | ||
526 | |||
527 | LPCWSTR wzDomain = psu->wzDomain; | ||
528 | if (wzDomain && *wzDomain) | ||
529 | { | ||
530 | er = ::DsGetDcNameW(NULL, wzDomain, NULL, NULL, NULL, &pDomainControllerInfo); | ||
531 | if (RPC_S_SERVER_UNAVAILABLE == er) | ||
532 | { | ||
533 | // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag | ||
534 | er = ::DsGetDcNameW(NULL, wzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo); | ||
535 | } | ||
536 | if (ERROR_SUCCESS == er && pDomainControllerInfo->DomainControllerName) | ||
537 | { | ||
538 | // If the \\ prefix on the queried domain was present, skip it. | ||
539 | if ('\\' == *pDomainControllerInfo->DomainControllerName && '\\' == *pDomainControllerInfo->DomainControllerName + 1) | ||
540 | { | ||
541 | wzDomain = pDomainControllerInfo->DomainControllerName + 2; | ||
542 | } | ||
543 | else | ||
544 | { | ||
545 | wzDomain = pDomainControllerInfo->DomainControllerName; | ||
546 | } | ||
547 | } | ||
548 | } | ||
549 | 524 | ||
550 | er = ::NetUserGetInfo(wzDomain, psu->wzName, 0, reinterpret_cast<LPBYTE*>(pUserInfo)); | 525 | er = ::NetUserGetInfo(pwzDomainName, psu->wzName, 0, reinterpret_cast<LPBYTE*>(&pUserInfo)); |
551 | if (NERR_Success == er) | 526 | if (NERR_Success == er) |
552 | { | 527 | { |
553 | ueUserExists = USER_EXISTS_YES; | 528 | ueUserExists = USER_EXISTS_YES; |
@@ -560,7 +535,7 @@ HRESULT ScaUserExecute( | |||
560 | { | 535 | { |
561 | ueUserExists = USER_EXISTS_INDETERMINATE; | 536 | ueUserExists = USER_EXISTS_INDETERMINATE; |
562 | hr = HRESULT_FROM_WIN32(er); | 537 | hr = HRESULT_FROM_WIN32(er); |
563 | WcaLog(LOGMSG_VERBOSE, "Failed to check existence of domain: %ls, user: %ls (error code 0x%x) - continuing", wzDomain, psu->wzName, hr); | 538 | WcaLog(LOGMSG_VERBOSE, "Failed to check existence of domain: %ls, user: %ls (error code 0x%x) - continuing", pwzDomainName, psu->wzName, hr); |
564 | hr = S_OK; | 539 | hr = S_OK; |
565 | er = ERROR_SUCCESS; | 540 | er = ERROR_SUCCESS; |
566 | } | 541 | } |
@@ -685,11 +660,6 @@ HRESULT ScaUserExecute( | |||
685 | ::NetApiBufferFree(static_cast<LPVOID>(pUserInfo)); | 660 | ::NetApiBufferFree(static_cast<LPVOID>(pUserInfo)); |
686 | pUserInfo = NULL; | 661 | pUserInfo = NULL; |
687 | } | 662 | } |
688 | if (pDomainControllerInfo) | ||
689 | { | ||
690 | ::NetApiBufferFree(static_cast<LPVOID>(pDomainControllerInfo)); | ||
691 | pDomainControllerInfo = NULL; | ||
692 | } | ||
693 | } | 663 | } |
694 | 664 | ||
695 | LExit: | 665 | LExit: |
@@ -697,14 +667,12 @@ LExit: | |||
697 | ReleaseStr(pwzScriptKey); | 667 | ReleaseStr(pwzScriptKey); |
698 | ReleaseStr(pwzActionData); | 668 | ReleaseStr(pwzActionData); |
699 | ReleaseStr(pwzRollbackData); | 669 | ReleaseStr(pwzRollbackData); |
670 | ReleaseStr(pwzDomainName); | ||
671 | |||
700 | if (pUserInfo) | 672 | if (pUserInfo) |
701 | { | 673 | { |
702 | ::NetApiBufferFree(static_cast<LPVOID>(pUserInfo)); | 674 | ::NetApiBufferFree(static_cast<LPVOID>(pUserInfo)); |
703 | } | 675 | } |
704 | if (pDomainControllerInfo) | ||
705 | { | ||
706 | ::NetApiBufferFree(static_cast<LPVOID>(pDomainControllerInfo)); | ||
707 | } | ||
708 | 676 | ||
709 | return hr; | 677 | return hr; |
710 | } | 678 | } |
diff --git a/src/ext/Util/ca/utilca.cpp b/src/ext/Util/ca/utilca.cpp index 37664a1c..d41f00c2 100644 --- a/src/ext/Util/ca/utilca.cpp +++ b/src/ext/Util/ca/utilca.cpp | |||
@@ -1,3 +1,59 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | #include "precomp.h" | 3 | #include "precomp.h" |
4 | |||
5 | HRESULT GetDomainFromServerName( | ||
6 | __deref_out_z LPWSTR* ppwzDomainName, | ||
7 | __in_z LPCWSTR wzServerName, | ||
8 | __in DWORD dwFlags | ||
9 | ) | ||
10 | { | ||
11 | HRESULT hr = S_OK; | ||
12 | DWORD er = ERROR_SUCCESS; | ||
13 | PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; | ||
14 | LPCWSTR wz = wzServerName ? wzServerName : L""; // initialize the domain to the provided server name (or empty string). | ||
15 | |||
16 | // If the server name was not empty, try to get the domain name out of it. | ||
17 | if (*wz) | ||
18 | { | ||
19 | er = ::DsGetDcNameW(NULL, wz, NULL, NULL, dwFlags, &pDomainControllerInfo); | ||
20 | if (RPC_S_SERVER_UNAVAILABLE == er) | ||
21 | { | ||
22 | // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag. | ||
23 | er = ::DsGetDcNameW(NULL, wz, NULL, NULL, dwFlags | DS_FORCE_REDISCOVERY, &pDomainControllerInfo); | ||
24 | } | ||
25 | ExitOnWin32Error(er, hr, "Could not get domain name from server name: %ls", wz); | ||
26 | |||
27 | if (pDomainControllerInfo->DomainControllerName) | ||
28 | { | ||
29 | // Skip the \\ prefix if present. | ||
30 | if ('\\' == *pDomainControllerInfo->DomainControllerName && '\\' == *(pDomainControllerInfo->DomainControllerName + 1)) | ||
31 | { | ||
32 | wz = pDomainControllerInfo->DomainControllerName + 2; | ||
33 | } | ||
34 | else | ||
35 | { | ||
36 | wz = pDomainControllerInfo->DomainControllerName; | ||
37 | } | ||
38 | } | ||
39 | } | ||
40 | |||
41 | LExit: | ||
42 | // Note: we overwrite the error code here as failure to contact domain controller above is not a fatal error. | ||
43 | if (wz && *wz) | ||
44 | { | ||
45 | hr = StrAllocString(ppwzDomainName, wz, 0); | ||
46 | } | ||
47 | else // return NULL the server name ended up empty. | ||
48 | { | ||
49 | ReleaseNullStr(*ppwzDomainName); | ||
50 | hr = S_OK; | ||
51 | } | ||
52 | |||
53 | if (pDomainControllerInfo) | ||
54 | { | ||
55 | ::NetApiBufferFree((LPVOID)pDomainControllerInfo); | ||
56 | } | ||
57 | |||
58 | return hr; | ||
59 | } | ||
diff --git a/src/ext/Util/ca/utilca.h b/src/ext/Util/ca/utilca.h new file mode 100644 index 00000000..97c54561 --- /dev/null +++ b/src/ext/Util/ca/utilca.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #pragma once | ||
2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
3 | |||
4 | HRESULT GetDomainFromServerName( | ||
5 | __deref_out_z LPWSTR* ppwzDomainName, | ||
6 | __in_z LPCWSTR wzServerName, | ||
7 | __in DWORD dwFlags | ||
8 | ); | ||