/*
**	Command & Conquer Renegade(tm)
**	Copyright 2025 Electronic Arts Inc.
**
**	This program is free software: you can redistribute it and/or modify
**	it under the terms of the GNU General Public License as published by
**	the Free Software Foundation, either version 3 of the License, or
**	(at your option) any later version.
**
**	This program is distributed in the hope that it will be useful,
**	but WITHOUT ANY WARRANTY; without even the implied warranty of
**	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**	GNU General Public License for more details.
**
**	You should have received a copy of the GNU General Public License
**	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/***********************************************************************************************
 ***                            Confidential - Westwood Studios                              ***
 ***********************************************************************************************
 *                                                                                             *
 *                 Project Name : Commando                                                     *
 *                                                                                             *
 *                     $Archive:: /Commando/Code/Commando/datasafe.h                          $*
 *                                                                                             *
 *                      $Author:: Steve_t                                                     $*
 *                                                                                             *
 *                     $Modtime:: 1/31/02 12:13p                                              $*
 *                                                                                             *
 *                    $Revision:: 20                                                          $*
 *                                                                                             *
 *---------------------------------------------------------------------------------------------*
 * Functions:                                                                                  *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#ifndef _DATASAFE_H
#define _DATASAFE_H

/*
** Adapted from original code by Jeff Brown
**
**   //=============================================================================
**   // DataSafe.h
**   // Public header file for the datasafe
**   // Author: Jeff Brown
**   // Date: Apr 16, 1999
**   //=============================================================================
**
**
**
**
** Class Overview. ST - 7/11/2001 8:19PM
**
**	DataSafeHandleClass.
**		Used to manage handles to items stored in the data safe.
**
**	DataSafeEntryClass and DataSafeEntryDataClass<T>.
**		Represent a single item as stored in the data safe. DataSafeEntryClass has the header
** 		information used to retrieve the item from the safe and the derived DataSafeEntryDataClass
**		also includes the actual type specific data payload.
**
**	DataSafeEntryListClass
**		This is a manager class for a linked list of DataSafeEntryDataClass<T>'s. Only the same
**		type of DataSafeEntryDataClass<T> classes can currently be linked together and exist in
**		the same list.
**
**	DataSafeEntryTypeClass
**		Every object put into the data safe is allocated a type ID so that like types (with the
**		same ID) can be identified for linking and swapping purposes. DataSafeEntryTypeClass is
**		a covenient holder for type information.
**
**	GenericDataSafeClass and DataSafeClass<T>
**     The safe itself consists of one static GenericDataSafeClass and many DataSafeClass<T>'s -
**		one DataSafeClass<T> for every type of data we want to store in the data safe.
**		Also included is an array of DataSafeEntryListClass's that act as pointers to the data safe
**		entries.
**
**
**	SafeDataClass
**		This is a convenience class used to automate insertion and removal of items and provide
**		a set of operators for common types. Using this class, adding existing data to the data safe
**		can be as simple as just changing how it's declared. e.g.
**
**		int SomeData;
**
**			becomes
**
**		SafeDataClass<int> SomeData;
**
**			There are also some macros provided to make declaration easier so you could also just say
**
**		safe_int SomeData;
**
** 		Currently, only a subset of operators are defined but more can easily be added as needed.
** 		Some changes to code will be required where operators are not available. For example
**
** 		SomeData += 10;
**
** 			would be a problem because the += operator is not defined. However the 'int' operator, the
**			= operator and the conversion operator () are defined so you could change the code to read
**
** 		SomeData = (int)SomeData + 10;
**
** 			or
**
** 		SomeData = SomeData() + 10;
**
**		You can pretty much throw anything into the data safe using this class to automate isertion
**		and retrieval. Some examples.
**
**		safe_float		HideyFloat;
**     safe_double		CantFindMe[256];
**		SafeDataClass<SomeNamedClass> ASafeClass;
**		SafeDataClass<SomeOtherType> ASafeType;
**
**		For types without existing macros, you will have to declare a new DataSafeClass<T> once for
**		each type in DataSafe.cpp using the DECLARE_DATA_SAFE macro. So in the above example, you
**		would have to add the following lines in DataSafe.cpp to allow storage of the new types
**
**		DECLARE_DATA_SAFE(SomeNamedClass);
**		DECLARE_DATA_SAFE(SomeOtherType);
**
**
**
**
**	Known external dependencies.
**		DynamicVectorClass
**		TICKS_PER_SECOND = 1000
**		FreeRandom - Renegade random number generator.
**		WWDEBUG_SAY - Equivalent to DebugString in C&C. Just a formatted debug output.
**
*/

/*
** Includes.
*/
#ifndef 	_ALWAYS_H
#include "always.h"
#include <assert.h>
#include <malloc.h>
#include <memory.h>
#include <windows.h>
#endif	//_ALWAYS_H

#ifndef 	_TIMEMGR_H
#include	"timemgr.h"
#endif	//_TIMEMGR_H

#ifndef	_WWDEBUG_H
#include "wwdebug.h"
#endif	//_WWDEBUG_H

//#ifndef	MMSYS_H
//#include "mmsys.h"
//#endif	//MMSYS_H
#include "systimer.h"

/*
** Use Renegade assert.
*/
#ifdef WWASSERT
#define ds_assert WWASSERT
#else	//WWASSERT
#define ds_assert assert
#endif	//WWASSERT


/*
** TEMP. Profile builds don't have asserts.
*/
#ifndef DEBUG
#undef ds_assert
#define ds_assert(x)
#pragma warning(disable : 4189)
#endif //DEBUG

#ifndef WWDEBUG
#pragma warning(disable : 4101)
#endif


/*
** Enable this define to make the datasafe thread safe (there is a performance penalty).
*/
//#define THREAD_SAFE_DATA_SAFE

/*
** Number of linked lists we can create for data safe items. Only like sized items can be stored in the same list.
*/
#define MAX_DATASAFE_LISTS	8192

/*
** The maximum number of different data types that can be stored in the data safe. This should normally fit into a byte for
** handle encoding reasons.
*/
#define MAX_DATASAFE_TYPES 128

/*
** Max number of entries in a single list before we have to create a second list for items of the same size. The smaller this
** value, the quicker we will be able to retrieve data from the safe. The larger we make it, the more secure the data safe will
** be.
*/
#define MAX_ENTRIES_PER_LIST	16

/*
** How often the data safe entries get shuffled around and re-keyed. This is the delay between each shuffle.
*/
#define SHUFFLE_TIME (TICKS_PER_SECOND * 7)

/*
** The delay between each integrity check on the data safe. This is a slow operation.
*/
#define SECURITY_CHECK_TIME (TICKS_PER_SECOND * 15)

/*
** The number of copies of objects of any one type that can exist in an unencrypted state. These copies are only used as return
** values and changes to the copies can never be propagated back into the safe.
*/
#define MAX_OBJECT_COPIES 8

/*
** Sentinel values. Used to see if someone just zeroes the whole safe or tampered with the get function.
*/
#define SENTINEL_ONE 0x29874362
#define SENTINEL_TWO 0x0bad0bad

#define DATASAFE_TIME_CHECK_CALLS	100000

/*
** Defines to allow convenient use of built-in types inside the data safe.
**
*/
#ifdef PARAM_EDITING_ON

#define safe_int int
#define safe_unsigned_int unsigned int

#define safe_long long
#define safe_unsigned_long unsigned long

#define safe_float float

#define safe_double double

#else //PARAM_EDITING_ON

#define safe_int SafeDataClass<int>
#define safe_unsigned_int SafeDataClass<unsigned int>

#define safe_long SafeDataClass<int>
#define safe_unsigned_long SafeDataClass<unsigned int>

#define safe_float SafeDataClass<float>

#define safe_double SafeDataClass<double>

#endif	//PARAM_EDITING_ON


/*
** Make sure we pulled in the right timer defines.
*/
#if TICKS_PER_SECOND != 1000
#error Code assumes TICKS_PER_SECOND == 1000
#endif


/*
** We want to inline functions within inline functions to make the code harder to hack by having multiple copies of it.
*/
#pragma inline_recursion(on)
#pragma inline_depth(4)
#pragma warning(disable : 4714)

/*
** Data safe handle.
**
** This consists of a linked list number, an entry identifier and a type.
**
** The whole shooting match can just be treated like an int.
**
*/
class DataSafeHandleClass
{
	public:

		/*
		** Consturctor.
		*/
		DataSafeHandleClass(int val = 0) {
			Handle.Whole.WholeHandle = val;
		};

		/*
		** Validity check.
		*/
		bool Is_Valid(void) const {
			return(Handle.Whole.WholeHandle != -1);
		};

		/*
		** Convenience functions and operators to handle setting or getting a handle using an int.
		*/
		inline int operator = (const int &val) {
			Handle.Whole.WholeHandle = val;
			return(val);
		};

		inline operator int (void) {
			return(Handle.Whole.WholeHandle);
		}

		inline operator int (void) const {
			return(Handle.Whole.WholeHandle);
		}

		inline int &operator () (void) {
			return(Handle.Whole.WholeHandle);
		}

