diff options
| author | Bevan Weiss <bevan.weiss@gmail.com> | 2024-06-18 19:03:40 +1000 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2025-02-11 23:14:49 -0800 |
| commit | 7b1bb025dea1d1e9e144cce0dcbba2d86f053b8f (patch) | |
| tree | c2fc969615d858ee40f54cfba406648e9c2743c3 /src/ext/Util/ca/scaexec.cpp | |
| parent | 040e50ec2859c1de70cd8e9f957474321774f293 (diff) | |
| download | wix-7b1bb025dea1d1e9e144cce0dcbba2d86f053b8f.tar.gz wix-7b1bb025dea1d1e9e144cce0dcbba2d86f053b8f.tar.bz2 wix-7b1bb025dea1d1e9e144cce0dcbba2d86f053b8f.zip | |
CreateGroups additions
Signed-off-by: Bevan Weiss <bevan.weiss@gmail.com>
Diffstat (limited to 'src/ext/Util/ca/scaexec.cpp')
| -rw-r--r-- | src/ext/Util/ca/scaexec.cpp | 628 |
1 files changed, 628 insertions, 0 deletions
diff --git a/src/ext/Util/ca/scaexec.cpp b/src/ext/Util/ca/scaexec.cpp index 8579b8bb..5a750c6b 100644 --- a/src/ext/Util/ca/scaexec.cpp +++ b/src/ext/Util/ca/scaexec.cpp | |||
| @@ -291,6 +291,145 @@ LExit: | |||
| 291 | return hr; | 291 | return hr; |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | static HRESULT AddGroupToGroup( | ||
| 295 | __in LPWSTR wzMember, | ||
| 296 | __in LPCWSTR wzMemberDomain, | ||
| 297 | __in LPCWSTR wzGroup, | ||
| 298 | __in LPCWSTR wzGroupDomain | ||
| 299 | ) | ||
| 300 | { | ||
| 301 | Assert(wzMember && *wzMember && wzMemberDomain && wzGroup && *wzGroup && wzGroupDomain); | ||
| 302 | |||
| 303 | HRESULT hr = S_OK; | ||
| 304 | IADsGroup* pGroup = NULL; | ||
| 305 | BSTR bstrMember = NULL; | ||
| 306 | BSTR bstrGroup = NULL; | ||
| 307 | LPWSTR pwzMember = NULL; | ||
| 308 | LPWSTR pwzServerName = NULL; | ||
| 309 | LOCALGROUP_MEMBERS_INFO_3 lgmi {}; | ||
| 310 | |||
| 311 | GetDomainServerName(wzGroupDomain, &pwzServerName); | ||
| 312 | |||
| 313 | // Try adding it to the local group | ||
| 314 | if (wzMemberDomain) | ||
| 315 | { | ||
| 316 | hr = StrAllocFormatted(&pwzMember, L"%s\\%s", wzMemberDomain, wzMember); | ||
| 317 | ExitOnFailure(hr, "failed to allocate group domain string"); | ||
| 318 | } | ||
| 319 | |||
| 320 | lgmi.lgrmi3_domainandname = (NULL == pwzMember ? wzMember : pwzMember); | ||
| 321 | NET_API_STATUS ui = ::NetLocalGroupAddMembers(pwzServerName, wzGroup, 3, reinterpret_cast<LPBYTE>(&lgmi), 1); | ||
| 322 | hr = HRESULT_FROM_WIN32(ui); | ||
| 323 | if (HRESULT_FROM_WIN32(ERROR_MEMBER_IN_ALIAS) == hr) // if they're already a member of the group don't report an error | ||
| 324 | { | ||
| 325 | hr = S_OK; | ||
| 326 | } | ||
| 327 | |||
| 328 | // | ||
| 329 | // If we failed, try active directory | ||
| 330 | // | ||
| 331 | if (FAILED(hr)) | ||
| 332 | { | ||
| 333 | WcaLog(LOGMSG_VERBOSE, "Failed to add group: %ls, domain %ls to group: %ls, domain: %ls with error 0x%x. Attempting to use Active Directory", wzMember, wzMemberDomain, wzGroup, wzGroupDomain, hr); | ||
| 334 | |||
| 335 | hr = UserCreateADsPath(wzMemberDomain, wzMember, &bstrMember); | ||
| 336 | ExitOnFailure(hr, "failed to create group ADsPath for group: %ls domain: %ls", wzMember, wzMemberDomain); | ||
| 337 | |||
| 338 | hr = UserCreateADsPath(wzGroupDomain, wzGroup, &bstrGroup); | ||
| 339 | ExitOnFailure(hr, "failed to create group ADsPath for group: %ls domain: %ls", wzGroup, wzGroupDomain); | ||
| 340 | |||
| 341 | hr = ::ADsGetObject(bstrGroup, IID_IADsGroup, reinterpret_cast<void**>(&pGroup)); | ||
| 342 | ExitOnFailure(hr, "Failed to get group '%ls'.", reinterpret_cast<WCHAR*>(bstrGroup)); | ||
| 343 | |||
| 344 | hr = pGroup->Add(bstrMember); | ||
| 345 | if ((HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS) == hr) || (HRESULT_FROM_WIN32(ERROR_MEMBER_IN_ALIAS) == hr)) | ||
| 346 | hr = S_OK; | ||
| 347 | |||
| 348 | ExitOnFailure(hr, "Failed to add group %ls to group '%ls'.", reinterpret_cast<WCHAR*>(bstrMember), reinterpret_cast<WCHAR*>(bstrGroup)); | ||
| 349 | } | ||
| 350 | |||
| 351 | LExit: | ||
| 352 | ReleaseStr(pwzServerName); | ||
| 353 | ReleaseStr(pwzMember); | ||
| 354 | ReleaseBSTR(bstrMember); | ||
| 355 | ReleaseBSTR(bstrGroup); | ||
| 356 | ReleaseObject(pGroup); | ||
| 357 | |||
| 358 | return hr; | ||
| 359 | } | ||
| 360 | |||
| 361 | static HRESULT RemoveGroupFromGroup( | ||
| 362 | __in LPWSTR wzMember, | ||
| 363 | __in LPCWSTR wzMemberDomain, | ||
| 364 | __in LPCWSTR wzGroup, | ||
| 365 | __in LPCWSTR wzGroupDomain | ||
| 366 | ) | ||
| 367 | { | ||
| 368 | Assert(wzMember && *wzMember && wzMemberDomain && wzGroup && *wzGroup && wzGroupDomain); | ||
| 369 | |||
| 370 | HRESULT hr = S_OK; | ||
| 371 | IADsGroup* pGroup = NULL; | ||
| 372 | BSTR bstrMember = NULL; | ||
| 373 | BSTR bstrGroup = NULL; | ||
| 374 | LPWSTR pwzMember = NULL; | ||
| 375 | LPWSTR pwzServerName = NULL; | ||
| 376 | LOCALGROUP_MEMBERS_INFO_3 lgmi {}; | ||
| 377 | |||
| 378 | GetDomainServerName(wzGroupDomain, &pwzServerName, DS_WRITABLE_REQUIRED); | ||
| 379 | |||
| 380 | // Try removing it from the local group | ||
| 381 | if (wzMemberDomain) | ||
| 382 | { | ||
| 383 | hr = StrAllocFormatted(&pwzMember, L"%s\\%s", wzMemberDomain, wzMember); | ||
| 384 | ExitOnFailure(hr, "failed to allocate group domain string"); | ||
| 385 | } | ||
| 386 | |||
| 387 | lgmi.lgrmi3_domainandname = (NULL == pwzMember ? wzMember : pwzMember); | ||
| 388 | NET_API_STATUS ui = ::NetLocalGroupDelMembers(pwzServerName, wzGroup, 3, reinterpret_cast<LPBYTE>(&lgmi), 1); | ||
| 389 | hr = HRESULT_FROM_WIN32(ui); | ||
| 390 | if (HRESULT_FROM_WIN32(ERROR_MEMBER_NOT_IN_ALIAS) == hr | ||
| 391 | || HRESULT_FROM_WIN32(NERR_GroupNotFound) == hr | ||
| 392 | || HRESULT_FROM_WIN32(ERROR_NO_SUCH_MEMBER) == hr) // if they're already not a member of the group, or the group doesn't exist, don't report an error | ||
| 393 | { | ||
| 394 | hr = S_OK; | ||
| 395 | } | ||
| 396 | |||
| 397 | // | ||
| 398 | // If we failed, try active directory | ||
| 399 | // | ||
| 400 | if (FAILED(hr)) | ||
| 401 | { | ||
| 402 | WcaLog(LOGMSG_VERBOSE, "Failed to remove group: %ls, domain %ls from group: %ls, domain: %ls with error 0x%x. Attempting to use Active Directory", wzMember, wzMemberDomain, wzGroup, wzGroupDomain, hr); | ||
| 403 | |||
| 404 | hr = UserCreateADsPath(wzMemberDomain, wzMember, &bstrMember); | ||
| 405 | ExitOnFailure(hr, "failed to create group ADsPath in order to remove group: %ls domain: %ls from a group", wzMember, wzMemberDomain); | ||
| 406 | |||
| 407 | hr = UserCreateADsPath(wzGroupDomain, wzGroup, &bstrGroup); | ||
| 408 | ExitOnFailure(hr, "failed to create group ADsPath in order to remove group from group: %ls domain: %ls", wzGroup, wzGroupDomain); | ||
| 409 | |||
| 410 | hr = ::ADsGetObject(bstrGroup, IID_IADsGroup, reinterpret_cast<void**>(&pGroup)); | ||
| 411 | if ((HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)) // if parent group not found, no need to remove membership from group | ||
| 412 | { | ||
| 413 | hr = S_OK; | ||
| 414 | ExitFunction(); | ||
| 415 | } | ||
| 416 | ExitOnFailure(hr, "Failed to get group '%ls'.", reinterpret_cast<WCHAR*>(bstrGroup)); | ||
| 417 | |||
| 418 | hr = pGroup->Remove(bstrMember); | ||
| 419 | if ((HRESULT_FROM_WIN32(ERROR_MEMBER_NOT_IN_ALIAS) == hr)) // if already not a member, no need to worry about error | ||
| 420 | hr = S_OK; | ||
| 421 | ExitOnFailure(hr, "Failed to remove group %ls from group '%ls'.", reinterpret_cast<WCHAR*>(bstrMember), reinterpret_cast<WCHAR*>(bstrGroup)); | ||
| 422 | } | ||
| 423 | |||
| 424 | LExit: | ||
| 425 | ReleaseStr(pwzServerName); | ||
| 426 | ReleaseStr(pwzMember); | ||
| 427 | ReleaseBSTR(bstrMember); | ||
| 428 | ReleaseBSTR(bstrGroup); | ||
| 429 | ReleaseObject(pGroup); | ||
| 430 | |||
| 431 | return hr; | ||
| 432 | } | ||
| 294 | 433 | ||
| 295 | static HRESULT GetUserHasRight( | 434 | static HRESULT GetUserHasRight( |
| 296 | __in LSA_HANDLE hPolicy, | 435 | __in LSA_HANDLE hPolicy, |
| @@ -590,6 +729,15 @@ static HRESULT SetUserComment(__in LPWSTR pwzServerName, __in LPWSTR pwzName, __ | |||
| 590 | return HRESULT_FROM_WIN32(er); | 729 | return HRESULT_FROM_WIN32(er); |
| 591 | } | 730 | } |
| 592 | 731 | ||
| 732 | static HRESULT SetGroupComment(__in LPWSTR pwzServerName, __in LPWSTR pwzName, __in LPWSTR pwzComment) | ||
| 733 | { | ||
| 734 | _LOCALGROUP_INFO_1002 groupInfo1002 {}; | ||
| 735 | |||
| 736 | groupInfo1002.lgrpi1002_comment = pwzComment; | ||
| 737 | NET_API_STATUS er = ::NetLocalGroupSetInfo(pwzServerName, pwzName, 1002, reinterpret_cast<LPBYTE>(&groupInfo1002), NULL); | ||
| 738 | return HRESULT_FROM_WIN32(er); | ||
| 739 | } | ||
| 740 | |||
| 593 | static HRESULT SetUserFlags(__in LPWSTR pwzServerName, __in LPWSTR pwzName, __in DWORD flags) | 741 | static HRESULT SetUserFlags(__in LPWSTR pwzServerName, __in LPWSTR pwzName, __in DWORD flags) |
| 594 | { | 742 | { |
| 595 | NET_API_STATUS er = NERR_Success; | 743 | NET_API_STATUS er = NERR_Success; |
| @@ -693,6 +841,76 @@ LExit: | |||
| 693 | return hr; | 841 | return hr; |
| 694 | } | 842 | } |
| 695 | 843 | ||
| 844 | static HRESULT RemoveGroupInternal( | ||
| 845 | LPWSTR wzGroupCaData, | ||
| 846 | LPWSTR wzDomain, | ||
| 847 | LPWSTR wzName, | ||
| 848 | int iAttributes | ||
| 849 | ) | ||
| 850 | { | ||
| 851 | HRESULT hr = S_OK; | ||
| 852 | |||
| 853 | LPWSTR pwz = NULL; | ||
| 854 | LPWSTR pwzGroup = NULL; | ||
| 855 | LPWSTR pwzGroupDomain = NULL; | ||
| 856 | LPWSTR pwzServerName = NULL; | ||
| 857 | |||
| 858 | // | ||
| 859 | // Remove the Group if the group was created by us. | ||
| 860 | // | ||
| 861 | if (!(SCAG_DONT_CREATE_GROUP & iAttributes)) | ||
| 862 | { | ||
| 863 | GetDomainServerName(wzDomain, &pwzServerName, DS_WRITABLE_REQUIRED); | ||
| 864 | |||
| 865 | NET_API_STATUS er = ::NetLocalGroupDel(pwzServerName, wzName); | ||
| 866 | hr = HRESULT_FROM_WIN32(er); | ||
| 867 | if (HRESULT_FROM_WIN32(ERROR_NO_SUCH_ALIAS) == hr | ||
| 868 | || HRESULT_FROM_WIN32(NERR_GroupNotFound) == hr) // we wanted to delete it.. and the group doesn't exist.. solved. | ||
| 869 | { | ||
| 870 | hr = S_OK; | ||
| 871 | } | ||
| 872 | ExitOnFailure(hr, "failed to delete group: %ls", wzName); | ||
| 873 | } | ||
| 874 | else | ||
| 875 | { | ||
| 876 | // | ||
| 877 | // Remove the group from other groups | ||
| 878 | // | ||
| 879 | pwz = wzGroupCaData; | ||
| 880 | while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup))) | ||
| 881 | { | ||
| 882 | hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain); | ||
| 883 | |||
| 884 | if (FAILED(hr)) | ||
| 885 | { | ||
| 886 | WcaLogError(hr, "failed to get domain for group: %ls, continuing anyway.", pwzGroup); | ||
| 887 | } | ||
| 888 | else | ||
| 889 | { | ||
| 890 | hr = RemoveGroupFromGroup(wzName, wzDomain, pwzGroup, pwzGroupDomain); | ||
| 891 | if (FAILED(hr)) | ||
| 892 | { | ||
| 893 | WcaLogError(hr, "failed to remove group: %ls from group %ls, continuing anyway.", wzName, pwzGroup); | ||
| 894 | } | ||
| 895 | } | ||
| 896 | } | ||
| 897 | |||
| 898 | if (E_NOMOREITEMS == hr) // if there are no more items, all is well | ||
| 899 | { | ||
| 900 | hr = S_OK; | ||
| 901 | } | ||
| 902 | |||
| 903 | ExitOnFailure(hr, "failed to get next group from which to remove group:%ls", wzName); | ||
| 904 | } | ||
| 905 | LExit: | ||
| 906 | ReleaseStr(pwzServerName); | ||
| 907 | ReleaseStr(pwzGroup); | ||
| 908 | ReleaseStr(pwzGroupDomain); | ||
| 909 | |||
| 910 | return hr; | ||
| 911 | } | ||
| 912 | |||
| 913 | |||
| 696 | /******************************************************************** | 914 | /******************************************************************** |
| 697 | CreateUser - CUSTOM ACTION ENTRY POINT for creating users | 915 | CreateUser - CUSTOM ACTION ENTRY POINT for creating users |
| 698 | 916 | ||
| @@ -1173,3 +1391,413 @@ LExit: | |||
| 1173 | 1391 | ||
| 1174 | return WcaFinalize(er); | 1392 | return WcaFinalize(er); |
| 1175 | } | 1393 | } |
| 1394 | |||
| 1395 | /******************************************************************** | ||
| 1396 | CreateGroup - CUSTOM ACTION ENTRY POINT for creating groups | ||
| 1397 | |||
| 1398 | Input: deferred CustomActionData - GroupName\tDomain\tComment\tAttributes | ||
| 1399 | * *****************************************************************/ | ||
| 1400 | extern "C" UINT __stdcall CreateGroup( | ||
| 1401 | __in MSIHANDLE hInstall | ||
| 1402 | ) | ||
| 1403 | { | ||
| 1404 | //AssertSz(0, "Debug CreateGroup"); | ||
| 1405 | |||
| 1406 | HRESULT hr = S_OK; | ||
| 1407 | NET_API_STATUS er = ERROR_SUCCESS; | ||
| 1408 | |||
| 1409 | LPWSTR pwzData = NULL; | ||
| 1410 | LPWSTR pwz = NULL; | ||
| 1411 | LPWSTR pwzName = NULL; | ||
| 1412 | LPWSTR pwzDomain = NULL; | ||
| 1413 | LPWSTR pwzComment = NULL; | ||
| 1414 | LPWSTR pwzScriptKey = NULL; | ||
| 1415 | LPWSTR pwzGroup = NULL; | ||
| 1416 | LPWSTR pwzGroupDomain = NULL; | ||
| 1417 | int iAttributes = 0; | ||
| 1418 | BOOL fInitializedCom = FALSE; | ||
| 1419 | |||
| 1420 | LOCALGROUP_INFO_1* pGroupInfo1 = NULL; | ||
| 1421 | |||
| 1422 | WCA_CASCRIPT_HANDLE hRollbackScript = NULL; | ||
| 1423 | int iRollbackAttributes = 0; | ||
| 1424 | |||
| 1425 | DWORD dw; | ||
| 1426 | LPWSTR pwzServerName = NULL; | ||
| 1427 | |||
| 1428 | hr = WcaInitialize(hInstall, "CreateGroup"); | ||
| 1429 | ExitOnFailure(hr, "failed to initialize"); | ||
| 1430 | |||
| 1431 | hr = ::CoInitialize(NULL); | ||
| 1432 | ExitOnFailure(hr, "failed to initialize COM"); | ||
| 1433 | fInitializedCom = TRUE; | ||
| 1434 | |||
| 1435 | hr = WcaGetProperty(L"CustomActionData", &pwzData); | ||
| 1436 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 1437 | |||
| 1438 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | ||
| 1439 | |||
| 1440 | // | ||
| 1441 | // Read in the CustomActionData | ||
| 1442 | // | ||
| 1443 | pwz = pwzData; | ||
| 1444 | hr = WcaReadStringFromCaData(&pwz, &pwzName); | ||
| 1445 | ExitOnFailure(hr, "failed to read group name from custom action data"); | ||
| 1446 | |||
| 1447 | hr = WcaReadStringFromCaData(&pwz, &pwzDomain); | ||
| 1448 | ExitOnFailure(hr, "failed to read domain from custom action data"); | ||
| 1449 | |||
| 1450 | hr = WcaReadStringFromCaData(&pwz, &pwzComment); | ||
| 1451 | ExitOnFailure(hr, "failed to read group comment from custom action data"); | ||
| 1452 | |||
| 1453 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); | ||
| 1454 | ExitOnFailure(hr, "failed to read attributes from custom action data"); | ||
| 1455 | |||
| 1456 | hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); | ||
| 1457 | ExitOnFailure(hr, "failed to read encoding key from custom action data"); | ||
| 1458 | |||
| 1459 | if (!(SCAG_DONT_CREATE_GROUP & iAttributes)) | ||
| 1460 | { | ||
| 1461 | hr = GetDomainServerName(pwzDomain, &pwzServerName, DS_WRITABLE_REQUIRED); | ||
| 1462 | ExitOnFailure(hr, "failed to find Domain %ls.", pwzDomain); | ||
| 1463 | |||
| 1464 | // Set the group's comment | ||
| 1465 | if (SCAG_REMOVE_COMMENT & iAttributes) | ||
| 1466 | { | ||
| 1467 | StrAllocString(&pwzComment, L"", 0); | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | // | ||
| 1471 | // Create the Group | ||
| 1472 | // | ||
| 1473 | LOCALGROUP_INFO_1 groupInfo1; | ||
| 1474 | groupInfo1.lgrpi1_name = pwzName; | ||
| 1475 | groupInfo1.lgrpi1_comment = pwzComment; | ||
| 1476 | er = ::NetLocalGroupAdd(pwzServerName, 1, reinterpret_cast<LPBYTE>(&groupInfo1), &dw); | ||
| 1477 | hr = HRESULT_FROM_WIN32(er); | ||
| 1478 | |||
| 1479 | if (HRESULT_FROM_WIN32(ERROR_ALIAS_EXISTS) == hr | ||
| 1480 | || HRESULT_FROM_WIN32(NERR_GroupExists) == hr) | ||
| 1481 | { | ||
| 1482 | if (SCAG_FAIL_IF_EXISTS & iAttributes) | ||
| 1483 | { | ||
| 1484 | MessageExitOnFailure(hr, msierrGRPFailedGroupCreateExists, "Group (%ls) was not supposed to exist, but does", pwzName); | ||
| 1485 | } | ||
| 1486 | |||
| 1487 | hr = S_OK; // Make sure that we don't report this situation as an error | ||
| 1488 | // if we fall through the tests that follow. | ||
| 1489 | |||
| 1490 | if (SCAG_UPDATE_IF_EXISTS & iAttributes) | ||
| 1491 | { | ||
| 1492 | er = ::NetLocalGroupGetInfo(pwzServerName, pwzName, 1, reinterpret_cast<LPBYTE*>(&pGroupInfo1)); | ||
| 1493 | hr = HRESULT_FROM_WIN32(er); | ||
| 1494 | if (S_OK == hr) | ||
| 1495 | { | ||
| 1496 | // There is no rollback scheduled if the key is empty. | ||
| 1497 | // Best effort to get original configuration and save it in the script so rollback can restore it. | ||
| 1498 | if (*pwzScriptKey) | ||
| 1499 | { | ||
| 1500 | // Try to open the rollback script | ||
| 1501 | hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript); | ||
| 1502 | |||
| 1503 | if (hRollbackScript && INVALID_HANDLE_VALUE != hRollbackScript->hScriptFile) | ||
| 1504 | { | ||
| 1505 | WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE); | ||
| 1506 | } | ||
| 1507 | else | ||
| 1508 | { | ||
| 1509 | hRollbackScript = NULL; | ||
| 1510 | hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, FALSE, &hRollbackScript); | ||
| 1511 | ExitOnFailure(hr, "Failed to open rollback CustomAction script."); | ||
| 1512 | |||
| 1513 | iRollbackAttributes = 0; | ||
| 1514 | |||
| 1515 | hr = WcaCaScriptWriteString(hRollbackScript, pGroupInfo1->lgrpi1_comment); | ||
| 1516 | ExitOnFailure(hr, "Failed to add rollback comment to rollback script."); | ||
| 1517 | |||
| 1518 | if (!pGroupInfo1->lgrpi1_comment || !*pGroupInfo1->lgrpi1_comment) | ||
| 1519 | { | ||
| 1520 | iRollbackAttributes |= SCAG_REMOVE_COMMENT; | ||
| 1521 | } | ||
| 1522 | |||
| 1523 | hr = WcaCaScriptWriteNumber(hRollbackScript, iRollbackAttributes); | ||
| 1524 | ExitOnFailure(hr, "Failed to add rollback attributes to rollback script."); | ||
| 1525 | |||
| 1526 | // Nudge the system to get all our rollback data written to disk. | ||
| 1527 | WcaCaScriptFlush(hRollbackScript); | ||
| 1528 | } | ||
| 1529 | } | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | if (S_OK == hr) | ||
| 1533 | { | ||
| 1534 | if (SCAG_REMOVE_COMMENT & iAttributes) | ||
| 1535 | { | ||
| 1536 | hr = SetGroupComment(pwzServerName, pwzName, L""); | ||
| 1537 | if (FAILED(hr)) | ||
| 1538 | { | ||
| 1539 | WcaLogError(hr, "failed to clear comment for group %ls\\%ls, continuing anyway.", pwzServerName, pwzName); | ||
| 1540 | hr = S_OK; | ||
| 1541 | } | ||
| 1542 | } | ||
| 1543 | else if (pwzComment && *pwzComment) | ||
| 1544 | { | ||
| 1545 | hr = SetGroupComment(pwzServerName, pwzName, pwzComment); | ||
| 1546 | if (FAILED(hr)) | ||
| 1547 | { | ||
| 1548 | WcaLogError(hr, "failed to set comment to %ls for group %ls\\%ls, continuing anyway.", pwzComment, pwzServerName, pwzName); | ||
| 1549 | hr = S_OK; | ||
| 1550 | } | ||
| 1551 | } | ||
| 1552 | } | ||
| 1553 | } | ||
| 1554 | } | ||
| 1555 | MessageExitOnFailure(hr, msierrGRPFailedGroupCreate, "failed to create group: %ls", pwzName); | ||
| 1556 | |||
| 1557 | // | ||
| 1558 | // Add the groups to groups | ||
| 1559 | // | ||
| 1560 | while (S_OK == (hr = WcaReadStringFromCaData(&pwz, &pwzGroup))) | ||
| 1561 | { | ||
| 1562 | hr = WcaReadStringFromCaData(&pwz, &pwzGroupDomain); | ||
| 1563 | ExitOnFailure(hr, "failed to get domain for group: %ls", pwzGroup); | ||
| 1564 | |||
| 1565 | WcaLog(LOGMSG_STANDARD, "Adding group %ls\\%ls to group %ls\\%ls", pwzDomain, pwzName, pwzGroupDomain, pwzGroup); | ||
| 1566 | hr = AddGroupToGroup(pwzName, pwzDomain, pwzGroup, pwzGroupDomain); | ||
| 1567 | MessageExitOnFailure(hr, msierrUSRFailedUserGroupAdd, "failed to add group: %ls to group %ls", pwzName, pwzGroup); | ||
| 1568 | } | ||
| 1569 | if (E_NOMOREITEMS == hr) // if there are no more items, all is well | ||
| 1570 | { | ||
| 1571 | hr = S_OK; | ||
| 1572 | } | ||
| 1573 | ExitOnFailure(hr, "failed to get next group in which to include group: %ls", pwzName); | ||
| 1574 | } | ||
| 1575 | |||
| 1576 | LExit: | ||
| 1577 | WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_PRESERVE); | ||
| 1578 | |||
| 1579 | if (pGroupInfo1) | ||
| 1580 | { | ||
| 1581 | ::NetApiBufferFree((LPVOID)pGroupInfo1); | ||
| 1582 | } | ||
| 1583 | |||
| 1584 | ReleaseStr(pwzData); | ||
| 1585 | ReleaseStr(pwzName); | ||
| 1586 | ReleaseStr(pwzDomain); | ||
| 1587 | ReleaseStr(pwzComment); | ||
| 1588 | ReleaseStr(pwzScriptKey); | ||
| 1589 | ReleaseStr(pwzGroup); | ||
| 1590 | ReleaseStr(pwzGroupDomain); | ||
| 1591 | |||
| 1592 | if (fInitializedCom) | ||
| 1593 | { | ||
| 1594 | ::CoUninitialize(); | ||
| 1595 | } | ||
| 1596 | |||
| 1597 | if (SCAG_NON_VITAL & iAttributes) | ||
| 1598 | { | ||
| 1599 | er = ERROR_SUCCESS; | ||
| 1600 | } | ||
| 1601 | else if (FAILED(hr)) | ||
| 1602 | { | ||
| 1603 | er = ERROR_INSTALL_FAILURE; | ||
| 1604 | } | ||
| 1605 | |||
| 1606 | return WcaFinalize(er); | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | |||
| 1610 | /******************************************************************** | ||
| 1611 | CreateGroupRollback - CUSTOM ACTION ENTRY POINT for CreateGroup rollback | ||
| 1612 | |||
| 1613 | * *****************************************************************/ | ||
| 1614 | extern "C" UINT __stdcall CreateGroupRollback( | ||
| 1615 | MSIHANDLE hInstall | ||
| 1616 | ) | ||
| 1617 | { | ||
| 1618 | //AssertSz(0, "Debug CreateGroupRollback"); | ||
| 1619 | |||
| 1620 | HRESULT hr = S_OK; | ||
| 1621 | UINT er = ERROR_SUCCESS; | ||
| 1622 | |||
| 1623 | LPWSTR pwzData = NULL; | ||
| 1624 | LPWSTR pwz = NULL; | ||
| 1625 | LPWSTR pwzScriptKey = NULL; | ||
| 1626 | LPWSTR pwzName = NULL; | ||
| 1627 | LPWSTR pwzDomain = NULL; | ||
| 1628 | LPWSTR pwzComment = NULL; | ||
| 1629 | int iAttributes = 0; | ||
| 1630 | BOOL fInitializedCom = FALSE; | ||
| 1631 | |||
| 1632 | WCA_CASCRIPT_HANDLE hRollbackScript = NULL; | ||
| 1633 | LPWSTR pwzRollbackData = NULL; | ||
| 1634 | int iOriginalAttributes = 0; | ||
| 1635 | LPWSTR pwzOriginalComment = NULL; | ||
| 1636 | |||
| 1637 | hr = WcaInitialize(hInstall, "CreateGroupRollback"); | ||
| 1638 | ExitOnFailure(hr, "failed to initialize"); | ||
| 1639 | |||
| 1640 | hr = ::CoInitialize(NULL); | ||
| 1641 | ExitOnFailure(hr, "failed to initialize COM"); | ||
| 1642 | fInitializedCom = TRUE; | ||
| 1643 | |||
| 1644 | hr = WcaGetProperty(L"CustomActionData", &pwzData); | ||
| 1645 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 1646 | |||
| 1647 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | ||
| 1648 | |||
| 1649 | // | ||
| 1650 | // Read in the CustomActionData | ||
| 1651 | // | ||
| 1652 | pwz = pwzData; | ||
| 1653 | hr = WcaReadStringFromCaData(&pwz, &pwzScriptKey); | ||
| 1654 | ExitOnFailure(hr, "failed to read encoding key from custom action data"); | ||
| 1655 | |||
| 1656 | hr = WcaReadStringFromCaData(&pwz, &pwzName); | ||
| 1657 | ExitOnFailure(hr, "failed to read name from custom action data"); | ||
| 1658 | |||
| 1659 | hr = WcaReadStringFromCaData(&pwz, &pwzDomain); | ||
| 1660 | ExitOnFailure(hr, "failed to read domain from custom action data"); | ||
| 1661 | |||
| 1662 | hr = WcaReadStringFromCaData(&pwz, &pwzComment); | ||
| 1663 | ExitOnFailure(hr, "failed to read comment from custom action data"); | ||
| 1664 | |||
| 1665 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); | ||
| 1666 | ExitOnFailure(hr, "failed to read attributes from custom action data"); | ||
| 1667 | |||
| 1668 | // Best effort to read original configuration from CreateUser. | ||
| 1669 | hr = WcaCaScriptOpen(WCA_ACTION_INSTALL, WCA_CASCRIPT_ROLLBACK, FALSE, pwzScriptKey, &hRollbackScript); | ||
| 1670 | if (FAILED(hr)) | ||
| 1671 | { | ||
| 1672 | WcaLogError(hr, "Failed to open rollback CustomAction script, continuing anyway."); | ||
| 1673 | } | ||
| 1674 | else | ||
| 1675 | { | ||
| 1676 | hr = WcaCaScriptReadAsCustomActionData(hRollbackScript, &pwzRollbackData); | ||
| 1677 | if (FAILED(hr)) | ||
| 1678 | { | ||
| 1679 | WcaLogError(hr, "Failed to read rollback script into CustomAction data, continuing anyway."); | ||
| 1680 | } | ||
| 1681 | else | ||
| 1682 | { | ||
| 1683 | WcaLog(LOGMSG_TRACEONLY, "Rollback Data: %ls", pwzRollbackData); | ||
| 1684 | |||
| 1685 | pwz = pwzRollbackData; | ||
| 1686 | hr = WcaReadStringFromCaData(&pwz, &pwzOriginalComment); | ||
| 1687 | if (FAILED(hr)) | ||
| 1688 | { | ||
| 1689 | WcaLogError(hr, "failed to read comment from rollback data, continuing anyway"); | ||
| 1690 | } | ||
| 1691 | else | ||
| 1692 | { | ||
| 1693 | pwzComment = pwzOriginalComment; | ||
| 1694 | } | ||
| 1695 | hr = WcaReadIntegerFromCaData(&pwz, &iOriginalAttributes); | ||
| 1696 | if (FAILED(hr)) | ||
| 1697 | { | ||
| 1698 | WcaLogError(hr, "failed to read attributes from rollback data, continuing anyway"); | ||
| 1699 | } | ||
| 1700 | else | ||
| 1701 | { | ||
| 1702 | iAttributes |= iOriginalAttributes; | ||
| 1703 | } | ||
| 1704 | } | ||
| 1705 | } | ||
| 1706 | |||
| 1707 | hr = RemoveGroupInternal(pwz, pwzDomain, pwzName, iAttributes); | ||
| 1708 | |||
| 1709 | LExit: | ||
| 1710 | WcaCaScriptClose(hRollbackScript, WCA_CASCRIPT_CLOSE_DELETE); | ||
| 1711 | |||
| 1712 | ReleaseStr(pwzData); | ||
| 1713 | ReleaseStr(pwzName); | ||
| 1714 | ReleaseStr(pwzDomain); | ||
| 1715 | ReleaseStr(pwzComment); | ||
| 1716 | ReleaseStr(pwzScriptKey); | ||
| 1717 | ReleaseStr(pwzRollbackData); | ||
| 1718 | ReleaseStr(pwzOriginalComment); | ||
| 1719 | |||
| 1720 | if (fInitializedCom) | ||
| 1721 | { | ||
| 1722 | ::CoUninitialize(); | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | if (FAILED(hr)) | ||
| 1726 | { | ||
| 1727 | er = ERROR_INSTALL_FAILURE; | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | return WcaFinalize(er); | ||
| 1731 | } | ||
| 1732 | |||
| 1733 | |||
| 1734 | /******************************************************************** | ||
| 1735 | RemoveGroup - CUSTOM ACTION ENTRY POINT for removing groups | ||
| 1736 | |||
| 1737 | Input: deferred CustomActionData - Name\tDomain | ||
| 1738 | * *****************************************************************/ | ||
| 1739 | extern "C" UINT __stdcall RemoveGroup( | ||
| 1740 | MSIHANDLE hInstall | ||
| 1741 | ) | ||
| 1742 | { | ||
| 1743 | //AssertSz(0, "Debug RemoveGroup"); | ||
| 1744 | |||
| 1745 | HRESULT hr = S_OK; | ||
| 1746 | UINT er = ERROR_SUCCESS; | ||
| 1747 | |||
| 1748 | LPWSTR pwzData = NULL; | ||
| 1749 | LPWSTR pwz = NULL; | ||
| 1750 | LPWSTR pwzName = NULL; | ||
| 1751 | LPWSTR pwzDomain = NULL; | ||
| 1752 | LPWSTR pwzComment = NULL; | ||
| 1753 | int iAttributes = 0; | ||
| 1754 | BOOL fInitializedCom = FALSE; | ||
| 1755 | |||
| 1756 | hr = WcaInitialize(hInstall, "RemoveGroup"); | ||
| 1757 | ExitOnFailure(hr, "failed to initialize"); | ||
| 1758 | |||
| 1759 | hr = ::CoInitialize(NULL); | ||
| 1760 | ExitOnFailure(hr, "failed to initialize COM"); | ||
| 1761 | fInitializedCom = TRUE; | ||
| 1762 | |||
| 1763 | hr = WcaGetProperty(L"CustomActionData", &pwzData); | ||
| 1764 | ExitOnFailure(hr, "failed to get CustomActionData"); | ||
| 1765 | |||
| 1766 | WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzData); | ||
| 1767 | |||
| 1768 | // | ||
| 1769 | // Read in the CustomActionData | ||
| 1770 | // | ||
| 1771 | pwz = pwzData; | ||
| 1772 | hr = WcaReadStringFromCaData(&pwz, &pwzName); | ||
| 1773 | ExitOnFailure(hr, "failed to read name from custom action data"); | ||
| 1774 | |||
| 1775 | hr = WcaReadStringFromCaData(&pwz, &pwzDomain); | ||
| 1776 | ExitOnFailure(hr, "failed to read domain from custom action data"); | ||
| 1777 | |||
| 1778 | hr = WcaReadStringFromCaData(&pwz, &pwzComment); | ||
| 1779 | ExitOnFailure(hr, "failed to read comment from custom action data"); | ||
| 1780 | |||
| 1781 | hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); | ||
| 1782 | ExitOnFailure(hr, "failed to read attributes from custom action data"); | ||
| 1783 | |||
| 1784 | hr = RemoveGroupInternal(pwz, pwzDomain, pwzName, iAttributes); | ||
| 1785 | |||
| 1786 | LExit: | ||
| 1787 | ReleaseStr(pwzData); | ||
| 1788 | ReleaseStr(pwzName); | ||
| 1789 | ReleaseStr(pwzDomain); | ||
| 1790 | ReleaseStr(pwzComment); | ||
| 1791 | |||
| 1792 | if (fInitializedCom) | ||
| 1793 | { | ||
| 1794 | ::CoUninitialize(); | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | if (FAILED(hr)) | ||
| 1798 | { | ||
| 1799 | er = ERROR_INSTALL_FAILURE; | ||
| 1800 | } | ||
| 1801 | |||
| 1802 | return WcaFinalize(er); | ||
| 1803 | } | ||
