Solved

Asynchronous I/O Piping

Posted on 2004-04-19
9
1,436 Views
Last Modified: 2007-12-19
I am trying to work out how to construct a pipe where the client does not need to wait, while calling the WriteFile(), until the server completed its ReadFile() call.

/*
 * Client
 */
void ClientWriteToPipe() {
...
   fSuccess = WriteFile(hPipe, packet, nLength, &cbWritten, &clientoverlapped);

...
}


/*
 * Server
 */
void ServerReadFromPipe() {
...
   fSuccess = ReadFile(hPipe,&readPacket,sizeof(someStruct),&cbBytesRead,&serveroverlapped);
...
}

can anyone tell me how to construct the pipe connection, read from pipe, and write to pipe appropriately? i failed to read the data correctly(as in the amount of data written by client does not match with the amount of data read by server)...

please help!! thanks in advance...

gotenks
0
Comment
Question by:gotenks
  • 5
  • 3
9 Comments
 
LVL 45

Expert Comment

by:sunnycoder
ID: 10865900
Hi gotenks,

post the complete code and we will try to get it working

Sunnycoder
0
 

Author Comment

by:gotenks
ID: 10867757
Sunnycoder,
sorry for late reply, below are the code :

/*
   ServerPipe.c
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 50
#define MAX_BUF_SIZE 512
#define MY_PIPENAME "\\\\.\\pipe\\mypipe"

#define STOPPIPE_EVT "StopPipeEvent"

typedef unsigned char BYTE;
#define BOOL bool

OVERLAPPED overlapped;

void BackgroundThread(void);
BOOL ServerReadPipe(HANDLE);

HANDLE InitServerPipeConnection();
void CloseServerPipeConnection(HANDLE);

//Signal and wait functions
void WaitStopPipeEvent();
BOOL SignalStopPipeEvent();

int main() {
      DWORD dwThreadId;
      HANDLE hThread;

      hThread = CreateThread(
            NULL,                  //no security attribute
            0,                  //default stack size
            (LPTHREAD_START_ROUTINE) BackgroundThread,
            NULL,            //thread parameter
            0,                  //not suspended
            &dwThreadId);            //returns thread ID

      if (hThread == NULL) {
            return 0;
      }
      else {
            CloseHandle(hThread);
      }
      
      WaitStopPipeEvent();
      Sleep(1000);
      return 1;
}

void BackgroundThread() {
      HANDLE hPipe;
      BYTE chReadBuf[BUFSIZE];
      DWORD cbBytesRead;
      DWORD dwMode;
      BOOL fConnected, fSuccess;
      BOOL fMoreData = FALSE;
      int i;

      printf("Starting background thread...\n");
      hPipe = InitServerPipeConnection();
      
      if(hPipe == INVALID_HANDLE_VALUE) {
            // Pipe creation failed. Return and exit thread?
            while(!SignalStopPipeEvent());
      
            return;
      }

      printf("Waiting for client connection...\n");
      // Wait for client to make connection with this pipe
      fConnected = ConnectNamedPipe(hPipe, NULL) ?
                        TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);

      if (fConnected) {
            // Wait for data to be read from pipe
            while (1) {
                  // NOTE: there might be time that the data to
                  // read needs more than a loop to success
                  fSuccess = ReadFile(
                        hPipe,            //handle to pipe
                        &chReadBuf,      //buffer to recieve data
                        BUFSIZE,      //size of buffer
                        &cbBytesRead,      //number of bytes read
                        &overlapped);            //not overlapped I/O

                  if (fSuccess) {
                        printf("Client data : %s\n", chReadBuf);
                  }
                  else {
                        if(cbBytesRead == 0) {
                              break;
                        }
                  }
            }

            FlushFileBuffers(hPipe);
            DisconnectNamedPipe(hPipe);
            printf("Client closes connection\n");
      }
      
      CloseServerPipeConnection(hPipe);
      while(!SignalStopPipeEvent());
}


HANDLE InitServerPipeConnection() {
      HANDLE hPipe;
      LPTSTR lpszPipename = MY_PIPENAME;

      hPipe = CreateNamedPipe(
            lpszPipename,                  //pipe name
            PIPE_ACCESS_DUPLEX,            //read/write access
            PIPE_TYPE_MESSAGE |             //message type pipe
            PIPE_READMODE_MESSAGE |            //message-read mode
            PIPE_WAIT,                   //blocking mode
//      PIPE_NOWAIT,                   //non-blocking mode
//      PIPE_UNLIMITED_INSTANCES,      //max. instances
            1,                              //1 instance
            BUFSIZE,                  //output buffer size
            BUFSIZE,                  //input buffer size
            NMPWAIT_USE_DEFAULT_WAIT,      //client time-out
            NULL);                        //no security attribute

      return hPipe;
}

BOOL ServerReadPipe(HANDLE hPipe) {
      BOOL fSuccess = FALSE;
      char chReadBuf[BUFSIZE];
      DWORD cbBytesRead;

      fSuccess = ReadFile(
            hPipe,            //handle to pipe
            &chReadBuf,      //buffer to recieve data
            BUFSIZE,      //size of buffer
            &cbBytesRead,      //number of bytes read
            &overlapped);            //not overlapped I/O

      if (fSuccess) {
            printf("Client message : %s\n", chReadBuf);
      }

      if(!fSuccess || cbBytesRead == 0) {
            return fSuccess;
      }
      else
            return TRUE;
}

void WaitStopPipeEvent() {        
      HANDLE hWaitStopEvent;
      
      // Create a request event
      hWaitStopEvent = CreateEvent(NULL, FALSE, FALSE, STOPPIPE_EVT);
      // if CreateEvent fails, then this event might already exists
      // therefore, check if the error message is ERROR_ALREADY_EXISTS
      if ( hWaitStopEvent == NULL && GetLastError() == ERROR_ALREADY_EXISTS) {
            // since event already exists,
            // open this event
            hWaitStopEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, STOPPIPE_EVT);
      }

      // Wait until this request event is signalled
      WaitForSingleObject(hWaitStopEvent, INFINITE);
      // Event has been signalled, reset this event
      ResetEvent(hWaitStopEvent);
      // Close the handle of this event
      CloseHandle(hWaitStopEvent);
}

BOOL SignalStopPipeEvent() {
      HANDLE hSignalStopEvent;
      BOOL bSt = TRUE;

      hSignalStopEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, STOPPIPE_EVT);
      if ( hSignalStopEvent == NULL ) {
            return FALSE;
      }

      bSt = SetEvent(hSignalStopEvent);
      CloseHandle(hSignalStopEvent);

    return bSt;
}

void CloseServerPipeConnection(HANDLE hPipe) {
      CloseHandle(hPipe);
}

/*
   ClientPipe.c
*/

