Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

327 lines
7.5 KiB

/* --------------------------------------------------------------------
File : npclnt.cxx
Title : Client runtime transport classes for namepipes.
Description :
History :
stevez 4-10-91 Initial async version for windows.
-------------------------------------------------------------------- */
#define INCL_WIN
#include <windows.h>
#define INCL_ERRORS
#include <bseerr.h>
#include "rpc.h"
#include "gssapi.h"
#include "gsssup.h"
#include "util.hxx"
#include "protstck.hxx"
#include "mutex.hxx"
#include "threads.hxx"
#include "handle.hxx"
#include "rpcdebug.hxx"
#include "osfpcket.hxx"
#include "osfclnt.hxx"
#include "npclnt.hxx"
#define APIENTRY pascal far
#define USHORT unsigned short
#define PUSHORT unsigned short far *
#define HFILE short
#define void * void far *
#define PFN void (pascal far *)(void far *)
typedef struct _AVAILDATA { /* PeekNMPipe Bytes Available record */
USHORT cbpipe; /* bytes left in the pipe */
USHORT cbmessage; /* bytes left in current message */
} AVAILDATA, far *PAVAILDATA;
USHORT APIENTRY DosPeekNmPipe(HFILE, void *, USHORT, PUSHORT, PAVAILDATA, PUSHORT);
USHORT APIENTRY DosSetNmPHandState(HFILE, USHORT);
USHORT APIENTRY DosWaitNmPipe(char far *, unsigned long);
USHORT APIENTRY DosReadAsyncNmPipe(HFILE, PFN, PUSHORT, void *, unsigned int, unsigned int far *);
USHORT APIENTRY DosWriteAsyncNmPipe(HFILE, PFN, PUSHORT, void *, unsigned int, unsigned int far *);
unsigned _cdecl _dos_open(const char far *, unsigned, unsigned short far *);
unsigned _cdecl _dos_close(int);
#define cbSMBheader 48
//BUGBUG: is maxSend always 1024??
unsigned int maxSend = 1024 - cbSMBheader;
extern HANDLE hInstanceDLL;
int
NP_CCONNECTION::TransReceive (
IN OUT void PAPI * PAPI * Buffer,
IN OUT unsigned int PAPI * BufferLength
)
{
unsigned int ActualLength;
USHORT State, retval;
AVAILDATA Available;
char PAPI * BuffCur;
if (! *Buffer)
{
*BufferLength = maxSend/2;
if (TransGetBuffer(Buffer,*BufferLength))
return(-1);
retval = AsyncReadWrite(*Buffer, BufferLength, ASYNC_READ);
if (retval == ERROR_MORE_DATA)
{
if (DosPeekNmPipe(Pipe, *Buffer,0,(PUSHORT) &ActualLength,
&Available,&State))
return(-1);
BuffCur = (char PAPI *) *Buffer;
if (TransGetBuffer(Buffer, *BufferLength+Available.cbmessage))
return(-1);
fCopy(*Buffer, BuffCur, *BufferLength);
if (TransFreeBuffer(BuffCur))
return(-1);
// Async operations are limited to maxSend size, so read the
// pipe as many times as needed to get the whole message
BuffCur = ((char PAPI *) *Buffer) + *BufferLength;
*BufferLength += Available.cbmessage;
do {
ActualLength = maxSend;
retval = AsyncReadWrite(BuffCur, &ActualLength, ASYNC_READ);
Available.cbmessage -= ActualLength;
BuffCur += ActualLength;
}
while (Available.cbmessage > 0);
}
}
else
retval = AsyncReadWrite(*Buffer, BufferLength, ASYNC_READ);
return(retval);
}
int
NP_CCONNECTION::TransSend (
IN void PAPI * Buffer,
IN unsigned int BufferLength
)
{
unsigned int cbRequest = BufferLength;
unsigned int retval;
retval = AsyncReadWrite(Buffer, &BufferLength, ASYNC_WRITE);
if (cbRequest != BufferLength)
retval = 1;
return(retval);
}
int
NP_CCONNECTION::TransSendReceive (
IN void PAPI * SendBuffer,
IN unsigned int SendBufferLength,
IN OUT void PAPI * PAPI * ReceiveBuffer,
IN OUT unsigned int PAPI * ReceiveBufferLength
)
{
unsigned int retval;
retval = TransSend(SendBuffer, SendBufferLength);
if (retval)
return(retval);
return(TransReceive(ReceiveBuffer, ReceiveBufferLength));
}
int
NP_CCONNECTION::TransOpenConnection (
IN unsigned char PAPI * TransportInfo,
IN unsigned int TransportInfoLength,
IN unsigned char PAPI * SecurityInfo,
IN unsigned int SecurityInfoLength,
IN unsigned long SecurityType
)
{
unsigned short retval;
int RetryCount = 2;
const mode = 0x0002 | 0x0040 | 0x0080;// OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE | OPENFLAGS_NOINHERIT
UNUSED(TransportInfoLength);
UNUSED(SecurityInfo);
UNUSED(SecurityInfoLength);
UNUSED(SecurityType);
while (RetryCount != 0)
{
RetryCount -= 1;
retval = _dos_open(TransportInfo, mode, &Pipe);
if (retval == 0)
{
if (DosSetNmPHandState(Pipe,
// PIPE_WAIT | PIPE_READMODE_MESSAGE
0x0000 | 0x0100))
{
_dos_close(Pipe);
return(-1);
}
return(0);
}
if (retval != ERROR_PIPE_BUSY)
return(-1);
retval = DosWaitNmPipe(TransportInfo,100L);
if (retval && (retval != ERROR_SEM_TIMEOUT))
PauseExecution(100L);
}
return(-1);
}
int
NP_CCONNECTION::TransCloseConnection (
)
{
return(_dos_close(Pipe));
}
unsigned int
NP_CCONNECTION::TransMaximumSend (
)
{
return(maxSend);
}
ASYNCItem *CurrentRequest;
unsigned long AsyncDelay = 3000;
#define END_DIALOG 0x1854
// This is called at interrupt time! Make sure this is a loadds proc!
void far pascal AsyncDone(
IN void PAPI * Buffer
)
{
// int3();
for (ASYNCItem *pAI = AsyncList.First(); pAI; pAI = pAI->Next())
if (pAI->Buffer == Buffer)
{
pAI->fDone = TRUE;
// if the dialog has initialized itself, send a message to
// it to quit, which will return control to AsyncReadWrite()
if (pAI->hWnd)
PostMessage(pAI->hWnd, WM_USER, END_DIALOG, 0);
return;
}
}
unsigned int far pascal BusyBox(
HWND hDlg,
unsigned message,
unsigned int wParam,
LONG lParam
) //-----------------------------------------------------------------------//
{
UNUSED(lParam);
switch (message){
case WM_INITDIALOG:
// fill in my window handle so I can receive the finish message
WinEnterCritical();
if (!CurrentRequest->fDone)
CurrentRequest->hWnd = hDlg;
WinExitCritical();
case WM_USER:
if (wParam == END_DIALOG || CurrentRequest->fDone)
EndDialog(hDlg, 0);
}
return(FALSE);
}
int
NP_CCONNECTION::AsyncReadWrite (
IN void PAPI * Buffer,
IN unsigned int PAPI *BufferLength,
ASYNC_OP operation
)
{
HANDLE TaskSelf = GetCurrentTask();
USHORT retval;
// scan the list of pending request to detect deadlock
for (ASYNCItem *pAI = AsyncList.First(); pAI; pAI = pAI->Next())
if (pAI->Owner == TaskSelf)
return(-1);
// int3();
for (int cTry = 0; cTry < 4; cTry++)
{
CurrentRequest = new ASYNCItem(TaskSelf, Buffer);
if (operation == ASYNC_READ)
retval = DosReadAsyncNmPipe(Pipe, AsyncDone, &retval, Buffer, *BufferLength, BufferLength);
else
retval = DosWriteAsyncNmPipe(Pipe, AsyncDone, &retval, Buffer, *BufferLength, BufferLength);
// The async request is now pending. Wait a little while for it to
// complete. Then put up a dialog box which tells the user that an
// RPC request is pending which will allow them to switch away
while(! CurrentRequest->fDone && !retval)
{
// Yield();
if (GetCurrentTime() > CurrentRequest->TimeRequested + AsyncDelay)
DialogBox (hInstanceDLL, "BUSYBOX", GetFocus(), BusyBox);
}
delete CurrentRequest;
// only retry the request if the server rejected the request
if (retval == 0 || retval != ERROR_REQ_NOT_ACCEP)
break;
}
return(retval);
}