Unable to load Firebird client library on Windows 10 - delphi

Tw days ago, I installed Windows 10 build 1709 16299.192 and Embarcadero Delphi 10.2.2 Tokyo.
Since I installed them, my applications can't load the Firebird client library at runtime.
If I have an exe file compiled with older Windows and Delphi 10.2.2, it works fine, but every exe file compiled with the new Windows and Delphi are not working.
If I test a connection through TFDConnection, it connects successfully, but when I run the application I get this error:
[firedac][phys][fb]-314 cannot load vendor library [c:\users\username\desktop\projectname\bin\fbclient.dll] The specified module could not be found
Hint: check it is in the PATH or application EXE directories, and has x86 bitness.
The path is correct, and the client library is for x86. The same application was working before installing Windows 10 build 1907 16299.192.
I tried DevArt UniDac and compiled as Win64, still have the same problem.
Reinstalling Windows and Delphi 10.2.2 (tested with 2 versions 25.0.28979.1978 and 25.0.29039.2004) still didn't help.
I think it's a permissions issue, but I don't know how to fix it. I gave bds.exe all permissions over all groups, but still not working.
I have only this code on my test application
procedure TForm1.FormCreate(Sender: TObject);
var
Path: string;
begin
Path := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName));
FDPhysFBDriverLink1.VendorHome := Path;
FDPhysFBDriverLink1.VendorLib := 'fbclient.dll';
FDConnection1.Params.Database := Path + 'FBDV3.0.FDB';
FDConnection1.DriverName := 'FB';
FDConnection1.Params.UserName := 'sysdba';
FDConnection1.Params.Password := 'masterke';
FDConnection1.LoginPrompt := False;
FDConnection1.Connected := True;
end;
Included Files and Folders in bin Folder:
plugins (Folder contain engine12.dll)
fbclient.dll
ib_util.dll
icudt52.dll
icudt52l.dat
icuuc52.dll

