module Puppet::Util::Windows::Process
Constants
- CREATE_NO_WINDOW
docs.microsoft.com/en-us/windows/desktop/ProcThread/process-creation-flags
- ERROR_NO_SUCH_PRIVILEGE
- MAX_PATH_LENGTH
docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation
- PROCESS_QUERY_INFORMATION
docs.microsoft.com/en-us/windows/desktop/ProcThread/process-security-and-access-rights
- TOKEN_ALL_ACCESS
- TOKEN_QUERY
- WAIT_INTERVAL
- WAIT_TIMEOUT
Public Class Methods
Returns whether or not the owner of the current process is running with elevated security privileges.
Only supported on Windows Vista or later.
# File lib/puppet/util/windows/process.rb 253 def elevated_security? 254 # default / pre-Vista 255 elevated = false 256 handle = nil 257 258 begin 259 handle = get_current_process 260 open_process_token(handle, TOKEN_QUERY) do |token_handle| 261 get_token_information(token_handle, :TokenElevation) do |token_info| 262 token_elevation = parse_token_information_as_token_elevation(token_info) 263 # TokenIsElevated member of the TOKEN_ELEVATION struct 264 elevated = token_elevation[:TokenIsElevated] != 0 265 end 266 end 267 268 elevated 269 rescue Puppet::Util::Windows::Error => e 270 raise e if e.code != ERROR_NO_SUCH_PRIVILEGE 271 ensure 272 FFI::WIN32.CloseHandle(handle) if handle 273 end 274 end
# File lib/puppet/util/windows/process.rb 19 def execute(command, arguments, stdin, stdout, stderr) 20 create_args = { 21 :command_line => command, 22 :startup_info => { 23 :stdin => stdin, 24 :stdout => stdout, 25 :stderr => stderr 26 }, 27 :close_handles => false, 28 } 29 if arguments[:suppress_window] 30 create_args[:creation_flags] = CREATE_NO_WINDOW 31 end 32 if arguments[:cwd] 33 create_args[:cwd] = arguments[:cwd] 34 end 35 Process.create(create_args) 36 end
# File lib/puppet/util/windows/process.rb 62 def get_current_process 63 # this pseudo-handle does not require closing per MSDN docs 64 GetCurrentProcess() 65 end
Returns a hash of the current environment variables encoded as UTF-8 The memory block returned from GetEnvironmentStringsW is double-null terminated and the vars are paired as below; Var1=Value10 Var2=Value20 VarX=ValueX00 Note - Some env variable names start with '=' and are excluded from the return value Note - The env_ptr MUST be freed using the FreeEnvironmentStringsW function Note - There is no technical limitation to the size of the environment block returned.
However a practical limit of 64K is used as no single environment variable can exceed 32KB
# File lib/puppet/util/windows/process.rb 306 def get_environment_strings 307 env_ptr = GetEnvironmentStringsW() 308 309 # pass :invalid => :replace to the Ruby String#encode to use replacement characters 310 pairs = env_ptr.read_arbitrary_wide_string_up_to(65534, :double_null, { :invalid => :replace }) 311 .split(?\x00) 312 .reject { |env_str| env_str.nil? || env_str.empty? || env_str[0] == '=' } 313 .reject do |env_str| 314 # reject any string containing the Unicode replacement character 315 if env_str.include?("\uFFFD") 316 Puppet.warning(_("Discarding environment variable %{string} which contains invalid bytes") % { string: env_str }) 317 true 318 end 319 end 320 .map { |env_pair| env_pair.split('=', 2) } 321 Hash[ pairs ] 322 ensure 323 if env_ptr && ! env_ptr.null? 324 if FreeEnvironmentStringsW(env_ptr) == FFI::WIN32_FALSE 325 Puppet.debug "FreeEnvironmentStringsW memory leak" 326 end 327 end 328 end
# File lib/puppet/util/windows/process.rb 123 def get_process_image_name_by_pid(pid) 124 image_name = String.new 125 126 Puppet::Util::Windows::Security.with_privilege(Puppet::Util::Windows::Security::SE_DEBUG_NAME) do 127 open_process(PROCESS_QUERY_INFORMATION, false, pid) do |phandle| 128 FFI::MemoryPointer.new(:dword, 1) do |exe_name_length_ptr| 129 # UTF is 2 bytes/char: 130 max_chars = MAX_PATH_LENGTH + 1 131 exe_name_length_ptr.write_dword(max_chars) 132 FFI::MemoryPointer.new(:wchar, max_chars) do |exe_name_ptr| 133 use_win32_path_format = 0 134 result = QueryFullProcessImageNameW(phandle, use_win32_path_format, exe_name_ptr, exe_name_length_ptr) 135 if result == FFI::WIN32_FALSE 136 raise Puppet::Util::Windows::Error.new( 137 "QueryFullProcessImageNameW(phandle, #{use_win32_path_format}, " + 138 "exe_name_ptr, #{max_chars}") 139 end 140 image_name = exe_name_ptr.read_wide_string(exe_name_length_ptr.read_dword) 141 end 142 end 143 end 144 end 145 146 image_name 147 end
# File lib/puppet/util/windows/process.rb 350 def get_system_default_ui_language 351 GetSystemDefaultUILanguage() 352 end
# File lib/puppet/util/windows/process.rb 171 def get_token_information(token_handle, token_information, &block) 172 # to determine buffer size 173 FFI::MemoryPointer.new(:dword, 1) do |return_length_ptr| 174 result = GetTokenInformation(token_handle, token_information, nil, 0, return_length_ptr) 175 return_length = return_length_ptr.read_dword 176 177 if return_length <= 0 178 raise Puppet::Util::Windows::Error.new( 179 "GetTokenInformation(#{token_handle}, #{token_information}, nil, 0, #{return_length_ptr})") 180 end 181 182 # re-call API with properly sized buffer for all results 183 FFI::MemoryPointer.new(return_length) do |token_information_buf| 184 result = GetTokenInformation(token_handle, token_information, 185 token_information_buf, return_length, return_length_ptr) 186 187 if result == FFI::WIN32_FALSE 188 raise Puppet::Util::Windows::Error.new( 189 "GetTokenInformation(#{token_handle}, #{token_information}, #{token_information_buf}, " + 190 "#{return_length}, #{return_length_ptr})") 191 end 192 193 yield token_information_buf 194 end 195 end 196 197 # GetTokenInformation buffer has been cleaned up by this point, nothing to return 198 nil 199 end
# File lib/puppet/util/windows/process.rb 150 def lookup_privilege_value(name, system_name = '', &block) 151 FFI::MemoryPointer.new(LUID.size) do |luid_ptr| 152 result = LookupPrivilegeValueW( 153 wide_string(system_name), 154 wide_string(name.to_s), 155 luid_ptr 156 ) 157 158 if result == FFI::WIN32_FALSE 159 raise Puppet::Util::Windows::Error.new( 160 "LookupPrivilegeValue(#{system_name}, #{name}, #{luid_ptr})") 161 end 162 163 yield LUID.new(luid_ptr) 164 end 165 166 # the underlying MemoryPointer for LUID is cleaned up by this point 167 nil 168 end
# File lib/puppet/util/windows/process.rb 68 def open_process(desired_access, inherit_handle, process_id, &block) 69 phandle = nil 70 inherit = inherit_handle ? FFI::WIN32_TRUE : FFI::WIN32_FALSE 71 begin 72 phandle = OpenProcess(desired_access, inherit, process_id) 73 if phandle == FFI::Pointer::NULL_HANDLE 74 raise Puppet::Util::Windows::Error.new( 75 "OpenProcess(#{desired_access.to_s(8)}, #{inherit}, #{process_id})") 76 end 77 78 yield phandle 79 ensure 80 FFI::WIN32.CloseHandle(phandle) if phandle 81 end 82 83 # phandle has had CloseHandle called against it, so nothing to return 84 nil 85 end
# File lib/puppet/util/windows/process.rb 88 def open_process_token(handle, desired_access, &block) 89 token_handle = nil 90 begin 91 FFI::MemoryPointer.new(:handle, 1) do |token_handle_ptr| 92 result = OpenProcessToken(handle, desired_access, token_handle_ptr) 93 if result == FFI::WIN32_FALSE 94 raise Puppet::Util::Windows::Error.new( 95 "OpenProcessToken(#{handle}, #{desired_access.to_s(8)}, #{token_handle_ptr})") 96 end 97 98 yield token_handle = token_handle_ptr.read_handle 99 end 100 101 token_handle 102 ensure 103 FFI::WIN32.CloseHandle(token_handle) if token_handle 104 end 105 106 # token_handle has had CloseHandle called against it, so nothing to return 107 nil 108 end
# File lib/puppet/util/windows/process.rb 218 def parse_token_information_as_token_elevation(token_information_buf) 219 TOKEN_ELEVATION.new(token_information_buf) 220 end
# File lib/puppet/util/windows/process.rb 202 def parse_token_information_as_token_privileges(token_information_buf) 203 raw_privileges = TOKEN_PRIVILEGES.new(token_information_buf) 204 privileges = { :count => raw_privileges[:PrivilegeCount], :privileges => [] } 205 206 offset = token_information_buf + TOKEN_PRIVILEGES.offset_of(:Privileges) 207 privilege_ptr = FFI::Pointer.new(LUID_AND_ATTRIBUTES, offset) 208 209 # extract each instance of LUID_AND_ATTRIBUTES 210 0.upto(privileges[:count] - 1) do |i| 211 privileges[:privileges] << LUID_AND_ATTRIBUTES.new(privilege_ptr[i]) 212 end 213 214 privileges 215 end
# File lib/puppet/util/windows/process.rb 225 def process_privilege_symlink? 226 privilege_symlink = false 227 handle = get_current_process 228 open_process_token(handle, TOKEN_ALL_ACCESS) do |token_handle| 229 lookup_privilege_value('SeCreateSymbolicLinkPrivilege') do |luid| 230 get_token_information(token_handle, :TokenPrivileges) do |token_info| 231 token_privileges = parse_token_information_as_token_privileges(token_info) 232 privilege_symlink = token_privileges[:privileges].any? { |p| p[:Luid].values == luid.values } 233 end 234 end 235 end 236 237 privilege_symlink 238 rescue Puppet::Util::Windows::Error => e 239 if e.code == ERROR_NO_SUCH_PRIVILEGE 240 false # pre-Vista 241 else 242 raise e 243 end 244 end
# File lib/puppet/util/windows/process.rb 331 def set_environment_variable(name, val) 332 raise Puppet::Util::Windows::Error(_('environment variable name must not be nil or empty')) if ! name || name.empty? 333 334 FFI::MemoryPointer.from_string_to_wide_string(name) do |name_ptr| 335 if (val.nil?) 336 if SetEnvironmentVariableW(name_ptr, FFI::MemoryPointer::NULL) == FFI::WIN32_FALSE 337 raise Puppet::Util::Windows::Error.new(_("Failed to remove environment variable: %{name}") % { name: name }) 338 end 339 else 340 FFI::MemoryPointer.from_string_to_wide_string(val) do |val_ptr| 341 if SetEnvironmentVariableW(name_ptr, val_ptr) == FFI::WIN32_FALSE 342 raise Puppet::Util::Windows::Error.new(_("Failed to set environment variable: %{name}") % { name: name }) 343 end 344 end 345 end 346 end 347 end
Returns whether or not the OS has the ability to set elevated token information.
Returns true on Windows Vista or later, otherwise false
# File lib/puppet/util/windows/process.rb 360 def supports_elevated_security? 361 windows_major_version >= 6 362 end
# File lib/puppet/util/windows/process.rb 39 def wait_process(handle) 40 while WaitForSingleObject(handle, WAIT_INTERVAL) == WAIT_TIMEOUT 41 sleep(0) 42 end 43 44 exit_status = -1 45 FFI::MemoryPointer.new(:dword, 1) do |exit_status_ptr| 46 if GetExitCodeProcess(handle, exit_status_ptr) == FFI::WIN32_FALSE 47 raise Puppet::Util::Windows::Error.new(_("Failed to get child process exit code")) 48 end 49 exit_status = exit_status_ptr.read_dword 50 51 # $CHILD_STATUS is not set when calling win32/process Process.create 52 # and since it's read-only, we can't set it. But we can execute a 53 # a shell that simply returns the desired exit status, which has the 54 # desired effect. 55 %x{#{ENV['COMSPEC']} /c exit #{exit_status}} 56 end 57 58 exit_status 59 end
# File lib/puppet/util/windows/process.rb 277 def windows_major_version 278 ver = 0 279 280 FFI::MemoryPointer.new(OSVERSIONINFO.size) do |os_version_ptr| 281 os_version = OSVERSIONINFO.new(os_version_ptr) 282 os_version[:dwOSVersionInfoSize] = OSVERSIONINFO.size 283 284 result = GetVersionExW(os_version_ptr) 285 286 if result == FFI::WIN32_FALSE 287 raise Puppet::Util::Windows::Error.new(_("GetVersionEx failed")) 288 end 289 290 ver = os_version[:dwMajorVersion] 291 end 292 293 ver 294 end
Execute a block with the current process token
# File lib/puppet/util/windows/process.rb 112 def with_process_token(access, &block) 113 handle = get_current_process 114 open_process_token(handle, access) do |token_handle| 115 yield token_handle 116 end 117 118 # all handles have been closed, so nothing to safely return 119 nil 120 end
Private Instance Methods
Returns whether or not the owner of the current process is running with elevated security privileges.
Only supported on Windows Vista or later.
# File lib/puppet/util/windows/process.rb 253 def elevated_security? 254 # default / pre-Vista 255 elevated = false 256 handle = nil 257 258 begin 259 handle = get_current_process 260 open_process_token(handle, TOKEN_QUERY) do |token_handle| 261 get_token_information(token_handle, :TokenElevation) do |token_info| 262 token_elevation = parse_token_information_as_token_elevation(token_info) 263 # TokenIsElevated member of the TOKEN_ELEVATION struct 264 elevated = token_elevation[:TokenIsElevated] != 0 265 end 266 end 267 268 elevated 269 rescue Puppet::Util::Windows::Error => e 270 raise e if e.code != ERROR_NO_SUCH_PRIVILEGE 271 ensure 272 FFI::WIN32.CloseHandle(handle) if handle 273 end 274 end
# File lib/puppet/util/windows/process.rb 19 def execute(command, arguments, stdin, stdout, stderr) 20 create_args = { 21 :command_line => command, 22 :startup_info => { 23 :stdin => stdin, 24 :stdout => stdout, 25 :stderr => stderr 26 }, 27 :close_handles => false, 28 } 29 if arguments[:suppress_window] 30 create_args[:creation_flags] = CREATE_NO_WINDOW 31 end 32 if arguments[:cwd] 33 create_args[:cwd] = arguments[:cwd] 34 end 35 Process.create(create_args) 36 end
# File lib/puppet/util/windows/process.rb 62 def get_current_process 63 # this pseudo-handle does not require closing per MSDN docs 64 GetCurrentProcess() 65 end
Returns a hash of the current environment variables encoded as UTF-8 The memory block returned from GetEnvironmentStringsW is double-null terminated and the vars are paired as below; Var1=Value10 Var2=Value20 VarX=ValueX00 Note - Some env variable names start with '=' and are excluded from the return value Note - The env_ptr MUST be freed using the FreeEnvironmentStringsW function Note - There is no technical limitation to the size of the environment block returned.
However a practical limit of 64K is used as no single environment variable can exceed 32KB
# File lib/puppet/util/windows/process.rb 306 def get_environment_strings 307 env_ptr = GetEnvironmentStringsW() 308 309 # pass :invalid => :replace to the Ruby String#encode to use replacement characters 310 pairs = env_ptr.read_arbitrary_wide_string_up_to(65534, :double_null, { :invalid => :replace }) 311 .split(?\x00) 312 .reject { |env_str| env_str.nil? || env_str.empty? || env_str[0] == '=' } 313 .reject do |env_str| 314 # reject any string containing the Unicode replacement character 315 if env_str.include?("\uFFFD") 316 Puppet.warning(_("Discarding environment variable %{string} which contains invalid bytes") % { string: env_str }) 317 true 318 end 319 end 320 .map { |env_pair| env_pair.split('=', 2) } 321 Hash[ pairs ] 322 ensure 323 if env_ptr && ! env_ptr.null? 324 if FreeEnvironmentStringsW(env_ptr) == FFI::WIN32_FALSE 325 Puppet.debug "FreeEnvironmentStringsW memory leak" 326 end 327 end 328 end
# File lib/puppet/util/windows/process.rb 123 def get_process_image_name_by_pid(pid) 124 image_name = String.new 125 126 Puppet::Util::Windows::Security.with_privilege(Puppet::Util::Windows::Security::SE_DEBUG_NAME) do 127 open_process(PROCESS_QUERY_INFORMATION, false, pid) do |phandle| 128 FFI::MemoryPointer.new(:dword, 1) do |exe_name_length_ptr| 129 # UTF is 2 bytes/char: 130 max_chars = MAX_PATH_LENGTH + 1 131 exe_name_length_ptr.write_dword(max_chars) 132 FFI::MemoryPointer.new(:wchar, max_chars) do |exe_name_ptr| 133 use_win32_path_format = 0 134 result = QueryFullProcessImageNameW(phandle, use_win32_path_format, exe_name_ptr, exe_name_length_ptr) 135 if result == FFI::WIN32_FALSE 136 raise Puppet::Util::Windows::Error.new( 137 "QueryFullProcessImageNameW(phandle, #{use_win32_path_format}, " + 138 "exe_name_ptr, #{max_chars}") 139 end 140 image_name = exe_name_ptr.read_wide_string(exe_name_length_ptr.read_dword) 141 end 142 end 143 end 144 end 145 146 image_name 147 end
# File lib/puppet/util/windows/process.rb 350 def get_system_default_ui_language 351 GetSystemDefaultUILanguage() 352 end
# File lib/puppet/util/windows/process.rb 171 def get_token_information(token_handle, token_information, &block) 172 # to determine buffer size 173 FFI::MemoryPointer.new(:dword, 1) do |return_length_ptr| 174 result = GetTokenInformation(token_handle, token_information, nil, 0, return_length_ptr) 175 return_length = return_length_ptr.read_dword 176 177 if return_length <= 0 178 raise Puppet::Util::Windows::Error.new( 179 "GetTokenInformation(#{token_handle}, #{token_information}, nil, 0, #{return_length_ptr})") 180 end 181 182 # re-call API with properly sized buffer for all results 183 FFI::MemoryPointer.new(return_length) do |token_information_buf| 184 result = GetTokenInformation(token_handle, token_information, 185 token_information_buf, return_length, return_length_ptr) 186 187 if result == FFI::WIN32_FALSE 188 raise Puppet::Util::Windows::Error.new( 189 "GetTokenInformation(#{token_handle}, #{token_information}, #{token_information_buf}, " + 190 "#{return_length}, #{return_length_ptr})") 191 end 192 193 yield token_information_buf 194 end 195 end 196 197 # GetTokenInformation buffer has been cleaned up by this point, nothing to return 198 nil 199 end
# File lib/puppet/util/windows/process.rb 150 def lookup_privilege_value(name, system_name = '', &block) 151 FFI::MemoryPointer.new(LUID.size) do |luid_ptr| 152 result = LookupPrivilegeValueW( 153 wide_string(system_name), 154 wide_string(name.to_s), 155 luid_ptr 156 ) 157 158 if result == FFI::WIN32_FALSE 159 raise Puppet::Util::Windows::Error.new( 160 "LookupPrivilegeValue(#{system_name}, #{name}, #{luid_ptr})") 161 end 162 163 yield LUID.new(luid_ptr) 164 end 165 166 # the underlying MemoryPointer for LUID is cleaned up by this point 167 nil 168 end
# File lib/puppet/util/windows/process.rb 68 def open_process(desired_access, inherit_handle, process_id, &block) 69 phandle = nil 70 inherit = inherit_handle ? FFI::WIN32_TRUE : FFI::WIN32_FALSE 71 begin 72 phandle = OpenProcess(desired_access, inherit, process_id) 73 if phandle == FFI::Pointer::NULL_HANDLE 74 raise Puppet::Util::Windows::Error.new( 75 "OpenProcess(#{desired_access.to_s(8)}, #{inherit}, #{process_id})") 76 end 77 78 yield phandle 79 ensure 80 FFI::WIN32.CloseHandle(phandle) if phandle 81 end 82 83 # phandle has had CloseHandle called against it, so nothing to return 84 nil 85 end
# File lib/puppet/util/windows/process.rb 88 def open_process_token(handle, desired_access, &block) 89 token_handle = nil 90 begin 91 FFI::MemoryPointer.new(:handle, 1) do |token_handle_ptr| 92 result = OpenProcessToken(handle, desired_access, token_handle_ptr) 93 if result == FFI::WIN32_FALSE 94 raise Puppet::Util::Windows::Error.new( 95 "OpenProcessToken(#{handle}, #{desired_access.to_s(8)}, #{token_handle_ptr})") 96 end 97 98 yield token_handle = token_handle_ptr.read_handle 99 end 100 101 token_handle 102 ensure 103 FFI::WIN32.CloseHandle(token_handle) if token_handle 104 end 105 106 # token_handle has had CloseHandle called against it, so nothing to return 107 nil 108 end
# File lib/puppet/util/windows/process.rb 218 def parse_token_information_as_token_elevation(token_information_buf) 219 TOKEN_ELEVATION.new(token_information_buf) 220 end
# File lib/puppet/util/windows/process.rb 202 def parse_token_information_as_token_privileges(token_information_buf) 203 raw_privileges = TOKEN_PRIVILEGES.new(token_information_buf) 204 privileges = { :count => raw_privileges[:PrivilegeCount], :privileges => [] } 205 206 offset = token_information_buf + TOKEN_PRIVILEGES.offset_of(:Privileges) 207 privilege_ptr = FFI::Pointer.new(LUID_AND_ATTRIBUTES, offset) 208 209 # extract each instance of LUID_AND_ATTRIBUTES 210 0.upto(privileges[:count] - 1) do |i| 211 privileges[:privileges] << LUID_AND_ATTRIBUTES.new(privilege_ptr[i]) 212 end 213 214 privileges 215 end
# File lib/puppet/util/windows/process.rb 225 def process_privilege_symlink? 226 privilege_symlink = false 227 handle = get_current_process 228 open_process_token(handle, TOKEN_ALL_ACCESS) do |token_handle| 229 lookup_privilege_value('SeCreateSymbolicLinkPrivilege') do |luid| 230 get_token_information(token_handle, :TokenPrivileges) do |token_info| 231 token_privileges = parse_token_information_as_token_privileges(token_info) 232 privilege_symlink = token_privileges[:privileges].any? { |p| p[:Luid].values == luid.values } 233 end 234 end 235 end 236 237 privilege_symlink 238 rescue Puppet::Util::Windows::Error => e 239 if e.code == ERROR_NO_SUCH_PRIVILEGE 240 false # pre-Vista 241 else 242 raise e 243 end 244 end
# File lib/puppet/util/windows/process.rb 331 def set_environment_variable(name, val) 332 raise Puppet::Util::Windows::Error(_('environment variable name must not be nil or empty')) if ! name || name.empty? 333 334 FFI::MemoryPointer.from_string_to_wide_string(name) do |name_ptr| 335 if (val.nil?) 336 if SetEnvironmentVariableW(name_ptr, FFI::MemoryPointer::NULL) == FFI::WIN32_FALSE 337 raise Puppet::Util::Windows::Error.new(_("Failed to remove environment variable: %{name}") % { name: name }) 338 end 339 else 340 FFI::MemoryPointer.from_string_to_wide_string(val) do |val_ptr| 341 if SetEnvironmentVariableW(name_ptr, val_ptr) == FFI::WIN32_FALSE 342 raise Puppet::Util::Windows::Error.new(_("Failed to set environment variable: %{name}") % { name: name }) 343 end 344 end 345 end 346 end 347 end
Returns whether or not the OS has the ability to set elevated token information.
Returns true on Windows Vista or later, otherwise false
# File lib/puppet/util/windows/process.rb 360 def supports_elevated_security? 361 windows_major_version >= 6 362 end
# File lib/puppet/util/windows/process.rb 39 def wait_process(handle) 40 while WaitForSingleObject(handle, WAIT_INTERVAL) == WAIT_TIMEOUT 41 sleep(0) 42 end 43 44 exit_status = -1 45 FFI::MemoryPointer.new(:dword, 1) do |exit_status_ptr| 46 if GetExitCodeProcess(handle, exit_status_ptr) == FFI::WIN32_FALSE 47 raise Puppet::Util::Windows::Error.new(_("Failed to get child process exit code")) 48 end 49 exit_status = exit_status_ptr.read_dword 50 51 # $CHILD_STATUS is not set when calling win32/process Process.create 52 # and since it's read-only, we can't set it. But we can execute a 53 # a shell that simply returns the desired exit status, which has the 54 # desired effect. 55 %x{#{ENV['COMSPEC']} /c exit #{exit_status}} 56 end 57 58 exit_status 59 end
# File lib/puppet/util/windows/process.rb 277 def windows_major_version 278 ver = 0 279 280 FFI::MemoryPointer.new(OSVERSIONINFO.size) do |os_version_ptr| 281 os_version = OSVERSIONINFO.new(os_version_ptr) 282 os_version[:dwOSVersionInfoSize] = OSVERSIONINFO.size 283 284 result = GetVersionExW(os_version_ptr) 285 286 if result == FFI::WIN32_FALSE 287 raise Puppet::Util::Windows::Error.new(_("GetVersionEx failed")) 288 end 289 290 ver = os_version[:dwMajorVersion] 291 end 292 293 ver 294 end
Execute a block with the current process token
# File lib/puppet/util/windows/process.rb 112 def with_process_token(access, &block) 113 handle = get_current_process 114 open_process_token(handle, access) do |token_handle| 115 yield token_handle 116 end 117 118 # all handles have been closed, so nothing to safely return 119 nil 120 end