		/*
		** Handle data.
		*/
		union tHandle {
			struct {
				/*
				** All the handle components conveniently together in an int.
				*/
				int WholeHandle;
			} Whole;

			struct {

				/*
				** ID is basically the index of the item in the linked list. It's a little more complex
				** than that since an ID can be re-used after the original user is removed from the
				** list but the whole list is searched for a matching ID when retrieving anyway.
				*/
				unsigned char ID;

				/*
				** The type of object this handle represents.
				*/
				unsigned char Type;

				/*
				** The list number where we can find this object.
				*/
				unsigned short List;
			} Part;

		} Handle;
};

/*
** Known packing is required here otherwise the default alignment is the same as the largest member
** of the structure. When combined with an expansion of DataSafeEntryDataClass<T> for doubles, the
** packing alignment becomes 8 (the size of a double) thus the offset of Data is not always as expected.
** i.e. you can no longer use sizeof(DataSafeEntryClass) to get the offset of the Data member of
** the derived class. This also prevents bloating (due to the bool member) when using large expansions
** for 'T'
*/
#pragma pack(push)
#pragma pack(4)

/*
**
** This class represents an internal data safe entry minus the actual data. In practice, this class will never be used
** except to refer to a DataSafeEntryDataClass<T> which actually contains the type specific data.
**
*/
class DataSafeEntryClass
{

	public:

		/*
		** Identifying handle.
		*/
		DataSafeHandleClass Handle;

		/*
		** Linked list next and prev.
		**
		** Note: These can point to a DataSafeEntryDataClass expanded for any type.
		*/
		DataSafeEntryClass *Next;
		DataSafeEntryClass *Prev;

		/*
		** Size of data.
		*/
		unsigned long Size;

		/*
		** Is this a slop (fake, to allow swapping with only 1 real entry) entry?
		*/
		bool IsSlop;
};


/*
** This is a complete internal data safe entry including the header and the encrypted data.
**
*/
template<class T>
class DataSafeEntryDataClass : public DataSafeEntryClass
{
	public:
		T Data;
};

#pragma pack(pop)



/*
** This class represents a single data safe entry list. There can be mutiple lists in a data safe but all entries in a single
** list must be of the same type.
*/
class DataSafeEntryListClass
{
	public:

		/*
		** Constructor.
		*/
		DataSafeEntryListClass(void) {
			SafeList = NULL;
			EntryCount = 0;
			EntryType = -1;
			SlopCount = 0;
			memset(HandleIDUsage, 0, sizeof(HandleIDUsage));
		};

		/*
		** Pointer to the head of the list.
		*/
		DataSafeEntryClass *SafeList;

		/*
		** Number of entries in the list.
		*/
		int EntryCount;

		/*
		** Type of entry in this list.
		*/
		int EntryType;

		/*
		** Number of slop entries in this list.
		*/
		int SlopCount;

		/*
		** Handle IDs used in this list.
		*/
		char HandleIDUsage[MAX_ENTRIES_PER_LIST];
};


/*
**
** This class describes a type of entry in the data safe. It's important to keep track of the types of objects we add since
** only similar types can be swapped in memory. This class is just a convenient container to help us match type codes with
** unique IDs.
**
**
*/
class DataSafeEntryTypeClass
{
	public:

		DataSafeEntryTypeClass(void) {
			TypeCode = 0;
			ID = -1;
			Size = 0;
		};


		/*
		** A unique number used to match and assign type IDs. This can come from anywhere as long as it's different for every type.
		*/
		unsigned long TypeCode;

		/*
		** This is the user friendly ID that is stored along with entries in the data safe and returned in the handle that's
		** given out when something is added to the safe.
		** It's also the index into the type list.
		*/
		int ID;

		/*
		** The size of this type of object. Must be a multiple of 4 bytes for the data safe. (This is redundant now that we
		** have a type/size lookup table).
		*/
		int Size;
};







/*
**  GenericDataSafeClass
**
**		This class represents a single data safe. It can only function as the base class to one or more instances of
** 	DataSafeClass<T>.
**
**
** 	This class functions as a base class for all the templated 'DataSafeClass'es so that they can all share a single set of
**		static data. Normally, static data in a templated class is duplicated for each expansion of the class.
**
**    Even though there may be many instances and expansions of the derived DataSafeClass<T> there is only ever one global
**		data safe and that is represented by this class.
**
*/
class GenericDataSafeClass
{
	public:

		/*
		** Constructor.
		*/
		GenericDataSafeClass(void);

		/*
		** Query functions.
		*/
		static DataSafeEntryClass * Get_Entry(DataSafeHandleClass handle);
		static int Get_Entry_Type(DataSafeHandleClass handle);

		/*
		** System timer reset.
		*/
		static void Reset_Timers(void);

		/*
		** Thread safety. This is normally handled automatically but if you need to manually lock the safe for a period of time
		** to do a read/hold/write then this is the way to do it.
		*/
#ifdef THREAD_SAFE_DATA_SAFE
		static void Lock(void);
		static void Unlock(void);
#endif //THREAD_SAFE_DATA_SAFE

		/*
		** Stats, debug helpers.
		*/
		static void Dump_Safe_Stats(char *dump_buffer, int buffer_size);
		static void Print_Safe_Stats_To_Debug_Output(void);
		static void Reset(void);


#ifdef THREAD_SAFE_DATA_SAFE
		static void Set_Preferred_Thread(unsigned int){};
#else //THREAD_SAFE_DATA_SAFE
		static void Set_Preferred_Thread(unsigned int thread_id) {PreferredThread = thread_id;};
#endif //THREAD_SAFE_DATA_SAFE

	protected:

		/*
		** Cleanup.
		*/
		void Shutdown(void);

		/*
		** Query functions.
		*/
		static DataSafeEntryClass * Get_Entry_By_Index(int list, int index);

		/*
		** Security
		*/
		static void Shuffle(bool forced = false);
		static void Swap_Entries(DataSafeEntryClass *first, DataSafeEntryClass *second, int type);
		static void Encrypt(void *data, int size, unsigned long key = SimpleKey, bool do_checksum = true);
		static void Decrypt(void *data, int size, unsigned long key = SimpleKey, bool do_checksum = true);
		static void Mem_Copy_Encrypt(void *dest, void *src, int size, bool do_checksum);
		static void Mem_Copy_Decrypt(void *dest, void *src, int size, bool do_checksum);
		static __forceinline void Security_Check(void);
		static __forceinline void Security_Fault(void);
		static void Say_Security_Fault(void);

		/*
		** Insertion support.
		*/
		static int Get_Random_List_For_Insertion(int type);
		static void Random_Insertion(DataSafeEntryClass *entry, int list, int type, bool is_slop = false);
		static int Create_Safe_List(int type);
		static int Get_Handle_ID(int list);

		/*
		** Deletion support. Just used to make sure we are doing type safe deletion.
		*/
		static void Remove_From_List(int list, DataSafeEntryClass *entry_ptr);
		static void Free_Handle_ID(int list, int id);

		/*
		** Type identification.
		*/
		static inline int Get_Type_Size(int type);

#ifdef THREAD_SAFE_DATA_SAFE
		/*
		** Thread safety.
		*/
		class ThreadLockClass
		{
			public:
				/*
				** Constructor. Grabs the mutex.
				*/
				inline ThreadLockClass(void) {
					int deadlock = WaitForSingleObject(GenericDataSafeClass::SafeMutex, 10 * 1000);
					if (deadlock == WAIT_TIMEOUT) {
						WWDEBUG_SAY(("Data Safe: Timeout waiting for data safe mutex\n"));
						ds_assert(deadlock != WAIT_TIMEOUT);
					}
				};

				/*
				** Destructor, releases the mutex.
				*/
				inline ~ThreadLockClass(void) {
					ReleaseMutex(GenericDataSafeClass::SafeMutex);
				};
		};
#else //THREAD_SAFE_DATA_SAFE

		/*
		** If thread safety is not required, this class compiles out to nothing when used in release mode.
		*/
		class ThreadLockClass
		{
			public:
#ifdef WWDEBUG
				__forceinline ThreadLockClass(void) {
					if (GenericDataSafeClass::PreferredThread != GetCurrentThreadId()) {
						WWDEBUG_SAY(("DATASAFE.H - PreferredThread = %08X, GetCurrentThreadId() == %08X\n", GenericDataSafeClass::PreferredThread, GetCurrentThreadId()));
					}
					ds_assert(GenericDataSafeClass::PreferredThread == GetCurrentThreadId());
				};
#endif //WWDEBUG
		};

		static unsigned int PreferredThread;
#endif //THREAD_SAFE_DATA_SAFE

		friend ThreadLockClass;

		/*
		** Static data. We only need one each of these, regardless of how many DataSafeClass 'types' there are.
		**
		**
		**
		*/

		/*
		** Simple key value used for xoring.
		*/
		static unsigned long SimpleKey;

		/*
		** Key used for encrypting handles.
		*/
		static unsigned long HandleKey;

		/*
		** Number of valid entries in the Safe list.
		*/
		static int NumLists;

		/*
		** Array of pointers to data lists. We can't use a dynamic vector class here because the handles we give out include
		** an index into this array. Dynamic vector class moves entries around to remove gaps in the array which would leave
		** the handles pointing to the wrong element.
		*/
		static DataSafeEntryListClass *Safe[MAX_DATASAFE_LISTS];

