diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2022-06-24 12:26:42 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2022-06-27 11:14:21 -0500 |
commit | 6ee12a64cb75097a238e60d4fd0ea542e8312214 (patch) | |
tree | 0cd7d8637e167e8c294a107ccdb99db016f67a60 | |
parent | 78b5daf01555d86293c1012ed3de704752880a6a (diff) | |
download | wix-6ee12a64cb75097a238e60d4fd0ea542e8312214.tar.gz wix-6ee12a64cb75097a238e60d4fd0ea542e8312214.tar.bz2 wix-6ee12a64cb75097a238e60d4fd0ea542e8312214.zip |
Add LoadSystemApiSet.
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/apputil.cpp | 84 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/dutil.h | 16 |
2 files changed, 87 insertions, 13 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/apputil.cpp b/src/libs/dutil/WixToolset.DUtil/apputil.cpp index 147d1d1e..b70c8cfb 100644 --- a/src/libs/dutil/WixToolset.DUtil/apputil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/apputil.cpp | |||
@@ -17,10 +17,13 @@ | |||
17 | #define AppExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_APPUTIL, e, x, s, __VA_ARGS__) | 17 | #define AppExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_APPUTIL, e, x, s, __VA_ARGS__) |
18 | #define AppExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_APPUTIL, g, x, s, __VA_ARGS__) | 18 | #define AppExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_APPUTIL, g, x, s, __VA_ARGS__) |
19 | 19 | ||
20 | const DWORD PRIVATE_LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800; | ||
21 | typedef BOOL(WINAPI *LPFN_SETDEFAULTDLLDIRECTORIES)(DWORD); | 20 | typedef BOOL(WINAPI *LPFN_SETDEFAULTDLLDIRECTORIES)(DWORD); |
22 | typedef BOOL(WINAPI *LPFN_SETDLLDIRECTORYW)(LPCWSTR); | 21 | typedef BOOL(WINAPI *LPFN_SETDLLDIRECTORYW)(LPCWSTR); |
23 | 22 | ||
23 | static BOOL vfInitialized = FALSE; | ||
24 | static LPFN_SETDEFAULTDLLDIRECTORIES vpfnSetDefaultDllDirectories = NULL; | ||
25 | static LPFN_SETDLLDIRECTORYW vpfnSetDllDirectory = NULL; | ||
26 | |||
24 | /******************************************************************** | 27 | /******************************************************************** |
25 | EscapeCommandLineArgument - encodes wzArgument such that | 28 | EscapeCommandLineArgument - encodes wzArgument such that |
26 | ::CommandLineToArgv() will parse it back unaltered. If no escaping | 29 | ::CommandLineToArgv() will parse it back unaltered. If no escaping |
@@ -32,12 +35,48 @@ static HRESULT EscapeCommandLineArgument( | |||
32 | __out_z LPWSTR* psczEscaped | 35 | __out_z LPWSTR* psczEscaped |
33 | ); | 36 | ); |
34 | 37 | ||
38 | static void Initialize() | ||
39 | { | ||
40 | HRESULT hr = S_OK; | ||
41 | HMODULE hKernel32 = NULL; | ||
42 | |||
43 | if (vfInitialized) | ||
44 | { | ||
45 | ExitFunction(); | ||
46 | } | ||
47 | |||
48 | hKernel32 = ::GetModuleHandleW(L"kernel32"); | ||
49 | AppExitOnNullWithLastError(hKernel32, hr, "Failed to get module handle for kernel32."); | ||
50 | |||
51 | vpfnSetDefaultDllDirectories = (LPFN_SETDEFAULTDLLDIRECTORIES)::GetProcAddress(hKernel32, "SetDefaultDllDirectories"); | ||
52 | vpfnSetDllDirectory = (LPFN_SETDLLDIRECTORYW)::GetProcAddress(hKernel32, "SetDllDirectoryW"); | ||
53 | |||
54 | vfInitialized = TRUE; | ||
55 | |||
56 | LExit: | ||
57 | return; | ||
58 | } | ||
59 | |||
35 | DAPI_(HRESULT) LoadSystemLibrary( | 60 | DAPI_(HRESULT) LoadSystemLibrary( |
36 | __in_z LPCWSTR wzModuleName, | 61 | __in_z LPCWSTR wzModuleName, |
37 | __out HMODULE* phModule | 62 | __out HMODULE* phModule |
38 | ) | 63 | ) |
39 | { | 64 | { |
40 | HRESULT hr = LoadSystemLibraryWithPath(wzModuleName, phModule, NULL); | 65 | HRESULT hr = S_OK; |
66 | |||
67 | Initialize(); | ||
68 | |||
69 | if (vpfnSetDefaultDllDirectories) // LOAD_LIBRARY_SEARCH_SYSTEM32 was added at same time as SetDefaultDllDirectories. | ||
70 | { | ||
71 | *phModule = ::LoadLibraryExW(wzModuleName, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); | ||
72 | AppExitOnNullWithLastError(*phModule, hr, "Failed to get load library with LOAD_LIBRARY_SEARCH_SYSTEM32."); | ||
73 | } | ||
74 | else | ||
75 | { | ||
76 | hr = LoadSystemLibraryWithPath(wzModuleName, phModule, NULL); | ||
77 | } | ||
78 | |||
79 | LExit: | ||
41 | return hr; | 80 | return hr; |
42 | } | 81 | } |
43 | 82 | ||
@@ -63,7 +102,7 @@ DAPI_(HRESULT) LoadSystemLibraryWithPath( | |||
63 | hr = ::StringCchCatW(wzPath, MAX_PATH, wzModuleName); | 102 | hr = ::StringCchCatW(wzPath, MAX_PATH, wzModuleName); |
64 | AppExitOnRootFailure(hr, "Failed to create the fully-qualified path to %ls.", wzModuleName); | 103 | AppExitOnRootFailure(hr, "Failed to create the fully-qualified path to %ls.", wzModuleName); |
65 | 104 | ||
66 | *phModule = ::LoadLibraryW(wzPath); | 105 | *phModule = ::LoadLibraryExW(wzPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); |
67 | AppExitOnNullWithLastError(*phModule, hr, "Failed to load the library %ls.", wzModuleName); | 106 | AppExitOnNullWithLastError(*phModule, hr, "Failed to load the library %ls.", wzModuleName); |
68 | 107 | ||
69 | if (psczPath) | 108 | if (psczPath) |
@@ -76,6 +115,31 @@ LExit: | |||
76 | return hr; | 115 | return hr; |
77 | } | 116 | } |
78 | 117 | ||
118 | DAPI_(HRESULT) LoadSystemApiSet( | ||
119 | __in_z LPCWSTR wzApiSet, | ||
120 | __out HMODULE* phModule | ||
121 | ) | ||
122 | { | ||
123 | HRESULT hr = S_OK; | ||
124 | |||
125 | Initialize(); | ||
126 | |||
127 | if (!vpfnSetDefaultDllDirectories) | ||
128 | { | ||
129 | // For many API sets, the .dll does not actually exist on disk so there's no point on even trying if SetDefaultDllDirectories is not available. | ||
130 | // On OS's where API sets are implemented, the loader requires just the API set name with .dll. | ||
131 | // It is not safe to pass such strings to LoadLibraryEx without LOAD_LIBRARY_SEARCH_SYSTEM32, which isn't available on old OS's. | ||
132 | AppExitWithRootFailure(hr, E_MODNOTFOUND, "OS doesn't support API sets."); | ||
133 | } | ||
134 | else | ||
135 | { | ||
136 | hr = LoadSystemLibrary(wzApiSet, phModule); | ||
137 | } | ||
138 | |||
139 | LExit: | ||
140 | return hr; | ||
141 | } | ||
142 | |||
79 | DAPI_(void) AppInitialize( | 143 | DAPI_(void) AppInitialize( |
80 | __in_ecount(cSafelyLoadSystemDlls) LPCWSTR rgsczSafelyLoadSystemDlls[], | 144 | __in_ecount(cSafelyLoadSystemDlls) LPCWSTR rgsczSafelyLoadSystemDlls[], |
81 | __in DWORD cSafelyLoadSystemDlls | 145 | __in DWORD cSafelyLoadSystemDlls |
@@ -87,13 +151,12 @@ DAPI_(void) AppInitialize( | |||
87 | 151 | ||
88 | ::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); | 152 | ::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0); |
89 | 153 | ||
154 | Initialize(); | ||
155 | |||
90 | // Best effort call to initialize default DLL directories to system only. | 156 | // Best effort call to initialize default DLL directories to system only. |
91 | HMODULE hKernel32 = ::GetModuleHandleW(L"kernel32"); | 157 | if (vpfnSetDefaultDllDirectories) |
92 | Assert(hKernel32); | ||
93 | LPFN_SETDEFAULTDLLDIRECTORIES pfnSetDefaultDllDirectories = (LPFN_SETDEFAULTDLLDIRECTORIES)::GetProcAddress(hKernel32, "SetDefaultDllDirectories"); | ||
94 | if (pfnSetDefaultDllDirectories) | ||
95 | { | 158 | { |
96 | if (pfnSetDefaultDllDirectories(PRIVATE_LOAD_LIBRARY_SEARCH_SYSTEM32)) | 159 | if (vpfnSetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32)) |
97 | { | 160 | { |
98 | fSetDefaultDllDirectories = TRUE; | 161 | fSetDefaultDllDirectories = TRUE; |
99 | } | 162 | } |
@@ -109,10 +172,9 @@ DAPI_(void) AppInitialize( | |||
109 | if (!fSetDefaultDllDirectories) | 172 | if (!fSetDefaultDllDirectories) |
110 | { | 173 | { |
111 | // Remove current working directory from search order. | 174 | // Remove current working directory from search order. |
112 | LPFN_SETDLLDIRECTORYW pfnSetDllDirectory = (LPFN_SETDLLDIRECTORYW)::GetProcAddress(hKernel32, "SetDllDirectoryW"); | 175 | if (!vpfnSetDllDirectory || !vpfnSetDllDirectory(L"")) |
113 | if (!pfnSetDllDirectory || !pfnSetDllDirectory(L"")) | ||
114 | { | 176 | { |
115 | hr = HRESULT_FROM_WIN32(::GetLastError()); | 177 | hr = vpfnSetDllDirectory ? HRESULT_FROM_WIN32(::GetLastError()) : HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); |
116 | TraceError(hr, "Failed to call SetDllDirectory."); | 178 | TraceError(hr, "Failed to call SetDllDirectory."); |
117 | } | 179 | } |
118 | 180 | ||
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/dutil.h b/src/libs/dutil/WixToolset.DUtil/inc/dutil.h index 4a29b66b..6f099f35 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/dutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/dutil.h | |||
@@ -207,8 +207,8 @@ extern "C" { | |||
207 | // other functions | 207 | // other functions |
208 | 208 | ||
209 | /******************************************************************* | 209 | /******************************************************************* |
210 | LoadSystemLibrary - Fully qualifies the path to a module in the | 210 | LoadSystemLibrary - Securely loads the module from the |
211 | Windows system directory and loads it. | 211 | Windows system directory. |
212 | 212 | ||
213 | Returns | 213 | Returns |
214 | E_MODNOTFOUND - The module could not be found. | 214 | E_MODNOTFOUND - The module could not be found. |
@@ -234,6 +234,18 @@ HRESULT DAPI LoadSystemLibraryWithPath( | |||
234 | __deref_out_z_opt LPWSTR* psczPath | 234 | __deref_out_z_opt LPWSTR* psczPath |
235 | ); | 235 | ); |
236 | 236 | ||
237 | /******************************************************************* | ||
238 | LoadSystemApiSet - Securely loads the API set provided by the system. | ||
239 | |||
240 | Returns | ||
241 | E_MODNOTFOUND - The module could not be found. | ||
242 | * - Another error occured. | ||
243 | ********************************************************************/ | ||
244 | DAPI_(HRESULT) LoadSystemApiSet( | ||
245 | __in_z LPCWSTR wzApiSet, | ||
246 | __out HMODULE* phModule | ||
247 | ); | ||
248 | |||
237 | #ifdef __cplusplus | 249 | #ifdef __cplusplus |
238 | } | 250 | } |
239 | #endif | 251 | #endif |