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

Вниз

Как подменить COM?   Найти похожие ветки 

 
@!!ex ©   (2008-09-25 18:16) [0]

Программа создает D3D COM объект.
Нужно перехватить нажатия клавиш и подменять их своими...
как это можно сделать?


 
Поросенок Винни-Пух ©   (2008-09-25 18:18) [1]

может просто подменить гуиды?


 
Sapersky   (2008-09-25 18:51) [2]

Если нужен перехват методов COM-интерфейсов, то в библиотеке madCodeHook есть пример с Direct3D.


 
@!!ex ©   (2008-09-25 19:18) [3]

> [2] Sapersky   (25.09.08 18:51)

Спасибо!

P.S.
Я ошибся. не D3D, DI конечно.


 
@!!ex ©   (2008-09-25 21:04) [4]

> [2] Sapersky   (25.09.08 18:51)

Пример есть, интересный...
только там для перекрытия методов используется их позиция в объекте... а как ее узнать-то?


 
МистерТ   (2008-09-26 11:57) [5]

Помнится D3D и DI не являются полноценными СОМ-объектами, в том плане, что они создаются вызовом CreateInterface() непосредственно из библиотек d3d.dll и dinput.dll (не учитываю версии библиотек), а не через стандартные СОМ-методы.
Соответственно самый простой способ - реализация подмены этих библиотек своими - прокси библиотеками.


 
Sapersky   (2008-09-26 14:34) [6]

только там для перекрытия методов используется их позиция в объекте

Позиция в интерфейсе. Cмотрим заголовки D3D/DInput и отсчитываем с начала, или относительно индексов тех методов, которые используются в примере (если с начала - вроде нужно ещё 3 добавить, на AddRef, Release и QueryInterface).


 
@!!ex ©   (2008-09-27 12:06) [7]

var
 IID_IDirectInput7A       : TGUID = "{9A4CB684-236D-11D3-8E9D-00C04F6844AE}";
function DirectInputCreateExCallback(hinst : THandle; dwVersion: DWORD; const riidltf: TGUID; out ppvOut:pointer; punkOuter: IUnknown): dword; stdcall;
var
 di:IUnknown;
begin
 result := DirectInputCreateExNext(hinst, dwVersion, riidltf,ppvOut,punkOuter);
   if @CreateDevice7Next = nil then begin
     IUnknown(ppvOut^).QueryInterface(IID_IDirectInput7A, di);
     HookCode(GetInterfaceMethod(di, 4), @CreateDevice7Callback, @CreateDevice7Next)
   end else
     RenewHook(@CreateDevice7Next);
end;

function HookDI : boolean;
begin
 result := HookAPI("dinput_orig.dll", "DirectInputCreateEx", @DirectInputCreateExCallback, @DirectInputCreateExNext);
end;


Падает на строчке:
IUnknown(ppvOut^).QueryInterface(IID_IDirectInput7A, di);

Memory access violation


 
Sapersky   (2008-09-27 20:12) [8]

QueryInterface там не нужен.
Он используется только в некоторых конкретных случаях, в частности при инициализации D3D7 (Мелкософту когда-то казалось, что "типа клёво" получать таким образом более функциональный интерфейс из менее функционального). А DirectInputCreateEx сразу выдаёт IDirectInput7, ничего Query"ть там не надо.
Судя по примерам с DInput, последовательность хуков должна быть такая:
DirectInputCreate/DirectInputCreateEx/DirectInput8Create (для разных версий DI)
IDirectInput.CreateDevice(GUID_SysKeyboard, ...)
IDirectInputDevice.GetDeviceState
или, если было IDirectInputDevice.SetProperty(DIPROP_BUFFERSIZE, ...) -
IDirectInputDevice.GetDeviceData (буферизованный ввод).


 
@!!ex ©   (2008-09-27 20:27) [9]

> [8] Sapersky   (27.09.08 20:12)

Я так и думал. Сначала сделал обычным способом. Потом решил попробовать так...

Вот код всей либы... падает на строчке begin в CreateDevice7Callback

library dinput;
uses Windows, madCodeHook,
    unitOlddinput in "unitOlddinput.pas";

procedure DirectInputCreateEx(); stdcall;
asm
 jmp unitOlddinput.DirectInputCreateEx
end;

exports
 DirectInputCreateEx;

function GetInterfaceMethod(const intf; methodIndex: dword) : pointer;
begin
 result := pointer(pointer(dword(pointer(intf)^) + methodIndex * 4)^);
end;

// ***************************************************************************
// DirectInput

var
 DirectInputCreateExNext :function (hinst : THandle; dwVersion: DWORD; const riidltf: TGUID; out ppvOut; punkOuter: IUnknown): dword; stdcall;
 CreateDevice7Next:function (const rguid: TGUID; out lplpDirectInputDevice: pointer; pUnkOuter: IUnknown): dword; stdcall;
 GetDeviceData7Next:function (cbObjectData: DWORD; rgdod: pointer; out pdwInOut: DWORD; dwFlags: DWORD): dword; stdcall;

