unit ULDrvUtl;
interface
uses
  Windows, Registry,
  WinIOCtl, ULDrvTyp,
  UtlType, WinUtl, BinHex, DevMode;

function UL_IO(fn: DWORD): DWORD;
function UL_IOR(fn: DWORD): DWORD;
function UL_IOW(fn: DWORD): DWORD;

function UL_NEWMSG: DWORD;
function UL_TAILMSG: DWORD;
function UL_FREEMSG: DWORD;
function  UL_ACCEPTMSG: DWORD;
function UL_ACTAILMSG: DWORD;
function UL_ADDFILT: DWORD;
function UL_ABORTMSG: DWORD;
function UL_REWMSG: DWORD;
function UL_INEPOLL: DWORD;
function UL_KLOGBLL: DWORD;
function UL_STROKE: DWORD;
function UL_DEBFLG: DWORD;

{v0.11}
{v0.21}
function ULDrvReqReadWrite(read:boolean; var APortAddr: integer;
  var APortIrq: integer; var APCUlanAddr: integer;
  var AUlanBaudRate: integer{v0.49}; var AStartType: TDevDrvStartType{/v0.49}): integer;
  { if read then read parameters from registry, if not found there,
    remain unchanged;
    if not read then write the parameters to registry.
    Returns:
      -1 for recursive call
      if read then:
        0 if read ok from registry,
        otherwise returns number of errors encountered
        (number of not found in reg events)
      if not read then:
        0 if written to reg ok,
        either number of errors or code of the last error
  }

