sysutils.inc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  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. { MCBS functions }
  12. {$i sysansi.inc}
  13. {$i syscodepages.inc}
  14. {$macro on}
  15. {$define PathStr:=UnicodeString}
  16. {$define PathPChar:=PWideChar}
  17. {$define SYSUTILSUNICODE}
  18. { Read filename handling functions implementation }
  19. {$i fina.inc}
  20. { Read disk function implementations }
  21. {$i disk.inc}
  22. {$undef SYSUTILSUNICODE}
  23. {$define PathStr:=RawByteString}
  24. {$define PathPChar:=PAnsiChar}
  25. { Read filename handling functions implementation }
  26. {$i fina.inc}
  27. { Read disk function implementations }
  28. {$i disk.inc}
  29. {$undef PathStr}
  30. {$undef PathPChar}
  31. { Read file utility functions implementation }
  32. {$i filutil.inc}
  33. { variant error codes }
  34. {$i varerror.inc}
  35. { Type helpers}
  36. {$i syshelp.inc}
  37. {$ifndef OS_FILEISREADONLY}
  38. Function FileIsReadOnly(const FileName: RawByteString): Boolean;
  39. begin
  40. Result := (FileGetAttr(FileName) and faReadOnly) <> 0;
  41. end;
  42. Function FileIsReadOnly(const FileName: UnicodeString): Boolean;
  43. begin
  44. Result := (FileGetAttr(FileName) and faReadOnly) <> 0;
  45. end;
  46. {$endif OS_FILEISREADONLY}
  47. {$ifndef OS_FILESETDATEBYNAME}
  48. Function FileSetDate (Const FileName : RawByteString;Age : Longint) : Longint;
  49. Var
  50. fd : THandle;
  51. begin
  52. { at least windows requires fmOpenWrite here }
  53. fd:=FileOpen(FileName,fmOpenWrite);
  54. If (Fd<>feInvalidHandle) then
  55. try
  56. Result:=FileSetDate(fd,Age);
  57. finally
  58. FileClose(fd);
  59. end
  60. else
  61. {$ifdef HAS_OSERROR}
  62. Result:=GetLastOSError;
  63. {$else}
  64. Result:=-1;
  65. {$endif}
  66. end;
  67. Function FileSetDate (Const FileName : UnicodeString;Age : Longint) : Longint;
  68. Var
  69. fd : THandle;
  70. begin
  71. { at least windows requires fmOpenWrite here }
  72. fd:=FileOpen(FileName,fmOpenWrite);
  73. If (Fd<>feInvalidHandle) then
  74. try
  75. Result:=FileSetDate(fd,Age);
  76. finally
  77. FileClose(fd);
  78. end
  79. else
  80. {$ifdef HAS_OSERROR}
  81. Result:=GetLastOSError;
  82. {$else}
  83. Result:=-1;
  84. {$endif}
  85. end;
  86. {$endif}
  87. { Read String Handling functions implementation }
  88. {$i sysstr.inc}
  89. { Read date & Time function implementations }
  90. {$ifndef FPUNONE}
  91. {$i dati.inc}
  92. {$endif}
  93. {$IFNDEF HAS_GETTICKCOUNT}
  94. function GetTickCount: LongWord;
  95. begin
  96. Result := LongWord(GetTickCount64);
  97. end;
  98. {$ENDIF}
  99. {$IFNDEF HAS_GETTICKCOUNT64}
  100. function GetTickCount64: QWord;
  101. begin
  102. {$IFDEF FPU_NONE}
  103. {$IFDEF HAS_SYSTIMERTICK}
  104. Result := SysTimerTick;
  105. {$ELSE}
  106. Result := 0;
  107. {$ENDIF}
  108. {$ELSE}
  109. Result := Trunc(Now * 24 * 60 * 60 * 1000);
  110. {$ENDIF}
  111. end;
  112. {$ENDIF}
  113. { Read pchar handling functions implementation }
  114. {$i syspch.inc}
  115. { generic internationalisation code }
  116. {$i sysint.inc}
  117. { wide string functions }
  118. {$i syswide.inc}
  119. {$ifdef FPC_HAS_UNICODESTRING}
  120. { unicode string functions }
  121. {$i sysuni.inc}
  122. {$i sysencoding.inc}
  123. {$endif FPC_HAS_UNICODESTRING}
  124. { threading stuff }
  125. {$i sysuthrd.inc}
  126. { OS utility code }
  127. {$i osutil.inc}
  128. procedure FreeAndNil(var obj);
  129. var
  130. temp: tobject;
  131. begin
  132. temp:=tobject(obj);
  133. pointer(obj):=nil;
  134. temp.free;
  135. end;
  136. { Interfaces support }
  137. {$i sysuintf.inc}
  138. constructor Exception.Create(const msg : string);
  139. begin
  140. inherited create;
  141. fmessage:=msg;
  142. end;
  143. constructor Exception.CreateFmt(const msg : string; const args : array of const);
  144. begin
  145. inherited create;
  146. fmessage:=Format(msg,args);
  147. end;
  148. constructor Exception.CreateRes(ResString: PString);
  149. begin
  150. inherited create;
  151. fmessage:=ResString^;
  152. end;
  153. constructor Exception.CreateResFmt(ResString: PString; const Args: array of const);
  154. begin
  155. inherited create;
  156. fmessage:=Format(ResString^,args);
  157. end;
  158. constructor Exception.CreateHelp(const Msg: string; AHelpContext: Longint);
  159. begin
  160. inherited create;
  161. fmessage:=Msg;
  162. fhelpcontext:=AHelpContext;
  163. end;
  164. constructor Exception.CreateFmtHelp(const Msg: string; const Args: array of const;
  165. AHelpContext: Longint);
  166. begin
  167. inherited create;
  168. fmessage:=Format(Msg,args);
  169. fhelpcontext:=AHelpContext;
  170. end;
  171. constructor Exception.CreateResHelp(ResString: PString; AHelpContext: Longint);
  172. begin
  173. inherited create;
  174. fmessage:=ResString^;
  175. fhelpcontext:=AHelpContext;
  176. end;
  177. constructor Exception.CreateResFmtHelp(ResString: PString; const Args: array of const;
  178. AHelpContext: Longint);
  179. begin
  180. inherited create;
  181. fmessage:=Format(ResString^,args);
  182. fhelpcontext:=AHelpContext;
  183. end;
  184. Function Exception.ToString : String;
  185. begin
  186. Result:=ClassName+': '+Message;
  187. end;
  188. procedure EHeapMemoryError.FreeInstance;
  189. begin
  190. if AllowFree then
  191. inherited FreeInstance;
  192. end;
  193. Constructor EVariantError.CreateCode (Code : longint);
  194. begin
  195. case Code of
  196. VAR_OK:
  197. Create(SNoError);
  198. VAR_PARAMNOTFOUND:
  199. Create(SVarParamNotFound);
  200. VAR_TYPEMISMATCH:
  201. Create(SInvalidVarCast);
  202. VAR_BADVARTYPE:
  203. Create(SVarBadType);
  204. VAR_OVERFLOW:
  205. Create(SVarOverflow);
  206. VAR_BADINDEX:
  207. Create(SVarArrayBounds);
  208. VAR_ARRAYISLOCKED:
  209. Create(SVarArrayLocked);
  210. VAR_NOTIMPL:
  211. Create(SVarNotImplemented);
  212. VAR_OUTOFMEMORY:
  213. Create(SVarOutOfMemory);
  214. VAR_INVALIDARG:
  215. Create(SVarInvalid);
  216. VAR_UNEXPECTED,
  217. VAR_EXCEPTION:
  218. Create(SVarUnexpected);
  219. else
  220. CreateFmt(SUnknownErrorCode,[Code]);
  221. end;
  222. ErrCode:=Code;
  223. end;
  224. {$ifdef windows}
  225. function EExternal.GetExceptionRecord: PExceptionRecord;
  226. begin
  227. result:=@FExceptionRecord;
  228. end;
  229. {$endif windows}
  230. {$push}
  231. {$S-}
  232. Procedure CatchUnhandledException (Obj : TObject; Addr: CodePointer; FrameCount: Longint; Frames: PCodePointer);[public,alias:'FPC_BREAK_UNHANDLED_EXCEPTION'];
  233. Var
  234. i : longint;
  235. hstdout : ^text;
  236. begin
  237. if WriteErrorsToStdErr then
  238. hstdout:=@stderr
  239. else
  240. hstdout:=@stdout;
  241. Writeln(hstdout^,'An unhandled exception occurred at $',HexStr(Addr),':');
  242. if Obj is exception then
  243. Writeln(hstdout^,Obj.ClassName,': ',Exception(Obj).Message)
  244. else if Obj is TObject then
  245. Writeln(hstdout^,'Exception object ',Obj.ClassName,' is not of class Exception.')
  246. else
  247. Writeln(hstdout^,'Exception object is not a valid class.');
  248. {$IFDEF HAS_OSERROR}
  249. {$IFDEF DEBUG_EXCEPTIONS_LASTOSERROR}
  250. WriteLn (HStdOut^, 'Last OS error detected in the RTL: ', GetLastOSError);
  251. {$ENDIF DEBUG_EXCEPTIONS_LASTOSERROR}
  252. {$ENDIF HAS_OSERROR}
  253. Writeln(hstdout^,BackTraceStrFunc(Addr));
  254. if (FrameCount>0) then
  255. begin
  256. for i:=0 to FrameCount-1 do
  257. Writeln(hstdout^,BackTraceStrFunc(Frames[i]));
  258. end;
  259. Writeln(hstdout^,'');
  260. end;
  261. type
  262. PExceptMapEntry=^TExceptMapEntry;
  263. TExceptMapEntry=record
  264. code: byte;
  265. cls: ExceptClass;
  266. {$IFDEF FPC_HAS_FEATURE_RESOURCES} // This is necessary for 2.4.4, which does not have reasources as a separate feature
  267. msg: PResStringRec;
  268. {$else FPC_HAS_FEATURE_RESOURCES}
  269. msg: PString;
  270. {$endif FPC_HAS_FEATURE_RESOURCES}
  271. end;
  272. const
  273. exceptmap: array[0..29] of TExceptMapEntry = (
  274. (code: 200; cls: EDivByZero; msg: @SDivByZero),
  275. (code: 201; cls: ERangeError; msg: @SRangeError),
  276. (code: 202; cls: EStackOverflow; msg: @SStackOverflow),
  277. (code: 205; cls: EOverflow; msg: @SOverflow),
  278. (code: 206; cls: EUnderflow; msg: @SUnderflow),
  279. (code: 207; cls: EInvalidOp; msg: @SInvalidOp),
  280. { Delphi distinguishes reDivByZero from reZeroDivide, but maps both to code 200. }
  281. (code: 208; cls: EZeroDivide; msg: @SZeroDivide),
  282. (code: 210; cls: EObjectCheck; msg: @SObjectCheckError),
  283. (code: 211; cls: EAbstractError; msg: @SAbstractError),
  284. (code: 212; cls: EExternalException; msg: @SExternalException),
  285. (code: 214; cls: EBusError; msg: @SBusError),
  286. (code: 215; cls: EIntOverflow; msg: @SIntOverflow),
  287. (code: 216; cls: EAccessViolation; msg: @SAccessViolation),
  288. (code: 217; cls: EControlC; msg: @SControlC),
  289. (code: 218; cls: EPrivilege; msg: @SPrivilege),
  290. (code: 219; cls: EInvalidCast; msg: @SInvalidCast),
  291. (code: 220; cls: EVariantError; msg: @SInvalidVarCast),
  292. (code: 221; cls: EVariantError; msg: @SInvalidVarOp),
  293. (code: 222; cls: EVariantError; msg: @SDispatchError),
  294. (code: 223; cls: EVariantError; msg: @SVarArrayCreate),
  295. (code: 224; cls: EVariantError; msg: @SVarNotArray),
  296. (code: 225; cls: EVariantError; msg: @SVarArrayBounds),
  297. (code: 227; cls: EAssertionFailed; msg: @SAssertionFailed),
  298. (code: 228; cls: EIntfCastError; msg: @SIntfCastError),
  299. (code: 229; cls: ESafecallException; msg: @SSafecallException),
  300. (code: 231; cls: EConvertError; msg: @SiconvError),
  301. (code: 232; cls: ENoThreadSupport; msg: @SNoThreadSupport),
  302. (code: 233; cls: ENoWideStringSupport; msg: @SSigQuit),
  303. (code: 234; cls: ENoWideStringSupport; msg: @SMissingWStringManager),
  304. (code: 235; cls: ENoDynLibsSupport; msg: @SNoDynLibsSupport)
  305. );
  306. function FindExceptMapEntry(err: longint): PExceptMapEntry;
  307. var
  308. i: longint;
  309. begin
  310. for i:=low(exceptmap) to high(exceptmap) do
  311. if err=exceptmap[i].code then
  312. begin
  313. result:=@exceptmap[i];
  314. exit;
  315. end;
  316. result:=nil;
  317. end;
  318. Var OutOfMemory : EOutOfMemory;
  319. InValidPointer : EInvalidPointer;
  320. Procedure RunErrorToExcept (ErrNo : Longint; Address : CodePointer; Frame : Pointer);
  321. var
  322. E: Exception;
  323. HS: PString;
  324. Entry: PExceptMapEntry;
  325. begin
  326. Case Errno of
  327. 1,203 : E:=OutOfMemory;
  328. 204 : E:=InvalidPointer;
  329. else
  330. Entry:=FindExceptMapEntry(ErrNo);
  331. if Assigned(Entry) then
  332. E:=Entry^.cls.CreateRes(Entry^.msg)
  333. else
  334. begin
  335. HS:=nil;
  336. Case Errno of
  337. 2 : HS:=@SFileNotFound;
  338. 3 : HS:=@SInvalidFileName;
  339. 4 : HS:=@STooManyOpenFiles;
  340. 5 : HS:=@SAccessDenied;
  341. 6 : HS:=@SInvalidFileHandle;
  342. 15 : HS:=@SInvalidDrive;
  343. 100 : HS:=@SEndOfFile;
  344. 101 : HS:=@SDiskFull;
  345. 102 : HS:=@SFileNotAssigned;
  346. 103 : HS:=@SFileNotOpen;
  347. 104 : HS:=@SFileNotOpenForInput;
  348. 105 : HS:=@SFileNotOpenForOutput;
  349. 106 : HS:=@SInvalidInput;
  350. end;
  351. if Assigned(HS) then
  352. E:=EInOutError.CreateRes(HS)
  353. else
  354. E:=EInOutError.CreateResFmt(@SUnknownRunTimeError,[errno]);
  355. // this routine can be called from FPC_IOCHECK,
  356. // which clears inoutres and then passes its
  357. // original value to HandleErrorFrame() (which calls
  358. // us). So use errno rather than IOResult, and clear
  359. // InOutRes explicitly in case we can also be called
  360. // from a place that does not clear InOutRes explicitly
  361. EInoutError(E).ErrorCode:=errno;
  362. inoutres:=0;
  363. end;
  364. end;
  365. Raise E at Address,Frame;
  366. end;
  367. {$IFDEF HAS_OSERROR}
  368. Procedure RaiseLastOSError;overload;
  369. begin
  370. RaiseLastOSError(GetLastOSError);
  371. end;
  372. Procedure RaiseLastOSError(LastError: Integer);overload;
  373. var
  374. E : EOSError;
  375. begin
  376. If (LastError<>0) then
  377. E:=EOSError.CreateFmt(SOSError, [LastError, SysErrorMessage(LastError)])
  378. else
  379. E:=EOSError.Create(SUnkOSError);
  380. E.ErrorCode:=LastError;
  381. Raise E;
  382. end;
  383. {$else}
  384. Procedure RaiseLastOSError;overload;
  385. begin
  386. Raise Exception.Create('RaiseLastOSError not implemented on this platform.');
  387. end;
  388. Procedure RaiseLastOSError(LastError: Integer);overload;
  389. begin
  390. RaiseLastOSError;
  391. end;
  392. {$endif}
  393. Procedure AssertErrorHandler (Const Msg,FN : ShortString;LineNo:longint; TheAddr : pointer);
  394. Var
  395. S : String;
  396. begin
  397. If Msg='' then
  398. S:=SAssertionFailed
  399. else
  400. S:=Msg;
  401. Raise EAssertionFailed.Createfmt(SAssertError,[S,Fn,LineNo]) at get_caller_addr(theAddr), get_caller_frame(theAddr);
  402. end;
  403. {$pop} //{$S-} for Error handling functions
  404. Procedure InitExceptions;
  405. {
  406. Must install uncaught exception handler (ExceptProc)
  407. and install exceptions for system exceptions or signals.
  408. (e.g: SIGSEGV -> ESegFault or so.)
  409. }
  410. begin
  411. ExceptionClass := Exception;
  412. ExceptProc:=@CatchUnhandledException;
  413. // Create objects that may have problems when there is no memory.
  414. OutOfMemory:=EOutOfMemory.Create(SOutOfMemory);
  415. OutOfMemory.AllowFree:=false;
  416. InvalidPointer:=EInvalidPointer.Create(SInvalidPointer);
  417. InvalidPointer.AllowFree:=false;
  418. AssertErrorProc:=@AssertErrorHandler;
  419. ErrorProc:=@RunErrorToExcept;
  420. OnShowException:=Nil;
  421. end;
  422. Procedure DoneExceptions;
  423. begin
  424. OutOfMemory.AllowFree:=true;
  425. OutOfMemory.Free;
  426. InValidPointer.AllowFree:=true;
  427. InValidPointer.Free;
  428. end;
  429. { Exception handling routines }
  430. function ExceptObject: TObject;
  431. begin
  432. If RaiseList=Nil then
  433. Result:=Nil
  434. else
  435. Result:=RaiseList^.FObject;
  436. end;
  437. function ExceptAddr: CodePointer;
  438. begin
  439. If RaiseList=Nil then
  440. Result:=Nil
  441. else
  442. Result:=RaiseList^.Addr;
  443. end;
  444. function ExceptFrameCount: Longint;
  445. begin
  446. If RaiseList=Nil then
  447. Result:=0
  448. else
  449. Result:=RaiseList^.Framecount;
  450. end;
  451. function ExceptFrames: PCodePointer;
  452. begin
  453. If RaiseList=Nil then
  454. Result:=Nil
  455. else
  456. Result:=RaiseList^.Frames;
  457. end;
  458. function ExceptionErrorMessage(ExceptObject: TObject; ExceptAddr: Pointer;
  459. Buffer: PChar; Size: Integer): Integer;
  460. Var
  461. S : AnsiString;
  462. Len : Integer;
  463. begin
  464. S:=Format(SExceptionErrorMessage,[ExceptAddr,ExceptObject.ClassName]);
  465. If ExceptObject is Exception then
  466. S:=Format('%s:'#10'%s',[S,Exception(ExceptObject).Message]);
  467. Len:=Length(S);
  468. If S[Len]<>'.' then
  469. begin
  470. S:=S+'.';
  471. Inc(len);
  472. end;
  473. If Len>Size then
  474. Len:=Size;
  475. if Len > 0 then
  476. Move(S[1],Buffer^,Len);
  477. Result:=Len;
  478. end;
  479. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);
  480. // use shortstring. On exception, the heap may be corrupt.
  481. Var
  482. Buf : ShortString;
  483. begin
  484. SetLength(Buf,ExceptionErrorMessage(ExceptObject,ExceptAddr,@Buf[1],255));
  485. If IsConsole Then
  486. writeln(Buf)
  487. else
  488. If Assigned(OnShowException) Then
  489. OnShowException (Buf);
  490. end;
  491. procedure Abort;
  492. begin
  493. Raise EAbort.Create(SAbortError) at CodePointer(Get_Caller_addr(Get_Frame));
  494. end;
  495. procedure OutOfMemoryError;
  496. begin
  497. Raise OutOfMemory;
  498. end;
  499. { ---------------------------------------------------------------------
  500. Initialization/Finalization/exit code
  501. ---------------------------------------------------------------------}
  502. Type
  503. PPRecord = ^TPRecord;
  504. TPRecord = Record
  505. Func : TTerminateProc;
  506. NextFunc : PPRecord;
  507. end;
  508. Const
  509. TPList : PPRecord = Nil;
  510. procedure AddTerminateProc(TermProc: TTerminateProc);
  511. Var
  512. TPR : PPRecord;
  513. begin
  514. New(TPR);
  515. With TPR^ do
  516. begin
  517. NextFunc:=TPList;
  518. Func:=TermProc;
  519. end;
  520. TPList:=TPR;
  521. end;
  522. function CallTerminateProcs: Boolean;
  523. Var
  524. TPR : PPRecord;
  525. begin
  526. Result:=True;
  527. TPR:=TPList;
  528. While Result and (TPR<>Nil) do
  529. begin
  530. Result:=TPR^.Func();
  531. TPR:=TPR^.NextFunc;
  532. end;
  533. end;
  534. { ---------------------------------------------------------------------
  535. Diskh functions, OS independent.
  536. ---------------------------------------------------------------------}
  537. Function GetCurrentDir: {$ifdef FPC_UNICODE_RTL}UnicodeString{$else}AnsiString{$endif};
  538. begin
  539. GetDir(0,Result);
  540. end;
  541. { ---------------------------------------------------------------------
  542. Other functions, OS independent.
  543. ---------------------------------------------------------------------}
  544. Var
  545. GUIDCalledRandomize : Boolean = False;
  546. Procedure GetRandomBytes(Var Buf; NBytes : Integer);
  547. Var
  548. I : Integer;
  549. P : PByte;
  550. begin
  551. P:=@Buf;
  552. If Not GUIDCalledRandomize then
  553. begin
  554. Randomize;
  555. GUIDCalledRandomize:=True;
  556. end;
  557. For I:=0 to NBytes-1 do
  558. P[i]:=Random(256);
  559. end;
  560. {$IFDEF HASCREATEGUID}
  561. Function SysCreateGUID(out GUID : TGUID) : Integer; forward;
  562. {$ENDIF}
  563. Function CreateGUID(out GUID : TGUID) : Integer;
  564. begin
  565. If Assigned(OnCreateGUID) then
  566. Result:=OnCreateGUID(GUID)
  567. else
  568. begin
  569. {$IFDEF HASCREATEGUID}
  570. Result:=SysCreateGUID(GUID);
  571. {$ELSE}
  572. GetRandomBytes(GUID,SizeOf(Guid));
  573. guid.clock_seq_hi_and_reserved:=(guid.clock_seq_hi_and_reserved and $3F) + 64;
  574. guid.time_hi_and_version :=(guid.time_hi_and_version and $0FFF)+ $4000;
  575. Result:=0;
  576. {$ENDIF}
  577. end;
  578. end;
  579. function SafeLoadLibrary(const FileName: AnsiString;
  580. ErrorMode: DWord = {$ifdef windows}SEM_NOOPENFILEERRORBOX{$else windows}0{$endif windows}): HMODULE;
  581. {$if defined(cpui386) or defined(cpux86_64)}
  582. var
  583. mode : DWord;
  584. fpucw : Word;
  585. ssecw : DWord;
  586. {$endif}
  587. begin
  588. {$if defined(win64) or defined(win32)}
  589. mode:=SetErrorMode(ErrorMode);
  590. {$endif}
  591. try
  592. {$if defined(cpui386) or defined(cpux86_64)}
  593. fpucw:=Get8087CW;
  594. {$ifdef cpui386}
  595. if has_sse_support then
  596. {$endif cpui386}
  597. ssecw:=GetMXCSR;
  598. {$endif}
  599. {$if defined(windows) or defined(win32)}
  600. Result:=LoadLibraryA(PChar(Filename));
  601. {$else}
  602. Result:=0;
  603. {$endif}
  604. finally
  605. {$if defined(cpui386) or defined(cpux86_64)}
  606. Set8087CW(fpucw);
  607. {$ifdef cpui386}
  608. if has_sse_support then
  609. {$endif cpui386}
  610. SetMXCSR(ssecw);
  611. {$endif}
  612. {$if defined(win64) or defined(win32)}
  613. SetErrorMode(mode);
  614. {$endif}
  615. end;
  616. end;
  617. function GetModuleName(Module: HMODULE): string;
  618. begin
  619. {$ifdef MSWINDOWS}
  620. SetLength(Result,MAX_PATH);
  621. SetLength(Result,GetModuleFileNameA(Module, Pchar(Result),Length(Result)));
  622. {$ELSE}
  623. Result:='';
  624. {$ENDIF}
  625. end;
  626. { Beep support }
  627. procedure Beep;
  628. begin
  629. If Assigned(OnBeep) then
  630. OnBeep;
  631. end;