-
Content Count
2914 -
Joined
-
Last visited
-
Days Won
130
Everything posted by Remy Lebeau
-
Calling a Form's constructor directly will just create the object immediately, and lets you specify the desired Owner. That is al it does. In VCL, there is not much difference to that. Calling TApplication.CreateForm() merely creates the specified class type, hard-coding the TApplication object as its Owner. But it also sets the TApplication.MainForm if it is not already assigned and a TForm is being created. Calling Create() directly does not do that. In FMX, there is little bit more of a difference. It also creates requested objects with TApplication as the Owner, but it also caches those requests until TApplication.CreateRealForms() is called, at which time all requested (and subsequent) objects are then physically created. It also does not set the TApplication.MainForm at all, there is a separate TApplication.CreateMainForm() call for that.
-
Getting an Object Instance Name when ancestor is of TComponent
Remy Lebeau replied to bravesofts's topic in Algorithms, Data Structures and Class Design
Self.Name will never work in this situation, since it has not been assigned a value yet while the constructor is still running. The Name property is assigned a value after the constructor exits, whether that be at design-time or run-time. The only way around that is to pass in the desired value as a parameter to the constructor (but that will obviously not work for objects created at desing-time), eg: constructor TConcrete.New(aValue: string; aName: string; aOwner: TComponent); begin inherited Create(aOwner); Self.Name := aName; // <-- fReadOnlyProperty := aValue + Self.ClassName +' ] '+ sLineBreak + 'Object Instance Name is: [' + aName +' ]'; end; -
FYI: D11 SMTP IdSSLIOHandlerSocketOpenSSL win32
Remy Lebeau replied to Rinzwind's topic in Delphi IDE and APIs
There are no "Indy DLLs". If you mean the "OpenSSL DLLs", I wouldn't expect Embarcadero to distribute them, you have to download them yourself from online. Indy has a GitHub repo for that purpose: https://github.com/IndySockets/OpenSSL-Binaries -
♫ Into the Unknooo-ooo-ooo-own... ♫ (sorry, couldn't help myself )
-
why shortstring in Delphi cannot used in our Programs using New IDE?
Remy Lebeau replied to bravesofts's topic in Algorithms, Data Structures and Class Design
That notice has been in the documentation since XE4. All ANSI types (P/AnsiChar, AnsiString/(N), ShortString) were disabled in the NEXTGEN mobile compilers in XE3. Under NEXTGEN, UTF8String and RawByteString were re-enabled in 10.1 Berlin, and then the rest of the ANSI types were re-enabled in 10.4 Sydney when NEXTGEN was dropped completely so mobile platforms now match desktop platforms in terms of language features. Looks like the ShortString documentation has not been updated yet to reflect that. Yes. Only in XE3 through 10.3. In 10.4 onward, ShortString can be used on mobile. No. Because ALL ANSI types were initially eliminated, as mobile platforms are Unicode-based. Then the types slowly started being re-introduced as needs arose, until eventually Embarcadero decided that having separate compiler architectures just wasn't working out. Hardly. -
<ARG!> I just now noticed that you are connecting to Office 365 on port 993. That is an IMPLICIT TLS port. But, you are not using any TLS settings on your TIdIMAP4 at all! Rather than assigning a TIdIOHandlerStack component to the TIdIMAP4.IOHandler property, you need to assign a TIdSSLIOHandlerSocketBase-derived component instead, like TIdSSLIOHandlerSocketOpenSSL (TIdSSLIOHandlerSocketBase derives from TIdIOHandlerStack and thus also has the TransparentProxy property). And then set the TIdIMAP4.UseTLS property to utUseImplicitTLS.
-
Using a memory-mapped file of a Delphi app in C#
Remy Lebeau replied to jaenicke's topic in Delphi IDE and APIs
As you can see in the source code I linked to earlier, that simply calls this: return OpenExisting(mapName, MemoryMappedFileRights.ReadWrite, HandleInheritability.None); That simply calls this: return OpenExisting(mapName, desiredAccessRights, HandleInheritability.None); Which ultimately just calls OpenFileMapping() with the specified name, access/inheritance rights as-is, and then wraps the HANDLE in a MemoryMappedFile object. -
Delphi 11 Windows XP compatibility tweak
Remy Lebeau replied to mitzi's topic in RTL and Delphi Object Pascal
The problem with using QueryPerformanceCounter()/QueryPerformanceFrequency() is that it is not consistent on all systems, especially on multi-core systems, or systems without a stable TSC (Mozilla had to write code to work around that for https://bugzilla.mozilla.org/show_bug.cgi?id=784859). That is the main reason Indy stopped using QPC/QPF over a decade ago for the implementation of its Ticks/64() functions, now favoring GetTickCount64() instead (use of QPC/QPF can be re-enabed with a compiler define). -
Delphi 11 Windows XP compatibility tweak
Remy Lebeau replied to mitzi's topic in RTL and Delphi Object Pascal
From RSP-35459: -
Delphi 11 Windows XP compatibility tweak
Remy Lebeau replied to mitzi's topic in RTL and Delphi Object Pascal
I'm not sure this can be solved truly lock-free. Even if you make the low-part of the counter thread-local to avoid a lock, you still have the high-part of the counter to deal with to track rollovers, and that will have to be protected from concurrent access, either with a lock, or atomic access, etc. I really don't know if that will work or not. I think the entire counter needs to be global, so that new threads will start with the latest accumulated value properly. I'm thinking something like the following, based on ideas I've seen in other implementations: var TickCount64: UInt64 = 0; function GetTickCount64Emu: UInt64; var OrigValue, NewValue, TmpValue: UInt64; CurrTicks: UInt32; begin OrigValue := TInterlocked.Read(TickCount64); repeat CurrTicks := Windows.GetTickCount; NewValue := (OldValue and $FFFFFFFF00000000) + CurrTicks; if CurrTicks < UInt32(OrigValue and $FFFFFFFF) then Inc(NewValue, $100000000); TmpValue := TInterlocked.CompareExchange(TickCount64, NewValue, OrigValue); if OrigValue = TmpValue then Break; if TmpValue > NewValue then Exit(TmpValue); OrigValue := TmpValue; until False; Result := NewValue; end; Yes, that would be required no matter what. Oh yeah, I forgot about that. Well, then just call GetProcAddress() manually at startup (or first call) instead of using 'delayed'. This is what Indy does. -
Will getit work for C++ Builder
Remy Lebeau replied to alank2's topic in ICS - Internet Component Suite
Most likely, either Int8 or CSIDL_DESKTOP has already been #define'd to a value earlier, and that define is then interfering with these declarations. -
Delphi 11 Windows XP compatibility tweak
Remy Lebeau replied to mitzi's topic in RTL and Delphi Object Pascal
What about (in a loop) using TInterlocked to Read() the counter into a local variable, update the two halves of that variable as needed, and then CompareExchange() the result back into the counter until it takes effect for multi-threaded access? Looking at some other apps (Mozilla, etc), that is how they solved this problem years ago. How? Without using thread-local variables? Would still need a locking mechanism to avoid races across threads. Why? -
Delphi 11 Windows XP compatibility tweak
Remy Lebeau replied to mitzi's topic in RTL and Delphi Object Pascal
Here is an implementation of GetTickCount64() for Win2K and XP, it would be trivial to use the native GetTickCount64() on Vista+ and fallback to this version on pre-Vista systems: https://titanwolf.org/Network/Articles/Article?AID=7398e4d3-ddc2-42b0-ae21-d52654fe9287#gsc.tab=0 -
Look at the actual declaration more carefully: class procedure MessageDialog( const AMessage: string; const ADialogType: TMsgDlgType; const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn; const AHelpCtx: THelpContext; const ACloseDialogProc: TInputCloseDialogProc); The 3rd parameter is a TMsgDlgButtons, which is a Set of TMsgDlgBtn. But you were originally trying to pass a single TMsgDlgBtn. Also, the 5th parameter is a THelpContext, which is an integer, not a pointer. So, you can't pass nil to it. Try this: TDialogService.MessageDialog( 'You want to ........ ', TMsgDlgType.mtConfirmation, mbYesNo, // or [TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo] TMsgDlgBtn.mbNo, 0, procedure(const aResult: TModalResult) begin ... end );
-
WinInet API 4095 How can I remove this limit?
Remy Lebeau replied to Turan Can's topic in Windows API
I can't answer that. I see nothing in your code that would limit the size of the download. But, I can address other problems I see with your code. For one thing, you are only downloading 11 bytes at a time, why so small a buffer? That is pretty inefficient for a network transfer. Also, when you are trying to decode the buffer, you are converting from AnsiChar[] to String, and then copying BufferLen characters. The conversion to String is wrong, as you don't take the BufferLen into account during that conversion. And there is no guarantee that the number of bytes in the buffer is the same as the number of characters in the String. You shouldn't even be using Copy() in this manner at all - use TEncoding.UTF.GetString() instead, which lets you pass in a byte array, starting index, and byte count. But most importantly, you simply can't UTF8-decode arbitrary byte buffers while you are downloading them. You should download all of the bytes first, then decode them as a whole. Otherwise, if you really want to decode on the fly, you must take codepoint boundaries into account properly, decoding only complete byte sequences, and saving incomplete sequences for future iterations to complete and decode. Otherwise you risk corrupting the decoded data. And all of this assumes the data is even encoded in UTF-8 to begin with, which your code is not checking for by looking at the HTTP Content-Type response header or the body content (in case of a <meta> charset tag in HTML, etc). -
Without seeing a trace log of what's going on over the wire, I honestly could not tell you what is going on. Can you get a Wireshark capture of the connect attempt?
-
Using a memory-mapped file of a Delphi app in C#
Remy Lebeau replied to jaenicke's topic in Delphi IDE and APIs
What is the actual value of MMFName on both sides? What error does OpenExisting() report when it fails? Is that call actually succeeding or failing? Also, why are you hard-coding $FFFFFFFF instead of using the INVALID_HANDLE_VALUE constant, like the documentation says to use? Are you compiling for 32bit or 64bit? For 64bit, $FFFFFFFF extended to $00000000FFFFFFFF would be the wrong value to use, it would need to be $FFFFFFFFFFFFFFFF instead. I don't think that is going to make a difference, since MemoryMappedFile.OpenExisting() just calls the Win32 OpenFileMapping() API (you can see the source code for yourself at https://referencesource.microsoft.com/#system.core/System/IO/MemoryMappedFiles/MemoryMappedFile.cs) Not enough information to diagnose that.. -
No, it was introduced in XE2.
-
I can't answer that. There simply has not been enough information provided yet to diagnose the root cause. You are just going to have to continue debugging deeper.
-
Did you do what Twilio said to do? Did you verify the TLS version and ciphers being used by your server during a failed connection? Have you tried sniffing the TLS handshake with Wireshark to see what is actually going on inside of it? The only time I have ever seen that happen is when OpenSSL decides to reject a handshake and just closes the TCP connection abruptly without first sending a TLS alert to explain why it is being rejected. That usually implies that something in the handshake is corrupted or incorrect, and OpenSSL is just being cautious about sending anything, but that is not always the case. I doubt it, since this is not really an Indy issue, it is more of an OpenSSL TLS issue, but whether it is on the client side or the server side is still TBD.
-
https://devblogs.microsoft.com/oldnewthing/20091125-00/?p=15923 https://devblogs.microsoft.com/oldnewthing/20090223-00/?p=19063 https://stackoverflow.com/a/14018468/65863
-
Technically, when double-clicking on a file, Explorer will ask the Shell to invoke the file's default action, and the Shell will execute the "open" action if that is the default action. Sure, this may be the case in 99% of the cases, but there is always that 1% that will be different. Double-clicking on a file, and calling ShellExecute/Ex("open") on the file, are NOT the same thing, even if they usually end up performing the same action on most systems, But they are still logically different operations.
-
Technically, the OP asked how to execute a specific command, so shouldn't be using ShellExecute/Ex() at all. Double-clicking a file in Explorer executes the default action. And 'open' is not always the default action. It depends on the file extension's actual registration in the Registry, whether the user or 3rd-party apps have customized it, etc (for instance, on my system, the default action of a PDF file is to pass the file to AVG for scanning before then opening it). Which is incorrect, because that is not what Explorer does. Maybe on YOUR system, perhaps. Not 100% guaranteed on every other system.
-
The correct way to invoke the default action is to set the verb parameter to nil, not 'open'.