TidHashSHA512.isavailable is false on Windows 10 - delphi

I am using that function on Delphi XE2 to hash a string.
I have a bad result if the program is run on Windows 10 — the result is null because TidHashSHA512.isavailable is FALSE.
What do I have to do?
function HashSHA512String(Text: String): String;
var
IdHashSHA512: TIdHashSHA512;
begin
Result := '';
if HashFunctionsOpenSSLLoaded then begin
if TIdHashSHA512.IsAvailable then begin // <-- ADD THIS
IdHashSHA512 := TIdHashSHA512.Create;
try
Result := IdHashSHA512.HashStringAsHex(Text);
finally
FreeAndNil(IdHashSHA512);
end;
end;
end;
end;

Most of Indy's SHA hashes depend on your app hooking up an external hashing library to Indy. Only SHA-1 (amongst a few other non-SHA hashes) is currently implemented natively.
To enable SHA-512, the following callback function pointers in the IdFIPS unit must be assigned at runtime:
IsHashingIntfAvail
UpdateHashInst
FinalHashInst
IsSHA512HashIntfAvail
GetSHA512HashInst
You can use any hashing library you want, as long as the above function pointers are assigned to suitable functions.
Indy provides an implementation that uses hashing functions from OpenSSL. To use it, you can either:
add the IdSSLOpenSSLHeaders unit to your uses clause, and then call its Load() function at runtime.
add the IdSSLOpenSSL unit to your uses clause, and then call its LoadOpenSSLLibrary() function at runtime.
Either way, you will have to distribute the two OpenSSL DLLs with your app (libeay32.dll and ssleay32.dll, which you can download from Indy's Fulgan mirror). Be sure to use builds that have been compiled with SHA-512 enabled.

Related

Dynamicly handle not defined functions in a dll in dlephi

I have a dll which defines a simple functions to show a message:
library testdll;
uses SysUtils, Classes, Dialogs;
{$R *res}
procedure ShowDll;stdcall;
begin
ShowMessage('ShowDLL testdll.dll');
end;
exports ShowDLL;
begin
end.
And my main file call this dll dynamicly using this procedure:
i defined a new type:
type
testdll = procedure;stdcall;
Then on my button click event:
procedure TForm1.Button1Click(Sender:TObject);
var
dllHandle: THandle; //Don't use Cardinal; it's limited to 32-bits
test : testdll;
begin
dllHandle := LoadLibrary('testdll.dll');
if dllHandle <> 0 then
begin
#test := GetProcAddress(dllHandle,'ShowDLL');
if Assigned(test) then
ShowDLL
else
ShowMessage('Func not found');
end
else
ShowMessage('dll not found');
end;
This works. But I don't know if it's possible to handle not defined functions with my dll. My purpose here is to call a function without knowing if it will be defined in my dll. So i would like the dll to tell me if the functions exists or not.
For example here i only have a ShowDLL procedure. If i call another method which does not exists it will show 'Func not found' from my main application. But i would my dll to tell me this. Is this possible? If yes, how could i achieve this pls?
EDIT: I can't modify the main function this is only a test. In my final version there will be only the dll. So exporting all functions into my main application is not possible here. That's why i want to know id the dll alone can handle it rather than doing this in my main application which i can't do.
I don't have acces to the main application to modify any code in it. I only know what are functions that will be used in this application that i will later export in my dll using exports statement. So what i try to achieve is to catch a not defined function with the dll if it's possible.
Your code already demonstrates how to detect the presence of an export. Namely to call GetProcAddress and compare the result with nil.
You can reduce the amount of boiler plate code by using delay loading. This essentially lets the compiler generate the code the performs the checks. This relies on the delayed keyword.
procedure testdll; stdcall;
external 'testdll.dll` delayed;
When you call this function, if it cannot be found, an exception is raised. Indeed this behaviour can be customised, as described in the documentation: http://docwiki.embarcadero.com/RADStudio/en/Libraries_and_Packages#Delayed_Loading
Update
In a comment to this answer you state that the executable cannot be changed. In which case, the message that you wish to avoid will be shown if the function is missing. You ask if the missing export can be handled by the DLL but that is not possible. When you call GetProcAddress, no code inside the DLL is executed. All the processing is done external to the DLL by reading its PE metadata.
The obvious conclusion is that the DLL must export the function. If the true DLL does not, put another DLL in its place. Use an interposer DLL that exports the function. Implement the function by delegating to the true DLL, if the true DLL exports the function. Otherwise do something else, whatever you please.

Point to a DLL using a dynamic path

My problem is not exporting a function, but importing it. I know for sure that both the function and DLL both work because I have used a hard-coded path to point to the DLL.
This is what is currently working:
function RoamingAppDataPath: String; external 'C:\Users\Peter\AppData\Roaming\ss\Application\ss.dll';
However I need to point to the DLL with a dynamic value so what I tried to do is
Declare a global variable (DLLPath: String)
Assign DLLPath the value - RoamingAppDataPath+'\ss\Application\ss.dll'
Note: RoamingAppDataPath is a function that outputs the path to the roaming app data folder.
The code I am trying to run is:
function RoamingAppDataPath: String; external DLLPath;
When I compile the code, Delphi is telling me that it is expecting a constant expression:
E2026 Constant expression expected
What is the work around for this?
You have to bind at runtime and that means you need to use LoadLibrary and GetProcAddress:
var
lib: HMODULE;
RoamingAppDataPath: function: string;
lib := LoadLibrary(dllfilename);
if lib=0 then
RaiseLastOSError;
Pointer(RoamingAppDataPath) := GetProcAddress(lib, 'RoamingAppDataPath');
And then you can call it:
radp := RoamingAppDataPath;
Some comments:
I don't know why you write this function when it exists in standard system libraries.
Using string across DLL boundaries is liable to fail. You need to be using ShareMem and make sure that all code is built with the same Delphi version. Better to allocate the buffer in the calling code.
Even if you would be able to use a Variable, you would nowhere be able to set a value to DLLPATH, since already initalization would not be used if a static DLL can not be used.
You will have to use dynamic loadingif you want to define the path for the DLL.
procedure Test;external 'Notexists.DLL';
var
Form2: TForm2;
implementation
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
test;
end;
initialization
Showmessage('Hallo'); // will never be seen if test is used.

Why are certain Delphi SOAP RTL OpConvert.pas methods deprecated if they use a String instead of a Stream as their XML document type?

I have a warning in my code that I can't figure out how to remove. The method is a utility method that is invoking THTTPRIO's FConverter field's IOPConvert.ProcessResponse method.
There are several overloaded versions of ProcessResponse in IOPConvert, and the one that is declared with parameter type InvString as the first parameter is the deprecated one.
Throughout the Delphi SOAP RTL, the trend has been away from String types and towards stream types, since Delphi 7, up to now (Delphi XE/XE2).
The question is WHY? In this case I can't even figure out how to convert my helper code unless I add an ugly string-stream wrapper:
TRIOHelper = class helper for THTTPRIO
public
function HelperMethod(aMethName: String; aSoapString: String) : TRemotable;
end;
function TRIOHelper.HelperMethod(aMethName, aSoapString: String): TRemotable;
var
tmpString:String;
begin
//FConverter is a field in THTTPRIO
tmpStr := GrievousXmlHackery(aSoapString);
FConverter.ProcessResponse(InvString(tmpStr), IntfMD, MethMD, FContext);
...
end;
The code above the deprecated call is tweaking an XML document (the SOAP response) and removing some problematic elements from the incoming stream. Yes, a hack. How should I change it,and why are strings bad in OpConvert?
I guess I need to make a String Stream or Memory Stream wrapper for tmpString? Note that in my case, the GrievousXmlHackery function removes the <encoding> tag when present, from the SOAP for evil reasons that remain unimportant here.
Unless there is something actually technically WRONG with the old methods and the string based apis, I'm going to put up with the warning. But if (like many places in the VCL), the deprecated warning also means "here be dragons", I'd like to know about it.
I'm not familiar with Delphi's SOAP implementation, but why can't you just use a TStringStream instead?
function TRIOHelper.HelperMethod(aMethName, aSoapString: String): TRemotable;
var
Strm: TStringStream;
begin
//FConverter is a field in THTTPRIO
Strm := TStringStream.Create(GrievousXmlHackery(aSoapString));
// or
// Strm := TStringStream.Create('');
// Strm.DataString := GreviousXmlHackery(aSoapString);
FConverter.ProcessResponse(Strm, IntfMD, MethMD, FContext);
// Not sure if you or THTTPRIO is responsible for releasing the stream
...
end;

Using DwmIsCompositionEnabled (JwaDwmApi) on pre-vista causes error

Been trying to use the following code in order to check if Windows Aero is enabled:
function AeroEnabled: boolean;
var
enabled: bool;
begin
// Function from the JwaDwmapi unit (JEDI Windows Api Library)
DwmIsCompositionEnabled(enabled);
Result := enabled;
end;
...
if (CheckWin32Version(5,4)) and (AeroEnabled) then
CampaignTabs.ColorBackground := clBlack
else begin
GlassFrame.Enabled := False;
CampaignTabs.ColorBackground := clWhite;
end;
However, doing so on a pre-vista machine causes the app to crash because the DWMApi.dll is missing. I've also tried this code however it produces 2 AV's in a row. How can I do this ? I am using Delphi 2010. :)
You've got your versions wrong. Vista/2008 server are version 6.0. Your test should be:
CheckWin32Version(6,0)
I believe that you are using Delphi 2010 or later in which case you should simply call the DwmCompositionEnabled function from the built-in Dwmapi unit. This organises the version check and the delayed binding for you. No need for JEDI.
Edit: Text below was written before the question was edited.
Probably the easiest approach is to check the Windows version. You need Win32MajorVersion>=6 (i.e. Vista or 2008 server) in order to call DwmIsCompositionEnabled.
If you were binding yourself then you would call LoadLibrary with DWMApi.dll and if that succeeded you would then call GetProcAddress to bind. If that succeeded you are good. But, as I said, since you aren't handling the binding yourself then a version check is probably the simplest.
So the function would be:
function AeroEnabled: boolean;
var
enabled: bool;
begin
if Win32MajorVersion>=6 then begin
DwmIsCompositionEnabled(enabled);
Result := enabled;
end else begin
Result := False;
end;
end;
Note, I'm assuming that your library is doing late binding, i.e. explicit linking. If not then you'll need LoadLibrary/GetProcAddress, exactly as is done in #RRUZ's code to which you link.

