{"record":{"id":"1a127818bd2aae59","repo":"puppetlabs/puppet","slug":"queryfullprocessimagenamew-phandle-use-win32-pa","errorCode":null,"errorMessage":"QueryFullProcessImageNameW(phandle, #{use_win32_path_format}, exe_name_ptr, #{max_chars}","messagePattern":"QueryFullProcessImageNameW\\(phandle, #(.+?), exe_name_ptr, #(.+?)","errorType":"exception","errorClass":"Puppet::Util::Windows::Error","httpStatus":null,"severity":"error","filePath":"lib/puppet/util/windows/process.rb","lineNumber":136,"sourceCode":"    # all handles have been closed, so nothing to safely return\n    nil\n  end\n  module_function :with_process_token\n\n  def get_process_image_name_by_pid(pid)\n    image_name = ''.dup\n\n    Puppet::Util::Windows::Security.with_privilege(Puppet::Util::Windows::Security::SE_DEBUG_NAME) do\n      open_process(PROCESS_QUERY_INFORMATION, false, pid) do |phandle|\n        FFI::MemoryPointer.new(:dword, 1) do |exe_name_length_ptr|\n          # UTF is 2 bytes/char:\n          max_chars = MAX_PATH_LENGTH + 1\n          exe_name_length_ptr.write_dword(max_chars)\n          FFI::MemoryPointer.new(:wchar, max_chars) do |exe_name_ptr|\n            use_win32_path_format = 0\n            result = QueryFullProcessImageNameW(phandle, use_win32_path_format, exe_name_ptr, exe_name_length_ptr)\n            if result == FFI::WIN32_FALSE\n              raise Puppet::Util::Windows::Error, \"QueryFullProcessImageNameW(phandle, #{use_win32_path_format}, \" \\\n                                                  \"exe_name_ptr, #{max_chars}\"\n            end\n            image_name = exe_name_ptr.read_wide_string(exe_name_length_ptr.read_dword)\n          end\n        end\n      end\n    end\n\n    image_name\n  end\n  module_function :get_process_image_name_by_pid\n\n  def lookup_privilege_value(name, system_name = '', &block)\n    FFI::MemoryPointer.new(LUID.size) do |luid_ptr|\n      result = LookupPrivilegeValueW(\n        wide_string(system_name),\n        wide_string(name.to_s),\n        luid_ptr","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/util/windows/process.rb#L118-L154","documentation":"Raised by Process.get_process_image_name_by_pid (lib/puppet/util/windows/process.rb:136) when QueryFullProcessImageNameW returns FALSE. The method already runs under SE_DEBUG_NAME via Security.with_privilege, opens the pid with PROCESS_QUERY_INFORMATION, and sizes the buffer at MAX_PATH_LENGTH + 1 = 32768 wchars, so the realistic failures are: the process exited between OpenProcess and the query (ERROR_INVALID_HANDLE / stale), or the target is a protected process that refuses the query even with SeDebugPrivilege (ERROR_ACCESS_DENIED).","triggerScenarios":"Polling the image name of short-lived processes that vanish mid-call; querying protected-process-light binaries such as antivirus or lsass; the caller lacking the ability to acquire SeDebugPrivilege (not elevated), which surfaces when targeting other sessions' processes.","commonSituations":"Process-monitoring loops racing process exit; agents checking which executable owns a lock or a port; inventory scripts hitting protected services.","solutions":["Rescue Puppet::Util::Windows::Error and treat failure as 'process gone / not inspectable' — return nil and let the caller skip.","In polling loops, tolerate gaps: the next tick usually succeeds for long-lived processes.","Confirm the agent runs elevated (SeDebugPrivilege acquirable) when inspecting other sessions' processes.","Branch on e.code: 6 (invalid handle) means an exit race, 5 (access denied) means a protected process."],"exampleFix":"# before\nimage = Process.get_process_image_name_by_pid(pid)\n\n# after — tolerate the exit race\nbegin\n  image = Process.get_process_image_name_by_pid(pid)\nrescue Puppet::Util::Windows::Error\n  image = nil # process exited or is protected\nend","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"def safe_image_name(pid)\n  Process.get_process_image_name_by_pid(pid)\nrescue Puppet::Util::Windows::Error => e\n  Puppet.debug \"image lookup failed for pid #{pid} (#{e.code}): #{e.message}\"\n  nil # caller falls back to cached data or skips this tick\nend","preventionTips":["Never assume a pid stays alive across the call — always rescue in monitoring loops","Run inventory agents as SYSTEM so SE_DEBUG_NAME can be enabled","Debounce: skip pids seen for the first time to avoid racing process startup and teardown"],"tags":["windows","win32-api","process","race-condition","privilege","ffi","puppet"],"backgroundTag":"win32-query-process-image-failed","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}