#include <windows.h>
#include <stdio.h>

#define BUFSIZE 50
#define MAX_BUF_SIZE 512
#define MY_PIPENAME "\\\\.\\pipe\\mypipe"

typedef unsigned char BYTE;

OVERLAPPED overlapped;

HANDLE InitClientPipeConnection();
BOOL ClientWritePipe(HANDLE, BYTE *, DWORD);
void CloseClientPipeConnection(HANDLE);
void EvaluateData(BYTE *);

int main()
{
      HANDLE hPipe;
      BYTE buffer[BUFSIZE];
      DWORD nLength;
      int index = 0;

      hPipe = InitClientPipeConnection();
      
      if (hPipe == INVALID_HANDLE_VALUE ){
            return 0;
      }

    while (index < 5) {
        sprintf((char *)buffer, "default data from client %i", (index + 1));
            nLength = strlen((const char*)buffer);
            ClientWritePipe(hPipe,buffer, nLength);
            index++;
    }

      Sleep(5000);
    CloseClientPipeConnection(hPipe);

      return 0;
}

BOOL ClientReadPipe(HANDLE hPipe) {
      BOOL fSuccess = FALSE;
      char chReadBuf[BUFSIZE];
      DWORD cbRead;

      while(1) {
            fSuccess = ReadFile(
                  hPipe,    // pipe handle
                  &chReadBuf,    // buffer to receive reply
                  BUFSIZE,      // size of buffer
                  &cbRead,  // number of bytes read
                  &overlapped);    // not overlapped

            overlapped.Offset = overlapped.Offset + cbRead;

          if (! fSuccess && GetLastError() != ERROR_MORE_DATA)
                  break;
      }

      return fSuccess;
}