		/*
		** Integrity check.
		*/
		static unsigned long Checksum;

		/*
		** Shuffle delay.
		*/
		static unsigned long ShuffleDelay;

		/*
		** Security check delay.
		*/
		static unsigned long SecurityCheckDelay;

		/*
		** List of types that are stored in the data safe.
		*/
		static DataSafeEntryTypeClass TypeList[MAX_DATASAFE_TYPES];
		static int TypeListCount;

		/*
		** Mutex to ensure thread safety.
		*/
#ifdef THREAD_SAFE_DATA_SAFE
		static HANDLE SafeMutex;
#endif //THREAD_SAFE_DATA_SAFE

		/*
		** Sentinels. Can't use 'SafeDataClass' as it's constructor adds data to the safe - i.e. us.
		*/
		static DataSafeHandleClass SentinelOne;
		static DataSafeHandleClass SentinelTwo;

		/*
		** Number of CRC errors so we can report it in the game results.
		*/
		static int CRCErrors;


		/*
		** Statistics - debug only.
		*/
#ifdef WWDEBUG
		static unsigned long LastDump;
		static int NumSwaps;
		static int NumFetches;
		static int SlopCount;
		static int NumSecurityChecks;
		static int NumShuffles;
#endif	//WWDEBUG

};



/*
**  DataSafeClass<T>
**
** 	This templated class is used to provide type specific functionality in the data safe. There must be at least one instance
**		of this class for each type of data we want to store in the safe. This, along with 'GenericDataSafeClass' represents
**		a single global data safe.
**
*/
template<class T>
class DataSafeClass : public GenericDataSafeClass
{

	public:
		DataSafeClass(T *bogus_ptr = NULL, int slopcount = 3);
		~DataSafeClass(void);

		/*
		** Query functions.
		*/
		static bool Get(DataSafeHandleClass handle, T* &item);
		static inline bool In_Return_List(T *ptr) {
			if (ptr) {
				void *temp = (void*)ptr;
				if (temp >= &ReturnList[0][0] && temp < &ReturnList[MAX_OBJECT_COPIES][0]) {
					if (((unsigned long) temp - (unsigned long)(&ReturnList[0][0])) % sizeof(T) == 0) {
						return(true);
					}
				}
			}
			return(false);

		};

		/*
		** Set functions.
		*/
		static bool Set(DataSafeHandleClass handle, T *data);

		/*
		** Add functions.
		*/
		static DataSafeHandleClass Add_Entry(T &value, bool is_slop = false);

		/*
		** Removal functions.
		*/
		static void Delete_Entry(DataSafeHandleClass handle);


	private:

		/*
		** Type identification.
		*/
		static int Get_Type_ID(unsigned long type_code, int size);
		static unsigned long Get_Type_Code(void);

		/*
		** Type of this DataSafe.
		*/
		static int Type;

		/*
		** Min slop entries for this type of safe.
		*/
		static int MinSlop;

		/*
		** Copies of items in the data safe. Only used to return copies of items in the safe.
		**
		** The number of elements in this list is the number of times you can call the 'Get' function before you start to
		** invalidate the data you got 'n' calls ago. For this reason, you should always make a copy of data retrieved from
		** the safe if you plan to use it more than once.
		*/
		static char ReturnList[MAX_OBJECT_COPIES][sizeof(T)];
		static int ReturnIndex;
};




/*
**
**  Macros to help in declaring data safe types.
**
**
**
*/
#define DECLARE_DATA_SAFE(type) 																\
	DataSafeClass<type> DataSafe##type;														\
	int DataSafeClass<type>::Type;															\
	char DataSafeClass<type>::ReturnList[MAX_OBJECT_COPIES][sizeof(type)];		\
	int DataSafeClass<type>::ReturnIndex;													\
	int DataSafeClass<type>::MinSlop;





/*
**
** SafeDataClass.
**
** This class is for convenience when using the data safe. Just expand this class for the type you want to add to the data safe
** and it will keep track of the handle and automate the adding in, and removal of, data in the safe.
**
*/
extern char ErrorVal[1024];
template<class T>
class SafeDataClass
{

	public:

		/*
		** Constructor, destructor.
		*/
		SafeDataClass(void);
		SafeDataClass(T data);
		~SafeDataClass(void);

		/*
		** Copy constructor. This is a bad thing to call.
		*/
		SafeDataClass(SafeDataClass &) {
			ds_assert(false);
		};

		/*
		** Helper functions for data safe class storage.
		*/
		inline T* Get_Ptr(void) const;
		inline bool Commit(T* data_ptr) const;

		/*
		** Operators.
		*/
		inline T &operator () (void) const;

		inline T &operator = (T const &data);
		inline T &operator = (SafeDataClass<T> &safedata);

		inline operator int(void) const;
		inline operator unsigned int(void) const;
		inline operator long(void) const;
		inline operator unsigned long(void) const;
		inline operator float(void) const;
		inline operator double(void) const;

		inline bool operator == (T const &data);
		inline bool operator == (SafeDataClass<T> &safedata);

		inline bool operator != (T const &data);
		inline bool operator != (SafeDataClass<T> &safedata);

		inline bool operator > (T const &data);
		inline bool operator > (SafeDataClass<T> &safedata);

		inline bool operator >= (T const &data);
		inline bool operator >= (SafeDataClass<T> &safedata);

		inline bool operator < (T const &data);
		inline bool operator < (SafeDataClass<T> &safedata);

		inline bool operator <= (T const &data);
		inline bool operator <= (SafeDataClass<T> &safedata);

		inline T &operator + (T const &data);
		inline T &operator + (SafeDataClass<T> &safedata);

		inline T &operator += (T const &data);
		inline T &operator += (SafeDataClass<T> &safedata);

		inline T &operator - (T const &data);
		inline T &operator - (SafeDataClass<T> &safedata);

		inline T &operator -= (T const &data);
		inline T &operator -= (SafeDataClass<T> &safedata);

		inline T &operator * (T const &data);
		inline T &operator * (SafeDataClass<T> &safedata);

		inline T &operator *= (T const &data);
		inline T &operator *= (SafeDataClass<T> &safedata);

		inline T &operator / (T const &data);
		inline T &operator / (SafeDataClass<T> &safedata);

		inline T &operator /= (T const &data);
		inline T &operator /= (SafeDataClass<T> &safedata);

		inline T &operator ++ (void);
		inline T &operator -- (void);

		inline T &operator ++ (int);
		inline T &operator -- (int);

		/*
		** Query and set functions.
		*/
		DataSafeHandleClass Get_Handle(void) {return(Handle);};
		T Get(void);
		void Set(T);


	private:
		/*
		** This is the handle that represents this classes data in the datasafe.
		*/
		DataSafeHandleClass Handle;

#ifdef WWDEBUG
		T DebugData;
#endif //WWDEBUG


};












/***********************************************************************************************
**
**
**
** 		File separation.
**
**
*/











/*
** Simple functions, suitable for inline expansion.
**
**
**
**
*/


/*
**
**
**    GenericDataSafeClass functions.
**
**
*/

/***********************************************************************************************
 * GenericDataSafeClass::Get_Type_Size -- Get the size of this type                            *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Type ID of object                                                                 *
 *                                                                                             *
 * OUTPUT:   Size of object                                                                    *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   6/27/2001 12:47PM ST : Created                                                            *
 *=============================================================================================*/
inline int GenericDataSafeClass::Get_Type_Size(int type)
{
	ds_assert(type >= 0);
	ds_assert(type < MAX_DATASAFE_TYPES);
	ds_assert(type < TypeListCount);
	return(TypeList[type].Size);
}





/***********************************************************************************************
 * GenericDataSafeClass::Security_Fault -- Security fault handler                              *
 *                                                                                             *
 *   __forceinline used to make sure there are multiple copies of this code. It's bloaty       *
 *   but it makes it harder to hack out (but only a little bit)                                *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/9/2001 2:20PM ST : Created                                                              *
 *=============================================================================================*/
__forceinline void GenericDataSafeClass::Security_Fault(void)
{
	WWDEBUG_SAY(("Data Safe:Security fault\n"));
	CRCErrors++;

	Say_Security_Fault();
	ds_assert(false);
}


/***********************************************************************************************
 * GenericDataSafeClass::Security_Check -- Look for security problems.                         *
 *                                                                                             *
 *   __forceinline used to make sure there are multiple copies of this code. It's bloaty       *
 *   but it makes it harder to hack out (but only a little bit)                                *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS:                                                                                   *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/9/2001 1:08PM ST : Created                                                              *
 *=============================================================================================*/
