//version 0.31 beta
unit FileUtilsEx;
{$MODE Delphi}
{$codepage UTF8}
interface
uses windows, sysutils, ShellApi, Classes;
type TExePlatform = (expUnknown, exp32Bit, exp64Bit, expOther);
//stdcalls
function FileVersion (AFileName: String): String;
function FileSize2Str (const AFileSize: Int64; AStringNames: Array of String; const ADecimalPlaces: Byte): String; Stdcall; Overload;
function FileSize2Str (const AFileSize: Int64; AStringNames: Array of String): String; Stdcall; Overload;
function FileSize2Str (const AFileSize: Int64; const ADecimalPlaces: Byte): String; Overload;
function FileSize2Str (const AFileSize: Int64): String; Overload;
function FileAccessDateToDateTime (FileTime: TFILETIME): TDateTime; Stdcall;
function RenameDir (const DirName, NewName: String): Boolean; STDCALL;
function GetEXEPlatform (const AFileName: String): TExePlatform; STDCALL;
implementation
const AFileSizeNames: Array[0..4] of String = ('Byte', 'KB', 'MB', 'GB', 'TB');
//Getting version of the file
function FileVersion (AFileName: String): String;
var szName: array[0..255] of Char;
    P: Pointer;
    Value: Pointer;
    Len: UINT;
    GetTranslationString: String;
    FFileName: PChar;
    FValid:boolean;
    FSize: DWORD;
    FHandle: DWORD;
    FBuffer: PChar;
begin
try
 FFileName:= StrPCopy(StrAlloc(Length(AFileName) + 1), AFileName);
 FValid:= False;
 FSize:= GetFileVersionInfoSize(FFileName, FHandle);
 if FSize > 0 then
  try
   GetMem(FBuffer, FSize);
   FValid:= GetFileVersionInfo(FFileName, FHandle, FSize, FBuffer);
   except
   FValid:= False;
   raise;
   end;
 Result:= '';
 if FValid then
  VerQueryValue(FBuffer, '\VarFileInfo\Translation', P, Len)
  else
  P:= nil;
 if P <> nil then
  GetTranslationString:= IntToHex(MakeLong(HiWord(Longint(P^)), LoWord(Longint(P^))), 8);
 if FValid then
  begin
  StrPCopy(szName, '\StringFileInfo\' + GetTranslationString + '\FileVersion');
  if VerQueryValue(FBuffer, szName, Value, Len) then
   Result:= StrPas(PChar(Value));
  end;
 finally
 try
  if FBuffer <> nil then
   FreeMem(FBuffer, FSize);
  except
  end;
 try
  StrDispose(FFileName);
  except
  end;
 end;
end;
//FileSize2Str
function FileSize2Str (const AFileSize: Int64; AStringNames: Array of String; const ADecimalPlaces: Byte): String; Overload;
 function FrmtSize (const ASize, ADelim: Int64; const ADP: Byte): String;
 var VDelim: Int64;
     Indx: Byte;
 begin
 VDelim:= 1;
 for Indx:= 0 to ADP do
  VDelim:= VDelim*10;
 Result:= FloatToStr(round((ASize*VDelim)/ADelim)/VDelim);
 end;
const AFrmtsStr: String = '%s %s';
begin
//Bytes
if AFileSize < 1024 then
 Result:= Format(AFrmtsStr, [IntToStr(AFileSize), AStringNames[0]]);
//KiloBytes
if (AFileSize >= 1024) and (AFileSize < 1048576) then
 Result:= Format(AFrmtsStr, [FrmtSize(AFileSize, 1024, ADecimalPlaces), AStringNames[1]]);
//MegaBytes
if (AFileSize >= 1048576) and (AFileSize < 1073741824) then
 Result:= Format(AFrmtsStr, [FrmtSize(AFileSize, 1048576, ADecimalPlaces), AStringNames[2]]);
//GigaBytes
if (AFileSize >= 1073741824) and (AFileSize < 1099511627776) then
 Result:= Format(AFrmtsStr, [FrmtSize(AFileSize, 1073741824, ADecimalPlaces), AStringNames[3]]);
//TeraBytes
if (AFileSize >= 1099511627776) then
 Result:= Format(AFrmtsStr, [FrmtSize(AFileSize, 1073741824, ADecimalPlaces), AStringNames[4]]);
end;
function FileSize2Str (const AFileSize: Int64; AStringNames: Array of String): String; Overload;
begin
Result:= FileSize2Str(AFileSize, AStringNames, 2);
end;
function FileSize2Str (const AFileSize: Int64; const ADecimalPlaces: Byte): String; Overload;
begin
Result:= FileSize2Str(AFileSize, AFileSizeNames, ADecimalPlaces);
end;
function FileSize2Str (const AFileSize: Int64): String; Overload;
begin
Result:= FileSize2Str(AFileSize, AFileSizeNames, 2);
end;
//FileAccessDateToDateTime
//Author: Дураг (http://www.sql.ru/forum/memberinfo.aspx?mid=32731) from http://www.sql.ru/forum/259218/kak-poluchit-datu-i-vremya-sozdaniya-fayla
function FileAccessDateToDateTime (FileTime: TFILETIME): TDateTime;
var LocalTime: TFILETIME;
    DOSFileTime: DWORD;
begin
FileTimeToLocalFileTime(FileTime, LocalTime);
FileTimeToDosDateTime(LocalTime, LongRec(DOSFileTime).Hi, LongRec(DOSFileTime).Lo);
Result:= FileDateToDateTime(DOSFileTime);
end;
//RenameDir
function RenameDir (const DirName, NewName: String): Boolean;
var shellinfo: TSHFILEOPSTRUCT;
    DirFrom, DirTo: String;
begin
DirFrom:= DirName;
DirTo:= NewName;
with shellinfo do
 begin
 Wnd:= 0;
 wFunc:= FO_RENAME;
 pFrom:= PChar(DirFrom);
 pTo:= PChar(DirTo);
 fFlags:= FOF_FILESONLY or FOF_ALLOWUNDO or FOF_SILENT or FOF_NOCONFIRMATION;
 end;
SHFileOperation(shellinfo);
Result:= DirectoryExists(NewName);
end;
//GetEXEPlatform
//Author Dmitry Arefiev (http://www.sql.ru/forum/808857/kak-opredelit-razryadnost-prilozheniya)
function GetEXEPlatform (const AFileName: String): TExePlatform;
var oFS: TFileStream;
    iPeOffset: Integer;
    iPeHead: LongWord;
    iMachineType: Word;
begin
Result:= expUnknown;
try
 oFS:= TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone);
 try
  oFS.Seek($3C, soFromBeginning);
  oFS.Read(iPeOffset, SizeOf(iPeOffset));
  oFS.Seek(iPeOffset, soFromBeginning);
  oFS.Read(iPeHead, SizeOf(iPeHead));
  if iPeHead <> $00004550 then
   Exit;
  oFS.Read(iMachineType, SizeOf(iMachineType));
  case iMachineType of
   $8664, $0200: Result:= exp64Bit;
   $014C: Result:= exp32Bit;
   else
   Result:= expOther;
   end;
  finally
   oFS.Free;
  end;
 except
 end;
end;
end.
