Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
4-2421
Sanad
2003-11-21 08:24
2004.02.02
Перехват принтера


6-2267
favorit_
2003-11-28 00:09
2004.02.02
Изменение настроек IE


1-2231
man
2004-01-19 19:49
2004.02.02
как получить список процессов, которые используют данный файл


1-2061
Oyster
2004-01-18 10:04
2004.02.02
Глюки с русскими буквами в консольном приложении


1-2213
Oyster
2004-01-19 13:31
2004.02.02
Что делать с ресурсами программы?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский