Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Можно ли узнать имя родительского процесса в 64 разрядной винде? [D7, WinXP]


Страницы:   1 2

sniknik ©   (2010-06-17 11:42:00) 

Интересует естественно вариант из 32 разрядной программы на Delphi запущенной 64 разрядным "родителем".
Ну и понятно не интересно если, это будет имя виртуальной машины (или чего там) т.е. что-то промежуточное, и всегда одинаковое (хотя сейчас и это не получается).

Вариант работающий в 32 разрядной -
type
 PROCESS_BASIC_INFORMATION = packed record
   ExitStatus: DWORD;
   PebBaseAddress: Pointer;
   AffinityMask: DWORD;
   BasePriority: DWORD;
   uUniqueProcessId: Ulong;
   uInheritedFromUniqueProcessId: Ulong;
 end;

function NtQueryInformationProcess(ProcessHandle: THandle; ProcessInformationClass: Byte; ProcessInformation: Pointer;
                                  ProcessInformationLength: ULONG; ReturnLength: PULONG): DWORD; stdcall; external 'ntdll.dll';

function ParentProcName: string;
var
 Info: PROCESS_BASIC_INFORMATION;
 ProcessName: string;
 Hndl: THandle;
begin
 result:= 'noname';
 if NtQueryInformationProcess(GetCurrentProcess, 0, @Info, SizeOf(Info), nil) = NO_ERROR
   then begin
     Hndl:= OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, Info.uInheritedFromUniqueProcessId);
     if Hndl <> 0 then
       try
         SetLength(ProcessName, MAX_PATH);
         if GetModuleBaseNameA(Hndl, 0, PChar(ProcessName), MAX_PATH) > 0
           then result:= PChar(ProcessName);
       finally
         CloseHandle(Hndl);
       end;
   end;
end;

в 64, не работает... (??? на проверки было мало времени, т.к. ограничен доступ к 64 винде. но вроде те пару раз, что выдало "noname" показательны)

p.s. Догадки, и тесты (типа что за ошибку дает вот в этом месте) могу проверить только вечером. А вот если есть "железный" вариант, то можно и сейчас побегать...


sniknik   (2010-06-18 07:38:00) [1]

> у меня не заработало...
Блин, проверил, у меня тоже ;(. Можно посмотреть ошибку от Module32First (валится тут похоже на ней), "завернуть" ее в Win32Check, но это после, на работу пора. ;)


KilkennyCat   (2010-06-18 07:06:00) [2]

Ага, я пробовал через снапшот, но где-то ошибался, у меня не заработало...
Появится еще время - оформлю все это в какой-нить PsApi2


sniknik   (2010-06-18 00:22:00) [3]

Еще один, наверное окончательный вариант... ;) обработка одного из проверенных здесь  (отличие от того - дает полный путь, что и требуется в одном из случаев).
 uses ... TlHelp32;
 function GetModuleFileName(pID: DWORD): string;
 var
   hSnapshot: THandle;
   mEntr: tagMODULEENTRY32;
 begin
   result:= 'noname';
   hSnapshot:= CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
   if hSnapshot <> INVALID_HANDLE_VALUE then
   try
     mEntr.dwSize:= SizeOf(mEntr);
     if Module32First(hSnapshot, mEntr) then
       result:= mEntr.szExePath;
   finally
     CloseHandle(hSnapshot)
   end;
 end;

 function ParentProcName: string;
 var
   pID: DWORD;
   hSnapshot: THandle;
   ProcessEntry: TProcessEntry32;
 begin
   result:= 'noname';
   hSnapshot:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   if hSnapshot <> INVALID_HANDLE_VALUE then
   try
     ProcessEntry.dwSize:= SizeOf(ProcessEntry);
     if Process32First(hSnapshot, ProcessEntry) then begin
       pID:= GetCurrentProcessID;
       repeat
         if ProcessEntry.th32ProcessID = pID then begin
           result:= GetModuleFileName(ProcessEntry.th32ParentProcessID);
           Break;
         end;
       until not Process32Next(hSnapshot, ProcessEntry);
     end;
   finally
     CloseHandle(hSnapshot)
   end;
 end;

На нем и остановлюсь.


KilkennyCat   (2010-06-17 17:34:00) [4]

да, юникод постоянно преподносит сюрпрайзы... хорошо еще, что тут очевидно.


KilkennyCat   (2010-06-17 17:33:00) [5]

исходный путь D:\
тупо сделал так: Move(sRes[1], lpFilename[0], result + 1000);
получилось - C:\Windows\explorer.exe


sniknik   (2010-06-17 17:33:00) [6]

