Module: Puppet::Util::Windows::Process Private

Extended by:
FFI::Windows::Functions, String
Includes:
FFI::Windows::Structs
Defined in:
lib/puppet/util/windows/process.rb

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Constant Summary collapse

WAIT_TIMEOUT =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

0x102
WAIT_INTERVAL =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

200
CREATE_NO_WINDOW =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

docs.microsoft.com/en-us/windows/desktop/ProcThread/process-creation-flags

0x08000000
PROCESS_QUERY_INFORMATION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

docs.microsoft.com/en-us/windows/desktop/ProcThread/process-security-and-access-rights

0x0400
MAX_PATH_LENGTH =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation

32767
TOKEN_ALL_ACCESS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

0xF01FF
ERROR_NO_SUCH_PRIVILEGE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

1313
TOKEN_QUERY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

0x0008

Constants included from FFI::Windows::Functions

FFI::Windows::Functions::SC_ENUM_TYPE, FFI::Windows::Functions::SC_STATUS_TYPE

Constants included from FFI::Windows::Constants

FFI::Windows::Constants::ABOVE_NORMAL_PRIORITY_CLASS, FFI::Windows::Constants::ALL_SERVICE_TYPES, FFI::Windows::Constants::BELOW_NORMAL_PRIORITY_CLASS, FFI::Windows::Constants::CREATE_BREAKAWAY_FROM_JOB, FFI::Windows::Constants::CREATE_DEFAULT_ERROR_MODE, FFI::Windows::Constants::CREATE_NEW_CONSOLE, FFI::Windows::Constants::CREATE_NEW_PROCESS_GROUP, FFI::Windows::Constants::CREATE_PRESERVE_CODE_AUTHZ_LEVEL, FFI::Windows::Constants::CREATE_PROTECTED_PROCESS, FFI::Windows::Constants::CREATE_SEPARATE_WOW_VDM, FFI::Windows::Constants::CREATE_SHARED_WOW_VDM, FFI::Windows::Constants::CREATE_SUSPENDED, FFI::Windows::Constants::CREATE_UNICODE_ENVIRONMENT, FFI::Windows::Constants::DEBUG_ONLY_THIS_PROCESS, FFI::Windows::Constants::DEBUG_PROCESS, FFI::Windows::Constants::DELETE, FFI::Windows::Constants::DETACHED_PROCESS, FFI::Windows::Constants::ERROR_ALREADY_EXISTS, FFI::Windows::Constants::ERROR_FILE_NOT_FOUND, FFI::Windows::Constants::ERROR_PATH_NOT_FOUND, FFI::Windows::Constants::ERROR_SERVICE_DOES_NOT_EXIST, FFI::Windows::Constants::FILE_ALL_ACCESS, FFI::Windows::Constants::FILE_APPEND_DATA, FFI::Windows::Constants::FILE_ATTRIBUTE_DIRECTORY, FFI::Windows::Constants::FILE_ATTRIBUTE_READONLY, FFI::Windows::Constants::FILE_ATTRIBUTE_REPARSE_POINT, FFI::Windows::Constants::FILE_DELETE_CHILD, FFI::Windows::Constants::FILE_DEVICE_FILE_SYSTEM, FFI::Windows::Constants::FILE_EXECUTE, FFI::Windows::Constants::FILE_FLAG_BACKUP_SEMANTICS, FFI::Windows::Constants::FILE_FLAG_OPEN_REPARSE_POINT, FFI::Windows::Constants::FILE_GENERIC_EXECUTE, FFI::Windows::Constants::FILE_GENERIC_READ, FFI::Windows::Constants::FILE_GENERIC_WRITE, FFI::Windows::Constants::FILE_READ_ATTRIBUTES, FFI::Windows::Constants::FILE_READ_DATA, FFI::Windows::Constants::FILE_READ_EA, FFI::Windows::Constants::FILE_SHARE_READ, FFI::Windows::Constants::FILE_SHARE_WRITE, FFI::Windows::Constants::FILE_WRITE_ATTRIBUTES, FFI::Windows::Constants::FILE_WRITE_DATA, FFI::Windows::Constants::FILE_WRITE_EA, FFI::Windows::Constants::FINAL_STATES, FFI::Windows::Constants::FSCTL_GET_REPARSE_POINT, FFI::Windows::Constants::GENERIC_ALL, FFI::Windows::Constants::GENERIC_EXECUTE, FFI::Windows::Constants::GENERIC_READ, FFI::Windows::Constants::GENERIC_WRITE, FFI::Windows::Constants::HANDLE_FLAG_INHERIT, FFI::Windows::Constants::HIGH_PRIORITY_CLASS, FFI::Windows::Constants::IDLE_PRIORITY_CLASS, FFI::Windows::Constants::INHERIT_PARENT_AFFINITY, FFI::Windows::Constants::INVALID_FILE_ATTRIBUTES, FFI::Windows::Constants::INVALID_HANDLE_VALUE, FFI::Windows::Constants::IO_REPARSE_TAG_CSV, FFI::Windows::Constants::IO_REPARSE_TAG_DEDUP, FFI::Windows::Constants::IO_REPARSE_TAG_DFS, FFI::Windows::Constants::IO_REPARSE_TAG_DFSR, FFI::Windows::Constants::IO_REPARSE_TAG_HSM, FFI::Windows::Constants::IO_REPARSE_TAG_HSM2, FFI::Windows::Constants::IO_REPARSE_TAG_MOUNT_POINT, FFI::Windows::Constants::IO_REPARSE_TAG_NFS, FFI::Windows::Constants::IO_REPARSE_TAG_SIS, FFI::Windows::Constants::IO_REPARSE_TAG_SYMLINK, FFI::Windows::Constants::IO_REPARSE_TAG_WIM, FFI::Windows::Constants::LOGON_WITH_PROFILE, FFI::Windows::Constants::MAXIMUM_REPARSE_DATA_BUFFER_SIZE, FFI::Windows::Constants::METHOD_BUFFERED, FFI::Windows::Constants::NORMAL_PRIORITY_CLASS, FFI::Windows::Constants::OPEN_EXISTING, FFI::Windows::Constants::PROCESS_ALL_ACCESS, FFI::Windows::Constants::PROCESS_SET_INFORMATION, FFI::Windows::Constants::PROCESS_TERMINATE, FFI::Windows::Constants::PROCESS_VM_READ, FFI::Windows::Constants::REALTIME_PRIORITY_CLASS, FFI::Windows::Constants::REPLACEFILE_IGNORE_ACL_ERRORS, FFI::Windows::Constants::REPLACEFILE_IGNORE_MERGE_ERRORS, FFI::Windows::Constants::REPLACEFILE_WRITE_THROUGH, FFI::Windows::Constants::SC_MANAGER_ALL_ACCESS, FFI::Windows::Constants::SC_MANAGER_CONNECT, FFI::Windows::Constants::SC_MANAGER_CREATE_SERVICE, FFI::Windows::Constants::SC_MANAGER_ENUMERATE_SERVICE, FFI::Windows::Constants::SC_MANAGER_LOCK, FFI::Windows::Constants::SC_MANAGER_MODIFY_BOOT_CONFIG, FFI::Windows::Constants::SC_MANAGER_QUERY_LOCK_STATUS, FFI::Windows::Constants::SEM_FAILCRITICALERRORS, FFI::Windows::Constants::SEM_NOGPFAULTERRORBOX, FFI::Windows::Constants::SERVICENAME_MAX, FFI::Windows::Constants::SERVICE_ACCEPT_HARDWAREPROFILECHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_NETBINDCHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_PARAMCHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_PAUSE_CONTINUE, FFI::Windows::Constants::SERVICE_ACCEPT_POWEREVENT, FFI::Windows::Constants::SERVICE_ACCEPT_PRESHUTDOWN, FFI::Windows::Constants::SERVICE_ACCEPT_SESSIONCHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_SHUTDOWN, FFI::Windows::Constants::SERVICE_ACCEPT_STOP, FFI::Windows::Constants::SERVICE_ACCEPT_TIMECHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_TRIGGEREVENT, FFI::Windows::Constants::SERVICE_ACCEPT_USER_LOGOFF, FFI::Windows::Constants::SERVICE_ACTIVE, FFI::Windows::Constants::SERVICE_ALL_ACCESS, FFI::Windows::Constants::SERVICE_AUTO_START, FFI::Windows::Constants::SERVICE_BOOT_START, FFI::Windows::Constants::SERVICE_CHANGE_CONFIG, FFI::Windows::Constants::SERVICE_CONFIG_DELAYED_AUTO_START_INFO, FFI::Windows::Constants::SERVICE_CONFIG_DESCRIPTION, FFI::Windows::Constants::SERVICE_CONFIG_FAILURE_ACTIONS, FFI::Windows::Constants::SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, FFI::Windows::Constants::SERVICE_CONFIG_LAUNCH_PROTECTED, FFI::Windows::Constants::SERVICE_CONFIG_PREFERRED_NODE, FFI::Windows::Constants::SERVICE_CONFIG_PRESHUTDOWN_INFO, FFI::Windows::Constants::SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, FFI::Windows::Constants::SERVICE_CONFIG_SERVICE_SID_INFO, FFI::Windows::Constants::SERVICE_CONFIG_TRIGGER_INFO, FFI::Windows::Constants::SERVICE_CONFIG_TYPES, FFI::Windows::Constants::SERVICE_CONTINUE_PENDING, FFI::Windows::Constants::SERVICE_CONTROL_CONTINUE, FFI::Windows::Constants::SERVICE_CONTROL_DEVICEEVENT, FFI::Windows::Constants::SERVICE_CONTROL_HARDWAREPROFILECHANGE, FFI::Windows::Constants::SERVICE_CONTROL_INTERROGATE, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDADD, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDDISABLE, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDENABLE, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDREMOVE, FFI::Windows::Constants::SERVICE_CONTROL_PARAMCHANGE, FFI::Windows::Constants::SERVICE_CONTROL_PAUSE, FFI::Windows::Constants::SERVICE_CONTROL_POWEREVENT, FFI::Windows::Constants::SERVICE_CONTROL_PRESHUTDOWN, FFI::Windows::Constants::SERVICE_CONTROL_SESSIONCHANGE, FFI::Windows::Constants::SERVICE_CONTROL_SHUTDOWN, FFI::Windows::Constants::SERVICE_CONTROL_SIGNALS, FFI::Windows::Constants::SERVICE_CONTROL_STOP, FFI::Windows::Constants::SERVICE_CONTROL_TIMECHANGE, FFI::Windows::Constants::SERVICE_CONTROL_TRIGGEREVENT, FFI::Windows::Constants::SERVICE_DEMAND_START, FFI::Windows::Constants::SERVICE_DISABLED, FFI::Windows::Constants::SERVICE_ENUMERATE_DEPENDENTS, FFI::Windows::Constants::SERVICE_FILE_SYSTEM_DRIVER, FFI::Windows::Constants::SERVICE_INACTIVE, FFI::Windows::Constants::SERVICE_INTERACTIVE_PROCESS, FFI::Windows::Constants::SERVICE_INTERROGATE, FFI::Windows::Constants::SERVICE_KERNEL_DRIVER, FFI::Windows::Constants::SERVICE_NO_CHANGE, FFI::Windows::Constants::SERVICE_PAUSED, FFI::Windows::Constants::SERVICE_PAUSE_CONTINUE, FFI::Windows::Constants::SERVICE_PAUSE_PENDING, FFI::Windows::Constants::SERVICE_QUERY_CONFIG, FFI::Windows::Constants::SERVICE_QUERY_STATUS, FFI::Windows::Constants::SERVICE_RUNNING, FFI::Windows::Constants::SERVICE_START, FFI::Windows::Constants::SERVICE_START_PENDING, FFI::Windows::Constants::SERVICE_START_TYPES, FFI::Windows::Constants::SERVICE_STATES, FFI::Windows::Constants::SERVICE_STATE_ALL, FFI::Windows::Constants::SERVICE_STOP, FFI::Windows::Constants::SERVICE_STOPPED, FFI::Windows::Constants::SERVICE_STOP_PENDING, FFI::Windows::Constants::SERVICE_SYSTEM_START, FFI::Windows::Constants::SERVICE_USER_DEFINED_CONTROL, FFI::Windows::Constants::SERVICE_USER_OWN_PROCESS, FFI::Windows::Constants::SERVICE_USER_SHARE_PROCESS, FFI::Windows::Constants::SERVICE_WIN32_OWN_PROCESS, FFI::Windows::Constants::SERVICE_WIN32_SHARE_PROCESS, FFI::Windows::Constants::SHGFI_DISPLAYNAME, FFI::Windows::Constants::SHGFI_PIDL, FFI::Windows::Constants::SPECIFIC_RIGHTS_ALL, FFI::Windows::Constants::STANDARD_RIGHTS_ALL, FFI::Windows::Constants::STANDARD_RIGHTS_EXECUTE, FFI::Windows::Constants::STANDARD_RIGHTS_READ, FFI::Windows::Constants::STANDARD_RIGHTS_REQUIRED, FFI::Windows::Constants::STANDARD_RIGHTS_WRITE, FFI::Windows::Constants::STARTF_USESTDHANDLES, FFI::Windows::Constants::SYNCHRONIZE, FFI::Windows::Constants::TOKEN_INFORMATION_CLASS, FFI::Windows::Constants::UNSAFE_PENDING_STATES, FFI::Windows::Constants::WRITE_DAC, FFI::Windows::Constants::WRITE_OWNER