I just had to install the Microsoft Visual C++ 2010 Redistributable.
It took me hours of trying and trying many things, I couldn't find any clue what causes it, even by debugging deep into the FD sources (Delphi 10.4.2). Too bad there is no useful error message anywhere. But then I used SysInternals Process Explorer and found this dependency. Thanks to #Remy.
(Just copying msvcr100.dll didn't help in my case.)
Of course I cannot say if this would have helped here, but at least it could help many others. The symptoms were the same - it worked in the IDE (data explorer), but not in the compiled application, even though the dll was there.
By debugging I also verified that the error message asking for not only fbclient.dll, but also fbembed.dll, is not a sign of any wrong parameters: it is always looking for the second one if the first one cannot be loaded (not only if it is not found).

Related

Can't detect network drive under Debugger with Delphi 2007 on Windows 10

It is probably me being stupid, but I am having problems detecting if a network drive is up, but only when running the program in the IDE – when running the program outside of the IDE, the network drive is correctly detected. The IDE works fine on Windows 7.
While the program in question is different, I can reproduce the issue by creating a new project and adding the following into the Forms OnActivate event:
var
bRet: Boolean;
LTemp2: string;
LFreeSpace: Int64;
LTotalSpace: Int64;
begin
LTemp2 := 'T:\';
bRet := GetDiskFreeSpaceEx(PAnsiChar(LTemp2), #LFreeSpace, #LTotalSpace, nil);
ShowMessage('GetDiskFreeSpaceEx: Drive T: is up? '+BoolToStr(bRet, True));
end;
Assuming I have a networked drive T:, if I run the program in the IDE then the above always returns False, but if I run the built program from a desktop shortcut then it returns True. I get the same behaviour if I run it via a button click after the program starts. Doing DiskSize() and FindFirst() on the root directory give the same results.
It is a clean Windows 10 install, not an upgrade, with a clean install of CodeGear 2007 with all the patches applied. I have tried “Run as administrator” and all the Compatibility Modes back to Windows 7.
Am I doing something stupid?
After R. Hoek's great insight, and while it does not fully sort out the issue, it is at least enough for a workaround. By the way, at least in my case, it does not matter if I launch Delphi 2007 with "Run as administrator" or not.
I added a TOpenDialog hooked up to a button: once I run this and select a file on T: then GetLogicalDrives() works fine.
So what I now suspect is that I installed Delphi 2007 as an administrator - not sure how, but I think I will re-install everything.
Even if that does not resolve it, and since it only occurs in the IDE and not in production usage, I can add code to pop up a TOpenDialog if GetLogicalDrives() returns 4.
Weird. Thank you all very much.
By the way, one aspect of this discussion may not have been clear: Delphi 2007 was running under the user account (and it could see the network drive without problems) - it is only the program which is being debugged that cannot see the networked drive. That is why using the TOpenDialog resolved the issue (until Delphi or the computer was restarted).

Can I use Indy in Android and iOS apps? [duplicate]

I'm trying to download a file with TIdHTTP.Get in Delphi Seattle. It's an app for android and all my attempts fails. All i get it's the same error "Could not load SSL library". This is the procedure:
procedure TfrmMain.DownloadPicture(const AURL: string);
var
MeS: TMemoryStream;
cidSSL: TIdSSLIOHandlerSocketOpenSSL;
cidHTTP: TIdHTTP;
begin
cidHTTP:= TIdHTTP.Create(nil);
cidSSL:= TIdSSLIOHandlerSocketOpenSSL.Create(nil);
Mes := TMemoryStream.Create;
try
cidHTTP.ReadTimeout := 30000;
cidHTTP.IOHandler := IdSSL;
cidSSL.SSLOptions.Method := sslvSSLv3;
cidSSL.SSLOptions.Mode := sslmUnassigned;
cidSSL.StartSSL;
cidHTTP.Get(AURL, Mes);
except
on E : Exception do
begin showmessage('Error: '+E.Message);
end;
end;
Mes.Position := 0;
frmImage.Image.Bitmap.LoadFromStream(Mes);
end;
If you are NOT using Android 6 Marshmallow, OpenSSL should be working fine on Android. When you get the "could not load" error, you can call Indy's WhichFailedToLoad() function in the IdSSLOpenSSLHeaders unit to find out why OpenSSL could not be loaded. If your device does not have OpenSSL pre-installed, you can deploy the OpenSSL binaries with your app, and use Indy's IdOpenSSLSetLibPath() function to tell Indy where to load them from.
That being said, starting with Android 6 Marshmallow, Google no longer supports OpenSSL on Android. It has been replaced with a custom fork named BoringSSL, which Indy does not fully support yet (although some BoringSSL-related changes have been made to Indy after Seattle's release). So, if you are having trouble with using Indy SSL/TLS on Android 6, you can try upgrading to the latest Github snapshot to see if it helps.
BoringSSL makes some major changes to the OpenSSL API interface (dropping functions, changing data types, etc), so it is not backwards-compatible with existing OpenSSL code. But to make matters worse, BoringSSL uses the same library filenames as OpenSSL, and is pre-loaded at device startup, so it is not possible to deploy custom-built OpenSSL library binaries with your Android app. Android will simply use the pre-loaded BoringSSL binaries when the app tries to load the OpenSSL library filenames at runtime (regardless of whether you call Indy's IdOpenSSLSetLibPath() function).
Indy operates at the NDK level of Android, not the Java level, so to make Indy avoid BoringSSL would require users to either:
recompile the OpenSSL libraries with new filenames that don't conflict with BoringSSL (AFAIK no known version of this is available), and then update Indy to use those filenames.
compile the OpenSSL source code directly into their Android app. Indy is not currently setup to support static-linking of OpenSSL on any platform other than iOS, but this should be a minor change to update Indy's IdSSLOpenSSLHeaders_static unit with the relevant definitions if someone can produce viable .a files for OpenSSL on Android. I do know of at least one user attempting this route, but that user has not had success yet (errors getting the source code to fully link correctly).
switch to Android's higher-level Java-based crypto APIs. This is Google's preferred solution. But Indy does not support it at this time. Doing so would require writing a whole new set of TIdStack and TIdIOHandler classes for Android socket I/O and SSL/TLS, using JNI calls to access the Java APIs. But this has performance and threading issues that need to be dealt with.
So, there is no known viable workaround available at this time to make Indy SSL/TLS work on Android 6+.
Update: a user in the Embarcadero forums was able to find OpenSSL .so files that are compatible with Indy and work on Android 6:
https://forums.embarcadero.com/thread.jspa?threadID=211089
After many reports of my apps crashing if installed in Android 6 devices I've searched the net for some tips and the couple of needed .so compiled files, 1.02 version, added the two files to the play store deployment of my apps (assets\internal) and changed the Indy's path calling
IdOpenSSLSetLibPath(TPath.GetDocumentsPath)
in the OnCreate of my datamodule.
After those modifications of my code my Apps run perfectly on my brand new S7 with Android 6.0.1, and on all the other recent Android devices (tested using the Play Store deployment).
And now the Google warning pops up telling me that the OpsnSSL files deployed with my apps are not of the minimum required 1.02f version (or 1.01r).... and so my post in this forum.
...
Anyway you can download here the latest .so files, the ones that I deploy at this moment:
https://drive.google.com/file/d/0B7AxqW32K0oXWW9nUk9qaFpHT0k/view?usp=sharing
Another user in the same discussion also seems to have some success as well:
Ive been running on android 6 loading the .so libraries just fine for months. The new problem is we need to compile new versions of the openssl libraries. Cygwin is not working correctly to compile for me so im switching to a linux install to create them (if possible) https://wiki.openssl.org/index.php/Android#Build_the_OpenSSL_Library_2
heres a repository you can grab some current prebuilt ones https://github.com/emileb/OpenSSL-for-Android-Prebuilt.git
Update: The following (German) forum discussion provides OpenSSL 1.0.2g binaries for Android (and iOS Simulator) to registered users. They do not display the security warning in the Google Play store:
http://www.delphipraxis.net/188736-kompilierte-openssl-bibliotheken-fuer-android.html
OpenSSL 1.0.2g Android.zip
OpenSSL 1.0.2g iOS Simulator.zip
Update: the Android binaries for OpenSSL 1.0.2g are now available in the Embarcadero Attachments forum:
https://forums.embarcadero.com/thread.jspa?threadID=211147
Then, to load OpenSSL instead of BoringSSL, follow these steps:
Add the 2 .so files to your project deployment and set them to deploy to the .\assets\internal\ folder
add the System.StartupCopy unit as the first unit in your DPR's uses clause.
call IdOpenSSLSetLibPath(TPath.GetDocumentsPath) at app startup.
Update: OpenSSL 1.0.1t and 1.0.2h binaries are now in the Embarcadero Attachments forum:
https://forums.embarcadero.com/thread.jspa?threadID=211147
Update: the binaries have now been posted on Indy's Fulgan mirror:
http://indy.fulgan.com/SSL/
Update: Indy is no longer using the Fulgan mirror for hosting OpenSSL binaries. They are now in their own GitHub repo:
https://www.indyproject.org/2020/06/16/openssl-binaries-moved-to-github/
https://github.com/IndySockets/OpenSSL-Binaries
Just swap the TidHTTP component for TNetHTTPClient
Probably you have a new OpenSSL library and an older Indy version. Check this:
Indy 10 - IdSMTP.Connect raising "Could not load SSL library."
There are versions for 32/64 bits.
Make sure you have the correct version of the files.
See this FTP for correct version.
Other mirror for download binaries here.
I use this code and this works:
procedure TfPrecos.GetImageByUrl(URL: string);
var
Strm: TMemoryStream;
vIdHTTP: TIdHTTP;
cidSSL: TIdSSLIOHandlerSocketOpenSSL;
begin
IdOpenSSLSetLibPath(TPath.GetDocumentsPath); //libcrypto.so and libssl.so in ./assets/internal
vIdHTTP.IOHandler := cidSSL;
cidSSL.SSLOptions.Method := sslvSSLv23; // version 2.3
cidSSL.SSLOptions.Mode := sslmUnassigned;
cidSSL.StartSSL;
try
vIdHTTP.Get(URL, Strm);
if (Strm.Size > 0) then
begin
Strm.Position := 0;
try
Image1.Bitmap.LoadFromStream(Strm);
finally
end;
end;
finally
Strm.DisposeOf;
vIdHTTP.DisposeOf;
end;
end;

Recommended PE header settings for Delphi 7 application running on terminal server?

While investigating external exception C0000006 errors reported by some users running a Delphi 7 application on a Windows 2008 terminal server, I found several questions on this and related issues already. I'm wondering if anyone has a definitive list of these settings that would be appropriate for a standard Delphi 7 database application running on a terminal server.
The questions I've looked at include:
External exception C0000006
Delphi - invalid stream format errors on run
Are there risks associated with IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP or IMAGE_FILE_NET_RUN_FROM_SWAP?
Delphi TOpenDialog hangs in windows 2008 when run as remote desktop application
Delphi 2007 : How to Set TSAWARE?
How can I force Delphi 7 to load the whole executable?
So far from reading these I'm thinking I should add the following to the .dpr file:
const
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = $8000;
// Following are already defined in D7's Windows.pas
IMAGE_FILE_RELOCS_STRIPPED = $0001;
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;
{$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE}
{$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED
or IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
or IMAGE_FILE_NET_RUN_FROM_SWAP}
Edit: Stripping the relocation section is probably unnecessary, so here's the revised version:
const
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = $8000;
// Following are already defined in D7's Windows.pas
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = $0400;
IMAGE_FILE_NET_RUN_FROM_SWAP = $0800;
{$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE}
{$SetPEFlags IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
or IMAGE_FILE_NET_RUN_FROM_SWAP}
{$SetPEOptFlags IMAGE_DLLCHARACTERISTICS_TERMINAL_ SERVER_AWARE}
{$SetPEFlags IMAGE_FILE_RELOCS_STRIPPED
or IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
or IMAGE_FILE_NET_RUN_FROM_SWAP}
is fine for your needs. I suspect that IMAGE_FILE_NET_RUN_FROM_SWAP is what you need to deal with C0000006. That error typically happens when you run from a network drive and the drive is not able to satisfy a page in request for the executable.
The other PE flags are fine for you either way. I would have it as you do.
As for whether or not IMAGE_DLLCHARACTERISTICS_TERMINAL_ SERVER_AWARE is right, only you know. Does you app meet the requiresments to be considered a non-legacy app for terminal services, as documented on MSDN? If so, use IMAGE_DLLCHARACTERISTICS_TERMINAL_ SERVER_AWARE.

WMDropFiles problem on win7

I've implemented the following procedure and it works properly when I compile it on my computer running windows vista, computer #1. If I share the created .exe file to another computer running win7, computer #2, it runs fine aswell. The problem is when I let the computer #2 compile it, it wont simply recognize that anything's dropped on the application. There's no response at all in this code. It's built and compiled without errors or warnings.
I've been searching the net for a while without finding anything that explains why this happens or someone else with this problem.
Both computers use Delphi 2010 with the same components installed.
Is this the way to go to allow the user to drop files onto the application? If not, how should it be done nowdays?
Any ideas why it works when it's compiled on computer #1 but not computer #2? (The program works properly on both computers when compiled on computer #1)
Any help or comment is highly appreciated.
procedure TfMainForm.WMDROPFILES(var msg: TWMDropFiles);
const
MaxLength = 255;
var
nFiles : integer;
i : integer;
fileName : array [0..MaxLength] of char;
fileNames : TStringArray;
begin
// Get number of files dropped
nFiles := DragQueryFile(msg.Drop, $FFFFFFFF, fileName, MaxLength);
// Get filenames
SetLength(fileNames, nFiles);
for i := 0 to nFiles - 1 do begin
DragQueryFile(msg.Drop, i, fileName, MaxLength);
fileNames[i] := fileName;
end;
// Add files
projectHandler.addFiles(fileNames);
//release memory
DragFinish(msg.Drop);
end;
I'm going to take a wild guess that if you are running from within the IDE on computer #2. I bet that if you compile on computer #2 but start the executable from explorer rather than from the IDE, it works. The final piece of the jigsaw is that I bet you are running your IDE on computer #2 as administrator.
On Vista and Windows 7 you can't send messages to a process with a higher integrity level. If your process is being run as administrator then it will have a higher integrity level than explorer and so won't accept the dropped files.
If my guess is correct I recommend that you stop running Delphi as administrator, it doesn't need this.
As for whether or not WM_DROPFILES is a reasonable approach, I see no problems with using it.
At http://www.web-developer.de/content/download/7387/137496/file/Listings.zip you can find an example written using Delphi XE (compiles with D2010 as well). The subfolder "2_WmDropFiles" contains a project "WmDropFiles.dpr" that shows how to an app that runs elevated can receive files from an app which does not run elevated. The comments etc. are in German, so please use Google translate when in doubt.
Hope this helps,
Olaf

Microsoft speech api 5.1 GetVoices returns voices that don't exist on Windows 7

I'm migrating from XP to Windows 7 64 bit. My app which I compiled on my XP machine works properly on XP. However when I run the exe on my W7 machine, the list of voices returned by GetVoices is as follows:
Microsoft Anna
Microsoft Mary
Microsoft Mike
Sample TTS Voice.
Checking the W7 Speech Properties dialog shows that only Microsoft Anna is loaded on the machine. Checking the registry at HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Speech/Voices confirms this.
Recompiling my app on my new Windows 7 development machine creates an exe that duplicate the above behavior. (The XP compiled code and the W7 compiled code reproduce the same error when executed under W7)
I'm developing in Delphi 7 on Windows 7 64 bit and I'm using the Microsoft Speech Object Library (Version 5.4) (note: 5.4 is what shows in the Import Type Library list).
I installed SpeechSDK51.exe onto my W7 machine. This came from:
http://www.microsoft.com/downloads/details.aspx?FamilyID=5e86ec97-40a7-453f-b0ee-6583171b4530&DisplayLang=en
The following code produces the list of 4 voices on Windows 7 even though there should only be one voice:
procedure TForm1.FormCreate(Sender: TObject);
var
i: integer;
SOToken: ISpeechObjectToken;
SOTokens: ISpeechObjectTokens;
begin
cbbVoices.Clear;
SOTokens := SpVoice1.GetVoices('', '');
for i := 0 to SOTokens.Count - 1 do begin
SOToken := SOTokens.Item(i);
cbbVoices.AddItem( SOToken.GetDescription(0), TObject(SOToken) );
SOToken._AddRef;
end;
end;
Any suggestions on how to deal with this problem?
thanks,
shawnh
Microsoft Anna is the only 64-bit voice you have
the other ones are 32-bit engines.
Your system can only use the 64-bit engine(Anna) so only this one can be selected in the panel. But the other ones are installed as well. If you open this file: /%Windows%/SystemWOW64/Speech/SpeechUX/sapi.cpl you will see a dialog similar to the one for the control panel but now you will be able to select any one of those voices as the standart voice.
Unconfirmed yet, but I think that Microsoft Sam, Microsoft Mike and Microsoft Mary do not work on Windows Vista and later.
I guess you could install them with the 5.1 SDK, so they are reported back when you query the voices, but being possibly not compatible with the 5.4 engine, they cannot be used.
You may want to filter GetVoices with the EngineProperties attribute to limit what is returned.
Disclaimer: all this is untested/guesswork/doc-reading....

Resources