sysutils.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. Sysutils unit for win32
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit sysutils;
  14. interface
  15. {$MODE objfpc}
  16. { force ansistrings }
  17. {$H+}
  18. uses
  19. dos,windows;
  20. { Include platform independent interface part }
  21. {$i sysutilh.inc}
  22. type
  23. TSystemTime = Windows.TSystemTime;
  24. Var
  25. Win32Platform : Longint;
  26. implementation
  27. { Include platform independent implementation part }
  28. {$i sysutils.inc}
  29. {****************************************************************************
  30. File Functions
  31. ****************************************************************************}
  32. Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
  33. const
  34. AccessMode: array[0..2] of Cardinal = (
  35. GENERIC_READ,
  36. GENERIC_WRITE,
  37. GENERIC_READ or GENERIC_WRITE);
  38. ShareMode: array[0..4] of Integer = (
  39. 0,
  40. 0,
  41. FILE_SHARE_READ,
  42. FILE_SHARE_WRITE,
  43. FILE_SHARE_READ or FILE_SHARE_WRITE);
  44. Var
  45. FN : string;
  46. begin
  47. FN:=FileName+#0;
  48. result := CreateFile(@FN[1], dword(AccessMode[Mode and 3]),
  49. dword(ShareMode[(Mode and $F0) shr 4]), nil, OPEN_EXISTING,
  50. FILE_ATTRIBUTE_NORMAL, 0);
  51. end;
  52. Function FileCreate (Const FileName : String) : Longint;
  53. Var
  54. FN : string;
  55. begin
  56. FN:=FileName+#0;
  57. Result := CreateFile(@FN[1], GENERIC_READ or GENERIC_WRITE,
  58. 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
  59. end;
  60. Function FileRead (Handle : Longint; Var Buffer; Count : longint) : Longint;
  61. Var
  62. res : dword;
  63. begin
  64. if ReadFile(Handle, Buffer, Count, res, nil) then
  65. FileRead:=Res
  66. else
  67. FileRead:=-1;
  68. end;
  69. Function FileWrite (Handle : Longint; const Buffer; Count : Longint) : Longint;
  70. Var
  71. Res : dword;
  72. begin
  73. if WriteFile(Handle, Buffer, Count, Res, nil) then
  74. FileWrite:=Res
  75. else
  76. FileWrite:=-1;
  77. end;
  78. Function FileSeek (Handle,FOffset,Origin : Longint) : Longint;
  79. begin
  80. Result := longint(SetFilePointer(Handle, FOffset, nil, Origin));
  81. end;
  82. Function FileSeek (Handle : Longint; FOffset,Origin : Int64) : Int64;
  83. begin
  84. {$warning need to add 64bit call }
  85. Result := longint(SetFilePointer(Handle, FOffset, nil, Origin));
  86. end;
  87. Procedure FileClose (Handle : Longint);
  88. begin
  89. if Handle<=4 then
  90. exit;
  91. CloseHandle(Handle);
  92. end;
  93. Function FileTruncate (Handle,Size: Longint) : boolean;
  94. begin
  95. Result:=longint(SetFilePointer(handle,Size,nil,FILE_BEGIN))<>-1;
  96. If Result then
  97. Result:=SetEndOfFile(handle);
  98. end;
  99. Function DosToWinTime (DTime:longint;Var Wtime : TFileTime):longbool;
  100. var
  101. lft : TFileTime;
  102. begin
  103. DosToWinTime:=DosDateTimeToFileTime(longrec(dtime).hi,longrec(dtime).lo,@lft) and
  104. LocalFileTimeToFileTime(lft,@Wtime);
  105. end;
  106. Function WinToDosTime (Var Wtime : TFileTime;var DTime:longint):longbool;
  107. var
  108. lft : FileTime;
  109. begin
  110. WinToDosTime:=FileTimeToLocalFileTime(WTime,@lft) and
  111. FileTimeToDosDateTime(lft,@Longrec(Dtime).Hi,@LongRec(DTIME).lo);
  112. end;
  113. Function FileAge (Const FileName : String): Longint;
  114. var
  115. Handle: THandle;
  116. FindData: TWin32FindData;
  117. begin
  118. Handle := FindFirstFile(Pchar(FileName), @FindData);
  119. if Handle <> INVALID_HANDLE_VALUE then
  120. begin
  121. Windows.FindClose(Handle);
  122. if (FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) = 0 then
  123. If WinToDosTime(FindData.ftLastWriteTime,Result) then
  124. exit;
  125. end;
  126. Result := -1;
  127. end;
  128. Function FileExists (Const FileName : String) : Boolean;
  129. var
  130. Handle: THandle;
  131. FindData: TWin32FindData;
  132. begin
  133. Handle := FindFirstFile(Pchar(FileName), @FindData);
  134. Result:=Handle <> INVALID_HANDLE_VALUE;
  135. If Result then
  136. Windows.FindClose(Handle);
  137. end;
  138. Function FindMatch(var f: TSearchRec) : Longint;
  139. begin
  140. { Find file with correct attribute }
  141. While (F.FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
  142. begin
  143. if not FindNextFile (F.FindHandle,@F.FindData) then
  144. begin
  145. Result:=GetLastError;
  146. exit;
  147. end;
  148. end;
  149. { Convert some attributes back }
  150. WinToDosTime(F.FindData.ftLastWriteTime,F.Time);
  151. f.size:=F.FindData.NFileSizeLow;
  152. f.attr:=F.FindData.dwFileAttributes;
  153. f.Name:=StrPas(@F.FindData.cFileName);
  154. Result:=0;
  155. end;
  156. Function FindFirst (Const Path : String; Attr : Longint; Var Rslt : TSearchRec) : Longint;
  157. begin
  158. Rslt.Name:=Path;
  159. Rslt.Attr:=attr;
  160. Rslt.ExcludeAttr:=(not Attr) and ($1e);
  161. { $1e = faHidden or faSysFile or faVolumeID or faDirectory }
  162. { FindFirstFile is a Win32 Call }
  163. Rslt.FindHandle:=FindFirstFile (PChar(Path),@Rslt.FindData);
  164. If Rslt.FindHandle=Invalid_Handle_value then
  165. begin
  166. Result:=GetLastError;
  167. exit;
  168. end;
  169. { Find file with correct attribute }
  170. Result:=FindMatch(Rslt);
  171. end;
  172. Function FindNext (Var Rslt : TSearchRec) : Longint;
  173. begin
  174. if FindNextFile(Rslt.FindHandle, @Rslt.FindData) then
  175. Result := FindMatch(Rslt)
  176. else
  177. Result := GetLastError;
  178. end;
  179. Procedure FindClose (Var F : TSearchrec);
  180. begin
  181. if F.FindHandle <> INVALID_HANDLE_VALUE then
  182. Windows.FindClose(F.FindHandle);
  183. end;
  184. Function FileGetDate (Handle : Longint) : Longint;
  185. Var
  186. FT : TFileTime;
  187. begin
  188. If GetFileTime(Handle,nil,nil,@ft) and
  189. WinToDosTime(FT,Result) then
  190. exit;
  191. Result:=-1;
  192. end;
  193. Function FileSetDate (Handle,Age : Longint) : Longint;
  194. Var
  195. FT: TFileTime;
  196. begin
  197. Result := 0;
  198. if DosToWinTime(Age,FT) and
  199. SetFileTime(Handle, ft, ft, FT) then
  200. Exit;
  201. Result := GetLastError;
  202. end;
  203. Function FileGetAttr (Const FileName : String) : Longint;
  204. begin
  205. Result:=GetFileAttributes(PChar(FileName));
  206. end;
  207. Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
  208. begin
  209. if not SetFileAttributes(PChar(FileName), Attr) then
  210. Result := GetLastError
  211. else
  212. Result:=0;
  213. end;
  214. Function DeleteFile (Const FileName : String) : Boolean;
  215. begin
  216. DeleteFile:=Windows.DeleteFile(Pchar(FileName));
  217. end;
  218. Function RenameFile (Const OldName, NewName : String) : Boolean;
  219. begin
  220. Result := MoveFile(PChar(OldName), PChar(NewName));
  221. end;
  222. {****************************************************************************
  223. Disk Functions
  224. ****************************************************************************}
  225. function GetDiskFreeSpace(drive:pchar;var sector_cluster,bytes_sector,
  226. freeclusters,totalclusters:longint):longbool;
  227. external 'kernel32' name 'GetDiskFreeSpaceA';
  228. type
  229. TGetDiskFreeSpaceEx = function(drive:pchar;var availableforcaller,total,free):longbool;stdcall;
  230. var
  231. GetDiskFreeSpaceEx : TGetDiskFreeSpaceEx;
  232. function diskfree(drive : byte) : int64;
  233. var
  234. disk : array[1..4] of char;
  235. secs,bytes,
  236. free,total : longint;
  237. qwtotal,qwfree,qwcaller : int64;
  238. begin
  239. if drive=0 then
  240. begin
  241. disk[1]:='\';
  242. disk[2]:=#0;
  243. end
  244. else
  245. begin
  246. disk[1]:=chr(drive+64);
  247. disk[2]:=':';
  248. disk[3]:='\';
  249. disk[4]:=#0;
  250. end;
  251. if assigned(GetDiskFreeSpaceEx) then
  252. begin
  253. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  254. diskfree:=qwfree
  255. else
  256. diskfree:=-1;
  257. end
  258. else
  259. begin
  260. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  261. diskfree:=int64(free)*secs*bytes
  262. else
  263. diskfree:=-1;
  264. end;
  265. end;
  266. function disksize(drive : byte) : int64;
  267. var
  268. disk : array[1..4] of char;
  269. secs,bytes,
  270. free,total : longint;
  271. qwtotal,qwfree,qwcaller : int64;
  272. begin
  273. if drive=0 then
  274. begin
  275. disk[1]:='\';
  276. disk[2]:=#0;
  277. end
  278. else
  279. begin
  280. disk[1]:=chr(drive+64);
  281. disk[2]:=':';
  282. disk[3]:='\';
  283. disk[4]:=#0;
  284. end;
  285. if assigned(GetDiskFreeSpaceEx) then
  286. begin
  287. if GetDiskFreeSpaceEx(@disk,qwcaller,qwtotal,qwfree) then
  288. disksize:=qwtotal
  289. else
  290. disksize:=-1;
  291. end
  292. else
  293. begin
  294. if GetDiskFreeSpace(@disk,secs,bytes,free,total) then
  295. disksize:=int64(total)*secs*bytes
  296. else
  297. disksize:=-1;
  298. end;
  299. end;
  300. Function GetCurrentDir : String;
  301. begin
  302. GetDir(0, result);
  303. end;
  304. Function SetCurrentDir (Const NewDir : String) : Boolean;
  305. begin
  306. {$I-}
  307. ChDir(NewDir);
  308. {$I+}
  309. result := (IOResult = 0);
  310. end;
  311. Function CreateDir (Const NewDir : String) : Boolean;
  312. begin
  313. {$I-}
  314. MkDir(NewDir);
  315. {$I+}
  316. result := (IOResult = 0);
  317. end;
  318. Function RemoveDir (Const Dir : String) : Boolean;
  319. begin
  320. {$I-}
  321. RmDir(Dir);
  322. {$I+}
  323. result := (IOResult = 0);
  324. end;
  325. {****************************************************************************
  326. Time Functions
  327. ****************************************************************************}
  328. Procedure GetLocalTime(var SystemTime: TSystemTime);
  329. Var
  330. Syst : Windows.TSystemtime;
  331. begin
  332. windows.Getlocaltime(@syst);
  333. SystemTime.year:=syst.wYear;
  334. SystemTime.month:=syst.wMonth;
  335. SystemTime.day:=syst.wDay;
  336. SystemTime.hour:=syst.wHour;
  337. SystemTime.minute:=syst.wMinute;
  338. SystemTime.second:=syst.wSecond;
  339. SystemTime.millisecond:=syst.wMilliSeconds;
  340. end;
  341. {****************************************************************************
  342. Misc Functions
  343. ****************************************************************************}
  344. procedure Beep;
  345. begin
  346. MessageBeep(0);
  347. end;
  348. {****************************************************************************
  349. Locale Functions
  350. ****************************************************************************}
  351. Procedure InitAnsi;
  352. Var
  353. i : longint;
  354. begin
  355. { Fill table entries 0 to 127 }
  356. for i := 0 to 96 do
  357. UpperCaseTable[i] := chr(i);
  358. for i := 97 to 122 do
  359. UpperCaseTable[i] := chr(i - 32);
  360. for i := 123 to 191 do
  361. UpperCaseTable[i] := chr(i);
  362. Move (CPISO88591UCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  363. for i := 0 to 64 do
  364. LowerCaseTable[i] := chr(i);
  365. for i := 65 to 90 do
  366. LowerCaseTable[i] := chr(i + 32);
  367. for i := 91 to 191 do
  368. LowerCaseTable[i] := chr(i);
  369. Move (CPISO88591LCT,UpperCaseTable[192],SizeOf(CPISO88591UCT));
  370. end;
  371. function GetLocaleStr(LID, LT: Longint; const Def: string): ShortString;
  372. var
  373. L: Integer;
  374. Buf: array[0..255] of Char;
  375. begin
  376. L := GetLocaleInfo(LID, LT, Buf, SizeOf(Buf));
  377. if L > 0 then
  378. SetString(Result, @Buf[0], L - 1)
  379. else
  380. Result := Def;
  381. end;
  382. function GetLocaleChar(LID, LT: Longint; Def: Char): Char;
  383. var
  384. Buf: array[0..1] of Char;
  385. begin
  386. if GetLocaleInfo(LID, LT, Buf, 2) > 0 then
  387. Result := Buf[0]
  388. else
  389. Result := Def;
  390. end;
  391. Function GetLocaleInt(LID,TP,Def: LongInt): LongInt;
  392. Var
  393. S: String;
  394. C: Integer;
  395. Begin
  396. S:=GetLocaleStr(LID,TP,'0');
  397. Val(S,Result,C);
  398. If C<>0 Then
  399. Result:=Def;
  400. End;
  401. procedure GetFormatSettings;
  402. var
  403. HF : Shortstring;
  404. LID : LCID;
  405. I,Day,DateOrder : longint;
  406. begin
  407. LID := GetThreadLocale;
  408. { Date stuff }
  409. for I := 1 to 12 do
  410. begin
  411. ShortMonthNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVMONTHNAME1+I-1,ShortMonthNames[i]);
  412. LongMonthNames[I]:=GetLocaleStr(LID,LOCALE_SMONTHNAME1+I-1,LongMonthNames[i]);
  413. end;
  414. for I := 1 to 7 do
  415. begin
  416. Day := (I + 5) mod 7;
  417. ShortDayNames[I]:=GetLocaleStr(LID,LOCALE_SABBREVDAYNAME1+Day,ShortDayNames[i]);
  418. LongDayNames[I]:=GetLocaleStr(LID,LOCALE_SDAYNAME1+Day,LongDayNames[i]);
  419. end;
  420. DateSeparator := GetLocaleChar(LID, LOCALE_SDATE, '/');
  421. DateOrder := GetLocaleInt(LID, LOCALE_IDate, 0);
  422. Case DateOrder Of
  423. 1: Begin
  424. ShortDateFormat := 'dd/mm/yyyy';
  425. LongDateFormat := 'dddd, d. mmmm yyyy';
  426. End;
  427. 2: Begin
  428. ShortDateFormat := 'yyyy/mm/dd';
  429. LongDateFormat := 'dddd, yyyy mmmm d.';
  430. End;
  431. else
  432. // Default american settings...
  433. ShortDateFormat := 'mm/dd/yyyy';
  434. LongDateFormat := 'dddd, mmmm d. yyyy';
  435. End;
  436. { Time stuff }
  437. TimeSeparator := GetLocaleChar(LID, LOCALE_STIME, ':');
  438. TimeAMString := GetLocaleStr(LID, LOCALE_S1159, 'AM');
  439. TimePMString := GetLocaleStr(LID, LOCALE_S2359, 'PM');
  440. if StrToIntDef(GetLocaleStr(LID, LOCALE_ITLZERO, '0'), 0) = 0 then
  441. HF:='h'
  442. else
  443. HF:='hh';
  444. // No support for 12 hour stuff at the moment...
  445. ShortTimeFormat := HF+':nn';
  446. LongTimeFormat := HF + ':nn:ss';
  447. { Currency stuff }
  448. CurrencyString:=GetLocaleStr(LID, LOCALE_SCURRENCY, '');
  449. CurrencyFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRENCY, '0'), 0);
  450. NegCurrFormat:=StrToIntDef(GetLocaleStr(LID, LOCALE_INEGCURR, '0'), 0);
  451. { Number stuff }
  452. ThousandSeparator:=GetLocaleChar(LID, LOCALE_STHOUSAND, ',');
  453. DecimalSeparator:=GetLocaleChar(LID, LOCALE_SDECIMAL, '.');
  454. CurrencyDecimals:=StrToIntDef(GetLocaleStr(LID, LOCALE_ICURRDIGITS, '0'), 0);
  455. end;
  456. Procedure InitInternational;
  457. begin
  458. InitAnsi;
  459. GetFormatSettings;
  460. end;
  461. {****************************************************************************
  462. Target Dependent
  463. ****************************************************************************}
  464. function FormatMessageA(dwFlags : DWORD;
  465. lpSource : Pointer;
  466. dwMessageId : DWORD;
  467. dwLanguageId: DWORD;
  468. lpBuffer : PCHAR;
  469. nSize : DWORD;
  470. Arguments : Pointer): DWORD; external 'kernel32' name 'FormatMessageA';
  471. function SysErrorMessage(ErrorCode: Integer): String;
  472. const
  473. MaxMsgSize = Format_Message_Max_Width_Mask;
  474. var
  475. MsgBuffer: pChar;
  476. begin
  477. GetMem(MsgBuffer, MaxMsgSize);
  478. FillChar(MsgBuffer^, MaxMsgSize, #0);
  479. FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
  480. nil,
  481. ErrorCode,
  482. MakeLangId(LANG_NEUTRAL, SUBLANG_DEFAULT),
  483. MsgBuffer, { This function allocs the memory }
  484. MaxMsgSize, { Maximum message size }
  485. nil);
  486. SysErrorMessage := StrPas(MsgBuffer);
  487. FreeMem(MsgBuffer, MaxMsgSize);
  488. end;
  489. {****************************************************************************
  490. Initialization code
  491. ****************************************************************************}
  492. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  493. var
  494. s : string;
  495. i : longint;
  496. hp,p : pchar;
  497. begin
  498. Result:='';
  499. p:=GetEnvironmentStrings;
  500. hp:=p;
  501. while hp^<>#0 do
  502. begin
  503. s:=strpas(hp);
  504. i:=pos('=',s);
  505. if upcase(copy(s,1,i-1))=upcase(envvar) then
  506. begin
  507. Result:=copy(s,i+1,length(s)-i);
  508. break;
  509. end;
  510. { next string entry}
  511. hp:=hp+strlen(hp)+1;
  512. end;
  513. FreeEnvironmentStrings(p);
  514. end;
  515. {****************************************************************************
  516. Initialization code
  517. ****************************************************************************}
  518. var
  519. versioninfo : OSVERSIONINFO;
  520. kernel32dll : THandle;
  521. function FreeLibrary(hLibModule : THANDLE) : longbool;
  522. external 'kernel32' name 'FreeLibrary';
  523. function GetVersionEx(var VersionInformation:OSVERSIONINFO) : longbool;
  524. external 'kernel32' name 'GetVersionExA';
  525. function LoadLibrary(lpLibFileName : pchar):THandle;
  526. external 'kernel32' name 'LoadLibraryA';
  527. function GetProcAddress(hModule : THandle;lpProcName : pchar) : pointer;
  528. external 'kernel32' name 'GetProcAddress';
  529. Initialization
  530. InitExceptions; { Initialize exceptions. OS independent }
  531. InitInternational; { Initialize internationalization settings }
  532. versioninfo.dwOSVersionInfoSize:=sizeof(versioninfo);
  533. GetVersionEx(versioninfo);
  534. kernel32dll:=0;
  535. GetDiskFreeSpaceEx:=nil;
  536. Win32Platform:=versionInfo.dwPlatformId;
  537. if ((versioninfo.dwPlatformId=VER_PLATFORM_WIN32_WINDOWS) and
  538. (versioninfo.dwBuildNUmber>=1000)) or
  539. (versioninfo.dwPlatformId=VER_PLATFORM_WIN32_NT) then
  540. begin
  541. kernel32dll:=LoadLibrary('kernel32');
  542. if kernel32dll<>0 then
  543. GetDiskFreeSpaceEx:=TGetDiskFreeSpaceEx(GetProcAddress(kernel32dll,'GetDiskFreeSpaceExA'));
  544. end;
  545. Finalization
  546. DoneExceptions;
  547. if kernel32dll<>0 then
  548. FreeLibrary(kernel32dll);
  549. end.
  550. {
  551. $Log$
  552. Revision 1.16 2002-10-02 21:17:03 florian
  553. * we've to reimport TSystemTime time from the windows unit
  554. Revision 1.15 2002/09/07 16:01:29 peter
  555. * old logs removed and tabs fixed
  556. Revision 1.14 2002/05/09 08:28:23 carl
  557. * Merges from Fixes branch
  558. Revision 1.13 2002/03/24 19:26:49 marco
  559. * Added win32platform
  560. Revision 1.12 2002/01/25 16:23:04 peter
  561. * merged filesearch() fix
  562. }