Process Handles Objname empty in Win XP

delphi package - easy access to kernel objects etc.
Post Reply
brian
Posts: 45
Joined: Fri Feb 29, 2008 11:12 am

Process Handles Objname empty in Win XP

Post by brian »

Not sure when this happened, but probably during the added support for Unicode/XE, with the latest madKernel, Process.Handles.Items.KernelObj.Objname are now empty when running in Windows XP.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Process Handles Objname empty in Win XP

Post by madshi »

Can you post some sample code with which I can reproduce the problem, please?
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Process Handles Objname empty in Win XP

Post by madshi »

P.S: Just tried the following code and it worked just fine on my XPSP3 PC. Tested with both Delphi 7 and XE2:

Code: Select all

procedure TForm1.Button1Click(Sender: TObject);
var s1, s2 : AnsiString;
    i1     : integer;
begin
  s1 := '';
  with Process('calc.exe').Handles do
    for i1 := 0 to ItemCount - 1 do begin
      s2 := Items[i1].KernelObj.ObjName;
      if s2 <> '' then
        s1 := s1 + s2 + #$D#$A;
    end;
  MessageBoxA(0, PAnsiChar(s1), 'info', 0);
end;
brian
Posts: 45
Joined: Fri Feb 29, 2008 11:12 am

Re: Process Handles Objname empty in Win XP

Post by brian »

Using this code:

Code: Select all

procedure TForm1.Button2Click(Sender: TObject);
Var a: integer;
    b: string;
begin
  Memo1.Clear;
  Memo1.Lines.BeginUpdate;
  with Process('vlc.exe').Handles do
  for a := 0 to ItemCount - 1 do
  with Items[a] do
  begin
    if not IsValid then Continue;
    if not (ObjType in [otFile]) then Continue;
    b := KernelObj.ObjName;
    if b = '' then Continue;
    Memo1.Lines.Add(b);
  end;
  Memo1.Lines.EndUpdate;
end;
Run on win7 works, run on a XP results in empty names:

Image

I just noticed something really odd though:

I tried other code to retrieve the names, which does work in both XP and W7, and.. if I run that code, then madKernel's without closing the program, it works from then on while the app is running oO

Image
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Process Handles Objname empty in Win XP

Post by madshi »

Then it's probably a privilege problem. Just try enabling all privileges first:

Code: Select all

var PrivilegesEnabled : boolean = false;
procedure EnableAllPrivileges;
type TTokenPrivileges = record
       PrivilegeCount : dword;
       Privileges     : array [0..maxInt shr 4 - 1] of TLUIDAndAttributes;
     end;
var token : THandle;
    c2    : dword;
    i1    : integer;
    ptp   : ^TTokenPrivileges;
begin
  if PrivilegesEnabled then
    exit;
  if OpenProcessToken(windows.GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, token) then
    try
      c2 := 0;
      GetTokenInformation(token, TokenPrivileges, nil, 0, c2);
      if c2 <> 0 then begin
        ptp := pointer(LocalAlloc(LPTR, c2 * 2));
        if GetTokenInformation(token, TokenPrivileges, ptp, c2 * 2, c2) then begin
          for i1 := 0 to integer(ptp^.PrivilegeCount) - 1 do
            ptp^.Privileges[i1].Attributes := ptp^.Privileges[i1].Attributes or SE_PRIVILEGE_ENABLED;
          AdjustTokenPrivileges(token, false, PTokenPrivileges(ptp)^, c2, PTokenPrivileges(nil)^, dword(pointer(nil)^));
        end;
        LocalFree(HLOCAL(ptp));
      end;
    finally CloseHandle(token) end;
  PrivilegesEnabled := true;
end;
brian
Posts: 45
Joined: Fri Feb 29, 2008 11:12 am

Re: Process Handles Objname empty in Win XP

Post by brian »

Nice, it works now! I had actually a proc in the other code to enable privs. but didn't think of that, since the other code was working without enabling them first.

Anyway while we are on this, do you mind a couple related things to this:

1) It might be good to modify the code at GetHandleTableNt to loop the call until it succeeds, as per info from http://forum.sysinternals.com/howto-enu ... 18892.html
An unusual aspect of calling NtQuerySystemInformation with SystemHandleInformation is that if you supply a buffer which is too small, it returns STATUS_INFO_LENGTH_MISMATCH (0xc0000004) instead of giving you the correct buffer size in ReturnLength. This means you will have to guess the buffer size. A common technique is to call NtQuerySystemInformation in a loop until it succeeds with STATUS_SUCCESS (0), reallocating and doubling the buffer size each time it fails with STATUS_INFO_LENGTH_MISMATCH.
Maybe rather than re-sizing the buffer once we could do something like