BOOL ClientWritePipe(HANDLE hPipe, BYTE * packet, DWORD nLength) {
      BOOL fSuccess = FALSE;
      DWORD cbWritten;

      fSuccess = WriteFile(
            hPipe,                  // pipe handle
            packet,             // message
            nLength + 1, // message length
            &cbWritten,             // bytes written
            &overlapped);                  // not overlapped

      overlapped.Offset = overlapped.Offset + cbWritten;
      
      return fSuccess;
}


HANDLE InitClientPipeConnection() {
      BOOL fSuccess = FALSE;
      HANDLE hPipe;
      DWORD dwMode;
      char * lpszPipename = MY_PIPENAME;

      // Try to open a named pipe; wait for it, if necessary.
      while (1)
      {
            hPipe = CreateFile(
                  lpszPipename,   // pipe name
                  GENERIC_READ |  // read and write access
                  GENERIC_WRITE,
                  0,              // no sharing
                  NULL,           // no security attributes
                  OPEN_EXISTING,  // opens existing pipe
                  FILE_FLAG_OVERLAPPED, // overlapped
                  NULL);          // no template file

            // Break if the pipe handle is valid.
            if (hPipe != INVALID_HANDLE_VALUE)
                  break;

            // Exit if an error other than ERROR_PIPE_BUSY occurs.
            if (GetLastError() != ERROR_PIPE_BUSY)
            {
                  return hPipe;
            }

            // All pipe instances are busy, so wait for 20 seconds.
            if (!WaitNamedPipe(lpszPipename, 20000))
            {
                  return hPipe;
            }
      }

      // The pipe connected; change to message-read mode and NO WAIT mode.
      dwMode = PIPE_READMODE_MESSAGE | PIPE_NOWAIT;
      fSuccess = SetNamedPipeHandleState(
            hPipe,    // pipe handle
            &dwMode,  // new pipe mode
            NULL,     // don't set maximum bytes
            NULL);    // don't set maximum time

      if (!fSuccess)
      {
            return hPipe;
      }

      return hPipe;
}

void EvaluateData(BYTE * buffer) {
      printf("Buffer from server : %s\n", buffer);
}

void CloseClientPipeConnection(HANDLE hPipe) {
    CloseHandle(hPipe);
}


Thanks!!

gotenks
0
 

Author Comment

by:gotenks
ID: 10867779
before this, i did not change the mode to PIPE_NOWAIT, but for the above, i changed it to PIPE_NOWAIT inside InitClientPipeConnection().
Before changing, i need to wait until server completes the reading before the client can send the next data, and the server is able to receive all the five packets sent.

...
     dwMode = PIPE_READMODE_MESSAGE | PIPE_NOWAIT;
     fSuccess = SetNamedPipeHandleState(
          hPipe,    // pipe handle
          &dwMode,  // new pipe mode
          NULL,     // don't set maximum bytes
          NULL);    // don't set maximum time
...

gotenks
0
 

Author Comment

by:gotenks
ID: 10884293
sunnycoder,

i have made some changes inside Client.c and Server.c as below :
for client, i check for the writefile return value (success or failed) and if failed, do some other stuff for a while (like sleep(100), etc...). this works fine but the problem arises when server needs more than 100 miliseconds (if i set sleep(100) for client). i.e. the problem will still occurs if server took more than 100 miliseconds to process the data from client.

i have also increased the input buffer for the pipe from BUFSIZE to 3 * BUFSIZE but that doesn't seems to help much. however, it is surely better than using just BUFSIZE.

any idea?
and how do we actually flush/clear the pipe buffer? or can we?


