sysutils.pp 17 KB

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