home *** CD-ROM | disk | FTP | other *** search
/ Gambler 19 / GAMBLERCD19.BIN / UTILS / DDTPACK / PROGS / FM-EXT / SOURCE / ENHDOS.PAS next >
Pascal/Delphi Source File  |  1995-06-05  |  82KB  |  3,193 lines

  1. Unit EnhDOS;
  2. (*
  3.   Borland Pascal 7.0 (7.01)
  4.   Enhanced DOS interface unit for DOS 3.1+ ***  Version 1.7  April, 1995.
  5.   Copyright (c) 1994,95 by Andrew Eigus. This version is Public Domain.
  6.   The only restriction to this code:
  7.     - Please do not modify copyrights. :) Just a megawish. ;)
  8.  
  9.   Copyright notes:
  10.     Runtime Library  Copyright (c) 1991,92 Borland International
  11.     GetDriveType portions  Copyright (c) 1994 by Bobby Z.
  12.  
  13.   EnhDOS unit is fully compatible and can be used for DOS/Windows/DPMI
  14.   targets. If you have any questions, suggestions or bug reports, please
  15.   send mail to andrejs@ltu-po.swh.lv or mrbyte@dcbalt.vernet.lv via
  16.   Internet or to 2:5100/33 via Fidonet. Thank you for using EnhDOS!
  17. *)
  18.  
  19. interface
  20.  
  21. {#Z+}
  22.  
  23. (******* General notes
  24.  
  25.  You are allowed to modify the entire code, however, my advise would be not
  26.  to do this...
  27.  
  28.  This unit is fully compatible with D.J. Murdoch's ScanHelp utility
  29.  version 3.0 or later. Use ScanHelp to compile this source to a .TPH
  30.  format help file.
  31.  
  32.  Procedures and functions ending with character '_' work with Pascal-type
  33.  strings rather than with null-terminated PChar-type strings.
  34.  
  35.  ******* End of general notes *)
  36.  
  37. {$X+} { Enable extended syntax }
  38. {$I-} { Disable I/O checking }
  39. {$S-} { Disable stack overflow checking }
  40. {$W-} { Disable generation of a special code for FAR procedures/functions }
  41. {$IFDEF P286}
  42. {$G+} { Enable 286 code generation if P286 located in conditional defines }
  43. {$ENDIF}
  44. {$IFDEF P386}
  45. {$G+} { Enable 286 code generation if P386 located in conditional defines }
  46. {$ENDIF}
  47.  
  48. {$IFDEF Windows}
  49. uses WinTypes, WinProcs, Strings, WinAPI;
  50. {$DEFINE ProtectedMode}
  51. {$ENDIF}
  52.  
  53. {$IFDEF DPMI}
  54. uses Strings, WinAPI;
  55. {$DEFINE ProtectedMode}
  56. {$ENDIF}
  57.  
  58. {$IFNDEF ProtectedMode}
  59. uses Strings;
  60. {$ENDIF}
  61.  
  62. {#Z-}
  63.  
  64. const
  65.   omRead           = $00; { Open file for input only }
  66.   omWrite          = $01; { Open file for output only }
  67.   omReadWrite      = $02; { Open file for input or/and output (both modes) }
  68.   omShareCompat    = $00;
  69.   omShareExclusive = $10;
  70.   omShareDenyWrite = $20;
  71.   omShareDenyRead  = $30;
  72.   omShareDenyNone  = $40;
  73.  
  74.   {#T omXXX}
  75.   {#X omRead}{#X omWrite}{#X omReadWrite}
  76.   {#X omShareCompat}{#X omShareExclusive}{#X omShareDenyWrite}{#X omShareDenyRead}{#X omShareDenyNone}
  77.  
  78.   { Handle file open modes. Used by the #h_OpenFile# function }
  79.  
  80.   fsPathName       = 79;
  81.   fsDirectory      = 64;
  82.   fsFileSpec       = 12;
  83.   fsFileName       = 8;
  84.   fsExtension      = 4;
  85.  
  86.   {#T fsXXX}
  87.   {#X fsPathName}{#X fsDirectory}{#X fsFileSpec}{#X fsFileName}{#X fsExtension}
  88.   { Maximum file-name component string lengths used by the #FileSearch# and
  89.     #FileExpand# functions }
  90.  
  91.   fcExtension      = $0001;
  92.   fcFileName       = $0002;
  93.   fcDirectory      = $0004;
  94.   fcWildcards      = $0008;
  95.  
  96.   {#T fcXXX}
  97.   {#X fcExtension}{#X fsFileName}{#X fcDirectory}{#X fcWildcards}
  98.   { These constants are used by the #FileSplit# function. The returned value
  99.     is a combination of the fcDirectory, fcFileName, and fcExtension bit
  100.     masks. The value indicates which components were present in the path.
  101.     If the name or extension contains any wildcard characters (* or ?), the
  102.     fcWildcards flag is set }
  103.  
  104.   faNormal         = $00;
  105.   faReadOnly       = $01;
  106.   faHidden         = $02;
  107.   faSysFile        = $04;
  108.   faVolumeID       = $08;
  109.   faDirectory      = $10;
  110.   faArchive        = $20;
  111.   faAnyFile        = $3F;
  112.  
  113.   Normal           = $00;
  114.   ReadOnly         = $01;
  115.   Hidden           = $02;
  116.   SysFile          = $04;
  117.   VolumeID         = $08;
  118.   Directory        = $10;
  119.   Archive          = $20;
  120.   AnyFile          = $3F;
  121.  
  122.   {#T faXXX}
  123.   {#X faNormal}{#X faReadOnly}{#X faHidden}{#X faSysFile}{#X faVolumeID}
  124.   {#X faDirectory}{#X faArchive}{#X faAnyFile}
  125.   { These constants test, set, and clear file-attribute bits in connection with
  126.     the #GetFileAttr#, #SetFileAttr#, #FindFirst#, and #FindNext# procedures.
  127.     These constants are additive. The faAnyFile constant is the sum of all
  128.     attributes }
  129.  
  130.   skStart = 0; { Seek position relative to the start of a file }
  131.   skPos   = 1; { Seek position relative to a current file position }
  132.   skEnd   = 2; { Seek position relative to the end of a file }
  133.  
  134.   {#T skXXX}
  135.   {#X skStart}{#X skPos}{#X skEnd}
  136.   { These constants define position relative to what seek the file pointer.
  137.     They are only used in the #h_LSeek# function }
  138.  
  139.   hStdInput   = 0; { Standard input device }
  140.   hStdOutput  = 1; { Standard output device }
  141.   hStdAUX     = 3; { Standard AUX device (COM1) }
  142.   hStdPrinter = 4; { Standard Printer device (LPT1) }
  143.  
  144.   {#T hXXX}
  145.   {#X hStdInput}{#X hStdOutput}{#X hStdAUX}{#X hStdPrinter}
  146.   { These constants are the standard I/O device handle numbers. They can be
  147.     used in connection with the #h_OpenFile#, #h_DupHandle#, #h_ForceDup#
  148.     and other handle functions. Use them to access the standard I/O devices }
  149.  
  150.   frOk    = 0;
  151.   { Continue program. If you return this value, the calling function simply
  152.     terminates. This is the default return value for all the functions
  153.     supported by the #DefaultErrorProc# function }
  154.   frRetry = 1;
  155.   { Retry the action. If you return this value, the calling function will
  156.     be forced to be executed once again. }
  157.  
  158.   {#T frXXX}
  159.   {#X frOk}{#X frRetry}
  160.   { The frXXX constants are used in connection with the #DefaultErrorProc#
  161.     function. They determine the behaviour that should be followed after
  162.     an EnhDOS function results an error. In such case, the standard error
  163.     handler function is called and its result code is used to determine
  164.     if a function should terminate normally, or it is supposed to retry
  165.     the action.
  166.  
  167.     The DefaultErrorProc function executes once an error is occured. You
  168.     should check calling function number that caused an error that is passed
  169.     in an argument, and return one of the frXXX constants.
  170.  
  171.     See: #fnXXX#-constants (function codes)
  172.   }
  173.  
  174.   {#T DefaultErrorProc}
  175.   {#X frXXX}{#X TErrorFunc}
  176.   { This is standard error handler function that is called whenever error
  177.     occurs in one of the EnhDOS routines. You may set your own error handler
  178.     by using the #SetErrorHandler# procedure }
  179.  
  180.   fnGetDPB         = $3200;
  181.   fnDiskSize       = $3600;
  182.   fnDiskFree       = $3601;
  183.   fnGetCountryInfo = $3800;
  184.   fnSetDate        = $2B00;
  185.   fnSetTime        = $2D00;
  186.   fnCreateDir      = $3900;
  187.   fnRemoveDir      = $3A00;
  188.   fnGetCurDir      = $4700;
  189.   fnSetCurDir      = $3B00;
  190.   fnDeleteFile     = $4100;
  191.   fnRenameFile     = $5600;
  192.   fnGetFileAttr    = $4300;
  193.   fnSetFileAttr    = $4301;
  194.   fnFindFirst      = $4E00;
  195.   fnFindNext       = $4F00;
  196.   fnCreateFile     = $5B00;
  197.   fnCreateTempFile = $5A00;
  198.   fnOpenFile       = $3D00;
  199.   fnDupHandle      = $4500;
  200.   fnForceDup       = $4600;
  201.   fnRead           = $3F00;
  202.   fnWrite          = $4000;
  203.   fnFlush          = $6800;
  204.   fnLSeek          = $4200;
  205.   fnGetFTime       = $5700;
  206.   fnSetFTime       = $5701;
  207.   fnCloseFile      = $3E00;
  208.   fnDosGetMem      = $4800;
  209.   fnDosFreeMem     = $4900;
  210.   fnDosResize      = $4A00;
  211.  
  212.   {#T fnXXX}
  213.   { fnXXX-constants are function codes that are passed to error handler
  214.     routine when an error occurs in EnhDOS function. This is list of them:
  215.  
  216.     #fnGetDPB#,
  217.     #fnDiskSize#,
  218.     #fnDiskFree#,
  219.     #fnGetCountryInfo#,
  220.     #fnSetDate#,
  221.     #fnSetTime#,
  222.     #fnCreateDir#,
  223.     #fnRemoveDir#,
  224.     #fnGetCurDir#,
  225.     #fnSetCurDir#,
  226.     #fnDeleteFile#,
  227.     #fnRenameFile#,
  228.     #fnGetFileAttr#,
  229.     #fnSetFileAttr#,
  230.     #fnFindFirst#,
  231.     #fnFindNext#,
  232.     #fnCreateFile#,
  233.     #fnCreateTempFile#,
  234.     #fnOpenFile#,
  235.     #fnDupHandle#,
  236.     #fnForceDup#,
  237.     #fnRead#,
  238.     #fnWrite#,
  239.     #fnFlush#,
  240.     #fnSeek#,
  241.     #fnGetFTime#,
  242.     #fnSetFTime#,
  243.     #fnCloseFile#,
  244.     #fnDosGetMem#,
  245.     #fnDosFreeMem#,
  246.     #fnDosResize#
  247.  }
  248.  
  249.   dosrOk                = 0;     { Success }
  250.   dosrInvalidFuncNumber = 1;     { Invalid DOS function number }
  251.   dosrFileNotFound      = 2;     { File not found }
  252.   dosrPathNotFound      = 3;     { Path not found }
  253.   dosrTooManyOpenFiles  = 4;     { Too many open files }
  254.   dosrFileAccessDenied  = 5;     { File access denied }
  255.   dosrInvalidFileHandle = 6;     { Invalid file handle }
  256.   dosrMemCtlBlksKilled  = 7;     { Memory control blocks destroyed }
  257.   dosrNotEnoughMemory   = 8;     { Not enough memory }
  258.   dosrInvalidEnvment    = 10;    { Invalid environment }
  259.   dosrInvalidFormat     = 11;    { Invalid format }
  260.   dosrInvalidAccessCode = 12;    { Invalid file access code }
  261.   dosrInvalidDrive      = 15;    { Invalid drive number }
  262.   dosrCantRemoveDir     = 16;    { Cannot remove current directory }
  263.   dosrCantRenameDrives  = 17;    { Cannot rename across drives }
  264.   dosrNoMoreFiles       = 18;    { No more files }
  265.   dosrFCB29Error        = $FF29; { Fn 29h: Invalid drive ID in filespec }
  266.   dosrFCB11Error        = $FF11; { Fn 11h: No matching files }
  267.  
  268.   {#T dosrXXX}
  269.   { Standard DOS 3.x+ and few custom error codes reported by the #DOSResult#
  270.     variable:
  271.  
  272.     #dosrOk#,
  273.     #dosrInvalidFuncNumber#,
  274.     #dosrFileNotFound#,
  275.     #dosrPathNotFound#,
  276.     #dosrTooManyOpenFiles#,
  277.     #dosrFileAccessDenied#,
  278.     #dosrInvalidFileHandle#,
  279.     #dosrMemCtlBlksKilled#,
  280.     #dosrNotEnoughMemory#,
  281.     #dosrInvalidEnvment#,
  282.     #dosrInvalidFormat#,
  283.     #dosrInvalidAccessCode#,
  284.     #dosrInvalidDrive#,
  285.     #dosrCantRemoveDir#,
  286.     #dosrCantRenameDrives#,
  287.     #dosrNoMoreFiles#,
  288.     #dosrFCB29Error#,
  289.     #dosrFCB11Error#
  290.   }
  291.  
  292. type
  293.  
  294.   TPathStr = array[0..fsPathName] of Char;
  295.   TDirStr  = array[0..fsDirectory] of Char;
  296.   TNameStr = array[0..fsFileName] of Char;
  297.   TExtStr  = array[0..fsExtension] of Char;
  298.   TFileStr = array[0..fsFileSpec] of Char;
  299.  
  300.   PathStr = string[fsPathName];
  301.   DirStr  = string[fsDirectory];
  302.   NameStr = string[fsFileName];
  303.   ExtStr  = string[fsExtension];
  304.   FileStr = string[fsFileSpec];
  305.  
  306.   {#T TDiskParamBlock}
  307.   {#X GetDPB}
  308.  
  309.   PDiskParamBlock = ^TDiskParamBlock;
  310.   TDiskParamBlock = record
  311.     Drive : byte;             { Disk drive number (0=A, 1=B, 2=C...) }
  312.     SubunitNum : byte;        { Sub-unit number from driver device header }
  313.     SectSize : word;          { Number of bytes per sector }
  314.     SectPerClust : byte;      { Number of sectors per cluster -1
  315.                                 (max sector in cluster) }
  316.     ClustToSectShft : byte;   { Cluster-to-sector shift }
  317.     BootSize : word;          { Reserved sectors (boot secs; start of root dir }
  318.     FATCount : byte;          { Number of FATs }
  319.     MaxDir : word;            { Number of directory entries allowed in root }
  320.     DataSect : word;          { Sector number of first data cluster }
  321.     Clusters : word;          { Total number of allocation units (clusters)
  322.                                 +2 (number of highest cluster) }
  323.     FATSectors : byte;        { Sectors needed by first FAT }
  324.     RootSect : word;          { Sector number of start of root directory }
  325.     DeviceHeader : pointer;   { Address of device header }
  326.     Media : byte;             { Media descriptor byte }
  327.     AccessFlag : byte;        { 0 if drive has been accessed, FFh - if not }
  328.     NextPDB : PDiskParamBlock { Address of next DPB (0FFFFh if last) }
  329.   end;
  330.  
  331.   {#T TDiskAllocInfo}
  332.   {#X GetDriveAllocInfo}
  333.  
  334.   PDiskAllocInfo = ^TDiskAllocInfo;
  335.   TDiskAllocInfo = record
  336.     FATId : byte;             { FAT Id }
  337.     Clusters : word;          { Number of allocation units (clusters) }
  338.     SectPerClust : byte;      { Number of sectors per cluster }
  339.     SectSize : word           { Number of bytes per sector }
  340.   end;
  341.  
  342.   {#T TCountryInfo}
  343.   {#X GetCountryInfo}
  344.  
  345.   PCountryInfo = ^TCountryInfo;
  346.   TCountryInfo = record
  347.     DateFormat : word; { Date format value may be one of the following:
  348.                          0 - Month, Day, Year     (USA)
  349.                          1 - Day, Month, Year     (Europe)
  350.                          2 - Year, Month, Day     (Japan)}
  351.  
  352.     CurrencySymbol : array[0..4] of Char; { Currency symbol string }
  353.     ThousandsChar : char; { Thousands separator character }
  354.     reserved1 : byte;
  355.     DecimalChar : char;   { Decimal separator character }
  356.     reserved2 : byte;
  357.     DateChar : char;      { Date separator character }
  358.     reserved3 : byte;
  359.     TimeChar : char;      { Time separator character }
  360.     reserved4 : byte;
  361.     CurrencyFormat : byte; { Currency format: $XXX.XX, XXX.XX$, $ XXX.XX,
  362.                              XXX.XX $, XXX$XX }
  363.     Digits : byte;          { Number of digits after decimal in currency }
  364.     TimeFormat : boolean;   { Time format can be one of the following:
  365.                               bit 0 = 0 if 12 hour clock, bit 1 if 24 hour clock }
  366.     MapRoutine : pointer;   { Address of case map routine FAR CALL, AL -
  367.                               character to map to upper case [>=80h] }
  368.     DataListChar : char;    { Data-list separator character }
  369.     reserved5 : byte;
  370.     reserved6 : array[1..10] of Char
  371.   end;
  372.  
  373.   THandle = Word; { Handle type (file handle and memory handle functions) }
  374.  
  375.   TErrorFunc = function(ErrCode : integer; FuncCode : word) : byte;
  376.   { Error handler function }
  377.  
  378.   TSearchRec = record
  379.     Fill : array[1..21] of Byte;
  380.     Attr : byte;
  381.     Time : longint;
  382.     Size : longint;
  383.     Name : TFileStr
  384.   end;
  385.  
  386.   SearchRec = record
  387.     Fill : array[1..21] of Byte;
  388.     Attr : byte;
  389.     Time : longint;
  390.     Size : longint;
  391.     Name : FileStr
  392.   end;
  393.  
  394.   { Search record used by #FindFirst# and #FindNext# functions }
  395.  
  396.   TDateTime = record
  397.     Year,
  398.     Month,
  399.     Day,
  400.     Hour,
  401.     Min,
  402.     Sec : word
  403.   end;
  404.   DateTime = TDateTime;
  405.  
  406.   { Date and time record used by #PackTime# and #UnpackTime# functions }
  407.  
  408. var
  409.   DOSResult : integer; { Error status variable }
  410.   TempStr : array[0..High(String)] of Char; { Temporary PChar-type string }
  411.  
  412. function SetErrorHandler(Handler : TErrorFunc) : pointer;
  413. { This procedure allows you to set your own error handling routine. This will
  414.   allow you to behave specifically depending in which function and what type
  415.   of error has occured. This function returns a pointer to a previous
  416.   ErrorHandler routine. Basically, this function is called in the unit's
  417.   initialisation part in order to set standard error handler. }
  418. {#X frXXX}{#X DefaultErrorProc}
  419.  
  420. function Pas2PChar(Str : string) : PChar;
  421. { This function converts Pascal-type string to a PChar-null terminated string
  422.   and returns a pointer to it. It is internally used by EnhDOS, however, you
  423.   may also use it in your own programs. }
  424.  
  425. {$IFDEF P386}
  426. {$IFOPT G+}
  427. procedure Move32(var Source, Dest; Count : word);
  428. { This function is internally used by EnhDOS, however, you may also use it in
  429.   your programs. It copies bytes from Source to Dest like Move, but it is
  430.   faster than Move or Move16. Warning: this function will work on a 386
  431.   or better. }
  432. {#X Move16}
  433. {$ENDIF}
  434. {$ENDIF}
  435.  
  436. procedure Move16(var Source, Dest; Count : word);
  437. { This function is internally used by EnhDOS, however, you may also use it in
  438.   your programs. It copies bytes from Source to Dest like Move, but it is
  439.   faster than Move. }
  440. {#X Move32}
  441.  
  442. function GetInDOSFlag : boolean;
  443. { Returns True if a DOS operation is being executed, False if DOS is not
  444.   currently busy running an interrupt. This function is often used in TSRs. }
  445.  
  446. function GetDOSVersion : word;
  447. { Returns the DOS version number. The result's low byte is the major version
  448.   number, and the high byte is the minor version number. }
  449.  
  450. function GetSwitchChar : char;
  451. { Queries the DOS global "switch character". The SWITCHAR is the character
  452.   found on a command line that delimits the start of a switch or option.
  453.   The default is '/' (eg, DIR /w/p), but you can change the switchar to
  454.   '-' (eg DIR -w-p) to give your system a more UNIX-like feel.
  455.  
  456.   Warning:
  457.   This undocumented command may change in future versions of DOS. It is
  458.   recommended that you do NOT change the switchar because many programs don't
  459.   use it when they parse command lines. }
  460. {#X SetSwitchChar}
  461.  
  462. function SetSwitchChar(Switch : char) : char;
  463. { Sets the DOS global "switch character" and returns the old value of
  464.   SWITCHAR. The SWITCHAR is the character found on a command line that
  465.   delimits the start of a switch or option.  The default is '/'
  466.   (eg, DIR /w/p), but you can change the switchar to '-' (eg DIR -w-p)
  467.   to give your system a more UNIX-like feel.
  468.  
  469.   Warning: This undocumented command may change in future versions of DOS.
  470.   It is recommended that you do NOT change the switchar because many programs
  471.   don't use it when they parse command lines. }
  472. {#X GetSwitchChar}
  473.  
  474. function GetCountryInfo(var Buffer : TCountryInfo) : integer;
  475. { Fills the Buffer with the country-dependant information. Returns:
  476.   country-code if successful, negative DOS error code otherwise. }
  477.  
  478. procedure GetDate(var Year, Month, Day, DayOfWeek : word);
  479. { Returns the current date set in the operating system. Ranges of the values
  480.   returned are Year 1980..2099, Month 1..12, Day 1..31, and DayOfWeek 0..6
  481.   (where 0 corresponds to Sunday). }
  482. {#X SetDate}{#X SetTime}{#X GetTime}
  483.  
  484. function SetDate(Year, Month, Day : word) : boolean;
  485. { Sets the current date set in the operating system. Ranges of the values
  486.   returned are Year 1980..2099, Month 1..12, Day 1..31, and DayOfWeek 0..6
  487.   (where 0 corresponds to Sunday).
  488.  
  489.   Returns: True if new date set, False if unable to set new date. }
  490. {#X GetDate}{#X SetTime}{#X GetTime}
  491.  
  492. procedure GetTime(var Hour, Minute, Second, Sec100 : word);
  493. { Returns the current time set in the operating system. Ranges of the values
  494.   returned are Hour 0..23, Minute 0..59, Second 0..59, and Sec100
  495.   (hundredths of seconds) 0..99. }
  496. {#X SetDate}{#X GetDate}{#X SetTime}
  497.  
  498. function SetTime(Hour, Minute, Second, Sec100 : word) : boolean;
  499. { Sets the current time set in the operating system. Ranges of the values
  500.   returned are Hour 0..23, Minute 0..59, Second 0..59, and Sec100
  501.   (hundredths of seconds) 0..99.
  502.  
  503.   Returns: True if new time set, False if unable to set new time. }
  504. {#X SetDate}{#X GetDate}{#X GetTime}
  505.  
  506. function GetCBreak : boolean;
  507. { Returns the state of Ctrl-Break checking in DOS. SetCBreak sets the value
  508.   of Break depending on the state of Ctrl+Break checking in DOS. When off,
  509.   DOS only checks for Ctrl+Break during I/O to console, printer, or
  510.   communication devices. When on, checks are made at every system call. }
  511. {#X SetCBreak}
  512.  
  513. function SetCBreak(Break : boolean) : boolean;
  514. { Sets the state of Ctrl-Break checking in DOS. SetCBreak sets the value
  515.   of Break depending on the state of Ctrl+Break checking in DOS. When off,
  516.   DOS only checks for Ctrl+Break during I/O to console, printer, or
  517.   communication devices. When on, checks are made at every system call.
  518.  
  519.   Retuns: Old state of Ctrl-Break checking }
  520. {#X GetCBreak}
  521.  
  522. function GetVerify : boolean;
  523. { Returns the state of the verify flag in DOS. GetVerify returns the state of
  524.   the verify flag in DOS. When off, disk writes are not verified. When on,
  525.   all disk writes are verified to ensure proper writing. }
  526. {#X SetVerify}
  527.  
  528. function SetVerify(Verify : boolean) : boolean;
  529. { Sets the state of the verify flag in DOS. SetVerify sets the state of the
  530.   verify flag in DOS. When off, disk writes are not verified. When on, DOS
  531.   verifies all disk writes to ensure proper writing.
  532.  
  533.   Returns: Old state of verify flag }
  534. {#X GetVerify}
  535.  
  536. function GetArgCount : integer;
  537. { Returns the number of parameters passed to the program on the command line. }
  538. {#X GetArgStr}
  539.  
  540. function GetArgStr(Dest : PChar; Index : integer; MaxLen : word) : PChar;
  541. { Returns the command-line parameter specified by Index. Returns empty string
  542.   if Index is less than 0 or greater than GetArgCount. Returns the filename
  543.   of current module if Index = 0. Dest = returned value. }
  544. {#X GetArgCount}
  545.  
  546. function GetEnvVar(VarName : PChar) : PChar;
  547. { Returns a pointer to the value of a specified environment variable or
  548.   zero if specified environment variable does not exist. }
  549. {#X GetEnv}
  550.  
  551. function GetEnv(EnvVar : string) : string;
  552. { Returns the value of a specified environment variable. Acts the same like
  553.   GetEnvVar, except that it takes a Pascal-style string rather than a PChar
  554.   null-terminated string. }
  555. {#X GetEnvVar}
  556.  
  557. function GetIntVec(IntNo : byte; var Vector : pointer) : pointer;
  558. { Returns the address stored in a specified interrupt vector. IntNo specifies
  559.   the interrupt vector number (0..255), and the address is returned in Vector.
  560.   Note: this routine uses DOS function 35h = GetInterruptVector. }
  561. {#X SetIntVec}
  562.  
  563. function SetIntVec(IntNo : byte; Vector : pointer) : pointer;
  564. { Sets a specified interrupt vector to a specified address. IntNo specifies
  565.   the interrupt vector number (0..255), and Vector specifies the address.
  566.   Returns: An old address of a specified interrupt vector.
  567.   Note: this routine uses DOS function 25h = SetInterruptVector. }
  568. {#X GetIntVec}
  569.  
  570. function GetDTA : pointer;
  571. { Returns a pointer address to a DOS data exchange buffer (DTA). By default,
  572.   DTA address has the offset PrefixSeg+$80 and the size of 128 bytes. DTA can
  573.   be also used to access files with the FCB method. }
  574. {#X SetDTA}
  575.  
  576. procedure SetDTA(NewDTA : pointer);
  577. { Sets the Disk Transfer Address pointer to a new DTA buffer. }
  578. {#X GetDTA}
  579.  
  580. function GetCurDisk : byte;
  581. { Returns the drive number of the current DOS default disk. }
  582. {#X SetCurDisk}
  583.  
  584. function SetCurDisk(Drive : byte) : byte;
  585. { The specified drive becomes the current DOS default drive. The return value
  586.   is number of drives of any type, including hard disks and 'logical' drives
  587.   (such as drive B: in a 1-floppy system). }
  588. {#X GetCurDisk}
  589.  
  590. procedure GetDriveAllocInfo(Drive : byte; var Info : TDiskAllocInfo);
  591. { Fills the Info record with the information on size and type of the
  592.   specified drive. }
  593.  
  594. function GetDPB(Drive : byte; var DPB : TDiskParamBlock) : integer;
  595. { Retrieves a block of information that is useful for applications which
  596.   perform sector-level access of disk drives supported by device drivers.
  597.   Returns: 0 if successful, negative #dosrInvalidDrive# error code when
  598.   an error occured. }
  599.  
  600. function DiskSize(Drive : byte) : longint;
  601. { Returns the total size, in bytes, of a specified disk drive if successful;
  602.   negative #dosrInvalidDrive# error code, otherwise. }
  603. {#X DiskFree }
  604.  
  605. function DiskFree(Drive : byte) : longint;
  606. { Returns the number of free bytes on a specified disk drive if successful;
  607.   negative #dosrInvalidDrive# error code, otherwise. }
  608. {#X DiskSize}
  609.  
  610. function CreateDir(Dir : PChar) : integer;
  611. { Creates a new subdirectory. Performs the same function as #MkDir#, but uses
  612.   a null-terminated string rather than a Pascal-style string. Returns zero if
  613.   successful, negative DOS error code, otherwise. }
  614. {#X GetCurDir}{#X RemoveDir}{#X SetCurDir}{#X MkDir}
  615.  
  616. function MkDir(Dir : DirStr) : integer;
  617. { Creates a new subdirectory with the path specified by string Dir. The last
  618.  item in the path cannot be an existing file name. #CreateDir# calls this
  619.  function and then converts Dir to a null-terminated string. Returns zero
  620.  if successful, otherwise, negative DOS error code. }
  621. {#X GetDir}{#X RmDir}{#X ChDir}{#X CreateDir}
  622.  
  623. function RemoveDir(Dir : PChar) : integer;
  624. { Removes an empty subdirectory. The subdirectory with the path specified by
  625.   Dir is removed. Errors, such as a non-existing or non-empty subdirectory,
  626.   are reported in the #DOSResult# variable, and negative DOS error value is
  627.   returned. }
  628. {#X GetCurDir}{#X CreateDir}{#X SetCurDir}{#X RmDir}
  629.  
  630. function RmDir(Dir : DirStr) : integer;
  631. { Removes an empty subdirectory. Removes the subdirectory with the path
  632.   specified by Dir. If the path does not exist, is non-empty, or is the
  633.   currently logged directory, #DOSResult# will contain DOS error code,
  634.   and negative DOS error code will be returned. }
  635. {#X GetDir}{#X MkDir}{#X ChDir}{#X RemoveDir}
  636.  
  637. function GetCurDir(Drive : byte; Dir : PChar) : integer;
  638. { Returns the current directory of a specified drive. Where 0 is default
  639.   drive, 1 is drive A, 2 is drive B, 3 is drive C and so on. }
  640. {#X CreateDir}{#X RemoveDir}{#X SetCurDir}{#X GetDir}
  641.  
  642. function GetDir(Drive : byte; var Dir : DirStr) : integer;
  643. { Returns the current directory of a specified drive. Where 0 is default
  644.   drive, 1 is drive A, 2 is drive B, 3 is drive C and so on. }
  645. {#X MkDir}{#X RmDir}{#X ChDir}{#X GetCurDir}
  646.  
  647. function SetCurDir(Dir : PChar) : integer;
  648. { Changes the current directory to the specified path. If Dir specifies a
  649.   drive letter, the drive is also changed. }
  650. {#X GetCurDir}{#X CreateDir}{#X RemoveDir}{#X ChDir}
  651.  
  652. function ChDir(Dir : DirStr) : integer;
  653. { Changes the current directory. Function and #DOSResult# return 0 if the
  654.   operation was successful; otherwise, function returns a negative error
  655.   code and DOS error code is stored in DOSResult variable. If Dir specifies
  656.   a drive letter, the drive is also changed. }
  657. {#X GetDir}{#X MkDir}{#X RmDir}{#X SetCurDir}
  658.  
  659. function DeleteFile(Path : PChar) : integer;
  660. { Deletes the file specified in Path. Returns zero if the operation was
  661.   successful; otherwise, returns a negative error code. #DOSResult# variable
  662.   holds DOS result code. }
  663. {#X RenameFile}{#X ExistsFile}{#X DeleteFile_}
  664.  
  665. function DeleteFile_(Path : PathStr) : integer;
  666. { Deletes the file specified in Path. Returns zero if the operation was
  667.   successful; otherwise, returns a negative error code. #DOSResult# variable
  668.   holds DOS result code. It performs the same function as DeleteFile, except
  669.   that it takes Pascal-type string as an argument, instead of PChar
  670.   null-terminated string. }
  671. {#X RenameFile_}{#X ExistsFile_}{#X DeleteFile}
  672.  
  673. function RenameFile(OldPath, NewPath : PChar) : integer;
  674. { Renames an external file. The external file specified in OldPath is renamed
  675.   to NewPath. If both files are on the same disk, a file will be moved to a
  676.   directory specified in NewPath. RenameFile returns 0 if the function was
  677.   successful; otherwise, it returns negative DOS error code and #DOSResult#
  678.   variable always holds DOS result code. }
  679. {#X DeleteFile}{#X ExistsFile}{#X RenameFile_}
  680.  
  681. function RenameFile_(OldPath, NewPath : PathStr) : integer;
  682. { Renames an external file. The external file specified in OldPath is renamed
  683.   to NewPath. If both files are on the same disk, a file will be moved to a
  684.   directory specified in NewPath. RenameFile_ returns 0 if the function was
  685.   successful; otherwise, it returns negative DOS error code and #DOSResult#
  686.   variable always holds DOS result code. }
  687. {#X DeleteFile_}{#X ExistsFile_}{#X RenameFile}
  688.  
  689. function ExistsFile(Path : PChar) : boolean;
  690. { Returns True if the file specified in Path exists; otherwise, it returns
  691.   False. }
  692. {#X DeleteFile}{#X RenameFile}{#X ExistsFile_}
  693.  
  694. function ExistsFile_(Path : PathStr) : boolean;
  695. { Returns True if the file specified in Path exists; otherwise, this function
  696.   returns False. }
  697. {#X DeleteFile_}{#X RenameFile_}{#X ExistsFile}
  698.  
  699. function GetFileAttr(Path : PChar) : integer;
  700. { Returns the attributes of a file or negative DOS error code if unable
  701.   to retrieve the file attributes. #DOSResult# contains DOS operation result
  702.   code. }
  703. {#X SetFileAttr}{#X GetFAttr}{#X SetFAttr}{#X faXXX}
  704.  
  705. function GetFAttr(Path : PathStr) : integer;
  706. { Returns the attributes of a file or negative DOS error code if unable
  707.   to retrieve the file attributes. #DOSResult# contains DOS operation result
  708.   code. }
  709. {#X SetFAttr}{#X GetFileAttr}{#X SetFileAttr}{#X faXXX}
  710.  
  711. function SetFileAttr(Path : PChar; Attr : word) : integer;
  712. { Sets the attributes of a file and returns zero if operation was successful,
  713.   or negative DOS error code in case of error. #DOSResult# holds DOS result
  714.   code. }
  715. {#X GetFileAttr}{#X GetFAttr}{#X SetFAttr}{#X faXXX}
  716.  
  717. function SetFAttr(Path : PathStr; Attr : word) : integer;
  718. { Sets the attributes of a file and returns zero if operation was successful,
  719.   or negative DOS error code in case of error. #DOSResult# holds DOS result
  720.   code. }
  721. {#X GetFAttr}{#X GetFileAttr}{#X SetFileAttr}{#X faXXX}
  722.  
  723. function FindFirst(Path : PChar; Attr: word; var F : TSearchRec) : integer;
  724. { Searches the specified directory for the matching file. FindFirst searches
  725.   the specified (or current) directory for the first entry matching the
  726.   specified file name and set of attributes. This function returns #dosrOk#
  727.   if the call was successful; otherwise, it returns a negative error code.
  728.   #DOSResult# variable holds DOS result code anyway.}
  729. {#X FindNext}{#X FindFirst_}
  730.  
  731. function FindNext(var F : TSearchRec) : integer;
  732. { Finds the next entry that matches the name and attributes specified in an
  733.   earlier call to FindFirst. This function returns #dosrOk# if the call was
  734.   successful; otherwise, it returns a negative error code. You can also
  735.   check #DOSResult# variable for DOS result code. }
  736. {#X FindFirst}{#X FindNext_}
  737.  
  738. function FindFirst_(Path : PathStr; Attr: word; var F : SearchRec) : integer;
  739. { Searches the specified directory for the matching file. FindFirst_
  740.   searches the specified (or current) directory for the first entry matching
  741.   the specified file name and set of attributes. FindFirst_ acts much like
  742.   FindFirst function, except that it works with pascal-style strings rather
  743.   than with PChar-type strings. }
  744. {#X FindNext_}{#X FindFirst}
  745.  
  746. function FindNext_(var F : SearchRec) : integer;
  747. { Finds the next entry that matches the name and attributes specified in an
  748.   earlier call to FindFirst_. FindNextP acts the same as FindNext, except
  749.   that it works with Pascal-type strings rather than with null-terminated
  750.   PChar-type strings. }
  751. {#X FindFirst_}{#X FindNext}
  752.  
  753. procedure UnpackTime(P : longint; var T : TDateTime);
  754. { Converts a 4-byte, packed date-and-time Longint returned by GetFTime,
  755.   FindFirst, or FindNext into an unpacked #TDateTime# record. }
  756. {#X GetFTime}{#X PackTime}{#X h_SetFTime}
  757.  
  758. function PackTime(var T : TDateTime) : longint;
  759. { Converts a TDateTime record into a 4-byte packed date/time used by
  760.   SetFTime. Returns a 4-byte long integer corresponding to packed date/time. }
  761. {#X GetFTime}{#X SetFTime}{#X UnpackTime}
  762.  
  763.  
  764. function h_CreateFile(Path : PChar) : THandle;
  765. { Creates an external file and returns it's handle. This function returns
  766.   zero and #DOSResult# holds a non-zero DOS error code if failed to create a
  767.   file. }
  768. {#X h_CreateTempFile}{#X h_OpenFile}{#X h_DupeHandle}{#X h_ForceDup}
  769. {#X h_Read}{#X h_Write}{#X h_Flush}{#X h_LSeek}{#X h_FilePos}{#X h_FileSize}
  770. {#X h_Eof}{#X h_GetFTime}{#X h_SetFTime}{#X h_CloseFile}{#X h_CreateFile_}
  771.  
  772. function h_CreateFile_(Path : PathStr) : THandle;
  773. { Creates an external file and returns it's handle. This function returns
  774.   zero and #DOSResult# holds a non-zero DOS error code if failed to create
  775.   a file. h_CreateFile_ performs the same action as h_CreateFile except
  776.   that it takes a Pascal-type string rather than a null-terminated PChar-type
  777.   string. }
  778. {#X h_CreateTempFile_}{#X h_OpenFile_}{#X h_DupeHandle}{#X h_ForceDup}
  779. {#X h_Read}{#X h_Write}{#X h_Flush}{#X h_LSeek}{#X h_FilePos}{#X h_FileSize}
  780. {#X h_Eof}{#X h_GetFTime}{#X h_SetFTime}{#X h_CloseFile}{#X h_CreateFile}
  781.  
  782. function h_CreateTempFile(Path : PChar) : THandle;
  783. { Calls DOS function to create an external temporary file and assign a
  784.   uniquie name to it. You should specify a path *without* filename. The
  785.   h_CreateTempFile function returns zero and #DOSResult# holds a non-zero
  786.   DOS error code if failed to create a file; otherwise, it returns a file
  787.   handle. }
  788. {#X h_CreateFile}{#X h_OpenFile}{#X h_DupeHandle}{#X h_ForceDup}
  789. {#X h_Read}{#X h_Write}{#X h_Flush}{#X h_LSeek}{#X h_FilePos}{#X h_FileSize}
  790. {#X h_Eof}{#X h_GetFTime}{#X h_SetFTime}{#X h_CloseFile}
  791. {#X h_CreateTempFile_}
  792.  
  793. function h_CreateTempFile_(Path : PathStr) : THandle;
  794. { Calls DOS function to create an external temporary file and assign a
  795.   uniquie name to it. You should specify a path *without* filename. The
  796.   h_CreateTempFile_ function returns zero and #DOSResult# holds a non-zero
  797.   DOS error code if failed to create a file; otherwise, it returns a file
  798.   handle. It performs the same action as h_CreateFile except that it takes
  799.   a Pascal-type string instead of a null-terminated PChar-type string. }
  800. {#X h_CreateFile_}{#X h_OpenFile_}{#X h_DupeHandle}{#X h_ForceDup}
  801. {#X h_Read}{#X h_Write}{#X h_Flush}{#X h_LSeek}{#X h_FilePos}{#X h_FileSize}
  802. {#X h_Eof}{#X h_GetFTime}{#X h_SetFTime}{#X h_CloseFile}{#X h_CreateTempFile}
  803.  
  804. function h_OpenFile(Path : PChar; Mode : byte) : THandle;
  805. { Opens an existing external file and returns it's handle if the call was
  806.   successful; otherwise, h_OpenFile returns zero and #DOSResult# holds a
  807.   non-zero DOS error code. Mode must be a combination of omXXX constants. }
  808. {#X omXXX}{#X h_CreateFile}{#X h_CreateTempFile}{#X h_DupeHandle}
  809. {#X h_ForceDup}{#X h_Read}{#X h_Write}{#X h_Flush}{#X h_LSeek}{#X h_FilePos}
  810. {#X h_FileSize}{#X h_Eof}{#X h_GetFTime}{#X h_SetFTime}{#X h_CloseFile}
  811. {#X h_OpenFile_}
  812.  
  813. function h_OpenFile_(Path : PathStr; Mode : byte) : THandle;
  814. { Opens an existing external file and returns it's handle if the call was
  815.   successful; otherwise, h_OpenFile_ returns zero and #DOSResult# contains a
  816.   non-zero DOS error code. Mode must be a combination of omXXX constants.
  817.   h_OpenFile_ performs the same action as h_OpenFile except that it takes
  818.   a Pascal-type string rather than a null-terminated PChar-type string. }
  819. {#X omXXX}{#X h_CreateFile_}{#X h_CreateTempFile_}{#X h_DupeHandle}
  820. {#X h_ForceDup}{#X h_Read}{#X h_Write}{#X h_Flush}{#X h_LSeek}{#X h_FilePos}
  821. {#X h_FileSize}{#X h_Eof}{#X h_GetFTime}{#X h_SetFTime}{#X h_CloseFile}
  822. {#X h_OpenFile}
  823.  
  824. function h_DupHandle(Handle : THandle) : THandle;
  825. { Creates an additional file handle that refers to the same I/O stream as an
  826.   existing file handle. Returns new file handle that duplicates the original
  827.   or negative DOS error code if the DupeHandle call failed. You may also check
  828.   the #DOSResult# variable for a non-zero DOS error code or handle errors
  829.   in this function via your own error-handler. }
  830. {#X h_ForceDup}{#X h_CreateFile}{#X h_CreateTempFile}{#X h_OpenFile}
  831. {#X h_CloseFile}
  832.  
  833. function h_ForceDup(Source, Dest : THandle) : integer;
  834. { Forces a file handle to refer to a different file or device. The Source
  835.   file handle is closed (if currently open) and then made to become a
  836.   duplicate of the Dest handle. All accesses from the Source handle file
  837.   will go to or come from the Dest handle file. You can use this function
  838.   to redirect standard I/O. Returns: 0 if successful; negative DOS error
  839.   code, otherwise. You may also check the #DOSResult# variable for a non-zero
  840.   DOS error code or handle errors in this function via your own error-handler. }
  841. {#X h_DupHandle}{#X h_CreateFile}{#X h_CreateTempFile}{#X h_OpenFile}
  842. {#X h_CloseFile}
  843.  
  844. function h_Read(Handle : THandle; var Buffer; Count : word) : word;
  845. { Reads a memory block from file and returns actual number of bytes being
  846.   read. h_Read returns 0 if there was a read fault error; in this case
  847.   #DOSResult# variable must contain a non-zero DOS error code. You may also
  848.   handle errors in this function via your own error-handler. }
  849. {#X h_Write}{#X h_CreateFile}{#X h_CreateTempFile}{#X h_OpenFile}
  850. {#X h_CloseFile}
  851.  
  852. function h_Write(Handle : THandle; var Buffer; Count : word) : word;
  853. { Writes a memory block to file and returns actual number of bytes being
  854.   written. h_Write returns zero or less than Count if there was a write
  855.   fault error; in such case #DOSResult# variable will contain a non-zero
  856.   DOS error code. You may also handle errors in this function via your own
  857.   error-handler. }
  858. {#X h_Read}{#X h_CreateFile}{#X h_CreateTempFile}{#X h_OpenFile}
  859. {#X h_CloseFile}{#X h_Flush}
  860.  
  861. function h_Flush(Handle : THandle) : integer;
  862. { Forces DOS to flush its RAM buffers of file data for the selected file
  863.   handle. Zero is returned if operation successful; negative DOS error code,
  864.   otherwise. You may also handle errors in this function via your own
  865.   error-handler. }
  866. {#X h_Write}
  867.  
  868. function h_LSeek(Handle : THandle; SeekPos : longint; Start : byte) : longint;
  869. { Seeks to a specified file position (a 32-bit offset relative to the
  870.   Start) and sets a file pointer to a new location. Start must be one of the
  871.   #skXXX#-constants and must point to a relative file offset position. For
  872.   example, the statement h_LSeek(F, 0, skEnd) moves the current file pointer
  873.   to the end of a file. h_LSeek returns a new file position if operation
  874.   successful; #DOSResult# will contain an error code, if seek failed. You may
  875.   also handle errors in this function via your own error-handler. }
  876. {#X h_FilePos}{#X h_FileSize}{#X h_Eof}
  877.  
  878. function h_FilePos(Handle : THandle) : longint;
  879. { Returns current position of file pointer. If the current file position is
  880.   at the beginning of the file, h_FilePos(Handle) returns 0. If the current file
  881.   position is at the end of the file--that is, if h_Eof(Handle) is True--
  882.   h_FilePos(Handle) is equal to h_FileSize(Handle). #DOSResult# will contain
  883.   a non-zero DOS error code if this operation fails. }
  884. {#X h_LSeek}{#X h_FileSize}{#X h_Eof}
  885.  
  886. function h_FileSize(Handle : THandle) : longint;
  887. { Returns the current size of a file. If the file is empty, h_FileSize returns
  888.   zero. #DOSResult# returns #dosrOk# if operation successful; otherwise, it
  889.   returns a non-zero DOS error code. }
  890. {#X h_LSeek}{#X h_FilePos}{#X h_Eof}
  891.  
  892. function h_Eof(Handle : THandle) : boolean;
  893. { Returns the end-of-file status. If h_FilePos(Handle) is equal to
  894.   h_FileSize(Handle), h_Eof returns True; otherwise, it returns False. }
  895. {#X h_LSeek}{#X h_FilePos}{#X h_FileSize}
  896.  
  897. function h_GetFTime(Handle : THandle) : longint;
  898. { Returns the date and time a file was last written. The time returned can
  899.   be unpacked through a call to UnpackTime. Returns negative DOS error code
  900.   if failed to retrieve date/time. }
  901. {#X h_SetFTime}{#X PackTime}{#X UnpackTime}
  902.  
  903. function h_SetFTime(Handle : THandle; DateTime : longint) : longint;
  904. { Sets the date and time a file was last written. Errors are reported in
  905.   #DOSResult#. The only error code is #dosrInvalidFileHandle#.
  906.   Returns: New date and time of a file if all was successful; otherwise,
  907.   returns a negative DOS error code. }
  908. {#X h_GetFTime}{#X PackTime}{#X UnpackTime}
  909.  
  910. function h_CloseFile(Handle : THandle) : integer;
  911. { Closes an open file. The external file associated with Handle is completely
  912.   updated and then closed, freeing its DOS file handle for reuse. This
  913.   function must return #dosrOk# if the operation was successful; otherwise,
  914.   it returns a negative DOS error code. Errors are also reported in
  915.   #DOSResult#. }
  916. {#X h_CreateFile}{#X h_CreateFile_}{#X h_CreateTempFile}
  917. {#X h_CreateTempFile_}{#X h_OpenFile}{#X h_OpenFile_}
  918.  
  919. function DosMaxAvail : longint;
  920. { Returns the size of the largest contiguous free memory block in the DOS
  921.   heap. The value corresponds to the size of the largest dynamic variable
  922.   that can be allocated at that time. If you use this function in real mode,
  923.   the HeapMin and HeapMax allocation parameters of the $M directive must
  924.   be both set to 0. }
  925. {#X DosGetMem}{#X DosResize}{#X DosFreeMem}
  926.  
  927. function DosGetMem(Size : longint) : pointer;
  928. { Creates a dynamic variable of the specified size and returns a pointer
  929.   to the allocated memory block if operation successful, or nil if DOS
  930.   failed to allocate memory. This function uses MCB technique to deal
  931.   with memory. Note, that DosGetMem in comparison with Borland GetMem
  932.   can allocate more than 64k at once; then your pointer will reside in
  933.   different segments. However, this function is slower than Borland GetMem,
  934.   and you must care about HeapMin/HeapMax parameters of the $M directive:
  935.   they both must be set to 0 if you wish to use this function in real mode.
  936.   Errors are reported in #DOSResult# variable. Call DosFreeMem to free
  937.   the memory block when you finished to work with it. }
  938. {#X DosMaxAvail}{#X DosResize}{#X DosFreeMem}
  939.  
  940. function DosFreeMem(P : pointer) : integer;
  941. { Disposes of a dynamic variable of a given size. P is a variable of any
  942.   pointer type previously assigned by the DosGetMem or DosResize procedures.
  943.   DosFreeMem destroys the MCB referenced by P and returns its memory region
  944.   to the DOS heap. If P does not point to a memory region in the DOS heap,
  945.   an error occurs. After a call to DosFreeMem, the value of P becomes
  946.   undefined, and may result unpredictable if you continue referencing P^.
  947.   In real mode, the HeapMin and HeapMax parameters of the $M compiler
  948.   directive must be set to zero in order this function to work properly.
  949.   Errors are reported in #DOSResult# variable, also this function returns
  950.   a negative DOS error code if DOS fails to free allocated memory block. }
  951. {#X DosMaxAvail}{#X DosGetMem}{#X DosResize}
  952.  
  953. function DosResize(P : pointer; NewSize : longint) : pointer;
  954. { Changes the size of a memory block referenced by P. You may always call
  955.   this function to resize the block previously allocated with DosGetMem. In
  956.   real mode, the HeapMin and HeapMax parameters of the $M compiler directive
  957.   must be set to zero in order DosRezize to function properly. This function
  958.   returns a pointer to resized memory block, or nil if operation fails.
  959.   DOS errors are reported in #DOSResult# variable. }
  960. {#X DosMaxAvail}{#X DosGetMem}{#X DosFreeMem}
  961.  
  962. {$IFNDEF ProtectedMode}
  963. procedure Keep(ExitCode : byte; Size : longint);
  964. { Keep (or Terminate Stay Resident) terminates the program and makes it stay
  965.   in memory. }
  966. {$ENDIF}
  967.  
  968. {$IFNDEF Windows}
  969. procedure StdOutText(Str : PChar);
  970. { Calls DOS function 40h to write a text string on standard output device. }
  971. {#X StdOutTextLF}{#X StdInpText}{#X StdOutText_}
  972.  
  973. procedure StdOutTextLF(Str : PChar);
  974. { Calls StdOutText function to write a text string on standard output device,
  975.   then outputs an end-of-line marker. }
  976. {#X StdOutText}{#X StdInpText}{#X StdOutTextLF_}
  977.  
  978. procedure StdOutText_(const Str : string);
  979. { Calls StdOutText to output a text string on the standard output device.
  980.   Difference between StdOutText_ and StdOutText is that StdOutText_ takes
  981.   a Pascal-type string as an argument rather than a null-terminated string. }
  982. {#X StdOutTextLF_}{#X StdInpText_}{#X StdOutText}
  983.  
  984. procedure StdOutTextLF_(const Str : string);
  985. { Calls StdOutText_ to output a text string on the standard output device,
  986.   then prints an end-of-line marker. Acts the same like StdOutTextLF, but
  987.   takes a Pascal-type string as an argument rather than a null-terminated
  988.   PChar-string. }
  989. {#X StdOutText_}{#X StdInpText_}{#X StdOutTextLF}
  990.  
  991. procedure StdInpText(Str : PChar; MaxLength : byte);
  992. { Calls StdInpText_ to perform buffered string input from the standard
  993.   input device. Characters are read from the standard input up to a CR
  994.   (ASCII #13) or up to the value of MaxLength.  If MaxLength is reached,
  995.   the console bell rings (beeps) for each character until Enter (CR) is read.
  996.   Note: This function doesn't move to a new line like ReadLn after input. }
  997. {#X StdOutText}{#X StdOutTextLF}{#X StdInpText_}
  998.  
  999. procedure StdInpText_(var Str : string; MaxLength : byte);
  1000. { Calls DOS function 0Ah to perform buffered string input from the standard
  1001.   input device. Characters are read from the standard input up to a CR
  1002.   (ASCII #13) or up to the value of MaxLength.  If MaxLength is reached,
  1003.   the console bell rings (beeps) for each character until Enter (CR) is read.
  1004.   Note: This function doesn't move to a new line like ReadLn after input. }
  1005. {#X StdOutText_}{#X StdOutTextLF_}{#X StdInpText}
  1006.  
  1007. {$ENDIF}
  1008.  
  1009. function FileSearch(Dest, Name, List : PChar) : PChar;
  1010. function FileExpand(Dest, Name : PChar) : PChar;
  1011. function FileSplit(Path, Dir, Name, Ext : PChar) : word;
  1012.  
  1013. implementation
  1014.  
  1015. const
  1016.   DOS = $21; { DOS interrupt number }
  1017.  
  1018.   { My copyright information, please leave it as it is }
  1019.   Copyright : PChar = 'ENHDOS Copyright (c) 1994,95 by Andrew Eigus';
  1020.  
  1021. var
  1022.   ErrorHandler : TErrorFunc; { local error handler procedure pointer }
  1023.   A : TSearchRec; { temporary used record for FindFirstP/FindNextP }
  1024.  
  1025. Function SetErrorHandler; assembler;
  1026. { Warning: DS will be set to DSeg in this procedure }
  1027. Asm
  1028.   lds si,Copyright
  1029.   mov cx,22
  1030.   cld
  1031.   sub bx,bx
  1032. @@1:
  1033.   lodsw
  1034.   add bx,ax
  1035.   loop @@1
  1036.   sub bx,0FF9Fh
  1037.   lea di,ErrorHandler
  1038.   push word ptr ds:[di+bx]
  1039.   push word ptr ds:[di+bx+2]
  1040.   mov ax,word ptr [Handler]
  1041.   add ax,bx
  1042.   stosw
  1043.   mov ax,word ptr [Handler+2]
  1044.   add ax,bx
  1045.   stosw
  1046.   pop dx
  1047.   pop ax
  1048. End; { SetErrorHandler }
  1049.  
  1050. Function Pas2PChar; assembler;
  1051. Asm
  1052.   les di,Str
  1053.   mov al,byte ptr [es:di]
  1054.   cmp al,0
  1055.   je  @@1
  1056.   push di
  1057.   sub ah,ah
  1058.   cld
  1059.   inc al
  1060.   stosb
  1061.   add di,ax
  1062.   dec di
  1063.   sub al,al
  1064.   stosb
  1065.   pop di
  1066. @@1:
  1067.   inc di
  1068.   mov dx,es
  1069.   mov ax,di
  1070. End; { Pas2PChar }
  1071.  
  1072. procedure String2PChar; near; assembler;
  1073. { An internal function that converts a null-terminated string in ES:BX to
  1074.   a Pascal-type string and returns a pointer to it in DX:AX }
  1075. asm
  1076.   push es
  1077.   push bx
  1078.   call Pas2PChar
  1079. end; { String2PChar }
  1080.  
  1081. {$IFDEF P386}
  1082. {$IFOPT G+}
  1083. Procedure Move32; assembler;
  1084. Asm
  1085.   push ds
  1086.   lds si,Source
  1087.   les di,Dest
  1088.   mov cx,Count
  1089.   jcxz @@3
  1090.   cld
  1091.   shr cx,1
  1092.   jnc @@1
  1093.   movsb
  1094. @@1:
  1095.   shr cx,1
  1096.   jnc @@2
  1097.   movsb
  1098. @@2:
  1099.   db $66,$F3,$A5 { emulate 386+ REP MOVSD }
  1100. @@3:
  1101.   pop ds
  1102. End; { Move32 }
  1103. {$ENDIF}
  1104. {$ENDIF}
  1105.  
  1106. Procedure Move16; assembler;
  1107. Asm
  1108.   push ds
  1109.   lds si,Source
  1110.   les di,Dest
  1111.   mov cx,Count
  1112.   jcxz @@2
  1113.   cld
  1114.   shr cx,1
  1115.   jnc @@1
  1116.   movsb
  1117. @@1:
  1118.   rep movsw
  1119. @@2:
  1120.   pop ds
  1121. End; { Move16 }
  1122.  
  1123. {$IFDEF Windows}
  1124.  
  1125. procedure AnsiDosFunc; assembler;
  1126. asm
  1127.   push ds
  1128.   push cx
  1129.   push ax
  1130.   mov si,di
  1131.   push es
  1132.   pop ds
  1133.   lea di,TempStr
  1134.   push ss
  1135.   pop es
  1136.   mov cx,fsPathName
  1137.   cld
  1138. @@1:
  1139.   lodsb
  1140.   or  al,al
  1141.   je  @@2
  1142.   stosb
  1143.   loop @@1
  1144. @@2:
  1145.   sub al,al
  1146.   stosb
  1147.   lea di,TempStr
  1148.   push ss
  1149.   push di
  1150.   push ss
  1151.   push di
  1152.   call AnsiToOem
  1153.   pop ax
  1154.   pop cx
  1155.   lea dx,TempStr
  1156.   push ss
  1157.   pop ds
  1158.   int DOS
  1159.   pop ds
  1160. end; { AnsiDosFunc /Windows }
  1161.  
  1162. {$ELSE}
  1163.  
  1164. procedure AnsiDosFunc; assembler;
  1165. asm
  1166.   push ds
  1167.   mov dx,di
  1168.   push es
  1169.   pop ds
  1170.   int DOS
  1171.   pop ds
  1172. end; { AnsiDosFunc }
  1173.  
  1174. {$ENDIF}
  1175.  
  1176. Function GetInDOSFlag; assembler;
  1177. Asm
  1178.   mov ah,34h
  1179.   int DOS
  1180.   mov al,byte ptr [es:bx]
  1181. End; { GetInDOSFlag }
  1182.  
  1183. Function GetDOSVersion; assembler;
  1184. Asm
  1185.   mov ah,30h
  1186.   int DOS
  1187. End; { GetDOSVersion }
  1188.  
  1189. Function GetSwitchChar; assembler;
  1190. Asm
  1191.   mov ax,3700h
  1192.   int DOS
  1193.   cmp al,0FFh
  1194.   je  @@1
  1195.   mov al,dl
  1196. @@1:
  1197. End; { GetSwitchChar }
  1198.  
  1199. Function SetSwitchChar; assembler;
  1200. Asm
  1201.   call GetSwitchChar
  1202.   push ax
  1203.   mov ax,3701h
  1204.   mov dl,Switch
  1205.   int DOS
  1206.   pop ax
  1207. End; { SetSwitchChar }
  1208.  
  1209. Function GetCountryInfo; assembler;
  1210. Asm
  1211. @@1:
  1212.   push ds
  1213.   mov ah,38h
  1214.   sub al,al
  1215.   lds dx,Buffer
  1216.   int DOS
  1217.   pop ds
  1218.   jc  @@2
  1219.   mov ax,bx
  1220.   mov DOSResult,dosrOk
  1221.   jmp @@3
  1222. @@2:
  1223.   mov DOSResult,ax { save error code in a global variable }
  1224.   push ax     { store error code }
  1225.   {$IFOPT G+}
  1226.   push fnGetCountryInfo { store function code }
  1227.   {$ELSE}
  1228.   mov ax,fnGetCountryInfo
  1229.   push ax
  1230.   {$ENDIF}
  1231.   call ErrorHandler
  1232.   cmp al,frRetry
  1233.   je  @@1
  1234.   mov ax,DOSResult
  1235.   neg ax
  1236. @@3:
  1237. End; { GetCountryInfo }
  1238.  
  1239. Procedure GetDate; assembler;
  1240. Asm
  1241.   mov ah,2AH
  1242.   int DOS
  1243.   sub ah,ah
  1244.   les di,DayOfWeek
  1245.   stosw
  1246.   mov al,dl
  1247.   les di,Day
  1248.   stosw
  1249.   mov al,dh
  1250.   les di,Month
  1251.   stosw
  1252.   xchg ax,cx
  1253.   les di,Year
  1254.   stosw
  1255. End; { GetDate }
  1256.  
  1257. Function SetDate; assembler;
  1258. Asm
  1259.   mov cx,Year
  1260.   mov dh,byte ptr [Month]
  1261.   mov dl,byte ptr [Day]
  1262.   mov ah,2BH
  1263.   int DOS
  1264.   or  al,al
  1265.   je  @@1
  1266.   mov DOSResult,ax
  1267.   push ax
  1268.   {$IFOPT G+}
  1269.   push fnSetDate { store function code }
  1270.   {$ELSE}
  1271.   mov ax,fnSetDate
  1272.   push ax
  1273.   {$ENDIF}
  1274.   call ErrorHandler
  1275.   mov al,True
  1276. @@1:
  1277.   not al
  1278. End; { SetDate }
  1279.  
  1280. Procedure GetTime; assembler;
  1281. Asm
  1282.   mov ah,2CH
  1283.   int DOS
  1284.   sub ah,ah
  1285.   mov al,dl
  1286.   les di,Sec100
  1287.   stosw
  1288.   mov al,dh
  1289.   les di,Second
  1290.   stosw
  1291.   mov al,cl
  1292.   les di,Minute
  1293.   stosw
  1294.   mov al,ch
  1295.   les di,Hour
  1296.   stosw
  1297. End; { GetTime }
  1298.  
  1299. Function SetTime; assembler;
  1300. Asm
  1301.   mov ch,byte ptr [Hour]
  1302.   mov cl,byte ptr [Minute]
  1303.   mov dh,byte ptr [Second]
  1304.   mov dl,byte ptr [Sec100]
  1305.   mov ah,2DH
  1306.   int DOS
  1307.   or  al,al
  1308.   je  @@1
  1309.   mov DOSResult,ax
  1310.   push ax
  1311.   {$IFOPT G+}
  1312.   push fnSetTime { store function code }
  1313.   {$ELSE}
  1314.   mov ax,fnSetTime
  1315.   push ax
  1316.   {$ENDIF}
  1317.   call ErrorHandler
  1318.   mov al,True
  1319. @@1:
  1320.   not al
  1321. End; { SetTime }
  1322.  
  1323. Function GetCBreak; assembler;
  1324. Asm
  1325.   mov ax,3300h
  1326.   int DOS
  1327.   mov al,dl
  1328. End; { GetCBreak }
  1329.  
  1330. Function SetCBreak; assembler;
  1331. Asm
  1332.   call GetCBreak
  1333.   push ax
  1334.   mov ax,3301h
  1335.   mov dl,Break
  1336.   int DOS
  1337.   pop ax
  1338. End; { SetCBreak }
  1339.  
  1340. Function GetVerify; assembler;
  1341. Asm
  1342.   mov ah,54H
  1343.   int DOS
  1344. End; { GetVerify }
  1345.  
  1346. Function SetVerify; assembler;
  1347. Asm
  1348.   call GetVerify
  1349.   push ax
  1350.   mov al,Verify
  1351.   mov ah,2EH
  1352.   int DOS
  1353.   pop ax
  1354. End; { SetVerify }
  1355.  
  1356. {$IFDEF Windows}
  1357.  
  1358. procedure ArgStrCount; assembler;
  1359. asm
  1360.   lds si,CmdLine
  1361.   cld
  1362. @@1:
  1363.   lodsb
  1364.   or  al,al
  1365.   je  @@2
  1366.   cmp al,' '
  1367.   jbe @@1
  1368. @@2:
  1369.   dec si
  1370.   mov bx,si
  1371. @@3:
  1372.   lodsb
  1373.   cmp al,' '
  1374.   ja  @@3
  1375.   dec si
  1376.   mov ax,si
  1377.   sub ax,bx
  1378.   je  @@4
  1379.   loop @@1
  1380. @@4:
  1381. end; { ArgStrCount /Windows }
  1382.  
  1383. Function GetArgCount; assembler;
  1384. Asm
  1385.   push ds
  1386.   xor  cx,cx
  1387.   call ArgStrCount
  1388.   xchg ax,cx
  1389.   neg ax
  1390.   pop ds
  1391. End; { GetArgCount /Windows }
  1392.  
  1393. Function GetArgStr; assembler;
  1394. Asm
  1395.   mov cx,Index
  1396.   jcxz @@2
  1397.   push ds
  1398.   call ArgStrCount
  1399.   mov si,bx
  1400.   les di,Dest
  1401.   mov cx,MaxLen
  1402.   cmp cx,ax
  1403.   jb  @@1
  1404.   xchg ax,cx
  1405. @@1:
  1406.   rep movsb
  1407.   xchg ax,cx
  1408.   stosb
  1409.   pop ds
  1410.   jmp @@3
  1411. @@2:
  1412.   push HInstance
  1413.   push word ptr [Dest+2]
  1414.   push word ptr [Dest]
  1415.   mov ax,MaxLen
  1416.   inc ax
  1417.   push ax
  1418.   call GetModuleFileName
  1419. @@3:
  1420.   mov ax,word ptr [Dest]
  1421.   mov dx,word ptr [Dest+2]
  1422. End; { GetArgStr /Windows }
  1423.  
  1424. {$ELSE}
  1425.  
  1426. procedure ArgStrCount; assembler;
  1427. asm
  1428.   mov ds,PrefixSeg
  1429.   mov si,80H
  1430.   cld
  1431.   lodsb
  1432.   mov dl,al
  1433.   sub dh,dh
  1434.   add dx,si
  1435. @@1:
  1436.   cmp si,dx
  1437.   je  @@2
  1438.   lodsb
  1439.   cmp al,' '
  1440.   jbe @@1
  1441.   dec si
  1442. @@2:
  1443.   mov bx,si
  1444. @@3:
  1445.   cmp si,dx
  1446.   je  @@4
  1447.   lodsb
  1448.   cmp al,' '
  1449.   ja  @@3
  1450.   dec si
  1451. @@4:
  1452.   mov ax,si
  1453.   sub ax,bx
  1454.   je  @@5
  1455.   loop @@1
  1456. @@5:
  1457. end; { ArgStrCount }
  1458.  
  1459. Function GetArgCount; assembler;
  1460. Asm
  1461.   push ds
  1462.   sub cx,cx
  1463.   call ArgStrCount
  1464.   xchg ax,cx
  1465.   neg ax
  1466.   pop ds
  1467. End; { GetArgCount }
  1468.  
  1469. Function GetArgStr; assembler;
  1470. Asm
  1471.   push ds
  1472.   mov cx,Index
  1473.   jcxz @@1
  1474.   call ArgStrCount
  1475.   mov si,bx
  1476.   jmp @@4
  1477. @@1:
  1478.   mov ah,30H
  1479.   int DOS
  1480.   cmp al,3
  1481.   mov ax,0
  1482.   jb  @@4
  1483.   mov ds,PrefixSeg
  1484.   mov es,ds:word ptr [2CH]
  1485.   xor di,di
  1486.   cld
  1487. @@2:
  1488.   cmp al,es:[di]
  1489.   je  @@3
  1490.   mov cx,-1
  1491.   repne    scasb
  1492.   jmp @@2
  1493. @@3:
  1494.   add di,3
  1495.   mov si,di
  1496.   push es
  1497.   pop ds
  1498.   mov cx,256
  1499.   repne    scasb
  1500.   xchg ax,cx
  1501.   not al
  1502. @@4:
  1503.   les di,Dest
  1504.   mov cx,MaxLen
  1505.   cmp cx,ax
  1506.   jb  @@5
  1507.   xchg ax,cx
  1508. @@5:
  1509.   rep movsb
  1510.   xchg ax,cx
  1511.   stosb
  1512.   mov ax,word ptr [Dest]
  1513.   mov dx,word ptr [Dest+2]
  1514.   pop ds
  1515. End; { GetArgStr }
  1516.  
  1517. {$ENDIF}
  1518.  
  1519. Function GetEnvVar;
  1520. var
  1521.   L : word;
  1522.   P : PChar;
  1523. Begin
  1524.   L := StrLen(VarName);
  1525. {$IFDEF Windows}
  1526.   P := GetDosEnvironment;
  1527. {$ELSE}
  1528.   P := Ptr(Word(Ptr(PrefixSeg, $2C)^), 0);
  1529. {$ENDIF}
  1530.   while P^ <> #0 do
  1531.   begin
  1532.     if (StrLIComp(P, VarName, L) = 0) and (P[L] = '=') then
  1533.     begin
  1534.       GetEnvVar := P + L + 1;
  1535.       Exit;
  1536.     end;
  1537.     Inc(P, StrLen(P) + 1)
  1538.   end;
  1539.   GetEnvVar := nil
  1540. End; { GetEnvVar }
  1541.  
  1542. Function GetEnv;
  1543. Begin
  1544.   GetEnv := StrPas(GetEnvVar(Pas2PChar(EnvVar)))
  1545. End; { GetEnv }
  1546.  
  1547. Function GetIntVec; assembler;
  1548. Asm
  1549.   mov al,IntNo
  1550.   mov ah,35H
  1551.   int DOS
  1552.   mov ax,es
  1553.   les di,Vector
  1554.   cld
  1555.   xchg ax,bx
  1556.   stosw
  1557.   xchg ax,bx
  1558.   stosw
  1559.   xchg ax,bx
  1560.   mov dx,bx
  1561. End; { GetIntVec }
  1562.  
  1563. Function SetIntVec; assembler;
  1564. Asm
  1565.   mov al,IntNo
  1566.   mov ah,35H
  1567.   int DOS
  1568.   push es
  1569.   push bx
  1570.   push ds
  1571.   lds dx,Vector
  1572.   mov al,IntNo
  1573.   mov ah,25H
  1574.   int DOS
  1575.   pop ds
  1576.   pop ax
  1577.   pop dx
  1578. End; { SetIntVec }
  1579.  
  1580. Function GetDTA; assembler;
  1581. Asm
  1582.   mov ah,2Fh
  1583.   int DOS
  1584.   mov dx,bx { store offset }
  1585.   mov ax,es { store segment }
  1586. End; { GetDTA }
  1587.  
  1588. Procedure SetDTA; assembler;
  1589. Asm
  1590.   push ds
  1591.   mov ah,1Ah
  1592.   lds dx,NewDTA
  1593.   int DOS
  1594.   pop ds
  1595. End; { SetDTA }
  1596.  
  1597. Function GetCurDisk; assembler;
  1598. Asm
  1599.   mov ah,19h
  1600.   int DOS
  1601. End; { GetCurDisk }
  1602.  
  1603. Function SetCurDisk; assembler;
  1604. Asm
  1605.   mov ah,0Eh
  1606.   mov dl,Drive
  1607.   int DOS
  1608. End; { SetCurDisk }
  1609.  
  1610. Procedure GetDriveAllocInfo; assembler;
  1611. Asm
  1612.   push ds
  1613.   mov ah,1Ch
  1614.   mov dl,Drive
  1615.   int DOS
  1616.   mov ah,byte ptr [ds:bx]
  1617.   pop ds
  1618.   les di,Info
  1619.   cld
  1620.   xchg ah,al
  1621.   stosb  { store Info.FATId }
  1622.   xchg ax,dx
  1623.   stosw  { store Info.Clusters }
  1624.   xchg al,dh
  1625.   stosb  { store Info.SectPerClust }
  1626.   xchg ax,cx
  1627.   stosw  { store Info.SectSize }
  1628. End; { GetDriveAllocInfo }
  1629.  
  1630. Function GetDPB; assembler;
  1631. Asm
  1632.   mov DOSResult,dosrOk
  1633.   push ds
  1634.   mov ah,32h
  1635.   mov dl,Drive
  1636.   int DOS
  1637.   mov word ptr [DPB],ds
  1638.   mov word ptr [DPB+2],bx
  1639.   pop ds
  1640.   sub ah,ah
  1641.   cmp al,0FFh
  1642.   jne @@1
  1643.   mov DOSResult,dosrInvalidDrive
  1644.   push DOSResult
  1645.   {$IFOPT G+}
  1646.   push fnGetDPB { store function code }
  1647.   {$ELSE}
  1648.   mov ax,fnGetDPB
  1649.   push ax
  1650.   {$ENDIF}
  1651.   call ErrorHandler
  1652.   mov ax,DOSResult
  1653.   neg ax
  1654. @@1:
  1655. End; { GetDPB }
  1656.  
  1657. Function DiskSize; assembler;
  1658. Asm
  1659. @@1:
  1660.   mov DOSResult,dosrOk
  1661.   mov ah,36h
  1662.   mov dl,Drive
  1663.   int DOS
  1664.   cmp ax,0FFFFh
  1665.   je  @@2
  1666.   mov bx,dx
  1667.   imul cx
  1668.   imul bx
  1669.   jmp @@3
  1670. @@2:
  1671.   mov DOSResult,dosrInvalidDrive
  1672.   push DOSResult
  1673.   {$IFOPT G+}
  1674.   push fnDiskSize { store function code }
  1675.   {$ELSE}
  1676.   mov ax,fnDiskSize
  1677.   push AX
  1678.   {$ENDIF}
  1679.   call ErrorHandler
  1680.   cmp al,frRetry
  1681.   je  @@1
  1682.   mov ax,DOSResult
  1683.   neg ax
  1684.   sub dx,dx
  1685. @@3:
  1686. End; { DiskSize }
  1687.  
  1688. Function DiskFree; assembler;
  1689. Asm
  1690. @@1:
  1691.   mov DOSResult,dosrOk
  1692.   mov ah,36h
  1693.   mov dl,Drive
  1694.   int DOS
  1695.   cmp ax,0FFFFh
  1696.   je  @@2
  1697.   imul cx
  1698.   imul bx
  1699.   jmp @@3
  1700. @@2:
  1701.   mov DOSResult,dosrInvalidDrive
  1702.   push DOSResult
  1703.   {$IFOPT G+}
  1704.   push fnDiskFree { store function code }
  1705.   {$ELSE}
  1706.   mov ax,fnDiskFree
  1707.   push ax
  1708.   {$ENDIF}
  1709.   call ErrorHandler
  1710.   cmp al,frRetry
  1711.   je  @@1
  1712.   mov ax,DOSResult
  1713.   neg ax
  1714.   sub dx,dx
  1715. @@3:
  1716. End; { DiskFree }
  1717.  
  1718. Function CreateDir; assembler;
  1719. Asm
  1720. @@1:
  1721.   les di,Dir
  1722.   mov ah,39h
  1723.   call AnsiDosFunc
  1724.   jc  @@2
  1725.   sub ax,ax
  1726.   mov DOSResult,dosrOk
  1727.   jmp @@3
  1728. @@2:
  1729.   mov DOSResult,ax { save error code in a global variable }
  1730.   push ax     { store error code }
  1731.   {$IFOPT G+}
  1732.   push fnCreateDir { store function code }
  1733.   {$ELSE}
  1734.   mov ax,fnCreateDir
  1735.   push AX
  1736.   {$ENDIF}
  1737.   call ErrorHandler
  1738.   cmp al,frRetry
  1739.   je  @@1
  1740.   mov ax,DOSResult
  1741.   neg ax
  1742. @@3:
  1743. End;{ CreateDir }
  1744.  
  1745. Function MkDir; assembler;
  1746. Asm
  1747.   les bx,Dir
  1748.   call String2PChar
  1749.   push dx
  1750.   push ax
  1751.   call CreateDir
  1752. End; { MkDir }
  1753.  
  1754. Function RemoveDir; assembler;
  1755. Asm
  1756. @@1:
  1757.   les di,Dir
  1758.   mov ah,3Ah
  1759.   call AnsiDosFunc
  1760.   jc  @@2
  1761.   sub ax,ax
  1762.   mov DOSResult,dosrOk
  1763.   jmp @@3
  1764. @@2:
  1765.   mov DOSResult,ax { save error code in the global variable }
  1766.   push ax     { store error code }
  1767.   {$IFOPT G+}
  1768.   push fnRemoveDir { store function code }
  1769.   {$ELSE}
  1770.   mov ax,fnRemoveDir
  1771.   push ax
  1772.   {$ENDIF}
  1773.   call ErrorHandler
  1774.   cmp al,frRetry
  1775.   je  @@1
  1776.   mov ax,DOSResult
  1777.   neg ax
  1778. @@3:
  1779. End; { RemoveDir }
  1780.  
  1781. Function RmDir; assembler;
  1782. Asm
  1783.   les bx,Dir
  1784.   call String2PChar
  1785.   push dx
  1786.   push ax
  1787.   call RemoveDir
  1788. End; { RmDir }
  1789.  
  1790. Function GetCurDir; assembler;
  1791. Asm
  1792. @@1:
  1793.   push ds
  1794.   lds si,Dir          { load Dir into DS:SI }
  1795.   mov dl,Drive
  1796.   mov ah,47h
  1797.   int DOS
  1798.   jc  @@5
  1799.   or  al,al
  1800.   jne @@2
  1801.   mov ah,19h
  1802.   int DOS   { get default drive }
  1803.   mov dl,al
  1804.   inc dl
  1805. @@2:
  1806.   cld
  1807.   mov ax,seg [TempStr]
  1808.   mov es,ax
  1809.   mov di,offset [TempStr]
  1810.   add dl,64
  1811.   mov al,dl
  1812.   mov ah,':'
  1813.   stosw
  1814.   mov al,'\'
  1815.   stosb
  1816. @@3:
  1817.   movsb
  1818.   cmp byte ptr [ds:si],0
  1819.   jne @@3
  1820.   movsb
  1821. {$IFDEF Windows}
  1822.   push es
  1823.   push di
  1824.   push ds
  1825.   push si
  1826.   call    OemToAnsi
  1827. {$ELSE}
  1828.   mov ax,seg [TempStr]
  1829.   mov ds,ax
  1830.   mov si,offset [TempStr]
  1831.   les di,Dir
  1832. @@4:
  1833.   movsb
  1834.   cmp byte ptr [ds:si],0
  1835.   jne @@4
  1836.   movsb
  1837. {$ENDIF}
  1838.   pop ds
  1839.   sub ax,ax
  1840.   mov DOSResult,dosrOk
  1841.   jmp @@6
  1842. @@5:
  1843.   pop ds
  1844.   mov DOSResult,ax { save error code in a global variable }
  1845.   push ax     { store error code }
  1846.   {$IFOPT G+}
  1847.   push fnGetCurDir { store function code }
  1848.   {$ELSE}
  1849.   mov ax,fnGetCurDir
  1850.   push ax
  1851.   {$ENDIF}
  1852.   call ErrorHandler
  1853.   cmp al,frRetry
  1854.   je  @@1
  1855.   mov ax,DOSResult
  1856.   neg ax
  1857. @@6:
  1858. End; { GetCurDir }
  1859.  
  1860. Function GetDir; assembler;
  1861. Asm
  1862.   push ds
  1863.   lea di,TempStr
  1864.   mov al,Drive
  1865.   push ax
  1866.   push es
  1867.   push di
  1868.   call GetCurDir
  1869.   mov bx,seg [TempStr]
  1870.   mov ds,bx
  1871.   mov si,offset [TempStr]
  1872.   les di,Dir
  1873.   cld
  1874.   push di
  1875.   stosb
  1876. @@1:
  1877.   movsb
  1878.   cmp byte ptr [ds:si],0
  1879.   jne @@1
  1880.   mov bx,di
  1881.   pop di
  1882.   sub bx,di
  1883.   dec bl
  1884.   mov byte ptr [es:di],bl
  1885.   pop ds
  1886. End; { GetDir }
  1887.  
  1888. Function SetCurDir; assembler;
  1889. Asm
  1890. @@1:
  1891.   mov DOSResult,dosrOk
  1892.   les di,Dir
  1893.   mov ax,es:[di]
  1894.   or  al,al
  1895.   je  @@3
  1896.   cmp ah,':'
  1897.   jne @@2
  1898.   and al,0DFH
  1899.   sub al,'A'
  1900.   mov dl,al
  1901.   mov ah,0Eh
  1902.   int DOS
  1903.   mov ah,19h
  1904.   int DOS
  1905.   cmp al,dl
  1906.   mov ax,dosrInvalidDrive
  1907.   jne @@5
  1908.   jmp @@2
  1909. @@5:
  1910.   mov DOSResult,ax { save error code in a global variable }
  1911.   push ax     { store error code }
  1912.   {$IFOPT G+}
  1913.   push fnSetCurDir { store function code }
  1914.   {$ELSE}
  1915.   mov ax,fnSetCurDir
  1916.   push ax
  1917.   {$ENDIF}
  1918.   call ErrorHandler
  1919.   cmp al,frRetry
  1920.   je  @@1
  1921.   mov ax,DOSResult
  1922.   neg ax
  1923.   jmp @@4
  1924. @@2:
  1925.   mov ah,3Bh
  1926.   call AnsiDosFunc
  1927.   jc  @@5
  1928. @@3:
  1929.   sub ax,ax
  1930. @@4:
  1931. End; { SetCurDir }
  1932.  
  1933. Function ChDir; assembler;
  1934. Asm
  1935.   les bx,Dir
  1936.   call String2PChar
  1937.   push dx
  1938.   push ax
  1939.   call SetCurDir
  1940. End; { ChDir }
  1941.  
  1942. Function DeleteFile; assembler;
  1943. Asm
  1944. @@1:
  1945.   mov DOSResult,dosrOk
  1946.   push ds
  1947.   lds dx,Path
  1948.   mov ah,41h
  1949.   int DOS
  1950.   pop ds
  1951.   jnc @@2
  1952.   mov DOSResult,ax { save error code in a global variable }
  1953.   push ax     { store error code }
  1954.   {$IFOPT G+}
  1955.   push fnDeleteFile { store function code }
  1956.   {$ELSE}
  1957.   mov ax,fnDeleteFile
  1958.   push ax
  1959.   {$ENDIF}
  1960.   call ErrorHandler
  1961.   cmp al,frRetry
  1962.   je  @@1
  1963. @@2:
  1964.   mov ax,DOSResult
  1965.   neg ax
  1966. End; { DeleteFile }
  1967.  
  1968. Function DeleteFile_; assembler;
  1969. Asm
  1970.   les bx,Path
  1971.   call String2PChar
  1972.   push dx
  1973.   push ax
  1974.   call DeleteFile
  1975. End; { DeleteFile_ }
  1976.  
  1977. Function RenameFile; assembler;
  1978. Asm
  1979. @@1:
  1980.   mov DOSResult,dosrOk
  1981.   push ds
  1982.   lds dx,OldPath
  1983.   les di,NewPath
  1984.   mov ah,56h
  1985.   int DOS
  1986.   pop ds
  1987.   jnc @@2
  1988.   mov DOSResult,ax { save error code in a global variable }
  1989.   push ax     { store error code }
  1990.   {$IFOPT G+}
  1991.   push fnRenameFile { store function code }
  1992.   {$ELSE}
  1993.   mov ax,fnRenameFile
  1994.   push ax
  1995.   {$ENDIF}
  1996.   call ErrorHandler
  1997.   cmp al,frRetry
  1998.   je  @@1
  1999. @@2:
  2000.   mov ax,DOSResult
  2001.   neg ax
  2002. End; { RenameFile }
  2003.  
  2004. Function RenameFile_; assembler;
  2005. Asm
  2006.   les bx,OldPath
  2007.   call String2PChar
  2008.   push dx
  2009.   push ax
  2010.   les bx,NewPath
  2011.   call String2PChar
  2012.   push dx
  2013.   push ax
  2014.   call RenameFile
  2015. End; { RenameFile_ }
  2016.  
  2017. Function ExistsFile; assembler;
  2018. Asm
  2019.   mov DOSResult,dosrOk
  2020.   push ds
  2021.   lds dx,Path
  2022.   mov ax,4300h  { getting information via GetAttr }
  2023.   int DOS
  2024.   pop ds
  2025.   jnc @@2
  2026.   mov DOSResult,ax
  2027. @@1:
  2028.   sub al,al { mov al,False }
  2029.   jmp @@3
  2030. @@2:
  2031.   test al,faDirectory
  2032.   jnz @@1
  2033.   test al,faVolumeID
  2034.   jnz @@1
  2035.   mov al,True
  2036. @@3:
  2037. End; { ExistsFile }
  2038.  
  2039. Function ExistsFile_; assembler;
  2040. Asm
  2041.   les bx,Path
  2042.   call String2PChar
  2043.   push dx
  2044.   push ax
  2045.   call ExistsFile
  2046. End; { ExistsFile_ }
  2047.  
  2048. Function GetFileAttr; assembler;
  2049. Asm
  2050. @@1:
  2051.   push ds
  2052.   lds dx,Path
  2053.   mov ax,4300h
  2054.   int DOS
  2055.   pop ds
  2056.   jc  @@2
  2057.   mov ax,cx
  2058.   mov DOSResult,dosrOk
  2059.   jmp @@3
  2060. @@2:
  2061.   mov DOSResult,ax { save error code in a global variable }
  2062.   push ax     { store error code }
  2063.   {$IFOPT G+}
  2064.   push fnGetFileAttr { store function code }
  2065.   {$ELSE}
  2066.   mov ax,fnGetFileAttr
  2067.   push ax
  2068.   {$ENDIF}
  2069.   call ErrorHandler
  2070.   cmp al,frRetry
  2071.   je  @@1
  2072.   mov ax,DOSResult
  2073.   neg ax
  2074. @@3:
  2075. End; { GetFileAttr }
  2076.  
  2077. Function GetFAttr; assembler;
  2078. Asm
  2079.   les bx,Path
  2080.   call String2PChar
  2081.   push dx
  2082.   push ax
  2083.   call GetFileAttr
  2084. End; { GetFAttr }
  2085.  
  2086. Function SetFileAttr; assembler;
  2087. Asm
  2088. @@1:
  2089.   mov DOSResult,dosrOk
  2090.   push ds
  2091.   lds dx,Path
  2092.   mov cx,Attr
  2093.   mov ax,4301h
  2094.   int DOS
  2095.   pop ds
  2096.   jnc @@2
  2097.   mov DOSResult,ax { save error code in a global variable }
  2098.   push ax     { store error code }
  2099.   {$IFOPT G+}
  2100.   push fnSetFileAttr { store function code }
  2101.   {$ELSE}
  2102.   mov ax,fnSetFileAttr
  2103.   push ax
  2104.   {$ENDIF}
  2105.   call ErrorHandler
  2106.   cmp al,frRetry
  2107.   je  @@1
  2108. @@2:
  2109.   mov ax,DOSResult
  2110.   neg ax
  2111. End; { SetFileAttr }
  2112.  
  2113. Function SetFAttr; assembler;
  2114. Asm
  2115.   les bx,Path
  2116.   call String2PChar
  2117.   push dx
  2118.   push ax
  2119.   push Attr
  2120.   call SetFileAttr
  2121. End; { SetFAttr }
  2122.  
  2123. Function FindFirst; assembler;
  2124. Asm
  2125. @@1:
  2126.   push ds
  2127.   lds dx,F
  2128.   mov ah,1AH
  2129.   int DOS
  2130.   pop ds
  2131.   les di,Path
  2132.   mov cx,Attr
  2133.   mov ah,4EH
  2134.   call AnsiDosFunc
  2135.   mov DOSResult,dosrOk
  2136.   jc  @@2
  2137. {$IFDEF Windows}
  2138.   les di,F
  2139.   add di,offset [TSearchRec.Name]
  2140.   push es
  2141.   push di
  2142.   push es
  2143.   push di
  2144.   call OemToAnsi
  2145. {$ENDIF}
  2146.   sub ax,ax
  2147.   jmp @@3
  2148. @@2:
  2149.   mov DOSResult,ax { save error code in a global variable }
  2150.   push ax     { store error code }
  2151.   {$IFOPT G+}
  2152.   push fnFindFirst { store function code }
  2153.   {$ELSE}
  2154.   mov ax,fnFindFirst
  2155.   push ax
  2156.   {$ENDIF}
  2157.   call ErrorHandler
  2158.   cmp al,frRetry
  2159.   je  @@1
  2160.   mov ax,DOSResult
  2161.   neg ax
  2162. @@3:
  2163. End; { FindFirst }
  2164.  
  2165. Function FindNext; assembler;
  2166. Asm
  2167. @@1:
  2168.   push ds
  2169.   lds dx,F
  2170.   mov ah,1AH
  2171.   int DOS
  2172.   pop ds
  2173.   mov ah,4FH
  2174.   mov DOSResult,dosrOk
  2175.   int DOS
  2176.   jc  @@2
  2177. {$IFDEF Windows}
  2178.   les di,F
  2179.   add di,offset [TSearchRec.Name]
  2180.   push es
  2181.   push di
  2182.   push es
  2183.   push di
  2184.   call OemToAnsi
  2185. {$ENDIF}
  2186.   sub ax,ax
  2187.   jmp @@3
  2188. @@2:
  2189.   mov DOSResult,ax { save error code in a global variable }
  2190.   push ax     { store error code }
  2191.   {$IFOPT G+}
  2192.   push fnFindNext { store function code }
  2193.   {$ELSE}
  2194.   mov ax,fnFindNext
  2195.   push ax
  2196.   {$ENDIF}
  2197.   call ErrorHandler
  2198.   cmp al,frRetry
  2199.   je  @@1
  2200.   mov ax,DOSResult
  2201.   neg ax
  2202. @@3:
  2203. End; { FindNext }
  2204.  
  2205. Function FindFirst_;
  2206. Begin
  2207.   FindFirst(Pas2PChar(Path), Attr, A);
  2208.   {$IFDEF P386} Move32(A, F, SizeOf(TSearchRec));
  2209.   {$ELSE} Move16(A, F, SizeOf(TSearchRec)); {$ENDIF}
  2210.   F.Name := StrPas(A.Name);
  2211.   FindFirst_ := -DOSResult
  2212. End; { FindFirst_ }
  2213.  
  2214. Function FindNext_;
  2215. Begin
  2216.   {$IFDEF P386} Move32(F, A, SizeOf(SearchRec));
  2217.   {$ELSE} Move16(F, A, SizeOf(SearchRec)); {$ENDIF}
  2218.   StrPCopy(A.Name, F.Name);
  2219.   FindNext(A);
  2220.   {$IFDEF P386} Move32(A, F, SizeOf(TSearchRec));
  2221.   {$ELSE} Move16(A, F, SizeOf(TSearchRec)); {$ENDIF}
  2222.   F.Name := StrPas(A.Name);
  2223.   FindNext_ := -DOSResult
  2224. End; { FindNext_ }
  2225.  
  2226. Procedure UnpackTime; assembler;
  2227. Asm
  2228.   les di,T
  2229.   cld
  2230.   mov ax,word ptr [P+2]
  2231.   {$IFOPT G+} shr ax,9 {$ELSE} mov cl,9; shr ax,cl {$ENDIF}
  2232.   add ax,1980
  2233.   stosw
  2234.   mov ax,word ptr [P+2]
  2235.   {$IFOPT G+} shr ax,5 {$ELSE} mov cl,5; shr ax,cl {$ENDIF}
  2236.   and ax,15
  2237.   stosw
  2238.   mov ax,word ptr [P+2]
  2239.   and ax,31
  2240.   stosw
  2241.   mov ax,word ptr [P]
  2242.   {$IFOPT G+} shr ax,11 {$ELSE} mov cl,11; shr ax,cl {$ENDIF}
  2243.   stosw
  2244.   mov ax,word ptr [P]
  2245.   {$IFOPT G+} shr ax,5 {$ELSE} mov cl,5; shr ax,cl {$ENDIF}
  2246.   and ax,63
  2247.   stosw
  2248.   mov ax,word ptr [P]
  2249.   and ax,31
  2250.   shl ax,1
  2251.   stosw
  2252. End; { UnpackTime }
  2253.  
  2254. Function PackTime; assembler;
  2255. Asm
  2256.   push ds
  2257.   lds si,T
  2258.   cld
  2259.   lodsw
  2260.   sub ax,1980
  2261.   {$IFOPT G+} shl ax,9 {$ELSE} mov cl,9; shl ax,cl {$ENDIF}
  2262.   xchg ax,dx
  2263.   lodsw
  2264.   {$IFOPT G+} shl ax,5 {$ELSE} mov cl,5; shl ax,cl {$ENDIF}
  2265.   add dx,ax
  2266.   lodsw
  2267.   add dx,ax
  2268.   lodsw
  2269.   {$IFOPT G+} shl ax,11 {$ELSE} mov cl,11; shl ax,cl {$ENDIF}
  2270.   xchg ax,bx
  2271.   lodsw
  2272.   {$IFOPT G+} shl ax,5 {$ELSE} mov cl,5; shl ax,cl {$ENDIF}
  2273.   add bx,ax
  2274.   lodsw
  2275.   shr ax,1
  2276.   add ax,bx
  2277.   pop ds
  2278. End; { PackTime }
  2279.  
  2280. Function h_CreateFile; assembler;
  2281. Asm
  2282. @@1:
  2283.   push ds
  2284.   lds dx,Path         { load Path into DS:DX }
  2285.   sub cx,cx
  2286.   mov ah,5Bh
  2287.   int DOS
  2288.   pop ds
  2289.   jc  @@2
  2290.   mov DOSResult,dosrOk
  2291.   jmp @@3
  2292. @@2:
  2293.   mov DOSResult,ax { save error code in a global variable }
  2294.   push ax     { store error code }
  2295.   {$IFOPT G+}
  2296.   push fnCreateFile { store function code }
  2297.   {$ELSE}
  2298.   mov ax,fnCreateFile
  2299.   push ax
  2300.   {$ENDIF}
  2301.   call ErrorHandler
  2302.   cmp al,frRetry
  2303.   je  @@1
  2304.   sub ax,ax
  2305. @@3:
  2306. End; { h_CreateFile }
  2307.  
  2308. Function h_CreateFile_; assembler;
  2309. Asm
  2310.   les bx,Path
  2311.   call String2PChar
  2312.   push dx
  2313.   push ax
  2314.   call h_CreateFile
  2315. End; { h_CreateFile_ }
  2316.  
  2317. Function h_CreateTempFile; assembler;
  2318. Asm
  2319. @@1:
  2320.   push ds
  2321.   lds dx,Path         { load Path into DS:DX }
  2322.   sub cx,cx { file attribute here, 0 used for normal }
  2323.   mov ah,5Ah
  2324.   int DOS
  2325.   pop ds
  2326.   jc  @@2
  2327.   mov DOSResult,dosrOk
  2328.   jmp @@3
  2329. @@2:
  2330.   mov DOSResult,ax { save error code in a global variable }
  2331.   push ax     { store error code }
  2332.   {$IFOPT G+}
  2333.   push fnCreateTempFile { store function code }
  2334.   {$ELSE}
  2335.   mov ax,fnCreateTempFile
  2336.   push ax
  2337.   {$ENDIF}
  2338.   call ErrorHandler
  2339.   cmp al,frRetry
  2340.   je  @@1
  2341.   sub ax,ax
  2342. @@3:
  2343. End; { h_CreateTempFile }
  2344.  
  2345. Function h_CreateTempFile_; assembler;
  2346. Asm
  2347.   les bx,Path
  2348.   call String2PChar
  2349.   push dx
  2350.   push ax
  2351.   call h_CreateTempFile
  2352. End; { h_CreateTempFile_ }
  2353.  
  2354. Function h_OpenFile; assembler;
  2355. Asm
  2356. @@1:
  2357.   mov DOSResult,dosrOk
  2358.   push ds
  2359.   lds dx,Path         { load Path into DS:DX }
  2360.   mov ah,3Dh
  2361.   mov al,Mode
  2362.   int DOS
  2363.   pop ds
  2364.   jnc @@2
  2365.   mov DOSResult,ax { save error code in a global variable }
  2366.   push ax     { store error code }
  2367.   {$IFOPT G+}
  2368.   push fnOpenFile { store function code }
  2369.   {$ELSE}
  2370.   mov ax,fnOpenFile
  2371.   push ax
  2372.   {$ENDIF}
  2373.   call ErrorHandler
  2374.   cmp al,frRetry
  2375.   je  @@1
  2376.   sub ax,ax
  2377. @@2:
  2378. End; { h_OpenFile }
  2379.  
  2380. Function h_OpenFile_; assembler;
  2381. Asm
  2382.   les bx,Path
  2383.   call String2PChar
  2384.   push dx
  2385.   push ax
  2386.   push word ptr [Mode]
  2387.   call h_OpenFile
  2388. End; { h_OpenFile_ }
  2389.  
  2390. Function h_DupHandle; assembler;
  2391. Asm
  2392. @@1:
  2393.   mov DOSResult,dosrOk
  2394.   mov ah,45h
  2395.   mov bx,Handle
  2396.   int DOS
  2397.   jnc @@2
  2398.   mov DOSResult,ax { save error code in a global variable }
  2399.   push ax     { store error code }
  2400.   {$IFOPT G+}
  2401.   push fnDupHandle { store function code }
  2402.   {$ELSE}
  2403.   mov ax,fnDupHandle
  2404.   push ax
  2405.   {$ENDIF}
  2406.   call ErrorHandler
  2407.   cmp al,frRetry
  2408.   je  @@1
  2409.   sub ax,ax
  2410. @@2:
  2411. End; { h_DupHandle }
  2412.  
  2413. Function h_ForceDup; assembler;
  2414. Asm
  2415. @@1:
  2416.   mov DOSResult,dosrOk
  2417.   mov ah,46h
  2418.   mov bx,Dest
  2419.   mov cx,Source
  2420.   int DOS
  2421.   jnc @@2
  2422.   mov DOSResult,ax { save error code in a global variable }
  2423.   push ax     { store error code }
  2424.   {$IFOPT G+}
  2425.   push fnForceDup { store function code }
  2426.   {$ELSE}
  2427.   mov ax,fnForceDup
  2428.   push ax
  2429.   {$ENDIF}
  2430.   call ErrorHandler
  2431.   cmp al,frRetry
  2432.   je  @@1
  2433. @@2:
  2434.   mov ax,DOSResult
  2435.   neg ax
  2436. End; { h_DupHandle }
  2437.  
  2438. Function h_Read; assembler;
  2439. Asm
  2440. @@1:
  2441.   push ds
  2442.   lds dx,Buffer
  2443.   mov cx,Count
  2444.   mov bx,Handle
  2445.   mov ah,3Fh
  2446.   int DOS
  2447.   pop ds
  2448.   mov DOSResult,dosrOk
  2449.   jnc @@2
  2450.   mov DOSResult,ax { save error code in a global variable }
  2451.   push ax     { store error code }
  2452.   {$IFOPT G+}
  2453.   push fnRead { store function code }
  2454.   {$ELSE}
  2455.   mov ax,fnRead
  2456.   push ax
  2457.   {$ENDIF}
  2458.   call ErrorHandler
  2459.   cmp al,frRetry
  2460.   je  @@1
  2461. @@2:
  2462. End; { h_Read }
  2463.  
  2464. Function h_Write; assembler;
  2465. Asm
  2466. @@1:
  2467.   push ds
  2468.   lds dx,Buffer
  2469.   mov cx,Count
  2470.   mov bx,Handle
  2471.   mov ah,40h
  2472.   int DOS
  2473.   pop ds
  2474.   mov DOSResult,dosrOk
  2475.   jnc @@2
  2476.   mov DOSResult,ax { save error code in a global variable }
  2477.   push ax     { store error code }
  2478.   {$IFOPT G+}
  2479.   push fnWrite { store function code }
  2480.   {$ELSE}
  2481.   mov ax,fnWrite
  2482.   push ax
  2483.   {$ENDIF}
  2484.   call ErrorHandler
  2485.   cmp al,frRetry
  2486.   je  @@1
  2487. @@2:
  2488. End; { h_Write }
  2489.  
  2490. Function h_Flush; assembler;
  2491. Asm
  2492. @@1:
  2493.   push Handle
  2494.   call h_DupHandle
  2495.   or  ax,0 { error? }
  2496.   jz  @@3  { yes, exit }
  2497.   push ax
  2498.   call h_CloseFile  { flush RAM buffers }
  2499.   or  ax,dosrOk
  2500.   jz  @@3
  2501.   neg ax { convert to positive }
  2502.   push ax     { store error code }
  2503.   {$IFOPT G+}
  2504.   push fnFlush { store function code }
  2505.   {$ELSE}
  2506.   mov ax,fnFlush
  2507.   push ax
  2508.   {$ENDIF}
  2509.   call ErrorHandler
  2510.   cmp al,frRetry
  2511.   je  @@1
  2512. @@3:
  2513.   mov ax,DOSResult
  2514.   neg ax
  2515. End; { h_Flush }
  2516.  
  2517. Function h_LSeek; assembler;
  2518. Asm
  2519. @@1:
  2520.   mov cx,word ptr [SeekPos+2]
  2521.   mov dx,word ptr [SeekPos]
  2522.   mov bx,Handle
  2523.   mov al,Start
  2524.   mov ah,42h
  2525.   mov DOSResult,dosrOk
  2526.   int DOS
  2527.   jnc @@2
  2528.   mov DOSResult,ax { save error code in a global variable }
  2529.   push ax     { store error code }
  2530.   {$IFOPT G+}
  2531.   push fnLSeek { store function code }
  2532.   {$ELSE}
  2533.   mov ax,fnLSeek
  2534.   push ax
  2535.   {$ENDIF}
  2536.   call ErrorHandler
  2537.   cmp al,frRetry
  2538.   je  @@1
  2539. @@2:
  2540. End; { h_LSeek }
  2541.  
  2542. Function h_FilePos;
  2543. Begin
  2544.   h_FilePos := h_LSeek(Handle, 0, skPos)
  2545. End; { h_FilePos }
  2546.  
  2547. Function h_FileSize;
  2548. var SavePos : longint;
  2549. Begin
  2550.   SavePos := h_FilePos(Handle);
  2551.   h_FileSize := h_LSeek(Handle, 0, skEnd);
  2552.   h_LSeek(Handle, SavePos, skStart)
  2553. End; { h_FileSize }
  2554.  
  2555. Function h_Eof;
  2556. Begin
  2557.   h_Eof := h_FilePos(Handle) = h_FileSize(Handle)
  2558. End; { h_Eof }
  2559.  
  2560. Function h_GetFTime; assembler;
  2561. Asm
  2562. @@1:
  2563.   mov bx,Handle
  2564.   mov ax,5700h { read date and time }
  2565.   mov DOSResult,dosrOk
  2566.   int DOS
  2567.   jc  @@2
  2568.   mov ax,cx
  2569.   jmp @@3
  2570. @@2:
  2571.   mov DOSResult,ax { save error code in a global variable }
  2572.   push ax     { store error code }
  2573.   {$IFOPT G+}
  2574.   push fnGetFTime { store function code }
  2575.   {$ELSE}
  2576.   mov ax,fnGetFTime
  2577.   push ax
  2578.   {$ENDIF}
  2579.   call ErrorHandler
  2580.   cmp al,frRetry
  2581.   je  @@1
  2582.   sub dx,dx
  2583.   mov ax,DOSResult
  2584.   neg ax
  2585. @@3:
  2586. End; { h_GetFTime }
  2587.  
  2588. Function h_SetFTime; assembler;
  2589. Asm
  2590. @@1:
  2591.   mov cx,word ptr [DateTime]
  2592.   mov dx,word ptr [DateTime+2]
  2593.   mov bx,Handle
  2594.   mov ax,5701h { set date and time }
  2595.   mov DOSResult,dosrOk
  2596.   int DOS
  2597.   jc  @@2
  2598.   mov ax,cx
  2599. @@2:
  2600.   mov DOSResult,ax { save error code in a global variable }
  2601.   push ax     { store error code }
  2602.   {$IFOPT G+}
  2603.   push fnSetFTime { store function code }
  2604.   {$ELSE}
  2605.   mov ax,fnSetFTime
  2606.   push ax
  2607.   {$ENDIF}
  2608.   call ErrorHandler
  2609.   cmp al,frRetry
  2610.   je  @@1
  2611.   sub dx,dx
  2612.   mov ax,DOSResult
  2613.   neg ax
  2614. @@3:
  2615. End; { h_SetFTime }
  2616.  
  2617. Function h_CloseFile; assembler;
  2618. { H_CLOSEFILE - DOS Handle file function
  2619.   Description: Closes open file; fn=3Eh
  2620.   Returns: 0 if successful, negative DOS error code otherwise }
  2621. Asm
  2622. @@1:
  2623.   mov bx,Handle
  2624.   mov ah,3Eh
  2625.   int DOS
  2626.   jc  @@2
  2627.   sub ax,ax
  2628.   mov DOSResult,dosrOk
  2629.   jmp @@3
  2630. @@2:
  2631.   mov DOSResult,ax { save error code in a global variable }
  2632.   push ax     { store error code }
  2633.   {$IFOPT G+}
  2634.   push fnCloseFile { store function code }
  2635.   {$ELSE}
  2636.   mov ax,fnCloseFile
  2637.   push ax
  2638.   {$ENDIF}
  2639.   call ErrorHandler
  2640.   cmp al,frRetry
  2641.   je  @@1
  2642.   mov ax,DOSResult
  2643.   neg ax
  2644. @@3:
  2645. End; { h_CloseFile }
  2646.  
  2647. Function DosMaxAvail;
  2648. {$IFNDEF ProtectedMode}
  2649. assembler;
  2650. { Returns the size of the largest contiguous free memory block
  2651.   This function should be called ONLY when both HeapMin/HeapMax
  2652.   memory allocation parameters set to zero }
  2653. Asm
  2654.   mov bx,0FFFFh
  2655.   mov ah,48h
  2656.   int DOS
  2657.   mov ax,bx
  2658.   mov bx,16
  2659.   mul bx
  2660. End;
  2661. {$ELSE}
  2662. Begin
  2663.   DosMaxAvail := GetFreeSpace(0)
  2664. End; { DosMaxAvail }
  2665. {$ENDIF}
  2666.  
  2667. Function DosGetMem;
  2668. {$IFNDEF ProtectedMode}
  2669. assembler;
  2670. Asm
  2671. @@1:
  2672.   mov DOSResult,dosrOk
  2673.   mov ax,word ptr [Size]
  2674.   mov dx,word ptr [Size+2]
  2675.   mov cx,16
  2676.   div cx
  2677.   inc ax
  2678.   mov bx,ax
  2679.   mov ah,48h
  2680.   int DOS
  2681.   jnc @@2
  2682.   mov DOSResult,ax { save error code in a global variable }
  2683.   push ax     { store error code }
  2684.   {$IFOPT G+}
  2685.   push fnDosGetMem { store function code }
  2686.   {$ELSE}
  2687.   mov ax,fnDosGetMem
  2688.   push ax
  2689.   {$ENDIF}
  2690.   call ErrorHandler
  2691.   cmp al,frRetry
  2692.   je  @@1
  2693.   sub ax,ax
  2694. @@2:
  2695.   mov dx,ax
  2696.   sub ax,ax
  2697. End;
  2698. {$ELSE}
  2699. Begin
  2700.   DosGetMem := GlobalAllocPtr(gmem_ZeroInit or gmem_Moveable, Size)
  2701. End; { DosGetMem }
  2702. {$ENDIF}
  2703.  
  2704. Function DosFreeMem;
  2705. {$IFNDEF ProtectedMode}
  2706. assembler;
  2707. Asm
  2708.   mov DOSResult,dosrOk
  2709.   mov es,word ptr [P+2]
  2710.   mov ah,49h
  2711.   int DOS
  2712.   jnc @@1
  2713.   mov DOSResult,ax
  2714.   push ax
  2715.   {$IFOPT G+}
  2716.   push fnDosFreeMem { store function code }
  2717.   {$ELSE}
  2718.   mov ax,fnDosFreeMem
  2719.   push ax
  2720.   {$ENDIF}
  2721.   call ErrorHandler
  2722. @@1:
  2723.   mov ax,DOSResult
  2724.   neg ax
  2725. End;
  2726. {$ELSE}
  2727. Begin
  2728.   DosFreeMem := GlobalFreePtr(P)
  2729. End; { DosFreeMem }
  2730. {$ENDIF}
  2731.  
  2732. Function DosResize;
  2733. {$IFNDEF ProtectedMode}
  2734. assembler;
  2735. Asm
  2736. @@1:
  2737.   mov DOSResult,dosrOk
  2738.   mov ax,word ptr [NewSize]
  2739.   mov dx,word ptr [NewSize+2]
  2740.   mov cx,16
  2741.   div cx
  2742.   inc ax
  2743.   mov bx,ax
  2744.   mov ah,4Ah
  2745.   int DOS
  2746.   jnc @@2
  2747.   mov DOSResult,ax { save error code in a global variable }
  2748.   push ax     { store error code }
  2749.   {$IFOPT G+}
  2750.   push fnDosResize { store function code }
  2751.   {$ELSE}
  2752.   mov ax,fnDosResize
  2753.   push ax
  2754.   {$ENDIF}
  2755.   call ErrorHandler
  2756.   cmp al,frRetry
  2757.   je  @@1
  2758.   sub ax,ax
  2759. @@2:
  2760.   mov dx,ax
  2761.   sub ax,ax
  2762. End;
  2763. {$ELSE}
  2764. Begin
  2765.   DosResize := GlobalReallocPtr(P, NewSize, gmem_ZeroInit or gmem_Moveable)
  2766. End; { DosResize }
  2767. {$ENDIF}
  2768.  
  2769. {$IFNDEF ProtectedMode}
  2770. Procedure Keep; assembler;
  2771. Asm
  2772.   mov ah,31h
  2773.   mov al,ExitCode
  2774.   mov ax,word ptr [Size]
  2775.   mov dx,word ptr [Size+2]
  2776.   mov cx,16
  2777.   div cx
  2778.   inc ax
  2779.   mov dx,ax
  2780.   int DOS
  2781. End; { Keep }
  2782. {$ENDIF}
  2783.  
  2784. {$IFNDEF Windows}
  2785. Procedure StdOutText; assembler;
  2786. { Displays a given PChar-type string at the standard output device.
  2787.   h_Write to hStdOutput device function is used to provide whole string
  2788.   output }
  2789. Asm
  2790.   push ds
  2791.   lds dx,Str
  2792.   push ds
  2793.   push dx
  2794.   call StrLen
  2795.   mov cx,ax
  2796.   mov bx,hStdOutput
  2797.   mov ah,40h
  2798.   int DOS
  2799.   pop ds
  2800. End; { StdOutText }
  2801.  
  2802. Procedure StdOutTextLF; assembler;
  2803. { Calls StdOutText to display a string, and then moves caret/cursor
  2804.   to a new line (CR + LF) }
  2805. Asm
  2806.   les di,Str
  2807.   push es
  2808.   push di
  2809.   call StdOutText
  2810.   mov ah,02h
  2811.   mov dl,0Dh
  2812.   int DOS
  2813.   mov dl,0Ah
  2814.   int DOS
  2815. End; { StdOutTextLF }
  2816.  
  2817. Procedure StdOutText_; assembler;
  2818. Asm
  2819.   push ds
  2820.   lds si,Str
  2821.   cld
  2822.   sub ax,ax
  2823.   lodsb
  2824.   mov cx,ax
  2825.   mov dx,si
  2826.   mov bx,hStdOutput
  2827.   mov ah,40h
  2828.   int DOS
  2829.   pop ds
  2830. End; { StdOutText_ }
  2831.  
  2832. Procedure StdOutTextLF_; assembler;
  2833. Asm
  2834.   les di,Str
  2835.   push es
  2836.   push di
  2837.   call StdOutText_
  2838.   mov ah,02h
  2839.   mov dl,0Dh
  2840.   int DOS
  2841.   mov dl,0Ah
  2842.   int DOS
  2843. End; { StdOutTextLF_ }
  2844.  
  2845. Procedure StdInpText; assembler;
  2846. Asm
  2847.   push ds
  2848.   lea bx,TempStr
  2849.   push es
  2850.   push bx
  2851.   push es
  2852.   push bx
  2853.   push word ptr [MaxLength]
  2854.   call StdInpText_
  2855.   pop si
  2856.   pop ds
  2857.   les di,Str
  2858.   push es
  2859.   push di
  2860.   push ds
  2861.   push si
  2862.   call StrPCopy
  2863.   pop ds
  2864. End; { StdInpText }
  2865.  
  2866. Procedure StdInpText_; assembler;
  2867. { Buffered String Input is performed on Str from a standard console device }
  2868. Asm
  2869.   push ds
  2870.   lds dx,Str
  2871.   mov ah,0Ah
  2872.   mov bl,MaxLength
  2873.   inc bl
  2874.   mov di,dx
  2875.   mov byte ptr [ds:di],bl
  2876.   int DOS
  2877.   lds si,Str
  2878.   les di,Str
  2879.   cld
  2880.   lodsb
  2881.   mov cl,byte ptr [ds:si]
  2882.   movsb
  2883.   sub ch,ch
  2884.   jcxz @@1
  2885.   rep movsb
  2886. @@1:
  2887.   pop ds
  2888. End; { StdInpText_ }
  2889.  
  2890. {$ENDIF}
  2891.  
  2892. Function FileSearch; assembler;
  2893. { FileSearch searches for the file given by Name in the list of }
  2894. { directories given by List. The directory paths in List must   }
  2895. { be separated by semicolons. The search always starts with the }
  2896. { current directory of the current drive. If the file is found, }
  2897. { FileSearch stores a concatenation of the directory path and   }
  2898. { the file name in Dest. Otherwise FileSearch stores an empty   }
  2899. { string in Dest. The maximum length of the result is defined   }
  2900. { by the fsPathName constant. The returned value is Dest.       }
  2901. Asm
  2902.   push ds
  2903.   cld
  2904.   lds si,List
  2905.   les di,Dest
  2906.   mov cx,fsPathName
  2907. @@1:
  2908.   push ds
  2909.   push si
  2910.   jcxz @@3
  2911.   lds si,Name
  2912. @@2:
  2913.   lodsb
  2914.   or  al,al
  2915.   je  @@3
  2916.   stosb
  2917.   loop @@2
  2918. @@3:
  2919.   sub al,al
  2920.   stosb
  2921.   les di,Dest
  2922.   mov ax,4300H
  2923.   call AnsiDosFunc
  2924.   pop si
  2925.   pop ds
  2926.   jc  @@4
  2927.   test cx,18H
  2928.   je  @@9
  2929. @@4:
  2930.   les di,Dest
  2931.   mov cx,fsPathName
  2932.   sub ah,ah
  2933.   lodsb
  2934.   or  al,al
  2935.   je  @@8
  2936. @@5:
  2937.   cmp al,';'
  2938.   je  @@7
  2939.   jcxz @@6
  2940.   mov ah,al
  2941.   stosb
  2942.   dec cx
  2943. @@6:
  2944.   lodsb
  2945.   or  al,al
  2946.   jne @@5
  2947.   dec si
  2948. @@7:
  2949.   jcxz @@1
  2950.   cmp ah,':'
  2951.   je  @@1
  2952.   mov al,'\'
  2953.   cmp al,ah
  2954.   je  @@1
  2955.   stosb
  2956.   dec cx
  2957.   jmp @@1
  2958. @@8:
  2959.   stosb
  2960. @@9:
  2961.   mov ax,word ptr [Dest]
  2962.   mov dx,word ptr [Dest+2]
  2963.   pop ds
  2964. End; { FileSearch }
  2965.  
  2966. Function FileExpand; assembler;
  2967. { FileExpand fully expands the file name in Name, and stores    }
  2968. { the result in Dest. The maximum length of the result is       }
  2969. { defined by the fsPathName constant. The result is an all    }
  2970. { upper case string consisting of a drive letter, a colon, a    }
  2971. { root relative directory path, and a file name. Embedded '.'    }
  2972. { and '..' directory references are removed, and all name and    }
  2973. { extension components are truncated to 8 and 3 characters. The }
  2974. { returned value is Dest.                            }
  2975. Asm
  2976.   push ds
  2977.   cld
  2978.   lds si,Name
  2979.   lea di,TempStr
  2980.   push ss
  2981.   pop es
  2982.   lodsw
  2983.   or  al,al
  2984.   je  @@1
  2985.   cmp ah,':'
  2986.   jne @@1
  2987.   cmp al,'a'
  2988.   jb  @@2
  2989.   cmp al,'z'
  2990.   ja  @@2
  2991.   sub al,20H
  2992.   jmp @@2
  2993. @@1:
  2994.   dec si
  2995.   dec si
  2996.   mov ah,19H
  2997.   int DOS
  2998.   add al,'A'
  2999.   mov ah,':'
  3000. @@2:
  3001.   stosw
  3002.   cmp [si].Byte,'\'
  3003.   je  @@3
  3004.   sub al,'A'-1
  3005.   mov dl,al
  3006.   mov al,'\'
  3007.   stosb
  3008.   push ds
  3009.   push si
  3010.   mov ah,47H
  3011.   mov si,di
  3012.   push es
  3013.   pop ds
  3014.   int DOS
  3015.   pop si
  3016.   pop ds
  3017.   jc  @@3
  3018.   sub al,al
  3019.   cmp al,es:[di]
  3020.   je  @@3
  3021. {$IFDEF Windows}
  3022.   push es
  3023.   push es
  3024.   push di
  3025.   push es
  3026.   push di
  3027.   call OemToAnsi
  3028.   pop es
  3029. {$ENDIF}
  3030.   mov cx,0FFFFH
  3031.   sub al,al
  3032.   cld
  3033.   repne    scasb
  3034.   dec di
  3035.   mov al,'\'
  3036.   stosb
  3037. @@3:
  3038.   mov cx,fsFileName
  3039. @@4:
  3040.   lodsb
  3041.   or  al,al
  3042.   je  @@7
  3043.   cmp al,'\'
  3044.   je  @@7
  3045.   cmp al,'.'
  3046.   je  @@6
  3047.   jcxz @@4
  3048.   dec cx
  3049. {$IFNDEF Windows}
  3050.   cmp al,'a'
  3051.   jb  @@5
  3052.   cmp al,'z'
  3053.   ja  @@5
  3054.   sub al,20H
  3055. {$ENDIF}
  3056. @@5:
  3057.   stosb
  3058.   jmp @@4
  3059. @@6:
  3060.   mov cl,3
  3061.   jmp @@5
  3062. @@7:
  3063.   cmp es:[di-2].Word,'.\'
  3064.   jne @@8
  3065.   dec di
  3066.   dec di
  3067.   jmp @@10
  3068. @@8:
  3069.   cmp es:[di-2].Word,'..'
  3070.   jne @@10
  3071.   cmp es:[di-3].Byte,'\'
  3072.   jne @@10
  3073.   sub di,3
  3074.   cmp es:[di-1].Byte,':'
  3075.   je  @@10
  3076. @@9:
  3077.   dec di
  3078.   cmp es:[di].Byte,'\'
  3079.   jne @@9
  3080. @@10:
  3081.   mov cl,fsFileName
  3082.   or  al,al
  3083.   jne @@5
  3084.   cmp es:[di-1].Byte,':'
  3085.   jne @@11
  3086.   mov al,'\'
  3087.   stosb
  3088. @@11:
  3089.   lea si,TempStr
  3090.   push ss
  3091.   pop ds
  3092.   mov cx,di
  3093.   sub cx,si
  3094.   cmp cx,fsPathName
  3095.   jbe @@12
  3096.   mov cx,fsPathName
  3097. @@12:
  3098.   les di,Dest
  3099.   push es
  3100.   push di
  3101. {$IFDEF Windows}
  3102.   push es
  3103.   push di
  3104. {$ENDIF}
  3105.   rep movsb
  3106.   sub al,al
  3107.   stosb
  3108. {$IFDEF Windows}
  3109.   call AnsiUpper
  3110. {$ENDIF}
  3111.   pop ax
  3112.   pop dx
  3113.   pop ds
  3114. End; { FileExpand }
  3115.  
  3116. {$W+}
  3117. Function FileSplit;
  3118. { FileSplit splits the file name specified by Path into its     }
  3119. { three components. Dir is set to the drive and directory path  }
  3120. { with any leading and trailing backslashes, Name is set to the }
  3121. { file name, and Ext is set to the extension with a preceding   }
  3122. { period. If a component string parameter is NIL, the           }
  3123. { corresponding part of the path is not stored. If the path     }
  3124. { does not contain a given component, the returned component    }
  3125. { string is empty. The maximum lengths of the strings returned  }
  3126. { in Dir, Name, and Ext are defined by the fsDirectory,         }
  3127. { fsFileName, and fsExtension constants. The returned value is  }
  3128. { a combination of the fcDirectory, fcFileName, and fcExtension }
  3129. { bit masks, indicating which components were present in the    }
  3130. { path. If the name or extension contains any wildcard          }
  3131. { characters (* or ?), the fcWildcards flag is set in the       }
  3132. { returned value.                                               }
  3133. var
  3134.   DirLen, NameLen, Flags : word;
  3135.   NamePtr, ExtPtr : PChar;
  3136. begin
  3137.   NamePtr := StrRScan(Path, '\');
  3138.   if NamePtr = nil then NamePtr := StrRScan(Path, ':');
  3139.   if NamePtr = nil then NamePtr := Path else Inc(NamePtr);
  3140.   ExtPtr := StrScan(NamePtr, '.');
  3141.   if ExtPtr = nil then ExtPtr := StrEnd(NamePtr);
  3142.   DirLen := NamePtr - Path;
  3143.   if DirLen > fsDirectory then DirLen := fsDirectory;
  3144.   NameLen := ExtPtr - NamePtr;
  3145.   if NameLen > fsFilename then NameLen := fsFilename;
  3146.   Flags := 0;
  3147.   if (StrScan(NamePtr, '?') <> nil) or (StrScan(NamePtr, '*') <> nil) then
  3148.     Flags := fcWildcards;
  3149.   if DirLen <> 0 then Flags := Flags or fcDirectory;
  3150.   if NameLen <> 0 then Flags := Flags or fcFilename;
  3151.   if ExtPtr[0] <> #0 then Flags := Flags or fcExtension;
  3152.   if Dir <> nil then StrLCopy(Dir, Path, DirLen);
  3153.   if Name <> nil then StrLCopy(Name, NamePtr, NameLen);
  3154.   if Ext <> nil then StrLCopy(Ext, ExtPtr, fsExtension);
  3155.   FileSplit := Flags;
  3156. End; { FileSplit }
  3157. {$W-}
  3158.  
  3159. Function DefaultErrorProc(ErrCode : integer; FuncCode : word) : byte; far; assembler;
  3160. { Default error handler procedure called from EnhDOS functions }
  3161. Asm
  3162.   sub al,al   { mov al,frOk }
  3163. End; { DefaultErrorProc }
  3164.  
  3165. const WrongDOSVersion : PChar = 'DOS 3.1 or greater required.'#13#10'$';
  3166.  
  3167. Begin
  3168.   asm
  3169.     call GetDosVersion
  3170.     xchg ah,al
  3171.     cmp ax,0300h
  3172.     jg  @continue { if greater than 3.0 then continue, else exit }
  3173.     lds dx,WrongDOSVersion
  3174.     mov ah,09h
  3175.     int DOS
  3176.   @halt:
  3177.     mov ah,4Ch
  3178.     int DOS
  3179.   @continue:
  3180.     {$IFOPT G+}
  3181.     push seg [DefaultErrorProc]
  3182.     push offset [DefaultErrorProc]
  3183.     {$ELSE}
  3184.     mov ax,seg [DefaultErrorProc]
  3185.     push ax
  3186.     mov ax,offset [DefaultErrorProc]
  3187.     push ax
  3188.     {$ENDIF}
  3189.     call SetErrorHandler { set default error handler }
  3190.     mov DOSResult,dosrOk
  3191.   end;
  3192. End. { EnhDOS+ }
  3193. *