summaryrefslogtreecommitdiff
path: root/src/ext/Util/ca/scaexec.cpp
diff options
context:
space:
mode:
authorBevan Weiss <bevan.weiss@gmail.com>2024-06-18 19:03:40 +1000
committerRob Mensching <rob@firegiant.com>2025-02-11 23:14:49 -0800
commit7b1bb025dea1d1e9e144cce0dcbba2d86f053b8f (patch)
treec2fc969615d858ee40f54cfba406648e9c2743c3 /src/ext/Util/ca/scaexec.cpp
parent040e50ec2859c1de70cd8e9f957474321774f293 (diff)
downloadwix-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.cpp628
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
294static 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
351LExit:
352 ReleaseStr(pwzServerName);
353 ReleaseStr(pwzMember);
354 ReleaseBSTR(bstrMember);
355 ReleaseBSTR(bstrGroup);
356 ReleaseObject(pGroup);
357
358 return hr;
359}
360
361static 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
424LExit:
425 ReleaseStr(pwzServerName);
426 ReleaseStr(pwzMember);
427 ReleaseBSTR(bstrMember);
428 ReleaseBSTR(bstrGroup);
429 ReleaseObject(pGroup);
430
431 return hr;
432}
294 433
295static HRESULT GetUserHasRight( 434static 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
732static 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
593static HRESULT SetUserFlags(__in LPWSTR pwzServerName, __in LPWSTR pwzName, __in DWORD flags) 741static 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
844static 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 }
905LExit:
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 * *****************************************************************/
1400extern "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
1576LExit:
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 * *****************************************************************/
1614extern "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
1709LExit:
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 * *****************************************************************/
1739extern "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
1786LExit:
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}