home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vp21beta.zip / ARTLSRC.RAR / VPSYSW32.PAS < prev    next >
Pascal/Delphi Source File  |  2000-08-16  |  60KB  |  2,218 lines

  1. //█▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀█
  2. //█                                                       █
  3. //█      Virtual Pascal Runtime Library.  Version 2.1.    █
  4. //█      System interface layer Win32                     █
  5. //█      ─────────────────────────────────────────────────█
  6. //█      Copyright (C) 1995-2000 vpascal.com              █
  7. //█                                                       █
  8. //▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  9.  
  10. var
  11.   SysBufInfo: TConsoleScreenBufferInfo;
  12.   SysScrBuf: array[0..16*1024-1] of Char;
  13.  
  14. type
  15.   TSysMouQUeue = array[0..15] of TSysMouseEvent;
  16.   PSysMouQueue = ^TSysMouQueue;
  17.   TSysKeyQueue = array[0..15] of TSysKeyEvent;
  18.   PSysKeyQueue = ^tSysKeyQueue;
  19.  
  20. const
  21.   // Pointers to keyboard interface variables located either in the
  22.   // VpKbdW32 unit, or in the VpKbdW32.Dll file, if available
  23.   pSysKeyCount   : pLongint     = nil;
  24.   pSysMouCount   : pLongint     = nil;
  25.   pSysKeyQue     : pSysKeyQueue = nil;
  26.   pSysMouQue     : pSysMouQueue = nil;
  27.   pSysShiftState : pByte        = nil;
  28.  
  29.   SysConIn:    Longint = -1;
  30.   SysConOut:   Longint = -1;
  31.   tidCursor:   Longint = -1;  // Thread ID of cursor thread
  32.   semCursor:   Longint = -1;  // Event semaphore, set when cursor pos changes
  33.   CurXPos:     Longint = -1;  // Internally maintained cursor position
  34.   CurYPos:     Longint = -1;
  35.   SysPlatform: Longint = -1;  // Platform ID, from SysPlatformID
  36.  
  37. type
  38.   PStandardCell = ^TStandardCell;
  39.   TStandardCell = packed record
  40.     Ch   : Char;
  41.     Attr : Byte;
  42.   end;
  43.  
  44.   TKbdInit = procedure(var _pSysKeyCount, _pSysKeyQue, _pSysShiftState, _pSysMouCount, _pSysMouQue);
  45.   TKbdUpdateEventQueues = procedure;
  46.  
  47. const
  48.   KbdDllName     = 'VpKbdW32.Dll'; // Name of keyboard handler DLL
  49.   hKbdDll        : Longint = -1;   // Handle of keyboard DLL
  50.   name_KbdInit             = 'KbdInit';
  51.   name_KbdUpdateEventQueue = 'KbdUpdateEventQueues';
  52.  
  53.   pKbdInit : TKbdInit = nil;
  54.   pKbdUpdateEventQueues : TKbdUpdateEventQueues = nil;
  55.  
  56. function QueryProcAddr(Name: PChar; IsKernel: Boolean): Pointer;
  57. const
  58.   Names: array[Boolean] of PChar = ('user32.dll', 'kernel32.dll');
  59.   Handles: array[Boolean] of THandle = (0, 0);
  60. var
  61.   K: Boolean;
  62. begin
  63.   K := IsKernel;
  64.   if Handles[K] = 0 then
  65.     Handles[K] := LoadLibrary(Names[K]);
  66.   Result := GetProcAddress(Handles[K], Name);
  67. end;
  68.  
  69. const
  70.   AccessMode: array[0..2] of Integer = (
  71.     generic_Read, generic_Write, generic_Read or generic_Write);
  72.   ShareMode: array[0..4] of Integer = (
  73.     0, 0, file_share_Read, file_share_Write, file_share_Read or file_share_Write);
  74.  
  75. function SetResult(Success: Boolean): Longint;
  76. begin
  77.   Result := 0;
  78.   if not Success then
  79.     Result := GetLastError;
  80. end;
  81.  
  82. function SysFileStdIn: Longint;
  83. begin
  84.   Result := GetStdHandle(std_Input_Handle);
  85. end;
  86.  
  87. function SysFileStdOut: Longint;
  88. begin
  89.   Result := GetStdHandle(std_Output_Handle);
  90. end;
  91.  
  92. function SysFileStdErr: Longint;
  93. begin
  94.   Result := GetStdHandle(std_Error_Handle);
  95. end;
  96.  
  97. threadvar
  98.   SysAnsiFn: Array[0..260] of char;
  99.   SysOemFn: Array[0..260] of char;
  100.  
  101. function AnsiFn(_FileName: PChar): PChar;
  102. begin
  103.   // Convert filename to ANSI character set
  104.   OemToChar(_FileName, SysAnsiFn);
  105.   Result := SysAnsiFn;
  106. end;
  107.  
  108. function OemFn(_FileName: PChar): PChar;
  109. begin
  110.   // Convert filename to OEM character set
  111.   CharToOem(_FileName, SysOemFn);
  112.   Result := SysOemFn;
  113. end;
  114.  
  115. function SysFileOpen_Create(Open: Boolean;FileName: PChar; Mode,Attr,Action: Longint; var Handle: Longint): Longint;
  116. var
  117.   SA: TSecurityAttributes;
  118.   APIFlags: Longint;
  119. begin
  120.   if Open then
  121.     if Action and open_CreateIfNew <> 0 then
  122.       APIFlags := open_Always       // Open or create
  123.     else if Action and open_TruncateIfExists <> 0 then
  124.       APIFlags := truncate_existing // Open and truncate
  125.     else
  126.       APIFlags := open_Existing     // Open; fail if no file
  127.   else
  128.     if Action and create_TruncateIfExists <> 0 then
  129.       APIFlags := create_Always     // Create and truncate
  130.     else
  131.       APIFlags := create_New;       // Create; fail if exists
  132.  
  133.   SA.nLength := SizeOf(SA);
  134.   SA.lpSecurityDescriptor := nil;
  135.   SA.bInheritHandle := True;
  136.   Handle := CreateFile(AnsiFn(FileName), AccessMode[Mode and 3], ShareMode[(Mode and $F0) shr 4],
  137.       @SA, APIFlags, file_attribute_Normal, 0);
  138.   Result := SetResult(Handle <> invalid_Handle_Value);
  139. end;
  140.  
  141. function SysFileOpen(FileName: PChar; Mode: Longint; var Handle: Longint): Longint;
  142. var
  143.   SA: TSecurityAttributes;
  144. begin
  145.   SA.nLength := SizeOf(SA);
  146.   SA.lpSecurityDescriptor := nil;
  147.   SA.bInheritHandle := True;
  148.   Handle := CreateFile(AnsiFn(FileName), AccessMode[Mode and 3], ShareMode[(Mode and $F0) shr 4],
  149.     @SA, open_Existing, file_attribute_Normal, 0);
  150.   Result := SetResult(Handle <> invalid_Handle_Value);
  151. end;
  152.  
  153. function SysFileCreate(FileName: PChar; Mode,Attr: Longint; var Handle: Longint): Longint;
  154. var
  155.   SA: TSecurityAttributes;
  156. begin
  157.   SA.nLength := SizeOf(SA);
  158.   SA.lpSecurityDescriptor := nil;
  159.   SA.bInheritHandle := True;
  160.   Handle := CreateFile(AnsiFn(FileName), AccessMode[Mode and 3], ShareMode[(Mode and $F0) shr 4],
  161.     @SA, create_Always, file_attribute_Normal, 0);
  162.   Result := SetResult(Handle <> invalid_Handle_Value);
  163. end;
  164.  
  165. function SysFileCopy(_Old, _New: PChar; _Overwrite: Boolean): Boolean;
  166. begin
  167.   Result := CopyFile(_Old, _New, not _Overwrite);
  168. end;
  169.  
  170. function SysFileSeek(Handle,Distance,Method: Longint; var Actual: Longint): Longint;
  171. begin
  172.   Actual := SetFilePointer(Handle, Distance, nil, Method);
  173.   Result := SetResult(Actual <> $FFFFFFFF);
  174. end;
  175.  
  176. function SysFileRead(Handle: Longint; var Buffer; Count: Longint; var Actual: Longint): Longint;
  177. begin
  178.   Result := SetResult(ReadFile(Handle, Buffer, Count, DWord(Actual), nil));
  179. end;
  180.  
  181. function SysFileWrite(Handle: Longint; const Buffer; Count: Longint; var Actual: Longint): Longint;
  182. var
  183.   sbi: TConsoleScreenBufferInfo;
  184. begin
  185.   Result := SetResult(WriteFile(Handle, Buffer, Count, DWord(Actual), nil));
  186.   if (tidCursor <> -1) and (Handle = SysConOut) then
  187.     begin
  188.       // Writeln without Crt unit: Update cursor position variable
  189.       GetConsoleScreenBufferInfo(SysConOut, sbi);
  190.       CurXPos := sbi.dwCursorPosition.x;
  191.       CurYPos := sbi.dwCursorPosition.y;
  192.     end;
  193. end;
  194.  
  195. function SysFileSetSize(Handle,NewSize: Longint): Longint;
  196. var
  197.   CurPos: Longint;
  198. begin
  199.   CurPos := SetFilePointer(Handle, 0, nil, file_Current);
  200.   Result := SetResult((CurPos <> $FFFFFFFF) and
  201.     (SetFilePointer(Handle, NewSize, nil, file_Begin) <> $FFFFFFFF) and
  202.     SetEndOfFile(Handle) or
  203.     (SetFilePointer(Handle, CurPos, nil, file_Begin) <> $FFFFFFFF));
  204. end;
  205.  
  206. function SysFileClose(Handle: Longint): Longint;
  207. begin
  208.   Result := SetResult(CloseHandle(Handle));
  209. end;
  210.  
  211. function SysFileFlushBuffers(Handle: Longint): Longint;
  212. begin
  213.   Result := SetResult(FlushFileBuffers(Handle));
  214. end;
  215.  
  216. function SysFileDelete(FileName: PChar): Longint;
  217. begin
  218.   Result := SetResult(DeleteFile(AnsiFn(FileName)));
  219. end;
  220.  
  221. function SysFileMove(OldName,NewName: PChar): Longint;
  222. begin
  223.   Result := SetResult(MoveFile(OldName, NewName));
  224. end;
  225.  
  226. function SysFileIsDevice(Handle: Longint): Longint;
  227. var
  228.   HandleType: Longint;
  229. begin
  230.   HandleType := GetFileType(Handle);
  231.   case HandleType of
  232.   0,1 : Result := 0; // File;
  233.     2 : Result := 1; // Device
  234.     3 : Result := 2; // Pipe
  235.   end;
  236. end;
  237.  
  238. function SysDirGetCurrent(Drive: Longint; Path: PChar): Longint;
  239. var
  240.   DriveName: array[0..3] of Char;
  241.   Buffer: array[0..259] of Char;
  242. begin
  243.   // !! Compiler problem? Result is set by GetCurrentDirectory call!
  244.   Result := 0;
  245.   if Drive <> 0 then
  246.   begin
  247.     DriveName[0] := Chr(Drive + (Ord('A') - 1));
  248.     DriveName[1] := ':';
  249.     DriveName[2] := #0;
  250.     GetCurrentDirectory(SizeOf(Buffer), Buffer);
  251.     SetCurrentDirectory(DriveName);
  252.   end;
  253.   GetCurrentDirectory(260, Path);
  254.   StrCopy( Path, OemFn(Path) );
  255.   if Drive <> 0 then
  256.     SetCurrentDirectory(Buffer);
  257. end;
  258.  
  259. function SysDirSetCurrent(Path: PChar): Longint;
  260. begin
  261.   if Path^ = #0 then
  262.     Result := 0 // Otherwise returns rc = 161: Bad path name
  263.   else
  264.     Result := SetResult(SetCurrentDirectory(AnsiFn(Path)));
  265. end;
  266.  
  267. function SysDirCreate(Path: PChar): Longint;
  268. begin
  269.   Result := SetResult(CreateDirectory(AnsiFn(Path), nil));
  270. end;
  271.  
  272. function SysDirDelete(Path: PChar): Longint;
  273. begin
  274.   Result := SetResult(RemoveDirectory(AnsiFn(Path)));
  275. end;
  276.  
  277. function SysMemAvail: Longint;
  278. var
  279.   Status: TMemoryStatus;
  280. begin
  281.   Status.dwLength := SizeOf(TMemoryStatus);
  282.   GlobalMemoryStatus(Status);
  283.   with Status do
  284.   begin
  285.     Result := dwAvailPhys + dwAvailPageFile;
  286.     if Result > dwAvailVirtual then
  287.       Result := dwAvailVirtual;
  288.   end;
  289. end;
  290.  
  291. function SysMemAlloc(Size,Flags: Longint; var MemPtr: Pointer): Longint;
  292. begin
  293.   MemPtr := VirtualAlloc(nil, Size, Flags, page_ReadWrite);
  294.   Result := SetResult(MemPtr <> nil);
  295. end;
  296.  
  297. function SysMemFree(MemPtr: Pointer): Longint;
  298. begin
  299.   Result := SetResult(VirtualFree(MemPtr, 0, mem_Release));
  300. end;
  301.  
  302. function SysSysMsCount: Longint;
  303. begin
  304.   Result := GetTickCount;
  305. end;
  306.  
  307. procedure SysSysSelToFlat(var P: Pointer);
  308. begin
  309.   // Do nothing; n/a for Win32
  310. end;
  311.  
  312. procedure SysSysFlatToSel(var P: Pointer);
  313. begin
  314.   // Do nothing; n/a for Win32
  315. end;
  316.  
  317. function SysCtrlSelfAppType: Longint;
  318. var
  319.   F       : File;
  320.   lExeHdr : TImageDosHeader;
  321.   lPEHdr  : TImageNtHeaders;
  322.   SaveMode: Integer;
  323. begin
  324.   // Set default return value: GUI
  325.   Result := 3;
  326.  
  327.   // Attempt to read information from PE file header.  This only works
  328.   // if the file has not been compressed or otherwise manipulated.
  329.   SaveMode := FileMode;
  330.   FileMode := $40;          // Read-only, deny-none
  331.   Assign(F, ParamStr(0));
  332.   Reset(F, 1);
  333.   if IOResult = 0 then
  334.     begin
  335.       BlockRead(f, lExeHdr, SizeOf(lExeHdr));
  336.  
  337.       if (IOResult = 0) and (lExeHdr.e_Magic = image_DOS_Signature) then
  338.         begin
  339.           Seek(F, lExeHdr.e_lfanew);
  340.           BlockRead(F, lExeHdr.e_magic, SizeOf(lExeHdr.e_magic));
  341.         end
  342.       else
  343.         lExeHdr.e_lfanew := 0;
  344.  
  345.       Seek(F, lExeHdr.e_lfanew);
  346.       if (IOResult = 0) and (lExeHdr.e_magic = image_NT_Signature) then
  347.         begin
  348.           BlockRead(F, lPEHdr, SizeOf(lPEHdr));
  349.           if (IOResult = 0) and (lPEHdr.Signature = image_NT_Signature) then
  350.             if lPEHdr.OptionalHeader.SubSystem = image_Subsystem_Windows_CUI then
  351.               Result := 2; // Text mode
  352.         end;
  353.       Close(F);
  354.       InOutRes := 0;
  355.     end;
  356.   FileMode := SaveMode;
  357. end;
  358.  
  359. function SysGetThreadId: Longint;
  360. begin
  361.   Result := GetCurrentThreadId;
  362. end;
  363.  
  364. function SysCtrlKillThread(Handle: Longint): Longint;
  365. begin
  366.   Result := SetResult(TerminateThread(Handle, 0));
  367. end;
  368.  
  369. function SysCtrlSuspendThread(Handle: Longint): Longint;
  370. begin
  371.   Result := SetResult(SuspendThread(Handle) <> $FFFFFFFF);
  372. end;
  373.  
  374. function SysCtrlResumeThread(Handle: Longint): Longint;
  375. begin
  376.   Result := SetResult(ResumeThread(Handle) <> $FFFFFFFF);
  377. end;
  378.  
  379. procedure SysCtrlExitThread(ExitCode: Longint);
  380. var
  381.   P: Pointer;
  382. type
  383.   TExitThread = procedure(ExitCode: Longint) stdcall;
  384. begin
  385.   P := QueryProcAddr('ExitThread', True);
  386.   if P <> nil then
  387.     TExitThread(P)(ExitCode)
  388.   else
  389.     SysCtrlExitProcess(ExitCode);
  390. end;
  391.  
  392. procedure SysCtrlExitProcess(ExitCode: Longint);
  393. begin
  394.   ExitProcess(ExitCode);
  395. end;
  396.  
  397. function SysCtrlCreateThread(Attrs: Pointer; StackSize: Longint; Func,Param: Pointer; Flags: Longint; var Tid: Longint): Longint;
  398. begin
  399.   Result := SetResult(CreateThread(Attrs, StackSize, Func, Param, Flags, Tid) <> 0);
  400. end;
  401.  
  402. function SysCtrlGetModuleName(Handle: Longint; Buffer: PChar): Longint;
  403. begin
  404.   SetResult(GetModuleFileName(0, Buffer, 260) <> 0);
  405. end;
  406.  
  407. var
  408.   SysCritSec: TRTLCriticalSection;
  409.   InitCritSec: Boolean;
  410.  
  411. procedure SysCtrlEnterCritSec;
  412. begin
  413.   if not InitCritSec then
  414.   begin
  415.     InitializeCriticalSection(SysCritSec);
  416.     InitCritSec := True;
  417.   end;
  418.   EnterCriticalSection(SysCritSec);
  419. end;
  420.  
  421. procedure SysCtrlLeaveCritSec;
  422. begin
  423.   LeaveCriticalSection(SysCritSec);
  424. end;
  425.  
  426. function GetParamStr(P: PChar; var Param: ShortString): PChar;
  427. var
  428.   Len: Longint;
  429. begin
  430.   Result := P;
  431.   repeat
  432.     while Result^ in [#1..' '] do
  433.       Inc(Result);
  434.     if PSmallWord(Result)^ = (Ord('"') shl 8 + Ord('"')) then
  435.       Inc(Result, 2)
  436.     else
  437.       Break;
  438.   until False;
  439.   Len := 0;
  440.   while Result^ > ' ' do
  441.     if Result^ = '"' then
  442.       begin
  443.         Inc(Result);
  444.         while not (Result^ in [#0,'"']) do
  445.         begin
  446.           Inc(Len);
  447.           Param[Len] := Result^;
  448.           Inc(Result);
  449.         end;
  450.         if Result^ <> #0 then
  451.           Inc(Result);
  452.       end
  453.     else
  454.       begin
  455.         Inc(Len);
  456.         Param[Len] := Result^;
  457.         Inc(Result);
  458.       end;
  459.   Param[0] := Chr(Len);
  460. end;
  461.  
  462. function SysCmdln: PChar;
  463. begin
  464.   Result := GetCommandLine;
  465. end;
  466.  
  467. function SysCmdlnCount: Longint;
  468. var
  469.   P: PChar;
  470.   S: ShortString;
  471. begin
  472.   P := SysCmdln;
  473.   Result := -1;
  474.   repeat
  475.     P := GetParamStr(P, S);
  476.     if S = '' then
  477.       Exit;
  478.     Inc(Result);
  479.   until False;
  480. end;
  481.  
  482. procedure SysCmdlnParam(Index: Longint; var Param: ShortString);
  483. var
  484.   I: Longint;
  485.   P: PChar;
  486.   Buffer: array[0..260] of Char;
  487. begin
  488.   I := Index;
  489.   if I = 0 then
  490.     begin
  491.       SysCtrlGetModuleName(0, Buffer);
  492.       P := Buffer;
  493.       Param := '';
  494.       while (P^ <> #0) and (I < 255) do
  495.       begin
  496.         Inc(I);
  497.         Param[I] := P^;
  498.         Inc(P);
  499.       end;
  500.       SetLength(Param, I);
  501.     end
  502.   else
  503.     begin
  504.       // Skip ParamStr(0)
  505.       P := SysCmdln;// + Length(ParamStr(0));
  506.       repeat
  507.         P := GetParamStr(P, Param);
  508.         if (I = 0) or (Param = '') then
  509.           Exit;
  510.         Dec(I);
  511.       until False;
  512.     end;
  513. end;
  514.  
  515. function SysCtrlGetTlsMapMem: Pointer;
  516. var
  517.   IsNew: Boolean;
  518.   MapHandle: Longint;
  519.   SharedMemName: record
  520.     L0: Longint;
  521.     L1: Longint;
  522.     L2: Longint;
  523.     ID: array[0..11] of Char;
  524.   end;
  525.   P: Pointer;
  526. type
  527.   TOpenFileMapping = function(Acc: DWord; Inherit: Bool; Name: PChar): THandle stdcall;
  528.  
  529. begin
  530.   SharedMemName.L0 := Ord('S') + Ord('H') shl 8 + Ord('A') shl 16 + Ord('R') shl 24;
  531.   SharedMemName.L1 := Ord('E') + Ord('D') shl 8 + Ord('M') shl 16 + Ord('E') shl 24;
  532.   SharedMemName.L2 := Ord('M') + Ord('4') shl 8 + Ord('V') shl 16 + Ord('R') shl 24;
  533.   Str(GetCurrentProcessID, SharedMemName.ID);
  534.   MapHandle := 0;
  535.   IsNew := False;
  536.   P := QueryProcAddr('OpenFileMappingA', True);
  537.   if P = nil then
  538.     begin
  539.       GetMem(Result, SharedMemSize);
  540.       IsNew := True;
  541.     end
  542.   else
  543.     begin
  544.       MapHandle := TOpenFileMapping(P)(file_map_Read+file_map_Write, False, PChar(@SharedMemName));
  545.       if MapHandle = 0 then
  546.       begin
  547.         MapHandle := CreateFileMapping($FFFFFFFF, nil, page_ReadWrite, 0, SharedMemSize, PChar(@SharedMemName));
  548.         IsNew := True;
  549.       end;
  550.       Result := MapViewOfFile(MapHandle, file_map_Read+file_map_Write, 0, 0, 0);
  551.     end;
  552.   if IsNew then
  553.   begin
  554.     FillChar(Result^, SharedMemSize, $FF);
  555.     FillChar(Result^, SizeOf(TSharedMem), 0);
  556.     with PSharedMem(Result)^ do
  557.       begin
  558.         // Set up pointers to functions to use when allocating memory
  559.         TlsMemMgr := System.GetPMemoryManager;
  560.         // Set up pointer to function managing the TlsSemaphore
  561.         TlsSemMgr := @SysSysWaitSem;
  562.         // Initialise the TlsSemaphore
  563.         TlsSemaphore := 0;
  564.       end;
  565.   end;
  566. end;
  567.  
  568. function SysGetEnvironment: PChar;
  569. begin
  570.   Result := GetEnvironmentStrings;
  571. end;
  572.  
  573. function SysOsVersion: Longint;
  574. begin
  575.   Result := SmallWord(GetVersion);
  576. end;
  577.  
  578. function SysPlatformID: Longint;
  579. var
  580.   OSVersionInfo: TOSVersionInfo;
  581. begin
  582.   OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo);
  583.   GetVersionEx(OSVersionInfo);
  584.   Result := OSVersionInfo.dwPlatformId;
  585. end;
  586.  
  587. procedure SysGetDateTime(Year,Month,Day,DayOfWeek,Hour,Minute,Second,MSec: PLongint);
  588. var
  589.   DT: TSystemTime;
  590. begin
  591.   GetLocalTime(DT);
  592.   if Year <> nil then Year^ := DT.wYear;
  593.   if Month <> nil then Month^ := DT.wMonth;
  594.   if Day <> nil then Day^ := DT.wDay;
  595.   if DayOfWeek <> nil then DayOfWeek^ := DT.wDayOfWeek;
  596.   if Hour <> nil then Hour^ := DT.wHour;
  597.   if Minute <> nil then Minute^ := DT.wMinute;
  598.   if Second <> nil then Second^ := DT.wSecond;
  599.   if MSec <> nil then MSec^ := DT.wMilliseconds;
  600. end;
  601.  
  602. procedure SysSetDateTime(Year,Month,Day,Hour,Minute,Second,MSec: PLongint);
  603. var
  604.   DT: TSystemTime;
  605. begin
  606.   GetLocalTime(DT);
  607.   if Year <> nil then DT.wYear := Year^;
  608.   if Month <> nil then DT.wMonth := Month^;
  609.   if Day <> nil then DT.wDay := Day^;
  610.   if Hour <> nil then DT.wHour := Hour^;
  611.   if Minute <> nil then DT.wMinute := Minute^;
  612.   if Second <> nil then DT.wSecond := Second^;
  613.   if MSec <> nil then DT.wMilliseconds := MSec^;
  614.   SetLocalTime(DT);
  615. end;
  616.  
  617. function SysVerify(SetValue: Boolean; Value: Boolean): Boolean;
  618. begin
  619.   Result := False;
  620. end;
  621.  
  622. function SysDiskFreeLong(Drive: Byte): TQuad;
  623. var
  624.   RootPath: array[0..3] of Char;
  625.   RootPtr: PChar;
  626.   SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters: DWord;
  627. begin
  628.   RootPtr := nil;
  629.   if Drive > 0 then
  630.   begin
  631.     RootPath[0] := Char(Drive + (Ord('A') - 1));
  632.     RootPath[1] := ':';
  633.     RootPath[2] := '\';
  634.     RootPath[3] := #0;
  635.     RootPtr := RootPath;
  636.   end;
  637.   if GetDiskFreeSpace(RootPtr, SectorsPerCluster, BytesPerSector, FreeClusters, TotalClusters) then
  638.     Result := 1.0 * SectorsPerCluster * BytesPerSector * FreeClusters
  639.   else
  640.     Result := -1;
  641. end;
  642.  
  643. function SysDiskSizeLong(Drive: Byte): TQuad;
  644. var
  645.   RootPath: array[0..3] of Char;
  646.   RootPtr: PChar;
  647.   SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters: DWord;
  648. begin
  649.   RootPtr := nil;
  650.   if Drive > 0 then
  651.   begin
  652.     RootPath[0] := Char(Drive + (Ord('A') - 1));
  653.     RootPath[1] := ':';
  654.     RootPath[2] := '\';
  655.     RootPath[3] := #0;
  656.     RootPtr := RootPath;
  657.   end;
  658.   if GetDiskFreeSpace(RootPtr, SectorsPerCluster, BytesPerSector, FreeClusters, TotalClusters) then
  659.     Result := 1.0 *SectorsPerCluster * BytesPerSector * TotalClusters
  660.   else
  661.     Result := -1;
  662. end;
  663.  
  664. function SysGetFileAttr(FileName: PChar; var Attr: Longint): Longint;
  665. begin
  666.   Attr := GetFileAttributes(AnsiFn(FileName));
  667.   Result := SetResult(Attr <> -1);
  668.   if Attr = -1 then
  669.     Inc(Attr);
  670. end;
  671.  
  672. function SysSetFileAttr(FileName: PChar; Attr: Longint): Longint;
  673. begin
  674.   Result := SetResult(SetFileAttributes(AnsiFn(FileName), Attr));
  675. end;
  676.  
  677. function SysGetFileTime(Handle: Longint; var Time: Longint): Longint;
  678. var
  679.   FileTime, LocalFileTime: TFileTime;
  680. begin
  681.   Result := SetResult(GetFileTime(Handle, nil, nil, @FileTime) and
  682.     FileTimeToLocalFileTime(FileTime, LocalFileTime) and
  683.     FileTimeToDosDateTime(LocalFileTime, TDateTimeRec(Time).FDate, TDateTimeRec(Time).FTime));
  684. end;
  685.  
  686. function SysSetFileTime(Handle: Longint; Time: Longint): Longint;
  687. var
  688.   LocalFileTime, FileTime: TFileTime;
  689. begin
  690.   Result := SetResult(DosDateTimeToFileTime(TDateTimeRec(Time).FDate, TDateTimeRec(Time).FTime, LocalFileTime) and
  691.     LocalFileTimeToFileTime(LocalFileTime, FileTime) and
  692.     SetFileTime(Handle, nil, nil, @FileTime));
  693. end;
  694.  
  695. function DoFindFile(var F: TOSSearchRec; IsPChar: Boolean): Longint;
  696. var
  697.   LocalFileTime: TFileTime;
  698.   ExclAttr: Longint;
  699.   InclAttr: Longint;
  700. begin
  701.   // Extract Include/Exclude attributes from F.ExcludeAttr field
  702.   ExclAttr := not F.ExcludeAttr and (file_Attribute_Hidden or file_Attribute_System or $8 or file_Attribute_Directory or file_Attribute_Archive);
  703.   InclAttr := (F.ExcludeAttr and $FF00) shr 8;
  704.   // Make sure attributes are not both excluded and included
  705.   ExclAttr := ExclAttr and not InclAttr;
  706.   with F do
  707.   begin
  708.     // Reject entries where
  709.     // - Attributes that are excluded are present.
  710.     // - Attributes that must be present are not all there
  711.     while (FindData.dwFileAttributes and ExclAttr <> 0) or
  712.       (FindData.dwFileAttributes and InclAttr <> InclAttr) do
  713.       if not FindNextFile(Handle, FindData) then
  714.       begin
  715.         Result := GetLastError;
  716.         Exit;
  717.       end;
  718.     FileTimeToLocalFileTime(FindData.ftLastWriteTime, LocalFileTime);
  719.     FileTimeToDosDateTime(LocalFileTime, TDateTimeRec(Time).FDate, TDateTimeRec(Time).FTime);
  720.     Size := FindData.nFileSizeLow;
  721.     Attr := FindData.dwFileAttributes;
  722.     // Convert filename to OEM character set
  723.     CharToOem(FindData.cFileName, FindData.cFileName);
  724.     if IsPChar then
  725.       StrCopy(PChar(@Name), FindData.cFileName)
  726.     else
  727.       Name := StrPas(FindData.cFileName);
  728.   end;
  729.   Result := 0;
  730. end;
  731.  
  732. function SysFindFirst(Path: PChar; Attr: Longint; var F: TOSSearchRec; IsPChar: Boolean): Longint;
  733. begin
  734.   F.ExcludeAttr := Attr;
  735.   F.Handle := FindFirstFile(Path, F.FindData);
  736.   if F.Handle <> invalid_Handle_Value then
  737.     begin
  738.       Result := DoFindFile(F, IsPChar);
  739.       if Result <> 0 then
  740.         begin
  741.           FindClose(F.Handle);
  742.           F.Handle := invalid_Handle_Value;
  743.         end;
  744.     end
  745.   else
  746.     Result := GetLastError;
  747. end;
  748.  
  749. function SysFindNext(var F: TOSSearchRec; IsPChar: Boolean): Longint;
  750. begin
  751.   if FindNextFile(F.Handle, F.FindData) then
  752.     Result := DoFindFile(F, IsPChar)
  753.   else
  754.     Result := GetLastError;
  755. end;
  756.  
  757. function SysFindClose(var F: TOSSearchRec): Longint;
  758. begin
  759.   if F.Handle = invalid_Handle_Value then
  760.     Result := 0
  761.   else
  762.     Result := SetResult(Windows.FindClose(F.Handle));
  763.   F.Handle := invalid_Handle_Value;
  764. end;
  765.  
  766. // Check if file exists; if it does, update FileName parameter
  767. // to include correct case of existing file
  768. function SysFileAsOS(FileName: PChar): Boolean;
  769. var
  770.   Handle: THandle;
  771.   FindData: TWin32FindData;
  772.   LocalFileTime: TFileTime;
  773.   P: PChar;
  774. begin
  775.   Handle := FindFirstFile(AnsiFn(FileName), FindData);
  776.   if Handle <> invalid_Handle_Value then
  777.     begin
  778.       if FindData.cFileName[0] <> #0 then
  779.         begin
  780.           // Replace filename part with data returned by Windows
  781.           P := StrRScan(FileName, '\');
  782.           if P = nil then
  783.             P := FileName
  784.           else
  785.             inc(P); // Point to first character of file name
  786.           strcopy(P, FindData.cFileName);
  787.         end;
  788.       FindClose(Handle);
  789.       Result := True;
  790.     end
  791.   else
  792.     Result := False;
  793. end;
  794.  
  795. function SysFileSearch(Dest,Name,List: PChar): PChar;
  796. var
  797.   I, P, L: Integer;
  798.   Buffer: array[0..259] of Char;
  799. begin
  800.   Result := Dest;
  801.   StrCopy(Buffer, Name);
  802.   P := 0;
  803.   L := StrLen(List);
  804.   while True do
  805.   begin
  806.     if SysFileAsOS(Buffer) then
  807.     begin
  808.       SysFileExpand(Dest, Buffer);
  809.       Exit;
  810.     end;
  811.     while (P < L) and (List[P] = ';') do
  812.       Inc(P);
  813.     if P >= L then
  814.       Break;
  815.     I := P;
  816.     while (P < L) and (List[P] <> ';') do
  817.       Inc(P);
  818.     StrLCopy(Buffer, List + I, P - I);
  819.     if not (List[P-1] in [':', '\']) then
  820.       StrLCat(Buffer, '\', 259);
  821.     StrLCat(Buffer, Name, 259);
  822.   end;
  823.   Dest^ := #0;
  824. end;
  825.  
  826. function SysFileExpand(Dest,Name: PChar): PChar;
  827. var
  828.   L: Longint;
  829.   NameOnly: PChar;
  830. begin
  831.   if strlen(Name) = 0 then
  832.     SysDirGetCurrent(0, Dest)
  833.   else
  834.     if GetFullPathName(Name, 260, Dest, NameOnly) = 0 then
  835.       StrCopy(Dest, Name) // API failed; copy name to dest
  836.     else
  837.       if (StrComp(Name, '.') <> 0) and (StrComp(Name, '..') <> 0) then
  838.         begin
  839.           L := StrLen(Name);
  840.           if (L > 0) and (Name[L-1] = '.') then
  841.           begin
  842.             L := StrLen(Dest);
  843.             if (L > 0) and (Dest[L-1] <> '.') then
  844.             begin
  845.               Dest[L] := '.';
  846.               Dest[L+1] := #0;
  847.             end;
  848.           end;
  849.         end;
  850.   Result := Dest;
  851. end;
  852.  
  853. threadvar
  854.   ProcessInfo: TProcessInformation;
  855.   LastAsync: Boolean;
  856.  
  857. function SysExecute(Path,CmdLine,Env: PChar; Async: Boolean; PID: PLongint; StdIn,StdOut,StdErr: Longint): Longint;
  858. var
  859.   P: PChar;
  860.   Flags: Longint;
  861.   StartupInfo: TStartupInfo;
  862.   CmdLineBuf: array [0..8191] of Char;
  863. begin
  864.   P := CmdLineBuf;
  865.   P^ := '"';                   // Quotes to support spaces
  866.   inc(P);
  867.   P := StrECopy(P, Path);      // 'Path'#0
  868.   P^ := '"';
  869.   inc(P);
  870.   P^ := ' ';
  871.   StrCopy(P+1, CmdLine);                // 'Path CommandLine'#0
  872.   FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  873.   with StartupInfo do
  874.   begin
  875.     cb := SizeOf(TStartupInfo);
  876.     dwFlags := startf_UseShowWindow;
  877.     wShowWindow := sw_ShowNormal;
  878.     if StdIn = -1 then
  879.       hStdInput := SysFileStdIn
  880.     else
  881.       hStdInput := StdIn;
  882.     if StdOut = -1 then
  883.       hStdOutput := SysFileStdOut
  884.     else
  885.       hStdOutput := StdOut;
  886.     if StdErr = -1 then
  887.       hStdError := SysFileStdErr
  888.     else
  889.       hStdError := StdErr;
  890.     if (StdIn <> - 1) or (StdOut <> -1) or (StdErr <> -1) then
  891.       Inc(dwFlags, startf_UseStdHandles);
  892.   end;
  893.   Flags := normal_Priority_Class;
  894.   LastAsync := Async;
  895.   Result := SetResult(CreateProcess(Path, CmdLineBuf, nil, nil, True, Flags, Env, nil, StartupInfo, ProcessInfo));
  896.   if Result = 0 then
  897.     if Async then
  898.       begin
  899.         if PID <> nil then
  900.           PID^ := ProcessInfo.hProcess;
  901.       end
  902.     else
  903.       WaitForSingleObject(ProcessInfo.hProcess, Infinite);
  904. end;
  905.  
  906. function SysExitCode: Longint;
  907. begin
  908.   if LastAsync then
  909.     WaitForSingleObject(ProcessInfo.hProcess, Infinite);
  910.   GetExitCodeProcess(ProcessInfo.hProcess, Result);
  911. end;
  912.  
  913. procedure SysGetCaseMap(TblLen: Longint; Tbl: PChar );
  914. begin
  915.   CharUpperBuff(Tbl, TblLen);
  916. end;
  917.  
  918. procedure SysGetWeightTable(TblLen: Longint; WeightTable: PChar);
  919. var
  920.   I: Longint;
  921.  
  922. begin
  923.   // !!! Must use Win32 function
  924.   for I := 0 to pred(TblLen) do
  925.     begin
  926.       WeightTable^ := Chr(i);
  927.       inc(WeightTable);
  928.     end;
  929. end;
  930.  
  931. function SysGetCodePage: Longint;
  932. var
  933.   P: Pointer;
  934. type
  935.   TGetKBCodePage = function: Longint;
  936. begin
  937.   P := QueryProcAddr('GetKBCodePage', False);
  938.   if P = nil then
  939.     Result := 0
  940.   else
  941.     Result := TGetKBCodePage(P);
  942. end;
  943.  
  944. function SysCompareStrings(s1, s2: PChar; l1, l2: Longint; IgnoreCase: Boolean): Longint;
  945. begin
  946.   if IgnoreCase then
  947.     Result := CompareString(Locale_User_Default, norm_ignorecase,S1, l1, s2, l2)-2
  948.   else
  949.     Result := CompareString(Locale_User_Default, 0, S1, l1, s2, l2)-2;
  950. end;
  951.  
  952. procedure SysChangeCase(Source, Dest: PChar; Len: Longint; NewCase: TCharCase);
  953. var
  954.   I: Longint;
  955. begin
  956.   if NewCase in [ccLower, ccUpper] then
  957.     begin
  958.       i := 0;
  959.       while i < Len do
  960.         begin
  961.           if NewCase = ccLower then
  962.             if Source^ in ['A'..'Z'] then
  963.               Dest^ := chr(ord(Source^)+32)
  964.             else
  965.               Dest^ := Source^
  966.           else
  967.             if Source^ in ['a'..'z'] then
  968.               Dest^ := chr(ord(Source^)-32)
  969.             else
  970.               Dest^ := Source^;
  971.           inc(i);
  972.           inc(Source);
  973.           inc(Dest);
  974.         end;
  975.     end
  976.   else
  977.     begin
  978.       // AnsiUpper and AnsiLower
  979.       StrLCopy(Dest, Source, Len);
  980.       if NewCase = ccAnsiLower then
  981.         CharLowerBuff(Dest, Len)
  982.       else
  983.         CharUpperBuff(Dest, Len);
  984.     end;
  985. end;
  986.  
  987. function SysLowerCase(s: PChar): PChar;
  988. begin
  989.   Result := CharLower(s);
  990. end;
  991.  
  992. function SysUpperCase(s: PChar): PChar;
  993. begin
  994.   Result := CharUpper(s);
  995. end;
  996.  
  997. var
  998.   PrevXcptProc: Pointer;
  999.  
  1000. function SignalHandler(Report:       PExceptionRecord;
  1001.                        Registration: Pointer;
  1002.                        Context:      PContext;
  1003.                        P:            Pointer): Longint; stdcall;
  1004. begin
  1005.   if (Report^.ExceptionCode = status_Control_C_Exit) and Assigned(CtrlBreakHandler) and CtrlBreakHandler then
  1006.     Result := 1
  1007.   else
  1008.     Result := 0;
  1009.   XcptProc := PrevXcptProc;
  1010. end;
  1011.  
  1012. function CtrlHandler(CtrlType: DWord): Bool; stdcall;
  1013. begin
  1014.   if Assigned(CtrlBreakHandler) and CtrlBreakHandler then
  1015.     Result := True
  1016.   else
  1017.     Result := False;
  1018. end;
  1019.  
  1020. procedure SysCtrlSetCBreakHandler;
  1021. begin
  1022.   PrevXcptProc := XcptProc;
  1023.   XcptProc := @SignalHandler;
  1024.   SetConsoleCtrlHandler(@CtrlHandler, True);
  1025. end;
  1026.  
  1027. function SysFileIncHandleCount(Count: Longint): Longint;
  1028. begin
  1029.   // Return 0, indicating success.  In Win95/NT, the number of file handles
  1030.   // is limited by available physical memory only.
  1031.   Result := 0;
  1032. end;
  1033.  
  1034. procedure DoSetCursorPosition;
  1035. var
  1036.   CurPos: TCoord;
  1037. begin
  1038.   CurPos.x := CurXPos;
  1039.   CurPos.y := CurYPos;
  1040.   SetConsoleCursorPosition(SysConOut, CurPos);
  1041. end;
  1042.  
  1043. function CursorThreadFunc(P: Pointer): Longint;
  1044. var
  1045.   LastX, LastY: Longint;
  1046. begin
  1047.   LastX := -1;
  1048.   LastY := -1;
  1049.   repeat
  1050.     SemWaitEvent(semCursor, 300);
  1051.     if (CurXPos <> LastX) or (CurYPos <> LastY) then
  1052.       begin
  1053.         DoSetCursorPosition;
  1054.         LastX := CurXPos;
  1055.         LastY := CurYPos;
  1056.       end;
  1057.   until tidCursor = -2;
  1058.   tidCursor := -1;
  1059. end;
  1060.  
  1061. procedure CursorThreadExitProc;
  1062. begin
  1063.   // Force cursor thread to terminate
  1064.   tidCursor := -2;
  1065.   SemPostEvent(semCursor);
  1066.   // Update cursor position
  1067.   DoSetCursorPosition;
  1068. end;
  1069.  
  1070. procedure InitialiseKeyboardHandler;
  1071. begin
  1072.   if hKbdDll = -1 then // First try - attempt load
  1073.     begin
  1074.       hKbdDll := LoadLibrary(KbdDllName);
  1075.       if hKbdDll <> 0 then
  1076.         begin
  1077.           @pKbdInit := GetProcAddress(hKbdDll, name_KbdInit);
  1078.           @pKbdUpdateEventQueues := GetProcAddress(hKbdDll, name_KbdUpdateEventQueue);
  1079.         end;
  1080.       // If any of the entry points were not found in the DLL, point them
  1081.       // to statically linked default handlers
  1082.       if not assigned(pKbdInit) or not assigned(pKbdUpdateEventQueues) then
  1083.         begin
  1084.           @pKbdInit := @VpKbdW32.KbdInit;
  1085.           @pKbdUpdateEventQueues := @VpKbdW32.KbdUpdateEventQueues;
  1086.         end;
  1087.       pKbdInit(pSysKeyCount, pSysKeyQue, pSysShiftState, pSysMouCount, pSysMouQue);
  1088.     end;
  1089. end;
  1090.  
  1091. procedure InitialiseConsole;
  1092. begin
  1093.   SysConIn  := SysFileStdIn; //CreateFile('CONIN$' , generic_Read or generic_Write, file_share_Read, nil, open_Existing, file_attribute_Normal, 0);
  1094.   SysConOut := SysFileStdOut; //CreateFile('CONOUT$', generic_Read or generic_Write, file_share_Read or file_share_Write, nil, open_Existing, file_attribute_Normal, 0);
  1095.  
  1096.   InitialiseKeyboardHandler;
  1097. end;
  1098.  
  1099.  
  1100. const
  1101.   CrtScanCode: Byte = 0;
  1102.  
  1103. function SysKeyPressed: Boolean;
  1104. begin
  1105.   if CrtScanCode <> 0 then
  1106.     Result := True
  1107.   else
  1108.     begin
  1109.       InitialiseKeyboardHandler;
  1110.       pKbdUpdateEventQueues;
  1111.       Result := pSysKeyCount^ <> 0;
  1112.     end;
  1113. end;
  1114.  
  1115. function SysPeekKey(Var Ch: Char): Boolean;
  1116. begin
  1117.   pKbdUpdateEventQueues;
  1118.   if pSysKeyCount^ > 0 then
  1119.     Result := False
  1120.   else
  1121.     begin
  1122.       Result := True;
  1123.       if Lo(pSysKeyQue^[0].skeKeyCode) in [0,$E0] then
  1124.         Ch := #0
  1125.       else
  1126.         Ch := Chr(Lo(pSysKeyQue^[0].skeKeyCode));
  1127.     end;
  1128. end;
  1129.  
  1130. function SysReadKey: Char;
  1131. var
  1132.   EventCount: DWord;
  1133.   InRec: TInputRecord;
  1134. begin
  1135.   if CrtScanCode <> 0 then
  1136.     begin
  1137.       Result := Chr(CrtScanCode);
  1138.       CrtScanCode := 0;
  1139.     end
  1140.   else
  1141.     begin
  1142.       InitialiseKeyboardHandler;
  1143.       repeat
  1144.         pKbdUpdateEventQueues;
  1145.         if pSysKeyCount^ = 0 then
  1146.           WaitForSingleObject(SysConIn, infinite);
  1147.       until pSysKeyCount^ <> 0;
  1148.       Dec(pSysKeyCount^);
  1149.       if Lo(pSysKeyQue^[0].skeKeyCode) in [0,$E0] then
  1150.         begin
  1151.           CrtScanCode := Hi(pSysKeyQue^[0].skeKeyCode);
  1152.           Result := #0;
  1153.         end
  1154.       else
  1155.         Result := Chr(Lo(pSysKeyQue^[0].skeKeyCode));
  1156.       Move(pSysKeyQue^[1], pSysKeyQue^[0], pSysKeyCount^ * SizeOf(TSysKeyEvent));
  1157.     end;
  1158. end;
  1159.  
  1160. procedure SysFlushKeyBuf;
  1161. begin
  1162.   InitialiseKeyboardHandler;
  1163.   CrtScanCode := 0;
  1164.   pSysKeyCount^ := 0;
  1165.   FlushConsoleInputBuffer(SysConIn);
  1166. end;
  1167.  
  1168. procedure InitialiseCursorThread;
  1169. var
  1170.   sbi: TConsoleScreenBufferInfo;
  1171. begin
  1172.   if tidCursor = -1 then
  1173.     begin
  1174.       // Get initial cursor position
  1175.       GetConsoleScreenBufferInfo(SysConOut, sbi);
  1176.       CurXPos := sbi.dwCursorPosition.x;
  1177.       CurYPos := sbi.dwCursorPosition.y;
  1178.  
  1179.       semCursor := SemCreateEvent(nil, false, false);
  1180.       BeginThread(nil, 16384, CursorThreadFunc, nil, 0, tidCursor );
  1181.       SemPostEvent(semCursor);
  1182.       AddExitProc(CursorThreadExitProc);
  1183.     end;
  1184. end;
  1185.  
  1186. procedure SysWrtCharStrAtt(CharStr: Pointer; Len, X, Y: SmallWord; var Attr: Byte);
  1187. var
  1188.   Buffer: Array[0..255] of TWin32Cell;
  1189.   BufferSize,
  1190.   BufferCoord: TCoord;
  1191.   WriteRegion: TSmallRect;
  1192.   BufNext: ^TWin32Cell;
  1193.   I: Longint;
  1194. begin
  1195.   InitialiseCursorThread;
  1196.   BufNext := @Buffer;
  1197.   for i := 0 to Len-1 do
  1198.     begin
  1199.       BufNext^.Attr := Attr;
  1200.       BufNext^.Ch := Ord( PChar(CharStr)^ );
  1201.       inc(PChar(CharStr));
  1202.       inc(BufNext);
  1203.     end;
  1204.   with BufferSize do
  1205.     begin
  1206.       x := Len;
  1207.       y := 1;
  1208.     end;
  1209.   with BufferCoord do
  1210.     begin
  1211.       x := 0;
  1212.       y := 0;
  1213.     end;
  1214.   with WriteRegion do
  1215.     begin
  1216.       Left := x;
  1217.       Top := y;
  1218.       Right := x+Len-1;
  1219.       Bottom := y;
  1220.     end;
  1221.   WriteConsoleOutput( SysConOut, @Buffer, BufferSize, BufferCoord, WriteRegion );
  1222. end;
  1223.  
  1224. function SysReadAttributesAt(x,y: SmallWord): Byte;
  1225. var
  1226.   WasRead: Longint;
  1227.   Coor: TCoord;
  1228.   Temp: SmallWord;
  1229. begin
  1230.   SysTVInitCursor;
  1231.   Coor.x := x;
  1232.   Coor.y := y;
  1233.   ReadConsoleOutputAttribute(SysConOut, @Temp, 1, Coor, WasRead);
  1234.   Result := Temp;
  1235. end;
  1236.  
  1237. function SysReadCharAt(x,y: SmallWord): Char;
  1238. var
  1239.   WasRead: Longint;
  1240.   Coor: TCoord;
  1241. begin
  1242.   SysTVInitCursor;
  1243.   Coor.x := x;
  1244.   Coor.y := y;
  1245.   ReadConsoleOutputCharacter(SysConOut, @Result, 1, Coor, WasRead);
  1246.   if WasRead = 0 then
  1247.     Result := #0;
  1248. end;
  1249.  
  1250. procedure SysScrollUp(X1,Y1,X2,Y2,Lines,Cell: SmallWord);
  1251. var
  1252.   Cliprect,
  1253.   ScrollRect: TSmallRect;
  1254.   DestCoord: TCoord;
  1255.   Fill: TWin32Cell;
  1256.   i: Integer;
  1257. begin
  1258.   if SysPlatform = -1 then
  1259.     SysPlatform := SysPlatformID;
  1260.   Fill.ch := Lo(Cell);
  1261.   Fill.Attr := Hi( Cell );
  1262.   ScrollRect.Left := X1;
  1263.   ScrollRect.Top := Y1;
  1264.   ScrollRect.Right := X2;
  1265.   ScrollRect.Bottom := Y2;
  1266.   ClipRect := ScrollRect;
  1267.   if SysPlatform = VER_PLATFORM_WIN32_NT then
  1268.     begin
  1269.       DestCoord.x := X1;       // This API works in Windows NT
  1270.       DestCoord.y := Y1-Lines;
  1271.       ScrollConsoleScreenBuffer(SysConOut, ScrollRect, @ClipRect, DestCoord, PCharInfo(@Fill)^);
  1272.     end
  1273.   else
  1274.     begin
  1275.       if Lines > 1 then
  1276.         for i := 1 to 2 do // Half a screen at a time; bug in Win95
  1277.           begin
  1278.             DestCoord.x := X1;
  1279.             DestCoord.y := Y1-Lines div 2;
  1280.             ScrollConsoleScreenBuffer(SysConOut, ScrollRect, @ClipRect, DestCoord, PCharInfo(@Fill)^);
  1281.           end;
  1282.       if odd(Lines) then // Also do last line, if odd number
  1283.         begin
  1284.           DestCoord.x := X1;
  1285.           DestCoord.y := Y1-1;
  1286.           ScrollConsoleScreenBuffer(SysConOut, ScrollRect, @ClipRect, DestCoord, PCharInfo(@Fill)^);
  1287.         end;
  1288.     end;
  1289. end;
  1290.  
  1291. procedure SysScrollDn(X1,Y1,X2,Y2,Lines,Cell: SmallWord);
  1292. var
  1293.   ScrollRect: TSmallRect;
  1294.   DestCoord: TCoord;
  1295.   Fill: TWin32Cell;
  1296. begin
  1297.   Fill.ch := Lo(Cell);
  1298.   Fill.Attr := Hi(Cell);
  1299.   ScrollRect.Left := X1;
  1300.   ScrollRect.Top := Y1;
  1301.   ScrollRect.Right := X2;
  1302.   ScrollRect.Bottom := Y2-Lines;
  1303.   DestCoord.x := X1;
  1304.   DestCoord.y := Y1+Lines;
  1305.   ScrollConsoleScreenBuffer(SysConOut, ScrollRect, nil, DestCoord, PCharInfo(@Fill)^);
  1306. end;
  1307.  
  1308. procedure SysGetCurPos(var X,Y: SmallWord);
  1309. begin
  1310.   if CurXPos = -1 then
  1311.     InitialiseCursorThread;
  1312.   X := CurXPos;
  1313.   Y := CurYPos;
  1314. end;
  1315.  
  1316. function SysTVDetectMouse: Longint;
  1317. begin
  1318.   Result := 2;
  1319. end;
  1320.  
  1321. procedure SysTVInitMouse(var X,Y: Integer);
  1322. begin
  1323.   X := 0;
  1324.   Y := 0;
  1325. end;
  1326.  
  1327. procedure SysTVDoneMouse(Close: Boolean);
  1328. begin
  1329. end;
  1330.  
  1331. procedure SysTVShowMouse; // No control over mouse pointer in Win32
  1332. begin
  1333. end;
  1334.  
  1335. procedure SysTVHideMouse; // No control over mouse pointer in Win32
  1336. begin
  1337. end;
  1338.  
  1339. procedure SysTVUpdateMouseWhere(var X,Y: Integer);
  1340. begin
  1341. end;
  1342.  
  1343. function SysTVGetMouseEvent(var Event: TSysMouseEvent): Boolean;
  1344. begin
  1345.   InitialiseKeyboardHandler;
  1346.   pKbdUpdateEventQueues;
  1347.   if pSysMouCount^ = 0 then
  1348.     Result := False
  1349.   else
  1350.     begin
  1351.       Dec(pSysMouCount^);
  1352.       Event := pSysMouQue^[0];
  1353.       Move(pSysMouQue^[1], pSysMouQue^[0], pSysMouCount^ * SizeOf(TSysMouseEvent));
  1354.       Result := True;
  1355.     end;
  1356. end;
  1357.  
  1358. procedure SysTVKbdInit;
  1359. begin
  1360.   SetConsoleMode(SysConIn, ENABLE_MOUSE_INPUT);
  1361. end;
  1362.  
  1363. function SysTVGetKeyEvent(var Event: TSysKeyEvent): Boolean;
  1364. begin
  1365.   InitialiseKeyboardHandler;
  1366.   pKbdUpdateEventQueues;
  1367.   if pSysKeyCount^ = 0 then
  1368.     Result := False
  1369.   else
  1370.     begin
  1371.       Dec(pSysKeyCount^);
  1372.       Event := pSysKeyQue^[0];
  1373.       Move(pSysKeyQue^[1], pSysKeyQue^[0], pSysKeyCount^ * SizeOf(TSysKeyEvent));
  1374.       Result := True;
  1375.     end;
  1376. end;
  1377.  
  1378. function SysTVPeekKeyEvent(var Event: TSysKeyEvent): Boolean;
  1379. begin
  1380.   InitialiseKeyboardHandler;
  1381.   pKbdUpdateEventQueues;
  1382.   if pSysKeyCount^ = 0 then
  1383.     Result := False
  1384.   else
  1385.     begin
  1386.       Event := pSysKeyQue^[0];
  1387.       Result := True;
  1388.     end;
  1389. end;
  1390.  
  1391. function SysTVGetShiftState: Byte;
  1392. begin
  1393.   InitialiseKeyboardHandler;
  1394.   Result := pSysShiftState^;
  1395. end;
  1396.  
  1397. procedure SysTVSetCurPos(X,Y: Integer);
  1398. var
  1399.   CurPos: TCoord;
  1400. begin
  1401.   CurXPos := X;
  1402.   CurYPos := Y;
  1403.   if tidCursor = -1 then
  1404.     // Set cursor position without using cursor thread
  1405.     DoSetCursorPosition
  1406.   else
  1407.     // Record cursor position; tell cursor thread to update
  1408.     SemPostEvent(semCursor);
  1409. end;
  1410.  
  1411. procedure SysTVSetCurType(Y1,Y2: Integer; Show: Boolean);
  1412. var
  1413.   Info: TConsoleCursorInfo;
  1414. begin
  1415.   Info.bVisible := Show;
  1416.   if Abs(Y1 - Y2) <= 1 then
  1417.     Info.dwSize := 15
  1418.   else
  1419.     Info.dwSize := 99;
  1420.   SetConsoleCursorInfo(SysConOut, Info);
  1421. end;
  1422.  
  1423. procedure SysTVGetCurType(var Y1,Y2: Integer; var Visible: Boolean);
  1424. var
  1425.   Info: TConsoleCursorInfo;
  1426. begin
  1427.   GetConsoleCursorInfo(SysConOut, Info);
  1428.   Visible := Info.bVisible;
  1429.   if Info.dwSize <= 25 then
  1430.     begin
  1431.       Y1 := 6;
  1432.       Y2 := 7;
  1433.     end
  1434.   else
  1435.     begin
  1436.       Y1 := 1;
  1437.       Y2 := 7;
  1438.     end;
  1439. end;
  1440.  
  1441. procedure WriteConsoleLine(X,Y: Integer; Len: Integer);
  1442. var
  1443.   P: PChar;
  1444.   Q: PWin32Cell;
  1445.   LineBuf: array[0..255] of TWin32Cell;
  1446.   R: TSmallRect;
  1447.   BufPos: TCoord;
  1448.   LineSize: TCoord;
  1449. begin
  1450.   InitialiseCursorThread;
  1451.   { Prepared parameters }
  1452.   LineSize.X := SysBufInfo.dwSize.X;
  1453.   LineSize.Y := 1;
  1454.   BufPos.X := 0;
  1455.   BufPos.Y := 0;
  1456.   R.Left := X;
  1457.   R.Top  := Y;
  1458.   R.Right := X + Len - 1;
  1459.   R.Bottom := Y;
  1460.   { Translate the buffer from DOS-OS/2 format to Win32 }
  1461.   P := SysScrBuf + ((Y * SysBufInfo.dwSize.X) + X) * 2;
  1462.   Q := @LineBuf;
  1463.   while Len > 0 do
  1464.   begin
  1465.     Q^.Ch := Ord(P^);
  1466.     Inc(P);
  1467.     Q^.Attr := Ord(P^);
  1468.     Inc(P);
  1469.     Inc(Q);
  1470.     Dec(Len);
  1471.   end;
  1472.   WriteConsoleOutput(SysConOut, @LineBuf, LineSize, BufPos, R);
  1473. end;
  1474.  
  1475. function Min(X,Y: Integer): Integer;
  1476. begin
  1477.   Result := Y;
  1478.   if X < Y then
  1479.     Result := X;
  1480. end;
  1481.  
  1482. procedure SysTVShowBuf(Pos,Size: Integer);
  1483. var
  1484.   I,X,Y: Integer;
  1485. begin
  1486.   Pos := Pos div 2;
  1487.   X := Pos mod SysBufInfo.dwSize.X;
  1488.   Y := Pos div SysBufInfo.dwSize.X;
  1489.   while Size > 0 do
  1490.   begin
  1491.     I := Min(SysBufInfo.dwSize.X - X, Size div 2);
  1492.     WriteConsoleLine(X, Y, I);
  1493.     Dec(Size, I * 2);
  1494.     X := 0;
  1495.     Inc(Y);
  1496.   end;
  1497. end;
  1498.  
  1499. procedure SysTVClrScr;
  1500. var
  1501.   I,BufSize: Integer;
  1502. begin
  1503.   BufSize := SysBufInfo.dwSize.X * SysBufInfo.dwSize.Y * 2;
  1504.   I := 0;
  1505.   while I < BufSize do
  1506.   begin
  1507.     SysScrBuf[I] := ' ';
  1508.     Inc(I);
  1509.     SysScrBuf[I] := #7;
  1510.     Inc(I);
  1511.   end;
  1512.   SysTVShowBuf(0, BufSize);
  1513.   SysTVSetCurPos(0, 0);
  1514. end;
  1515.  
  1516. function SysTVGetScrMode(Size: PSysPoint): Integer;
  1517. begin
  1518.   GetConsoleScreenBufferInfo(SysConOut, SysBufInfo);
  1519.   case SysBufInfo.dwSize.Y of
  1520.     25:    Result := $0003;
  1521.     43,50: Result := $0103;
  1522.     else   Result := $00FF;
  1523.   end;
  1524.   if Size <> nil then
  1525.     with Size^ do
  1526.     begin
  1527.       X := SysBufInfo.dwSize.X;
  1528.       Y := SysBufInfo.dwSize.Y;
  1529.       if Size.Y > 234 then
  1530.         Size.Y := 234;
  1531.     end;
  1532. end;
  1533.  
  1534. procedure SysTVSetScrMode(Mode: Integer);
  1535. var
  1536.   R: TSmallRect;
  1537.   Size: TCoord;
  1538. begin
  1539.   Size.X := 80;
  1540.   Size.Y := 25;
  1541.   if Mode and $0100 <> 0 then
  1542.     Size.Y := 50;
  1543.   SetConsoleScreenBufferSize(SysConOut, Size);
  1544.   R.Left   := 0;
  1545.   R.Top    := 0;
  1546.   R.Right  := Size.X - 1;
  1547.   R.Bottom := Size.Y - 1;
  1548.   SetConsoleWindowInfo(SysConOut, True, R);
  1549. end;
  1550.  
  1551. function SysTVGetSrcBuf: Pointer;
  1552. const
  1553.   First: Boolean = True;
  1554.   UpLeft: TCoord= (X:0; Y:0);
  1555.   ReadFrom: TSmallRect = (Left:0; Top:0; Right:0; Bottom:0);
  1556. var
  1557.   Size: TSysPoint;
  1558.   Coord: TCoord;
  1559.   Buffer: PWin32Cell;
  1560.   PDest: PStandardCell;
  1561.   PSrc: PWin32Cell;
  1562.   X,Y: Longint;
  1563. begin
  1564.   Result := @SysScrBuf;
  1565.   if First then
  1566.     begin
  1567.       First := False;
  1568.       SysTVGetScrMode(@Size);
  1569.       Coord.X := Size.X;
  1570.       Coord.Y := Size.Y;
  1571.       ReadFrom.Right := Size.X;
  1572.       ReadFrom.Bottom := Size.Y;
  1573.       // Read existing content of screen into buffer
  1574.       GetMem(Buffer, (Size.X+1)*(Size.Y+1)*SizeOf(TWin32Cell));
  1575.       if not ReadConsoleOutput(SysConOut, Buffer, Coord, UpLeft, ReadFrom) then
  1576.         X := GetLastError;
  1577.       // Move the data to the screen buffer in standard format
  1578.       PSrc := Buffer;
  1579.       PDest := Result;
  1580.       for Y := 0 to Size.Y-1 do
  1581.         for X := 0 to Size.X-1 do
  1582.           begin
  1583.             PDest^.Ch := chr(PSrc^.Ch);
  1584.             PDest^.Attr := byte(PSrc^.Attr);
  1585.             inc(PSrc);
  1586.             inc(PDest);
  1587.           end;
  1588.       FreeMem(Buffer);
  1589.     end;
  1590. end;
  1591.  
  1592. procedure SysTVInitCursor;
  1593. begin
  1594.   if SysConIn = -1 then
  1595.     InitialiseConsole;
  1596. end;
  1597.  
  1598. procedure SysCtrlSleep(Delay: Integer);
  1599. begin
  1600.   Sleep(Delay);
  1601. end;
  1602.  
  1603. function SysGetValidDrives: Longint;
  1604. begin
  1605.   Result := GetLogicalDrives;
  1606. end;
  1607.  
  1608. procedure SysDisableHardErrors;
  1609. begin
  1610.   SetErrorMode(sem_FailCriticalErrors);
  1611. end;
  1612.  
  1613. function SysKillProcess(Process: Longint): Longint;
  1614. begin
  1615.   Result := SetResult(TerminateProcess(Process, -1));
  1616. end;
  1617.  
  1618. function SysAllocSharedMem(Size: Longint; var MemPtr: Pointer): Longint;
  1619. begin
  1620.   Result := -1;
  1621. end;
  1622.  
  1623. function SysGiveSharedMem(MemPtr: Pointer): Longint;
  1624. begin
  1625.   Result := -1;
  1626. end;
  1627.  
  1628. function SysPipeCreate(var ReadHandle,WriteHandle: Longint; Size: Longint): Longint;
  1629. var
  1630.   SA: TSecurityAttributes;
  1631. begin
  1632.   SA.nLength := SizeOf(SA);
  1633.   SA.lpSecurityDescriptor := nil;
  1634.   SA.bInheritHandle := True;
  1635.   Result := SetResult(CreatePipe(ReadHandle, WriteHandle, @SA, Size));
  1636. end;
  1637.  
  1638. function SysPipePeek(Pipe: Longint; Buffer: Pointer; BufSize: Longint; var BytesRead: Longint; var IsClosing: Boolean): Longint;
  1639. var
  1640.   State: Longint;
  1641. begin
  1642.   Result := SetResult(PeekNamedPipe(Pipe, Buffer, BufSize, @BytesRead, nil, nil));
  1643.   IsClosing := WaitForSingleObject(ProcessInfo.hProcess, 0) = wait_Object_0;
  1644. end;
  1645.  
  1646. function SysPipeClose(Pipe: Longint): Longint;
  1647. begin
  1648.   Result := SysFileClose(Pipe);
  1649. end;
  1650.  
  1651. function SysLoadResourceString(ID: Longint; Buffer: PChar; BufSize: Longint): PChar;
  1652. begin
  1653.   Buffer[0] := #0;
  1654.   LoadString(HInstance, ID, Buffer, BufSize);
  1655.   Result := Buffer;
  1656. end;
  1657.  
  1658. function SysFileUNCExpand(Dest,Name: PChar): PChar;
  1659.  
  1660.   procedure GetUNCPath(FileName: PChar);
  1661.   type
  1662.     PNetResourceArray = ^TNetResourceArray;
  1663.     TNetResourceArray = array[0..MaxInt div SizeOf(TNetResource) - 1] of TNetResource;
  1664.   var
  1665.     Done: Boolean;
  1666.     I,Count,Size: Integer;
  1667.     NetHandle: THandle;
  1668.     P,NetResources: PNetResource;
  1669.     RemoteNameInfo: array[0..1023] of Byte;
  1670.     Drive: char;
  1671.   begin
  1672.     if SysPlatform <> VER_PLATFORM_WIN32_WINDOWS then
  1673.       begin
  1674.         Size := SizeOf(RemoteNameInfo);
  1675.         if WNetGetUniversalName(FileName, UNIVERSAL_NAME_INFO_LEVEL,
  1676.           @RemoteNameInfo, Size) <> NO_ERROR then
  1677.           Exit;
  1678.         StrCopy(FileName, PRemoteNameInfo(@RemoteNameInfo).lpUniversalName);
  1679.       end
  1680.     else
  1681.       begin
  1682.       { The following works around a bug in WNetGetUniversalName under Windows 95 }
  1683.         Drive := UpCase(FileName[1]);
  1684.         if (Drive < 'A') or (Drive > 'Z') or (StrLen(FileName) < 3) or
  1685.           (FileName[1] <> ':') or (FileName[2] <> '\') then
  1686.           Exit;
  1687.         if WNetOpenEnum(RESOURCE_CONNECTED, RESOURCETYPE_DISK, 0, nil, NetHandle) <> NO_ERROR then
  1688.           Exit;
  1689.         Count := -1;
  1690.         if WNetEnumResource(NetHandle, Count, nil, Size) = ERROR_MORE_DATA then
  1691.         begin
  1692.           GetMem(NetResources, Size);
  1693.           Done := False;
  1694.           P := NetResources;
  1695.           repeat
  1696.             if WNetEnumResource(NetHandle, Count, P, Size) <> NO_ERROR then
  1697.               Break;
  1698.             I := 0;
  1699.             while I < Count do
  1700.             begin
  1701.               with P^ do
  1702.                 if (lpLocalName <> nil) and (UpCase(FileName[0]) = UpCase(lpLocalName[0])) then
  1703.                 begin
  1704.                   I := StrLen(lpRemoteName);
  1705.                   StrMove(@FileName[I], @FileName[2], MaxInt);
  1706.                   Move(lpRemoteName^, FileName^, I);
  1707.                   Done := True;
  1708.                   Break;
  1709.                 end;
  1710.               Inc(I);
  1711.               Inc(P);
  1712.             end;
  1713.           until Done;
  1714.           FreeMem(NetResources);
  1715.         end;
  1716.         WNetCloseEnum(NetHandle);
  1717.       end;
  1718.   end;
  1719.  
  1720. begin
  1721.   if SysPlatform = -1 then
  1722.     SysPlatform := SysPlatformID;
  1723.   SysFileExpand(Dest, Name);
  1724.   if (UpCase(Dest[0]) in ['A'..'Z']) and (Dest[1] = ':') and (Dest[2] = '\') then
  1725.     GetUNCPath(Dest);
  1726.   Result := Dest;
  1727. end;
  1728.  
  1729. function SysGetSystemError(Code: Longint; Buffer: PChar; BufSize: Longint;var MsgLen: Longint): PChar;
  1730. begin
  1731.   MsgLen := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
  1732.     FORMAT_MESSAGE_ARGUMENT_ARRAY, nil, Code, 0, Buffer, BufSize, nil);
  1733.   Result := Buffer;
  1734. end;
  1735.  
  1736. function GetLocaleStr(Locale,LocaleType: Integer; Default,Dest: PChar): PChar;
  1737. begin
  1738.   if GetLocaleInfo(Locale, LocaleType, Dest, 260) <= 0 then
  1739.     StrCopy(Dest, Default);
  1740.   Result := Dest;
  1741. end;
  1742.  
  1743. function GetLocaleChar(Locale, LocaleType: Integer; Default: Char): Char;
  1744. var
  1745.   Buffer: array[0..1] of Char;
  1746. begin
  1747.   if GetLocaleInfo(Locale, LocaleType, @Buffer, 2) > 0 then
  1748.     Result := Buffer[0] else
  1749.     Result := Default;
  1750. end;
  1751.  
  1752. function SysStrToIntDef(S: PChar; Default: Integer): Integer;
  1753. var
  1754.   E: Integer;
  1755. begin
  1756.   Val(S, Result, E);
  1757.   if E <> 0 then
  1758.     Result := Default;
  1759. end;
  1760.  
  1761. procedure SysGetCurrencyFormat(CString: PChar; var CFormat, CNegFormat, CDecimals: Byte; var CThousandSep, CDecimalSep: Char);
  1762. var
  1763.   DefaultLCID: LCID;
  1764.   Buffer: array[0..259] of Char;
  1765. begin
  1766.   DefaultLCID := GetThreadLocale;
  1767.   GetLocaleStr(DefaultLCID, LOCALE_SCURRENCY, '', CString);
  1768.   CFormat := SysStrToIntDef(GetLocaleStr(DefaultLCID, LOCALE_ICURRENCY, '0', Buffer), 0);
  1769.   CNegFormat := SysStrToIntDef(GetLocaleStr(DefaultLCID, LOCALE_INEGCURR, '0', Buffer), 0);
  1770.   CThousandSep := GetLocaleChar(DefaultLCID, LOCALE_STHOUSAND, ',');
  1771.   CDecimalSep := GetLocaleChar(DefaultLCID, LOCALE_SDECIMAL, '.');
  1772.   CDecimals := SysStrToIntDef(GetLocaleStr(DefaultLCID, LOCALE_ICURRDIGITS, '0', Buffer), 0);
  1773. end;
  1774.  
  1775. procedure SysGetDateFormat(var DateSeparator: Char; ShortDateFormat, LongDateFormat: PChar);
  1776. var
  1777.   DefaultLCID: LCID;
  1778. begin
  1779.   DefaultLCID := GetThreadLocale;
  1780.   DateSeparator := GetLocaleChar(DefaultLCID, LOCALE_SDATE, '/');
  1781.   GetLocaleStr(DefaultLCID, LOCALE_SSHORTDATE, 'm/d/yy', ShortDateFormat);
  1782.   GetLocaleStr(DefaultLCID, LOCALE_SLONGDATE, 'mmmm d, yyyy', LongDateFormat);
  1783. end;
  1784.  
  1785. procedure SysGetTimeFormat(var TimeSeparator: Char; TimeAMString,TimePMString,ShortTimeFormat,LongTimeFormat: PChar);
  1786. var
  1787.   TimePostfix: PChar;
  1788.   DefaultLCID: LCID;
  1789.   Buffer: array[0..259] of Char;
  1790. begin
  1791.   DefaultLCID := GetThreadLocale;
  1792.   TimeSeparator := GetLocaleChar(DefaultLCID, LOCALE_STIME, ':');
  1793.   GetLocaleStr(DefaultLCID, LOCALE_S1159, 'am', TimeAMString);
  1794.   GetLocaleStr(DefaultLCID, LOCALE_S2359, 'pm', TimePMString);
  1795.   TimePostfix := '';
  1796.   if SysStrToIntDef(GetLocaleStr(DefaultLCID, LOCALE_ITLZERO, '0', Buffer), 0) = 0 then
  1797.     begin
  1798.       StrCopy(ShortTimeFormat, 'h:mm');
  1799.       StrCopy(LongTimeFormat, 'h:mm:ss');
  1800.     end
  1801.   else
  1802.     begin
  1803.       StrCopy(ShortTimeFormat, 'hh:mm');
  1804.       StrCopy(LongTimeFormat, 'hh:mm:ss');
  1805.     end;
  1806.   if SysStrToIntDef(GetLocaleStr(DefaultLCID, LOCALE_ITIME, '0', Buffer), 0) = 0 then
  1807.     TimePostfix := ' AMPM';
  1808.   StrCat(ShortTimeFormat, TimePostfix);
  1809.   StrCat(LongTimeFormat, TimePostfix);
  1810. end;
  1811.  
  1812. function SysGetModuleName(var Address: Pointer; Buffer: PChar; BufSize: Longint): PChar;
  1813. var
  1814.   MemInfo: TMemoryBasicInformation;
  1815.   ModName: array[0..Max_Path] of Char;
  1816. begin
  1817.   VirtualQuery(Address, MemInfo, SizeOf(MemInfo));
  1818.   if (MemInfo.State <> mem_Commit) or
  1819.      (GetModuleFilename(THandle(MemInfo.AllocationBase), ModName, SizeOf(ModName)) = 0) then
  1820.     begin
  1821.       GetModuleFileName(HInstance, ModName, SizeOf(ModName));
  1822.       if Assigned(Address) then
  1823.         Dec(PChar(Address), $1000);
  1824.     end
  1825.   else
  1826.     Dec(PChar(Address), Longint(MemInfo.AllocationBase));
  1827.   StrLCopy(Buffer, StrRScan(ModName, '\') + 1, BufSize - 1);
  1828.   Result := Buffer;
  1829. end;
  1830.  
  1831. procedure SysDisplayConsoleError(PopupErrors: Boolean; Title, Msg: PChar);
  1832. var
  1833.   Count: Longint;
  1834. begin
  1835.   SysFileWrite(SysFileStdOut, Msg^, StrLen(Msg), Count);
  1836. end;
  1837.  
  1838. procedure SysDisplayGUIError(Title, Msg: PChar);
  1839. begin
  1840.   MessageBox(0, Msg, Title, MB_OK or MB_IconStop or MB_TaskModal);
  1841. end;
  1842.  
  1843. procedure SysBeep;
  1844. begin
  1845.   MessageBeep(0);
  1846. end;
  1847.  
  1848. procedure SysBeepEx(Freq,Dur: Longint);
  1849. begin
  1850.   Windows.Beep(Freq, Dur);
  1851. end;
  1852.  
  1853. function SysGetVolumeLabel(Drive: Char): ShortString;
  1854. const
  1855.   Root: Array[0..4] of char = 'C:\'#0;
  1856. var
  1857.   VolLabel: Array[0..256] of char;
  1858.   MaxLength: Longint;
  1859.   FSFlags: Longint;
  1860. begin
  1861.   Root[0] := Drive;
  1862.   if GetVolumeInformation(Root, VolLabel, Sizeof(VolLabel),
  1863.     nil, MaxLength, FSFlags, nil, 0) then
  1864.     Result := StrPas(VolLabel)
  1865.   else
  1866.     Result := '';
  1867. end;
  1868.  
  1869. function SysSetVolumeLabel(Drive: Char; _Label: ShortString): Boolean;
  1870. const
  1871.   Root: Array[0..4] of char = 'C:\'#0;
  1872. begin
  1873.   Root[0] := Drive;
  1874.   _Label[Length(_Label)+1] := #0;
  1875.   Result := SetVolumeLabel(Root, PChar(@_Label[1]));
  1876. end;
  1877.  
  1878. function SysGetForegroundProcessId: Longint;
  1879. var
  1880.   WHandle: Longint;
  1881.   ThreadID: Longint;
  1882. begin
  1883.   WHandle := GetForegroundWindow;
  1884.   Result := GetWindowThreadProcessId(WHandle, @ThreadID);
  1885. end;
  1886.  
  1887. function SysGetBootDrive: Char;
  1888. begin
  1889.   Result := 'C';
  1890. end;
  1891.  
  1892. function SysGetDriveType(Drive: Char): TDriveType;
  1893. const
  1894.   Root: Array[0..4] of char = 'C:\'#0;
  1895. var
  1896.   FSName: Array[0..255] of char;
  1897.   MaxLength: Longint;
  1898.   FSFlags: Longint;
  1899. begin
  1900.   Root[0] := Drive;
  1901.   Result := dtInvalid;
  1902.   if GetVolumeInformation(Root, nil, 0, nil, MaxLength, FSFlags, FSName, sizeof(FSName)) then
  1903.     begin
  1904.       if StrLComp(FSName, 'FAT', 3) = 0 then
  1905.         Result := dtHDFAT
  1906.       else if StrComp(FSName, 'HPFS') = 0 then
  1907.         Result := dtHDHPFS
  1908.       else if StrComp(FSName, 'NTFS') = 0 then
  1909.         Result := dtHDNTFS
  1910.       else if StrLComp(FSName, 'CD', 2) = 0 then
  1911.         Result := dtCDROM
  1912.       else if StrComp(FSName, 'LAN') = 0 then
  1913.         Result := dtLan
  1914.       else if StrComp(FSName, 'NOVELL') = 0 then
  1915.         Result := dtNovellNet;
  1916.     end;
  1917.  
  1918.   if Result = dtInvalid then
  1919.     case GetDriveType(Root) of
  1920.       Drive_Fixed     : Result := dtHDFAT;
  1921.       Drive_Removable : Result := dtFloppy;
  1922.       Drive_CDRom     : Result := dtCDROM;
  1923.       Drive_Remote    : Result := dtLAN;
  1924.       0, 1            : Result := dtInvalid;
  1925.     else                Result := dtUnknown;
  1926.     end;
  1927. end;
  1928.  
  1929. function SysGetVideoModeInfo( Var Cols, Rows, Colours : Word ): Boolean;
  1930. var
  1931.   Buffer: TConsoleScreenBufferInfo;
  1932. begin
  1933.   SysTVInitCursor;
  1934.   GetConsoleScreenBufferInfo(SysConOut, Buffer);
  1935.  
  1936.   Cols := Buffer.dwSize.x;
  1937.   Rows := Buffer.dwSize.y;
  1938.   Colours := 16; //Buffer.wAttributes;
  1939. end;
  1940.  
  1941. function SysGetVisibleLines( var Top, Bottom: Longint ): Boolean;
  1942. var
  1943.   Buffer: TConsoleScreenBufferInfo;
  1944. begin
  1945.   SysTVInitCursor;
  1946.   GetConsoleScreenBufferInfo(SysConOut, Buffer);
  1947.   Top := Buffer.srwindow.top+1;
  1948.   Bottom := Buffer.srwindow.bottom+1;
  1949.   Result := True;
  1950. end;
  1951.  
  1952. function SysSetVideoMode( Cols, Rows: Word ): Boolean;
  1953. var
  1954.   Size: TCoord;
  1955.   R: TSmallRect;
  1956. begin
  1957.   SysTVInitCursor;
  1958.   Size.X := Cols;
  1959.   Size.Y := Rows;
  1960.   Result := SetConsoleScreenBufferSize(SysConOut, Size);
  1961.   R.Left   := 0;
  1962.   R.Top    := 0;
  1963.   R.Right  := Size.X - 1;
  1964.   R.Bottom := Size.Y - 1;
  1965.   Result := SetConsoleWindowInfo(SysConOut, True, R);
  1966. end;
  1967.  
  1968. function SemCreateEvent(_Name: pChar; _Shared, _State: Boolean): TSemHandle;
  1969. var
  1970.   Security: TSecurityAttributes;
  1971. begin
  1972.   if _Shared then
  1973.     begin
  1974.       with Security do
  1975.         begin
  1976.           nLength := Sizeof(Security);
  1977.           lpSecurityDescriptor := nil;
  1978.           bInheritHandle := True;
  1979.         end;
  1980.       Result := CreateEvent(@Security, False, _State, _Name);
  1981.     end
  1982.   else
  1983.     Result := CreateEvent(nil, False, _State, _Name);
  1984. end;
  1985.  
  1986. function SemAccessEvent(_Name: PChar): TSemHandle;
  1987. begin
  1988.   Result := OpenEvent( Event_all_access, False, _Name);
  1989.   if Result = 0 then
  1990.     Result := -1;
  1991. end;
  1992.  
  1993. function SemPostEvent(_Handle: TSemhandle): Boolean;
  1994. begin
  1995.   Result := SetEvent(_Handle);
  1996. end;
  1997.  
  1998. function SemWaitEvent(_Handle: TSemHandle; _TimeOut: Longint): Boolean;
  1999. begin
  2000.   Result := WaitForSingleObject(_Handle, _TimeOut) = WAIT_OBJECT_0;
  2001. end;
  2002.  
  2003. function SemCreateMutex(_Name: PChar; _Shared, _State: Boolean): TSemHandle;
  2004. var
  2005.   Security: TSecurityAttributes;
  2006. begin
  2007.   if _Shared then
  2008.     begin
  2009.       with Security do
  2010.         begin
  2011.           nLength := Sizeof(Security);
  2012.           lpSecurityDescriptor := nil;
  2013.           bInheritHandle := True;
  2014.         end;
  2015.       Result := CreateMutex(@Security, _State, _Name);
  2016.     end
  2017.   else
  2018.     // Non-shared mutex does not require security descriptor
  2019.     Result := CreateMutex(nil, _State, _Name);
  2020. end;
  2021.  
  2022. function SemRequestMutex(_Handle: TSemHandle; _TimeOut: Longint): Boolean;
  2023. begin
  2024.   Result := WaitForSingleObject(_Handle, _TimeOut) = WAIT_OBJECT_0;
  2025. end;
  2026.  
  2027. function SemAccessMutex(_Name: PChar): TSemHandle;
  2028. begin
  2029.   Result := OpenMutex( mutex_all_access, False, _Name);
  2030.   if Result = 0 then
  2031.     Result := -1;
  2032. end;
  2033.  
  2034. function SemReleaseMutex(_Handle: TSemHandle): Boolean;
  2035. begin
  2036.   Result := ReleaseMutex( _Handle );
  2037. end;
  2038.  
  2039. procedure SemCloseEvent(_Handle: TSemHandle);
  2040. begin
  2041.   CloseHandle(_Handle);
  2042. end;
  2043.  
  2044. procedure SemCloseMutex(_Handle: TSemHandle);
  2045. begin
  2046.   CloseHandle(_Handle);
  2047. end;
  2048.  
  2049. function SysMemInfo(_Base: Pointer; _Size: Longint; var _Flags: Longint): Boolean;
  2050. var
  2051.   Buffer: TMemoryBasicInformation;
  2052. begin
  2053.   Result := VirtualQuery(_Base, Buffer, Sizeof(Buffer)) = Sizeof(Buffer);
  2054.   if Result then
  2055.     with Buffer do
  2056.      begin
  2057.        _Flags := 0;
  2058.        if Protect and (Page_ReadOnly or Page_ReadWrite or Page_Execute_Read) <> 0 then
  2059.          _Flags := _Flags or sysmem_Read or sysmem_Execute;
  2060.        if Protect and (Page_WriteCopy or Page_ReadWrite) <> 0 then
  2061.          _Flags := _Flags or sysmem_Write;
  2062.        if Protect and (Page_Execute or Page_Execute_Read or Page_Execute_ReadWrite) <> 0 then
  2063.          _Flags := _Flags or sysmem_Execute;
  2064.        if Protect and Page_Guard <> 0 then
  2065.          _Flags := _Flags or sysmem_Guard;
  2066.      end;
  2067. end;
  2068.  
  2069. function SysSetMemProtection(_Base: Pointer; _Size: Longint; _Flags: Longint): Boolean;
  2070. var
  2071.   Flags: Longint;
  2072.   Buffer: TMemoryBasicInformation;
  2073. begin
  2074.   VirtualQuery(_Base, Buffer, Sizeof(Buffer));
  2075.   if _Flags and sysmem_Execute <> 0 then
  2076.     if _Flags and sysmem_Read <> 0 then
  2077.       if _Flags and sysmem_Write <> 0 then
  2078.         Flags := page_Execute_ReadWrite
  2079.       else
  2080.         Flags := page_Execute_Read
  2081.     else
  2082.       if _Flags and sysmem_Write <> 0 then
  2083.         Flags := page_Execute_WriteCopy
  2084.       else
  2085.         Flags := page_Execute
  2086.   else
  2087.     if _Flags and sysmem_Read <> 0 then
  2088.       if _Flags and sysmem_Write <> 0 then
  2089.         Flags := page_ReadWrite
  2090.       else
  2091.         Flags := page_ReadOnly
  2092.     else
  2093.       if _Flags and sysmem_Write <> 0 then
  2094.         Flags := page_WriteCopy
  2095.       else
  2096.         Flags := page_NoAccess;
  2097.   Result := VirtualProtect(_Base, _Size, Flags, @Buffer);
  2098. end;
  2099.  
  2100. procedure SysMessageBox(_Msg, _Title: PChar; _Error: Boolean);
  2101. var
  2102.   Flag: Longint;
  2103. begin
  2104.   if _Error then
  2105.     Flag := mb_IconError
  2106.   else
  2107.     Flag := mb_IconInformation;
  2108.   MessageBox( 0, _Msg, _Title, Flag or mb_ApplModal);
  2109. end;
  2110.  
  2111. function SysClipCanPaste: Boolean;
  2112. var
  2113.   IsClipboardFormatAvailable: function(Format: UInt): Bool stdcall;
  2114. begin
  2115.   @IsClipboardFormatAvailable := QueryProcAddr('IsClipboardFormatAvailable', False);
  2116.   if Assigned(IsClipboardFormatAvailable) then
  2117.     Result := IsClipboardFormatAvailable(cf_Text)
  2118.   else
  2119.     Result := False;
  2120. end;
  2121.  
  2122. function SysClipCopy(P: PChar; Size: Longint): Boolean;
  2123. var
  2124.   Q: pChar;
  2125.   MemHandle: HGlobal;
  2126.   OpenClipboard: function(Wnd: hWnd): Bool stdcall;
  2127.   EmptyClipboard: function: Bool stdcall;
  2128.   CloseClipboard: function: Bool stdcall;
  2129.   SetClipboardData: function(Format: UInt; Mem: THandle): THandle stdcall;
  2130. begin
  2131.   Result := False;
  2132.   @OpenClipboard := QueryProcAddr('OpenClipboard', False);
  2133.   @EmptyClipboard := QueryProcAddr('EmptyClipboard', False);
  2134.   @CloseClipboard := QueryProcAddr('CloseClipboard', False);
  2135.   @SetClipboardData := QueryProcAddr('SetClipboardData', False);
  2136.   if Assigned(OpenClipboard) and Assigned(EmptyClipboard) and
  2137.     Assigned(CloseClipboard) and Assigned(SetClipboardData) then
  2138.   begin
  2139.     // Open clipboard
  2140.     if OpenClipboard(0) then
  2141.     begin
  2142.       EmptyClipboard;
  2143.       // Allocate a shared block of memory
  2144.       MemHandle := GlobalAlloc(gmem_Moveable or gmem_DDEShare, Size+1);
  2145.       Q := GlobalLock(MemHandle);
  2146.       // Copy clipboard data across and translate to ANSI charset
  2147.       Result := OemToCharBuff(P, Q, Size);
  2148.       Q[Size]:=#0;
  2149.       GlobalUnlock(MemHandle);
  2150.       // Insert data into clipboard
  2151.       if Result then
  2152.         Result := SetClipboardData(cf_Text, MemHandle) <> 0;
  2153.       // Do not free memory: Windows does this!
  2154.       // GlobalFree(MemHandle);
  2155.     end;
  2156.     CloseClipboard;
  2157.   end;
  2158. end;
  2159.  
  2160. function SysClipPaste(var Size: Integer): Pointer;
  2161. var
  2162.   P: Pointer;
  2163.   MemHandle: HGlobal;
  2164.   OpenClipboard: function(Wnd: hWnd): Bool stdcall;
  2165.   CloseClipboard: function: Bool stdcall;
  2166.   GetClipboardData: function(Format: UInt): THandle stdcall;
  2167. begin
  2168.   Result := nil;
  2169.   @OpenClipboard := QueryProcAddr('OpenClipboard', False);
  2170.   @CloseClipboard := QueryProcAddr('CloseClipboard', False);
  2171.   @GetClipboardData := QueryProcAddr('GetClipboardData', False);
  2172.   if Assigned(OpenClipboard) and Assigned(CloseClipboard)
  2173.     and Assigned(GetClipboardData) then
  2174.   begin
  2175.     if OpenClipboard(0) then
  2176.     begin
  2177.       MemHandle := GetClipboardData(cf_Text);
  2178.       P := GlobalLock(MemHandle);
  2179.       if Assigned(P) then
  2180.       begin
  2181.         Size := StrLen(P) + 1;
  2182.         GetMem(Result, Size);
  2183.         // Copy clipboard data across and translate to OEM charset
  2184.         CharToOemBuff(P, Result, Size);
  2185.       end;
  2186.       GlobalUnlock(MemHandle);
  2187.       CloseClipBoard;
  2188.     end;
  2189.   end;
  2190. end;
  2191.  
  2192. // Pharlap's TNT Embedded System support
  2193.  
  2194. function _malloc(Size: Longint): Pointer; cdecl; orgname;
  2195. begin
  2196.   GetMem(Result, Size);
  2197. end;
  2198.  
  2199. procedure _free(P: Pointer); cdecl; orgname;
  2200. begin
  2201.   FreeMem(P);
  2202. end;
  2203.  
  2204. // Retrieve various system settings, bitmapped:
  2205. // 0: Enhanced keyboard installed
  2206.  
  2207. function SysGetSystemSettings: Longint;
  2208. var
  2209.   KbdFlag: Longint;
  2210. begin
  2211.   Result := 0;
  2212.   KbdFlag := GetKeyboardType(0);
  2213.   if KbdFlag in [2, 4] then
  2214.     Result := Result OR 1;
  2215. end;
  2216.  
  2217.  
  2218.