// Client.c
BOOL ClientWritePipe(HANDLE hPipe, BYTE * packet, DWORD nLength) {
      static int index = 0;
      BOOL fSuccess = FALSE;
      BOOL bResult;
      DWORD cbWritten;
      DWORD dwError;

      fSuccess = WriteFile(
            hPipe,                  // pipe handle
            packet,             // message
            nLength + 1, // message length
            &cbWritten,             // bytes written
            &gOverlapped);                  // not overlapped

      index++;

      if (!fSuccess)
      {
            switch (dwError = GetLastError())
            {
        case ERROR_HANDLE_EOF:
                  {
                        printf("ERROR_HANDLE_EOF\n");
                  }
                  
        case ERROR_IO_PENDING:
                  {
                        printf("ERROR_IO_PENDING at %d\n", index);
                        // do something else for a while
                        Sleep(100);
//                        WaitWritePipeEvent(100);
                        
                        bResult = GetOverlappedResult(hPipe, &gOverlapped,
                              &cbWritten, FALSE) ;
                        
                        if (!bResult)
                        {
                              switch (dwError = GetLastError())
                              {
                    case ERROR_HANDLE_EOF:
                                    {
                                          printf("ERROR_HANDLE_EOF\n");
                                    }
                              }
                        }
                  } // end case
            } // end switch
      } // end if

      return fSuccess;
}


// Server.c
HANDLE InitServerPipeConnection() {
...
      hPipe = CreateNamedPipe(
            lpszPipename,                  //pipe name
            PIPE_ACCESS_DUPLEX,            //read/write access
            PIPE_TYPE_MESSAGE |             //message type pipe
            PIPE_READMODE_MESSAGE |            //message-read mode
            PIPE_WAIT,                   //blocking mode
//      PIPE_NOWAIT,                   //non-blocking mode
//      PIPE_UNLIMITED_INSTANCES,      //max. instances
            1,                              //1 instance
            BUFSIZE,                  //output buffer size
            3 * BUFSIZE,                  //input buffer size
            NMPWAIT_USE_DEFAULT_WAIT,      //client time-out
            NULL);                        //no security attribute
...
}

void BackgroundThread() {
...
            while (1) {
                  fSuccess = ReadFile(
                        hPipe,            //handle to pipe
                        &chReadBuf,      //buffer to recieve data
                        BUFSIZE,      //size of buffer
                        &cbBytesRead,      //number of bytes read
                        &overlapped);            //not overlapped I/O

                  if (fSuccess) {
                        printf("Client data : %s\n", chReadBuf);
                        index++;
                        Sleep(50);
                  }
                  else {
                        if(cbBytesRead == 0) {
                              break;
                        }
                  }
            }
...
      }
...
}

0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 4

Expert Comment

by:booki
ID: 10895689
gotenks,

On examination, you have created the pipe for non-overlapped io.  The OVERLAPPED parameter to ReadFile/WriteFile should be NULL.

I have run your code changing only the OVERLAPPED parameter to NULL in ReadFile/WriteFile and it seems to work fine.  I also removed the calls to sleep in both client and server.

b.
0
 

Author Comment

by:gotenks
ID: 10897542
booki,

actually what i would like to achieve is below :

1)client doesn't need to wait for server. i.e. client will continue sending data to pipe by calling WriteFile and immediately return from WriteFile function without waiting for server to complete reading that data written by client.

2)the server will read the data and then process it (which will take some time and i purposely put in the Sleep() after reading the data to somehow simulate the processing). and since i wish to make the client to return immediately without waiting for the server finish reading that data (to put it in the other way, the client will just keep throwing data to that pipe without caring if server is fast enough to read that data and process it).

any idea of how to achieve this?
thanks,

gotenks
0
 
LVL 4

Expert Comment

by:booki
ID: 10898664
gotenks,

use overlapped io on the client side.  in your call to  SetNamedPipeHandleState do not use PIPE_NOWAIT.  As it says in the documentation you should not use it to acheive asynchronous io.

