Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Сервис. DLL. Не работают функции экспортируемые из DLL. Хуки... [D7, WinXP]


MInd_f ©   (2007-06-21 21:19:00) 

Написал DLL. В ней нужные мне функции (пока только хук на клавиатуру - возможно корявый, но в обычной(не сервисе) программе работает коряво, но планирую еще несколько функций) Вроде все сделал правильно, сервис работает. И вроде функции из DLL все же вызываются, но хук не работает. Не понимаю.
Проверял с обычной програмой - работает отлично.

Сообствено вопросы:
1. Может есть какие-нить особенности в реалезации на сервисе?
2. Обязательно ли в DLL так называемы EntryPoint? И без него работает.
3. Ниже код DLL и сервиса.. если есть какие-нить очевидные ошибки или просто замечания укажыте пожалуста


===============DLL=============
library SpyDll;

uses
 SysUtils,Messages,Windows;

var
 HookHandle: hHook;
 MainProg: HWND;

function KeyboardProc(code: integer; wParam: word; lParam: longint): longint; stdcall;
var
 AppWnd: HWND;
 //Buf: array [0..254] of Char;
 //kbState: TKeyboardState;
begin
 if code < 0 then
 begin
   CallNextHookEx(HookHandle, Code, wParam, lParam);
   Result:=0;
   Exit;
 end;
 if (((lParam and KF_UP)=0) and (wParam>=65) and (wParam<=90)) OR
     (((lParam and KF_UP)=0) and (wParam=VK_SPACE)) then
  begin
    AppWnd:=GetForegroundWindow();
    GetKeyboardState(kbState);
    //ToUnicode(wParam,lParam,kbState,@Buf,255, 0);
    MessageBox(0, PChar('In '+ IntToStr(AppWnd) +'  wParam = ' + intToStr(wParam) + ', lparam = ' +  intToStr(wParam)+ '   =   ' + Buf), 'Message from SpyDll.dll', MB_OK+MB_SERVICE_NOTIFICATION);
  end;
 Result:=CallNextHookEx(HookHandle, Code, wParam, lParam);
end;

procedure Set_Hook(MainProg:HWND); export; stdcall;
begin
 SpyDll.MainProg:=MainProg;
 //MessageBox(0, 'Hook instaled.', 'Message from SpyDll.dll', MB_OK+MB_SERVICE_NOTIFICATION);
 HookHandle:=SetWindowsHookEx(WH_KEYBOARD, @KeyboardProc, HInstance, 0);
end;

procedure Del_Hook; export; stdcall;
begin
 //MessageBox(0, 'Hook deleted.', 'Message from SpyDll.dll', MB_OK);
 UnhookWindowsHookEx(HookHandle);
end;

//procedure DLLEntryPoint(dwReason: DWord); stdcall;
//begin
//  if dwReason=DLL_PROCESS_DETACH then Del_Hook;
//end;

exports Set_Hook,Del_Hook;

{$R *.res}

begin
//DLLProc:=@DLLEntryPoint;
end.

=====================service=====================
unit mainUnit;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs;

type
 TSpyServ = class(TService)
 procedure ServiceExecute(Sender: TService);
 procedure ServiceStop(Sender: TService; var Stopped: Boolean);
 procedure ServiceStart(Sender: TService; var Started: Boolean);
 private
   { Private declarations }
 public
   function GetServiceController: TServiceController; override;
   { Public declarations }
 end;

var
 SpyServ: TSpyServ;
 logOnOffPath:String;

 procedure Set_Hook(MainProg:HWND); stdcall; external 'SpyDll.dll';
 procedure Del_Hook; stdcall; external 'SpyDll.dll';
 
implementation

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
 SpyServ.Controller(CtrlCode);
end;

function TSpyServ.GetServiceController: TServiceController;
begin
 Result := ServiceController;
end;

procedure TSpyServ.ServiceExecute(Sender: TService);
begin
 Set_Hook(ServiceThread.Handle);
 while not terminated do
   begin
   //MessageBox(0, 'Service Execited', 'Message from UserSpy.exe', MB_OK+MB_SERVICE_NOTIFICATION);
   ServiceThread.ProcessRequests(False);
   end;
 Del_Hook;
end;

procedure TSpyServ.ServiceStart(Sender: TService; var Started: Boolean);
 Started:=True;
end;

procedure TSpyServ.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
 Stopped:=True;
end;

end.

и еще вопрос как с помощью функции ToUnicode, перехватив сообщение перевести его в символ?

