Jump to content

rvk

Members
  • Content Count

    34
  • Joined

  • Last visited

Posts posted by rvk


  1. 4 hours ago, PeterPanettone said:

    Or is there a way to activate both the 32-bit hook AND the 64-bit hook with ONE SINGLE exe?

    I'm not sure but there might be a way to do it from one exe. But that might be really advanced stuff (haven't looked st the details).

     

    A 64-bit process can access a 32-bit DLL across a process boundary if the 32-bit DLL is loaded into a separate 32-bit surrogate process space, and the application makes use of the built-in IPC mechanisms that support data exchange between 32-bit and 64-bit processes.

     

    https://blog.mattmags.com/2007/06/30/accessing-32-bit-dlls-from-64-bit-code/


  2. 15 minutes ago, jon_bondy said:

    One thing that puzzled me was that the code without permissions was working on another Android device, but not this one.

    Because with older Android version the permission is given during install (if it's asked for by the program). With newer Android the permission needs to be given during runtime (because during install everybody just clicks through without thinking).


  3. 27 minutes ago, PeterPanettone said:

    Are there any grown-up people here?

    Yes, there are... (although I could also appreciate the comment of FredS :classic_ninja:)

     

    I have it working here in 64 bit.

    Besides the INVALID_HANDLE_VALUE I mentioned earlier, you need to use the correct GetMsgProc() definition.

    The one now used is only valid in 32 bit.

    If you change it into this it worked here (both in the implementation and interface part).

     

    Quote

    function GetMsgProc(Ignore: integer; wParam: Windows.WPARAM; uMessage: Windows.LPARAM): LRESULT; stdcall;

    (although you might want to avoid a parameter named wParam because it is also a type in the Windows unit which you need, solved here with unit-prefixing)

     

     

    • Like 1

  4. 1 minute ago, PeterPanettone said:

    However, I also do not get a callback when clicking on any system menu item in any application.

    Yep. That was my conclusion too. There still must be something wrong.

     

    Using WH_CBT you do get some messages. There supposed to be a HCBT_SYSCOMMAND message containing the information but I haven't looked at it further.

     


  5. 22 minutes ago, PeterPanettone said:

    The error seems to be in the DLL code in the function Hookup in the line GetMsgProcRec^.Hwnd := Hwnd:

       Access violation at address 0000000003585C9F in Modul 'fwGetMsgProc.dll'. Reading from address 0000000000000000.

    The reason for this is because GetMsgProcRec seems to be nil in the DLL.

    It seems that the call to CreateFileMapping fails in 64 bit.

     

    For testing this you can add your fwGetMsgProc dll project to the projectgroup of TESTHks and debug the dll-calls.

    Set a breakpoint in InitializeDll and you'll see it stops at the first MappedMem line.

    Next (on the second try) trace into the procedure with F7 and you'll see the exception for cErrorCreating,['TMappedMem'] is called.

     

    You'll see a $FFFFFFFF as parameter, meaning an invalid handle (see https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga)

    But INVALID_HANDLE_VALUE is THandle(-1) which is something different then $FFFFFFFF in 64 bit. (you'll need $FFFFFFFFFFFFFFFF)

     

    So change it to

    Quote

        fHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0,  Size, PChar(Name));

    Now the hook can successfully be installed.

     

    (I hadn't much luck with catching anything but now you're a step closer :classic_blink:)

     


  6. 16 hours ago, PeterPanettone said:

    How can I make it sending a message to my application's window?

    I don't think 'injecting code' is the best way to go.

     

    I think you need to catch the WM_SYSCOMMAND which is sent to the other application(s).

    You should be able to do that with SetWindowsHookEx().

    https://social.msdn.microsoft.com/Forums/windows/en-US/f87193b7-ccc2-4c30-9b1e-195addd375c8/how-to-intercept-a-wmsyscommand-sent-to-another-app?forum=winforms

     

    An example in C++ http://forums.codeguru.com/showthread.php?161054-System-wide-hook-for-WM_SYSCOMMAND

     


  7. 4 minutes ago, aehimself said:

    The code I was talking about is about 50-100 lines in Delphi...

    Correct. The base of the code from NumWords is just 70-somewhat lines and can easily be adjusted to follow the additional/proper rules.

     

    const
      Digits: array [1 .. 9] of string = (
        'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
    
      Teens: array [1 .. 9] of string = (
        'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen');
    
      TenTimes: array [1 .. 9] of string = (
        'ten', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety');
    
    function DoTriplet(TheNumber: Integer): string;
    var
      Digit, Num: Integer;
    begin
      Result := '';
      Num := TheNumber mod 100;
      if (Num > 10) and (Num < 20) then
      begin
        Result := Teens[Num - 10];
        Num := TheNumber div 100;
      end
      else
      begin
        Num := TheNumber;
        Digit := Num mod 10;
        Num := Num div 10;
        if Digit > 0 then Result := Digits[Digit];
        Digit := Num mod 10;
        Num := Num div 10;
        if Digit > 0 then Result := TenTimes[Digit] + ' ' + Result;
        Result := Trim(Result);
      end;
      Digit := Num mod 10;
      if (Result <> '') and (Digit > 0) then Result := 'and ' + Result;
      if Digit > 0 then Result := Digits[Digit] + ' hundred ' + Result;
      Result := Trim(Result);
    end;
    
    function NumberInWords(TheNumber: Integer): string;
    var
      Num, Triplet, Pass: Integer;
    begin
      if TheNumber < 0 then Result := 'Minus ' + NumberInWords(-TheNumber)
      else
      begin
        Result := '';
        Num := TheNumber;
        if Num > 999999999 then
            raise Exception.Create('Can''t express more than 999,999,999 in words');
        for Pass := 1 to 3 do
        begin
          Triplet := Num mod 1000;
          Num := Num div 1000;
          if Triplet > 0 then
          begin
            if (Pass > 1) and (Result <> '') then Result := ', ' + Result;
            case Pass of
              2: Result := ' thousand' + Result;
              3: Result := ' million' + Result;
            end;
            Result := Trim(DoTriplet(Triplet) + Result);
          end;
        end;
      end;
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Showmessage(NumberInWords(2120229));
    end;


     

    • Like 1

  8. 9 minutes ago, Attila Kovacs said:

    Rule 2a. Hyphenate all compound numbers from twenty-one through ninety-nine.

    Rule 8b. When writing out numbers above 999, do not use commas.

    You mentioned a "great solution on a website". https://www.calculator.org/calculate-online/mathematics/text-number.html

    It translates 2019 to "two thousand, nineteen"

    How does that one follow those rules?

     

    But maybe there are better ones.

    But I haven't even seen any ones online that convert according to those rules.

    (or maybe this one https://www.tools4noobs.com/online_tools/number_spell_words/)


  9. Looking at the source, each time you press the OK button a private variable FAttempt is increased. When it goes over the AttemptNumber a Cancel is automatically triggered. So the Login will fail.

     

    procedure TJvLoginForm.OkBtnClick(Sender: TObject);
    begin
      Inc(FAttempt);
      if Assigned(FOnOkClick) then
        FOnOkClick(Self)
      else
        ModalResult := mrOk;
      if (ModalResult <> mrOk) and (FAttempt >= AttemptNumber) then
        ModalResult := mrCancel;
    end;


     


  10. 4 hours ago, Ian Branch said:

    It runs immediately the App is started and seemingly before the application's Form is created.

    That depends on where you put the TJvLoginDialog.

     

    If you have a DataModule, ideally the TJvLoginDialog goes on the TDataModule and you'll execute it in the DataModuleCreate() after connecting to the TDatabase. Set Active to false at designtime so you can do this yourself in the DataModuleCreate().

    Login.Active := true;
    if not Login.Execute then
    begin
      // inform the user and exit
      Application.Terminate;
    end;

     

    In the OnCheckUser you can check the database if the user has entered valid credentials.

     

    If you have the TDatabase component on a TForm and you initialize it there, then you'll need to put the TJvLoginDialog there too (in FormCreate() and after the initialization of the TDatabase-component).


  11. On 9/14/2019 at 9:24 AM, Stéphane Wierzbicki said:

    If not, is there any free library available?

    Like I stated before, you can do it with Synapse (from Ararat) and libssh2.dll. There is a SimpleSFTP.pas in the demo-directory. But that one uses cryptlib.dll which isn't free distributable. But there are version which can also use libssh2.dll (which is free). I have one for FPC but not ported to Delphi.

     

    There are also versions which use plain winsock in combination with libssh2.dll (no need for Synapse).

    For example: https://github.com/pult/libssh2_delphi (and like others on github)

     

    Using the searchwords libssh2 and delphi in Google will get you a lot of results too.

    For the Synapse version you can just search for SimpleSFTP.pas and libssh2 and you can search for the latest working with libssh2.dll.

     

    If you have any problems let us know.

     

    • Like 1
    • Thanks 1

  12. You can do it with Synapse in combination with cryptlib, or better libssh2.dll, for free.

     

    There is some source out there (I think sftp_2000) for Delphi.

     

    If you can't find it I could convert the example I have from FPC/Lazarus back to Delphi (will need some time for that).

     

     


  13. 49 minutes ago, pcplayer99 said:

    I can not get plain text that user can read at all.

    You can use TWebBrowser.WebBrowser1DocumentComplete() and read out WebBrowser1.Document.documentElement.outerHTML;

    (like discussed above)

    You can strip out any script tags and html tags and you end up with the plain text.

    (you should add line breaks on div en br tags though otherwise you have text on one line.)

     

    Or you might look for HTML2TEXT function which does all that work for you.

    But the readable text is there in the .outerHTML.

     


  14. 1 hour ago, David Schwartz said:

    Thanks, you created a trivial example to prove YOUR case, not what I'm dealing with. BRAVO!

    You might want to dial down the sarcasme. I'm trying to help you here and with that attitude I'm feeling less and less inclined to do so.

     

    With my example I retrieved your search result and got this (this is a snippet just to show you the content is there).

     

    <div class="I6vAHd h5RoYd ads-creative">Dr. Lazer is a <b>Baltimore Dentist</b> Dedicated To Quality <b>Dental</b> Care. Financing Available. Patient Focused <b>Dentistry</b>. Top <b>Baltimore Dentists</b>. Advanced Training. Services: Cosmetic <b>dentistry</b>, General <b>dentistry</b>, Porcelain veneers, Teeth whitening, <b>Dental</b> implants, Cosmetic dentures, <b>Dental</b> crowns.</div><ul class="OkkX2d"><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/our-office/ed-lazer-dds/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoAHoECA8QBA" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABABGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_0RkT0b2u8xR9l7_LEQw9VUouKjzQ&adurl=&rct=j&q=">Meet Dr. Ed Lazer</a></li><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/for-patients/special-offers/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoAXoECA8QBQ" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABACGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_2gU3L1cLsoIxMZDy60AJIwH1-G4w&adurl=&rct=j&q=">Special Offers</a></li><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/smile-gallery/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoAnoECA8QBg" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABADGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_0Eq9nb4XnF90RRE1Ik35kT7kFBQQ&adurl=&rct=j&q=">Smile Gallery</a></li><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/request-appointment/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoA3oECA8QBw" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABAEGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_2N4qM3fV1hZgFsH22ko3zEIjVzFQ&adurl=&rct=j&q=">Schedule Appointment</a></li><li><a class="V0MxL" onmousedown="return google.f[this.getAttribute('data-mousedown')](this)" ontouchstart="return google.f[this.getAttribute('data-touchstart')](this)" href="https://www.cosmeticdentistbaltimore.com/contact/?TrackNum=410-753-2005" data-ved="2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQpigoBHoECA8QCA" data-touchstart="bez1fd" data-mousedown="LmvwCb" data-arwt="//www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABAFGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_0sMvnrhd-h49qKlc3LKos0K2h67w&adurl=&rct=j&q=">Contact Us</a></li></ul></li><li class="ads-ad" data-hveid="CBAQAA" data-bg="1"><div class="ad_cclk"><a id="n1s0p2c0" style="display: none;" href="https://www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwia64isiIPkAhVH5HcKHQCGCzoYABAGGgJlZg&ohost=www.google.com&cid=CAASE-RoDCdUQXMX66yba6ZIKqfKGC0&sig=AOD64_38aJbvxP_v7qoqtk0s9Byp6f8NQw&rct=j&q=&ved=2ahUKEwj7o4KsiIPkAhVEJlAKHYQZDhMQ0Qx6BAgQEAE&adurl="></a><a class="V0MxL r-ieStqovnU5rk" id="vn1s0p2c0" onmousedown="return google.arwt(this)" ontouchstart="return google.arwt(this)" href="https://www.aspendental.com/dentist/md/dundalk/1401-merritt-blvd" jsl="$t t-r1glFWqNI5A;$x 0;"><h3 class="sA5rQ">Official Aspen Dental | Affordable dentistry‎</h3><br><div class="ads-visurl">

    You see that text: Dr. Lazer is a <b>Baltimore Dentist</b> Dedicated To Quality <b>Dental</b> Care. Financing Available.

     

    Is that what you are after? (this is from the outerHTML)

    Yes, it's riddled with javascript and lots of tags. But it's valid HTML with the content provided on screen of the user.

     

    If it's not, please provide some text that you did expect.

     

    BTW, You do need to read out outerHTML in WebBrowser1DocumentComplete() because the javascript needs time to run. But I assumed you already knew this.

     

     

     

    • Like 2

  15. On 8/13/2019 at 3:48 PM, David Schwartz said:

    Try it on a Google search or on some news sites, and let me know what you find.

    Why should I try it????

    But alright... I tried and it works.

     

    With this source file

    Test
    <div id=content>
    Some other content
    </div>
    
    <script type = "text/JavaScript">
    document.getElementById("content").innerHTML = "Changed content";
    </script>

    I got this in Delphi for 

    var
      d: OleVariant;
    begin
      d := WebBrowser1.Document;
      Memo1.Lines.Text := d.documentElement.outerHTML;
    end;

     

    <HTML><HEAD></HEAD>
    <BODY>Test 
    <DIV id=content>Changed content</DIV>
    <SCRIPT type=text/JavaScript>
    document.getElementById("content").innerHTML = "Changed content";
    </SCRIPT>
    </BODY></HTML>

    Note the "Changed content" between the divs of id=content !!

     

    The javascript itself obviously stays there because it's part of the source but the content itself is the way it is represented to the end-user after executing the javascript. The DOM even places the missing HTML, HEAD and BODY tags in there.

     

     

     

     


  16. If you can put together an example and the virtual channels work the same on RDP on win10, I can take a look.

     

    I take it this should do the same as TSScan and RemoteDesktopTwain but then directly from your own local utility program.

     

     


  17. Ah. But it does not not crap out :classic_biggrin:

    There is definitely some alignment problem.

     

    You say "RDS" DLL. How is that DLL different?

    Is there something done with the calls?

    Could you share the code?

     

    Maybe if that problem is fixed, the other method with ttmNative is fixed automatically too.

     

     

×