diff options
Diffstat (limited to 'src/ext/Util/ca/scaexec.cpp')
-rw-r--r-- | src/ext/Util/ca/scaexec.cpp | 375 |
1 files changed, 265 insertions, 110 deletions
diff --git a/src/ext/Util/ca/scaexec.cpp b/src/ext/Util/ca/scaexec.cpp index 5845c1b4..7bd271d1 100644 --- a/src/ext/Util/ca/scaexec.cpp +++ b/src/ext/Util/ca/scaexec.cpp | |||
@@ -2,7 +2,6 @@ | |||
2 | 2 | ||
3 | #include "precomp.h" | 3 | #include "precomp.h" |
4 | 4 | ||
5 | |||
6 | /******************************************************************** | 5 | /******************************************************************** |
7 | * CreateSmb - CUSTOM ACTION ENTRY POINT for creating fileshares | 6 | * CreateSmb - CUSTOM ACTION ENTRY POINT for creating fileshares |
8 | * | 7 | * |
@@ -520,55 +519,88 @@ static HRESULT ModifyUserLocalBatchRight( | |||
520 | return hr; | 519 | return hr; |
521 | } | 520 | } |
522 | 521 | ||
523 | static void SetUserPasswordAndAttributes( | 522 | static HRESULT ApplyAttributes(int iAttributes, DWORD* pFlags) |
524 | __in USER_INFO_1* puserInfo, | ||
525 | __in LPWSTR wzPassword, | ||
526 | __in int iAttributes | ||
527 | ) | ||
528 | { | 523 | { |
529 | Assert(puserInfo); | 524 | HRESULT hr = S_OK; |
530 | |||
531 | // Set the User's password | ||
532 | puserInfo->usri1_password = wzPassword; | ||
533 | 525 | ||
534 | // Apply the Attributes | ||
535 | if (SCAU_DONT_EXPIRE_PASSWRD & iAttributes) | 526 | if (SCAU_DONT_EXPIRE_PASSWRD & iAttributes) |
536 | { | 527 | { |
537 | puserInfo->usri1_flags |= UF_DONT_EXPIRE_PASSWD; | 528 | *pFlags |= UF_DONT_EXPIRE_PASSWD; |
538 | } | 529 | } |
539 | else | 530 | else |
540 | { | 531 | { |
541 | puserInfo->usri1_flags &= ~UF_DONT_EXPIRE_PASSWD; | 532 | *pFlags &= ~UF_DONT_EXPIRE_PASSWD; |
542 | } | 533 | } |
543 | 534 | ||
544 | if (SCAU_PASSWD_CANT_CHANGE & iAttributes) | 535 | if (SCAU_PASSWD_CANT_CHANGE & iAttributes) |
545 | { | 536 | { |
546 | puserInfo->usri1_flags |= UF_PASSWD_CANT_CHANGE; | 537 | *pFlags |= UF_PASSWD_CANT_CHANGE; |
547 | } | 538 | } |
548 | else | 539 | else |
549 | { | 540 | { |
550 | puserInfo->usri1_flags &= ~UF_PASSWD_CANT_CHANGE; | 541 | *pFlags &= ~UF_PASSWD_CANT_CHANGE; |
551 | } | 542 | } |
552 | 543 | ||
553 | if (SCAU_DISABLE_ACCOUNT & iAttributes) | 544 | if (SCAU_DISABLE_ACCOUNT & iAttributes) |
554 | { | 545 | { |
555 | puserInfo->usri1_flags |= UF_ACCOUNTDISABLE; | 546 | *pFlags |= UF_ACCOUNTDISABLE; |
556 | } | 547 | } |
557 | else | 548 | else |
558 | { | 549 | { |
559 | puserInfo->usri1_flags &= ~UF_ACCOUNTDISABLE; | 550 | *pFlags &= ~UF_ACCOUNTDISABLE; |
560 | } | 551 | } |
561 | 552 | ||
562 | if (SCAU_PASSWD_CHANGE_REQD_ON_LOGIN & iAttributes) // TODO: for some reason this doesn't work | 553 | if (SCAU_PASSWD_CHANGE_REQD_ON_LOGIN & iAttributes) // TODO: for some reason this doesn't work |
563 | { | 554 | { |
564 | puserInfo->usri1_flags |= UF_PASSWORD_EXPIRED; | 555 | *pFlags |= UF_PASSWORD_EXPIRED; |
565 | } | 556 | } |
566 | else | 557 | else |
567 | { | 558 | { |
568 | puserInfo->usri1_flags &= ~UF_PASSWORD_EXPIRED; | 559 | *pFlags &= ~UF_PASSWORD_EXPIRED; |
560 | } | ||
561 | |||
562 | return hr; | ||
563 | } | ||
564 | |||
565 | static HRESULT ApplyComment(int iAttributes, LPWSTR pwzComment, LPWSTR* ppComment) | ||
566 | { | ||
567 | HRESULT hr = S_OK; | ||
568 | |||
569 | if (SCAU_REMOVE_COMMENT & iAttributes) | ||
570 | { | ||
571 | *ppComment = L""; | ||
572 | } | ||
573 | else if (pwzComment && *pwzComment) | ||
574 | { | ||
575 | *ppComment = pwzComment; | ||
569 | } | 576 | } |
577 | |||
578 | return hr; | ||
579 | } | ||
580 | |||
581 | static NET_API_STATUS SetUserPassword(__in LPWSTR pwzServerName, __in LPWSTR pwzName, __in LPWSTR pwzPassword) | ||
582 | { | ||
583 | _USER_INFO_1003 userInfo1003; | ||
584 | |||
585 | userInfo1003.usri1003_password = pwzPassword; | ||
586 | return ::NetUserSetInfo(pwzServerName, pwzName, 1003, reinterpret_cast<LPBYTE>(&userInfo1003), NULL); | ||
570 | } | 587 | } |
571 | 588 | ||
589 | static NET_API_STATUS SetUserComment(__in LPWSTR pwzServerName, __in LPWSTR pwzName, __in LPWSTR pwzComment) | ||
590 | { | ||
591 | _USER_INFO_1007 userInfo1007; | ||
592 | |||
593 | userInfo1007.usri1007_comment = pwzComment; | ||
594 | return ::NetUserSetInfo(pwzServerName, pwzName, 1007, reinterpret_cast<LPBYTE>(&userInfo1007), NULL); | ||
595 | } | ||
596 | |||
597 | static NET_API_STATUS SetUserFlags(__in LPWSTR pwzServerName, __in LPWSTR pwzName, __in DWORD flags) | ||
598 | { | ||
599 | _USER_INFO_1008 userInfo1008; | ||
600 | |||
601 | userInfo1008.usri1008_flags = flags; | ||
602 | return ::NetUserSetInfo(pwzServerName, pwzName, 1008, reinterpret_cast<LPBYTE>(&userInfo1008), NULL); | ||
603 | } | ||
572 | 604 | ||
573 | static HRESULT RemoveUserInternal( | 605 | static HRESULT RemoveUserInternal( |
574 | LPWSTR wzGroupCaData, | 606 | LPWSTR wzGroupCaData, |
@@ -624,7 +656,12 @@ static HRESULT RemoveUserInternal( | |||
624 | } | 656 | } |
625 | if (ERROR_SUCCESS == er) | 657 | if (ERROR_SUCCESS == er) |
626 | { | 658 | { |
627 | wz = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix | 659 | if (2 <= wcslen(pDomainControllerInfo->DomainControllerName)) |
660 | { | ||
661 | wz = pDomainControllerInfo->DomainControllerName + 2; // Add 2 so that we don't get the \\ prefix. | ||
662 | // Pass the entire string if it is too short | ||
663 | // to have a \\ prefix. | ||
664 | } | ||
628 | } | 665 | } |
629 | else | 666 | else |
630 | { | 667 | { |
@@ -680,6 +717,41 @@ LExit: | |||
680 | return hr; | 717 | return hr; |
681 | } | 718 | } |
682 | 719 | ||
720 | static HRESULT GetServerName(LPWSTR pwzDomain, LPWSTR* ppwzServerName) | ||
721 | { | ||
722 | HRESULT hr = S_OK; | ||
723 | |||
724 | PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; | ||
725 | UINT er; | ||
726 | |||
727 | if (pwzDomain && *pwzDomain) | ||
728 | { | ||
729 | er = ::DsGetDcNameW(NULL, (LPCWSTR)pwzDomain, NULL, NULL, NULL, &pDomainControllerInfo); | ||
730 | if (RPC_S_SERVER_UNAVAILABLE == er) | ||
731 | { | ||
732 | // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag | ||
733 | er = ::DsGetDcNameW(NULL, (LPCWSTR)pwzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo); | ||
734 | } | ||
735 | if (ERROR_SUCCESS == er | ||
736 | && 2 <= wcslen(pDomainControllerInfo->DomainControllerName) | ||
737 | && '\\' == *pDomainControllerInfo->DomainControllerName | ||
738 | && '\\' == *pDomainControllerInfo->DomainControllerName + 1) | ||
739 | { | ||
740 | *ppwzServerName = pDomainControllerInfo->DomainControllerName + 2; // Skip the \\ prefix | ||
741 | } | ||
742 | else | ||
743 | { | ||
744 | *ppwzServerName = pwzDomain; | ||
745 | } | ||
746 | } | ||
747 | |||
748 | if (pDomainControllerInfo) | ||
749 | { | ||
750 | ::NetApiBufferFree((LPVOID)pDomainControllerInfo); | ||
751 | } | ||
752 | |||
753 | return hr; | ||
754 | } | ||
683 | 755 | ||
684 | /******************************************************************** | 756 | /******************************************************************** |
685 | CreateUser - CUSTOM ACTION ENTRY POINT for creating users | 757 | CreateUser - CUSTOM ACTION ENTRY POINT for creating users |
@@ -688,7 +760,7 @@ LExit: | |||
688 | * *****************************************************************/ | 760 | * *****************************************************************/ |
689 | extern "C" UINT __stdcall CreateUser( | 761 | extern "C" UINT __stdcall CreateUser( |
690 | __in MSIHANDLE hInstall | 762 | __in MSIHANDLE hInstall |
691 | ) | 763 | ) |
692 | { | 764 | { |
693 | //AssertSz(0, "Debug CreateUser"); | 765 | //AssertSz(0, "Debug CreateUser"); |
694 | 766 | ||
@@ -699,11 +771,11 @@ extern "C" UINT __stdcall CreateUser( | |||
699 | LPWSTR pwz = NULL; | 771 | LPWSTR pwz = NULL; |
700 | LPWSTR pwzName = NULL; | 772 | LPWSTR pwzName = NULL; |
701 | LPWSTR pwzDomain = NULL; | 773 | LPWSTR pwzDomain = NULL; |
774 | LPWSTR pwzComment = NULL; | ||
702 | LPWSTR pwzScriptKey = NULL; | 775 | LPWSTR pwzScriptKey = NULL; |
703 | LPWSTR pwzPassword = NULL; | 776 | LPWSTR pwzPassword = NULL; |
704 | LPWSTR pwzGroup = NULL; | 777 | LPWSTR pwzGroup = NULL; |
705 | LPWSTR pwzGroupDomain = NULL; | 778 | LPWSTR pwzGroupDomain = NULL; |
706 | PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; | ||
707 | int iAttributes = 0; | 779 | int iAttributes = 0; |
708 | BOOL fInitializedCom = FALSE; | 780 | BOOL fInitializedCom = FALSE; |
709 | 781 | ||
@@ -711,10 +783,10 @@ extern "C" UINT __stdcall CreateUser( | |||
711 | int iOriginalAttributes = 0; | 783 | int iOriginalAttributes = 0; |
712 | int iRollbackAttributes = 0; | 784 | int iRollbackAttributes = 0; |
713 | 785 | ||
714 | USER_INFO_1 userInfo; | 786 | USER_INFO_1 userInfo1; |
715 | USER_INFO_1* puserInfo = NULL; | 787 | USER_INFO_1* pUserInfo1 = NULL; |
716 | DWORD dw; | 788 | DWORD dw; |
717 | LPCWSTR wz = NULL; | 789 | LPWSTR pwzServerName = NULL; |
718 | 790 | ||
719 | hr = WcaInitialize(hInstall, "CreateUser"); | 791 | hr = WcaInitialize(hInstall, "CreateUser"); |
720 | ExitOnFailure(hr, "failed to initialize"); | 792 | ExitOnFailure(hr, "failed to initialize"); |
@@ -723,7 +795,7 @@ extern "C" UINT __stdcall CreateUser( | |||
723 | ExitOnFailure(hr, "failed to initialize COM"); | 795 | ExitOnFailure(hr, "failed to initialize COM"); |
724 | fInitializedCom = TRUE; | 796 | fInitializedCom = TRUE; |
725 | 797 | ||
726 | hr = WcaGetProperty( L"CustomActionData", &pwzData); | 798 | hr = WcaGetProperty(L"CustomActionData", &pwzData); |
727 | ExitOnFailure(hr, "failed to get CustomActionData"); | 799 | ExitOnFailure(hr, "failed to get CustomActionData"); |
728 | 800 | ||
729 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | 801 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); |
@@ -738,6 +810,9 @@ extern "C" UINT __stdcall CreateUser( | |||
738 | hr = WcaReadStringFromCaData(&pwz, &pwzDomain); | 810 | hr = WcaReadStringFromCaData(&pwz, &pwzDomain); |
739 | ExitOnFailure(hr, "failed to read domain from custom action data"); | 811 | ExitOnFailure(hr, "failed to read domain from custom action data"); |
740 | 812 | ||
813 | hr = WcaReadStringFromCaData(&pwz, &pwzComment); | ||
814 | ExitOnFailure(hr, "failed to read user comment from custom action data"); | ||
815 | |||
741 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); | 816 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); |
742 | ExitOnFailure(hr, "failed to read attributes from custom action data"); | 817 | ExitOnFailure(hr, "failed to read attributes from custom action data"); |
743 | 818 | ||
@@ -747,96 +822,155 @@ extern "C" UINT __stdcall CreateUser( | |||
747 | hr = WcaReadStringFromCaData(&pwz, &pwzPassword); | 822 | hr = WcaReadStringFromCaData(&pwz, &pwzPassword); |
748 | ExitOnFailure(hr, "failed to read password from custom action data"); | 823 | ExitOnFailure(hr, "failed to read password from custom action data"); |
749 | 824 | ||
750 | // There is no rollback scheduled if the key is empty. | ||
751 | // Best effort to get original configuration and save it in the script so rollback can restore it. | ||
752 | if (*pwzScriptKey) | ||
753 | { | ||
754 | hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, FALSE, &hRollbackScript); | ||
755 | ExitOnFailure(hr, "Failed to open rollback CustomAction script."); | ||
756 | |||
757 | iRollbackAttributes = 0; | ||
758 | hr = GetExistingUserRightsAssignments(pwzDomain, pwzName, &iOriginalAttributes); | ||
759 | if (FAILED(hr)) | ||
760 | { | ||
761 | WcaLogError(hr, "failed to get existing user rights: %ls, continuing anyway.", pwzName); | ||
762 | } | ||
763 | else | ||
764 | { | ||
765 | if (!(SCAU_ALLOW_LOGON_AS_SERVICE & iOriginalAttributes) && (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes)) | ||
766 | { | ||
767 | iRollbackAttributes |= SCAU_ALLOW_LOGON_AS_SERVICE; | ||
768 | } | ||
769 | if (!(SCAU_ALLOW_LOGON_AS_BATCH & iOriginalAttributes) && (SCAU_ALLOW_LOGON_AS_BATCH & iAttributes)) | ||
770 | { | ||
771 | iRollbackAttributes |= SCAU_ALLOW_LOGON_AS_BATCH; | ||
772 | } | ||
773 | } | ||
774 | |||
775 | hr = WcaCaScriptWriteNumber(hRollbackScript, iRollbackAttributes); | ||
776 | ExitOnFailure(hr, "Failed to add data to rollback script."); | ||
777 | |||
778 | // Nudge the system to get all our rollback data written to disk. | ||
779 | WcaCaScriptFlush(hRollbackScript); | ||
780 | } | ||
781 | |||
782 | if (!(SCAU_DONT_CREATE_USER & iAttributes)) | 825 | if (!(SCAU_DONT_CREATE_USER & iAttributes)) |
783 | { | 826 | { |
784 | ::ZeroMemory(&userInfo, sizeof(USER_INFO_1)); | 827 | pUserInfo1 = &userInfo1; |
785 | userInfo.usri1_name = pwzName; | 828 | ::ZeroMemory(pUserInfo1, sizeof(USER_INFO_1)); |
786 | userInfo.usri1_priv = USER_PRIV_USER; | 829 | pUserInfo1->usri1_name = pwzName; |
787 | userInfo.usri1_flags = UF_SCRIPT; | 830 | pUserInfo1->usri1_priv = USER_PRIV_USER; |
788 | userInfo.usri1_home_dir = NULL; | 831 | pUserInfo1->usri1_flags = UF_SCRIPT; |
789 | userInfo.usri1_comment = NULL; | 832 | pUserInfo1->usri1_home_dir = NULL; |
790 | userInfo.usri1_script_path = NULL; | 833 | pUserInfo1->usri1_comment = NULL; |
791 | 834 | pUserInfo1->usri1_script_path = NULL; | |
792 | SetUserPasswordAndAttributes(&userInfo, pwzPassword, iAttributes); | 835 | |
836 | // Set the user's password | ||
837 | pUserInfo1->usri1_password = pwzPassword; | ||
838 | |||
839 | // Set the user's comment | ||
840 | hr = ApplyComment(iAttributes, pwzComment, &pUserInfo1->usri1_comment); | ||
841 | ExitOnFailure(hr, "failed to apply comment"); | ||
842 | |||
843 | // Set the user's flags | ||
844 | hr = ApplyAttributes(iAttributes, &pUserInfo1->usri1_flags); | ||
845 | ExitOnFailure(hr, "failed to apply attributes"); | ||
793 | 846 | ||
794 | // | 847 | // |
795 | // Create the User | 848 | // Create the User |
796 | // | 849 | // |
797 | if (pwzDomain && *pwzDomain) | 850 | hr = GetServerName(pwzDomain, &pwzServerName); |
851 | ExitOnFailure(hr, "failed to get server name"); | ||
852 | |||
853 | er = ::NetUserAdd(pwzServerName, 1, reinterpret_cast<LPBYTE>(pUserInfo1), &dw); | ||
854 | if (NERR_UserExists == er) | ||
798 | { | 855 | { |
799 | er = ::DsGetDcNameW( NULL, (LPCWSTR)pwzDomain, NULL, NULL, NULL, &pDomainControllerInfo ); | 856 | er = ERROR_SUCCESS; // Make sure that we don't report this situation as an error |
800 | if (RPC_S_SERVER_UNAVAILABLE == er) | 857 | // if we fall through the tests that follow. |
801 | { | 858 | if (SCAU_FAIL_IF_EXISTS & iAttributes) |
802 | // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag | ||
803 | er = ::DsGetDcNameW( NULL, (LPCWSTR)pwzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo ); | ||
804 | } | ||
805 | if (ERROR_SUCCESS == er) | ||
806 | { | 859 | { |
807 | wz = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix | 860 | hr = HRESULT_FROM_WIN32(er); |
861 | ExitOnFailure(hr, "User was not supposed to exist, but does."); | ||
808 | } | 862 | } |
809 | else | ||
810 | { | ||
811 | wz = pwzDomain; | ||
812 | } | ||
813 | } | ||
814 | 863 | ||
815 | er = ::NetUserAdd(wz, 1, reinterpret_cast<LPBYTE>(&userInfo), &dw); | ||
816 | if (NERR_UserExists == er) | ||
817 | { | ||
818 | if (SCAU_UPDATE_IF_EXISTS & iAttributes) | 864 | if (SCAU_UPDATE_IF_EXISTS & iAttributes) |
819 | { | 865 | { |
820 | er = ::NetUserGetInfo(wz, pwzName, 1, reinterpret_cast<LPBYTE*>(&puserInfo)); | 866 | pUserInfo1 = NULL; |
821 | if (NERR_Success == er) | 867 | er = ::NetUserGetInfo(pwzServerName, pwzName, 1, reinterpret_cast<LPBYTE*>(&pUserInfo1)); |
868 | if (ERROR_SUCCESS == er) | ||
822 | { | 869 | { |
823 | // Change the existing user's password and attributes again then try | 870 | // There is no rollback scheduled if the key is empty. |
824 | // to update user with this new data | 871 | // Best effort to get original configuration and save it in the script so rollback can restore it. |
825 | SetUserPasswordAndAttributes(puserInfo, pwzPassword, iAttributes); | 872 | |
873 | if (*pwzScriptKey) | ||
874 | { | ||
875 | // Try to open the rollback script | ||
876 | hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript); | ||
877 | |||
878 | if (INVALID_HANDLE_VALUE != hRollbackScript) | ||
879 | { | ||
880 | WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE); | ||
881 | } | ||
882 | else | ||
883 | { | ||
884 | hRollbackScript = NULL; | ||
885 | hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, FALSE, &hRollbackScript); | ||
886 | ExitOnFailure(hr, "Failed to open rollback CustomAction script."); | ||
887 | |||
888 | iRollbackAttributes = 0; | ||
889 | hr = GetExistingUserRightsAssignments(pwzDomain, pwzName, &iOriginalAttributes); | ||
890 | if (FAILED(hr)) | ||
891 | { | ||
892 | WcaLogError(hr, "failed to get existing user rights: %ls, continuing anyway.", pwzName); | ||
893 | } | ||
894 | else | ||
895 | { | ||
896 | if (!(SCAU_ALLOW_LOGON_AS_SERVICE & iOriginalAttributes) && (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes)) | ||
897 | { | ||
898 | iRollbackAttributes |= SCAU_ALLOW_LOGON_AS_SERVICE; | ||
899 | } | ||
900 | |||
901 | if (!(SCAU_ALLOW_LOGON_AS_BATCH & iOriginalAttributes) && (SCAU_ALLOW_LOGON_AS_BATCH & iAttributes)) | ||
902 | { | ||
903 | iRollbackAttributes |= SCAU_ALLOW_LOGON_AS_BATCH; | ||
904 | } | ||
905 | } | ||
906 | |||
907 | hr = WcaCaScriptWriteString(hRollbackScript, pUserInfo1->usri1_comment); | ||
908 | ExitOnFailure(hr, "Failed to add rollback comment to rollback script."); | ||
909 | |||
910 | if (!pUserInfo1->usri1_comment || !*pUserInfo1->usri1_comment) | ||
911 | { | ||
912 | iRollbackAttributes |= SCAU_REMOVE_COMMENT; | ||
913 | } | ||
914 | |||
915 | hr = WcaCaScriptWriteNumber(hRollbackScript, iRollbackAttributes); | ||
916 | ExitOnFailure(hr, "Failed to add rollback attributes to rollback script."); | ||
917 | |||
918 | // Nudge the system to get all our rollback data written to disk. | ||
919 | WcaCaScriptFlush(hRollbackScript); | ||
920 | } | ||
921 | } | ||
922 | } | ||
826 | 923 | ||
827 | er = ::NetUserSetInfo(wz, pwzName, 1, reinterpret_cast<LPBYTE>(puserInfo), &dw); | 924 | if (ERROR_SUCCESS == er) |
925 | { | ||
926 | hr = HRESULT_FROM_WIN32(::SetUserPassword(pwzServerName, pwzName, pwzPassword)); | ||
927 | if (FAILED(hr)) | ||
928 | { | ||
929 | WcaLogError(hr, "failed to set user password for user %ls\\%ls, continuing anyway.", pwzServerName, pwzName); | ||
930 | } | ||
931 | |||
932 | if (SCAU_REMOVE_COMMENT & iAttributes) | ||
933 | { | ||
934 | hr = HRESULT_FROM_WIN32(SetUserComment(pwzServerName, pwzName, L"")); | ||
935 | if (FAILED(hr)) | ||
936 | { | ||
937 | WcaLogError(hr, "failed to clear user comment for user %ls\\%ls, continuing anyway.", pwzServerName, pwzName); | ||
938 | } | ||
939 | } | ||
940 | else if (pwzComment && *pwzComment) | ||
941 | { | ||
942 | hr = HRESULT_FROM_WIN32(SetUserComment(pwzServerName, pwzName, pwzComment)); | ||
943 | if (FAILED(hr)) | ||
944 | { | ||
945 | WcaLogError(hr, "failed to set user comment to %ls for user %ls\\%ls, continuing anyway.", pwzComment, pwzServerName, pwzName); | ||
946 | } | ||
947 | } | ||
948 | |||
949 | DWORD flags = pUserInfo1->usri1_flags; | ||
950 | |||
951 | hr = ApplyAttributes(iAttributes, &flags); | ||
952 | if (FAILED(hr)) | ||
953 | { | ||
954 | WcaLogError(hr, "failed to apply attributes for user %ls\\%ls, continuing anyway.", pwzServerName, pwzName); | ||
955 | } | ||
956 | |||
957 | hr = HRESULT_FROM_WIN32(SetUserFlags(pwzServerName, pwzName, flags)); | ||
958 | if (FAILED(hr)) | ||
959 | { | ||
960 | WcaLogError(hr, "failed to set user flags for user %ls\\%ls, continuing anyway.", pwzServerName, pwzName); | ||
961 | } | ||
828 | } | 962 | } |
829 | } | 963 | } |
830 | else if (!(SCAU_FAIL_IF_EXISTS & iAttributes)) | ||
831 | { | ||
832 | er = NERR_Success; | ||
833 | } | ||
834 | } | 964 | } |
835 | else if (NERR_PasswordTooShort == er || NERR_PasswordTooLong == er) | 965 | else if (NERR_PasswordTooShort == er || NERR_PasswordTooLong == er) |
836 | { | 966 | { |
837 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrUSRFailedUserCreatePswd, "failed to create user: %ls due to invalid password.", pwzName); | 967 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrUSRFailedUserCreatePswd, "failed to create user: %ls due to invalid password.", pwzName); |
838 | } | 968 | } |
839 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrUSRFailedUserCreate, "failed to create user: %ls", pwzName); | 969 | |
970 | if (ERROR_SUCCESS != er) | ||
971 | { | ||
972 | MessageExitOnFailure(hr = HRESULT_FROM_WIN32(er), msierrUSRFailedUserCreate, "failed to create user: %ls", pwzName); | ||
973 | } | ||
840 | } | 974 | } |
841 | 975 | ||
842 | if (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes) | 976 | if (SCAU_ALLOW_LOGON_AS_SERVICE & iAttributes) |
@@ -851,14 +985,15 @@ extern "C" UINT __stdcall CreateUser( | |||
851 | MessageExitOnFailure(hr, msierrUSRFailedGrantLogonAsService, "Failed to grant logon as batch job rights to user: %ls", pwzName); | 985 | MessageExitOnFailure(hr, msierrUSRFailedGrantLogonAsService, "Failed to grant logon as batch job rights to user: %ls", pwzName); |
852 | } | 986 | } |
853 | 987 | ||
854 | // | 988 | // |
855 | // Add the users to groups | 989 | // Add the users to groups |
856 | // | 990 | // |
857 | while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup))) | 991 | while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup))) |
858 | { | 992 | { |
859 | hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain); | 993 | hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain); |
860 | ExitOnFailure(hr, "failed to get domain for group: %ls", pwzGroup); | 994 | ExitOnFailure(hr, "failed to get domain for group: %ls", pwzGroup); |
861 | 995 | ||
996 | WcaLog(LOGMSG_STANDARD, "Adding user %ls\\%ls to group %ls\\%ls", pwzDomain, pwzName, pwzGroupDomain, pwzGroup); | ||
862 | hr = AddUserToGroup(pwzName, pwzDomain, pwzGroup, pwzGroupDomain); | 997 | hr = AddUserToGroup(pwzName, pwzDomain, pwzGroup, pwzGroupDomain); |
863 | MessageExitOnFailure(hr, msierrUSRFailedUserGroupAdd, "failed to add user: %ls to group %ls", pwzName, pwzGroup); | 998 | MessageExitOnFailure(hr, msierrUSRFailedUserGroupAdd, "failed to add user: %ls to group %ls", pwzName, pwzGroup); |
864 | } | 999 | } |
@@ -866,24 +1001,23 @@ extern "C" UINT __stdcall CreateUser( | |||
866 | { | 1001 | { |
867 | hr = S_OK; | 1002 | hr = S_OK; |
868 | } | 1003 | } |
1004 | |||
869 | ExitOnFailure(hr, "failed to get next group in which to include user:%ls", pwzName); | 1005 | ExitOnFailure(hr, "failed to get next group in which to include user:%ls", pwzName); |
870 | 1006 | ||
1007 | ExitOnFailure(hr, "failed to get next group in which to include user:%ls", pwzName); | ||
1008 | |||
871 | LExit: | 1009 | LExit: |
872 | WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE); | 1010 | WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE); |
873 | 1011 | ||
874 | if (puserInfo) | 1012 | if (pUserInfo1 && pUserInfo1 != &userInfo1) |
875 | { | 1013 | { |
876 | ::NetApiBufferFree((LPVOID)puserInfo); | 1014 | ::NetApiBufferFree((LPVOID)pUserInfo1); |
877 | } | ||
878 | |||
879 | if (pDomainControllerInfo) | ||
880 | { | ||
881 | ::NetApiBufferFree((LPVOID)pDomainControllerInfo); | ||
882 | } | 1015 | } |
883 | 1016 | ||
884 | ReleaseStr(pwzData); | 1017 | ReleaseStr(pwzData); |
885 | ReleaseStr(pwzName); | 1018 | ReleaseStr(pwzName); |
886 | ReleaseStr(pwzDomain); | 1019 | ReleaseStr(pwzDomain); |
1020 | ReleaseStr(pwzComment); | ||
887 | ReleaseStr(pwzScriptKey); | 1021 | ReleaseStr(pwzScriptKey); |
888 | ReleaseStr(pwzPassword); | 1022 | ReleaseStr(pwzPassword); |
889 | ReleaseStr(pwzGroup); | 1023 | ReleaseStr(pwzGroup); |
@@ -922,15 +1056,17 @@ extern "C" UINT __stdcall CreateUserRollback( | |||
922 | 1056 | ||
923 | LPWSTR pwzData = NULL; | 1057 | LPWSTR pwzData = NULL; |
924 | LPWSTR pwz = NULL; | 1058 | LPWSTR pwz = NULL; |
1059 | LPWSTR pwzScriptKey = NULL; | ||
925 | LPWSTR pwzName = NULL; | 1060 | LPWSTR pwzName = NULL; |
926 | LPWSTR pwzDomain = NULL; | 1061 | LPWSTR pwzDomain = NULL; |
927 | LPWSTR pwzScriptKey = NULL; | 1062 | LPWSTR pwzComment = NULL; |
928 | int iAttributes = 0; | 1063 | int iAttributes = 0; |
929 | BOOL fInitializedCom = FALSE; | 1064 | BOOL fInitializedCom = FALSE; |
930 | 1065 | ||
931 | WCA_CASCRIPT_HANDLE hRollbackScript = NULL; | 1066 | WCA_CASCRIPT_HANDLE hRollbackScript = NULL; |
932 | LPWSTR pwzRollbackData = NULL; | 1067 | LPWSTR pwzRollbackData = NULL; |
933 | int iOriginalAttributes = 0; | 1068 | int iOriginalAttributes = 0; |
1069 | LPWSTR pwzOriginalComment = NULL; | ||
934 | 1070 | ||
935 | hr = WcaInitialize(hInstall, "CreateUserRollback"); | 1071 | hr = WcaInitialize(hInstall, "CreateUserRollback"); |
936 | ExitOnFailure(hr, "failed to initialize"); | 1072 | ExitOnFailure(hr, "failed to initialize"); |
@@ -957,6 +1093,9 @@ extern "C" UINT __stdcall CreateUserRollback( | |||
957 | hr = WcaReadStringFromCaData(&pwz, &pwzDomain); | 1093 | hr = WcaReadStringFromCaData(&pwz, &pwzDomain); |
958 | ExitOnFailure(hr, "failed to read domain from custom action data"); | 1094 | ExitOnFailure(hr, "failed to read domain from custom action data"); |
959 | 1095 | ||
1096 | hr = WcaReadStringFromCaData(&pwz, &pwzComment); | ||
1097 | ExitOnFailure(hr, "failed to read comment from custom action data"); | ||
1098 | |||
960 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); | 1099 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); |
961 | ExitOnFailure(hr, "failed to read attributes from custom action data"); | 1100 | ExitOnFailure(hr, "failed to read attributes from custom action data"); |
962 | 1101 | ||
@@ -978,6 +1117,15 @@ extern "C" UINT __stdcall CreateUserRollback( | |||
978 | WcaLog(LOGMSG_TRACEONLY, "Rollback Data: %ls", pwzRollbackData); | 1117 | WcaLog(LOGMSG_TRACEONLY, "Rollback Data: %ls", pwzRollbackData); |
979 | 1118 | ||
980 | pwz = pwzRollbackData; | 1119 | pwz = pwzRollbackData; |
1120 | hr = WcaReadStringFromCaData(&pwz, &pwzOriginalComment); | ||
1121 | if (FAILED(hr)) | ||
1122 | { | ||
1123 | WcaLogError(hr, "failed to read comment from rollback data, continuing anyway"); | ||
1124 | } | ||
1125 | else | ||
1126 | { | ||
1127 | pwzComment = pwzOriginalComment; | ||
1128 | } | ||
981 | hr = WcaReadIntegerFromCaData(&pwz, &iOriginalAttributes); | 1129 | hr = WcaReadIntegerFromCaData(&pwz, &iOriginalAttributes); |
982 | if (FAILED(hr)) | 1130 | if (FAILED(hr)) |
983 | { | 1131 | { |
@@ -998,8 +1146,10 @@ LExit: | |||
998 | ReleaseStr(pwzData); | 1146 | ReleaseStr(pwzData); |
999 | ReleaseStr(pwzName); | 1147 | ReleaseStr(pwzName); |
1000 | ReleaseStr(pwzDomain); | 1148 | ReleaseStr(pwzDomain); |
1149 | ReleaseStr(pwzComment); | ||
1001 | ReleaseStr(pwzScriptKey); | 1150 | ReleaseStr(pwzScriptKey); |
1002 | ReleaseStr(pwzRollbackData); | 1151 | ReleaseStr(pwzRollbackData); |
1152 | ReleaseStr(pwzOriginalComment); | ||
1003 | 1153 | ||
1004 | if (fInitializedCom) | 1154 | if (fInitializedCom) |
1005 | { | 1155 | { |
@@ -1033,6 +1183,7 @@ extern "C" UINT __stdcall RemoveUser( | |||
1033 | LPWSTR pwz = NULL; | 1183 | LPWSTR pwz = NULL; |
1034 | LPWSTR pwzName = NULL; | 1184 | LPWSTR pwzName = NULL; |
1035 | LPWSTR pwzDomain = NULL; | 1185 | LPWSTR pwzDomain = NULL; |
1186 | LPWSTR pwzComment = NULL; | ||
1036 | int iAttributes = 0; | 1187 | int iAttributes = 0; |
1037 | BOOL fInitializedCom = FALSE; | 1188 | BOOL fInitializedCom = FALSE; |
1038 | 1189 | ||
@@ -1058,6 +1209,9 @@ extern "C" UINT __stdcall RemoveUser( | |||
1058 | hr = WcaReadStringFromCaData(&pwz, &pwzDomain); | 1209 | hr = WcaReadStringFromCaData(&pwz, &pwzDomain); |
1059 | ExitOnFailure(hr, "failed to read domain from custom action data"); | 1210 | ExitOnFailure(hr, "failed to read domain from custom action data"); |
1060 | 1211 | ||
1212 | hr = WcaReadStringFromCaData(&pwz, &pwzComment); | ||
1213 | ExitOnFailure(hr, "failed to read comment from custom action data"); | ||
1214 | |||
1061 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); | 1215 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); |
1062 | ExitOnFailure(hr, "failed to read attributes from custom action data"); | 1216 | ExitOnFailure(hr, "failed to read attributes from custom action data"); |
1063 | 1217 | ||
@@ -1067,6 +1221,7 @@ LExit: | |||
1067 | ReleaseStr(pwzData); | 1221 | ReleaseStr(pwzData); |
1068 | ReleaseStr(pwzName); | 1222 | ReleaseStr(pwzName); |
1069 | ReleaseStr(pwzDomain); | 1223 | ReleaseStr(pwzDomain); |
1224 | ReleaseStr(pwzComment); | ||
1070 | 1225 | ||
1071 | if (fInitializedCom) | 1226 | if (fInitializedCom) |
1072 | { | 1227 | { |