6#include <winpr/tchar.h> 
    7#include <winpr/winpr.h> 
    9#include <winpr/print.h> 
   10#include <winpr/synch.h> 
   11#include <winpr/thread.h> 
   13#define PIPE_BUFFER_SIZE 32 
   14#define PIPE_TIMEOUT_MS 20000  
   16static BYTE SERVER_MESSAGE[PIPE_BUFFER_SIZE];
 
   17static BYTE CLIENT_MESSAGE[PIPE_BUFFER_SIZE];
 
   19static BOOL bClientSuccess = FALSE;
 
   20static BOOL bServerSuccess = FALSE;
 
   22static HANDLE serverReadyEvent = NULL;
 
   24static LPTSTR lpszPipeName = _T(
"\\\\.\\pipe\\winpr_test_pipe_overlapped");
 
   26static DWORD WINAPI named_pipe_client_thread(LPVOID arg)
 
   30  HANDLE hNamedPipe = NULL;
 
   31  BYTE* lpReadBuffer = NULL;
 
   32  BOOL fSuccess = FALSE;
 
   34  DWORD nNumberOfBytesToRead = 0;
 
   35  DWORD nNumberOfBytesToWrite = 0;
 
   36  DWORD NumberOfBytesTransferred = 0;
 
   40  status = WaitForSingleObject(serverReadyEvent, PIPE_TIMEOUT_MS);
 
   41  if (status != WAIT_OBJECT_0)
 
   43    printf(
"client: failed to wait for server ready event: %" PRIu32 
"\n", status);
 
   48  if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
 
   50    printf(
"client: CreateEvent failure: %" PRIu32 
"\n", GetLastError());
 
   53  overlapped.hEvent = hEvent;
 
   57  hNamedPipe = CreateFile(lpszPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
 
   58                          FILE_FLAG_OVERLAPPED, NULL);
 
   60  if (hNamedPipe == INVALID_HANDLE_VALUE)
 
   62    printf(
"client: Named Pipe CreateFile failure: %" PRIu32 
"\n", GetLastError());
 
   68  nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
 
   69  NumberOfBytesTransferred = 0;
 
   71  fSuccess = WriteFile(hNamedPipe, CLIENT_MESSAGE, nNumberOfBytesToWrite, NULL, &overlapped);
 
   74    fSuccess = (GetLastError() == ERROR_IO_PENDING);
 
   78    printf(
"client: NamedPipe WriteFile failure (initial): %" PRIu32 
"\n", GetLastError());
 
   82  status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
 
   83  if (status != WAIT_OBJECT_0)
 
   85    printf(
"client: failed to wait for overlapped event (write): %" PRIu32 
"\n", status);
 
   89  fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
 
   92    printf(
"client: NamedPipe WriteFile failure (final): %" PRIu32 
"\n", GetLastError());
 
   95  printf(
"client: WriteFile transferred %" PRIu32 
" bytes:\n", NumberOfBytesTransferred);
 
   99  if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
 
  101    printf(
"client: Error allocating read buffer\n");
 
  105  nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
 
  106  NumberOfBytesTransferred = 0;
 
  108  fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, NULL, &overlapped);
 
  111    fSuccess = (GetLastError() == ERROR_IO_PENDING);
 
  115    printf(
"client: NamedPipe ReadFile failure (initial): %" PRIu32 
"\n", GetLastError());
 
  119  status = WaitForMultipleObjects(1, &hEvent, FALSE, PIPE_TIMEOUT_MS);
 
  120  if (status != WAIT_OBJECT_0)
 
  122    printf(
"client: failed to wait for overlapped event (read): %" PRIu32 
"\n", status);
 
  126  fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, TRUE);
 
  129    printf(
"client: NamedPipe ReadFile failure (final): %" PRIu32 
"\n", GetLastError());
 
  133  printf(
"client: ReadFile transferred %" PRIu32 
" bytes:\n", NumberOfBytesTransferred);
 
  134  winpr_HexDump(
"pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
 
  136  if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE ||
 
  137      memcmp(lpReadBuffer, SERVER_MESSAGE, PIPE_BUFFER_SIZE) != 0)
 
  139    printf(
"client: received unexpected data from server\n");
 
  143  printf(
"client: finished successfully\n");
 
  144  bClientSuccess = TRUE;
 
  149    (void)CloseHandle(hNamedPipe);
 
  151    (void)CloseHandle(hEvent);
 
  156static DWORD WINAPI named_pipe_server_thread(LPVOID arg)
 
  159  HANDLE hEvent = NULL;
 
  160  HANDLE hNamedPipe = NULL;
 
  161  BYTE* lpReadBuffer = NULL;
 
  163  BOOL fSuccess = FALSE;
 
  164  BOOL fConnected = FALSE;
 
  165  DWORD nNumberOfBytesToRead = 0;
 
  166  DWORD nNumberOfBytesToWrite = 0;
 
  167  DWORD NumberOfBytesTransferred = 0;
 
  172  if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
 
  174    printf(
"server: CreateEvent failure: %" PRIu32 
"\n", GetLastError());
 
  175    (void)SetEvent(serverReadyEvent); 
 
  178  overlapped.hEvent = hEvent;
 
  183      CreateNamedPipe(lpszPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
 
  184                      PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
 
  185                      PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, 0, NULL);
 
  187  if (hNamedPipe == INVALID_HANDLE_VALUE)
 
  189    printf(
"server: CreateNamedPipe failure: %" PRIu32 
"\n", GetLastError());
 
  190    (void)SetEvent(serverReadyEvent); 
 
  194  (void)SetEvent(serverReadyEvent);
 
  198  fConnected = ConnectNamedPipe(hNamedPipe, &overlapped);
 
  199  status = GetLastError();
 
  216    fConnected = (status == ERROR_PIPE_CONNECTED);
 
  218  printf(
"server: ConnectNamedPipe status: %" PRIu32 
"\n", status);
 
  220  if (!fConnected && status == ERROR_IO_PENDING)
 
  223    printf(
"server: waiting up to %u ms for connection ...\n", PIPE_TIMEOUT_MS);
 
  224    status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
 
  225    if (status == WAIT_OBJECT_0)
 
  226      fConnected = GetOverlappedResult(hNamedPipe, &overlapped, &dwDummy, FALSE);
 
  228      printf(
"server: failed to wait for overlapped event (connect): %" PRIu32 
"\n", status);
 
  233    printf(
"server: ConnectNamedPipe failed: %" PRIu32 
"\n", status);
 
  237  printf(
"server: named pipe successfully connected\n");
 
  241  if (!(lpReadBuffer = (BYTE*)calloc(1, PIPE_BUFFER_SIZE)))
 
  243    printf(
"server: Error allocating read buffer\n");
 
  247  nNumberOfBytesToRead = PIPE_BUFFER_SIZE;
 
  248  NumberOfBytesTransferred = 0;
 
  250  fSuccess = ReadFile(hNamedPipe, lpReadBuffer, nNumberOfBytesToRead, NULL, &overlapped);
 
  253    fSuccess = (GetLastError() == ERROR_IO_PENDING);
 
  257    printf(
"server: NamedPipe ReadFile failure (initial): %" PRIu32 
"\n", GetLastError());
 
  261  status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
 
  262  if (status != WAIT_OBJECT_0)
 
  264    printf(
"server: failed to wait for overlapped event (read): %" PRIu32 
"\n", status);
 
  268  fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
 
  271    printf(
"server: NamedPipe ReadFile failure (final): %" PRIu32 
"\n", GetLastError());
 
  275  printf(
"server: ReadFile transferred %" PRIu32 
" bytes:\n", NumberOfBytesTransferred);
 
  276  winpr_HexDump(
"pipe.test", WLOG_DEBUG, lpReadBuffer, NumberOfBytesTransferred);
 
  278  if (NumberOfBytesTransferred != PIPE_BUFFER_SIZE ||
 
  279      memcmp(lpReadBuffer, CLIENT_MESSAGE, PIPE_BUFFER_SIZE) != 0)
 
  281    printf(
"server: received unexpected data from client\n");
 
  287  nNumberOfBytesToWrite = PIPE_BUFFER_SIZE;
 
  288  NumberOfBytesTransferred = 0;
 
  290  fSuccess = WriteFile(hNamedPipe, SERVER_MESSAGE, nNumberOfBytesToWrite, NULL, &overlapped);
 
  293    fSuccess = (GetLastError() == ERROR_IO_PENDING);
 
  297    printf(
"server: NamedPipe WriteFile failure (initial): %" PRIu32 
"\n", GetLastError());
 
  301  status = WaitForSingleObject(hEvent, PIPE_TIMEOUT_MS);
 
  302  if (status != WAIT_OBJECT_0)
 
  304    printf(
"server: failed to wait for overlapped event (write): %" PRIu32 
"\n", status);
 
  308  fSuccess = GetOverlappedResult(hNamedPipe, &overlapped, &NumberOfBytesTransferred, FALSE);
 
  311    printf(
"server: NamedPipe WriteFile failure (final): %" PRIu32 
"\n", GetLastError());
 
  315  printf(
"server: WriteFile transferred %" PRIu32 
" bytes:\n", NumberOfBytesTransferred);
 
  318  bServerSuccess = TRUE;
 
  319  printf(
"server: finished successfully\n");
 
  322  (void)CloseHandle(hNamedPipe);
 
  323  (void)CloseHandle(hEvent);
 
  328int TestPipeCreateNamedPipeOverlapped(
int argc, 
char* argv[])
 
  330  HANDLE ClientThread = NULL;
 
  331  HANDLE ServerThread = NULL;
 
  335  FillMemory(SERVER_MESSAGE, PIPE_BUFFER_SIZE, 0xAA);
 
  336  FillMemory(CLIENT_MESSAGE, PIPE_BUFFER_SIZE, 0xBB);
 
  338  if (!(serverReadyEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
 
  340    printf(
"CreateEvent failed: %" PRIu32 
"\n", GetLastError());
 
  343  if (!(ClientThread = CreateThread(NULL, 0, named_pipe_client_thread, NULL, 0, NULL)))
 
  345    printf(
"CreateThread (client) failed: %" PRIu32 
"\n", GetLastError());
 
  348  if (!(ServerThread = CreateThread(NULL, 0, named_pipe_server_thread, NULL, 0, NULL)))
 
  350    printf(
"CreateThread (server) failed: %" PRIu32 
"\n", GetLastError());
 
  354  if (WAIT_OBJECT_0 != WaitForSingleObject(ClientThread, INFINITE))
 
  356    printf(
"%s: Failed to wait for client thread: %" PRIu32 
"\n", __func__, GetLastError());
 
  359  if (WAIT_OBJECT_0 != WaitForSingleObject(ServerThread, INFINITE))
 
  361    printf(
"%s: Failed to wait for server thread: %" PRIu32 
"\n", __func__, GetLastError());
 
  365  if (bClientSuccess && bServerSuccess)
 
  371    (void)CloseHandle(ClientThread);
 
  373    (void)CloseHandle(ServerThread);
 
  374  if (serverReadyEvent)
 
  375    (void)CloseHandle(serverReadyEvent);
 
  380    printf(
"%s: Error, this test is currently expected not to succeed on this platform.\n",
 
  386    printf(
"%s: This test is currently expected to fail on this platform.\n", __func__);