here's a link to a named pipe server using completion routines (overlapped io).  you can do something similar on the client side.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ipc/base/named_pipe_server_using_completion_routines.asp

As an alternative, you may want to consider a multithreaded server where io is handled by one thread and processing is handled by another.

b.
0
 
LVL 4

Accepted Solution

by:
booki earned 100 total points
ID: 10901640
gotenks,

Well, you're in luck.  I had some spare time so here's the client code.  You can use your server code as is (your original post).

b.

////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <stdio.h>

#define MY_PIPENAME "\\\\.\\pipe\\mypipe"
#define BUFSIZE 50

typedef struct _tagIOREQUEST {
      union {
            DWORD Offset;
            DWORD IoPending;
      };
      DWORD OffsetHigh;
      DWORD dwAdditionalIoContext;
      BOOL bRead;
      HANDLE hFile;
      LPVOID lpBuffer;
      DWORD dwTransferCount;
      HANDLE hHeap;
      struct _tagIOREQUEST *next;
}IOREQUEST, *PIOREQUEST;


IOREQUEST IoRequestList;
HANDLE IoWorkerListLock; // mutex
HANDLE IoWorkerListSemaphore; // semaphore
HANDLE ExitEvent; // event
HANDLE IoPendingEvent; //

BOOL NoIoPending(PIOREQUEST pIoRequestList) {
      return pIoRequestList->IoPending == 0;
}

PIOREQUEST RemoveHeadList(PIOREQUEST pIoRequestList) {
      PIOREQUEST pHead;
      if ((pHead = pIoRequestList->next) != NULL) {
            pIoRequestList->next = pIoRequestList->next->next;
            ++(pIoRequestList->IoPending);
      }
      return pHead;
}

void IoCompletedList(PIOREQUEST pIoRequestList) {
      --(IoRequestList.IoPending);
}

void EnqueueList(PIOREQUEST pIoRequestList,PIOREQUEST pIoRequest) {
      PIOREQUEST ptr = pIoRequestList;
      while (ptr->next) ptr = ptr->next;
      ptr->next = pIoRequest;
      pIoRequest->next = NULL;
}


//Completion Routine:
VOID CALLBACK IoCompletionRoutine(DWORD dwErrorCode,
            DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) {
      HANDLE hHeap;
      // If an I/O error occurs, display the error and exit.
      if (dwErrorCode) {
            printf("FATAL I/O Error %ld I/O Context %lx.%lx\n",
                  dwErrorCode, lpOverlapped, lpOverlapped->hEvent);
            ExitProcess(dwErrorCode);
      }
      hHeap = GetProcessHeap();
      printf("Client Write Completed\n");
      HeapFree(hHeap,0,lpOverlapped);
      WaitForSingleObjectEx(IoWorkerListLock,INFINITE,FALSE);
      IoCompletedList(&IoRequestList);
      if (NoIoPending(&IoRequestList))
            SetEvent(IoPendingEvent);
      ReleaseMutex(IoWorkerListLock);
}

