main
cpp 169 lines 5.28 KB
Raw
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 static HMODULE s_hKernel32;
6 static BOOL s_fWow64Initialized;
7 static BOOL (*s_pfnDisableWow64)(__out PVOID* );
8 static BOOL (*s_pfnRevertWow64)(__in PVOID );
9 static BOOL (*s_pfnIsWow64Process) (HANDLE, PBOOL);
10 static PVOID s_Wow64FSRevertState;
11 static BOOL s_fWow64FSDisabled;
12
13 /********************************************************************
14 WcaInitializeWow64() - Initializes the Wow64 API
15
16 ********************************************************************/
17 extern "C" HRESULT WIXAPI WcaInitializeWow64()
18 {
19 AssertSz(WcaIsInitialized(), "WcaInitialize() should be called before calling WcaInitializeWow64()");
20 AssertSz(!WcaIsWow64Initialized(), "WcaInitializeWow64() should not be called twice without calling WcaFinalizeWow64()");
21
22 s_fWow64Initialized = FALSE;
23 HRESULT hr = S_OK;
24 s_Wow64FSRevertState = NULL;
25 s_fWow64FSDisabled = false;
26
27 // Test if we have access to the Wow64 API, and store the result in bWow64APIPresent
28 s_hKernel32 = ::GetModuleHandleW(L"kernel32.dll");
29 if (!s_hKernel32)
30 {
31 ExitWithLastError(hr, "failed to get handle to kernel32.dll");
32 }
33
34 // This will test if we have access to the Wow64 API
35 s_pfnIsWow64Process = (BOOL (*)(HANDLE, PBOOL))::GetProcAddress(s_hKernel32, "IsWow64Process");
36 if (NULL != s_pfnIsWow64Process)
37 {
38 s_pfnDisableWow64 = (BOOL (*)(PVOID *))::GetProcAddress(s_hKernel32, "Wow64DisableWow64FsRedirection");
39 // If we fail, log the error but proceed, because we may not need a particular function, or the Wow64 API at all
40 if (!s_pfnDisableWow64)
41 {
42 return S_FALSE;
43 }
44
45 s_pfnRevertWow64 = (BOOL (*)(PVOID))::GetProcAddress(s_hKernel32, "Wow64RevertWow64FsRedirection");
46 if (!s_pfnRevertWow64)
47 {
48 return S_FALSE;
49 }
50
51 if (s_pfnDisableWow64 && s_pfnRevertWow64)
52 {
53 s_fWow64Initialized = TRUE;
54 }
55 }
56 else
57 {
58 return S_FALSE;
59 }
60
61 LExit:
62
63 return hr;
64 }
65
66 /********************************************************************
67 WcaIsWow64Process() - determines if the current process is running
68 in WOW
69
70 ********************************************************************/
71 extern "C" BOOL WIXAPI WcaIsWow64Process()
72 {
73 BOOL fIsWow64Process = FALSE;
74 if (s_fWow64Initialized)
75 {
76 if (!s_pfnIsWow64Process(GetCurrentProcess(), &fIsWow64Process))
77 {
78 // clear out the value since call failed
79 fIsWow64Process = FALSE;
80 }
81 }
82 return fIsWow64Process;
83 }
84
85 /********************************************************************
86 WcaIsWow64Initialized() - determines if WcaInitializeWow64() has
87 been successfully called
88
89 ********************************************************************/
90 extern "C" BOOL WIXAPI WcaIsWow64Initialized()
91 {
92 return s_fWow64Initialized;
93 }
94
95 /********************************************************************
96 WcaDisableWow64FSRedirection() - Disables Wow64 FS Redirection
97
98 ********************************************************************/
99 extern "C" HRESULT WIXAPI WcaDisableWow64FSRedirection()
100 {
101 AssertSz(s_fWow64Initialized && s_pfnDisableWow64 != NULL, "WcaDisableWow64FSRedirection() called, but Wow64 API was not initialized");
102
103 #ifdef DEBUG
104 AssertSz(!s_fWow64FSDisabled, "You must call WcaRevertWow64FSRedirection() before calling WcaDisableWow64FSRedirection() again");
105 #endif
106
107 HRESULT hr = S_OK;
108 if (s_pfnDisableWow64(&s_Wow64FSRevertState))
109 {
110 s_fWow64FSDisabled = TRUE;
111 }
112 else
113 {
114 ExitWithLastError(hr, "Failed to disable WOW64.");
115 }
116
117 LExit:
118 return hr;
119 }
120
121 /********************************************************************
122 WcaRevertWow64FSRedirection() - Reverts Wow64 FS Redirection to its
123 pre-disabled state
124
125 ********************************************************************/
126 extern "C" HRESULT WIXAPI WcaRevertWow64FSRedirection()
127 {
128 AssertSz(s_fWow64Initialized && s_pfnDisableWow64 != NULL, "WcaRevertWow64FSRedirection() called, but Wow64 API was not initialized");
129
130 #ifdef DEBUG
131 AssertSz(s_fWow64FSDisabled, "You must call WcaDisableWow64FSRedirection() before calling WcaRevertWow64FSRedirection()");
132 #endif
133
134 HRESULT hr = S_OK;
135 if (s_pfnRevertWow64(s_Wow64FSRevertState))
136 {
137 s_fWow64FSDisabled = FALSE;
138 }
139 else
140 {
141 ExitWithLastError(hr, "Failed to revert WOW64.");
142 }
143
144 LExit:
145 return hr;
146 }
147
148 /********************************************************************
149 WcaFinalizeWow64() - Cleans up after Wow64 API Initialization
150
151 ********************************************************************/
152 extern "C" HRESULT WIXAPI WcaFinalizeWow64()
153 {
154 if (s_fWow64FSDisabled)
155 {
156 #ifdef DEBUG
157 AssertSz(FALSE, "WcaFinalizeWow64() called while Filesystem redirection was disabled.");
158 #else
159 // If we aren't in debug mode, let's do our best to recover gracefully
160 WcaRevertWow64FSRedirection();
161 #endif
162 }
163
164 s_fWow64Initialized = FALSE;
165 s_pfnDisableWow64 = NULL;
166 s_pfnRevertWow64 = NULL;
167
168 return S_OK;
169 }