From 7342cccbb5f9a83eb909a158c089979caee4084d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Salvador=20D=C3=ADaz=20Fau?= Date: Sun, 2 Sep 2018 13:11:43 +0200 Subject: [PATCH] Added more error information to TCefApplication.CheckCEFLibrary TCefApplication.CheckCEFLibrary now shows the binaries version and it also checks that the DLL and the application are compiled for the same architecture. --- source/uCEFApplication.pas | 63 ++++++++++++++++++++++++++++++- source/uCEFConstants.pas | 12 ++++++ source/uCEFMiscFunctions.pas | 73 ++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 2 deletions(-) diff --git a/source/uCEFApplication.pas b/source/uCEFApplication.pas index d82b552c..5429ea27 100644 --- a/source/uCEFApplication.pas +++ b/source/uCEFApplication.pas @@ -186,6 +186,7 @@ type procedure SetOsmodalLoop(aValue : boolean); function GetChromeVersion : string; + function GetLibCefVersion : string; function GetLibCefPath : string; function GetChromeElfPath : string; function GetMustCreateResourceBundleHandler : boolean; @@ -339,6 +340,7 @@ type property ChromeRelease : uint16 read FChromeVersionInfo.Release; property ChromeBuild : uint16 read FChromeVersionInfo.Build; property ChromeVersion : string read GetChromeVersion; + property LibCefVersion : string read GetLibCefVersion; property LibCefPath : string read GetLibCefPath; property ChromeElfPath : string read GetChromeElfPath; property SmoothScrolling : TCefState read FSmoothScrolling write FSmoothScrolling; @@ -635,6 +637,14 @@ begin Result := FileVersionInfoToString(FChromeVersionInfo); end; +function TCefApplication.GetLibCefVersion : string; +begin + Result := IntToStr(CEF_SUPPORTED_VERSION_MAJOR) + '.' + + IntToStr(CEF_SUPPORTED_VERSION_MINOR) + '.' + + IntToStr(CEF_SUPPORTED_VERSION_RELEASE) + '.' + + IntToStr(CEF_SUPPORTED_VERSION_BUILD); +end; + function TCefApplication.GetLibCefPath : string; begin if (length(FFrameworkDirPath) > 0) then @@ -778,6 +788,8 @@ function TCefApplication.CheckCEFLibrary : boolean; var TempString, TempOldDir : string; TempMissingFrm, TempMissingRsc, TempMissingLoc : boolean; + TempMachine : integer; + TempVersionInfo : TFileVersionInfo; begin Result := False; @@ -813,14 +825,61 @@ begin CEF_SUPPORTED_VERSION_MINOR, CEF_SUPPORTED_VERSION_RELEASE, CEF_SUPPORTED_VERSION_BUILD) then - Result := True + begin + if GetDLLHeaderMachine(LibCefPath, TempMachine) then + case TempMachine of + IMAGE_FILE_MACHINE_I386 : + if Is32BitProcess then + Result := True + else + begin + FStatus := asErrorDLLVersion; + TempString := 'Wrong CEF3 binaries !' + + CRLF + CRLF + + 'Use the 32 bit CEF3 binaries with 32 bits applications only.'; + + ShowErrorMessageDlg(TempString); + end; + + IMAGE_FILE_MACHINE_AMD64 : + if not(Is32BitProcess) then + Result := True + else + begin + FStatus := asErrorDLLVersion; + TempString := 'Wrong CEF3 binaries !' + + CRLF + CRLF + + 'Use the 64 bit CEF3 binaries with 64 bits applications only.'; + + ShowErrorMessageDlg(TempString); + end; + + else + begin + FStatus := asErrorDLLVersion; + TempString := 'Unknown CEF3 binaries !' + + CRLF + CRLF + + 'Use only the CEF3 binaries specified in the CEF4Delphi Readme.md file at ' + + CEF4DELPHI_URL; + + ShowErrorMessageDlg(TempString); + end; + end + else + Result := True; + end else begin FStatus := asErrorDLLVersion; TempString := 'Unsupported CEF version !' + CRLF + CRLF + 'Use only the CEF3 binaries specified in the CEF4Delphi Readme.md file at ' + - CRLF + CEF4DELPHI_URL; + CEF4DELPHI_URL; + + if GetDLLVersion(LibCefPath, TempVersionInfo) then + TempString := TempString + CRLF + CRLF + + 'Expected ' + LIBCEF_DLL + ' version : ' + LibCefVersion + CRLF + + 'Found ' + LIBCEF_DLL + ' version : ' + FileVersionInfoToString(TempVersionInfo); ShowErrorMessageDlg(TempString); end; diff --git a/source/uCEFConstants.pas b/source/uCEFConstants.pas index c899ec95..43b139dc 100644 --- a/source/uCEFConstants.pas +++ b/source/uCEFConstants.pas @@ -402,6 +402,18 @@ const CEF4DELPHI_URL = 'https://github.com/salvadordf/CEF4Delphi'; CRLF = #13 + #10; + // Bitness constants used in + IMAGE_FILE_MACHINE_UNKNOWN = 0; + IMAGE_FILE_MACHINE_I386 = $014c; // Intel x86 + IMAGE_FILE_MACHINE_IA64 = $0200; // Intel Itanium Processor Family (IPF) + IMAGE_FILE_MACHINE_AMD64 = $8664; // x64 (AMD64 or EM64T) + IMAGE_FILE_MACHINE_R3000_BE = $160; // MIPS big-endian + IMAGE_FILE_MACHINE_R3000 = $162; // MIPS little-endian, 0x160 big-endian + IMAGE_FILE_MACHINE_R4000 = $166; // MIPS little-endian + IMAGE_FILE_MACHINE_R10000 = $168; // MIPS little-endian + IMAGE_FILE_MACHINE_ALPHA = $184; // Alpha_AXP } + IMAGE_FILE_MACHINE_POWERPC = $1F0; // IBM PowerPC Little-Endian + implementation end. diff --git a/source/uCEFMiscFunctions.pas b/source/uCEFMiscFunctions.pas index bcd12ff5..18949a8a 100644 --- a/source/uCEFMiscFunctions.pas +++ b/source/uCEFMiscFunctions.pas @@ -121,6 +121,7 @@ procedure WindowInfoAsWindowless(var aWindowInfo : TCefWindowInfo; aParent : TCe {$ENDIF} {$IFDEF MSWINDOWS} +function ProcessUnderWow64(hProcess: THandle; var Wow64Process: BOOL): BOOL; external Kernel32DLL name 'IsWow64Process'; function TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation: PTimeZoneInformation; lpLocalTime, lpUniversalTime: PSystemTime): BOOL; stdcall; external Kernel32DLL; function SystemTimeToTzSpecificLocalTime(lpTimeZoneInformation: PTimeZoneInformation; lpUniversalTime, lpLocalTime: PSystemTime): BOOL; stdcall; external Kernel32DLL; @@ -171,6 +172,8 @@ function CheckDLLs(const aFrameworkDirPath : string; var aMissingFiles : string) function CheckDLLVersion(const aDLLFile : string; aMajor, aMinor, aRelease, aBuild : uint16) : boolean; function FileVersionInfoToString(const aVersionInfo : TFileVersionInfo) : string; function CheckFilesExist(var aList : TStringList; var aMissingFiles : string) : boolean; +function GetDLLHeaderMachine(const aDLLFile : string; var aMachine : integer) : boolean; +function Is32BitProcess : boolean; function CefParseUrl(const url: ustring; var parts: TUrlParts): Boolean; function CefCreateUrl(var parts: TUrlParts): ustring; @@ -1166,6 +1169,76 @@ begin (TempVersionInfo.Build = aBuild); end; +// This function is based on the answer given by 'Alex' in StackOverflow +// https://stackoverflow.com/questions/2748474/how-to-determine-if-dll-file-was-compiled-as-x64-or-x86-bit-using-either-delphi +function GetDLLHeaderMachine(const aDLLFile : string; var aMachine : integer) : boolean; +var + TempHeader : TImageDosHeader; + TempImageNtHeaders : TImageNtHeaders; + TempStream : TFileStream; +begin + Result := False; + aMachine := IMAGE_FILE_MACHINE_UNKNOWN; + TempStream := nil; + + try + try + if FileExists(aDLLFile) then + begin + TempStream := TFileStream.Create(aDLLFile, fmOpenRead); + TempStream.seek(0, soFromBeginning); + TempStream.ReadBuffer(TempHeader, SizeOf(TempHeader)); + + if (TempHeader.e_magic = IMAGE_DOS_SIGNATURE) and + (TempHeader._lfanew <> 0) then + begin + TempStream.Position := TempHeader._lfanew; + TempStream.ReadBuffer(TempImageNtHeaders, SizeOf(TempImageNtHeaders)); + + if (TempImageNtHeaders.Signature = IMAGE_NT_SIGNATURE) then + begin + aMachine := TempImageNtHeaders.FileHeader.Machine; + Result := True; + end; + end; + end; + except + on e : exception do + if CustomExceptionHandler('GetDLLBitness', e) then raise; + end; + finally + if (TempStream <> nil) then FreeAndNil(TempStream); + end; +end; + +function Is32BitProcess : boolean; +{$IFDEF MSWINDOWS} +var + TempResult : BOOL; +{$ENDIF} +begin + {$IFDEF CPUX32} + Result := True; + exit; + {$ENDIF} + + {$IFDEF WIN32} + Result := True; + exit; + {$ENDIF} + + {$IFDEF MSWINDOWS} + Result := ProcessUnderWow64(GetCurrentProcess, TempResult) and TempResult; + exit; + {$ENDIF} + + {$IFDEF DELPHI16_UP} + Result := TOSVersion.Architecture in [arIntelX86, arARM32]; + {$ELSE} + Result := False; + {$ENDIF} +end; + function CustomPathIsRelative(const aPath : string) : boolean; begin {$IFDEF DELPHI12_UP}