sysutils.pp 16 KB

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