-
Content Count
2903 -
Joined
-
Last visited
-
Days Won
129
Everything posted by Remy Lebeau
-
Why does CoInitializeEx returns 1 or $80010106 ?
Remy Lebeau replied to maXcomX's topic in Windows API
Unfortunately, as I already pointed out earlier, the VCL's TApplication constructor calls OleInitialize() before the ComObj unit has a chance to call CoInitialize/Ex(), and OleInitialize() internally calls CoInitialize(nil), so if you require CoInitializeEx() with any mode other than COINIT_APARTMENTTHREADED then you will have to do your COM work in a separate worker thread instead of in the UI thread. The ComObj unit is not the only unit that uses InitProc. InitProc is a chained list of initialization procedures, so you can't use Assigned(InitProc) alone as an indicator of whether you should call CoInitializeEx() or not. If you need CoInitializeEx() called, then just call it yourself unconditionally, and just be sure to pay attention to whether it fails or not. Returning S_FALSE is NOT a failure condition! A thread cannot change its COM threading mode once it has been set. That is what the RPC_E_CHANGED_MODE error code tells you. That IS a failure condition! If you need to use a different COM threading model than the calling thread has already been set to, you will have to move your COM work to another thread that is able to be set to the desired COM model. Typically, but not necessarily always. It really depends on each app's particular requirements. -
In that kind of example, I would probably opt to use the TThread.OnTerminate event instead, eg: type TMainForm = class(TForm) private ProcessingThread: TThread; procedure EnableUI; procedure DisableUI; procedure ThreadFinished(Sender: TObject); procedure ThreadTerminated(Sender: TObject); ... end; procedure TMainForm.BtnClick(Sender: TObject); begin if Assigned(ProcessingThread) then Exit; DisableUI; try ProcessingThread := TThread.CreateAnonymousThread( procedure begin // do work here end ); ProcessingThread.OnTerminate := ThreadFinished; try ProcessingThread.Start; except FreeAndNil(ProcessingThread); raise; end; except EnableUI; end; end; procedure TMainForm.ThreadFinished(Sender: TObject); begin ProcessingThread := nil; EnableUI; end; procedure TMainForm.ThreadTerminated(Sender: TObject); begin ProcessingThread := nil; Close; end; procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin CanClose := not Assigned(ProcessingThread); if not CanClose then begin ProcessingThread.OnTerminate := ThreadTerminated; ProcessingThread.Terminate; // display a "Please wait" UI ... end; end;
-
SSL not found when using idHttp in docker image
Remy Lebeau replied to Die Holländer's topic in Indy
When loading OpenSSL, Indy checks for a whole list of different filenames, including the 4 you have shown above. The order in which that list is attempted can be influenced by setting Indy's CanLoadSymLinks and LoadSymLinksFirst settings before the libs are loaded. By default, it will attempt to load the unversioned files first, so if that is problematic (because they map to a newer unsupported version of OpenSSL) then you should turn off the CanLoadSymLinks or LoadSymLinksFirst setting so the version-specific libs are attempted first/solely. There are public IdOpenSSLSetCanLoadSymLinks() and IdOpenSSLSetLoadSymLinksFirst() functions in the IdSSLOpenSSLHeaders unit for that purpose. See https://www.indyproject.org/2018/05/04/changes-for-how-openssl-is-loaded-on-nix-platforms/ -
SSL not found when using idHttp in docker image
Remy Lebeau replied to Die Holländer's topic in Indy
What does Indy's IdSSLOpenSSLHeaders.WhichFailedToLoad() function return after the error has occurred? Indy's default TIdSSLIOHandlerSocketOpenSSL component supports up to OpenSSL 1.0.2, it cannot use OpenSSL 1.1.x+, so you need to use this work-in-progress SSLIOHandler instead for newer OpenSSL versions. -
You are probably thinking of the TIdTCPStream class. You can assign a target TIdTCPConnection to it, and then pass it to the IOHandler.ReadStream() method of a source TIdTCPConnection. You can then tell ReadStream() to either read a specific number of bytes, or to read endlessly until the source socket disconnects. Any bytes read in from the source will be written out to the target.
-
Why does CoInitializeEx returns 1 or $80010106 ?
Remy Lebeau replied to maXcomX's topic in Windows API
Can you be more specific? -
Why does CoInitializeEx returns 1 or $80010106 ?
Remy Lebeau replied to maXcomX's topic in Windows API
Per https://stackoverflow.com/a/20019023/65863: And also: https://learn.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-oleinitialize So, there you go. If your project uses the ComObj unit, it will call CoInitialize/Ex() when Vcl.Forms.TApplication.Initialize() is called, which won't matter since the constructor of Vcl.Forms.TApplication will have already called OleInitialize() beforehand, which calls CoInitializeEx(): constructor TApplication.Create(AOwner: TComponent); var ... begin inherited Create(AOwner); if not IsLibrary then FNeedToUninitialize := Succeeded(OleInitialize(nil)); ... end; -
Why does CoInitializeEx returns 1 or $80010106 ?
Remy Lebeau replied to maXcomX's topic in Windows API
That is S_FALSE. That is RPC_E_CHANGED_MODE. Per the documentation: https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializeex This means that you are calling CoInitializeEx() on a thread that has already called CoInitialize/Ex() successfully, where S_FALSE means you are trying to set the same concurrency model that has already been assigned to the thread, whereas RPC_E_CHANGED_MODE means you are specifying a concurrency model that is not compatible with the thread's current concurrency model. For instance, are you calling CoInitializeEx() in the main UI thread? The RTL's System.Win.ComObj unit initializes COM in the main UI thread during program startup, using the global CoInitFlags variable to decide whether to use CoInitialize() or CoInitializeEx(). -
1 is S_FALSE. Per the documentation: https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializeex This means that you are calling CoInitializeEx() on a thread that has already called CoInitialize/Ex() successfully, and you are specifying the same concurrency model that has already been assigned to the thread. For instance, are you calling CoInitializeEx() in the main UI thread? The RTL's System.Win.ComObj unit initializes COM in the main UI thread during program startup, using the global CoInitFlags variable to decide whether to use CoInitialize() or CoInitializeEx().
-
Best way to embed a binary structure so it is linked/compiled in
Remy Lebeau replied to alank2's topic in General Help
Put the raw data into a separate binary file, and then add an .rc script to your project (or use the Resources and Images dialog) to compile the data file as an RCDATA resource in your final executable's resources. Then, in your code, you can use a TResourceStream whenever you want to access the resource data at runtime. See Resource Files Support (just ignore the part about using a Multi-Device project, this works in a VCL project, too). -
No recent updates, still pending review: https://github.com/indySockets/indy/pull/299 Correct. It is just built on top of Indy. Their website says: https://www.esegece.com/products/indy/features-overview I agree. As already pointed out, Indy's license does allow them to sell their derivative work. However, I don't like that their website is advertising their product as "Indy", it really should be advertised as "sgcIndy" instead. @esegece I would really appreciate it if you changed the product naming on your website accordingly, and actually explain on it what your product actually is. It is not Indy itself, it is a modification/addon to Indy. Also, your "Quick Start" guide suggests that you have made custom modifications to Indy's default OpenSSL SSLIOHandler, rather than introducing a new SSLIOHandler, as the pending pull request is doing. I would be interested in knowing what kind of modifications you have made to enable that in the default SSLIOHandler, given the extensive and breaking API changes that were introduced in OpenSSL 1.1.x.
-
Can to elaborate more?
-
Beginner to Delphi. Have no idea what I'm doing wrong here
Remy Lebeau replied to Willicious's topic in Delphi IDE and APIs
You forgot to add an OnKeyUp event handler to reset the direction. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin case Key of Ord('W'): fdirection := diup; Ord('A'): fDirection := diLeft; Ord('D'): fDirection := diRight; Ord('X'): fDirection := diDown; end; end; procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); begin case Key of Ord('W'), Ord('A'), Ord('D'), Ord('X'): fDirection := diNone; end; end; -
Protected TCP/IP Client/Server connection
Remy Lebeau replied to shineworld's topic in Network, Cloud and Web
That is exactly what TLS is meant for. It handles ALL of that stuff for you. Clients can validate that they are connected to the official server and not another server (especially a man-in-the-middle). And the server can validate that only trusted clients are connecting to it. And ALL communication is encrypted back and forth. -
OpenSSL is an external 3rd party library written in C, so of course it can't use a Delphi unit. Also, OpenSSL uses 2 lib binaries that are LINKED together when they are compiled, the filenames are not hard-coded in code, they are established during the compile/link stages (ie, 1 lib statically imports functions from the other lib), hence why you would have to recompile OpenSSL in order to change its lib filenames.
-
Create() is just a class constructor. In runs in the context of whatever thread calls it, like any other class method. And it does not create any OS window, that happens later. For VCL, all TWinControl-derived UI controls have their own window handle that is created by calling into the OS, and all TGraphicControl-derived UI controls use their parent TWinControl's window. The creation of that window happens in the context of whatever thread is first to access the window. IOW the control creates its OS window on an as-needed basis. However, once it has been created, it is bound to the thread context that created it. There is no OS thread transferring ownership to a Delphi thread. So, for example, if you create a VCL UI control in the context of the main thread, but the first use of its window is in the context of a worker thread, then the window is bound to the worker thread, not to the main thread. As such, only the worker thread can receive and dispatch messages for the window, even though the Delphi object that owns the window is in the main thread. For FMX, by default child UI controls do not have their own OS windows at all, only the parent TForm has an OS window. Child UI controls are designed to act upon, and render themselves inside of, the parent Form's window. However, this is complicated in recent Delphi versions by the introduction of the ControlType property on various controls, like TEdit. In which case, it is possible for some child UI controls to have a native OS window of their own, which runs on top of the parent Form's window, similar to VCL controls.
-
That would require recompiling the OpenSSL libs so could can still find each other using the new filenames. I think this may be device-specific. I've had some reports that OpenSSL libs couldn't be loaded if they were using the same filenames as the BoringSSL libs, and at the time (I don't know if this is still true) BoringSSL did use the original OpenSSL filenames. And I've had some reports of users successfully loading OpenSSL libs even on BoringSSL systems. The OpenSSL filenames are hard-coded in Indy. I would have to add a new API to the IdSSLOpenSSLHeaders unit to allow loading of user-defined filenames.
-
It used to, but Google dropped support for OpenSSL in favor of BoringSSL (their own customized fork of OpenSSL) in Android 6. See this answer on StackOverflow, which I posted about this issue at the time.
-
WEB Standalone console APP “Indy http” in production ?
Remy Lebeau replied to borni69's topic in Network, Cloud and Web
Why are you using MaxInt for the timeout, and not simply using Infinite instead? Then you can get rid of the while loop. // now the server is processing requests // wait for terminate signal MyEvent.WaitFor(Infinite); -
How to draw a semitransparent ellipse on a canvas?
Remy Lebeau replied to vshvetsov's topic in General Help
TColor is an enum representing an integer, and so it is subject to endian. TRGBQuad is not. You should be using the ColorToRGB() function to convert an TColor value into an integer value, and then using the Get(R|G|B)Value() functions to obtain the individual R/G/B values of that integer. The PremultiplyAlpha() function is operating on a bitmap's raw R/G/B pixel bytes directly, it is not going through TColor at all. -
Correct, since FMX is cross-platform, but you are trying to use platform-specific code. So, you will have to #ifdef your code for Windows, and then #include the relevant header files, in this case <windows.h> and <shlobj.h> (NOT <shlobj_core.h> directly). Also, FYI, SHGetSpecialFolderLocation() is very old, so you should be using SHGetFolderPathW() instead, or even SHGetKnownFolderPath(). That is just a warning. Ignore it, and or turn it off in the compiler settings. SHGetFolderPath() was introduced in Windows 2000. Any old compiler that doesn't recognize it is too old to support FireMonkey anyway.
-
How to register a shell property sheet for a single file type?
Remy Lebeau replied to FPiette's topic in Windows API
Just a thought - have you tried using SysInternals Process Monitor yet to see all of the Registry activity that Explorer invokes on Windows7 vs Windows 10/11 while registering the property handler and while loading the .arw file? -
How to register a shell property sheet for a single file type?
Remy Lebeau replied to FPiette's topic in Windows API
That is a very good point, I completely forgot about that! It has been a long time since I last worked with Shell Extension handlers. -
The scanner app does not need to know the local device IP just to send data to another device. It only needs to know the receiver's IP. Probably best to use DNS/mDNS or other local network discovery protocol to discover the receiver's IP dynamically at runtime. The Android server app does not need to know the local device IP just to connect to another server. And it does not need to know the local device IP to accept connections, for that matter. So, I'm still wondering why you actually need to query the device IP at all.
-
Why do you need to retrieve an Android device's IP address in the first place? What are you planning on doing with it, exactly?