sysutils.pp 39 KB

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