__forceinline void GenericDataSafeClass::Security_Check(void)
{
	ThreadLockClass locker;

	/*
	** Flag to prevent recursion.
	*/
	static bool _checking = false;

	/*
	** Only check the time every n calls.
	*/
	static unsigned long _calls = 0;
	_calls++;
	if (_calls < DATASAFE_TIME_CHECK_CALLS) {
		return;
	}
	_calls = 0;

	/*
	** See if SimpleKey has been zeroed out.
	*/
	if (HandleKey - SimpleKey == HandleKey) {
		WWDEBUG_SAY(("Data Safe: Simple Key compromised!\n"));
		Security_Fault();
	}

	/*
	** See if HandleKey has been zeroed out.
	*/
	if (SimpleKey - HandleKey == SimpleKey) {
		WWDEBUG_SAY(("Data Safe: Handle Key compromised!\n"));
		Security_Fault();
	}

	/*
	** Use the checksum to verify the whole data safe.
	** Yes, the whole safe. A teeny bit slow maybe.
	**
	** Since we are going through the whole safe here, we might as well make a note of where slop
	** needs to be added or removed and count how many total slop entries we have.
	*/
	unsigned long time = TIMEGETTIME();
	if (time < SecurityCheckDelay || (time | SecurityCheckDelay) == 0 || (time - SecurityCheckDelay) > SECURITY_CHECK_TIME) {

#ifdef WWDEBUG
		SlopCount = 0;
		NumSecurityChecks++;
#endif	//WWDEBUG

		/*
		** If toooo much time has gone by then do it anyway.
		*/
		if (!_checking) {	// || (time - SecurityCheckDelay) > SECURITY_CHECK_TIME * 5) {

			_checking = true;
			//WWDEBUG_SAY(("Data Safe: Performing security check\n"));
			SecurityCheckDelay = time;
			unsigned long checkey = ~SimpleKey;

			/*
			** Loop through every list.
			*/
			for (int i=0 ; i<NumLists ; i++) {
				ds_assert(Safe[i] != NULL);
				if (Safe[i] != NULL && Safe[i]->EntryCount > 0) {

					/*
					** Dereference stuff - make sure the list makes sense.
					*/
					DataSafeEntryClass *entry_ptr = Safe[i]->SafeList;
					unsigned long *data = NULL;
					ds_assert(entry_ptr != NULL);
					int data_size = entry_ptr->Size;
					ds_assert((data_size & 3) == 0);
					data_size = data_size >> 2;

					if (entry_ptr) {

						/*
						** Go through each entry in the list.
						*/
						for (int j=0 ; j<Safe[i]->EntryCount ; j++) {
#ifdef WWDEBUG
							/*
							** Count slop entries for debug purposes.
							*/
							if (entry_ptr->IsSlop) {
								SlopCount++;
							}
#endif	//WWDEBUG
							/*
							** Add in the handle.
							*/
							checkey ^= entry_ptr->Handle;

							/*
							** Add in the data.
							*/
							data = (unsigned long *) (((char*)entry_ptr) + sizeof(*entry_ptr));
							for (int z=0 ; z<data_size ; z++) {
								checkey ^= *data++;
							}

							/*
							** Next entry.
							*/
							entry_ptr = entry_ptr->Next;
						}
					}
				}
			}

			if (checkey != Checksum) {
				WWDEBUG_SAY(("Data Safe: Incorrect checksum!\n"));
				Security_Fault();
			}

			/*
			** Check the values of the sentinels.
			*/
			if (NumLists) {
				int *val = NULL;
				if ((int)SentinelOne != 0) {
					bool got = DataSafeClass<int>::Get(SentinelOne, val);
					if (!got || val == NULL || *val != SENTINEL_ONE) {
						WWDEBUG_SAY(("Data Safe: Incorrect sentinel value!\n"));
						Security_Fault();
					}
				}
				val = NULL;
				if ((int)SentinelTwo != 0) {
					bool got = DataSafeClass<int>::Get(SentinelTwo, val);
					if (!got || val == NULL || *val != SENTINEL_TWO) {
						WWDEBUG_SAY(("Data Safe: Incorrect sentinel value!\n"));
						Security_Fault();
					}
				}
			}
#ifdef	WWDEBUG
			Print_Safe_Stats_To_Debug_Output();
#endif	//WWDEBUG
			_checking = false;
		}
	}
}









/*
**
**
**    DataSafeClass functions.
**
**
*/


/***********************************************************************************************
 * DataSafeClass::DataSafeClass -- Class constructor                                           *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Bogus pointer. Pointer that isn't referenced. It's only used for type info        *
 *           Number of 'slop' entries to create                                                *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   6/25/2001 1:51PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
DataSafeClass<T>::DataSafeClass(T*, int slopcount)
{
	ThreadLockClass locker;

	/*
	** Clear out the return list.
	*/
	memset(ReturnList, 0, sizeof(ReturnList));
	ReturnIndex = 0;

	/*
	** Get the type info for 'T'. Different types get stored in different places in the safe. Only similar types can be in the
	** same safe list.
	*/
	int data_size = sizeof(T);
	int type_code = Get_Type_Code();

	/*
	** Get_Type_ID will return the Type ID for this type code (instruction pointer). It will create a new type if this one
	** doesn't already exist.
	*/
	int id = Get_Type_ID(type_code, data_size);
	Type = id;

	MinSlop = slopcount;

	/*
	** Add some slop entries here. These are just bogues entries than can be swapped in memory with real entries. The less
	** commonly added data types should be give more slop entries.
	*/
	for (int i=0 ; i<slopcount ; i++) {

		/*
		** We need to make sure the constructor gets called for this object type before it's added to the safe. But we must
		** also make sure that the destructor *isn't* called when we go out of scope here - it will be called explicitly
		** when the datasafe is destructed. By using _alloca, and doing an in-place new, the memory that the object sits in
		** will be freed when it goes out of scope but the destructor for 'T' won't be called.
		*/
		void *stackmem = _alloca(sizeof(T));
		T *slop_ptr = new (stackmem) T;
		Add_Entry(*slop_ptr, true);
	}
}




/***********************************************************************************************
 * DataSafeClass::~DataSafeClass -- Class destructor. Removes remaining slop entries.          *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/5/2001 11:38AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
DataSafeClass<T>::~DataSafeClass(void)
{
	ThreadLockClass locker;

	/*
	** Remove all slop enries of our type from all lists. Note that this will delete non-slop entries too if any remain at this
	** time.
	*/
	for (int i=0 ; i<NumLists ; i++) {
		ds_assert(Safe[i] != NULL);
		if (Safe[i] != NULL && Safe[i]->EntryType == Type && Safe[i]->EntryCount > 0) {

			while (Safe[i]->EntryCount > 0) {

				/*
				** Delete the first entry in the list.
				*/
				int entries = Safe[i]->EntryCount;
				DataSafeHandleClass handle = Safe[i]->SafeList->Handle ^ SimpleKey;
				handle = handle ^ HandleKey;
				Delete_Entry(handle);

				/*
				** Safety check. If something goes wrong and we didn't delete the entry then we will never get out of this loop
				** so check for that case.
				*/
				ds_assert(entries == Safe[i]->EntryCount+1);
				if (entries != Safe[i]->EntryCount+1) {
					break;
				}
			}
		}
	}
	Shutdown();
}





/***********************************************************************************************
 * DataSafeClass::Get_Type_Code -- Get a unique code per type without using RTTI               *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Type code                                                                         *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/2/2001 11:17AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
unsigned long DataSafeClass<T>::Get_Type_Code(void)
{
	/*
	** Make sure this function gets expanded multiple times for different types by referencing the type.
	*/
	volatile int data_size = sizeof(T);
	data_size = data_size;

	/*
	** Since we aren't using RTTI I need some other way of distinguishing types in the safe. Because it's templatised, this
	** code will get expanded once for each type it's used with. I will use the location in memory of the function to
	** uniquely identify each type. What a cunning plan.
	*/
	static unsigned long instruction_pointer;
	instruction_pointer = 0;
	__asm {
here:
		lea	eax,here
		mov	[instruction_pointer],eax
	};

	ds_assert(instruction_pointer != 0);

	return(instruction_pointer);
}





/***********************************************************************************************
 * DataSafeClass::Get_Type_ID -- Get the id for the given type and size                        *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Type identifier code                                                              *
 *           Size of type                                                                      *
 *                                                                                             *
 * OUTPUT:   Type ID                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   6/27/2001 12:44PM ST : Created                                                            *
 *=============================================================================================*/
template <class T>
int DataSafeClass<T>::Get_Type_ID(unsigned long type_code, int size)
{
	int id = 0;

	/*
	** See if we already have an ID for this type code.
	*/
	for (int i=0 ; i<TypeListCount ; i++) {
		if (TypeList[i].TypeCode == type_code) {
			ds_assert(TypeList[i].Size == size);
			return(TypeList[i].ID);
		}
	}

	/*
	** Create a new type entry.
	*/
	ds_assert(TypeListCount < MAX_DATASAFE_TYPES);
	if (TypeListCount < MAX_DATASAFE_TYPES) {
		ds_assert(TypeList[TypeListCount].TypeCode == 0);
		ds_assert(TypeList[TypeListCount].Size == 0);
		TypeList[TypeListCount].TypeCode = type_code;
		TypeList[TypeListCount].ID = TypeListCount;
		TypeList[TypeListCount].Size = size;
		id = TypeListCount++;
	}

	return(id);
}