Constants included from FFI::Windows::Structs

FFI::Windows::Structs::MAXIMUM_REPARSE_DATA_BUFFER_SIZE

Class Method Summary collapse

Methods included from String

wide_string

Class Method Details

.elevated_security?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns whether or not the owner of the current process is running with elevated security privileges.

Only supported on Windows Vista or later.

Returns:

  • (Boolean)


253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/puppet/util/windows/process.rb', line 253

def elevated_security?
  # default / pre-Vista
  elevated = false
  handle = nil

  begin
    handle = get_current_process
    open_process_token(handle, TOKEN_QUERY) do |token_handle|
      get_token_information(token_handle, :TokenElevation) do |token_info|
        token_elevation = parse_token_information_as_token_elevation(token_info)
        # TokenIsElevated member of the TOKEN_ELEVATION struct
        elevated = token_elevation[:TokenIsElevated] != 0
      end
    end

    elevated
  rescue Puppet::Util::Windows::Error => e
    raise e if e.code != ERROR_NO_SUCH_PRIVILEGE
  ensure
    FFI::WIN32.CloseHandle(handle) if handle
  end
end

.execute(command, arguments, stdin, stdout, stderr) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/puppet/util/windows/process.rb', line 19

def execute(command, arguments, stdin, stdout, stderr)
  create_args = {
    :command_line => command,
    :startup_info => {
      :stdin => stdin,
      :stdout => stdout,
      :stderr => stderr
    },
    :close_handles => false,
  }
  if arguments[:suppress_window]
    create_args[:creation_flags] = CREATE_NO_WINDOW
  end
  if arguments[:cwd]
    create_args[:cwd] = arguments[:cwd]
  end
  Process.create(create_args)
