5

When new updates are available, my Delphi application counts processes running from the same directory. If it finds the current process only, then it downloads the updates and restarts itself.

For counting processes by full file name, I'm using OpenProcess and GetModuleFileNameEx as shown in this question.

In most cases, everything works but one of my customers uses thin clients and a server in which the application is installed in several directories (Each user has its own installation folder on the server).

When an user starts the application from his thin client, the application finds also the processes that belongs to other users but it can't obtain the executable full file name because OpenProcess causes an access denied error:

ERROR_ACCESS_DENIED

5 (0x5)

Access is denied.

Here is how I'm calling OpenProcess and GetModuleFileNameEx:

const
  S_PROCESS_QUERY_LIMITED_INFORMATION = $1000;

function GetFullFileNameFromPID(const PID: Cardinal) : string;
var
  ProcessHandle : THandle;
  Path : array[0..MAX_PATH - 1] of Char;
begin
  ProcessHandle := OpenProcess(S_PROCESS_QUERY_LIMITED_INFORMATION, False, PID);
  if(ProcessHandle <> 0) then
  begin
    if(GetModuleFileNameEx(ProcessHandle, 0, Result, MAX_PATH) = 0)
    then RaiseLastOSError
    else Result := Path;

    CloseHandle(ProcessHandle);
  end else
    RaiseLastOSError;
end;

Is there a way to get this information from a process for which the application have no permissions?


Update:

The filename is not enough for my purpose, I noticed that I can get the full file name using Task manager with the same user who gets ERROR_ACCESS_DENIED but I don't understand how it is obtaining that information.

enter image description here

Community
  • 1
  • 1
