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
|
#
# Author:: Adam Edwards (<adamed@opscode.com>)
# Copyright:: Copyright (c) 2013 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'chef/exceptions'
require 'chef/platform/query_helpers'
require 'win32/api' if Chef::Platform.windows?
require 'chef/win32/api/process' if Chef::Platform.windows?
require 'chef/win32/api/error' if Chef::Platform.windows?
class Chef
module Mixin
module WindowsArchitectureHelper
if Chef::Platform.windows?
include Chef::ReservedNames::Win32::API::Process
include Chef::ReservedNames::Win32::API::Error
end
def node_windows_architecture(node)
node[:kernel][:machine].to_sym
end
def wow64_architecture_override_required?(node, desired_architecture)
desired_architecture == :x86_64 &&
node_windows_architecture(node) == :x86_64 &&
is_i386_process_on_x86_64_windows?
end
def with_os_architecture(node)
node ||= begin
os_arch = ENV['PROCESSOR_ARCHITEW6432'] ||
ENV['PROCESSOR_ARCHITECTURE']
Hash.new.tap do |n|
n[:kernel] = Hash.new
n[:kernel][:machine] = os_arch == 'AMD64' ? :x86_64 : :i386
end
end
wow64_redirection_state = nil
if wow64_architecture_override_required?(node, node_windows_architecture(node))
wow64_redirection_state = disable_wow64_file_redirection(node)
end
begin
yield
ensure
if wow64_redirection_state
restore_wow64_file_redirection(node, wow64_redirection_state)
end
end
end
def node_supports_windows_architecture?(node, desired_architecture)
assert_valid_windows_architecture!(desired_architecture)
return (node_windows_architecture(node) == :x86_64 ||
desired_architecture == :i386) ? true : false
end
def valid_windows_architecture?(architecture)
return (architecture == :x86_64) || (architecture == :i386)
end
def assert_valid_windows_architecture!(architecture)
if ! valid_windows_architecture?(architecture)
raise Chef::Exceptions::Win32ArchitectureIncorrect,
"The specified architecture was not valid. It must be one of :i386 or :x86_64"
end
end
def is_i386_process_on_x86_64_windows?
if Chef::Platform.windows?
is_64_bit_process_result = FFI::MemoryPointer.new(:int)
# The return value of IsWow64Process is nonzero value if the API call succeeds.
# The result data are returned in the last parameter, not the return value.
call_succeeded = IsWow64Process(GetCurrentProcess(), is_64_bit_process_result)
# The result is nonzero if IsWow64Process's calling process, in the case here
# this process, is running under WOW64, i.e. the result is nonzero if this
# process is 32-bit (aka :i386).
result = (call_succeeded != 0) && (is_64_bit_process_result.get_int(0) != 0)
else
false
end
end
def disable_wow64_file_redirection( node )
original_redirection_state = ['0'].pack('P')
if ( ( node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?)
win32_wow_64_disable_wow_64_fs_redirection =
::Win32::API.new('Wow64DisableWow64FsRedirection', 'P', 'L', 'kernel32')
succeeded = win32_wow_64_disable_wow_64_fs_redirection.call(original_redirection_state)
if succeeded == 0
raise Win32APIError "Failed to disable Wow64 file redirection"
end
end
original_redirection_state
end
def restore_wow64_file_redirection( node, original_redirection_state )
if ( (node_windows_architecture(node) == :x86_64) && ::Chef::Platform.windows?)
win32_wow_64_revert_wow_64_fs_redirection =
::Win32::API.new('Wow64RevertWow64FsRedirection', 'P', 'L', 'kernel32')
succeeded = win32_wow_64_revert_wow_64_fs_redirection.call(original_redirection_state)
if succeeded == 0
raise Win32APIError "Failed to revert Wow64 file redirection"
end
end
end
end
end
end
|