Getting size of a file in Delphi 2010 or later?

Delphi 2010 has a nice set of new file access functions in IOUtils.pas (I especially like the UTC versions of the date-related functions). What I miss so far is something like
TFile.GetSize (const Path : String)
What is the Delphi 2010-way to get the size of a file? Do I have to go back and use FindFirst to access TSearchRec.FindData?
Thanks.
I'm not sure if there's a "Delphi 2010" way, but there is a Windows way that doesn't involve FindFirst and all that jazz.
I threw together this Delphi conversion of that routine (and in the process modified it to handle > 4GB size files, should you need that).
uses
WinApi.Windows;
function FileSize(const aFilename: String): Int64;
var
info: TWin32FileAttributeData;
begin
result := -1;
if NOT GetFileAttributesEx(PChar(aFileName), GetFileExInfoStandard, #info) then
EXIT;
result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
end;
You could actually just use GetFileSize() but this requires a file HANDLE, not just a file name, and similar to the GetCompressedFileSize() suggestion, this requires two variables to call. Both GetFileSize() and GetCompressedFileSize() overload their return value, so testing for success and ensuring a valid result is just that little bit more awkward.
GetFileSizeEx() avoids the nitty gritty of handling > 4GB file sizes and detecting valid results, but also requires a file HANDLE, rather than a name, and (as of Delphi 2009 at least, I haven't checked 2010) isn't declared for you in the VCL anywhere, you would have to provide your own import declaration.
Using an Indy unit:
uses IdGlobalProtocols;
function FileSizeByName(const AFilename: TIdFileName): Int64;
You can also use DSiFileSize from DSiWin32. Works in "all" Delphis. Internally it calls CreateFile and GetFileSize.
function DSiFileSize(const fileName: string): int64;
var
fHandle: DWORD;
begin
fHandle := CreateFile(PChar(fileName), 0, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if fHandle = INVALID_HANDLE_VALUE then
Result := -1
else try
Int64Rec(Result).Lo := GetFileSize(fHandle, #Int64Rec(Result).Hi);
finally CloseHandle(fHandle); end;
end; { DSiFileSize }
I'd like to mention few Pure Delphi ways. Though i think Deltics made a most speed-effective answer for Windows platform, yet sometimes you want just rely on RTL and also make portable code that would work in Delphi for MacOS or in FreePascal/Virtual Pascal/whatever.
There is FileSize function left from Turbo Pascal days.
http://turbopascal.org/system-functions-filepos-and-filesize
http://docwiki.embarcadero.com/CodeExamples/XE2/en/SystemFileSize_(Delphi)
http://docwiki.embarcadero.com/Libraries/XE2/en/System.FileSize
The sample above lacks "read-only" mode setting. You would require that to open r/o file such as one on CD-ROM media or in folder with ACLs set to r/o. Before calling ReSet there should be zero assigned to FileMode global var.
http://docwiki.embarcadero.com/Libraries/XE2/en/System.FileMode
It would not work on files above 2GB size (maybe with negative to cardinal cast - up to 4GB) but is "out of the box" one.
There is one more approach, that you may be familiar if you ever did ASM programming for MS-DOS. You Seek file pointer to 1st byte, then to last byte, and check the difference.
I can't say exactly which Delphi version introduced those, but i think it was already in some ancient version like D5 or D7, though that is just common sense and i cannot check it.
That would take you an extra THandle variable and try-finally block to always close the handle after size was obtained.
Sample of getting length and such
http://docwiki.embarcadero.com/Libraries/XE2/en/System.SysUtils.FileOpen
http://docwiki.embarcadero.com/Libraries/XE2/en/System.SysUtils.FileSeek
Aside from 1st approach this is int64-capable.
It is also compatible with FreePascal, though with some limitations
http://www.freepascal.org/docs-html/rtl/sysutils/fileopen.html
You can also create and use TFileStream-typed object - which was the primary, officially blessed avenue for file operations since Delphi 1.0
http://www.freepascal.org/docs-html/rtl/classes/tfilestream.create.html
http://www.freepascal.org/docs-html/rtl/classes/tstream.size.html
http://docwiki.embarcadero.com/Libraries/XE2/en/System.Classes.TFileStream.Create
http://docwiki.embarcadero.com/Libraries/XE2/en/System.Classes.TStream.Size
As a side note, this avenue is of course integrated with aforementioned IOUtils unit.
http://docwiki.embarcadero.com/Libraries/XE3/en/System.IOUtils.TFile.OpenRead
This is a short solution using FileSize that does the job:
function GetFileSize(p_sFilePath : string) : Int64;
var
oFile : file of Byte;
begin
Result := -1;
AssignFile(oFile, p_sFilePath);
try
Reset(oFile);
Result := FileSize(oFile);
finally
CloseFile(oFile);
end;
end;
From what I know, FileSize is available only from XE2.
uses
System.Classes, System.IOUtils;
function GetFileSize(const FileName : string) : Int64;
var
Reader: TFileStream;
begin
Reader := TFile.OpenRead(FileName);
try
result := Reader.Size;
finally
Reader.Free;
end;
end;

Resources