Господа, а как дернуть pid по hwnd?
Я так люблю виндовые переопределения типов... Задолбался уже...
Во 1 GetWindowThreadProcessId я же правильно понимаю, что это НЕ оно? Он же id потока вернет?
GetProcessHandleFromHwnd требует чтобы ему передали HWND__. Что есть это нашлась только одна страничка с гордой структурой из одного инта. Как еще через ffi воссоздать не понимаю. Объявляю define, делаю ffi.new('HWND__[1]' говорит declaration specifier expected near 'HWND__'...
хэндл естественно имеет type number луашный. workwindow()
Не, ну чего ты как маленький...
https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types
Берешь свой HWND и распутываешь до С-совместимого типа. А вообще все должно прекрасно кастится к интам/войдам, Да там в целом вариантов то других и нет
Ну так я был там. В том и проблема, что HWND__ там нет. О нем вообще описание от майкрософта "сами напрямую использовать не можете" и на этом все. GetProcessHandleFromHwnd требует его. По крайней мере луа орет на него. Попытки объявить эту структуру ни к чему не привели. В доках требуется HWND, а не HWND__.
ffi.cdef([[
typedef void * PVOID;
typedef PVOID HANDLE;
typedef HANDLE HWND;
typedef unsigned long DWORD;
HANDLE GetProcessHandleFromHwnd(HWND hwnd);
DWORD GetProcessId(HANDLE Process);
]])
local ole = ffi.load('Oleacc.dll')
--local user, kernel = ffi.load('User32'), ffi.load('Kernel32')
local PROCESS_VM_READ = 0x0010
function readDword(address)
if workwindow() == 0 then log('No Workwindow') return -1 end
local PID, pointer_int, hwnd = ffi.new('unsigned long[1]'), ffi.new('int[1]'), ffi.new('HWND[1]')
local puint = ffi.new('unsigned int[1]')
puint[1] = workwindow()
hwnd = ffi.cast("HWND", puint)
log(tostring(hwnd))
PID[1] = ole.GetProcessHandleFromHwnd(hwnd[1])
--lua
local ffi = require("ffi")
local user = ffi.load('User32')
log 'clear' log 'mode compact'
ffi.cdef[[
typedef unsigned long DWORD;
typedef DWORD *LPDWORD;
struct HWND__ { int unused; }; typedef struct HWND__ *HWND;
DWORD GetWindowThreadProcessId( HWND hWnd, LPDWORD lpdwProcessId );
]]
local pid = ffi.new('DWORD[1]')
user.GetWindowThreadProcessId(ffi.cast('HWND', workwindow()), pid)
log(tonumber(pid[0]))
--lua
local ffi = require("ffi")
local user = ffi.load('User32')
log 'clear' log 'mode compact'
ffi.cdef[[
typedef unsigned long DWORD;
typedef DWORD *LPDWORD;
DWORD GetWindowThreadProcessId( unsigned long hWnd, LPDWORD lpdwProcessId );
]]
local pid = ffi.new('DWORD[1]')
user.GetWindowThreadProcessId(workwindow(), pid)
log(tonumber(pid[0]))
GetWindowThreadProcessId вернет разве id процесса? Он же потока возвращает. В этом то и суть проблемы. C GetWindowThreadProcessId работало и у меня =)
ffi.cdef([[
typedef void * PVOID;
typedef PVOID HANDLE;
typedef HANDLE HWND;
typedef unsigned long DWORD;
HANDLE GetProcessHandleFromHwnd(HWND hwnd);
DWORD GetProcessId(HANDLE Process);
]])
local ole = ffi.load('Oleacc.dll')
--local user, kernel = ffi.load('User32'), ffi.load('Kernel32')
local PROCESS_VM_READ = 0x0010
function readDword(address)
if workwindow() == 0 then log('No Workwindow') return -1 end
local PID, pointer_int, hwnd = ffi.new('unsigned long[1]'), ffi.new('int[1]'), ffi.new('HWND[1]')
local puint = ffi.new('unsigned int[1]')
puint[1] = workwindow()
hwnd = ffi.cast("HWND", puint)
log(tostring(hwnd))
PID[1] = ole.GetProcessHandleFromHwnd(hwnd[1])
GetWindowThreadProcessId возвращает ид потока, в переменную ид процесса.
мля а вот теперь стыдно стало =)
тем не менее GetProcessHandleFromHwnd почему не шуршит то? прям зацепило...
ffi.cdef([[
typedef void * PVOID;
typedef PVOID HANDLE;
typedef HANDLE HWND;
typedef unsigned long DWORD;
typedef DWORD * LPDWORD;
HANDLE GetProcessHandleFromHwnd(HWND hwnd);
DWORD GetProcessId(HANDLE Process);
int OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
int GetWindowThreadProcessId(int hWnd, int *lpdwProcessId);
bool CloseHandle(int hObject);
bool ReadProcessMemory(int hProcess, int lpBaseAddress, void *lpBuffer, int nSize, int *lpNumberOfBytesRead);
int GetModuleHandleA(const char *lpModuleName);
]])
local ole = ffi.load('Oleacc.dll')
local user, kernel = ffi.load('User32'), ffi.load('Kernel32')
local PROCESS_VM_READ = 0x0010
function readDword(address)
if workwindow() == 0 then log('No Workwindow') return -1 end
local PID, pointer_int, hwnd = ffi.new('unsigned long[1]'), ffi.new('int[1]'), ffi.new('unsigned int[1]')
local puint = ffi.new('unsigned int[1]')
puint[0] = workwindow()
hwnd = ffi.cast("HWND", puint)
-- log(tostring(hwnd))
local pvoid = ole.GetProcessHandleFromHwnd(hwnd)
log(tostring(pvoid))
local r = ffi.cast("unsigned int * ", pvoid)
log(tostring(r))
log(tostring(r[0]))
log(tonumber(r[0]))
log"wtf"
А почему вообще оле используется ? Зачем он тут
Проще так:
--lua
local ffi = require("ffi")
log 'clear' log 'mode compact'
ffi.cdef([[
unsigned int GetProcessHandleFromHwnd(unsigned int hwnd);
]])
local ole = ffi.load('Oleacc.dll')
function readDword()
if workwindow() == 0 then log('No Workwindow') return -1 end
return ole.GetProcessHandleFromHwnd(workwindow())
end
log (readDword())
Куда туда ? Зачем что то засовывать, если cirus дал конечный код. Если у тебя при его использовании выводится в лог не 0, то все работает.
user.GetWindowThreadProcessId(ffi.cast('HWND', workwindow()), pid)
Работает на пилоте, на блокноте не хочет. На Notepad++ работает, если привязать к заголовку, но не работает, если привязать к рабочей области...
Не проще посмотреть пример чтения памяти?
https://forum.uokit.com/index.php?s=&showtopic=70333&view=findpost&p=437715
Банально взять тот же ReadProcessMemory
по майкрософту он
BOOL ReadProcessMemory(
[in] HANDLE hProcess,
[in] LPCVOID lpBaseAddress,
[out] LPVOID lpBuffer,
[in] SIZE_T nSize,
[out] SIZE_T *lpNumberOfBytesRead
);
HANDLE это цепочка
typedef void * PVOID;
typedef PVOID HANDLE;
Т.е. по сути у нас должен отправиться указатель на данные. Ну т.е. типа принимающая функция ее должна разыменовать и работать с данными. cirus передает не указатель на данные, а непосредственно int с данными:
bool ReadProcessMemory(int hProcess, int lpBaseAddress, void *lpBuffer, int nSize, int
При этом указатель не пашет, а инт пашет. Учитывая сказанное тобой выше про то, что хэндл это не совсем указатель единственное, что мне приходит в голову, что есть некоторый лист хэндлов, а тип данных тут от балды и в целевой функции нет разыменовывания и данные используются напрямую (типа индекса в листе). Но зачем тогда городить указатели, а не объявить изначально хэндл интом я вообще не понимаю. Указатель должен указывать на адрес, а он(когда там хэндл) указывает на не аллоцированную область.
Вся цепочка проблем с которыми я столкнулся по сути одинаковая в каждой функции. Я хэндл воспринимал, как указатель на данные (а по typedef так и есть), а там сами данные...
Ну давай попробуем по порядку:
1) Любой указатель можно представить как int, т.к. по сути указатель и есть число, обозначающее номер ячейки памяти
2) Функция принимает:
- хендл
- базовый адрес откуда читаем
- выходной буффер куда пишем
- указатель на переменную в которую запишется кол-во считанных байт
Т,е. даже из самой сигнатуры становится понятно, что чтение будет из LPCVOID lpBaseAddress и хендл здесь является тем чем и должен - просто дескриптором процесса, в котором аллоцирован блок памяти, доступный по LPCVOID lpBaseAddress (может быть и смещенным).
Откуда у тебя убеждение что хендл == указатель на данные я не понимаю. То что он тайпдефнут как void* или еще что-то не делает его НЕ int'ом. Это все то же число которое можно представить и как int и как void* и как char*. Конкретное его значение интерпретируется в кишках системы везде по разному - где-то это реально поинтер на данные, где-то индекс в буффере ядра, о чем и пишут где-то мелкомягкие. пользователю достаточно этот хендл гонять из функции в функцию и не пытаться его разыменовать/прочитать и т.д.
Использование void* не в качестве указателя обусловлено необходимостью поддерживать родную для системы битность. Ну т.е. если написать int, то не факт что в скомпилированном приложении он будет 32(64) бита занимать, а void* всегда либо 32 либо 64 в зависимости под какую битность собираешь. Но это вроде даже в Си уже улучшили, просто мелкомягкие не обновили доки + хедеры.
Собственно HANDLE так вот и прячет детали реализации от юзера апи
Да, возвращает GetWindowThreadProcessId действительно thread id, но там есть out параметр для пида.
Скопипасчу пример кода из адаптера для винапи который я сделал.
local WinUser = ffi.load('User32')
ffi.cdef[[
int __stdcall GetWindowThreadProcessId(int hWnd, int *lpdwProcessId);
]]
local WinApiInterface = {}
function WinApiInterface.GetWindowThreadProcessId(handle)
local pid = ffi.new("int[1]")
local threadId = WinUser.GetWindowThreadProcessId(handle, pid)
assert(threadId ~= 0, 'GetWindowThreadProcessId error: incorrect handle passed: '..handle)
return {
pid = pid[0],
threadId = threadId
}
end
return WinApiInterface
А есть ли у тебя опыт поддержки кодовой базы в миллионы строк кода на протяжении лет 20-30 ? Это с высоты текущих лет все кажется быдлокодом и костылями, а во времена когда это писалось просто не было даже намека на современные возможности/подходы к разработке.
Ну это прям разные случаи. От тебя не зависело до половины пользователей ПК в мире)
А между тем, реального говнокода полно в банках, на нем крутится куча транзакций и ничего. И когда переводишь кому то деньгу - знай, в этот момент работает сортировка аналогичная твоей.
Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)