Click here to Skip to main content
15,892,298 members
Articles / Desktop Programming / MFC

The Win32 Foundation Classes (WFC) - Version 45

Rate me:
Please Sign up or sign in to vote.
4.93/5 (40 votes)
16 May 2000 469.5K   12.7K   280  
The Win32 Foundation Classes (WFC) are a library of C++ classes that extend Microsoft Foundation Classes (MFC) beyond mere GUI applications, and provide extensive support for system and NT specific applications
#include <wfc.h>
#pragma hdrstop

/*
** Author: Samuel R. Blackburn
** Internet: wfc@pobox.com
**
** You can use it any way you like as long as you don't try to sell it.
**
** Any attempt to sell WFC in source code form must have the permission
** of the original author. You can produce commercial executables with
** WFC but you can't sell WFC.
**
** Copyright, 2000, Samuel R. Blackburn
**
** $Workfile: namdpipe.cpp $
** $Revision: 23 $
** $Modtime: 3/17/00 4:39p $
** $Reuse Tracing Code: 1 $
*/

#if defined( _DEBUG ) && ! defined( WFC_STL )
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif // _DEBUG

CNamedPipe::CNamedPipe( DWORD _input_buffer_size, DWORD _output_buffer_size )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::CNamedPipe()" ) );
   WFCTRACEVAL( TEXT( "pointer is " ), (VOID *) this );
   m_Initialize( _input_buffer_size, _output_buffer_size );
}

CNamedPipe::~CNamedPipe()
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::~CNamedPipe()" ) );
   WFCTRACEVAL( TEXT( "pointer is " ), (VOID *) this );

   if ( m_AutomaticallyDelete != FALSE )
   {
      WFCTRACE( TEXT( "Automatically Deleting" ) );

      if ( m_PipeHandle != (HANDLE) NULL )
      {
         Close();
      }
   }

   if ( m_InputBuffer != (LPVOID) NULL )
   {
      WFCTRACE( TEXT( "Freeing input buffer" ) );

      /*
      ** Free our memory
      */

      delete [] m_InputBuffer;

      m_InputBuffer     = (LPVOID) NULL;
      m_InputBufferSize = 0L;
   }

   if ( m_OutputBuffer != (LPVOID) NULL )
   {
      WFCTRACE( TEXT( "Freeing output buffer" ) );

      /*
      ** Free our memory
      */

      delete [] m_OutputBuffer;

      m_OutputBuffer     = (LPVOID) NULL;
      m_OutputBufferSize = 0L;
   }
}

void CNamedPipe::m_Initialize( DWORD _input_buffer_size, DWORD _output_buffer_size )
{
   m_AutomaticallyDelete = TRUE;
   m_ErrorCode           = 0L;
   m_PipeHandle          = (HANDLE) INVALID_HANDLE_VALUE;
   m_Timeout             = NMPWAIT_USE_DEFAULT_WAIT;
   m_PipeName.Empty();

   m_InputBufferSize  = _input_buffer_size;
   m_OutputBufferSize = _output_buffer_size;

   try
   {
      m_InputBuffer = new BYTE[ m_InputBufferSize ];
   }
   catch( ... )
   {
      m_InputBuffer = NULL;
   }

   try
   {
      m_OutputBuffer = new BYTE[ m_OutputBufferSize ];
   }
   catch( ... )
   {
      m_OutputBuffer = NULL;
   }
}

#if defined( _DEBUG ) && ! defined( WFC_NO_DUMPING )