ЗЫ. Разобрался бы сам, но время поджимает. Нужна помощь.


MInd_f   (2007-06-24 13:20:00) [1]

тот же хук. та же DLL. **и не важно что корявый.. )

вопрос:
почему функция KeyboardProcвызываеться два раза, хотя нажатие было одно?..
как выснить что было и WM_KEYDOWNи WM_KEYUP, и тогда только обработать, а иначе вызвать следующий хук?


Cj   (2007-06-22 04:37:00) [2]


> видимо придется обойтись без хука.. а сделать то же с помощью
> GetAsyncKeyState ..


советую не этой а просто GetKeyState пользоваться, тк некоторые проги и игры у меня засекали ее испорльзование и отказывались работать, типа "Тренер запущен" или другое.

Кстати реализацию ее использования можешь посмотреть в моем компоненте, или лучше используй его самого:
http://code.progler.ru/get/439


MInd_f   (2007-06-21 23:13:00) [3]

> Инс   (21.06.07 23:12) [16]
спасибо. *буду знать.


MInd_f   (2007-06-21 23:12:00) [4]

видимо придется обойтись без хука.. а сделать то же с помощью GetAsyncKeyState..

хотелось бы подведения итога: как сделать хук в сервисе? *хотя бы для справки, по пунктам*

и еще пример с функцией ToUnicode, если возможно.
int ToUnicode(UINT wVirtKey,
   UINT wScanCode,
   const PBYTE lpKeyState,
   LPWSTR pwszBuff,
   int cchBuff,
   UINT wFlags
);

непонятно почему необходим буфер.. т.е. почему возможен не один символ, а несколько. *может я не особо вник в описание функции.. не знаю.


Инс   (2007-06-21 23:12:00) [5]

Так, к сведению автора... Параметр wParam имеет тип DWord, а времена, когда он был Word давно канули в лету...


Eraser   (2007-06-21 22:54:00) [6]

> [14] Leonid Troyanovsky ©   (21.06.07 22:39)

ну в другой терм. сессии вообще хук установить нельзя из текущего приложения или сервиса..


Leonid Troyanovsky   (2007-06-21 22:39:00) [7]


> Eraser ©   (21.06.07 22:30) [11]

> не будет, если права просто наследовать.. или я что-то недопонял?
>  )

Не знаю, что ты, а я недопонял, причем тут терм. сессии :)

--
Regards, LVT.


Eraser   (2007-06-21 22:39:00) [8]

> [12] Leonid Troyanovsky ©   (21.06.07 22:34)

да да да.. и точно, надо в каждом десктопе ставить.. и подзабыл уже )

> [10] MInd_f ©   (21.06.07 22:28)

тогда нужно в цикле или по таймеру проверять OpenInputDesktop, к примеру.. и если десктоп поменялся - ставить в нем хук ))


Leonid Troyanovsky   (2007-06-21 22:34:00) [9]


> MInd_f ©   (21.06.07 22:27) [9]

> т.е. хотите сказать, что такой хук в сервисе работать не
> будет? хмм...

Это не я, а msdn: SetWindowsHookEx Function

These events are associated either with a specific thread or with all threads in the same desktop as the calling thread

--
Regards, LVT.


Eraser   (2007-06-21 22:30:00) [10]

> [8] Leonid Troyanovsky ©   (21.06.07 22:26)

так оно итак вроде будет на всех десктопах текущей терм. сессии.. только по-умолчанию доступа к MMF у обычных приложений не будет, если права просто наследовать.. или я что-то недопонял? )


MInd_f   (2007-06-21 22:28:00) [11]

> Eraser ©   (21.06.07 22:22) [6]
спасибо. буду разбираться. )


MInd_f   (2007-06-21 22:27:00) [12]

> Leonid Troyanovsky ©   (21.06.07 22:08) [5]
т.е. хотите сказать, что такой хук в сервисе работать не будет? хмм...
если правильно понял, на десктопе обычного приложения клавиатурный ввод отлавливаться будет, а в службе нет..

тогда какой выход посоветуете? если с MMF, то как сообственно разрешить туда запись для сервиса?


Leonid Troyanovsky   (2007-06-21 22:26:00) [13]


> Eraser ©   (21.06.07 22:23) [7]

> > И в-третьих, надо выяснить, откуда, собс-но, берется
> > клавиатурный ввод на десктопе сервиса.
>
> а это еще зачем? )

Чтобы перехватить в зародыше :)

--
Regards, LVT.


