-
Content Count
3001 -
Joined
-
Last visited
-
Days Won
135
Everything posted by Remy Lebeau
-
Changes in System.sysutils.pas were not reflecting in other unit in Delphi 11
Remy Lebeau replied to sp0987's topic in General Help
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. -
Changes in System.sysutils.pas were not reflecting in other unit in Delphi 11
Remy Lebeau replied to sp0987's topic in General Help
Yes. 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. Yes. -
"EIdSocketError" on S3 file upload - Delphi 7
Remy Lebeau replied to adeptusgb's topic in Network, Cloud and Web
Then you should have gotten an exception like EIdOSSLCouldNotLoadSSLLibrary from TIdHTTP when it failed to load the necessary TLS functions from the DLLs. -
"EIdSocketError" on S3 file upload - Delphi 7
Remy Lebeau replied to adeptusgb's topic in Network, Cloud and Web
url should be SignedURL instead. Is it an actual EAccessViolation, or some other exception? I see nothing in the code you have shown that should be causing an EAccessViolation. What is the complete error message? There should be more detail about the exact socket error that actually occurred. Sure, since you are disabling use of TLS. You can't connect to an HTTPS url without TLS. 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? 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? -
Changes in System.sysutils.pas were not reflecting in other unit in Delphi 11
Remy Lebeau replied to sp0987's topic in General Help
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. -
How I can know the procedure that was executed before another procedure ?
Remy Lebeau replied to William23668's topic in Delphi IDE and APIs
Are you compiling your project in Release mode instead of Debug mode? Or with debug info disabled? Have you tried doing a diff between your project file and a working project file? -
TProgressBar (and by extension, the underlying Win32 control) has never had an option to display text. That would require subclassing the ProgressBar to augment its drawing manually.
-
NULL iterators in C++ Builder - 32 bit vs. 64 bit
Remy Lebeau replied to Arvid P.'s topic in General Help
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()); } -
crNo DOES map to a system cursor - IDC_NO: Why it is not transparent, who knows. Ask Microsoft.
-
I think you mean a design-time package. 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.
-
NULL iterators in C++ Builder - 32 bit vs. 64 bit
Remy Lebeau replied to Arvid P.'s topic in General Help
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; } -
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.
-
Just because you are on a budget doesn't mean you should use outdated tools. Especially tools that can be obtained for free. 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. Is the client creating a new connection for each poll? Or reusing connections? 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. Hard to say without seeing your actual code to see why it is not shutting down correctly. Possibly. Again, hard to say without knowing the root cause first. Define "safely". Is there a particular problem you are thinking of? Known issues are documented in the Update instructions, ie: https://github.com/IndySockets/Indy/wiki/Updating-Indy#delphicbuilderradstudio-101-berlin-and-later
-
memory; Memory not freed in Linux but freed in Windows
Remy Lebeau replied to michel.seicon's topic in Cross-platform
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. You should consider re-writing your code to make better use of memory buffers so they are (re-)allocated and freed less often. That is not true. Memory management and fragmentation are important issues to be aware of on Windows too, or any OS for that matter. -
File opening error C++ builder CE trivial program
Remy Lebeau replied to BruceV's topic in General Help
You probably need to recreate the project and make sure the VCL library is enabled. 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. -
Waiting for anonymous methods to complete
Remy Lebeau replied to brk303's topic in RTL and Delphi Object Pascal
You have a race condition. You are incrementing the counter at the point where the work is actually performed, but if the work is merely queued but the work thread hasn't actually started the work yet, then the counter may not have been incremented yet by the time you compare it in your destructor. You need to increment the counter at the point where the work is being queued, not where it is acted on. You didn't say which platform(s) you are targeting, On Windows for instance, a better strategy would be to put the thread's handles into an array, and then you can use (Msg)WaitForMultipleObjects() to wait for the handles to be signaled when the threads are fully terminated. However, you mention anonymous threads, so be aware that TThread.CreateAnonymousThread() sets TThread.FreeOnTerminate=true, which doesn't mix well with waiting on thread handles. So you would have to manually set FreeOnTerminate=false when starting the anonymous threads, and then free the threads yourself when they are finished running. -
NULL iterators in C++ Builder - 32 bit vs. 64 bit
Remy Lebeau replied to Arvid P.'s topic in General Help
Can you show the actual code? Standard iterators are not initializable/comparable with NULL values. So your code is likely wrong to begin with and just happened to work before due to implementation details of the old standard library, but the new standard library is exposing your bugs. You need to fix your buggy code to use iterators correctly. But it's hard to explain what you need to change until we see what you are actually doing. -
TCP Port Check with timeout
Remy Lebeau replied to chmichael's topic in ICS - Internet Component Suite
You are leaking the socket handle if connect() fails. You have to close the handle if socket() succeeds, regardless of whether connect() succeeds. You can't reduce (or even set) the timeout on a blocking connect(). You have to use a non-blocking connect() and then use select() or equivalent to implement the timeout. AFAIK, you can't disable SACK on a per-socket basis. You have to use the Registry or command-line netsh utility to disable it globally: https://superuser.com/questions/1808254/how-to-disable-tcp-sack-in-windows-xp https://www.linkedin.com/advice/3/how-can-tcp-selective-acknowledgment-sack-improve-heatc -
The standard FMX TMemo simply does not support HTML (or even basic text formatting in general). You will have to use a 3rd party control (or make your own from scratch) to display rich/formatted text.
-
File opening error C++ builder CE trivial program
Remy Lebeau replied to BruceV's topic in General Help
The C++ standard file library really sucks what it comes to error reporting. I would suggest using TFileStream or even CreateFile() directly to get better details about what the actual failure is. On a side note: kbhit() is a really old-school Borland function, it is not standard in either C or C++. Consider using C++'s standard std::cin.get() method instead. Try this: #include <iostream> #include <memory> #include <System.SysUtils.hpp> #include <System.Classes.hpp> int _tmain(int argc, _TCHAR* argv[]) { try { auto ifs = std::make_unique<TFileStream>(_D("C:\\Junk\\testfile.txt"), fmOpenRead); std::cout << "Opened OK\n"; } catch (const Sysutils::Exception &e) { std::wcout << L"Can't open input file. Error: " << e.Message.c_str() << "\n"; std::cin.get(); return 1; } std::cin.get(); return 0; } Or: #include <iostream> #include <windows.h> int _tmain(int argc, _TCHAR* argv[]) { HANDLE hFile = CreateFileW(L"C:\\Junk\\testfile.txt", GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); if (hFile == INVALID_HANDLE_VALUE) { DWORD dwError = GetLastError(); cout << "Can't open input file. Error: " << dwError << "\n"; std::cin.get(); return 1; } std::cout << "Opened OK\n"; CloseHandle(hFile); std::cin.get(); return 0; } -
How to write several SetAs...Array procedures ?
Remy Lebeau replied to RayTmsk's topic in RTL and Delphi Object Pascal
For example: procedure TDataField.SetAsAnyArray<T>(SourceItems: TArray<T>); begin case GetTypeKind(T) of tkInteger: begin ... end; tkUString: begin ... end; tkFloat: begin ... end; tkRecord: begin if TypeInfo(T) <> TypeInfo(TGuid) then raise ...; ... end; else raise ...; end; end; -
How to write several SetAs...Array procedures ?
Remy Lebeau replied to RayTmsk's topic in RTL and Delphi Object Pascal
You can use a Generic so you have only 1 method to declare and implement which can accept multiple types as input, eg: procedure TDataField.SetAsAnyArray<T>(SourceItems: TArray<T>); But, it looks like you have different data members for each array type, so you would have to use RTTI to detect the actual type used for T and write different code branches to handle each type that you want T to accept. That's not much better than just writing a separate method for each type of T. -
At this time, TIdHTTP does not support compressing requests, only decompressing responses. You would have to manually compress your post stream yourself and then set the TIdHTTP.Request.ContentEncoding header accordingly.
-
TCP Port Check with timeout
Remy Lebeau replied to chmichael's topic in ICS - Internet Component Suite
DNS lookups and connect attempts are two different things. I don't think you can do non-blocking DNS lookups using the standard hostbyname()/getaddrinfo() APIs that most people's socket code uses. You would have to use platform-specific APIs (ie, like DnsQueryEx() on Windows), or send manual DNS queries over non-blocking sockets. A connect() timeout can be implemented by just using a non-blocking socket and close() the socket after the timeout elapses. If it uses a thread internally, that is just an implementation detail of the OS, but that shouldn't block the app from being able to move on. -
TCP Port Check with timeout
Remy Lebeau replied to chmichael's topic in ICS - Internet Component Suite
Why TIcsIpStrmLog and not TSslWSocket directly? Are you saying that ICS does not support connect timeouts on TCP sockets at all? Or just that the TIcsIpStrmLog component specifically does not support this? In general, there are ways to implement a connect timeout on a TCP socket - namely: by using a non-blocking socket with select() or (e)poll() for the timeout. by aborting the socket from another thread. I would be surprised if ICS does not use the first one.