/***********************************************************************************************
 * DataSafeClass::Add_Entry -- Create a new data safe entry and init it to the value provided  *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Value                                                                             *
 *                                                                                             *
 * OUTPUT:   Handle                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   6/19/2001 8:34PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
DataSafeHandleClass DataSafeClass<T>::Add_Entry(T &value, bool is_slop)
{
	ThreadLockClass locker;
	Security_Check();

	/*
	** Allocate memory for the new entry.
	*/
	DataSafeEntryClass *entry_ptr = (DataSafeEntryClass*) new char [sizeof(DataSafeEntryDataClass<T>)];
	ds_assert(entry_ptr);

	if (entry_ptr) {

		/*
		** Init the data safe entry to reasonable values.
		*/
		entry_ptr->Next = NULL;
		entry_ptr->Prev = NULL;
		entry_ptr->Size = sizeof(value);
		entry_ptr->IsSlop = is_slop;

		/*
		** Copy the data to the safe entry.
		*/
		DataSafeEntryDataClass<T>* data_ptr = (DataSafeEntryDataClass<T>*)  entry_ptr;
		Mem_Copy_Encrypt(& data_ptr->Data, &value, sizeof(value), true);

		/*
		** Find out which list we will be adding the entry to.
		*/
		int list = Get_Random_List_For_Insertion(Type);
		ds_assert(list >= 0 && list < MAX_DATASAFE_LISTS);
		ds_assert(Safe[list] != NULL);

		if (list != -1 && Safe[list] != NULL) {

			/*
			** Now we know the list, we can get the next index id for that list and build a handle for the entry.
			*/
			int index = Get_Handle_ID(list);
			ds_assert(index >= 0 && index < MAX_ENTRIES_PER_LIST);
			DataSafeHandleClass handle;
			handle.Handle.Part.List = list;
			handle.Handle.Part.ID = index;
			handle.Handle.Part.Type = Type;

			/*
			** We have a handle. Better encrypt it.
			*/
			DataSafeHandleClass encrypted_handle = handle ^ SimpleKey;
			Checksum = Checksum ^ encrypted_handle;

			/*
			** Store it in the entry so we can do a search and match to get this entry out again.
			*/
			entry_ptr->Handle = encrypted_handle;

			/*
			** Insert the entry into the chosen list.
			*/
			Random_Insertion(entry_ptr, list, Type, is_slop);

			/*
			** Maybe add slop here if there is only one entry in the list.
			** It will get removed later as more entries are added.
			*/
			if (Safe[list]->EntryCount == 1 && !is_slop) {
				for (int i=0 ; i<MinSlop ; i++) {
					entry_ptr = (DataSafeEntryClass*) new char [sizeof(DataSafeEntryDataClass<T>)];
					ds_assert(entry_ptr);

					if (entry_ptr) {
						entry_ptr->Next = NULL;
						entry_ptr->Prev = NULL;
						entry_ptr->Size = sizeof(T);
						entry_ptr->IsSlop = true;

						/*
						** Encrypt the garbage data in the uninitialized memory we just allocated for the
						** object. It has to be encrypted to keep the CRC right.
						*/
						Encrypt(&((DataSafeEntryDataClass<T>*)entry_ptr)->Data, sizeof(T), SimpleKey, true);

						/*
						** Get a handle ID. Not really needed since we won't be returning a handle but it
						** keeps the ID usage list neat. Fill in the rest of the handle to make it valid.
						*/
						DataSafeHandleClass slop_handle;
						slop_handle.Handle.Part.ID = Get_Handle_ID(list);
						slop_handle.Handle.Part.List = list;
						slop_handle.Handle.Part.Type = Type;
						DataSafeHandleClass encrypted_slop_handle = slop_handle ^ SimpleKey;
						Checksum = Checksum ^ encrypted_slop_handle;
						entry_ptr->Handle = encrypted_slop_handle;

						/*
						** Insert the slop entry.
						*/
						Random_Insertion(entry_ptr, list, Type, true);
					}
				}
				ds_assert(Safe[list]->SlopCount == MinSlop);
				ds_assert(Safe[list]->EntryCount == MinSlop + 1);
			}

			/*
			** Maybe remove some slop if the list is filling up.
			*/
			if (Safe[list]->SlopCount != 0 && Safe[list]->EntryCount > Safe[list]->SlopCount * 2 && !is_slop) {

				/*
				** Lots of entries here. Remove all slop by building a list of slop entries then
				** removing them one by one.
				*/
				entry_ptr = Safe[list]->SafeList;
				ds_assert(entry_ptr != NULL);
				DataSafeHandleClass removal_list[MAX_ENTRIES_PER_LIST];
				int removal_count = 0;

				if (entry_ptr) {

					/*
					** Go through each entry in the list.
					*/
					for (int j=0 ; j<Safe[list]->EntryCount ; j++) {

						/*
						** If this is a slop entry then mark it for removal.
						*/
						if (entry_ptr->IsSlop) {
							DataSafeHandleClass decode_handle = entry_ptr->Handle ^ SimpleKey;
							decode_handle = decode_handle ^ HandleKey;
							removal_list[removal_count++] = decode_handle;
						}

						/*
						** Next entry.
						*/
						entry_ptr = entry_ptr->Next;
					}
				}

				/*
				** Remove all marked entries. Delete_Entry will fix up the lists slop count.
				*/
				for (int j=0 ; j<removal_count ; j++) {
					Delete_Entry(removal_list[j]);
				}
				ds_assert(Safe[list]->SlopCount == 0);
			}

			/*
			** Return the handle, encrypted using the handle key.
			*/
			handle.Handle.Whole.WholeHandle ^= HandleKey;
			return(handle);
		}
	}

	/*
	** Allocation error.
	*/
	return((DataSafeHandleClass)-1);

}




/***********************************************************************************************
 * DataSafeClass::Delete_Entry -- Delete an entry from the data safe                           *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Handle to entry                                                                   *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   6/25/2001 1:32PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
void DataSafeClass<T>::Delete_Entry(DataSafeHandleClass handle)
{
	/*
	** Locals.
	*/
	ThreadLockClass locker;
	int list;
	int id;

	/*
	** Asserts.
	*/
	ds_assert(handle.Is_Valid());

	/*
	** Check safe integrity.
	*/
	Security_Check();

	/*
	** The handles we give out are encrypted so we need to decrypt temporarily to extract the list number.
	*/
	DataSafeHandleClass new_handle = handle ^ HandleKey;
	list = new_handle.Handle.Part.List;
	id = new_handle.Handle.Part.ID;

	/*
	** Check that list number.
	*/
	ds_assert(list >= 0);
	ds_assert(list < NumLists);
	ds_assert(Safe[list] != NULL);

	/*
	** Get a pointer to the actual entry in the safe list.
	*/
	DataSafeEntryClass *entry_ptr = Get_Entry(handle);
	ds_assert(entry_ptr != NULL);

	if (entry_ptr != NULL) {

		/*
		** Apply the current data key to the handle to fix up the checksum.
		*/
		DataSafeHandleClass match_handle = new_handle ^ SimpleKey;
		Checksum ^= match_handle;

		/*
		** We found the entry for this handle. We need to fix up the list pointers and delete the memory.
		** Since we originally memcpy'ed this object into place we will have to call the destructor explicitly. The explicit
		** destructor call will have no effect if the object doesn't have a destructor defined.
		**
		** We need to decrypt the object in place before calling the desturctor otherwise it will have a hard time acting on
		** it's own data. This has the bonus of fixing up the checksum too.
		*/
		DataSafeEntryDataClass<T> *whole_entry_ptr = (DataSafeEntryDataClass<T>*) entry_ptr;
		Decrypt(&whole_entry_ptr->Data, Get_Type_Size(Safe[list]->EntryType), SimpleKey);
		if (!whole_entry_ptr->IsSlop) {
			whole_entry_ptr->Data.T::~T();
		}
		Remove_From_List(list, entry_ptr);
		Free_Handle_ID(list, id);
		delete [] (void*) entry_ptr;
		return;
	}

	/*
	** No match found.
	*/
	WWDEBUG_SAY(("Datasafe: No item found for handle %08x\n", (int)handle));
}




/***********************************************************************************************
 * DataSafeClass::Get -- Get a copy of an item in the data safe.                               *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Handle to data safe entry                                                         *
 *           (out) Pointer to copy of object                                                   *
 *                                                                                             *
 * OUTPUT:   True if object retrieved OK                                                       *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/2/2001 11:07AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
bool DataSafeClass<T>::Get(DataSafeHandleClass handle, T* &item)
{
	ThreadLockClass locker;

	/*
	** Get a pointer to the entry.
	*/
	DataSafeEntryClass *entry_ptr = Get_Entry(handle);

	if (entry_ptr == NULL) {
		return(false);
	}

	DataSafeEntryDataClass<T> *data_entry_ptr = (DataSafeEntryDataClass<T>*) entry_ptr;

	/*
	** Copy the object from the data safe and decrypt it in one pass. Don't adjust the checksum as the object is staying
	** the same in the safe.
	*/
	Mem_Copy_Decrypt(&ReturnList[ReturnIndex][0], &data_entry_ptr->Data, sizeof(T), false);

	/*
	** Return the object.
	*/
	item = (T*)(&ReturnList[ReturnIndex][0]);

	/*
	** Fix up the return list index.
	*/
	ReturnIndex++;
	if (ReturnIndex >= MAX_OBJECT_COPIES) {
		ReturnIndex = 0;
	}

	/*
	** Move stuff around.
	*/
	Shuffle();

	/*
	** Check safe integrity.
	*/
	Security_Check();

	return(true);
}




