//
//  Copyright (c) 2001, Reson, Inc. All Rights Reserved.
//
//  Filename:   OverLapped.cpp
//
//  Project:    6046
//
//  Author(s):  W. Arcus
//
//  Purpose:    Implementation of COverLapped class to support Win32 overlapped io.
//
//  Notes:      
//

#include "StdAfx.h"
#include "OverLapped.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// COverLapped class implementation.

COverLapped::COverLapped(   BOOL    bCreateEvent, 
                            HANDLE  hNewFile,
                            LPVOID  lpNewBuffer)
{
    ManageDllState_m();

    Internal     = 0;
    InternalHigh = 0;
    Offset       = 0;
    OffsetHigh   = 0;

    if ( bCreateEvent )
    {
        hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );

        if ( hEvent == NULL )
        {
            TRACE( _T( "COverLapped::COverLapped(), Event handle is NULL\n" ) );
        }
    }
    else
    {
        hEvent = NULL;
    }

    m_hFile    = hNewFile;
    m_lpBuffer = lpNewBuffer;
}
    
COverLapped::COverLapped(   HANDLE hNewEvent, 
                            HANDLE hNewFile,
                            LPVOID lpNewBuffer)
{
    ManageDllState_m();

    Internal     = 0;
    InternalHigh = 0;
    Offset       = 0;
    OffsetHigh   = 0;

    hEvent       = hNewEvent;
    m_hFile      = hNewFile;
    m_lpBuffer   = lpNewBuffer;
}
    
COverLapped::COverLapped( const COverLapped &rRhs )
{
    Internal     = rRhs.Internal;
    InternalHigh = rRhs.InternalHigh;
    Offset       = rRhs.Offset;
    OffsetHigh   = rRhs.OffsetHigh;
    hEvent       = rRhs.hEvent;

    m_hFile      = rRhs.m_hFile;
    m_lpBuffer   = rRhs.m_lpBuffer;
}

COverLapped::COverLapped(   LPOVERLAPPED    lpOverlapped,
                            HANDLE          hFile,
                            LPVOID          lpBuffer)
{
    Internal     = lpOverlapped->Internal;
    InternalHigh = lpOverlapped->InternalHigh;
    Offset       = lpOverlapped->Offset;
    OffsetHigh   = lpOverlapped->OffsetHigh;
    hEvent       = lpOverlapped->hEvent;

    m_hFile      = hFile;
    m_lpBuffer   = lpBuffer;
}
    
BOOL COverLapped::GetResult(    LPDWORD lpdwBytes,
                                BOOL    bBlock )
{
    return ::GetOverlappedResult( m_hFile, this, lpdwBytes, bBlock );
}
    
BOOL COverLapped::Recycle(  DWORD                           dwBytesToTransfer,
                            LPDWORD                         lpdwBytesTransferred,
                            LPOVERLAPPED_COMPLETION_ROUTINE lpCompletion)
{
    BOOL bRetcode = FALSE; // Assume failure for now.
    
    switch ( m_eLastOperation )
    {
        case operationReadFile:

            bRetcode = ::ReadFile( m_hFile, m_lpBuffer, dwBytesToTransfer, lpdwBytesTransferred, this );
            break;

      case operationWriteFile:

            bRetcode = ::WriteFile( m_hFile, m_lpBuffer, dwBytesToTransfer, lpdwBytesTransferred, this );
            break;

      case operationReadFileEx:

            bRetcode = ::ReadFileEx( m_hFile, m_lpBuffer, dwBytesToTransfer, this, lpCompletion );
            break;

      case operationWriteFileEx:

            bRetcode = ::WriteFileEx( m_hFile, m_lpBuffer, dwBytesToTransfer, this, lpCompletion );
            break;

      default:

            TRACE( _T( "COverLapped::Recycle(), Previous operation unrecognized...!\n"));
            bRetcode = FALSE;
            break;
    }

    return bRetcode;
}

// Get and set methods.

void COverLapped::SetFile( HANDLE hFile )
{
   m_hFile = hFile;
}

LPVOID COverLapped::GetBuffer( void )
{
   return m_lpBuffer;
}

VOID COverLapped::SetBuffer( LPVOID lpBuffer )
{
   m_lpBuffer = lpBuffer;
}

COverLapped::EOPERATION COverLapped::GetPreviousOperation( void ) const
{
    return m_eLastOperation;
}

VOID COverLapped::SetPreviousOperation( const EOPERATION &reOperation)
{
   m_eLastOperation = reOperation;
}

HANDLE COverLapped::GetEventHandle( void )
{
    return hEvent;
}

VOID COverLapped::SetEventHandle( HANDLE hEvent )
{
    this->hEvent = hEvent;
}

DWORD COverLapped::GetOffset( void )
{
    return Offset;
}

VOID COverLapped::SetOffset( DWORD dwOffset )
{
    Offset = dwOffset;
}

DWORD & COverLapped::FileOffset( void )
{
   return ((DWORD &) Offset);
}

DWORD & COverLapped::FileOffsetHigh(void)
{
    return ((DWORD &) OffsetHigh);
}

COverLapped::operator OVERLAPPED * () const
{
    return ((::OVERLAPPED *) this );
}