Code: Select all

function GetHandleTableNt : TNtHandleTable;
var c1 : cardinal;
    p1 : pointer;
    r: Cardinal;
begin
  result.ItemCount := 0;
  result.Items := nil;
  if @NtQuerySystemInformation = nil then
    NtQuerySystemInformation := GetProcAddress(GetModuleHandle(ntdll), 'NtQuerySystemInformation');
  dword(p1) := LocalAlloc(LPTR, 20);
  try
    c1 := 0;
    r := NtQuerySystemInformation(16, p1, 20, @c1);
    LocalFree(dword(p1));
    //dword(p1) := LocalAlloc(LPTR, c1 * 2);
    while r = $C0000004 do begin
      dword(p1) := LocalAlloc(LPTR, c1 * 2);
      r := NtQuerySystemInformation(16, p1, c1 * 2, @c1)
    end;
    //if NtQuerySystemInformation(16, p1, c1 * 2, nil) = 0 then begin
    if r = 0 then begin
      result.ItemCount := TPInteger(p1)^;
      SetLength(result.Items, result.ItemCount);
      Move(pointer(integer(p1) + 4)^, pointer(result.Items)^, result.ItemCount * sizeOf(TNtHandleItem));
    end;
  finally LocalFree(dword(p1)) end;
end;
($C0000004 = STATUS_INFO_LENGTH_MISMATCH)

2) Filenames with Unicode return with garbage, for example "123★456" comes up as "123?456". Any way to fix that?

Thanks.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Process Handles Objname empty in Win XP

Post by madshi »

I'm already looping NtQuerySystemInformation if it doesn't return the needed buffer size.

The current madKernel version is still not converted to Unicode and/or x64. I will probably do the conversion at some point in the future, but it's currently not very high on my priority list.
brian
Posts: 45
Joined: Fri Feb 29, 2008 11:12 am

Re: Process Handles Objname empty in Win XP

Post by brian »

There's only 1 extra call in the original code

Code: Select all

function GetHandleTableNt : TNtHandleTable;
var c1 : cardinal;
    p1 : pointer;
begin
  result.ItemCount := 0;
  result.Items := nil;
  if @NtQuerySystemInformation = nil then
    NtQuerySystemInformation := GetProcAddress(GetModuleHandle(ntdll), 'NtQuerySystemInformation');
  dword(p1) := LocalAlloc(LPTR, 20);
  try
    c1 := 0;
    NtQuerySystemInformation(16, p1, 20, @c1);
    LocalFree(dword(p1));
    dword(p1) := LocalAlloc(LPTR, c1 * 2);
    if NtQuerySystemInformation(16, p1, c1 * 2, nil) = 0 then begin
      result.ItemCount := TPInteger(p1)^;
      SetLength(result.Items, result.ItemCount);
      Move(pointer(integer(p1) + 4)^, pointer(result.Items)^, result.ItemCount * sizeOf(TNtHandleItem));
    end;
  finally LocalFree(dword(p1)) end;
end;
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Process Handles Objname empty in Win XP

Post by madshi »

Ah sorry, I looked in the wrong unit... :shock:

Anyway, the code works, doesn't it? I've not had any reports that it would fail on any OS. My solution is different to that suggested by your link, but what does it matter if it works? There are often multiple solutions to one problem.
brian
Posts: 45
Joined: Fri Feb 29, 2008 11:12 am

Re: Process Handles Objname empty in Win XP

Post by brian »

Yeah never had it fail besides this XP issue earlier, but just out of safety.. idk. In other tests with different code the call fails randomly, sometimes once, sometimes up to 3 times, although incrementing the size only 1kb each iteration. I guess 2x is never gonna have an issue. Pretty lame that microsoft never documented this.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: Process Handles Objname empty in Win XP

Post by madshi »

Well, if that quote "An unusual aspect of calling NtQuerySystemInformation with SystemHandleInformation is that if you supply a buffer which is too small, it returns STATUS_INFO_LENGTH_MISMATCH (0xc0000004) instead of giving you the correct buffer size in ReturnLength" were true, my code would fail, every time, on every OS. That is not the case, so obviously that quote is totally incorrect.

Anyway, if you can reproduce a situation where my code fails, please let me know and I will look into it.
Post Reply