Module: Facter::Util::Windows::Process

Extended by:
FFI::Library
Defined in:
lib/facter/util/windows.rb,
lib/facter/util/windows/process.rb

Defined Under Namespace

Classes: OSVERSIONINFOEX, TOKEN_ELEVATION

Constant Summary collapse

TOKEN_QUERY =
0x0008
STATUS_SUCCESS =
0
SM_SERVERR2 =
89
TOKEN_INFORMATION_CLASS =
enum(
    :TokenUser, 1,
    :TokenGroups,
    :TokenPrivileges,
    :TokenOwner,
    :TokenPrimaryGroup,
    :TokenDefaultDacl,
    :TokenSource,
    :TokenType,
    :TokenImpersonationLevel,
    :TokenStatistics,
    :TokenRestrictedSids,
    :TokenSessionId,
    :TokenGroupsAndPrivileges,
    :TokenSessionReference,
    :TokenSandBoxInert,
    :TokenAuditPolicy,
    :TokenOrigin,
    :TokenElevationType,
    :TokenLinkedToken,
    :TokenElevation,
    :TokenHasRestrictions,
    :TokenAccessInformation,
    :TokenVirtualizationAllowed,
    :TokenVirtualizationEnabled,
    :TokenIntegrityLevel,
    :TokenUIAccess,
    :TokenMandatoryPolicy,
    :TokenLogonSid,
    :TokenIsAppContainer,
    :TokenCapabilities,
    :TokenAppContainerSid,
    :TokenAppContainerNumber,
    :TokenUserClaimAttributes,
    :TokenDeviceClaimAttributes,
    :TokenRestrictedUserClaimAttributes,
    :TokenRestrictedDeviceClaimAttributes,
    :TokenDeviceGroups,
    :TokenRestrictedDeviceGroups,
    :TokenSecurityAttributes,
    :TokenIsRestricted,
    :MaxTokenInfoClass
)

Class Method Summary collapse

Class Method Details

.elevated_security?Boolean

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)


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/facter/util/windows/process.rb', line 78

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 Facter::Util::Windows::Error => e
    raise e if e.code != ERROR_NO_SUCH_PRIVILEGE
  ensure
    Facter::Util::Windows::FFI::WIN32.CloseHandle(handle) if handle
  end
end

.get_current_processObject



7
8
9
10
# File 'lib/facter/util/windows/process.rb', line 7

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

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



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

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 = Facter::Util::Windows::FFI.read_dword(return_length_ptr)

    if return_length <= 0
      raise Facter::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 == Facter::Util::Windows::FFI::WIN32_FALSE
        raise Facter::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

.is_2003_r2?Boolean

Returns:

  • (Boolean)


147
148
149
150
151
# File 'lib/facter/util/windows/process.rb', line 147

def is_2003_r2?
  # Peculiar API from user32 - the docs for SM_SERVER2 indicate
  # The build number if the system is Windows Server 2003 R2; otherwise, 0.
  GetSystemMetrics(SM_SERVERR2) != 0
end

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



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/facter/util/windows/process.rb', line 13

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 == Facter::Util::Windows::FFI::WIN32_FALSE
        raise Facter::Util::Windows::Error.new(
            "OpenProcessToken(#{handle}, #{desired_access.to_s(8)}, #{token_handle_ptr})")
      end

      yield token_handle = Facter::Util::Windows::FFI.read_handle(token_handle_ptr)
    end

    token_handle
  ensure
    Facter::Util::Windows::FFI::WIN32.CloseHandle(token_handle) if token_handle
  end

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

.os_version(&block) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/facter/util/windows/process.rb', line 104

def os_version(&block)
  FFI::MemoryPointer.new(OSVERSIONINFOEX.size) do |ver_ptr|
    ver = OSVERSIONINFOEX.new(ver_ptr)
    ver[:dwOSVersionInfoSize] = OSVERSIONINFOEX.size

    result = RtlGetVersion(ver_ptr)

    if result != STATUS_SUCCESS
      raise RuntimeError, 'Calling Windows RtlGetVersion failed'
    end

    yield ver
  end

  # ver_ptr has already had free called, so nothing to return
  nil
end

.os_version_stringObject



134
135
136
137
138
139
140
141
# File 'lib/facter/util/windows/process.rb', line 134

def os_version_string
  ver = ''
  self.os_version do |version|
    ver = "#{version[:dwMajorVersion]}.#{version[:dwMinorVersion]}.#{version[:dwBuildNumber]}"
  end

  ver
end

.parse_token_information_as_token_elevation(token_information_buf) ⇒ Object



67
68
69
# File 'lib/facter/util/windows/process.rb', line 67

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

.supports_elevated_security?Boolean

Returns:

  • (Boolean)


154
155
156
# File 'lib/facter/util/windows/process.rb', line 154

def supports_elevated_security?
  windows_major_version >= 6
end

.windows_major_versionObject



123
124
125
126
127
128
129
130
131
# File 'lib/facter/util/windows/process.rb', line 123

def windows_major_version
  ver = 0

  self.os_version do |version|
    ver = version[:dwMajorVersion]
  end

  ver
end