Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2009.11.08;
Скачать: [xml.tar.bz2];

Вниз

Как подменить 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.006 c
2-1253006175
Гость
2009-09-15 13:16
2009.11.08
Проверить создан ли объект


2-1253184578
vegarulez
2009-09-17 14:49
2009.11.08
Просьба не банить.


2-1253620987
kate158
2009-09-22 16:03
2009.11.08
поиск ячеек по excel файлам


2-1254033768
faiwer
2009-09-27 10:42
2009.11.08
Autosize для RichEdit


2-1253272954
Mishenka
2009-09-18 15:22
2009.11.08
Какой тип параметра выбрать для передачи Memo поля в ADOStorProc





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский