{"record":{"id":"02493d26e3323ab7","repo":"puppetlabs/puppet","slug":"gettokeninformation-token-handle-token-infor","errorCode":null,"errorMessage":"GetTokenInformation(#{token_handle}, #{token_information}, nil, 0, #{return_length_ptr})","messagePattern":"GetTokenInformation\\(#(.+?), #(.+?), nil, 0, #(.+?)\\)","errorType":"exception","errorClass":"Puppet::Util::Windows::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/util/windows/process.rb","lineNumber":176,"sourceCode":"        raise Puppet::Util::Windows::Error, \"LookupPrivilegeValue(#{system_name}, #{name}, #{luid_ptr})\"\n      end\n\n      yield LUID.new(luid_ptr)\n    end\n\n    # the underlying MemoryPointer for LUID is cleaned up by this point\n    nil\n  end\n  module_function :lookup_privilege_value\n\n  def get_token_information(token_handle, token_information, &block)\n    # to determine buffer size\n    FFI::MemoryPointer.new(:dword, 1) do |return_length_ptr|\n      result = GetTokenInformation(token_handle, token_information, nil, 0, return_length_ptr)\n      return_length = return_length_ptr.read_dword\n\n      if return_length <= 0\n        raise Puppet::Util::Windows::Error, \"GetTokenInformation(#{token_handle}, #{token_information}, nil, 0, #{return_length_ptr})\"\n      end\n\n      # re-call API with properly sized buffer for all results\n      FFI::MemoryPointer.new(return_length) do |token_information_buf|\n        result = GetTokenInformation(token_handle, token_information,\n                                     token_information_buf, return_length, return_length_ptr)\n\n        if result == FFI::WIN32_FALSE\n          raise Puppet::Util::Windows::Error, \"GetTokenInformation(#{token_handle}, #{token_information}, #{token_information_buf}, \" \\\n                                              \"#{return_length}, #{return_length_ptr})\"\n        end\n\n        yield token_information_buf\n      end\n    end\n\n    # GetTokenInformation buffer has been cleaned up by this point, nothing to return\n    nil","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/windows/process.rb#L158-L194","documentation":"Raised by Process.get_token_information (lib/puppet/util/windows/process.rb:176) when the sizing pass of GetTokenInformation leaves return_length <= 0. The code infers failure from the length rather than the return BOOL, so this means the first call accomplished nothing: the token handle is invalid or closed, lacks TOKEN_QUERY access, or the token information class passed is not valid on this OS.","triggerScenarios":"Passing a token handle that has already been closed (open_process_token closes it when its block ends); opening a token with only TOKEN_ADJUST_PRIVILEGES and then reading information from it; requesting a Token* class unsupported on the Windows version; passing a bogus class symbol.","commonSituations":"Saving the token handle into a variable used after the open_process_token block; privilege-enabling code that never asks for TOKEN_QUERY; version drift in token class names/values.","solutions":["Keep all token reads inside the open_process_token block — the handle's lifetime is that block.","Open the token with TOKEN_QUERY included (TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES when adjusting privileges).","Verify the token information class (e.g. :TokenUser, :TokenPrivileges, :TokenElevation) is spelled and valued correctly.","Rescue and inspect e.code — 6 (invalid handle) points at lifetime bugs, 5 (access denied) at the mask."],"exampleFix":"# before — handle escapes its block and is already closed\nProcess.open_process_token(h, 0x20) { |t| saved = t }\nProcess.get_token_information(saved, :TokenUser)\n\n# after — query inside the block, with TOKEN_QUERY\nProcess.open_process_token(h, Process::TOKEN_QUERY | 0x20) do |t|\n  Process.get_token_information(t, :TokenUser) { |buf| use(buf) }\nend","handlingStrategy":"try-catch","validationCode":"# ensure the access mask includes TOKEN_QUERY before any information read\nmask |= Process::TOKEN_QUERY if (mask & Process::TOKEN_QUERY).zero?\nProcess.open_process_token(handle, mask) { |t| Process.get_token_information(t, info_class) { |b| use(b) } }","typeGuard":null,"tryCatchPattern":"begin\n  Process.get_token_information(token, info_class) { |buf| use(buf) }\nrescue Puppet::Util::Windows::Error => e\n  Puppet.err \"token query #{info_class} failed (#{e.code}): #{e.message}\"\n  nil\nend","preventionTips":["Never let a token handle outlive its open_process_token block","Always include TOKEN_QUERY in the access mask when reading token information","Pin the token class list to the oldest Windows version you support"],"tags":["windows","win32-api","token","handle","ffi","puppet"],"backgroundTag":"win32-gettokeninformation-failed","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}