1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 1999-2000 by Florian Klaempfl
- member of the Free Pascal development team
- SysUtils unit for win32
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit SysUtils;
- interface
- {$MODE objfpc}
- {$MODESWITCH OUT}
- { force ansistrings }
- {$H+}
- {$modeswitch typehelpers}
- {$modeswitch advancedrecords}
- uses
- windows;
- {$DEFINE HAS_SLEEP}
- {$DEFINE HAS_OSERROR}
- {$DEFINE HAS_OSCONFIG}
- {$DEFINE HAS_OSUSERDIR}
- {$DEFINE HAS_CREATEGUID}
- {$DEFINE HAS_LOCALTIMEZONEOFFSET}
- {$DEFINE HAS_GETTICKCOUNT}
- {$DEFINE HAS_GETTICKCOUNT64}
- {$DEFINE OS_FILESETDATEBYNAME}
- // this target has an fileflush implementation, don't include dummy
- {$DEFINE SYSUTILS_HAS_FILEFLUSH_IMPL}
- { used OS file system APIs use unicodestring }
- {$define SYSUTILS_HAS_UNICODESTR_FILEUTIL_IMPL}
- { OS has an ansistring/single byte environment variable API }
- {$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
- { OS has a unicodestring/two byte environment variable API }
- {$define SYSUTILS_HAS_UNICODESTR_ENVVAR_IMPL}
- { Include platform independent interface part }
- {$i sysutilh.inc}
- type
- TSystemTime = Windows.TSystemTime;
- EWin32Error = class(Exception)
- public
- ErrorCode : DWORD;
- end;
- Var
- Win32Platform : Longint;
- Win32MajorVersion,
- Win32MinorVersion,
- Win32BuildNumber : dword;
- Win32CSDVersion : ShortString; // CSD record is 128 bytes only?
- const
- MaxEraCount = 7;
- var
- EraNames: array [1..MaxEraCount] of String;
- EraYearOffsets: array [1..MaxEraCount] of Integer;
- { Compatibility with Delphi }
- function Win32Check(res:boolean):boolean;inline;
- function WinCheck(res:boolean):boolean;
- function CheckWin32Version(Major,Minor : Integer ): Boolean;
- function CheckWin32Version(Major : Integer): Boolean;
- Procedure RaiseLastWin32Error;
- function GetFileVersion(const AFileName: string): Cardinal;
- function GetFileVersion(const AFileName: UnicodeString): Cardinal;
- procedure GetFormatSettings;
- procedure GetLocaleFormatSettings(LCID: Integer; var FormatSettings: TFormatSettings); platform;
- implementation
- uses
- sysconst,
- windirs;
- var
- FindExInfoDefaults : TFINDEX_INFO_LEVELS = FindExInfoStandard;
- FindFirstAdditionalFlags : DWord = 0;
- function WinCheck(res:boolean):boolean;
- begin
- if not res then
- RaiseLastOSError;
- result:=res;
- end;
- function Win32Check(res:boolean):boolean;inline;
- begin
- result:=WinCheck(res);
- end;
- procedure RaiseLastWin32Error;
- begin
- RaiseLastOSError;
- end;
- function CheckWin32Version(Major : Integer): Boolean;
- begin
- Result:=CheckWin32Version(Major,0)
- end;
- function CheckWin32Version(Major,Minor: Integer): Boolean;
- begin
- Result:=(Win32MajorVersion>dword(Major)) or
- ((Win32MajorVersion=dword(Major)) and (Win32MinorVersion>=dword(Minor)));
- end;
- function GetFileVersion(const AFileName:string):Cardinal;
- var
- { useful only as long as we don't need to touch different stack pages }
- buf : array[0..3071] of byte;
- bufp : pointer;
- fn : string;
- valsize,
- size : DWORD;
- h : DWORD;
- valrec : PVSFixedFileInfo;
- begin
- result:=$fffffff;
- fn:=AFileName;
- UniqueString(fn);
- size:=GetFileVersionInfoSizeA(pchar(fn),@h);
- if size>sizeof(buf) then
- begin
- getmem(bufp,size);
- try
- if GetFileVersionInfoA(pchar(fn),h,size,bufp) then
- if VerQueryValue(bufp,'\',valrec,valsize) then
- result:=valrec^.dwFileVersionMS;
- finally
- freemem(bufp);
- end;
- end
- else
- begin
- if GetFileVersionInfoA(pchar(fn),h,size,@buf) then
- if VerQueryValue(@buf,'\',valrec,valsize) then
- result:=valrec^.dwFileVersionMS;
- end;
- end;
- function GetFileVersion(const AFileName:UnicodeString):Cardinal;
- var
- { useful only as long as we don't need to touch different stack pages }
- buf : array[0..3071] of byte;
- bufp : pointer;
- fn : unicodestring;
- valsize,
- size : DWORD;
- h : DWORD;
- valrec : PVSFixedFileInfo;
- begin
- result:=$fffffff;
- fn:=AFileName;
- UniqueString(fn);
- size:=GetFileVersionInfoSizeW(pwidechar(fn),@h);
- if size>sizeof(buf) then
- begin
- getmem(bufp,size);
- try
- if GetFileVersionInfoW(pwidechar(fn),h,size,bufp) then
- if VerQueryValue(bufp,'\',valrec,valsize) then
- result:=valrec^.dwFileVersionMS;
- finally
- freemem(bufp);
- end;
- end
- else
- begin
- if GetFileVersionInfoW(pwidechar(fn),h,size,@buf) then
- if VerQueryValueW(@buf,'\',valrec,valsize) then
- result:=valrec^.dwFileVersionMS;
- end;
- end;
- {$define HASCREATEGUID}
- {$define HASEXPANDUNCFILENAME}
- {$DEFINE FPC_NOGENERICANSIROUTINES}
- {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
- {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
- function ConvertEraYearString(Count ,Year,Month,Day : integer) : string; forward;
- function ConvertEraString(Count ,Year,Month,Day : integer) : string; forward;
- { Include platform independent implementation part }
- {$i sysutils.inc}
- function GetTempFileName(Dir,Prefix: PChar; uUnique: DWORD; TempFileName: PChar):DWORD;
- begin
- Result:= Windows.GetTempFileNameA(Dir,Prefix,uUnique,TempFileName);
- end;
- { UUID generation. }
- function CoCreateGuid(out guid: TGUID): HResult; stdcall; external 'ole32.dll' name 'CoCreateGuid';
- function SysCreateGUID(out Guid: TGUID): Integer;
- begin
- Result := Integer(CoCreateGuid(Guid));
- end;
- function ExpandUNCFileName (const filename:rawbytestring) : rawbytestring;
- { returns empty string on errors }
- var
- u: unicodestring;
- begin
- { prevent data loss due to unsupported characters in ansi code page }
- u:=ExpandUNCFileName(unicodestring(filename));
- widestringmanager.Unicode2AnsiMoveProc(punicodechar(u),result,DefaultRTLFileSystemCodePage,length(u));
- end;
- function ExpandUNCFileName (const filename:unicodestring) : unicodestring;
- { returns empty string on errors }
- var
- s : unicodestring;
- size : dword;
- rc : dword;
- buf : pwidechar;
- begin
- s := ExpandFileName (filename);
- s := s + #0;
- size := max_path;
- getmem(buf,size);
- try
- rc := WNetGetUniversalNameW (pwidechar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
- if rc=ERROR_MORE_DATA then
- begin
- buf:=reallocmem(buf,size);
- rc := WNetGetUniversalNameW (pwidechar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
- end;
- if rc = NO_ERROR then
- Result := PRemoteNameInfoW(buf)^.lpUniversalName
- else if rc = ERROR_NOT_CONNECTED then
- Result := filename
- else
- Result := '';
- finally
- freemem(buf);
- end;
- end;
- {****************************************************************************
- File Functions
- ****************************************************************************}
- const
- AccessMode: array[0..2] of Cardinal = (
- GENERIC_READ,
- GENERIC_WRITE,
- GENERIC_READ or GENERIC_WRITE or FILE_WRITE_ATTRIBUTES);
- ShareModes: array[0..4] of Integer = (
- 0,
- 0,
- FILE_SHARE_READ,
- FILE_SHARE_WRITE,
- FILE_SHARE_READ or FILE_SHARE_WRITE);
- function FileFlush(Handle: THandle): Boolean;
- begin
- Result:= FlushFileBuffers(Handle);
- end;
- Function FileOpen (Const FileName : unicodestring; Mode : Integer) : THandle;
- begin
- result := CreateFileW(PWideChar(FileName), dword(AccessMode[Mode and 3]),
- dword(ShareModes[(Mode and $F0) shr 4]), nil, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, 0);
- //if fail api return feInvalidHandle (INVALIDE_HANDLE=feInvalidHandle=-1)
- end;
- Function FileCreate (Const FileName : UnicodeString) : THandle;
- begin
- FileCreate:=FileCreate(FileName, fmShareExclusive, 0);
- end;
- Function FileCreate (Const FileName : UnicodeString; Rights:longint) : THandle;
- begin
- FileCreate:=FileCreate(FileName, fmShareExclusive, Rights);
- end;
- Function FileCreate (Const FileName : UnicodeString; ShareMode : Integer; Rights : Integer) : THandle;
- begin
- Result := CreateFileW(PwideChar(FileName), GENERIC_READ or GENERIC_WRITE,
- dword(ShareModes[(ShareMode and $F0) shr 4]), nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
- end;
- Function FileRead (Handle : THandle; out Buffer; Count : longint) : Longint;
- Var
- res : dword;
- begin
- if ReadFile(Handle, Buffer, Count, res, nil) then
- FileRead:=Res
- else
- FileRead:=-1;
- end;
- Function FileWrite (Handle : THandle; const Buffer; Count : Longint) : Longint;
- Var
- Res : dword;
- begin
- if WriteFile(Handle, Buffer, Count, Res, nil) then
- FileWrite:=Res
- else
- FileWrite:=-1;
- end;
- Function FileSeek (Handle : THandle;FOffset,Origin : Longint) : Longint;
- begin
- Result := longint(SetFilePointer(Handle, FOffset, nil, Origin));
- end;
- Function FileSeek (Handle : THandle; FOffset: Int64; Origin: Longint) : Int64;
- var
- rslt: Int64Rec;
- begin
- rslt := Int64Rec(FOffset);
- rslt.lo := SetFilePointer(Handle, rslt.lo, @rslt.hi, Origin);
- if (rslt.lo = $FFFFFFFF) and (GetLastError <> 0) then
- rslt.hi := $FFFFFFFF;
- Result := Int64(rslt);
- end;
- Procedure FileClose (Handle : THandle);
- begin
- CloseHandle(Handle);
- end;
- Function FileTruncate (Handle : THandle;Size: Int64) : boolean;
- begin
- {
- Result:=longint(SetFilePointer(handle,Size,nil,FILE_BEGIN))<>-1;
- }
- if FileSeek (Handle, Size, FILE_BEGIN) = Size then
- Result:=SetEndOfFile(handle)
- else
- Result := false;
- end;
- Function DosToWinTime (DTime:longint;Var Wtime : TFileTime):longbool;
- var
- lft : TFileTime;
- begin
- DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,@lft) and
- LocalFileTimeToFileTime(lft,Wtime);
- end;
- Function WinToDosTime (Var Wtime : TFileTime;var DTime:longint):longbool;
- var
- lft : TFileTime;
- begin
- WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
- FileTimeToDosDateTime(lft,Longrec(Dtime).Hi,LongRec(DTIME).lo);
- end;
- Function FileAge (Const FileName : UnicodeString): Longint;
- var
- Handle: THandle;
- FindData: TWin32FindDataW;
- begin
- Handle := FindFirstFileW(Pwidechar(FileName), FindData);
- if Handle <> INVALID_HANDLE_VALUE then
- begin
- Windows.FindClose(Handle);
- if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
- If WinToDosTime(FindData.ftLastWriteTime,Result) then
- exit;
- end;
- Result := -1;
- end;
- function FileGetSymLinkTarget(const FileName: UnicodeString; out SymLinkRec: TUnicodeSymLinkRec): Boolean;
- { reparse point specific declarations from Windows headers }
- const
- IO_REPARSE_TAG_MOUNT_POINT = $A0000003;
- IO_REPARSE_TAG_SYMLINK = $A000000C;
- ERROR_REPARSE_TAG_INVALID = 4393;
- FSCTL_GET_REPARSE_POINT = $900A8;
- MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024;
- SYMLINK_FLAG_RELATIVE = 1;
- FILE_FLAG_OPEN_REPARSE_POINT = $200000;
- FILE_READ_EA = $8;
- type
- TReparseDataBuffer = record
- ReparseTag: ULONG;
- ReparseDataLength: Word;
- Reserved: Word;
- SubstituteNameOffset: Word;
- SubstituteNameLength: Word;
- PrintNameOffset: Word;
- PrintNameLength: Word;
- case ULONG of
- IO_REPARSE_TAG_MOUNT_POINT: (
- PathBufferMount: array[0..4095] of WCHAR);
- IO_REPARSE_TAG_SYMLINK: (
- Flags: ULONG;
- PathBufferSym: array[0..4095] of WCHAR);
- end;
- const
- CShareAny = FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE;
- COpenReparse = FILE_FLAG_OPEN_REPARSE_POINT or FILE_FLAG_BACKUP_SEMANTICS;
- var
- HFile, Handle: THandle;
- PBuffer: ^TReparseDataBuffer;
- BytesReturned: DWORD;
- begin
- SymLinkRec := Default(TUnicodeSymLinkRec);
- HFile := CreateFileW(PUnicodeChar(FileName), FILE_READ_EA, CShareAny, Nil, OPEN_EXISTING, COpenReparse, 0);
- if HFile <> INVALID_HANDLE_VALUE then
- try
- GetMem(PBuffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
- try
- if DeviceIoControl(HFile, FSCTL_GET_REPARSE_POINT, Nil, 0,
- PBuffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, @BytesReturned, Nil) then begin
- case PBuffer^.ReparseTag of
- IO_REPARSE_TAG_MOUNT_POINT: begin
- SymLinkRec.TargetName := WideCharLenToString(
- @PBuffer^.PathBufferMount[4 { skip start '\??\' } +
- PBuffer^.SubstituteNameOffset div SizeOf(WCHAR)],
- PBuffer^.SubstituteNameLength div SizeOf(WCHAR) - 4);
- end;
- IO_REPARSE_TAG_SYMLINK: begin
- SymLinkRec.TargetName := WideCharLenToString(
- @PBuffer^.PathBufferSym[PBuffer^.PrintNameOffset div SizeOf(WCHAR)],
- PBuffer^.PrintNameLength div SizeOf(WCHAR));
- if (PBuffer^.Flags and SYMLINK_FLAG_RELATIVE) <> 0 then
- SymLinkRec.TargetName := ExpandFileName(ExtractFilePath(FileName) + SymLinkRec.TargetName);
- end;
- end;
- Handle := FindFirstFileExW(PUnicodeChar(FileName), FindExInfoDefaults , @SymLinkRec.FindData,
- FindExSearchNameMatch, Nil, 0);
- if Handle <> INVALID_HANDLE_VALUE then begin
- Windows.FindClose(Handle);
- SymLinkRec.Attr := SymLinkRec.FindData.dwFileAttributes;
- SymLinkRec.Size := QWord(SymLinkRec.FindData.nFileSizeHigh) shl 32 + QWord(SymLinkRec.FindData.nFileSizeLow);
- end else
- SymLinkRec.TargetName := '';
- end else
- SetLastError(ERROR_REPARSE_TAG_INVALID);
- finally
- FreeMem(PBuffer);
- end;
- finally
- CloseHandle(HFile);
- end;
- Result := SymLinkRec.TargetName <> '';
- end;
- function FileOrDirExists(const FileOrDirName: UnicodeString; CheckDir: Boolean; FollowLink: Boolean): Boolean;
- const
- CDirAttributes: array[Boolean] of DWORD = (0, FILE_ATTRIBUTE_DIRECTORY);
- function FoundByEnum: Boolean;
- var
- FindData: TWin32FindDataW;
- Handle: THandle;
- begin
- { FindFirstFileEx is faster than FindFirstFile }
- Handle := FindFirstFileExW(PUnicodeChar(FileOrDirName), FindExInfoDefaults , @FindData,
- FindExSearchNameMatch, Nil, 0);
- Result := Handle <> INVALID_HANDLE_VALUE;
- if Result then begin
- Windows.FindClose(Handle);
- Result := (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = CDirAttributes[CheckDir];
- end;
- end;
- function LinkFileExists: Boolean;
- var
- LinkTargetName: UnicodeString;
- begin
- Result := FileGetSymLinkTarget(FileOrDirName, LinkTargetName) and
- FileOrDirExists(LinkTargetName, CheckDir, False);
- end;
- const
- CNotExistsErrors = [
- ERROR_FILE_NOT_FOUND,
- ERROR_PATH_NOT_FOUND,
- ERROR_INVALID_NAME, // protects from names in the form of masks like '*'
- ERROR_INVALID_DRIVE,
- ERROR_NOT_READY,
- ERROR_INVALID_PARAMETER,
- ERROR_BAD_PATHNAME,
- ERROR_BAD_NETPATH,
- ERROR_BAD_NET_NAME
- ];
- var
- Attr : DWord;
- begin
- Attr := GetFileAttributesW(PUnicodeChar(FileOrDirName));
- if Attr = INVALID_FILE_ATTRIBUTES then
- Result := not (GetLastError in CNotExistsErrors) and FoundByEnum
- else begin
- Result := (Attr and FILE_ATTRIBUTE_DIRECTORY) = CDirAttributes[CheckDir];
- if Result and FollowLink and ((Attr and FILE_ATTRIBUTE_REPARSE_POINT) <> 0) then
- Result := LinkFileExists;
- end;
- end;
- Function FileExists (Const FileName : UnicodeString; FollowLink : Boolean) : Boolean;
- begin
- Result := FileOrDirExists(FileName, False, FollowLink);
- end;
- Function DirectoryExists (Const Directory : UnicodeString; FollowLink : Boolean) : Boolean;
- begin
- Result := FileOrDirExists(Directory, True, FollowLink);
- end;
- Function FindMatch(var f: TAbstractSearchRec; var Name: UnicodeString) : Longint;
- begin
- { Find file with correct attribute }
- While (F.FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
- begin
- if not FindNextFileW (F.FindHandle,F.FindData) then
- begin
- Result:=GetLastError;
- exit;
- end;
- end;
- { Convert some attributes back }
- WinToDosTime(F.FindData.ftLastWriteTime,F.Time);
- f.size:=F.FindData.NFileSizeLow+(qword(maxdword)+1)*F.FindData.NFileSizeHigh;
- f.attr:=F.FindData.dwFileAttributes;
- Name:=F.FindData.cFileName;
- Result:=0;
- end;
- Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData);
- begin
- if Handle <> INVALID_HANDLE_VALUE then
- begin
- Windows.FindClose(Handle);
- Handle:=INVALID_HANDLE_VALUE;
- end;
- end;
- Function InternalFindFirst (Const Path : UnicodeString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name : UnicodeString) : Longint;
- begin
- Name:=Path;
- Rslt.Attr:=attr;
- Rslt.ExcludeAttr:=(not Attr) and ($1e);
- { $1e = faHidden or faSysFile or faVolumeID or faDirectory }
- { FindFirstFile is a Win32 Call }
- Rslt.FindHandle:=FindFirstFileExW(PUnicodeChar(Path), FindExInfoDefaults , @Rslt.FindData,
- FindExSearchNameMatch, Nil, FindFirstAdditionalFlags);
- If Rslt.FindHandle=Invalid_Handle_value then
- begin
- Result:=GetLastError;
- exit;
- end;
- { Find file with correct attribute }
- Result:=FindMatch(Rslt,Name);
- if (Result<>0) then
- InternalFindClose(Rslt.FindHandle,Rslt.FindData);
- end;
- Function InternalFindNext (Var Rslt : TAbstractSearchRec; var Name: UnicodeString) : Longint;
- begin
- if FindNextFileW(Rslt.FindHandle, Rslt.FindData) then
- Result := FindMatch(Rslt, Name)
- else
- Result := GetLastError;
- end;
- Function FileGetDate (Handle : THandle) : Longint;
- Var
- FT : TFileTime;
- begin
- If GetFileTime(Handle,nil,nil,@ft) and
- WinToDosTime(FT,Result) then
- exit;
- Result:=-1;
- end;
- Function FileSetDate (Handle : THandle;Age : Longint) : Longint;
- Var
- FT: TFileTime;
- begin
- Result := 0;
- if DosToWinTime(Age,FT) and
- SetFileTime(Handle, nil, nil, @FT) then
- Exit;
- Result := GetLastError;
- end;
- {$IFDEF OS_FILESETDATEBYNAME}
- Function FileSetDate (Const FileName : UnicodeString;Age : Longint) : Longint;
- Var
- fd : THandle;
- begin
- FD := CreateFileW (PWideChar (FileName), GENERIC_READ or GENERIC_WRITE,
- FILE_SHARE_WRITE, nil, OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS, 0);
- If (Fd<>feInvalidHandle) then
- try
- Result:=FileSetDate(fd,Age);
- finally
- FileClose(fd);
- end
- else
- Result:=GetLastOSError;
- end;
- {$ENDIF}
- Function FileGetAttr (Const FileName : UnicodeString) : Longint;
- begin
- Result:=Longint(GetFileAttributesW(PWideChar(FileName)));
- end;
- Function FileSetAttr (Const Filename : UnicodeString; Attr: longint) : Longint;
- begin
- if SetFileAttributesW(PWideChar(FileName), Attr) then
- Result:=0
- else
- Result := GetLastError;
- end;
- Function DeleteFile (Const FileName : UnicodeString) : Boolean;
- begin
- Result:=Windows.DeleteFileW(PWidechar(FileName));
- end;
- Function RenameFile (Const OldName, NewName : UnicodeString) : Boolean;
- begin
- Result := MoveFileW(PWideChar(OldName), PWideChar(NewName));
- end;
- {****************************************************************************
- Disk Functions
- ****************************************************************************}
- type
- TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,total,free):longbool;stdcall;
- var
- GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
- function diskfree(drive : byte) : int64;
- var
- disk : array[1..4] of char;
- secs,bytes,
- free,total : dword;
- qwtotal,qwfree,qwcaller : int64;
- begin
- if drive=0 then
- begin
- disk[1]:='\';
- disk[2]:=#0;
- end
- else
- begin
- disk[1]:=chr(drive+64);
- disk[2]:=':';
- disk[3]:='\';
- disk[4]:=#0;
- end;
- if assigned(GetDiskFreeSpaceEx) then
- begin
- if GetDiskFreeSpaceEx(@disk[1],qwcaller,qwtotal,qwfree) then
- diskfree:=qwfree
- else
- diskfree:=-1;
- end
- else
- begin
- if GetDiskFreeSpace(@disk[1],secs,bytes,free,total) then
- diskfree:=int64(free)*secs*bytes
- else
- diskfree:=-1;
- end;
- end;
- function disksize(drive : byte) : int64;
- var
- disk : array[1..4] of char;
- secs,bytes,
- free,total : dword;
- qwtotal,qwfree,qwcaller : int64;
- begin
- if drive=0 then
- begin
- disk[1]:='\';
- disk[2]:=#0;
- end
- else
- begin
- disk[1]:=chr(drive+64);
- disk[2]:=':';
- disk[3]:='\';
- disk[4]:=#0;
- end;
- if assigned(GetDiskFreeSpaceEx) then
- begin
- if GetDiskFreeSpaceEx(@disk[1],qwcaller,qwtotal,qwfree) then
- disksize:=qwtotal
- else
- disksize:=-1;
- end
- else
- begin
- if GetDiskFreeSpace(@disk[1],secs,bytes,free,total) then
- disksize:=int64(total)*secs*bytes
- else
- disksize:=-1;
- end;
- end;
- {****************************************************************************
- Time Functions
- ****************************************************************************}
- Procedure GetLocalTime(var SystemTime: TSystemTime);
- begin
- windows.Getlocaltime(SystemTime);
- end;
- function GetLocalTimeOffset: Integer;
- var
- TZInfo: TTimeZoneInformation;
- begin
- case GetTimeZoneInformation(TZInfo) of
- TIME_ZONE_ID_UNKNOWN:
- Result := TZInfo.Bias;
- TIME_ZONE_ID_STANDARD:
- Result := TZInfo.Bias + TZInfo.StandardBias;
- TIME_ZONE_ID_DAYLIGHT:
- Result := TZInfo.Bias + TZInfo.DaylightBias;
- else
- Result := 0;
- end;
- end;
- function GetTickCount: LongWord;
- begin
- Result := Windows.GetTickCount;
- end;
- {$IFNDEF WINCE}
- type
- TGetTickCount64 = function : QWord; stdcall;
- var
- WinGetTickCount64: TGetTickCount64 = Nil;
- {$ENDIF}
- function GetTickCount64: QWord;
- {$IFNDEF WINCE}
- var
- lib: THandle;
- {$ENDIF}
- begin
- {$IFNDEF WINCE}
- { on Vista and newer there is a GetTickCount64 implementation }
- if Win32MajorVersion >= 6 then begin
- if not Assigned(WinGetTickCount64) then begin
- lib := LoadLibrary('kernel32.dll');
- WinGetTickCount64 := TGetTickCount64(
- GetProcAddress(lib, 'GetTickCount64'));
- end;
- Result := WinGetTickCount64();
- end else
- {$ENDIF}
- Result := Windows.GetTickCount;
- end;
- {****************************************************************************
- Misc Functions
- ****************************************************************************}
- procedure sysbeep;
- begin
- MessageBeep(0);
- end;
- {****************************************************************************
- Locale Functions
- ****************************************************************************}
- function GetLocaleStr(LID, LT: Longint; const Def: string): ShortString;
- var
- L: Integer;
- Buf: array[0..255] of Char;
- begin
- L := GetLocaleInfoA(LID, LT, Buf, SizeOf(Buf));
- if L > 0 then
- SetString(Result, @Buf[0], L - 1)
- else
- Result := Def;
- end;
- function GetLocaleChar(LID, LT: Longint; Def: Char): Char;
- var
- Buf: array[0..3] of Char; // sdate allows 4 chars.
- begin
- if GetLocaleInfoA(LID, LT, Buf, sizeof(buf)) > 0 then
- Result := Buf[0]
- else
- Result := Def;
- end;
- function ConvertEraString(Count ,Year,Month,Day : integer) : string;
- var
- ASystemTime: TSystemTime;
- wbuf: array[0..100] of WideChar;
- ALCID : LCID;
- begin
- Result := ''; if (Count<=0) then exit;
- DateTimeToSystemTime(EncodeDate(Year,Month,Day),ASystemTime);
- ALCID := GetThreadLocale;
- // ALCID := SysLocale.DefaultLCID;
- if GetDateFormatW(ALCID , DATE_USE_ALT_CALENDAR
- , @ASystemTime, PWChar('gg')
- , @wbuf, SizeOf(wbuf)) > 0 then
- begin
- if Count = 1 then
- wbuf[1] := #0;
- Result := string(WideString(wbuf));
- end;
- end;
- function ConvertEraYearString(Count ,Year,Month,Day : integer) : string;
- var
- ALCID : LCID;
- ASystemTime : TSystemTime;
- AFormatText : string;
- buf : array[0..100] of Char;
- begin
- Result := '';
- DateTimeToSystemTime(EncodeDate(Year,Month,Day),ASystemTime);
- if Count <= 2 then
- AFormatText := 'yy'
- else
- AFormatText := 'yyyy';
- ALCID := GetThreadLocale;
- // ALCID := SysLocale.DefaultLCID;
- if GetDateFormatA(ALCID, DATE_USE_ALT_CALENDAR
- , @ASystemTime, PChar(AFormatText)
- , @buf, SizeOf(buf)) > 0 then
- begin
- Result := buf;
- if (Count = 1) and (Result[1] = '0') then
- Result := Copy(Result, 2, Length(Result)-1);
- end;
- end;
- Function GetLocaleInt(LID,TP,Def: LongInt): LongInt;
- Var
- S: String;
- C: Integer;
- Begin
- S:=GetLocaleStr(LID,TP,'0');
- Val(S,Result,C);
- If C<>0 Then
- Result:=Def;
- End;
- function EnumEraNames(Names: PChar): WINBOOL; stdcall;
- var
- i : integer;
- begin
- Result := False;
- for i := Low(EraNames) to High(EraNames) do
- if (EraNames[i] = '') then
- begin
- EraNames[i] := Names;
- Result := True;
- break;
- end;
- end;
- function EnumEraYearOffsets(YearOffsets: PChar): WINBOOL; stdcall;
- var
- i : integer;
- begin
- Result := False;
- for i := Low(EraYearOffsets) to High(EraYearOffsets) do
- if (EraYearOffsets[i] = -1) then
- begin
- EraYearOffsets[i] := StrToIntDef(YearOffsets, 0);
- Result := True;
- break;
- end;
- end;
- procedure GetEraNamesAndYearOffsets;
- var
- ACALID : CALID;
- ALCID : LCID;
- buf : array[0..10] of char;
- i : integer;
- begin
- for i:= 1 to MaxEraCount do
- begin
- EraNames[i] := ''; EraYearOffsets[i] := -1;
- end;
- ALCID := GetThreadLocale;
- if GetLocaleInfoA(ALCID , LOCALE_IOPTIONALCALENDAR, buf, sizeof(buf)) <= 0 then exit;
- ACALID := StrToIntDef(buf,1);
- if ACALID in [3..5] then
- begin
- EnumCalendarInfoA(@EnumEraNames, ALCID, ACALID , CAL_SERASTRING);
- EnumCalendarInfoA(@EnumEraYearOffsets, ALCID, ACALID, CAL_IYEAROFFSETRANGE);
- end;
- (*
- 1 CAL_GREGORIAN Gregorian (localized)
- 2 CAL_GREGORIAN_US Gregorian (English strings always)
- 3 CAL_JAPAN Japanese Emperor Era
- 4 CAL_TAIWAN Taiwan Calendar
- 5 CAL_KOREA Korean Tangun Era
- 6 CAL_HIJRI Hijri (Arabic Lunar)
- 7 CAL_THAI Thai
- 8 CAL_HEBREW Hebrew (Lunar)
- 9 CAL_GREGORIAN_ME_FRENCH Gregorian Middle East French
- 10 CAL_GREGORIAN_ARABIC Gregorian Arabic
- 11 CAL_GREGORIAN_XLIT_ENGLISH Gregorian transliterated English
- 12 CAL_GREGORIAN_XLIT_FRENCH Gregorian transliterated French
- 23 CAL_UMALQURA Windows Vista or later: Um Al Qura (Arabic lunar) calendar
- *)
- end;
- procedure GetLocaleFormatSettings(LCID: Integer; var FormatSettings: TFormatSettings);
- var
- HF : Shortstring;
- LID : Windows.LCID;
- I,Day : longint;
- begin
- LID := LCID;
- with FormatSettings do
- begin
- { Date stuff }
- for I := 1 to 12 do
- begin
- ShortMonthNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVMONTHNAME1+I-1,ShortMonthNames[i]);
- LongMonthNames[I]:=GetLocaleStr(LID,LOCALE_SMONTHNAME1+I-1,LongMonthNames[i]);
- end;
- for I := 1 to 7 do
- begin
- Day := (I + 5) mod 7;
- ShortDayNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVDAYNAME1+Day,ShortDayNames[i]);
- LongDayNames[I]:=GetLocaleStr(LID,LOCALE_SDAYNAME1+Day,LongDayNames[i]);
- end;
- DateSeparator := GetLocaleChar(LID, LOCALE_SDATE, '/');
- ShortDateFormat := GetLocaleStr(LID, LOCALE_SSHORTDATE, 'm/d/yy');
- LongDateFormat := GetLocaleStr(LID, LOCALE_SLONGDATE, 'mmmm d, yyyy');
- { Time stuff }
- TimeSeparator := GetLocaleChar(LID, LOCALE_STIME, ':');
- TimeAMString := GetLocaleStr(LID, LOCALE_S1159, 'AM');
- TimePMString := GetLocaleStr(LID, LOCALE_S2359, 'PM');
- if StrToIntDef(GetLocaleStr(LID, LOCALE_ITLZERO, '0'), 0) = 0 then
- HF:='h'
- else
- HF:='hh';
- // No support for 12 hour stuff at the moment...
- ShortTimeFormat := HF+':nn';
- LongTimeFormat := HF + ':nn:ss';
- { Currency stuff }
- CurrencyString:=GetLocaleStr(LID, LOCALE_SCURRENCY, '');
- CurrencyFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRENCY, '0'), 0);
- NegCurrFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_INEGCURR, '0'), 0);
- { Number stuff }
- ThousandSeparator:=GetLocaleChar(LID, LOCALE_STHOUSAND, ',');
- DecimalSeparator:=GetLocaleChar(LID, LOCALE_SDECIMAL, '.');
- CurrencyDecimals:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRDIGITS, '0'), 0);
- ListSeparator := GetLocaleChar(LID, LOCALE_SLIST, ',');
- end;
- end;
- procedure GetFormatSettings;
- begin
- GetlocaleFormatSettings(GetThreadLocale, DefaultFormatSettings);
- end;
- Procedure InitLeadBytes;
- var
- I,B,C,E: Byte;
- Info: TCPInfo;
- begin
- GetCPInfo(CP_ACP,Info);
- I:=0;
- With Info do
- begin
- B:=LeadByte[i];
- E:=LeadByte[i+1];
- while (I<MAX_LEADBYTES) and (B<>0) and (E<>0) do
- begin
- for C:=B to E do
- Include(LeadBytes,AnsiChar(C));
- Inc(I,2);
- if (I<MAX_LEADBYTES) then
- begin
- B:=LeadByte[i];
- E:=LeadByte[i+1];
- end;
- end;
- end;
- end;
- Procedure InitInternational;
- var
- { A call to GetSystemMetrics changes the value of the 8087 Control Word on
- Pentium4 with WinXP SP2 }
- old8087CW: word;
- DefaultCustomLocaleID : LCID; // typedef DWORD LCID;
- DefaultCustomLanguageID : Word; // typedef WORD LANGID;
- begin
- /// workaround for Windows 7 bug, see bug report #18574
- SetThreadLocale(GetUserDefaultLCID);
- InitInternationalGeneric;
- old8087CW:=Get8087CW;
- SysLocale.MBCS:=GetSystemMetrics(SM_DBCSENABLED)<>0;
- SysLocale.RightToLeft:=GetSystemMetrics(SM_MIDEASTENABLED)<>0;
- SysLocale.DefaultLCID := $0409;
- SysLocale.PriLangID := LANG_ENGLISH;
- SysLocale.SubLangID := SUBLANG_ENGLISH_US;
- // probably needs update with getthreadlocale. post 2.0.2
- DefaultCustomLocaleID := GetThreadLocale;
- if DefaultCustomLocaleID <> 0 then
- begin
- { Locale Identifiers
- +-------------+---------+-------------------------+
- | Reserved | Sort ID | Language ID |
- +-------------+---------+-------------------------+
- 31 20 19 16 15 0 bit }
- DefaultCustomLanguageID := DefaultCustomLocaleID and $FFFF; // 2^16
- if DefaultCustomLanguageID <> 0 then
- begin
- SysLocale.DefaultLCID := DefaultCustomLocaleID;
- { Language Identifiers
- +-------------------------+-------------------------+
- | SubLanguage ID | Primary Language ID |
- +-------------------------+-------------------------+
- 15 10 9 0 bit }
- SysLocale.PriLangID := DefaultCustomLanguageID and $3ff; // 2^10
- SysLocale.SubLangID := DefaultCustomLanguageID shr 10;
- end;
- end;
- Set8087CW(old8087CW);
- GetFormatSettings;
- if SysLocale.FarEast then GetEraNamesAndYearOffsets;
- end;
- {****************************************************************************
- Target Dependent
- ****************************************************************************}
- function SysErrorMessage(ErrorCode: Integer): String;
- const
- MaxMsgSize = Format_Message_Max_Width_Mask;
- var
- MsgBuffer: unicodestring;
- len: longint;
- begin
- SetLength(MsgBuffer, MaxMsgSize);
- len := FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
- nil,
- ErrorCode,
- MakeLangId(LANG_NEUTRAL, SUBLANG_DEFAULT),
- PUnicodeChar(MsgBuffer),
- MaxMsgSize,
- nil);
- // Remove trailing #13#10
- if (len > 1) and (MsgBuffer[len - 1] = #13) and (MsgBuffer[len] = #10) then
- Dec(len, 2);
- SetLength(MsgBuffer, len);
- Result := MsgBuffer;
- end;
- {****************************************************************************
- Initialization code
- ****************************************************************************}
- {$push}
- { GetEnvironmentStrings cannot be checked by CheckPointer function }
- {$checkpointer off}
- Function GetEnvironmentVariable(Const EnvVar : String) : String;
- var
- oemenvvar, oemstr : RawByteString;
- i, hplen : longint;
- hp,p : pchar;
- begin
- oemenvvar:=uppercase(envvar);
- SetCodePage(oemenvvar,CP_OEMCP);
- Result:='';
- p:=GetEnvironmentStringsA;
- hp:=p;
- while hp^<>#0 do
- begin
- oemstr:=hp;
- { cache length, may change after uppercasing depending on code page }
- hplen:=length(oemstr);
- { all environment variables are encoded in the oem code page }
- SetCodePage(oemstr,CP_OEMCP,false);
- i:=pos('=',oemstr);
- if uppercase(copy(oemstr,1,i-1))=oemenvvar then
- begin
- Result:=copy(oemstr,i+1,length(oemstr)-i);
- break;
- end;
- { next string entry}
- hp:=hp+hplen+1;
- end;
- FreeEnvironmentStringsA(p);
- end;
- Function GetEnvironmentVariable(Const EnvVar : UnicodeString) : UnicodeString;
- var
- s, upperenv : Unicodestring;
- i : longint;
- hp,p : pwidechar;
- begin
- Result:='';
- p:=GetEnvironmentStringsW;
- hp:=p;
- upperenv:=uppercase(envvar);
- while hp^<>#0 do
- begin
- s:=hp;
- i:=pos('=',s);
- if uppercase(copy(s,1,i-1))=upperenv then
- begin
- Result:=copy(s,i+1,length(s)-i);
- break;
- end;
- { next string entry}
- hp:=hp+strlen(hp)+1;
- end;
- FreeEnvironmentStringsW(p);
- end;
- Function GetEnvironmentVariableCount : Integer;
- var
- hp,p : pchar;
- begin
- Result:=0;
- p:=GetEnvironmentStringsA;
- hp:=p;
- If (Hp<>Nil) then
- while hp^<>#0 do
- begin
- Inc(Result);
- hp:=hp+strlen(hp)+1;
- end;
- FreeEnvironmentStringsA(p);
- end;
- Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
- var
- hp,p : pchar;
- {$ifdef FPC_RTL_UNICODE}
- tmpstr : RawByteString;
- {$endif}
- begin
- Result:='';
- p:=GetEnvironmentStringsA;
- hp:=p;
- If (Hp<>Nil) then
- begin
- while (hp^<>#0) and (Index>1) do
- begin
- Dec(Index);
- hp:=hp+strlen(hp)+1;
- end;
- If (hp^<>#0) then
- begin
- {$ifdef FPC_RTL_UNICODE}
- tmpstr:=hp;
- SetCodePage(tmpstr,CP_OEMCP,false);
- Result:=tmpstr;
- {$else}
- Result:=hp;
- SetCodePage(RawByteString(Result),CP_OEMCP,false);
- {$endif}
- end;
- end;
- FreeEnvironmentStringsA(p);
- end;
- {$pop}
- function ExecuteProcess(Const Path: RawByteString; Const ComLine: RawByteString;Flags:TExecuteFlags=[]):integer;
- begin
- result:=ExecuteProcess(Unicodestring(Path),UnicodeString(ComLine),Flags);
- end;
- function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
- // win specific function
- var
- SI: TStartupInfoW;
- PI: TProcessInformation;
- Proc : THandle;
- l : DWord;
- CommandLine : unicodestring;
- e : EOSError;
- ExecInherits : longbool;
- begin
- FillChar(SI, SizeOf(SI), 0);
- SI.cb:=SizeOf(SI);
- SI.wShowWindow:=1;
- { always surround the name of the application by quotes
- so that long filenames will always be accepted. But don't
- do it if there are already double quotes, since Win32 does not
- like double quotes which are duplicated!
- }
- if pos('"',path)=0 then
- CommandLine:='"'+path+'"'
- else
- CommandLine:=path;
- if ComLine <> '' then
- CommandLine:=Commandline+' '+ComLine+#0
- else
- CommandLine := CommandLine + #0;
- ExecInherits:=ExecInheritsHandles in Flags;
- if not CreateProcessW(nil, pwidechar(CommandLine),
- Nil, Nil, ExecInherits,$20, Nil, Nil, SI, PI) then
- begin
- e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
- e.ErrorCode:=GetLastError;
- raise e;
- end;
- Proc:=PI.hProcess;
- if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then
- begin
- GetExitCodeProcess(Proc,l);
- CloseHandle(Proc);
- CloseHandle(PI.hThread);
- result:=l;
- end
- else
- begin
- e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
- e.ErrorCode:=GetLastError;
- CloseHandle(Proc);
- CloseHandle(PI.hThread);
- raise e;
- end;
- end;
- function ExecuteProcess(Const Path: RawByteString; Const ComLine: Array of RawByteString;Flags:TExecuteFlags=[]):integer;
- var
- CommandLine: UnicodeString;
- I: integer;
- begin
- Commandline := '';
- for I := 0 to High (ComLine) do
- if Pos (' ', ComLine [I]) <> 0 then
- CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
- else
- CommandLine := CommandLine + ' ' + Comline [I];
- ExecuteProcess := ExecuteProcess (UnicodeString(Path), CommandLine,Flags);
- end;
- function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
- var
- CommandLine: UnicodeString;
- I: integer;
- begin
- Commandline := '';
- for I := 0 to High (ComLine) do
- if Pos (' ', ComLine [I]) <> 0 then
- CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
- else
- CommandLine := CommandLine + ' ' + Comline [I];
- ExecuteProcess := ExecuteProcess (Path,CommandLine,Flags);
- end;
- Procedure Sleep(Milliseconds : Cardinal);
- begin
- Windows.Sleep(MilliSeconds)
- end;
- Function GetLastOSError : Integer;
- begin
- Result:=GetLastError;
- end;
- {****************************************************************************
- Initialization code
- ****************************************************************************}
- var
- kernel32dll : THandle;
- Procedure LoadVersionInfo;
- // and getfreespaceex
- Var
- versioninfo : TOSVERSIONINFO;
- begin
- GetDiskFreeSpaceEx:=nil;
- versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
- GetVersionEx(versioninfo);
- Win32Platform:=versionInfo.dwPlatformId;
- Win32MajorVersion:=versionInfo.dwMajorVersion;
- Win32MinorVersion:=versionInfo.dwMinorVersion;
- Win32BuildNumber:=versionInfo.dwBuildNumber;
- Move (versioninfo.szCSDVersion ,Win32CSDVersion[1],128);
- win32CSDVersion[0]:=chr(strlen(pchar(@versioninfo.szCSDVersion)));
- kernel32dll:=GetModuleHandle('kernel32');
- if kernel32dll<>0 then
- GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
- if Win32MajorVersion<6 then
- FindExInfoDefaults := FindExInfoStandard; // also searches SFNs. XP only.
- if (Win32MajorVersion>=6) and (Win32MinorVersion>=1) then
- FindFirstAdditionalFlags := FIND_FIRST_EX_LARGE_FETCH; // win7 and 2008R2+
- end;
- Function GetAppConfigDir(Global : Boolean) : String;
- begin
- If Global then
- Result:=GetWindowsSpecialDir(CSIDL_COMMON_APPDATA)
- else
- Result:=GetWindowsSpecialDir(CSIDL_LOCAL_APPDATA);
- If (Result<>'') then
- begin
- if VendorName<>'' then
- Result:=IncludeTrailingPathDelimiter(Result+VendorName);
- Result:=IncludeTrailingPathDelimiter(Result+ApplicationName);
- end
- else
- Result:=IncludeTrailingPathDelimiter(DGetAppConfigDir(Global));
- end;
- Function GetAppConfigFile(Global : Boolean; SubDir : Boolean) : String;
- begin
- result:=DGetAppConfigFile(Global,SubDir);
- end;
- Function GetUserDir : String;
- begin
- Result:=GetWindowsSpecialDir(CSIDL_PROFILE);
- end;
- Procedure InitSysConfigDir;
- begin
- SetLength(SysConfigDir, MAX_PATH);
- SetLength(SysConfigDir, GetWindowsDirectoryA(PChar(SysConfigDir), MAX_PATH));
- end;
- {****************************************************************************
- Target Dependent WideString stuff
- ****************************************************************************}
- { This is the case of Win9x. Limited to current locale of course, but it's better
- than not working at all. }
- function DoCompareStringA(P1, P2: PWideChar; L1, L2: PtrUInt; Flags: DWORD): PtrInt;
- var
- a1, a2: AnsiString;
- begin
- if L1>0 then
- widestringmanager.Wide2AnsiMoveProc(P1,a1,DefaultSystemCodePage,L1);
- if L2>0 then
- widestringmanager.Wide2AnsiMoveProc(P2,a2,DefaultSystemCodePage,L2);
- SetLastError(0);
- Result:=CompareStringA(LOCALE_USER_DEFAULT,Flags,pchar(a1),
- length(a1),pchar(a2),length(a2))-2;
- end;
- function DoCompareStringW(P1, P2: PWideChar; L1, L2: PtrUInt; Flags: DWORD): PtrInt;
- begin
- SetLastError(0);
- Result:=CompareStringW(LOCALE_USER_DEFAULT,Flags,P1,L1,P2,L2)-2;
- if GetLastError=0 then
- Exit;
- if GetLastError=ERROR_CALL_NOT_IMPLEMENTED then // Win9x case
- Result:=DoCompareStringA(P1, P2, L1, L2, Flags);
- if GetLastError<>0 then
- RaiseLastOSError;
- end;
- const
- WinAPICompareFlags : array [TCompareOption] of LongWord
- = ({LINGUISTIC_IGNORECASE, LINGUISTIC_IGNOREDIACRITIC, }NORM_IGNORECASE{,
- NORM_IGNOREKANATYPE, NORM_IGNORENONSPACE, NORM_IGNORESYMBOLS, NORM_IGNOREWIDTH,
- NORM_LINGUISTIC_CASING, SORT_DIGITSASNUMBERS, SORT_STRINGSORT});
- function Win32CompareWideString(const s1, s2 : WideString; Options : TCompareOptions) : PtrInt;
- Var
- O : LongWord;
- CO : TCompareOption;
- begin
- O:=0;
- for CO in TCompareOption do
- if CO in Options then
- O:=O or WinAPICompareFlags[CO];
- Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), O);
- end;
- function Win32CompareTextWideString(const s1, s2 : WideString) : PtrInt;
- begin
- Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), NORM_IGNORECASE);
- end;
- function Win32AnsiUpperCase(const s: string): string;
- begin
- if length(s)>0 then
- begin
- result:=s;
- UniqueString(result);
- CharUpperBuffA(pchar(result),length(result));
- end
- else
- result:='';
- end;
- function Win32AnsiLowerCase(const s: string): string;
- begin
- if length(s)>0 then
- begin
- result:=s;
- UniqueString(result);
- CharLowerBuffA(pchar(result),length(result));
- end
- else
- result:='';
- end;
- function Win32AnsiCompareStr(const S1, S2: string): PtrInt;
- begin
- result:=CompareStringA(LOCALE_USER_DEFAULT,0,pchar(s1),length(s1),
- pchar(s2),length(s2))-2;
- end;
- function Win32AnsiCompareText(const S1, S2: string): PtrInt;
- begin
- result:=CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE,pchar(s1),length(s1),
- pchar(s2),length(s2))-2;
- end;
- function Win32AnsiStrComp(S1, S2: PChar): PtrInt;
- begin
- result:=CompareStringA(LOCALE_USER_DEFAULT,0,s1,-1,s2,-1)-2;
- end;
- function Win32AnsiStrIComp(S1, S2: PChar): PtrInt;
- begin
- result:=CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE,s1,-1,s2,-1)-2;
- end;
- function Win32AnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
- begin
- result:=CompareStringA(LOCALE_USER_DEFAULT,0,s1,maxlen,s2,maxlen)-2;
- end;
- function Win32AnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
- begin
- result:=CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE,s1,maxlen,s2,maxlen)-2;
- end;
- function Win32AnsiStrLower(Str: PChar): PChar;
- begin
- CharLowerA(str);
- result:=str;
- end;
- function Win32AnsiStrUpper(Str: PChar): PChar;
- begin
- CharUpperA(str);
- result:=str;
- end;
- function Win32CompareUnicodeString(const s1, s2 : UnicodeString; Options : TCompareOptions) : PtrInt;
- Var
- O : LongWord;
- CO : TCompareOption;
- begin
- O:=0;
- for CO in TCompareOption do
- if CO in Options then
- O:=O or WinAPICompareFlags[CO];
- Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), O);
- end;
- function Win32CompareTextUnicodeString(const s1, s2 : UnicodeString) : PtrInt;
- begin
- Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), NORM_IGNORECASE);
- end;
- { there is a similiar procedure in the system unit which inits the fields which
- are relevant already for the system unit }
- procedure InitWin32Widestrings;
- begin
- { return value: number of code points in the string. Whenever an invalid
- code point is encountered, all characters part of this invalid code point
- are considered to form one "character" and the next character is
- considered to be the start of a new (possibly also invalid) code point }
- //!!! CharLengthPCharProc : function(const Str: PChar): PtrInt;
- { return value:
- -1 if incomplete or invalid code point
- 0 if NULL character,
- > 0 if that's the length in bytes of the code point }
- //!!!! CodePointLengthProc : function(const Str: PChar; MaxLookAead: PtrInt): Ptrint;
- widestringmanager.CompareWideStringProc:=@Win32CompareWideString;
- widestringmanager.UpperAnsiStringProc:=@Win32AnsiUpperCase;
- widestringmanager.LowerAnsiStringProc:=@Win32AnsiLowerCase;
- widestringmanager.CompareStrAnsiStringProc:=@Win32AnsiCompareStr;
- widestringmanager.CompareTextAnsiStringProc:=@Win32AnsiCompareText;
- widestringmanager.StrCompAnsiStringProc:=@Win32AnsiStrComp;
- widestringmanager.StrICompAnsiStringProc:=@Win32AnsiStrIComp;
- widestringmanager.StrLCompAnsiStringProc:=@Win32AnsiStrLComp;
- widestringmanager.StrLICompAnsiStringProc:=@Win32AnsiStrLIComp;
- widestringmanager.StrLowerAnsiStringProc:=@Win32AnsiStrLower;
- widestringmanager.StrUpperAnsiStringProc:=@Win32AnsiStrUpper;
- widestringmanager.CompareUnicodeStringProc:=@Win32CompareUnicodeString;
- end;
- { Platform-specific exception support }
- function WinExceptionObject(code: Longint; const rec: TExceptionRecord): Exception;
- var
- entry: PExceptMapEntry;
- begin
- entry := FindExceptMapEntry(code);
- if assigned(entry) then
- result:=entry^.cls.CreateRes(entry^.msg)
- else
- result:=EExternalException.CreateResFmt(@SExternalException,[rec.ExceptionCode]);
- if result is EExternal then
- EExternal(result).FExceptionRecord:=rec;
- end;
- function WinExceptionClass(code: longint): ExceptClass;
- var
- entry: PExceptMapEntry;
- begin
- entry := FindExceptMapEntry(code);
- if assigned(entry) then
- result:=entry^.cls
- else
- result:=EExternalException;
- end;
- Initialization
- InitWin32Widestrings;
- InitExceptions; { Initialize exceptions. OS independent }
- {$ifdef mswindows} { Keeps exe size down for systems that do not use SEH }
- ExceptObjProc:=@WinExceptionObject;
- ExceptClsProc:=@WinExceptionClass;
- {$endif mswindows}
- InitLeadBytes;
- InitInternational; { Initialize internationalization settings }
- LoadVersionInfo;
- InitSysConfigDir;
- OnBeep:=@SysBeep;
- Finalization
- DoneExceptions;
- FreeTerminateProcs;
- end.
|