sysutils.inc 14 KB

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