aboutsummaryrefslogtreecommitdiff
path: root/src/libs/wcautil/WixToolset.WcaUtil/wcawow64.cpp
blob: 8174c43e69bbf691b205d11c1fc2d170c870025a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// 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.

#include "precomp.h"

static HMODULE s_hKernel32;
static BOOL s_fWow64Initialized;
static BOOL (*s_pfnDisableWow64)(__out PVOID* );
static BOOL (*s_pfnRevertWow64)(__in PVOID );
static BOOL (*s_pfnIsWow64Process) (HANDLE, PBOOL);
static PVOID s_Wow64FSRevertState;
static BOOL s_fWow64FSDisabled;

/********************************************************************
 WcaInitializeWow64() - Initializes the Wow64 API

********************************************************************/
extern "C" HRESULT WIXAPI WcaInitializeWow64()
{
    AssertSz(WcaIsInitialized(), "WcaInitialize() should be called before calling WcaInitializeWow64()");
    AssertSz(!WcaIsWow64Initialized(), "WcaInitializeWow64() should not be called twice without calling WcaFinalizeWow64()");

    s_fWow64Initialized = FALSE;
    HRESULT hr = S_OK;
    s_Wow64FSRevertState = NULL;
    s_fWow64FSDisabled = false;

    // Test if we have access to the Wow64 API, and store the result in bWow64APIPresent
    s_hKernel32 = ::GetModuleHandleW(L"kernel32.dll");
    if (!s_hKernel32)
    {
        ExitWithLastError(hr, "failed to get handle to kernel32.dll");
    }

    // This will test if we have access to the Wow64 API
    s_pfnIsWow64Process = (BOOL (*)(HANDLE, PBOOL))::GetProcAddress(s_hKernel32, "IsWow64Process");
    if (NULL != s_pfnIsWow64Process)
    {
        s_pfnDisableWow64 = (BOOL (*)(PVOID *))::GetProcAddress(s_hKernel32, "Wow64DisableWow64FsRedirection");
        // If we fail, log the error but proceed, because we may not need a particular function, or the Wow64 API at all
        if (!s_pfnDisableWow64)
        {
            return S_FALSE;
        }

        s_pfnRevertWow64 = (BOOL (*)(PVOID))::GetProcAddress(s_hKernel32, "Wow64RevertWow64FsRedirection");
        if (!s_pfnRevertWow64)
        {
            return S_FALSE;
        }

        if (s_pfnDisableWow64 && s_pfnRevertWow64)
        {
            s_fWow64Initialized = TRUE;
        }
    }
    else
    {
        return S_FALSE;
    }

LExit:

    return hr;
}

/********************************************************************
 WcaIsWow64Process() - determines if the current process is running 
                       in WOW

********************************************************************/
extern "C" BOOL WIXAPI WcaIsWow64Process()
{
    BOOL fIsWow64Process = FALSE;
    if (s_fWow64Initialized)
    {
        if (!s_pfnIsWow64Process(GetCurrentProcess(), &fIsWow64Process))
        {
            // clear out the value since call failed
            fIsWow64Process = FALSE;
        }
    }
    return fIsWow64Process;
}

/********************************************************************
 WcaIsWow64Initialized() - determines if WcaInitializeWow64() has
                           been successfully called

********************************************************************/
extern "C" BOOL WIXAPI WcaIsWow64Initialized()
{
    return s_fWow64Initialized;
}

/********************************************************************
 WcaDisableWow64FSRedirection() - Disables Wow64 FS Redirection

********************************************************************/
extern "C" HRESULT WIXAPI WcaDisableWow64FSRedirection()
{
    AssertSz(s_fWow64Initialized && s_pfnDisableWow64 != NULL, "WcaDisableWow64FSRedirection() called, but Wow64 API was not initialized");

#ifdef DEBUG
    AssertSz(!s_fWow64FSDisabled, "You must call WcaRevertWow64FSRedirection() before calling WcaDisableWow64FSRedirection() again");
#endif

    HRESULT hr = S_OK;
    if (s_pfnDisableWow64(&s_Wow64FSRevertState))
    {
        s_fWow64FSDisabled = TRUE;
    }
    else
    {
        ExitWithLastError(hr, "Failed to disable WOW64.");
    }

LExit:
    return hr;
}

/********************************************************************
 WcaRevertWow64FSRedirection() - Reverts Wow64 FS Redirection to its
                                 pre-disabled state

********************************************************************/
extern "C" HRESULT WIXAPI WcaRevertWow64FSRedirection()
{
    AssertSz(s_fWow64Initialized && s_pfnDisableWow64 != NULL, "WcaRevertWow64FSRedirection() called, but Wow64 API was not initialized");

#ifdef DEBUG
    AssertSz(s_fWow64FSDisabled, "You must call WcaDisableWow64FSRedirection() before calling WcaRevertWow64FSRedirection()");
#endif

    HRESULT hr = S_OK;
    if (s_pfnRevertWow64(s_Wow64FSRevertState))
    {
        s_fWow64FSDisabled = FALSE;
    }
    else
    {
        ExitWithLastError(hr, "Failed to revert WOW64.");
    }

LExit:
    return hr;
}

/********************************************************************
 WcaFinalizeWow64() - Cleans up after Wow64 API Initialization

********************************************************************/
extern "C" HRESULT WIXAPI WcaFinalizeWow64()
{
    if (s_fWow64FSDisabled)
    {
#ifdef DEBUG
        AssertSz(FALSE, "WcaFinalizeWow64() called while Filesystem redirection was disabled.");
#else
        // If we aren't in debug mode, let's do our best to recover gracefully
        WcaRevertWow64FSRedirection();
#endif
    }

    s_fWow64Initialized = FALSE;
    s_pfnDisableWow64 = NULL;
    s_pfnRevertWow64 = NULL;

    return S_OK;
}