sysutils.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2010 by Sven Barth
  4. member of the Free Pascal development team
  5. Sysutils unit for NativeNT
  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. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH OUT}
  16. { force ansistrings }
  17. {$H+}
  18. uses
  19. ndk;
  20. {$DEFINE HAS_SLEEP}
  21. {$DEFINE HAS_CREATEGUID}
  22. { Include platform independent interface part }
  23. {$i sysutilh.inc}
  24. implementation
  25. uses
  26. sysconst, ndkutils;
  27. {$DEFINE FPC_NOGENERICANSIROUTINES}
  28. { Include platform independent implementation part }
  29. {$i sysutils.inc}
  30. {****************************************************************************
  31. File Functions
  32. ****************************************************************************}
  33. function FileOpen(const FileName : string; Mode : Integer) : THandle;
  34. const
  35. AccessMode: array[0..2] of ACCESS_MASK = (
  36. GENERIC_READ,
  37. GENERIC_WRITE,
  38. GENERIC_READ or GENERIC_WRITE);
  39. ShareMode: array[0..4] of ULONG = (
  40. 0,
  41. 0,
  42. FILE_SHARE_READ,
  43. FILE_SHARE_WRITE,
  44. FILE_SHARE_READ or FILE_SHARE_WRITE);
  45. var
  46. ntstr: UNICODE_STRING;
  47. objattr: OBJECT_ATTRIBUTES;
  48. iostatus: IO_STATUS_BLOCK;
  49. begin
  50. AnsiStrToNtStr(FileName, ntstr);
  51. InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
  52. NtCreateFile(@Result, AccessMode[Mode and 3] or NT_SYNCHRONIZE, @objattr,
  53. @iostatus, Nil, FILE_ATTRIBUTE_NORMAL, ShareMode[(Mode and $F0) shr 4],
  54. FILE_OPEN, FILE_NON_DIRECTORY_FILE or FILE_SYNCHRONOUS_IO_NONALERT, Nil, 0);
  55. FreeNtStr(ntstr);
  56. end;
  57. function FileCreate(const FileName : String) : THandle;
  58. var
  59. ntstr: UNICODE_STRING;
  60. objattr: OBJECT_ATTRIBUTES;
  61. iostatus: IO_STATUS_BLOCK;
  62. res: NTSTATUS;
  63. begin
  64. AnsiStrToNTStr(FileName, ntstr);
  65. InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
  66. NtCreateFile(@Result, GENERIC_READ or GENERIC_WRITE or NT_SYNCHRONIZE,
  67. @objattr, @iostatus, Nil, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF,
  68. FILE_NON_DIRECTORY_FILE or FILE_SYNCHRONOUS_IO_NONALERT, Nil, 0);
  69. FreeNtStr(ntstr);
  70. end;
  71. function FileCreate(const FileName : String; Rights: longint) : THandle;
  72. begin
  73. FileCreate := FileCreate(FileName);
  74. end;
  75. function FileCreate(const FileName : String; ShareMode : longint; Rights: longint) : THandle;
  76. begin
  77. FileCreate := FileCreate(FileName);
  78. end;
  79. function FileRead(Handle : THandle; out Buffer; Count : longint) : Longint;
  80. var
  81. iostatus: IO_STATUS_BLOCK;
  82. res: NTSTATUS;
  83. begin
  84. res := NtReadFile(Handle, 0, Nil, Nil, @iostatus, @Buffer, Count, Nil, Nil);
  85. if res = STATUS_PENDING then begin
  86. res := NtWaitForSingleObject(Handle, False, Nil);
  87. if NT_SUCCESS(res) then
  88. res := iostatus.union1.Status;
  89. end;
  90. if NT_SUCCESS(res) then
  91. Result := LongInt(iostatus.Information)
  92. else
  93. Result := -1;
  94. end;
  95. function FileWrite(Handle : THandle; const Buffer; Count : Longint) : Longint;
  96. var
  97. iostatus: IO_STATUS_BLOCK;
  98. res: NTSTATUS;
  99. begin
  100. res := NtWriteFile(Handle, 0, Nil, Nil, @iostatus, @Buffer, Count, Nil,
  101. Nil);
  102. if res = STATUS_PENDING then begin
  103. res := NtWaitForSingleObject(Handle, False, Nil);
  104. if NT_SUCCESS(res) then
  105. res := iostatus.union1.Status;
  106. end;
  107. if NT_SUCCESS(res) then
  108. Result := LongInt(iostatus.Information)
  109. else
  110. Result := -1;
  111. end;
  112. function FileSeek(Handle : THandle;FOffset,Origin : Longint) : Longint;
  113. begin
  114. Result := longint(FileSeek(Handle, Int64(FOffset), Origin));
  115. end;
  116. function FileSeek(Handle : THandle; FOffset: Int64; Origin: Longint) : Int64;
  117. const
  118. ErrorCode = $FFFFFFFFFFFFFFFF;
  119. var
  120. position: FILE_POSITION_INFORMATION;
  121. standard: FILE_STANDARD_INFORMATION;
  122. iostatus: IO_STATUS_BLOCK;
  123. res: NTSTATUS;
  124. begin
  125. { determine the new position }
  126. case Origin of
  127. fsFromBeginning:
  128. position.CurrentByteOffset.QuadPart := FOffset;
  129. fsFromCurrent: begin
  130. res := NtQueryInformationFile(Handle, @iostatus, @position,
  131. SizeOf(FILE_POSITION_INFORMATION), FilePositionInformation);
  132. if res < 0 then begin
  133. Result := ErrorCode;
  134. Exit;
  135. end;
  136. position.CurrentByteOffset.QuadPart :=
  137. position.CurrentByteOffset.QuadPart + FOffset;
  138. end;
  139. fsFromEnd: begin
  140. res := NtQueryInformationFile(Handle, @iostatus, @standard,
  141. SizeOf(FILE_STANDARD_INFORMATION), FileStandardInformation);
  142. if res < 0 then begin
  143. Result := ErrorCode;
  144. Exit;
  145. end;
  146. position.CurrentByteOffset.QuadPart := standard.EndOfFile.QuadPart +
  147. FOffset;
  148. end;
  149. else begin
  150. Result := ErrorCode;
  151. Exit;
  152. end;
  153. end;
  154. { set the new position }
  155. res := NtSetInformationFile(Handle, @iostatus, @position,
  156. SizeOf(FILE_POSITION_INFORMATION), FilePositionInformation);
  157. if res < 0 then
  158. Result := ErrorCode
  159. else
  160. Result := position.CurrentByteOffset.QuadPart;
  161. end;
  162. procedure FileClose(Handle : THandle);
  163. begin
  164. NtClose(Handle);
  165. end;
  166. function FileTruncate(Handle : THandle;Size: Int64) : boolean;
  167. var
  168. endoffileinfo: FILE_END_OF_FILE_INFORMATION;
  169. allocinfo: FILE_ALLOCATION_INFORMATION;
  170. iostatus: IO_STATUS_BLOCK;
  171. res: NTSTATUS;
  172. begin
  173. // based on ReactOS' SetEndOfFile
  174. endoffileinfo.EndOfFile.QuadPart := Size;
  175. res := NtSetInformationFile(Handle, @iostatus, @endoffileinfo,
  176. SizeOf(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation);
  177. if NT_SUCCESS(res) then begin
  178. allocinfo.AllocationSize.QuadPart := Size;
  179. res := NtSetInformationFile(handle, @iostatus, @allocinfo,
  180. SizeOf(FILE_ALLOCATION_INFORMATION), FileAllocationInformation);
  181. Result := NT_SUCCESS(res);
  182. end else
  183. Result := False;
  184. end;
  185. function NTToDosTime(const NtTime: LARGE_INTEGER): LongInt;
  186. var
  187. userdata: PKUSER_SHARED_DATA;
  188. local, bias: LARGE_INTEGER;
  189. fields: TIME_FIELDS;
  190. zs: LongInt;
  191. begin
  192. userdata := SharedUserData;
  193. repeat
  194. bias.u.HighPart := userdata^.TimeZoneBias.High1Time;
  195. bias.u.LowPart := userdata^.TimeZoneBias.LowPart;
  196. until bias.u.HighPart = userdata^.TimeZoneBias.High2Time;
  197. local.QuadPart := NtTime.QuadPart - bias.QuadPart;
  198. RtlTimeToTimeFields(@local, @fields);
  199. { from objpas\datutil.inc\DateTimeToDosDateTime }
  200. Result := - 1980;
  201. Result := Result + fields.Year and 127;
  202. Result := Result shl 4;
  203. Result := Result + fields.Month;
  204. Result := Result shl 5;
  205. Result := Result + fields.Day;
  206. Result := Result shl 16;
  207. zs := fields.Hour;
  208. zs := zs shl 6;
  209. zs := zs + fields.Minute;
  210. zs := zs shl 5;
  211. zs := zs + fields.Second div 2;
  212. Result := Result + (zs and $ffff);
  213. end;
  214. function DosToNtTime(aDTime: LongInt; var aNtTime: LARGE_INTEGER): Boolean;
  215. var
  216. fields: TIME_FIELDS;
  217. local, bias: LARGE_INTEGER;
  218. userdata: PKUSER_SHARED_DATA;
  219. begin
  220. { from objpas\datutil.inc\DosDateTimeToDateTime }
  221. fields.Second := (aDTime and 31) * 2;
  222. aDTime := aDTime shr 5;
  223. fields.Minute := aDTime and 63;
  224. aDTime := aDTime shr 6;
  225. fields.Hour := aDTime and 31;
  226. aDTime := aDTime shr 5;
  227. fields.Day := aDTime and 31;
  228. aDTime := aDTime shr 5;
  229. fields.Month := aDTime and 15;
  230. aDTime := aDTime shr 4;
  231. fields.Year := aDTime + 1980;
  232. Result := RtlTimeFieldsToTime(@fields, @local);
  233. if not Result then
  234. Exit;
  235. userdata := SharedUserData;
  236. repeat
  237. bias.u.HighPart := userdata^.TimeZoneBias.High1Time;
  238. bias.u.LowPart := userdata^.TimeZoneBias.LowPart;
  239. until bias.u.HighPart = userdata^.TimeZoneBias.High2Time;
  240. aNtTime.QuadPart := local.QuadPart + bias.QuadPart;
  241. end;
  242. function FileAge(const FileName: String): Longint;
  243. begin
  244. Result := -1;
  245. end;
  246. function FileExists(const FileName: String): Boolean;
  247. var
  248. ntstr: UNICODE_STRING;
  249. objattr: OBJECT_ATTRIBUTES;
  250. res: NTSTATUS;
  251. iostatus: IO_STATUS_BLOCK;
  252. h: THandle;
  253. begin
  254. AnsiStrToNtStr(FileName, ntstr);
  255. InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
  256. res := NtOpenFile(@h, 0, @objattr, @iostatus,
  257. FILE_SHARE_READ or FILE_SHARE_WRITE,
  258. FILE_NON_DIRECTORY_FILE or FILE_SYNCHRONOUS_IO_NONALERT);
  259. Result := NT_SUCCESS(res);
  260. if Result then
  261. NtClose(h);
  262. FreeNtStr(ntstr);
  263. end;
  264. function DirectoryExists(const Directory : String) : Boolean;
  265. var
  266. ntstr: UNICODE_STRING;
  267. objattr: OBJECT_ATTRIBUTES;
  268. res: NTSTATUS;
  269. iostatus: IO_STATUS_BLOCK;
  270. h: THandle;
  271. begin
  272. AnsiStrToNtStr(Directory, ntstr);
  273. InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
  274. { first test wether this is a object directory }
  275. res := NtOpenDirectoryObject(@h, 0, @objattr);
  276. if NT_SUCCESS(res) then
  277. Result := True
  278. else begin
  279. if res = STATUS_OBJECT_TYPE_MISMATCH then begin
  280. { this is a file object! }
  281. res := NtOpenFile(@h, 0, @objattr, @iostatus,
  282. FILE_SHARE_READ or FILE_SHARE_WRITE,
  283. FILE_DIRECTORY_FILE or FILE_SYNCHRONOUS_IO_NONALERT);
  284. Result := NT_SUCCESS(res);
  285. end else
  286. Result := False;
  287. end;
  288. if Result then
  289. NtClose(h);
  290. FreeNtStr(ntstr);
  291. end;
  292. function FindMatch(var f: TSearchRec): Longint;
  293. begin
  294. Result := -1;
  295. end;
  296. function FindFirst(const Path: String; Attr: Longint; out Rslt: TSearchRec): Longint;
  297. begin
  298. Result := -1;
  299. end;
  300. function FindNext(var Rslt: TSearchRec): Longint;
  301. begin
  302. Result := -1;
  303. end;
  304. procedure FindClose(var F: TSearchrec);
  305. begin
  306. { empty }
  307. end;
  308. function FileGetDate(Handle: THandle): Longint;
  309. var
  310. res: NTSTATUS;
  311. basic: FILE_BASIC_INFORMATION;
  312. iostatus: IO_STATUS_BLOCK;
  313. begin
  314. res := NtQueryInformationFile(Handle, @iostatus, @basic,
  315. SizeOf(FILE_BASIC_INFORMATION), FileBasicInformation);
  316. if NT_SUCCESS(res) then
  317. Result := NtToDosTime(basic.LastWriteTime)
  318. else
  319. Result := -1;
  320. end;
  321. function FileSetDate(Handle: THandle;Age: Longint): Longint;
  322. var
  323. res: NTSTATUS;
  324. basic: FILE_BASIC_INFORMATION;
  325. iostatus: IO_STATUS_BLOCK;
  326. begin
  327. res := NtQueryInformationFile(Handle, @iostatus, @basic,
  328. SizeOf(FILE_BASIC_INFORMATION), FileBasicInformation);
  329. if NT_SUCCESS(res) then begin
  330. if not DosToNtTime(Age, basic.LastWriteTime) then begin
  331. Result := -1;
  332. Exit;
  333. end;
  334. res := NtSetInformationFile(Handle, @iostatus, @basic,
  335. SizeOf(FILE_BASIC_INFORMATION), FileBasicInformation);
  336. if NT_SUCCESS(res) then
  337. Result := 0
  338. else
  339. Result := res;
  340. end else
  341. Result := res;
  342. end;
  343. function FileGetAttr(const FileName: String): Longint;
  344. var
  345. objattr: OBJECT_ATTRIBUTES;
  346. info: FILE_NETWORK_OPEN_INFORMATION;
  347. res: NTSTATUS;
  348. ntstr: UNICODE_STRING;
  349. begin
  350. AnsiStrToNtStr(FileName, ntstr);
  351. InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
  352. res := NtQueryFullAttributesFile(@objattr, @info);
  353. if NT_SUCCESS(res) then
  354. Result := info.FileAttributes
  355. else
  356. Result := 0;
  357. FreeNtStr(ntstr);
  358. end;
  359. function FileSetAttr(const Filename: String; Attr: LongInt): Longint;
  360. var
  361. h: THandle;
  362. objattr: OBJECT_ATTRIBUTES;
  363. ntstr: UNICODE_STRING;
  364. basic: FILE_BASIC_INFORMATION;
  365. res: NTSTATUS;
  366. iostatus: IO_STATUS_BLOCK;
  367. begin
  368. AnsiStrToNtStr(Filename, ntstr);
  369. InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
  370. res := NtOpenFile(@h,
  371. NT_SYNCHRONIZE or FILE_READ_ATTRIBUTES or FILE_WRITE_ATTRIBUTES,
  372. @objattr, @iostatus,
  373. FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
  374. FILE_SYNCHRONOUS_IO_NONALERT);
  375. FreeNtStr(ntstr);
  376. if NT_SUCCESS(res) then begin
  377. res := NtQueryInformationFile(h, @iostatus, @basic,
  378. SizeOf(FILE_BASIC_INFORMATION), FileBasicInformation);
  379. if NT_SUCCESS(res) then begin
  380. basic.FileAttributes := Attr;
  381. Result := NtSetInformationFile(h, @iostatus, @basic,
  382. SizeOf(FILE_BASIC_INFORMATION), FileBasicInformation);
  383. end;
  384. NtClose(h);
  385. end else
  386. Result := res;
  387. end;
  388. function DeleteFile(const FileName: String): Boolean;
  389. var
  390. h: THandle;
  391. objattr: OBJECT_ATTRIBUTES;
  392. ntstr: UNICODE_STRING;
  393. dispinfo: FILE_DISPOSITION_INFORMATION;
  394. res: NTSTATUS;
  395. iostatus: IO_STATUS_BLOCK;
  396. begin
  397. AnsiStrToNtStr(Filename, ntstr);
  398. InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
  399. res := NtOpenFile(@h, NT_DELETE, @objattr, @iostatus,
  400. FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
  401. FILE_NON_DIRECTORY_FILE);
  402. FreeNtStr(ntstr);
  403. if NT_SUCCESS(res) then begin
  404. dispinfo.DeleteFile := True;
  405. res := NtSetInformationFile(h, @iostatus, @dispinfo,
  406. SizeOf(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);
  407. Result := NT_SUCCESS(res);
  408. NtClose(h);
  409. end else
  410. Result := False;
  411. end;
  412. function RenameFile(const OldName, NewName: String): Boolean;
  413. var
  414. h: THandle;
  415. objattr: OBJECT_ATTRIBUTES;
  416. iostatus: IO_STATUS_BLOCK;
  417. dest, src: UNICODE_STRING;
  418. renameinfo: PFILE_RENAME_INFORMATION;
  419. res: LongInt;
  420. begin
  421. { check whether the destination exists first }
  422. AnsiStrToNtStr(NewName, dest);
  423. InitializeObjectAttributes(objattr, @dest, 0, 0, Nil);
  424. res := NtCreateFile(@h, 0, @objattr, @iostatus, Nil, 0,
  425. FILE_SHARE_READ or FILE_SHARE_WRITE, FILE_OPEN,
  426. FILE_NON_DIRECTORY_FILE, Nil, 0);
  427. if NT_SUCCESS(res) then begin
  428. { destination already exists => error }
  429. NtClose(h);
  430. Result := False;
  431. end else begin
  432. AnsiStrToNtStr(OldName, src);
  433. InitializeObjectAttributes(objattr, @src, 0, 0, Nil);
  434. res := NtCreateFile(@h,
  435. GENERIC_ALL or NT_SYNCHRONIZE or FILE_READ_ATTRIBUTES,
  436. @objattr, @iostatus, Nil, 0, FILE_SHARE_READ or FILE_SHARE_WRITE,
  437. FILE_OPEN, FILE_OPEN_FOR_BACKUP_INTENT or FILE_OPEN_REMOTE_INSTANCE
  438. or FILE_NON_DIRECTORY_FILE or FILE_SYNCHRONOUS_IO_NONALERT, Nil,
  439. 0);
  440. if NT_SUCCESS(res) then begin
  441. renameinfo := GetMem(SizeOf(FILE_RENAME_INFORMATION) + dest.Length);
  442. with renameinfo^ do begin
  443. ReplaceIfExists := False;
  444. RootDirectory := 0;
  445. FileNameLength := dest.Length;
  446. Move(dest.Buffer^, renameinfo^.FileName, dest.Length);
  447. end;
  448. res := NtSetInformationFile(h, @iostatus, renameinfo,
  449. SizeOf(FILE_RENAME_INFORMATION) + dest.Length,
  450. FileRenameInformation);
  451. if not NT_SUCCESS(res) then begin
  452. { this could happen if src and destination reside on different drives,
  453. so we need to copy the file manually }
  454. {$message warning 'RenameFile: Implement file copy!'}
  455. Result := False;
  456. end else
  457. Result := True;
  458. NtClose(h);
  459. end else
  460. Result := False;
  461. FreeNtStr(src);
  462. end;
  463. FreeNtStr(dest);
  464. end;
  465. {****************************************************************************
  466. Disk Functions
  467. ****************************************************************************}
  468. function diskfree(drive: byte): int64;
  469. begin
  470. { here the mount manager needs to be queried }
  471. Result := -1;
  472. end;
  473. function disksize(drive: byte): int64;
  474. begin
  475. { here the mount manager needs to be queried }
  476. Result := -1;
  477. end;
  478. function GetCurrentDir: String;
  479. begin
  480. GetDir(0, result);
  481. end;
  482. function SetCurrentDir(const NewDir: String): Boolean;
  483. begin
  484. {$I-}
  485. ChDir(NewDir);
  486. {$I+}
  487. Result := IOResult = 0;
  488. end;
  489. function CreateDir(const NewDir: String): Boolean;
  490. begin
  491. {$I-}
  492. MkDir(NewDir);
  493. {$I+}
  494. Result := IOResult = 0;
  495. end;
  496. function RemoveDir(const Dir: String): Boolean;
  497. begin
  498. {$I-}
  499. RmDir(Dir);
  500. {$I+}
  501. Result := IOResult = 0;
  502. end;
  503. {****************************************************************************
  504. Time Functions
  505. ****************************************************************************}
  506. procedure GetLocalTime(var SystemTime: TSystemTime);
  507. var
  508. bias, syst: LARGE_INTEGER;
  509. fields: TIME_FIELDS;
  510. userdata: PKUSER_SHARED_DATA;
  511. begin
  512. // get UTC time
  513. userdata := SharedUserData;
  514. repeat
  515. syst.u.HighPart := userdata^.SystemTime.High1Time;
  516. syst.u.LowPart := userdata^.SystemTime.LowPart;
  517. until syst.u.HighPart = userdata^.SystemTime.High2Time;
  518. // adjust to local time
  519. repeat
  520. bias.u.HighPart := userdata^.TimeZoneBias.High1Time;
  521. bias.u.LowPart := userdata^.TimeZoneBias.LowPart;
  522. until bias.u.HighPart = userdata^.TimeZoneBias.High2Time;
  523. syst.QuadPart := syst.QuadPart - bias.QuadPart;
  524. RtlTimeToTimeFields(@syst, @fields);
  525. SystemTime.Year := fields.Year;
  526. SystemTime.Month := fields.Month;
  527. SystemTime.Day := fields.Day;
  528. SystemTime.Hour := fields.Hour;
  529. SystemTime.Minute := fields.Minute;
  530. SystemTime.Second := fields.Second;
  531. SystemTime.Millisecond := fields.MilliSeconds;
  532. end;
  533. {****************************************************************************
  534. Misc Functions
  535. ****************************************************************************}
  536. procedure sysbeep;
  537. begin
  538. { empty }
  539. end;
  540. procedure InitInternational;
  541. begin
  542. InitInternationalGeneric;
  543. end;
  544. {****************************************************************************
  545. Target Dependent
  546. ****************************************************************************}
  547. function SysErrorMessage(ErrorCode: Integer): String;
  548. begin
  549. Result := 'NT error code: 0x' + IntToHex(ErrorCode, 8);
  550. end;
  551. {****************************************************************************
  552. Initialization code
  553. ****************************************************************************}
  554. function wstrlen(p: PWideChar): SizeInt; external name 'FPC_PWIDECHAR_LENGTH';
  555. function GetEnvironmentVariable(const EnvVar: String): String;
  556. var
  557. s : string;
  558. i : longint;
  559. hp: pwidechar;
  560. len: sizeint;
  561. begin
  562. { TODO : test once I know how to execute processes }
  563. Result:='';
  564. hp:=PPEB(CurrentPEB)^.ProcessParameters^.Environment;
  565. while hp^<>#0 do
  566. begin
  567. len:=UnicodeToUTF8(Nil, hp, 0);
  568. SetLength(s,len);
  569. UnicodeToUTF8(PChar(s), hp, len);
  570. //s:=strpas(hp);
  571. i:=pos('=',s);
  572. if uppercase(copy(s,1,i-1))=upcase(envvar) then
  573. begin
  574. Result:=copy(s,i+1,length(s)-i);
  575. break;
  576. end;
  577. { next string entry}
  578. hp:=hp+wstrlen(hp)+1;
  579. end;
  580. end;
  581. function GetEnvironmentVariableCount: Integer;
  582. var
  583. hp : pwidechar;
  584. begin
  585. Result:=0;
  586. hp:=PPEB(CurrentPEB)^.ProcessParameters^.Environment;
  587. If (Hp<>Nil) then
  588. while hp^<>#0 do
  589. begin
  590. Inc(Result);
  591. hp:=hp+wstrlen(hp)+1;
  592. end;
  593. end;
  594. function GetEnvironmentString(Index: Integer): String;
  595. var
  596. hp : pwidechar;
  597. len: sizeint;
  598. begin
  599. Result:='';
  600. hp:=PPEB(CurrentPEB)^.ProcessParameters^.Environment;
  601. If (Hp<>Nil) then
  602. begin
  603. while (hp^<>#0) and (Index>1) do
  604. begin
  605. Dec(Index);
  606. hp:=hp+wstrlen(hp)+1;
  607. end;
  608. If (hp^<>#0) then
  609. begin
  610. len:=UnicodeToUTF8(Nil, hp, 0);
  611. SetLength(Result, len);
  612. UnicodeToUTF8(PChar(Result), hp, len);
  613. end;
  614. end;
  615. end;
  616. function ExecuteProcess(const Path: AnsiString; const ComLine: AnsiString;
  617. Flags: TExecuteFlags = []): Integer;
  618. begin
  619. { TODO : implement }
  620. Result := 0;
  621. end;
  622. function ExecuteProcess(const Path: AnsiString;
  623. const ComLine: Array of AnsiString; Flags:TExecuteFlags = []): Integer;
  624. var
  625. CommandLine: AnsiString;
  626. I: integer;
  627. begin
  628. Commandline := '';
  629. for I := 0 to High (ComLine) do
  630. if Pos (' ', ComLine [I]) <> 0 then
  631. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  632. else
  633. CommandLine := CommandLine + ' ' + Comline [I];
  634. ExecuteProcess := ExecuteProcess (Path, CommandLine,Flags);
  635. end;
  636. procedure Sleep(Milliseconds: Cardinal);
  637. const
  638. DelayFactor = 10000;
  639. var
  640. interval: LARGE_INTEGER;
  641. begin
  642. interval.QuadPart := - Milliseconds * DelayFactor;
  643. NtDelayExecution(False, @interval);
  644. end;
  645. {****************************************************************************
  646. Initialization code
  647. ****************************************************************************}
  648. initialization
  649. InitExceptions; { Initialize exceptions. OS independent }
  650. InitInternational; { Initialize internationalization settings }
  651. OnBeep := @SysBeep;
  652. finalization
  653. DoneExceptions;
  654. end.