660 lines
21 KiB
C
660 lines
21 KiB
C
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1994 - 1999
|
|
//
|
|
// File: np.c
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Filename: np.c
|
|
//
|
|
// Description: This file contains common routines for named pipe
|
|
// routines for use with IPC raw networl performance
|
|
// tests.
|
|
// This module is written using win32 API calls.
|
|
//
|
|
// Authors: Scott Holden (Translator from NT API to win32 API)
|
|
// Mahesh Keni (Mahesh wrote this application using mostly
|
|
// NT native API calls)
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "rawcom.h"
|
|
#include "np.h"
|
|
|
|
/*++
|
|
NamedPipe function implementations
|
|
--*/
|
|
|
|
/************************************************************************/
|
|
NTSTATUS
|
|
NMP_Initialize(
|
|
IN USHORT NClients,
|
|
IN PCHAR ServerName,
|
|
IN USHORT SrvCli)
|
|
{
|
|
CHAR TempSrv[256];
|
|
// use local pipe name for server or if Name not provided
|
|
if (SrvCli || (!ServerName)) {
|
|
strcpy(TempSrv,PERF_PIPE);
|
|
}
|
|
else{
|
|
if (!ServerName) {
|
|
strcpy(TempSrv, RM_PERF_PIPE_PRFX);
|
|
}
|
|
else {
|
|
strcpy(TempSrv, (const char *)ServerName);
|
|
}
|
|
strcat(TempSrv, RM_PERF_PIPE_SUFX);
|
|
}
|
|
printf("NMP: Pipe name - %s\n", TempSrv);
|
|
pipeName = _strdup(TempSrv);
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible Creating a NamedPipe instance for the given
|
|
thread.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_PerClientInit(
|
|
IN USHORT CIndex, // client index
|
|
IN USHORT SrvCli )
|
|
{
|
|
NTSTATUS pstatus = 0;
|
|
|
|
if (SrvCli) {
|
|
// create namedpipe for this client
|
|
pstatus = CreateNamedPipeInstance(CIndex);
|
|
}
|
|
else { // for Client initialize all the thread parameters
|
|
;
|
|
}
|
|
return pstatus;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for issueing Listen and waiting till a
|
|
client is connected. When this routine returns successfully we can
|
|
assume that a connection is established.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_Wait_For_Client(
|
|
IN USHORT CIndex) // client index and namedpipe instance number
|
|
{
|
|
NTSTATUS wstatus;
|
|
wstatus = ConnectNamedPipe(Clients[CIndex].c_Nmp.c_PipeHandle,
|
|
NULL);
|
|
|
|
if (wstatus == FALSE) {
|
|
printf("Error: ConnectNamedPipe - 0x%08x, %ld\n", GetLastError(), GetLastError());
|
|
}
|
|
return (wstatus);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for issueing Disconnect to close the
|
|
connection with a client.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_Disconnect_Client(
|
|
IN USHORT CIndex) // client index and namedpipe instance number
|
|
{
|
|
NTSTATUS dstatus;
|
|
|
|
// post a Disconnect
|
|
// first find the status of the pipe to make sure that it's empty
|
|
|
|
dstatus = FlushFileBuffers(Clients[CIndex].c_Nmp.c_PipeHandle);
|
|
if (dstatus == FALSE) {
|
|
printf("Error: FlushFileBuffers failed - 0x%08x\n", GetLastError());
|
|
}
|
|
dstatus = DisconnectNamedPipe(Clients[CIndex].c_Nmp.c_PipeHandle);
|
|
if (dstatus == FALSE) {
|
|
printf("Error: DisconnectNamedPipe failed - 0x%08x, %ld\n", GetLastError(), GetLastError());
|
|
}
|
|
return dstatus;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for establishing a connection to the
|
|
server side. When this routine returns successfully we can assume that
|
|
a connection is established.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_Connect_To_Server(
|
|
IN USHORT CIndex) // client index and namedpipe instance number
|
|
{
|
|
NTSTATUS cstatus;
|
|
DWORD dwPipeMode;
|
|
|
|
Clients[CIndex].c_Nmp.c_PipeHandle = CreateFile( //connect to the server
|
|
pipeName, // address of filename
|
|
GENERIC_READ | GENERIC_WRITE, // access mode
|
|
0L, // share mode
|
|
NULL, // security attributes
|
|
OPEN_EXISTING, // create mode
|
|
0L, // attributes and flags
|
|
NULL); // template file handle
|
|
if (Clients[CIndex].c_Nmp.c_PipeHandle == INVALID_HANDLE_VALUE) {
|
|
printf("Error: CreateFile failed - 0x%08x\n", GetLastError());
|
|
cstatus = FALSE;
|
|
}
|
|
else {
|
|
dwPipeMode = PIPE_READMODE_MESSAGE;
|
|
cstatus = SetNamedPipeHandleState(Clients[CIndex].c_Nmp.c_PipeHandle, // pipe handle
|
|
&dwPipeMode, // new pipe mode
|
|
NULL, // do not set the max bytes
|
|
NULL); // do not set the max time
|
|
if (cstatus == FALSE) {
|
|
printf("Error: SetNamedPipeHandleState failed - 0x%08x\n", GetLastError());
|
|
}
|
|
}
|
|
return(cstatus);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine allocates memory required for all the buffers for a client.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_Allocate_Memory(
|
|
IN USHORT CIndex) // client index and namedpipe instance number
|
|
{
|
|
NTSTATUS astatus = STATUS_SUCCESS;
|
|
ULONG AllocSize;
|
|
|
|
AllocSize = MAXBUFSIZE;
|
|
(LPVOID) Clients[CIndex].c_pSendBuf = VirtualAlloc(
|
|
(LPVOID) Clients[CIndex].c_pSendBuf,
|
|
(DWORD)AllocSize,
|
|
(DWORD)MEM_COMMIT,
|
|
(DWORD)PAGE_READWRITE);
|
|
sprintf(Clients[CIndex].c_pSendBuf,"Client%d Send Data",CIndex+1);
|
|
if (Clients[CIndex].c_pSendBuf == NULL) {
|
|
astatus = GetLastError();
|
|
printf("\nVirtual Alloc error\n");
|
|
}
|
|
AllocSize = MAXBUFSIZE;
|
|
(LPVOID) Clients[CIndex].c_pRecvBuf = VirtualAlloc(
|
|
(LPVOID) Clients[CIndex].c_pRecvBuf,
|
|
(DWORD)AllocSize,
|
|
(DWORD)MEM_COMMIT,
|
|
(DWORD)PAGE_READWRITE);
|
|
sprintf(Clients[CIndex].c_pRecvBuf,"Client%d Recv Data",CIndex+1);
|
|
if (Clients[CIndex].c_pRecvBuf == NULL) {
|
|
astatus = GetLastError();
|
|
printf("\nVirtual Alloc error\n");
|
|
}
|
|
return astatus;
|
|
}
|
|
/************************************************************************/
|
|
/*++
|
|
This routine deallocates memory for a client.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_Deallocate_Memory(
|
|
IN USHORT CIndex) // client index and namedpipe instance number
|
|
{
|
|
NTSTATUS dstatus;
|
|
ULONG DeallocSize;
|
|
|
|
DeallocSize = MAXBUFSIZE;
|
|
dstatus = VirtualFree(
|
|
(LPVOID) Clients[CIndex].c_pSendBuf,
|
|
DeallocSize,
|
|
MEM_DECOMMIT);
|
|
if (!NT_SUCCESS(dstatus)) {
|
|
return dstatus;
|
|
}
|
|
|
|
DeallocSize = MAXBUFSIZE;
|
|
dstatus = VirtualFree(
|
|
(LPVOID) Clients[CIndex].c_pRecvBuf,
|
|
DeallocSize,
|
|
MEM_DECOMMIT);
|
|
if (!NT_SUCCESS(dstatus)) {
|
|
return dstatus;
|
|
}
|
|
return dstatus;
|
|
}
|
|
/************************************************************************/
|
|
/*++
|
|
This routine is responsible for disconnecting a session.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_Disconnect_From_Server(
|
|
IN USHORT CIndex) // client index and namedpipe instance number
|
|
{
|
|
NTSTATUS dstatus;
|
|
|
|
dstatus = CloseHandle(Clients[CIndex].c_Nmp.c_PipeHandle);
|
|
|
|
if (!NT_SUCCESS(dstatus)) {
|
|
//DbgPrint("Nmp: Error in Disconnect err: %lx \n", dstatus);
|
|
}
|
|
return (dstatus);
|
|
}
|
|
|
|
/************************************************************************/
|
|
// no need for this function
|
|
/*
|
|
NTSTATUS
|
|
NamedPipe_FsControl(
|
|
IN HANDLE lhandle,
|
|
IN ULONG FsControlCode,
|
|
IN PVOID pInBuffer,
|
|
IN ULONG InBufLen,
|
|
OUT PVOID pOutBuffer,
|
|
IN ULONG OutBufLen)
|
|
{
|
|
|
|
NTSTATUS lstatus;
|
|
IO_STATUS_BLOCK ioStatusBlock;
|
|
DWORD actOutBufLen;
|
|
|
|
// now post listen on this handle
|
|
|
|
lstatus = NtFsControlFile (
|
|
lhandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&ioStatusBlock,
|
|
FsControlCode, // LISTEN or DISCONNECT or TRANSCEIVE maybe PEEK
|
|
pInBuffer,
|
|
InBufLen,
|
|
pOutBuffer, // Xceive or Peek buffer NULL otherwise
|
|
OutBufLen // Xceive or peek buffer length 0L otherwise
|
|
);
|
|
|
|
lstatus = TransactNamedPipe(lhandle, // pipe handle
|
|
pInBuffer, // write buffer
|
|
InBufLen, // write buffer length
|
|
pOutBuffer, // read buffer
|
|
OutBufLen, // read buffer length
|
|
&actOutBufLen, // the actual number of bytes read from the buffer
|
|
NULL);
|
|
if (lstatus == STATUS_PENDING) {
|
|
lstatus = WaitForSingleObjectEx(lhandle,
|
|
INFINITE,
|
|
TRUE);
|
|
if (NT_SUCCESS(lstatus)) {
|
|
lstatus = ioStatusBlock.Status;
|
|
if (!NT_SUCCESS(lstatus) &&(FsControlCode != FSCTL_PIPE_TRANSCEIVE)) {
|
|
//DbgPrint("Listen/Disconn/Xceive failed, err=%lx\n", lstatus);
|
|
}
|
|
}
|
|
else {
|
|
//DbgPrint("Error in Wait while FsCtrl %lx\n",lstatus);}
|
|
}
|
|
else {
|
|
if (NT_SUCCESS(lstatus)) {
|
|
lstatus = ioStatusBlock.Status;
|
|
}
|
|
else {
|
|
//DbgPrint("Error in FSCTL: %lx\n", lstatus);
|
|
}
|
|
}
|
|
|
|
return(lstatus);
|
|
|
|
}
|
|
/*
|
|
/************************************************************************/
|
|
/*++
|
|
This routine does handshake with it's peer. For Server this means
|
|
receiving request message from a client. For Client it means just the
|
|
opposite.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_DoHandshake(
|
|
IN USHORT CIndex, // client index and namedpipe instance number
|
|
IN USHORT SrvCli // if it's a server or client
|
|
)
|
|
{
|
|
NTSTATUS dstatus;
|
|
ULONG RWLen;
|
|
ULONG RWreqLen;
|
|
|
|
RWreqLen = sizeof(struct reqbuf);
|
|
// for server do receive for a request buffer
|
|
|
|
if (SrvCli) {
|
|
dstatus = ReadNamedPipe(
|
|
Clients[CIndex].c_Nmp.c_PipeHandle,
|
|
RWreqLen,
|
|
(PVOID) &(Clients[CIndex].c_reqbuf),
|
|
(PULONG) &RWLen);
|
|
if (!NT_SUCCESS(dstatus)) {
|
|
//DbgPrint("Nmp: Error in ReadNamedPipe: err:%lx \n", dstatus);
|
|
return dstatus;
|
|
}
|
|
|
|
}
|
|
else { // for Client do send of reqbuf size
|
|
// Based on TestCmd make changes i.e. 'U'->'P'
|
|
dstatus = WriteNamedPipe(
|
|
Clients[CIndex].c_Nmp.c_PipeHandle,
|
|
RWreqLen,
|
|
(PVOID) &(Clients[CIndex].c_reqbuf),
|
|
(PULONG) &RWLen);
|
|
if (!NT_SUCCESS(dstatus)) {
|
|
//DbgPrint("Nmp: Error in WriteNamedPipe: err:%lx \n", dstatus);
|
|
return dstatus;
|
|
}
|
|
}
|
|
// check if read/write length is ok
|
|
if (RWLen != sizeof(struct reqbuf)) {
|
|
//DbgPrint("Nmp: Read/WriteNamedPipe Len mismatch: read %ld \n", RWLen);
|
|
}
|
|
// MyDbgPrint("handshake: Sendl:%ld Recvl:%ld \n",Clients[CIndex].c_reqbuf.SendSize,Clients[CIndex].c_reqbuf.RecvSize);
|
|
return dstatus;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine Reads data from IPC. For server it means reading data
|
|
NumSends times in SendBuffers and for a client NumRecvs times into
|
|
RecvBuffer.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_ReadFromIPC(
|
|
IN USHORT CIndex, // client index and namedpipe instance number
|
|
IN OUT PULONG pReadDone,
|
|
IN USHORT SrvCli) // if it's a server or client
|
|
{
|
|
NTSTATUS rstatus;
|
|
ULONG NumReads;
|
|
ULONG ReadLen;
|
|
PCHAR ReadBuf;
|
|
|
|
if (SrvCli) { // set proper iterations and buffer for Server
|
|
NumReads = Clients[CIndex].c_reqbuf.NumSends;
|
|
ReadBuf = Clients[CIndex].c_pSendBuf;
|
|
ReadLen = Clients[CIndex].c_reqbuf.SendSize;
|
|
}
|
|
else { // for client do proper settings
|
|
NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
|
|
ReadBuf = Clients[CIndex].c_pRecvBuf;
|
|
ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
|
|
}
|
|
while (NumReads--) {
|
|
rstatus = ReadNamedPipe(
|
|
Clients[CIndex].c_Nmp.c_PipeHandle,
|
|
ReadLen,
|
|
(PVOID) ReadBuf,
|
|
(PULONG) pReadDone);
|
|
if (!NT_SUCCESS(rstatus)) {
|
|
//DbgPrint("Nmp: Error in ReadNamedPipe: err:%lx \n", rstatus);
|
|
break;
|
|
}
|
|
}
|
|
return rstatus;
|
|
}
|
|
/************************************************************************/
|
|
NTSTATUS
|
|
ReadNamedPipe(
|
|
IN HANDLE rhandle,
|
|
IN ULONG rlength,
|
|
IN OUT PVOID rpbuffer,
|
|
IN OUT PULONG rpdatalen)
|
|
{
|
|
NTSTATUS rstatus;
|
|
DWORD actRLength;
|
|
|
|
rstatus = ReadFile( rhandle, // pipe handle
|
|
rpbuffer, // buffer to receive reply
|
|
rlength, // size of the buffer
|
|
&actRLength, // number of bytes read
|
|
NULL); // not overlapped
|
|
if (rstatus == TRUE) {
|
|
*rpdatalen = actRLength;
|
|
}
|
|
else {
|
|
if (GetLastError() == ERROR_MORE_DATA) {
|
|
rstatus = WaitForSingleObjectEx(rhandle,
|
|
INFINITE,
|
|
TRUE);
|
|
if (rstatus == TRUE) {
|
|
*rpdatalen = actRLength;
|
|
if (rlength != *rpdatalen) {
|
|
printf("Error: No. of bytes read != buffer length\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(rstatus);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine Writes data to IPC. For server it means writing data
|
|
NumRecvs times in RecvBuffers and for a client NumSends times into
|
|
SendBuffer.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_WriteToIPC(
|
|
IN USHORT CIndex, // client index and namedpipe instance number
|
|
IN OUT PULONG pWriteDone,
|
|
IN USHORT SrvCli) // if it's a server or client
|
|
{
|
|
NTSTATUS wstatus;
|
|
ULONG NumWrites;
|
|
ULONG WriteLen;
|
|
PCHAR WriteBuf;
|
|
|
|
if (SrvCli) { // set proper iterations and buffer for Server
|
|
NumWrites = Clients[CIndex].c_reqbuf.NumRecvs;
|
|
WriteBuf = Clients[CIndex].c_pRecvBuf;
|
|
WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
|
|
}
|
|
else { // for client do proper settings
|
|
NumWrites = Clients[CIndex].c_reqbuf.NumSends;
|
|
WriteBuf = Clients[CIndex].c_pSendBuf;
|
|
WriteLen = Clients[CIndex].c_reqbuf.SendSize;
|
|
}
|
|
while (NumWrites--) {
|
|
wstatus = WriteNamedPipe(
|
|
Clients[CIndex].c_Nmp.c_PipeHandle,
|
|
WriteLen,
|
|
(PVOID) WriteBuf,
|
|
(PULONG) pWriteDone);
|
|
if (!NT_SUCCESS(wstatus)) {
|
|
//DbgPrint("Nmp: Error in WriteNamedPipe: err:%lx \n", wstatus);
|
|
break;
|
|
}
|
|
}
|
|
return wstatus;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/*++
|
|
This routine does transaction type IO to IPC. This just assumes that
|
|
both Number of reads and writes are equal and will use Number of reads
|
|
as it's basis.
|
|
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_XactIO(
|
|
IN USHORT CIndex, // client index and namedpipe instance number
|
|
IN OUT PULONG pReadDone,
|
|
IN OUT PULONG pWriteDone,
|
|
IN USHORT SrvCli, // if it's a server or client
|
|
IN BOOLEAN FirstIter) // ignore for NamedPipe
|
|
{
|
|
NTSTATUS xstatus;
|
|
ULONG NumReads;
|
|
ULONG ReadLen;
|
|
PCHAR ReadBuf;
|
|
ULONG WriteLen;
|
|
PCHAR WriteBuf;
|
|
DWORD actReadLen;
|
|
|
|
NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
|
|
|
|
if (SrvCli) { // set proper iterations and buffer for Server
|
|
ReadBuf = Clients[CIndex].c_pSendBuf;
|
|
ReadLen = Clients[CIndex].c_reqbuf.SendSize;
|
|
WriteBuf = Clients[CIndex].c_pRecvBuf;
|
|
WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
|
|
}
|
|
else { // for client do proper settings
|
|
ReadBuf = Clients[CIndex].c_pRecvBuf;
|
|
ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
|
|
WriteBuf = Clients[CIndex].c_pSendBuf;
|
|
WriteLen = Clients[CIndex].c_reqbuf.SendSize;
|
|
}
|
|
while (NumReads--) {
|
|
xstatus = TransactNamedPipe(Clients[CIndex].c_Nmp.c_PipeHandle, // pipe name
|
|
WriteBuf, // write buffer
|
|
WriteLen, // write buffer length
|
|
ReadBuf, // read buffer
|
|
ReadLen, // read buffer length
|
|
&actReadLen, // actual read buffer length
|
|
NULL); // not overlapped
|
|
if (xstatus == FALSE) {
|
|
printf("Error: TransactNamedPipe failed - 0x%08x\n", GetLastError());
|
|
*pReadDone = 0L;
|
|
*pWriteDone = 0L;
|
|
break;
|
|
}
|
|
*pReadDone = ReadLen;
|
|
*pWriteDone = WriteLen;
|
|
}
|
|
return xstatus;
|
|
}
|
|
|
|
/************************************************************************/
|
|
NTSTATUS
|
|
WriteNamedPipe(
|
|
IN HANDLE whandle,
|
|
IN ULONG wlength,
|
|
IN OUT PVOID wpbuffer,
|
|
IN OUT PULONG wpdatalen)
|
|
{
|
|
NTSTATUS wstatus;
|
|
DWORD actWLength;
|
|
|
|
wstatus = WriteFile(whandle, // pipe handle
|
|
wpbuffer, // address of data buffer to write to file
|
|
wlength, // length of data buffer
|
|
&actWLength,// actual length of data read
|
|
NULL); // not overlapped
|
|
if (wstatus == TRUE) {
|
|
*wpdatalen = actWLength;
|
|
}
|
|
else {
|
|
if (GetLastError() == ERROR_MORE_DATA) {
|
|
wstatus = WaitForSingleObjectEx(whandle,
|
|
INFINITE,
|
|
TRUE);
|
|
if (wstatus == TRUE) {
|
|
*wpdatalen = actWLength;
|
|
if (wlength != *wpdatalen) {
|
|
printf("Error: No. of bytes written != buffer length\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(wstatus);
|
|
}
|
|
/************************************************************************/
|
|
// this is now a win32 defined function
|
|
/*
|
|
NTSTATUS DisconnectNamedPipe(IN HANDLE dhandle)
|
|
{
|
|
|
|
NTSTATUS wstatus;
|
|
// IO_STATUS_BLOCK ioStatusBlock;
|
|
wstatus = NamedPipe_FsControl( // post DisConnect
|
|
dhandle,
|
|
FSCTL_PIPE_DISCONNECT,
|
|
NULL, // input buffer
|
|
0L, // inbuf len
|
|
NULL, // output buffer
|
|
0L); // outbuf len
|
|
if (!NT_SUCCESS(wstatus)) {
|
|
//DbgPrint ("Pipe Disconnect failed, err=%lx\n", wstatus);
|
|
}
|
|
return(wstatus);
|
|
}
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/*++ This routine creates one instance of NamedPipe for a given client.
|
|
A client is identified by its index number.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
CreateNamedPipeInstance(
|
|
IN USHORT Nindex) // client index and namedpipe instance number
|
|
{
|
|
NTSTATUS nstatus = 0;
|
|
HANDLE NMPhandle;
|
|
|
|
NMPhandle = CreateNamedPipe(pipeName, // the given pipe name entered by the user
|
|
PIPE_ACCESS_DUPLEX, // GENERIC_READ | GENERIC_WRITE
|
|
PIPE_READMODE_MESSAGE | // pipe mode (message...)
|
|
PIPE_TYPE_MESSAGE |
|
|
PIPE_WAIT,
|
|
NClients, // max number of instances(clients)
|
|
Quotas, // max in buffer length
|
|
Quotas, // max out buffer length
|
|
600000, // 60 second default timeout
|
|
NULL); // default security attributes
|
|
if (NMPhandle == INVALID_HANDLE_VALUE) {
|
|
nstatus = GetLastError();
|
|
printf ("Failed to Create NamedPipe, err=%lx, %ld\n", nstatus, nstatus);
|
|
}
|
|
else {
|
|
// initialize this client's values
|
|
Clients[Nindex].c_Nmp.c_PipeHandle = NMPhandle;
|
|
Clients[Nindex].c_client_num = Nindex;//index into the Client array
|
|
}
|
|
return(nstatus);
|
|
}
|
|
/************************************************************************/
|
|
NTSTATUS
|
|
NMP_Cleanup(VOID)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
/************************************************************************/
|
|
|
|
/*++
|
|
This routine does a client specific cleanup work.
|
|
--*/
|
|
|
|
NTSTATUS
|
|
NMP_ThreadCleanUp(
|
|
IN USHORT CIndex)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
/************************************************************************/
|