> забавные пути...
У тебя с юникодом нужно размер char на 2 умножать... ну и все сдвинулось из-за этого.


sniknik   (2010-06-17 17:31:00) [7]

KilkennyCat ©   (17.06.10 17:10) [18]
Ну, вот это и требовалось.

Хотя тут вроде неправильно...
> из проводника win7x64 - C:\ Windows\ ediskVolume1\ Windows\explorer.exe
Похоже DevicePathToWin32Path криво отработал (опять юникод?). Какой у тебя тут исходный путь? От GetProcessImageFileName.

> еще дополнение - ниже указанные функции не повлияли на вышеуказанный результат
Судя по всему единственное проблемное это 64 vs нормального в 32.


KilkennyCat   (2010-06-17 17:22:00) [8]


> из проводника win7x64 - C:\Windows\ediskVolume1\Windows\explorer.
> exe
>
> родитель ie64 - C:\Program Files\InterneProgram Files\Internet
> Explorer\iexplore.exe
>
> ie32 - C:\Program Files (x86)\Integram Files (x86)\Internet
> Explorer\iexplore.exe

забавные пути...


KilkennyCat   (2010-06-17 17:19:00) [9]

ну и последнее забыл - результаты идентичны для пользователей с правами: администратора; домашних пользователей; пользователя.


KilkennyCat   (2010-06-17 17:15:00) [10]

еще дополнение - ниже указанные функции не повлияли на вышеуказанный результат

procedure EnableAllPrivileges;
var c1, c2 : dword;
   ptp : PTokenPrivileges;
   i1 : integer;
begin
 if OpenProcessToken(windows.GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, c1) then
   try
     c2 := 0;
     GetTokenInformation(c1, TokenPrivileges, nil, 0, c2);
     if c2 <> 0 then begin
       ptp := AllocMem(c2);
       if GetTokenInformation(c1, TokenPrivileges, ptp, c2, 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(c1, false, ptp^, c2, PTokenPrivileges(nil)^, cardinal(pointer(nil)^));
       end;
       FreeMem(ptp);
     end;
   finally CloseHandle(c1) end;
end;

function ChangeFSRedirection(bDisable: Boolean): Boolean;
type
    TWow64DisableWow64FsRedirection = Function(Var Wow64FsEnableRedirection: LongBool): LongBool; StdCall;
    TWow64EnableWow64FsRedirection = Function(var Wow64FsEnableRedirection: LongBool): LongBool; StdCall;
var
   hHandle: THandle;
   Wow64DisableWow64FsRedirection: TWow64DisableWow64FsRedirection;
   Wow64EnableWow64FsRedirection: TWow64EnableWow64FsRedirection;
   Wow64FsEnableRedirection: LongBool;
begin
 Result := false;

// if not IsWindows64 then
  //  Exit;

 try
   hHandle := GetModuleHandle('kernel32.dll');
   @Wow64EnableWow64FsRedirection := GetProcAddress(hHandle, 'Wow64EnableWow64FsRedirection');
   @Wow64DisableWow64FsRedirection := GetProcAddress(hHandle, 'Wow64DisableWow64FsRedirection');

   if bDisable then
   begin
    if (hHandle <> 0) and (@Wow64DisableWow64FsRedirection <> nil) then
    begin
      Wow64DisableWow64FsRedirection(Wow64FsEnableRedirection);
      Result := True;
    end;
   end else
   begin
    if (hHandle <> 0) and (@Wow64EnableWow64FsRedirection <> nil) then
    begin
      Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection);
      Result := True;
    end;
   end;
 Except
 end;
end;


KilkennyCat   (2010-06-17 17:11:00) [11]

напомню, на всяк пожарный, что тест проходит с коррекцией A на W


KilkennyCat   (2010-06-17 17:10:00) [12]

Работает при вызове из среды - C:\Program Files (x86)\Embarcad Files (x86)\Embarcadero\RAD Studio\7.0\bin\bds.exe

из проводника win7x64 - C:\Windows\ediskVolume1\Windows\explorer.exe

родитель ie64 - C:\Program Files\InterneProgram Files\Internet Explorer\iexplore.exe

ie32 - C:\Program Files (x86)\Integram Files (x86)\Internet Explorer\iexplore.exe


sniknik   (2010-06-17 16:46:00) [13]

Еще на проверку... ???
Уже ради новой функции GetModuleFileNameEx.

function GetProcessImageFileName(hProcess: tHANDLE; lpImageFileName: LPTSTR; nSize: DWORD): DWORD; stdcall; external 'psapi.dll' name 'GetProcessImageFileNameA';

