aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBevan Weiss <bevan.weiss@gmail.com>2025-01-03 15:06:15 +1100
committerRob Mensching <rob@firegiant.com>2025-02-11 23:14:49 -0800
commit8f5130afdc60f4957086e41d62cfe9f8d70d5321 (patch)
treeda9f8a9d217eff1484bf78003d52624d1f91433b /src
parentfcae786168ee7c148ac932d725357f9714ad6631 (diff)
downloadwix-8f5130afdc60f4957086e41d62cfe9f8d70d5321.tar.gz
wix-8f5130afdc60f4957086e41d62cfe9f8d70d5321.tar.bz2
wix-8f5130afdc60f4957086e41d62cfe9f8d70d5321.zip
Fix ups for Domain Group creation / removal.
Signed-off-by: Bevan Weiss <bevan.weiss@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/ext/Util/ca/precomp.h1
-rw-r--r--src/ext/Util/ca/scaexec.cpp6
-rw-r--r--src/ext/Util/ca/scagroup.cpp17
-rw-r--r--src/ext/Util/ca/scanet.cpp9
-rw-r--r--src/ext/Util/ca/scanet.h14
-rw-r--r--src/test/burn/WixTestTools/RuntimeFactAttribute.cs4
-rw-r--r--src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionGroupTests.cs6
7 files changed, 45 insertions, 12 deletions
diff --git a/src/ext/Util/ca/precomp.h b/src/ext/Util/ca/precomp.h
index 9456c691..0d7cae18 100644
--- a/src/ext/Util/ca/precomp.h
+++ b/src/ext/Util/ca/precomp.h
@@ -51,5 +51,6 @@
51#include "scasmb.h" 51#include "scasmb.h"
52#include "scasmbexec.h" 52#include "scasmbexec.h"
53#include "utilca.h" 53#include "utilca.h"
54#include "scanet.h"
54 55
55#include "..\..\caDecor.h" 56#include "..\..\caDecor.h"
diff --git a/src/ext/Util/ca/scaexec.cpp b/src/ext/Util/ca/scaexec.cpp
index a2ecdaab..ee3c164f 100644
--- a/src/ext/Util/ca/scaexec.cpp
+++ b/src/ext/Util/ca/scaexec.cpp
@@ -716,7 +716,7 @@ static HRESULT RemoveGroupInternal(
716 // 716 //
717 if (!(SCAG_DONT_CREATE_GROUP & iAttributes)) 717 if (!(SCAG_DONT_CREATE_GROUP & iAttributes))
718 { 718 {
719 hr = GetDomainFromServerName(&pwzServerName, wzDomain, DS_WRITABLE_REQUIRED); 719 hr = GetDomainServerName(wzDomain, &pwzServerName, DS_WRITABLE_REQUIRED);
720 720
721 NET_API_STATUS er = ::NetLocalGroupDel(pwzServerName, wzName); 721 NET_API_STATUS er = ::NetLocalGroupDel(pwzServerName, wzName);
722 hr = HRESULT_FROM_WIN32(er); 722 hr = HRESULT_FROM_WIN32(er);
@@ -1284,7 +1284,7 @@ extern "C" UINT __stdcall CreateGroup(
1284 1284
1285 if (!(SCAG_DONT_CREATE_GROUP & iAttributes)) 1285 if (!(SCAG_DONT_CREATE_GROUP & iAttributes))
1286 { 1286 {
1287 hr = GetDomainFromServerName(&pwzServerName, pwzDomain, DS_WRITABLE_REQUIRED); 1287 hr = GetDomainServerName(pwzDomain, &pwzServerName, DS_WRITABLE_REQUIRED);
1288 ExitOnFailure(hr, "failed to find writable server for domain %ls.", pwzDomain); 1288 ExitOnFailure(hr, "failed to find writable server for domain %ls.", pwzDomain);
1289 1289
1290 // Set the group's comment 1290 // Set the group's comment
@@ -1680,7 +1680,7 @@ HRESULT AlterGroupMembership(BOOL fRemove, BOOL fIsRollback)
1680 } 1680 }
1681 1681
1682 1682
1683 hr = GetDomainFromServerName(&pwzServerName, pwzParentDomain, DS_WRITABLE_REQUIRED); 1683 hr = GetDomainServerName(pwzParentDomain, &pwzServerName, DS_WRITABLE_REQUIRED);
1684 ExitOnFailure(hr, "failed to obtain writable server for domain %ls", pwzParentDomain); 1684 ExitOnFailure(hr, "failed to obtain writable server for domain %ls", pwzParentDomain);
1685 1685
1686 if (*pwzChildDomain) 1686 if (*pwzChildDomain)
diff --git a/src/ext/Util/ca/scagroup.cpp b/src/ext/Util/ca/scagroup.cpp
index bab438ea..666100b0 100644
--- a/src/ext/Util/ca/scagroup.cpp
+++ b/src/ext/Util/ca/scagroup.cpp
@@ -1,7 +1,6 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. 1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 2
3#include "precomp.h" 3#include "precomp.h"
4#include "scanet.h"
5 4
6LPCWSTR vcsGroupQuery = L"SELECT `Group`, `Component_`, `Name`, `Domain` FROM `Wix4Group` WHERE `Group`=?"; 5LPCWSTR vcsGroupQuery = L"SELECT `Group`, `Component_`, `Name`, `Domain` FROM `Wix4Group` WHERE `Group`=?";
7enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain }; 6enum eGroupQuery { vgqGroup = 1, vgqComponent, vgqName, vgqDomain };
@@ -458,7 +457,20 @@ HRESULT ScaGroupExecute(
458 // and removing groups. Note: MSDN says that it is safe to call these APIs from any 457 // and removing groups. Note: MSDN says that it is safe to call these APIs from any
459 // user, so we should be safe calling it during immediate mode. 458 // user, so we should be safe calling it during immediate mode.
460 459
461 hr = GetDomainServerName(psg->wzDomain, &pwzServerName); 460 hr = GetDomainServerName(psg->wzDomain, &pwzServerName, 0);
461 if (HRESULT_FROM_WIN32(ERROR_NO_SUCH_DOMAIN) == hr)
462 {
463 if (SCAG_NON_VITAL & psg->iAttributes)
464 {
465 WcaLog(LOGMSG_VERBOSE, "Domain does not exist for non-vital group: %ls\\%ls - continuing", psg->wzDomain, psg->wzName);
466 hr = S_OK;
467 goto ExitCurrentGroup;
468 }
469 else
470 {
471 ExitOnFailure(hr, "Domain does not exist for vital group: %ls\\%ls - aborting", psg->wzDomain, psg->wzName);
472 }
473 }
462 474
463 er = ::NetLocalGroupGetInfo(pwzServerName, psg->wzName, 0, reinterpret_cast<LPBYTE*>(&pGroupInfo)); 475 er = ::NetLocalGroupGetInfo(pwzServerName, psg->wzName, 0, reinterpret_cast<LPBYTE*>(&pGroupInfo));
464 if (NERR_Success == er) 476 if (NERR_Success == er)
@@ -597,6 +609,7 @@ HRESULT ScaGroupExecute(
597 ExitOnFailure(hr, "failed to schedule RemoveGroup"); 609 ExitOnFailure(hr, "failed to schedule RemoveGroup");
598 } 610 }
599 611
612 ExitCurrentGroup:
600 ReleaseNullStr(pwzScriptKey); 613 ReleaseNullStr(pwzScriptKey);
601 ReleaseNullStr(pwzActionData); 614 ReleaseNullStr(pwzActionData);
602 ReleaseNullStr(pwzRollbackData); 615 ReleaseNullStr(pwzRollbackData);
diff --git a/src/ext/Util/ca/scanet.cpp b/src/ext/Util/ca/scanet.cpp
index a8ad0316..ad6c8b01 100644
--- a/src/ext/Util/ca/scanet.cpp
+++ b/src/ext/Util/ca/scanet.cpp
@@ -8,8 +8,13 @@ HRESULT GetDomainServerName(LPCWSTR pwzDomain, LPWSTR* ppwzServerName, ULONG fla
8 DWORD er = ERROR_SUCCESS; 8 DWORD er = ERROR_SUCCESS;
9 PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; 9 PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL;
10 HRESULT hr = S_OK; 10 HRESULT hr = S_OK;
11 WCHAR pwzComputerName[MAX_COMPUTERNAME_LENGTH + 1];
12 DWORD cchComputerName = countof(pwzComputerName);
11 13
12 if (pwzDomain && *pwzDomain) 14 hr = ::GetComputerNameW(pwzComputerName, &cchComputerName);
15 ExitOnFailure(hr, "failed to obtain computer name");
16
17 if (pwzDomain && *pwzDomain && 0!=lstrcmpiW(pwzComputerName, pwzDomain) && 0!=lstrcmpiW(L".", pwzDomain))
13 { 18 {
14 er = ::DsGetDcNameW(NULL, pwzDomain, NULL, NULL, flags, &pDomainControllerInfo); 19 er = ::DsGetDcNameW(NULL, pwzDomain, NULL, NULL, flags, &pDomainControllerInfo);
15 if (RPC_S_SERVER_UNAVAILABLE == er) 20 if (RPC_S_SERVER_UNAVAILABLE == er)
@@ -21,7 +26,7 @@ HRESULT GetDomainServerName(LPCWSTR pwzDomain, LPWSTR* ppwzServerName, ULONG fla
21 if (ERROR_SUCCESS == er && pDomainControllerInfo->DomainControllerName) 26 if (ERROR_SUCCESS == er && pDomainControllerInfo->DomainControllerName)
22 { 27 {
23 // Skip the \\ prefix if present. 28 // Skip the \\ prefix if present.
24 if ('\\' == *pDomainControllerInfo->DomainControllerName && '\\' == *pDomainControllerInfo->DomainControllerName + 1) 29 if ('\\' == *pDomainControllerInfo->DomainControllerName && '\\' == *(pDomainControllerInfo->DomainControllerName + 1) )
25 { 30 {
26 hr = StrAllocString(ppwzServerName, pDomainControllerInfo->DomainControllerName + 2, 0); 31 hr = StrAllocString(ppwzServerName, pDomainControllerInfo->DomainControllerName + 2, 0);
27 } 32 }
diff --git a/src/ext/Util/ca/scanet.h b/src/ext/Util/ca/scanet.h
index 1fee61f8..efe6a408 100644
--- a/src/ext/Util/ca/scanet.h
+++ b/src/ext/Util/ca/scanet.h
@@ -1,4 +1,16 @@
1#pragma once 1#pragma once
2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. 2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3 3
4HRESULT GetDomainServerName(LPCWSTR pwzDomain, LPWSTR* ppwzServerName, ULONG flags = 0); 4
5/**
6 * Locates a domain controller (server name) for a given input domain.
7 * Flags can be provided where required (as per those for DsGetDcName) for a specific server to be returned.
8 * NOTE: Where the domain provided is identical to the local machine, this function will return NULL, such that the
9 * result can be provided directly to NetUserAdd or similar functions.
10 *
11 * @param pwzDomain Pointer to the domain name to be queried
12 * @param ppwzServerName Pointer to the server name to be returned
13 * @param flags Flags to be used in the DsGetDcName call(s)
14 * @return HRESULT to indicate if an error was encountered
15 */
16HRESULT GetDomainServerName(LPCWSTR pwzDomain, LPWSTR* ppwzServerName, ULONG flags);
diff --git a/src/test/burn/WixTestTools/RuntimeFactAttribute.cs b/src/test/burn/WixTestTools/RuntimeFactAttribute.cs
index d7f56f70..2644a1cc 100644
--- a/src/test/burn/WixTestTools/RuntimeFactAttribute.cs
+++ b/src/test/burn/WixTestTools/RuntimeFactAttribute.cs
@@ -47,6 +47,8 @@ namespace WixTestTools
47 47
48 var domainTestsEnabledString = Environment.GetEnvironmentVariable(RequiredDomainEnvironmentVariableName); 48 var domainTestsEnabledString = Environment.GetEnvironmentVariable(RequiredDomainEnvironmentVariableName);
49 RuntimeDomainTestsEnabled = Boolean.TryParse(domainTestsEnabledString, out var domainTestsEnabled) && domainTestsEnabled; 49 RuntimeDomainTestsEnabled = Boolean.TryParse(domainTestsEnabledString, out var domainTestsEnabled) && domainTestsEnabled;
50
51 RunningOnWindowsServer = IsWindowsServer();
50 } 52 }
51 53
52 public bool DomainRequired 54 public bool DomainRequired
@@ -63,8 +65,6 @@ namespace WixTestTools
63 this.Skip = $"These tests require the test host to be running as a domain member ({(RunningInDomain ? "passed" : "failed")}). These tests affect both MACHINE AND DOMAIN state. To accept the consequences, set the {RequiredDomainEnvironmentVariableName} environment variable to true ({(RuntimeDomainTestsEnabled ? "passed" : "failed")})."; 65 this.Skip = $"These tests require the test host to be running as a domain member ({(RunningInDomain ? "passed" : "failed")}). These tests affect both MACHINE AND DOMAIN state. To accept the consequences, set the {RequiredDomainEnvironmentVariableName} environment variable to true ({(RuntimeDomainTestsEnabled ? "passed" : "failed")}).";
64 } 66 }
65 } 67 }
66
67 RunningOnWindowsServer = IsWindowsServer();
68 } 68 }
69 69
70 private bool _RequireWindowsServer; 70 private bool _RequireWindowsServer;
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionGroupTests.cs b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionGroupTests.cs
index cee357a6..e379047d 100644
--- a/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionGroupTests.cs
+++ b/src/test/msi/WixToolsetTest.MsiE2E/UtilExtensionGroupTests.cs
@@ -151,12 +151,14 @@ namespace WixToolsetTest.MsiE2E
151 [RuntimeFact] 151 [RuntimeFact]
152 public void FailsIfRestrictedDomain() 152 public void FailsIfRestrictedDomain()
153 { 153 {
154 var testDomain = "DOESNOTEXIST";
155 var testGroup = "testName1";
154 var productRestrictedDomain = this.CreatePackageInstaller("ProductRestrictedDomain"); 156 var productRestrictedDomain = this.CreatePackageInstaller("ProductRestrictedDomain");
155 157
156 string logFile = productRestrictedDomain.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, "TESTDOMAIN=DOESNOTEXIST"); 158 string logFile = productRestrictedDomain.InstallProduct(MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, $"TESTDOMAIN={testDomain}");
157 159
158 // Verify expected error message in the log file 160 // Verify expected error message in the log file
159 Assert.True(LogVerifier.MessageInLogFile(logFile, "CreateGroup: Error 0x8007054b: failed to find Domain DOESNOTEXIST.")); 161 Assert.True(LogVerifier.MessageInLogFile(logFile, $"ConfigureGroups: Error 0x8007054b: Domain does not exist for vital group: {testDomain}\\{testGroup} - aborting"));
160 } 162 }
161 163
162 // Verify that a group can be created with a group comment 164 // Verify that a group can be created with a group comment