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 }