{ **************************************************************
	Package: XWB - Kernel RPCBroker
	Date Created: Sept 18, 1997 (Version 1.1)
	Site Name: Oakland, OI Field Office, Dept of Veteran Affairs
	Developers: Danila Manapsal, Don Craven, Joel Ivey
	Description: winsock utilities.
	Current Release: Version 1.1 Patch 40 (January 7, 2005))
*************************************************************** }


unit RpcNet ;
{
  Changes in v1.1.13 (JLI -- 8/23/00) -- XWB*1.1*13
    Made changes to cursor dependent on current cursor being crDefault so
       that the application can set it to a different cursor for long or
       repeated processes without the cursor 'flashing' repeatedly.
}
interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, winsock;

Const XWB_GHIP = WM_USER + 10000;
//Const XWB_SELECT = WM_USER + 10001;

Const WINSOCK1_1 = $0101;
Const PF_INET = 2;
Const SOCK_STREAM = 1;
Const IPPROTO_TCP = 6;
Const INVALID_SOCKET = -1;
Const SOCKET_ERROR = -1;
Const FIONREAD = $4004667F;
Const ActiveConnection: boolean = False;

type EchatError = class(Exception);

type
  TRPCFRM1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
    procedure XWBGHIP(var msgSock: TMessage);
    //procedure xwbSelect(var msgSock: TMessage);           //P14
    procedure WndProc(var Message : TMessage); reintroduce; //P14
end;

type
  WinTaskRec = record
     InUse: boolean;
     pTCPResult: Pointer;
     strTemp: string; {generic output string for async calls}
     chrTemp: PChar; {generic out PChar for async calls}
     hTCP: THandle; {pseudo handle for async calls}
     hWin: hWnd; {handle for owner window}
     CallWait: boolean;
     CallAbort: boolean;
     RPCFRM1: TRPCFRM1;
  end;

var
   WRec: array[1..128] of WinTaskRec;
   Hash: array[0..159] of char;

{Windows OS abstraction functions.  Should be taken over by VA Kernel}

function libGetCurrentProcess: word;

{Socket functions using library RPCLIB.DLL, in this case called locally}

//function  libAbortCall(inst: integer): integer; export;   //P14
function  libGetHostIP1(inst: integer; HostName: PChar;
          var outcome: PChar): integer; export;
function  libGetLocalIP(inst: integer; var outcome: PChar): integer; export;
procedure libClose(inst: integer); export;
function  libOpen:integer; export;

function GetTCPError:string;

{Secure Hash Algorithm functions, library SHA.DLL and local interfaces}

function libGetLocalModule: PChar; export;
function GetFileHash(fn: PChar): longint; export;

implementation

uses rpcconf1;

{function shsTest: integer; far; external 'SHA';
procedure shsHash(plain: PChar; size: integer;
          Hash: PChar); far; external 'SHA';}    //Removed in P14

{$R *.DFM}



function libGetCurrentProcess: word;
begin
  Result := GetCurrentProcess;
end;

function libGetLocalIP(inst: integer; var outcome: PChar): integer;
var
   local: PChar;
begin
     local := StrAlloc(255);
     gethostname( local, 255);
     Result := libGetHostIP1(inst, local, outcome);
     StrDispose(local);
end;

function libGetLocalModule: PChar;
var
   tsk: THandle;
   name: PChar;
begin
     tsk := GetCurrentProcess;
     name := StrAlloc(1024);
     GetModuleFilename(tsk, name, 1024);
     Result := name;

end;

function GetFileHash(fn: PChar): longint;
var
   hFn: integer;
   finfo: TOFSTRUCT;
   bytesRead, status: longint;
   tBuf: PChar;

begin
     tBuf := StrAlloc(160);
     hFn := OpenFile(fn, finfo, OF_READ);
     bytesRead := 0;
     status := _lread(hFn, tBuf, sizeof(tBuf));
     while status <> 0 do
     begin
          status := _lread(hFn, tBuf, sizeof(tBuf));
          inc(bytesRead,status);
     end;
     _lclose(hFn);
     StrDispose(tBuf);
     Result := bytesRead;
end;

function libOpen:integer;
var
   inst: integer;
   WSData: TWSADATA;
   RPCFRM1: TRPCFRM1;
begin
     inst := 1; {in this case, no DLL so instance is always 1}
     RPCFRM1 := TRPCFRM1.Create(nil);    //P14
     with WRec[inst] do
     begin
     hWin := AllocateHWnd(RPCFRM1.wndproc);

     WSAStartUp(WINSOCK1_1, WSData);
     WSAUnhookBlockingHook;

     Result := inst;
     InUse := True;
     end;
     RPCFRM1.Release;                    //P14
