Конференция "WinAPI" » Можно ли узнать имя родительского процесса в 64 разрядной винде? [D7, WinXP]
 
  • sniknik © (17.06.10 11:42) [0]
    Интересует естественно вариант из 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. Догадки, и тесты (типа что за ошибку дает вот в этом месте) могу проверить только вечером. А вот если есть "железный" вариант, то можно и сейчас побегать...
  • KilkennyCat © (17.06.10 12:46) [1]
    рискну пальцем в небо ткнуть...
    if NtQueryInformationProcess(GetCurrentProcess, 26, @Info, SizeOf(Info), nil) = NO_ERROR
  • sniknik © (17.06.10 12:49) [2]
    Проверю вечером.
  • KilkennyCat © (17.06.10 12:50) [3]
    я ща сам проверю... я на семерке
  • KilkennyCat © (17.06.10 13:13) [4]
    не, не помогло.
  • sniknik © (17.06.10 13:15) [5]
    Оно и понятно... посмотрел MSDN

    ProcessWow64Information 26
    -
    Determines whether the process is running in the WOW64 environment (WOW64 is the x86 emulator that allows Win32-based applications to run on 64-bit Windows).

    It is best to use the IsWow64Process function to obtain this information.


    т.е. это просто "информационный дубль".
  • KilkennyCat © (17.06.10 13:31) [6]
    ну. но я подумал, фиг знает... уже бывало, напишут одно, работает по-другому.
  • sniknik © (17.06.10 13:59) [7]
    > я ща сам проверю... я на семерке
    А вот такой "тупой" перебор не проверишь? Мало надежды конечно, но ...
    > напишут одно, работает по-другому.


    uses ... TlHelp32;

    function ParentProcName2: string;
    var
     i: integer;
     ProcessID, ParentProcessID: DWORD;
     hSnapshot: THandle;
     ProcessEntry: TProcessEntry32;
     ProcessList: TStringList;
    begin
     result:= 'noname';

     ProcessList:= TStringList.Create;
     try
       ProcessID:= GetCurrentProcessID;
       ParentProcessID:= 0;
       hSnapshot:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
       if hSnapshot <> INVALID_HANDLE_VALUE then try
         ProcessEntry.dwSize:= SizeOf(ProcessEntry);
         if Process32First(hSnapshot, ProcessEntry) then begin
           repeat
             ProcessList.AddObject(ProcessEntry.szExeFile, TObject(ProcessEntry.th32ProcessID));
             if ProcessEntry.th32ProcessID = ProcessID then
               ParentProcessID:= ProcessEntry.th32ParentProcessID;
           until not Process32Next(hSnapshot, ProcessEntry)
         end
       finally
         CloseHandle(hSnapshot)
       end;
       if ParentProcessID <> 0 then begin
         i:= ProcessList.IndexOfObject(TObject(ParentProcessID));
         if i <> -1 then
           result:= ProcessList.Strings[i]
       end;
     finally
       ProcessList.Free
     end;
    end;

  • KilkennyCat © (17.06.10 14:24) [8]
    Работает!

    В первом варианте, как я понял, не отрабатывает GetModuleBaseNameA.

    Тестировалось на Delphi10, win7 x64, AMD 4ядра
    при запуске из под делфи оба варианта выдают bds.exe
    при запуске из IE64 (умнее не придумал) первый - ошибка, второй - iexplore.exe
  • KilkennyCat © (17.06.10 14:33) [9]
    GetModuleBaseNameEx в PsAPI отсутствует, а зря...
  • sniknik © (17.06.10 14:50) [10]
    > Работает!
    Спасибо!

    > GetModuleBaseNameEx в PsAPI отсутствует, а зря...
    А что с ним тоже работает?
  • KilkennyCat © (17.06.10 14:54) [11]

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

    да вот пытаюсь разобраться, существует ли она ваще в природе...
  • sniknik © (17.06.10 14:58) [12]
    > GetModuleBaseNameEx в PsAPI отсутствует, а зря...
    У меня присутствует, но использовать наверное лучше GetModuleFileNameExA в моем варианте (у тебя если Delphi10, с юникодом Delphi10 GetModuleFileNameExW).

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

    > первый - ошибка
    Это скорее всего из-за "юникодности" твоей дельфи из-за которой мой код стал не совсем правильным.
  • KilkennyCat © (17.06.10 15:11) [13]

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

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


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

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


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

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

    а как принудительно заставить компилятор принять PSAPI_VERSION=1 и надо ли это делать? (попалось обсуждение аналогичной проблемы у драйверописателей)
  • sniknik © (17.06.10 15:25) [14]
    > GetModuleFileNameExW тоже не работает при родителе x64
    Ну и ладно, все остальное это уже чисто ради интереса (если кому вообще это интересно), меня и перебор процессов устроит, все одно делается это только один раз при старте.

    > а как принудительно заставить компилятор принять PSAPI_VERSION=1 и надо ли это делать?
    Х.з.
  • KilkennyCat © (17.06.10 15:31) [15]
    Ну, я еще потрепыхался, немного переписал PSAPI и вызвал K32GetModuleBaseNameW из kernel32 - разницы нет, если родитель 32 - работает, если 64 - не работает


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

    это должно быть всем интересно, ибо x64 у юзверей все более и более...
  • sniknik © (17.06.10 15:45) [16]
    > это должно быть всем интересно, ибо x64 у юзверей все более и более...
    Согласен. Мне самому тоже, оказывается... нашел в другой проге использование GetModuleFileNameEx ... счастье, что ее еще под x64 не запускали. Как понимаю как только так будет та же проблема (там у меня ей читается полный путь к программе, а т.к. это единственное чем разделяются копии... в общем можно продолжить).
  • sniknik © (17.06.10 16:46) [17]
    Еще на проверку... ???
    Уже ради новой функции 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;

  • KilkennyCat © (17.06.10 17:10) [18]
    Работает при вызове из среды -
    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

  • KilkennyCat © (17.06.10 17:11) [19]
    напомню, на всяк пожарный, что тест проходит с коррекцией A на W
 
Конференция "WinAPI" » Можно ли узнать имя родительского процесса в 64 разрядной винде? [D7, WinXP]
Есть новые Нет новых   [134431   +10][b:0][p:0.003]