2
0

sysutils.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  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. procedure FreeMemAndNil(var p);
  137. var
  138. temp:Pointer;
  139. begin
  140. temp := Pointer(p);
  141. Pointer(P):=nil;
  142. FreeMem(temp);
  143. end;
  144. { Interfaces support }
  145. {$i sysuintf.inc}
  146. constructor Exception.Create(const msg : string);
  147. begin
  148. inherited create;
  149. fmessage:=msg;
  150. end;
  151. constructor Exception.CreateFmt(const msg : string; const args : array of const);
  152. begin
  153. inherited create;
  154. fmessage:=Format(msg,args);
  155. end;
  156. constructor Exception.CreateRes(ResString: PString);
  157. begin
  158. inherited create;
  159. fmessage:=ResString^;
  160. end;
  161. constructor Exception.CreateResFmt(ResString: PString; const Args: array of const);
  162. begin
  163. inherited create;
  164. fmessage:=Format(ResString^,args);
  165. end;
  166. constructor Exception.CreateHelp(const Msg: string; AHelpContext: Longint);
  167. begin
  168. inherited create;
  169. fmessage:=Msg;
  170. fhelpcontext:=AHelpContext;
  171. end;
  172. constructor Exception.CreateFmtHelp(const Msg: string; const Args: array of const;
  173. AHelpContext: Longint);
  174. begin
  175. inherited create;
  176. fmessage:=Format(Msg,args);
  177. fhelpcontext:=AHelpContext;
  178. end;
  179. constructor Exception.CreateResHelp(ResString: PString; AHelpContext: Longint);
  180. begin
  181. inherited create;
  182. fmessage:=ResString^;
  183. fhelpcontext:=AHelpContext;
  184. end;
  185. constructor Exception.CreateResFmtHelp(ResString: PString; const Args: array of const;
  186. AHelpContext: Longint);
  187. begin
  188. inherited create;
  189. fmessage:=Format(ResString^,args);
  190. fhelpcontext:=AHelpContext;
  191. end;
  192. Function Exception.ToString : String;
  193. begin
  194. Result:=ClassName+': '+Message;
  195. end;
  196. procedure EHeapMemoryError.FreeInstance;
  197. begin
  198. if AllowFree then
  199. inherited FreeInstance;
  200. end;
  201. Constructor EVariantError.CreateCode (Code : longint);
  202. begin
  203. case Code of
  204. VAR_OK:
  205. Create(SNoError);
  206. VAR_PARAMNOTFOUND:
  207. Create(SVarParamNotFound);
  208. VAR_TYPEMISMATCH:
  209. Create(SInvalidVarCast);
  210. VAR_BADVARTYPE:
  211. Create(SVarBadType);
  212. VAR_OVERFLOW:
  213. Create(SVarOverflow);
  214. VAR_BADINDEX:
  215. Create(SVarArrayBounds);
  216. VAR_ARRAYISLOCKED:
  217. Create(SVarArrayLocked);
  218. VAR_NOTIMPL:
  219. Create(SVarNotImplemented);
  220. VAR_OUTOFMEMORY:
  221. Create(SVarOutOfMemory);
  222. VAR_INVALIDARG:
  223. Create(SVarInvalid);
  224. VAR_UNEXPECTED,
  225. VAR_EXCEPTION:
  226. Create(SVarUnexpected);
  227. else
  228. CreateFmt(SUnknownErrorCode,[Code]);
  229. end;
  230. ErrCode:=Code;
  231. end;
  232. {$if defined(win32) or defined(win64) or defined (wince)}
  233. function EExternal.GetExceptionRecord: PExceptionRecord;
  234. begin
  235. result:=@FExceptionRecord;
  236. end;
  237. {$endif win32 or win64 or wince}
  238. {$push}
  239. {$S-}
  240. Procedure CatchUnhandledException (Obj : TObject; Addr: CodePointer; FrameCount: Longint; Frames: PCodePointer);[public,alias:'FPC_BREAK_UNHANDLED_EXCEPTION'];
  241. Var
  242. i : longint;
  243. hstdout : ^text;
  244. begin
  245. if WriteErrorsToStdErr then
  246. hstdout:=@stderr
  247. else
  248. hstdout:=@stdout;
  249. Writeln(hstdout^,'An unhandled exception occurred at $',HexStr(Addr),':');
  250. if Obj is exception then
  251. Writeln(hstdout^,Obj.ClassName,': ',Exception(Obj).Message)
  252. else if Obj is TObject then
  253. Writeln(hstdout^,'Exception object ',Obj.ClassName,' is not of class Exception.')
  254. else
  255. Writeln(hstdout^,'Exception object is not a valid class.');
  256. {$IFDEF HAS_OSERROR}
  257. {$IFDEF DEBUG_EXCEPTIONS_LASTOSERROR}
  258. WriteLn (HStdOut^, 'Last OS error detected in the RTL: ', GetLastOSError);
  259. {$ENDIF DEBUG_EXCEPTIONS_LASTOSERROR}
  260. {$ENDIF HAS_OSERROR}
  261. Writeln(hstdout^,BackTraceStrFunc(Addr));
  262. if (FrameCount>0) then
  263. begin
  264. for i:=0 to FrameCount-1 do
  265. Writeln(hstdout^,BackTraceStrFunc(Frames[i]));
  266. end;
  267. Writeln(hstdout^,'');
  268. end;
  269. type
  270. PExceptMapEntry=^TExceptMapEntry;
  271. TExceptMapEntry=record
  272. code: byte;
  273. cls: ExceptClass;
  274. {$IFDEF FPC_HAS_FEATURE_RESOURCES} // This is necessary for 2.4.4, which does not have reasources as a separate feature
  275. msg: PResStringRec;
  276. {$else FPC_HAS_FEATURE_RESOURCES}
  277. msg: PString;
  278. {$endif FPC_HAS_FEATURE_RESOURCES}
  279. end;
  280. const
  281. exceptmap: array[0..30] of TExceptMapEntry = (
  282. (code: 200; cls: EDivByZero; msg: @SDivByZero),
  283. (code: 201; cls: ERangeError; msg: @SRangeError),
  284. (code: 202; cls: EStackOverflow; msg: @SStackOverflow),
  285. (code: 205; cls: EOverflow; msg: @SOverflow),
  286. (code: 206; cls: EUnderflow; msg: @SUnderflow),
  287. (code: 207; cls: EInvalidOp; msg: @SInvalidOp),
  288. { Delphi distinguishes reDivByZero from reZeroDivide, but maps both to code 200. }
  289. (code: 208; cls: EZeroDivide; msg: @SZeroDivide),
  290. (code: 210; cls: EObjectCheck; msg: @SObjectCheckError),
  291. (code: 211; cls: EAbstractError; msg: @SAbstractError),
  292. (code: 212; cls: EExternalException; msg: @SExternalException),
  293. (code: 214; cls: EBusError; msg: @SBusError),
  294. (code: 215; cls: EIntOverflow; msg: @SIntOverflow),
  295. (code: 216; cls: EAccessViolation; msg: @SAccessViolation),
  296. (code: 217; cls: EControlC; msg: @SControlC),
  297. (code: 218; cls: EPrivilege; msg: @SPrivilege),
  298. (code: 219; cls: EInvalidCast; msg: @SInvalidCast),
  299. (code: 220; cls: EVariantError; msg: @SInvalidVarCast),
  300. (code: 221; cls: EVariantError; msg: @SInvalidVarOp),
  301. (code: 222; cls: EVariantError; msg: @SDispatchError),
  302. (code: 223; cls: EVariantError; msg: @SVarArrayCreate),
  303. (code: 224; cls: EVariantError; msg: @SVarNotArray),
  304. (code: 225; cls: EVariantError; msg: @SVarArrayBounds),
  305. (code: 227; cls: EAssertionFailed; msg: @SAssertionFailed),
  306. (code: 228; cls: EIntfCastError; msg: @SIntfCastError),
  307. (code: 229; cls: ESafecallException; msg: @SSafecallException),
  308. (code: 231; cls: EConvertError; msg: @SiconvError),
  309. (code: 232; cls: ENoThreadSupport; msg: @SNoThreadSupport),
  310. (code: 233; cls: ESigQuit; msg: @SSigQuit),
  311. (code: 234; cls: ENoWideStringSupport; msg: @SMissingWStringManager),
  312. (code: 235; cls: ENoDynLibsSupport; msg: @SNoDynLibsSupport),
  313. (code: 236; cls: EThreadError; msg: @SThreadError)
  314. );
  315. function FindExceptMapEntry(err: longint): PExceptMapEntry;
  316. var
  317. i: longint;
  318. begin
  319. for i:=low(exceptmap) to high(exceptmap) do
  320. if err=exceptmap[i].code then
  321. begin
  322. result:=@exceptmap[i];
  323. exit;
  324. end;
  325. result:=nil;
  326. end;
  327. Var OutOfMemory : EOutOfMemory;
  328. InValidPointer : EInvalidPointer;
  329. Procedure RunErrorToExcept (ErrNo : Longint; Address : CodePointer; Frame : Pointer);
  330. var
  331. E: Exception;
  332. HS: PString;
  333. Entry: PExceptMapEntry;
  334. begin
  335. Case Errno of
  336. 1,203 : E:=OutOfMemory;
  337. 204 : E:=InvalidPointer;
  338. else
  339. Entry:=FindExceptMapEntry(ErrNo);
  340. if Assigned(Entry) then
  341. E:=Entry^.cls.CreateRes(Entry^.msg)
  342. else
  343. begin
  344. HS:=nil;
  345. Case Errno of
  346. 2 : HS:=@SFileNotFound;
  347. 3 : HS:=@SInvalidFileName;
  348. 4 : HS:=@STooManyOpenFiles;
  349. 5 : HS:=@SAccessDenied;
  350. 6 : HS:=@SInvalidFileHandle;
  351. 15 : HS:=@SInvalidDrive;
  352. 100 : HS:=@SEndOfFile;
  353. 101 : HS:=@SDiskFull;
  354. 102 : HS:=@SFileNotAssigned;
  355. 103 : HS:=@SFileNotOpen;
  356. 104 : HS:=@SFileNotOpenForInput;
  357. 105 : HS:=@SFileNotOpenForOutput;
  358. 106 : HS:=@SInvalidInput;
  359. end;
  360. if Assigned(HS) then
  361. E:=EInOutError.CreateRes(HS)
  362. else
  363. E:=EInOutError.CreateResFmt(@SUnknownRunTimeError,[errno]);
  364. // this routine can be called from FPC_IOCHECK,
  365. // which clears inoutres and then passes its
  366. // original value to HandleErrorFrame() (which calls
  367. // us). So use errno rather than IOResult, and clear
  368. // InOutRes explicitly in case we can also be called
  369. // from a place that does not clear InOutRes explicitly
  370. EInoutError(E).ErrorCode:=errno;
  371. inoutres:=0;
  372. end;
  373. end;
  374. Raise E at Address,Frame;
  375. end;
  376. {$IFDEF HAS_OSERROR}
  377. Procedure RaiseLastOSError;overload;
  378. begin
  379. RaiseLastOSError(GetLastOSError);
  380. end;
  381. Procedure RaiseLastOSError(LastError: Integer);overload;
  382. var
  383. E : EOSError;
  384. begin
  385. If (LastError<>0) then
  386. E:=EOSError.CreateFmt(SOSError, [LastError, SysErrorMessage(LastError)])
  387. else
  388. E:=EOSError.Create(SUnkOSError);
  389. E.ErrorCode:=LastError;
  390. Raise E;
  391. end;
  392. {$else}
  393. Procedure RaiseLastOSError;overload;
  394. begin
  395. Raise Exception.Create('RaiseLastOSError not implemented on this platform.');
  396. end;
  397. Procedure RaiseLastOSError(LastError: Integer);overload;
  398. begin
  399. RaiseLastOSError;
  400. end;
  401. {$endif}
  402. procedure CheckOSError(LastError: Integer);
  403. begin
  404. if LastError <> 0 then
  405. RaiseLastOSError(LastError);
  406. end;
  407. Procedure AssertErrorHandler (Const Msg,FN : ShortString;LineNo:longint; TheAddr : pointer);
  408. Var
  409. S : String;
  410. begin
  411. If Msg='' then
  412. S:=SAssertionFailed
  413. else
  414. S:=Msg;
  415. Raise EAssertionFailed.Createfmt(SAssertError,[S,Fn,LineNo]) at get_caller_addr(theAddr), get_caller_frame(theAddr);
  416. end;
  417. {$pop} //{$S-} for Error handling functions
  418. Procedure InitExceptions;
  419. {
  420. Must install uncaught exception handler (ExceptProc)
  421. and install exceptions for system exceptions or signals.
  422. (e.g: SIGSEGV -> ESegFault or so.)
  423. }
  424. begin
  425. ExceptionClass := Exception;
  426. ExceptProc:=@CatchUnhandledException;
  427. // Create objects that may have problems when there is no memory.
  428. OutOfMemory:=EOutOfMemory.Create(SOutOfMemory);
  429. OutOfMemory.AllowFree:=false;
  430. InvalidPointer:=EInvalidPointer.Create(SInvalidPointer);
  431. InvalidPointer.AllowFree:=false;
  432. AssertErrorProc:=@AssertErrorHandler;
  433. ErrorProc:=@RunErrorToExcept;
  434. OnShowException:=Nil;
  435. end;
  436. Procedure DoneExceptions;
  437. begin
  438. OutOfMemory.AllowFree:=true;
  439. OutOfMemory.Free;
  440. InValidPointer.AllowFree:=true;
  441. InValidPointer.Free;
  442. end;
  443. { Exception handling routines }
  444. function ExceptObject: TObject;
  445. begin
  446. If RaiseList=Nil then
  447. Result:=Nil
  448. else
  449. Result:=RaiseList^.FObject;
  450. end;
  451. function ExceptAddr: CodePointer;
  452. begin
  453. If RaiseList=Nil then
  454. Result:=Nil
  455. else
  456. Result:=RaiseList^.Addr;
  457. end;
  458. function ExceptFrameCount: Longint;
  459. begin
  460. If RaiseList=Nil then
  461. Result:=0
  462. else
  463. Result:=RaiseList^.Framecount;
  464. end;
  465. function ExceptFrames: PCodePointer;
  466. begin
  467. If RaiseList=Nil then
  468. Result:=Nil
  469. else
  470. Result:=RaiseList^.Frames;
  471. end;
  472. function ExceptionErrorMessage(ExceptObject: TObject; ExceptAddr: Pointer;
  473. Buffer: PChar; Size: Integer): Integer;
  474. Var
  475. S : AnsiString;
  476. Len : Integer;
  477. begin
  478. S:=Format(SExceptionErrorMessage,[ExceptAddr,ExceptObject.ClassName]);
  479. If ExceptObject is Exception then
  480. S:=Format('%s:'#10'%s',[S,Exception(ExceptObject).Message]);
  481. Len:=Length(S);
  482. If S[Len]<>'.' then
  483. begin
  484. S:=S+'.';
  485. Inc(len);
  486. end;
  487. If Len>Size then
  488. Len:=Size;
  489. if Len > 0 then
  490. Move(S[1],Buffer^,Len);
  491. Result:=Len;
  492. end;
  493. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);
  494. // use shortstring. On exception, the heap may be corrupt.
  495. Var
  496. Buf : ShortString;
  497. begin
  498. SetLength(Buf,ExceptionErrorMessage(ExceptObject,ExceptAddr,@Buf[1],255));
  499. If IsConsole Then
  500. writeln(Buf)
  501. else
  502. If Assigned(OnShowException) Then
  503. OnShowException (Buf);
  504. end;
  505. procedure Abort;
  506. begin
  507. Raise EAbort.Create(SAbortError) at CodePointer(Get_Caller_addr(Get_Frame));
  508. end;
  509. procedure OutOfMemoryError;
  510. begin
  511. Raise OutOfMemory;
  512. end;
  513. { ---------------------------------------------------------------------
  514. Initialization/Finalization/exit code
  515. ---------------------------------------------------------------------}
  516. Type
  517. PPRecord = ^TPRecord;
  518. TPRecord = Record
  519. Func : TTerminateProc;
  520. NextFunc : PPRecord;
  521. end;
  522. Const
  523. TPList : PPRecord = Nil;
  524. procedure AddTerminateProc(TermProc: TTerminateProc);
  525. Var
  526. TPR : PPRecord;
  527. begin
  528. New(TPR);
  529. With TPR^ do
  530. begin
  531. NextFunc:=TPList;
  532. Func:=TermProc;
  533. end;
  534. TPList:=TPR;
  535. end;
  536. function CallTerminateProcs: Boolean;
  537. Var
  538. TPR : PPRecord;
  539. begin
  540. Result:=True;
  541. TPR:=TPList;
  542. While Result and (TPR<>Nil) do
  543. begin
  544. Result:=TPR^.Func();
  545. TPR:=TPR^.NextFunc;
  546. end;
  547. end;
  548. { ---------------------------------------------------------------------
  549. Diskh functions, OS independent.
  550. ---------------------------------------------------------------------}
  551. Function GetCurrentDir: {$ifdef FPC_UNICODE_RTL}UnicodeString{$else}AnsiString{$endif};
  552. begin
  553. GetDir(0,Result);
  554. end;
  555. { ---------------------------------------------------------------------
  556. Other functions, OS independent.
  557. ---------------------------------------------------------------------}
  558. Var
  559. GUIDCalledRandomize : Boolean = False;
  560. Procedure GetRandomBytes(Var Buf; NBytes : Integer);
  561. Var
  562. I : Integer;
  563. P : PByte;
  564. begin
  565. P:=@Buf;
  566. If Not GUIDCalledRandomize then
  567. begin
  568. Randomize;
  569. GUIDCalledRandomize:=True;
  570. end;
  571. For I:=0 to NBytes-1 do
  572. P[i]:=Random(256);
  573. end;
  574. {$IFDEF HASCREATEGUID}
  575. Function SysCreateGUID(out GUID : TGUID) : Integer; forward;
  576. {$ENDIF}
  577. Function CreateGUID(out GUID : TGUID) : Integer;
  578. begin
  579. If Assigned(OnCreateGUID) then
  580. Result:=OnCreateGUID(GUID)
  581. else
  582. begin
  583. {$IFDEF HASCREATEGUID}
  584. Result:=SysCreateGUID(GUID);
  585. {$ELSE}
  586. GetRandomBytes(GUID,SizeOf(Guid));
  587. guid.clock_seq_hi_and_reserved:=(guid.clock_seq_hi_and_reserved and $3F) + 64;
  588. guid.time_hi_and_version :=(guid.time_hi_and_version and $0FFF)+ $4000;
  589. Result:=0;
  590. {$ENDIF}
  591. end;
  592. end;
  593. function SafeLoadLibrary(const FileName: AnsiString; ErrorMode: DWord = {$ifdef windows}SEM_NOOPENFILEERRORBOX{$else windows}0{$endif windows}): HMODULE;
  594. {$if defined(win64) or defined(win32)}
  595. var
  596. mode : DWord;
  597. begin
  598. mode:=SetErrorMode(ErrorMode);
  599. try
  600. Result:=System.SafeLoadLibrary(FileName);
  601. finally
  602. SetErrorMode(mode);
  603. end;
  604. end;
  605. {$else}
  606. begin
  607. {$ifdef FPC_HAS_FEATURE_DYNLIBS}
  608. Result:=System.SafeLoadLibrary(FileName);
  609. {$else}
  610. Result:=HModule(nil);
  611. {$endif not FPC_HAS_FEATURE_DYNLIBS}
  612. end;
  613. {$endif}
  614. {$if defined(win32) or defined(win64) or defined(wince)}
  615. function GetModuleName(Module: HMODULE): string;
  616. var
  617. ResultLength, BufferLength: DWORD;
  618. Buffer: UnicodeString;
  619. begin
  620. BufferLength := MAX_PATH div 2;
  621. repeat
  622. Inc(BufferLength, BufferLength);
  623. SetLength(Buffer, BufferLength);
  624. ResultLength := GetModuleFileNameW(Module, Pointer(Buffer), BufferLength);
  625. if ResultLength = 0 then
  626. Exit('');
  627. until ResultLength < BufferLength;
  628. SetLength(Buffer, ResultLength);
  629. Result := Buffer;
  630. end;
  631. {$elseif defined(win16)}
  632. function GetModuleName(Module: HMODULE): string;
  633. var
  634. ResultLength, BufferLength: DWORD;
  635. Buffer: RawByteString;
  636. begin
  637. BufferLength := MAX_PATH div 2;
  638. repeat
  639. Inc(BufferLength, BufferLength);
  640. SetLength(Buffer, BufferLength);
  641. ResultLength := GetModuleFileName(Module, FarAddr(Buffer[1]), BufferLength);
  642. if ResultLength = 0 then
  643. Exit('');
  644. until ResultLength < BufferLength;
  645. SetLength(Buffer, ResultLength);
  646. Result := Buffer;
  647. end;
  648. {$else}
  649. function GetModuleName(Module: HMODULE): string;
  650. begin
  651. Result:='';
  652. end;
  653. {$endif}
  654. { Beep support }
  655. procedure Beep;
  656. begin
  657. If Assigned(OnBeep) then
  658. OnBeep;
  659. end;
  660. // OSes that only provide 1 byte versions can enable the following define
  661. {$ifdef executeprocuni}
  662. function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
  663. begin
  664. result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ToSingleByteFileSystemEncodedFileName(ComLine));
  665. end;
  666. function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
  667. var
  668. ComLineA : array of RawByteString;
  669. I : Integer;
  670. begin
  671. SetLength(ComLineA,high(comline)-low(comline)+1);
  672. For I:=0 to length(ComLineA)-1 Do
  673. ComLineA[i]:=ToSingleByteFileSystemEncodedFileName(ComLine[I]);
  674. result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ComLineA);
  675. end;
  676. {$endif}
  677. // generic ifthen..
  678. {$IFNDEF VER3_0}
  679. generic function IfThen<T>(val:boolean;const iftrue:T; const iffalse:T) :T; inline; overload;
  680. begin
  681. if val then
  682. Result := ifTrue
  683. else
  684. Result:=ifFalse;
  685. end;
  686. {$ENDIF}