sysutils.pp 38 KB

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