sysutils.pp 40 KB

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