![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как подменить COM?
@!!ex © (2008-09-25 18:16:00)Программа создает D3D COM объект.
Нужно перехватить нажатия клавиш и подменять их своими...
как это можно сделать?
@!!ex (2008-09-28 17:11:00) [1]Просто все остальное я уже проверил. :))
GetAsyncKetState и KeyBoardState в ехешке даже строк таких нету...
WM_CHAR/ WM_KEYDOWN - ставил хук WH_KEYBOARD - полный игнор этого хука.
Вроде похоже, что играю юзает DI для ввода, потому что CapsLock игнорируется, а вот Shift - меняет регистр.
Sapersky (2008-09-28 16:59:00) [2]Ну не знаю. Может, всё-таки не через DInput оно работает. IDirectInputDevice для клавиатуры создаётся в движке по умолчанию, но фактически не используется.
Попробуй для проверки перехватить мышь. Если заработает, можно будет точно сказать, что проблема не в коде перехвата.
@!!ex (2008-09-28 16:35:00) [3]Целевое приложение - игра.
Использует мышь для собственно игры и клаву для ввода имени пользователя.
Все нормально работает.
Написана на Blitz.
Sapersky (2008-09-28 16:20:00) [4]Странно. Может, целевое приложение из-за каких-то отладочных манипуляций теряет фокус ввода? Оно нормально вообще работает?
Чтобы предотвратить потери фокуса, можно перехватить Device.SetCooperativeLevel и заменить передаваемые флаги на DISCL_NONEXCLUSIVE or DISCL_BACKGROUND.
@!!ex (2008-09-28 14:44:00) [5]Сделал вот так:
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 не вызывается...
@!!ex (2008-09-28 14:15:00) [6]ага. используется CreateDeviceEx как ты и говорил. только его позиция не 10, а 9.
@!!ex (2008-09-28 14:09:00) [7]если ставлю 3 - метод никогда не вызывается...
пипец какой-то...
Sapersky (2008-09-28 13:50:00) [8]Вероятно, IDirectInput.CreateDevice - номер 3.
Во всяком случае, в D3D7 IDirect3D7.CreateDevice - второй по счёту метод, а хук ставится на 4-й.
@!!ex (2008-09-28 13:26:00) [9]на пост выше код не правильный.
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.
@!!ex (2008-09-28 13:14:00) [10]сделал:
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;
Падает также.в том же месте..
Sapersky (2008-09-28 12:45:00) [11]function CreateDevice7Callback(const rguid: TGUID; out lplpDirectInputDevice: pointer; pUnkOuter: IUnknown) : dword; stdcall;
Когда мы имитируем метод объекта/интерфейса обычной процедурой, нужно добавлять первый параметр - self. Смотри внимательнее пример с D3D...
У DirectInput7, кстати, есть ещё CreateDeviceEx, в примерах из документации к SDK используют именно его.
@!!ex (2008-09-27 20:27:00) [12]> [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-27 20:12:00) [13]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 12:06:00) [14]
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-26 14:34:00) [15]только там для перекрытия методов используется их позиция в объекте
Позиция в интерфейсе. Cмотрим заголовки D3D/DInput и отсчитываем с начала, или относительно индексов тех методов, которые используются в примере (если с начала - вроде нужно ещё 3 добавить, на AddRef, Release и QueryInterface).
МистерТ (2008-09-26 11:57:00) [16]Помнится D3D и DI не являются полноценными СОМ-объектами, в том плане, что они создаются вызовом CreateInterface() непосредственно из библиотек d3d.dll и dinput.dll (не учитываю версии библиотек), а не через стандартные СОМ-методы.
Соответственно самый простой способ - реализация подмены этих библиотек своими - прокси библиотеками.
@!!ex (2008-09-25 21:04:00) [17]> [2] Sapersky (25.09.08 18:51)
Пример есть, интересный...
только там для перекрытия методов используется их позиция в объекте... а как ее узнать-то?
@!!ex (2008-09-25 19:18:00) [18]> [2] Sapersky (25.09.08 18:51)
Спасибо!
P.S.
Я ошибся. не D3D, DI конечно.
Sapersky (2008-09-25 18:51:00) [19]Если нужен перехват методов COM-интерфейсов, то в библиотеке madCodeHook есть пример с Direct3D.
Поросенок Винни-Пух (2008-09-25 18:18:00) [20]может просто подменить гуиды?