mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1293 lines
28 KiB
1293 lines
28 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cltnvns.c
|
|
|
|
Abstract:
|
|
|
|
This is the client side loadable transport module for VINES
|
|
|
|
Author:
|
|
|
|
tony chan (tonychan) 5-May-1995 Creation
|
|
MazharM fixed race conditions and other misc problems..
|
|
|
|
Revision History:
|
|
--*/
|
|
|
|
// Vines includes
|
|
#define INCL_SOCK
|
|
#define INCL_ST
|
|
#define INCL_WS
|
|
#include <vnsapi.h>
|
|
|
|
typedef int SOCKET;
|
|
|
|
#define SOCKADDR_VNS struct vns_sockaddr
|
|
#define FD_SETSIZE 1
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <windows.h>
|
|
#include "windows.h"
|
|
|
|
#include "sysinc.h"
|
|
#include "rpc.h"
|
|
#include "rpcdcep.h"
|
|
#include "rpctran.h"
|
|
#include "rpcerrp.h"
|
|
#include "callback.h"
|
|
|
|
|
|
#define PFC_FIRST_FRAG 0x01
|
|
#define SET_PORT(p,wkp) \
|
|
((p[8] = (unsigned char)HIBYTE((unsigned short) wkp), \
|
|
p[9] = (unsigned char)LOBYTE((unsigned short) wkp)))
|
|
|
|
|
|
typedef struct
|
|
{
|
|
SOCKET Socket;
|
|
long Timeout;
|
|
IPCPORT remoteport; /* address to keep around for VINES */
|
|
unsigned int cid;
|
|
IPCPORT localport;
|
|
struct sockreq srdata;
|
|
unsigned short fCallComplete ;
|
|
unsigned short fLocalYield ;
|
|
} CONNECTION, *PCONNECTION;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
HWND hWnd;
|
|
HANDLE hYield;
|
|
HTASK task;
|
|
} TASK, *PTASK;
|
|
|
|
#define MAX_CONN 10
|
|
|
|
near _printf(const char *format, ...);
|
|
void __far __pascal MyWep();
|
|
extern void (_far pascal _far *DllTermination)(void);
|
|
BOOL CheckForCompletion() ;
|
|
|
|
#define ENDIAN_MASK 16
|
|
#define NO_MORE_SENDS_OR_RECVS 2
|
|
#define ENDPOINT_LEN 5
|
|
|
|
// The maximum send is the size of four user data frames on an ethernet.
|
|
|
|
#define MAXIMUM_SEND ((3 * 1450) & 0xFFF8)
|
|
#define HOSTNAME_LEN 32
|
|
#define DLL_NAME "rpcltc8.dll"
|
|
#define ENDPOINT_MAPPER_EP "385"
|
|
|
|
#define ADDRESS_FAMILY AF_BAN
|
|
#define SOCKET_TYPE SOCK_SEQPACKET
|
|
#define PROTOCOL -1
|
|
|
|
|
|
#define WNDCLASSNAME "CLNTVNS"
|
|
#define WNDTEXT "RPC VNS"
|
|
extern HANDLE hInstanceDLL;
|
|
|
|
WORD VM_SocketNotify;
|
|
PCONNECTION * HeadConn;
|
|
|
|
PTASK * HeadTask;
|
|
|
|
|
|
#define MAKEWORD(a, b) ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))
|
|
|
|
|
|
/*
|
|
Following Macros and structs are needed for Tower Stuff
|
|
*/
|
|
|
|
#pragma pack(1)
|
|
|
|
#define TRANSPORTID 0x1A
|
|
#define TRANSPORTHOSTID 0x1C
|
|
#define TOWERFLOORS 5
|
|
#define TOWEREPSIZE 4
|
|
#define TOWERSIZE (TOWEREPSIZE+2)
|
|
#define PROTSEQ "ncacn_vns_spp"
|
|
|
|
|
|
typedef struct _FLOOR_234 {
|
|
unsigned short ProtocolIdByteCount;
|
|
unsigned char FloorId;
|
|
unsigned short AddressByteCount;
|
|
unsigned char Data[2];
|
|
} FLOOR_234;
|
|
typedef FLOOR_234 PAPI UNALIGNED * PFLOOR_234;
|
|
|
|
|
|
#define NEXTFLOOR(t,x) (t)((unsigned char PAPI *)x +((t)x)->ProtocolIdByteCount\
|
|
+ ((t)x)->AddressByteCount\
|
|
+ sizeof(((t)x)->ProtocolIdByteCount)\
|
|
+ sizeof(((t)x)->AddressByteCount))
|
|
|
|
int VNS_Verbose = 0 ;
|
|
|
|
#define TRACE(_X_) {\
|
|
if (VNS_Verbose)\
|
|
{\
|
|
MyPrintToDebugger _X_ ;\
|
|
}\
|
|
}
|
|
/*
|
|
End of Tower Stuff!
|
|
*/
|
|
|
|
#pragma pack()
|
|
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
InsertTask(IN PTASK pTask)
|
|
{
|
|
PTASK *tmpPtr;
|
|
int i ;
|
|
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Insert Task 0x%x\n", pTask->task)) ;
|
|
#endif
|
|
|
|
tmpPtr = HeadTask;
|
|
for( i = 0 ; i < MAX_CONN; i++)
|
|
{
|
|
// find free sport
|
|
if(*tmpPtr == NULL)
|
|
{
|
|
*tmpPtr = pTask ;
|
|
break;
|
|
}
|
|
tmpPtr++;
|
|
}
|
|
|
|
if(i == MAX_CONN)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Insert Task Failed, 0x%x\n", pTask->task)) ;
|
|
#endif
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
else
|
|
{
|
|
return (RPC_S_OK);
|
|
}
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
RemoveTask(IN PTASK pTask)
|
|
{
|
|
PTASK *tmpPtr;
|
|
int i ;
|
|
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Remove Task 0x%x\n", pTask->task)) ;
|
|
#endif
|
|
|
|
tmpPtr = HeadTask;
|
|
for( i = 0 ; i < MAX_CONN; i++)
|
|
{
|
|
if(*tmpPtr == pTask)
|
|
{
|
|
*tmpPtr = NULL;
|
|
break;
|
|
}
|
|
tmpPtr++;
|
|
}
|
|
if(i == MAX_CONN)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Remove Task, 0x%x, note found\n", pTask->task)) ;
|
|
#endif
|
|
return(RPC_S_INTERNAL_ERROR);
|
|
}
|
|
else
|
|
{
|
|
return (RPC_S_OK);
|
|
}
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
InsertConn(IN PCONNECTION pConn)
|
|
{
|
|
|
|
PCONNECTION * tmpPtr;
|
|
LPSOCKREQ pTmp;
|
|
int i ;
|
|
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Insert Conn 0x%l\n", pConn)) ;
|
|
#endif
|
|
|
|
tmpPtr = HeadConn;
|
|
for( i = 0 ; i < MAX_CONN; i++)
|
|
{
|
|
// find free sport
|
|
if(*tmpPtr == NULL)
|
|
{
|
|
*tmpPtr = pConn ;
|
|
break;
|
|
}
|
|
tmpPtr++;
|
|
}
|
|
|
|
if(i == MAX_CONN)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Insert Conn 0x%l failed\n", pConn)) ;
|
|
#endif
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
else
|
|
{
|
|
return (RPC_S_OK);
|
|
}
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
RemoveConn(IN PCONNECTION pConn)
|
|
{
|
|
PCONNECTION * tmpPtr;
|
|
LPSOCKREQ pTmp;
|
|
int i ;
|
|
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Remove Conn 0x%l\n", pConn)) ;
|
|
#endif
|
|
|
|
tmpPtr = HeadConn;
|
|
for( i = 0 ; i < MAX_CONN; i++)
|
|
{
|
|
if(tmpPtr != NULL && (*tmpPtr == pConn))
|
|
{
|
|
*tmpPtr = NULL;
|
|
break;
|
|
}
|
|
tmpPtr++;
|
|
}
|
|
|
|
if(i == MAX_CONN)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Remove Conn, 0x%l not found\n", pConn)) ;
|
|
#endif
|
|
return(RPC_S_INTERNAL_ERROR);
|
|
}
|
|
else
|
|
{
|
|
return (RPC_S_OK);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
PCONNECTION
|
|
VnsFindConn(LPSOCKREQ pSrdata)
|
|
{
|
|
PCONNECTION * tmpPtr;
|
|
LPSOCKREQ pTmp;
|
|
PCONNECTION pConn;
|
|
int i ;
|
|
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Find Conn pSrdata=0x%l\n", pSrdata)) ;
|
|
#endif
|
|
|
|
tmpPtr = HeadConn;
|
|
for( i = 0 ; i < MAX_CONN; i++)
|
|
{
|
|
pConn = *tmpPtr;
|
|
if(pConn != NULL)
|
|
{
|
|
pTmp = &(pConn->srdata);
|
|
if( pTmp == pSrdata)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
tmpPtr++;
|
|
}
|
|
|
|
if(i == MAX_CONN)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Connection not found\n")) ;
|
|
#endif
|
|
return(NULL);
|
|
}
|
|
else
|
|
{
|
|
return (pConn);
|
|
}
|
|
}
|
|
|
|
PTASK VnsFindWindowByTask(HTASK htask )
|
|
{
|
|
/* returns pointer to TASK structure
|
|
or NULL if not found */
|
|
PTASK pTask;
|
|
PTASK *tmpPtr;
|
|
int i;
|
|
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: FindWindowByTask 0x%x\n", htask)) ;
|
|
#endif
|
|
tmpPtr = HeadTask;
|
|
for( i = 0 ; i < MAX_CONN; i++)
|
|
{
|
|
pTask = *tmpPtr;
|
|
if( (pTask != NULL) && pTask->task == htask)
|
|
{
|
|
break;
|
|
}
|
|
tmpPtr++;
|
|
}
|
|
|
|
if( i == MAX_CONN)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: FindWindowByTask 0x%x, task not found\n", htask)) ;
|
|
#endif
|
|
return(NULL);
|
|
}
|
|
else
|
|
{
|
|
return(pTask);
|
|
}
|
|
}
|
|
|
|
void CALLBACK __loadds
|
|
ClntVnsCleanup(HTASK htask)
|
|
{
|
|
// Create a windows for VINES lib to post message if necessary
|
|
|
|
PTASK pTask;
|
|
|
|
pTask = VnsFindWindowByTask(htask);
|
|
if (pTask != NULL)
|
|
{
|
|
RemoveTask(pTask);
|
|
|
|
// calling destroy window during exit list processing
|
|
// causes bad problems
|
|
/* DestroyWindow(pTask->hWnd); */
|
|
|
|
I_RpcFree(pTask);
|
|
}
|
|
}
|
|
|
|
|
|
RPC_STATUS MayBeCreateWindow()
|
|
{
|
|
PTASK pTask;
|
|
int err;
|
|
|
|
pTask = VnsFindWindowByTask (GetCurrentTask());
|
|
|
|
if(pTask == NULL)
|
|
{ /* we couldn't find it. */
|
|
if(WinDLLAtExit(ClntVnsCleanup) == FALSE)
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
pTask = (PTASK) I_RpcAllocate(sizeof(TASK));
|
|
if( pTask == NULL)
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
/* set up the pTask struct */
|
|
/* Create hidden window to receive Async messages */
|
|
pTask->hWnd = CreateWindow(WNDCLASSNAME,
|
|
WNDTEXT,
|
|
WS_OVERLAPPEDWINDOW,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
CW_USEDEFAULT,
|
|
(HWND)NULL,
|
|
(HMENU)NULL,
|
|
hInstanceDLL,
|
|
(LPVOID)0);
|
|
if (!pTask->hWnd)
|
|
{
|
|
return (RPC_S_OUT_OF_RESOURCES);
|
|
}
|
|
|
|
UpdateWindow(pTask->hWnd);
|
|
|
|
ShowWindow(pTask->hWnd, SW_HIDE);
|
|
|
|
pTask->hYield = (HANDLE)NULL;
|
|
pTask->task = GetCurrentTask();
|
|
|
|
/* retrun code is none */
|
|
VnsSocketNotifyWindow(pTask->hWnd, -1);
|
|
|
|
if(InsertTask(pTask) != RPC_S_OK)
|
|
{
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
ASSERT(pTask->hWnd != NULL);
|
|
return(RPC_S_OK);
|
|
|
|
}
|
|
|
|
#define TIMEOUT 2000
|
|
|
|
int BlockForRecv(PCONNECTION pConn)
|
|
/**++
|
|
Block for recv while yielding in the runtime
|
|
Return Values:
|
|
0: The call failed
|
|
1: The call succeeded
|
|
--*/
|
|
{
|
|
|
|
PTASK pTask;
|
|
int status = 0 ;
|
|
MSG wMsg ;
|
|
|
|
pConn->fLocalYield = FALSE ;
|
|
pConn->fCallComplete = FALSE ;
|
|
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Calling BlockForRecv\n")) ;
|
|
#endif
|
|
|
|
pTask = VnsFindWindowByTask (GetCurrentTask());
|
|
ASSERT(pTask != NULL);
|
|
|
|
if ((status = I_RpcWinAsyncCallWait(pTask->hYield, pTask->hWnd, TIMEOUT))
|
|
== RPC_WIN_WAIT_TIMEOUT)
|
|
{
|
|
while ((pConn->fCallComplete == FALSE) &&
|
|
(status = CheckForCompletion()) == 0)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Waiting in BlockForRecv...")) ;
|
|
#endif
|
|
if (PeekMessage(&wMsg, pTask->hWnd, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&wMsg);
|
|
DispatchMessage(&wMsg);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (status == RPC_WIN_WAIT_ABORTED
|
|
|| pConn->srdata.error)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: BlockForRecv failed\n")) ;
|
|
#endif
|
|
return (0) ;
|
|
}
|
|
|
|
ASSERT(status == RPC_WIN_WAIT_SUCCESS &&
|
|
pConn->srdata.error == 0) ;
|
|
|
|
return 1 ;
|
|
}
|
|
|
|
int LocalBlockForSendRecv(PCONNECTION pConn)
|
|
/**++
|
|
Block Locally for the call to complete
|
|
Return Values:
|
|
0: The call failed
|
|
1: The call succeeded
|
|
--*/
|
|
{
|
|
MSG wMsg;
|
|
DWORD dwYieldTime ;
|
|
PTASK pTask;
|
|
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Calling LocalBlockForRecv\n")) ;
|
|
#endif
|
|
pTask = VnsFindWindowByTask (GetCurrentTask());
|
|
ASSERT(pTask != NULL);
|
|
|
|
pConn->fLocalYield = TRUE ;
|
|
pConn->fCallComplete = FALSE ;
|
|
|
|
while (1)
|
|
{
|
|
dwYieldTime = GetCurrentTime() + 2000 ;
|
|
|
|
while (!pConn->fCallComplete && GetCurrentTime() < dwYieldTime)
|
|
{
|
|
if (PeekMessage(&wMsg, pTask->hWnd, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&wMsg);
|
|
DispatchMessage(&wMsg);
|
|
}
|
|
}
|
|
|
|
if (pConn->fCallComplete)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: LocalBlockForRecv, completed\n")) ;
|
|
#endif
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: LocalBlockForRecv, failed\n")) ;
|
|
#endif
|
|
if (CheckForCompletion() == -1)
|
|
return 0 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
ClientOpen (
|
|
IN PCONNECTION pConn,
|
|
IN RPC_CHAR * NetworkAddress,
|
|
IN RPC_CHAR * Endpoint,
|
|
IN RPC_CHAR * NetworkOptions,
|
|
IN RPC_CHAR * TransportAddress,
|
|
IN RPC_CHAR * RpcProtocolSequence,
|
|
IN unsigned int Timeout
|
|
)
|
|
|
|
// Open a client connection
|
|
|
|
{
|
|
int err;
|
|
|
|
// Vines add on
|
|
VNS_ST_SESS StSess;
|
|
char szOService[STNAMELEN];
|
|
IPCPORT remoteport;
|
|
struct sockreq srdata; /* to send/receive data */
|
|
CallStatus cs;
|
|
short len = STNAMELEN;
|
|
RPC_STATUS Status ;
|
|
|
|
UNUSED(NetworkAddress);
|
|
UNUSED(NetworkOptions);
|
|
UNUSED(TransportAddress);
|
|
UNUSED(RpcProtocolSequence);
|
|
UNUSED(Timeout);
|
|
|
|
if (NetworkAddress == NULL || NetworkAddress[0] == '\0')
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: ClientOpen failed, SERVER_UNAVAILABLE\n")) ;
|
|
#endif
|
|
/* local server is not supported right? */
|
|
return(RPC_S_SERVER_UNAVAILABLE);
|
|
}
|
|
|
|
|
|
RpcpMemorySet((char *)szOService, 0, sizeof(char) * STNAMELEN);
|
|
RpcpMemorySet((char *)remoteport,0,sizeof(IPCPORT));
|
|
|
|
cs = VnsStartStSession(NULL, TRUE, NULL, &StSess);
|
|
if(cs != 0)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: ClientOpen failed, VnsStartStSession failed, %d\n",cs)) ;
|
|
#endif
|
|
return(RPC_S_SERVER_UNAVAILABLE);
|
|
}
|
|
|
|
|
|
cs = VnsGetSSppPort(
|
|
&StSess,
|
|
NetworkAddress,
|
|
remoteport,
|
|
szOService,
|
|
&len
|
|
);
|
|
|
|
|
|
|
|
if(cs != 0)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: ClientOpen failed, VnsGetSSppPort failed, %d\n",cs)) ;
|
|
#endif
|
|
return(RPC_S_SERVER_UNAVAILABLE);
|
|
|
|
}
|
|
|
|
VnsEndStSession( &StSess );
|
|
|
|
/* set the port to the endpoint */
|
|
|
|
SET_PORT(remoteport, atoi(Endpoint) );
|
|
|
|
RpcpMemoryCopy(&(pConn->remoteport), &remoteport, sizeof(IPCPORT)) ; ;
|
|
|
|
//
|
|
// Get a socket
|
|
//
|
|
|
|
err = VnsOpenSocket(&pConn->Socket, ADDRESS_FAMILY,
|
|
SOCKET_TYPE, PROTOCOL, pConn->localport , 0);
|
|
if (err != 0)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: ClientOpen failed, VnsOpenSocket failed, %d\n",err)) ;
|
|
#endif
|
|
return (RPC_S_SERVER_UNAVAILABLE);
|
|
}
|
|
|
|
srdata.error = 0;
|
|
srdata.type = SO_CONNECT;
|
|
srdata.msg = NetworkAddress;
|
|
srdata.len = 0;
|
|
srdata.s = pConn->Socket;
|
|
srdata.flags = SO_EOM ;
|
|
srdata.timeout = (unsigned int)-1;
|
|
RpcpMemoryCopy(&(srdata.addr), &remoteport, sizeof(IPCPORT)) ;
|
|
err = VnsSocketSend(&srdata);
|
|
if (!err) err = srdata.error;
|
|
if (err)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE((
|
|
"CLNTVNS: ClientOpen failed, VnsSocketSend (SO_CONNECT) failed, %d\n",
|
|
err)) ;
|
|
#endif
|
|
return(RPC_S_SERVER_UNAVAILABLE);
|
|
}
|
|
|
|
/* save the cid for next send */
|
|
pConn->cid = srdata.cid;
|
|
pConn->Timeout = RPC_C_CANCEL_INFINITE_TIMEOUT;
|
|
|
|
Status = MayBeCreateWindow() ;
|
|
if (Status != RPC_S_OK)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: MayBeCreateWindow failed %d\n", Status)) ;
|
|
#endif
|
|
}
|
|
InsertConn(pConn);
|
|
return (RPC_S_OK);
|
|
|
|
}
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
ClientClose (
|
|
IN PCONNECTION pConn
|
|
)
|
|
|
|
// Close a client connection
|
|
|
|
{
|
|
struct sockreq srdata;
|
|
int err;
|
|
|
|
RemoveConn(pConn);
|
|
|
|
srdata.error = 0;
|
|
srdata.type = SO_DISCONNECT;
|
|
srdata.len = 0;
|
|
srdata.s = pConn->Socket;
|
|
srdata.flags = SO_EOM ;
|
|
srdata.timeout = (unsigned int)-1;
|
|
srdata.cid = pConn->cid;
|
|
RpcpMemoryCopy(&(srdata.addr), &(pConn->remoteport), sizeof(IPCPORT)) ;
|
|
err = VnsSocketSend(&srdata);
|
|
if (!err) err = srdata.error;
|
|
if (err)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: VnsSocketSend, SO_DISCONNECT failed, %d\n",err)) ;
|
|
#endif
|
|
return(RPC_S_INTERNAL_ERROR);
|
|
}
|
|
VnsCloseSocket(pConn->Socket);
|
|
}
|
|
|
|
BOOL CheckForCompletion()
|
|
/**++
|
|
Checks if the async call is complete
|
|
Return Values:
|
|
0: Call hasn't completed
|
|
1: Call has completed
|
|
-1: An error occured
|
|
--*/
|
|
{
|
|
LPSOCKREQ pSrdata ;
|
|
PCONNECTION pConn;
|
|
int err ;
|
|
|
|
err = VnsSocketWait(&pSrdata, 0);
|
|
if (err != 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
pConn = VnsFindConn(pSrdata);
|
|
if(pConn == NULL)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE((
|
|
"CLNTVNS: AsyncEventProc, couldn't find connection, pSrdata=%l\n",
|
|
pSrdata)) ;
|
|
#endif
|
|
|
|
return -1 ;
|
|
}
|
|
|
|
pConn->fCallComplete = TRUE ;
|
|
|
|
if(pConn->fLocalYield == FALSE)
|
|
{
|
|
I_RpcWinAsyncCallComplete(pConn);
|
|
}
|
|
|
|
if (pConn->srdata.error)
|
|
{
|
|
return -1 ;
|
|
}
|
|
|
|
return (1);
|
|
}
|
|
|
|
LONG FAR PASCAL _loadds
|
|
AsyncEventProc(HWND hWnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
if(msg == VM_SocketNotify)
|
|
{
|
|
if (CheckForCompletion() != TRUE)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
ClientSend (
|
|
IN PCONNECTION pConn,
|
|
IN void PAPI * Buffer,
|
|
IN unsigned int BufferLength
|
|
)
|
|
|
|
// Write a message to a connection. This operation is retried in case
|
|
// the server is "busy".
|
|
|
|
{
|
|
int err;
|
|
|
|
pConn->srdata.error = 0;
|
|
pConn->srdata.type = SO_DATA;
|
|
pConn->srdata.msg = Buffer;
|
|
pConn->srdata.len = BufferLength;
|
|
pConn->srdata.s = pConn->Socket;
|
|
pConn->srdata.flags = SO_EOM | SO_ASYNC ;
|
|
pConn->srdata.timeout = (unsigned int)-1;
|
|
pConn->srdata.cid = pConn->cid;
|
|
RpcpMemoryCopy(&(pConn->srdata.addr), &(pConn->remoteport), sizeof(IPCPORT)) ;
|
|
|
|
err = VnsSocketSend(&(pConn->srdata));
|
|
if (!err) err = pConn->srdata.error;
|
|
|
|
if (err)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: ClientSend SO_DATA failed, %d\n", err)) ;
|
|
#endif
|
|
ClientClose(pConn);
|
|
return(RPC_P_SEND_FAILED);
|
|
}
|
|
|
|
if (LocalBlockForSendRecv(pConn) == 0)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: ClientSend SO_DATA failed (ASYNC)\n")) ;
|
|
#endif
|
|
ClientClose(pConn);
|
|
return(RPC_P_SEND_FAILED);
|
|
}
|
|
|
|
return(RPC_S_OK);
|
|
|
|
}
|
|
|
|
|
|
RPC_TRANS_STATUS RPC_ENTRY
|
|
ClientRecv (
|
|
IN PCONNECTION pConn,
|
|
IN OUT void PAPI * PAPI * Buffer,
|
|
IN OUT unsigned int PAPI * BufferLength
|
|
)
|
|
|
|
// Read a message from a connection.
|
|
|
|
{
|
|
RPC_STATUS RpcStatus;
|
|
int err;
|
|
int retry;
|
|
int total_bytes = 0;
|
|
BOOL firstRecv = TRUE;
|
|
PTASK pTask;
|
|
|
|
pTask = VnsFindWindowByTask (GetCurrentTask());
|
|
ASSERT(pTask != NULL);
|
|
|
|
pConn->srdata.type = SO_DATA ;
|
|
pConn->srdata.s = pConn->Socket;
|
|
pConn->srdata.timeout = (unsigned int) -1 ;
|
|
pConn->srdata.cid = pConn->cid;
|
|
pConn->srdata.flags = SO_CREC | SO_ASYNC ;
|
|
RpcpMemoryCopy(&(pConn->srdata.addr), &(pConn->localport), sizeof(IPCPORT)) ;
|
|
|
|
|
|
/* allocate 1k for small messages */
|
|
|
|
*BufferLength = 1450; /* that's the default buffer size for VINES */
|
|
RpcStatus = I_RpcTransClientReallocBuffer(pConn,
|
|
Buffer,
|
|
0,
|
|
*BufferLength);
|
|
if (RpcStatus != RPC_S_OK)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: ClientRecv, I_RpcReallocBuf failed, %l\n",RpcStatus)) ;
|
|
#endif
|
|
ClientClose(pConn);
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
while(1)
|
|
{
|
|
pConn->srdata.msg =(char FAR *)*Buffer + total_bytes;
|
|
pConn->srdata.len = *BufferLength - total_bytes;
|
|
pConn->srdata.error = 0;
|
|
err = VnsSocketReceive(&(pConn->srdata));
|
|
if (!err) err = pConn->srdata.error;
|
|
|
|
if( err != 0 )
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: VnsSocketReceive failed %d\n", err)) ;
|
|
#endif
|
|
ClientClose ( pConn );
|
|
return(RPC_P_RECEIVE_FAILED);
|
|
}
|
|
|
|
|
|
if(firstRecv)
|
|
{
|
|
pTask->hYield = I_RpcWinAsyncCallBegin(pConn);
|
|
if(BlockForRecv(pConn) == 0)
|
|
{
|
|
ClientClose ( pConn );
|
|
I_RpcWinAsyncCallEnd(pTask->hYield);
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: BlockForRecv failed\n")) ;
|
|
#endif
|
|
return(RPC_P_RECEIVE_FAILED);
|
|
}
|
|
|
|
firstRecv = FALSE;
|
|
I_RpcWinAsyncCallEnd(pTask->hYield);
|
|
}
|
|
else
|
|
{
|
|
if (LocalBlockForSendRecv(pConn) == 0)
|
|
{
|
|
ClientClose ( pConn );
|
|
return(RPC_P_RECEIVE_FAILED);
|
|
}
|
|
}
|
|
|
|
if((pConn->srdata.flags != (SO_CREC + SO_EOM + SO_ASYNC)))
|
|
{
|
|
total_bytes += pConn->srdata.cc;
|
|
*BufferLength = MAXIMUM_SEND;
|
|
RpcStatus = I_RpcTransClientReallocBuffer(pConn,
|
|
Buffer,
|
|
total_bytes,
|
|
*BufferLength);
|
|
if (RpcStatus != RPC_S_OK)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: ClientRecv, I_RpcReallocBuffer failed %l\n",
|
|
RpcStatus)) ;
|
|
#endif
|
|
ClientClose ( pConn );
|
|
return(RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
total_bytes += pConn->srdata.cc;
|
|
*BufferLength = total_bytes;
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef DEBUGRPC
|
|
TRACE(("CLNTVNS: Internal error in receive\n")) ;
|
|
#endif
|
|
ASSERT(0);
|
|
return(RPC_S_INTERNAL_ERROR);
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma pack(1)
|
|
RPC_STATUS RPC_ENTRY
|
|
ClientTowerConstruct(
|
|
IN char PAPI * Endpoint,
|
|
IN char PAPI * NetworkAddress,
|
|
OUT short PAPI * Floors,
|
|
OUT unsigned long PAPI * ByteCount,
|
|
OUT unsigned char PAPI * PAPI * Tower,
|
|
IN char PAPI * Protseq
|
|
)
|
|
{
|
|
unsigned long TowerSize;
|
|
unsigned short portnum;
|
|
UNALIGNED PFLOOR_234 Floor;
|
|
unsigned long hostval;
|
|
unsigned short AddressSize = 0;
|
|
UNUSED(Protseq);
|
|
|
|
/* Compute the memory size of the tower. */
|
|
*Floors = TOWERFLOORS;
|
|
TowerSize = TOWERSIZE;
|
|
|
|
if (NetworkAddress == NULL || NetworkAddress[0] == '\0')
|
|
{
|
|
/* local server is not supported right? */
|
|
return(RPC_S_SERVER_UNAVAILABLE);
|
|
}
|
|
|
|
AddressSize = strlen(NetworkAddress) + 1;
|
|
TowerSize += 2*sizeof(FLOOR_234) - 4 + AddressSize;
|
|
|
|
/* Allocate memory for the tower. */
|
|
*ByteCount = TowerSize;
|
|
if ((*Tower = (unsigned char PAPI*)I_RpcAllocate(TowerSize)) == NULL)
|
|
{
|
|
return (RPC_S_OUT_OF_MEMORY);
|
|
}
|
|
|
|
/* Put the endpoint address and transport protocol id in the first floor. */
|
|
Floor = (PFLOOR_234) *Tower;
|
|
Floor->ProtocolIdByteCount = 1;
|
|
Floor->FloorId = (unsigned char)(TRANSPORTID & 0xFF);
|
|
Floor->AddressByteCount = 2;
|
|
if (Endpoint == NULL || *Endpoint == '\0')
|
|
{
|
|
Endpoint = ENDPOINT_MAPPER_EP;
|
|
}
|
|
portnum = (unsigned short) atoi (Endpoint) ;
|
|
Floor->Data[0] = HIBYTE(portnum) ;
|
|
Floor->Data[1] = LOBYTE(portnum) ;
|
|
|
|
/* Put the network address and the transport host protocol id in the
|
|
second floor. */
|
|
Floor = NEXTFLOOR(PFLOOR_234, Floor);
|
|
Floor->ProtocolIdByteCount = 1;
|
|
Floor->FloorId = (unsigned char)(TRANSPORTHOSTID & 0xFF);
|
|
Floor->AddressByteCount = TOWEREPSIZE;
|
|
|
|
Floor->Data[0] = '\0';
|
|
Floor->Data[1] = '\0';
|
|
|
|
|
|
if ((NetworkAddress) && (*NetworkAddress))
|
|
{
|
|
Floor->AddressByteCount = AddressSize ;
|
|
RpcpMemoryCopy((char PAPI *)&Floor->Data[0], NetworkAddress, AddressSize);
|
|
}
|
|
else
|
|
return ( RPC_S_OUT_OF_MEMORY ) ;
|
|
|
|
return(RPC_S_OK);
|
|
}
|
|
|
|
|
|
RPC_STATUS RPC_ENTRY
|
|
ClientTowerExplode(
|
|
IN unsigned char PAPI * Tower,
|
|
OUT char PAPI * PAPI * Protseq,
|
|
OUT char PAPI * PAPI * Endpoint,
|
|
OUT char PAPI * PAPI * NetworkAddress
|
|
)
|
|
{
|
|
UNALIGNED PFLOOR_234 Floor = (PFLOOR_234) Tower;
|
|
RPC_STATUS Status = RPC_S_OK;
|
|
unsigned short portnum;
|
|
|
|
if (Protseq != NULL)
|
|
{
|
|
*Protseq = (char PAPI * ) I_RpcAllocate(strlen(PROTSEQ) + 1);
|
|
if (*Protseq == NULL)
|
|
Status = RPC_S_OUT_OF_MEMORY;
|
|
else
|
|
RpcpMemoryCopy(*Protseq, PROTSEQ, strlen(PROTSEQ) + 1);
|
|
}
|
|
|
|
if ((Endpoint == NULL) || (Status != RPC_S_OK))
|
|
{
|
|
return (Status);
|
|
}
|
|
|
|
*Endpoint = (char PAPI *) I_RpcAllocate(ENDPOINT_LEN+1); //Ports are all <64K [5 decimal dig +1]
|
|
if (*Endpoint == NULL)
|
|
{
|
|
Status = RPC_S_OUT_OF_MEMORY;
|
|
if (Protseq != NULL)
|
|
{
|
|
I_RpcFree(*Protseq);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
portnum = MAKEWORD(Floor->Data[1], Floor->Data[0]) ;
|
|
_itoa(portnum, *Endpoint, 10);
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
#pragma pack()
|
|
RPC_CLIENT_TRANSPORT_INFO TransInfo =
|
|
{
|
|
RPC_TRANSPORT_INTERFACE_VERSION,
|
|
TRANSPORTID,
|
|
|
|
ClientTowerConstruct,
|
|
ClientTowerExplode,
|
|
|
|
MAXIMUM_SEND,
|
|
sizeof (CONNECTION),
|
|
|
|
ClientOpen,
|
|
ClientClose,
|
|
ClientSend,
|
|
ClientRecv,
|
|
NULL,
|
|
0,
|
|
|
|
0,
|
|
0
|
|
};
|
|
|
|
RPC_CLIENT_TRANSPORT_INFO PAPI * RPC_ENTRY TransportLoad (
|
|
IN RPC_CHAR PAPI * RpcProtocolSequence,
|
|
IN RPC_CLIENT_RUNTIME_INFO PAPI * RpcClientRuntimeInfo
|
|
)
|
|
|
|
// Loadable transport initialization function
|
|
|
|
{
|
|
WNDCLASS wc;
|
|
int err;
|
|
RpcRuntimeInfo = RpcClientRuntimeInfo;
|
|
|
|
|
|
UNUSED (RpcProtocolSequence);
|
|
|
|
|
|
|
|
RpcRuntimeInfo = RpcClientRuntimeInfo;
|
|
|
|
/* need to delete this??? */
|
|
AsyncCallComplete = RpcRuntimeInfo->AsyncCallComplete;
|
|
|
|
DllTermination = MyWep;
|
|
|
|
wc.style = WS_OVERLAPPED;
|
|
wc.lpfnWndProc = (WNDPROC) AsyncEventProc;
|
|
wc.cbWndExtra = sizeof(PCONNECTION);
|
|
wc.cbClsExtra = 0;
|
|
wc.hInstance = hInstanceDLL;
|
|
wc.hIcon = NULL;
|
|
wc.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
|
|
wc.hbrBackground = GetStockObject (WHITE_BRUSH);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = WNDCLASSNAME;
|
|
|
|
RegisterClass(&wc);
|
|
VM_SocketNotify = RegisterWindowMessage("VM_SOCKETNOTIFY");
|
|
|
|
HeadConn = (PCONNECTION*) I_RpcAllocate(MAX_CONN * sizeof(PCONNECTION)); /* need to free this */
|
|
if (HeadConn == 0)
|
|
{
|
|
return NULL ;
|
|
}
|
|
|
|
RpcpMemorySet( HeadConn, 0, MAX_CONN * sizeof(PCONNECTION) );
|
|
|
|
HeadTask = (PTASK *) I_RpcAllocate(MAX_CONN * sizeof(PTASK)); /* need to free this */
|
|
if (HeadTask == 0)
|
|
{
|
|
return NULL ;
|
|
}
|
|
|
|
RpcpMemorySet(HeadTask, 0, MAX_CONN * sizeof(PTASK) );
|
|
|
|
return(&TransInfo);
|
|
}
|
|
|
|
|
|
void __far __pascal
|
|
MyWep(
|
|
)
|
|
{
|
|
VnsDone();
|
|
}
|
|
|
|
#ifdef DEBUGRPC
|
|
|
|
#define win_putc(c) {*pOut++ = c; \
|
|
if (pOut >= &outBuff[sizeof(outBuff)-1]) flushoutB();}
|
|
|
|
char NL[] = "\n\r";
|
|
|
|
char outBuff[80];
|
|
char *pOut = outBuff;
|
|
|
|
void _fastcall flushoutB()
|
|
{
|
|
*pOut = 0;
|
|
OutputDebugString(outBuff);
|
|
pOut = outBuff;
|
|
}
|
|
|
|
void _fastcall win_puts(char *pString)
|
|
{
|
|
while(*pString){
|
|
|
|
if (*pString == '\n')
|
|
win_putc('\r');
|
|
|
|
win_putc(*pString++);
|
|
}
|
|
}
|
|
|
|
MyPrintToDebugger(const char *format, int args)
|
|
{
|
|
register char far *pParms = (char far *)&args;
|
|
static char T[10];
|
|
char fLong;
|
|
|
|
while(*format){
|
|
|
|
switch(*format){
|
|
|
|
case '%':
|
|
|
|
fLong = FALSE;
|
|
l:
|
|
switch(*++format){
|
|
|
|
case 'l':
|
|
fLong = TRUE;
|
|
goto l;
|
|
|
|
case 'd':
|
|
case 'x':
|
|
|
|
if (fLong){
|
|
_ltoa(*(long far *)pParms, T, (*format == 'd')? 10: 16);
|
|
pParms += sizeof(int);
|
|
}
|
|
else
|
|
RpcItoa(*(int far *)pParms, T, (*format == 'd')? 10: 16);
|
|
|
|
win_puts(T);
|
|
|
|
pParms += sizeof(int);
|
|
break;
|
|
|
|
case 'u':
|
|
|
|
if (fLong){
|
|
_ultoa(*(long far *)pParms, T, 10);
|
|
pParms += sizeof(int);
|
|
}
|
|
else
|
|
_ultoa((unsigned long) *(unsigned far *)pParms, T, 10);
|
|
|
|
win_puts(T);
|
|
|
|
pParms += sizeof(int);
|
|
break;
|
|
|
|
case 's':
|
|
win_puts(*(char * far *)pParms);
|
|
pParms += sizeof(char *);
|
|
break;
|
|
|
|
default:
|
|
win_putc('%'); win_putc(*format);
|
|
}
|
|
break;
|
|
|
|
case '\n':
|
|
win_putc('\r');
|
|
|
|
default:
|
|
win_putc(*format);
|
|
}
|
|
|
|
format++;
|
|
}
|
|
|
|
flushoutB();
|
|
}
|
|
|
|
void __far I_RpcWinAssert(char __far *con,
|
|
char __far *file,
|
|
unsigned long line)
|
|
{
|
|
static char T[10];
|
|
|
|
_ultoa(line, T, 10);
|
|
|
|
OutputDebugString("Assertiong failed: ");
|
|
OutputDebugString(file);
|
|
OutputDebugString("(");
|
|
OutputDebugString(T);
|
|
OutputDebugString(") : ");
|
|
OutputDebugString(con);
|
|
|
|
__asm { int 3 }
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|