function ParentProcName: string;
var
 Info: PROCESS_BASIC_INFORMATION;
 ProcessName: string;
 Hndl: THandle;

 function GetModuleFileNameEx(hProcess: THandle; lpFilename: PChar; nSize: DWORD): DWORD;

   function DevicePathToWin32Path(lpFilename: PChar): DWORD;
   var
     c: char;
     sPath, sRes, s: string;
     i: integer;
   begin
     sPath:= lpFilename;

     i:= PosEx('\', sPath, 2);
     i:= PosEx('\', sPath, i + 1);
     sRes:= Copy(sPath, i, Length(sPath));
     Delete(sPath, i, Length(sPath));

     for c:= 'A' to 'Z' do begin
       SetLength(s, MAX_PATH);
       if QueryDosDevice(PChar(String(c) + ':'), PChar(s), 1000) <> 0 then begin
         s:= PChar(s);
         if SameText(sPath, s) then begin
           sRes:= c + ':' + sRes;
           result:= Length(sRes);
           Move(sRes[1], lpFilename[0], result + 1);
           Exit;
         end;
       end;
     end;

     result:= 0;
   end;

 begin
   result:= GetProcessImageFileName(hProcess, lpFilename, nSize);
   if result > 0 then
     result:= DevicePathToWin32Path(lpFilename);
 end;

begin
 result:= 'noname';
 if NtQueryInformationProcess(GetCurrentProcess, 0, @Info, SizeOf(Info), nil) = NO_ERROR
   then begin
     Hndl:= OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, Info.uInheritedFromUniqueProcessId);
     if Hndl <> 0 then
       try
         SetLength(ProcessName, MAX_PATH);

         if GetModuleFileNameEx(Hndl, PChar(ProcessName), MAX_PATH) > 0
           then result:= PChar(ProcessName);
       finally
         CloseHandle(Hndl);
       end;
   end;
end;


sniknik   (2010-06-17 15:45:00) [14]

> это должно быть всем интересно, ибо x64 у юзверей все более и более...
Согласен. Мне самому тоже, оказывается... нашел в другой проге использование GetModuleFileNameEx ... счастье, что ее еще под x64 не запускали. Как понимаю как только так будет та же проблема (там у меня ей читается полный путь к программе, а т.к. это единственное чем разделяются копии... в общем можно продолжить).


KilkennyCat   (2010-06-17 15:31:00) [15]

Ну, я еще потрепыхался, немного переписал PSAPI и вызвал K32GetModuleBaseNameW из kernel32 - разницы нет, если родитель 32 - работает, если 64 - не работает


> если кому вообще это интересно

это должно быть всем интересно, ибо x64 у юзверей все более и более...


sniknik   (2010-06-17 15:25:00) [16]

> GetModuleFileNameExW тоже не работает при родителе x64
Ну и ладно, все остальное это уже чисто ради интереса (если кому вообще это интересно), меня и перебор процессов устроит, все одно делается это только один раз при старте.

> а как принудительно заставить компилятор принять PSAPI_VERSION=1 и надо ли это делать?
Х.з.


KilkennyCat   (2010-06-17 15:11:00) [17]


> то скорее всего из-за "юникодности" твоей дельфи из-за которой
> мой код стал не совсем правильным.

разумеется, но это я подправил (GetModuleBaseNameW(Hndl, 0, PWideChar(ProcessName), MAX_PATH)


> GetModuleBaseNameEx в PsAPI отсутствует, а зря...
> У меня присутствует

гм... странно.
вообще, как я понял из MSDN, ее нет, и все должно корректно работать, если ее вызов подменяется вызовом K32GetModuleBaseName,


> Проверь если не сложно.

GetModuleFileNameExW тоже не работает при родителе x64

а как принудительно заставить компилятор принять PSAPI_VERSION=1 и надо ли это делать? (попалось обсуждение аналогичной проблемы у драйверописателей)


sniknik   (2010-06-17 14:58:00) [18]

> GetModuleBaseNameEx в PsAPI отсутствует, а зря...
У меня присутствует, но использовать наверное лучше GetModuleFileNameEx Aв моем варианте (у тебя если Delphi10, с юникодом Delphi10 GetModuleFileNameEx W).

Проверь если не сложно.

> первый - ошибка
Это скорее всего из-за "юникодности" твоей дельфи из-за которой мой код стал не совсем правильным.


KilkennyCat   (2010-06-17 14:54:00) [19]


> А что с ним тоже работает?

да вот пытаюсь разобраться, существует ли она ваще в природе...


sniknik   (2010-06-17 14:50:00) [20]

> Работает!
Спасибо!

> GetModuleBaseNameEx в PsAPI отсутствует, а зря...
А что с ним тоже работает?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо