So, ich greife das Ganze hier mal auf.
CreatePrcess() kann ich ausschließen, da es in diesem Zusammenhang nicht benutzt wird. Es liegt definitiv an GetThreadContext().
Beispiel, damit Ihr es testen koennt:
Delphi-Quellcode:
procedure Test();
var
Context: TContext;
begin
ZeroMemory(@Context, SizeOf(TContext));
Context.ContextFlags := CONTEXT_DEBUG_REGISTERS;
writeln(GetThreadContext(GetCurrentThread(), Context));
end;
var
Context: TContext;
begin
ZeroMemory(@Context, SizeOf(TContext));
Context.ContextFlags := CONTEXT_DEBUG_REGISTERS;
writeln(GetThreadContext(GetCurrentThread(), Context));
Test();
readln;
end.
Ausgabe:
Getestet mit der Delphi 2010 Trial.
GetLastError sagt 998: Unzulaessiger Zugriff auf einen Speicherbereich.
Im
msdn steht folgendes:
Zitat:
A pointer to a CONTEXT structure that receives the appropriate context of the specified thread. The value of the ContextFlags member of this structure specifies which portions of a thread's context are retrieved. The CONTEXT structure is highly processor specific. Refer to the
WinNt.h header file for processor-specific definitions of this structures and
any alignment requirements.
Das würde es in meinen Augen auch erklären. ABER beide sind 4 Byte-Aligned. Und da Delphi nur 32bit Executables erzeugen kann sollte dass doch passen, oder?
Main: Context: _CONTEXT $411E44
Procedure: Context: _CONTEXT $18FEA8
Wenn ich den Speicher dynamisch anfordere funktioniert das Ganze (Ausgabe: TRUE);
Delphi-Quellcode:
procedure Test_Dynamic();
var
Context: PContext;
begin
GetMem(Context, SizeOf(TContext)); //Context: PContext ebx : $20CCD10
ZeroMemory(Context, SizeOf(TContext));
writeln(GetThreadContext(GetCurrentThread(), Context^));
end;
Ich würde mich nur ungerne darauf verlassen, dass es nur funktioniert, wenn der Speicher dynamisch angefordert wird.
Was mir spontan ins Auge springt, ist das Alignment. Es ist immer 8 Byte, wenn es funktioniert (0x18FEA8 und 0x20CCD10). Ich kann mich aber auch nicht drauf verlassen, dass Delphi mir mit GetMem einen Speicherblock liefert, der auf 8 Byte Aligned ist.
Ich habe den Gedanken mal weiter verfolgt und was soll ich sagen, es stimmt. GetThreadContext() verlangt einen Speicherblock, der auf 8 Byte-Aligned ist. (Ja, ich beseitzt einen 64bit Prozessor + passendes
OS)
Um auf Nummer sicher zu gehen sollte man den Speicher mit so einer Krücke reservieren:
Delphi-Quellcode:
function Get8ByteAlignedContext(): PContext;
begin
GetMem(result, SizeOf(TContext) + 8);
while ((DWord(result) mod 8) <> 0) do
result := Pointer(DWord(result) + 1);
end;
AHHRG: Kommando zurueck! Ich sehe gerade, dass Context in der Main _NICHT_ 8 Byte Aligned war, sondern 4. Und es funktioniert trotzdem. (Wenn man testet dann auch richtig, und nicht nur 8Byte und ungerade Aligments...)
Halten wir also Fest:
Context muss 4Byte-Aligned seinen:
Delphi-Quellcode:
procedure Test_Alignment();
var
Context: PContext;
i: Integer;
begin
GetMem(Context, SizeOf(TContext) * 2);
ZeroMemory(Context, SizeOf(TContext) * 2);
for i := 0 to 12 do
begin
ZeroMemory(Context, SizeOf(TContext));
if ((DWord(Context) mod 4) = 0) then
write('[Aligned] ')
else
write('[Not Aligned] ');
writeln(GetThreadContext(GetCurrentThread(), Context^));
Context := Pointer(DWord(Context) + 1);
end;
end;
Code:
[Aligned] TRUE
[Not Aligned] FALSE
[Not Aligned] FALSE
[Not Aligned] FALSE
[Aligned] TRUE
[Not Aligned] FALSE
[Not Aligned] FALSE
[Not Aligned] FALSE
[Aligned] TRUE
[Not Aligned] FALSE
[Not Aligned] FALSE
[Not Aligned] FALSE
[Aligned] TRUE
Aber wieso Funktioniert der Aufruf im Main Abschnitt und in der Funktion nicht?
Wenn sich jemand durch die "Wall-of-Text" gekaempft hat, danke schon mal dafuer. Bin fuer alle Ideen und Anregungen offen.
Grüße,
Win32.API