Jump to content

Remy Lebeau

Members
  • Content Count

    2986
  • Joined

  • Last visited

  • Days Won

    134

Posts posted by Remy Lebeau


  1. Try using GetClipboardSequenceNumber() on each message to check if the clipboard content has actually changed. 

     

    Also, the OnCreate/OnDestroy events are not the best place to register/remove your listener. Those events are tied to the lifetime of the Form object, not its HWND window, which may be recreated dynamically during the Form's lifetime. You should instead override the Form's virtual CreateWnd() and DestroyWnd() methods. 

    • Like 1

  2. 1 hour ago, corneliusdavid said:
    
    dir c:\* /s

    This is probably filtering out hidden and system files while FindFirst does not.

    There are 2 other mistakes in the FindFirst code -

    1. It is counting all of the files AND the subdirectories (despite MikeZ87's claim to the contrary) AND the '.' and '..' entries.
    2. Every time FileSearch() is called, it is searching the C:\ root again and again. It is not searching the DirName that is passed in.

    Try this instead:

    var
      MyTotal : Int64;  //This gets set to 0 in the button.click code when FileSearch is initially run.
    
    procedure TForm1.ButtonClick(Sender: TObject);
    begin
      MyTotal := 0;
      FileSearch('C:');
    end;
    
    procedure TForm1.FileSearch(dirName: string);
    var
      searchResult: TSearchRec;
    begin
      dirName := IncludeTrailingPathDelimiter(dirName);
      if FindFirst(dirName + '*', faAnyFile, searchResult) = 0 then begin // <-- NOT THE ROOT!
        try
          repeat
            if (searchResult.Attr and faDirectory) = 0 then begin
              Inc(MyTotal); // <-- MOVE HERE!
              //...
            end else if (searchResult.Name <> '.') and (searchResult.Name <> '..') then begin
              FileSearch(dirName + searchResult.Name);
            end;
          until FindNext(searchResult) <> 0;
        finally
          FindClose(searchResult);
        end;
      end;
    end;

    That being said, I would suggest a slight modification - make FileSearch() be a function that returns the file count, rather than modifying a class member, eg:

    procedure TForm1.ButtonClick(Sender: TObject);
    var
      TotalFiles : Int64;
    begin
      TotalFiles := FileSearch('C:');
      // use TotalFiles as needed...
    end;
    
    function TForm1.FileSearch(dirName: string): Int64;
    var
      searchResult: TSearchRec;
    begin
      Result := 0;
      dirName := IncludeTrailingPathDelimiter(dirName);
      if FindFirst(dirName + '*', faAnyFile, searchResult) = 0 then begin
        try
          repeat
            if (searchResult.Attr and faDirectory) = 0 then begin
              Inc(Result);
              //...
            end else if (searchResult.Name <> '.') and (searchResult.Name <> '..') then begin
              Inc(Result, FileSearch(dirName + searchResult.Name));
            end;
          until FindNext(searchResult) <> 0;
        finally
          FindClose(searchResult);
        end;
      end;
    end;

     


  3. 51 minutes ago, Aztec said:

    We do have Apache setup with a proxy

    Did you check the Apache logs for problems?

    51 minutes ago, Aztec said:

    when we first started the project, Indy didnt have support for the latest ssl  ... Ideally I would like to not use a proxy, and have the service run on https. I am not sure if we can do this now, with the latest indy? (We run on Ubuntu linux 22.04)

    You can enable SSL/TLS in TIdHTTPServer.  But no, Indy does not natively support an up-to-date version of OpenSSL yet, only up to 1.0.2u, but that does support TLS 1.2.  However, there are other 3rd party options for using newer TLS versions with Indy.  And, nothing stops you from writing a custom TIdSSLIOHandlerSocketBase-derived class to interact with whatever TLS library you want.  So, it is not an ideal situation, but it is not a show-stopper, either.

    51 minutes ago, Aztec said:

    When we get the 404, there are no response headers. It simply gives the error socket hang up as above.

    What you showed is not an HTTP 404 error.  It sounds like a communication problem between the proxy and the TIdHTTPServer.

    51 minutes ago, Aztec said:

    The ports are open in the firewall, and as I say, it is random. Other times we get the response back correctly.

    Then you are just going to have to keep debugging and logging until you can figure out what reproduces it.

    51 minutes ago, Aztec said:

    I am assuming that Indy is happy being set up as a daemon ?

    It should be fine, provided the ports are being blocked by either the firewall or the OS.


  4. 15 hours ago, Aztec said:

    I am getting random 404 errors when making a call to our indy server. 

    The only time that Indy's TIdHTTPServer sends a 404 automatically is if you call AResponseInfo.SmartServeFile() on a file that doesn't exist.  Otherwise, it sends a 404 only if you explicitly set AResponseInfo.ResponseNo to 404 yourself.  So, are you doing either of those in your OnCommandOther event handler?  If not, then are you sure the 404 response is coming from TIdHTPServer, and not maybe from a firewall/router in front of your server that could be intercepting the request and replying to it before TIdHTTPServer sees it?  What do the actual response headers look like?  There is simply not enough info to diagnose your problem.


  5. 6 hours ago, Dave Craggs said:

    Got these from the event log

     

    image.png.7f83303e9eb8c1f9622294334da94a9f.png

    0xEEDFADE is a Delphi exception. That's a good sign, it means it was thrown deliberately, not something unexpected like an Access Violation, etc.  The 2nd IDE instance that is debugging the 1st instance should be able to show you what the exception actually is.

    6 hours ago, Dave Craggs said:

    image.thumb.png.852fbb218a599c79c1e27c84ccf45d0d.png

    0xC000041D is STATUS_FATAL_USER_CALLBACK_EXCEPTION.  That is not a good sign.  Of course, it could also just be a side effect of the 1st error.

     

    Do you have the same problem if you load the component package dynamically at runtime via LoadPackage()?  Or does the error happen strictly during install only?

     


  6. 3 hours ago, PawelPepe said:

    When application main window is hidded there is a big problem! 

     

    What I do:
    Form2.Show; -> OnShow And OnActivate events are fired.
    BUT, if I show form2 again (second, third time), only OnShow event is fired - OnActivate event is not working! WHY?

    Are you merely hiding and reshowing Form2 on each message?  Or are you fully destroying and recreating it?

    3 hours ago, PawelPepe said:

    I hide mainform to Tray:

    
       Application.ShowMainForm := False;
       MainFrm.Hide;
       ShowWindow(Application.Handle, SW_HIDE);

     

    And I show it using:

    
       MainFrm.Show;
       Application.ShowMainForm := True;
       ShowWindow(Application.Handle, SW_SHOW);
       Application.BringToFront();

     

    FYI, Application.ShowMainForm only affects the startup of Application.Run(), so once the app is up and running then setting ShowMainForm has no effect.  Also, hiding/showing the Application.Handle is only useful in this case if Application.MainFormOnTaskbar is false, which is not the default in modern Delphi projects.


  7. 11 minutes ago, tobenschain said:

    if I try to delete the file manually it says it's still in use by the program 

    Are you sure it is YOUR program that has the file open?  Did you verify that, such has with a tool like SysInternals Process Explorer?  Maybe the file is open by the OS, or an antivirus/antimalware, etc.


  8. 6 minutes ago, limelect said:

    2. drag and drop were tested on

    The-Drag-and-Drop-Component-Suite-for-Delphi-master

    This also does not work on  any of my computers and different Delphi

    except as an exe.

    What does that have to do with the IDE? Those components are for dragging things at runtime only.  What is the actual PROBLEM you are having?  WHAT are you trying to drag, FROM where, TO where?  You are not explaining yourself very well.

     


  9. 2 hours ago, sp0987 said:

    This is the actual function:

     

    function InterceptCreate(const TargetProc, InterceptProc: Pointer; const Param: Pointer = nil; const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload;

    That function returns a pointer to a trampoline.  You must use that pointer when your hook function wants to call the original function.

     

     

    https://github.com/MahdiSafsafi/DDetours/wiki#interceptcreate

    Quote

    Return: If the function succeeds, the return value is a pointer to a TrampoLine function that can be used either to call the original function or to call the next hook (if exists). If the function fails, the return value is nil.

    For example:

    var
      TrampolineGetLocalTime: procedure(var st: TSystemTime); stdcall;
    
    procedure myNewLocalTime(var st: TSystemTime); stdcall;
    begin
      ...
      TrampolineGetLocalTime(st);
      ...
    end;
    
    TrampolineGetLocalTime := InterceptCreate(@Windows.GetLocalTime, @myNewLocalTime, ...);

    This is demonstrated in the DDetours documentation:

    https://github.com/MahdiSafsafi/DDetours/wiki#hooking-winapi-function

    • Thanks 1

  10. 1 hour ago, sp0987 said:

    Great idea, thank you. I will save the original reference before the detour and use that from within.

    That is not how a detour works. If you just save the original function address then you would call back into yourself, as you fear. The original function is still called everywhere, the detour simply modifies the first few bytes of the function to jump to your new function. So creating a detour requires saving the original bytes being modified so the new function can still execute them before jumping back into the original function past the modified bytes to continue the work normally. This is known as a "trampoline".

     

    However, in the case of a DLL function, it is simpler to just modify the PE imports table at runtime to redirect the entry of the target function to simply point at a different function, thus bypassing the original function completely. All calls go directly to the new function. In which case, yes, you would need to save the address of the original function so you can call it normally when needed.

     

    Since we don't know what your createNewDetour() is actually doing, it's important to know which technique is actually being used.


  11. 46 minutes ago, sp0987 said:

    GetLocalTime is just reference into external Windows DLL in Windows unit I think.

    Yes.

    46 minutes ago, sp0987 said:

    I'll need to create a wrapper with same name around it with additional logic somewhere within my project which can be reached by the original GetLocalTime in sysUtils?

    You would write a replacement function in your code, and then detour the original DLL function, and then all calls to the DLL function will go through your replacement function instead.  A detour doesn't care whether the original function resides in a DLL or not.  It is all in the same address space of the calling process.

    46 minutes ago, sp0987 said:

    Correction: it doesn't need to have same name. I could do something like:

     

    // excuse wrong code as I do not have D11 in front of me

    createNewDetour(@Window.GetLocalTime, @myNewLocalTime, ...);

     

    yes?

    Yes.


  12. 1 hour ago, adeptusgb said:

    That was the problem. The project only had OpenSSL v0.9.8.33 DLLs, I noticed there were some OpenSSL DLLs but didn't check if the version supported TLS 1.2 :classic_blink:

    Then you should have gotten an exception like EIdOSSLCouldNotLoadSSLLibrary from TIdHTTP when it failed to load the necessary TLS functions from the DLLs.


  13. 1 hour ago, adeptusgb said:

    res := httpClient.Put(url, fileStream);

    url should be SignedURL instead.

    1 hour ago, adeptusgb said:

    With this code I get an access violation at the res := httpClient.Put(url, fileStream);

    Is it an actual EAccessViolation, or some other exception?  I see nothing in the code you have shown that should be causing an EAccessViolation.

    1 hour ago, adeptusgb said:

    if I run just the Put on runtime, without assigning the response to a variable I get a "Delphi exception EIdSocketError at $2646F905".

    What is the complete error message?  There should be more detail about the exact socket error that actually occurred.

    1 hour ago, adeptusgb said:

    Removing the SSLIOHandler, I get a "Socket Error #10054 Connection reset by peer.".

    Sure, since you are disabling use of TLS.  You can't connect to an HTTPS url without TLS.

    1 hour ago, adeptusgb said:

    I assume it's either because of AWS using HTTPS ... and my SSL/TLS not working properly

    Other then the url issue mentioned above, the rest of the code looks fine.  Do you have OpenSSL v1.0.2 DLLs installed alongside your app?

    1 hour ago, adeptusgb said:

    or I'm passing the file binaries in the wrong format and the AWS server is refusing the connection instantly.

    More likely, either you are posting to the wrong URL, or there is a problem with the TLS handshake.  Have you tried using a packet sniffer, like Wireshark, to look at the raw TCP data for any differences between the postman handshake and the TIdHTTP handshake?  If the handshake is working, have you tried comparing Postman's HTTP request to TIdHTTP's HTTP request for differences?


  14. 20 minutes ago, sp0987 said:

    If it's really about the interface section, then i have tested the same without modifying interface section. I just created a new function in implementation section and tried to call the newly added function in our sample app. It also gives me the same error.

    If you modify a unit's interface, you have to recompile everything that uses that unit.

     

    If you add functionality to a unit's implementation, you can't access it from other units without exposing it in the interface. Catch-22.

     

    Best option is to not modify system/rtl units except for non-interface bug fixes. If you need custom functionality, best to just implement it in your own unit.


  15. 11 hours ago, Arvid P. said:

    In my defense, this is a very old project and I'm not the original developer. This concept was used in some classes and I used it for others that I added. So unfortunately I'll have to change quite a lot of classes since no inheritance was used. I guess I'll fix that too.

    The original code you showed makes sense if the calling code is using this kind of pattern:

    first();
    while (next()) {
    	// do something with getPresent() ...
    }

    Whereas my 2nd example would need this kind of pattern instead:

    if (First()) {
    	do {
    		// do something with getPresent() ...
    	}
    	while (Next());
    }

     


  16. 13 hours ago, #ifdef said:

    Why are the system cursor and the application cursor different?

    crNo DOES map to a system cursor - IDC_NO:

    image.png.43540c862733c359e2e36f8d81e2c24b.png

    Why it is not transparent, who knows.  Ask Microsoft.

    • Like 1

  17. 3 hours ago, Lajos Juhász said:

    No VCL application should try to compile DesignIntf.pas it is a violation of the licence. Only a runtime package can use it.

    I think you mean a design-time package.

    4 hours ago, Derrek Curtis said:

    That message is generated when the Vcl library is complied from within the project.

    Why are you recompiling the VCL?  Don't do that.  Your project is clearly not setup correctly.  Start over with a fresh project, and add your existing project source files to it.  And make sure your design-time package (not a runtime package!) has the DesignIDE package listed in its requires clause. You should not be compiling DesignIntf.pas directly.

    • Like 1

  18. 8 hours ago, Arvid P. said:
    
    void MyTypes::first()
    {
    	mp1MyType = NULL;
    }

     

    That is absolutely the wrong thing to do.  There is no such concept as a "null iterator" in the standard library.  An iterator has to always point at something valid, whether it is the 1st item in a container/range, the end of a container/range, or anything in between.

     

    For what you are attempting, you would need to wrap the iterator inside a std::optional (or equivalent, like Roger Cigol suggested), eg:

    std::optional<std::list<MyType*>::const_iterator> mp1MyType;
    
    void MyTypes::first()
    {
    	mp1MyType = std::nullopt();
    }
    
    bool MyTypes::next()
    {
    	if ( !mp1MyType.has_value() )
    		mp1MyType = mLstMyTypes.begin();
    	else
    		++(*mp1MyType);
    
    	if ( *mp1MyType == mLstMyTypes.end() )
    	{
    		mp1MyType = std::nullopt();
    		return false;
    	}
    
    	return true;
    }
    
    MyType* MyTypes::getPresent() const
    {
    	return mp1MyType.has_value() ? *(*mp1MyType) : nullptr;
    }

    But, why are you waiting until next() is called to move the iterator to the 1st item?  Why can't you do it in first() instead?  Seems like first() should return a bool indicating whether the iterator is valid, just like next() does, eg:

    std::list<MyType*>::const_iterator mp1MyType;
    
    bool MyTypes::first()
    {
    	mp1MyType = mLstMyTypes.begin();
    	return ( mp1MyType != mLstMyTypes.end() );
    }
    
    bool MyTypes::next()
    {
    	if ( mp1MyType != mLstMyTypes.end() )
    	{
    		++mp1MyType;
    		if ( mp1MyType != mLstMyTypes.end() )
    			return true;
    	}
    	return false;
    }
    
    MyType* MyTypes::getPresent() const
    {
    	return ( mp1MyType != mLstMyTypes.end() ) ? *mp1MyType : nullptr;
    }
    • Like 1

  19. 3 minutes ago, bugdude said:

    The connection is a long lived websocket connection (just one), but with the client hitting so often I think it gets hit again before the shutdown waittimes can expire and may be talking to a partially torn down object. That was why I wondered if there was a 'clean' way to abort/disconnect the SSL connection from the server side that could be used before trying to set active false on the server.

    Again, without seeing the actual code, it is hard to answer definitively.  Ideally, you would just set a flag that your server's OnExecute event handler can look for periodically and close the connection of the calling thread so it can terminate gracefully.  But, if you absolutely had to close the connection quickly, then calling Binding.CloseSocket() from outside the server should suffice (like I said, modern Indy already does that, but maybe your older version is not), provided you are not swallowing any subsequent exceptions that may arise.


  20. 2 hours ago, bugdude said:

    I am a hobbyist on a budget, so I use dated versions of Delphi and Indy (10.3.3 Delphi and the included Indy).

    Just because you are on a budget doesn't mean you should use outdated tools.  Especially tools that can be obtained for free.

    2 hours ago, bugdude said:

    I ran into problems with a project which uses TidCustomTCPServer to implement a web server with websocket support using OpenSSL. Basically the issue is that if the server has an active SSL websocket connection and TCPServer.Active is set false, the application stalls and gets locked into a loop in Indy (I think). Looking in the debugger I see that even though StopListeners was already called the recv handler is still being called repeatedly and generating exceptions.

    What you describe sounds like the TCP server threads are not shutting down correctly.  There couple be a number of reasons for that to happen.  For instance:

     

    Are you catching and discarding the exceptions?  If so, don't discard them.  Rethrow them and let the server handle them.

     

    Are you shutting down the server in the main thread, and syncing with the main thread in your server events?  If so, that is a guaranteed deadlock.  Either shutdown the server from a worker thread so the main thread is free to continue processing sync requests.  Or simply get rid of the syncs during shutdown.

    2 hours ago, bugdude said:

    The browser code polls the server every 100ms for screen updates so the calls may originate from the client, but the connection does still seem to be active. (project based on sourceforge ThinVNC with SSL added and other things added).

     

    Is the client creating a new connection for each poll?  Or reusing connections?

    2 hours ago, bugdude said:

    saw some notes about this issue in issue in GitHub, but I tried the solution mentioned there and that alone did not help.. (replaced call to AContext.Connection.Disconnect with Binding.CloseSocket call)

    Simply closing the sockets may not be enough. The server has to be allowed to process the closures so it can terminate its worker threads.  Besides, TIdTCPServer already calls CloseSocket() internally during its shutdown.  At least it does in recent years - it USED to call Disconnect() instead, but that proved to cause problems with OpenSSL connections across thread boundaries.

    2 hours ago, bugdude said:

    Q1 - is there a particular code sequence I could follow to block out those active SSL connections before setting active False that would circumvent this problem without upgrading Indy ?

    Hard to say without seeing your actual code to see why it is not shutting down correctly.

    2 hours ago, bugdude said:

    Q2 - would upgrading Indy from GitHub fix this specific issue ?

    Possibly.  Again, hard to say without knowing the root cause first.

    2 hours ago, bugdude said:

    Q3 - would the Indy cleanup script work on Delphi 10.3.3 safely ?

    Define "safely".  Is there a particular problem you are thinking of?

    2 hours ago, bugdude said:

    Q4 - is upgrading Indy likely to break anything else in this older version of Delphi ?

    Known issues are documented in the Update instructions, ie:

    https://github.com/IndySockets/Indy/wiki/Updating-Indy#delphicbuilderradstudio-101-berlin-and-later


  21. 3 hours ago, michel.seicon said:

    In the example above, if you increase the loop so that it consumes 4gb, and at the end release the objects, the correct thing would be to release this memory to the OS

    Unfortunately, that is not how Delphi's memory manager works, on any OS.  Freed memory is held onto and reused, it is rarely returned to the OS until the app is exited.

    3 hours ago, michel.seicon said:

    The problem is that in our system, if we manipulate images, files, and send them via Sockets then over time the system simply consumes a lot of memory and never releases it.

    You should consider re-writing your code to make better use of memory buffers so they are (re-)allocated and freed less often.

    3 hours ago, michel.seicon said:

    As I mentioned, this problem simply does not occur on Windows and only on Linux.

    That is not true.  Memory management and fragmentation are important issues to be aware of on Windows too, or any OS for that matter.


  22. 7 hours ago, BruceV said:

    Your first suggestion threw up 40 (!) linker errors which are all way above my pay grade, and I wouldn't trouble you to go anywhere with them.

    You probably need to recreate the project and make sure the VCL library is enabled.

    7 hours ago, BruceV said:

    The second one, the standard WIN32 approach, works fine and will do what I want.

    That wasn't the point of the exercise, though.  It was to get more details about why the file is not opening correctly.  But, if CreateFile() succeeds and std::ifstream fails, then there has to be another factor at play that is not being accounted for.

×