Contributor: JON JASIUNAS             
{
From: JON JASIUNAS
Subj: Share Multi-tasking
}
{**************************
 *     SHARE.PAS v1.0     *
 *                        *
 *  General purpose file  *
 *    sharing routines    *
 **************************
1992-93 HyperDrive Software
Released into the public domain.}
{$S-,R-,D-}
{$IFOPT O+}
  {$F+}
{$ENDIF}
unit Share;
{\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\}
                                   interface
{/////////////////////////////////////////////////////////////////////////////}
const
  MaxLockRetries : Byte = 10;
  NormalMode = $02; { ---- 0010 }
  ReadOnly   = $00; { ---- 0000 }
  WriteOnly  = $01; { ---- 0001 }
  ReadWrite  = $02; { ---- 0010 }
  DenyAll    = $10; { 0001 ---- }
  DenyWrite  = $20; { 0010 ---- }
  DenyRead   = $30; { 0011 ---- }
  DenyNone   = $40; { 0100 ---- }
  NoInherit  = $70; { 1000 ---- }
type
  Taskers = (NoTasker, DesqView, DoubleDOS, Windows, OS2, NetWare);
var
  MultiTasking: Boolean;
  MultiTasker : Taskers;
  VideoSeg    : Word;
  VideoOfs    : Word;
procedure SetFileMode(Mode: Word);
  {- Set filemode for typed/untyped files }
procedure ResetFileMode;
  {- Reset filemode to ReadWrite (02h) }
procedure LockFile(var F);
  {- Lock file F }
procedure UnLockFile(var F);
  {- Unlock file F }
procedure LockBytes(var F;  Start, Bytes: LongInt);
  {- Lock Bytes bytes of file F, starting with Start }
procedure UnLockBytes(var F;  Start, Bytes: LongInt);
  {- Unlock Bytes bytes of file F, starting with Start }
procedure LockRecords(var F;  Start, Records: LongInt);
  {- Lock Records records of file F, starting with Start }
procedure UnLockRecords(var F;  Start, Records: LongInt);
  {- Unlock Records records of file F, starting with Start }
function  TimeOut: Boolean;
  {- Check for LockRetry timeout }
procedure TimeOutReset;
  {- Reset internal LockRetry counter }
function  InDos: Boolean;
  {- Is DOS busy? }
procedure GiveTimeSlice;
  {- Give up remaining CPU time slice }
procedure BeginCrit;
  {- Enter critical region }
procedure EndCrit;
  {- End critical region }
{\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\}
                                 implementation
{/////////////////////////////////////////////////////////////////////////////}
uses
  Dos;
var
  InDosFlag: ^Word;
  LockRetry: Byte;
{=============================================================================}
procedure FLock(Handle: Word; Pos, Len: LongInt);
Inline(
  $B8/$00/$5C/    {  mov   AX,$5C00        ;DOS FLOCK, Lock subfunction}
  $8B/$5E/$04/    {  mov   BX,[BP + 04]    ;Place file handle in Bx register}
  $C4/$56/$06/    {  les   DX,[BP + 06]    ;Load position in ES:DX}
  $8C/$C1/        {  mov   CX,ES           ;Move ES pointer to CX register}
  $C4/$7E/$08/    {  les   DI,[BP + 08]    ;Load length in ES:DI}
  $8C/$C6/        {  mov   SI,ES           ;Move ES pointer to SI register}
  $CD/$21);       {  int   $21             ;Call DOS}
{-----------------------------------------------------------------------------}
procedure FUnlock(Handle: Word; Pos, Len: LongInt);
Inline(
  $B8/$01/$5C/    {  mov   AX,$5C01        ;DOS FLOCK, Unlock subfunction}
  $8B/$5E/$04/    {  mov   BX,[BP + 04]    ;Place file handle in Bx register}
  $C4/$56/$06/    {  les   DX,[BP + 06]    ;Load position in ES:DX}
  $8C/$C1/        {  mov   CX,ES           ;Move ES pointer to CX register}
  $C4/$7E/$08/    {  les   DI,[BP + 08]    ;Load length in ES:DI}
  $8C/$C6/        {  mov   SI,ES           ;Move ES pointer to SI register}
  $CD/$21);       {  int   $21             ;Call DOS}
{=============================================================================}
procedure SetFileMode(Mode: Word);
begin
  FileMode := Mode;
end;    { SetFileMode }
{-----------------------------------------------------------------------------}
procedure ResetFileMode;
begin
  FileMode := NormalMode;
end;    { ResetFileMode }
{-----------------------------------------------------------------------------}
procedure LockFile(var F);
begin
  If not MultiTasking then
    Exit;
  While InDos do
    GiveTimeSlice;
  FLock(FileRec(F).Handle, 0, FileSize(File(F)));
end;    { LockFile }
{-----------------------------------------------------------------------------}
procedure UnLockFile(var F);
begin
  If not MultiTasking then
    Exit;
  While InDos do
    GiveTimeSlice;
  FLock(FileRec(F).Handle, 0, FileSize(File(F)));
end;    { UnLockFile }
{-----------------------------------------------------------------------------}
procedure LockBytes(var F;  Start, Bytes: LongInt);
begin
  If not MultiTasking then
    Exit;
  While InDos do
    GiveTimeSlice;
  FLock(FileRec(F).Handle, Start, Bytes);
end;    { LockBytes }
{-----------------------------------------------------------------------------}
procedure UnLockBytes(var F;  Start, Bytes: LongInt);
begin
  If not MultiTasking then
    Exit;
  While InDos do
    GiveTimeSlice;
  FLock(FileRec(F).Handle, Start, Bytes);
end;    { UnLockBytes }
{-----------------------------------------------------------------------------}
procedure LockRecords(var F;  Start, Records: LongInt);
begin
  If not MultiTasking then
    Exit;
  While InDos do
    GiveTimeSlice;
  FLock(FileRec(F).Handle, Start * FileRec(F).RecSize, Records * FileRec(F).Rec
end;    { LockBytes }
{-----------------------------------------------------------------------------}
procedure UnLockRecords(var F;  Start, Records: LongInt);
begin
  If not MultiTasking then
    Exit;
  While InDos do
    GiveTimeSlice;
  FLock(FileRec(F).Handle, Start * FileRec(F).RecSize, Records * FileRec(F).Rec
end;    { UnLockBytes }
{-----------------------------------------------------------------------------}
function  TimeOut: Boolean;
begin
  GiveTimeSlice;
  TimeOut := True;
  If MultiTasking and (LockRetry < MaxLockRetries) then
    begin
      TimeOut := False;
      Inc(LockRetry);
    end;  { If }
end;    { TimeOut }
{-----------------------------------------------------------------------------}
procedure TimeOutReset;
begin
  LockRetry := 0;
end;    { TimeOutReset }
{-----------------------------------------------------------------------------}
function  InDos: Boolean;
begin   { InDos }
  InDos := InDosFlag^ > 0;
end;    { InDos }
{-----------------------------------------------------------------------------}
procedure GiveTimeSlice;  ASSEMBLER;
asm     { GiveTimeSlice }
  cmp   MultiTasker, DesqView
  je    @DVwait
  cmp   MultiTasker, DoubleDOS
  je    @DoubleDOSwait
  cmp   MultiTasker, Windows
  je    @WinOS2wait
  cmp   MultiTasker, OS2
  je    @WinOS2wait
  cmp   MultiTasker, NetWare
  je    @Netwarewait
@Doswait:
  int   $28
  jmp   @WaitDone
@DVwait:
  mov   AX,$1000
  int   $15
  jmp   @WaitDone
@DoubleDOSwait:
  mov   AX,$EE01
  int   $21
  jmp   @WaitDone
@WinOS2wait:
  mov   AX,$1680
  int   $2F
  jmp   @WaitDone
@Netwarewait:
  mov   BX,$000A
  int   $7A
  jmp   @WaitDone
@WaitDone:
end;    { TimeSlice }
{----------------------------------------------------------------------------}
procedure BeginCrit;  ASSEMBLER;
asm     { BeginCrit }
  cmp   MultiTasker, DesqView
  je    @DVCrit
  cmp   MultiTasker, DoubleDOS
  je    @DoubleDOSCrit
  cmp   MultiTasker, Windows
  je    @WinCrit
  jmp   @EndCrit
@DVCrit:
  mov   AX,$101B
  int   $15
  jmp   @EndCrit
@DoubleDOSCrit:
  mov   AX,$EA00
  int   $21
  jmp   @EndCrit
@WinCrit:
  mov   AX,$1681
  int   $2F
  jmp   @EndCrit
@EndCrit:
end;    { BeginCrit }
{----------------------------------------------------------------------------}
procedure EndCrit;  ASSEMBLER;
asm     { EndCrit }
  cmp   MultiTasker, DesqView
  je    @DVCrit
  cmp   MultiTasker, DoubleDOS
  je    @DoubleDOSCrit
  cmp   MultiTasker, Windows
  je    @WinCrit
  jmp   @EndCrit
@DVCrit:
  mov   AX,$101C
  int   $15
  jmp   @EndCrit
@DoubleDOSCrit:
  mov   AX,$EB00
  int   $21
  jmp   @EndCrit
@WinCrit:
  mov   AX,$1682
  int   $2F
  jmp   @EndCrit
@EndCrit:
end;    { EndCrit }
{============================================================================}
begin { Share }
  {- Init }
  LockRetry:= 0;
  asm
  @CheckDV:
    mov   AX, $2B01
    mov   CX, $4445
    mov   DX, $5351
    int   $21
    cmp   AL, $FF
    je    @CheckDoubleDOS
    mov   MultiTasker, DesqView
    jmp   @CheckDone
  @CheckDoubleDOS:
    mov   AX, $E400
    int   $21
    cmp   AL, $00
    je    @CheckWindows
    mov   MultiTasker, DoubleDOS
    jmp   @CheckDone
  @CheckWindows:
    mov   AX, $1600
    int   $2F
    cmp   AL, $00
    je    @CheckOS2
    cmp   AL, $80
    je    @CheckOS2
    mov   MultiTasker, Windows
    jmp   @CheckDone
  @CheckOS2:
    mov   AX, $3001
    int   $21
    cmp   AL, $0A
    je    @InOS2
    cmp   AL, $14
    jne   @CheckNetware
  @InOS2:
    mov   MultiTasker, OS2
    jmp   @CheckDone
  @CheckNetware:
    mov   AX,$7A00
    int   $2F
    cmp   AL,$FF
    jne   @NoTasker
    mov   MultiTasker, NetWare
    jmp   @CheckDone
  @NoTasker:
    mov   MultiTasker, NoTasker
  @CheckDone:
  {-Set MultiTasking }
    cmp   MultiTasker, NoTasker
    mov   VideoSeg, $B800
    mov   VideoOfs, $0000
    je    @NoMultiTasker
    mov   MultiTasking, $01
  {-Get video address }
    mov   AH, $FE
    les   DI, [$B8000000]
    int   $10
    mov   VideoSeg, ES
    mov   VideoOfs, DI
    jmp   @Done
  @NoMultiTasker:
    mov   MultiTasking, $00
  @Done:
  {-Get InDos flag }
    mov   AH, $34
    int   $21
    mov   WORD PTR InDosFlag, BX
    mov   WORD PTR InDosFlag + 2, ES
  end;  { asm }
end.  { Share }