Jump to content

Remy Lebeau

Members
  • Content Count

    3053
  • Joined

  • Last visited

  • Days Won

    139

Posts posted by Remy Lebeau


  1. Your Start() function is not compatible with rundll32. It's a wonder your code ever worked at all. You are invoking undefined behavior.

     

    Read: INFO: Windows Rundll and Rundll32 Interface

     

    Your Start() function MUST have the following signature in order for rundll32 to call it correctly:

    procedure Start(hwnd: HWND; hinst: HINSTANCE; lpszCmdLine: PAnsiChar; nCmdShow: Integer); stdcall;

  2. On 7/14/2025 at 7:43 AM, Mimiko said:

    The filestream creates a unique temp file where the data goes. Within ServerCommandOther the data is written to a second filestream with the final filename (the final name isn't yet known on CreatePostStream, so I need to copy later).

    Why not simply rename or move (not copy) the original temp file to the new filename, instead of copying its data to a new file?

    On 7/14/2025 at 7:43 AM, Mimiko said:

    As long as the data is within a 500-600 MB range, all works well. If the uploaded data is larger, then the client gets a network timeout after a few seconds. But the session thread is still active and the copy process is still running.

    The only way I can see that happening is if you are not sending a response to the client until after the file data has been copied to the final file, and it's taking a long time to do that copy.  Clients are not going to wait around forever for a response after they send their data to the server, so you should try to send a response as soon as possible, ie when the data has been saved in the temp file, or once processing of that file has begun in the background.  If that is not an option, they you have no control over the client's timeout settings on the server side, so all you can do is optimize your processing to speed it up.  If your processing is going to take a long time, then return a response ASAP and then provide a separate API for the client to poll the status of the processing, ie a separate REST endpoint, or a WebSocket, or server push events, etc.

    On 7/14/2025 at 7:43 AM, Mimiko said:

    Copying between PostStream and TargetStream is done via CopyFrom and so I placed some logging within its Read/Write loop. As soon as the copy process goes beyond the mentioned 500-600 MB, that loop seems to stop its process for several seconds, then it resumes copying, and this repeats randomly.

    That has nothing to do with Indy, but with your OS and/or hard drive performance.  Maybe you are writing to bad sectors, or there are other I/Os in progress that slow down the OS's handling of your file, etc.   No way to diagnose that from your limited description.

     

    Also, TStream.CopyFrom() was pretty basic in 10.3. It was re-written sometime after 10.3 with more buffering logic.  Speaking of buffering, consider using TBufferedFileStream instead of a plain TFileStream.  TBufferedFileStream was introduced in Delphi 10.1. That way, more of the copying process is done in memory rather than directly on the hard drive. Handling data with file I/O will always be inherently slower than handling data in memory.

    On 7/14/2025 at 7:43 AM, Mimiko said:

    I just don't understand why THTTPsServer closed the connection while the thread's still working.

    It didn't.  The client timed out and closed the connection on its end.  If you are doing your file processing directly in your OnCommand handler then the server CAN'T close its end of the connection until you return control back to the server, ie by exiting the handler.

    On 7/14/2025 at 7:43 AM, Mimiko said:

    Is there something I can do to the session or the server to avoid the network timeout at the client?

    Yes - don't perform long-running processes directly in your OnCommand handler that makes the client wait a long time for a response.

    On 7/14/2025 at 7:43 AM, Mimiko said:

    Or is there a problem with TFileStream regarding threads?

    No.  Especially if different threads are working on different files.

    On 7/14/2025 at 7:43 AM, Mimiko said:

    I tried setting all possible timeouts (ConnectTimeout, ReadTimeout, WriteTimeout on the session socket), enable/disable nagle, KeepAlive, ReuseSocket... all that, but to no success.

    There is no timeout you can set on the server side that will affect the client's own timeouts.  However, one thing you might try is TCP keepalives, not HTTP keepalives, ie via the AContext.Connection.Socket.Binding.SetKeepAliveValues() method.  But, that won't prevent the client from just giving up if no response arrives in a long time.

    • Like 1

  3. Pascal code is compiled top-down in a single pass. DEFINE, IFDEF, etc are compiler directives that are evaluated only at compile-time. The resulting code is fixed, it cannot be changed at runtime. If you try to IFDEF something before it has been DEFINE'd, the result will be False. Hence the name IF-DEFined.

     

    In any case, DEFINE/IFDEF is not the correct solution for your problem anyway. You are making a decision based on data known only at runtime, so you need to add an extra parameter to your function that is called at runtime (you need to add a Sender parameter, too), eg:

    function doTheReport(Sender: TObject; Bo: Boolean);
    begin
      if Bo then
        Result := DoCharges(true, -1, False, False, False, lg('CLOSE CHARGES'), '1', dm2.SysDate.FieldByName('date').AsDateTime)
      else
        Result := DoCharges(Sender=nil, -1, False, False, False, lg(TDsFancyButton(Sender).Caption), '', 0, dm2.SysDate.FieldByName('date').AsDateTime);
    end;
    
    function selectReport(Sender: TObject);
    begin
      doTheReport(Sender, Sender = good1);
    end;

    Alternatively:

    function doTheReport(Sender: TObject);
    begin
      if Sender = good1 then
        Result := DoCharges(true, -1, False, False, False, lg('CLOSE CHARGES'), '1', dm2.SysDate.FieldByName('date').AsDateTime)
      else
        Result := DoCharges(Sender=nil, -1, False, False, False, lg(TDsFancyButton(Sender).Caption), '', 0, dm2.SysDate.FieldByName('date').AsDateTime);
    end;
    
    function selectReport(Sender: TObject);
    begin
      doTheReport(Sender);
    end;

     

    • Thanks 1

  4. 56 minutes ago, Del Murray said:

    If I do this ..

    s :=  IdSSLOpenSSL.OpenSSLVersion();

    then Indy wants to actually load the sll libraries so that it can return the value.

    During that load process, which is before I even try to do a http function like a GET, the libraries cant load.

    That is why I suggested calling it AFTER the load had already failed the first time.  But, I guess it doesn't matter, since it is unable to even load the DLLs into memory, so it will not be able to call the exported function that reports the version number.

    56 minutes ago, Del Murray said:

    Here is the failing code ...  It fails on the call to SafeLoadLibrary.

    If you were using an up-to-date version of Indy, then on Windows WhichFailedToLoad() would include the error code for why SafeLoadLibrary() failed.  It is clear from your screenshot that you are using an old version that does have include that error code.

    56 minutes ago, Del Murray said:

    Snippet of code where failure occurs at "SafeLoadLibrary" ...

    And here are the values of GIdOpenSSLPath and SSLCLIB_DLL_name at run time 

    and here are those files on the hard drive at that location

    Offhand, that looks ok. But its hard to diagnose without knowing exactly where you got those DLLs from, and what external dependencies they actually have.  If you right-click on the DLLs, what version numbers do their Properties show?  And have you tried running the DLLs through any Dependency Viewer tools?  You might also try using SysInternal Process Monitor to see what additional files Windows tries to access while the DLLs are being loaded.

    56 minutes ago, Del Murray said:

    Does anyone have an idea of anything else I can check.

    Yes, but I already mentioned the dependency issue in an earlier reply and you haven't addressed it yet.  That is the most common reason for (Safe)LoadLibrary() to fail.


  5. 7 minutes ago, Freeeee said:

    1 is the stratup form. I want a button on that form

    to close form 1 and open form 6 for further input.

    Is Form 1 the Main form? Closing the Main form will terminate the app.  You could just hide it instead, buy why do you want to close Form 1 at all?

    7 minutes ago, Freeeee said:

    How do I do this?    Sounds simple but I haven't found a tutorial or book that shows the code yet.

    I know the code goes into the buttonclick procedure and I have found the USES clause for Form 6

    but making the transfer from 1 to 6??? not yet.

    What exactly is stopping you from accomplishing what you want?  What exactly have you attempted so far that is not working for you?  Do you know how to create and open forms?  Do you know how to add procedures to classes, and how to call them?  Sounds like you are missing some fundamentals.

     

    Try something like this

    unit Unit1;
    
    interface
    
    ...
    
    type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        ...
      end;
    
    implementation
    
    uses
      Unit6;
    
    ...
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Form6 := TForm6.Create(Application);
      Form6.Show;
      Hide;
      Form6.DoSomething;
    end;
    
    end.
    unit Unit6;
    
    interface
    
    ...
    
    type
      TForm6 = class(TForm)
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        ...
      public
        procedure DoSomething;
      end;
    
    var
      Form6: TForm6;
    
    implementation
    
    ...
    
    procedure TForm6.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action := caFree;
      Form6 := nil;
    end;
    
    procedure TForm6.DoSomething;
    begin
      ...
    end;
    
    end.

     


  6. 5 hours ago, apachx said:

    To target max version Windows 11 23H2, is it enough to simply change the line to:

    
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22631.0" />

    Will this be sufficient for the Microsoft Store to treat my app as compatible with both Windows 10 and Windows 11? 

    Did you try it and see if it does?


  7. 1 hour ago, Marsil said:

    But clearly the properties of Item are NOT duplicated. Thanks for reporting that.

    I'm not sure why item properties are duplicated when the item itself is supposed to be added to the Items, why the properties are duplicated and where?

    The documentation is misleading. The properties are NOT duplicated at all. If you pass in an existing TListItem then it gets inserted as-is and becomes part of the TListView.

    • Thanks 1

  8. 1 hour ago, Del Murray said:

    After much debugging I have determined that Indy can not load the ssl libs that I am pointing to using the IdOpenSSLSetLibPath function. If I point to older libs in different place it loads them fine.

    What do the IdSSLOpenSSL.OpenSSLVersion() and IdSSLOpenSSLHeaders.WhichFailedToload() functions report after the load fails?

    1 hour ago, Del Murray said:

    I could be that my new libs are corrupt somehow and the system SafeLoadLibrary function cant load them because that's where it is failing in the Indy code.

    So, the problem is in loading the DLLs themselves into memory, and not with obtaining pointers to the exported functions after the DLLs are loaded into memory?

    1 hour ago, Del Murray said:

    I have downloaded them again from IndyGetHub. They now load so previous files must have been corrupted somehow.

    Perhaps the DLLs you were using have external dependencies (ie, VC++ runtime, etc) that were missing?  Most of the DLLs on Indy's GitHub are built without external dependencies.

    1 hour ago, Del Murray said:

    New question is .... Does the version of libeay32.dll and ssleay32.dll  both created 12/21/2019 support TLS1.2 ?

    Yes.  The TLS 1.2 spec was released in 2008, and TLS 1.2 was implemented in OpenSSL 1.0.1 in 2012.

    1 hour ago, Del Murray said:

    I've looked at later version of SSl on the Indy GitHub and they seem to have the crypto libraries instead and not the older named "eay" libraries.

    What do you referring to?


  9. On 7/5/2025 at 3:08 AM, Marsil said:

    I tried this

    
    var Item := TListItem.Create (ListView1.Items);
    Item.Caption := SomeLinkedObject.Name;
    Item.Checked := SomeLinkedObject.Enabled;
    Item.Data := SomeLinkedObject;
    ListView1.Items.AddItem (Item);

    but the item is shown without caption!, and memory leak occurred!

    I cannot reproduce any memory leak with that code, but I can reproduce the caption issue.  You need to add the item before changing its Caption:

    var Item := TListItem.Create (ListView1.Items);
    ListView1.Items.AddItem (Item); // <-- move here
    Item.Caption := SomeLinkedObject.Name;
    Item.Checked := SomeLinkedObject.Enabled;
    Item.Data := SomeLinkedObject;

    The reason is because setting the Caption assigns the LPSTR_TEXTCALLBACK flag on the item, which TListView needs to display the assigned String data, but AddItem() does not set that same flag. So, if you set the Caption and then Add, the flag is not set and the ListView has no text data to display.  Looks like a bug, I have reported it:

     

    RSS-3772: TListItems.AddItem() does not set LPSTR_TEXTCALLBACK flag for existing TListItem

    • Thanks 1

  10. 4 hours ago, DelphiUdIT said:

    My sources about Posix are in "C:\Program Files (x86)\Embarcadero\Studio\23.0\source\rtl\posix"

    Same here.

    2 hours ago, pyscripter said:

    As mentioned I can compile code.  Just the sources in the above path are missing.

    Do you have all of the available patches installed for 12.3?


  11. 13 hours ago, Marsil said:

    But I still don't understand why the ListView is firing the checked event for an item that still being created and still not properly initialized yet?😕

    As I said earlier, you are getting the event when the new item's default state image is assigned.

     

    More specifically, when TListView.Items.Add() creates a new TListItem object and inserts it into the TListView.Items, it calls the Win32 ListView_InsertItem() function, which immediately sends the TListView a LVN_ITEMCHANGED notification before it returns. In that notification, the item's uChanged field is LVIF_STATE and the state image has changed index from 0 to 1.  That condition is what fires the OnItemChecked event.

     

    The item is fully initialized from the Win32 perspective before TListView.Items.Add() returns.  Anything you do extra to the item after Add() returns is optional, and is initialization from your perspective, not the Win32 perspective.

    • Thanks 1

  12. The checkboxes are implemented as state images. You are getting the event when the item's initial state is assigned.  Just check for the nil condition and don't access the object when it's not ready yet:

    procedure TForm1.ListView1ItemChecked(Sender: TObject; Item: TListItem);
    begin
      if Assigned(Item.Data) then
        TSomeLinkedObject(Item.Data).Enabled := Item.Checked;
    end;

    Alternatively, disable the event when adding an item, and then re-enable the event when ready:

    ListView1.OnItemChecked := nil;
    var Item := ListView1.Items.Add;
    ...
    ListView1.OnItemChecked := ListView1ItemChecked;
    • Thanks 1

  13. You don't need to create an instance of your hint class. By setting the HintWindowClass variable, the VCL will instantiate your class when needed.

     

    In any case, the reason your code doesn't work is because by default THintWindow responds to WM_NCHITTEST to return HTTRANSPARENT, thus all mouse activity gets directed to the window that is underneath the hint.  You can intercept WM_NCHITTEST yourself to return HTCLIENT instead, so thus your WM_LBUTTONDOWN handler will be triggered when clicking on the hint window.

     

    However, then you run into a new problem, because as soon as the mouse enters the hint window, it effectively leaves the control underneath the hint, and thus the control hides the hint immediately before you can click on it.  You can work around that by having TMyHintWindow override the virtual ShouldHideHint() method to return False.  Then, you will have opportunity to click on the hint window.

     

    However, then you run into a new problem, because as soon as your click closes the hint, the mouse will effectively re-enter the control that was underneath the hint, and the control will reshow the hint again.

     

    Isn't this fun? :classic_wacko: What exactly are you trying to accomplish by messing with the hint window's default behavior?


  14. The correct link is https://docwiki.embarcadero.com/Libraries/en/Vcl.Forms.HintWindowClass

     

    Also, you don't need to assign the HintWindowClass before Application.Run() is called (though you certainly can). Just be sure to assign it before any hints are displayed at runtime. For instance, in the MainForm's OnCreate event would suffice.

     

    Also, if you don't want to override the hint behavior globally, you can customize the hint on a per-invocation basis by using the TApplication[Events].OnShowHint event. It gives you access to a THintInfo describing the hint that is about to be displayed, which has a HintWindowClass field (amongst many others). 


  15. 4 hours ago, Tommi Prami said:

    In case of I get Invite, if someone can make good guess to get JCL to install and compile on the beta. I would download it just in case.

    That would need to be a discussion for the beta testers to have in private.


  16. 11 hours ago, PeterBelow said:

    Actually I newer participated in a beta due to lack of time and spare hardware

    You can always use VMs for betas.  But I hear you.  I usually don't have spare time to actively do any testing, but I do like to join in to see what's coming ahead of time.

    • Like 4

  17. 6 hours ago, BuilderFox said:

    Unfortunately I have a lot of problems.

    What kind of problems, exactly?

    6 hours ago, BuilderFox said:

    The old projects compiles on my old Windows 7 PC (yep!) without any errors. I suspect that the new compilers are less tolerant.

    Less tolerant of what?

    6 hours ago, BuilderFox said:

    Which compiler versions (for C++Builder AND Delphi, Delphi because I use a lot of 3rd-party components) can I use/select.

    I don't understand the question.

    6 hours ago, BuilderFox said:

    And where in the settings? Especially the "old" ones!

    Huh?


  18. 1 hour ago, DelphiUdIT said:

    EDIT, try this old thing: set the PassThrough of SSLIOHandler to false.

     

    After setting the ChiperList inserto this line:

    
      IdSSLIOHandlerSocketOpenSSL1.PassThrough := false;

     

    That should have no effect on TIdHTTP, as it internally toggles the PassThrough property based on whether an HTTP or HTTPS url is being requested.


  19. 3 hours ago, Del Murray said:

    I'm very puzzled about the reference to SSL3_get error  

    In OpenSSL, SSL 3.0 and TLS 1.x share some common code during the handshake, so you may see references to SSL3 when TLS is actually being used.

    3 hours ago, Del Murray said:

    I set no cipher string in the test.

    Nor should you, except when you have very specific security requirements.  If you don't set a CipherList explicitly, a default one is used, which should usually be suitable for most tasks.

     

    HOWEVER, do note that in July 2018 (between D10.2 and D10.3), there was a behavior change made in Indy.  Maybe that is contributing to your issue?

     

    Prior to the change (ie, in the Indy bundled with XE7), if the CipherList was empty then Indy used a hard-coded cipher list that was taken from the OpenSSL SDK:

     

    'AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH'

     

    After the change, Indy no longer uses that.  It now lets OpenSSL use whatever default cipher list it was compiled with.

    3 hours ago, Del Murray said:

    This code in idSSLOpenSSL is never true ..

      if IsTLSv1_2Available then begin
        if not ( sslvTLSv1_2 in SSLVersions) then begin
          SSL_CTX_set_options(fContext, SSL_OP_NO_TLSv1_2);
        end;
      end;

     

    Which seems to indicate that the libeay32 and ssleay32  may not have TLSV1_2 available. I'm using Libs just downloaded from GitHub

    If IsTLSv1_2Available() returns False, that means the OpenSSL DLLs you are using do not export the TLSv1_2_method(), TLSv1_2_server_method() and, TLSv1_2_client_method() functions.  I can assure you that the OpenSSL 1.0.2 DLLs in Indy's GitHub repo DO export those functions.

     

    Note, if Indy doesn't detect TLS 1.1 and TLS 1.2 are available, it will silently fallback to TLS 1.0.  That might also be contributing to your issue.

     

    Just to check, what does Indy's OpenSSLVersion() function report for you after the DLLs are loaded?  I would also suggest using SysInternals Process Explorer to view your app's process at runtime and verify that your app is actually loading the expected OpenSSL DLLs and not some other incompatible OpenSSL DLLs that may be located elsewhere on your PC.

    • Like 1

  20. 5 hours ago, Squall_FF8 said:

    However when I use the result in Query, I get error - it messes up the syntax of the SQL.

    Then you will have to escape control characters manually, which QuotedStr() doesn't do for you.

     

    But, you really shouldn't be concatenating strings to create SQL queries to begin with. Use a parameterized query instead, letting the DB enging handle all of the escaping and quoting for you. Or, use a blob stream (though, I would use TFQQuery.CreateBlobStream() instead of creating TFDBlobStream directly, but either way works).

    6 hours ago, Squall_FF8 said:

    Since when RTF includes control codes (ASCII < 32)? If that is the case then things like `\par` are nonsense.

    AFAIK, RTF does not use ASCII control characters. Line breaks are handled by \line and \par control words. And there should be no #0 characters at all. That being said, if there are raw line breaks in the RTF, it might be for human reading purposes, but not machine reading.

    6 hours ago, Squall_FF8 said:

    The RTF text states version 2.0. Do you know what version of RichEdit Delphi 12+ uses?

    Delphi 12 uses RichEdit 4.1 (since D11) , which is the current version available from Microsoft at this time. I don't know offhand what version of RTF it supports.

    6 hours ago, Squall_FF8 said:

    I'm not familiar with "RTF using 8bit characters". Does Delpji / Windows RichEdit supports that? Do you know of a program that supports that?

    RTF is encoded in ASCII, which fits in 8bit (AnsiChar) characters in memory, so you don't need to waste memory using 16bit (WideChar) characters to hold it. A Delphi String is 16bit since D2009. This is why I suggested using varchar instead of nvarchar in the DB. Or, a blob field will suffice, too.

     

    • Thanks 1
×