home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 31 / CDASC_31_1996_juillet_aout.iso / vrac / cuj0796.zip / HEYMAN.ZIP / NMPIPE.CPP < prev    next >
C/C++ Source or Header  |  1996-05-08  |  7KB  |  312 lines

  1. #include <stdio.h>
  2. #include <stdarg.h>
  3.  
  4. #include <windows.h>
  5.  
  6. #include "nmpipe.h"
  7.  
  8. #ifdef REPORT_ERRORS
  9. #define REPORT (printf)
  10. #else
  11. inline void REPORT(...) { }
  12. #endif
  13.  
  14. nmpipe_cNamedPipe::nmpipe_cNamedPipe()
  15. :   hPipe(INVALID_HANDLE_VALUE)
  16. ,   bInError(FALSE)
  17. {
  18.     memset(&Overlap, 0, sizeof(Overlap));
  19.     Overlap.hEvent = CreateEvent(NULL,
  20.         FALSE,    // Event semaphore resets itself automatically.
  21.             FALSE,    // It is initially in an unsignaled state.
  22.         NULL);
  23.  
  24.     if (!Overlap.hEvent) {
  25.     REPORT("Failure: CreateEvent() -- WinError = %u\n", GetLastError());
  26.     bInError = TRUE;
  27.     }
  28. }
  29.  
  30. nmpipe_cNamedPipe::~nmpipe_cNamedPipe()
  31. {
  32. }
  33.  
  34. nmpipe_eRetcode nmpipe_cNamedPipe::GetAvailableData(DWORD cbExpected)
  35. {
  36.     DWORD cbTransfer;
  37.  
  38.     BOOL bSuccess = GetOverlappedResult(hPipe, &Overlap, &cbTransfer, TRUE);
  39.  
  40.     if (!bSuccess) {
  41.     DWORD rc = GetLastError();
  42.  
  43.     switch (rc) {
  44.         case ERROR_MORE_DATA:
  45.         return nmpipeOK;
  46.  
  47.         case ERROR_PIPE_NOT_CONNECTED:
  48.         case ERROR_BROKEN_PIPE:
  49.         case ERROR_NO_DATA:
  50.         REPORT("Failure: GetOverlappedResult() -- broken pipe\n");
  51.         return nmpipeDisconnect;
  52.  
  53.         default:
  54.         REPORT("Failure: GetOverlappedResult() -- WinError = %u\n",
  55.             GetLastError());
  56.         return nmpipeError;
  57.     }
  58.     }
  59.  
  60.     if (cbExpected != cbTransfer) {
  61.     // We didn't get all of the data expected.
  62.     REPORT("Failure: Expected %u bytes, transferred %u bytes\n",
  63.             cbExpected, cbTransfer);
  64.     return nmpipeError;
  65.     }
  66.  
  67.     return nmpipeOK;
  68. }
  69.  
  70. nmpipe_eRetcode nmpipe_cNamedPipe::BlockForIO(HANDLE hUserEvent,
  71.     DWORD TimeOut, DWORD cbExpected)
  72. {
  73.     HANDLE hEvents[2];
  74.     int    NumEvents = 0;
  75.  
  76.     hEvents[NumEvents++] = Overlap.hEvent;
  77.  
  78.     if (hUserEvent) {
  79.     hEvents[NumEvents++] = hUserEvent;
  80.     }
  81.  
  82.     DWORD rc = WaitForMultipleObjects(NumEvents, hEvents,
  83.         FALSE,    // Wait for pipe operation or "user" event.
  84.         TimeOut);
  85.  
  86.     if (rc == WAIT_FAILED) {
  87.     REPORT("Failure: WaitForMultipleObjects() -- WinError = %u\n",
  88.         GetLastError());
  89.     return nmpipeError;
  90.     }
  91.  
  92.     if (rc == WAIT_TIMEOUT) {
  93.     REPORT("Failure: WaitForMultipleObjects() -- time-out\n");
  94.     return nmpipeTimeOut;
  95.     }
  96.  
  97.     DWORD ihEvents = rc - WAIT_OBJECT_0;
  98.  
  99.     if (hUserEvent && (hEvents[ihEvents] == hUserEvent)) {
  100.     REPORT("User event received.\n");
  101.     return nmpipeEvent;
  102.     }
  103.  
  104.     if (hEvents[ihEvents] == Overlap.hEvent) {
  105.     return GetAvailableData(cbExpected);
  106.     }
  107.  
  108.     REPORT("Failure: WaitForMultipleObjects() -- WinError = %u\n",
  109.             GetLastError());
  110.  
  111.     return nmpipeError;
  112. }
  113.  
  114. nmpipe_eRetcode nmpipe_cNamedPipe::Read(void *pBuffer, DWORD cbBuffer,
  115.     DWORD TimeOut)
  116. {
  117.     DWORD cbRead;
  118.  
  119.     BOOL bSuccess = ReadFile(hPipe, pBuffer, cbBuffer, &cbRead, &Overlap);
  120.  
  121.     if (!bSuccess) {
  122.  
  123.     DWORD rc = GetLastError();
  124.  
  125.     switch (rc) {
  126.         case ERROR_BROKEN_PIPE:
  127.         case ERROR_NO_DATA:
  128.         REPORT("Failure: ReadFile() -- broken pipe\n");
  129.             return nmpipeDisconnect;
  130.  
  131.         case ERROR_IO_PENDING: 
  132.         return BlockForIO((HANDLE) NULL, TimeOut, cbBuffer);
  133.  
  134.         case ERROR_MORE_DATA:
  135.             return nmpipeOK;
  136.  
  137.         default:
  138.         REPORT("Failure: ReadFile() -- WinError = %u\n",
  139.             GetLastError());
  140.         return nmpipeError;
  141.     }
  142.     }
  143.  
  144.     if (cbRead != cbBuffer) {
  145.     REPORT("Warning: Expected %u bytes, read %u bytes (retrying)\n",
  146.             cbBuffer, cbRead);
  147.     return Read((char *) pBuffer + cbRead, cbBuffer - cbRead, TimeOut);
  148.     }
  149.  
  150.     return nmpipeOK;
  151. }
  152.  
  153. nmpipe_eRetcode nmpipe_cNamedPipe::Write(const void *pBuffer, DWORD cbBuffer,
  154.     DWORD TimeOut)
  155. {
  156.     DWORD cbWritten;
  157.  
  158.     BOOL bSuccess = WriteFile(hPipe, pBuffer, cbBuffer, &cbWritten, &Overlap);
  159.  
  160.     if (!bSuccess) {
  161.  
  162.     DWORD rc = GetLastError();
  163.  
  164.     switch (rc) {
  165.         case ERROR_BROKEN_PIPE:
  166.         case ERROR_NO_DATA:
  167.         REPORT("Failure: WriteFile() -- broken pipe\n");
  168.             return nmpipeDisconnect;
  169.  
  170.         case ERROR_IO_PENDING: 
  171.         return BlockForIO((HANDLE) NULL, TimeOut, cbBuffer);
  172.  
  173.         default:
  174.         REPORT("Failure: WriteFile() -- WinError = %u\n",
  175.             GetLastError());
  176.         return nmpipeError;
  177.     }
  178.     }
  179.  
  180.     if (cbWritten != cbBuffer) {
  181.     REPORT("Warning: Expected %u bytes, wrote %u bytes (retrying)\n",
  182.             cbBuffer, cbWritten);
  183.     return Write((char *) pBuffer + cbWritten, cbBuffer - cbWritten, TimeOut);
  184.     }
  185.  
  186.     return nmpipeOK;
  187. }
  188.  
  189. nmpipe_cConnector::nmpipe_cConnector(const char *pPipeName, int MaxRetries)
  190. {
  191.     if (bInError) {
  192.     return;
  193.     }
  194.  
  195.     for (int i=0; i<MaxRetries; i++) {
  196.     BOOL bSuccess = WaitNamedPipe(pPipeName, NMPWAIT_USE_DEFAULT_WAIT);
  197.     
  198.     if (bSuccess) {
  199.         hPipe = CreateFile(pPipeName,
  200.             GENERIC_WRITE | GENERIC_READ,
  201.             FILE_SHARE_READ | FILE_SHARE_WRITE,
  202.             NULL,
  203.             OPEN_EXISTING,
  204.             FILE_FLAG_OVERLAPPED,
  205.             NULL);
  206.     
  207.         if (hPipe != INVALID_HANDLE_VALUE) {
  208.         return;
  209.         }
  210.     
  211.         REPORT("Failure: CreateFile() -- WinError = %u\n", GetLastError());
  212.     }
  213.     else {
  214.         REPORT("Warning: WaitNamedPipe() failed (retrying)"
  215.             " -- WinError = %u\n", GetLastError());
  216.     }
  217.     }
  218.  
  219.     REPORT("Failure: WaitNamedPipe() -- retry limit exceeded\n");
  220.     bInError = TRUE;
  221. }
  222.  
  223. nmpipe_cConnector::~nmpipe_cConnector()
  224. {
  225.     if (hPipe != INVALID_HANDLE_VALUE) {
  226.     FlushFileBuffers(hPipe);
  227.     CloseHandle(hPipe);
  228.     }
  229. }
  230.  
  231. nmpipe_cListener::nmpipe_cListener(const char *pPipeName,
  232.     HANDLE hEventShutdown_, DWORD ClientConnectionTimeOut)
  233. :   hEventShutdown(hEventShutdown_)
  234. {
  235.     if (bInError) {
  236.     return;
  237.     }
  238.  
  239.     SECURITY_DESCRIPTOR SecDesc;
  240.  
  241.     memset(&SecDesc, 0, sizeof(SecDesc));
  242.  
  243.     InitializeSecurityDescriptor(&SecDesc, SECURITY_DESCRIPTOR_REVISION);
  244.     SetSecurityDescriptorDacl(&SecDesc, TRUE, (PACL) NULL, FALSE);
  245.  
  246.     SECURITY_ATTRIBUTES SecAttr;
  247.  
  248.     memset(&SecAttr, 0, sizeof(SecAttr));
  249.  
  250.     SecAttr.nLength         = sizeof(SecAttr);
  251.     SecAttr.lpSecurityDescriptor = &SecDesc;
  252.     SecAttr.bInheritHandle     = TRUE;
  253.  
  254.     hPipe = CreateNamedPipe(pPipeName,
  255.             PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
  256.             PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
  257.             PIPE_UNLIMITED_INSTANCES, 0, 0,
  258.             ClientConnectionTimeOut, &SecAttr);
  259.  
  260.     if (hPipe == INVALID_HANDLE_VALUE) {
  261.     REPORT("Failure: CreateNamedPipe() -- WinError = %u\n",
  262.         GetLastError());
  263.     bInError = TRUE;
  264.     }
  265. }
  266.  
  267. nmpipe_cListener::~nmpipe_cListener()
  268. {
  269.     if (hPipe != INVALID_HANDLE_VALUE) {
  270.     CloseHandle(hPipe);
  271.     }
  272. }
  273.  
  274. nmpipe_eRetcode nmpipe_cListener::Connect(DWORD ServerConnectionTimeOut)
  275. {
  276.     BOOL bConnected = ConnectNamedPipe(hPipe, &Overlap);
  277.  
  278.     if (!bConnected) {
  279.  
  280.     DWORD rc = GetLastError();
  281.  
  282.     switch (rc) {
  283.         case ERROR_PIPE_CONNECTED:
  284.             break;
  285.  
  286.         case ERROR_IO_PENDING: 
  287.         return BlockForIO(hEventShutdown, ServerConnectionTimeOut, 0);
  288.  
  289.         default:
  290.         REPORT("Failure: ConnectNamedPipe() -- WinError = %u\n",
  291.             GetLastError());
  292.         return nmpipeError;
  293.     }
  294.     }
  295.  
  296.     return nmpipeOK;
  297. }
  298.  
  299. nmpipe_eRetcode nmpipe_cListener::Disconnect()
  300. {
  301.     FlushFileBuffers(hPipe);
  302.  
  303.     if (!DisconnectNamedPipe(hPipe)) {
  304.     REPORT("Failure: DisconnectNamedPipe() -- WinError = %u\n",
  305.         GetLastError());
  306.     return nmpipeError;
  307.     }
  308.  
  309.     return nmpipeOK;
  310. }
  311.  
  312.