home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 12
/
CD_ASCQ_12_0294.iso
/
news
/
563
/
nwtp04
/
nwsema.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-01-01
|
14KB
|
394 lines
{$X+,V-,B-}
Unit nwSema;
{ nwSema unit as of 931228 / NwTP 0.4 API. (c) 1994, R.Spronk }
INTERFACE
{ Primary functions: Interrupt: comments:
* OpenSemaphore (F220/00)
* ExamineSemaphore (F220/01)
* WaitOnSemaphore (F220/02)
* SignalSemaphore (F220/03)
* CloseSemaphore (F220/04)
GetSemaphoreInformation (F217/F3)
Notes: -Functions marked with a '*' are tested and found correct.
}
Uses nwMisc;
Var Result:word;
{C500 [2.0/2.1/3.x]}
FUNCTION OpenSemaphore( SemName :String; InitVal :Integer;
VAR SemHandle :LongInt;
VAR OpenCount :Word ) :Boolean;
{ Semaphores are used for exclusion when record locking is not appropriate }
{ The value is set the first time the semaphore is opened, thereafter you }
{ must use wait semaphore or signal semaphore to change the value }
{C501 [2.0/2.1/3.x]}
FUNCTION ExamineSemaphore( SemHandle :LongInt;
VAR Value :Integer;
VAR OpenCount :Word ) :Boolean;
{ This functions returns the current value and open count of a semaphore.}
{ The semaphore value is decremented for each WAIT_ON_SEMAPHORE, }
{ and incremented for each SIGNAL_SEMAPHORE. A negative semaphore }
{ value indicates the number of processes waiting to use the semaphore. }
{ Count is the number of processes that are using the same semaphore.}
{ The open count is incremented any time a station opens the semaphore }
{ This can be used for controlling the number of users using your software }
{ Value is the current value associates with the semaphore. }
{C502 [2.0/2.1/3.x]}
FUNCTION WaitOnSemaphore( SemHandle :LongInt;
Wait_Time :Word ) :Boolean;
{ Decrement the semaphore value and, if it is negative, }
{ wait until it becomes non-negative or until a }
{ timeout occurs. }
{C503 [2.0/2.1/3.x]}
FUNCTION SignalSemaphore(SemHandle:LongInt) : Boolean;
{ Increment the semaphore value and release if waiting. If any stations }
{ are waiting, the station that has been waiting the longest will be }
{ signalled to proceed }
{C504 [2.0/2.1/3.x]}
FUNCTION CloseSemaphore(SemHandle:LongInt) : Boolean;
{ Decrement the open count of a semaphore.}
{ When the open count goes to zero, the semaphore is destroyed. }
{ In other words: if the requesting process is the last process to have
this semaphore open, the semaphore is deleted.}
IMPLEMENTATION {=============================================================}
uses dos;
{F:C500 [2.x/3.x]}
FUNCTION OpenSemaphore(SemName : String; InitVal : Integer;
VAR SemHandle : LongInt;
VAR OpenCount : Word) : Boolean;
Var Regs:Registers;
BEGIN
WITH Regs
DO BEGIN
IF (InitVal < 0) OR (InitVal > 127)
THEN BEGIN
Result:=$FF; { Invalid Semaphore Value }
OpenSemaphore := False; { InitVal must be between 0 and 127 }
Exit;
END;
IF (SemName[0]>#127) { Semaphore must not exceed 127 chars }
THEN BEGIN
Result:=$FE; { Invalid Semaphore name Length }
OpenSemaphore := false;
Exit;
END;
AH := $C5; { Semaphore function }
AL := $00; { Sub-Function 0 = open }
DS := Seg(SemName); { DS:DX points to name }
DX := Ofs(SemName); { Byte 0 = length 0..127 }
CL := InitVal; { Initial Value 0..127 }
MsDos(Regs); { Give it to Int 21h }
OpenCount := BL; { Number of users using this semaphore }
Result:=AL;
OpenSemaphore := (AL = 0); { OK if AL comes back as 0 }
{ FEh Invalid Semaphore Name Length}
{ FFh Invalid Semaphore Value }
SemHandle:=MakeLong(CX,DX); { CX:DX holds the semaphore handle }
END; { with Regs do }
END; {Function Open_Semaphore }
{F:C501 [2.x/3.x]}
FUNCTION ExamineSemaphore(SemHandle:LongInt;
VAR Value : Integer;
VAR OpenCount : Word ) : Boolean;
{ The semaphore value that comes back in CL is the count from the open call }
{ DL represents the current open count - the open count is incremented }
{ anytime a station opens the semaphore this can be used for controlling }
{ the number of users using your software }
Var Regs:Registers;
BEGIN
WITH Regs
DO BEGIN
AH := $C5; { Semaphore function call }
AL := 1; { Sub-Function 1 = examine }
CX := HiLong(SemHandle);
DX := LowLong(SemHandle);
MsDos(Regs); { Give it to DOS }
Value := CX; { Semaphore value in CX }
OpenCount := DL; { Number using this semaphore }
Result := AL; { AL = $FF invalid handle }
ExamineSemaphore := (AL = 0); { AL = 0 means OK }
END;
END; { function Examine_Semaphore }
{F:C502 [2.x/3.x]}
FUNCTION WaitOnSemaphore( SemHandle : LongInt;
Wait_Time : Word ) : Boolean;
{ Decrement the semaphore value and wait if it is negative. If negative,}
{ the workstation will wait until it becomes non-negative or until a }
{ timeout occurs. }
Var regs:registers;
BEGIN
WITH Regs
DO BEGIN
AH := $C5; { Semaphore function call }
AL := 2; { Sub-Function 2 = wait }
BP := Wait_Time; { In 1/18 seconds, 0 = No wait }
CX := HiLong(SemHandle);
DX := LowLong(SemHandle);
MsDos(Regs); { Give it to DOS }
Result:=AL;
WaitOnSemaphore := (AL = 0); { AL = $00 means OK,
$FE timeout failure,
$FF Invalid handle }
END;
END; { function Wait_Semaphore }
{C503 [2.x/3.x]}
FUNCTION SignalSemaphore(SemHandle:LongInt) : Boolean;
{ Increment the semaphore value and release if waiting. If any stations}
{ are waiting, the station that has been waiting the longest will be }
{ signalled to proceed }
Var Regs:Registers;
BEGIN
WITH Regs
DO BEGIN
AH := $C5; { Semaphore function call }
AL := 3; { Sub-Function 3 = signal }
CX := HiLong(SemHandle);
DX := LowLong(SemHandle);
MsDos(Regs); { Give it to DOS }
Result:=AL;
SignalSemaphore := (AL = 0); { AL = $00 means OK, else
$01 overflow ( value > 127 ) or
$FF Invalid handle }
END;
END; { function Signal_Semaphore }
{C504 [2.x/3.x]}
FUNCTION CloseSemaphore(SemHandle:LongInt) : Boolean;
{ Decrement the open count of a semaphore. When the open count goes }
{ to zero, the semaphore is destroyed. }
Var Regs:Registers;
BEGIN
WITH Regs
DO BEGIN
AH := $C5; { Semaphore function call }
AL := 04; { Sub-Function 4 = close }
CX := HiLong(SemHandle);
DX := LowLong(SemHandle);
MsDos(Regs); { Give it to DOS }
Result:=AL;
CloseSemaphore := (AL = 0); { AL = 0 means OK, FF: Invalid handle }
END;
END; { function Close_Semaphore }
{E3E1 [2.1x/2.2]
GET CONNECTION'S SEMAPHORES
AH = E3h subfn E1h
DS:SI -> request buffer (see below)
ES:DI -> reply buffer (see below)
Return: AL = status
00h successful
C6h no console rights
Notes: this function is supported by Advanced NetWare 2.1+
the calling workstation must have console operator privileges
SeeAlso: AH=E3h/SF=C8h,AH=E3h/SF=DBh,AH=E3h/SF=DFh,AH=E3h/SF=E2h
Format of request buffer:
Offset Size Description
00h WORD 0005h (length of following data)
02h BYTE E1h (subfunction "Get Connection's Semaphores")
03h WORD (big-endian) logical connection number
05h WORD (big-endian) last record seen (0000h on first call)
Format of reply buffer:
Offset Size Description
00h WORD (call) size of following results record (max 1FEh)
02h WORD next request record (place in "last record" field on next call)
04h BYTE number of records following
05h var array of Semaphore Information Records
Format of Semaphore Information Record:
Offset Size Description
00h WORD (big-endian) open count
02h BYTE semaphore value (-128 to 127)
03h BYTE task number
04h BYTE lock type
05h BYTE length of semaphore's name
06h N BYTEs semaphore's name
14 BYTEs filename}
{E3E2 [2.1x/2.2]
GET SEMAPHORE INFORMATION
AH = E3h subfn E2h
DS:SI -> request buffer (see below)
ES:DI -> reply buffer (see below)
Return: AL = status
00h successful
C6h no console rights
Notes: this function is supported by Advanced NetWare 2.1+
the calling workstation must have console operator privileges
SeeAlso: AH=E3h/SF=C8h,AH=E3h/SF=E1h
Format of request buffer:
Offset Size Description
00h WORD length of following data (max 83h)
02h BYTE E2h (subfunction "Get LAN Driver's Configuration Information")
03h WORD (big-endian) last record seen (0000h on first call)
05h BYTE length of semaphore's name (01h-7Fh)
06h N BYTEs semaphore's name
Format of reply buffer:
Offset Size Description
00h WORD (call) size of following results buffer (max 1FEh)
02h WORD next request record (place in "last record" on next call)
0000h if no more
04h WORD (big-endian) number of logical connections opening semaphore
06h BYTE semaphore value (-127 to 128)
07h BYTE number of records following
08h var array of Semaphore Information records (see below)
Format of Semaphore Information:
Offset Size Description
00h WORD (big-endian) logical connection number
02h BYTE task number}
{F217/F3 [3.11+]}
Function GetSemaphoreInformation(SemaName:string;
{i/o:} Var ReqRecordNbr:Integer;
{out:} Var openCount:word;
Var semValue:byte;
Var connections:TconnectionList):boolean;
{ This call returns information about a single semaphore. The
values returned are similiar to those returned in the old
version of this call. This function may be called iteratively
to return all of the connection information for the specified
semaphore. }
{ 2.x: ?? if there are no more records, ReqRecordNbr is set to 0... }
{ need console rights to do this.. }
{ The function returns the connectionNumbers and taskNumbers as words.
for the sake of compatibilty, they are returned as bytes. Not too many
>250 user licences floating around.. I hope.. }
Var req:record
len :word; {lo-hi !}
subF :byte;
lastRec :word; {hi-lo, initially 0 }
_semaName:string; { max len=128 }
end;
reply:record
nextRec :word; {hi-lo }
_OpenCount :word; {hi-lo }
_semValue :byte;
{ ?? Opencount:byte en semvalue:word ?? }
NumberOfRecords:word; {hi-lo }
_connTask:array[1..100] of record
connNbr, {hi-lo !}
taskNbr:word; {hi-lo !}
end;
end;
regs:registers;
t:byte;
BEGIN
With req
do begin
subF:=$F3;
if ReqRecordNbr=-1
then lastRec:=0 { correct false initial value.}
else lastRec:=swap(ReqRecordNbr); {force hi-lo}
_semaName:=semaName; UpString(_semaName);
if semaName[0]>#127 then _semaName[0]:=#127;
len:=ord(semaName[0])+6;
end;
With regs
do begin
ax := $f217;
ds:=SEG(req); si := OFs(req);
cx:=sizeOf(req);
es:=SEG(reply); di := OFs(reply);
dx:=sizeOf(reply);
MsDos(regs);
result:=al;
end;
If result=0
then with reply
do begin
FillChar(connections,sizeOf(connections),#0);
for t:=0 to swap(NumberOfRecords) { <= 100, force lo-hi }
do begin
if _connTask[t].connNbr<=$FF
then connections[t]:=hi(_connTask[t].connNbr); {= LO}
end;
Opencount:=swap(_opencount); { force lo-hi }
ReqRecordNbr:=swap(nextRec); { force lo-hi }
semValue:=_semValue;
end;
GetSemaphoreInformation:=(result=0);
end;
{F2/ [2.15c+]
Function ( {i/o:} {out: :boolean;
Var req:record
len :word;
subF :byte;
end;
reply:record
end;
regs:registers;
BEGIN
With req
do begin
subF:=
len:=
end;
With regs
do begin
ax := $f217;
ds:=SEG(req); si := OFs(req);
cx:=sizeOf(req);
es:=SEG(reply); di := OFs(reply);
dx:=sizeOf(reply);
MsDos(regs);
result:=al;
end;
If result=0
then with reply
do begin
end;
:=(result=0);
end;}
BEGIN
END.