sysutils.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  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. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. { Read filename handling functions implementation }
  12. {$i fina.inc}
  13. { variant error codes }
  14. {$i varerror.inc}
  15. Function FileSearch (Const Name, DirList : String) : String;
  16. Var
  17. I : longint;
  18. Temp : String;
  19. begin
  20. Result:='';
  21. temp:=Dirlist;
  22. repeat
  23. While (Length(Temp)>0) and (Temp[1]=PathSeparator) do
  24. Delete(Temp,1,1);
  25. I:=pos(PathSep,Temp);
  26. If I<>0 then
  27. begin
  28. Result:=Copy (Temp,1,i-1);
  29. system.Delete(Temp,1,I);
  30. end
  31. else
  32. begin
  33. Result:=Temp;
  34. Temp:='';
  35. end;
  36. If (Length(Result)>0) and (result[length(result)]<>DirectorySeparator) then
  37. Result:=Result+DirectorySeparator;
  38. Result:=Result+name;
  39. If not FileExists(Result) Then
  40. Result:='';
  41. until (length(temp)=0) or (length(result)<>0);
  42. end;
  43. {$ifndef OS_FILEISREADONLY}
  44. Function FileIsReadOnly(const FileName: String): Boolean;
  45. begin
  46. Result := (FileGetAttr(FileName) and faReadOnly) <> 0;
  47. end;
  48. {$endif OS_FILEISREADONLY}
  49. {$ifndef OS_FILESETDATEBYNAME}
  50. Function FileSetDate (Const FileName : String;Age : Longint) : Longint;
  51. Var
  52. fd : THandle;
  53. begin
  54. fd:=FileOpen(FileName,fmOpenRead);
  55. If (Fd<>feInvalidHandle) then
  56. try
  57. Result:=FileSetDate(fd,Age);
  58. finally
  59. FileClose(fd);
  60. end
  61. else
  62. Result:=Fd;
  63. end;
  64. {$endif}
  65. { Read String Handling functions implementation }
  66. {$i sysstr.inc}
  67. { Read date & Time function implementations }
  68. {$i dati.inc}
  69. { Read pchar handling functions implementation }
  70. {$i syspch.inc}
  71. { generic internationalisation code }
  72. {$i sysint.inc}
  73. { MCBS functions }
  74. {$i sysansi.inc}
  75. { wide string functions }
  76. {$i syswide.inc}
  77. { threading stuff }
  78. {$i sysuthrd.inc}
  79. { OS utility code }
  80. {$i osutil.inc}
  81. procedure FreeAndNil(var obj);
  82. var
  83. temp: tobject;
  84. begin
  85. temp:=tobject(obj);
  86. pointer(obj):=nil;
  87. temp.free;
  88. end;
  89. { Interfaces support }
  90. {$i sysuintf.inc}
  91. constructor Exception.Create(const msg : string);
  92. begin
  93. inherited create;
  94. fmessage:=msg;
  95. end;
  96. constructor Exception.CreateFmt(const msg : string; const args : array of const);
  97. begin
  98. inherited create;
  99. fmessage:=Format(msg,args);
  100. end;
  101. constructor Exception.CreateRes(ResString: PString);
  102. begin
  103. inherited create;
  104. fmessage:=ResString^;
  105. end;
  106. constructor Exception.CreateResFmt(ResString: PString; const Args: array of const);
  107. begin
  108. inherited create;
  109. fmessage:=Format(ResString^,args);
  110. end;
  111. constructor Exception.CreateHelp(const Msg: string; AHelpContext: Integer);
  112. begin
  113. inherited create;
  114. fmessage:=Msg;
  115. fhelpcontext:=AHelpContext;
  116. end;
  117. constructor Exception.CreateFmtHelp(const Msg: string; const Args: array of const;
  118. AHelpContext: Integer);
  119. begin
  120. inherited create;
  121. fmessage:=Format(Msg,args);
  122. fhelpcontext:=AHelpContext;
  123. end;
  124. constructor Exception.CreateResHelp(ResString: PString; AHelpContext: Integer);
  125. begin
  126. inherited create;
  127. fmessage:=ResString^;
  128. fhelpcontext:=AHelpContext;
  129. end;
  130. constructor Exception.CreateResFmtHelp(ResString: PString; const Args: array of const;
  131. AHelpContext: Integer);
  132. begin
  133. inherited create;
  134. fmessage:=Format(ResString^,args);
  135. fhelpcontext:=AHelpContext;
  136. end;
  137. procedure EHeapMemoryError.FreeInstance;
  138. begin
  139. if AllowFree then
  140. inherited FreeInstance;
  141. end;
  142. Constructor EVariantError.CreateCode (Code : longint);
  143. begin
  144. case Code of
  145. VAR_OK:
  146. Create(SNoError);
  147. VAR_PARAMNOTFOUND:
  148. Create(SVarParamNotFound);
  149. VAR_TYPEMISMATCH:
  150. Create(SInvalidVarCast);
  151. VAR_BADVARTYPE:
  152. Create(SVarBadType);
  153. VAR_OVERFLOW:
  154. Create(SVarOverflow);
  155. VAR_BADINDEX:
  156. Create(SVarArrayBounds);
  157. VAR_ARRAYISLOCKED:
  158. Create(SVarArrayLocked);
  159. VAR_NOTIMPL:
  160. Create(SVarNotImplemented);
  161. VAR_OUTOFMEMORY:
  162. Create(SVarOutOfMemory);
  163. VAR_INVALIDARG:
  164. Create(SVarInvalid);
  165. VAR_UNEXPECTED,
  166. VAR_EXCEPTION:
  167. Create(SVarUnexpected);
  168. else
  169. CreateFmt(SUnknownErrorCode,[Code]);
  170. end;
  171. ErrCode:=Code;
  172. end;
  173. {$ifopt S+}
  174. {$define STACKCHECK_WAS_ON}
  175. {$S-}
  176. {$endif OPT S }
  177. Procedure CatchUnhandledException (Obj : TObject; Addr: Pointer; FrameCount: Longint; Frames: PPointer);[public,alias:'FPC_BREAK_UNHANDLED_EXCEPTION'];
  178. Var
  179. Message : String;
  180. i : longint;
  181. begin
  182. Writeln(stdout,'An unhandled exception occurred at $',HexStr(Ptrint(Addr),sizeof(PtrInt)*2),' :');
  183. if Obj is exception then
  184. begin
  185. Message:=Exception(Obj).ClassName+' : '+Exception(Obj).Message;
  186. Writeln(stdout,Message);
  187. end
  188. else
  189. Writeln(stdout,'Exception object ',Obj.ClassName,' is not of class Exception.');
  190. Writeln(stdout,BackTraceStrFunc(Addr));
  191. if (FrameCount>0) then
  192. begin
  193. for i:=0 to FrameCount-1 do
  194. Writeln(stdout,BackTraceStrFunc(Frames[i]));
  195. end;
  196. Writeln(stdout,'');
  197. end;
  198. Var OutOfMemory : EOutOfMemory;
  199. InValidPointer : EInvalidPointer;
  200. Procedure RunErrorToExcept (ErrNo : Longint; Address,Frame : Pointer);
  201. Var E : Exception;
  202. S : String;
  203. begin
  204. Case Errno of
  205. 1,203 : E:=OutOfMemory;
  206. 204 : E:=InvalidPointer;
  207. 2,3,4,5,6,100,101,102,103,105,106 : { I/O errors }
  208. begin
  209. Case Errno of
  210. 2 : S:=SFileNotFound;
  211. 3 : S:=SInvalidFileName;
  212. 4 : S:=STooManyOpenFiles;
  213. 5 : S:=SAccessDenied;
  214. 6 : S:=SInvalidFileHandle;
  215. 15 : S:=SInvalidDrive;
  216. 100 : S:=SEndOfFile;
  217. 101 : S:=SDiskFull;
  218. 102 : S:=SFileNotAssigned;
  219. 103 : S:=SFileNotOpen;
  220. 104 : S:=SFileNotOpenForInput;
  221. 105 : S:=SFileNotOpenForOutput;
  222. 106 : S:=SInvalidInput;
  223. end;
  224. E:=EinOutError.Create (S);
  225. EInoutError(E).ErrorCode:=IOresult; // Clears InOutRes !!
  226. end;
  227. // We don't set abstracterrorhandler, but we do it here.
  228. // Unless the use sets another handler we'll get here anyway...
  229. 200 : E:=EDivByZero.Create(SDivByZero);
  230. 201 : E:=ERangeError.Create(SRangeError);
  231. 205 : E:=EOverflow.Create(SOverflow);
  232. 206 : E:=EOverflow.Create(SUnderflow);
  233. 207 : E:=EInvalidOp.Create(SInvalidOp);
  234. 211 : E:=EAbstractError.Create(SAbstractError);
  235. 214 : E:=EBusError.Create(SBusError);
  236. 215 : E:=EIntOverflow.Create(SIntOverflow);
  237. 216 : E:=EAccessViolation.Create(SAccessViolation);
  238. 217 : E:=EPrivilege.Create(SPrivilege);
  239. 218 : E:=EControlC.Create(SControlC);
  240. 219 : E:=EInvalidCast.Create(SInvalidCast);
  241. 220 : E:=EVariantError.Create(SInvalidVarCast);
  242. 221 : E:=EVariantError.Create(SInvalidVarOp);
  243. 222 : E:=EVariantError.Create(SDispatchError);
  244. 223 : E:=EVariantError.Create(SVarArrayCreate);
  245. 224 : E:=EVariantError.Create(SVarNotArray);
  246. 225 : E:=EVariantError.Create(SVarArrayBounds);
  247. 227 : E:=EAssertionFailed.Create(SAssertionFailed);
  248. 228 : E:=EExternalException.Create(SExternalException);
  249. 229 : E:=EIntfCastError.Create(SIntfCastError);
  250. 230 : E:=ESafecallException.Create(SSafecallException);
  251. 232 : E:=ENoThreadSupport.Create(SNoThreadSupport);
  252. else
  253. E:=Exception.CreateFmt (SUnKnownRunTimeError,[Errno]);
  254. end;
  255. Raise E at Address,Frame;
  256. end;
  257. {$IFDEF HAS_OSERROR}
  258. Procedure RaiseLastOSError;
  259. var
  260. ECode: Cardinal;
  261. E : EOSError;
  262. begin
  263. ECode := GetLastOSError;
  264. If (ECode<>0) then
  265. E:=EOSError.CreateFmt(SOSError, [ECode, SysErrorMessage(ECode)])
  266. else
  267. E:=EOSError.Create(SUnkOSError);
  268. E.ErrorCode:=ECode;
  269. Raise E;
  270. end;
  271. {$else}
  272. Procedure RaiseLastOSError;
  273. begin
  274. Raise Exception.Create('RaiseLastOSError not implemented on this platform.');
  275. end;
  276. {$endif}
  277. Procedure AssertErrorHandler (Const Msg,FN : ShortString;LineNo:longint; TheAddr : pointer);
  278. Var
  279. S : String;
  280. begin
  281. If Msg='' then
  282. S:=SAssertionFailed
  283. else
  284. S:=Msg;
  285. Raise EAssertionFailed.Createfmt(SAssertError,[S,Fn,LineNo]); // at Pointer(theAddr);
  286. end;
  287. {$ifdef STACKCHECK_WAS_ON}
  288. {$S+}
  289. {$endif}
  290. Procedure InitExceptions;
  291. {
  292. Must install uncaught exception handler (ExceptProc)
  293. and install exceptions for system exceptions or signals.
  294. (e.g: SIGSEGV -> ESegFault or so.)
  295. }
  296. begin
  297. ExceptProc:=@CatchUnhandledException;
  298. // Create objects that may have problems when there is no memory.
  299. OutOfMemory:=EOutOfMemory.Create(SOutOfMemory);
  300. OutOfMemory.AllowFree:=false;
  301. InvalidPointer:=EInvalidPointer.Create(SInvalidPointer);
  302. InvalidPointer.AllowFree:=false;
  303. AssertErrorProc:=@AssertErrorHandler;
  304. ErrorProc:=@RunErrorToExcept;
  305. OnShowException:=Nil;
  306. end;
  307. Procedure DoneExceptions;
  308. begin
  309. OutOfMemory.AllowFree:=true;
  310. OutOfMemory.Free;
  311. InValidPointer.AllowFree:=true;
  312. InValidPointer.Free;
  313. end;
  314. { Exception handling routines }
  315. function ExceptObject: TObject;
  316. begin
  317. If RaiseList=Nil then
  318. Result:=Nil
  319. else
  320. Result:=RaiseList^.FObject;
  321. end;
  322. function ExceptAddr: Pointer;
  323. begin
  324. If RaiseList=Nil then
  325. Result:=Nil
  326. else
  327. Result:=RaiseList^.Addr;
  328. end;
  329. function ExceptFrameCount: Longint;
  330. begin
  331. If RaiseList=Nil then
  332. Result:=0
  333. else
  334. Result:=RaiseList^.Framecount;
  335. end;
  336. function ExceptFrames: PPointer;
  337. begin
  338. If RaiseList=Nil then
  339. Result:=Nil
  340. else
  341. Result:=RaiseList^.Frames;
  342. end;
  343. function ExceptionErrorMessage(ExceptObject: TObject; ExceptAddr: Pointer;
  344. Buffer: PChar; Size: Integer): Integer;
  345. Var
  346. S : AnsiString;
  347. Len : Integer;
  348. begin
  349. S:=Format(SExceptionErrorMessage,[ExceptAddr,ExceptObject.ClassName]);
  350. If ExceptObject is Exception then
  351. S:=Format('%s:'#10'%s',[S,Exception(ExceptObject).Message]);
  352. Len:=Length(S);
  353. If S[Len]<>'.' then
  354. begin
  355. S:=S+'.';
  356. Inc(len);
  357. end;
  358. If Len>Size then
  359. Len:=Size;
  360. if Len > 0 then
  361. Move(S[1],Buffer^,Len);
  362. Result:=Len;
  363. end;
  364. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);
  365. // use shortstring. On exception, the heap may be corrupt.
  366. Var
  367. Buf : ShortString;
  368. begin
  369. SetLength(Buf,ExceptionErrorMessage(ExceptObject,ExceptAddr,@Buf[1],255));
  370. If IsConsole Then
  371. writeln(Buf)
  372. else
  373. If Assigned(OnShowException) Then
  374. OnShowException (Buf);
  375. end;
  376. procedure Abort;
  377. begin
  378. Raise EAbort.Create(SAbortError) at Pointer(Get_Caller_addr(Get_Frame));
  379. end;
  380. procedure OutOfMemoryError;
  381. begin
  382. Raise OutOfMemory;
  383. end;
  384. { ---------------------------------------------------------------------
  385. Initialization/Finalization/exit code
  386. ---------------------------------------------------------------------}
  387. Type
  388. PPRecord = ^TPRecord;
  389. TPRecord = Record
  390. Func : TTerminateProc;
  391. NextFunc : PPRecord;
  392. end;
  393. Const
  394. TPList : PPRecord = Nil;
  395. procedure AddTerminateProc(TermProc: TTerminateProc);
  396. Var
  397. TPR : PPRecord;
  398. begin
  399. New(TPR);
  400. With TPR^ do
  401. begin
  402. NextFunc:=TPList;
  403. Func:=TermProc;
  404. end;
  405. TPList:=TPR;
  406. end;
  407. function CallTerminateProcs: Boolean;
  408. Var
  409. TPR : PPRecord;
  410. begin
  411. Result:=True;
  412. TPR:=TPList;
  413. While Result and (TPR<>Nil) do
  414. begin
  415. Result:=TPR^.Func();
  416. TPR:=TPR^.NextFunc;
  417. end;
  418. end;
  419. { ---------------------------------------------------------------------
  420. Diskh functions, OS independent.
  421. ---------------------------------------------------------------------}
  422. function ForceDirectories(Const Dir: string): Boolean;
  423. var
  424. E: EInOutError;
  425. ADrv : String;
  426. function DoForceDirectories(Const Dir: string): Boolean;
  427. var
  428. ADir : String;
  429. begin
  430. Result:=True;
  431. ADir:=ExcludeTrailingPathDelimiter(Dir);
  432. if (ADir='') then Exit;
  433. if Not DirectoryExists(ADir) then
  434. begin
  435. Result:=DoForceDirectories(ExtractFilePath(ADir));
  436. If Result then
  437. Result := CreateDir(ADir);
  438. end;
  439. end;
  440. begin
  441. Result := False;
  442. ADrv := ExtractFileDrive(Dir);
  443. if (ADrv<>'') and (not DirectoryExists(ADrv)) then Exit;
  444. if Dir='' then
  445. begin
  446. E:=EInOutError.Create(SCannotCreateEmptyDir);
  447. E.ErrorCode:=3;
  448. Raise E;
  449. end;
  450. Result := DoForceDirectories(Dir);
  451. end;
  452. Procedure GetRandomBytes(Var Buf; NBytes : Integer);
  453. Var
  454. I : Integer;
  455. P : PByte;
  456. begin
  457. P:=@Buf;
  458. Randomize;
  459. For I:=0 to NBytes-1 do
  460. P[i]:=Random(256);
  461. end;
  462. {$IFDEF HASCREATEGUID}
  463. Function SysCreateGUID(out GUID : TGUID) : Integer; forward;
  464. {$ENDIF}
  465. Function CreateGUID(out GUID : TGUID) : Integer;
  466. begin
  467. If Assigned(OnCreateGUID) then
  468. Result:=OnCreateGUID(GUID)
  469. else
  470. begin
  471. {$IFDEF HASCREATEGUID}
  472. Result:=SysCreateGUID(GUID);
  473. {$ELSE}
  474. GetRandomBytes(GUID,SizeOf(Guid));
  475. Result:=0;
  476. {$ENDIF}
  477. end;
  478. end;
  479. function SafeLoadLibrary(const FileName: AnsiString;
  480. ErrorMode: DWord = {$ifdef windows}SEM_NOOPENFILEERRORBOX{$else windows}0{$endif windows}): HMODULE;
  481. {$if defined(cpui386) or defined(cpux86_64)}
  482. var
  483. mode : DWord;
  484. fpucw : Word;
  485. ssecw : DWord;
  486. {$endif}
  487. begin
  488. {$if defined(win64) or defined(win32)}
  489. mode:=SetErrorMode(ErrorMode);
  490. {$endif}
  491. try
  492. {$if defined(cpui386) or defined(cpux86_64)}
  493. fpucw:=Get8087CW;
  494. {$ifdef cpui386}
  495. if has_sse_support then
  496. {$endif cpui386}
  497. ssecw:=GetSSECSR;
  498. {$endif}
  499. {$if defined(windows) or defined(win32)}
  500. Result:=LoadLibraryA(PChar(Filename));
  501. {$else}
  502. Result:=0;
  503. {$endif}
  504. finally
  505. {$if defined(cpui386) or defined(cpux86_64)}
  506. Set8087CW(fpucw);
  507. {$ifdef cpui386}
  508. if has_sse_support then
  509. {$endif cpui386}
  510. SetSSECSR(ssecw);
  511. {$endif}
  512. {$if defined(win64) or defined(win32)}
  513. SetErrorMode(mode);
  514. {$endif}
  515. end;
  516. end;