Jump to content

TiGü

Members
  • Content Count

    44
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by TiGü


  1. Hm...in Delphi Tokyo we can find in SysSysctlTypes.inc:

     

    (* TODO -otgerdes -cTranslate: kinfo_proc (needs proc.h)
    struct kinfo_proc {
            struct  extern_proc kp_proc;                    // proc structure
            struct  eproc {
                    struct  proc *e_paddr;          // address of proc
                    struct  session *e_sess;        // session pointer
                    struct  _pcred e_pcred;         // process credentials
                    struct  _ucred e_ucred;         // current credentials
                    struct   vmspace e_vm;          // address space
                    pid_t   e_ppid;                 // parent process id
                    pid_t   e_pgid;                 // process group id
                    short   e_jobc;                 // job control counter
                    dev_t   e_tdev;                 // controlling tty dev
                    pid_t   e_tpgid;                // tty process group id
                    struct  session *e_tsess;       // tty session pointer
    #define WMESGLEN        7
                    char    e_wmesg[WMESGLEN+1];    // wchan message
                    segsz_t e_xsize;                // text size
                    short   e_xrssize;              // text rss
                    short   e_xccount;              // text references
                    short   e_xswrss;
                    int32_t e_flag;
    #define EPROC_CTTY      0x01    // controlling tty vnode active
    #define EPROC_SLEADER   0x02    // session leader
    #define COMAPT_MAXLOGNAME       12
                    char    e_login[COMAPT_MAXLOGNAME];     // short setlogin() name
    #if CONFIG_LCTX
                    pid_t   e_lcid;
                    int32_t e_spare[3];
    #else
                    int32_t e_spare[4];
    #endif
            } kp_eproc;
    };
    *)

     


  2. 18 hours ago, David Heffernan said:

    Even on windows, IsDebuggerPresent is not the same as System.DebugHook <> 0. The former tests for any debugger, the latter tests for the Emba debugger.

    That's good to know! Thank you for the clarification. 

    I stumbled upon this interesting blog post:

    https://xorl.wordpress.com/2017/11/20/reverse-engineering-isdebuggerpresent/

     

    There must be similar mechanics on iOS, Android, Linux and macOS. I personally know too little about that. 😞


  3. 17 minutes ago, Sherlock said:

    To easy @TiGü:

     

    But as we can see in the 

    class procedure TThread.NameThreadForDebugging(AThreadName: string; AThreadID: TThreadID);

    there are following lines:

    ...
    {$ELSEIF Defined(ANDROID)}
      if (System.DebugHook <> 0) or (getenv(EMBDBKPRESENTNAME) <> nil) then
    {$ELSE}
    ...

    So, i guess it's defined for Windows and Android and working on both platforms.

     

    Hast du wirklich deine IDE auf Deutsch gestellt?  


  4. Hi Primož,

     

    that's a nice piece of code, but i notice in my Delphi Tokyo, that the ens-Result for the TEnumSet (for valid values) is empty.

    But if you add a untyped Move, than it works:

     

    program Project1;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      System.TypInfo,
      System.Rtti,
      System.SysUtils;
    
    resourcestring
      SValueLiesOutsideAllowedRange = 'Value %d lies outside allowed range for %s (%d .. %d)';
    
    type
      TypeInfoCache<T> = class
      class var
        FMinIntVal: Integer;
        FMaxIntVal: Integer;
        FIsSet: Boolean;
      public
        class constructor Create;
        class property MaxIntVal: Integer read FMaxIntVal;
        class property MinIntVal: Integer read FMinIntVal;
        class property IsSet: Boolean read FIsSet;
      end;
    
      Range<T> = record
      private
        class function MaxIntVal: Integer; static; inline;
        class function MinIntVal: Integer; static; inline;
        class procedure RaiseException(const Value: Integer); static;
      public
        class function Check(const Value: Integer): T; static;
      end;
    
      { Range<T> }
    
    class function Range<T>.Check(const Value: Integer): T;
    begin
      if (Value < MinIntVal) or (Value > MaxIntVal) then
        RaiseException(Value);
    
      if TypeInfoCache<T>.IsSet then
      begin
        Move(Value, Result, SizeOf(T)); // here is the magic
      end;
    end;
    
    class function Range<T>.MaxIntVal: Integer;
    begin
      Result := TypeInfoCache<T>.MaxIntVal;
    end;
    
    class function Range<T>.MinIntVal: Integer;
    begin
      Result := TypeInfoCache<T>.MinIntVal;
    end;
    
    class procedure Range<T>.RaiseException(const Value: Integer);
    begin
      raise Exception.CreateFmt(SValueLiesOutsideAllowedRange,
        [Value, PTypeInfo(TypeInfo(T)).Name, MinIntVal, MaxIntVal]);
    end;
    
    { TypeInfoCache<T> }
    
    class constructor TypeInfoCache<T>.Create;
    var
      ti: PTypeInfo;
      typeData: PTypeData;
      i: Integer;
    begin
      ti := TypeInfo(T);
      FIsSet := ti.Kind = tkSet;
      if FIsSet then
        ti := GetTypeData(ti).CompType^;
      typeData := GetTypeData(ti);
      FMinIntVal := typeData.MinValue;
    
      if FIsSet then
      begin
        FMaxIntVal := 0;
        for i := typeData.MinValue to typeData.MaxValue do
          FMaxIntVal := FMaxIntVal or (1 shl i);
      end
      else
        FMaxIntVal := typeData.MaxValue;
    end;
    
    type
      TEnum = (en1, en2, en3);
      TEnumSet = set of TEnum;
    
    var
      en: TEnum;
      ens: TEnumSet;
    
    begin
      try
    
        try
          en := Range<TEnum>.Check(0);
          en := Range<TEnum>.Check(2);
          en := Range<TEnum>.Check(3);
        except
          on E: Exception do
            Writeln('Expected exception: ', E.ClassName, ' ', E.Message);
        end;
    
        try
          ens := Range<TEnumSet>.Check(0);
          ens := Range<TEnumSet>.Check(2);
          ens := Range<TEnumSet>.Check(7);
          ens := Range<TEnumSet>.Check(8);
        except
          on E: Exception do
            Writeln('Expected exception: ', E.ClassName, ' ', E.Message);
        end;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
      if DebugHook <> 0 then
        Readln;
    
    end.

     

    • Like 1

  5. program Project1;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    
    uses
      System.SysUtils,
      Winapi.Windows;
    
    procedure Main;
    var
      I: Integer;
    begin
      Writeln('Start');
    
      while not IsDebuggerPresent do
      begin
        Writeln('I''m waiting for you!');
        Sleep(100);
      end;
    
      for I := 1 to 1000 do
        Writeln(' I:', I);
    
      Writeln('End');
    end;
    
    begin
      try
        Main;
        Readln;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    
    end.

    Try the good old While-Not-IsDebuggerPresent-Trick! 

    • Like 1
    • Thanks 1

  6. Wow, it could be easier.
    You have to set the Converter.Options after casting to the EarsivWebService interface. Then they are not reset and you can avoid the AfterExecute handler.

     

    unit Earsiv.View;
    
    interface
    
    uses
      System.SysUtils,
      System.Classes,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
      EarsivWebService1,
      Soap.SOAPHTTPClient,
      Soap.OpConvertOptions;
    
    type
      TForm5 = class(TForm)
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        FRIO: THTTPRIO;
        FEarsivWebService: EarsivWebService;
      public
      end;
    
    var
      Form5: TForm5;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm5.FormCreate(Sender: TObject);
    begin
      FRIO := THTTPRIO.Create(nil);
      FRIO.URL := 'https://earsiv.efinans.com.tr/earsiv/ws/EarsivWebService';
      FEarsivWebService := (FRIO as EarsivWebService);
    
      FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams];
    end;
    
    procedure TForm5.Button1Click(Sender: TObject);
    var
      Request: faturaOlustur;
      Response: faturaOlusturResponse;
    begin
      Request := nil;
      Response := nil;
    
      Request := faturaOlustur.Create();
      Request.input := 'Hello';
      Request.fatura := belge.Create();
      Request.fatura.belgeFormati := belgeFormatiEnum.PDF;
    
      try
        Response := FEarsivWebService.faturaOlustur(Request);
      finally
        if Assigned(Response) then
        begin
          if Assigned(Response.return) then
          begin
            ShowMessage(Response.return.resultCode + sLineBreak + Response.return.resultText);
          end;
          Response.Free;
        end;
    
        Request.Free;
      end;
    end;
    
    end.

     


  7. Hi @ertank!  I play with your code and do some debugging in the depths of the Delphi SOAP sources. As you can see in the TOPToSoapDomConvert.ProcessResponse (Line 2037 in Tokyo 10.2.3) it calls a inline class helper function IsBareLiteral. 

     

    Making long story short: Set every time the THTTPRIO.Converter.Options (see Unit Soap.OpConvertOptions) and the Response will be filled.

     

    Try this:

     

    unit Earsiv.View;
    
    interface
    
    uses
      System.SysUtils,
      System.Classes,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
      EarsivWebService1,
      Soap.SOAPHTTPClient,
      Soap.OpConvertOptions;
    
    type
      TForm5 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        FRIO: THTTPRIO;
        WS: EarsivWebService;
        procedure MyHTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream);
      public
      end;
    
    var
      Form5: TForm5;
    
    implementation
    
    {$R *.dfm}
    
    
    procedure TForm5.Button1Click(Sender: TObject);
    var
      Request: faturaOlustur;
      Response: faturaOlusturResponse;
    begin
      if not Assigned(FRIO) then
      begin
        FRIO := THTTPRIO.Create(nil);
        FRIO.OnAfterExecute := MyHTTPRIO1AfterExecute;
        FRIO.URL := 'https://earsiv.efinans.com.tr/earsiv/ws/EarsivWebService';
        // the following line are not enough, see MyHTTPRIO1AfterExecute
        FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams];
        WS := (FRIO as EarsivWebService);
      end;
    
      Request := nil;
      Response := nil;
    
      Request := faturaOlustur.Create();
      Request.input := 'Hello';
      Request.fatura := belge.Create();
      Request.fatura.belgeFormati := belgeFormatiEnum.PDF;
    
      try
        Response := WS.faturaOlustur(Request);
      finally
        if Assigned(Response) and Assigned(Response.return) then
        begin
          ShowMessage(Response.return.resultCode + sLineBreak + Response.return.resultText);
        end;
    
        Request.Free;
        Response.Free;
      end;
    end;
    
    procedure TForm5.MyHTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream);
    begin
      FRIO.Converter.Options := FRIO.Converter.Options + [soDocument, soLiteralParams];
    end;
    
    end.

     

    • Like 1
×