Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.02.02;
Скачать: CL | DM;

Вниз

Как определить запуск кокого либо приложения?   Найти похожие ветки 

 
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 вся ветка

Текущий архив: 2004.02.02;
Скачать: CL | DM;

Наверх




Память: 0.63 MB
Время: 0.029 c
1-2144
Broot
2004-01-22 05:37
2004.02.02
Pazzle - Дробление картинки


1-2097
scorpi
2004-01-20 08:26
2004.02.02
Версия программы


1-2064
pirat
2004-01-19 19:32
2004.02.02
DoubleBuffered:=true и ThemeServices : палка о двух концах ?


1-2115
Grinder
2004-01-19 00:20
2004.02.02
TextToShortcut с клавишей Win


14-2304
Murad
2004-01-12 15:21
2004.02.02
Как Закачать сайт из инета со всеми файлами и структурой