hello
hello,
I'm trying to use a class helper to replace a public method from a base class and to add other methods.
If the base class method has no operators then the patch works, the code calls the function of the class helper (same function name and parameters).
In my case the base class function has a override directive, from another ancestor class with virtual, abstract method. In this case the code calls the function method of the base class instead of the helper one.
Any hint?
It's a bug or a bad behavior?
I'm trying to use a class helper to replace a public method from a base class and to add other methods.
If the base class method has no operators then the patch works, the code calls the function of the class helper (same function name and parameters).
In my case the base class function has a override directive, from another ancestor class with virtual, abstract method. In this case the code calls the function method of the base class instead of the helper one.
Any hint?
It's a bug or a bad behavior?
I like to build a little patch for webbroker, adding async read write (actually read and write are syncronous blocking the thread).
ReplyDeleteI don't want to modify the delphi sources (further it's not permitted by license), and i fpossible I don't want to use VirtualProtect API and low level pointers exchange...
Look (very preliminary code, the status should be sent into iocomp loop, checkings etc ...).
unit IsapiHelper;
(we should add this unit into the main project and webbroker should read/write asynchronosly releasing the threads immediately, by default webbroker has a limit of 32 datamodule and 25 threads).
Now I see that for patching virtual methods I should use RTTI, and for static methods VirtualProtect RW replacing the address of the function.
...
interface
uses Windows, System.SysUtils, Web.Win.IsapiHTTP, Winapi.Isapi2;
type
PWritePacket = ^TWritePacket;
TWritePacket = record
Content: TBytes;
Size: DWord;
end;
//type
//TIsapiCallback = procedure(ECB: PEXTENSION_CONTROL_BLOCK; Packet: PWritePacket; Count, Error: DWord); stdcall;
type
TIsapiRequestHelper = class helper for TIsapiRequest
private
// FOnCallBack:TIsapiCallBack;
public
function ReadClient(var Buffer; Count: Integer): Integer;
function WriteClient(var Buffer; Count: Integer): Integer;
end;
const
HSE_IO_ASYNC = $00000002;
procedure OnPageComplete(ECB: PEXTENSION_CONTROL_BLOCK; Packet: PWritePacket; Count, Error: DWord); stdcall;
implementation
function TIsapiRequestHelper.ReadClient(var Buffer; Count: Integer): Integer;
begin
Result := Count;
if not ECB.ReadClient(ECB.ConnID,@Buffer, DWord(Result)) then
Result := -1;
end;
function TIsapiRequestHelper.WriteClient(var Buffer; Count: Integer): Integer;
var
Size: cardinal;
Packet: PWritePacket;
begin
Result := -1;
New(Packet);
SetLength(Packet^.Content, Count);
Move(Buffer, Packet^.Content, Count);
Packet^.Size := Count;
if (ECB.ServerSupportFunction(ECB.ConnID, HSE_REQ_IO_COMPLETION,@OnPageComplete, nil,@Packet)) then
begin
Size := Packet^.Size;
if (ECB.WriteClient(ECB.ConnID,@Packet^.Content[0], Size, HSE_IO_ASYNC)) then
Result := Size; // todo: return HSE_STATUS_PENDING
end;
end;
procedure OnPageComplete(ECB: PEXTENSION_CONTROL_BLOCK; Packet: PWritePacket; Count, Error: DWord); stdcall;
var
Size: cardinal;
begin
if Count < Packet^.Size then
begin
Dec(Packet^.Size, Count);
Size := Packet^.Size;
ECB.WriteClient(ECB.ConnID,@Packet^.Content[Count], Size, HSE_IO_ASYNC);
end
else
begin
SetLength(Packet.Content, 0);
Dispose(Packet);
ECB.ServerSupportFunction(ECB.ConnID, HSE_REQ_DONE_WITH_SESSION, nil, nil, nil);
end;
end;
end.
Now you've got a real question!. My advice: Copy paste the code and ask the question on SO.
ReplyDeleteI got the answer, RTTI for dinamic mthods, API for static..
ReplyDelete