sysutils.pp 17 KB

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