//Main Thread:
VOID IoWorkerThread(LPVOID lpvParam) {
      HANDLE HandleVector[4];
      DWORD CompletionStatus;
      PIOREQUEST IoRequestPacket;
      LPOVERLAPPED Overlapped;
      BOOL IoOperationStatus;
      HANDLE hHeap;
      HandleVector[0] = IoWorkerListSemaphore;
      HandleVector[1] = ExitEvent;
      HandleVector[2] = IoWorkerListLock;
      HandleVector[3] = IoPendingEvent;
      hHeap = GetProcessHeap();

      for(;;) {
            // Do an alertable wait on the handle vector.
            CompletionStatus = WaitForMultipleObjectsEx(2, HandleVector,
                  FALSE, INFINITE, TRUE);
 
            // If the wait failed, error out.
            if (CompletionStatus == -1) {
                  printf("FATAL WAIT ERROR %ld\n", GetLastError());
                  ExitProcess(1);
            }
            // If an I/O completion occurred, wait for another
            // I/O request or I/O completion.
            if (CompletionStatus != WAIT_IO_COMPLETION) {
                  // The wait was satisfied. there is something in
                  // the queue or the main thread has requested an exit.
                  if (CompletionStatus == WAIT_OBJECT_0) {
                        ; // do nothing.. ExitEvent may be signaled but don't break
                  } else if (CompletionStatus == WAIT_OBJECT_0+1) {
                        break; // ExitEvent signaled.. break out of for(;;)
                  }
                  CompletionStatus = WaitForSingleObjectEx(HandleVector[2],INFINITE,TRUE);
                  // If the wait failed, error out.
                  if (CompletionStatus == -1) {
                        printf("FATAL WAIT ERROR %ld\n", GetLastError());
                        ExitProcess(1);
                  }
                  // If an I/O completion occurred, wait for another
                  // I/O request or I/O completion.
                  if (CompletionStatus != WAIT_IO_COMPLETION) {
                        // Ownership of the I/O request queue is exclusive.
                        // To insert something in the queue, the
                        // inserter gets the list lock (mutex), inserts an entry,
                        // signals the list semaphore, and finally releases the
                        // list lock.
      
                        IoRequestPacket = RemoveHeadList(&IoRequestList);
                        ReleaseMutex(IoWorkerListLock);

                        // Allocate an overlapped structure.
                        Overlapped = (LPOVERLAPPED)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(OVERLAPPED));
                        if (!Overlapped) {
                              printf("FATAL allocation error\n");
                              ExitProcess(1);
                        }

                        Overlapped->Offset = IoRequestPacket->Offset;
                        Overlapped->OffsetHigh = IoRequestPacket->OffsetHigh;
                        Overlapped->hEvent =
                                    (HANDLE)IoRequestPacket->dwAdditionalIoContext;
                        if (IoRequestPacket->bRead) {IoOperationStatus = ReadFileEx(IoRequestPacket->hFile,
                                    IoRequestPacket->lpBuffer,
                                    IoRequestPacket->dwTransferCount,
                                    Overlapped, IoCompletionRoutine);
                        } else {
                              printf("Client Write Initiated: %s\n", IoRequestPacket->lpBuffer);
                              IoOperationStatus = WriteFileEx(IoRequestPacket->hFile,
                                          IoRequestPacket->lpBuffer,
                                          IoRequestPacket->dwTransferCount,
                                          Overlapped,IoCompletionRoutine);
                              HeapFree(hHeap,0,IoRequestPacket->lpBuffer);
                        }
                        ResetEvent(HandleVector[3]);
      
                        HeapFree(hHeap,0,IoRequestPacket);

                        // Test to see if the I/O was queued successfully.
                        if (!IoOperationStatus) {
                              printf("FATAL I/O Error %ld I/O Context %lx.%lx\n",
                                    GetLastError(), Overlapped, Overlapped->hEvent);
                              ExitProcess(1);
                        }
      
                        // The I/O queued successfully. Go back into the
                        // alertable wait for I/O completion or for
                        // more I/O requests.
                  }
            }
      }
      // Wait for all pending io to complete before exiting
      for (;;) {
            CompletionStatus = WaitForSingleObjectEx(HandleVector[3],INFINITE,TRUE);
            if (CompletionStatus == -1) {
                  printf("FATAL WAIT ERROR %ld\n", GetLastError());
                  ExitProcess(1);
            }
            if (CompletionStatus != WAIT_IO_COMPLETION) {
                  if (CompletionStatus == WAIT_OBJECT_0) {
                        break;
                  } else {
                        break; // error
                  }
            }
      }
}


ClientWritePipe(HANDLE hPipe, LPVOID buffer, int nLength) {
      static HANDLE hHeap = GetProcessHeap();
      DWORD dwWaitResult;
      PIOREQUEST pIoRequest;
      pIoRequest = (PIOREQUEST)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(IOREQUEST));
      pIoRequest->hFile = hPipe;
      pIoRequest->lpBuffer = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(IOREQUEST));
      CopyMemory(pIoRequest->lpBuffer,buffer,nLength);
      pIoRequest->dwTransferCount = nLength;
      pIoRequest->hHeap = hHeap;
      pIoRequest->bRead = FALSE;
      dwWaitResult = WaitForSingleObjectEx(IoWorkerListLock,INFINITE,FALSE);
      if (dwWaitResult != WAIT_OBJECT_0)
            return FALSE;
      EnqueueList(&IoRequestList,pIoRequest);
      ReleaseMutex(IoWorkerListLock);
      if (!ReleaseSemaphore(IoWorkerListSemaphore,1,NULL))
            return FALSE; // Deal with the error.
      return TRUE;
}

