Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Разное
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Закрытая тема
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 04.07.2012, 15:25
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию Ошибка получения имени модуля

Вызываю функцию CreateProcess с ключами DEBUG_PROCESS or DEBUG_ONLY_THIS_PROCESS, получаю хэндл процесса, спокойно его (в смысле память процесса) читаю/пишу, запрашиваю состояния памяти, какбе все норм, но вот вызывая GetModuleFileNameEx(или GetModuleBaseName) получаю в LastError = 6 (INVALID_HANDLE_VALUE).
Тут есть какая-то специфика использования этой ф-ии, или может я что-то не то понаделал?

Задача - получить имя и путь запущенного приложения.

P.S. При приаттачивании процесса функции работают корректно.

Уж не придется ли переходить на NtQuerySystemInformation?
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию

Последний раз редактировалось M.A.D.M.A.N., 04.07.2012 в 15:40.
  #2  
Старый 04.07.2012, 16:21
Pyro Pyro вне форума
Так проходящий
 
Регистрация: 18.07.2011
Сообщения: 805
Версия Delphi: 7Lite
Репутация: 6063
По умолчанию

такая вроде работает
Код:
uses psapi;

function ProcessFileName(PID: DWORD): string;
var
  Handle: THandle;
begin
  Result := '';
  Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
  if Handle <> 0 then
    try
      SetLength(Result, MAX_PATH);
      if GetModuleFileNameEx(Handle, 0, PChar(Result), MAX_PATH) > 0 then
        SetLength(Result, StrLen(PChar(Result)))
      else
        Result := '';
    finally
      CloseHandle(Handle);
    end;
end;
  #3  
Старый 04.07.2012, 18:34
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Так-то она работает, а вот при пошаговой загрузке процесса почему-то не хочет (хотя тот же процес эксплорер отображает информацию). Т.е. я отлавливаю событие ON_DLL_LOAD и пытаюсь получить имя модуля по base address, в итоге фига с маслом. Но все равно не понятно, почему результат invalid handle, а не что-то другое.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
  #4  
Старый 04.07.2012, 18:37
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Вот оно чё:
Цитата:
If you call this function shortly after creating the process, or if the process was created suspended, the module list may not have been created yet and this function fails with ERROR_INVALID_HANDLE.

ПРидется ковырять в сторону NtQuerySystemInformation, или еще того хуже.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию

Последний раз редактировалось M.A.D.M.A.N., 04.07.2012 в 18:39.
  #5  
Старый 05.07.2012, 10:37
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Вот решение:
Код:
type
   PDebugModule = ^TDebugModule;
   TDebugModule = packed record
     Reserved: array [0..1] of Cardinal;
     Base: Cardinal;
     Size: Cardinal;
     Flags: Cardinal;
     Index: Word;
     Unknown: Word;
     LoadCount: Word;
     ModuleNameOffset: Word;
     ImageName: array [0..$FF] of Char;
   end;
 
 type
   PDebugModuleInformation = ^TDebugModuleInformation;
   TDebugModuleInformation = record
     Count: Cardinal;
     Modules: array [0..0] of TDebugModule;
   end;
   PDebugBuffer = ^TDebugBuffer;
   TDebugBuffer = record
     SectionHandle: THandle;
     SectionBase: Pointer;
     RemoteSectionBase: Pointer;
     SectionBaseDelta: Cardinal;
     EventPairHandle: THandle;
     Unknown: array [0..1] of Cardinal;
     RemoteThreadHandle: THandle;
     InfoClassMask: Cardinal;
     SizeOfInfo: Cardinal;
     AllocatedSize: Cardinal;
     SectionSize: Cardinal;
     ModuleInformation: PDebugModuleInformation;
     BackTraceInformation: Pointer;
     HeapInformation: Pointer;
     LockInformation: Pointer;
     Reserved: array [0..7] of Pointer;
   end;
 
 const
   PDI_MODULES = $01;
   ntdll = 'ntdll.dll';
 
var
  Form1: TForm1;
  HNtDll: HMODULE;
 
type
   TFNRtlCreateQueryDebugBuffer = function(Size: Cardinal;
     EventPair: Boolean): PDebugBuffer;
    stdcall;
   TFNRtlQueryProcessDebugInformation = function(ProcessId,
     DebugInfoClassMask: Cardinal; var DebugBuffer: TDebugBuffer): Integer;
    stdcall;
   TFNRtlDestroyQueryDebugBuffer = function(DebugBuffer: PDebugBuffer): Integer;
    stdcall;
 
 var
   RtlCreateQueryDebugBuffer: TFNRtlCreateQueryDebugBuffer;
   RtlQueryProcessDebugInformation: TFNRtlQueryProcessDebugInformation;
   RtlDestroyQueryDebugBuffer: TFNRtlDestroyQueryDebugBuffer;
 
implementation
 
{$R *.dfm}
 
function LoadRtlQueryDebug: LongBool;
 begin
   if HNtDll = 0 then
   begin
     HNtDll := LoadLibrary(ntdll);
     if HNtDll <> 0 then
     begin
       RtlCreateQueryDebugBuffer       := GetProcAddress(HNtDll,
         'RtlCreateQueryDebugBuffer');
       RtlQueryProcessDebugInformation := GetProcAddress(HNtDll,
         'RtlQueryProcessDebugInformation');
       RtlDestroyQueryDebugBuffer      := GetProcAddress(HNtDll,
         'RtlDestroyQueryDebugBuffer');
     end;
   end;
   Result := Assigned(RtlCreateQueryDebugBuffer) and
     Assigned(RtlQueryProcessDebugInformation) and
     Assigned(RtlQueryProcessDebugInformation);
 end;
 
function getProcessModule(pid : cardinal):String;
 var
   DbgBuffer: PDebugBuffer;
   Loop: Integer;
   s:string;
 begin
Result:='';
   if not LoadRtlQueryDebug then Exit;
 
   DbgBuffer := RtlCreateQueryDebugBuffer(0, false);
   if Assigned(DbgBuffer) then
     try
       if RtlQueryProcessDebugInformation(pid, PDI_MODULES, DbgBuffer^) >= 0 then
       begin
         for Loop := 0 to DbgBuffer.ModuleInformation.Count - 1 do
          S:=S+#13#10+DbgBuffer.ModuleInformation.Modules[Loop].ImageName;
          Result:=S;
       end;
     finally
       RtlDestroyQueryDebugBuffer(DbgBuffer);
     end;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Text:=getProcessModule(GetCurrentProcessId);
end;

Интересно работает, заставляет процесс подгрузить все модули без сигнализирования события отладчику.
Решение сперто отсюда: http://forum.sources.ru/index.php?showtopic=324532
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Закрытая тема


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 13:07.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter