#ifndef _COMMON_GLOBALDATA_HPP_
#define _COMMON_GLOBALDATA_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_TYPES_HPP_
#include <common/types.hpp>
#endif
#ifndef _COMMON_EXCEPTION_HPP_
#include <common/except.hpp>
#endif

template <class T>
class GlobalData
{
public:
	GlobalData(void);
  GlobalData(const GlobalData<T> &someGlobalData);
	GlobalData(DWORD sizeData,UINT globalFlags=GMEM_FIXED);
	virtual ~GlobalData();
	DWORD size(void)const;
	WORD size(DWORD sizeData,UINT globalFlags=GMEM_FIXED);
	UINT globalFlags(void)const;
	void globalFlags(UINT globalFlags);
  T &operator[](DWORD itemIndex);
	WORD operator==(const GlobalData<T> &someGlobalData)const;
	GlobalData<T> &operator=(const GlobalData<T> &someGlobalData);
	bool setZero(void);
	HANDLE getHandle(void)const;
	WORD isOkay(void)const;
private:
	void destroyGlobalData(void);
	WORD createGlobalData(void);
	T HUGE *mlpGlobalData;
  HGLOBAL mhGlobalData;
	UINT mGlobalFlags;
	DWORD mSizeData;
};

template <class T>
inline
GlobalData<T>::GlobalData(void)
: mlpGlobalData(0), mGlobalFlags(GMEM_FIXED), mSizeData(0), mhGlobalData(0)
{
}

template <class T>
inline
GlobalData<T>::GlobalData(const GlobalData<T> &someGlobalData)
: mlpGlobalData(0), mGlobalFlags(GMEM_FIXED), mSizeData(0), mhGlobalData(0)
{
  *this=someGlobalData;
}

template <class T>
inline
GlobalData<T>::GlobalData(DWORD sizeData,UINT globalFlags)
: mlpGlobalData(0), mGlobalFlags(globalFlags), mSizeData(sizeData), mhGlobalData(0)
{
  createGlobalData();
}

template <class T>
inline
GlobalData<T>::~GlobalData()
{
	destroyGlobalData();
}

template <class T>
inline
DWORD GlobalData<T>::size(void)const
{
	return mSizeData;
}

template <class T>
inline
WORD GlobalData<T>::size(DWORD sizeData,UINT globalFlags)
{
  mGlobalFlags=globalFlags;
	mSizeData=sizeData;
	if(createGlobalData())return TRUE;
	mSizeData=0;
	mGlobalFlags=GMEM_FIXED;
	return FALSE;
}

template <class T>
inline
UINT GlobalData<T>::globalFlags(void)const
{
	return mGlobalFlags;
}

template <class T>
inline
void GlobalData<T>::globalFlags(UINT globalFlags)
{
	mGlobalFlags=globalFlags;
}

template <class T>
inline
T &GlobalData<T>::operator[](DWORD itemIndex)
{
	if(itemIndex>=mSizeData)throw(BoundaryError());
	return *(mlpGlobalData+itemIndex);
}

template <class T>
inline
WORD GlobalData<T>::createGlobalData(void)
{
	destroyGlobalData();
	if(!mSizeData)return FALSE;
	mhGlobalData=::GlobalAlloc(mGlobalFlags,mSizeData*sizeof(T));
  if(!mhGlobalData)return FALSE;
	mlpGlobalData=(T HUGE*)::GlobalLock(mhGlobalData);
  return TRUE;
}

template <class T>
inline
void GlobalData<T>::destroyGlobalData(void)
{
  if(!mlpGlobalData)return;
	::GlobalUnlock(mhGlobalData);
	::GlobalFree(mhGlobalData);
	mhGlobalData=0;
	mlpGlobalData=0;
}

template <class T>
inline
HANDLE GlobalData<T>::getHandle(void)const
{
  return ::GlobalHandle(mlpGlobalData);
}

template <class T>
inline
WORD GlobalData<T>::isOkay(void)const
{
	return (mlpGlobalData?TRUE:FALSE);
}
#if defined(_MSC_VER)
#include <common/gdata.tpp>
#endif
#endif