Fabrizio
  • 7,603
  • 6
  • 44
  • 104
  • 2
    If >= 2k3 try opening with only PROCESS_QUERY_LIMITED_INFORMATION then use GetProcessImageFileName() – Alex K. Nov 16 '16 at 11:22
  • @AlexK.: I've updated the code in the question using `PROCESS_QUERY_LIMITED_INFORMATION` but its' still raising `ERROR_ACCESS_DENIED` error – Fabrizio Nov 16 '16 at 14:01
  • @David Heffernan: It's exactly the same question but for my goal the exe name isn't enought, I need the full file name. In the taskmanager I can see it for the same processes which gives me ERROR_ACCESS_DENIED (right click, properties) – Fabrizio Nov 16 '16 at 14:05
  • I think that the dupe also asks for the same information. – David Heffernan Nov 16 '16 at 14:24
  • @DavidHeffernan: Maybe, but he accepted an answer who doesn't allow him to get that information. What should be done in this case? – Fabrizio Nov 16 '16 at 14:31
  • It's difficult. It's really the exact same question. Best is an answer at the original site. Let me see if I can come up with one ...... – David Heffernan Nov 16 '16 at 14:32
  • @DavidHeffernan: I agree with you, I'll wait for your answer – Fabrizio Nov 16 '16 at 14:41
  • 2
    There's some Delphi code here: https://wj32.org/processhacker/forums/viewtopic.php?t=18 translated from here https://wj32.org/wp/2010/03/30/get-the-image-file-name-of-any-process-from-any-user-on-vista-and-above/ – David Heffernan Nov 16 '16 at 14:54
  • @ExDev - you are sure that got `ERROR_ACCESS_DENIED` with `PROCESS_QUERY_LIMITED_INFORMATION` ?? with this you even can open windows protected processes. you need use `GetProcessImageFileName` but not `GetModuleFileNameEx` which of course give you `ERROR_ACCESS_DENIED` – RbMm Nov 16 '16 at 15:07
  • really you can use `ZwQueryInformationProcess` with `ProcessImageFileName` (this is the same as `GetProcessImageFileNameW`) or `ProcessImageFileNameWin32` (available from vista if i not mistake). process handle need only `PROCESS_QUERY_LIMITED_INFORMATION` – RbMm Nov 16 '16 at 15:14
  • @DavidHeffernan: Thank you very much! It works! What happens on executing that code on a SO older than Vista? (`LoadLibrary('ntdll.dll')` will return 0 or where else it will fail?) – Fabrizio Nov 16 '16 at 15:33
  • @RbMm: Yes, I'm sure. It's `OpenProcess` who fails and returns 0, then `RaiseLastOSError` shows `ERROR_ACCESS_DENIED`. I've tested it on Windows Server 2012 R2. I'm executing `OpenProcess` function parametrized as follows: `OpenProcess($1000, False, PID)` – Fabrizio Nov 16 '16 at 15:34
  • @ExDev - ok, this can be if run under restricted user account. in this case you can use `ZwQuerySystemInformation(SystemProcessInformation)` - this give you list of all processes in system with full image path and process id. task manager use exactly this method – RbMm Nov 16 '16 at 15:43
  • 1
    On older systems, the call to `NtQuerySystemInformation` will fail – David Heffernan Nov 16 '16 at 15:54
  • @RbMm: The user who is executing OpenProcess is administrator but this doesn't avoid ERROR_ACCESS_DENIED. Which unit should be added to uses clause in order to use SystemProcessInformation? – Fabrizio Nov 16 '16 at 15:57
  • @ExDev - this is very strange, because how i know - all system processes (even protected) have 0x1000 access usual for administrators(`S-1-5-32-544` ) or to `S-1-5-11` (`authenticated users`) in case `audiodg.exe`. i be on your place try open another (system processes) and check result. NtQuerySystemInformation is form ntdll. you need use ntdll.lib or ntdllp.lib from WDK – RbMm Nov 16 '16 at 16:07
  • @DavidHeffernan - you mistake. `NtQuerySystemInformation` will be worked even on win2000 for `ProcessImageFileName` infoclass. `ProcessImageFileNameWin32` - from vista worked – RbMm Nov 16 '16 at 16:09
  • @RbMm: I'm not so skilled about that. I don't know how to set up the function and how to manage the result. If you're sure about that and you want to add an answer to [the other question](http://stackoverflow.com/questions/9146498/how-to-get-a-process-file-name-from-pid-if-openprocess-fails-with-access-deni) (this one is duplicated), I'll be glad to test it. – Fabrizio Nov 16 '16 at 16:18
  • @RbMm No, I'm afraid that you are mistaken. The code that I linked to does not work on versions before Vista. Read the article. – David Heffernan Nov 16 '16 at 16:32
  • @DavidHeffernan - i not mistaken. i very wide use NtQuerySystemInformation begin from xp and all prefect worked. i not lloked your code but use self. but i really mistaken(forget) in another. `SystemProcessInformation` give to us only process name, without path. so this not solution – RbMm Nov 16 '16 at 16:36
  • @RbMm You aren't listening. Do try to listen. I agree that your info class works on pre-Vista. I linked to an article that uses a different info class, introduce in Vista. How can you tell me that I am wrong when you haven't even attempted to understand what I said? Follow the link. What I wrote was correct. You just failed to understand what I wrote. If I had said what you guessed that I said, then I would indeed have been wrong. But I didn't say it. You imagined it. – David Heffernan Nov 16 '16 at 16:39
  • @DavidHeffernan - sorry, i really not understand you. i based on your comment "On older systems, the call to NtQuerySystemInformation will fail" but i mean another infoclass. – RbMm Nov 16 '16 at 16:49
  • @RbMm I was responded to the asker's question about the article I linked to. That article uses an info class that does not exist in XP, at least that's what the article says. I have no doubt that the info class you refer to does indeed exist on XP. – David Heffernan Nov 16 '16 at 16:52
  • @ExDev - also, are you enable `SE_DEBUG_PRIVILEGE` before openprocess ? this is important for result. about `SystemProcessInformation` give to us only process name, without path. usual process DACLs - http://pastebin.com/FkhPQ4zK but if you have `SE_DEBUG_PRIVILEGE` you can open any process without DACL check. exception - protected processes, but with `PROCESS_QUERY_LIMITED_INFORMATION` this also must be opened – RbMm Nov 16 '16 at 16:59
  • @DavidHeffernan - sorry again. i haste, without fully understand your response. i was wrong. however i think OP problem can be in not enabled SE_DEBUG_PRIVILEGE before call OpenProcess with PROCESS_QUERY_LIMITED_INFORMATION – RbMm Nov 16 '16 at 17:09

0 Answers0