/***********************************************************************************************
 * DataSafeClass::Set -- Set the value of an entry in the data safe                            *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Handle to data in the safe                                                        *
 *           New value to set                                                                  *
 *                                                                                             *
 * OUTPUT:   True if handle was valid                                                          *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:11PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
bool DataSafeClass<T>::Set(DataSafeHandleClass handle, T *data)
{
	ThreadLockClass locker;

	/*
	** Get a pointer to the entry.
	*/
	DataSafeEntryClass *entry_ptr = Get_Entry(handle);

	if (entry_ptr == NULL) {
		return(false);
	}

	DataSafeEntryDataClass<T> *data_entry_ptr = (DataSafeEntryDataClass<T>*) entry_ptr;

	/*
	** Decrypt the old entry just to fix up the checksum.
	*/
	Decrypt(&data_entry_ptr->Data, sizeof(T), SimpleKey, true);

	/*
	** Copy the object into the data safe and encrypt it in one pass.
	*/
	Mem_Copy_Encrypt(&data_entry_ptr->Data, data, sizeof(T), true);

	/*
	** Move stuff around.
	*/
	Shuffle();

	/*
	** Check safe integrity.
	*/
	Security_Check();

	return(true);
}







/*
**
**
** 	SafeDataClass functions.
**
**
*/


/***********************************************************************************************
 * SafeDataClass::SafeDataClass -- Class constructor. Adds the data to the data safe           *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Initial value to store in the safe                                                *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 11:50AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline SafeDataClass<T>::SafeDataClass(T data)
{
	Handle = DataSafeClass<T>::Add_Entry(data);
#ifdef WWDEBUG
	DebugData = data;
#endif //WWDEBUG
}


/***********************************************************************************************
 * SafeDataClass::SafeDataClass -- Class constructor. Adds the fetches a safe handle           *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 11:50AM ST : Created                                                             *
 *=============================================================================================*/
//warning C4700: local variable 'data' used without having been initialized
//#pragma warning(push, 0)
//#pragma warning(disable : 4700)
template <class T>
SafeDataClass<T>::SafeDataClass(void)
{
	/*
	** The data here isn't initialised since no default value was provided. I have to provide *some* sort of
	** init though as the bloody compiler won't let me turn off the 'local variable 'data' used without having been initialized'
	** message. Grrrr.
	**
	** Allocating the memory on the stack then doing an in place new seems to mollify the compiler so we don't get the warning
	** and it does much the same thing as just declaring 'T data'. It also has the benefit that the destructor won't be called
	** for the slop object when we exit this function but the memory will be freed.
	*/
	void *stackmem = _alloca(sizeof(T));
	T *data = new (stackmem) T;

	/*
	** Add the entry to the data safe and note the handle.
	*/
	Handle = DataSafeClass<T>::Add_Entry(*data);
#ifdef WWDEBUG
	DebugData = *data;
#endif //WWDEBUG

}
//#pragma warning(pop)


/***********************************************************************************************
 * SafeDataClass::~SafeDataClass -- Class desturctor. Removes the data from the data safe      *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 11:51AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline SafeDataClass<T>::~SafeDataClass(void)
{
	if (Handle.Is_Valid()) {
		DataSafeClass<T>::Delete_Entry(Handle);
	}
}




/***********************************************************************************************
 * SafeDataClass::operator = - assignment operator.                                            *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to assign                                                                    *
 *                                                                                             *
 * OUTPUT:   Data assigned                                                                     *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator = (T const &data)
{
	/*
	** If we have a valid handle, then set the data into the data safe.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Set(Handle, (T*) &data);
		ds_assert(ok);
#ifdef WWDEBUG
		DebugData = data;
#endif //WWDEBUG
	}

	return((T&)data);
}




/***********************************************************************************************
 * SafeDataClass::operator = - assignment operator for assigning from other SafeDataClass's    *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to assign                                                                    *
 *                                                                                             *
 * OUTPUT:   Data assigned                                                                     *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator = (SafeDataClass<T> &safedata)
{
	/*
	** Locals.
	*/
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safedata.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));

	/*
	** If we have a valid handle, then get the data for this handle from the data safe.
	*/
	if (Handle.Is_Valid()) {
		/*
		** Get the value for the other safe data class
		** and set it into the safe entry with our handle.
		*/
		other_value = safedata.Get_Ptr();
		ds_assert(other_value != NULL);

		if (other_value) {
#ifdef WWDEBUG
			bool ok =
#endif //WWDEBUG
				DataSafeClass<T>::Set(Handle, (T*) other_value);
			ds_assert(ok);
#ifdef WWDEBUG
			DebugData = *other_value;
#endif //WWDEBUG
		} else {
			/*
			** Bad error case, have to return something so use the value we already have.
			*/
			return((T&)*other_value);
		}
	}

	return((T&)*other_value);
}






/***********************************************************************************************
 * SafeDataClass::operator == - Equality check operator.                                       *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to compare against                                                           *
 *                                                                                             *
 * OUTPUT:   true if equal                                                                     *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator == (T const &data)
{
	T *data_ptr = NULL;

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			return(*data_ptr == data);
		}
	}

	return(false);
}






/***********************************************************************************************
 * SafeDataClass::operator == - Equality check operator.                                       *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Safe Data to compare against                                                      *
 *                                                                                             *
 * OUTPUT:   true if equal                                                                     *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator == (SafeDataClass<T> &safedata)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safedata.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {

			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			*/
			other_value = safedata.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {

				/*
				** Check them against each other,
				*/
				return(*data_ptr == *other_value);
			}
		}
	}

	return(false);
}






/***********************************************************************************************
 * SafeDataClass::operator != - Inequality check operator.                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to compare against                                                           *
 *                                                                                             *
 * OUTPUT:   true if not equal                                                                 *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator != (T const &data)
{
	T *data_ptr = NULL;

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			return(*data_ptr != data);
		}
	}

	return(true);
}




/***********************************************************************************************
 * SafeDataClass::operator != - Inequality check operator.                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to compare against                                                           *
 *                                                                                             *
 * OUTPUT:   true if not equal                                                                 *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator != (SafeDataClass<T> &safedata)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safedata.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {

			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			*/
			other_value = safedata.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {

				/*
				** Check them against each other,
				*/
				return(*data_ptr != *other_value);
			}
		}
	}

	return(false);
}






/***********************************************************************************************
 * SafeDataClass::operator > - > operator.                                                    *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to compare against                                                           *
 *                                                                                             *
 * OUTPUT:   true if greater than                                                              *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator > (T const &data)
{
	T *data_ptr = NULL;

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			return(*data_ptr > data);
		}
	}

	return(false);
}






/***********************************************************************************************
 * SafeDataClass::operator > - > operator.                                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Safe Data to compare against                                                      *
 *                                                                                             *
 * OUTPUT:   true if greater than                                                              *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator > (SafeDataClass<T> &safedata)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safedata.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {

			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			*/
			other_value = safedata.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {

				/*
				** Check them against each other,
				*/
				return(*data_ptr > *other_value);
			}
		}
	}

	return(false);
}








/***********************************************************************************************
 * SafeDataClass::operator >= - >= operator.                                                   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to compare against                                                           *
 *                                                                                             *
 * OUTPUT:   true if greater than or equal                                                     *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator >= (T const &data)
{
	T *data_ptr = NULL;

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			return(*data_ptr >= data);
		}
	}

	return(false);
}






/***********************************************************************************************
 * SafeDataClass::operator >= - >= operator.                                                   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Safe Data to compare against                                                      *
 *                                                                                             *
 * OUTPUT:   true if greater than or equal                                                     *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator >= (SafeDataClass<T> &safedata)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safedata.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {

			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			*/
			other_value = safedata.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {

				/*
				** Check them against each other,
				*/
				return(*data_ptr >= *other_value);
			}
		}
	}

	return(false);
}







/***********************************************************************************************
 * SafeDataClass::operator < - < operator.                                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to compare against                                                           *
 *                                                                                             *
 * OUTPUT:   true if less than                                                                 *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator < (T const &data)
{
	T *data_ptr = NULL;

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			return(*data_ptr < data);
		}
	}

	return(false);
}






/***********************************************************************************************
 * SafeDataClass::operator < - < operator.                                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Safe Data to compare against                                                      *
 *                                                                                             *
 * OUTPUT:   true if less than                                                                 *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator < (SafeDataClass<T> &safedata)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safedata.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {

			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			*/
			other_value = safedata.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {

				/*
				** Check them against each other,
				*/
				return(*data_ptr < *other_value);
			}
		}
	}

	return(false);
}










