sysutils.pp 33 KB

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