void CNamedPipe::Dump( CDumpContext& dump_context ) const
{
   dump_context << TEXT( "m_AutomaticallyDelete = "      ) << m_AutomaticallyDelete      << TEXT( "\n" );
   dump_context << TEXT( "m_PipeHandle = "               ) << m_PipeHandle               << TEXT( "\n" );
   dump_context << TEXT( "m_MaximumNumberOfInstances = " ) << m_MaximumNumberOfInstances << TEXT( "\n" );
   dump_context << TEXT( "m_InputBufferSize = "          ) << m_InputBufferSize          << TEXT( "\n" );
   dump_context << TEXT( "m_OutputBufferSize = "         ) << m_OutputBufferSize         << TEXT( "\n" );
   dump_context << TEXT( "m_NumberOfBytesToWrite = "     ) << m_NumberOfBytesToWrite     << TEXT( "\n" );
   dump_context << TEXT( "m_NumberOfBytesRead = "        ) << m_NumberOfBytesRead        << TEXT( "\n" );
   dump_context << TEXT( "m_Timeout = "                  ) << m_Timeout                  << TEXT( "\n" );
   dump_context << TEXT( "m_PipeName = \""               ) << m_PipeName                 << TEXT( "\"\n" );
   dump_context << TEXT( "m_FullPipeName is " );
   m_FullPipeName.Dump( dump_context );
   dump_context << TEXT( "m_PipeState = "                ) << m_PipeState                << TEXT( "\n" );
   dump_context << TEXT( "m_NumberOfInstances = "        ) << m_NumberOfInstances        << TEXT( "\n" );
   dump_context << TEXT( "m_MaximumNumberOfBytesBeforeRemoteTransmission = "           ) << m_MaximumNumberOfBytesBeforeRemoteTransmission << TEXT( "\n" );
   dump_context << TEXT( "m_MaximumNumberOfMillisecondsBeforeRemoteTransmission = "    ) << m_MaximumNumberOfMillisecondsBeforeRemoteTransmission << TEXT( "\n" );
   dump_context << TEXT( "m_UserNameOfClientProcess = \"" ) << m_UserNameOfClientProcess << TEXT( "\"\n" );
}

#endif // _DEBUG

BOOL CNamedPipe::Call( CString& pipe_name, 
                       LPVOID   write_buffer, 
                       DWORD    size_of_write_buffer, 
                       LPVOID   read_buffer, 
                       DWORD    size_of_read_buffer, 
                       DWORD   *address_of_number_of_bytes_read,
                       DWORD    number_of_milliseconds_to_wait )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::Call()" ) );

   ASSERT( write_buffer != NULL );
   ASSERT( read_buffer  != NULL );

   if ( write_buffer == NULL || read_buffer == NULL )
   {
      m_ErrorCode = ERROR_INVALID_PARAMETER;
      return( FALSE );
   }

   /*
   ** Writes to the pipe then reads from it
   */

   BOOL return_value = FALSE;

   return_value = ::CallNamedPipe( pipe_name, 
                                   write_buffer,
                                   size_of_write_buffer,
                                   read_buffer,
                                   size_of_read_buffer,
                                   address_of_number_of_bytes_read,
                                   number_of_milliseconds_to_wait );

   if ( return_value == FALSE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

void CNamedPipe::Close( void )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::Close()" ) );

   if ( m_PipeHandle != (HANDLE) INVALID_HANDLE_VALUE )
   {
      ::wfc_close_handle( m_PipeHandle );
      m_PipeHandle = (HANDLE) INVALID_HANDLE_VALUE;
   }
}