/***********************************************************************************************
 * SafeDataClass::operator <= - <= operator.                                                   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to compare against                                                           *
 *                                                                                             *
 * OUTPUT:   true if less than or equal                                                        *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator <= (T const &data)
{
	T *data_ptr = NULL;

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			return(*data_ptr <= data);
		}
	}

	return(false);
}






/***********************************************************************************************
 * SafeDataClass::operator <= - <= operator.                                                   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Safe Data to compare against                                                      *
 *                                                                                             *
 * OUTPUT:   true if less than or equal                                                        *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::operator <= (SafeDataClass<T> &safedata)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safedata.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safedata.Get_Handle()));

	/*
	** If we have a valid handle, then check the value against the supplied data.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {

			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			*/
			other_value = safedata.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {

				/*
				** Check them against each other,
				*/
				return(*data_ptr <= *other_value);
			}
		}
	}

	return(false);
}






/***********************************************************************************************
 * SafeDataClass::operator + - + operator.                                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to add                                                                       *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator + (T const &value)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			*data_ptr = *data_ptr + value;
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}



/***********************************************************************************************
 * SafeDataClass::operator + - + operator                                                      *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to add                                                                       *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator + (SafeDataClass<T> &safevalue)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safevalue.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));

	/*
	** If we have a valid handle, then get the data for this handle from the data safe.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			** and do the math.
			*/
			other_value = safevalue.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {
				*data_ptr = *data_ptr + *other_value;
				return((T&)*data_ptr);
			} else {
				/*
				** Bad error case, have to return something so use the value we already have.
				*/
				return((T&)*data_ptr);
			}
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}









/***********************************************************************************************
 * SafeDataClass::operator += - += operator.                                                   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to add                                                                       *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator += (T const &value)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			*data_ptr = *data_ptr + value;

#ifdef WWDEBUG
			bool ok =
#endif //WWDEBUG
				DataSafeClass<T>::Set(Handle, data_ptr);
			ds_assert(ok);
#ifdef WWDEBUG
			DebugData = *data_ptr;
#endif //WWDEBUG
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}



/***********************************************************************************************
 * SafeDataClass::operator += - += operator                                                    *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to add                                                                       *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator += (SafeDataClass<T> &safevalue)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safevalue.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));

	/*
	** If we have a valid handle, then get the data for this handle from the data safe.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			** and do the math.
			*/
			other_value = safevalue.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {
				*data_ptr = *data_ptr + *other_value;
#ifdef WWDEBUG
				ok =
#endif //WWDEBUG
					DataSafeClass<T>::Set(Handle, data_ptr);
				ds_assert(ok);
#ifdef WWDEBUG
				DebugData = *data_ptr;
#endif //WWDEBUG
				return((T&)*data_ptr);
			} else {
				/*
				** Bad error case, have to return something so use the value we already have.
				*/
				return((T&)*data_ptr);
			}
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}







/***********************************************************************************************
 * SafeDataClass::operator - - - operator.                                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to subtract                                                                  *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator - (T const &value)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			*data_ptr = *data_ptr - value;
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}



/***********************************************************************************************
 * SafeDataClass::operator - - - operator                                                      *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to subtract                                                                  *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator - (SafeDataClass<T> &safevalue)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safevalue.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));

	/*
	** If we have a valid handle, then get the data for this handle from the data safe.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			** and do the math.
			*/
			other_value = safevalue.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {
				*data_ptr = *data_ptr - *other_value;
				return((T&)*data_ptr);
			} else {
				/*
				** Bad error case, have to return something so use the value we already have.
				*/
				return((T&)*data_ptr);
			}
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}









/***********************************************************************************************
 * SafeDataClass::operator -= - -= operator.                                                   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to subtract                                                                  *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator -= (T const &value)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			*data_ptr = *data_ptr - value;

#ifdef WWDEBUG
			bool ok =
#endif //WWDEBUG
				DataSafeClass<T>::Set(Handle, data_ptr);
			ds_assert(ok);
#ifdef WWDEBUG
			DebugData = *data_ptr;
#endif //WWDEBUG
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}



/***********************************************************************************************
 * SafeDataClass::operator -= - -= operator                                                    *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to subtract                                                                  *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator -= (SafeDataClass<T> &safevalue)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safevalue.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));

	/*
	** If we have a valid handle, then get the data for this handle from the data safe.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			** and do the math.
			*/
			other_value = safevalue.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {
				*data_ptr = *data_ptr - *other_value;
#ifdef WWDEBUG
				ok =
#endif //WWDEBUG
					DataSafeClass<T>::Set(Handle, data_ptr);
				ds_assert(ok);
#ifdef WWDEBUG
				DebugData = *data_ptr;
#endif //WWDEBUG
				return((T&)*data_ptr);
			} else {
				/*
				** Bad error case, have to return something so use the value we already have.
				*/
				return((T&)*data_ptr);
			}
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}











/***********************************************************************************************
 * SafeDataClass::operator * - * operator.                                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to multiply by                                                               *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator * (T const &value)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			*data_ptr = *data_ptr * value;
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}



/***********************************************************************************************
 * SafeDataClass::operator * - * operator                                                      *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to multiply by                                                               *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator * (SafeDataClass<T> &safevalue)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safevalue.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));

	/*
	** If we have a valid handle, then get the data for this handle from the data safe.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			** and do the math.
			*/
			other_value = safevalue.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {
				*data_ptr = *data_ptr * *other_value;
				return((T&)*data_ptr);
			} else {
				/*
				** Bad error case, have to return something so use the value we already have.
				*/
				return((T&)*data_ptr);
			}
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}









/***********************************************************************************************
 * SafeDataClass::operator *= - *= operator.                                                   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to multiply by                                                               *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator *= (T const &value)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			*data_ptr = *data_ptr * value;

#ifdef WWDEBUG
			bool ok =
#endif //WWDEBUG
				DataSafeClass<T>::Set(Handle, data_ptr);
			ds_assert(ok);
#ifdef WWDEBUG
			DebugData = *data_ptr;
#endif //WWDEBUG
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}



/***********************************************************************************************
 * SafeDataClass::operator *= - *= operator                                                    *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to multiply by                                                               *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator *= (SafeDataClass<T> &safevalue)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safevalue.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));

	/*
	** If we have a valid handle, then get the data for this handle from the data safe.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			** and do the math.
			*/
			other_value = safevalue.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {
				*data_ptr = *data_ptr * *other_value;
#ifdef WWDEBUG
				ok =
#endif //WWDEBUG
					DataSafeClass<T>::Set(Handle, data_ptr);
				ds_assert(ok);
#ifdef WWDEBUG
				DebugData = *data_ptr;
#endif //WWDEBUG
				return((T&)*data_ptr);
			} else {
				/*
				** Bad error case, have to return something so use the value we already have.
				*/
				return((T&)*data_ptr);
			}
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}





/***********************************************************************************************
 * SafeDataClass::operator / - / operator.                                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to divide by                                                                 *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator / (T const &value)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(value != 0);

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			*data_ptr = *data_ptr / value;
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}



/***********************************************************************************************
 * SafeDataClass::operator / - / operator                                                      *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to divide by                                                                 *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator / (SafeDataClass<T> &safevalue)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safevalue.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));

	/*
	** If we have a valid handle, then get the data for this handle from the data safe.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			** and do the math.
			*/
			other_value = safevalue.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {
				ds_assert(*other_value != 0);
				*data_ptr = *data_ptr / *other_value;
				return((T&)*data_ptr);
			} else {
				/*
				** Bad error case, have to return something so use the value we already have.
				*/
				return((T&)*data_ptr);
			}
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}









/***********************************************************************************************
 * SafeDataClass::operator /= - /= operator.                                                   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to divide by                                                                 *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator /= (T const &value)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(value != 0);

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			*data_ptr = *data_ptr / value;

#ifdef WWDEBUG
			bool ok =
#endif //WWDEBUG
				DataSafeClass<T>::Set(Handle, data_ptr);
			ds_assert(ok);
#ifdef WWDEBUG
			DebugData = *data_ptr;
#endif //WWDEBUG
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}



/***********************************************************************************************
 * SafeDataClass::operator /= - /= operator                                                    *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Data to divide by                                                                 *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator /= (SafeDataClass<T> &safevalue)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;
	T *other_value = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());
	ds_assert(safevalue.Get_Handle().Is_Valid());
	ds_assert(GenericDataSafeClass::Get_Entry_Type(Handle) == GenericDataSafeClass::Get_Entry_Type(safevalue.Get_Handle()));

	/*
	** If we have a valid handle, then get the data for this handle from the data safe.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			/*
			** Looks like we have the value for this safe data class. Get the value for the other one.
			** and do the math.
			*/
			other_value = safevalue.Get_Ptr();
			ds_assert(other_value != NULL);

			if (other_value) {
				ds_assert(*other_value != 0);
				*data_ptr = *data_ptr / *other_value;
#ifdef WWDEBUG
				ok =
#endif //WWDEBUG
					DataSafeClass<T>::Set(Handle, data_ptr);
				ds_assert(ok);
#ifdef WWDEBUG
				DebugData = *data_ptr;
#endif //WWDEBUG
				return((T&)*data_ptr);
			} else {
				/*
				** Bad error case, have to return something so use the value we already have.
				*/
				return((T&)*data_ptr);
			}
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}



