diff options
| author | Ron Martin <cpuwzd@comcast.net> | 2022-08-29 18:38:07 -0400 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2022-10-21 19:08:08 -0700 |
| commit | 08cdc6aa2b9dd0e273a3c3a22893616d26342a0e (patch) | |
| tree | 1d0b9f7e21cec02abfda50b1a3c6d0c24308998b /src/ext/Util/ca/scauser.cpp | |
| parent | 40bd65379768f99ec28bffe2691ba43c78c9e9c4 (diff) | |
| download | wix-08cdc6aa2b9dd0e273a3c3a22893616d26342a0e.tar.gz wix-08cdc6aa2b9dd0e273a3c3a22893616d26342a0e.tar.bz2 wix-08cdc6aa2b9dd0e273a3c3a22893616d26342a0e.zip | |
Support add, modify and remove comments on user accounts
Fixes 5371
Diffstat (limited to 'src/ext/Util/ca/scauser.cpp')
| -rw-r--r-- | src/ext/Util/ca/scauser.cpp | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/src/ext/Util/ca/scauser.cpp b/src/ext/Util/ca/scauser.cpp index f92ebf1b..dc5bebba 100644 --- a/src/ext/Util/ca/scauser.cpp +++ b/src/ext/Util/ca/scauser.cpp | |||
| @@ -2,8 +2,8 @@ | |||
| 2 | 2 | ||
| 3 | #include "precomp.h" | 3 | #include "precomp.h" |
| 4 | 4 | ||
| 5 | LPCWSTR vcsUserQuery = L"SELECT `User`, `Component_`, `Name`, `Domain`, `Password` FROM `Wix4User` WHERE `User`=?"; | 5 | LPCWSTR vcsUserQuery = L"SELECT `User`, `Component_`, `Name`, `Domain`, `Comment`, `Password` FROM `Wix4User` WHERE `User`=?"; |
| 6 | enum eUserQuery { vuqUser = 1, vuqComponent, vuqName, vuqDomain, vuqPassword }; | 6 | enum eUserQuery { vuqUser = 1, vuqComponent, vuqName, vuqDomain, vuqComment, vuqPassword }; |
| 7 | 7 | ||
| 8 | LPCWSTR vcsGroupQuery = L"SELECT `Group`, `Component_`, `Name`, `Domain` FROM `Wix4Group` WHERE `Group`=?"; | 8 | LPCWSTR vcsGroupQuery = L"SELECT `Group`, `Component_`, `Name`, `Domain` FROM `Wix4Group` WHERE `Group`=?"; |
| 9 | enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain }; | 9 | enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain }; |
| @@ -11,8 +11,8 @@ enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain }; | |||
| 11 | LPCWSTR vcsUserGroupQuery = L"SELECT `User_`, `Group_` FROM `Wix4UserGroup` WHERE `User_`=?"; | 11 | LPCWSTR vcsUserGroupQuery = L"SELECT `User_`, `Group_` FROM `Wix4UserGroup` WHERE `User_`=?"; |
| 12 | enum eUserGroupQuery { vugqUser = 1, vugqGroup }; | 12 | enum eUserGroupQuery { vugqUser = 1, vugqGroup }; |
| 13 | 13 | ||
| 14 | LPCWSTR vActionableQuery = L"SELECT `User`,`Component_`,`Name`,`Domain`,`Password`,`Attributes` FROM `Wix4User` WHERE `Component_` IS NOT NULL"; | 14 | LPCWSTR vActionableQuery = L"SELECT `User`,`Component_`,`Name`,`Domain`,`Password`,`Comment`,`Attributes` FROM `Wix4User` WHERE `Component_` IS NOT NULL"; |
| 15 | enum eActionableQuery { vaqUser = 1, vaqComponent, vaqName, vaqDomain, vaqPassword, vaqAttributes }; | 15 | enum eActionableQuery { vaqUser = 1, vaqComponent, vaqName, vaqDomain, vaqPassword, vaqComment, vaqAttributes }; |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | static HRESULT AddUserToList( | 18 | static HRESULT AddUserToList( |
| @@ -78,6 +78,11 @@ HRESULT __stdcall ScaGetUser( | |||
| 78 | hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData); | 78 | hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData); |
| 79 | ExitOnFailure(hr, "Failed to copy domain string to user object"); | 79 | ExitOnFailure(hr, "Failed to copy domain string to user object"); |
| 80 | 80 | ||
| 81 | hr = WcaGetRecordFormattedString(hRec, vuqComment, &pwzData); | ||
| 82 | ExitOnFailure(hr, "Failed to get Wix4User.Comment"); | ||
| 83 | hr = ::StringCchCopyW(pscau->wzComment, countof(pscau->wzComment), pwzData); | ||
| 84 | ExitOnFailure(hr, "Failed to copy comment string to user object"); | ||
| 85 | |||
| 81 | hr = WcaGetRecordFormattedString(hRec, vuqPassword, &pwzData); | 86 | hr = WcaGetRecordFormattedString(hRec, vuqPassword, &pwzData); |
| 82 | ExitOnFailure(hr, "Failed to get Wix4User.Password"); | 87 | ExitOnFailure(hr, "Failed to get Wix4User.Password"); |
| 83 | hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData); | 88 | hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData); |
| @@ -154,6 +159,11 @@ HRESULT __stdcall ScaGetUserDeferred( | |||
| 154 | hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData); | 159 | hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData); |
| 155 | ExitOnFailure(hr, "Failed to copy domain string to user object (in deferred CA)"); | 160 | ExitOnFailure(hr, "Failed to copy domain string to user object (in deferred CA)"); |
| 156 | 161 | ||
| 162 | hr = WcaGetRecordString(hRec, vuqComment, &pwzData); | ||
| 163 | ExitOnFailure(hr, "Failed to get Wix4User.Comment"); | ||
| 164 | hr = ::StringCchCopyW(pscau->wzComment, countof(pscau->wzComment), pwzData); | ||
| 165 | ExitOnFailure(hr, "Failed to copy comment string to user object (in deferred CA)"); | ||
| 166 | |||
| 157 | hr = WcaGetRecordString(hRec, vuqPassword, &pwzData); | 167 | hr = WcaGetRecordString(hRec, vuqPassword, &pwzData); |
| 158 | ExitOnFailure(hr, "Failed to get Wix4User.Password"); | 168 | ExitOnFailure(hr, "Failed to get Wix4User.Password"); |
| 159 | hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData); | 169 | hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData); |
| @@ -316,7 +326,7 @@ HRESULT ScaUserRead( | |||
| 316 | ExitOnFailure(hr, "failed to get Component state for Wix4User"); | 326 | ExitOnFailure(hr, "failed to get Component state for Wix4User"); |
| 317 | 327 | ||
| 318 | // don't bother if we aren't installing or uninstalling this component | 328 | // don't bother if we aren't installing or uninstalling this component |
| 319 | if (WcaIsInstalling(isInstalled, isAction) || WcaIsUninstalling(isInstalled, isAction)) | 329 | if (WcaIsInstalling(isInstalled, isAction) || WcaIsUninstalling(isInstalled, isAction)) |
| 320 | { | 330 | { |
| 321 | // | 331 | // |
| 322 | // Add the user to the list and populate it's values | 332 | // Add the user to the list and populate it's values |
| @@ -345,6 +355,10 @@ HRESULT ScaUserRead( | |||
| 345 | ExitOnFailure(hr, "failed to get Wix4User.Domain"); | 355 | ExitOnFailure(hr, "failed to get Wix4User.Domain"); |
| 346 | hr = ::StringCchCopyW(psu->wzDomain, countof(psu->wzDomain), pwzData); | 356 | hr = ::StringCchCopyW(psu->wzDomain, countof(psu->wzDomain), pwzData); |
| 347 | ExitOnFailure(hr, "failed to copy user domain: %ls", pwzData); | 357 | ExitOnFailure(hr, "failed to copy user domain: %ls", pwzData); |
| 358 | hr = WcaGetRecordFormattedString(hRec, vaqComment, &pwzData); | ||
| 359 | ExitOnFailure(hr, "failed to get Wix4User.Comment"); | ||
| 360 | hr = ::StringCchCopyW(psu->wzComment, countof(psu->wzComment), pwzData); | ||
| 361 | ExitOnFailure(hr, "failed to copy user comment: %ls", pwzData); | ||
| 348 | 362 | ||
| 349 | hr = WcaGetRecordFormattedString(hRec, vaqPassword, &pwzData); | 363 | hr = WcaGetRecordFormattedString(hRec, vaqPassword, &pwzData); |
| 350 | ExitOnFailure(hr, "failed to get Wix4User.Password"); | 364 | ExitOnFailure(hr, "failed to get Wix4User.Password"); |
| @@ -492,15 +506,16 @@ HRESULT ScaUserExecute( | |||
| 492 | { | 506 | { |
| 493 | USER_EXISTS ueUserExists = USER_EXISTS_INDETERMINATE; | 507 | USER_EXISTS ueUserExists = USER_EXISTS_INDETERMINATE; |
| 494 | 508 | ||
| 495 | // Always put the User Name and Domain plus Attributes on the front of the CustomAction | 509 | // Always put the User Name, Domain, and Comment on the front of the CustomAction data. |
| 496 | // data. Sometimes we'll add more data. | 510 | // The attributes will be added when we have finished adjusting them. Sometimes we'll |
| 511 | // add more data. | ||
| 497 | Assert(psu->wzName); | 512 | Assert(psu->wzName); |
| 498 | hr = WcaWriteStringToCaData(psu->wzName, &pwzActionData); | 513 | hr = WcaWriteStringToCaData(psu->wzName, &pwzActionData); |
| 499 | ExitOnFailure(hr, "Failed to add user name to custom action data: %ls", psu->wzName); | 514 | ExitOnFailure(hr, "Failed to add user name to custom action data: %ls", psu->wzName); |
| 500 | hr = WcaWriteStringToCaData(psu->wzDomain, &pwzActionData); | 515 | hr = WcaWriteStringToCaData(psu->wzDomain, &pwzActionData); |
| 501 | ExitOnFailure(hr, "Failed to add user domain to custom action data: %ls", psu->wzDomain); | 516 | ExitOnFailure(hr, "Failed to add user domain to custom action data: %ls", psu->wzDomain); |
| 502 | hr = WcaWriteIntegerToCaData(psu->iAttributes, &pwzActionData); | 517 | hr = WcaWriteStringToCaData(psu->wzComment, &pwzActionData); |
| 503 | ExitOnFailure(hr, "failed to add user attributes to custom action data for user: %ls", psu->wzKey); | 518 | ExitOnFailure(hr, "Failed to add user comment to custom action data: %ls", psu->wzComment); |
| 504 | 519 | ||
| 505 | // 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 |
| 506 | // and removing users. Note: MSDN says that it is safe to call these APIs from any | 521 | // and removing users. Note: MSDN says that it is safe to call these APIs from any |
| @@ -520,7 +535,12 @@ HRESULT ScaUserExecute( | |||
| 520 | } | 535 | } |
| 521 | if (ERROR_SUCCESS == er) | 536 | if (ERROR_SUCCESS == er) |
| 522 | { | 537 | { |
| 523 | wzDomain = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix | 538 | if (2 <= wcslen(pDomainControllerInfo->DomainControllerName)) |
| 539 | { | ||
| 540 | wzDomain = pDomainControllerInfo->DomainControllerName + 2; // Add 2 so that we don't get the \\ prefix. | ||
| 541 | // Pass the entire string if it is too short | ||
| 542 | // to have a \\ prefix. | ||
| 543 | } | ||
| 524 | } | 544 | } |
| 525 | } | 545 | } |
| 526 | 546 | ||
| @@ -544,23 +564,32 @@ HRESULT ScaUserExecute( | |||
| 544 | 564 | ||
| 545 | if (WcaIsInstalling(psu->isInstalled, psu->isAction)) | 565 | if (WcaIsInstalling(psu->isInstalled, psu->isAction)) |
| 546 | { | 566 | { |
| 547 | // If the user exists, check to see if we are supposed to fail if user the exists before | 567 | // If the user exists, check to see if we are supposed to fail if the user exists before |
| 548 | // the install. | 568 | // the install. |
| 549 | if (USER_EXISTS_YES == ueUserExists) | 569 | if (USER_EXISTS_YES == ueUserExists) |
| 550 | { | 570 | { |
| 551 | // Reinstalls will always fail if we don't remove the check for "fail if exists". | 571 | // Re-installs will always fail if we don't remove the check for "fail if exists". |
| 552 | if (WcaIsReInstalling(psu->isInstalled, psu->isAction)) | 572 | if (WcaIsReInstalling(psu->isInstalled, psu->isAction)) |
| 553 | { | 573 | { |
| 554 | psu->iAttributes &= ~SCAU_FAIL_IF_EXISTS; | 574 | psu->iAttributes &= ~SCAU_FAIL_IF_EXISTS; |
| 575 | |||
| 576 | // If install would create the user, re-install should be able to update the user. | ||
| 577 | if (!(psu->iAttributes & SCAU_DONT_CREATE_USER)) | ||
| 578 | { | ||
| 579 | psu->iAttributes |= SCAU_UPDATE_IF_EXISTS; | ||
| 580 | } | ||
| 555 | } | 581 | } |
| 556 | 582 | ||
| 557 | if ((SCAU_FAIL_IF_EXISTS & (psu->iAttributes)) && !(SCAU_UPDATE_IF_EXISTS & (psu->iAttributes))) | 583 | if (SCAU_FAIL_IF_EXISTS & psu->iAttributes && !(SCAU_UPDATE_IF_EXISTS & psu->iAttributes)) |
| 558 | { | 584 | { |
| 559 | hr = HRESULT_FROM_WIN32(NERR_UserExists); | 585 | hr = HRESULT_FROM_WIN32(NERR_UserExists); |
| 560 | MessageExitOnFailure(hr, msierrUSRFailedUserCreateExists, "Failed to create user: %ls because user already exists.", psu->wzName); | 586 | MessageExitOnFailure(hr, msierrUSRFailedUserCreateExists, "Failed to create user: %ls because user already exists.", psu->wzName); |
| 561 | } | 587 | } |
| 562 | } | 588 | } |
| 563 | 589 | ||
| 590 | hr = WcaWriteIntegerToCaData(psu->iAttributes, &pwzActionData); | ||
| 591 | ExitOnFailure(hr, "failed to add user attributes to custom action data for user: %ls", psu->wzKey); | ||
| 592 | |||
| 564 | // Rollback only if the user already exists, we couldn't determine if the user exists, or we are going to create the user | 593 | // Rollback only if the user already exists, we couldn't determine if the user exists, or we are going to create the user |
| 565 | if ((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists) || !(psu->iAttributes & SCAU_DONT_CREATE_USER)) | 594 | if ((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists) || !(psu->iAttributes & SCAU_DONT_CREATE_USER)) |
| 566 | { | 595 | { |
| @@ -597,7 +626,6 @@ HRESULT ScaUserExecute( | |||
| 597 | ExitOnFailure(hr, "Failed to add user domain to rollback custom action data: %ls", psu->wzDomain); | 626 | ExitOnFailure(hr, "Failed to add user domain to rollback custom action data: %ls", psu->wzDomain); |
| 598 | hr = WcaWriteIntegerToCaData(iRollbackUserAttributes, &pwzRollbackData); | 627 | hr = WcaWriteIntegerToCaData(iRollbackUserAttributes, &pwzRollbackData); |
| 599 | ExitOnFailure(hr, "failed to add user attributes to rollback custom action data for user: %ls", psu->wzKey); | 628 | ExitOnFailure(hr, "failed to add user attributes to rollback custom action data for user: %ls", psu->wzKey); |
| 600 | |||
| 601 | // If the user already exists, add relevant group information to rollback data | 629 | // If the user already exists, add relevant group information to rollback data |
| 602 | if (USER_EXISTS_YES == ueUserExists || USER_EXISTS_INDETERMINATE == ueUserExists) | 630 | if (USER_EXISTS_YES == ueUserExists || USER_EXISTS_INDETERMINATE == ueUserExists) |
| 603 | { | 631 | { |
| @@ -630,11 +658,13 @@ HRESULT ScaUserExecute( | |||
| 630 | } | 658 | } |
| 631 | else if (((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists)) && WcaIsUninstalling(psu->isInstalled, psu->isAction) && !(psu->iAttributes & SCAU_DONT_REMOVE_ON_UNINSTALL)) | 659 | else if (((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists)) && WcaIsUninstalling(psu->isInstalled, psu->isAction) && !(psu->iAttributes & SCAU_DONT_REMOVE_ON_UNINSTALL)) |
| 632 | { | 660 | { |
| 661 | hr = WcaWriteIntegerToCaData(psu->iAttributes, &pwzActionData); | ||
| 662 | ExitOnFailure(hr, "failed to add user attributes to custom action data for user: %ls", psu->wzKey); | ||
| 663 | |||
| 633 | // Add user's group information - this will ensure the user can be removed from any groups they were added to, if the user isn't be deleted | 664 | // Add user's group information - this will ensure the user can be removed from any groups they were added to, if the user isn't be deleted |
| 634 | hr = WriteGroupInfo(psu->psgGroups, &pwzActionData); | 665 | hr = WriteGroupInfo(psu->psgGroups, &pwzActionData); |
| 635 | ExitOnFailure(hr, "failed to add group information to custom action data"); | 666 | ExitOnFailure(hr, "failed to add group information to custom action data"); |
| 636 | 667 | ||
| 637 | // | ||
| 638 | // Schedule the removal because the user exists and we don't have any flags set | 668 | // Schedule the removal because the user exists and we don't have any flags set |
| 639 | // that say, don't remove the user on uninstall. | 669 | // that say, don't remove the user on uninstall. |
| 640 | // | 670 | // |
| @@ -642,7 +672,7 @@ HRESULT ScaUserExecute( | |||
| 642 | // CustomAction. | 672 | // CustomAction. |
| 643 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RemoveUser"), pwzActionData, COST_USER_DELETE); | 673 | hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RemoveUser"), pwzActionData, COST_USER_DELETE); |
| 644 | ExitOnFailure(hr, "failed to schedule RemoveUser"); | 674 | ExitOnFailure(hr, "failed to schedule RemoveUser"); |
| 645 | } | 675 | } |
| 646 | 676 | ||
| 647 | ReleaseNullStr(pwzScriptKey); | 677 | ReleaseNullStr(pwzScriptKey); |
| 648 | ReleaseNullStr(pwzActionData); | 678 | ReleaseNullStr(pwzActionData); |
