/* ** 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 . */ /*********************************************************************************************** *** 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. ** 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's. Only the same ** type of DataSafeEntryDataClass 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 ** The safe itself consists of one static GenericDataSafeClass and many DataSafeClass's - ** one DataSafeClass 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 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 ASafeClass; ** SafeDataClass ASafeType; ** ** For types without existing macros, you will have to declare a new DataSafeClass 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 #include #include #include #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 #define safe_unsigned_int SafeDataClass #define safe_long SafeDataClass #define safe_unsigned_long SafeDataClass #define safe_float SafeDataClass #define safe_double SafeDataClass #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 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 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 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. ** ** ** 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 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 ** ** 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 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 DataSafe##type; \ int DataSafeClass::Type; \ char DataSafeClass::ReturnList[MAX_OBJECT_COPIES][sizeof(type)]; \ int DataSafeClass::ReturnIndex; \ int DataSafeClass::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 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 &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 &safedata); inline bool operator != (T const &data); inline bool operator != (SafeDataClass &safedata); inline bool operator > (T const &data); inline bool operator > (SafeDataClass &safedata); inline bool operator >= (T const &data); inline bool operator >= (SafeDataClass &safedata); inline bool operator < (T const &data); inline bool operator < (SafeDataClass &safedata); inline bool operator <= (T const &data); inline bool operator <= (SafeDataClass &safedata); inline T &operator + (T const &data); inline T &operator + (SafeDataClass &safedata); inline T &operator += (T const &data); inline T &operator += (SafeDataClass &safedata); inline T &operator - (T const &data); inline T &operator - (SafeDataClass &safedata); inline T &operator -= (T const &data); inline T &operator -= (SafeDataClass &safedata); inline T &operator * (T const &data); inline T &operator * (SafeDataClass &safedata); inline T &operator *= (T const &data); inline T &operator *= (SafeDataClass &safedata); inline T &operator / (T const &data); inline T &operator / (SafeDataClass &safedata); inline T &operator /= (T const &data); inline T &operator /= (SafeDataClass &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 ; iEntryCount > 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 ; jEntryCount ; 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 ; zNext; } } } } 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::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::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 DataSafeClass::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 DataSafeClass::~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 ; iEntryType == 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 unsigned long DataSafeClass::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 int DataSafeClass::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 DataSafeHandleClass DataSafeClass::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)]; 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* data_ptr = (DataSafeEntryDataClass*) 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)]; 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*)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 ; jEntryCount ; 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 ; jSlopCount == 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 void DataSafeClass::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 *whole_entry_ptr = (DataSafeEntryDataClass*) 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 bool DataSafeClass::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 *data_entry_ptr = (DataSafeEntryDataClass*) 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 bool DataSafeClass::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 *data_entry_ptr = (DataSafeEntryDataClass*) 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 inline SafeDataClass::SafeDataClass(T data) { Handle = DataSafeClass::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 SafeDataClass::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::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 inline SafeDataClass::~SafeDataClass(void) { if (Handle.Is_Valid()) { DataSafeClass::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 inline T &SafeDataClass::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::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 inline T &SafeDataClass::operator = (SafeDataClass &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::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 inline bool SafeDataClass::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::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 inline bool SafeDataClass::operator == (SafeDataClass &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::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 inline bool SafeDataClass::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::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 inline bool SafeDataClass::operator != (SafeDataClass &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::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 inline bool SafeDataClass::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::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 inline bool SafeDataClass::operator > (SafeDataClass &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::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 inline bool SafeDataClass::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::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 inline bool SafeDataClass::operator >= (SafeDataClass &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::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 inline bool SafeDataClass::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::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 inline bool SafeDataClass::operator < (SafeDataClass &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::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 inline bool SafeDataClass::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::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 inline bool SafeDataClass::operator <= (SafeDataClass &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::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 inline T &SafeDataClass::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::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 inline T &SafeDataClass::operator + (SafeDataClass &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::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 inline T &SafeDataClass::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::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::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 inline T &SafeDataClass::operator += (SafeDataClass &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::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::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 inline T &SafeDataClass::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::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 inline T &SafeDataClass::operator - (SafeDataClass &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::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 inline T &SafeDataClass::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::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::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 inline T &SafeDataClass::operator -= (SafeDataClass &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::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::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 inline T &SafeDataClass::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::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 inline T &SafeDataClass::operator * (SafeDataClass &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::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 inline T &SafeDataClass::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::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::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 inline T &SafeDataClass::operator *= (SafeDataClass &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::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::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 inline T &SafeDataClass::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::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 inline T &SafeDataClass::operator / (SafeDataClass &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::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 inline T &SafeDataClass::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::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::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 inline T &SafeDataClass::operator /= (SafeDataClass &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::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::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 inline T &SafeDataClass::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::Get(Handle, data_ptr); ds_assert(ok); ds_assert(data_ptr); if (data_ptr) { (*data_ptr)++; #ifdef WWDEBUG ok = #endif //WWDEBUG DataSafeClass::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 inline T &SafeDataClass::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::Get(Handle, data_ptr); ds_assert(ok); ds_assert(data_ptr); if (data_ptr) { (*data_ptr)--; #ifdef WWDEBUG ok = #endif //WWDEBUG DataSafeClass::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 inline T &SafeDataClass::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 inline T &SafeDataClass::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 inline T &SafeDataClass::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::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 inline SafeDataClass::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::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 inline SafeDataClass::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::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 inline SafeDataClass::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::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 inline SafeDataClass::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::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 inline SafeDataClass::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::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 inline SafeDataClass::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::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 inline T *SafeDataClass::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::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 inline bool SafeDataClass::Commit(T *data_ptr) const { ds_assert(Handle.Is_Valid()); ds_assert(DataSafeClass::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::In_Return_List(data_ptr)) { #ifdef WWDEBUG DebugData = *data_ptr; #endif //WWDEBUG return(DataSafeClass::Set(Handle, data_ptr)); } } return(false); } #pragma warning(default : 4189) #pragma warning(default : 4101) #endif //_DATASAFE_H