sysutils.pp 41 KB

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