end;

procedure libClose(inst: integer);
begin

     with WRec[inst] do
     begin
        InUse := False;
        WSACleanup;
        DeallocateHWnd(hWin);
     end;
end;

function libGetHostIP1(inst: integer; HostName: PChar;
         var outcome: PChar): integer;
var
   //RPCFRM1: TRPCFRM1; {P14}
   //wMsg: TMSG;        {P14}
   //hWnd: THandle;     {P14}
   ChangeCursor: Boolean;

begin

   outcome[0] := #0;

   if Screen.Cursor = crDefault then
     ChangeCursor := True
   else
     ChangeCursor := False;
   if ChangeCursor then
     Screen.Cursor := crHourGlass;

   with WRec[inst] do
   begin

   if HostName[0] = #0 then
   begin
        StrCat(outcome,'No Name to Resolve!');
        Result := -1;
        exit;
   end;

   if CallWait = True then
   begin
        outcome[0] := #0;
        StrCat(outcome, 'Call in Progress');
        Result := -1;
        exit;
   end;

   if inet_addr(HostName) > INADDR_ANY then
   begin
        outcome := Hostname;
        Result := 0;
        if ChangeCursor then
          Screen.Cursor := crDefault;
        WSACleanup;
        exit;
   end;

   GetMem(pTCPResult, MAXGETHOSTSTRUCT+1);
   try
      begin
           CallWait := True;
           CallAbort := False;
           PHostEnt(pTCPResult)^.h_name := nil;
           hTCP := WSAAsyncGetHostByName(hWin, XWB_GHIP, HostName,
                pTCPResult, MAXGETHOSTSTRUCT );
           { loop while CallWait is True }
           CallAbort := False;
           while CallWait = True do
                 Application.ProcessMessages;
      end;
   except on EInValidPointer do
     begin
        StrCat(outcome,'Error in GetHostByName');
        if ChangeCursor then
          Screen.Cursor := crDefault;
     end;

   end;

   FreeMem(pTCPResult, MAXGETHOSTSTRUCT+1);
   StrCopy(outcome,chrTemp);
   Result := 0;
   if ChangeCursor then
     Screen.Cursor := crDefault;
   end;
   end;

(*procedure TRPCFRM1.XWBSELECT(var msgSock: TMessage);
var
   noop: integer;
begin
     case msgSock.lparam of
       FD_ACCEPT: {connection arrived}
          begin
               noop := 1;
          end;
       FD_CONNECT: {connection initiated}
          begin
               noop := 1;
          end;
       FD_READ:    {data received, put in display}
          begin
               noop := 1;
          end;
       FD_CLOSE:   {disconnection of accepted socket}
          begin
               noop := 1;
          end;
       else
              noop := 1;
       end;
end;*)     //Procedure removed in P14.

procedure TRPCFRM1.WndProc(var Message : TMessage);
begin
  with Message do
       case Msg of
            {XWB_SELECT : xwbSelect(Message);}    //P14
            XWB_GHIP: xwbghip(Message);
       else
           DefWindowProc(WRec[1].hWin, Msg, wParam, lParam);
           {Inherited WndProc(Message);}
       end;
end;

procedure TRPCFRM1.XWBGHIP(var msgSock: TMessage);
var
   TCPResult: PHostEnt;
   WSAError: integer;
   HostAddr: TSockaddr;
   inst: integer;

begin
   inst := 1; {local case is always 1}


   with WRec[inst] do
   begin

   hTCP := msgSock.WParam;
   
   chrTemp := StrAlloc(512);

   CallWait := False;
   If CallAbort = True then  { User aborted call }
   begin
        StrCopy(ChrTemp,'Abort!');
        exit;
   end;

   WSAError := WSAGetAsyncError(hTCP); { in case async call failed }
   If  WSAError < 0 then
   begin
        StrPCopy(chrTemp,IntToStr(WSAError));
        exit;
   end;

   try
   begin
      TCPResult := PHostEnt(pTCPResult);
      StrTemp := '';
       if TCPResult^.h_name = nil then
         begin
              StrCopy(chrTemp, 'Unknown!');
              if rpcconfig <> nil then
                rpcconfig.panel4.Caption := StrPas(chrTemp);
              exit;
         end;
      {success, return resolved address}
      HostAddr.sin_addr.S_addr := longint(plongint(TCPResult^.h_addr_list^)^);
      chrTemp := inet_ntoa(HostAddr.sin_addr);
   end;
   except on EInValidPointer do StrCat(chrTemp, 'Error in GetHostByName');
   end;