function GetDeviceData7CallBack(cbObjectData: DWORD; rgdod: pointer; out pdwInOut: DWORD; dwFlags: DWORD): dword; stdcall;
begin
 Result:=GetDeviceData7Next(cbObjectData,rgdod,pdwInOut,dwFlags);
end;

function CreateDevice7Callback(const rguid: TGUID; out lplpDirectInputDevice: pointer; pUnkOuter: IUnknown) : dword; stdcall;
begin
 result := CreateDevice7Next(rguid,lplpDirectInputDevice,pUnkOuter);
 if @GetDeviceData7Next = nil then
   HookCode(GetInterfaceMethod(lplpDirectInputDevice^, 11), @GetDeviceData7CallBack, @GetDeviceData7Next)
 else
   RenewHook(@GetDeviceData7Next);
end;

function DirectInputCreateExCallback(hinst : THandle; dwVersion: DWORD; const riidltf: TGUID; out ppvOut:pointer; punkOuter: IUnknown): dword; stdcall;
begin
 result := DirectInputCreateExNext(hinst, dwVersion, riidltf,ppvOut,punkOuter);
   if @CreateDevice7Next = nil then begin
     HookCode(GetInterfaceMethod(ppvOut, 4), @CreateDevice7Callback, @CreateDevice7Next)
   end else
     RenewHook(@CreateDevice7Next);
end;

function HookDI : boolean;
begin
 result := HookAPI("dinput_orig.dll", "DirectInputCreateEx", @DirectInputCreateExCallback, @DirectInputCreateExNext);
end;

// ***************************************************************************

begin
 HookDI;
end.


 
Sapersky   (2008-09-28 12:45) [10]

function CreateDevice7Callback(const rguid: TGUID; out lplpDirectInputDevice: pointer; pUnkOuter: IUnknown) : dword; stdcall;

Когда мы имитируем метод объекта/интерфейса обычной процедурой, нужно добавлять первый параметр - self. Смотри внимательнее пример с D3D...
У DirectInput7, кстати, есть ещё CreateDeviceEx, в примерах из документации к SDK используют именно его.


 
@!!ex ©   (2008-09-28 13:14) [11]

сделал:
function CreateDeviceEx7Callback(self:pointer;const rguid, riid: TGUID; out pvOut: Pointer; pUnkOuter: IUnknown) : dword; stdcall;
begin
 result := CreateDeviceEx7Next(self,rguid, riid,pvOut,pUnkOuter);
 if @GetDeviceData7Next = nil then
   HookCode(GetInterfaceMethod(pvOut^, 11), @GetDeviceData7CallBack, @GetDeviceData7Next)
 else
   RenewHook(@GetDeviceData7Next);
end;

function DirectInputCreateExCallback(hinst : THandle; dwVersion: DWORD; const riidltf: TGUID; out ppvOut:pointer; punkOuter: IUnknown): dword; stdcall;
begin
 result := DirectInputCreateExNext(hinst, dwVersion, riidltf,ppvOut,punkOuter);
   if @CreateDeviceEx7Next = nil then begin
     HookCode(GetInterfaceMethod(ppvOut, 4), @CreateDeviceEx7Callback, @CreateDeviceEx7Next)
   end else
     RenewHook(@CreateDeviceEx7Next);
end;

Падает также.в том же месте..


 
@!!ex ©   (2008-09-28 13:26) [12]

на пост выше код не правильный.
HookCode(GetInterfaceMethod(ppvOut, 10), @CreateDeviceEx7Callback, @CreateDeviceEx7Next)

Но тогда CreateDeviceEx7Callback  никогда не вызывается.
Если делаю 4 и:
function CreateDevice7Callback(self:pointer;const rguid: TGUID; out pvOut: Pointer; pUnkOuter: IUnknown) : dword; stdcall;
begin
 result := CreateDevice7Next(self,rguid,pvOut,pUnkOuter);
 if @GetDeviceData7Next = nil then
   HookCode(GetInterfaceMethod(pvOut^, 11), @GetDeviceData7CallBack, @GetDeviceData7Next)
 else
   RenewHook(@GetDeviceData7Next);
end;

то опять падает на begin.


 
Sapersky   (2008-09-28 13:50) [13]

Вероятно, IDirectInput.CreateDevice - номер 3.
Во всяком случае, в D3D7 IDirect3D7.CreateDevice - второй по счёту метод, а хук ставится на 4-й.


 
@!!ex ©   (2008-09-28 14:09) [14]

если ставлю 3 - метод никогда не вызывается...
пипец какой-то...


 
@!!ex ©   (2008-09-28 14:15) [15]

ага. используется CreateDeviceEx как ты и говорил. только его позиция не 10, а 9.


 
@!!ex ©   (2008-09-28 14:44) [16]