end

.get_current_processObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



62
63
64
65
# File 'lib/puppet/util/windows/process.rb', line 62

def get_current_process
  # this pseudo-handle does not require closing per MSDN docs
  GetCurrentProcess()
end

.get_environment_stringsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

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


306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/puppet/util/windows/process.rb', line 306

def get_environment_strings
  env_ptr = GetEnvironmentStringsW()

  # pass :invalid => :replace to the Ruby String#encode to use replacement characters
  pairs = env_ptr.read_arbitrary_wide_string_up_to(65534, :double_null, { :invalid => :replace })
    .split(?\x00)
    .reject { |env_str| env_str.nil? || env_str.empty? || env_str[0] == '=' }
    .reject do |env_str|
      # reject any string containing the Unicode replacement character
      if env_str.include?("\uFFFD")
        Puppet.warning(_("Discarding environment variable %{string} which contains invalid bytes") % { string: env_str })
        true
      end
    end
    .map { |env_pair| env_pair.split('=', 2) }
  Hash[ pairs ]
ensure
  if env_ptr && ! env_ptr.null?
    if FreeEnvironmentStringsW(env_ptr) == FFI::WIN32_FALSE
      Puppet.debug "FreeEnvironmentStringsW memory leak"
    end
  end
end

.get_process_image_name_by_pid(pid) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



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
# File 'lib/puppet/util/windows/process.rb', line 123