BOOL ClientReadPipe(HANDLE hPipe, LPVOID buffer, int nLength) {
      static HANDLE hHeap = GetProcessHeap();
      DWORD dwWaitResult;
      PIOREQUEST pIoRequest;
      pIoRequest = (PIOREQUEST)HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(IOREQUEST));
      pIoRequest->hFile = hPipe;
      pIoRequest->lpBuffer = buffer;
      pIoRequest->dwTransferCount = nLength;
      pIoRequest->hHeap = hHeap;
      pIoRequest->bRead = TRUE;
      dwWaitResult = WaitForSingleObjectEx(IoWorkerListLock,INFINITE,FALSE);
      if (dwWaitResult != WAIT_OBJECT_0)
            return FALSE;
      EnqueueList(&IoRequestList,pIoRequest);
      ReleaseMutex(IoWorkerListLock);
      if (!ReleaseSemaphore(IoWorkerListSemaphore,1,NULL))
            return FALSE; // Deal with the error.
      return TRUE;
}

int main() {
      HANDLE hPipe, hIoThread;
      LPTSTR lpszPipename = MY_PIPENAME;
      BYTE buffer[BUFSIZE];
      DWORD nLength;
      int index = 0;
      BOOL fSuccess;
      DWORD dwMode, dwThreadId;

      IoWorkerListLock = CreateMutex(NULL,FALSE,NULL);
      IoWorkerListSemaphore = CreateSemaphore(NULL,0,100,NULL);
      ExitEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
      IoPendingEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
      ZeroMemory(&IoRequestList,sizeof(IOREQUEST));

      while (1) {
            hPipe = CreateFile(lpszPipename,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,
                  FILE_FLAG_OVERLAPPED,NULL);
             // Break if the pipe handle is valid.
            if ((hPipe != INVALID_HANDLE_VALUE) && (hPipe))
                  break;
             // Exit if an error other than ERROR_PIPE_BUSY occurs.
            if ((GetLastError()) != ERROR_PIPE_BUSY)
                  return 0; // Could not open pipe
             // All pipe instances are busy, so wait for 20 seconds.
            if (! WaitNamedPipe(lpszPipename, 20000) )
                  return 0; // Could not open pipe
      }
      // The pipe connected; change to message-read mode.
      dwMode = PIPE_READMODE_MESSAGE;
      fSuccess = SetNamedPipeHandleState(hPipe,&dwMode,NULL,NULL);
      if (!fSuccess)
            return 0; // SetNamedPipeHandleState failed

      hIoThread = CreateThread(
            NULL,              // no security attribute
            0,                 // default stack size
            (LPTHREAD_START_ROUTINE) IoWorkerThread,
            (LPVOID) hPipe,    // thread parameter
            0,                 // not suspended
            &dwThreadId);      // returns thread ID
      if (hIoThread == NULL)
            return 0; // CreateThread failed

      while (index < 5) {
            sprintf((char *)buffer, "default data from client %i", (index + 1));
            nLength = strlen((const char*)buffer);
            ClientWritePipe(hPipe,buffer, nLength);
            index++;
      }

      SetEvent(ExitEvent);  // notify thread of exit
      WaitForSingleObject(hIoThread,INFINITE); // wait for thread to finish io
      CloseHandle(hPipe);
      CloseHandle(hIoThread);
      return 0;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

0
 

Author Comment

by:gotenks
ID: 10915390
booki,

thanks for your spare time solution!!
appreciated that very much!!
thanks again.

gotenks
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Suggested Solutions

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now