Форум: "Основная";
Текущий архив: 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 в CreateDevice7Callbacklibrary 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