{/v0.21
procedure ULDrvReqReadWrite(read:boolean; var APortAddr: integer;
  var APortIrq: integer; var APCUlanAddr: integer);
  { if read then read parameters from registry, if not found there,
    remain unchanged;
    if not read then write the parameters to registry }
{/v0.11}

{v0.50}
function ULMessageGetLogStr(const AMessage: TULMessage): string;
{/v0.50}

implementation

function UL_IO(fn: DWORD): DWORD;
begin
  UL_IO := CTL_CODE(FILE_DEVICE_ULAN, UL_IOCTL_INDEX + fn,
    METHOD_BUFFERED, FILE_ANY_ACCESS)
end;

function UL_IOR(fn: DWORD): DWORD;
begin
  UL_IOR := CTL_CODE(FILE_DEVICE_ULAN, UL_IOCTL_INDEX + fn,
    METHOD_BUFFERED, FILE_ANY_ACCESS)
end;

function UL_IOW(fn: DWORD): DWORD;
begin
  UL_IOW := CTL_CODE(FILE_DEVICE_ULAN, UL_IOCTL_INDEX + fn,
    METHOD_BUFFERED, FILE_ANY_ACCESS)
end;

function UL_NEWMSG:DWORD;
begin
  UL_NEWMSG := UL_IOW($11);
end;

function UL_TAILMSG:DWORD;
begin
  UL_TAILMSG := UL_IOW($12)
end;

function UL_FREEMSG:DWORD;
begin
  UL_FREEMSG :=	UL_IO($13)
end;

function  UL_ACCEPTMSG:DWORD;
begin
  UL_ACCEPTMSG := UL_IOR($14);
end;

function  UL_ACTAILMSG:DWORD;
begin
  UL_ACTAILMSG := UL_IOR($15);
end;

function  UL_ADDFILT:DWORD;
begin
  UL_ADDFILT := UL_IOW($16);
end;

function UL_ABORTMSG: DWORD;
begin
  UL_ABORTMSG := UL_IO($17);
end;

function UL_REWMSG: DWORD;
begin
  UL_REWMSG := UL_IO($18);
end;

function UL_INEPOLL: DWORD;
begin
  UL_INEPOLL := UL_IO($19);
end;

function UL_KLOGBLL: DWORD;
begin
  UL_KLOGBLL := UL_IO($41);
end;

function UL_STROKE: DWORD;
begin
  UL_STROKE := UL_IO($42);
end;

function UL_DEBFLG: DWORD;
begin
  UL_DEBFLG := UL_IO($43)
   { arg = new debug mask }
end;

{v0.11}
const
  IsInRW:boolean = false;

{v0.21}
function ULDrvReqReadWrite(read:boolean; var APortAddr: integer;
  var APortIrq: integer; var APCUlanAddr: integer;
  var AUlanBaudRate: integer{v0.49};var AStartType: TDevDrvStartType{/v0.49}): integer;
{/v0.21
procedure ULDrvReqReadWrite(read:boolean; var APortAddr: integer;
  var APortIrq: integer; var APCUlanAddr: integer
  );}

const
{ RootKey = 'HKEY_LOCAL_MACHINE';}
  ServicesPath = '\SYSTEM\CurrentControlSet\Services';
  UlKey = 'ul_drv';
  ParKey = 'Parameters';

var
  tPortAddr: integer;
  tPortIrq: integer;
  tPCUlanAddr: integer;
  {v0.21}
  tUlanBaudRate: integer;
  {/v0.21}

var r: TRegistry;
begin
  {v0.21}
  Result := -1;
  {/v0.21}
  if IsInRW then
    exit;
  IsInRw := true;
  r := nil;
  try
  r := TRegistry.Create;
  {v0.49 delphi bug}{/v0.49
  r.LazyWrite := false;}
  r.RootKey := HKEY_LOCAL_MACHINE;
  if r.OpenKey(ServicesPath, false) then begin
    {v0.49}
    try
    {/v0.49}

    if r.OpenKey(UlKey, {v0.21} not read{/v0.21 true}) then begin
      {v0.21}
      if not read then
      {/v0.21}
      begin
        r.WriteInteger('Type', 1);
        r.WriteInteger('Start', {v0.49}ord(AStartType){/v0.49 1});
        r.WriteInteger('ErrorControl', 1);
        {v0.49}
        r.WriteString('DisplayName', UL_DEV_NAME);
        {/v0.49
        r.WriteString('DisplayName', 'uLan driver');}
        r.WriteString('Group', 'port');
        r.WriteInteger('Tag', 1);
      end {v0.49} else begin
        AStartType := TDevDrvStartType(r.ReadInteger('Start'));
      end{/v0.49};
      r.CloseKey;

      if r.OpenKey(ServicesPath + '\' + UlKey, false) then begin
        if r.OpenKey(ParKey, {v0.21} not read {/v0.21 true}) then begin
          if read then begin
            try
              tPortAddr := r.ReadInteger('Port Address');
            except
              tPortAddr := APortAddr;
              {v0.21}
              inc(Result);
              {/v0.21}
            end;
            APortAddr := tPortAddr;
          end{v0.21} else {/v0.21 ;}
            r.WriteInteger('Port Address', APortAddr);

          if read then begin                  {regopenkeyex}
            try
              tPortIrq := r.ReadInteger('IRQ Line');
            except
              tPortIrq := APortIrq;
              {v0.21}
              inc(Result);
              {/v0.21}
            end;
            APortIrq := tPortIrq;
          end{v0.21} else {/v0.21 ;}
            r.WriteInteger('IRQ Line', APortIrq);

          {v0.21}
          if read then begin
            try
              tUlanBaudRate := r.ReadInteger('Baud Rate');
            except
              tUlanBaudRate := AUlanBaudRate;
              {v0.21}
              inc(Result);
              {/v0.21}
            end;
            AUlanBaudRate := tUlanBaudRate;
          end else
            r.WriteInteger('Baud Rate', AUlanBaudRate);
          {/v0.21}


          {v0.21}
          if not read then
          {/v0.21}
          begin
            {v0.21}{/v0.21 r.WriteInteger('Baud Rate', $2580);}
            r.WriteInteger('Buffer Size', $4000);
          end;

          if read then begin
            try
              tPCUlanAddr := r.ReadInteger('My Addr');
            except
              tPCUlanAddr := APCUlanAddr;
              {v0.21}
              inc(Result);
              {/v0.21}
            end;
            APCUlanAddr := tPCUlanAddr;
          end{v0.21} else {/v0.21 ;}
            r.WriteInteger('My Addr', APCUlanAddr);

          {v0.21}
          if not read then
          {/v0.21}
            r.WriteInteger('Debug', $19);

          r.CloseKey;
        end{v0.21} else inc(Result){/v0.21};
      end{v0.21} else inc(Result){/v0.21};
    end {v0.21} else inc(Result){/v0.21};

    {v0.49}
    finally   {regflushkey}

    end;
    {/v0.49}
  end {v.21} else
    inc(Result){/v0.21};

{
REGEDIT4

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ul_drv]
"Type"=dword:00000001
"Start"=dword:00000001
"ErrorControl"=dword:00000001
"DisplayName"="uLan driver"
"Group"="port"
"Tag"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ul_drv\Parameters]
"Port Address"=dword:000002f8
"IRQ Line"=dword:00000003
"Baud Rate"=dword:00002580
"Buffer Size"=dword:00004000
"My Addr"=dword:00000002
"Debug"=dword:00000019
}
  finally
    r.Free;
    IsInRW := false;
  end;
end;
{/v0.11}

{v0.50}
function ULMessageGetLogStr(const AMessage: TULMessage): string;
var
  s: string;
begin
  s := 'DA:' +  IntToString(AMessage.dadr, 3) + ' SA:' + IntToString(AMessage.sadr, 3) +
    ' CM:' + IntToString(AMessage.cmd, 3) + ' F:$' + LongToHex(AMessage.flg) +
    ' L:' + IntToString(AMessage.len, 3) + ' S:$' + LongToHex(AMessage.flg);
  {
  for i := 0 to sizeof(FMessage)- 1 do begin
    s := s + IntToString(FMessage.Data[i], 4);
  end;
  }
  Result := s;
end;
{/v0.50}


end.