BOOL CNamedPipe::Connect( LPOVERLAPPED overlapped_p )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::Connect()" ) );

   // overlapped_p can be NULL

   BOOL return_value = FALSE;

   return_value = ::ConnectNamedPipe( m_PipeHandle, overlapped_p );

   if ( return_value == FALSE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

BOOL CNamedPipe::Create( LPCTSTR server_name,
                         LPCTSTR pipe_name,
                         DWORD   open_mode,
                         DWORD   type_of_pipe,
                         DWORD   number_of_pipes,
           LPSECURITY_ATTRIBUTES security_attributes_p )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::Create()" ) );

   ASSERT( pipe_name != NULL );

   /*
   ** Check parameters for errors
   */

   if ( pipe_name == NULL )
   {
      m_ErrorCode = ERROR_INVALID_PARAMETER;
      return( FALSE );
   }

   m_PipeName = TEXT( "\\\\" );

   if ( server_name == NULL )
   {
      m_PipeName += TEXT( "." );
   }
   else
   {
      m_PipeName += server_name;
   }

   m_PipeName += TEXT( "\\PIPE\\" );
   m_PipeName += pipe_name;

   WFCTRACEVAL( TEXT( "pipe_name is " ), CString( pipe_name ) );

   CSecurityAttributes security_attributes;
   SECURITY_DESCRIPTOR security_descriptor;

   if ( security_attributes_p == NULL )
   {
      WFCTRACE( TEXT( "Creating security attributes" ) );

      ::InitializeSecurityDescriptor( &security_descriptor, SECURITY_DESCRIPTOR_REVISION );

      ::SetSecurityDescriptorDacl( &security_descriptor, TRUE, NULL, FALSE );
      security_attributes.bInheritHandle = FALSE;
      security_attributes.lpSecurityDescriptor = &security_descriptor;

      security_attributes_p = (SECURITY_ATTRIBUTES *) &security_attributes;
   }

   m_PipeHandle = ::CreateNamedPipe( m_PipeName,
                                     open_mode,
                                     type_of_pipe, 
                                     number_of_pipes,
                                     m_OutputBufferSize,
                                     m_InputBufferSize,
                                     m_Timeout,
                                     security_attributes_p );

   if ( m_PipeHandle == (HANDLE) INVALID_HANDLE_VALUE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

BOOL CNamedPipe::Disconnect( void )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::Disconnect()" ) );

   BOOL return_value = FALSE;

   return_value = ::DisconnectNamedPipe( m_PipeHandle );

   if ( return_value == FALSE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

BOOL CNamedPipe::GetInformation( void )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::GetInformation()" ) );

   BOOL return_value = FALSE;

   DWORD type_of_pipe                = 0;
   DWORD size_of_output_buffer       = 0;
   DWORD size_of_input_buffer        = 0;
   DWORD maximum_number_of_instances = 0;

   return_value = ::GetNamedPipeInfo( m_PipeHandle,
                                     &type_of_pipe,
                                     &size_of_output_buffer,
                                     &size_of_input_buffer,
                                     &maximum_number_of_instances );

   if ( return_value == FALSE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

BOOL CNamedPipe::GetState( void )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::GetState()" ) );

   BOOL return_value = FALSE;

   TCHAR temp_string[ 513 ];

   ::ZeroMemory( temp_string, sizeof( temp_string ) );

   return_value = ::GetNamedPipeHandleState( m_PipeHandle,
                                            &m_PipeState,
                                            &m_NumberOfInstances,
                                            &m_MaximumNumberOfBytesBeforeRemoteTransmission,
                                            &m_MaximumNumberOfMillisecondsBeforeRemoteTransmission,
                                             temp_string,
                                             DIMENSION_OF( temp_string ) );

   m_UserNameOfClientProcess = temp_string;

   if ( return_value == FALSE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

#if ! defined( WFC_STL )
BOOL CNamedPipe::Open( LPCTSTR pipe_name, UINT, CFileException * )
#else // WFC_STL
BOOL CNamedPipe::Open( LPCTSTR pipe_name, UINT )
#endif // WFC_STL
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::Open()" ) );

   ASSERT( pipe_name != NULL );

   if ( pipe_name == (LPCTSTR) NULL )
   {
      m_ErrorCode = ERROR_INVALID_PARAMETER;

      return( FALSE );
   }

   /*
   ** pipe_name can be:
   ** "pipe_name" where the pipe will be openend on the local machine
   ** "\\server_name\pipe_name" where the pipe will be opened on the server
   ** "\\server_name\PIPE\pipe_name" which is a fully qualified pipe name
   */

   CUniversalNamingConvention unc( pipe_name );

   WFCTRACEVAL( TEXT( "unc is " ), CString( unc ) );

   if ( unc.ServerName.IsEmpty() != FALSE )
   {
      unc.ServerName = TEXT( "." );
   }

   if ( unc.ShareName.CompareNoCase( TEXT( "PIPE" ) ) != 0 )
   {
      CString temp_string = unc.ShareName;

      unc.ShareName = TEXT( "PIPE" );

      if ( temp_string.GetLength() > 0 )
      {
         unc.PathName = temp_string + TEXT( "\\" ) + unc.PathName;
      }
   }

   unc.Make();

   m_FullPipeName = unc;

   WFCTRACEVAL( TEXT( "Full Pipe Name is " ), CString( unc ) );

   return( Create( unc.ServerName, unc.PathName ) );
}

BOOL CNamedPipe::Peek( LPVOID buffer_address, 
                       DWORD  size_of_buffer,
                       DWORD& number_of_bytes_read,
                       DWORD& number_of_bytes_available,
                       DWORD& number_of_bytes_remaining_in_message )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::Peek()" ) );

   /*
   ** buffer_address can be NULL
   */

   BOOL return_value = FALSE;

   return_value = ::PeekNamedPipe( m_PipeHandle, 
                                   buffer_address, 
                                   size_of_buffer, 
                                  &number_of_bytes_read,
                                  &number_of_bytes_available,
                                  &number_of_bytes_remaining_in_message );

   if ( return_value == FALSE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

BOOL CNamedPipe::SetState( DWORD new_pipe_mode, 
                           DWORD maximum_number_of_bytes_before_transmission, 
                           DWORD maximum_number_of_milliseconds_before_transmission )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::SetState()" ) );

   BOOL return_value = FALSE;

   return_value = ::SetNamedPipeHandleState( m_PipeHandle,
                                            &new_pipe_mode,
                                            &maximum_number_of_bytes_before_transmission,
                                            &maximum_number_of_milliseconds_before_transmission );

   if ( return_value == FALSE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

BOOL CNamedPipe::Transact( LPOVERLAPPED overlapped_p )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::Transact()" ) );

   // overlapped_p can be NULL

   BOOL return_value = FALSE;

   return_value = ::TransactNamedPipe( m_PipeHandle,
                                       m_OutputBuffer,
                                       m_NumberOfBytesToWrite,
                                       m_InputBuffer,
                                       m_InputBufferSize,
                                      &m_NumberOfBytesRead,
                                       overlapped_p );

   if ( return_value == FALSE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

BOOL CNamedPipe::Wait( LPCTSTR name_of_server, LPCTSTR name_of_pipe, DWORD number_of_milliseconds )
{
   WFCLTRACEINIT( TEXT( "CNamedPipe::Wait()" ) );

   ASSERT( name_of_pipe != NULL );

   /*
   ** Check parameters for errors
   */

   if ( name_of_pipe == NULL )
   {
      m_ErrorCode = ERROR_INVALID_PARAMETER;
      return( FALSE );
   }

   BOOL return_value = FALSE;

   CString full_pipe_name( TEXT( "\\\\" ) ); // like \\servername\pipe\pipename

   if ( name_of_server == NULL )
   {
      full_pipe_name += TEXT( "." );
   }
   else
   {
      full_pipe_name += name_of_server;
   }

   full_pipe_name += TEXT( "\\pipe\\" );
   full_pipe_name += name_of_pipe;

   return_value = ::WaitNamedPipe( full_pipe_name, number_of_milliseconds );

   if ( return_value == FALSE )
   {
      m_ErrorCode = ::GetLastError();

      WFCTRACE( TEXT( "FAILED!" ) );
      WFCTRACEERROR( m_ErrorCode );

      return( FALSE );
   }
   else
   {
      return( TRUE );
   }
}

// End of source

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
I'm just a simple little NT programmer. Most of the work I do is remote controlling equipment in real time. I started out using Windows 3.0. Then came 3.1 and then NT. I started using NT but unfortunately, Microsoft didn't. I started using MFC but unfortunately, Microsoft didn't (and still doesn't) put any real support for NT into MFC so I wrote a bunch of C++ classes to make my life easier. Like all class libraries, mine grew. Now I'm giving it away, I call it Win32 Foundation Classes.

Check out Sam's homepage at www.SamBlackburn.com/wfc/.

Comments and Discussions