aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-06-03 17:50:22 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-06-07 19:44:36 -0500
commit8810aa8908ed7887616d86dd5fb821fcfa92f444 (patch)
tree8bc05667c36cc0d3db73504c867e85b01f1a79b0
parent266b097c0b0a13dd4934f55f61cad62ffcbb953d (diff)
downloadwix-8810aa8908ed7887616d86dd5fb821fcfa92f444.tar.gz
wix-8810aa8908ed7887616d86dd5fb821fcfa92f444.tar.bz2
wix-8810aa8908ed7887616d86dd5fb821fcfa92f444.zip
Update Burn algorithm for picking elevated temp path to use SystemTemp.
-rw-r--r--src/api/burn/balutil/inc/balutil.h2
-rw-r--r--src/api/burn/bextutil/inc/bextutil.h2
-rw-r--r--src/burn/engine/cache.cpp19
-rw-r--r--src/burn/engine/precomp.h1
-rw-r--r--src/burn/stub/stub.vcxproj4
-rw-r--r--src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj2
-rw-r--r--src/burn/test/BurnUnitTest/CacheTest.cpp2
-rw-r--r--src/libs/dutil/WixToolset.DUtil/dutil.vcxproj2
-rw-r--r--src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters6
-rw-r--r--src/libs/dutil/WixToolset.DUtil/env2util.cpp80
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/envutil.h11
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/pathutil.h9
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/polcutil.h14
-rw-r--r--src/libs/dutil/WixToolset.DUtil/inc/procutil.h10
-rw-r--r--src/libs/dutil/WixToolset.DUtil/path2utl.cpp38
-rw-r--r--src/libs/dutil/WixToolset.DUtil/path3utl.cpp143
-rw-r--r--src/libs/dutil/WixToolset.DUtil/pathutil.cpp80
-rw-r--r--src/libs/dutil/WixToolset.DUtil/polcutil.cpp43
-rw-r--r--src/libs/dutil/WixToolset.DUtil/procutil.cpp68
-rw-r--r--src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj3
-rw-r--r--src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters3
-rw-r--r--src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp45
-rw-r--r--src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp42
-rw-r--r--src/libs/dutil/test/DUtilUnitTest/precomp.h2
-rw-r--r--src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp30
-rw-r--r--src/test/burn/TestData/Manual/BafThmutilTesting/precomp.h3
26 files changed, 577 insertions, 87 deletions
diff --git a/src/api/burn/balutil/inc/balutil.h b/src/api/burn/balutil/inc/balutil.h
index 33f1a6de..3040cfe8 100644
--- a/src/api/burn/balutil/inc/balutil.h
+++ b/src/api/burn/balutil/inc/balutil.h
@@ -16,6 +16,7 @@ extern "C" {
16#define BalExitOnNullSource(d, p, x, e, f, ...) if (NULL == p) { x = e; BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; } 16#define BalExitOnNullSource(d, p, x, e, f, ...) if (NULL == p) { x = e; BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
17#define BalExitOnNullWithLastErrorSource(d, p, x, f, ...) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; } 17#define BalExitOnNullWithLastErrorSource(d, p, x, f, ...) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
18#define BalExitWithLastErrorSource(d, x, f, ...) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; } 18#define BalExitWithLastErrorSource(d, x, f, ...) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BalLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
19#define BalExitOnWin32ErrorSource(d, e, x, f, ...) if (ERROR_SUCCESS != e) { x = HRESULT_FROM_WIN32(e); if (!FAILED(x)) { x = E_FAIL; } BalLogError(x, f, __VA_ARGS__); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
19#define BalExitOnOptionalXmlQueryFailureSource(d, x, b, f, ...) { { if (S_FALSE == x || E_NOTFOUND == x) { b = FALSE; x = S_OK; } else { b = SUCCEEDED(x); } }; BalExitOnRootFailureSource(d, x, f, __VA_ARGS__); } 20#define BalExitOnOptionalXmlQueryFailureSource(d, x, b, f, ...) { { if (S_FALSE == x || E_NOTFOUND == x) { b = FALSE; x = S_OK; } else { b = SUCCEEDED(x); } }; BalExitOnRootFailureSource(d, x, f, __VA_ARGS__); }
20#define BalExitOnRequiredXmlQueryFailureSource(d, x, f, ...) { if (S_FALSE == x) { x = E_NOTFOUND; } BalExitOnRootFailureSource(d, x, f, __VA_ARGS__); } 21#define BalExitOnRequiredXmlQueryFailureSource(d, x, f, ...) { if (S_FALSE == x) { x = E_NOTFOUND; } BalExitOnRootFailureSource(d, x, f, __VA_ARGS__); }
21 22
@@ -26,6 +27,7 @@ extern "C" {
26#define BalExitOnNull(p, x, e, f, ...) BalExitOnNullSource(DUTIL_SOURCE_DEFAULT, p, x, e, f, __VA_ARGS__) 27#define BalExitOnNull(p, x, e, f, ...) BalExitOnNullSource(DUTIL_SOURCE_DEFAULT, p, x, e, f, __VA_ARGS__)
27#define BalExitOnNullWithLastError(p, x, f, ...) BalExitOnNullWithLastErrorSource(DUTIL_SOURCE_DEFAULT, p, x, f, __VA_ARGS__) 28#define BalExitOnNullWithLastError(p, x, f, ...) BalExitOnNullWithLastErrorSource(DUTIL_SOURCE_DEFAULT, p, x, f, __VA_ARGS__)
28#define BalExitWithLastError(x, f, ...) BalExitWithLastErrorSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__) 29#define BalExitWithLastError(x, f, ...) BalExitWithLastErrorSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
30#define BalExitOnWin32Error(e, x, f, ...) BalExitOnWin32ErrorSource(DUTIL_SOURCE_DEFAULT, e, x, f, __VA_ARGS__)
29#define BalExitOnOptionalXmlQueryFailure(x, b, f, ...) BalExitOnOptionalXmlQueryFailureSource(DUTIL_SOURCE_DEFAULT, x, b, f, __VA_ARGS__) 31#define BalExitOnOptionalXmlQueryFailure(x, b, f, ...) BalExitOnOptionalXmlQueryFailureSource(DUTIL_SOURCE_DEFAULT, x, b, f, __VA_ARGS__)
30#define BalExitOnRequiredXmlQueryFailure(x, f, ...) BalExitOnRequiredXmlQueryFailureSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__) 32#define BalExitOnRequiredXmlQueryFailure(x, f, ...) BalExitOnRequiredXmlQueryFailureSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
31 33
diff --git a/src/api/burn/bextutil/inc/bextutil.h b/src/api/burn/bextutil/inc/bextutil.h
index e3edff01..356ccc47 100644
--- a/src/api/burn/bextutil/inc/bextutil.h
+++ b/src/api/burn/bextutil/inc/bextutil.h
@@ -16,6 +16,7 @@ extern "C" {
16#define BextExitOnNullSource(d, p, x, e, f, ...) if (NULL == p) { x = e; BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; } 16#define BextExitOnNullSource(d, p, x, e, f, ...) if (NULL == p) { x = e; BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
17#define BextExitOnNullWithLastErrorSource(d, p, x, f, ...) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; } 17#define BextExitOnNullWithLastErrorSource(d, p, x, f, ...) if (NULL == p) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
18#define BextExitWithLastErrorSource(d, x, f, ...) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; } 18#define BextExitWithLastErrorSource(d, x, f, ...) { DWORD Dutil_er = ::GetLastError(); x = HRESULT_FROM_WIN32(Dutil_er); if (!FAILED(x)) { x = E_FAIL; } BextLogError(x, f, __VA_ARGS__); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
19#define BextExitOnWin32ErrorSource(d, e, x, f, ...) if (ERROR_SUCCESS != e) { x = HRESULT_FROM_WIN32(e); if (!FAILED(x)) { x = E_FAIL; } BextLogError(x, f, __VA_ARGS__); Dutil_RootFailure(__FILE__, __LINE__, x); ExitTraceSource(d, x, f, __VA_ARGS__); goto LExit; }
19#define BextExitOnOptionalXmlQueryFailureSource(d, x, b, f, ...) { { if (S_FALSE == x || E_NOTFOUND == x) { b = FALSE; x = S_OK; } else { b = SUCCEEDED(x); } }; BextExitOnRootFailureSource(d, x, f, __VA_ARGS__); } 20#define BextExitOnOptionalXmlQueryFailureSource(d, x, b, f, ...) { { if (S_FALSE == x || E_NOTFOUND == x) { b = FALSE; x = S_OK; } else { b = SUCCEEDED(x); } }; BextExitOnRootFailureSource(d, x, f, __VA_ARGS__); }
20#define BextExitOnRequiredXmlQueryFailureSource(d, x, f, ...) { if (S_FALSE == x) { x = E_NOTFOUND; } BextExitOnRootFailureSource(d, x, f, __VA_ARGS__); } 21#define BextExitOnRequiredXmlQueryFailureSource(d, x, f, ...) { if (S_FALSE == x) { x = E_NOTFOUND; } BextExitOnRootFailureSource(d, x, f, __VA_ARGS__); }
21 22
@@ -26,6 +27,7 @@ extern "C" {
26#define BextExitOnNull(p, x, e, f, ...) BextExitOnNullSource(DUTIL_SOURCE_DEFAULT, p, x, e, f, __VA_ARGS__) 27#define BextExitOnNull(p, x, e, f, ...) BextExitOnNullSource(DUTIL_SOURCE_DEFAULT, p, x, e, f, __VA_ARGS__)
27#define BextExitOnNullWithLastError(p, x, f, ...) BextExitOnNullWithLastErrorSource(DUTIL_SOURCE_DEFAULT, p, x, f, __VA_ARGS__) 28#define BextExitOnNullWithLastError(p, x, f, ...) BextExitOnNullWithLastErrorSource(DUTIL_SOURCE_DEFAULT, p, x, f, __VA_ARGS__)
28#define BextExitWithLastError(x, f, ...) BextExitWithLastErrorSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__) 29#define BextExitWithLastError(x, f, ...) BextExitWithLastErrorSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
30#define BextExitOnWin32Error(e, x, f, ...) BextExitOnWin32ErrorSource(DUTIL_SOURCE_DEFAULT, e, x, f, __VA_ARGS__)
29#define BextExitOnOptionalXmlQueryFailure(x, b, f, ...) BextExitOnOptionalXmlQueryFailureSource(DUTIL_SOURCE_DEFAULT, x, b, f, __VA_ARGS__) 31#define BextExitOnOptionalXmlQueryFailure(x, b, f, ...) BextExitOnOptionalXmlQueryFailureSource(DUTIL_SOURCE_DEFAULT, x, b, f, __VA_ARGS__)
30#define BextExitOnRequiredXmlQueryFailure(x, f, ...) BextExitOnRequiredXmlQueryFailureSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__) 32#define BextExitOnRequiredXmlQueryFailure(x, f, ...) BextExitOnRequiredXmlQueryFailureSource(DUTIL_SOURCE_DEFAULT, x, f, __VA_ARGS__)
31 33
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp
index 7fca8cc7..5eacb20d 100644
--- a/src/burn/engine/cache.cpp
+++ b/src/burn/engine/cache.cpp
@@ -1389,6 +1389,8 @@ static HRESULT CalculatePotentialBaseWorkingFolders(
1389 Assert(!pCache->rgsczPotentialBaseWorkingFolders && !pCache->cPotentialBaseWorkingFolders); 1389 Assert(!pCache->rgsczPotentialBaseWorkingFolders && !pCache->cPotentialBaseWorkingFolders);
1390 HRESULT hr = S_OK; 1390 HRESULT hr = S_OK;
1391 LPWSTR sczTemp = NULL; 1391 LPWSTR sczTemp = NULL;
1392 LPWSTR sczPolicy = NULL;
1393 BOOL fNeedsExpansion = FALSE;
1392 1394
1393 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pCache->rgsczPotentialBaseWorkingFolders), 6, sizeof(LPWSTR), 6); 1395 hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pCache->rgsczPotentialBaseWorkingFolders), 6, sizeof(LPWSTR), 6);
1394 ExitOnFailure(hr, "Failed to initialize array."); 1396 ExitOnFailure(hr, "Failed to initialize array.");
@@ -1408,12 +1410,22 @@ static HRESULT CalculatePotentialBaseWorkingFolders(
1408 // but only use it if elevated because it should be secured against non-admin users. 1410 // but only use it if elevated because it should be secured against non-admin users.
1409 if (pInternalCommand->fInitiallyElevated) 1411 if (pInternalCommand->fInitiallyElevated)
1410 { 1412 {
1411 hr = PolcReadString(POLICY_BURN_REGISTRY_PATH, L"EngineWorkingDirectory", NULL, &sczTemp); 1413 hr = PolcReadUnexpandedString(POLICY_BURN_REGISTRY_PATH, L"EngineWorkingDirectory", NULL, &fNeedsExpansion, &sczPolicy);
1412 ExitOnFailure(hr, "Failed to read EngineWorkingDirectory policy directory."); 1414 ExitOnFailure(hr, "Failed to read EngineWorkingDirectory policy directory.");
1413 1415
1414 if (sczTemp) 1416 if (S_FALSE != hr)
1415 { 1417 {
1416 // PolcReadString is supposed to automatically expand REG_EXPAND_SZ values. 1418 if (fNeedsExpansion)
1419 {
1420 hr = EnvExpandEnvironmentStringsForUser(NULL, sczPolicy, &sczTemp, NULL);
1421 ExitOnFailure(hr, "Failed to expand EngineWorkingDirectory policy directory.");
1422 }
1423 else
1424 {
1425 sczTemp = sczPolicy;
1426 sczPolicy = NULL;
1427 }
1428
1417 pCache->rgsczPotentialBaseWorkingFolders[pCache->cPotentialBaseWorkingFolders] = sczTemp; 1429 pCache->rgsczPotentialBaseWorkingFolders[pCache->cPotentialBaseWorkingFolders] = sczTemp;
1418 sczTemp = NULL; 1430 sczTemp = NULL;
1419 ++pCache->cPotentialBaseWorkingFolders; 1431 ++pCache->cPotentialBaseWorkingFolders;
@@ -1438,6 +1450,7 @@ static HRESULT CalculatePotentialBaseWorkingFolders(
1438 1450
1439LExit: 1451LExit:
1440 ReleaseStr(sczTemp); 1452 ReleaseStr(sczTemp);
1453 ReleaseStr(sczPolicy);
1441 1454
1442 return hr; 1455 return hr;
1443} 1456}
diff --git a/src/burn/engine/precomp.h b/src/burn/engine/precomp.h
index 19a6d48b..bc7046f6 100644
--- a/src/burn/engine/precomp.h
+++ b/src/burn/engine/precomp.h
@@ -31,6 +31,7 @@
31#include <certutil.h> 31#include <certutil.h>
32#include <cryputil.h> 32#include <cryputil.h>
33#include <dirutil.h> 33#include <dirutil.h>
34#include <envutil.h>
34#include <fileutil.h> 35#include <fileutil.h>
35#include <guidutil.h> 36#include <guidutil.h>
36#include <logutil.h> 37#include <logutil.h>
diff --git a/src/burn/stub/stub.vcxproj b/src/burn/stub/stub.vcxproj
index d73b9f49..0a2e1cae 100644
--- a/src/burn/stub/stub.vcxproj
+++ b/src/burn/stub/stub.vcxproj
@@ -55,14 +55,14 @@
55 55
56 <PropertyGroup> 56 <PropertyGroup>
57 <ProjectAdditionalIncludeDirectories>$(ProjectDir)..\engine\inc</ProjectAdditionalIncludeDirectories> 57 <ProjectAdditionalIncludeDirectories>$(ProjectDir)..\engine\inc</ProjectAdditionalIncludeDirectories>
58 <ProjectAdditionalLinkLibraries>cabinet.lib;crypt32.lib;msi.lib;rpcrt4.lib;shlwapi.lib;wininet.lib;wintrust.lib;wuguid.lib;engine.res</ProjectAdditionalLinkLibraries> 58 <ProjectAdditionalLinkLibraries>cabinet.lib;crypt32.lib;msi.lib;rpcrt4.lib;shlwapi.lib;userenv.lib;wininet.lib;wintrust.lib;wuguid.lib;engine.res</ProjectAdditionalLinkLibraries>
59 </PropertyGroup> 59 </PropertyGroup>
60 60
61 <ItemDefinitionGroup> 61 <ItemDefinitionGroup>
62 <Link> 62 <Link>
63 <SwapRunFromCD>true</SwapRunFromCD> 63 <SwapRunFromCD>true</SwapRunFromCD>
64 <SwapRunFromNET>true</SwapRunFromNET> 64 <SwapRunFromNET>true</SwapRunFromNET>
65 <DelayLoadDLLs>cabinet.dll;crypt32.dll;msi.dll;shlwapi.dll;version.dll;wininet.dll;wintrust.dll</DelayLoadDLLs> 65 <DelayLoadDLLs>cabinet.dll;crypt32.dll;msi.dll;shlwapi.dll;userenv.dll;version.dll;wininet.dll;wintrust.dll</DelayLoadDLLs>
66 </Link> 66 </Link>
67 </ItemDefinitionGroup> 67 </ItemDefinitionGroup>
68 68
diff --git a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
index b05666b2..e1a28712 100644
--- a/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
+++ b/src/burn/test/BurnUnitTest/BurnUnitTest.vcxproj
@@ -40,7 +40,7 @@
40 40
41 <PropertyGroup> 41 <PropertyGroup>
42 <ProjectAdditionalIncludeDirectories>$(ProjectAdditionalIncludeDirectories);$(BurnGeneratedHeaderDirectory);..\..\engine;..\..\..\api\burn\WixToolset.BootstrapperCore.Native\inc;..\..\..\libs\dutil\WixToolset.Dutil\inc</ProjectAdditionalIncludeDirectories> 42 <ProjectAdditionalIncludeDirectories>$(ProjectAdditionalIncludeDirectories);$(BurnGeneratedHeaderDirectory);..\..\engine;..\..\..\api\burn\WixToolset.BootstrapperCore.Native\inc;..\..\..\libs\dutil\WixToolset.Dutil\inc</ProjectAdditionalIncludeDirectories>
43 <ProjectAdditionalLinkLibraries>cabinet.lib;crypt32.lib;msi.lib;rpcrt4.lib;shlwapi.lib;wininet.lib;wintrust.lib;$(RootBuildFolder)libs\$(Configuration)\$(WixNativeSdkLibraryToolset)\$(PlatformTarget)\dutil.lib;engine.res</ProjectAdditionalLinkLibraries> 43 <ProjectAdditionalLinkLibraries>cabinet.lib;crypt32.lib;msi.lib;rpcrt4.lib;shlwapi.lib;userenv.lib;wininet.lib;wintrust.lib;$(RootBuildFolder)libs\$(Configuration)\$(WixNativeSdkLibraryToolset)\$(PlatformTarget)\dutil.lib;engine.res</ProjectAdditionalLinkLibraries>
44 </PropertyGroup> 44 </PropertyGroup>
45 45
46 <ItemGroup> 46 <ItemGroup>
diff --git a/src/burn/test/BurnUnitTest/CacheTest.cpp b/src/burn/test/BurnUnitTest/CacheTest.cpp
index eb0b31ab..2bec05fe 100644
--- a/src/burn/test/BurnUnitTest/CacheTest.cpp
+++ b/src/burn/test/BurnUnitTest/CacheTest.cpp
@@ -92,6 +92,8 @@ namespace Bootstrapper
92 VerifyBaseWorkingFolder(L"B:\\TEST\\TMP\\", cache.rgsczPotentialBaseWorkingFolders[0]); 92 VerifyBaseWorkingFolder(L"B:\\TEST\\TMP\\", cache.rgsczPotentialBaseWorkingFolders[0]);
93 CacheUninitialize(&cache); 93 CacheUninitialize(&cache);
94 94
95 // First fallback is impractical to mock out - %windir%\SystemTemp on Win11 when running as SYSTEM.
96
95 hr = RegCreate(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Policies\\WiX\\Burn", GENERIC_WRITE, &hkBurnPolicy); 97 hr = RegCreate(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Policies\\WiX\\Burn", GENERIC_WRITE, &hkBurnPolicy);
96 NativeAssert::Succeeded(hr, "Failed to create Burn policy key."); 98 NativeAssert::Succeeded(hr, "Failed to create Burn policy key.");
97 99
diff --git a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj
index 9d057461..3100768d 100644
--- a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj
+++ b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj
@@ -65,6 +65,7 @@
65 <PrecompiledHeader>Create</PrecompiledHeader> 65 <PrecompiledHeader>Create</PrecompiledHeader>
66 <DisableSpecificWarnings>4091;4458</DisableSpecificWarnings> 66 <DisableSpecificWarnings>4091;4458</DisableSpecificWarnings>
67 </ClCompile> 67 </ClCompile>
68 <ClCompile Include="env2util.cpp" />
68 <ClCompile Include="envutil.cpp" /> 69 <ClCompile Include="envutil.cpp" />
69 <ClCompile Include="eseutil.cpp" /> 70 <ClCompile Include="eseutil.cpp" />
70 <ClCompile Include="file2utl.cpp" /> 71 <ClCompile Include="file2utl.cpp" />
@@ -82,6 +83,7 @@
82 <ClCompile Include="monutil.cpp" /> 83 <ClCompile Include="monutil.cpp" />
83 <ClCompile Include="osutil.cpp" /> 84 <ClCompile Include="osutil.cpp" />
84 <ClCompile Include="path2utl.cpp" /> 85 <ClCompile Include="path2utl.cpp" />
86 <ClCompile Include="path3utl.cpp" />
85 <ClCompile Include="pathutil.cpp" /> 87 <ClCompile Include="pathutil.cpp" />
86 <ClCompile Include="perfutil.cpp" /> 88 <ClCompile Include="perfutil.cpp" />
87 <ClCompile Include="polcutil.cpp" /> 89 <ClCompile Include="polcutil.cpp" />
diff --git a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters
index 556468b7..c966c965 100644
--- a/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters
+++ b/src/libs/dutil/WixToolset.DUtil/dutil.vcxproj.filters
@@ -66,6 +66,9 @@
66 <ClCompile Include="dutil.cpp"> 66 <ClCompile Include="dutil.cpp">
67 <Filter>Source Files</Filter> 67 <Filter>Source Files</Filter>
68 </ClCompile> 68 </ClCompile>
69 <ClCompile Include="env2util.cpp">
70 <Filter>Source Files</Filter>
71 </ClCompile>
69 <ClCompile Include="envutil.cpp"> 72 <ClCompile Include="envutil.cpp">
70 <Filter>Source Files</Filter> 73 <Filter>Source Files</Filter>
71 </ClCompile> 74 </ClCompile>
@@ -111,6 +114,9 @@
111 <ClCompile Include="osutil.cpp"> 114 <ClCompile Include="osutil.cpp">
112 <Filter>Source Files</Filter> 115 <Filter>Source Files</Filter>
113 </ClCompile> 116 </ClCompile>
117 <ClCompile Include="path3utl.cpp">
118 <Filter>Source Files</Filter>
119 </ClCompile>
114 <ClCompile Include="path2utl.cpp"> 120 <ClCompile Include="path2utl.cpp">
115 <Filter>Source Files</Filter> 121 <Filter>Source Files</Filter>
116 </ClCompile> 122 </ClCompile>
diff --git a/src/libs/dutil/WixToolset.DUtil/env2util.cpp b/src/libs/dutil/WixToolset.DUtil/env2util.cpp
new file mode 100644
index 00000000..21bbd101
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/env2util.cpp
@@ -0,0 +1,80 @@
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
3#include "precomp.h"
4
5
6// Exit macros
7#define EnvExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
8#define EnvExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
9#define EnvExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
10#define EnvExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
11#define EnvExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
12#define EnvExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_ENVUTIL, x, e, s, __VA_ARGS__)
13#define EnvExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_ENVUTIL, x, s, __VA_ARGS__)
14#define EnvExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_ENVUTIL, p, x, e, s, __VA_ARGS__)
15#define EnvExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_ENVUTIL, p, x, s, __VA_ARGS__)
16#define EnvExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_ENVUTIL, p, x, e, s, __VA_ARGS__)
17#define EnvExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_ENVUTIL, p, x, s, __VA_ARGS__)
18#define EnvExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_ENVUTIL, e, x, s, __VA_ARGS__)
19#define EnvExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_ENVUTIL, g, x, s, __VA_ARGS__)
20
21#define ENV2_GOOD_ENOUGH 64
22
23DAPI_(HRESULT) EnvExpandEnvironmentStringsForUser(
24 __in_opt HANDLE hToken,
25 __in LPCWSTR wzSource,
26 __out LPWSTR* psczExpanded,
27 __out_opt SIZE_T* pcchExpanded
28 )
29{
30 HRESULT hr = S_OK;
31 DWORD cchExpanded = 0;
32 SIZE_T cchMax = 0;
33 const DWORD dwMaxAttempts = 20;
34
35 if (*psczExpanded)
36 {
37 hr = StrMaxLength(*psczExpanded, &cchMax);
38 EnvExitOnFailure(hr, "Failed to get max length of input buffer.");
39
40 cchExpanded = (DWORD)min(DWORD_MAX, cchMax);
41 }
42 else
43 {
44 cchExpanded = ENV2_GOOD_ENOUGH;
45
46 hr = StrAlloc(psczExpanded, cchExpanded);
47 EnvExitOnFailure(hr, "Failed to allocate space for expanded path.");
48 }
49
50 for (DWORD i = 0; i < dwMaxAttempts; ++i)
51 {
52 if (::ExpandEnvironmentStringsForUserW(hToken, wzSource, *psczExpanded, cchExpanded))
53 {
54 break;
55 }
56
57 hr = HRESULT_FROM_WIN32(::GetLastError());
58 if (E_INSUFFICIENT_BUFFER != hr || (dwMaxAttempts - 1) == i)
59 {
60 EnvExitWithRootFailure(hr, hr, "Failed to expand environment variables in string: %ls", wzSource);
61 }
62
63 cchExpanded *= 2;
64
65 hr = StrAlloc(psczExpanded, cchExpanded);
66 EnvExitOnFailure(hr, "Failed to re-allocate more space for expanded path.");
67 }
68
69 if (pcchExpanded)
70 {
71 hr = ::StringCchLengthW(*psczExpanded, STRSAFE_MAX_LENGTH, reinterpret_cast<size_t*>(pcchExpanded));
72 EnvExitOnFailure(hr, "Failed to get max length of written input buffer.");
73
74 // Add 1 for null terminator.
75 *pcchExpanded += 1;
76 }
77
78LExit:
79 return hr;
80}
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/envutil.h b/src/libs/dutil/WixToolset.DUtil/inc/envutil.h
index 8491b27b..4e4f6197 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/envutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/envutil.h
@@ -16,6 +16,17 @@ HRESULT DAPI EnvExpandEnvironmentStrings(
16 __out_opt SIZE_T* pcchExpanded 16 __out_opt SIZE_T* pcchExpanded
17 ); 17 );
18 18
19/********************************************************************
20 EnvExpandEnvironmentStringsForUser - Wrapper for ::ExpandEnvironmentStringsForUser.
21
22 *******************************************************************/
23HRESULT DAPI EnvExpandEnvironmentStringsForUser(
24 __in_opt HANDLE hToken,
25 __in LPCWSTR wzSource,
26 __out LPWSTR* psczExpanded,
27 __out_opt SIZE_T* pcchExpanded
28 );
29
19#ifdef __cplusplus 30#ifdef __cplusplus
20} 31}
21#endif 32#endif
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
index 875cfafb..f36e6ebc 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h
@@ -205,6 +205,15 @@ DAPI_(HRESULT) PathGetTempPath(
205 ); 205 );
206 206
207/******************************************************************* 207/*******************************************************************
208 PathSystemWindowsSubdirectory - returns the path to the Windows folder
209 or a subdirectory of that folder that is backslash terminated.
210*******************************************************************/
211DAPI_(HRESULT) PathSystemWindowsSubdirectory(
212 __in_z_opt LPCWSTR wzSubdirectory,
213 __out_z LPWSTR* psczFullPath
214 );
215
216/*******************************************************************
208 PathGetSystemTempPaths - returns the paths to system temp folders 217 PathGetSystemTempPaths - returns the paths to system temp folders
209 that are backslash terminated with higher preference first. 218 that are backslash terminated with higher preference first.
210*******************************************************************/ 219*******************************************************************/
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/polcutil.h b/src/libs/dutil/WixToolset.DUtil/inc/polcutil.h
index 13618043..7c873b80 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/polcutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/polcutil.h
@@ -34,6 +34,20 @@ HRESULT DAPI PolcReadString(
34 __deref_out_z LPWSTR* pscz 34 __deref_out_z LPWSTR* pscz
35 ); 35 );
36 36
37/********************************************************************
38PolcReadUnexpandedString - reads a string from policy, without expanding it.
39
40NOTE: S_FALSE returned if policy not set.
41NOTE: out is set to default on S_FALSE or any error.
42********************************************************************/
43HRESULT DAPI PolcReadUnexpandedString(
44 __in_z LPCWSTR wzPolicyPath,
45 __in_z LPCWSTR wzPolicyName,
46 __in_z_opt LPCWSTR wzDefault,
47 __inout BOOL* pfNeedsExpansion,
48 __deref_out_z LPWSTR* pscz
49 );
50
37#ifdef __cplusplus 51#ifdef __cplusplus
38} 52}
39#endif 53#endif
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/procutil.h b/src/libs/dutil/WixToolset.DUtil/inc/procutil.h
index 4f49313b..d5ab9242 100644
--- a/src/libs/dutil/WixToolset.DUtil/inc/procutil.h
+++ b/src/libs/dutil/WixToolset.DUtil/inc/procutil.h
@@ -18,6 +18,16 @@ HRESULT DAPI ProcElevated(
18 __out BOOL* pfElevated 18 __out BOOL* pfElevated
19 ); 19 );
20 20
21HRESULT DAPI ProcSystem(
22 __in HANDLE hProcess,
23 __out BOOL* pfSystem
24 );
25
26HRESULT DAPI ProcTokenUser(
27 __in HANDLE hProcess,
28 __out TOKEN_USER** ppTokenUser
29 );
30
21HRESULT DAPI ProcWow64( 31HRESULT DAPI ProcWow64(
22 __in HANDLE hProcess, 32 __in HANDLE hProcess,
23 __out BOOL* pfWow64 33 __out BOOL* pfWow64
diff --git a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
index 9e48f9d5..c6ff608c 100644
--- a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp
@@ -246,3 +246,41 @@ LExit:
246 ReleaseStr(sczCanonicalizedDirectory); 246 ReleaseStr(sczCanonicalizedDirectory);
247 return hr; 247 return hr;
248} 248}
249
250
251DAPI_(HRESULT) PathSystemWindowsSubdirectory(
252 __in_z_opt LPCWSTR wzSubdirectory,
253 __out_z LPWSTR* psczFullPath
254 )
255{
256 HRESULT hr = S_OK;
257 WCHAR wzTempPath[MAX_PATH + 1] = { };
258 DWORD cch = 0;
259
260 cch = ::GetSystemWindowsDirectoryW(wzTempPath, countof(wzTempPath));
261 if (!cch)
262 {
263 PathExitWithLastError(hr, "Failed to get Windows directory path.");
264 }
265 else if (cch >= countof(wzTempPath))
266 {
267 PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Windows directory path too long.");
268 }
269
270 if (wzSubdirectory)
271 {
272 hr = PathConcatRelativeToBase(wzTempPath, wzSubdirectory, psczFullPath);
273 PathExitOnFailure(hr, "Failed to concat subdirectory on Windows directory path.");
274 }
275 else
276 {
277 hr = StrAllocString(psczFullPath, wzTempPath, 0);
278 PathExitOnFailure(hr, "Failed to copy Windows directory path.");
279 }
280
281 hr = PathBackslashTerminate(psczFullPath);
282 PathExitOnFailure(hr, "Failed to terminate Windows directory path with backslash.");
283
284LExit:
285 return hr;
286}
diff --git a/src/libs/dutil/WixToolset.DUtil/path3utl.cpp b/src/libs/dutil/WixToolset.DUtil/path3utl.cpp
new file mode 100644
index 00000000..cb6ce6d5
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/path3utl.cpp
@@ -0,0 +1,143 @@
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
3#include "precomp.h"
4
5
6// Exit macros
7#define PathExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
8#define PathExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
9#define PathExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
10#define PathExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
11#define PathExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
12#define PathExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_PATHUTIL, x, e, s, __VA_ARGS__)
13#define PathExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_PATHUTIL, x, s, __VA_ARGS__)
14#define PathExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_PATHUTIL, p, x, e, s, __VA_ARGS__)
15#define PathExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, p, x, s, __VA_ARGS__)
16#define PathExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_PATHUTIL, p, x, e, s, __VA_ARGS__)
17#define PathExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_PATHUTIL, p, x, s, __VA_ARGS__)
18#define PathExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_PATHUTIL, e, x, s, __VA_ARGS__)
19#define PathExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_PATHUTIL, g, x, s, __VA_ARGS__)
20
21static HRESULT GetTempPathFromSystemEnvironmentVariable(
22 __in HKEY hKey,
23 __in_z LPCWSTR wzName,
24 __out_z LPWSTR* psczPath
25 );
26
27DAPI_(HRESULT) PathGetSystemTempPaths(
28 __inout_z LPWSTR** prgsczSystemTempPaths,
29 __inout DWORD* pcSystemTempPaths
30 )
31{
32 HRESULT hr = S_OK;
33 HMODULE hModule = NULL;
34 BOOL fSystem = FALSE;
35 HKEY hKey = NULL;
36 LPWSTR sczTemp = NULL;
37
38 // Follow documented precedence rules for SystemTemp/%TMP%/%TEMP% from ::GetTempPath2.
39 hr = LoadSystemLibrary(L"kernel32.dll", &hModule);
40 PathExitOnFailure(hr, "Failed to load kernel32.dll");
41
42 // The SystemTemp folder was added at the same time as ::GetTempPath2.
43 if (::GetProcAddress(hModule, "GetTempPath2W"))
44 {
45 hr = ProcSystem(::GetCurrentProcess(), &fSystem);
46 PathExitOnFailure(hr, "Failed to check if running as system.");
47
48 if (fSystem)
49 {
50 hr = PathSystemWindowsSubdirectory(L"SystemTemp", &sczTemp);
51 PathExitOnFailure(hr, "Failed to get system Windows subdirectory path SystemTemp.");
52
53 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 4);
54 PathExitOnFailure(hr, "Failed to ensure array size for Windows\\SystemTemp value.");
55
56 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
57 sczTemp = NULL;
58 *pcSystemTempPaths += 1;
59 }
60 }
61
62 // There is no documented API to get system environment variables, so read them from the registry.
63 hr = RegOpen(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Session Manager\\Environment", KEY_READ, &hKey);
64 if (E_FILENOTFOUND != hr)
65 {
66 PathExitOnFailure(hr, "Failed to open system environment registry key.");
67
68 hr = GetTempPathFromSystemEnvironmentVariable(hKey, L"TMP", &sczTemp);
69 PathExitOnFailure(hr, "Failed to get temp path from system TMP.");
70
71 if (S_FALSE != hr)
72 {
73 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 3);
74 PathExitOnFailure(hr, "Failed to ensure array size for system TMP value.");
75
76 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
77 sczTemp = NULL;
78 *pcSystemTempPaths += 1;
79 }
80
81 hr = GetTempPathFromSystemEnvironmentVariable(hKey, L"TEMP", &sczTemp);
82 PathExitOnFailure(hr, "Failed to get temp path from system TEMP.");
83
84 if (S_FALSE != hr)
85 {
86 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 2);
87 PathExitOnFailure(hr, "Failed to ensure array size for system TEMP value.");
88
89 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
90 sczTemp = NULL;
91 *pcSystemTempPaths += 1;
92 }
93 }
94
95 hr = PathSystemWindowsSubdirectory(L"TEMP", &sczTemp);
96 PathExitOnFailure(hr, "Failed to get system Windows subdirectory path TEMP.");
97
98 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 1);
99 PathExitOnFailure(hr, "Failed to ensure array size for Windows\\TEMP value.");
100
101 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
102 sczTemp = NULL;
103 *pcSystemTempPaths += 1;
104
105LExit:
106 ReleaseRegKey(hKey);
107 ReleaseStr(sczTemp);
108
109 return hr;
110}
111
112static HRESULT GetTempPathFromSystemEnvironmentVariable(
113 __in HKEY hKey,
114 __in_z LPCWSTR wzName,
115 __out_z LPWSTR* psczPath
116 )
117{
118 HRESULT hr = S_OK;
119 LPWSTR sczValue = NULL;
120 BOOL fNeedsExpansion = FALSE;
121
122 // Read the value unexpanded so that it can be expanded with system environment variables.
123 hr = RegReadUnexpandedString(hKey, wzName, &fNeedsExpansion, &sczValue);
124 if (E_FILENOTFOUND == hr)
125 {
126 ExitFunction1(hr = S_FALSE);
127 }
128 PathExitOnFailure(hr, "Failed to get system '%ls' value.", wzName);
129
130 if (fNeedsExpansion)
131 {
132 hr = EnvExpandEnvironmentStringsForUser(NULL, sczValue, psczPath, NULL);
133 PathExitOnFailure(hr, "Failed to expand environment variables for system in string: %ls", sczValue);
134 }
135
136 hr = PathBackslashTerminate(psczPath);
137 PathExitOnFailure(hr, "Failed to backslash terminate system '%ls' value.", wzName);
138
139LExit:
140 ReleaseStr(sczValue);
141
142 return hr;
143}
diff --git a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
index becfc67e..0e2a5dec 100644
--- a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
@@ -894,86 +894,6 @@ LExit:
894} 894}
895 895
896 896
897DAPI_(HRESULT) PathGetSystemTempPaths(
898 __inout_z LPWSTR** prgsczSystemTempPaths,
899 __inout DWORD* pcSystemTempPaths
900 )
901{
902 HRESULT hr = S_OK;
903 HKEY hKey = NULL;
904 LPWSTR sczTemp = NULL;
905 WCHAR wzTempPath[MAX_PATH + 1] = { };
906 DWORD cch = 0;
907
908 // There is no documented API to get system environment variables, so read them from the registry.
909 hr = RegOpen(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Session Manager\\Environment", KEY_READ, &hKey);
910 if (E_FILENOTFOUND != hr)
911 {
912 PathExitOnFailure(hr, "Failed to open system environment registry key.");
913
914 // Follow documented precedence rules for TMP/TEMP from ::GetTempPath.
915 // TODO: values will be expanded with the current environment variables instead of the system environment variables.
916 hr = RegReadString(hKey, L"TMP", &sczTemp);
917 if (E_FILENOTFOUND != hr)
918 {
919 PathExitOnFailure(hr, "Failed to get system TMP value.");
920
921 hr = PathBackslashTerminate(&sczTemp);
922 PathExitOnFailure(hr, "Failed to backslash terminate system TMP value.");
923
924 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 3);
925 PathExitOnFailure(hr, "Failed to ensure array size for system TMP value.");
926
927 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
928 sczTemp = NULL;
929 *pcSystemTempPaths += 1;
930 }
931
932 hr = RegReadString(hKey, L"TEMP", &sczTemp);
933 if (E_FILENOTFOUND != hr)
934 {
935 PathExitOnFailure(hr, "Failed to get system TEMP value.");
936
937 hr = PathBackslashTerminate(&sczTemp);
938 PathExitOnFailure(hr, "Failed to backslash terminate system TEMP value.");
939
940 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 2);
941 PathExitOnFailure(hr, "Failed to ensure array size for system TEMP value.");
942
943 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
944 sczTemp = NULL;
945 *pcSystemTempPaths += 1;
946 }
947 }
948
949 cch = ::GetSystemWindowsDirectoryW(wzTempPath, countof(wzTempPath));
950 if (!cch)
951 {
952 PathExitWithLastError(hr, "Failed to get Windows directory path.");
953 }
954 else if (cch >= countof(wzTempPath))
955 {
956 PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Windows directory path too long.");
957 }
958
959 hr = PathConcat(wzTempPath, L"TEMP\\", &sczTemp);
960 PathExitOnFailure(hr, "Failed to concat Temp directory on Windows directory path.");
961
962 hr = MemEnsureArraySizeForNewItems(reinterpret_cast<LPVOID*>(prgsczSystemTempPaths), *pcSystemTempPaths, 1, sizeof(LPWSTR), 1);
963 PathExitOnFailure(hr, "Failed to ensure array size for Windows\\TEMP value.");
964
965 (*prgsczSystemTempPaths)[*pcSystemTempPaths] = sczTemp;
966 sczTemp = NULL;
967 *pcSystemTempPaths += 1;
968
969LExit:
970 ReleaseRegKey(hKey);
971 ReleaseStr(sczTemp);
972
973 return hr;
974}
975
976
977DAPI_(HRESULT) PathGetKnownFolder( 897DAPI_(HRESULT) PathGetKnownFolder(
978 __in int csidl, 898 __in int csidl,
979 __out LPWSTR* psczKnownFolder 899 __out LPWSTR* psczKnownFolder
diff --git a/src/libs/dutil/WixToolset.DUtil/polcutil.cpp b/src/libs/dutil/WixToolset.DUtil/polcutil.cpp
index 1fdfa18c..c2247bc1 100644
--- a/src/libs/dutil/WixToolset.DUtil/polcutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/polcutil.cpp
@@ -102,6 +102,49 @@ LExit:
102 return hr; 102 return hr;
103} 103}
104 104
105extern "C" HRESULT DAPI PolcReadUnexpandedString(
106 __in_z LPCWSTR wzPolicyPath,
107 __in_z LPCWSTR wzPolicyName,
108 __in_z_opt LPCWSTR wzDefault,
109 __inout BOOL* pfNeedsExpansion,
110 __deref_out_z LPWSTR* pscz
111 )
112{
113 HRESULT hr = S_OK;
114 HKEY hk = NULL;
115
116 hr = OpenPolicyKey(wzPolicyPath, &hk);
117 if (E_FILENOTFOUND == hr || E_PATHNOTFOUND == hr)
118 {
119 ExitFunction1(hr = S_FALSE);
120 }
121 PolcExitOnFailure(hr, "Failed to open policy key: %ls", wzPolicyPath);
122
123 hr = RegReadUnexpandedString(hk, wzPolicyName, pfNeedsExpansion, pscz);
124 if (E_FILENOTFOUND == hr || E_PATHNOTFOUND == hr)
125 {
126 ExitFunction1(hr = S_FALSE);
127 }
128 PolcExitOnFailure(hr, "Failed to open policy key: %ls, name: %ls", wzPolicyPath, wzPolicyName);
129
130LExit:
131 ReleaseRegKey(hk);
132
133 if (S_FALSE == hr || FAILED(hr))
134 {
135 if (NULL == wzDefault)
136 {
137 ReleaseNullStr(*pscz);
138 }
139 else
140 {
141 hr = StrAllocString(pscz, wzDefault, 0);
142 }
143 }
144
145 return hr;
146}
147
105 148
106// internal functions 149// internal functions
107 150
diff --git a/src/libs/dutil/WixToolset.DUtil/procutil.cpp b/src/libs/dutil/WixToolset.DUtil/procutil.cpp
index a3131b7a..340a0cda 100644
--- a/src/libs/dutil/WixToolset.DUtil/procutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/procutil.cpp
@@ -9,6 +9,7 @@
9#define ProcExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_PROCUTIL, x, s, __VA_ARGS__) 9#define ProcExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_PROCUTIL, x, s, __VA_ARGS__)
10#define ProcExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_PROCUTIL, x, s, __VA_ARGS__) 10#define ProcExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_PROCUTIL, x, s, __VA_ARGS__)
11#define ProcExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_PROCUTIL, x, s, __VA_ARGS__) 11#define ProcExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_PROCUTIL, x, s, __VA_ARGS__)
12#define ProcExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_PROCUTIL, x, e, s, __VA_ARGS__)
12#define ProcExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_PROCUTIL, x, s, __VA_ARGS__) 13#define ProcExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_PROCUTIL, x, s, __VA_ARGS__)
13#define ProcExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_PROCUTIL, p, x, e, s, __VA_ARGS__) 14#define ProcExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_PROCUTIL, p, x, e, s, __VA_ARGS__)
14#define ProcExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_PROCUTIL, p, x, s, __VA_ARGS__) 15#define ProcExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_PROCUTIL, p, x, s, __VA_ARGS__)
@@ -75,6 +76,73 @@ LExit:
75 return hr; 76 return hr;
76} 77}
77 78
79extern "C" HRESULT DAPI ProcSystem(
80 __in HANDLE hProcess,
81 __out BOOL* pfSystem
82 )
83{
84 HRESULT hr = S_OK;
85 TOKEN_USER* pTokenUser = NULL;
86
87 hr = ProcTokenUser(hProcess, &pTokenUser);
88 ProcExitOnFailure(hr, "Failed to get TokenUser from process token.");
89
90 *pfSystem = ::IsWellKnownSid(pTokenUser->User.Sid, WinLocalSystemSid);
91
92LExit:
93 ReleaseMem(pTokenUser);
94
95 return hr;
96}
97
98extern "C" HRESULT DAPI ProcTokenUser(
99 __in HANDLE hProcess,
100 __out TOKEN_USER** ppTokenUser
101 )
102{
103 HRESULT hr = S_OK;
104 DWORD er = ERROR_SUCCESS;
105 HANDLE hToken = NULL;
106 TOKEN_USER* pTokenUser = NULL;
107 DWORD cbToken = 0;
108
109 if (!::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
110 {
111 ProcExitWithLastError(hr, "Failed to open process token.");
112 }
113
114 if (::GetTokenInformation(hToken, TokenUser, pTokenUser, 0, &cbToken))
115 {
116 er = ERROR_SUCCESS;
117 }
118 else
119 {
120 er = ::GetLastError();
121 }
122
123 if (er != ERROR_INSUFFICIENT_BUFFER)
124 {
125 ProcExitOnWin32Error(er, hr, "Failed to get user from process token size.");
126 }
127
128 pTokenUser = reinterpret_cast<TOKEN_USER*>(MemAlloc(cbToken, TRUE));
129 ProcExitOnNull(pTokenUser, hr, E_OUTOFMEMORY, "Failed to allocate token information.");
130
131 if (!::GetTokenInformation(hToken, TokenUser, pTokenUser, cbToken, &cbToken))
132 {
133 ProcExitWithLastError(hr, "Failed to get user from process token.");
134 }
135
136 *ppTokenUser = pTokenUser;
137 pTokenUser = NULL;
138
139LExit:
140 ReleaseMem(pTokenUser);
141 ReleaseHandle(hToken);
142
143 return hr;
144}
145
78extern "C" HRESULT DAPI ProcWow64( 146extern "C" HRESULT DAPI ProcWow64(
79 __in HANDLE hProcess, 147 __in HANDLE hProcess,
80 __out BOOL* pfWow64 148 __out BOOL* pfWow64
diff --git a/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj b/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj
index ee9f505e..a1f13239 100644
--- a/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj
+++ b/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj
@@ -40,7 +40,7 @@
40 40
41 <PropertyGroup> 41 <PropertyGroup>
42 <ProjectAdditionalIncludeDirectories>..\..\WixToolset.DUtil\inc</ProjectAdditionalIncludeDirectories> 42 <ProjectAdditionalIncludeDirectories>..\..\WixToolset.DUtil\inc</ProjectAdditionalIncludeDirectories>
43 <ProjectAdditionalLinkLibraries>rpcrt4.lib;Mpr.lib;Ws2_32.lib;shlwapi.lib;urlmon.lib;wininet.lib</ProjectAdditionalLinkLibraries> 43 <ProjectAdditionalLinkLibraries>rpcrt4.lib;Mpr.lib;Ws2_32.lib;shlwapi.lib;urlmon.lib;userenv.lib;wininet.lib</ProjectAdditionalLinkLibraries>
44 </PropertyGroup> 44 </PropertyGroup>
45 45
46 <ItemGroup> 46 <ItemGroup>
@@ -57,6 +57,7 @@
57 <ClCompile Include="MemUtilTest.cpp" /> 57 <ClCompile Include="MemUtilTest.cpp" />
58 <ClCompile Include="MonUtilTest.cpp" /> 58 <ClCompile Include="MonUtilTest.cpp" />
59 <ClCompile Include="PathUtilTest.cpp" /> 59 <ClCompile Include="PathUtilTest.cpp" />
60 <ClCompile Include="ProcUtilTest.cpp" />
60 <ClCompile Include="precomp.cpp"> 61 <ClCompile Include="precomp.cpp">
61 <PrecompiledHeader>Create</PrecompiledHeader> 62 <PrecompiledHeader>Create</PrecompiledHeader>
62 <!-- Warnings from referencing netstandard dlls --> 63 <!-- Warnings from referencing netstandard dlls -->
diff --git a/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters b/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters
index bcda6df0..cb0c8a73 100644
--- a/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters
+++ b/src/libs/dutil/test/DUtilUnitTest/DUtilUnitTest.vcxproj.filters
@@ -54,6 +54,9 @@
54 <ClCompile Include="PathUtilTest.cpp"> 54 <ClCompile Include="PathUtilTest.cpp">
55 <Filter>Source Files</Filter> 55 <Filter>Source Files</Filter>
56 </ClCompile> 56 </ClCompile>
57 <ClCompile Include="ProcUtilTest.cpp">
58 <Filter>Source Files</Filter>
59 </ClCompile>
57 <ClCompile Include="precomp.cpp"> 60 <ClCompile Include="precomp.cpp">
58 <Filter>Source Files</Filter> 61 <Filter>Source Files</Filter>
59 </ClCompile> 62 </ClCompile>
diff --git a/src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp b/src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp
index 76dfa774..94b9ab8e 100644
--- a/src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp
+++ b/src/libs/dutil/test/DUtilUnitTest/EnvUtilTests.cpp
@@ -3,8 +3,10 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5using namespace System; 5using namespace System;
6using namespace System::Collections;
6using namespace Xunit; 7using namespace Xunit;
7using namespace WixBuildTools::TestSupport; 8using namespace WixBuildTools::TestSupport;
9using namespace WixBuildTools::TestSupport::XunitExtensions;
8 10
9namespace DutilTests 11namespace DutilTests
10{ 12{
@@ -46,5 +48,48 @@ namespace DutilTests
46 ReleaseStr(sczExpanded); 48 ReleaseStr(sczExpanded);
47 } 49 }
48 } 50 }
51
52 [SkippableFact]
53 void EnvExpandEnvironmentStringsForUserTest()
54 {
55 HRESULT hr = S_OK;
56 LPWSTR sczExpanded = NULL;
57 SIZE_T cchExpanded = 0;
58 String^ variableName = nullptr;
59 String^ variableValue = nullptr;
60
61 // Find a system environment variable that doesn't have variables in its value;
62 for each (DictionaryEntry^ entry in Environment::GetEnvironmentVariables(EnvironmentVariableTarget::Machine))
63 {
64 variableValue = (String^)entry->Value;
65 if (variableValue->Contains("%"))
66 {
67 continue;
68 }
69
70 variableName = (String^)entry->Key;
71 break;
72 }
73
74 if (nullptr == variableName)
75 {
76 WixAssert::Skip("No suitable system environment variables");
77 }
78
79 pin_ptr<const wchar_t> wzUnexpanded = PtrToStringChars("%" + variableName + "%_%USERNAME%");
80 String^ expandedValue = variableValue + "_SYSTEM";
81
82 try
83 {
84 hr = EnvExpandEnvironmentStringsForUser(NULL, wzUnexpanded, &sczExpanded, &cchExpanded);
85 NativeAssert::Succeeded(hr, "Failed to expand %ls.", wzUnexpanded);
86 WixAssert::StringEqual(expandedValue, gcnew String(sczExpanded), false);
87 NativeAssert::Equal<SIZE_T>(expandedValue->Length + 1, cchExpanded);
88 }
89 finally
90 {
91 ReleaseStr(sczExpanded);
92 }
93 }
49 }; 94 };
50} 95}
diff --git a/src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp b/src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp
new file mode 100644
index 00000000..297d90f4
--- /dev/null
+++ b/src/libs/dutil/test/DUtilUnitTest/ProcUtilTest.cpp
@@ -0,0 +1,42 @@
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
3#include "precomp.h"
4
5using namespace System;
6using namespace System::Security::Principal;
7using namespace Xunit;
8using namespace WixBuildTools::TestSupport;
9
10namespace DutilTests
11{
12 public ref class ProcUtil
13 {
14 public:
15 [Fact]
16 void ProcTokenUserTest()
17 {
18 HRESULT hr = S_OK;
19 TOKEN_USER* pTokenUser = NULL;
20 LPWSTR sczSid = NULL;
21
22 try
23 {
24 hr = ProcTokenUser(::GetCurrentProcess(), &pTokenUser);
25 NativeAssert::Succeeded(hr, "Failed to get TokenUser for current process.");
26
27 if (!::ConvertSidToStringSidW(pTokenUser->User.Sid, &sczSid))
28 {
29 hr = HRESULT_FROM_WIN32(::GetLastError());
30 NativeAssert::Succeeded(hr, "Failed to get string SID from TokenUser SID.");
31 }
32
33 Assert::Equal<String^>(WindowsIdentity::GetCurrent()->User->Value, gcnew String(sczSid));
34 }
35 finally
36 {
37 ReleaseMem(pTokenUser);
38 ReleaseStr(sczSid);
39 }
40 }
41 };
42}
diff --git a/src/libs/dutil/test/DUtilUnitTest/precomp.h b/src/libs/dutil/test/DUtilUnitTest/precomp.h
index bc628816..ac57cdd4 100644
--- a/src/libs/dutil/test/DUtilUnitTest/precomp.h
+++ b/src/libs/dutil/test/DUtilUnitTest/precomp.h
@@ -5,6 +5,7 @@
5#include <windows.h> 5#include <windows.h>
6#include <strsafe.h> 6#include <strsafe.h>
7#include <ShlObj.h> 7#include <ShlObj.h>
8#include <sddl.h>
8 9
9// Include error.h before dutil.h 10// Include error.h before dutil.h
10#include <dutilsources.h> 11#include <dutilsources.h>
@@ -21,6 +22,7 @@
21#include <iniutil.h> 22#include <iniutil.h>
22#include <memutil.h> 23#include <memutil.h>
23#include <pathutil.h> 24#include <pathutil.h>
25#include <procutil.h>
24#include <strutil.h> 26#include <strutil.h>
25#include <monutil.h> 27#include <monutil.h>
26#include <regutil.h> 28#include <regutil.h>
diff --git a/src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp b/src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
index 3cf994fc..bc942dc8 100644
--- a/src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
+++ b/src/test/burn/TestData/Manual/BafThmutilTesting/BafThmUtilTesting.cpp
@@ -30,6 +30,7 @@ static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = {
30 { BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_STANDARD, L"StandardProgressBar" }, 30 { BAFTHMUTILTESTING_CONTROL_PROGRESSBAR_STANDARD, L"StandardProgressBar" },
31}; 31};
32 32
33static HRESULT LogUserSid();
33static void CALLBACK BafThmUtilTestingTraceError( 34static void CALLBACK BafThmUtilTestingTraceError(
34 __in_z LPCSTR szFile, 35 __in_z LPCSTR szFile,
35 __in int iLine, 36 __in int iLine,
@@ -494,6 +495,8 @@ HRESULT WINAPI CreateBAFunctions(
494 pResults->pvBAFunctionsProcContext = pBAFunctions; 495 pResults->pvBAFunctionsProcContext = pBAFunctions;
495 pBAFunctions = NULL; 496 pBAFunctions = NULL;
496 497
498 LogUserSid();
499
497LExit: 500LExit:
498 ReleaseObject(pBAFunctions); 501 ReleaseObject(pBAFunctions);
499 ReleaseObject(pEngine); 502 ReleaseObject(pEngine);
@@ -501,6 +504,33 @@ LExit:
501 return hr; 504 return hr;
502} 505}
503 506
507static HRESULT LogUserSid()
508{
509 HRESULT hr = S_OK;
510 TOKEN_USER* pTokenUser = NULL;
511 LPWSTR sczSid = NULL;
512
513 hr = ProcTokenUser(::GetCurrentProcess(), &pTokenUser);
514 BalExitOnFailure(hr, "Failed to get user from process token.");
515
516 if (!::ConvertSidToStringSidW(pTokenUser->User.Sid, &sczSid))
517 {
518 BalExitWithLastError(hr, "Failed to convert sid to string.");
519 }
520
521 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Current User SID: %ls", sczSid);
522
523LExit:
524 ReleaseMem(pTokenUser);
525
526 if (sczSid)
527 {
528 ::LocalFree(sczSid);
529 }
530
531 return hr;
532}
533
504static void CALLBACK BafThmUtilTestingTraceError( 534static void CALLBACK BafThmUtilTestingTraceError(
505 __in_z LPCSTR /*szFile*/, 535 __in_z LPCSTR /*szFile*/,
506 __in int /*iLine*/, 536 __in int /*iLine*/,
diff --git a/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.h b/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.h
index e7cd39dc..2e14786a 100644
--- a/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.h
+++ b/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.h
@@ -16,12 +16,15 @@
16#include <stdlib.h> 16#include <stdlib.h>
17#include <strsafe.h> 17#include <strsafe.h>
18#include <CommCtrl.h> 18#include <CommCtrl.h>
19#include <sddl.h>
19 20
20#include "dutil.h" 21#include "dutil.h"
21#include "dictutil.h" 22#include "dictutil.h"
22#include "fileutil.h" 23#include "fileutil.h"
23#include "locutil.h" 24#include "locutil.h"
25#include "memutil.h"
24#include "pathutil.h" 26#include "pathutil.h"
27#include "procutil.h"
25#include "strutil.h" 28#include "strutil.h"
26#include "thmutil.h" 29#include "thmutil.h"
27#include "regutil.h" 30#include "regutil.h"