sysutils.inc 18 KB

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