def get_process_image_name_by_pid(pid)
  image_name = ''.dup

  Puppet::Util::Windows::Security.with_privilege(Puppet::Util::Windows::Security::SE_DEBUG_NAME) do
    open_process(PROCESS_QUERY_INFORMATION, false, pid) do |phandle|
      FFI::MemoryPointer.new(:dword, 1) do |exe_name_length_ptr|
        # UTF is 2 bytes/char:
        max_chars = MAX_PATH_LENGTH + 1
        exe_name_length_ptr.write_dword(max_chars)
        FFI::MemoryPointer.new(:wchar, max_chars) do |exe_name_ptr|
          use_win32_path_format = 0
          result = QueryFullProcessImageNameW(phandle, use_win32_path_format, exe_name_ptr, exe_name_length_ptr)
          if result == FFI::WIN32_FALSE
            raise Puppet::Util::Windows::Error.new(
                    "QueryFullProcessImageNameW(phandle, #{use_win32_path_format}, " +
                    "exe_name_ptr, #{max_chars}")
          end
          image_name = exe_name_ptr.read_wide_string(exe_name_length_ptr.read_dword)
        end
      end
    end
  end

  image_name
end

.get_system_default_ui_languageObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



350
351
352
# File 'lib/puppet/util/windows/process.rb', line 350