Сделал вот так:
var
 DirectInputCreateExNext :function (hinst : THandle; dwVersion: DWORD; const riidltf: TGUID; out ppvOut; punkOuter: IUnknown): dword; stdcall;
 CreateDeviceEx7Next:function (self:pointer;const rguid,rii: TGUID; out pvOut: Pointer; pUnkOuter: IUnknown): dword; stdcall;
 GetDeviceData7Next:function (self:pointer;cbObjectData: DWORD; rgdod: pointer; out pdwInOut: DWORD; dwFlags: DWORD): dword; stdcall;
 GetDeviceState7Next:function (self:pointer; cbData: DWORD; lpvData: Pointer): dword; stdcall;
 SetEventNotification7Next:function (self:pointer; hEvent: THandle): HResult; stdcall;

 GUID_SysKeyboard    : TGUID = "{6F1D2B61-D5A0-11CF-BFC7-444553540000}";

function GetDeviceData7CallBack(self:pointer; cbObjectData: DWORD; rgdod: pointer; out pdwInOut: DWORD; dwFlags: DWORD): dword; stdcall;
begin
 Result:=GetDeviceData7Next(self,cbObjectData,rgdod,pdwInOut,dwFlags);
end;

function GetDeviceState7Callback (self:pointer;cbData: DWORD; lpvData: Pointer): dword; stdcall;
begin
 Result:=GetDeviceState7Next(self,cbData,lpvData);
end;

function SetEventNotification7Callback(self:pointer; hEvent: THandle): HResult; stdcall;
begin

end;

Function CompareMemory(s1,s2:Pointer; size:integer):boolean;
var
 pByte1,pByte2:PByte;
 i:integer;
begin
 Result:=true;
 pByte1:=s1;
 pByte2:=s2;
 for i := 0 to size - 1 do begin
   if pByte1^<>pByte2^ then begin
     Result:=false;
     Exit;
   end;
   inc(pByte1);
   inc(pByte2);
 end;
   
end;

function CreateDeviceEx7Callback(self:pointer;const rguid,rii: TGUID; out pvOut: Pointer; pUnkOuter: IUnknown) : dword; stdcall;
begin
 result := CreateDeviceEx7Next(self,rguid,rii,pvOut,pUnkOuter);

 if CompareMemory(@rguid,@GUID_SysKeyboard,sizeof(GUID_SysKeyboard)) then begin
   if @GetDeviceData7Next = nil then
     HookCode(GetInterfaceMethod(pvOut, 10), @GetDeviceData7CallBack, @GetDeviceData7Next)
   else
     RenewHook(@GetDeviceData7Next);

   if @GetDeviceState7Next = nil then
     HookCode(GetInterfaceMethod(pvOut, 9), @GetDeviceState7CallBack, @GetDeviceState7Next)
   else
     RenewHook(@GetDeviceState7Next);

   if @SetEventNotification7Next = nil then
     HookCode(GetInterfaceMethod(pvOut, 12), @SetEventNotification7Callback, @SetEventNotification7Next)
   else
     RenewHook(@SetEventNotification7Next);
 end;
end;

Ничего не падает, хуки ставятся, но при этом ни одна из захученных функция DirectInputDevice не вызывается...


 
Sapersky   (2008-09-28 16:20) [17]

Странно. Может, целевое приложение из-за каких-то отладочных манипуляций теряет фокус ввода? Оно нормально вообще работает?
Чтобы предотвратить потери фокуса, можно перехватить Device.SetCooperativeLevel и заменить передаваемые флаги на DISCL_NONEXCLUSIVE or DISCL_BACKGROUND.


 
@!!ex ©   (2008-09-28 16:35) [18]

Целевое приложение - игра.
Использует мышь для собственно игры и клаву для ввода имени пользователя.
Все нормально работает.
Написана на Blitz.


 
Sapersky   (2008-09-28 16:59) [19]

Ну не знаю. Может, всё-таки не через DInput оно работает. IDirectInputDevice для клавиатуры создаётся в движке по умолчанию, но фактически не используется.
Попробуй для проверки перехватить мышь. Если заработает, можно будет точно сказать, что проблема не в коде перехвата.


 
@!!ex ©   (2008-09-28 17:11) [20]

Просто все остальное я уже проверил. :))
GetAsyncKetState и KeyBoardState в ехешке даже строк таких нету...

WM_CHAR/ WM_KEYDOWN - ставил хук WH_KEYBOARD - полный игнор этого хука.

Вроде похоже, что играю юзает DI для ввода, потому что CapsLock игнорируется, а вот Shift - меняет регистр.



Страницы: 1 вся ветка

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

Наверх




Память: 0.53 MB
Время: 0.019 c
6-1186390697
Салат
2007-08-06 12:58
2009.11.08
Есть ли событие при приеме пакетов клиентом?


3-1229385486
Dem
2008-12-16 02:58
2009.11.08
ТCalendar


9-1183139502
CMOS
2007-06-29 21:51
2009.11.08
Организация OnClick у спарйта?


11-1207381883
Сашик
2008-04-05 11:51
2009.11.08
Запись в ресурсы DLL


2-1253875179
sergeii
2009-09-25 14:39
2009.11.08
Помогите с размерами форм