@joebigelow / wix / commits / 6ee12a64

Add LoadSystemApiSet.

Sean Hall committed Jun 24, 2022 at 12:26 UTC 6ee12a64cb75097a238e60d4fd0ea542e8312214
2 files changed +87 -13
src/libs/dutil/WixToolset.DUtil/apputil.cpp
+73 -11
@@ -17,10 +17,13 @@
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__)
19
20 -const DWORD PRIVATE_LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800;
20 typedef BOOL(WINAPI *LPFN_SETDEFAULTDLLDIRECTORIES)(DWORD);
21 typedef BOOL(WINAPI *LPFN_SETDLLDIRECTORYW)(LPCWSTR);
22
23 +static BOOL vfInitialized = FALSE;
24 +static LPFN_SETDEFAULTDLLDIRECTORIES vpfnSetDefaultDllDirectories = NULL;
25 +static LPFN_SETDLLDIRECTORYW vpfnSetDllDirectory = NULL;
26 +
27 /********************************************************************
28 EscapeCommandLineArgument - encodes wzArgument such that
29 ::CommandLineToArgv() will parse it back unaltered. If no escaping
@@ -32,12 +35,48 @@ static HRESULT EscapeCommandLineArgument(
35 __out_z LPWSTR* psczEscaped
36 );
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 +
60 DAPI_(HRESULT) LoadSystemLibrary(
61 __in_z LPCWSTR wzModuleName,
62 __out HMODULE* phModule
63 )
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:
80 return hr;
81 }
82
@@ -63,7 +102,7 @@ DAPI_(HRESULT) LoadSystemLibraryWithPath(
102 hr = ::StringCchCatW(wzPath, MAX_PATH, wzModuleName);
103 AppExitOnRootFailure(hr, "Failed to create the fully-qualified path to %ls.", wzModuleName);
104
66 - *phModule = ::LoadLibraryW(wzPath);
105 + *phModule = ::LoadLibraryExW(wzPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
106 AppExitOnNullWithLastError(*phModule, hr, "Failed to load the library %ls.", wzModuleName);
107
108 if (psczPath)
@@ -76,6 +115,31 @@ LExit:
115 return hr;
116 }
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 +
143 DAPI_(void) AppInitialize(
144 __in_ecount(cSafelyLoadSystemDlls) LPCWSTR rgsczSafelyLoadSystemDlls[],
145 __in DWORD cSafelyLoadSystemDlls
@@ -87,13 +151,12 @@ DAPI_(void) AppInitialize(
151
152 ::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
153
154 + Initialize();
155 +
156 // Best effort call to initialize default DLL directories to system only.
91 - HMODULE hKernel32 = ::GetModuleHandleW(L"kernel32");
92 - Assert(hKernel32);
93 - LPFN_SETDEFAULTDLLDIRECTORIES pfnSetDefaultDllDirectories = (LPFN_SETDEFAULTDLLDIRECTORIES)::GetProcAddress(hKernel32, "SetDefaultDllDirectories");
94 - if (pfnSetDefaultDllDirectories)
157 + if (vpfnSetDefaultDllDirectories)
158 {
96 - if (pfnSetDefaultDllDirectories(PRIVATE_LOAD_LIBRARY_SEARCH_SYSTEM32))
159 + if (vpfnSetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32))
160 {
161 fSetDefaultDllDirectories = TRUE;
162 }
@@ -109,10 +172,9 @@ DAPI_(void) AppInitialize(
172 if (!fSetDefaultDllDirectories)
173 {
174 // Remove current working directory from search order.
112 - LPFN_SETDLLDIRECTORYW pfnSetDllDirectory = (LPFN_SETDLLDIRECTORYW)::GetProcAddress(hKernel32, "SetDllDirectoryW");
113 - if (!pfnSetDllDirectory || !pfnSetDllDirectory(L""))
175 + if (!vpfnSetDllDirectory || !vpfnSetDllDirectory(L""))
176 {
115 - hr = HRESULT_FROM_WIN32(::GetLastError());
177 + hr = vpfnSetDllDirectory ? HRESULT_FROM_WIN32(::GetLastError()) : HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
178 TraceError(hr, "Failed to call SetDllDirectory.");
179 }
180
src/libs/dutil/WixToolset.DUtil/inc/dutil.h
+14 -2
@@ -207,8 +207,8 @@ extern "C" {
207 // other functions
208
209 /*******************************************************************
210 - LoadSystemLibrary - Fully qualifies the path to a module in the
211 - Windows system directory and loads it.
210 + LoadSystemLibrary - Securely loads the module from the
211 + Windows system directory.
212
213 Returns
214 E_MODNOTFOUND - The module could not be found.
@@ -234,6 +234,18 @@ HRESULT DAPI LoadSystemLibraryWithPath(
234 __deref_out_z_opt LPWSTR* psczPath
235 );
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 +
249 #ifdef __cplusplus
250 }
251 #endif