sysutils.pp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for win32
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH OUT}
  16. { force ansistrings }
  17. {$H+}
  18. uses
  19. windows;
  20. {$DEFINE HAS_SLEEP}
  21. {$DEFINE HAS_OSERROR}
  22. {$DEFINE HAS_OSCONFIG}
  23. {$DEFINE HAS_OSUSERDIR}
  24. {$DEFINE HAS_CREATEGUID}
  25. {$DEFINE HAS_LOCALTIMEZONEOFFSET}
  26. {$DEFINE HAS_GETTICKCOUNT}
  27. {$DEFINE HAS_GETTICKCOUNT64}
  28. { Include platform independent interface part }
  29. {$i sysutilh.inc}
  30. type
  31. TSystemTime = Windows.TSystemTime;
  32. EWin32Error = class(Exception)
  33. public
  34. ErrorCode : DWORD;
  35. end;
  36. Var
  37. Win32Platform : Longint;
  38. Win32MajorVersion,
  39. Win32MinorVersion,
  40. Win32BuildNumber : dword;
  41. Win32CSDVersion : ShortString; // CSD record is 128 bytes only?
  42. const
  43. MaxEraCount = 7;
  44. var
  45. EraNames: array [1..MaxEraCount] of String;
  46. EraYearOffsets: array [1..MaxEraCount] of Integer;
  47. { Compatibility with Delphi }
  48. function Win32Check(res:boolean):boolean;inline;
  49. function WinCheck(res:boolean):boolean;
  50. function CheckWin32Version(Major,Minor : Integer ): Boolean;
  51. function CheckWin32Version(Major : Integer): Boolean;
  52. Procedure RaiseLastWin32Error;
  53. function GetFileVersion(const AFileName: string): Cardinal;
  54. procedure GetFormatSettings;
  55. procedure GetLocaleFormatSettings(LCID: Integer; var FormatSettings: TFormatSettings); platform;
  56. implementation
  57. uses
  58. sysconst,
  59. windirs;
  60. function WinCheck(res:boolean):boolean;
  61. begin
  62. if not res then
  63. RaiseLastOSError;
  64. result:=res;
  65. end;
  66. function Win32Check(res:boolean):boolean;inline;
  67. begin
  68. result:=WinCheck(res);
  69. end;
  70. procedure RaiseLastWin32Error;
  71. begin
  72. RaiseLastOSError;
  73. end;
  74. function CheckWin32Version(Major : Integer): Boolean;
  75. begin
  76. Result:=CheckWin32Version(Major,0)
  77. end;
  78. function CheckWin32Version(Major,Minor: Integer): Boolean;
  79. begin
  80. Result:=(Win32MajorVersion>dword(Major)) or
  81. ((Win32MajorVersion=dword(Major)) and (Win32MinorVersion>=dword(Minor)));
  82. end;
  83. function GetFileVersion(const AFileName:string):Cardinal;
  84. var
  85. { useful only as long as we don't need to touch different stack pages }
  86. buf : array[0..3071] of byte;
  87. bufp : pointer;
  88. fn : string;
  89. valsize,
  90. size : DWORD;
  91. h : DWORD;
  92. valrec : PVSFixedFileInfo;
  93. begin
  94. result:=$fffffff;
  95. fn:=AFileName;
  96. UniqueString(fn);
  97. size:=GetFileVersionInfoSizeA(pchar(fn),@h);
  98. if size>sizeof(buf) then
  99. begin
  100. getmem(bufp,size);
  101. try
  102. if GetFileVersionInfoA(pchar(fn),h,size,bufp) then
  103. if VerQueryValue(bufp,'\',valrec,valsize) then
  104. result:=valrec^.dwFileVersionMS;
  105. finally
  106. freemem(bufp);
  107. end;
  108. end
  109. else
  110. begin
  111. if GetFileVersionInfoA(pchar(fn),h,size,@buf) then
  112. if VerQueryValue(@buf,'\',valrec,valsize) then
  113. result:=valrec^.dwFileVersionMS;
  114. end;
  115. end;
  116. {$define HASCREATEGUID}
  117. {$define HASEXPANDUNCFILENAME}
  118. {$DEFINE FPC_NOGENERICANSIROUTINES}
  119. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  120. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  121. {define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  122. {$define SYSUTILS_HAS_UNICODESTR_FILEUTIL_IMPL}
  123. function ConvertEraYearString(Count ,Year,Month,Day : integer) : string; forward;
  124. function ConvertEraString(Count ,Year,Month,Day : integer) : string; forward;
  125. { Include platform independent implementation part }
  126. {$i sysutils.inc}
  127. function GetTempFileName(Dir,Prefix: PChar; uUnique: DWORD; TempFileName: PChar):DWORD;
  128. begin
  129. Result:= Windows.GetTempFileNameA(Dir,Prefix,uUnique,TempFileName);
  130. end;
  131. { UUID generation. }
  132. function CoCreateGuid(out guid: TGUID): HResult; stdcall; external 'ole32.dll' name 'CoCreateGuid';
  133. function SysCreateGUID(out Guid: TGUID): Integer;
  134. begin
  135. Result := Integer(CoCreateGuid(Guid));
  136. end;
  137. function ExpandUNCFileName (const filename:string) : string;
  138. { returns empty string on errors }
  139. var
  140. s : ansistring;
  141. size : dword;
  142. rc : dword;
  143. buf : pchar;
  144. begin
  145. s := ExpandFileName (filename);
  146. s := s + #0;
  147. size := max_path;
  148. getmem(buf,size);
  149. try
  150. rc := WNetGetUniversalNameA (pchar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
  151. if rc=ERROR_MORE_DATA then
  152. begin
  153. buf:=reallocmem(buf,size);
  154. rc := WNetGetUniversalNameA (pchar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
  155. end;
  156. if rc = NO_ERROR then
  157. Result := PRemoteNameInfo(buf)^.lpUniversalName
  158. else if rc = ERROR_NOT_CONNECTED then
  159. Result := filename
  160. else
  161. Result := '';
  162. finally
  163. freemem(buf);
  164. end;
  165. end;
  166. function ExpandUNCFileName (const filename:unicodestring) : string;
  167. { returns empty string on errors }
  168. var
  169. s : unicodestring;
  170. size : dword;
  171. rc : dword;
  172. buf : pwidechar;
  173. begin
  174. s := ExpandFileName (filename);
  175. s := s + #0;
  176. size := max_path;
  177. getmem(buf,size);
  178. try
  179. rc := WNetGetUniversalNameW (pwidechar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
  180. if rc=ERROR_MORE_DATA then
  181. begin
  182. buf:=reallocmem(buf,size);
  183. rc := WNetGetUniversalNameW (pwidechar(s), UNIVERSAL_NAME_INFO_LEVEL, buf, @size);
  184. end;
  185. if rc = NO_ERROR then
  186. Result := PRemoteNameInfo(buf)^.lpUniversalName
  187. else if rc = ERROR_NOT_CONNECTED then
  188. Result := filename
  189. else
  190. Result := '';
  191. finally
  192. freemem(buf);
  193. end;
  194. end;
  195. {****************************************************************************
  196. File Functions
  197. ****************************************************************************}
  198. const
  199. AccessMode: array[0..2] of Cardinal = (
  200. GENERIC_READ,
  201. GENERIC_WRITE,
  202. GENERIC_READ or GENERIC_WRITE or FILE_WRITE_ATTRIBUTES);
  203. ShareModes: array[0..4] of Integer = (
  204. 0,
  205. 0,
  206. FILE_SHARE_READ,
  207. FILE_SHARE_WRITE,
  208. FILE_SHARE_READ or FILE_SHARE_WRITE);
  209. Function FileOpen (Const FileName : unicodestring; Mode : Integer) : THandle;
  210. begin
  211. result := CreateFileW(PWideChar(FileName), dword(AccessMode[Mode and 3]),
  212. dword(ShareModes[(Mode and $F0) shr 4]), nil, OPEN_EXISTING,
  213. FILE_ATTRIBUTE_NORMAL, 0);
  214. //if fail api return feInvalidHandle (INVALIDE_HANDLE=feInvalidHandle=-1)
  215. end;
  216. Function FileCreate (Const FileName : UnicodeString) : THandle;
  217. begin
  218. FileCreate:=FileCreate(FileName, fmShareExclusive, 0);
  219. end;
  220. Function FileCreate (Const FileName : UnicodeString; Rights:longint) : THandle;
  221. begin
  222. FileCreate:=FileCreate(FileName, fmShareExclusive, Rights);
  223. end;
  224. Function FileCreate (Const FileName : UnicodeString; ShareMode : Integer; Rights : Integer) : THandle;
  225. begin
  226. Result := CreateFileW(PwideChar(FileName), GENERIC_READ or GENERIC_WRITE,
  227. dword(ShareModes[(ShareMode and $F0) shr 4]), nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  228. end;
  229. Function FileRead (Handle : THandle; out Buffer; Count : longint) : Longint;
  230. Var
  231. res : dword;
  232. begin
  233. if ReadFile(Handle, Buffer, Count, res, nil) then
  234. FileRead:=Res
  235. else
  236. FileRead:=-1;
  237. end;
  238. Function FileWrite (Handle : THandle; const Buffer; Count : Longint) : Longint;
  239. Var
  240. Res : dword;
  241. begin
  242. if WriteFile(Handle, Buffer, Count, Res, nil) then
  243. FileWrite:=Res
  244. else
  245. FileWrite:=-1;
  246. end;
  247. Function FileSeek (Handle : THandle;FOffset,Origin : Longint) : Longint;
  248. begin
  249. Result := longint(SetFilePointer(Handle, FOffset, nil, Origin));
  250. end;
  251. Function FileSeek (Handle : THandle; FOffset: Int64; Origin: Longint) : Int64;
  252. var
  253. rslt: Int64Rec;
  254. begin
  255. rslt := Int64Rec(FOffset);
  256. rslt.lo := SetFilePointer(Handle, rslt.lo, @rslt.hi, Origin);
  257. if (rslt.lo = $FFFFFFFF) and (GetLastError <> 0) then
  258. rslt.hi := $FFFFFFFF;
  259. Result := Int64(rslt);
  260. end;
  261. Procedure FileClose (Handle : THandle);
  262. begin
  263. if Handle<=4 then
  264. exit;
  265. CloseHandle(Handle);
  266. end;
  267. Function FileTruncate (Handle : THandle;Size: Int64) : boolean;
  268. begin
  269. {
  270. Result:=longint(SetFilePointer(handle,Size,nil,FILE_BEGIN))<>-1;
  271. }
  272. if FileSeek (Handle, Size, FILE_BEGIN) = Size then
  273. Result:=SetEndOfFile(handle)
  274. else
  275. Result := false;
  276. end;
  277. Function DosToWinTime (DTime:longint;Var Wtime : TFileTime):longbool;
  278. var
  279. lft : TFileTime;
  280. begin
  281. DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,@lft) and
  282. LocalFileTimeToFileTime(lft,Wtime);
  283. end;
  284. Function WinToDosTime (Var Wtime : TFileTime;var DTime:longint):longbool;
  285. var
  286. lft : TFileTime;
  287. begin
  288. WinToDosTime:=FileTimeToLocalFileTime(WTime,lft) and
  289. FileTimeToDosDateTime(lft,Longrec(Dtime).Hi,LongRec(DTIME).lo);
  290. end;
  291. Function FileAge (Const FileName : UnicodeString): Longint;
  292. var
  293. Handle: THandle;
  294. FindData: TWin32FindDataW;
  295. begin
  296. Handle := FindFirstFileW(Pwidechar(FileName), FindData);
  297. if Handle <> INVALID_HANDLE_VALUE then
  298. begin
  299. Windows.FindClose(Handle);
  300. if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
  301. If WinToDosTime(FindData.ftLastWriteTime,Result) then
  302. exit;
  303. end;
  304. Result := -1;
  305. end;
  306. Function FileExists (Const FileName : UnicodeString) : Boolean;
  307. var
  308. Attr:Dword;
  309. begin
  310. Attr:=GetFileAttributesW(PWideChar(FileName));
  311. if Attr <> $ffffffff then
  312. Result:= (Attr and FILE_ATTRIBUTE_DIRECTORY) = 0
  313. else
  314. Result:=False;
  315. end;
  316. Function DirectoryExists (Const Directory : UnicodeString) : Boolean;
  317. var
  318. Attr:Dword;
  319. begin
  320. Attr:=GetFileAttributesW(PWideChar(Directory));
  321. if Attr <> $ffffffff then
  322. Result:= (Attr and FILE_ATTRIBUTE_DIRECTORY) > 0
  323. else
  324. Result:=False;
  325. end;
  326. Function FindMatch(var f: TRawByteSearchRec) : Longint;
  327. begin
  328. { Find file with correct attribute }
  329. While (F.FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  330. begin
  331. if not FindNextFileA (F.FindHandle,F.FindData) then
  332. begin
  333. Result:=GetLastError;
  334. exit;
  335. end;
  336. end;
  337. { Convert some attributes back }
  338. WinToDosTime(F.FindData.ftLastWriteTime,F.Time);
  339. f.size:=F.FindData.NFileSizeLow+(qword(maxdword)+1)*F.FindData.NFileSizeHigh;
  340. f.attr:=F.FindData.dwFileAttributes;
  341. f.Name:=F.FindData.cFileName;
  342. Result:=0;
  343. end;
  344. Function FindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TRawByteSearchRec) : Longint;
  345. begin
  346. Rslt.Name:=Path;
  347. Rslt.Attr:=attr;
  348. Rslt.ExcludeAttr:=(not Attr) and ($1e);
  349. { $1e = faHidden or faSysFile or faVolumeID or faDirectory }
  350. { FindFirstFile is a Win32 Call }
  351. Rslt.FindHandle:=FindFirstFileA (PChar(Path),Rslt.FindData);
  352. If Rslt.FindHandle=Invalid_Handle_value then
  353. begin
  354. Result:=GetLastError;
  355. exit;
  356. end;
  357. { Find file with correct attribute }
  358. Result:=FindMatch(Rslt);
  359. end;
  360. Function FindNext (Var Rslt : TRawByteSearchRec) : Longint;
  361. begin
  362. if FindNextFileA(Rslt.FindHandle, Rslt.FindData) then
  363. Result := FindMatch(Rslt)
  364. else
  365. Result := GetLastError;
  366. end;
  367. Procedure FindClose (Var F : TRawByteSearchRec);
  368. begin
  369. if F.FindHandle <> INVALID_HANDLE_VALUE then
  370. Windows.FindClose(F.FindHandle);
  371. end;
  372. Function FindMatch(var f: TUnicodeSearchRec) : Longint;
  373. begin
  374. { Find file with correct attribute }
  375. While (F.FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  376. begin
  377. if not FindNextFileW (F.FindHandle,F.FindData) then
  378. begin
  379. Result:=GetLastError;
  380. exit;
  381. end;
  382. end;
  383. { Convert some attributes back }
  384. WinToDosTime(F.FindData.ftLastWriteTime,F.Time);
  385. f.size:=F.FindData.NFileSizeLow+(qword(maxdword)+1)*F.FindData.NFileSizeHigh;
  386. f.attr:=F.FindData.dwFileAttributes;
  387. f.Name:=F.FindData.cFileName;
  388. Result:=0;
  389. end;
  390. Function FindFirst (Const Path : UnicodeString; Attr : Longint; out Rslt : TUnicodeSearchRec) : Longint;
  391. begin
  392. Rslt.Name:=Path;
  393. Rslt.Attr:=attr;
  394. Rslt.ExcludeAttr:=(not Attr) and ($1e);
  395. { $1e = faHidden or faSysFile or faVolumeID or faDirectory }
  396. { FindFirstFile is a Win32 Call }
  397. Rslt.FindHandle:=FindFirstFileW (PWideChar(Path),Rslt.FindData);
  398. If Rslt.FindHandle=Invalid_Handle_value then
  399. begin
  400. Result:=GetLastError;
  401. exit;
  402. end;
  403. { Find file with correct attribute }
  404. Result:=FindMatch(Rslt);
  405. end;
  406. Function FindNext (Var Rslt : TUnicodeSearchRec) : Longint;
  407. begin
  408. if FindNextFileW(Rslt.FindHandle, Rslt.FindData) then
  409. Result := FindMatch(Rslt)
  410. else
  411. Result := GetLastError;
  412. end;
  413. Procedure FindClose (Var F : TUnicodeSearchrec);
  414. begin
  415. if F.FindHandle <> INVALID_HANDLE_VALUE then
  416. Windows.FindClose(F.FindHandle);
  417. end;
  418. Function FileGetDate (Handle : THandle) : Longint;
  419. Var
  420. FT : TFileTime;
  421. begin
  422. If GetFileTime(Handle,nil,nil,@ft) and
  423. WinToDosTime(FT,Result) then
  424. exit;
  425. Result:=-1;
  426. end;
  427. Function FileSetDate (Handle : THandle;Age : Longint) : Longint;
  428. Var
  429. FT: TFileTime;
  430. begin
  431. Result := 0;
  432. if DosToWinTime(Age,FT) and
  433. SetFileTime(Handle, nil, nil, @FT) then
  434. Exit;
  435. Result := GetLastError;
  436. end;
  437. {Function FileGetAttr (Const FileName : String) : Longint;
  438. begin
  439. Result:=Longint(GetFileAttributesA(PChar(FileName)));
  440. end;
  441. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  442. begin
  443. if SetFileAttributesA(PChar(FileName), Attr) then
  444. Result:=0
  445. else
  446. Result := GetLastError;
  447. end;
  448. Function DeleteFile (Const FileName : String) : Boolean;
  449. begin
  450. Result:=Windows.DeleteFileA(Pchar(FileName));
  451. end;
  452. Function RenameFile (Const OldName, NewName : String) : Boolean;
  453. begin
  454. Result := MoveFileA(PChar(OldName), PChar(NewName));
  455. end;
  456. }
  457. Function FileGetAttr (Const FileName : UnicodeString) : Longint;
  458. begin
  459. Result:=Longint(GetFileAttributesW(PWideChar(FileName)));
  460. end;
  461. Function FileSetAttr (Const Filename : UnicodeString; Attr: longint) : Longint;
  462. begin
  463. if SetFileAttributesW(PWideChar(FileName), Attr) then
  464. Result:=0
  465. else
  466. Result := GetLastError;
  467. end;
  468. Function DeleteFile (Const FileName : UnicodeString) : Boolean;
  469. begin
  470. Result:=Windows.DeleteFileW(PWidechar(FileName));
  471. end;
  472. Function RenameFile (Const OldName, NewName : UnicodeString) : Boolean;
  473. begin
  474. Result := MoveFileW(PWideChar(OldName), PWideChar(NewName));
  475. end;
  476. {****************************************************************************
  477. Disk Functions
  478. ****************************************************************************}
  479. type
  480. TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,total,free):longbool;stdcall;
  481. var
  482. GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
  483. function diskfree(drive : byte) : int64;
  484. var
  485. disk : array[1..4] of char;
  486. secs,bytes,
  487. free,total : dword;
  488. qwtotal,qwfree,qwcaller : int64;
  489. begin
  490. if drive=0 then
  491. begin
  492. disk[1]:='\';
  493. disk[2]:=#0;
  494. end
  495. else
  496. begin
  497. disk[1]:=chr(drive+64);
  498. disk[2]:=':';
  499. disk[3]:='\';
  500. disk[4]:=#0;
  501. end;
  502. if assigned(GetDiskFreeSpaceEx) then
  503. begin
  504. if GetDiskFreeSpaceEx(@disk[1],qwcaller,qwtotal,qwfree) then
  505. diskfree:=qwfree
  506. else
  507. diskfree:=-1;
  508. end
  509. else
  510. begin
  511. if GetDiskFreeSpace(@disk[1],secs,bytes,free,total) then
  512. diskfree:=int64(free)*secs*bytes
  513. else
  514. diskfree:=-1;
  515. end;
  516. end;
  517. function disksize(drive : byte) : int64;
  518. var
  519. disk : array[1..4] of char;
  520. secs,bytes,
  521. free,total : dword;
  522. qwtotal,qwfree,qwcaller : int64;
  523. begin
  524. if drive=0 then
  525. begin
  526. disk[1]:='\';
  527. disk[2]:=#0;
  528. end
  529. else
  530. begin
  531. disk[1]:=chr(drive+64);
  532. disk[2]:=':';
  533. disk[3]:='\';
  534. disk[4]:=#0;
  535. end;
  536. if assigned(GetDiskFreeSpaceEx) then
  537. begin
  538. if GetDiskFreeSpaceEx(@disk[1],qwcaller,qwtotal,qwfree) then
  539. disksize:=qwtotal
  540. else
  541. disksize:=-1;
  542. end
  543. else
  544. begin
  545. if GetDiskFreeSpace(@disk[1],secs,bytes,free,total) then
  546. disksize:=int64(total)*secs*bytes
  547. else
  548. disksize:=-1;
  549. end;
  550. end;
  551. Function GetCurrentDir : String;
  552. begin
  553. GetDir(0, result);
  554. end;
  555. Function SetCurrentDir (Const NewDir : String) : Boolean;
  556. begin
  557. Result:=SetCurrentDirectoryA(PChar(NewDir));
  558. end;
  559. Function CreateDir (Const NewDir : String) : Boolean;
  560. begin
  561. Result:=CreateDirectoryA(PChar(NewDir),nil);
  562. end;
  563. Function RemoveDir (Const Dir : String) : Boolean;
  564. begin
  565. Result:=RemoveDirectoryA(PChar(Dir));
  566. end;
  567. {****************************************************************************
  568. Time Functions
  569. ****************************************************************************}
  570. Procedure GetLocalTime(var SystemTime: TSystemTime);
  571. begin
  572. windows.Getlocaltime(SystemTime);
  573. end;
  574. function GetLocalTimeOffset: Integer;
  575. var
  576. TZInfo: TTimeZoneInformation;
  577. begin
  578. case GetTimeZoneInformation(TZInfo) of
  579. TIME_ZONE_ID_UNKNOWN:
  580. Result := TZInfo.Bias;
  581. TIME_ZONE_ID_STANDARD:
  582. Result := TZInfo.Bias + TZInfo.StandardBias;
  583. TIME_ZONE_ID_DAYLIGHT:
  584. Result := TZInfo.Bias + TZInfo.DaylightBias;
  585. else
  586. Result := 0;
  587. end;
  588. end;
  589. function GetTickCount: LongWord;
  590. begin
  591. Result := Windows.GetTickCount;
  592. end;
  593. {$IFNDEF WINCE}
  594. type
  595. TGetTickCount64 = function : QWord; stdcall;
  596. var
  597. WinGetTickCount64: TGetTickCount64 = Nil;
  598. {$ENDIF}
  599. function GetTickCount64: QWord;
  600. {$IFNDEF WINCE}
  601. var
  602. lib: THandle;
  603. {$ENDIF}
  604. begin
  605. {$IFNDEF WINCE}
  606. { on Vista and newer there is a GetTickCount64 implementation }
  607. if Win32MajorVersion >= 6 then begin
  608. if not Assigned(WinGetTickCount64) then begin
  609. lib := LoadLibrary('kernel32.dll');
  610. WinGetTickCount64 := TGetTickCount64(
  611. GetProcAddress(lib, 'GetTickCount64'));
  612. end;
  613. Result := WinGetTickCount64();
  614. end else
  615. {$ENDIF}
  616. Result := Windows.GetTickCount;
  617. end;
  618. {****************************************************************************
  619. Misc Functions
  620. ****************************************************************************}
  621. procedure sysbeep;
  622. begin
  623. MessageBeep(0);
  624. end;
  625. {****************************************************************************
  626. Locale Functions
  627. ****************************************************************************}
  628. function GetLocaleStr(LID, LT: Longint; const Def: string): ShortString;
  629. var
  630. L: Integer;
  631. Buf: array[0..255] of Char;
  632. begin
  633. L := GetLocaleInfoA(LID, LT, Buf, SizeOf(Buf));
  634. if L > 0 then
  635. SetString(Result, @Buf[0], L - 1)
  636. else
  637. Result := Def;
  638. end;
  639. function GetLocaleChar(LID, LT: Longint; Def: Char): Char;
  640. var
  641. Buf: array[0..3] of Char; // sdate allows 4 chars.
  642. begin
  643. if GetLocaleInfoA(LID, LT, Buf, sizeof(buf)) > 0 then
  644. Result := Buf[0]
  645. else
  646. Result := Def;
  647. end;
  648. function ConvertEraString(Count ,Year,Month,Day : integer) : string;
  649. var
  650. ASystemTime: TSystemTime;
  651. buf: array[0..100] of char;
  652. ALCID : LCID;
  653. PriLangID : Word;
  654. SubLangID : Word;
  655. begin
  656. Result := ''; if (Count<=0) then exit;
  657. DateTimeToSystemTime(EncodeDate(Year,Month,Day),ASystemTime);
  658. ALCID := GetThreadLocale;
  659. // ALCID := SysLocale.DefaultLCID;
  660. if GetDateFormatA(ALCID , DATE_USE_ALT_CALENDAR
  661. , @ASystemTime, PChar('gg')
  662. , @buf, SizeOf(buf)) > 0 then
  663. begin
  664. Result := buf;
  665. if Count = 1 then
  666. begin
  667. PriLangID := ALCID and $3FF;
  668. SubLangID := (ALCID and $FFFF) shr 10;
  669. case PriLangID of
  670. LANG_JAPANESE:
  671. begin
  672. Result := Copy(WideString(Result),1,1);
  673. end;
  674. LANG_CHINESE:
  675. if (SubLangID = SUBLANG_CHINESE_TRADITIONAL) then
  676. begin
  677. Result := Copy(WideString(Result),1,1);
  678. end;
  679. end;
  680. end;
  681. end;
  682. // if Result = '' then Result := StringOfChar('G',Count);
  683. end;
  684. function ConvertEraYearString(Count ,Year,Month,Day : integer) : string;
  685. var
  686. ALCID : LCID;
  687. ASystemTime : TSystemTime;
  688. AFormatText : string;
  689. buf : array[0..100] of Char;
  690. begin
  691. Result := '';
  692. DateTimeToSystemTime(EncodeDate(Year,Month,Day),ASystemTime);
  693. if Count <= 2 then
  694. AFormatText := 'yy'
  695. else
  696. AFormatText := 'yyyy';
  697. ALCID := GetThreadLocale;
  698. // ALCID := SysLocale.DefaultLCID;
  699. if GetDateFormatA(ALCID, DATE_USE_ALT_CALENDAR
  700. , @ASystemTime, PChar(AFormatText)
  701. , @buf, SizeOf(buf)) > 0 then
  702. begin
  703. Result := buf;
  704. if (Count = 1) and (Result[1] = '0') then
  705. Result := Copy(Result, 2, Length(Result)-1);
  706. end;
  707. end;
  708. Function GetLocaleInt(LID,TP,Def: LongInt): LongInt;
  709. Var
  710. S: String;
  711. C: Integer;
  712. Begin
  713. S:=GetLocaleStr(LID,TP,'0');
  714. Val(S,Result,C);
  715. If C<>0 Then
  716. Result:=Def;
  717. End;
  718. function EnumEraNames(Names: PChar): WINBOOL; stdcall;
  719. var
  720. i : integer;
  721. begin
  722. Result := False;
  723. for i := Low(EraNames) to High(EraNames) do
  724. if (EraNames[i] = '') then
  725. begin
  726. EraNames[i] := Names;
  727. Result := True;
  728. break;
  729. end;
  730. end;
  731. function EnumEraYearOffsets(YearOffsets: PChar): WINBOOL; stdcall;
  732. var
  733. i : integer;
  734. begin
  735. Result := False;
  736. for i := Low(EraYearOffsets) to High(EraYearOffsets) do
  737. if (EraYearOffsets[i] = -1) then
  738. begin
  739. EraYearOffsets[i] := StrToIntDef(YearOffsets, 0);
  740. Result := True;
  741. break;
  742. end;
  743. end;
  744. procedure GetEraNamesAndYearOffsets;
  745. var
  746. ACALID : CALID;
  747. ALCID : LCID;
  748. buf : array[0..10] of char;
  749. i : integer;
  750. begin
  751. for i:= 1 to MaxEraCount do
  752. begin
  753. EraNames[i] := ''; EraYearOffsets[i] := -1;
  754. end;
  755. ALCID := GetThreadLocale;
  756. if GetLocaleInfoA(ALCID , LOCALE_IOPTIONALCALENDAR, buf, sizeof(buf)) <= 0 then exit;
  757. ACALID := StrToIntDef(buf,1);
  758. if ACALID in [3..5] then
  759. begin
  760. EnumCalendarInfoA(@EnumEraNames, ALCID, ACALID , CAL_SERASTRING);
  761. EnumCalendarInfoA(@EnumEraYearOffsets, ALCID, ACALID, CAL_IYEAROFFSETRANGE);
  762. end;
  763. (*
  764. 1 CAL_GREGORIAN Gregorian (localized)
  765. 2 CAL_GREGORIAN_US Gregorian (English strings always)
  766. 3 CAL_JAPAN Japanese Emperor Era
  767. 4 CAL_TAIWAN Taiwan Calendar
  768. 5 CAL_KOREA Korean Tangun Era
  769. 6 CAL_HIJRI Hijri (Arabic Lunar)
  770. 7 CAL_THAI Thai
  771. 8 CAL_HEBREW Hebrew (Lunar)
  772. 9 CAL_GREGORIAN_ME_FRENCH Gregorian Middle East French
  773. 10 CAL_GREGORIAN_ARABIC Gregorian Arabic
  774. 11 CAL_GREGORIAN_XLIT_ENGLISH Gregorian transliterated English
  775. 12 CAL_GREGORIAN_XLIT_FRENCH Gregorian transliterated French
  776. 23 CAL_UMALQURA Windows Vista or later: Um Al Qura (Arabic lunar) calendar
  777. *)
  778. end;
  779. procedure GetLocaleFormatSettings(LCID: Integer; var FormatSettings: TFormatSettings);
  780. var
  781. HF : Shortstring;
  782. LID : Windows.LCID;
  783. I,Day : longint;
  784. begin
  785. LID := LCID;
  786. with FormatSettings do
  787. begin
  788. { Date stuff }
  789. for I := 1 to 12 do
  790. begin
  791. ShortMonthNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVMONTHNAME1+I-1,ShortMonthNames[i]);
  792. LongMonthNames[I]:=GetLocaleStr(LID,LOCALE_SMONTHNAME1+I-1,LongMonthNames[i]);
  793. end;
  794. for I := 1 to 7 do
  795. begin
  796. Day := (I + 5) mod 7;
  797. ShortDayNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVDAYNAME1+Day,ShortDayNames[i]);
  798. LongDayNames[I]:=GetLocaleStr(LID,LOCALE_SDAYNAME1+Day,LongDayNames[i]);
  799. end;
  800. DateSeparator := GetLocaleChar(LID, LOCALE_SDATE, '/');
  801. ShortDateFormat := GetLocaleStr(LID, LOCALE_SSHORTDATE, 'm/d/yy');
  802. LongDateFormat := GetLocaleStr(LID, LOCALE_SLONGDATE, 'mmmm d, yyyy');
  803. { Time stuff }
  804. TimeSeparator := GetLocaleChar(LID, LOCALE_STIME, ':');
  805. TimeAMString := GetLocaleStr(LID, LOCALE_S1159, 'AM');
  806. TimePMString := GetLocaleStr(LID, LOCALE_S2359, 'PM');
  807. if StrToIntDef(GetLocaleStr(LID, LOCALE_ITLZERO, '0'), 0) = 0 then
  808. HF:='h'
  809. else
  810. HF:='hh';
  811. // No support for 12 hour stuff at the moment...
  812. ShortTimeFormat := HF+':nn';
  813. LongTimeFormat := HF + ':nn:ss';
  814. { Currency stuff }
  815. CurrencyString:=GetLocaleStr(LID, LOCALE_SCURRENCY, '');
  816. CurrencyFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRENCY, '0'), 0);
  817. NegCurrFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_INEGCURR, '0'), 0);
  818. { Number stuff }
  819. ThousandSeparator:=GetLocaleChar(LID, LOCALE_STHOUSAND, ',');
  820. DecimalSeparator:=GetLocaleChar(LID, LOCALE_SDECIMAL, '.');
  821. CurrencyDecimals:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRDIGITS, '0'), 0);
  822. ListSeparator := GetLocaleChar(LID, LOCALE_SLIST, ',');
  823. end;
  824. end;
  825. procedure GetFormatSettings;
  826. begin
  827. GetlocaleFormatSettings(GetThreadLocale, DefaultFormatSettings);
  828. end;
  829. Procedure InitInternational;
  830. var
  831. { A call to GetSystemMetrics changes the value of the 8087 Control Word on
  832. Pentium4 with WinXP SP2 }
  833. old8087CW: word;
  834. DefaultCustomLocaleID : LCID; // typedef DWORD LCID;
  835. DefaultCustomLanguageID : Word; // typedef WORD LANGID;
  836. begin
  837. /// workaround for Windows 7 bug, see bug report #18574
  838. SetThreadLocale(GetUserDefaultLCID);
  839. InitInternationalGeneric;
  840. old8087CW:=Get8087CW;
  841. SysLocale.MBCS:=GetSystemMetrics(SM_DBCSENABLED)<>0;
  842. SysLocale.RightToLeft:=GetSystemMetrics(SM_MIDEASTENABLED)<>0;
  843. SysLocale.DefaultLCID := $0409;
  844. SysLocale.PriLangID := LANG_ENGLISH;
  845. SysLocale.SubLangID := SUBLANG_ENGLISH_US;
  846. // probably needs update with getthreadlocale. post 2.0.2
  847. DefaultCustomLocaleID := GetThreadLocale;
  848. if DefaultCustomLocaleID <> 0 then
  849. begin
  850. { Locale Identifiers
  851. +-------------+---------+-------------------------+
  852. | Reserved | Sort ID | Language ID |
  853. +-------------+---------+-------------------------+
  854. 31 20 19 16 15 0 bit }
  855. DefaultCustomLanguageID := DefaultCustomLocaleID and $FFFF; // 2^16
  856. if DefaultCustomLanguageID <> 0 then
  857. begin
  858. SysLocale.DefaultLCID := DefaultCustomLocaleID;
  859. { Language Identifiers
  860. +-------------------------+-------------------------+
  861. | SubLanguage ID | Primary Language ID |
  862. +-------------------------+-------------------------+
  863. 15 10 9 0 bit }
  864. SysLocale.PriLangID := DefaultCustomLanguageID and $3ff; // 2^10
  865. SysLocale.SubLangID := DefaultCustomLanguageID shr 10;
  866. end;
  867. end;
  868. Set8087CW(old8087CW);
  869. GetFormatSettings;
  870. if SysLocale.FarEast then GetEraNamesAndYearOffsets;
  871. end;
  872. {****************************************************************************
  873. Target Dependent
  874. ****************************************************************************}
  875. function SysErrorMessage(ErrorCode: Integer): String;
  876. const
  877. MaxMsgSize = Format_Message_Max_Width_Mask;
  878. var
  879. MsgBuffer: pChar;
  880. begin
  881. GetMem(MsgBuffer, MaxMsgSize);
  882. FillChar(MsgBuffer^, MaxMsgSize, #0);
  883. FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
  884. nil,
  885. ErrorCode,
  886. MakeLangId(LANG_NEUTRAL, SUBLANG_DEFAULT),
  887. MsgBuffer, { This function allocs the memory }
  888. MaxMsgSize, { Maximum message size }
  889. nil);
  890. SysErrorMessage := MsgBuffer;
  891. FreeMem(MsgBuffer, MaxMsgSize);
  892. end;
  893. {****************************************************************************
  894. Initialization code
  895. ****************************************************************************}
  896. {$push}
  897. { GetEnvironmentStrings cannot be checked by CheckPointer function }
  898. {$checkpointer off}
  899. Function GetEnvironmentVariable(Const EnvVar : Ansistring) : String;
  900. var
  901. s : string;
  902. i : longint;
  903. hp,p : pchar;
  904. begin
  905. Result:='';
  906. p:=GetEnvironmentStringsA;
  907. hp:=p;
  908. while hp^<>#0 do
  909. begin
  910. s:=hp;
  911. i:=pos('=',s);
  912. if uppercase(copy(s,1,i-1))=upcase(envvar) then
  913. begin
  914. Result:=copy(s,i+1,length(s)-i);
  915. break;
  916. end;
  917. { next string entry}
  918. hp:=hp+strlen(hp)+1;
  919. end;
  920. FreeEnvironmentStringsA(p);
  921. end;
  922. Function GetEnvironmentVariable(Const EnvVar : UnicodeString) : UnicodeString;
  923. var
  924. s : Unicodestring;
  925. i : longint;
  926. hp,p : pwidechar;
  927. begin
  928. Result:='';
  929. p:=GetEnvironmentStringsW;
  930. hp:=p;
  931. while hp^<>#0 do
  932. begin
  933. s:=hp;
  934. i:=pos('=',s);
  935. if uppercase(copy(s,1,i-1))=uppercase(envvar) then
  936. begin
  937. Result:=copy(s,i+1,length(s)-i);
  938. break;
  939. end;
  940. { next string entry}
  941. hp:=hp+strlen(hp)+1;
  942. end;
  943. FreeEnvironmentStringsW(p);
  944. end;
  945. Function GetEnvironmentVariableCount : Integer;
  946. var
  947. hp,p : pchar;
  948. begin
  949. Result:=0;
  950. p:=GetEnvironmentStringsA;
  951. hp:=p;
  952. If (Hp<>Nil) then
  953. while hp^<>#0 do
  954. begin
  955. Inc(Result);
  956. hp:=hp+strlen(hp)+1;
  957. end;
  958. FreeEnvironmentStringsA(p);
  959. end;
  960. Function GetEnvironmentString(Index : Integer) : String;
  961. var
  962. hp,p : pchar;
  963. begin
  964. Result:='';
  965. p:=GetEnvironmentStringsA;
  966. hp:=p;
  967. If (Hp<>Nil) then
  968. begin
  969. while (hp^<>#0) and (Index>1) do
  970. begin
  971. Dec(Index);
  972. hp:=hp+strlen(hp)+1;
  973. end;
  974. If (hp^<>#0) then
  975. Result:=HP;
  976. end;
  977. FreeEnvironmentStringsA(p);
  978. end;
  979. {$pop}
  980. function ExecuteProcess(Const Path: AnsiString; Const ComLine: AnsiString;Flags:TExecuteFlags=[]):integer;
  981. // win specific function
  982. var
  983. SI: TStartupInfo;
  984. PI: TProcessInformation;
  985. Proc : THandle;
  986. l : DWord;
  987. CommandLine : ansistring;
  988. e : EOSError;
  989. ExecInherits : longbool;
  990. begin
  991. FillChar(SI, SizeOf(SI), 0);
  992. SI.cb:=SizeOf(SI);
  993. SI.wShowWindow:=1;
  994. { always surround the name of the application by quotes
  995. so that long filenames will always be accepted. But don't
  996. do it if there are already double quotes, since Win32 does not
  997. like double quotes which are duplicated!
  998. }
  999. if pos('"',path)=0 then
  1000. CommandLine:='"'+path+'"'
  1001. else
  1002. CommandLine:=path;
  1003. if ComLine <> '' then
  1004. CommandLine:=Commandline+' '+ComLine+#0
  1005. else
  1006. CommandLine := CommandLine + #0;
  1007. ExecInherits:=ExecInheritsHandles in Flags;
  1008. if not CreateProcessA(nil, pchar(CommandLine),
  1009. Nil, Nil, ExecInherits,$20, Nil, Nil, SI, PI) then
  1010. begin
  1011. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
  1012. e.ErrorCode:=GetLastError;
  1013. raise e;
  1014. end;
  1015. Proc:=PI.hProcess;
  1016. if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then
  1017. begin
  1018. GetExitCodeProcess(Proc,l);
  1019. CloseHandle(Proc);
  1020. CloseHandle(PI.hThread);
  1021. result:=l;
  1022. end
  1023. else
  1024. begin
  1025. e:=EOSError.CreateFmt(SExecuteProcessFailed,[CommandLine,GetLastError]);
  1026. e.ErrorCode:=GetLastError;
  1027. CloseHandle(Proc);
  1028. CloseHandle(PI.hThread);
  1029. raise e;
  1030. end;
  1031. end;
  1032. function ExecuteProcess(Const Path: AnsiString; Const ComLine: Array of AnsiString;Flags:TExecuteFlags=[]):integer;
  1033. var
  1034. CommandLine: AnsiString;
  1035. I: integer;
  1036. begin
  1037. Commandline := '';
  1038. for I := 0 to High (ComLine) do
  1039. if Pos (' ', ComLine [I]) <> 0 then
  1040. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  1041. else
  1042. CommandLine := CommandLine + ' ' + Comline [I];
  1043. ExecuteProcess := ExecuteProcess (Path, CommandLine,Flags);
  1044. end;
  1045. Procedure Sleep(Milliseconds : Cardinal);
  1046. begin
  1047. Windows.Sleep(MilliSeconds)
  1048. end;
  1049. Function GetLastOSError : Integer;
  1050. begin
  1051. Result:=GetLastError;
  1052. end;
  1053. {****************************************************************************
  1054. Initialization code
  1055. ****************************************************************************}
  1056. var
  1057. kernel32dll : THandle;
  1058. Procedure LoadVersionInfo;
  1059. // and getfreespaceex
  1060. Var
  1061. versioninfo : TOSVERSIONINFO;
  1062. begin
  1063. GetDiskFreeSpaceEx:=nil;
  1064. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  1065. GetVersionEx(versioninfo);
  1066. Win32Platform:=versionInfo.dwPlatformId;
  1067. Win32MajorVersion:=versionInfo.dwMajorVersion;
  1068. Win32MinorVersion:=versionInfo.dwMinorVersion;
  1069. Win32BuildNumber:=versionInfo.dwBuildNumber;
  1070. Move (versioninfo.szCSDVersion ,Win32CSDVersion[1],128);
  1071. win32CSDVersion[0]:=chr(strlen(pchar(@versioninfo.szCSDVersion)));
  1072. kernel32dll:=GetModuleHandle('kernel32');
  1073. if kernel32dll<>0 then
  1074. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  1075. end;
  1076. Function GetAppConfigDir(Global : Boolean) : String;
  1077. begin
  1078. If Global then
  1079. Result:=GetWindowsSpecialDir(CSIDL_COMMON_APPDATA)
  1080. else
  1081. Result:=GetWindowsSpecialDir(CSIDL_LOCAL_APPDATA);
  1082. If (Result<>'') then
  1083. begin
  1084. if VendorName<>'' then
  1085. Result:=IncludeTrailingPathDelimiter(Result+VendorName);
  1086. Result:=IncludeTrailingPathDelimiter(Result+ApplicationName);
  1087. end
  1088. else
  1089. Result:=IncludeTrailingPathDelimiter(DGetAppConfigDir(Global));
  1090. end;
  1091. Function GetAppConfigFile(Global : Boolean; SubDir : Boolean) : String;
  1092. begin
  1093. result:=DGetAppConfigFile(Global,SubDir);
  1094. end;
  1095. Function GetUserDir : String;
  1096. begin
  1097. Result:=GetWindowsSpecialDir(CSIDL_PROFILE);
  1098. end;
  1099. Procedure InitSysConfigDir;
  1100. begin
  1101. SetLength(SysConfigDir, MAX_PATH);
  1102. SetLength(SysConfigDir, GetWindowsDirectoryA(PChar(SysConfigDir), MAX_PATH));
  1103. end;
  1104. {****************************************************************************
  1105. Target Dependent WideString stuff
  1106. ****************************************************************************}
  1107. { This is the case of Win9x. Limited to current locale of course, but it's better
  1108. than not working at all. }
  1109. function DoCompareStringA(P1, P2: PWideChar; L1, L2: PtrUInt; Flags: DWORD): PtrInt;
  1110. var
  1111. a1, a2: AnsiString;
  1112. begin
  1113. if L1>0 then
  1114. widestringmanager.Wide2AnsiMoveProc(P1,a1,DefaultSystemCodePage,L1);
  1115. if L2>0 then
  1116. widestringmanager.Wide2AnsiMoveProc(P2,a2,DefaultSystemCodePage,L2);
  1117. SetLastError(0);
  1118. Result:=CompareStringA(LOCALE_USER_DEFAULT,Flags,pchar(a1),
  1119. length(a1),pchar(a2),length(a2))-2;
  1120. end;
  1121. function DoCompareStringW(P1, P2: PWideChar; L1, L2: PtrUInt; Flags: DWORD): PtrInt;
  1122. begin
  1123. SetLastError(0);
  1124. Result:=CompareStringW(LOCALE_USER_DEFAULT,Flags,P1,L1,P2,L2)-2;
  1125. if GetLastError=0 then
  1126. Exit;
  1127. if GetLastError=ERROR_CALL_NOT_IMPLEMENTED then // Win9x case
  1128. Result:=DoCompareStringA(P1, P2, L1, L2, Flags);
  1129. if GetLastError<>0 then
  1130. RaiseLastOSError;
  1131. end;
  1132. function Win32CompareWideString(const s1, s2 : WideString) : PtrInt;
  1133. begin
  1134. Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), 0);
  1135. end;
  1136. function Win32CompareTextWideString(const s1, s2 : WideString) : PtrInt;
  1137. begin
  1138. Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), NORM_IGNORECASE);
  1139. end;
  1140. function Win32AnsiUpperCase(const s: string): string;
  1141. begin
  1142. if length(s)>0 then
  1143. begin
  1144. result:=s;
  1145. UniqueString(result);
  1146. CharUpperBuffA(pchar(result),length(result));
  1147. end
  1148. else
  1149. result:='';
  1150. end;
  1151. function Win32AnsiLowerCase(const s: string): string;
  1152. begin
  1153. if length(s)>0 then
  1154. begin
  1155. result:=s;
  1156. UniqueString(result);
  1157. CharLowerBuffA(pchar(result),length(result));
  1158. end
  1159. else
  1160. result:='';
  1161. end;
  1162. function Win32AnsiCompareStr(const S1, S2: string): PtrInt;
  1163. begin
  1164. result:=CompareStringA(LOCALE_USER_DEFAULT,0,pchar(s1),length(s1),
  1165. pchar(s2),length(s2))-2;
  1166. end;
  1167. function Win32AnsiCompareText(const S1, S2: string): PtrInt;
  1168. begin
  1169. result:=CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE,pchar(s1),length(s1),
  1170. pchar(s2),length(s2))-2;
  1171. end;
  1172. function Win32AnsiStrComp(S1, S2: PChar): PtrInt;
  1173. begin
  1174. result:=CompareStringA(LOCALE_USER_DEFAULT,0,s1,-1,s2,-1)-2;
  1175. end;
  1176. function Win32AnsiStrIComp(S1, S2: PChar): PtrInt;
  1177. begin
  1178. result:=CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE,s1,-1,s2,-1)-2;
  1179. end;
  1180. function Win32AnsiStrLComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1181. begin
  1182. result:=CompareStringA(LOCALE_USER_DEFAULT,0,s1,maxlen,s2,maxlen)-2;
  1183. end;
  1184. function Win32AnsiStrLIComp(S1, S2: PChar; MaxLen: PtrUInt): PtrInt;
  1185. begin
  1186. result:=CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE,s1,maxlen,s2,maxlen)-2;
  1187. end;
  1188. function Win32AnsiStrLower(Str: PChar): PChar;
  1189. begin
  1190. CharLowerA(str);
  1191. result:=str;
  1192. end;
  1193. function Win32AnsiStrUpper(Str: PChar): PChar;
  1194. begin
  1195. CharUpperA(str);
  1196. result:=str;
  1197. end;
  1198. function Win32CompareUnicodeString(const s1, s2 : UnicodeString) : PtrInt;
  1199. begin
  1200. Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), 0);
  1201. end;
  1202. function Win32CompareTextUnicodeString(const s1, s2 : UnicodeString) : PtrInt;
  1203. begin
  1204. Result:=DoCompareStringW(PWideChar(s1), PWideChar(s2), Length(s1), Length(s2), NORM_IGNORECASE);
  1205. end;
  1206. { there is a similiar procedure in the system unit which inits the fields which
  1207. are relevant already for the system unit }
  1208. procedure InitWin32Widestrings;
  1209. begin
  1210. { return value: number of code points in the string. Whenever an invalid
  1211. code point is encountered, all characters part of this invalid code point
  1212. are considered to form one "character" and the next character is
  1213. considered to be the start of a new (possibly also invalid) code point }
  1214. //!!! CharLengthPCharProc : function(const Str: PChar): PtrInt;
  1215. { return value:
  1216. -1 if incomplete or invalid code point
  1217. 0 if NULL character,
  1218. > 0 if that's the length in bytes of the code point }
  1219. //!!!! CodePointLengthProc : function(const Str: PChar; MaxLookAead: PtrInt): Ptrint;
  1220. widestringmanager.CompareWideStringProc:=@Win32CompareWideString;
  1221. widestringmanager.CompareTextWideStringProc:=@Win32CompareTextWideString;
  1222. widestringmanager.UpperAnsiStringProc:=@Win32AnsiUpperCase;
  1223. widestringmanager.LowerAnsiStringProc:=@Win32AnsiLowerCase;
  1224. widestringmanager.CompareStrAnsiStringProc:=@Win32AnsiCompareStr;
  1225. widestringmanager.CompareTextAnsiStringProc:=@Win32AnsiCompareText;
  1226. widestringmanager.StrCompAnsiStringProc:=@Win32AnsiStrComp;
  1227. widestringmanager.StrICompAnsiStringProc:=@Win32AnsiStrIComp;
  1228. widestringmanager.StrLCompAnsiStringProc:=@Win32AnsiStrLComp;
  1229. widestringmanager.StrLICompAnsiStringProc:=@Win32AnsiStrLIComp;
  1230. widestringmanager.StrLowerAnsiStringProc:=@Win32AnsiStrLower;
  1231. widestringmanager.StrUpperAnsiStringProc:=@Win32AnsiStrUpper;
  1232. widestringmanager.CompareUnicodeStringProc:=@Win32CompareUnicodeString;
  1233. widestringmanager.CompareTextUnicodeStringProc:=@Win32CompareTextUnicodeString;
  1234. end;
  1235. { Platform-specific exception support }
  1236. function WinExceptionObject(code: Longint; const rec: TExceptionRecord): Exception;
  1237. var
  1238. entry: PExceptMapEntry;
  1239. begin
  1240. entry := FindExceptMapEntry(code);
  1241. if assigned(entry) then
  1242. result:=entry^.cls.CreateRes(entry^.msg)
  1243. else
  1244. result:=EExternalException.CreateResFmt(@SExternalException,[rec.ExceptionCode]);
  1245. if result is EExternal then
  1246. EExternal(result).FExceptionRecord:=rec;
  1247. end;
  1248. function WinExceptionClass(code: longint): ExceptClass;
  1249. var
  1250. entry: PExceptMapEntry;
  1251. begin
  1252. entry := FindExceptMapEntry(code);
  1253. if assigned(entry) then
  1254. result:=entry^.cls
  1255. else
  1256. result:=EExternalException;
  1257. end;
  1258. Initialization
  1259. InitWin32Widestrings;
  1260. InitExceptions; { Initialize exceptions. OS independent }
  1261. {$ifdef win64} { Nothing win64-specific here, just keeping exe size down
  1262. as these procedures aren't used in generic exception handling }
  1263. ExceptObjProc:=@WinExceptionObject;
  1264. ExceptClsProc:=@WinExceptionClass;
  1265. {$endif win64}
  1266. InitInternational; { Initialize internationalization settings }
  1267. LoadVersionInfo;
  1268. InitSysConfigDir;
  1269. OnBeep:=@SysBeep;
  1270. Finalization
  1271. DoneExceptions;
  1272. end.