In der
Unit mit dem Formular:
Delphi-Quellcode:
function CallBack(alert, param: Integer; pTransfer, pUser: Pointer): Integer;
begin
beep;
end;
...
ShrinkTo5.CallBack := CallBack;
...
Und in der Class TShrinkTo5:
Delphi-Quellcode:
type
...
TFNCallBack = function(alert, param: Integer; pTransfer, pUser: Pointer): Integer; stdcall;
TFNSetCallBack = procedure(pCallBack, pUser: Pointer); stdcall;
type
TShrinkTo5 = Class
private
fCallBack : TFNCallBack;
pUser : Pointer;
...
public
property CallBack : TFNCallBack write FCallBack;
...
end;
function TShrinkTo5.GetExecute: Integer;
{*******************************************************************************
* Den Transfer beginnen.
}
type
TThreadParams = record
FNTransferPath : TFNTransferPath;
TransferPath : String;
end;
PThreadParams = ^TThreadParams;
var
ThreadParams : PThreadParams;
hThread : THandle;
ThreadID : Cardinal;
lResult : Cardinal;
function Thread(p: PThreadParams): Cardinal;
var
PTransferPath : PChar;
PstopFlag : PChar;
FNTransferPath : TFNTransferPath;
lResult : Integer;
begin
PTransferPath := PChar(PThreadParams(p)^.TransferPath);
PstopFlag := PChar('0');
FNTransferPath := PThreadParams(p)^.FNTransferPath;
lResult := FNTransferPath(PTransferPath, PstopFlag);
FreeMem(p, sizeof(TThreadParams));
if lResult < 0
then Result := $0FFFFFFF - lResult
else Result := lResult;
end;
begin
Result := 0;
if DirectoryExists(fTransferPath)
and Assigned(FNTransferPath)
then try
{
* Das Callback setzen
}
pUser := nil;
FNSetCallBack(@FCallBack, pUser);
{
* Den Arbeitsthread erstellen
}
GetMem(ThreadParams, sizeof(TThreadParams));
ThreadParams.FNTransferPath := FNTransferPath;
ThreadParams.TransferPath := fTransferPath;
hThread := BeginThread(nil, 0, @Thread, ThreadParams, 0, ThreadID);
if hThread <> INVALID_HANDLE_VALUE
then begin
while WaitForSingleObject(hThread, 300) = WAIT_TIMEOUT
do Application.ProcessMessages;
{
* return codes for TransferPath
* >0 success - number of MegaBytes written
* 0 user aborted (stopFlag == 1)
* -2 if stream is scrambled and either descrambling failed or is disabled
* -5 source was not opened with "Open"
* -6 cannot authorize driveend;
}
end;
finally
GetExitCodeThread(hThread, lResult);
end;
if lResult > $0FFFfff0
then Result := lResult - $0FFFFFFF
else Result := lResult;
end;
So sieht die Procedure aus. Bin jetzt auf die Idee gekommen, das Projekt in OllyDebug (v2.0.0k von heute) anzusehen. Da steht dann
Code:
1000D23D | 8038 01 | CMP Byte PTR DS: [EAX], 1
Bei EAX steht 0000030. Was dann die Zugriffsverletzung darstellt.
Ich finde es irritierend, dass der Parameter pUser nicht mitgegeben wird. pUser als PInteger zu deklarieren, bringt keine Änderung.