//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
//  
// mfcsodlg.cpp : plik implementacji
//

#include "stdafx.h"
#include "mfcsock.h"
#include "overlap.h"
#include "ovsock.h"
#include "nspclass.h"
#include "namepipe.h"
#include "ovpipe.h"
#include "mfcsodlg.h"
#include "wnetlvl1.h"
#include <svcguid.h>
#include "perfhlpr.h"
#include "wnrpc.h"
#include "rpcclass.h"
#include "win32exc.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

TCHAR CMfcsockDlg::m_szComputerName[MAX_COMPUTERNAME_LENGTH + 1];


/////////////////////////////////////////////////////////////////////////////
// Okno dialogowe CMfcsockDlg

CMfcsockDlg::CMfcsockDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMfcsockDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CMfcsockDlg)
	m_nPacketSize = 0;
	m_nNumPackets = 0;
	m_szTargetServer = _T("");
	m_szOSVersion = _T("");
	//}}AFX_DATA_INIT
	// Proszę zauważyć, iż LoadIcon nie wymaga użycia DestroyIcon w Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
   m_hWNetUser = NULL;

#ifdef _USE_WINSOCK2_
   WSADATA WSAData;
   if (WSAStartup(0x0002, &WSAData) != 0)
      AfxThrowResourceException();
#endif
}

void CMfcsockDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMfcsockDlg)
	DDX_Text(pDX, IDC_PACKET_SIZE, m_nPacketSize);
	DDV_MinMaxUInt(pDX, m_nPacketSize, 512, 32768);
	DDX_Text(pDX, IDC_NUM_PACKETS, m_nNumPackets);
	DDV_MinMaxUInt(pDX, m_nNumPackets, 10, 100);
	DDX_Text(pDX, IDC_TARGET_SERVER, m_szTargetServer);
	DDV_MaxChars(pDX, m_szTargetServer, 25);
	DDX_Text(pDX, IDC_OS_VERSION, m_szOSVersion);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMfcsockDlg, CDialog)
	//{{AFX_MSG_MAP(CMfcsockDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_CASYNC_SOCKET, OnCasyncSocket)
	ON_BN_CLICKED(IDC_CSOCKET, OnCsocket)
	ON_BN_CLICKED(IDC_STANDARD_OVERLAPPED, OnStandardOverlapped)
	ON_BN_CLICKED(IDC_STANDARD_SYNCHRONOUS, OnStandardSynchronous)
	ON_BN_CLICKED(IDC_DATAGRAM, OnDatagram)
	ON_EN_KILLFOCUS(IDC_PACKET_SIZE, OnKillfocusPacketSize)
	ON_BN_CLICKED(IDC_CPP_OVERLAPPED, OnCppOverlapped)
	ON_BN_CLICKED(IDC_NAMED_PIPES, OnNamedPipes)
	ON_BN_CLICKED(IDC_OVERLAPPED_PIPES, OnOverlappedPipes)
	ON_BN_CLICKED(IDC_WNET_DLLS, OnWnetDlls)
	ON_BN_CLICKED(IDC_CPP_NAMED_PIPES, OnCppNamedPipes)
	ON_BN_CLICKED(IDC_CPP_OVERLAPPED_PIPES, OnCppOverlappedPipes)
	ON_BN_CLICKED(IDC_DOUBLE, OnDouble)
	ON_BN_CLICKED(IDC_RPC, OnRpc)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// Procedury obsługi wiadomości CMfcsockDlg

DWORD g_dwPacketSize = 0;
DWORD g_dwPackets = 0;

BOOL WINAPI ReceiveCallback(LPBYTE lpData, DWORD dwSize,
                            HANDLE hConnection)
{
   static DWORD dwTotalSent = 0;

   TRACE(_T("\Wejście do ReceiveCallback(), dwSize = %d"),
      dwSize);

   if (dwSize == 0)
      {
      dwTotalSent = dwSize;
      return TRUE;
      }
   else
      {
      dwTotalSent += dwSize;
      }

   TRACE(_T("\n\tdwTotalSent = %d"), dwTotalSent);

   BOOL bRetcode = WNetSend(hConnection, lpData, dwSize);

   TRACE(_T("Wyjście ReceiveCallback(), zwrot %d"),
      bRetcode);
   return bRetcode;
}

BOOL CMfcsockDlg::OnInitDialog()
{
   m_nPacketSize = 1024;
	m_nNumPackets = 100;
	m_szTargetServer = _T("NUMBER1");
   m_uControlID = IDC_STANDARD_SYNCHRONOUS;

   OSVERSIONINFO OsVersion;
   OsVersion.dwOSVersionInfoSize = sizeof (OsVersion);
   ::GetVersionEx(&OsVersion);

   m_szOSVersion.Format(_T("%s Wersja %-d.%-d [Numer %-d]"),
      OsVersion.dwPlatformId == VER_PLATFORM_WIN32_NT ?
        _T("Windows NT") : _T("Windows 95"),
      OsVersion.dwMajorVersion,
      OsVersion.dwMinorVersion,
      LOWORD(OsVersion.dwBuildNumber));

   ::ZeroMemory(m_szComputerName, sizeof (m_szComputerName));
   DWORD dwNameLength = sizeof (m_szComputerName);

   ::GetComputerName(m_szComputerName, &dwNameLength);

   CStringArray aszAllowedUsers;
   CStringArray aszDeniedUsers;

   aszAllowedUsers.Add(CString(_T("Wszyscy")));
   aszDeniedUsers.Add(CString(_T("Jasio")));

   try
      {
      m_pNamedPipesServer = new CNamedPipesServer(
         _T("WNET\\WNETBNCH"),
         PipesReceiveCallback,
         5,
         &aszAllowedUsers,
         &aszDeniedUsers,
         FALSE);  // Don't audit
      }
   catch (...)
      {
      // Nie można uruchomić serwera Pipes - prawdopodobnie system Windows 95
      m_pNamedPipesServer = NULL;
      }

   CheckRadioButton(IDC_STANDARD_SYNCHRONOUS, IDC_LAST_BUTTON,
      IDC_STANDARD_SYNCHRONOUS);
	CDialog::OnInitDialog();
	CenterWindow();

   WNetInit(ReceiveCallback,
           _T("wnetbnch"),
           &m_hWNetUser);
   
	return TRUE;  // zwrócenie TRUE, chyba że ognisko ustawiono na element sterujący
}

// Jeśli do okna dialogowego zostanie dodany przycisk minimalizacji, poniższy kod będzie niezbędny
//  do przeciągania ikonki. W przypadku aplikacji MFC korzystających z modelu dokument/widok
//  zostanie to wykonane automatycznie przez strukturę.

void CMfcsockDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // kontekst urządzenia służący do rysowania

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Wypośrodkowanie ikonki w prostokącie klienta
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Rysowanie ikonki
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// System wywołuje tę funkcję w celu uzyskania wskaźnika, kiedy użytkownik przeciąga
//  zminimalizowane okno.
HCURSOR CMfcsockDlg::OnQueryDragIcon()
{
   return (HCURSOR) m_hIcon;
}

void CMfcsockDlg::OnOK()
{
   UpdateData(TRUE);

   BeginWaitCursor();
   SetCapture();

   SetDlgItemText(IDC_MS_ELAPSED, TEXT(""));
   SetDlgItemText(IDC_BYTES_TRANSMITTED, TEXT(""));
   SetDlgItemText(IDC_BYTES_PER_SECOND, TEXT(""));

   switch (m_uControlID)
      {
      case IDC_STANDARD_SYNCHRONOUS:
         DoStandardSynchronous();
         break;
      case IDC_DATAGRAM:
         DoDatagram();
         break;
      case IDC_STANDARD_OVERLAPPED:
         DoStandardOverlapped();
         break;
      case IDC_CPP_OVERLAPPED:
         DoCPPOverlapped();
         break;
      case IDC_WNET_DLLS:
         DoWNetDlls();
         break;
      case IDC_CASYNC_SOCKET:
         DoCAsyncSocket();
         break;
      case IDC_CSOCKET:
         DoCSocket();
         break;
      case IDC_NAMED_PIPES:
         DoNamedPipes();
         break;
      case IDC_OVERLAPPED_PIPES:
         DoOverlappedPipes();
         break;
      case IDC_CPP_NAMED_PIPES:
         DoCPPNamedPipes();
         break;
      case IDC_CPP_OVERLAPPED_PIPES:
         DoCPPOverlappedPipes();
         break;
      case IDC_RPC:
         DoRPC();
         break;
      }

   ::ReleaseCapture();
   EndWaitCursor();
}

