sysutils.inc 20 KB

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