ठीक है, इसलिए मैं डायरेक्ट एक्स गेम पर कुछ अतिरिक्त बटनों के लिए कुछ ओवरले करने की कोशिश कर रहा हूं। http://www.gamedev.net/topic/359794-c-direct3d-hooking-sample/डी 3 डी 9 हुक - डायरेक्ट 3 डी 9
तो मैं यह डेल्फी में बदलने के लिए शुरू किया:
मैं एक C++ नमूना है कि काफी अच्छी तरह से यहाँ ओवरले पाया। कुछ प्रवेश के साथ मैं देख सकता हूँ कि यह() सही प्रक्रिया पर हुक शुरू होता है और सही ढंग से Direct3DCreate9 हुक।
अगला TMyDirect3D9 सफलतापूर्वक बनाया गया है। लेकिन प्रक्रिया यहां से दुर्घटनाग्रस्त हो जाती है।
मेरे अनुमान लगाने जब मैं शौकीन Direct3DCreate9() के माध्यम से मूल प्रक्रिया को वापस MyDirect3D9 लौट सकते हैं और यह वर्ग (इंटरफेस) में से एक कॉल करने के लिए कोशिश करता है यह विफल कार्य करता है कि (OllyDbg में कुछ डिबगिंग के आधार पर)।
कोड इस प्रकार है। अगर मैं मुझे बताने में मदद करने के लिए कोई अन्य जानकारी दे सकता हूं।
मुख्य DLL:
library LeagueUtilityBox;
{$R *.res}
{$DEFINE DEBUG}
uses
Windows,
APIHijack in 'APIHijack.pas',
Direct3D9 in '..\DirectX 9.0\Direct3D9.pas',
uSharedMem in '..\Misc\uSharedMem.pas',
MyDirect3D9 in 'MyDirect3D9.pas',
MyDirect3DDevice9 in 'MyDirect3DDevice9.pas',
{$IFDEF DEBUG}
SysUtils,
uLog in '..\Misc\uLog.pas',
{$ENDIF}
uMisc in 'uMisc.pas';
var
SharedMem : TSharedMem;
D3DHook: SDLLHook;
hHook : DWORD;
MyDirect3D9 : TMyDirect3D9;
function GetTargetProcess: String;
const
KeyBase : DWORD = HKEY_CURRENT_USER;
KeyLocation : String = 'Software\LeagueUtilityBox';
var
RegKey : HKEY;
TargetProcess : Array[0..511] Of Char;
Count : DWORD;
begin
Result := '';
If RegOpenKeyEx(KeyBase, PChar(KeyLocation), 0, KEY_QUERY_VALUE, RegKey) = ERROR_SUCCESS Then
begin
Count := 512;
If RegQueryValueEx(RegKey, nil, nil, nil, @TargetProcess[0], @Count) = ERROR_SUCCESS Then
begin
Result := String(TargetProcess);
end;
end;
end;
type
TDirect3DCreate9 = function(SDKVersion: LongWord): Pointer; stdcall;
function MyDirect3DCreate9(SDKVersion: LongWord): Pointer; stdcall;
var
OldFunc : TDirect3DCreate9;
D3D : PIDirect3D9;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'MyDirect3DCreate9 called');
{$ENDIF}
Result := nil;
OldFunc := TDirect3DCreate9(D3DHook.Functions[0].OrigFn);
D3D := OldFunc(SDKVersion);
If D3D <> nil Then
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'D3D created: 0x' + IntToHex(DWORD(Pointer(D3D)), 8));
{$ENDIF}
New(MyDirect3D9);
MyDirect3D9 := TMyDirect3D9.Create(D3D);
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'MyDirect3D9 Created');
{$ENDIF}
Result := @MyDirect3D9;
end;
end;
procedure InitializeHook;
var
Process : String;
I : Integer;
begin
SetLength(Process, 512);
GetModuleFileName(GetModuleHandle(nil), PChar(Process), 512);
For I := Length(Process) DownTo 1 Do
begin
If Process[I] = '\' Then Break;
end;
Process := Copy(Process, I + 1, Length(Process));
If CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, PChar(GetTargetProcess), -1, PChar(Process), -1) = 2 Then
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'Found target: ' + GetTargetProcess);
{$ENDIF}
With D3DHook Do
begin
Name := 'D3D9.DLL';
UseDefault := False;
DefaultFn := nil;
SetLength(Functions, 1);
Functions[0].Name := 'Direct3DCreate9';
Functions[0].HookFn := @MyDirect3DCreate9;
Functions[0].OrigFn := nil;
end;
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'About to hook: ' + String(AnsiString(D3DHook.Name)));
{$ENDIF}
HookAPICalls(@D3DHook);
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'Hook completed: ' + String(AnsiString(D3DHook.Name)));
{$ENDIF}
end;
end;
procedure InitializeDLL;
begin
SharedMem := TSharedMem.Create('LeagueUtilityBox', 1024);
Try
hHook := PDWORD(SharedMem.Buffer)^;
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'Initializing DLL: ' + IntToStr(hHook));
{$ENDIF}
Finally
SharedMem.Free;
end;
end;
procedure UninitializeDLL;
begin
UnhookWindowsHookEx(hHook);
end;
function WindowsHookCallback(nCode: Integer; WPARAM: Integer; LPARAM: Integer): LRESULT; stdcall;
begin
Result := CallNextHookEx(hHook, nCode, WPARAM, LPARAM);
end;
procedure EntryPoint(Reason: DWORD);
begin
Case Reason Of
DLL_PROCESS_ATTACH:
begin
InitializeDLL;
InitializeHook;
end;
DLL_PROCESS_DETACH:
begin
UninitializeDLL;
end;
end;
end;
exports
WindowsHookCallback;
begin
DLLProc := @EntryPoint;
EntryPoint(DLL_PROCESS_ATTACH);
end.
कस्टम IDirect3D9:
unit MyDirect3D9;
interface
uses Direct3D9, Windows, uMisc, uLog;
type
PMyDirect3D9 = ^TMyDirect3D9;
TMyDirect3D9 = class(TInterfacedObject, IDirect3D9)
private
fD3D: PIDirect3D9;
public
constructor Create(D3D: PIDirect3D9);
function QueryInterface(riid: REFIID; ppvObj: PPointer): HRESULT; stdcall;
function _AddRef: DWORD; stdcall;
function _Release: DWORD; stdcall;
function RegisterSoftwareDevice(pInitializeFunction: Pointer): HResult; stdcall;
function GetAdapterCount: LongWord; stdcall;
function GetAdapterIdentifier(Adapter: LongWord; Flags: DWord; out pIdentifier: TD3DAdapterIdentifier9): HResult; stdcall;
function GetAdapterModeCount(Adapter: LongWord; Format: TD3DFormat): LongWord; stdcall;
function EnumAdapterModes(Adapter: LongWord; Format: TD3DFormat; Mode: LongWord; out pMode: TD3DDisplayMode): HResult; stdcall;
function GetAdapterDisplayMode(Adapter: LongWord; out pMode: TD3DDisplayMode): HResult; stdcall;
function CheckDeviceType(Adapter: LongWord; CheckType: TD3DDevType; AdapterFormat, BackBufferFormat: TD3DFormat; Windowed: BOOL): HResult; stdcall;
function CheckDeviceFormat(Adapter: LongWord; DeviceType: TD3DDevType; AdapterFormat: TD3DFormat; Usage: DWord; RType: TD3DResourceType; CheckFormat: TD3DFormat): HResult; stdcall;
function CheckDeviceMultiSampleType(Adapter: LongWord; DeviceType: TD3DDevType; SurfaceFormat: TD3DFormat; Windowed: BOOL; MultiSampleType: TD3DMultiSampleType; pQualityLevels: PDWORD): HResult; stdcall;
function CheckDepthStencilMatch(Adapter: LongWord; DeviceType: TD3DDevType; AdapterFormat, RenderTargetFormat, DepthStencilFormat: TD3DFormat): HResult; stdcall;
function CheckDeviceFormatConversion(Adapter: LongWord; DeviceType: TD3DDevType; SourceFormat, TargetFormat: TD3DFormat): HResult; stdcall;
function GetDeviceCaps(Adapter: LongWord; DeviceType: TD3DDevType; out pCaps: TD3DCaps9): HResult; stdcall;
function GetAdapterMonitor(Adapter: LongWord): HMONITOR; stdcall;
function CreateDevice(Adapter: LongWord; DeviceType: TD3DDevType; hFocusWindow: HWND; BehaviorFlags: DWord; pPresentationParameters: PD3DPresentParameters; out ppReturnedDeviceInterface: IDirect3DDevice9): HResult; stdcall;
end;
implementation
uses MyDirect3DDevice9;
constructor TMyDirect3D9.Create(D3D: PIDirect3D9);
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.Create');
{$ENDIF}
fD3D := D3D;
end;
function TMyDirect3D9.QueryInterface(riid: REFIID; ppvObj: PPointer): HRESULT; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.QueryInterface');
{$ENDIF}
Result := fD3D^.QueryInterface(riid, ppvObj);
end;
function TMyDirect3D9._AddRef: DWORD; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9._AddRef');
{$ENDIF}
Result := fD3D^._AddRef;
end;
function TMyDirect3D9._Release: DWORD; stdcall;
var
count : DWORD;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9._Release');
{$ENDIF}
count := fD3D^._Release;
If count = 0 Then
begin
Self.Free;
end;
Result := count;
end;
function TMyDirect3D9.RegisterSoftwareDevice(pInitializeFunction: Pointer): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.RegisterSoftwareDevice');
{$ENDIF}
Result := fD3D^.RegisterSoftwareDevice(pInitializeFunction);
end;
function TMyDirect3D9.GetAdapterCount: LongWord; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.GetAdapterCount');
{$ENDIF}
Result := fD3D^.GetAdapterCount;
end;
function TMyDirect3D9.GetAdapterIdentifier(Adapter: LongWord; Flags: DWord; out pIdentifier: TD3DAdapterIdentifier9): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.GetAdapterIdentifier');
{$ENDIF}
Result := fD3D^.GetAdapterIdentifier(Adapter, Flags, pIdentifier);
end;
function TMyDirect3D9.GetAdapterModeCount(Adapter: LongWord; Format: TD3DFormat): LongWord; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.GetAdapterModeCount');
{$ENDIF}
Result := fD3D^.GetAdapterModeCount(Adapter, Format);
end;
function TMyDirect3D9.EnumAdapterModes(Adapter: LongWord; Format: TD3DFormat; Mode: LongWord; out pMode: TD3DDisplayMode): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.EnumAdapterModes');
{$ENDIF}
Result := fD3D^.EnumAdapterModes(Adapter, Format, Mode, pMode);
end;
function TMyDirect3D9.GetAdapterDisplayMode(Adapter: LongWord; out pMode: TD3DDisplayMode): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.GetAdapterDisplayMode');
{$ENDIF}
Result := fD3D^.GetAdapterDisplayMode(Adapter, pMode);
end;
function TMyDirect3D9.CheckDeviceType(Adapter: LongWord; CheckType: TD3DDevType; AdapterFormat, BackBufferFormat: TD3DFormat; Windowed: BOOL): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.CheckDeviceType');
{$ENDIF}
Result := fD3D^.CheckDeviceType(Adapter, CheckType, AdapterFormat, BackBufferFormat, Windowed);
end;
function TMyDirect3D9.CheckDeviceFormat(Adapter: LongWord; DeviceType: TD3DDevType; AdapterFormat: TD3DFormat; Usage: DWord; RType: TD3DResourceType; CheckFormat: TD3DFormat): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.CheckDeviceFormat');
{$ENDIF}
Result := fD3D^.CheckDeviceFormat(Adapter, DeviceType, AdapterFormat, Usage, RType, CheckFormat);
end;
function TMyDirect3D9.CheckDeviceMultiSampleType(Adapter: LongWord; DeviceType: TD3DDevType; SurfaceFormat: TD3DFormat; Windowed: BOOL; MultiSampleType: TD3DMultiSampleType; pQualityLevels: PDWORD): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.CheckDeviceMultiSampleType');
{$ENDIF}
Result := fD3D^.CheckDeviceMultiSampleType(Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType, pQualityLevels);
end;
function TMyDirect3D9.CheckDepthStencilMatch(Adapter: LongWord; DeviceType: TD3DDevType; AdapterFormat, RenderTargetFormat, DepthStencilFormat: TD3DFormat): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.CheckDepthStencilMatch');
{$ENDIF}
Result := fD3D^.CheckDepthStencilMatch(Adapter, DeviceType, AdapterFormat, RenderTargetFormat, DepthStencilFormat);
end;
function TMyDirect3D9.CheckDeviceFormatConversion(Adapter: LongWord; DeviceType: TD3DDevType; SourceFormat, TargetFormat: TD3DFormat): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.CheckDeviceFormatConversion');
{$ENDIF}
Result := fD3D^.CheckDeviceFormatConversion(Adapter, DeviceType, SourceFormat, TargetFormat);
end;
function TMyDirect3D9.GetDeviceCaps(Adapter: LongWord; DeviceType: TD3DDevType; out pCaps: TD3DCaps9): HResult; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.GetDeviceCaps');
{$ENDIF}
Result := fD3D^.GetDeviceCaps(Adapter, DeviceType, pCaps);
end;
function TMyDirect3D9.GetAdapterMonitor(Adapter: LongWord): HMONITOR; stdcall;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.GetAdapterMonitor');
{$ENDIF}
Result := fD3D^.GetAdapterMonitor(Adapter);
end;
function TMyDirect3D9.CreateDevice(Adapter: LongWord; DeviceType: TD3DDevType; hFocusWindow: HWND; BehaviorFlags: DWord; pPresentationParameters: PD3DPresentParameters; out ppReturnedDeviceInterface: IDirect3DDevice9): HResult; stdcall;
var
hr : HRESULT;
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'TMyDirect3D9.CreateDevice');
{$ENDIF}
hr := fD3D^.CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
If Succeeded(hr) Then
begin
{$IFDEF DEBUG}
WriteToLog('C:\LeagueUtilityBox.log', 'fD3D^.CreateDevice Succeeded');
{$ENDIF}
ppReturnedDeviceInterface := TMyDirect3DDevice9.Create(PIDirect3D9(@Self), @ppReturnedDeviceInterface);
end;
Result := hr;
end;
end.
अद्यतन: तो, के बाद से डेल्फी इंटरफेस एक असली भवन से अलग तरह से कार्य करने लगते हैं (डेल्फी एक में के बीच है इसके लिए अन्य इंटरफेस से सफलतापूर्वक बात करने के लिए)। इसलिए मैंने इंटरफेस को पॉइंटर्स की एक सरणी में बदल दिया।
अब कार्यक्रम को सफलतापूर्वक कॉल CreateDevice()। मैं इसे दोनों लॉग इन और ओलिडबग में कदम से देख सकता हूं।
अब क्या होता है कि जब CreateDevice मूल IDirect3D9.CreateDevice कॉल() इसे फिर से दुर्घटनाओं है। जब मैं OllyDbg में डिबग मुझे लगता है कि यह एक बार बहुत ज्यादा सूचक dereferencing है नोटिस।
अद्यतन 2: ठीक है, विभिन्न स्थानों में PIDirect3D9 के साथ कुछ सूचक संबंधी समस्याओं को ठीक बनाम IDirect3D9। तो मूल IDirect3D9.CreateDevice() को कॉल किया जाता है। लेकिन यह D3DERR_INVALIDCALL के साथ त्रुटियों !!
तो भ्रमित।
अद्यतन 3: ठीक है, कुछ और यह डिबगिंग के साथ लगता है कि जब मैं फ़ंक्शन को कॉल एक अतिरिक्त पैरामीटर ढेर पर धकेल दिया जाता है। जो पहला पैरा अमान्य बनाता है। यह डायरेक्टएक्स डीबगिंग द्वारा आगे साबित होता है जो कहता है कि iAdapter पैरामीटर अमान्य (पहला param)।
अद्यतन 4: IntRefToMethPtr का उपयोग कर के साथ() मूल CreateDevice कॉल मैं इसे ढेर एक ही साथ कॉल करने के लिए प्राप्त करने में सक्षम था के लिए सीधी सूचक मिलता है। वही परिणाम ऐसा लगता है कि मैं डेल्फी में इसे हुक करने की कोशिश के साथ गलत मार्ग चला गया हूं।
अद्यतन 5: दुबारा लिखा hooking विधि। अब मैं अनिवार्य रूप से एंडसेन() को हुक कर रहा हूं। हुक अब एक परीक्षण कार्यक्रम में ठीक काम करता है (Vertices.exe जो इस पोस्ट के पहले यूआरएल में मिले हुक डेमो के साथ आया था)। लेकिन मुख्य खेल में यह खेल दुर्घटनाग्रस्त हो जाता है। किसी भी तरह से मैंने बहुत कुछ सीखा है।
सी ++ कोड मैं गेम में ठीक कामों की प्रतिलिपि बना रहा हूं। मैंने हेडर को प्रत्यक्ष एक्स डेल्फी हेडर पैक से कॉपी किया है। असल में सी ++ कोड में आईडीआईआर 3 डी 9 'कक्षा MyDirect3D9: सार्वजनिक IDirect3D9' और उसी दिशा में IDirect3DDevice9 के आधार पर इसकी अपनी कक्षा है। इसके कन्स्ट्रक्टर में यह मूल डायरेक्ट 3 डीक्रेट 9() के साथ बनाई गई मूल आईडीएपी 3 डी 9 को बचाता है और इसके अलावा सबकुछ आगे बनाता है लेकिन CreateDevice() जिसमें यह इसके कस्टम IDirect3DDevice9 पर जाता है। मेरी समस्या डेल्फी (मेरे ज्ञान के लिए) में मेरी सटीक प्रतिलिपि है जब यह IDirect3D9 * का उपयोग करने का प्रयास करती है तो मैं क्रैश हो रहा हूं। – ThievingSix
इसके अलावा मुझे कई सी ++ उदाहरण मिल गए हैं, लेकिन डेल्फी में डायरेक्ट 3 डी 9 उदाहरण काम नहीं कर रहे हैं। यदि आप एक के बारे में जानते हैं, तो इसका स्वागत होगा। – ThievingSix
मुझे किसी भी डेल्फी उदाहरणों के बारे में पता नहीं है, लेकिन मुझे पता है कि जो क्रैश आप देख रहे हैं वह आम तौर पर विधि (ओं) को गलत या लागू नहीं किया जाता है। ऐसा प्रतीत होता है कि डेल्फी में 'आभासी' कीवर्ड है, जो उपयोगी हो सकता है (सी ++ में सभी COM विधियां वर्चुअल हैं)। विरासत सख्ती से जरूरी नहीं है, लेकिन कुछ संकलन-समय त्रुटि जांच करने की अनुमति देता है (यह सुनिश्चित करने के लिए कि सभी विधियों को सही ढंग से लागू किया गया हो)। – ssube