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