/***********************************************************************************************
 * SafeDataClass::operator ++ - prefix increment operator.                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator ++ (void)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			(*data_ptr)++;

#ifdef WWDEBUG
			ok =
#endif //WWDEBUG
				DataSafeClass<T>::Set(Handle, data_ptr);
			ds_assert(ok);
#ifdef WWDEBUG
			DebugData = *data_ptr;
#endif //WWDEBUG
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}





/***********************************************************************************************
 * SafeDataClass::operator -- - prefix decrement operator.                                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Result                                                                            *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator -- (void)
{
	/*
	** Locals.
	*/
	T *data_ptr = NULL;

	/*
	** Asserts.
	*/
	ds_assert(Handle.Is_Valid());

	/*
	** If we have a valid handle, then get the current value and apply the change
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		ds_assert(data_ptr);

		if (data_ptr) {
			(*data_ptr)--;

#ifdef WWDEBUG
			ok =
#endif //WWDEBUG
				DataSafeClass<T>::Set(Handle, data_ptr);
			ds_assert(ok);
#ifdef WWDEBUG
			DebugData = *data_ptr;
#endif //WWDEBUG
			return((T&)*data_ptr);
		}
	}

	/*
	** Error case, have to return something.
	*/
	return((T&)ErrorVal[0]);
}




/***********************************************************************************************
 * SafeDataClass::operator ++ - postfix ++ operator                                            *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    int (not used, denotes postfix operator)                                          *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/23/2001 3:54PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator ++ (int)
{
	/*
	** Just call the prefix version of the operator.
	*/
	return(this->operator ++ ());
}



/***********************************************************************************************
 * SafeDataClass::operator -- - postfix -- operator                                            *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    int (not used, denotes postfix operator)                                          *
 *                                                                                             *
 * OUTPUT:   Nothing                                                                           *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/23/2001 3:54PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator -- (int)
{
	/*
	** Just call the prefix version of the operator.
	*/
	return(this->operator -- ());
}








/***********************************************************************************************
 * SafeDataClass::operator () - Conversion operator used for data retrieval                    *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Copy of data in safe                                                              *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T &SafeDataClass<T>::operator () (void) const
{
	T *data_ptr = NULL;

	/*
	** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
	** handle.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		if (data_ptr) {
			return(*data_ptr);
		}
	}

	/*
	** Error case. Need to return some valid value.
	*/
	static T oh_dear;
	return(oh_dear);
}






/***********************************************************************************************
 * SafeDataClass::operator int -- Return the data for this class as an int                     *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Data cast to int                                                                  *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/6/2001 11:47AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline SafeDataClass<T>::operator int (void) const
{
	ds_assert(sizeof(T) == sizeof(int));

	T *data_ptr = NULL;

#ifdef WWDEBUG
	/*
	** Check that T is safe to return as an int
	*/
	T x = 0;
	int y = (T)x;
	ds_assert(x == y);
#endif	//WWDEBUG

	/*
	** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
	** handle.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		if (data_ptr) {
			return(*((int*)data_ptr));
		}
	}

	/*
	** Error case. Need to return some valid value.
	*/
	static int oh_dear;
	return(oh_dear);
}



/***********************************************************************************************
 * SafeDataClass::operator unsigned int -- Return the data for this class as an unsigned int   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Data cast to unsigned int                                                         *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/6/2001 11:47AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline SafeDataClass<T>::operator unsigned int (void) const
{
	ds_assert(sizeof(T) == sizeof(unsigned int));

	T *data_ptr = NULL;

#ifdef WWDEBUG
	/*
	** Check that T is safe to return as an unsigned int
	*/
	T x = 0;
	unsigned int y = (T)x;
	ds_assert(x == y);
#endif	//WWDEBUG

	/*
	** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
	** handle.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		if (data_ptr) {
			return(*((unsigned int*)data_ptr));
		}
	}

	/*
	** Error case. Need to return some valid value.
	*/
	static unsigned int oh_dear;
	return(oh_dear);
}



/***********************************************************************************************
 * SafeDataClass::operator long -- Return the data for this class as a long                    *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Data cast to long                                                                 *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/6/2001 11:47AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline SafeDataClass<T>::operator long (void) const
{
	ds_assert(sizeof(T) == sizeof(long));

	T *data_ptr = NULL;

#ifdef WWDEBUG
	/*
	** Check that T is safe to return as a long
	*/
	T x = 0;
	long y = (T)x;
	ds_assert(x == y);
#endif	//WWDEBUG

	/*
	** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
	** handle.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		if (data_ptr) {
			return(*((long*)data_ptr));
		}
	}

	/*
	** Error case. Need to return some valid value.
	*/
	static long oh_dear;
	return(oh_dear);
}




/***********************************************************************************************
 * SafeDataClass::operator int -- Return the data for this class as an unsigned long           *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Data cast to unsigned long                                                        *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/6/2001 11:47AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline SafeDataClass<T>::operator unsigned long (void) const
{
	ds_assert(sizeof(T) == sizeof(unsigned long));

	T *data_ptr = NULL;

#ifdef WWDEBUG
	/*
	** Check that T is safe to return as an unsigned long
	*/
	T x = 0;
	unsigned long y = (T)x;
	ds_assert(x == y);
#endif	//WWDEBUG

	/*
	** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
	** handle.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		if (data_ptr) {
			return(*((unsigned long*)data_ptr));
		}
	}

	/*
	** Error case. Need to return some valid value.
	*/
	static unsigned long oh_dear;
	return(oh_dear);
}



/***********************************************************************************************
 * SafeDataClass::operator int -- Return the data for this class as a float                    *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Data cast to float                                                                *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/6/2001 11:47AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline SafeDataClass<T>::operator float (void) const
{
	ds_assert(sizeof(T) == sizeof(float));

	T *data_ptr = NULL;

#ifdef WWDEBUG
	/*
	** Check that T is safe to return as a float
	*/
	T x = 0;
	float y = (T)x;
	ds_assert(x == y);
#endif	//WWDEBUG

	/*
	** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
	** handle.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		if (data_ptr) {
			return(*((float*)data_ptr));
		}
	}

	/*
	** Error case. Need to return some valid value.
	*/
	static float oh_dear;
	return(oh_dear);
}



/***********************************************************************************************
 * SafeDataClass::operator int -- Return the data for this class as a double                   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Data cast to double                                                               *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/6/2001 11:47AM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline SafeDataClass<T>::operator double (void) const
{
	ds_assert(sizeof(T) == sizeof(double));

	T *data_ptr = NULL;

#ifdef WWDEBUG
	/*
	** Check that T is safe to return as a double
	*/
	T x = 0;
	double y = (T)x;
	ds_assert(x == y);
#endif	//WWDEBUG

	/*
	** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
	** handle.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		if (data_ptr) {
			return(*((double*)data_ptr));
		}
	}

	/*
	** Error case. Need to return some valid value.
	*/
	static double oh_dear;
	return(oh_dear);
}









/***********************************************************************************************
 * SafeDataClass::Get_Ptr - Get a pointer to a decrypted version of a class in the data safe   *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    nothing                                                                           *
 *                                                                                             *
 * OUTPUT:   Ptr to copy of data in safe                                                       *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/3/2001 12:05PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline T *SafeDataClass<T>::Get_Ptr(void) const
{
	T *data_ptr = NULL;

	/*
	** If the handle we have is valid then use it to get a pointer to a temporary copy of the data safe contents for this
	** handle.
	*/
	if (Handle.Is_Valid()) {
#ifdef WWDEBUG
		bool ok =
#endif //WWDEBUG
			DataSafeClass<T>::Get(Handle, data_ptr);
		ds_assert(ok);
		if (data_ptr) {
			return(data_ptr);
		}
	}

	/*
	** Error case.
	*/
	ds_assert(false);
	return(NULL);
}





/***********************************************************************************************
 * SafeDataClass::Commit -- Write decrypted data safe data back into the safe                  *
 *                                                                                             *
 *                                                                                             *
 *                                                                                             *
 * INPUT:    Ptr to data (must be from prior return list)                                      *
 *                                                                                             *
 * OUTPUT:   True if commited back into the safe                                               *
 *                                                                                             *
 * WARNINGS: None                                                                              *
 *                                                                                             *
 * HISTORY:                                                                                    *
 *   7/13/2001 2:28PM ST : Created                                                             *
 *=============================================================================================*/
template <class T>
inline bool SafeDataClass<T>::Commit(T *data_ptr) const
{
	ds_assert(Handle.Is_Valid());
	ds_assert(DataSafeClass<T>::In_Return_List(data_ptr));

	/*
	** If the handle is valid, and the data pointer is one of our temporary return buffers
	** then copy the data back into the safe.
	*/
	if (Handle.Is_Valid()) {

		/*
		** Verify it's one of our temp data pointers.
		*/
		if (DataSafeClass<T>::In_Return_List(data_ptr)) {
#ifdef WWDEBUG
			DebugData = *data_ptr;
#endif //WWDEBUG
			return(DataSafeClass<T>::Set(Handle, data_ptr));
		}
	}
	return(false);
}



#pragma warning(default : 4189)
#pragma warning(default : 4101)


#endif //_DATASAFE_H