end;
end;

(*function libAbortCall(inst: integer): integer;
var
   WSAError: integer;
begin

   with WRec[inst] do
   begin

   WSAError := WSACancelAsyncRequest(hTCP);
   if WSAError = Socket_Error then
   begin
        WSAError := WSAGetLastError;
        CallWait := False;
        CallAbort := True;
        Result := WSAError;
   end;

   CallAbort := True;
   CallWait := False;
   Result := WSAError;

   end;

end; *)    //Removed in P14

function GetTCPError:string;
var
   x: string;
   r: integer;

begin
      r := WSAGetLastError;
      Case r of
        WSAEINTR           : x := 'WSAEINTR';
        WSAEBADF           : x := 'WSAEINTR';
        WSAEFAULT          : x := 'WSAEFAULT';
        WSAEINVAL          : x := 'WSAEINVAL';
        WSAEMFILE          : x := 'WSAEMFILE';
        WSAEWOULDBLOCK     : x := 'WSAEWOULDBLOCK';
        WSAEINPROGRESS     : x := 'WSAEINPROGRESS';
        WSAEALREADY        : x := 'WSAEALREADY';
        WSAENOTSOCK        : x := 'WSAENOTSOCK';
        WSAEDESTADDRREQ    : x := 'WSAEDESTADDRREQ';
        WSAEMSGSIZE        : x := 'WSAEMSGSIZE';
        WSAEPROTOTYPE      : x := 'WSAEPROTOTYPE';
        WSAENOPROTOOPT     : x := 'WSAENOPROTOOPT';
        WSAEPROTONOSUPPORT : x := 'WSAEPROTONOSUPPORT';
        WSAESOCKTNOSUPPORT : x := 'WSAESOCKTNOSUPPORT';
        WSAEOPNOTSUPP      : x := 'WSAEOPNOTSUPP';
        WSAEPFNOSUPPORT    : x := 'WSAEPFNOSUPPORT';
        WSAEAFNOSUPPORT    : x := 'WSAEAFNOSUPPORT';
        WSAEADDRINUSE      : x := 'WSAEADDRINUSE';
        WSAEADDRNOTAVAIL   : x := 'WSAEADDRNOTAVAIL';
        WSAENETDOWN        : x := 'WSAENETDOWN';
        WSAENETUNREACH     : x := 'WSAENETUNREACH';
        WSAENETRESET       : x := 'WSAENETRESET';
        WSAECONNABORTED    : x := 'WSAECONNABORTED';
        WSAECONNRESET      : x := 'WSAECONNRESET';
        WSAENOBUFS         : x := 'WSAENOBUFS';
        WSAEISCONN         : x := 'WSAEISCONN';
        WSAENOTCONN        : x := 'WSAENOTCONN';
        WSAESHUTDOWN       : x := 'WSAESHUTDOWN';
        WSAETOOMANYREFS    : x := 'WSAETOOMANYREFS';
        WSAETIMEDOUT       : x := 'WSAETIMEDOUT';
        WSAECONNREFUSED    : x := 'WSAECONNREFUSED';
        WSAELOOP           : x := 'WSAELOOP';
        WSAENAMETOOLONG    : x := 'WSAENAMETOOLONG';
        WSAEHOSTDOWN       : x := 'WSAEHOSTDOWN';
        WSAEHOSTUNREACH    : x := 'WSAEHOSTUNREACH';
        WSAENOTEMPTY       : x := 'WSAENOTEMPTY';
        WSAEPROCLIM        : x := 'WSAEPROCLIM';
        WSAEUSERS          : x := 'WSAEUSERS';
        WSAEDQUOT          : x := 'WSAEDQUOT';
        WSAESTALE          : x := 'WSAESTALE';
        WSAEREMOTE         : x := 'WSAEREMOTE';
        WSASYSNOTREADY     : x := 'WSASYSNOTREADY';
        WSAVERNOTSUPPORTED : x := 'WSAVERNOTSUPPORTED';
        WSANOTINITIALISED  : x := 'WSANOTINITIALISED';
        WSAHOST_NOT_FOUND  : x := 'WSAHOST_NOT_FOUND';
        WSATRY_AGAIN       : x := 'WSATRY_AGAIN';
        WSANO_RECOVERY     : x := 'WSANO_RECOVERY';
        WSANO_DATA         : x := 'WSANO_DATA';

        else x := 'Unknown Error';
  end;
  Result := x + ' (' + IntToStr(r) + ')';
end;


end.
