Форум: "WinAPI";
Текущий архив: 2004.02.02;
Скачать: [xml.tar.bz2];
ВнизКак определить запуск кокого либо приложения? Найти похожие ветки
← →
Piople (2003-11-17 09:08) [0]Скажите пожалуйста как можно перехватить запуск приложения, плизз. Я ставлю глобальный хук через dll на WM_create, но он ловит все сообщения в системе, а мне нужно только чтобы ловились вновь стартующие приложения, заранее ШПАШИБО.
← →
Digitman (2003-11-17 09:18) [1]после установки любого глоб.хука хук-DLL автоматически внедряется во все существующие GUI-процессы.
с этого момента, как только будут стартовать новые GUI-процессы, система будет автоматически внедрять твою хук-DLL в эти процессы.
это и можно считать фактом старта нового GUI-процесса, т.е. процедура инициализации твоей DLL будет получать управление всякий раз, когда система будет внедрять твою DLL во вновь стартовавший GUI-процесс. перехват же wm_create - это уже лишнее.
← →
Piople (2003-11-17 09:26) [2]
> после установки любого глоб.хука хук-DLL автоматически внедряется
> во все существующие GUI-процессы.
>
> с этого момента, как только будут стартовать новые GUI-процессы,
> система будет автоматически внедрять твою хук-DLL в эти
> процессы.
>
> это и можно считать фактом старта нового GUI-процесса, т.е.
> процедура инициализации твоей DLL будет получать управление
> всякий раз, когда система будет внедрять твою DLL во вновь
> стартовавший GUI-процесс. перехват же wm_create - это уже
> лишнее.
Не понял так как тогда обратится та к этому процессу
← →
Digitman (2003-11-17 09:49) [3]
> Не понял так как тогда обратится та к этому процессу
а я не понял, что значит "обратится"
← →
Piople (2003-11-17 09:59) [4]
> а я не понял, что значит "обратится"
Вообщем я хочу сделать так чтобы все главные формы приложений появлялись плавно, я использую для этого Alpha, все работает если напремую указать хэндл окна, но как быть только с вновь появляющимися
← →
Digitman (2003-11-17 10:06) [5]при инициализации хук-DLL перехватывай все winapi-вызовы CreateWindow[Ex], выполняемые в контексте данного процесса
← →
Piople (2003-11-17 10:09) [6]
> при инициализации хук-DLL перехватывай все winapi-вызовы
> CreateWindow[Ex], выполняемые в контексте данного процесса
А, это исходника нет, для наглядности :)
← →
Digitman (2003-11-17 10:29) [7]
function SetProcAddress(hModule: THandle; lpProcName: PChar; pProcAddr: Pointer): Boolean;
var
Peb: PPeb;
hProcess, hImporter: THandle;
pOptHdr: PImageOptionalHeader;
pImpDir: PImageImportDescriptor;
pExpDir: PImageExportDirectory;
pIATEntry: PImageThunkData;
pOldProcAddr: Pointer;
pdwNamePtr, pdwEntryPoint: PDWord;
pName: PChar;
pwOrdinalPtr: PWord;
i, nOrdinal, dwNewProcAddrRVA, dwProtect: DWord;
pLdrData : PPEB_LDR_DATA;
pLoadOrderList : PPLIST_ENTRY;
pInLoadModuleEntry: PModuleEntry;
pModuleNfo: PModuleInfo;
pImpModuleNfo: PModuleInfo;
sModuleName: String;
dwDirSize: DWord;
begin
Result := False;
if (hModule = 0) or (lpProcName = nil) then Exit;
peb := GetCurrentPEB;
LockLoader(Peb);
try
pModuleNfo := FindModuleInfo(hModule);
if not Assigned(pModuleNfo) then Exit;
sModuleName := WideCharToString(pModuleNfo^.BaseDllName.Buffer);
pOptHdr := PImageOptionalHeader(hModule + PImageDosHeader(hModule)._lfanew + SIZE_OF_NT_SIGNATURE + IMAGE_SIZEOF_FILE_HEADER);
dwDirSize := pOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
if (pOptHdr^.NumberOfRvaAndSizes < 16) or (dwDirSize = 0) then Exit;
pExpDir := PImageExportDirectory(hModule + pOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
pdwEntryPoint := nil;
pwOrdinalPtr := PWord(hModule + DWord(pExpDir^.AddressOfNameOrdinals));
if HiWord(DWord(lpProcName)) = 0 then
begin
nOrdinal := LoWord(DWord(lpProcName)) - pExpDir^.Base;
if (nOrdinal < pExpDir^.NumberOfFunctions) then
pdwEntryPoint := PDWord(hModule + DWord(pExpDir^.AddressOfFunctions) + nOrdinal * SizeOf(PDWord));
end
else
begin
pdwNamePtr := PDWord(hModule + DWord(pExpDir^.AddressOfNames));
for i := 0 to pExpDir^.NumberOfNames - 1 do
begin
pName := PChar(PDWord(hModule + PDword(pdwNamePtr)^));
if lstrcmp(pName,lpProcName) = 0 then
begin
nOrdinal := pwOrdinalPtr^;
pdwEntryPoint := PDWord(hModule + DWord(pExpDir^.AddressOfFunctions) + nOrdinal * SizeOf(PDWord));
Inc(nOrdinal, pExpDir^.Base);
Break;
end
else
begin
Inc(pdwNamePtr);
Inc(pwOrdinalPtr);
end
end;
end;
if not Assigned(pdwEntryPoint) then Exit;
pOldProcAddr := Pointer(hModule + pdwEntryPoint^);
if pOldProcAddr = pProcAddr then
Result := True
else
try
dwNewProcAddrRVA := DWord(pProcAddr) - hModule;
hProcess := OpenProcess(PROCESS_VM_OPERATION, False, GetCurrentProcessId);
Win32Check(hProcess <> 0);
try
Win32Check(VirtualProtectEx(hProcess, pExpDir, dwDirSize, PAGE_WRITECOPY, dwProtect));
try
pdwEntryPoint^ := dwNewProcAddrRVA;
finally
VirtualProtectEx(hProcess, pExpDir, dwDirSize, dwProtect, dwProtect);
end;
pName := PChar(sModuleName);
pLdrData := Peb^.LdrData;
pLoadOrderList := @pLdrData.InLoadOrderModuleList;
pInLoadModuleEntry := PModuleEntry(pLoadOrderList^);
while PPListEntry(pInLoadModuleEntry) <> pLoadOrderList do
begin
pImpModuleNfo := @pInLoadModuleEntry.ModuleInfoData;
if pImpModuleNfo <> pModuleNfo then
begin
hImporter := THandle(pImpModuleNfo^.DllBase);
pOptHdr := PImageOptionalHeader(hImporter + PImageDosHeader(hImporter)._lfanew + SIZE_OF_NT_SIGNATURE + IMAGE_SIZEOF_FILE_HEADER);
if pOptHdr^.NumberOfRvaAndSizes = 16 then
begin
dwDirSize := pOptHdr^.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
if dwDirSize > 0 then
begin
pImpDir := PImageImportDescriptor(hImporter + pOptHdr^.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while Assigned(PChar(pImpDir^.RVAImportModuleName)) do
begin
if lstrcmpi(PChar(hImporter + pImpDir^.RVAImportModuleName), pName) = 0 then
begin
pIATEntry := PImageThunkData(hImporter + DWord(pImpDir^.RVAImportAddressTable));
while Assigned(pIATEntry^.Func) do
begin
if pIATEntry^.Func = pOldProcAddr then
begin
Win32Check(VirtualProtectEx(hProcess, pIATEntry, SizeOf(pIATEntry), PAGE_WRITECOPY, dwProtect));
try
pIATEntry^.Func := pProcAddr;
finally
VirtualProtectEx(hProcess, pIATEntry, SizeOf(pIATEntry), dwProtect, dwProtect);
end;
Break;
end;
Inc(pIATEntry);
end;
end;
Inc(pImpDir);
end;
end;
end;
end;
pInLoadModuleEntry := PModuleEntry(pInLoadModuleEntry.InLoadOrderLinks.Flink);
end;
finally
CloseHandle(hProcess);
end;
Result := True;
except
end;
finally
UnLockLoader(Peb);
end;
end;
← →
Piople (2003-11-18 07:02) [8]У меня немного попроще. Вообщем я сам дапетрил как поставить глаб хук на запуск нового приложения, но вот как получить его Хэндл, для дальнейшей с ним работы я не знаю. Может быть подскажите. Заранее спасибо. Вот сам листинг:
library hook_dll;
uses
Windows,
Messages,
Forms;
var
SysHook : HHook = 0;
Wnd : Hwnd = 0;
function SysMsgProc(code : integer; wParam : word; lParam : longint) : longint; stdcall;
begin
if code = HSHELL_WINDOWCREATED then
begin
//Сдесь делаем с окном все что нужно
end;
Result:=CallNextHookEx(SysHook, Code, wParam, lParam);
end;
procedure hook(switch : Boolean) export; stdcall;
begin
if switch=true then
begin
SysHook := SetWindowsHookEx(WH_SHELL, @SysMsgProc, hInstance, 0);
if SysHook <> 0 then MessageBox(0, "HOOK2 установлен !", "Message", 0)
else MessageBox(0, "HOOK2 установить не удалось !", "Message", 0);
end
else
begin
if UnhookWindowsHookEx(SysHook) then MessageBox(0, "HOOK2 снят !","Message", 0)
else MessageBox(0, "HOOK2 снять не удалось !", "Message", 0);
SysHook := 0;
end;
end;
exports hook;
begin
end.
← →
Digitman (2003-11-18 08:24) [9]
> глаб хук на запуск нового приложения, но вот как получить
> его Хэндл
хэндл есть у процесса, хэндл есть у окна , хэндл есть у ... и т.д. и т.п.
но у приложений НЕТ никакого хэндла !
это - раз.
второе.
код твой работать не будет, потому что при ПЕРВОЙ ЖЕ попытке выполнения строчки
Result:=CallNextHookEx(SysHook, Code, wParam, lParam);
произойдет AV-исключение, ибо переменных SysHook будет столько, сколько экземпляров хук-DLL система создаст и загрузит в ВАП разлисных GUI-процессов при установке хука. Ты же инициализируешь только самый первый экз-р переменной, т.е. тот который фигурирует в явно загружаемом тобой экз-ре хук-DLL с целью вызова процедуры hook()
← →
Piople (2003-11-18 08:27) [10]Конкретизирую, мне надо хэндл главного окна, и если ты говоришь что не будт работать, то что мне надо подправить
← →
Demetrius2003 (2003-11-18 08:34) [11]>Digitman
:))))
Ну вы даёте, человек и хук толком ставить не умеет, а вы ему
перехватывай все winapi-вызовы CreateWindow[Ex] , он, наверное, и не понял, что это такое.
>Piople ©
Рано тебе ещё WinApi функции перехватывать(без обид)
← →
Piople (2003-11-18 08:35) [12]Удалено модератором
Примечание: Offtopic
← →
Digitman (2003-11-18 08:38) [13]
> Piople
а ведь Demetrius2003 © (18.11.03 08:34) [11] действительно прав !
тебе для начала нужно разобраться во всех тонкостях установки глоб.хука В ПРИНЦИПЕ, а уж затем "нагружать" хук-DLL предметной функциональностью.
Вникни в то , что я тебе сказал в [9] и исправь как минимум одну явную и серьезную ошибку в логике и принципах установки глоб.хука
← →
Piople (2003-11-18 08:41) [14]Удалено модератором
Примечание: Offtopic
← →
Digitman (2003-11-18 08:44) [15]
> Piople
здесь, на этом сайте, есть статья по принципам и логике реализации глов.хуков.
момент с хэндлом хука и глобальнодоступной памятью там изложен достаточно подробно и внятно.
изучи статью и примеры в ней, кое-что оч важное касаемое глоб.хуков у тебя при этом прояснится
← →
Piople (2003-11-18 11:42) [16]Удалено модератором
Примечание: Offtopic
← →
Demetrius2003 (2003-11-18 11:46) [17]>Piople ©
Разберись, что такое адрессное пространство процесса
Разберись , что такое ДЛЛ, и зачем она нужна, а потом сам всё поймёшь.
Джеффри Рихтер в помощь
← →
Digitman (2003-11-18 11:59) [18]
> А нет еще каких нибудь ссылок
а как же ? есть !
http://www.gramota.ru
с нее и начни, очень полезно будет для тебя, думаю
ну так ты статью-то на этом сайте изучил ? примеры разобрал ? сравнил со своим кодом ?
← →
Demetrius2003 (2003-11-18 12:08) [19]Удалено модератором
Примечание: Offtopic
← →
Piople (2003-11-19 08:29) [20]Усем, упасиба, за усЁ :)
← →
Piople (2003-11-19 08:46) [21]
> Digitman
Статью изучил, и почитал еще ряд статей, но вот про AV-исключения, и GUI не слова не нашел. Моя ошибка заключется в том, на сколько я понял, что я не обрабатываю создания других окон (кнопок, разных боксов, и т.д.) и поэтму мой хук ловит все подряд от создаваемого прложения, поэтому мне надо обработывать только создание главного окна, а то что мне не нужно пропускать, так я понял? да и зачем мне ссылка на сайт русского языка :)?
← →
Digitman (2003-11-19 10:43) [22]
> да и зачем мне ссылка на сайт русского языка
потому что у тебя и с этим, чувствуется, большие проблемы)
> Моя ошибка заключется в том, на сколько я понял, что я не
> обрабатываю создания других окон
твоя ошибка уже в том, что SysHook у тебя в момент вызова CallNextHookEx() соответствует корректному хэндлу хука только в том экз-ре хук-DLL, который ты загрузил явно.
во всех прочих экз-рах SysHook у тебя равен нулю (про AV я погорячился, его не будет), и , соотв-но, ф-ция CallNextHookEx() дает гарантированный отказ
← →
Digitman (2003-11-19 10:50) [23]ты там, в примерах в статье, видел вызовы ф-ций CreateFileMapping, MapViewOfFile ? Думаешь, от балды ф-ции вызываются ? Как раз не от балды, а из-за необходимости сделать значение хэндла хука глобально-доступным для всех процессов, в которые хук-DLL внедряется.
у тебя этого нет, а это крайне важно !
исправляй, потом будет дальнейший разговор про твои беды)
← →
Piople (2003-11-19 11:31) [24]Понял!!!
← →
Piople (2003-11-20 07:03) [25]Все сделал, статью прочитал, разобрался зачем нужны CreateFileMapping, MapViewOfFile ну и UnmapViewOfFile соответсятвенно, если обобщить они нудны для сохранения значения дескриптора установленной ловушки. Но в моем случае это было не столь важно, ведь я работаю под 2000, а она(Винда 2000), как вы и сами знаете, делает следующее:
если у вас имеется цепочка ловушек, то при выполнении функции CallNextHookEx(0, nCode, wParam, lParam ) вызывается следующая ловушка в цепочке, т.е. отпадает необходимость в передачи дескриптора, возвращаемого функцией SetWindowsHookEx.
Но тем ни мение я код подправил, как и было мне сказано :), вот что у меня получилось:
library hook_dll;
uses
Windows,
Messages,
Forms;
const
MMFName: PChar = "MemMepFile"; // имя объекта файлового отображения
//структура, поля которой будут отображены в файл подкачки
type
PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = packed record
SysHook: HWND; // дескриптор установленной ловушки
end;
var
GlobalData: PGlobalDLLData;
MMFHandle: THandle;
function SysMsgProc(code : integer; wParam : word; lParam : longint) : longint; stdcall;
begin
if code = HSHELL_WINDOWCREATED then
begin
//Здесь мне надо получить Handle гланого окна внось стартующего приложения
{Пытаемся передать сообщение дальше по цепочке hook-ов. }
Result:= CallNextHookEx(GlobalData^.SysHook, Code, wParam, lParam);
end;
{Процедура установки HOOK-а}
procedure hook(switch : Boolean) export; stdcall;
begin
if switch=true then
begin
GlobalData^.SysHook := SetWindowsHookEx(WH_SHELL, @SysMsgProc, HInstance, 0);
if GlobalData^.SysHook <> 0 then
MessageBox(0, "HOOK установлен !", "Message", 0)
else
MessageBox(0, "HOOK установить не удалось !", "Error Message", 0);
end
else
begin
if UnhookWindowsHookEx(GlobalData^.SysHook) then
MessageBox(0, "HOOK снят !", "Message", 0)
else
MessageBox(0, "HOOK снять не удалось !", "Error Message", 0);
end;
end;
procedure OpenGlobalData();
begin
{получаем объект файлового отображения}
MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TGlobalDLLData), MMFName);
if MMFHandle = 0 then
MessageBox(0, "Низя создать FileMapping", "Error Message", 0);
{отображаем глобальные данные на АП вызывающего процесса и получаем указатель
на начало выделенного пространства}
GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalDLLData));
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, "Низя заюзать MapViewOfFile", "Error Message", 0);
end;
end;
procedure CloseGlobalData();
begin
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;
procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
case dwReason of
DLL_PROCESS_ATTACH: OpenGlobalData;
DLL_PROCESS_DETACH: CloseGlobalData;
end;
end;
exports hook;
begin
{назначим поцедуру переменной DLLProc}
DLLProc:= @DLLEntryPoint;
{вызываем назначенную процедуру для отражения факта присоединения данной библиотеки к процессу}
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
Теперь мне не понятно как получить Handle гланого окна внось стартующего приложения, если я еще не сильно досталь, то БООООЛЬШОЕ пожалуйста объясните как.
← →
Digitman (2003-11-20 11:20) [26]
> ведь я работаю под 2000, а она(Винда 2000), как вы и сами
> знаете, делает следующее:
>
> если у вас имеется цепочка ловушек, то при выполнении функции
> CallNextHookEx(0, nCode, wParam, lParam ) вызывается следующая
> ловушка в цепочке, т.е. отпадает необходимость в передачи
> дескриптора, возвращаемого функцией SetWindowsHookEx.
где ты это выискал ? источник инф-ции ? я не вижу msdn подобных комментариев
var
hMainWnd: THandle = 0;
IsNewProcess: Boolean = True;
function SysMsgProc(code: integer; wParam, lParam : Cardinal) : LRESULT; stdcall;
begin
try
if IsNewProcess and (hMainWnd = 0) and (code = HSHELL_WINDOWCREATED) then
begin
hMainWnd := wParam; // хэндл самого первого созданного процессом окна
//Сдесь делаем с hMainWnd все что нужно
...
end;
finally
Result:=CallNextHookEx(SysHook, Code, wParam, lParam);
end;
end;
...
procedure DetermineCurrentProcess;
var
ThreadId: DWORD;
ProcessID: DWORD;
function EnumProc(hWnd: Thandle; Param: Cardinal): Boolean; stdcall;
var
PID: DWORD;
begin
Result := True;
if (GetWindowThreadProcessId(hWnd, PID) = ThreadId) and (PID = ProcessID) then
begin
IsNewProcess := False; //существует по кр.мере одно top-level-окно, созданное осн.код.потоком тек.процесса, т.е. тек.процесс GUI-приложения - не новый, а уже работающий (нас не интересующий)
Result := False;
end;
end;
begin
ThreadId := GetCurrentThreadId;
ProcessId := GetCurrentProcessId;
EnumWindows(@EnumProc, 0);
end;
...
procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
OpenGlobalData;
DetermineCurrentProcess;
end;
DLL_PROCESS_DETACH: CloseGlobalData;
end;
end;
← →
Piople (2003-11-24 10:17) [27]Об это я прочитал в статье которая лежит здесь, на мастаке.
И две процедуры которые вы мне дали, нижние, они зачем, что они делают?
← →
Piople (2003-11-24 10:41) [28]Если можно непосредственно листинг
← →
Digitman (2003-11-24 12:12) [29]ф-ция DetermineCurrentProcess вызывается на стадии иниц-ции экз-ра хук-ДЛЛ и определяет:
- внедряется ли текущий экз-р в уже существующий процесс (который уже создал хотя бы одно окно верхнего уровня, читай - самое первое создаваемое им окно и есть главное); поскольку гл.окно уже создано, хендл его никогда уже не будет фигурировать в SysMsgProc() с code = HSHELL_WINDOWCREATED
- внедряется ли текущий экз-р в новый процесс, только что стартованный системой , точнее - идет его инициализация; ни одно окно еще не создано, поэтому хэндл окна, фигурирующий в первом же SysMsgProc() с code = HSHELL_WINDOWCREATED можно считать главным
← →
Piople (2003-11-25 06:45) [30]Извените пожалуйсто за предыдущие 2-а коментария, затупил не подумав :(
Разобрался DetermineCurrentProcess копает в памяти и ищет первое верхнее окно, а чтобы оно его искало каждый раз при старте нового приложения его внедряют в DLLEntryPoint. Да и у вас небольшая опечатка в фильтре
result"у должен присваиваться:
Result := CallNextHookEx( GlobalData^.SysHook, Code, wParam, lParam);
А у вас:
Result := CallNextHookEx( SysHook, Code, wParam, lParam);
Забыли что мы используем CreateFileMapping, MapViewOfFile и UnmapViewOfFile.
Но это не столь важно, проблема в том что мы отлавливаем окно до того как оно прорисовалось, поэтому не получается то что мне нужно, вот весь листинг DLL"ки попробуйте откампилить, ну и соответственно установите его увидите что получится, если неохото, то получится следующее: после запуска вместо формы будет плавно появлятся черный экран и только после CallNextHookEx
окно прорисуется. Ну и сам листинг, для тех кому не лень :)))
library hook_dll;
uses
Windows,
Messages,
Forms, SysUtils;
const
MMFName: PChar = "MyMMF"; // имя объекта файлового отображения
{структура, поля которой будут отображены в файл подкачки}
type
PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = packed record
SysHook: HWND; // дескриптор установленной ловушки
end;
var
GlobalData: PGlobalDLLData;
MMFHandle: THandle;
hMainWnd: THandle = 0;
IsNewProcess: Boolean = True;
SetLayeredWindowAttributes: function(Hwnd: THandle; crKey: COLORREF; bAlpha: Byte; dwFlags: DWORD): Boolean; stdcall;
{Фильтр}
function SysMsgProc(code : integer; wParam : word; lParam : longint) : longint; stdcall;
var
LibHandle: THandle;
I : Integer;
begin
try
if IsNewProcess and (hMainWnd = 0) and (code = HSHELL_WINDOWCREATED) then
begin
hMainWnd := wParam;
//---cut--- эта часть отвечает за плавное появление
SetWindowLong(hMainWnd, GWL_EXSTYLE, GetWindowLong(hMainWnd, GWL_EXSTYLE) or WS_EX_LAYERED);
{гребем ее из USER32.DLL}
LibHandle := LoadLibrary("USER32.DLL");
if LibHandle <= 32 then Exit;
@SetLayeredWindowAttributes := GetProcAddress(LibHandle,"SetLayeredWindowAttributes");
if not Assigned(SetLayeredWindowAttributes) then
begin
FreeLibrary(LibHandle);
Exit;
end;
for i := 0 to 250 do
SetLayeredWindowAttributes(hMainWnd, 0, i, LWA_ALPHA);
FreeLibrary(LibHandle);
//---cut--- здесь заканчивается :)
end;
finally
Result:=CallNextHookEx(GlobalData^.SysHook, Code, wParam, lParam);
end;
end;
{Процедура установки HOOK-а}
procedure hook(switch : Boolean) export; stdcall;
begin
if switch=true then
begin
GlobalData^.SysHook := SetWindowsHookEx(WH_SHELL, @SysMsgProc, HInstance, 0);
if GlobalData^.SysHook <> 0 then
MessageBox(0, "HOOK установлен !", "Message", 0)
else
MessageBox(0, "HOOK установить не удалось !", "Error Message", 0);
end
else
begin
if UnhookWindowsHookEx(GlobalData^.SysHook) then
MessageBox(0, "HOOK снят !", "Message", 0)
else
MessageBox(0, "HOOK снять не удалось !", "Error Message", 0);
end;
end;
procedure OpenGlobalData();
begin
{получаем объект файлового отображения}
MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TGlobalDLLData), MMFName);
if MMFHandle = 0 then
MessageBox(0, "Низя создать FileMapping", "Error Message", 0);
{отображаем глобальные данные на АП вызывающего процесса и получаем указатель
на начало выделенного пространства}
GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TGlobalDLLData));
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, "Низя заюзать MapViewOfFile", "Error Message", 0);
end;
end;
procedure CloseGlobalData();
begin
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;
procedure DetermineCurrentProcess;
var
ThreadId: DWORD;
ProcessID: DWORD;
function EnumProc(hWnd: Thandle; Param: Cardinal): Boolean; stdcall;
var
PID: DWORD;
begin
Result := True;
if (GetWindowThreadProcessId(hWnd, PID) = ThreadId) and (PID = ProcessID) then
begin
IsNewProcess := False; //существует по кр.мере одно top-level-окно, созданное осн.код.потоком тек.процесса, т.е. тек.процесс GUI-приложения - не новый, а уже работающий (нас не интересующий)
Result := False;
end;
end;
begin
ThreadId := GetCurrentThreadId;
ProcessId := GetCurrentProcessId;
EnumWindows(@EnumProc, 0);
end;
procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
OpenGlobalData;
DetermineCurrentProcess;
end;
DLL_PROCESS_DETACH: CloseGlobalData;
end;
end;
exports hook;
begin
{назначим поцедуру переменной DLLProc}
DLLProc:= @DLLEntryPoint;
{вызываем назначенную процедуру для отражения факта присоединения данной библиотеки к процессу}
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
С уважение piople.
← →
Digitman (2003-11-25 08:52) [31]разумеется, при такой логике ты не получишь ожидаемого эффекта.
в фильтре SysMsgProc() для code = HSHELL_WINDOWCREATED тебе нужно всего лишь зафиксировать хэндл только что созданного окна, установить для него стиль WS_EX_LAYERED и установить layer-атрибут этого окна с параметром i = 0
в ходе обработки DLL_PROCESS_ATTACH тебе необходимо запустить доп.код.поток, которому фильтр SysMsgProc() после фиксации hMainWnd будет передавать этот "пойманный" хэндл параметром
твой код.поток создает таймер с нужным тебе периодом смены альфа-параметра, в обработчике которого в окно hMainWnd вызовом SendMessage() будет посылаться некое предопределенное сообщение X.
кроме SysMsgProc() ты должен установить хук на WH_CALLWNDPROC, в обработчике которого ты должен фильтровать сообщения X, посланные твоим код.потоком окну hMainWnd, и по факту обнаружения таковых менять layer-атрибут окна hMainWnd на следующий по инкременту (у тебя это должно произойти 250 раз, судя по коду)
примерные условия завершения процедуры твоего код.потока :
- достигнуто макс.значения альфа;
- фильтр в SysMsgProc() обнаружил событие HSHELL_WINDOWDESTROYED, т.е. hMainWnd разрушено;
- потоком получено сообщение QM_QUIT
- факт вызова обработчика DLL_PROCESS_DETACH как следствие выгрузки хук-ДЛЛ перед завершением тек.процесса
кр.того неразумно многократно грузить/выгружать USER32.DLL в фильтрах, все же это длительная и сложная операция для системы
достаточно загрузить эту библ-ку в DLL_PROCESS_ATTACH и тут же получить адрес нужной ф-ции, а выгрузить в DLL_PROCESS_DETACH.
вот так я себе это вижу
← →
Piople (2003-11-25 09:17) [32]
> в фильтре SysMsgProc() для code = HSHELL_WINDOWCREATED тебе
> нужно всего лишь зафиксировать хэндл только что созданного
> окна, установить для него стиль WS_EX_LAYERED и установить
> layer-атрибут этого окна с параметром i = 0
Это ясно
> в ходе обработки DLL_PROCESS_ATTACH тебе необходимо запустить
> доп.код.поток, которому фильтр SysMsgProc() после фиксации
> hMainWnd будет передавать этот "пойманный" хэндл параметром
Ну хэндл, я так думаю, можно передать описав переменную в глобал варе, присвоить ей хэндл ну и передать, но как реализовать доп.код.поток, т.е.
procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
OpenGlobalData;
DetermineCurrentProcess;
//Здесь передаем хэндл и создоем доп.код.поток
end;
DLL_PROCESS_DETACH: CloseGlobalData;
end;
end;
Я правильно понял? Пока остановлюсь здесь, а то все не пойму :)
← →
Digitman (2003-11-25 09:27) [33]
procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
case dwReason of
DLL_PROCESS_ATTACH:
begin
OpenGlobalData;
DetermineCurrentProcess;
//Здесь создАем доп.код.поток, при условии что IsNewProcess = True, с этого момента код.поток ждет, когда ему будет передан хэндл реально созданного окна
// никакого хэндла ему, потоку, здесь мы передать еще не можем
// ибо он нам еще неизвестен (известен он станет лишь когда фильтр в SysMsgproc() отработает и "поймает" момент создания гл.окна)
end;
DLL_PROCESS_DETACH:
//здесь, если IsNewProcess = True и код.поток еще работает, даем ему команду на завершение
CloseGlobalData;
end;
end;
← →
Piople (2003-11-25 09:34) [34]Т.е. первем будет фильтр, а только потом DLLEntryPoint?
← →
Digitman (2003-11-25 09:42) [35]
> Т.е. первем будет фильтр, а только потом DLLEntryPoint?
с какой стати ?
прежде чем любой библиотечный код получит управление, библиотека д.б. загружена и инициализирована
DllEntryPoint() как раз и вызывается в ходе инициализации библиотеки, и пока код DllEntryPoint() не отработает, никакой другой код библиотеки не м.б. вызван никем/ничем и не получит управление.
т.е. сначала ПОЛНОСТЬЮ отработает процедура DllEntryPoint() , а уж затем следует ожидать срабатывание и исполнение фильтр-функций
← →
Piople (2003-11-25 09:49) [36]Ну тогда я не понимаю как передать хэндл, ведь он уже отработает когда у нас появится хэндл?
← →
Digitman (2003-11-25 10:17) [37]
> ведь он уже отработает
кто "отработает" ? DllEntryPoint() что ли ?
ну и что ? ты стартуешь в ней код.поток, коиторый будет с этого момента работать параллельно и независимо ни от чего, ожидая, когда ему каким-либо способом передадут хэндл окна для работы с этим хэндлом
когда в какой-то момент времени возникнет событие HSHELL_WINDOWCREATED и станет известен хэндл нужного тебе окна, ты в обработчике SysMsgProc() просто передашь работающему код.потоку этот хэндл, и далее твой код.поток уже сам будет работать с этим хэндлом, посылая по таймеру сообщение окну, хэндл которого он получил
передача же параметров код.потоку - тема отдельного обсуждения
так что бросай на время свои "хуки" и займись всесторонним изучением всевозможных принципов и механизмов передачи параметров одним код.потоком другому код.потоку (а так же межпоточной синхронизации).. без твердого знания и понимания этих принципов и механизмов далее двигаться нет смысла - будешь тыкаться как слепой котенок, ничерта не понимая в происходящем
← →
Piople (2003-11-27 07:25) [38]А ну все понял, создаем поток который просто будет крутиться в памяти и ждать хэндла. Но насчет самих потоков у меня есть книженция, но там так стремно все описано, нет ли ссылочки?
← →
Digitman (2003-11-27 08:26) [39]
> но там так стремно
"стремно" - это как ?
нет таких слов в алгоритмике и программировании
будь любезен изъясняться не на уровне детсада, а четко и конкретно : что тебе непонятно и/или вызывает сомнения
← →
Piople (2003-11-27 08:30) [40]Удалено модератором
Примечание: Offtopic
Страницы: 1 2 вся ветка
Форум: "WinAPI";
Текущий архив: 2004.02.02;
Скачать: [xml.tar.bz2];
Память: 0.6 MB
Время: 0.009 c