///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Winnov L.P., 1996, All rights reserved
// Buffer.cpp: File mapped interprocess buffer class implementation
///////////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include <tchar.h>
#include <string.h>
#include "wnverr.h"
#include "debug.h"
#include "buffer.h"
#include "log.h"

///////////////////////////////////////////////////////////////////////////////
// PRIVATE
///////////////////////////////////////////////////////////////////////////////

// non-localizeable base file name
#define BASE_NAME TEXT("WNVBUFFER")

///////////////////////////////////////////////////////////////////////////////
// PUBLIC
///////////////////////////////////////////////////////////////////////////////

CBuffer::CBuffer()	    // constructor
{
    hMapFile = NULL;	    // handle to map
    lpMapAddress = NULL;    // mapped file base address
    dwMapSize = 0;	    // size of mapped file area
    lpMapMem = NULL;	    // available space
    dwMapUsed = 0;	    // bytes in use
}

CBuffer::~CBuffer() {};	    // destructor

///////////////////////////////////////////////////////////////////////////////

BUFFER_RESULT CBuffer::Reset (void)
{
    lpMapMem = (LPBYTE)lpMapAddress;
    dwMapUsed = 0;

    return 0;
}


///////////////////////////////////////////////////////////////////////////////

BUFFER_RESULT CBuffer::Allocate (LPVOID *ppBuf, DWORD dwSize)
{
    if ((dwMapUsed + dwSize) > dwMapSize)
	return BUFFER_RESULT_NOMEM;

    *ppBuf = lpMapMem;
    lpMapMem += dwSize;
    dwMapUsed += dwSize;

    return 0;
}

///////////////////////////////////////////////////////////////////////////////

BUFFER_RESULT CBuffer::Free (LPVOID lpBuf)
{
    return WNVERR_WNVIRQ_BUFFER_RESULT_NOTIMPLEMENTED;
}

///////////////////////////////////////////////////////////////////////////////
// called by driver enable

BUFFER_RESULT CBuffer::Enable (void)
{
    return 0;
}

///////////////////////////////////////////////////////////////////////////////
// called by driver disable
BUFFER_RESULT CBuffer::Disable (void)
{
    return 0;
}
	
///////////////////////////////////////////////////////////////////////////////
// close an open queue

BUFFER_RESULT CBuffer::Close (void)
{
    if (pSecurity)
    {
	pSecurity->Close ();
	delete pSecurity;
	pSecurity = NULL;
    }

    if (lpMapAddress)
    {
	if (!UnmapViewOfFile(lpMapAddress))
	{
	    DWORD dw = GetLastError ();
	    LogEvent (dw, L"\n********** CBuffer::Close: UnmapViewOfFile failed.");
	    return dw;
	}
	lpMapAddress = NULL;
    }
    if (hMapFile)
    {
	CloseHandle (hMapFile);
	hMapFile = NULL;
    }

    return 0;
}

///////////////////////////////////////////////////////////////////////////////
// open buffer

BUFFER_RESULT CBuffer::Open (PTCHAR szName, DWORD dwSize)
{
    TCHAR szFile [128] = {BASE_NAME};
    DWORD dwResult;

    if (hMapFile)
    {
	LogEvent (WNVERR_WNVIRQ_BUFFER_RESULT_MAPEXISTS, L"\n********** CBuffer::Open: hMapFile already open.");
	SetLastError (WNVERR_WNVIRQ_BUFFER_RESULT_MAPEXISTS);
	return WNVERR_WNVIRQ_BUFFER_RESULT_MAPEXISTS;
    }

    pSecurity = new CSecurity;
    dwResult = pSecurity->Open ();
    if (dwResult)
    {
	LogEvent (dwResult, L"\n********** CBuffer::Open: CSecurity::Open failed.");
	delete pSecurity;
	pSecurity = NULL;
	Close ();
	return dwResult;
    }

    dwMapSize = dwSize;
    _tcscat (szFile, szName);

    hMapFile = CreateFileMapping (
        (HANDLE)0xffffffff,		    // Current file handle (not a file)
        pSecurity->GetSecurityAttributes (),// Security attributes
        PAGE_READWRITE,			    // Read/write permission. 
        0,				    // Max. object size. 
        dwSize,				    // Size of hFile. 
        szFile);			    // Name of mapping object. 
    if (!hMapFile)
    {
	DWORD dw = GetLastError ();
	LogEvent (dw, L"\n********** CBuffer::Open: CreateFileMapping failed.");
	Close ();
	return dw;
    }

    // map a view of the file
    lpMapAddress = MapViewOfFile (
	hMapFile,			    // Handle to mapping object.  
	FILE_MAP_ALL_ACCESS,		    // Read/write permission 
	0,				    // Offset hi of mapping start in file
	0,	                            // Offset low of mapping start in file
	0);				    // Map entire file. 
     if (!lpMapAddress)
    {
	DWORD dw = GetLastError ();
	LogEvent (dw, L"\n********** CBuffer::Open: MapViewOfFile failed");
	Close ();
	return dw;
    }

    Reset ();

    return 0;	// pass
}

