sysutils.inc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. {%MainUnit sysutils.pp}
  2. {
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by Florian Klaempfl
  5. member of the Free Pascal development team
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. { MCBS functions }
  13. {$i sysansi.inc}
  14. {$i syscodepages.inc}
  15. {$macro on}
  16. {$define PathStr:=UnicodeString}
  17. {$define PathPChar:=PUnicodeChar}
  18. {$define SYSUTILSUNICODE}
  19. { Read filename handling functions implementation }
  20. {$i fina.inc}
  21. { Read disk function implementations }
  22. {$i disk.inc}
  23. {$undef SYSUTILSUNICODE}
  24. {$define PathStr:=RawByteString}
  25. {$define PathPChar:=PAnsiChar}
  26. { Read filename handling functions implementation }
  27. {$i fina.inc}
  28. { Read disk function implementations }
  29. {$i disk.inc}
  30. {$undef PathStr}
  31. {$undef PathPChar}
  32. { Read file utility functions implementation }
  33. {$i filutil.inc}
  34. { variant error codes }
  35. {$i varerror.inc}
  36. { Type helpers}
  37. {$i syshelp.inc}
  38. {$ifndef OS_FILEISREADONLY}
  39. Function FileIsReadOnly(const FileName: RawByteString): Boolean;
  40. begin
  41. Result := (FileGetAttr(FileName) and faReadOnly) <> 0;
  42. end;
  43. Function FileIsReadOnly(const FileName: UnicodeString): Boolean;
  44. begin
  45. Result := (FileGetAttr(FileName) and faReadOnly) <> 0;
  46. end;
  47. {$endif OS_FILEISREADONLY}
  48. {$ifndef OS_FILESETDATEBYNAME}
  49. Function FileSetDate (Const FileName : RawByteString;Age : Int64) : Longint;
  50. Var
  51. fd : THandle;
  52. begin
  53. { at least windows requires fmOpenWrite here }
  54. fd:=FileOpen(FileName,fmOpenWrite);
  55. If (Fd<>feInvalidHandle) then
  56. try
  57. Result:=FileSetDate(fd,Age);
  58. finally
  59. FileClose(fd);
  60. end
  61. else
  62. {$ifdef HAS_OSERROR}
  63. Result:=GetLastOSError;
  64. {$else}
  65. Result:=-1;
  66. {$endif}
  67. end;
  68. Function FileSetDate (Const FileName : UnicodeString;Age : Int64) : Longint;
  69. Var
  70. fd : THandle;
  71. begin
  72. { at least windows requires fmOpenWrite here }
  73. fd:=FileOpen(FileName,fmOpenWrite);
  74. If (Fd<>feInvalidHandle) then
  75. try
  76. Result:=FileSetDate(fd,Age);
  77. finally
  78. FileClose(fd);
  79. end
  80. else
  81. {$ifdef HAS_OSERROR}
  82. Result:=GetLastOSError;
  83. {$else}
  84. Result:=-1;
  85. {$endif}
  86. end;
  87. {$endif}
  88. { Read String Handling functions implementation }
  89. {$i sysstr.inc}
  90. { Read date & Time function implementations }
  91. {$ifndef FPUNONE}
  92. {$i dati.inc}
  93. {$endif}
  94. {$IFNDEF HAS_GETTICKCOUNT}
  95. function GetTickCount: LongWord;
  96. begin
  97. Result := LongWord(GetTickCount64);
  98. end;
  99. {$ENDIF}
  100. {$IFNDEF HAS_GETTICKCOUNT64}
  101. function GetTickCount64: QWord;
  102. begin
  103. {$IFDEF FPU_NONE}
  104. {$IFDEF HAS_SYSTIMERTICK}
  105. Result := SysTimerTick;
  106. {$ELSE}
  107. Result := 0;
  108. {$ENDIF}
  109. {$ELSE}
  110. Result := Trunc(Now * 24 * 60 * 60 * 1000);
  111. {$ENDIF}
  112. end;
  113. {$ENDIF}
  114. { Read PAnsiChar handling functions implementation }
  115. {$i syspch.inc}
  116. { generic internationalisation code }
  117. {$i sysint.inc}
  118. { wide string functions }
  119. {$i syswide.inc}
  120. {$ifdef FPC_HAS_UNICODESTRING}
  121. { unicode string functions }
  122. {$i sysuni.inc}
  123. {$i sysencoding.inc}
  124. {$endif FPC_HAS_UNICODESTRING}
  125. { threading stuff }
  126. {$i sysuthrd.inc}
  127. { OS utility code }
  128. {$i osutil.inc}
  129. procedure FreeAndNil(var obj);
  130. var
  131. temp: tobject;
  132. begin
  133. temp:=tobject(obj);
  134. pointer(obj):=nil;
  135. temp.free;
  136. end;
  137. procedure FreeMemAndNil(var p);
  138. var
  139. temp:Pointer;
  140. begin
  141. temp := Pointer(p);
  142. Pointer(P):=nil;
  143. FreeMem(temp);
  144. end;
  145. { Interfaces support }
  146. {$i sysuintf.inc}
  147. constructor Exception.Create(const msg : string);
  148. begin
  149. inherited create;
  150. fmessage:=msg;
  151. end;
  152. constructor Exception.CreateFmt(const msg : string; const args : array of const);
  153. begin
  154. inherited create;
  155. fmessage:=Format(msg,args);
  156. end;
  157. constructor Exception.CreateRes(ResString: PResStringRec);
  158. begin
  159. inherited create;
  160. fmessage:=ResString^;
  161. end;
  162. constructor Exception.CreateResFmt(ResString: PResStringRec; const Args: array of const);
  163. begin
  164. inherited create;
  165. fmessage:=Format(ResString^,args);
  166. end;
  167. constructor Exception.CreateHelp(const Msg: string; AHelpContext: Longint);
  168. begin
  169. inherited create;
  170. fmessage:=Msg;
  171. fhelpcontext:=AHelpContext;
  172. end;
  173. constructor Exception.CreateFmtHelp(const Msg: string; const Args: array of const;
  174. AHelpContext: Longint);
  175. begin
  176. inherited create;
  177. fmessage:=Format(Msg,args);
  178. fhelpcontext:=AHelpContext;
  179. end;
  180. constructor Exception.CreateResHelp(ResString: PResStringRec; AHelpContext: Longint);
  181. begin
  182. inherited create;
  183. fmessage:=ResString^;
  184. fhelpcontext:=AHelpContext;
  185. end;
  186. constructor Exception.CreateResFmtHelp(ResString: PResStringRec; const Args: array of const;
  187. AHelpContext: Longint);
  188. begin
  189. inherited create;
  190. fmessage:=Format(ResString^,args);
  191. fhelpcontext:=AHelpContext;
  192. end;
  193. Function Exception.ToString : RTLString;
  194. begin
  195. Result:=ClassName+': '+Message;
  196. end;
  197. procedure EHeapMemoryError.FreeInstance;
  198. begin
  199. if AllowFree then
  200. inherited FreeInstance;
  201. end;
  202. function Exception.GetBaseException : Exception;
  203. var
  204. _ExceptObjectStack : PExceptObject;
  205. begin
  206. _ExceptObjectStack:=RaiseList;
  207. While Assigned(_ExceptObjectStack) do
  208. begin
  209. result:=Exception(_ExceptObjectStack^.FObject);
  210. _ExceptObjectStack:=_ExceptObjectStack^.Next;
  211. end;
  212. end;
  213. Constructor EVariantError.CreateCode (Code : longint);
  214. begin
  215. case Code of
  216. VAR_OK:
  217. Create(SNoError);
  218. VAR_PARAMNOTFOUND:
  219. Create(SVarParamNotFound);
  220. VAR_TYPEMISMATCH:
  221. Create(SInvalidVarCast);
  222. VAR_BADVARTYPE:
  223. Create(SVarBadType);
  224. VAR_OVERFLOW:
  225. Create(SVarOverflow);
  226. VAR_BADINDEX:
  227. Create(SVarArrayBounds);
  228. VAR_ARRAYISLOCKED:
  229. Create(SVarArrayLocked);
  230. VAR_NOTIMPL:
  231. Create(SVarNotImplemented);
  232. VAR_OUTOFMEMORY:
  233. Create(SVarOutOfMemory);
  234. VAR_INVALIDARG:
  235. Create(SVarInvalid);
  236. VAR_UNEXPECTED,
  237. VAR_EXCEPTION:
  238. Create(SVarUnexpected);
  239. else
  240. CreateFmt(SUnknownErrorCode,[Code]);
  241. end;
  242. ErrCode:=Code;
  243. end;
  244. {$if defined(win32) or defined(win64) or defined (wince)}
  245. function EExternal.GetExceptionRecord: PExceptionRecord;
  246. begin
  247. result:=@FExceptionRecord;
  248. end;
  249. {$endif win32 or win64 or wince}
  250. {$push}
  251. {$S-}
  252. Procedure CatchUnhandledException (Obj : TObject; Addr: CodePointer; FrameCount: Longint; Frames: PCodePointer);[public,alias:'FPC_BREAK_UNHANDLED_EXCEPTION'];
  253. Var
  254. i : longint;
  255. hstdout : ^text;
  256. begin
  257. if WriteErrorsToStdErr then
  258. hstdout:=@stderr
  259. else
  260. hstdout:=@stdout;
  261. Writeln(hstdout^,'An unhandled exception occurred at $',HexStr(Addr),':');
  262. if Obj is exception then
  263. Writeln(hstdout^,Obj.ClassName,': ',Exception(Obj).Message)
  264. else if Obj is TObject then
  265. Writeln(hstdout^,'Exception object ',Obj.ClassName,' is not of class Exception.')
  266. else
  267. Writeln(hstdout^,'Exception object is not a valid class.');
  268. {$IFDEF HAS_OSERROR}
  269. {$IFDEF DEBUG_EXCEPTIONS_LASTOSERROR}
  270. WriteLn (HStdOut^, 'Last OS error detected in the RTL: ', GetLastOSError);
  271. {$ENDIF DEBUG_EXCEPTIONS_LASTOSERROR}
  272. {$ENDIF HAS_OSERROR}
  273. Writeln(hstdout^,BackTraceStrFunc(Addr));
  274. if (FrameCount>0) then
  275. begin
  276. for i:=0 to FrameCount-1 do
  277. Writeln(hstdout^,BackTraceStrFunc(Frames[i]));
  278. end;
  279. Writeln(hstdout^,'');
  280. end;
  281. type
  282. PExceptMapEntry=^TExceptMapEntry;
  283. TExceptMapEntry=record
  284. code: byte;
  285. cls: ExceptClass;
  286. {$IFDEF FPC_HAS_FEATURE_RESOURCES} // This is necessary for 2.4.4, which does not have reasources as a separate feature
  287. msg: PResStringRec;
  288. {$else FPC_HAS_FEATURE_RESOURCES}
  289. msg: PAnsiString;
  290. {$endif FPC_HAS_FEATURE_RESOURCES}
  291. end;
  292. const
  293. exceptmap: array[0..30] of TExceptMapEntry = (
  294. (code: 200; cls: EDivByZero; msg: @SDivByZero),
  295. (code: 201; cls: ERangeError; msg: @SRangeError),
  296. (code: 202; cls: EStackOverflow; msg: @SStackOverflow),
  297. (code: 205; cls: EOverflow; msg: @SOverflow),
  298. (code: 206; cls: EUnderflow; msg: @SUnderflow),
  299. (code: 207; cls: EInvalidOp; msg: @SInvalidOp),
  300. { Delphi distinguishes reDivByZero from reZeroDivide, but maps both to code 200. }
  301. (code: 208; cls: EZeroDivide; msg: @SZeroDivide),
  302. (code: 210; cls: EObjectCheck; msg: @SObjectCheckError),
  303. (code: 211; cls: EAbstractError; msg: @SAbstractError),
  304. (code: 212; cls: EExternalException; msg: @SExternalException),
  305. (code: 214; cls: EBusError; msg: @SBusError),
  306. (code: 215; cls: EIntOverflow; msg: @SIntOverflow),
  307. (code: 216; cls: EAccessViolation; msg: @SAccessViolation),
  308. (code: 217; cls: EControlC; msg: @SControlC),
  309. (code: 218; cls: EPrivilege; msg: @SPrivilege),
  310. (code: 219; cls: EInvalidCast; msg: @SInvalidCast),
  311. (code: 220; cls: EVariantError; msg: @SInvalidVarCast),
  312. (code: 221; cls: EVariantError; msg: @SInvalidVarOp),
  313. (code: 222; cls: EVariantError; msg: @SDispatchError),
  314. (code: 223; cls: EVariantError; msg: @SVarArrayCreate),
  315. (code: 224; cls: EVariantError; msg: @SVarNotArray),
  316. (code: 225; cls: EVariantError; msg: @SVarArrayBounds),
  317. (code: 227; cls: EAssertionFailed; msg: @SAssertionFailed),
  318. (code: 228; cls: EIntfCastError; msg: @SIntfCastError),
  319. (code: 229; cls: ESafecallException; msg: @SSafecallException),
  320. (code: 231; cls: EConvertError; msg: @SiconvError),
  321. (code: 232; cls: ENoThreadSupport; msg: @SNoThreadSupport),
  322. (code: 233; cls: ESigQuit; msg: @SSigQuit),
  323. (code: 234; cls: ENoWideStringSupport; msg: @SMissingWStringManager),
  324. (code: 235; cls: ENoDynLibsSupport; msg: @SNoDynLibsSupport),
  325. (code: 236; cls: EThreadError; msg: @SThreadError)
  326. );
  327. function FindExceptMapEntry(err: longint): PExceptMapEntry;
  328. var
  329. i: longint;
  330. begin
  331. for i:=low(exceptmap) to high(exceptmap) do
  332. if err=exceptmap[i].code then
  333. begin
  334. result:=@exceptmap[i];
  335. exit;
  336. end;
  337. result:=nil;
  338. end;
  339. Var OutOfMemory : EOutOfMemory;
  340. InValidPointer : EInvalidPointer;
  341. Procedure RunErrorToExcept (ErrNo : Longint; Address : CodePointer; Frame : Pointer);
  342. var
  343. E: Exception;
  344. HS: PResStringRec;
  345. Entry: PExceptMapEntry;
  346. begin
  347. Case Errno of
  348. 1,203 : E:=OutOfMemory;
  349. 204 : E:=InvalidPointer;
  350. else
  351. Entry:=FindExceptMapEntry(ErrNo);
  352. if Assigned(Entry) then
  353. E:=Entry^.cls.CreateRes(Entry^.msg)
  354. else
  355. begin
  356. HS:=nil;
  357. Case Errno of
  358. 2 : HS:=@SFileNotFound;
  359. 3 : HS:=@SInvalidFileName;
  360. 4 : HS:=@STooManyOpenFiles;
  361. 5 : HS:=@SAccessDenied;
  362. 6 : HS:=@SInvalidFileHandle;
  363. 15 : HS:=@SInvalidDrive;
  364. 100 : HS:=@SEndOfFile;
  365. 101 : HS:=@SDiskFull;
  366. 102 : HS:=@SFileNotAssigned;
  367. 103 : HS:=@SFileNotOpen;
  368. 104 : HS:=@SFileNotOpenForInput;
  369. 105 : HS:=@SFileNotOpenForOutput;
  370. 106 : HS:=@SInvalidInput;
  371. end;
  372. if Assigned(HS) then
  373. E:=EInOutError.CreateRes(HS)
  374. else
  375. E:=EInOutError.CreateResFmt(@SUnknownRunTimeError,[errno]);
  376. // this routine can be called from FPC_IOCHECK,
  377. // which clears inoutres and then passes its
  378. // original value to HandleErrorFrame() (which calls
  379. // us). So use errno rather than IOResult, and clear
  380. // InOutRes explicitly in case we can also be called
  381. // from a place that does not clear InOutRes explicitly
  382. EInoutError(E).ErrorCode:=errno;
  383. inoutres:=0;
  384. end;
  385. end;
  386. Raise E at Address,Frame;
  387. end;
  388. {$IFDEF HAS_OSERROR}
  389. Procedure RaiseLastOSError;overload;
  390. begin
  391. RaiseLastOSError(GetLastOSError);
  392. end;
  393. Procedure RaiseLastOSError(LastError: Integer);overload;
  394. var
  395. E : EOSError;
  396. begin
  397. If (LastError<>0) then
  398. E:=EOSError.CreateFmt(SOSError, [LastError, SysErrorMessage(LastError)])
  399. else
  400. E:=EOSError.Create(SUnkOSError);
  401. E.ErrorCode:=LastError;
  402. Raise E;
  403. end;
  404. {$else}
  405. Procedure RaiseLastOSError;overload;
  406. begin
  407. Raise Exception.Create('RaiseLastOSError not implemented on this platform.');
  408. end;
  409. Procedure RaiseLastOSError(LastError: Integer);overload;
  410. begin
  411. RaiseLastOSError;
  412. end;
  413. {$endif}
  414. procedure CheckOSError(LastError: Integer);
  415. begin
  416. if LastError <> 0 then
  417. RaiseLastOSError(LastError);
  418. end;
  419. Procedure AssertErrorHandler (Const Msg,FN : ShortString;LineNo:longint; TheAddr : pointer);
  420. Var
  421. S : String;
  422. begin
  423. If Msg='' then
  424. S:=SAssertionFailed
  425. else
  426. S:=Msg;
  427. Raise EAssertionFailed.Createfmt(SAssertError,[S,Fn,LineNo]) at get_caller_addr(theAddr), get_caller_frame(theAddr);
  428. end;
  429. {$pop} //{$S-} for Error handling functions
  430. Procedure InitExceptions;
  431. {
  432. Must install uncaught exception handler (ExceptProc)
  433. and install exceptions for system exceptions or signals.
  434. (e.g: SIGSEGV -> ESegFault or so.)
  435. }
  436. begin
  437. ExceptionClass := Exception;
  438. ExceptProc:=@CatchUnhandledException;
  439. // Create objects that may have problems when there is no memory.
  440. OutOfMemory:=EOutOfMemory.Create(SOutOfMemory);
  441. OutOfMemory.AllowFree:=false;
  442. InvalidPointer:=EInvalidPointer.Create(SInvalidPointer);
  443. InvalidPointer.AllowFree:=false;
  444. AssertErrorProc:=@AssertErrorHandler;
  445. ErrorProc:=@RunErrorToExcept;
  446. OnShowException:=Nil;
  447. end;
  448. Procedure DoneExceptions;
  449. begin
  450. OutOfMemory.AllowFree:=true;
  451. OutOfMemory.Free;
  452. InValidPointer.AllowFree:=true;
  453. InValidPointer.Free;
  454. end;
  455. { Exception handling routines }
  456. function ExceptObject: TObject;
  457. begin
  458. If RaiseList=Nil then
  459. Result:=Nil
  460. else
  461. Result:=RaiseList^.FObject;
  462. end;
  463. function ExceptAddr: CodePointer;
  464. begin
  465. If RaiseList=Nil then
  466. Result:=Nil
  467. else
  468. Result:=RaiseList^.Addr;
  469. end;
  470. function ExceptFrameCount: Longint;
  471. begin
  472. If RaiseList=Nil then
  473. Result:=0
  474. else
  475. Result:=RaiseList^.Framecount;
  476. end;
  477. function ExceptFrames: PCodePointer;
  478. begin
  479. If RaiseList=Nil then
  480. Result:=Nil
  481. else
  482. Result:=RaiseList^.Frames;
  483. end;
  484. function ExceptionErrorMessage(ExceptObject: TObject; ExceptAddr: Pointer;
  485. Buffer: PAnsiChar; Size: Integer): Integer;
  486. Var
  487. S : AnsiString;
  488. Len : Integer;
  489. begin
  490. S:=Format(SExceptionErrorMessage,[ExceptAddr,ExceptObject.ClassName]);
  491. If ExceptObject is Exception then
  492. S:=Format('%s:'#10'%s',[S,Exception(ExceptObject).Message]);
  493. Len:=Length(S);
  494. If S[Len]<>'.' then
  495. begin
  496. S:=S+'.';
  497. Inc(len);
  498. end;
  499. If Len>Size then
  500. Len:=Size;
  501. if Len > 0 then
  502. Move(S[1],Buffer^,Len);
  503. Result:=Len;
  504. end;
  505. procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);
  506. // use shortstring. On exception, the heap may be corrupt.
  507. Var
  508. Buf : ShortString;
  509. begin
  510. SetLength(Buf,ExceptionErrorMessage(ExceptObject,ExceptAddr,@Buf[1],255));
  511. If IsConsole Then
  512. writeln(Buf)
  513. else
  514. If Assigned(OnShowException) Then
  515. OnShowException (Buf);
  516. end;
  517. procedure Abort;
  518. begin
  519. Raise EAbort.Create(SAbortError) at CodePointer(Get_Caller_addr(Get_Frame));
  520. end;
  521. procedure OutOfMemoryError;
  522. begin
  523. Raise OutOfMemory;
  524. end;
  525. { ---------------------------------------------------------------------
  526. Initialization/Finalization/exit code
  527. ---------------------------------------------------------------------}
  528. Type
  529. PPRecord = ^TPRecord;
  530. TPRecord = Record
  531. Func : TTerminateProc;
  532. NextFunc : PPRecord;
  533. end;
  534. Const
  535. TPList : PPRecord = Nil;
  536. procedure AddTerminateProc(TermProc: TTerminateProc);
  537. Var
  538. TPR : PPRecord;
  539. begin
  540. New(TPR);
  541. With TPR^ do
  542. begin
  543. NextFunc:=TPList;
  544. Func:=TermProc;
  545. end;
  546. TPList:=TPR;
  547. end;
  548. function CallTerminateProcs: Boolean;
  549. Var
  550. TPR : PPRecord;
  551. begin
  552. Result:=True;
  553. TPR:=TPList;
  554. While Result and (TPR<>Nil) do
  555. begin
  556. Result:=TPR^.Func();
  557. TPR:=TPR^.NextFunc;
  558. end;
  559. end;
  560. procedure FreeTerminateProcs;
  561. var
  562. TPR1, TPR2: PPRecord;
  563. begin
  564. TPR1 := TPList;
  565. TPList := Nil;
  566. while Assigned(TPR1) do begin
  567. TPR2 := TPR1^.NextFunc;
  568. Dispose(TPR1);
  569. TPR1 := TPR2;
  570. end;
  571. end;
  572. { ---------------------------------------------------------------------
  573. Diskh functions, OS independent.
  574. ---------------------------------------------------------------------}
  575. Function GetCurrentDir: {$ifdef FPC_UNICODE_RTL}UnicodeString{$else}AnsiString{$endif};
  576. begin
  577. GetDir(0,Result);
  578. end;
  579. { ---------------------------------------------------------------------
  580. Other functions, OS independent.
  581. ---------------------------------------------------------------------}
  582. Var
  583. GUIDCalledRandomize : Boolean = False;
  584. Procedure GetRandomBytes(Var Buf; NBytes : Integer);
  585. Var
  586. I : Integer;
  587. P : PByte;
  588. begin
  589. P:=@Buf;
  590. If Not GUIDCalledRandomize then
  591. begin
  592. Randomize;
  593. GUIDCalledRandomize:=True;
  594. end;
  595. For I:=0 to NBytes-1 do
  596. P[i]:=Random(256);
  597. end;
  598. {$IFDEF HASCREATEGUID}
  599. Function SysCreateGUID(out GUID : TGUID) : Integer; forward;
  600. {$ENDIF}
  601. Function CreateGUID(out GUID : TGUID) : Integer;
  602. begin
  603. If Assigned(OnCreateGUID) then
  604. Result:=OnCreateGUID(GUID)
  605. else
  606. begin
  607. {$IFDEF HASCREATEGUID}
  608. Result:=SysCreateGUID(GUID);
  609. {$ELSE}
  610. GetRandomBytes(GUID,SizeOf(Guid));
  611. guid.clock_seq_hi_and_reserved:=(guid.clock_seq_hi_and_reserved and $3F) + 64;
  612. guid.time_hi_and_version :=(guid.time_hi_and_version and $0FFF)+ $4000;
  613. Result:=0;
  614. {$ENDIF}
  615. end;
  616. end;
  617. function SafeLoadLibrary(const FileName: AnsiString; ErrorMode: DWord = {$ifdef windows}SEM_NOOPENFILEERRORBOX{$else windows}0{$endif windows}): HMODULE;
  618. {$if defined(win64) or defined(win32)}
  619. var
  620. mode : DWord;
  621. begin
  622. mode:=SetErrorMode(ErrorMode);
  623. try
  624. Result:=System.SafeLoadLibrary(FileName);
  625. finally
  626. SetErrorMode(mode);
  627. end;
  628. end;
  629. {$else}
  630. begin
  631. {$ifdef FPC_HAS_FEATURE_DYNLIBS}
  632. Result:=System.SafeLoadLibrary(FileName);
  633. {$else}
  634. Result:=HModule(nil);
  635. {$endif not FPC_HAS_FEATURE_DYNLIBS}
  636. end;
  637. {$endif}
  638. {$if defined(win32) or defined(win64) or defined(wince)}
  639. function GetModuleName(Module: HMODULE): string;
  640. var
  641. ResultLength, BufferLength: DWORD;
  642. Buffer: UnicodeString;
  643. begin
  644. BufferLength := MAX_PATH div 2;
  645. repeat
  646. Inc(BufferLength, BufferLength);
  647. SetLength(Buffer, BufferLength);
  648. ResultLength := GetModuleFileNameW(Module, Pointer(Buffer), BufferLength);
  649. if ResultLength = 0 then
  650. Exit('');
  651. until ResultLength < BufferLength;
  652. SetLength(Buffer, ResultLength);
  653. Result := Buffer;
  654. end;
  655. {$elseif defined(win16)}
  656. function GetModuleName(Module: HMODULE): string;
  657. var
  658. ResultLength, BufferLength: DWORD;
  659. Buffer: RawByteString;
  660. begin
  661. BufferLength := MAX_PATH div 2;
  662. repeat
  663. Inc(BufferLength, BufferLength);
  664. SetLength(Buffer, BufferLength);
  665. ResultLength := GetModuleFileName(Module, FarAddr(Buffer[1]), BufferLength);
  666. if ResultLength = 0 then
  667. Exit('');
  668. until ResultLength < BufferLength;
  669. SetLength(Buffer, ResultLength);
  670. Result := Buffer;
  671. end;
  672. {$else}
  673. function GetModuleName(Module: HMODULE): string;
  674. begin
  675. Result:='';
  676. end;
  677. {$endif}
  678. { Beep support }
  679. procedure Beep;
  680. begin
  681. If Assigned(OnBeep) then
  682. OnBeep;
  683. end;
  684. // OSes that only provide 1 byte versions can enable the following define
  685. {$ifdef executeprocuni}
  686. function ExecuteProcess(Const Path: UnicodeString; Const ComLine: UnicodeString;Flags:TExecuteFlags=[]):integer;
  687. begin
  688. result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ToSingleByteFileSystemEncodedFileName(ComLine));
  689. end;
  690. function ExecuteProcess(Const Path: UnicodeString; Const ComLine: Array of UnicodeString;Flags:TExecuteFlags=[]):integer;
  691. var
  692. ComLineA : array of RawByteString;
  693. I : Integer;
  694. begin
  695. SetLength(ComLineA,high(comline)-low(comline)+1);
  696. For I:=0 to length(ComLineA)-1 Do
  697. ComLineA[i]:=ToSingleByteFileSystemEncodedFileName(ComLine[I]);
  698. result:=ExecuteProcess(ToSingleByteFileSystemEncodedFileName(Path),ComLineA);
  699. end;
  700. {$endif}
  701. // generic ifthen..
  702. {$IFNDEF VER3_0}
  703. generic function IfThen<T>(val:boolean;const iftrue:T; const iffalse:T) :T; inline; overload;
  704. begin
  705. if val then
  706. Result := ifTrue
  707. else
  708. Result:=ifFalse;
  709. end;
  710. {$ENDIF}
  711. Function ArrayOfConstToStrArray(Args: array of const) : TUTF8StringDynArray;
  712. var
  713. i: Integer;
  714. O : TObject;
  715. C : TClass;
  716. S : String;
  717. begin
  718. SetLength(Result,Length(Args));
  719. for i:=Low(Args) to High(Args) do
  720. case Args[i].VType of
  721. vtInteger: Result[i]:=IntToStr(Args[i].VInteger);
  722. vtBoolean: Result[i]:=BoolToStr(Args[i].VBoolean);
  723. vtChar: Result[i] := Args[i].VChar;
  724. {$ifndef FPUNONE}
  725. vtExtended: Result[i]:= FloatToStr(Args[i].VExtended^);
  726. {$ENDIF}
  727. vtString: Result[i] := Args[i].VString^;
  728. vtPointer: Result[i] := '0x'+HexStr(PtrInt(Args[i].VPointer),SizeOF(PtrInt));
  729. vtPChar: Result[i] := Args[i].VPChar;
  730. vtObject:
  731. begin
  732. O:=Args[i].VObject;
  733. if Assigned(O) then
  734. begin
  735. try
  736. S:=O.ClassName;
  737. except
  738. S:='<Invalid instance>';
  739. end;
  740. end
  741. else
  742. S:='';
  743. Result[I] := '<Object '+S+' 0x'+HexStr(PtrInt(O),SizeOF(PtrInt))+'>';
  744. end;
  745. vtClass:
  746. begin
  747. C:=Args[i].VClass;
  748. if Assigned(C) then
  749. begin
  750. try
  751. S:=C.ClassName;
  752. except
  753. S:='<Invalid Class>';
  754. end;
  755. end
  756. else
  757. S:='';
  758. Result[I] := '<Class '+S+' 0x'+HexStr(PtrInt(C),SizeOF(PtrInt))+'>';
  759. end;
  760. vtWideChar: Result[i] := UTF8Encode(Args[i].VWideChar);
  761. vtPWideChar: Result[i] := UTF8Encode(Args[i].VPWideChar^);
  762. vtAnsiString: Result[i] := AnsiString(Args[i].VAnsiString);
  763. vtCurrency: Result[i] := FLoatToSTr(Args[i].VCurrency^);
  764. vtVariant: Result[i] := Args[i].VVariant^;
  765. vtInterface: Result[I] := '<Interface 0x'+HexStr(PtrInt(Args[i].VInterface),SizeOF(PtrInt))+'>';
  766. vtWidestring: Result[i] := UTF8ENcode(WideString(Args[i].VWideString));
  767. vtInt64: Result[i] := IntToStr(Args[i].VInt64^);
  768. vtQWord: Result[i] := IntToStr(Args[i].VQWord^);
  769. vtUnicodeString:Result[i] := UTF8Encode(UnicodeString(Args[i].VUnicodeString));
  770. end;
  771. end;
  772. Function ArrayOfConstToStr(Args: array of const ; aSeparator : Char = ','; aQuoteBegin : Char = '"'; aQuoteEnd : Char = '"') : UTF8String;
  773. Procedure Add(s: UTF8String);
  774. begin
  775. if aQuoteBegin<>#0 then
  776. S:=aQuoteBegin+S;
  777. if aQuoteEnd<>#0 then
  778. S:=S+aQuoteEnd;
  779. if Result<>'' then
  780. Result:=Result+aSeparator;
  781. Result:=Result+S;
  782. end;
  783. Var
  784. S : UTF8String;
  785. begin
  786. Result:='';
  787. For S in ArrayOfConstToStrArray(Args) do
  788. Add(S);
  789. end;