def get_system_default_ui_language
  GetSystemDefaultUILanguage()
end

.get_token_information(token_handle, token_information, &block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/puppet/util/windows/process.rb', line 171

def get_token_information(token_handle, token_information, &block)
  # to determine buffer size
  FFI::MemoryPointer.new(:dword, 1) do |return_length_ptr|
    result = GetTokenInformation(token_handle, token_information, nil, 0, return_length_ptr)
    return_length = return_length_ptr.read_dword

    if return_length <= 0
      raise Puppet::Util::Windows::Error.new(
        "GetTokenInformation(#{token_handle}, #{token_information}, nil, 0, #{return_length_ptr})")
    end

    # re-call API with properly sized buffer for all results
    FFI::MemoryPointer.new(return_length) do |token_information_buf|
      result = GetTokenInformation(token_handle, token_information,
        token_information_buf, return_length, return_length_ptr)

      if result == FFI::WIN32_FALSE
        raise Puppet::Util::Windows::Error.new(
          "GetTokenInformation(#{token_handle}, #{token_information}, #{token_information_buf}, " +
            "#{return_length}, #{return_length_ptr})")
      end

      yield token_information_buf
    end
  end

  # GetTokenInformation buffer has been cleaned up by this point, nothing to return
  nil
end

.lookup_privilege_value(name, system_name = '', &block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/puppet/util/windows/process.rb', line 150

def lookup_privilege_value(name, system_name = '', &block)
  FFI::MemoryPointer.new(LUID.size) do |luid_ptr|
    result = LookupPrivilegeValueW(
      wide_string(system_name),
      wide_string(name.to_s),
      luid_ptr
      )

    if result == FFI::WIN32_FALSE
      raise Puppet::Util::Windows::Error.new(
        "LookupPrivilegeValue(#{system_name}, #{name}, #{luid_ptr})")
    end

    yield LUID.new(luid_ptr)
  end

  # the underlying MemoryPointer for LUID is cleaned up by this point
  nil
end

.open_process(desired_access, inherit_handle, process_id, &block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/puppet/util/windows/process.rb', line 68

def open_process(desired_access, inherit_handle, process_id, &block)
  phandle = nil
  inherit = inherit_handle ? FFI::WIN32_TRUE : FFI::WIN32_FALSE
  begin
    phandle = OpenProcess(desired_access, inherit, process_id)
    if phandle == FFI::Pointer::NULL_HANDLE
      raise Puppet::Util::Windows::Error.new(
        "OpenProcess(#{desired_access.to_s(8)}, #{inherit}, #{process_id})")
    end

    yield phandle
  ensure
    FFI::WIN32.CloseHandle(phandle) if phandle
  end

  # phandle has had CloseHandle called against it, so nothing to return
  nil
end

.open_process_token(handle, desired_access, &block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/puppet/util/windows/process.rb', line 88

def open_process_token(handle, desired_access, &block)
  token_handle = nil
  begin
    FFI::MemoryPointer.new(:handle, 1) do |token_handle_ptr|
      result = OpenProcessToken(handle, desired_access, token_handle_ptr)
      if result == FFI::WIN32_FALSE
        raise Puppet::Util::Windows::Error.new(
          "OpenProcessToken(#{handle}, #{desired_access.to_s(8)}, #{token_handle_ptr})")
      end

      yield token_handle = token_handle_ptr.read_handle
    end

    token_handle
  ensure
    FFI::WIN32.CloseHandle(token_handle) if token_handle
  end

  # token_handle has had CloseHandle called against it, so nothing to return
  nil
end

.parse_token_information_as_token_elevation(token_information_buf) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



218
219
220
# File 'lib/puppet/util/windows/process.rb', line 218

def parse_token_information_as_token_elevation(token_information_buf)
  TOKEN_ELEVATION.new(token_information_buf)
end

.parse_token_information_as_token_privileges(token_information_buf) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/puppet/util/windows/process.rb', line 202

def parse_token_information_as_token_privileges(token_information_buf)
  raw_privileges = TOKEN_PRIVILEGES.new(token_information_buf)
  privileges = { :count => raw_privileges[:PrivilegeCount], :privileges => [] }

  offset = token_information_buf + TOKEN_PRIVILEGES.offset_of(:Privileges)
  privilege_ptr = FFI::Pointer.new(LUID_AND_ATTRIBUTES, offset)

  # extract each instance of LUID_AND_ATTRIBUTES
  0.upto(privileges[:count] - 1) do |i|
    privileges[:privileges] <<  LUID_AND_ATTRIBUTES.new(privilege_ptr[i])
  end

  privileges
end

.process_privilege_symlink?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/puppet/util/windows/process.rb', line 225

def process_privilege_symlink?
  privilege_symlink = false
  handle = get_current_process
  open_process_token(handle, TOKEN_ALL_ACCESS) do |token_handle|
    lookup_privilege_value('SeCreateSymbolicLinkPrivilege') do |luid|
      get_token_information(token_handle, :TokenPrivileges) do |token_info|
        token_privileges = parse_token_information_as_token_privileges(token_info)
        privilege_symlink = token_privileges[:privileges].any? { |p| p[:Luid].values == luid.values }
      end
    end
  end

  privilege_symlink
rescue Puppet::Util::Windows::Error => e
  if e.code == ERROR_NO_SUCH_PRIVILEGE
    false # pre-Vista
  else
    raise e
  end
end

.set_environment_variable(name, val) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/puppet/util/windows/process.rb', line 331

def set_environment_variable(name, val)
  raise Puppet::Util::Windows::Error(_('environment variable name must not be nil or empty')) if ! name || name.empty?

  FFI::MemoryPointer.from_string_to_wide_string(name) do |name_ptr|
    if (val.nil?)
      if SetEnvironmentVariableW(name_ptr, FFI::MemoryPointer::NULL) == FFI::WIN32_FALSE
        raise Puppet::Util::Windows::Error.new(_("Failed to remove environment variable: %{name}") % { name: name })
      end
    else
      FFI::MemoryPointer.from_string_to_wide_string(val) do |val_ptr|
        if SetEnvironmentVariableW(name_ptr, val_ptr) == FFI::WIN32_FALSE
          raise Puppet::Util::Windows::Error.new(_("Failed to set environment variable: %{name}") % { name: name })
        end
      end
    end
  end
end

.supports_elevated_security?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns whether or not the OS has the ability to set elevated token information.

Returns true on Windows Vista or later, otherwise false

Returns:

  • (Boolean)


360
361
362
# File 'lib/puppet/util/windows/process.rb', line 360

def supports_elevated_security?
  windows_major_version >= 6
end

.wait_process(handle) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/puppet/util/windows/process.rb', line 39

def wait_process(handle)
  while WaitForSingleObject(handle, WAIT_INTERVAL) == WAIT_TIMEOUT
    sleep(0)
  end

  exit_status = -1
  FFI::MemoryPointer.new(:dword, 1) do |exit_status_ptr|
    if GetExitCodeProcess(handle, exit_status_ptr) == FFI::WIN32_FALSE
      raise Puppet::Util::Windows::Error.new(_("Failed to get child process exit code"))
    end
    exit_status = exit_status_ptr.read_dword

    # $CHILD_STATUS is not set when calling win32/process Process.create
    # and since it's read-only, we can't set it. But we can execute a
    # a shell that simply returns the desired exit status, which has the
    # desired effect.
    %x{#{ENV['COMSPEC']} /c exit #{exit_status}}
  end

  exit_status
end

.windows_major_versionObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/puppet/util/windows/process.rb', line 277

def windows_major_version
  ver = 0

  FFI::MemoryPointer.new(OSVERSIONINFO.size) do |os_version_ptr|
    os_version = OSVERSIONINFO.new(os_version_ptr)
    os_version[:dwOSVersionInfoSize] = OSVERSIONINFO.size

    result = GetVersionExW(os_version_ptr)

    if result == FFI::WIN32_FALSE
      raise Puppet::Util::Windows::Error.new(_("GetVersionEx failed"))
    end

    ver = os_version[:dwMajorVersion]
  end

  ver
end

.with_process_token(access, &block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Execute a block with the current process token



112
113
114
115
116
117
118
119
120
# File 'lib/puppet/util/windows/process.rb', line 112

def with_process_token(access, &block)
  handle = get_current_process
  open_process_token(handle, access) do |token_handle|
    yield token_handle
  end

  # all handles have been closed, so nothing to safely return
  nil
end