Eraser   (2007-06-21 22:23:00) [14]

> [5] Leonid Troyanovsky ©   (21.06.07 22:08)


> И в-третьих, надо выяснить, откуда, собс-но, берется
> клавиатурный ввод на десктопе сервиса.

а это еще зачем? )


Eraser   (2007-06-21 22:22:00) [15]

> [4] MInd_f ©   (21.06.07 21:50)


> на счет хука согласен, что не коректно, но работает ведь.

очень странно, что работает.. не должен по идее )

> да и к тому же разрешить программно запись в MMF непривелегированным
> пользователям.. это возможно?

возможно даже, что с "записью" я погорячился, может хватить только чтения.

> да и к тому же разрешить программно запись в MMF непривелегированным
> пользователям.. это возможно?

примерно так
procedure OpenInputSharedData;
var
 size: integer;
 pSD: PSECURITY_DESCRIPTOR;
 sa: SECURITY_ATTRIBUTES;
begin
 try
   pSD := PSECURITY_DESCRIPTOR(LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH));
   if not InitializeSecurityDescriptor (pSD,
      SECURITY_DESCRIPTOR_REVISION) then
   begin
     LocalFree(HLOCAL(pSD));
     Exit;
   end;
   // Добавить NULL ACL к дескриптору безопасности.
   if not SetSecurityDescriptorDacl(pSD, true, nil, false) then begin
     LocalFree(HLOCAL(pSD));
     Exit;
   end;
   sa.nLength := sizeof(sa);
   sa.lpSecurityDescriptor := pSD;
   sa.bInheritHandle := true;

   size := sizeof(TGlobalInputDLLData);
   MapHandleInput := CreateFileMapping(DWord(-1),
     @sa,
     PAGE_READWRITE,
     0,
     size,
     DllInputMapFileName);
   if MapHandleInput = 0 then
     Exit;

   InputGlobalData := MapViewOfFile(MapHandleInput,
     FILE_MAP_ALL_ACCESS,
     0,
     0,
     size);
   if InputGlobalData = nil then
     Exit;
   bIsInputGlobalDataExists := true;
 except
 end;
end;

procedure CloseInputSharedData;
begin
 if bIsInputGlobalDataExists then
 begin
   UnmapViewOfFile(InputGlobalData);
   CloseHandle(MapHandleInput);
   bIsInputGlobalDataExists := false;
 end;
end;

procedure DLLEntryPoint(dwReason: DWord);
begin
 case dwReason of
   DLL_PROCESS_ATTACH:
     begin
       OpenInputSharedData;
       DefaultOvrIndex;
       OpenSharedData;
     end;
   DLL_PROCESS_DETACH:
     begin
       CloseInputSharedData;
       UnCapt;
       ClosePictureData;
       CloseSharedData;
     end;
 end;
end;

кусок из рабочего проекта, требует доработки.. лишнее/недостающее подправите ))


Leonid Troyanovsky   (2007-06-21 22:08:00) [16]


> Eraser ©   (21.06.07 21:38) [3]


И в-третьих, надо выяснить, откуда, собс-но, берется
клавиатурный ввод на десктопе сервиса.

--
Regards, LVT.


MInd_f   (2007-06-21 21:50:00) [17]

> Eraser ©   (21.06.07 21:38) [3]
на счет хука согласен, что не коректно, но работает ведь. зачем тогда париться с MMF? **для меня в данный момент не столько важна коректность или "правильность" - сколько работоспособность. Еще бы разобраться как виртуальный код в unicode перевести.
да и к тому же разрешить программно запись в MMF непривелегированным пользователям.. это возможно?


Eraser   (2007-06-21 21:38:00) [18]

> [0] MInd_f ©   (21.06.07 21:19)

во-первых, хук неправильно написан, для хранения HookHandle нужно использовать, к примеру, MMF. Во-вторых, чтобы хук работал в сервисе нормально, нужно разрешить запись в MMF непривелегированным пользователям, но делать это надо осторожно, чтобы не получился локальный бэкдор.


MInd_f   (2007-06-21 21:21:00) [19]


> но в обычной(не сервисе) программе работает коряво

тьфу.. редактировать темы нельзя?. эхх.. в обычной проге работает норм.


MInd_f   (2007-06-21 21:21:00) [20]


> но в обычной(не сервисе) программе работает коряво

тьфу.. редактировать темы нельзя?. эхх.. в обычной проге работает норм.


Наверх

Титульная страница Поиск, карта сайта Написать письмо