void CMfcsockDlg::DoStandardSynchronous()
{
   SOCKET      sCall = INVALID_SOCKET;
   CString     szMessage;
   int         nTotalReceived, nReceived, nBytes;
   BYTE        szBuffer[32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted;
   DWORD      *lpCounterStart;
   DWORD      *lpCounterStop;
   DWORD       dwCounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];
   DWORD       dwInstances;

   TRACE("\nWejście do CMfcsockDlg::DoStandardSynchronous()");
   sCall = socket(AF_INET, SOCK_STREAM, 0);

   if (sCall == INVALID_SOCKET)
      {
      szMessage.Format(TEXT("Działanie socket() nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   if (!GetHostAddress(m_szTargetServer, "echo", "tcp"))
      {
      szMessage.Format(TEXT("Wyszukiwanie adresu nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   if (::connect(sCall, (LPSOCKADDR) &m_sin, sizeof (SOCKADDR_IN)) != 0)
      {
      szMessage.Format(TEXT("Połączenie nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }
   nBytes = ::send(sCall, (LPCSTR) szBuffer, 100, 0);

   for (nTotalReceived = nReceived = 0;
	nBytes != SOCKET_ERROR &&
	 nTotalReceived < nBytes;
       )
      {
      nReceived = ::recv(sCall, (LPSTR) szBuffer, nBytes, 0);
      if (nReceived != SOCKET_ERROR)
	 nTotalReceived += nReceived;
      }

   GetPerformanceCounterData(NETWORK_INTERFACE,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   for (i = 0, dwStartTime = ::GetCurrentTime();
	i < m_nNumPackets; ++i)
      {
      if ((nBytes = ::send(sCall, (LPCSTR) szBuffer, m_nPacketSize, 0))
	   != SOCKET_ERROR)
	 {
	 for (nReceived = 0, nTotalReceived = 0;
	      nTotalReceived < nBytes; )
	    {
	    if ((nReceived = ::recv(sCall, (LPSTR) szBuffer, nBytes, 0))
		   == SOCKET_ERROR)
		  break;
	    nTotalReceived += nReceived;
	    }
	 dwBytesTransmitted += (DWORD) nTotalReceived;
	 }
      }
   dwEndTime = GetCurrentTime();

   dwInstances =
      GetPerformanceCounterData(NETWORK_INTERFACE,
         BYTES_TOTAL_PER_SEC,
         (LPBYTE *) &lpCounterStop, SystemTime[1],
         SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   ::closesocket(sCall);

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   for (DWORD j = 0; j < dwInstances; ++j)
      {
      dwCounterDelta = lpCounterStop[j] -
                       lpCounterStart[j];

      if (dwCounterDelta != 0)
         break;

      }
   DisplayResults(dwStartTime, dwEndTime, dMilliSeconds, 
      dwCounterDelta, 
      (((double) dwCounterDelta) * 1000.0) / dMilliSeconds);

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

void CMfcsockDlg::DoRPC()
{
   BYTE        byInBuffer[60000];
   BYTE        byOutBuffer[60000];
   DWORD       dwStartTime, dwEndTime;
   double      dMilliSeconds;
   DWORD      *lpCounterStart;
   DWORD      *lpCounterStop;
   DWORD       dwCounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];
   DWORD       dwInstances;
   RPC_BINDING_HANDLE hBenchmark;
   RPC_STATUS  RpcStatus = RPC_S_OK;
   PTBYTE      lpServer;
   PTBYTE      lpProtocol;
   UINT        i;

   TRACE("\nWejście do CMfcsockDlg::DoRPC()");

   lpServer = (LPBYTE) (LPCTSTR) m_szTargetServer;

   // W przypadku nazwy komputera w postaci '.' należy użyć ncalrpc
   // W przeciwnym wypadku należy użyć ncacn_ip_tcp
   if (*lpServer == _T('.'))
      {
      lpServer   = NULL;
      lpProtocol = (PTBYTE) _T("ncalrpc");
      }
   else
      lpProtocol = (PTBYTE) _T("ncacn_ip_tcp");

   try
      {
      CRpcClient RpcClient(wnrpc_v1_0_c_ifspec,
                           lpServer,
                           &hBenchmark,
                           lpProtocol,
                           NULL,
                           CRpcClient::authNone);

      RpcClient.SetTimeout(RPC_C_BINDING_MIN_TIMEOUT);

      // Wysłanie kilku bajtów w celu upewnienia się
      // o poprawności wiązania.
      try
         {
         _RpcBenchmark(hBenchmark,
            100, (LPBYTE) byInBuffer, 
            (LPBYTE) byOutBuffer);
         }
      catch (CWin32Exception *e)
         {
         e->Delete();
         }
      GetPerformanceCounterData(NETWORK_INTERFACE,
         BYTES_TOTAL_PER_SEC,
         (LPBYTE *) &lpCounterStart, SystemTime[0],
         SampleTime[0]);

      for (i = 0, dwStartTime = GetCurrentTime(); 
          i < m_nNumPackets; ++i)
         {
         try
            {
            _RpcBenchmark(hBenchmark,
               m_nPacketSize, (LPBYTE) byInBuffer, 
               (LPBYTE) byOutBuffer);
            }
         catch (CWin32Exception *e)
            {
            RpcStatus = e->GetExceptionCode();
            delete e;
            }
         }
      dwEndTime = GetCurrentTime();
      dwInstances =
         GetPerformanceCounterData(NETWORK_INTERFACE,
            BYTES_TOTAL_PER_SEC,
            (LPBYTE *) &lpCounterStop, SystemTime[1],
            SampleTime[1]);

      RegCloseKey(HKEY_PERFORMANCE_DATA);

      LARGE_INTEGER PerformanceFrequency;

      if (QueryPerformanceFrequency(&PerformanceFrequency))
         dMilliSeconds =
            ((double) (((DWORD) SampleTime[1]) -
                       ((DWORD) SampleTime[0]))) /
            ((double) (PerformanceFrequency.LowPart))
            * 1000.0;
      else
         dMilliSeconds = SystemTime[1] - SystemTime[0];

      for (DWORD j = 0; j < dwInstances; ++j)
         {
         dwCounterDelta = lpCounterStop[j] -
                          lpCounterStart[j];

         if (dwCounterDelta != 0)
            break;

         }
      }
   catch (CResourceException *e)
      {
      RpcStatus = ::GetLastError();
      e->Delete();
      }

   if (RpcStatus == RPC_S_OK)
      {
      DisplayResults(dwStartTime, dwEndTime, dMilliSeconds, 
         dwCounterDelta, 
         (((double) dwCounterDelta) * 1000.0) / dMilliSeconds);
      }
   else
      {
      CString szMessage;
      szMessage.Format(_T("Wystąpił błąd RPC %d"),
         RpcStatus);
      AfxMessageBox(szMessage);
      }

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

void CMfcsockDlg::DoDatagram()
{
   SOCKET      sCall = INVALID_SOCKET;
   CString     szMessage;
   int         nTotalReceived, nReceived, nBytes;
   BYTE        szBuffer[32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted;
   int         nNameLen;
   DWORD      *lpCounterStart;
   DWORD      *lpCounterStop;
   DWORD       dwCounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];
   DWORD       dwInstances;

   TRACE("\nWejście do CMfcsockDlg::DoDatagram()");
   sCall = socket(AF_INET, SOCK_DGRAM, 0);

   if (sCall == INVALID_SOCKET)
      {
      szMessage.Format(TEXT("Działanie socket() nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   if (!GetHostAddress(m_szTargetServer, "echo", "udp"))
      {
      szMessage.Format(TEXT("Wyszukiwanie adresu nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   nBytes = ::sendto(sCall, (LPCSTR) szBuffer, 100, 0,
      (LPSOCKADDR) &m_sin, sizeof (SOCKADDR_IN));

   nNameLen = sizeof (SOCKADDR_IN);

   for (nTotalReceived = nReceived = 0;
	nBytes != SOCKET_ERROR &&
	 nTotalReceived < nBytes;
       )
      {
      nReceived = ::recvfrom(sCall, (LPSTR) szBuffer, nBytes, 0,
         (LPSOCKADDR) &m_sin, &nNameLen);
      if (nReceived != SOCKET_ERROR)
	 nTotalReceived += nReceived;
      }

   GetPerformanceCounterData(NETWORK_INTERFACE,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   for (i = 0, dwStartTime = ::GetCurrentTime();
	i < m_nNumPackets; ++i)
      {
      if ((nBytes = ::sendto(sCall, (LPCSTR) szBuffer, m_nPacketSize, 0,
           (LPSOCKADDR) &m_sin, sizeof (SOCKADDR_IN)))
	   != SOCKET_ERROR)
	 {
	 for (nReceived = 0, nTotalReceived = 0;
	      nTotalReceived < nBytes; )
	    {
	    if ((nReceived = ::recvfrom(sCall, (LPSTR) szBuffer, nBytes, 0,
	         (LPSOCKADDR) &m_sin, &nNameLen))
		   == SOCKET_ERROR)
		  break;
	    nTotalReceived += nReceived;
	    }
	 dwBytesTransmitted += (DWORD) nTotalReceived;
	 }
      }
   dwEndTime = GetCurrentTime();

   dwInstances =
      GetPerformanceCounterData(NETWORK_INTERFACE,
         BYTES_TOTAL_PER_SEC,
         (LPBYTE *) &lpCounterStop, SystemTime[1],
         SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   ::closesocket(sCall);

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   for (DWORD j = 0; j < dwInstances; ++j)
      {
      dwCounterDelta = lpCounterStop[j] -
                       lpCounterStart[j];

      if (dwCounterDelta != 0)
         break;

      }
   DisplayResults(dwStartTime, dwEndTime, dMilliSeconds, 
      dwCounterDelta, 
      (((double) dwCounterDelta) * 1000.0) / dMilliSeconds);

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

#ifdef _USE_WINSOCK2_
void CMfcsockDlg::DoStandardOverlapped()
{
   SOCKET        sCall = INVALID_SOCKET;
   CString       szMessage;
   DWORD         dwTotalReceived, dwReceived, dwBytes;
   int           nError;
   char          szBuffer[4][32768];
   WSABUF        WSABuffer[4];
   DWORD         dwStartTime, dwEndTime;
   UINT          i;
   DWORD         dwBytesTransmitted, dwBytesReceived;
   WSAEVENT      hEvents[4];
   WSAOVERLAPPED ov[4];
   DWORD         dwTotalBytes;
   DWORD         dwIoBytes;
   DWORD         dwWSAFlags = 0;
   BOOL          bSuccess;
   DWORD        *lpCounterStart;
   DWORD        *lpCounterStop;
   DWORD         dwCounterDelta;
   CSystemTime   SystemTime[2];
   CLargeInt     SampleTime[2];
   DWORD         dwInstances;

   TRACE("\nWejście do CMfcsockDlg::DoStandardOverlapped()");

   sCall = ::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, 
      WSA_FLAG_OVERLAPPED);

   if (sCall == INVALID_SOCKET)
      {
      szMessage.Format(TEXT("Działanie WSAsocket() nie powiodło się, "
                            "WSAGetLastError() = %d"),
         ::WSAGetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   // Utworzenie zdarzeń używanych przez standardowe wejście-wyjście.
   // Należy umieścić je w strukturach WSAOVERLAPPED.
   for ( i = 0; i < 4; i++ )
      {
      WSABuffer[i].len = m_nPacketSize;
      WSABuffer[i].buf = szBuffer[i];

      hEvents[i] = ::WSACreateEvent();
      if ( hEvents[i] == NULL )
         {
         szMessage.Format(TEXT("Działanie WSACreateEvent() nie powiodło się, "
                               "WSAGetLastError() = %d"),
            ::WSAGetLastError());
         ::closesocket(sCall);
         AfxMessageBox(szMessage);
         return;
         }
      ov[i].Internal = 0;
      ov[i].InternalHigh = 0;
      ov[i].Offset = 0;
      ov[i].OffsetHigh = 0;
      ov[i].hEvent = hEvents[i];
      }

   if (!GetHostAddress(m_szTargetServer, "echo", "tcp"))
      {
      szMessage.Format(TEXT("Wyszukanie adresu nie powiodło się, "
                            "WSAGetLastError() = %d"),
         ::WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   if (::WSAConnect(sCall, 
                    (LPSOCKADDR) &m_sin, 
                    sizeof (SOCKADDR_IN),
                    NULL,
                    NULL,
                    NULL,
                    NULL) != 0)
      {
      szMessage.Format(TEXT("Działanie WSAConnect() nie powiodło się, "
                            "WSAGetLastError() = %d"),
         ::WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   // Wysłanie nienakładającego się losowego pakietu.
   WSABuffer[0].len = 100;
   nError = ::WSASend(sCall, &WSABuffer[0], 1, &dwBytes,
        0, NULL, NULL);

   if (nError != 0)
      {
      szMessage.Format(TEXT("Transmisja pakietu przez WSASend() nie powiodło się, "
                            "błąd = %d"), nError);
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   for (dwTotalReceived = dwReceived = 0;
        dwTotalReceived < dwBytes;
       )
      {
      nError = ::WSARecv(sCall, &WSABuffer[0], 1, &dwReceived,
            &dwWSAFlags, NULL, NULL);
      if (nError != 0)
         {
         szMessage.Format(TEXT("Odbiór pakietu przez WSARecv() nie powiódł się, "
                               "WSAGetLastError() = %d"), 
            ::WSAGetLastError());
         ::closesocket(sCall);
         AfxMessageBox(szMessage);
         return;
         }
      dwTotalReceived += dwReceived;
      }

   WSABuffer[0].len = m_nPacketSize;

   // Wyłączenie buforowania po stronie wysyłającej poprzez
   // ustawienie wielkości bufora wysyłki na zero.
   i = 0;
   if (::setsockopt(sCall, SOL_SOCKET, SO_SNDBUF, 
       (LPSTR) &i, sizeof (i))
      == SOCKET_ERROR)
      {
      szMessage.Format(TEXT("Działanie ::setsockopt(SO_SNDBUF) nie powiodło się, "
                            "WSAGetLastError() = %d"),
         ::WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   // Konfiguracja gniazda na buforowanie 65000 bajtów
   // przychodzących danych.
   i = max(65000, 2 * m_nPacketSize);

   if (::setsockopt(sCall, SOL_SOCKET, SO_RCVBUF, 
       (LPSTR) &i, sizeof (i))
     == SOCKET_ERROR)
      {
      szMessage.Format(TEXT("Działanie ::setsockopt(SO_RCVBUF) nie powiodło się, "
                            "WSAGetLastError() = %d"),
         ::WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   dwTotalBytes = (DWORD) (m_nNumPackets * m_nPacketSize);

   GetPerformanceCounterData(NETWORK_INTERFACE,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   dwStartTime = GetCurrentTime();

   // Rozpoczęcie operacji.
   // Najpierw należy wykonać odczyt, aby zapewnić miejsce w buforze
   // do odbioru odpowiedzi serwera.
   ::WSARecv(sCall, &WSABuffer[RECV_1], 1,
             &dwIoBytes, &dwWSAFlags, &ov[RECV_1], NULL);

   ::WSARecv(sCall, &WSABuffer[RECV_2], 1,
             &dwIoBytes, &dwWSAFlags, &ov[RECV_2], NULL);

   ::WSASend(sCall, &WSABuffer[SEND_1], 1,
             &dwIoBytes, 0, &ov[SEND_1], NULL);

   ::WSASend(sCall, &WSABuffer[SEND_2], 1,
             &dwIoBytes, 0, &ov[SEND_2], NULL);

   dwBytesTransmitted = dwBytesReceived = 0;
   while ( TRUE )
      {
      // Oczekiwanie na zakończenie wywołania wejścia-wyjścia.

      i = ::WSAWaitForMultipleEvents(4, hEvents, FALSE, INFINITE, 
              FALSE);

      if (i >= 4)
         {
         szMessage.Format(
            TEXT("Działanie ::WSAWaitForMultipleEvents() nie powiodło się, "
                 "WSAGetLastError() = %d"),
            ::WSAGetLastError());
         ::closesocket(sCall);
         AfxMessageBox(szMessage);
         return;
         }

      // W wersji beta NT 4.0 o numerze 1234 użycie
      // WSAGetOverlappedResult() powodowało wystąpienie wyjątku
      // 0xC0000264 (nieudokumentowany).
      // GetOverlappedResult() działa poprawnie.
      bSuccess = ::GetOverlappedResult((HANDLE) sCall, &ov[i], 
                      &dwIoBytes, FALSE);
      if (!bSuccess)
         {
         szMessage.Format(TEXT("Działanie WSASend/WSARecv[%d] nie powiodło się, "
                               "WSAGetLastError() = %d"),
            i, ::WSAGetLastError());
         ::closesocket(sCall);
         AfxMessageBox(szMessage);
         return;
         }

      // Czy odczyt został zakończony?
      if ( i == RECV_1 || i == RECV_2 )
         {
         // Tak - dodanie licznika bajtów do łącznej liczby otrzymanych bajtów.
         dwBytesReceived += dwIoBytes;

         // Jeśli liczba bajtów jest równa lub przekracza wielkość pakietu
         // pomnożoną przez liczbę pakietów, to należy przerwać pętlę.
         if ((dwBytesReceived >= dwTotalBytes) )
            {
            break;
            }

         // Teoretycznie nie ma tu potrzeby wywołania
         // WSAResetEvent(). Według dokumentacji zdarzenie
         // jest automatycznie resetowane po powrocie operacji.
         // Wydaje się jednak, że Windows 95 "zapomina" o tym.
         ::WSAResetEvent(hEvents[i]);

         // WSARecv() zwraca 0, jeśli zakończyła pracę synchronicznie,
         // a SOCKET_ERROR (-1) w przeciwnym wypadku.
         // Z tego powodu do wartości zwrotnej należy dodać 1,
         // co pozwoli na konwersję do wartości logicznej.
         bSuccess = ::WSARecv(sCall, &WSABuffer[i], 1,
                       &dwIoBytes, &dwWSAFlags, &ov[i], NULL) + 1;

         // Jeśli operacja zakończy się synchronicznie, to należy upewnić się, 
         // czy zdarzenie znajduje się w stanie sygnalizacji.
         // Nastąpi powrót na początek pętli, a WSAWaitForMultipleEvents()
         // natychmiast się obudzi.
         if (bSuccess)
            ::WSASetEvent(hEvents[i]);

         if ((bSuccess && dwIoBytes == 0) ||
             (!bSuccess && (::WSAGetLastError() != WSA_IO_PENDING)))
            {
            // Operacja nie powiodła się, a więc należy przerwać pracę.
            break;
            }
         }
      else if (i == SEND_1 || i == SEND_2)
         {
         // Po zakończeniu zapisu należy dodać liczbę bajtów
         // do całkowitej liczby zapisanych bajtów.
         dwBytesTransmitted += dwIoBytes;

         // Sprawdzenie końca operacji jest tutaj wykonywane w inny sposób.
         // Ponieważ dwie operacje nakładają się, należy przerwać wysyłkę
         // danych kiedy całkowita liczba zapisanych bajtów jest równa
         // wielkości pakietu pomnożonego przez liczbę pakietów 
         // minus wielkość jednego pakietu.
         // Gdyby tylko porównać dwBytesTransmitted z dwTotalBytes,
         // to zostanie wysłanych zbyt wiele pakietów.
         if ( dwBytesTransmitted >= (dwTotalBytes - m_nPacketSize))
            {
            // Bardzo ważne jest zresetowanie zdarzenia.
            // Ponieważ nie jest rozpoczynana nowa operacja,
            // to po zresetowaniu zdarzenia nie będzie możliwości
            // wysłania sygnału, a to z kolei uniemożliwi ponowne
            // obudzenie WaitForMultipleObjects().
            ::WSAResetEvent(hEvents[i]);
            continue;
            }

         // Tutaj resetowane jest zdarzenie w celu obsłużenia systemu Windows 95.
         ::WSAResetEvent(hEvents[i]);
         bSuccess = ::WSASend(sCall, &WSABuffer[i], 1,
                       &dwIoBytes, 0, &ov[i], NULL) + 1;
         if (bSuccess)
            ::WSASetEvent(hEvents[i]);
         if ((bSuccess && dwIoBytes == 0) ||
             (!bSuccess && (::WSAGetLastError() != WSA_IO_PENDING)))
            {
            ::WSAResetEvent( hEvents[i] );
            continue;
            }
         }
      }
   dwEndTime = GetCurrentTime();

   dwInstances =
      GetPerformanceCounterData(NETWORK_INTERFACE,
         BYTES_TOTAL_PER_SEC,
         (LPBYTE *) &lpCounterStop, SystemTime[1],
         SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   ::closesocket(sCall);

   // Zamknięcie uchwytów zdarzeń.
   for (i = 0; i < 4; ++i)
      {
      ::WSACloseEvent(hEvents[i]);
      }

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   for (DWORD j = 0; j < dwInstances; ++j)
      {
      dwCounterDelta = lpCounterStop[j] -
                       lpCounterStart[j];

      if (dwCounterDelta != 0)
         break;

      }
   DisplayResults(dwStartTime, dwEndTime, dMilliSeconds, 
      dwCounterDelta, 
      (((double) dwCounterDelta) * 1000.0) / dMilliSeconds);

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}
#else
void CMfcsockDlg::DoStandardOverlapped()
{
   SOCKET      sCall = INVALID_SOCKET;
   CString     szMessage;
   int         nTotalReceived, nReceived, nBytes;
   char szBuffer[4][32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted, dwBytesReceived;
   HANDLE      hEvents[4];
   OVERLAPPED  ov[4];
   DWORD       dwTotalBytes;
   DWORD       dwIoBytes;
   BOOL        bSuccess;
   DWORD      *lpCounterStart;
   DWORD      *lpCounterStop;
   DWORD       dwCounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];
   DWORD       dwInstances;

   TRACE("\nWejście do CMfcsockDlg::DoStandardOverlapped()");
   sCall = socket(AF_INET, SOCK_STREAM, 0);

   if (sCall == INVALID_SOCKET)
      {
      szMessage.Format(TEXT("Działanie socket() nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   // Utworzenie zdarzeń używanych przez standardowe wejście-wyjście.
   // Należy umieścić je w strukturach OVERLAPPED.
   for ( i = 0; i < 4; i++ )
      {
      hEvents[i] = ::CreateEvent( NULL, TRUE, FALSE, NULL );
      if ( hEvents[i] == NULL )
	 {
	 szMessage.Format(TEXT("Działanie CreateEvent() nie powiodło się, GetLastError() = %d"),
	   ::GetLastError());
	 ::closesocket(sCall);
	 AfxMessageBox(szMessage);
	 return;
	 }
      ov[i].Internal = 0;
      ov[i].InternalHigh = 0;
      ov[i].Offset = 0;
      ov[i].OffsetHigh = 0;
      ov[i].hEvent = hEvents[i];
      }

   if (!GetHostAddress(m_szTargetServer, "echo", "tcp"))
      {
      szMessage.Format(TEXT("Wyszukiwanie adresu nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   if (::connect(sCall, (LPSOCKADDR) &m_sin, sizeof (SOCKADDR_IN)) != 0)
      {
      szMessage.Format(TEXT("Połączenie nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }
   nBytes = ::send(sCall, (LPCSTR) szBuffer[0], 100, 0);

   for (nTotalReceived = nReceived = 0;
	nBytes != SOCKET_ERROR &&
	 nTotalReceived < nBytes;
       )
      {
      nReceived = ::recv(sCall, (LPSTR) szBuffer[0], nBytes, 0);
      if (nReceived != SOCKET_ERROR)
	 nTotalReceived += nReceived;
      }

   // Wyłączenie buforowania po stronie wysyłającej poprzez
   // ustawienie wielkości bufora wysyłki na zero.
   i = 0;
   if (::setsockopt(sCall, SOL_SOCKET, SO_SNDBUF, (LPSTR) &i, sizeof (i))
      == SOCKET_ERROR)
      {
      szMessage.Format(TEXT("Działanie ::setsockopt(SO_SNDBUF) nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   // Konfiguracja gniazda na buforowanie 65000 bajtów
   // przychodzących danych.
   i = 65000;
   if (::setsockopt(sCall, SOL_SOCKET, SO_RCVBUF, (LPSTR) &i, sizeof (i))
     == SOCKET_ERROR)
      {
      szMessage.Format(TEXT("Działanie ::setsockopt(SO_RCVBUF) nie powiodło się, WSAGetLastError() = %d"),
	 WSAGetLastError());
      ::closesocket(sCall);
      AfxMessageBox(szMessage);
      return;
      }

   dwTotalBytes = (DWORD) (m_nNumPackets * m_nPacketSize);

   GetPerformanceCounterData(NETWORK_INTERFACE,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   dwStartTime = GetCurrentTime();

   // Rozpoczęcie nakładających się operacji.
   // Najpierw należy wykonać odczyt, aby zapewnić miejsce w buforze
   // do odbioru odpowiedzi serwera.
   ::ReadFile( (HANDLE)sCall, szBuffer[RECV_1], m_nPacketSize,
			      &dwIoBytes, &ov[RECV_1] );

   ::ReadFile( (HANDLE)sCall, szBuffer[RECV_2], m_nPacketSize,
			    &dwIoBytes, &ov[RECV_2] );

   ::WriteFile( (HANDLE)sCall, szBuffer[SEND_1], m_nPacketSize,
			    &dwIoBytes, &ov[SEND_1] );

   ::WriteFile( (HANDLE)sCall, szBuffer[SEND_2], m_nPacketSize,
			    &dwIoBytes, &ov[SEND_2] );
   dwBytesTransmitted = dwBytesReceived = 0;
   while ( TRUE )
      {
      // Oczekiwanie na zakończenie wywołania wejścia-wyjścia.
      i = ::WaitForMultipleObjects( 4, hEvents, FALSE, INFINITE );

      if (i >= 4)
	 {
	 szMessage.Format(TEXT("Działanie ::WaitForMultipleObjects() nie powiodło się, GetLastError() = %d"),
	    GetLastError());
	 ::closesocket(sCall);
	 AfxMessageBox(szMessage);
	 return;
	 }

      bSuccess = GetOverlappedResult( (HANDLE)sCall, &ov[i], &dwIoBytes, FALSE );
      if ( !bSuccess )
	 {
	 szMessage.Format(TEXT("Działanie WriteFile/ReadFile[%d] nie powiodło się, WSAGetLastError() = %d"),
	    i, GetLastError());
	 ::closesocket(sCall);
	 AfxMessageBox(szMessage);
	 return;
	 }

      // Czy odczyt został zakończony?
      if ( i == RECV_1 || i == RECV_2 )
         {
         // Tak - dodanie licznika bajtów do łącznej liczby otrzymanych bajtów.
	 dwBytesReceived += dwIoBytes;

         // eśli liczba bajtów jest równa lub przekracza wielkość pakietu
         // pomnożoną przez liczbę pakietów, to należy przerwać pętlę.
	 if ((dwBytesReceived >= dwTotalBytes) )
	    {
	    break;
	    }

         // Teoretycznie nie ma tu potrzeby wywołania
         // ResetEvent(). Według dokumentacji zdarzenie
         // jest automatycznie resetowane po powrocie operacji.
         // Wydaje się jednak, że Windows 95 "zapomina" o tym.
         // to do this.
	::ResetEvent(hEvents[i]);
	 bSuccess = ::ReadFile( (HANDLE)sCall, szBuffer[i], m_nPacketSize,
				    &dwIoBytes, &ov[i] );

         // Jeśli operacja zakończy się synchronicznie, to należy upewnić się, 
         // czy zdarzenie znajduje się w stanie sygnalizacji.
         // Nastąpi powrót na początek pętli, a WaitForMultipleEvents()
         // natychmiast się obudzi.
	 if (bSuccess)
	    ::SetEvent(hEvents[i]);

	 if ((bSuccess && dwIoBytes == 0) ||
	     (!bSuccess && (::GetLastError() != ERROR_IO_PENDING)))
	    {
            // Operacja nie powiodła się, a więc należy przerwać pracę.
            break;
	   }
	 }
      else if (i == SEND_1 || i == SEND_2)
	 {
         // Po zakończeniu zapisu należy dodać liczbę bajtów
         // do całkowitej liczby zapisanych bajtów.
	 dwBytesTransmitted += dwIoBytes;

         // Sprawdzenie końca operacji jest tutaj wykonywane w inny sposób.
         // Ponieważ dwie operacje nakładają się, należy przerwać wysyłkę
         // danych kiedy całkowita liczba zapisanych bajtów jest równa
         // wielkości pakietu pomnożonego przez liczbę pakietów 
         // minus wielkość jednego pakietu.
         // Gdyby tylko porównać dwBytesTransmitted z dwTotalBytes,
         // to zostanie wysłanych zbyt wiele pakietów.
	 if ( dwBytesTransmitted >= (dwTotalBytes - m_nPacketSize))
	    {
            // Bardzo ważne jest zresetowanie zdarzenia.
            // Ponieważ nie jest rozpoczynana nowa operacja,
            // to po zresetowaniu zdarzenia nie będzie możliwości
            // wysłania sygnału, a to z kolei uniemożliwi ponowne
            // obudzenie WaitForMultipleObjects().
	    ::ResetEvent( hEvents[i] );
	    continue;
	    }

         // Tutaj resetowane jest zdarzenie w celu obsłużenia systemu Windows 95.
	 ::ResetEvent(hEvents[i]);
	 bSuccess = ::WriteFile( (HANDLE)sCall, szBuffer[i], m_nPacketSize,
				     &dwIoBytes, &ov[i] );
	 if (bSuccess)
	    ::SetEvent(hEvents[i]);
	 if ((bSuccess && dwIoBytes == 0) ||
	     (!bSuccess && (::GetLastError() != ERROR_IO_PENDING)))
	    {
	    ::ResetEvent( hEvents[i] );
	    continue;
	    }

	 }
      }
   dwEndTime = GetCurrentTime();

   dwInstances =
      GetPerformanceCounterData(NETWORK_INTERFACE,
         BYTES_TOTAL_PER_SEC,
         (LPBYTE *) &lpCounterStop, SystemTime[1],
         SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   ::closesocket(sCall);

   // Zamknięcie uchwytów zdarzenia.
   for (i = 0; i < 4; ++i)
      {
      ::CloseHandle(hEvents[i]);
      }

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   for (DWORD j = 0; j < dwInstances; ++j)
      {
      dwCounterDelta = lpCounterStop[j] -
                       lpCounterStart[j];

      if (dwCounterDelta != 0)
         break;

      }
   DisplayResults(dwStartTime, dwEndTime, dMilliSeconds, 
      dwCounterDelta, 
      (((double) dwCounterDelta) * 1000.0) / dMilliSeconds);

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}
#endif

void CMfcsockDlg::DoCPPOverlapped()
{
   CString     szMessage;
   int         nTotalReceived, nReceived, nBytes;
   char szBuffer[4][32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted, dwBytesReceived;
   COverlapped ov[4];
   DWORD       dwTotalBytes;
   DWORD       dwIoBytes;
   BOOL        bSuccess;
   static GUID EchoGuid = SVCID_ECHO_TCP;
   CServiceInfo MyService;
   DWORD        dwLastError;
   DWORD      *lpCounterStart;
   DWORD      *lpCounterStop;
   DWORD       dwCounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];
   DWORD       dwInstances;

   TRACE("\nWejście do CMfcsockDlg::DoCPPOverlapped()");

   COverlappedSocket *lpSocket =
      MyService.Connect(&EchoGuid, (LPTSTR) (const char *)m_szTargetServer);

   if (lpSocket != NULL)
      {
      TRACE(_T("\nNawiązano połączenie z serwerem\n"));
      }
   else
      {
      szMessage.Format(TEXT("Działanie socket() nie powiodło się, WSAGetLastError() = %d"),
	      ::GetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   HANDLE hEvent[4];
   for ( i = 0; i < 4; i++ )
      {
      hEvent[i] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
      ov[i].SetEventHandle(hEvent[i]);
      }

   nBytes = lpSocket->GetSocket().Send((LPCSTR) szBuffer[0], 100);

   for (nTotalReceived = nReceived = 0;
         nBytes != SOCKET_ERROR &&
         nTotalReceived < nBytes;
       )
      {
      nReceived = lpSocket->GetSocket().Receive(
         (LPSTR) szBuffer[0], 100);
      if (nReceived != SOCKET_ERROR)
         nTotalReceived += nReceived;
      }
   i = 0;
   if (!lpSocket->GetSocket().SetSockOpt(
           SO_SNDBUF, (const void *) &i, sizeof (i)))
      {
      szMessage.Format(TEXT("Działanie ::setsockopt(SO_SNDBUF) nie powiodło się, WSAGetLastError() = %d"),
         lpSocket->GetSocket().GetLastError());
      lpSocket->Close();
      delete lpSocket;
      AfxMessageBox(szMessage);
      return;
      }

   i = 65000;
   if (!lpSocket->GetSocket().SetSockOpt(
          SO_RCVBUF, (const void *) &i, sizeof (i)))
      {
      szMessage.Format(TEXT("Działanie ::setsockopt(SO_RCVBUF) nie powiodło się, WSAGetLastError() = %d"),
         lpSocket->GetSocket().GetLastError());
      lpSocket->Close();
      delete lpSocket;
      AfxMessageBox(szMessage);
      return;
      }

   int nSuccessfulReads = 0, nSuccessfulWrites = 0;
   dwTotalBytes = (DWORD) (m_nNumPackets * m_nPacketSize);

   GetPerformanceCounterData(NETWORK_INTERFACE,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   dwStartTime = GetCurrentTime();

   if (lpSocket->Read(szBuffer[RECV_1], m_nPacketSize,
            &dwIoBytes, &ov[RECV_1] ) ||
         ::GetLastError() == ERROR_IO_PENDING)
      ++nSuccessfulReads;
   else
      dwLastError = ::GetLastError();

   if (lpSocket->Read(szBuffer[RECV_2], m_nPacketSize,
            &dwIoBytes, &ov[RECV_2] ) ||
         ::GetLastError() == ERROR_IO_PENDING)
      ++nSuccessfulReads;
   else
      dwLastError = ::GetLastError();

   if (lpSocket->Write(szBuffer[SEND_1], m_nPacketSize,
            &ov[SEND_1] ) ||
         ::GetLastError() == ERROR_IO_PENDING)
      ++nSuccessfulWrites;
   else
      dwLastError = ::GetLastError();

   if (lpSocket->Write(szBuffer[SEND_2], m_nPacketSize,
            &ov[SEND_2] ) ||
         ::GetLastError() == ERROR_IO_PENDING)
      ++nSuccessfulWrites;
   else
      dwLastError = ::GetLastError();
   dwBytesTransmitted = dwBytesReceived = 0;

   BOOL bContinue = (nSuccessfulReads > 0 && nSuccessfulWrites > 0);
   while (bContinue)
      {
      i = ::WaitForMultipleObjects(4, hEvent, FALSE, 5000);

      if (i >= 4)
         {
         szMessage.Format(TEXT("Działanie ::WaitForMultipleObjects() nie powiodło się, GetLastError() = %d"),
            GetLastError());
         lpSocket->Close();
         AfxMessageBox(szMessage);
         delete lpSocket;
         return;
         }

      bSuccess = ov[i].GetResult(&dwIoBytes, FALSE );
      if ( !bSuccess )
         {
         szMessage.Format(TEXT("Działanie WriteFile/ReadFile[%d] nie powiodło się, WSAGetLastError() = %d"),
            i, GetLastError());
         lpSocket->Close();
         AfxMessageBox(szMessage);
         delete lpSocket;
         return;
         }

      if (ov[i].GetPreviousOperation() == COverlapped::ReadFile)
         {
         dwBytesReceived += dwIoBytes;
         if ( dwBytesReceived >= dwTotalBytes )
            {
            break;
            }
         ::ResetEvent(hEvent[i]);
         }
      else   // Zakończono WriteFile()
         {
         dwBytesTransmitted += dwIoBytes;
         if ( dwBytesTransmitted >= (dwTotalBytes - m_nPacketSize))
            {
            ::ResetEvent(hEvent[i]);
            continue;
            }
         ::ResetEvent(hEvent[i]);
         }
      bSuccess = ov[i].Recycle(m_nPacketSize, &dwIoBytes);
      if (bSuccess)
         ::SetEvent(hEvent[i]);
      else if (::GetLastError() != ERROR_IO_PENDING)
         {
         szMessage.Format(TEXT("Działanie ::ReadFile() nie powiodło się, ::GetLastError() = %d"),
	       ::GetLastError());
         lpSocket->Close();
         AfxMessageBox(szMessage);
         delete lpSocket;
         return;
         }
      }
   dwEndTime = GetCurrentTime();

   dwInstances =
      GetPerformanceCounterData(NETWORK_INTERFACE,
         BYTES_TOTAL_PER_SEC,
         (LPBYTE *) &lpCounterStop, SystemTime[1],
         SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   for (i = 0; i < 4; ++i)
      ::CloseHandle(hEvent[i]);

   lpSocket->Close();

   delete lpSocket;

   if ((nSuccessfulReads > 0) && (nSuccessfulWrites > 0))
      {
      double dMilliSeconds;
      LARGE_INTEGER PerformanceFrequency;

      if (QueryPerformanceFrequency(&PerformanceFrequency))
         dMilliSeconds =
            ((double) (((DWORD) SampleTime[1]) -
                       ((DWORD) SampleTime[0]))) /
            ((double) (PerformanceFrequency.LowPart))
            * 1000.0;
      else
         dMilliSeconds = SystemTime[1] - SystemTime[0];

      for (DWORD j = 0; j < dwInstances; ++j)
         {
         dwCounterDelta = lpCounterStop[j] -
                          lpCounterStart[j];

         if (dwCounterDelta != 0)
            break;

         }
      DisplayResults(dwStartTime, dwEndTime, dMilliSeconds, 
         dwCounterDelta, 
         (((double) dwCounterDelta) * 1000.0) / dMilliSeconds);
      }
   else
      {
      szMessage.Format(TEXT("Brak udanych operacji odczytu lub zapisu, ::GetLastError() = %d"),
	       ::GetLastError());
      AfxMessageBox(szMessage);
      }

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

void CMfcsockDlg::DoCPPOverlappedPipes()
{
   CString     szMessage;
   char szBuffer[4][32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted, dwBytesReceived;
   COverlapped ov[4];
   DWORD       dwTotalBytes;
   DWORD       dwIoBytes;
   BOOL        bSuccess;
   DWORD       dwLastError;
   LARGE_INTEGER *lpCounterStart;
   LARGE_INTEGER *lpCounterStop;
   CLargeInt CounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];

   CString     szPipe;

   TRACE("\nWejście do CMfcsockDlg::DoCPPOverlappedPipes()");

   COverlappedPipe *lpPipe;

   szPipe = _T("\\\\");
   szPipe += m_szTargetServer;
   szPipe += _T("\\PIPE\\WNET\\WNETBNCH");

   try
      {
      lpPipe = 
         new COverlappedPipe((LPTSTR) (LPCTSTR) szPipe,
                ClientSide);
      }
   catch(...)
      {
      szMessage.Format(TEXT("Nawiązanie połączenia nie powiodło się, GetLastError() = %d"),
	      ::GetLastError());
      AfxMessageBox(szMessage);
      return;
      }
   TRACE(_T("\nNawiązano połączenie z serwerem\n"));

   HANDLE hEvent[4];
   for ( i = 0; i < 4; i++ )
      {
      hEvent[i] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
      ov[i].SetEventHandle(hEvent[i]);
      }

   int nSuccessfulReads = 0, nSuccessfulWrites = 0;
   int nPacketSize;

   dwTotalBytes = (DWORD) (m_nNumPackets * m_nPacketSize);

   GetPerformanceCounterData(REDIRECTOR,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   dwStartTime = GetCurrentTime();

   if (lpPipe->Read(szBuffer[RECV_1], 32768,
            &dwIoBytes, &ov[RECV_1] ) ||
         ::GetLastError() == ERROR_IO_PENDING)
      ++nSuccessfulReads;
   else
      dwLastError = ::GetLastError();

   if (lpPipe->Read(szBuffer[RECV_2], 32768,
            &dwIoBytes, &ov[RECV_2] ) ||
         ::GetLastError() == ERROR_IO_PENDING)
      ++nSuccessfulReads;
   else
      dwLastError = ::GetLastError();

   if (lpPipe->Write(szBuffer[SEND_1], m_nPacketSize,
            &ov[SEND_1] ) ||
         ::GetLastError() == ERROR_IO_PENDING)
      ++nSuccessfulWrites;
   else
      dwLastError = ::GetLastError();

   if (lpPipe->Write(szBuffer[SEND_2], m_nPacketSize,
            &ov[SEND_2] ) ||
         ::GetLastError() == ERROR_IO_PENDING)
      ++nSuccessfulWrites;
   else
      dwLastError = ::GetLastError();
   dwBytesTransmitted = dwBytesReceived = 0;

   BOOL bContinue = (nSuccessfulReads > 0 && nSuccessfulWrites > 0);
   while (bContinue)
      {
      i = ::WaitForMultipleObjects(4, hEvent, FALSE, 5000);

      if (i >= 4)
         {
         szMessage.Format(TEXT("Działanie ::WaitForMultipleObjects() nie powiodło się, GetLastError() = %d"),
            i, GetLastError());
         AfxMessageBox(szMessage);
         delete lpPipe;
         return;
         }

      bSuccess = ov[i].GetResult(&dwIoBytes, FALSE );
      if ( !bSuccess )
         {
         szMessage.Format(TEXT("Działanie WriteFile/ReadFile[%d] nie powiodło się, WSAGetLastError() = %d"),
            i, GetLastError());
         AfxMessageBox(szMessage);
         delete lpPipe;
         return;
         }

      if (ov[i].GetPreviousOperation() == COverlapped::ReadFile)
         {
         nPacketSize = 32768;
         dwBytesReceived += dwIoBytes;
         if ( dwBytesReceived >= dwTotalBytes )
            {
            break;
            }
         ::ResetEvent(hEvent[i]);
         }
      else   // Zakończono WriteFile()
         {
         nPacketSize = m_nPacketSize;
         dwBytesTransmitted += dwIoBytes;
         if ( dwBytesTransmitted >= (dwTotalBytes - m_nPacketSize))
            {
            ::ResetEvent(hEvent[i]);
            continue;
            }
         ::ResetEvent(hEvent[i]);
         }

      bSuccess = ov[i].Recycle(nPacketSize, &dwIoBytes);
      if (bSuccess)
         ::SetEvent(hEvent[i]);
      else if (::GetLastError() != ERROR_IO_PENDING)
         {
         szMessage.Format(TEXT("Działanie ::ReadFile() nie powiodło się, ::GetLastError() = %d"),
	       ::GetLastError());
         AfxMessageBox(szMessage);
         delete lpPipe;
         return;
         }
      }
   dwEndTime = GetCurrentTime();

   GetPerformanceCounterData(REDIRECTOR,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStop, SystemTime[1],
      SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   for (i = 0; i < 4; ++i)
      ::CloseHandle(hEvent[i]);

   CounterDelta = CLargeInt(*lpCounterStop) -
                  CLargeInt(*lpCounterStart);

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   lpPipe->Close();
   delete lpPipe;

   if ((nSuccessfulReads > 0) && (nSuccessfulWrites > 0))
      DisplayResults(dwStartTime, dwEndTime,
      dMilliSeconds, 
      (DWORD) CounterDelta,
      (((double) ((DWORD) CounterDelta)) * 1000.0)
      / dMilliSeconds);
   else
      {
      szMessage.Format(TEXT("Brak udanych operacji odczytu lub zapisu, ::GetLastError() = %d"),
	       ::GetLastError());
      AfxMessageBox(szMessage);
      }

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

void CMfcsockDlg::DoWNetDlls()
{
   HANDLE  hConnection;
   CString szMessage;
   DWORD   dwStartTime, dwEndTime;
   BYTE    szBuffer[2][65536];
   DWORD   i;
   DWORD      *lpCounterStart;
   DWORD      *lpCounterStop;
   DWORD       dwCounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];
   DWORD       dwInstances;

   hConnection = WNetCall(m_hWNetUser,
                          (LPVOID) (LPCTSTR) m_szTargetServer,
                          _T("wnetbnch"));
   if (hConnection == NULL)
      {
      szMessage.Format(TEXT("Działanie WNetCall() nie powiodło się, ::GetLastError() = %d"),
	    ::GetLastError());
      AfxMessageBox(szMessage);
      return;
      }
   GetPerformanceCounterData(NETWORK_INTERFACE,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   for (i = 0, dwStartTime = ::GetCurrentTime();
        i < m_nNumPackets; ++i)
      {
      if (WNetSend(hConnection, szBuffer[0], m_nPacketSize))
         {
         if (!WNetReceive(hConnection, szBuffer[1], m_nPacketSize,
               NULL))
            {
            szMessage.Format(TEXT("Działanie WNetReceive() nie powiodło się, ::GetLastError() = %d"),
	          ::GetLastError());
            AfxMessageBox(szMessage);
            WNetHangup(hConnection);
            return;
            }
         }
      else
         {
         szMessage.Format(TEXT("Działanie WNetSend() nie powiodło się, ::GetLastError() = %d"),
	       ::GetLastError());
         AfxMessageBox(szMessage);
         WNetHangup(hConnection);
         return;
         }
      }
   dwEndTime = GetCurrentTime();

   dwInstances =
      GetPerformanceCounterData(NETWORK_INTERFACE,
         BYTES_TOTAL_PER_SEC,
         (LPBYTE *) &lpCounterStop, SystemTime[1],
         SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   WNetHangup(hConnection);

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   for (DWORD j = 0; j < dwInstances; ++j)
      {
      dwCounterDelta = lpCounterStop[j] -
                       lpCounterStart[j];

      if (dwCounterDelta != 0)
         break;

      }
   DisplayResults(dwStartTime, dwEndTime, dMilliSeconds, 
      dwCounterDelta, 
      (((double) dwCounterDelta) * 1000.0) / dMilliSeconds);

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

void CMfcsockDlg::DoCAsyncSocket()
{
   CAsyncSocket sCall;
   CString     szMessage;
   int         nTotalReceived, nReceived, nBytes;
   BYTE        szBuffer[32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted;
   DWORD      *lpCounterStart;
   DWORD      *lpCounterStop;
   DWORD       dwCounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];
   DWORD       dwInstances;

   TRACE("\nWejście do CMfcsockDlg::DoCAsyncSocket()");
   // Create socket with no notifications
   if (!sCall.Create(0, SOCK_STREAM, 0))
      {
      szMessage.Format(TEXT("Działanie CAsyncSocket::Create() nie powiodło się, WSAGetLastError() = %d"),
	 sCall.GetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   DWORD dwBlockingIO = FALSE;
   sCall.IOCtl(FIONBIO, &dwBlockingIO);

   if (!GetHostAddress(m_szTargetServer, "echo", "tcp"))
      {
      szMessage.Format(TEXT("Uzyskanie adresu nie powiodło się, WSAGetLastError() = %d"),
	 ::WSAGetLastError());
      sCall.Close();
      AfxMessageBox(szMessage);
      return;
      }

   if (!sCall.Connect((const SOCKADDR *) &m_sin, sizeof (SOCKADDR_IN)))
      {
      szMessage.Format(TEXT("Działanie CAsyncSocket::Connect() nie powiodło się, WSAGetLastError() = %d"),
	 sCall.GetLastError());
      AfxMessageBox(szMessage);
      sCall.Close();
      return;
      }
   nBytes = sCall.Send((const void *) szBuffer, 100);

   if (nBytes == SOCKET_ERROR)
      {
      szMessage.Format(TEXT("Działanie CAsyncSocket::Connect() nie powiodło się, WSAGetLastError() = %d"),
	 sCall.GetLastError());
      AfxMessageBox(szMessage);
      sCall.Close();
      return;
      }
   for (nTotalReceived = nReceived = 0;
	nBytes != SOCKET_ERROR &&
	 nTotalReceived < nBytes;
       )
      {
      nReceived = sCall.Receive((LPVOID) szBuffer, nBytes);
      if (nReceived != SOCKET_ERROR)
	 nTotalReceived += nReceived;
      }

   GetPerformanceCounterData(NETWORK_INTERFACE,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   for (i = 0, dwStartTime = ::GetCurrentTime();
	i < m_nNumPackets; ++i)
      {
      if ((nBytes = sCall.Send((const void *) szBuffer, m_nPacketSize))
	   != SOCKET_ERROR)
	 {
	 for (nReceived = 0, nTotalReceived = 0;
	      nTotalReceived < nBytes; )
	    {
	    if ((nReceived = sCall.Receive((LPVOID) szBuffer, nBytes))
		   == SOCKET_ERROR)
		  break;
	    nTotalReceived += nReceived;
	    }
	 dwBytesTransmitted += (DWORD) nTotalReceived;
	 }
      }
   dwEndTime = GetCurrentTime();

   dwInstances =
      GetPerformanceCounterData(NETWORK_INTERFACE,
         BYTES_TOTAL_PER_SEC,
         (LPBYTE *) &lpCounterStop, SystemTime[1],
         SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   sCall.Close();

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   for (DWORD j = 0; j < dwInstances; ++j)
      {
      dwCounterDelta = lpCounterStop[j] -
                       lpCounterStart[j];

      if (dwCounterDelta != 0)
         break;

      }
   DisplayResults(dwStartTime, dwEndTime, dMilliSeconds, 
      dwCounterDelta, 
      (((double) dwCounterDelta) * 1000.0) / dMilliSeconds);

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

void CMfcsockDlg::DoCSocket()
{
   CSocket sCall;
   CString     szMessage;
   int         nTotalReceived, nReceived, nBytes;
   BYTE        szBuffer[32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted;
   DWORD      *lpCounterStart;
   DWORD      *lpCounterStop;
   DWORD       dwCounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];
   DWORD       dwInstances;

   TRACE("\nWejście do CMfcsockDlg::DoCSocket()");
   if (!sCall.Create())
      {
      szMessage.Format(TEXT("Działanie CSocket::Create() nie powiodło się, WSAGetLastError() = %d"),
	 sCall.GetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   if (!GetHostAddress(m_szTargetServer, "echo", "tcp"))
      {
      szMessage.Format(TEXT("Uzyskanie adresu nie powiodło się, WSAGetLastError() = %d"),
	 ::WSAGetLastError());
      sCall.Close();
      AfxMessageBox(szMessage);
      return;
      }

   if (!sCall.Connect((const SOCKADDR *) &m_sin, sizeof (SOCKADDR_IN)))
      {
      szMessage.Format(TEXT("Działanie CAsyncSocket::Connect() nie powiodło się, WSAGetLastError() = %d"),
	 sCall.GetLastError());
      AfxMessageBox(szMessage);
      sCall.Close();
      return;
      }

   nBytes = sCall.Send((const void *) szBuffer, 100);
   if (nBytes == SOCKET_ERROR)
      {
      szMessage.Format(TEXT("Działanie CAsyncSocket::Connect() nie powiodło się, WSAGetLastError() = %d"),
	 sCall.GetLastError());
      AfxMessageBox(szMessage);
      sCall.Close();
      return;
      }

   for (nTotalReceived = nReceived = 0;
        nBytes != SOCKET_ERROR &&
        nTotalReceived < nBytes;
       )
      {
      nReceived = sCall.Receive((LPVOID) szBuffer, nBytes);
      if (nReceived != SOCKET_ERROR)
	 nTotalReceived += nReceived;
      }

   GetPerformanceCounterData(NETWORK_INTERFACE,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   for (i = 0, dwStartTime = ::GetCurrentTime();
        i < m_nNumPackets; ++i)
      {
      if ((nBytes = sCall.Send((const void *) szBuffer, m_nPacketSize))
            != SOCKET_ERROR)
         {
         dwBytesTransmitted = 0;
         for (nReceived = 0, nTotalReceived = 0;
              nTotalReceived < nBytes; )
            {
            if ((nReceived = sCall.Receive((LPVOID) szBuffer, nBytes))
                  == SOCKET_ERROR)
               break;
            nTotalReceived += nReceived;
            }
         dwBytesTransmitted += (DWORD) nTotalReceived;
         }
      }
   dwEndTime = GetCurrentTime();

   dwInstances =
      GetPerformanceCounterData(NETWORK_INTERFACE,
         BYTES_TOTAL_PER_SEC,
         (LPBYTE *) &lpCounterStop, SystemTime[1],
         SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   sCall.Close();

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   for (DWORD j = 0; j < dwInstances; ++j)
      {
      dwCounterDelta = lpCounterStop[j] -
                       lpCounterStart[j];

      if (dwCounterDelta != 0)
         break;

      }
   DisplayResults(dwStartTime, dwEndTime, dMilliSeconds, 
      dwCounterDelta, 
      (((double) dwCounterDelta) * 1000.0) / dMilliSeconds);

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

void CMfcsockDlg::DoNamedPipes()
{
   HANDLE      hPipe = INVALID_HANDLE_VALUE;
   CString     szMessage;
   BYTE        szBuffer[32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted;
   CString     szPipe;
   LARGE_INTEGER *lpCounterStart;
   LARGE_INTEGER *lpCounterStop;
   CLargeInt CounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];

   TRACE("\nWejście do CMfcsockDlg::DoNamedPipes()");

   szPipe = _T("\\\\");
   szPipe += m_szTargetServer;
   szPipe += _T("\\PIPE\\WNET\\WNETBNCH");

   hPipe = ::CreateFile(
               szPipe,
               GENERIC_READ | GENERIC_WRITE,
               0,
               NULL,
               OPEN_EXISTING,
               0,
               NULL);

   if (hPipe == INVALID_HANDLE_VALUE)
      {
      szMessage.Format(_T("Brak możliwości połączenia z potokiem %s, GetLastError() = %d"),
         (LPCTSTR) szPipe, ::GetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   // W tym momencie połączenie z serwerem powinno być gotowe.
   DWORD dwMode = PIPE_WAIT | PIPE_READMODE_MESSAGE;

   ::SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL);

   TRACE(_T("Nawiązano połączenie z serwerem %s"), (LPCSTR) m_szTargetServer);

   GetPerformanceCounterData(REDIRECTOR,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   for (i = 0, dwStartTime = ::GetCurrentTime();
	    i < m_nNumPackets; ++i)
      {
      if (!::TransactNamedPipe(hPipe,
           szBuffer,
           m_nPacketSize,
           szBuffer,
           m_nPacketSize,
           &dwBytesTransmitted,
           NULL))
         {
         szMessage.Format(_T("Działanie TransactNamedPipe() nie powiodło się, GetLastError() = %d"),
            GetLastError());
         AfxMessageBox(szMessage);
         ::CloseHandle(hPipe);
         return;
         }
      }
   dwEndTime = GetCurrentTime();

   GetPerformanceCounterData(REDIRECTOR,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStop, SystemTime[1],
      SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   CounterDelta = CLargeInt(*lpCounterStop) -
                  CLargeInt(*lpCounterStart);

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   ::CloseHandle(hPipe);
   DisplayResults(dwStartTime, dwEndTime,
      dMilliSeconds, 
      (DWORD) CounterDelta,
      (((double) ((DWORD) CounterDelta)) * 1000.0)
      / dMilliSeconds);

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

void CMfcsockDlg::DoOverlappedPipes()
{
   HANDLE      hPipe = INVALID_HANDLE_VALUE;
   CString     szMessage;
   char szBuffer[4][32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted, dwBytesReceived;
   HANDLE      hEvents[4];
   OVERLAPPED  ov[4];
   DWORD       dwTotalBytes;
   DWORD       dwIoBytes;
   BOOL        bSuccess;
   LARGE_INTEGER *lpCounterStart;
   LARGE_INTEGER *lpCounterStop;
   CLargeInt CounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];

   TRACE("\nWejście do CMfcsockDlg::DoOverlappedPipes()");
   CString     szPipe;

   TRACE("\nWejście do CMfcsockDlg::DoNamedPipes()");

   szPipe = _T("\\\\");
   szPipe += m_szTargetServer;
   szPipe += _T("\\PIPE\\WNET\\WNETBNCH");

   hPipe = ::CreateFile(
               szPipe,
               GENERIC_READ | GENERIC_WRITE,
               0,
               NULL,
               OPEN_EXISTING,
               FILE_FLAG_OVERLAPPED,
               NULL);

   if (hPipe == INVALID_HANDLE_VALUE)
      {
      szMessage.Format(_T("Brak możliwości połączenia z potokiem %s, GetLastError() = %d"),
         (LPCTSTR) szPipe, ::GetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   for ( i = 0; i < 4; i++ )
      {
      hEvents[i] = ::CreateEvent( NULL, TRUE, FALSE, NULL );
      if ( hEvents[i] == NULL )
         {
         szMessage.Format(TEXT("Działanie CreateEvent() nie powiodło się, GetLastError() = %d"),
            ::GetLastError());
         ::CloseHandle(hPipe);
         AfxMessageBox(szMessage);
         return;
         }
      ov[i].Internal = 0;
      ov[i].InternalHigh = 0;
      ov[i].Offset = 0;
      ov[i].OffsetHigh = 0;
      ov[i].hEvent = hEvents[i];
      }

   dwTotalBytes = (DWORD) (m_nNumPackets * m_nPacketSize);

   GetPerformanceCounterData(REDIRECTOR,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   dwStartTime = GetCurrentTime();

   ::ReadFile( hPipe, szBuffer[RECV_1], sizeof (szBuffer[RECV_1]),
			      &dwIoBytes, &ov[RECV_1] );

   ::ReadFile( hPipe, szBuffer[RECV_2], sizeof (szBuffer[RECV_2]),
			    &dwIoBytes, &ov[RECV_2] );

   ::WriteFile( hPipe, szBuffer[SEND_1], m_nPacketSize,
			    &dwIoBytes, &ov[SEND_1] );

   ::WriteFile( hPipe, szBuffer[SEND_2], m_nPacketSize,
			    &dwIoBytes, &ov[SEND_2] );
   dwBytesTransmitted = dwBytesReceived = 0;
   while ( TRUE )
      {
      i = ::WaitForMultipleObjects( 4, hEvents, FALSE, INFINITE );

      if (i >= 4)
         {
         szMessage.Format(TEXT("Działanie ::WaitForMultipleObjects() nie powiodło się, GetLastError() = %d"),
            i, GetLastError());
         ::CloseHandle(hPipe);
         AfxMessageBox(szMessage);
         return;
         }

      bSuccess = GetOverlappedResult( hPipe, &ov[i], &dwIoBytes, FALSE );
      if ( !bSuccess )
         {
         szMessage.Format(TEXT("Działanie WriteFile/ReadFile[%d] nie powiodło się, WSAGetLastError() = %d"),
            i, GetLastError());
         ::CloseHandle(hPipe);
         AfxMessageBox(szMessage);
         return;
         }

      if ( i == RECV_1 || i == RECV_2 )
         {
         dwBytesReceived += dwIoBytes;
         if ( dwBytesReceived >= dwTotalBytes )
            {
            break;
            }
         ::ResetEvent( hEvents[i] );

         bSuccess = ::ReadFile( hPipe, szBuffer[i], 
                sizeof (szBuffer[i]),
				    &dwIoBytes, &ov[i] );
         if (bSuccess)
            ::SetEvent(hEvents[i]);
         else if (::GetLastError() != ERROR_IO_PENDING)
            {
            szMessage.Format(TEXT("Działanie ::ReadFile() nie powiodło się, ::GetLastError() = %d"),
               ::GetLastError());
            ::CloseHandle(hPipe);
            AfxMessageBox(szMessage);
            return;
            }
         }
      else if (i == SEND_1 || i == SEND_2)
         {
         dwBytesTransmitted += dwIoBytes;
         if ( dwBytesTransmitted >= (dwTotalBytes - m_nPacketSize))
            {
            ::ResetEvent( hEvents[i] );
            continue;
            }
         ::ResetEvent( hEvents[i] );
         bSuccess = ::WriteFile( hPipe, szBuffer[i], m_nPacketSize,
                     &dwIoBytes, &ov[i] );
         if (bSuccess)
            ::SetEvent(hEvents[i]);
         else if (::GetLastError() != ERROR_IO_PENDING)
            {
            szMessage.Format(TEXT("Działanie ::WriteFile() nie powiodło się, ::GetLastError() = %d"),
               ::GetLastError());
            ::CloseHandle(hPipe);
            AfxMessageBox(szMessage);
            return;
            }
         }
      }
   dwEndTime = GetCurrentTime();

   GetPerformanceCounterData(REDIRECTOR,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStop, SystemTime[1],
      SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   for (i = 0; i < 4; ++i)
      ::CloseHandle(hEvents[i]);

   CounterDelta = CLargeInt(*lpCounterStop) -
                  CLargeInt(*lpCounterStart);

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   ::CloseHandle(hPipe);
   DisplayResults(dwStartTime, dwEndTime,
      dMilliSeconds, 
      (DWORD) CounterDelta,
      (((double) ((DWORD) CounterDelta)) * 1000.0)
      / dMilliSeconds);

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

void CMfcsockDlg::DoCPPNamedPipes()
{
   CNamedPipe  *lpNamedPipe;
   CString     szMessage;
   BYTE        szBuffer[32768];
   DWORD       dwStartTime, dwEndTime;
   UINT        i;
   DWORD       dwBytesTransmitted;
   CString     szPipe;
   LARGE_INTEGER *lpCounterStart;
   LARGE_INTEGER *lpCounterStop;
   CLargeInt CounterDelta;
   CSystemTime SystemTime[2];
   CLargeInt   SampleTime[2];

   TRACE("\nWejście do CMfcsockDlg::DoCPPNamedPipes()");

   szPipe = _T("\\\\");
   szPipe += m_szTargetServer;
   szPipe += _T("\\PIPE\\WNET\\WNETBNCH");

   try
      {
      lpNamedPipe = new CNamedPipe(szPipe,
                      ClientSide);
      }
   catch(...)
      {
      szMessage.Format(TEXT("Brak możliwości połączenia, GetLastError() = %d"),
	      ::GetLastError());
      AfxMessageBox(szMessage);
      return;
      }

   // W tym momencie połączenie z serwerem powinno być gotowe.
   TRACE(_T("Nawiązano połączenie z serwerem %s"), (LPCSTR) m_szTargetServer);

   GetPerformanceCounterData(REDIRECTOR,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStart, SystemTime[0],
      SampleTime[0]);

   for (i = 0, dwStartTime = ::GetCurrentTime();
	    i < m_nNumPackets; ++i)
      {
      if (!lpNamedPipe->Transact(
           szBuffer,
           m_nPacketSize,
           szBuffer,
           m_nPacketSize,
           &dwBytesTransmitted))
         {
         szMessage.Format(_T("Działanie TransactNamedPipe() nie powiodło się, GetLastError() = %d"),
            GetLastError());
         AfxMessageBox(szMessage);
         delete lpNamedPipe;
         return;
         }
      }
   dwEndTime = GetCurrentTime();

   GetPerformanceCounterData(REDIRECTOR,
      BYTES_TOTAL_PER_SEC,
      (LPBYTE *) &lpCounterStop, SystemTime[1],
      SampleTime[1]);

   RegCloseKey(HKEY_PERFORMANCE_DATA);

   CounterDelta = CLargeInt(*lpCounterStop) -
                  CLargeInt(*lpCounterStart);

   double dMilliSeconds;
   LARGE_INTEGER PerformanceFrequency;

   if (QueryPerformanceFrequency(&PerformanceFrequency))
      dMilliSeconds =
         ((double) (((DWORD) SampleTime[1]) -
                    ((DWORD) SampleTime[0]))) /
         ((double) (PerformanceFrequency.LowPart))
         * 1000.0;
   else
      dMilliSeconds = SystemTime[1] - SystemTime[0];

   DisplayResults(dwStartTime, dwEndTime,
      dMilliSeconds, 
      (DWORD) CounterDelta,
      (((double) ((DWORD) CounterDelta)) * 1000.0)
      / dMilliSeconds);

   lpNamedPipe->Close();
   delete lpNamedPipe;

   ::HeapFree(::GetProcessHeap(), 0, lpCounterStart);
   ::HeapFree(::GetProcessHeap(), 0, lpCounterStop);
}

BOOL CMfcsockDlg::GetHostAddress(LPCSTR lpszHost,
				 LPCSTR lpszService,
				 LPCSTR lpszProto)
{
   LPHOSTENT lpHost;
   LPSERVENT lpServ;

   lpHost = ::gethostbyname(lpszHost);
   if (lpHost != NULL)
      {
      m_sin.sin_family = PF_INET;
      ::CopyMemory(&m_sin.sin_addr, lpHost->h_addr_list[0],
		   lpHost->h_length);
      lpServ = ::getservbyname(lpszService, lpszProto);
      if (lpServ != NULL)
	 {
	 m_sin.sin_port = lpServ->s_port;
	 ::ZeroMemory(m_sin.sin_zero, sizeof (m_sin.sin_zero));
	 return TRUE;
	 }
      }
   return FALSE;
}

void CMfcsockDlg::DisplayResults(DWORD dwStartTime, DWORD dwEndTime,
                                 double dPerfTime,
                                 DWORD  dwPerfBytesTransmitted,
                                 double dPerfStats)
{
   CString szBuffer;

   szBuffer.Format("%d (%-.0f)", dwEndTime - dwStartTime,
      dPerfTime);
   SetDlgItemText(IDC_MS_ELAPSED, (LPCSTR) szBuffer);
   szBuffer.Format("%d (%-d)", m_nNumPackets * m_nPacketSize * 2,
      dwPerfBytesTransmitted);

   SetDlgItemText(IDC_BYTES_TRANSMITTED, (LPCSTR) szBuffer);

   double dTotalBytes = ((double) m_nPacketSize) *
			((double) m_nNumPackets) * 2000.0;
   double dEndTime = (double) dwEndTime;
   double dStartTime = (double) dwStartTime;

   szBuffer.Format("%.2f (%.2f)",
       dTotalBytes / (dEndTime - dStartTime), dPerfStats);

   SetDlgItemText(IDC_BYTES_PER_SECOND, (LPCSTR) szBuffer);
}


void CMfcsockDlg::OnCasyncSocket()
{
   m_uControlID = IDC_CASYNC_SOCKET;

}

void CMfcsockDlg::OnCsocket()
{
   m_uControlID = IDC_CSOCKET;

}

void CMfcsockDlg::OnStandardOverlapped()
{
   m_uControlID = IDC_STANDARD_OVERLAPPED;

}

void CMfcsockDlg::OnStandardSynchronous()
{
   m_uControlID = IDC_STANDARD_SYNCHRONOUS;
}

void CMfcsockDlg::OnDatagram()
{
	m_uControlID = IDC_DATAGRAM;
}

void CMfcsockDlg::OnCppOverlapped()
{
   m_uControlID = IDC_CPP_OVERLAPPED;
}

void CMfcsockDlg::OnCppOverlappedPipes() 
{
   m_uControlID = IDC_CPP_OVERLAPPED_PIPES;
}

void CMfcsockDlg::OnKillfocusPacketSize()
{
	GetDlgItem(IDC_DOUBLE)->EnableWindow(
	   GetDlgItemInt(IDC_PACKET_SIZE) <= 16384);
}


void CMfcsockDlg::OnNamedPipes()
{
	m_uControlID = IDC_NAMED_PIPES;

}

void CMfcsockDlg::OnOverlappedPipes()
{
	m_uControlID = IDC_OVERLAPPED_PIPES;
}

void CMfcsockDlg::OnCppNamedPipes()
{
	m_uControlID = IDC_CPP_NAMED_PIPES;
}

void CMfcsockDlg::OnWnetDlls() 
{
	m_uControlID = IDC_WNET_DLLS;
}

void CMfcsockDlg::OnCancel() 
{
   if (m_hWNetUser != NULL)
      WNetShutdown(m_hWNetUser);	
   delete m_pNamedPipesServer;
   CString szMessage;

#ifdef _USE_WINSOCK2_
   WSACleanup();
#endif
	CDialog::OnCancel();
}

BOOL WINAPI CMfcsockDlg::PipesReceiveCallback(
      LPBYTE lpData,
      DWORD dwDataLength, 
      HANDLE hConnection)
{
   TRACE(_T("\nWejście do CMfcsockDlg::PipesReceiveCallback"));
   TRACE(_T("\n\tlpData = 0X%08X, dwDataLength = %d, hConnection = 0X%08X"),
      lpData, dwDataLength, hConnection);

   CNamedPipe *pPipe = (CNamedPipe *) hConnection;
   DWORD dwBytesWritten;

   // Wykonanie pięciu prób odesłania danych.
   for (int i = 0; i < 5; ++i)
      {
      if (!::WriteFile(pPipe->GetFileHandle(),
                       lpData,
                       dwDataLength,
                       &dwBytesWritten,
                       NULL))
         {
         TRACE(_T("\n\tDziałanie WriteFile() nie powiodło się, GetLastError() = %d"),
            ::GetLastError());
         }
      else
         {
         break;
         }
      }
   //pPipe->Write(lpData, dwDataLength);

   TRACE(_T("\nWyjście z CMfcsockDlg::PipesReceiveCallback"));

   return TRUE;
}

void CMfcsockDlg::OnDouble() 
{
   UpdateData(TRUE);

   if (m_nPacketSize <= 16384)
      m_nPacketSize <<= 1;
   else
      MessageBeep(0);

   GetDlgItem(IDC_DOUBLE)->EnableWindow(m_nPacketSize <= 16384);
   UpdateData(FALSE);
}

void CMfcsockDlg::OnRpc() 
{
	m_uControlID = IDC_RPC;
}

void __RPC_FAR * __RPC_API midl_user_allocate(size_t len)
{
    return(malloc(len));
}

void __RPC_API midl_user_free(void __RPC_FAR * ptr)
{
    free(ptr);
}
