diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Archive.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Archive.h new file mode 100755 index 00000000..30ddce43 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Archive.h @@ -0,0 +1,42 @@ +#ifndef BASE_WIN32_ARCHIVE_H +#define BASE_WIN32_ARCHIVE_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + +#ifdef PACK_BIG_ENDIAN + + inline double byteSwap(double value) { byteReverse64(&value); return value; } + inline float byteSwap(float value) { byteReverse32(&value); return value; } + inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; } + inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; } + inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; } + inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; } + inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; } + inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; } + +#else + + inline double byteSwap(double value) { return value; } + inline float byteSwap(float value) { return value; } + inline uint64 byteSwap(uint64 value) { return value; } + inline int64 byteSwap(int64 value) { return value; } + inline uint32 byteSwap(uint32 value) { return value; } + inline int32 byteSwap(int32 value) { return value; } + inline uint16 byteSwap(uint16 value) { return value; } + inline int16 byteSwap(int16 value) { return value; } + +#endif + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.cpp b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.cpp new file mode 100755 index 00000000..3b52563e --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.cpp @@ -0,0 +1,31 @@ +//////////////////////////////////////// +// Platform.cpp +// +// Purpose: +// 1. Implementation of the global functionality declaired in Platform.h. +// +// Revisions: +// 07/10/2001 Created +// + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + + CTimer::CTimer() : + mTimer(0) + { + } + + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.h new file mode 100755 index 00000000..aaee37b7 --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Platform.h @@ -0,0 +1,98 @@ +//////////////////////////////////////// +// Platform.h +// +// Purpose: +// 1. Include relevent system headers that are platform specific. +// 2. Declair global platform specific functionality. +// 3. Include primative type definitions +// +// Global Functions: +// getTimer() : Return the current high resolution clock count. +// getTimerFrequency() : Return the frequency of the high resolution clock. +// sleep() : Voluntarily relinquish timeslice of the calling thread for a +// specified number of milliseconds. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_PLATFORM_H +#define BASE_WIN32_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Types.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + uint64 getTimer(void); + uint64 getTimerFrequency(void); + + inline uint64 getTimer(void) + { + uint64 result; + if (!QueryPerformanceCounter(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline uint64 getTimerFrequency(void) + { + uint64 result; + if (!QueryPerformanceFrequency(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline void sleep(uint32 ms) + { + Sleep(ms); + } + + + class CTimer + { + public: + CTimer(); + + void Set(uint32 seconds); + void Signal(); + bool Expired(); + + private: + uint32 mTimer; + }; + + inline void CTimer::Set(uint32 interval) + { + mTimer = (uint32)time(0) + interval; + } + + inline void CTimer::Signal() + { + mTimer = 0; + } + + inline bool CTimer::Expired() + { + return (mTimer <= (uint32)time(0)); + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif BASE_WIN32_PLATFORM_H \ No newline at end of file diff --git a/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h new file mode 100755 index 00000000..0c64cb2c --- /dev/null +++ b/engine/server/application/CentralServer/src/shared/AuctionTransferGameAPI/Base/win32/Types.h @@ -0,0 +1,42 @@ +//////////////////////////////////////// +// Types.h +// +// Purpose: +// 1. Define integer types that are unambiguous with respect to size +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_TYPES_H +#define BASE_WIN32_TYPES_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN 0x80000000 +#define UINT32_MAX 0xFFFFFFFF + +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; + +typedef int int32; +typedef unsigned uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // BASE_WIN32_TYPES_H + diff --git a/engine/server/application/CommoditiesServer/src/win32/WinMain.cpp b/engine/server/application/CommoditiesServer/src/win32/WinMain.cpp new file mode 100755 index 00000000..5051cfa4 --- /dev/null +++ b/engine/server/application/CommoditiesServer/src/win32/WinMain.cpp @@ -0,0 +1,70 @@ +#include "FirstCommodityServer.h" + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedCompression/SetupSharedCompression.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/TreeFile.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedGame/CommoditiesAdvancedSearchAttribute.h" +#include "sharedGame/ConfigSharedGame.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "sharedNetwork/NetworkHandler.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "sharedThread/SetupSharedThread.h" +#include "sharedUtility/DataTableManager.h" +#include "CommodityServer.h" +#include "ConfigCommodityServer.h" +#include "LocalizationManager.h" +#include "UnicodeUtils.h" + +int main(int argc, char ** argv) +{ + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + //-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + + setupFoundationData.argc = argc; + setupFoundationData.argv = argv; + setupFoundationData.createWindow = false; + setupFoundationData.clockUsesSleep = true; + SetupSharedFoundation::install (setupFoundationData); + + ConfigSharedGame::install(); + SetupSharedCompression::install(); + SetupSharedFile::install(false); + SetupSharedNetworkMessages::install(); + + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + NetworkHandler::install(); + + ConfigCommodityServer::install(); + + const bool displayBadStringIds = ConfigSharedGame::getDisplayBadStringIds (); + const bool debugStringIds = ConfigSharedGame::getDebugStringIds (); + Unicode::NarrowString defaultLocale(ConfigSharedGame::getDefaultLocale ()); + Unicode::UnicodeNarrowStringVector localeVector; + localeVector.push_back(defaultLocale); + + LocalizationManager::install (new TreeFile::TreeFileFactory, localeVector, debugStringIds, NULL, displayBadStringIds); + ExitChain::add(LocalizationManager::remove, "LocalizationManager::remove"); + + DataTableManager::install(); + CommoditiesAdvancedSearchAttribute::install(); + + //-- run server + SetupSharedFoundation::callbackWithExceptionHandling(CommodityServer::run); + + SetupSharedFoundation::remove(); + + return 0; +} + +//----------------------------------------------------------------------- diff --git a/engine/server/application/TransferServer/src/win32/WinMain.cpp b/engine/server/application/TransferServer/src/win32/WinMain.cpp new file mode 100755 index 00000000..b1533f7c --- /dev/null +++ b/engine/server/application/TransferServer/src/win32/WinMain.cpp @@ -0,0 +1,60 @@ +// main.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstTransferServer.h" + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedCompression/SetupSharedCompression.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "sharedNetwork/NetworkHandler.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "sharedThread/SetupSharedThread.h" +#include "TransferServer.h" +#include "ConfigTransferServer.h" + +//----------------------------------------------------------------------- + +int main(int argc, char ** argv) +{ + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + //-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + + setupFoundationData.argc = argc; + setupFoundationData.argv = argv; + setupFoundationData.createWindow = true; + SetupSharedFoundation::install (setupFoundationData); + + SetupSharedCompression::install(); + SetupSharedFile::install(false); + SetupSharedNetworkMessages::install(); + + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + NetworkHandler::install(); + + //Os::setProgramName("TransferServer"); + ConfigTransferServer::install(); + + //-- run server + SetupSharedFoundation::callbackWithExceptionHandling(TransferServer::run); + + NetworkHandler::remove(); + SetupSharedFoundation::remove(); + SetupSharedThread::remove(); + + return 0; +} + +//----------------------------------------------------------------------- + diff --git a/engine/server/library/serverDatabase/src/win32/FirstServerDatabase.cpp b/engine/server/library/serverDatabase/src/win32/FirstServerDatabase.cpp new file mode 100755 index 00000000..944e604d --- /dev/null +++ b/engine/server/library/serverDatabase/src/win32/FirstServerDatabase.cpp @@ -0,0 +1,9 @@ +// ====================================================================== +// +// FirstServerDatabase.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "serverDatabase/FirstServerDatabase.h" + diff --git a/engine/server/library/serverGame/src/win32/FirstServerGame.cpp b/engine/server/library/serverGame/src/win32/FirstServerGame.cpp new file mode 100755 index 00000000..c10e7d27 --- /dev/null +++ b/engine/server/library/serverGame/src/win32/FirstServerGame.cpp @@ -0,0 +1,10 @@ +// ====================================================================== +// +// FirstServerGame.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "serverGame/FirstServerGame.h" + +// ====================================================================== diff --git a/engine/server/library/serverKeyShare/src/win32/FirstServerKeyShare.cpp b/engine/server/library/serverKeyShare/src/win32/FirstServerKeyShare.cpp new file mode 100755 index 00000000..541cbe71 --- /dev/null +++ b/engine/server/library/serverKeyShare/src/win32/FirstServerKeyShare.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstServerKeyShare.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "serverKeyShare/FirstServerKeyShare.h" diff --git a/engine/server/library/serverMetrics/src/win32/FirstServerMetrics.cpp b/engine/server/library/serverMetrics/src/win32/FirstServerMetrics.cpp new file mode 100755 index 00000000..5133f174 --- /dev/null +++ b/engine/server/library/serverMetrics/src/win32/FirstServerMetrics.cpp @@ -0,0 +1,9 @@ +// FirstServerMetrics.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "serverMetrics/FirstServerMetrics.h" + +//----------------------------------------------------------------------- diff --git a/engine/server/library/serverNetworkMessages/src/win32/FirstServerNetworkMessages.cpp b/engine/server/library/serverNetworkMessages/src/win32/FirstServerNetworkMessages.cpp new file mode 100755 index 00000000..16562107 --- /dev/null +++ b/engine/server/library/serverNetworkMessages/src/win32/FirstServerNetworkMessages.cpp @@ -0,0 +1,3 @@ + + +#include "serverNetworkMessages/FirstServerNetworkMessages.h" diff --git a/engine/server/library/serverPathfinding/src/win32/FirstServerPathfinding.cpp b/engine/server/library/serverPathfinding/src/win32/FirstServerPathfinding.cpp new file mode 100755 index 00000000..ac6ecea0 --- /dev/null +++ b/engine/server/library/serverPathfinding/src/win32/FirstServerPathfinding.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstServerPathfinding.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "serverPathfinding/FirstServerPathfinding.h" diff --git a/engine/server/library/serverScript/src/win32/FirstServerScript.cpp b/engine/server/library/serverScript/src/win32/FirstServerScript.cpp new file mode 100755 index 00000000..46a6979d --- /dev/null +++ b/engine/server/library/serverScript/src/win32/FirstServerScript.cpp @@ -0,0 +1,2 @@ + +#include "serverScript/FirstServerScript.h" \ No newline at end of file diff --git a/engine/server/library/serverUtility/src/win32/FirstServerUtility.cpp b/engine/server/library/serverUtility/src/win32/FirstServerUtility.cpp new file mode 100755 index 00000000..73488cc4 --- /dev/null +++ b/engine/server/library/serverUtility/src/win32/FirstServerUtility.cpp @@ -0,0 +1,2 @@ + +#include "serverUtility/FirstServerUtility.h" \ No newline at end of file diff --git a/engine/shared/application/TemplateCompiler/src/win32/FirstTemplateCompiler.cpp b/engine/shared/application/TemplateCompiler/src/win32/FirstTemplateCompiler.cpp new file mode 100755 index 00000000..ef9c16dc --- /dev/null +++ b/engine/shared/application/TemplateCompiler/src/win32/FirstTemplateCompiler.cpp @@ -0,0 +1 @@ +#include "FirstTemplateCompiler.h" diff --git a/engine/shared/application/TemplateCompiler/src/win32/FirstTemplateCompiler.h b/engine/shared/application/TemplateCompiler/src/win32/FirstTemplateCompiler.h new file mode 100755 index 00000000..355e5538 --- /dev/null +++ b/engine/shared/application/TemplateCompiler/src/win32/FirstTemplateCompiler.h @@ -0,0 +1,8 @@ +#include "sharedFoundationTypes/FoundationTypes.h" +#include "sharedDebug/FirstSharedDebug.h" +#include "sharedFoundation/FirstSharedFoundation.h" +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/engine/shared/application/TemplateDefinitionCompiler/src/win32/FirstTemplateDefinitionCompiler.cpp b/engine/shared/application/TemplateDefinitionCompiler/src/win32/FirstTemplateDefinitionCompiler.cpp new file mode 100755 index 00000000..1444700b --- /dev/null +++ b/engine/shared/application/TemplateDefinitionCompiler/src/win32/FirstTemplateDefinitionCompiler.cpp @@ -0,0 +1 @@ +#include "FirstTemplateDefinitionCompiler.h" \ No newline at end of file diff --git a/engine/shared/application/TemplateDefinitionCompiler/src/win32/FirstTemplateDefinitionCompiler.h b/engine/shared/application/TemplateDefinitionCompiler/src/win32/FirstTemplateDefinitionCompiler.h new file mode 100755 index 00000000..355e5538 --- /dev/null +++ b/engine/shared/application/TemplateDefinitionCompiler/src/win32/FirstTemplateDefinitionCompiler.h @@ -0,0 +1,8 @@ +#include "sharedFoundationTypes/FoundationTypes.h" +#include "sharedDebug/FirstSharedDebug.h" +#include "sharedFoundation/FirstSharedFoundation.h" +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/engine/shared/library/sharedCollision/src/win32/FirstSharedCollision.cpp b/engine/shared/library/sharedCollision/src/win32/FirstSharedCollision.cpp new file mode 100755 index 00000000..175da0d0 --- /dev/null +++ b/engine/shared/library/sharedCollision/src/win32/FirstSharedCollision.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstSharedCollision.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedCollision/FirstSharedCollision.h" diff --git a/engine/shared/library/sharedCommandParser/src/win32/FirstSharedCommandParser.cpp b/engine/shared/library/sharedCommandParser/src/win32/FirstSharedCommandParser.cpp new file mode 100755 index 00000000..e07abaf5 --- /dev/null +++ b/engine/shared/library/sharedCommandParser/src/win32/FirstSharedCommandParser.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstCommandParser.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedCommandParser/FirstSharedCommandParser.h" diff --git a/engine/shared/library/sharedCompression/src/win32/FirstSharedCompression.cpp b/engine/shared/library/sharedCompression/src/win32/FirstSharedCompression.cpp new file mode 100755 index 00000000..4c24e040 --- /dev/null +++ b/engine/shared/library/sharedCompression/src/win32/FirstSharedCompression.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstCompression.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedCompression/FirstSharedCompression.h" diff --git a/engine/shared/library/sharedDatabaseInterface/src/win32/FirstSharedDatabaseInterface.cpp b/engine/shared/library/sharedDatabaseInterface/src/win32/FirstSharedDatabaseInterface.cpp new file mode 100755 index 00000000..46137c3b --- /dev/null +++ b/engine/shared/library/sharedDatabaseInterface/src/win32/FirstSharedDatabaseInterface.cpp @@ -0,0 +1,9 @@ +// ====================================================================== +// +// FirstServerDatabaseInterface.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedDatabaseInterface/FirstSharedDatabaseInterface.h" + diff --git a/engine/shared/library/sharedDatabaseInterface/src/win32/SQLC_Defs.h b/engine/shared/library/sharedDatabaseInterface/src/win32/SQLC_Defs.h new file mode 100755 index 00000000..6722c280 --- /dev/null +++ b/engine/shared/library/sharedDatabaseInterface/src/win32/SQLC_Defs.h @@ -0,0 +1,19 @@ +/* SQLC_Defs.h + * + * This file includes common definitions needed by the other SQLClasses header files. + * (Don't include this file directly -- files that require it will include it.) + * + * Note that this file is specific to each OS, because what header files are + * needed varies in each OS. In particular, Unix versions don't want windows.h. + * + * ODBC versions: includes definitions of ODBC datatypes needed by the various + * SQLClasses + */ + +#ifndef _SQLC_DEFS_H +#define _SQLC_DEFS_H + +#include +#include + +#endif \ No newline at end of file diff --git a/engine/shared/library/sharedDebug/src/win32/DebugHelp.cpp b/engine/shared/library/sharedDebug/src/win32/DebugHelp.cpp new file mode 100755 index 00000000..b80a6a45 --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/DebugHelp.cpp @@ -0,0 +1,670 @@ +// ====================================================================== +// +// DebugHelp.cpp +// copyright 2000 Verant Interactive +// +// ====================================================================== + +#include "sharedDebug/FirstSharedDebug.h" +#include "sharedDebug/DebugHelp.h" + +#include "sharedFoundation/WindowsWrapper.h" + +#include +#include +#include + +// ====================================================================== + + +// ====================================================================== +// This was done to keep the header file from having to include or + +namespace DebugHelpNamespace +{ + static HINSTANCE library; + static HANDLE process; + + struct CallbackData + { + const char *name; + bool loaded; + }; + + typedef DWORD (__stdcall *SymSetOptionsFP)(IN DWORD SymOptions); + typedef BOOL (__stdcall *SymInitializeFP)(IN HANDLE hProcess, IN PSTR UserSearchPath, IN BOOL fInvadeProcess); + typedef BOOL (__stdcall *SymCleanupFP)(IN HANDLE hProcess); + + typedef BOOL (__stdcall *StackWalk64FP)(DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + typedef BOOL (__stdcall *SymGetModuleInfo64FP)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PIMAGEHLP_MODULE64 ModuleInfo); + typedef DWORD64 (__stdcall *SymLoadModule64FP)(IN HANDLE hProcess, IN HANDLE hFile, IN PSTR ImageName, IN PSTR ModuleName, IN DWORD64 BaseOfDll, IN DWORD SizeOfDll); + typedef BOOL (__stdcall *SymGetSymFromAddr64FP)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol); + typedef BOOL (__stdcall *SymGetLineFromAddr64FP)(IN HANDLE hProcess, IN DWORD64 dwAddr, OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line); + typedef PVOID (__stdcall *SymFunctionTableAccess64FP)(HANDLE hProcess, DWORD64 AddrBase); + typedef DWORD64 (__stdcall *SymGetModuleBase64FP)(IN HANDLE hProcess, IN DWORD64 dwAddr); + typedef BOOL (__stdcall *SymEnumerateModules64FP)(HANDLE hProcess, PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, PVOID UserContext); + typedef BOOL (__stdcall *EnumerateLoadedModules64FP)(IN HANDLE hProcess, IN PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, IN PVOID UserContext); + typedef BOOL (__stdcall *MiniDumpWriteDumpFP)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile, MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + + static SymSetOptionsFP symSetOptions; + static SymInitializeFP symInitialize; + static SymCleanupFP symCleanup; + static StackWalk64FP stackWalk64; + static SymGetModuleInfo64FP symGetModuleInfo64; + static SymLoadModule64FP symLoadModule64; + static SymGetSymFromAddr64FP symGetSymFromAddr64; + static SymGetLineFromAddr64FP symGetLineFromAddr64; + static SymFunctionTableAccess64FP symFunctionTableAccess64; + static SymGetModuleBase64FP symGetModuleBase64; + static SymEnumerateModules64FP symEnumerateModules64; + static EnumerateLoadedModules64FP enumerateLoadedModules64; + static MiniDumpWriteDumpFP miniDumpWriteDump; + static CRITICAL_SECTION criticalSection; + + // ---------------------------------------------------------------------- + + //BOOL CALLBACK loadSymbolsForDllCallback(PTSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext); + + // ---------------------------------------------------------------------- + + + typedef unsigned long int ub4; /* unsigned 4-byte quantities */ + typedef unsigned char ub1; /* unsigned 1-byte quantities */ + + #define hashsize(n) ((ub4)1<<(n)) + #define hashmask(n) (hashsize(n)-1) + + /* + -------------------------------------------------------------------- + mix -- mix 3 32-bit values reversibly. + For every delta with one or two bits set, and the deltas of all three + high bits or all three low bits, whether the original value of a,b,c + is almost all zero or is uniformly distributed, + * If mix() is run forward or backward, at least 32 bits in a,b,c + have at least 1/4 probability of changing. + * If mix() is run forward, every bit of c will change between 1/3 and + 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.) + mix() was built out of 36 single-cycle latency instructions in a + structure that could supported 2x parallelism, like so: + a -= b; + a -= c; x = (c>>13); + b -= c; a ^= x; + b -= a; x = (a<<8); + c -= a; b ^= x; + c -= b; x = (b>>13); + ... + Unfortunately, superscalar Pentiums and Sparcs can't take advantage + of that parallelism. They've also turned some of those single-cycle + latency instructions into multi-cycle latency instructions. Still, + this is the fastest good hash I could find. There were about 2^^68 + to choose from. I only looked at a billion or so. + -------------------------------------------------------------------- + */ + #define mix(a,b,c) \ + { \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<<8); \ + c -= a; c -= b; c ^= (b>>13); \ + a -= b; a -= c; a ^= (c>>12); \ + b -= c; b -= a; b ^= (a<<16); \ + c -= a; c -= b; c ^= (b>>5); \ + a -= b; a -= c; a ^= (c>>3); \ + b -= c; b -= a; b ^= (a<<10); \ + c -= a; c -= b; c ^= (b>>15); \ + } + + /* + -------------------------------------------------------------------- + hash() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + len : the length of the key, counting by bytes + initval : can be any 4-byte value + Returns a 32-bit value. Every bit of the key affects every bit of + the return value. Every 1-bit and 2-bit delta achieves avalanche. + About 6*len+35 instructions. + + The best hash table sizes are powers of 2. There is no need to do + mod a prime (mod is sooo slow!). If you need less than 32 bits, + use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); + In which case, the hash table should have hashsize(10) elements. + + If you are hashing n strings (ub1 **)k, do it like this: + for (i=0, h=0; i= 12) + { + a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24)); + b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24)); + c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24)); + mix(a,b,c); + k += 12; len -= 12; + } + + /*------------------------------------- handle the last 11 bytes */ + c += length; + switch(len) /* all the case statements fall through */ + { + case 11: c+=((ub4)k[10]<<24); + case 10: c+=((ub4)k[9]<<16); + case 9 : c+=((ub4)k[8]<<8); + /* the first byte of c is reserved for the length */ + case 8 : b+=((ub4)k[7]<<24); + case 7 : b+=((ub4)k[6]<<16); + case 6 : b+=((ub4)k[5]<<8); + case 5 : b+=k[4]; + case 4 : a+=((ub4)k[3]<<24); + case 3 : a+=((ub4)k[2]<<16); + case 2 : a+=((ub4)k[1]<<8); + case 1 : a+=k[0]; + /* case 0: nothing left to add */ + } + mix(a,b,c); + /*-------------------------------------------- report the result */ + return c; + } +#endif + + // version optimized for 4 byte input. + static ub4 hash_DWORD(const DWORD in, const ub4 initval) + { + ub1 *const k = (ub1 *)∈ + ub4 a, b, c, len; + + /* Set up the internal state */ + len = 4; + a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + c = initval; /* the previous hash value */ + + /*------------------------------------- handle the last 11 bytes */ + c += 4; + a+=((ub4)k[3]<<24); + a+=((ub4)k[2]<<16); + a+=((ub4)k[1]<<8); + a+=k[0]; + + mix(a,b,c); + + /*-------------------------------------------- report the result */ + return c; + } + + + // ---------------------------------------------------------------------- + + struct BaseAddressLookup + { + DWORD64 keyAddress; // key + DWORD64 baseAddress; // value + }; + + static BaseAddressLookup * s_baseAddressCache; + static inline unsigned _baseAddressCachePageBits() { return 8; } + static inline unsigned _baseAddressCacheBits() { return _baseAddressCachePageBits() + 12; } + static inline unsigned _baseAddressCacheSize() { return 1 << (_baseAddressCacheBits()); } + static inline unsigned _baseAddressCacheElements() { return _baseAddressCacheSize() / sizeof(*s_baseAddressCache); } + static inline unsigned _baseAddressCacheMask() { return _baseAddressCacheElements() - 1; } + + static int s_baseAddressCacheMisses; + static int s_baseAddressCacheHits; + + static int s_baseAddressElements; + static int s_baseAddressUsed; + + /* + static void _baseAddressCacheAnalyze() + { + s_baseAddressElements=0; + s_baseAddressUsed=0; + + unsigned i; + const unsigned count = _baseAddressCacheElements(); + for (i=0;ibaseAddress) + { + s_baseAddressUsed++; + } + } + } + */ + + static DWORD64 _baseAddressLookup(DWORD64 addr) + { + BaseAddressLookup *lookup; + + unsigned long bits = _baseAddressCacheBits(); + + DWORD *addr32 = (DWORD *)&addr; + unsigned long hash32 = hash_DWORD(addr32[0], addr32[1]); + unsigned long hash = (hash32>>(32-bits)) ^ hash32; + + unsigned long mask = _baseAddressCacheMask(); + + unsigned long index = hash & mask; + lookup = s_baseAddressCache + index; + if (lookup->keyAddress==addr) + { + s_baseAddressCacheHits++; + //DEBUG_FATAL(symGetModuleBase64(process, addr) != lookup->baseAddress, ("Cache failure.\n")); + return lookup->baseAddress; + } + else + { + s_baseAddressCacheMisses++; + + DWORD64 baseAddress = symGetModuleBase64(process, addr); + + lookup->keyAddress=addr; + lookup->baseAddress=baseAddress; + + return baseAddress; + } + } + + static DWORD64 __stdcall getModuleBase(HANDLE hProcess, DWORD64 dwAddr) + { + UNREF(hProcess); + DEBUG_FATAL(hProcess!=process, ("Wrong process handle for module base lookup.\n")); + return _baseAddressLookup(dwAddr); + } + + // ---------------------------------------------------------------------- + struct FunctionTableLookup + { + DWORD64 keyAddress; // key + PVOID functionTable; // value + }; + + static FunctionTableLookup * s_functionTableCache; + static inline unsigned _functionTableCachePageBits() { return 4; } + static inline unsigned _functionTableCacheBits() { return _functionTableCachePageBits() + 12; } + static inline unsigned _functionTableCacheSize() { return 1 << (_functionTableCacheBits()); } + static inline unsigned _functionTableCacheElements() { return _functionTableCacheSize() / sizeof(*s_functionTableCache); } + static inline unsigned _functionTableCacheMask() { return _functionTableCacheElements() - 1; } + + static int s_functionTableCacheMisses; + static int s_functionTableCacheHits; + + + static PVOID _functionTableLookup(DWORD64 addr) + { + FunctionTableLookup *lookup; + + unsigned long bits = _functionTableCacheBits(); + + DWORD *addr32 = (DWORD *)&addr; + unsigned long hash32 = hash_DWORD(addr32[0], addr32[1]); + unsigned long hash = (hash32>>(32-bits)) ^ hash32; + + unsigned long mask = _functionTableCacheMask(); + + unsigned long index = hash & mask; + lookup = s_functionTableCache + index; + if (lookup->keyAddress==addr) + { + s_functionTableCacheHits++; + //DEBUG_FATAL(symFunctionTableAccess64(process, addr) != lookup->functionTable, ("Cache failure.\n")); + return lookup->functionTable; + } + else + { + s_functionTableCacheMisses++; + PVOID functionTable = symFunctionTableAccess64(process, addr); + lookup->keyAddress=addr; + lookup->functionTable=functionTable; + + return functionTable; + } + } + + static PVOID __stdcall functionTableAccess(HANDLE hProcess, DWORD64 dwAddr) + { + UNREF(hProcess); + DEBUG_FATAL(hProcess!=process, ("Wrong process handle for module base lookup.\n")); + return _functionTableLookup(DWORD(dwAddr)); + } + + // ---------------------------------------------------------------------- +} +using namespace DebugHelpNamespace; + +// ---------------------------------------------------------------------- + +BOOL CALLBACK loadSymbolsForDllCallback(PSTR ModuleName, DWORD64 ModuleBase, ULONG ModuleSize, PVOID UserContext) +{ + if (!library) + return false; + + CallbackData *callbackData = reinterpret_cast(UserContext); + + // see if this is the right file module and if we can load its symbol information + if (_stricmp(ModuleName, callbackData->name) == 0 && symLoadModule64(process, NULL, ModuleName, 0, ModuleBase, ModuleSize) != 0) + { + callbackData->loaded = true; + return FALSE; + } + + return TRUE; +} + +// ====================================================================== + +void DebugHelp::install() +{ + DEBUG_FATAL(library, ("DebugHelp already installed")); + + library = LoadLibrary("dbghelp_6.3.17.0.dll"); + if (library) + { + process = GetCurrentProcess(); + +#define GPA(a, b) a = reinterpret_cast(GetProcAddress(library, #b)); DEBUG_FATAL(!a, ("GetProcAddress failed for " #b)) + GPA(symSetOptions, SymSetOptions); + GPA(symInitialize, SymInitialize); + GPA(symCleanup, SymCleanup); + GPA(stackWalk64, StackWalk64); + GPA(symGetModuleInfo64, SymGetModuleInfo64); + GPA(symLoadModule64, SymLoadModule64); + GPA(symGetSymFromAddr64, SymGetSymFromAddr64); + GPA(symGetLineFromAddr64, SymGetLineFromAddr64); + GPA(symFunctionTableAccess64, SymFunctionTableAccess64); + GPA(symGetModuleBase64, SymGetModuleBase64); + GPA(symEnumerateModules64, SymEnumerateModules64); + GPA(enumerateLoadedModules64, EnumerateLoadedModules64); + GPA(miniDumpWriteDump, MiniDumpWriteDump); +#undef GPA + + IGNORE_RETURN(symSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES)); + + // get the path to the executable + char executableDirectory[MAX_PATH * 2]; + const DWORD result = GetModuleFileName(NULL, executableDirectory, sizeof(executableDirectory)); + FATAL(result == 0, ("GetModuleFileName failed")); + char * const slash = strrchr(executableDirectory, '\\'); + DEBUG_FATAL(!slash, ("Executable path does not contain a slash")); + *slash = '\0'; + + const BOOL result1 = symInitialize(process, executableDirectory, TRUE); + UNREF(result1); + DEBUG_FATAL(!result1, ("SymInitialize failed")); + + // ----------------------------------------------------------------------- + + s_baseAddressCache = (BaseAddressLookup *)VirtualAlloc(0, _baseAddressCacheSize(), MEM_COMMIT, PAGE_READWRITE); + + s_functionTableCache = (FunctionTableLookup *)VirtualAlloc(0, _functionTableCacheSize(), MEM_COMMIT, PAGE_READWRITE); + + // ----------------------------------------------------------------------- + } + + // Initialize the critical section one time only. + InitializeCriticalSection(&criticalSection); +} + +// ---------------------------------------------------------------------- + +void DebugHelp::remove() +{ + if (s_baseAddressCache) + { + VirtualFree(s_baseAddressCache, 0, MEM_RELEASE); + s_baseAddressCache=0; + } + + if (s_functionTableCache) + { + VirtualFree(s_functionTableCache, 0, MEM_RELEASE); + s_functionTableCache=0; + } + + if (library) + { + IGNORE_RETURN(symCleanup(process)); + IGNORE_RETURN(FreeLibrary(library)); + library = NULL; + process = NULL; + symSetOptions = NULL; + symInitialize = NULL; + symCleanup = NULL; + stackWalk64 = NULL; + symGetModuleInfo64 = NULL; + symLoadModule64 = NULL; + symGetSymFromAddr64 = NULL; + symGetLineFromAddr64 = NULL; + symFunctionTableAccess64 = NULL; + symGetModuleBase64 = NULL; + symEnumerateModules64 = NULL; + enumerateLoadedModules64 = NULL; + } + + // Release resources used by the critical section object. + DeleteCriticalSection(&criticalSection); +} + +// ---------------------------------------------------------------------- + +bool DebugHelp::loadSymbolsForDll(const char *name) +{ + if (!library) + return false; + + CallbackData callbackData = { name, false }; + enumerateLoadedModules64(process, (PENUMLOADED_MODULES_CALLBACK64)loadSymbolsForDllCallback, reinterpret_cast(&callbackData)); + return callbackData.loaded; +} + +// ---------------------------------------------------------------------- +#pragma warning (disable: 4740 4748) +void DebugHelp::getCallStack(uint32 *callStack, int sizeOfCallStack) +{ + { + for (int i = 0; i < sizeOfCallStack; ++i) + callStack[i] = 0; + } + + if (!library) + return; + + CONTEXT context; + Zero(context); + context.ContextFlags = CONTEXT_FULL; + + // GetThreadContext returns invalid data when called from within the same thread + //if (!GetThreadContext(GetCurrentThread(), &context)) + // return; + + EnterCriticalSection(&criticalSection); + __asm + { + call GetEIP + GetEIP: + pop eax + mov context.Eip, eax + mov context.Esp, esp + mov context.Ebp, ebp + } + LeaveCriticalSection(&criticalSection); + + STACKFRAME64 stackFrame; + Zero(stackFrame); + stackFrame.AddrPC.Mode = AddrModeFlat; + stackFrame.AddrPC.Offset = context.Eip; + stackFrame.AddrStack.Offset = context.Esp; + stackFrame.AddrStack.Mode = AddrModeFlat; + stackFrame.AddrFrame.Offset = context.Ebp; + stackFrame.AddrFrame.Mode = AddrModeFlat; + + for (int i = 0; i < sizeOfCallStack; ++i, ++callStack) + { + if (stackWalk64(IMAGE_FILE_MACHINE_I386, process, process, &stackFrame, &context, NULL, functionTableAccess, getModuleBase, NULL)) + { + const DWORD64 Offset = stackFrame.AddrPC.Offset; + *callStack = DWORD(Offset); + } + } +} + +// ---------------------------------------------------------------------- + +void DebugHelp::reportCallStack(int const maxStackDepth) +{ + // look up the call stack information + int const callStackOffset = 2; + int const callStackSize = callStackOffset + maxStackDepth; + uint32 * callStack = static_cast(_alloca((callStackOffset + maxStackDepth) * sizeof(uint32))); + getCallStack(callStack, callStackOffset + maxStackDepth); + + // look up the caller's file and line + if (callStack[callStackOffset]) + { + char lib[4 * 1024] = { '\0' }; + char file[4 * 1024] = { '\0' }; + int line = 0; + for (int i = callStackOffset; i < callStackSize; ++i) + { + if (callStack[i]) + { + if (lookupAddress(callStack[i], lib, file, sizeof(file), line)) + REPORT_LOG(true, ("\t%s(%d) : caller %d\n", file, line, i-callStackOffset)); + else + REPORT_LOG(true, ("\tunknown(0x%08X) : caller %d\n", static_cast(callStack[i]), i-callStackOffset)); + } + } + } +} + +// ---------------------------------------------------------------------- + +bool DebugHelp::lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line) +{ + UNREF(libName); + + if (!library) + return false; + + // make sure the image is loaded + IMAGEHLP_MODULE64 imageHelpModule; + Zero(imageHelpModule); + imageHelpModule.SizeOfStruct = sizeof(imageHelpModule); + if (!symGetModuleInfo64(process, address, &imageHelpModule)) + return false; + + // look up the symbol + const int MaxNameLength = 256; + char buffer[sizeof(IMAGEHLP_SYMBOL64) + MaxNameLength]; + memset(buffer, 0, sizeof(buffer)); + IMAGEHLP_SYMBOL64 *imageHelpSymbol = reinterpret_cast(buffer); + imageHelpSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + imageHelpSymbol->Address = address; + imageHelpSymbol->MaxNameLength = MaxNameLength; + { + DWORD64 displacement = 0; + if (!symGetSymFromAddr64(process, address, &displacement, imageHelpSymbol)) + { + return false; + } + } + + // look up the source file name and line number + IMAGEHLP_LINE64 imageHelpLine; + Zero(imageHelpLine); + imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); + { + DWORD displacement = 0; + if (!symGetLineFromAddr64(process, address, &displacement, &imageHelpLine)) + { + return false; + } + } + + // return the results + strncpy(fileName, imageHelpLine.FileName, static_cast(fileNameLength)); + line = static_cast(imageHelpLine.LineNumber); + return true; +} + +// ---------------------------------------------------------------------- + +bool DebugHelp::writeMiniDump(char const *miniDumpFileName, PEXCEPTION_POINTERS exceptionPointers) +{ + if (!miniDumpWriteDump) + return false; + + char buffer[256]; + if (!miniDumpFileName) + { + // get the program name + char programName[512]; + DWORD result = GetModuleFileName(NULL, programName, sizeof(programName)); + if (result == 0) + return false; + + // get the file name without the path + const char *shortProgramName = strrchr(programName, '\\'); + if (shortProgramName) + ++shortProgramName; + else + shortProgramName = programName; + + // lop off the extension + char *dot = const_cast(strchr(shortProgramName, '.')); + if (dot) + *dot = '\0'; + + // create a reasonable minidump filename + snprintf(buffer, sizeof(buffer), "%s_%d.mdmp", shortProgramName, static_cast(GetCurrentProcessId())); + miniDumpFileName = buffer; + } + + // create the file + HANDLE const file = CreateFile(miniDumpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL); + if (file == INVALID_HANDLE_VALUE) + return false; + + // create the exception information + MINIDUMP_EXCEPTION_INFORMATION exceptionInformationData; + MINIDUMP_EXCEPTION_INFORMATION *exceptionInformation = 0; + if (exceptionPointers) + { + exceptionInformationData.ThreadId = GetCurrentThreadId(); + exceptionInformationData.ExceptionPointers = exceptionPointers; + exceptionInformationData.ClientPointers = true; + exceptionInformation = &exceptionInformationData; + } + + // @todo make the minidump style modifiable + BOOL const result = miniDumpWriteDump(process, GetCurrentProcessId(), file, MiniDumpNormal, exceptionInformation, NULL, NULL); + + // close the file + CloseHandle(file); + + return result ? true : false; +} + +// ====================================================================== diff --git a/engine/shared/library/sharedDebug/src/win32/DebugHelp.h b/engine/shared/library/sharedDebug/src/win32/DebugHelp.h new file mode 100755 index 00000000..ead64d75 --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/DebugHelp.h @@ -0,0 +1,35 @@ +// ====================================================================== +// +// DebugHelp.h +// copyright 2000 Verant Interactive +// +// ====================================================================== + +#ifndef DEBUG_HELP_H +#define DEBUG_HELP_H + +// ====================================================================== + +typedef unsigned long uint32; + +// ====================================================================== + +class DebugHelp +{ +public: + + static void install(); + static void remove(); + + static bool loadSymbolsForDll(const char *name); + + static void getCallStack(uint32 *callStack, int sizeOfCallStack); + static void reportCallStack(int const maxStackDepth = 4); + static bool lookupAddress(uint32 address, char *libName, char *fileName, int fileNameLength, int &line); + + static bool writeMiniDump(char const *miniDumpFileName=0, PEXCEPTION_POINTERS exceptionPointers=0); +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedDebug/src/win32/DebugMonitor.cpp b/engine/shared/library/sharedDebug/src/win32/DebugMonitor.cpp new file mode 100755 index 00000000..ebc7b249 --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/DebugMonitor.cpp @@ -0,0 +1,321 @@ +// ====================================================================== +// +// DebugMonitor.cpp +// copyright 1998 Bootprint Entertainment +// copyright 2001-2004 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedDebug/FirstSharedDebug.h" +#include "sharedDebug/DebugMonitor.h" + +#if PRODUCTION == 0 + +#include "sharedDebug/DebugFlags.h" +#include "sharedFoundation/ConfigFile.h" + +// ====================================================================== + +namespace DebugMonitorNamespace +{ + typedef void (*ChangedWindowCallback)(int x, int y, int width, int height); + + typedef bool (*InstallFunction)(int x, int y, int width, int height); + typedef void (*RemoveFunction)(); + typedef void (*ShowFunction)(); + typedef void (*HideFunction)(); + typedef void (*SetChangedWindowCallback)(ChangedWindowCallback); + typedef void (*SetBehindWindowFunction)(HWND window); + typedef void (*ClearScreenFunction)(); + typedef void (*ClearToCursorFunction)(); + typedef void (*GotoXYFunction)(int x, int y); + typedef void (*PrintFunction)(const char *string); + + void changedWindowCallback(int x, int y, int width, int height); + + HINSTANCE dll; + HKEY registryKey = HKEY_CLASSES_ROOT; + RemoveFunction removeFunction; + ShowFunction showFunction; + HideFunction hideFunction; + SetBehindWindowFunction setBehindWindowFunction; + ClearScreenFunction clearScreenFunction; + ClearToCursorFunction clearToCursorFunction; + GotoXYFunction gotoXYFunction; + PrintFunction printFunction; + + bool noClear; + + int GetRegistryValue(char const * name, int defaultValue) + { + int value; + DWORD type = 0; + DWORD size = sizeof(DWORD); + LONG result = RegQueryValueEx(registryKey, name, NULL, &type, reinterpret_cast(&value), &size); + if ((result != ERROR_SUCCESS || type != REG_DWORD) && (size != sizeof(int))) + value = defaultValue; + return value; + } + + void SetRegistryValue(char const * name, int value) + { + RegSetValueEx(registryKey, name, NULL, REG_DWORD, reinterpret_cast(&value), sizeof(int)); + } +} +using namespace DebugMonitorNamespace; + +// ====================================================================== +// Install the debug monitor subsystem +// +// Remarks: +// +// This routine will first attempt to install the selected debug monitor. + +void DebugMonitor::install() +{ + dll = LoadLibrary("debugWindow.dll"); + if (dll) + { + InstallFunction installFunction = reinterpret_cast(GetProcAddress(dll, "install")); + + RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Sony Online Entertainment\\DebugWindow", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, ®istryKey, NULL); + + int const x = ConfigFile::getKeyInt("SharedDebug", "debugWindowX", GetRegistryValue("x", 0)); + int const y = ConfigFile::getKeyInt("SharedDebug", "debugWindowY", GetRegistryValue("y", 0)); + int const width = ConfigFile::getKeyInt("SharedDebug", "debugWindowWidth", GetRegistryValue("width", 80)); + int const height = ConfigFile::getKeyInt("SharedDebug", "debugWindowHeight", GetRegistryValue("height", 50)); + + if (installFunction && installFunction(x, y, width, height)) + { + showFunction = reinterpret_cast(GetProcAddress(dll, "showWindow")); + hideFunction = reinterpret_cast(GetProcAddress(dll, "hideWindow")); + removeFunction = reinterpret_cast(GetProcAddress(dll, "remove")); + setBehindWindowFunction = reinterpret_cast(GetProcAddress(dll, "setBehindWindow")); + clearScreenFunction = reinterpret_cast(GetProcAddress(dll, "clearScreen")); + clearToCursorFunction = reinterpret_cast(GetProcAddress(dll, "clearToCursor")); + gotoXYFunction = reinterpret_cast(GetProcAddress(dll, "gotoXY")); + printFunction = reinterpret_cast(GetProcAddress(dll, "print")); + + SetChangedWindowCallback setChangedWindowCallback = reinterpret_cast(GetProcAddress(dll, "setChangedWindowCallback")); + if (setChangedWindowCallback) + (*setChangedWindowCallback)(changedWindowCallback); + + DebugFlags::registerFlag(noClear, "SharedDebug", "noDebugMonitorClear"); + + if (ConfigFile::getKeyBool("SharedDebug", "debugWindow", false)) + show(); + } + else + { + installFunction = NULL; + const BOOL result = FreeLibrary(dll); + dll = NULL; + UNREF(result); + DEBUG_FATAL(!result, ("FreeLibrary failed")); + } + } +} + +// ---------------------------------------------------------------------- +/** + * Remove the debug monitor subsystem. + */ + +void DebugMonitor::remove() +{ + if (removeFunction) + removeFunction(); + + removeFunction = NULL; + setBehindWindowFunction = NULL; + clearScreenFunction = NULL; + clearToCursorFunction = NULL; + gotoXYFunction = NULL; + printFunction = NULL; + + if (dll) + { + const BOOL result = FreeLibrary(dll); + UNREF(result); + DEBUG_FATAL(!result, ("FreeLibrary failed")); + dll = NULL; + + if (registryKey != HKEY_CLASSES_ROOT) + { + RegCloseKey(registryKey); + registryKey = HKEY_CLASSES_ROOT; + } + } +} + +// ---------------------------------------------------------------------- + +void DebugMonitorNamespace::changedWindowCallback(int const x, int const y, int const width, int const height) +{ + SetRegistryValue("x", x); + SetRegistryValue("y", y); + SetRegistryValue("width", width); + SetRegistryValue("height", height); +} + +// ---------------------------------------------------------------------- + +void DebugMonitor::show() +{ + if (showFunction) + (*showFunction)(); +} + +// ---------------------------------------------------------------------- + +void DebugMonitor::hide() +{ + if (hideFunction) + (*hideFunction)(); +} + +// ---------------------------------------------------------------------- +/** + * Set the debug window's z-order. + */ + +void DebugMonitor::setBehindWindow(HWND window) +{ + if (setBehindWindowFunction) + setBehindWindowFunction(window); +} + +// ---------------------------------------------------------------------- +/** + * Clear the debug monitor and home the cursor. + * + * If the mono monitor is not installed, this routine does nothing. + * + * This routine will clear the contents of the debug monitor, reset the screen + * offset to 0, and move the cursor to the upper left corner of the screen. + * + * @see DebugMonitor::home(), DebugMonitor::clearToCursor() + */ + +void DebugMonitor::clearScreen() +{ + if (noClear) + return; + + if (clearScreenFunction) + clearScreenFunction(); +} + +// ---------------------------------------------------------------------- +/** + * Clear the debug monitor to the current cursor position and home the cursor. + * + * If the debug monitor is not installed, this routine does nothing. + * + * This routine will clear the contents of the debug monitor only up to the + * cursor position. If the cursor is not very far down on the screen, + * this routine may be significantly more efficient clearing the screen. + * + * It will also move the cursor to the upper left corner of the screen. + * + * @see DebugMonitor::clearScreen(), DebugMonitor::home() + */ + +void DebugMonitor::clearToCursor() +{ + if (clearToCursorFunction) + clearToCursorFunction(); + else + clearScreen(); +} + +// ====================================================================== +// Move the cursor to the upper left hand corner of the mono monitor screen +// +// Remarks: +// +// If the debug monitor is not installed, this routine does nothing. +// +// All printing happens at the cursor position. +// +// This routine is identical to calling gotoXY(0,0); +// +// See Also: +// +// DebugMonitor::gotoXY() + +void DebugMonitor::home() +{ + gotoXY(0,0); +} + +// ---------------------------------------------------------------------- +/** + * Position the cursor on the debug monitor screen. + * + * If the debug monitor is not installed, this routine does nothing. + * + * All printing happens at the cursor position. + * + * @param x New X position for the cursor + * @param y New Y position for the cursor + */ + +void DebugMonitor::gotoXY(int x, int y) +{ + if (gotoXYFunction) + gotoXYFunction(x, y); +} + +// ---------------------------------------------------------------------- +/** + * Display a string on the debug monitor. + * + * If the debug monitor is not installed, this routine does nothing. + * + * Printing occurs from the cursor position. + * + * Newline characters '\n' will cause the cursor position to advance to the + * beginning of the next line. If the cursor is already on the last line of + * the screen, the screen will scroll up one line and the cursor will move to + * the beginning of the last line. + * + * The backspace character '\b' will cause the cursor to move one character + * backwards. If at the beginning of the line, the cursor will move to the + * end of the previous line. If already on the first line of the screen, the + * cursor position and screen contents will be unchanged. + * + * All other characters are placed directly into the text frame buffer. + * After each character, the cursor will be logically advanced one + * character forward. If the cursor was on the last column, it will advance + * to the next line. If the cursor was already on the last line, the screen + * will be scrolled up one line and the cursor will move to the beginning of + * the last line. + * + * @param string String to display on the debug monitor + */ + +void DebugMonitor::print(const char *string) +{ + if (printFunction) + printFunction(string); +} + +// ---------------------------------------------------------------------- +/** + * Ensure all changes to the DebugMonitor have taken effect by the time + * this function returns. + * + * Note: some platforms may do nothing here. The Win32 platform does not + * require flushing. The Linux platform does. Call it assuming + * that it is needed. It will be a no-op when not required. + */ + +void DebugMonitor::flushOutput() +{ + // Win32 debug monitors don't need to do anything here. +} + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedDebug/src/win32/DebugMonitor.h b/engine/shared/library/sharedDebug/src/win32/DebugMonitor.h new file mode 100755 index 00000000..c992ed11 --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/DebugMonitor.h @@ -0,0 +1,48 @@ +// ====================================================================== +// +// DebugMonitor.h +// +// Portions copyright 1998 Bootprint Entertainment +// Portions copyright 2002-2004 Sony Online Entertainment +// All Rights Reserved. +// +// ====================================================================== + +#ifndef INCLUDED_DebugMonitor_H +#define INCLUDED_DebugMonitor_H + +// ====================================================================== + +#include "sharedFoundation/Production.h" + +// ====================================================================== + +#if PRODUCTION == 0 + +class DebugMonitor +{ +public: + + static void install(); + static void remove(); + + static void setBehindWindow(HWND window); + + static void show(); + static void hide(); + + static void clearScreen(); + static void clearToCursor(); + + static void home(); + static void gotoXY(int x, int y); + static void print(const char *string); + + static void flushOutput(); +}; + +#endif + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedDebug/src/win32/FirstSharedDebug.cpp b/engine/shared/library/sharedDebug/src/win32/FirstSharedDebug.cpp new file mode 100755 index 00000000..ee53a32e --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/FirstSharedDebug.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstDebug.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "shareddebug/FirstSharedDebug.h" diff --git a/engine/shared/library/sharedDebug/src/win32/PerformanceTimer.cpp b/engine/shared/library/sharedDebug/src/win32/PerformanceTimer.cpp new file mode 100755 index 00000000..be770b7f --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/PerformanceTimer.cpp @@ -0,0 +1,105 @@ +// +// PerformanceTimer.cpp +// Copyright 2000-2004 Sony Online Entertainment +// + +//------------------------------------------------------------------- + +#include "shareddebug/FirstSharedDebug.h" +#include "shareddebug/PerformanceTimer.h" + +//------------------------------------------------------------------- + +#include + +//------------------------------------------------------------------- + +__int64 PerformanceTimer::ms_frequency; + +//------------------------------------------------------------------- + +void PerformanceTimer::install() +{ + BOOL result = QueryPerformanceFrequency(reinterpret_cast(&ms_frequency)); + FATAL(!result, ("PerformanceTimer::install QPF failed")); +} + +//------------------------------------------------------------------- + +PerformanceTimer::PerformanceTimer() : + m_startTime (0), + m_stopTime (0) +{ + DEBUG_FATAL (ms_frequency == 0.f, ("PerformanceTimer not installed")); +} + +//------------------------------------------------------------------- + +PerformanceTimer::~PerformanceTimer() +{ +} + +//------------------------------------------------------------------- + +void PerformanceTimer::start() +{ + //-- get the current time + BOOL result = QueryPerformanceCounter(reinterpret_cast(&m_startTime)); + DEBUG_FATAL(!result, ("PerformanceTimer::start QPC failed")); + UNREF (result); +} + +//------------------------------------------------------------------- + +void PerformanceTimer::resume() +{ + __int64 delta = m_stopTime - m_startTime; + start(); + m_startTime -= delta; +} + +//------------------------------------------------------------------- + +void PerformanceTimer::stop () +{ + //-- get the current time + BOOL result = QueryPerformanceCounter(reinterpret_cast(&m_stopTime)); + DEBUG_FATAL(!result, ("PerformanceTimer::stop QPC failed")); + UNREF (result); +} + +//------------------------------------------------------------------- + +float PerformanceTimer::getElapsedTime() const +{ + return static_cast (m_stopTime - m_startTime) / static_cast (ms_frequency); +} + +// ---------------------------------------------------------------------- + +float PerformanceTimer::getSplitTime() const +{ + __int64 currentTime; + BOOL result = QueryPerformanceCounter(reinterpret_cast(¤tTime)); + UNREF(result); + DEBUG_FATAL(!result, ("PerformanceTimer::getSplitTime QPC failed")); + + return static_cast (currentTime - m_startTime) / static_cast (ms_frequency); +} + +//------------------------------------------------------------------- + +void PerformanceTimer::logElapsedTime(const char* string) const +{ + UNREF (string); + +#ifdef _DEBUG + static char buffer [1000]; + sprintf (buffer, "%s : %1.5f seconds\n", string ? string : "null", getElapsedTime()); + DEBUG_REPORT_LOG_PRINT (true, ("%s", buffer)); + DEBUG_OUTPUT_CHANNEL("Foundation\\PerformanceTimer", ("%s", buffer)); +#endif +} + +//------------------------------------------------------------------- + diff --git a/engine/shared/library/sharedDebug/src/win32/PerformanceTimer.h b/engine/shared/library/sharedDebug/src/win32/PerformanceTimer.h new file mode 100755 index 00000000..0fda7c1a --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/PerformanceTimer.h @@ -0,0 +1,49 @@ +// +// PerformanceTimer.h +// Copyright 2000-2004 Sony Online Entertainment +// + +//------------------------------------------------------------------- + +#ifndef INCLUDED_PerformanceTimer_H +#define INCLUDED_PerformanceTimer_H + +//------------------------------------------------------------------- + +class PerformanceTimer +{ +public: + + static void install(); + +public: + + DLLEXPORT PerformanceTimer(); + DLLEXPORT ~PerformanceTimer(); + + void DLLEXPORT start(); + void DLLEXPORT resume(); + void DLLEXPORT stop(); + + float DLLEXPORT getElapsedTime() const; + float getSplitTime() const; // Get the time since the timer was started without stopping the timer. + void logElapsedTime(const char* string) const; + +private: + + PerformanceTimer(PerformanceTimer const &); + PerformanceTimer & operator=(PerformanceTimer const &); + +private: + + static __int64 ms_frequency; + +private: + + __int64 m_startTime; + __int64 m_stopTime; +}; + +//------------------------------------------------------------------- + +#endif \ No newline at end of file diff --git a/engine/shared/library/sharedDebug/src/win32/ProfilerTimer.cpp b/engine/shared/library/sharedDebug/src/win32/ProfilerTimer.cpp new file mode 100755 index 00000000..774765a6 --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/ProfilerTimer.cpp @@ -0,0 +1,90 @@ +// ====================================================================== +// +// ProfilerTimer.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "shareddebug/FirstSharedDebug.h" +#include "shareddebug/ProfilerTimer.h" + +#include "shareddebug/DebugFlags.h" +#include "sharedFoundation/WindowsWrapper.h" + +// ====================================================================== + +namespace ProfilerTimerNamespace +{ + ProfilerTimer::Type ms_qpcFrequency; + float ms_floatQpcFrequency; + __int64 ms_rdtsc; + __int64 ms_qpc; + bool ms_useRdtsc; + +} +using namespace ProfilerTimerNamespace; + +// ====================================================================== + +static __int64 __declspec(naked) __stdcall readTimeStampCounter() +{ + __asm + { + rdtsc; + ret; + } +} + +// ====================================================================== + +void ProfilerTimer::install() +{ + IGNORE_RETURN(QueryPerformanceCounter(reinterpret_cast(&ms_qpc))); + ms_rdtsc = readTimeStampCounter(); + + IGNORE_RETURN(QueryPerformanceFrequency(reinterpret_cast(&ms_qpcFrequency))); + ms_floatQpcFrequency = static_cast(ms_qpcFrequency); + + DebugFlags::registerFlag(ms_useRdtsc, "SharedDebug/Profiler", "useRdtsc"); +} + +// ---------------------------------------------------------------------- + +void ProfilerTimer::getTime(Type &time) +{ + if (ms_useRdtsc) + time = readTimeStampCounter(); + else + IGNORE_RETURN(QueryPerformanceCounter(reinterpret_cast(&time))); +} + +// ---------------------------------------------------------------------- + +void ProfilerTimer::getCalibratedTime(Type &time, Type &frequency) +{ + if (ms_useRdtsc) + { + __int64 qpc; + IGNORE_RETURN(QueryPerformanceCounter(reinterpret_cast(&qpc))); + __int64 rdtsc = readTimeStampCounter(); + + float const t = static_cast(qpc - ms_qpc) / ms_floatQpcFrequency; + frequency = static_cast<__int64>(static_cast(rdtsc - ms_rdtsc) / t); + + time = rdtsc; + ms_qpc = qpc; + ms_rdtsc = time; + } + else + { + IGNORE_RETURN(QueryPerformanceCounter(reinterpret_cast(&time))); + frequency = ms_qpcFrequency; + } +} + +void ProfilerTimer::getFrequency(Type &frequency) +{ + frequency = ms_qpcFrequency; +} + +// ====================================================================== diff --git a/engine/shared/library/sharedDebug/src/win32/ProfilerTimer.h b/engine/shared/library/sharedDebug/src/win32/ProfilerTimer.h new file mode 100755 index 00000000..fe1b8f9a --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/ProfilerTimer.h @@ -0,0 +1,29 @@ +// ====================================================================== +// +// ProfilerTimer.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_ProfilerTimer_H +#define INCLUDED_ProfilerTimer_H + +// ====================================================================== + +class ProfilerTimer +{ +public: + + typedef __int64 Type; + +public: + + static void install(); + static void getTime(Type &time); + static void getCalibratedTime(Type &time, Type &frequency); + static void getFrequency(Type &frequency); +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedDebug/src/win32/VTune.cpp b/engine/shared/library/sharedDebug/src/win32/VTune.cpp new file mode 100755 index 00000000..6b876fff --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/VTune.cpp @@ -0,0 +1,142 @@ +// ====================================================================== +// +// VTune.cpp +// Copyright 2000-01, Sony Online Entertainment Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "sharedDebug/FirstSharedDebug.h" +#include "sharedDebug/VTune.h" + +#if PRODUCTION == 0 + +#include "sharedDebug/DebugFlags.h" + +#include + +// ====================================================================== + +HMODULE VTune::ms_module; +VTune::PauseFunction VTune::ms_pauseFunction; +VTune::ResumeFunction VTune::ms_resumeFunction; +VTune::State VTune::ms_state; +bool VTune::ms_resumeNextFrame; +bool VTune::ms_pauseNextFrame; +bool VTune::ms_debugReport; + +// ====================================================================== + +void VTune::install() +{ + DEBUG_FATAL(ms_module, ("vtune already installed")); + + ms_module = LoadLibrary("VTuneAPI"); + if (!ms_module) + return; + + ms_pauseFunction = reinterpret_cast(GetProcAddress(ms_module, "VTPause")); + ms_resumeFunction = reinterpret_cast(GetProcAddress(ms_module, "VTResume")); + ms_state = S_default; + +#if PRODUCTION == 0 + DebugFlags::registerFlag(ms_debugReport, "SharedDebug", "vtuneState", debugReport); +#endif +} + +// ---------------------------------------------------------------------- + +void VTune::remove() +{ + if (ms_module) + { + FreeLibrary(ms_module); + ms_pauseFunction = 0; + ms_resumeFunction = 0; + } +} + +// ---------------------------------------------------------------------- + +void VTune::debugReport() +{ + switch (ms_state) + { + case S_default: + REPORT_PRINT(true, ("Vtune state unknown\n")); + break; + + case S_sampling: + REPORT_PRINT(true, ("Vtune is sampling\n")); + break; + + case S_paused: + REPORT_PRINT(true, ("Vtune is NOT sampling\n")); + break; + + default: + DEBUG_FATAL(true, ("bad case")); + + } +} + +// ---------------------------------------------------------------------- + +void VTune::resume() +{ + if (ms_module && ms_resumeFunction) + { + MessageBeep(MB_OK); + (*ms_resumeFunction)(); + ms_state = S_sampling; + } +} + +// ---------------------------------------------------------------------- + +void VTune::pause() +{ + if (ms_module && ms_pauseFunction) + { + (*ms_pauseFunction)(); + MessageBeep(MB_ICONEXCLAMATION); + ms_state = S_paused; + } +} + +// ---------------------------------------------------------------------- + +void VTune::pauseNextFrame() +{ + ms_pauseNextFrame = true; + ms_resumeNextFrame = false; +} + +// ---------------------------------------------------------------------- + +void VTune::resumeNextFrame() +{ + ms_pauseNextFrame = false; + ms_resumeNextFrame = true; +} + +// ---------------------------------------------------------------------- + +void VTune::beginFrame() +{ + if (ms_pauseNextFrame) + { + pause(); + ms_pauseNextFrame = false; + } + + if (ms_resumeNextFrame) + { + resume(); + ms_resumeNextFrame = false; + } +} + +// ====================================================================== + +#endif // PRODUCTION == 0 diff --git a/engine/shared/library/sharedDebug/src/win32/VTune.h b/engine/shared/library/sharedDebug/src/win32/VTune.h new file mode 100755 index 00000000..31125646 --- /dev/null +++ b/engine/shared/library/sharedDebug/src/win32/VTune.h @@ -0,0 +1,65 @@ +// ====================================================================== +// +// VTune.h +// Copyright 2000-01, Sony Online Entertainment Inc. +// All Rights Reserved. +// +// ====================================================================== + +#ifndef INCLUDED_VTune_H +#define INCLUDED_VTune_H + +// ====================================================================== + +#include "sharedFoundation/Production.h" + +// ====================================================================== + +#if PRODUCTION == 0 + +class VTune +{ +public: + + static void install(); + + static void resume(); + static void pause(); + + static void resumeNextFrame(); + static void pauseNextFrame(); + static void beginFrame(); + +private: + + static void remove(); + static void debugReport(); + +private: + + enum State + { + S_default, + S_sampling, + S_paused + }; + + typedef void (__cdecl *PauseFunction)(void); + typedef void (__cdecl *ResumeFunction)(void); + +private: + + static HMODULE ms_module; + static PauseFunction ms_pauseFunction; + static ResumeFunction ms_resumeFunction; + static State ms_state; + static bool ms_resumeNextFrame; + static bool ms_pauseNextFrame; + static bool ms_debugReport; +}; + +#endif // PRODUCTION == 0 + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFile/src/win32/FirstSharedFile.cpp b/engine/shared/library/sharedFile/src/win32/FirstSharedFile.cpp new file mode 100755 index 00000000..038a7931 --- /dev/null +++ b/engine/shared/library/sharedFile/src/win32/FirstSharedFile.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstFile.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedFile/FirstSharedFile.h" diff --git a/engine/shared/library/sharedFile/src/win32/OsFile.cpp b/engine/shared/library/sharedFile/src/win32/OsFile.cpp new file mode 100755 index 00000000..64acc1a7 --- /dev/null +++ b/engine/shared/library/sharedFile/src/win32/OsFile.cpp @@ -0,0 +1,195 @@ +// ====================================================================== +// +// OsFile.cpp +// Copyright 2002, Sony Online Entertainment Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "sharedFile/FirstSharedFile.h" +#include "sharedFile/OsFile.h" + +#ifdef _DEBUG +#include "sharedDebug/PerformanceTimer.h" +#endif + +namespace OsFileNamespace +{ + float ms_time; +} +using namespace OsFileNamespace; + +// ====================================================================== + +void OsFile::install() +{ + +} + +// ---------------------------------------------------------------------- + +float OsFile::getSpentTime() +{ + float const result = ms_time; + ms_time = 0.0f; + return result; +} + +// ---------------------------------------------------------------------- + +bool OsFile::exists(const char *fileName) +{ + NOT_NULL(fileName); + DWORD attributes = GetFileAttributes(fileName); + +#if _MSC_VER < 1300 + const DWORD INVALID_FILE_ATTRIBUTES = 0xffffffff; +#endif + return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0); +} + +// ---------------------------------------------------------------------- + +int OsFile::getFileSize(const char *fileName) +{ + NOT_NULL(fileName); + +#ifdef _DEBUG + PerformanceTimer t; + t.start(); +#endif + + HANDLE handle = CreateFile(fileName, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) + return -1; + + int const size = GetFileSize(handle, NULL); + CloseHandle(handle); + +#ifdef _DEBUG + t.stop(); + ms_time += t.getElapsedTime(); +#endif + return size; +} + +// ---------------------------------------------------------------------- + +OsFile *OsFile::open(const char *fileName, bool randomAccess) +{ +#ifdef _DEBUG + PerformanceTimer t; + t.start(); +#endif + + // attempt to open the file + HANDLE handle = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | (randomAccess ? FILE_FLAG_RANDOM_ACCESS : 0), NULL); + + // check to make sure the file opened sucessfully + if (handle == INVALID_HANDLE_VALUE) + return NULL; + +#ifdef _DEBUG + t.stop(); + ms_time += t.getElapsedTime(); +#endif + + return new OsFile(handle); +} + +// ---------------------------------------------------------------------- + +OsFile::OsFile(HANDLE handle) +: m_handle(handle), + m_offset(0) +{ +} + +// ---------------------------------------------------------------------- + +OsFile::~OsFile() +{ +#ifdef _DEBUG + PerformanceTimer t; + t.start(); +#endif + + CloseHandle(m_handle); + +#ifdef _DEBUG + t.stop(); + ms_time+= t.getElapsedTime(); +#endif +} + +// ---------------------------------------------------------------------- + +int OsFile::length() const +{ + return GetFileSize(m_handle, NULL); +} + +// ---------------------------------------------------------------------- + +void OsFile::seek(int newFilePosition) +{ +#ifdef _DEBUG + PerformanceTimer t; + t.start(); +#endif + + if (m_offset != newFilePosition) + { + const DWORD result = SetFilePointer(m_handle, newFilePosition, NULL, FILE_BEGIN); + DEBUG_FATAL(static_cast(result) != newFilePosition, ("SetFilePointer failed")); + UNREF(result); + m_offset = newFilePosition; + } + +#ifdef _DEBUG + t.stop(); + ms_time += t.getElapsedTime(); +#endif +} + +// ---------------------------------------------------------------------- + +int OsFile::read(void *destinationBuffer, int numberOfBytes) +{ +#ifdef _DEBUG + PerformanceTimer t; + t.start(); +#endif + + DWORD amountReadDword; + BOOL result = ReadFile(m_handle, destinationBuffer, static_cast(numberOfBytes), &amountReadDword, NULL); + +// miles crasher hack +#if 0 + FATAL(!result, ("FileStreamerThread::processRead ReadFile failed to read '%d' bytes with error '%d'", static_cast(numberOfBytes), GetLastError())); +#else + if(!result) + { + if(GetLastError() == 998) // access violation - buffer coming from miles hosed + { + WARNING(true,("FileStreamerThread::processRead ReadFile failed to read '%d' bytes with error '%d'", static_cast(numberOfBytes), GetLastError())); + return 0; + } + else + { + FATAL(true, ("FileStreamerThread::processRead ReadFile failed to read '%d' bytes with error '%d'", static_cast(numberOfBytes), GetLastError())); + } + } +#endif +// end miles crasher hack + +#ifdef _DEBUG + t.stop(); + ms_time += t.getElapsedTime(); +#endif + + m_offset += static_cast(amountReadDword); + return static_cast(amountReadDword); +} + +// ====================================================================== diff --git a/engine/shared/library/sharedFile/src/win32/OsFile.h b/engine/shared/library/sharedFile/src/win32/OsFile.h new file mode 100755 index 00000000..1f3e6ba9 --- /dev/null +++ b/engine/shared/library/sharedFile/src/win32/OsFile.h @@ -0,0 +1,48 @@ +// ====================================================================== +// +// OsFile.h +// Copyright 2002, Sony Online Entertainment Inc. +// All Rights Reserved. +// +// ====================================================================== + +#ifndef INCLUDED_OsFile_H +#define INCLUDED_OsFile_H + +// ====================================================================== + +class OsFile +{ +public: + + static void install(); + + static float getSpentTime(); + + static bool exists(const char *fileName); + static int getFileSize(const char *fileName); + static OsFile *open(const char *fileName, bool randomAccess=false); + +public: + + ~OsFile(); + + int length() const; + int tell() const; + void seek(int newFilePosition); + int read(void *destinationBuffer, int numberOfBytes); + +private: + + OsFile(HANDLE handle); + OsFile(const char *fileName); + +private: + + HANDLE m_handle; + int m_offset; +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/ByteOrder.cpp b/engine/shared/library/sharedFoundation/src/win32/ByteOrder.cpp new file mode 100755 index 00000000..12add8e5 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/ByteOrder.cpp @@ -0,0 +1,58 @@ +// ====================================================================== +// +// ByteOrder.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedFoundation/ByteOrder.h" + +// ====================================================================== + +// I'm using the arguments, but the compiler can't tell that +#pragma warning(disable: 4100) + +__declspec(naked) ulong ntohl(ulong netLong) +{ + _asm + { + mov eax, [esp+4] + bswap eax + ret + } +} //lint !e533 !e715 // function should return a value, argument not referenced + +__declspec(naked) ulong htonl(ulong hostLong) +{ + _asm + { + mov eax, [esp+4] + bswap eax + ret + } +} //lint !e533 !e715 // function should return a value, argument not referenced + +__declspec(naked) ushort ntohs(ushort netShort) +{ + _asm + { + mov eax, [esp+4] + bswap eax + shr eax, 16 + ret + } +} //lint !e533 !e715 // function should return a value, argument not referenced + +__declspec(naked) ushort htons(ushort hostShort) +{ + _asm + { + mov eax, [esp+4] + bswap eax + shr eax, 16 + ret + } +} //lint !e533 !e715 // function should return a value, argument not referenced + +// ====================================================================== diff --git a/engine/shared/library/sharedFoundation/src/win32/ByteOrder.h b/engine/shared/library/sharedFoundation/src/win32/ByteOrder.h new file mode 100755 index 00000000..4e478703 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/ByteOrder.h @@ -0,0 +1,22 @@ +// ====================================================================== +// +// ByteOrder.h +// copyright 1998 Bootprint Entertainment +// copyright 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef BYTE_ORDER_H +#define BYTE_ORDER_H + +// ====================================================================== + +ulong __cdecl ntohl(ulong netLong); +ushort __cdecl ntohs(ushort netShort); + +ulong __cdecl htonl(ulong hostLong); +ushort __cdecl htons(ushort hostShort); + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/ConfigSharedFoundation.cpp b/engine/shared/library/sharedFoundation/src/win32/ConfigSharedFoundation.cpp new file mode 100755 index 00000000..9498c256 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/ConfigSharedFoundation.cpp @@ -0,0 +1,324 @@ +// ====================================================================== +// +// ConfigSharedFoundation.cpp +// copyright 1998 Bootprint Entertainment +// copyright 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedFoundation/ConfigSharedFoundation.h" + +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/Production.h" + +// ====================================================================== + +#define KEY_INT(a,b) (ms_ ## a = ConfigFile::getKeyInt("SharedFoundation", #a, b)) +#define KEY_BOOL(a,b) (ms_ ## a = ConfigFile::getKeyBool("SharedFoundation", #a, b)) +#define KEY_FLOAT(a,b) (ms_ ## a = ConfigFile::getKeyFloat("SharedFoundation", #a, b)) +#define KEY_STRING(a,b) (ms_ ## a = ConfigFile::getKeyString("SharedFoundation", #a, b)) + +// ====================================================================== + +const int c_defaultFatalCallStackDepth = 32; +const int c_defaultWarningCallStackDepth = PRODUCTION ? -1 : 8; + +// ====================================================================== + +namespace ConfigSharedFoundationNamespace +{ + bool ms_noExceptionHandling; + + bool ms_fpuExceptionPrecision; + bool ms_fpuExceptionUnderflow; + bool ms_fpuExceptionOverflow; + bool ms_fpuExceptionZeroDivide; + bool ms_fpuExceptionDenormal; + bool ms_fpuExceptionInvalid; + + bool ms_demoMode; + + real ms_frameRateLimit; + real ms_minFrameRate; + + bool ms_useRemoteDebug; + int ms_defaultRemoteDebugPort; + + bool ms_profilerExpandAllBranches; + + bool ms_memoryManagerReportAllocations; + bool ms_memoryManagerReportOnOutOfMemory; + + bool ms_useMemoryBlockManager; + bool ms_memoryBlockManagerDebugDumpOnRemove; + + int ms_fatalCallStackDepth; + int ms_warningCallStackDepth; + bool ms_lookUpCallStackNames; + + int ms_processPriority; + + bool ms_verboseHardwareLogging; + bool ms_verboseWarnings; + + bool ms_causeAccessViolation; + + float ms_debugReportLongFrameTime; +} + +using namespace ConfigSharedFoundationNamespace; + +// ====================================================================== +// Determine the Platform-specific configuration information +// +// Remarks: +// +// This routine inspects the ConfigFile class to set some variables for rapid access +// by the rest of the engine. + +void ConfigSharedFoundation::install (const Defaults &defaults) +{ + KEY_BOOL(noExceptionHandling, false); + + KEY_BOOL(fpuExceptionPrecision, false); + KEY_BOOL(fpuExceptionUnderflow, false); + KEY_BOOL(fpuExceptionOverflow, false); + KEY_BOOL(fpuExceptionZeroDivide, false); + KEY_BOOL(fpuExceptionDenormal, false); + KEY_BOOL(fpuExceptionInvalid, false); + + KEY_BOOL(demoMode, defaults.demoMode); + +#if defined (WIN32) && PRODUCTION == 1 + // In production builds, force our frame rate limit to be the application defined limit + ms_frameRateLimit = defaults.frameRateLimit; +#else + KEY_FLOAT(frameRateLimit, defaults.frameRateLimit); +#endif + + KEY_FLOAT(minFrameRate, 1.0f); + + KEY_BOOL(useRemoteDebug, false); + KEY_INT(defaultRemoteDebugPort, 4445); + + KEY_BOOL(profilerExpandAllBranches, false); + KEY_BOOL(memoryManagerReportAllocations, true); + KEY_BOOL(memoryManagerReportOnOutOfMemory, true); + KEY_BOOL(useMemoryBlockManager, true); + KEY_BOOL(memoryBlockManagerDebugDumpOnRemove, false); + + KEY_INT(fatalCallStackDepth, c_defaultFatalCallStackDepth); + KEY_INT(warningCallStackDepth, PRODUCTION ? -1 : c_defaultWarningCallStackDepth); + KEY_BOOL(lookUpCallStackNames, true); + + KEY_INT(processPriority, 0); + + KEY_BOOL(verboseHardwareLogging, false); + KEY_BOOL(verboseWarnings, defaults.verboseWarnings); + + KEY_BOOL(causeAccessViolation, false); + + KEY_FLOAT(debugReportLongFrameTime, 0.25f); +} + +// ---------------------------------------------------------------------- +/** + * Return whether to run with exception handling enabled. + * + * @return True to run without exception handling + */ + +bool ConfigSharedFoundation::getNoExceptionHandling() +{ + return ms_noExceptionHandling; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getFpuExceptionPrecision() +{ + return ms_fpuExceptionPrecision; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getFpuExceptionUnderflow() +{ + return ms_fpuExceptionUnderflow; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getFpuExceptionOverflow() +{ + return ms_fpuExceptionOverflow; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getFpuExceptionZeroDivide() +{ + return ms_fpuExceptionZeroDivide; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getFpuExceptionDenormal() +{ + return ms_fpuExceptionDenormal; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getFpuExceptionInvalid() +{ + return ms_fpuExceptionInvalid; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getDemoMode() +{ + return ms_demoMode; +} + +// ---------------------------------------------------------------------- +/** + * Return the frame rate limit value for the game. + * + * @return The initial frame rate limiter value + */ + +real ConfigSharedFoundation::getFrameRateLimit() +{ + return ms_frameRateLimit; +} + +// ---------------------------------------------------------------------- +/** + * Return the minimum frame rate value for the game. Frames that take longer + * will log a warning and be hard set to the given value. + * + * @return The initial min frame rate value + */ + +real ConfigSharedFoundation::getMinFrameRate() +{ + return ms_minFrameRate; +} + +// ---------------------------------------------------------------------- + +int ConfigSharedFoundation::getDefaultRemoteDebugPort() +{ + return ms_defaultRemoteDebugPort; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getUseRemoteDebug() +{ + return ms_useRemoteDebug; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getProfilerExpandAllBranches() +{ + return ms_profilerExpandAllBranches; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getMemoryManagerReportAllocations() +{ + return ms_memoryManagerReportAllocations; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getMemoryManagerReportOnOutOfMemory() +{ + return ms_memoryManagerReportOnOutOfMemory; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getUseMemoryBlockManager() +{ + return ms_useMemoryBlockManager; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getMemoryBlockManagerDebugDumpOnRemove () +{ + return ms_memoryBlockManagerDebugDumpOnRemove; +} + +// ---------------------------------------------------------------------- + +int ConfigSharedFoundation::getFatalCallStackDepth() +{ + return ms_fatalCallStackDepth; +} + +// ---------------------------------------------------------------------- + +int ConfigSharedFoundation::getWarningCallStackDepth() +{ + return ms_warningCallStackDepth; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getLookUpCallStackNames() +{ + return ms_lookUpCallStackNames; +} + +// ---------------------------------------------------------------------- + +int ConfigSharedFoundation::getProcessPriority() +{ + return ms_processPriority; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getVerboseHardwareLogging() +{ + return ms_verboseHardwareLogging; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getVerboseWarnings() +{ + return ms_verboseWarnings; +} + +// ---------------------------------------------------------------------- + +void ConfigSharedFoundation::setVerboseWarnings(bool const verboseWarnings) +{ + ms_verboseWarnings = verboseWarnings; +} + +// ---------------------------------------------------------------------- + +bool ConfigSharedFoundation::getCauseAccessViolation() +{ + return ms_causeAccessViolation; +} + + +// ---------------------------------------------------------------------- + +float ConfigSharedFoundation::getDebugReportLongFrameTime() +{ + return ms_debugReportLongFrameTime; +} + +// ====================================================================== diff --git a/engine/shared/library/sharedFoundation/src/win32/ConfigSharedFoundation.h b/engine/shared/library/sharedFoundation/src/win32/ConfigSharedFoundation.h new file mode 100755 index 00000000..6efa3840 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/ConfigSharedFoundation.h @@ -0,0 +1,74 @@ +// ====================================================================== +// +// ConfigSharedFoundation.h +// copyright 1998 Bootprint Entertainment +// copyright 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_ConfigSharedFoundation_H +#define INCLUDED_ConfigSharedFoundation_H + +// ====================================================================== + +class ConfigSharedFoundation +{ +public: + + struct Defaults + { + int screenHeight; + int screenWidth; + bool windowed; + real frameRateLimit; + bool demoMode; + bool verboseWarnings; + }; + +public: + + static void install(const Defaults &defaults); + + static bool getNoExceptionHandling(); + + static bool getFpuExceptionPrecision(); + static bool getFpuExceptionUnderflow(); + static bool getFpuExceptionOverflow(); + static bool getFpuExceptionZeroDivide(); + static bool getFpuExceptionDenormal(); + static bool getFpuExceptionInvalid(); + + static bool getDemoMode(); + + static real getFrameRateLimit(); + static real getMinFrameRate(); + + static bool getUseRemoteDebug(); + static int getDefaultRemoteDebugPort(); + + static bool getProfilerExpandAllBranches(); + + static bool getMemoryManagerReportAllocations(); + static bool getMemoryManagerReportOnOutOfMemory(); + + static bool getUseMemoryBlockManager(); + static bool getMemoryBlockManagerDebugDumpOnRemove(); + + static int getFatalCallStackDepth(); + static int getWarningCallStackDepth(); + static bool getLookUpCallStackNames(); + + static int getProcessPriority(); + + static DLLEXPORT bool getVerboseHardwareLogging(); + static bool getVerboseWarnings(); + static void setVerboseWarnings(bool verboseWarnings); + + static bool getCauseAccessViolation(); + + static float getDebugReportLongFrameTime(); +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/FirstPlatform.h b/engine/shared/library/sharedFoundation/src/win32/FirstPlatform.h new file mode 100755 index 00000000..5a4d021a --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/FirstPlatform.h @@ -0,0 +1,82 @@ +// ====================================================================== +// +// FirstPlatform.h +// copyright 1998 Bootprint Entertainment +// copyright 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_FirstPlatform_H +#define INCLUDED_FirstPlatform_H + + +#ifdef WIN32 +#include +#include +#endif + +// ====================================================================== + +// C4127 conditional expression is constant +// C4291 no matching operator delete found; memory will not be freed if initialization throws an exception +// C4503 decorated name length exceeded, name was truncated +// C4514 unreferenced inline function has been removed +// C4702 unreachable code +// C4710 inline function not expanded +// C4786 identifier was truncated to 'number' characters in the debug + +#pragma warning(disable: 4127 4291 4503 4514 4702 4710 4786) + +// ====================================================================== +// If we haven't defined this yet, then we're not compiling a DLL + +#ifndef COMPILE_DLL +#define COMPILE_DLL 0 +#endif + +#if COMPILE_DLL +#define DLLEXPORT __declspec(dllimport) +#else +#define DLLEXPORT __declspec(dllexport) +#endif + +// ====================================================================== + +template +inline int ComGetReferenceCount(T *t) +{ + t->AddRef(); + return t->Release(); +} + +// ====================================================================== +// forward declare some windows stuff to avoid having to include here + +struct HCURSOR__; +struct HICON__; +struct HINSTANCE__; +struct HWND__; + +typedef void *HANDLE; +typedef HICON__ *HCURSOR; +typedef HICON__ *HICON; +typedef HINSTANCE__ *HINSTANCE; +typedef HWND__ *HWND; + +// @todo codereorg still working on this +#include "sharedFoundation/WindowsWrapper.h" + +// ====================================================================== +// convienent fatal macros that check windows HRESULT codes + +#define FATAL_HR(a,b) FATAL(FAILED(b), (a, HRESULT_CODE(b))) +#define DEBUG_FATAL_HR(a,b) DEBUG_FATAL(FAILED(b), (a, HRESULT_CODE(b))) + +// ====================================================================== +// include anything we need to replace missing functionality that other platforms provide + +#include "sharedFoundation/PlatformGlue.h" + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/FirstSharedFoundation.cpp b/engine/shared/library/sharedFoundation/src/win32/FirstSharedFoundation.cpp new file mode 100755 index 00000000..1cfb9020 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/FirstSharedFoundation.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstFoundation.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" diff --git a/engine/shared/library/sharedFoundation/src/win32/FloatingPointUnit.cpp b/engine/shared/library/sharedFoundation/src/win32/FloatingPointUnit.cpp new file mode 100755 index 00000000..f303e0eb --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/FloatingPointUnit.cpp @@ -0,0 +1,257 @@ +// ====================================================================== +// +// FloatingPointUnit.cpp +// copyright 1999 Bootprint Entertainment +// copyright 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedFoundation/FloatingPointUnit.h" + +#include "sharedFoundation/ConfigSharedFoundation.h" + +// ====================================================================== + +int FloatingPointUnit::updateNumber; +ushort FloatingPointUnit::status; +FloatingPointUnit::Precision FloatingPointUnit::precision; +FloatingPointUnit::Rounding FloatingPointUnit::rounding; +bool FloatingPointUnit::exceptionEnabled[E_max]; + +// ====================================================================== + +const WORD PRECISION_MASK = BINARY4(0000,0011,0000,0000); +const WORD PRECISION_24 = BINARY4(0000,0000,0000,0000); +const WORD PRECISION_53 = BINARY4(0000,0010,0000,0000); +const WORD PRECISION_64 = BINARY4(0000,0011,0000,0000); + +const WORD ROUND_MASK = BINARY4(0000,1100,0000,0000); +const WORD ROUND_NEAREST = BINARY4(0000,0000,0000,0000); +const WORD ROUND_CHOP = BINARY4(0000,1100,0000,0000); +const WORD ROUND_DOWN = BINARY4(0000,0100,0000,0000); +const WORD ROUND_UP = BINARY4(0000,1000,0000,0000); + +const WORD EXCEPTION_PRECISION = BINARY4(0000,0000,0010,0000); +const WORD EXCEPTION_UNDERFLOW = BINARY4(0000,0000,0001,0000); +const WORD EXCEPTION_OVERFLOW = BINARY4(0000,0000,0000,1000); +const WORD EXCEPTION_ZERO_DIVIDE = BINARY4(0000,0000,0000,0100); +const WORD EXCEPTION_DENORMAL = BINARY4(0000,0000,0000,0010); +const WORD EXCEPTION_INVALID = BINARY4(0000,0000,0000,0001); +const WORD EXCEPTION_ALL = BINARY4(0000,0000,0011,1111); + +// ====================================================================== + +void FloatingPointUnit::install(void) +{ + precision = P_24; + rounding = R_roundToNearestOrEven; + memset(exceptionEnabled, 0, sizeof(exceptionEnabled)); + + // preserve all other bits + status = getControlWord(); + status &= ~(PRECISION_MASK | ROUND_MASK | EXCEPTION_ALL); + + // set to single precision, rounding, and all exceptions masked + status |= PRECISION_24 | ROUND_NEAREST | EXCEPTION_ALL; + + // check the config platform flags to see if we should enable some exceptions + if (ConfigSharedFoundation::getFpuExceptionPrecision()) + { + exceptionEnabled[E_precision] = true; + status &= ~EXCEPTION_PRECISION; + } + + if (ConfigSharedFoundation::getFpuExceptionUnderflow()) + { + exceptionEnabled[E_underflow] = true; + status &= ~EXCEPTION_UNDERFLOW; + } + + if (ConfigSharedFoundation::getFpuExceptionOverflow()) + { + exceptionEnabled[E_overflow] = true; + status &= ~EXCEPTION_OVERFLOW; + } + + if (ConfigSharedFoundation::getFpuExceptionZeroDivide()) + { + exceptionEnabled[E_zeroDivide] = true; + status &= ~EXCEPTION_ZERO_DIVIDE; + } + + if (ConfigSharedFoundation::getFpuExceptionDenormal()) + { + exceptionEnabled[E_denormal] = true; + status &= ~EXCEPTION_DENORMAL; + } + + if (ConfigSharedFoundation::getFpuExceptionInvalid()) + { + exceptionEnabled[E_invalid] = true; + status &= ~EXCEPTION_INVALID; + } + + setControlWord(status); +} + +// ---------------------------------------------------------------------- + +void FloatingPointUnit::update(void) +{ + WORD currentStatus = getControlWord(); + + if (currentStatus != status) + { +// DEBUG_REPORT_LOG_PRINT(true, ("FPU: update=%d, in mode=%04x, should be in mode=%04x\n", updateNumber, static_cast(currentStatus), static_cast(status))); + setControlWord(status); + } + + ++updateNumber; +} + +// ---------------------------------------------------------------------- + +WORD FloatingPointUnit::getControlWord(void) +{ + WORD controlWord = 0; + + __asm fnstcw controlWord; + return controlWord; +} + +// ---------------------------------------------------------------------- + +void FloatingPointUnit::setControlWord(WORD controlWord) +{ + UNREF(controlWord); + __asm fldcw controlWord; +} + +// ---------------------------------------------------------------------- + +void FloatingPointUnit::setPrecision(Precision newPrecision) +{ + WORD bits = 0; + + switch (precision) + { + case P_24: + bits = PRECISION_24; + break; + + case P_53: + bits = PRECISION_53; + break; + + case P_64: + bits = PRECISION_64; + break; + + case P_max: + default: + DEBUG_FATAL(true, ("bad case")); + } + + // record the current state + precision = newPrecision; + + // set the proper bit pattern + status &= ~PRECISION_MASK; + status |= bits; + + // slam it into the FPU + setControlWord(status); +} + +// ---------------------------------------------------------------------- + +void FloatingPointUnit::setRounding(Rounding newRounding) +{ + WORD bits = 0; + + switch (newRounding) + { + case R_roundToNearestOrEven: + bits = ROUND_NEAREST; + break; + + case R_chop: + bits = ROUND_CHOP; + break; + + case R_roundDown: + bits = ROUND_DOWN; + break; + + case R_roundUp: + bits = ROUND_UP; + break; + + case R_max: + default: + DEBUG_FATAL(true, ("bad case")); + } + + // record the current state + rounding = newRounding; + + // set the proper bit pattern + status &= ~ROUND_MASK; + status |= bits; + + // slam it into the FPU + setControlWord(status); +} + +// ---------------------------------------------------------------------- + +void FloatingPointUnit::setExceptionEnabled(Exception exception, bool enabled) +{ + WORD bits = 0; + + switch (exception) + { + case E_precision: + bits = EXCEPTION_PRECISION; + break; + + case E_underflow: + bits = EXCEPTION_UNDERFLOW; + break; + + case E_overflow: + bits = EXCEPTION_OVERFLOW; + break; + + case E_zeroDivide: + bits = EXCEPTION_ZERO_DIVIDE; + break; + + case E_denormal: + bits = EXCEPTION_DENORMAL; + break; + + case E_invalid: + bits = EXCEPTION_INVALID; + break; + + case E_max: + default: + DEBUG_FATAL(true, ("bad case")); + } + + // record the current state + exceptionEnabled[exception] = enabled; + + // twiddle the bit appropriately. these bits masks, so set the bit to disable the exception, clear the bit to enable it. + if (enabled) + status &= ~bits; + else + status |= bits; + + // slam it into the FPU + setControlWord(status); +} + +// ====================================================================== diff --git a/engine/shared/library/sharedFoundation/src/win32/FloatingPointUnit.h b/engine/shared/library/sharedFoundation/src/win32/FloatingPointUnit.h new file mode 100755 index 00000000..9cda070d --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/FloatingPointUnit.h @@ -0,0 +1,104 @@ +// ====================================================================== +// +// FloatingPointUnit.h +// jeff grills +// +// copyright 1999 Bootprint Entertainment +// +// ====================================================================== + +#ifndef FLOATING_POINT_UNIT_H +#define FLOATING_POINT_UNIT_H + +// ====================================================================== + +class FloatingPointUnit +{ +public: + + typedef unsigned short WORD; + + enum Precision + { + P_24, + P_53, + P_64, + + P_max + }; + + enum Rounding + { + R_roundToNearestOrEven, + R_chop, + R_roundDown, + R_roundUp, + + R_max + }; + + enum Exception + { + E_precision, + E_underflow, + E_overflow, + E_zeroDivide, + E_denormal, + E_invalid, + + E_max + }; + +private: + + static int updateNumber; + static WORD status; + static Precision precision; + static Rounding rounding; + static bool exceptionEnabled[E_max]; + +public: + + static WORD getControlWord(void); + static void setControlWord(WORD controlWord); + +public: + + static void install(void); + + static void update(void); + + static void setPrecision(Precision newPrecision); + static void setRounding(Rounding newRounding); + static void setExceptionEnabled(Exception exception, bool enabled); + + static Precision getPrecision(void); + static Rounding getRounding(void); + static bool getExceptionEnabled(Exception exception); +}; + +// ====================================================================== + +inline FloatingPointUnit::Precision FloatingPointUnit::getPrecision(void) +{ + return precision; +} + +// ---------------------------------------------------------------------- + +inline FloatingPointUnit::Rounding FloatingPointUnit::getRounding(void) +{ + return rounding; +} + +// ---------------------------------------------------------------------- + +inline bool FloatingPointUnit::getExceptionEnabled(Exception theException) +{ + DEBUG_FATAL(static_cast(theException) < 0 || static_cast(theException) >= static_cast(E_max), ("exception out of range")); //lint !e568 // non-negative quantity is never less than 0 + return exceptionEnabled[theException]; +} + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/Os.cpp b/engine/shared/library/sharedFoundation/src/win32/Os.cpp new file mode 100755 index 00000000..9c828361 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/Os.cpp @@ -0,0 +1,1633 @@ +// ====================================================================== +// +// Os.cpp +// +// Portions copyright 1998 Bootprint Entertainment +// Portions copyright 2000-2002 Sony Online Entertainment +// All Rights Reserved +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedFoundation/Os.h" + +#include "sharedDebug/DebugFlags.h" +#include "sharedDebug/DebugKey.h" +#include "sharedDebug/DebugMonitor.h" +#include "sharedDebug/Profiler.h" +#include "sharedFoundation/Clock.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/ConfigSharedFoundation.h" +#include "sharedFoundation/CrashReportInformation.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/FloatingPointUnit.h" +#include "sharedFoundation/Production.h" +#include "sharedFoundation/StringCompare.h" +#include "sharedFoundation/WindowsWrapper.h" +#include "shellapi.h" + +#include +#include +#include +#include + +// ====================================================================== + +namespace OsNamespace +{ + void applyWindowChanges(); + void updateMousePosition(int x, int y); + + const int PROGRAM_NAME_SIZE = 512; + + bool ms_installed; + bool ms_processMessagePump = true; + +#if PRODUCTION == 0 + bool ms_validateGuardPatterns; + bool ms_validateFreePatterns; + bool ms_allowPopupDebugMenu; +#endif + + int ms_numberOfUpdates; + HWND ms_window; + HCURSOR ms_cursorArrow; + bool ms_engineOwnsWindow; + bool ms_wasFocusLost; + bool ms_gameOver; + bool ms_shouldReturnFromAbort; + bool ms_wantPopupDebugMenu; + bool ms_threadDied; + bool ms_mouseMoveInClient; + bool ms_clickToMove; + char ms_programName[PROGRAM_NAME_SIZE]; + char *ms_shortProgramName; + char ms_programStartupDirectory[MAX_PATH]; + Os::ThreadId ms_mainThreadId; + Os::IsGdiVisibleHookFunction ms_isGdiVisibleHookFunction; + Os::LostFocusHookFunction ms_lostFocusHookFunction; + Os::AcquiredFocusHookFunction ms_acquiredFocusHookFunction; + Os::AcquiredFocusHookFunction ms_acquiredFocusHookFunction2; + Os::QueueCharacterHookFunction ms_queueCharacterHookFunction; + Os::SetSystemMouseCursorPositionHookFunction ms_setSystemMouseCursorPositionHookFunction; + Os::SetSystemMouseCursorPositionHookFunction ms_setSystemMouseCursorPositionHookFunction2; + Os::GetHardwareMouseCursorEnabled ms_getHardwareMouseCursorEnabled; + Os::GetOtherAdapterRectsHookFunction ms_getOtherAdapterRectsHookFunction; + Os::WindowPositionChangedHookFunction ms_windowPositionChangedHookFunction; + Os::DisplayModeChangedHookFunction ms_displayModeChangedHookFunction; + Os::InputLanguageChangedHookFunction ms_inputLanguageChangedHookFunction; + Os::IMEHookFunction ms_IMEHookFunction; + Os::QueueKeyDownHookFunction ms_queueKeyDownHookFunction; + + int ms_processorCount; + int ms_debugKeyIndex; + int ms_SystemMouseCursorPositionX; + int ms_SystemMouseCursorPositionY; + + std::vector ms_otherAdapterRects; + + char ms_keyboardLayout[KL_NAMELENGTH]; + + bool ms_focused; + + int const ms_hotKeyId = 0xBEEF; + + extern "C" WINBASEAPI BOOL WINAPI IsDebuggerPresent(VOID); +}; + +using namespace OsNamespace; + + +static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +// ====================================================================== +/** + * Install the Os subsystem for games + * + * This routine is supported for all platforms, although different platforms may + * require different arguments to this routine. + * + * This routine registers the window class and creates the window for the application. + * + * This routine will add Os::remove to the ExitChain. + * + * @param instance Handle to the instance for this application + * @param windowName Name for the window title bar + * @paran normalIcon Normal icon for the game + * @param smallIcon Small icon for the task bar + * @see Os::remove() + */ + +void Os::install(HINSTANCE instance, const char *windowName, HICON normalIcon, HICON smallIcon) +{ + installCommon(); + + // setup the window class + WNDCLASSEX wclass; + Zero(wclass); + wclass.cbSize = sizeof(wclass); + wclass.style = CS_BYTEALIGNCLIENT; + wclass.lpfnWndProc = WindowProc; + wclass.hInstance = instance; + wclass.hIcon = normalIcon; + wclass.hCursor = NULL; + wclass.hbrBackground = reinterpret_cast(GetStockObject(BLACK_BRUSH)); + wclass.lpszClassName = windowName; + wclass.hIconSm = smallIcon; + + // register the window class + ATOM atom = RegisterClassEx(&wclass); + FATAL(atom == 0, ("RegisterClassEx failed")); + + // create the window + ms_window = CreateWindow( + windowName, // pointer to registered class name + windowName, // pointer to window name + WS_POPUP, // window style + 0, // horizontal position of window + 0, // vertical position of window + 640, // window width + 480, // window height + NULL, // handle to parent or owner window + NULL, // handle to menu or child-window identifier + instance, // handle to application instance + NULL); // pointer to window-creation data + FATAL(!ms_window, ("CreateWindow failed")); + ms_engineOwnsWindow = true; + + // load the arrow cursor + ms_cursorArrow = LoadCursor(NULL, IDC_ARROW); + FATAL(ms_cursorArrow == NULL, ("LoadCursor failed")); +} + +// ---------------------------------------------------------------------- +/** + * Install the Os subsystem for non-games. + * + * This routine is supported for all platforms, although different platforms may + * require different arguments to this routine.F + * + * This routine will add Os::remove to the ExitChain. + * + * @see Os::remove() + */ + +void Os::install(HWND newWindow, bool newProcessMessagePump) +{ + installCommon(); + ms_window = newWindow; + ms_processMessagePump = newProcessMessagePump; +} + +// ---------------------------------------------------------------------- +/** + * Install the Os subsystem for non-games. + * + * This routine is supported for all platforms, although different platforms may + * require different arguments to this routine. + * + * This routine will add Os::remove to the ExitChain. + * + * @see Os::remove() + */ + +void Os::install() +{ + installCommon(); +} + +// ---------------------------------------------------------------------- +/** + * This routine will remove the Os subsystem. + * + * This routine should not be called directly. It will be called from the ExitChain. + * + * @see Os::install() + */ + +void Os::remove() +{ + DEBUG_FATAL(!ms_installed, ("not installed")); + ms_installed = false; +} + +// ---------------------------------------------------------------------- + +void Os::installCommon() +{ + DEBUG_FATAL(ms_installed, ("already installed")); + + ExitChain::add(Os::remove, "Os::remove", 0, true); + + // get startup folder. + GetCurrentDirectory(sizeof(ms_programStartupDirectory), ms_programStartupDirectory); + + ms_numberOfUpdates = 0; + ms_mainThreadId = GetCurrentThreadId(); + setThreadName(ms_mainThreadId, "Main"); + +#if PRODUCTION == 0 + ms_allowPopupDebugMenu = ConfigFile::getKeyBool("SharedFoundation", "allowPopupDebugMenu", false); +#endif + + // get the name of the executable + DWORD result = GetModuleFileName(NULL, ms_programName, sizeof(ms_programName)); + FATAL(result == 0, ("GetModuleFileName failed")); + + // get the file name without the path + ms_shortProgramName = strrchr(ms_programName, '\\'); + if (ms_shortProgramName) + ++ms_shortProgramName; + else + ms_shortProgramName = ms_programName; + + // switch into single-precision floating point mode + FloatingPointUnit::install(); + + // get the amount of memory + MEMORYSTATUS memoryStatus; + GlobalMemoryStatus(&memoryStatus); + CrashReportInformation::addStaticText("Ram: %dmb\n", memoryStatus.dwTotalPhys / (1024 * 1024)); + + // log the os information + { + OSVERSIONINFO versionInfo; + Zero(versionInfo); + versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&versionInfo); + CrashReportInformation::addStaticText("Os1: %d.%d.%d\n", versionInfo.dwMajorVersion, versionInfo.dwMinorVersion, versionInfo.dwBuildNumber); + + char const * os = "Unknown"; + if (versionInfo.dwMajorVersion == 4 && versionInfo.dwMinorVersion == 10) + os = "Windows 98"; + else + if (versionInfo.dwMajorVersion == 4 && versionInfo.dwMinorVersion == 90) + os = "Windows Me"; + else + if (versionInfo.dwMajorVersion == 5 && versionInfo.dwMinorVersion == 0) + os = "Windows 2000"; + else + if (versionInfo.dwMajorVersion == 5 && versionInfo.dwMinorVersion == 1) + os = "Windows XP"; + else + if (versionInfo.dwMajorVersion == 5 && versionInfo.dwMinorVersion == 2) + os = "Windows Server 2003"; + else + if (versionInfo.dwMajorVersion == 6 && versionInfo.dwMinorVersion == 0) + os = "Windows Vista"; + + + + CrashReportInformation::addStaticText("Os2: %s %s\n", os, versionInfo.szCSDVersion); + } + + // get the number of processors + SYSTEM_INFO si; + GetSystemInfo(&si); + ms_processorCount = static_cast(si.dwNumberOfProcessors); + REPORT_LOG (ConfigSharedFoundation::getVerboseHardwareLogging(), ("Processor Count: %i\n", ms_processorCount)); + CrashReportInformation::addStaticText("NumProc: %d\n", ms_processorCount); + + { + HKEY key; + LONG result = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_EXECUTE, &key); + + if (result == ERROR_SUCCESS) + { + DWORD data; + DWORD type = REG_DWORD; + DWORD size = sizeof (data); + result = RegQueryValueEx (key, "~MHz", NULL, &type, reinterpret_cast (&data), &size); + if ((result == ERROR_SUCCESS) && (size > 0)) + REPORT_LOG (ConfigSharedFoundation::getVerboseHardwareLogging(), ("Processor Speed: %i MHz\n", data)); + + RegCloseKey (key); + } + } + + if (!GetKeyboardLayoutName(ms_keyboardLayout)) + ms_keyboardLayout[0] = '\0'; + + ms_installed = true; + +#if PRODUCTION == 0 + DebugFlags::registerFlag(ms_validateGuardPatterns, "SharedFoundation", "validateGuardPatterns"); + DebugFlags::registerFlag(ms_validateFreePatterns, "SharedFoundation", "validateFreePatterns"); +#endif + + switch (ConfigSharedFoundation::getProcessPriority()) + { + case -1: + setProcessPriority(P_low); + break; + + case 0: + setProcessPriority(P_normal); + break; + + case 1: + setProcessPriority(P_high); + break; + + default: + DEBUG_WARNING(true, ("invalid process priority, %d should be betweein [-1..1]", ConfigSharedFoundation::getProcessPriority())); + break; + } +} + +// ====================================================================== +// Return the window handle +// +// Return value: +// +// Handle to the window for this application +// +// Remarks: +// +// This routine is only supported on the Win* platforms, and should not be used by the +// game or the engine if portability is required. + +HWND Os::getWindow() +{ + return ms_window; +} + +// ---------------------------------------------------------------------- + +bool Os::engineOwnsWindow() +{ + return ms_engineOwnsWindow; +} + +// ---------------------------------------------------------------------- +/** + * Return the full name of the running executable. + * + * The program name will include the path as well. + * + * @return The full name of the running executable + * @see Os::getShortProgramName() + */ + +const char *Os::getProgramName() +{ + return ms_programName; +} + +// ---------------------------------------------------------------------- +/** + * Return the short name of the running executable. + * + * The program name will not include the path, but will just be the file name. + * + * @return The short name of the running executable + * @see Os::getProgramName() + */ + +const char *Os::getShortProgramName() +{ + return ms_shortProgramName; +} + +// ---------------------------------------------------------------------- +/** + * Return the current working directory when the program was started. + * + */ + +const char *Os::getProgramStartupDirectory() +{ + return ms_programStartupDirectory; +} + +// ---------------------------------------------------------------------- +/** + * Cause Os::abort() to return instead of abort the process. + * + * This routine should not be called directly by users. + * + * This routine is provided so that structured exception handling can catch + * an exception, call Fatal to run the ExitChain, and rethrow the exception + * so that the debugger will catch it. + */ + +void Os::returnFromAbort() +{ + ms_shouldReturnFromAbort = true; +} + +// ---------------------------------------------------------------------- +/** + * Check if the Os knows the game needs to shut down. + * + * The Os can decide that the game need to end for a number of reasons, + * including closing the application or shutting the machine down. + * + * @return True if the game should quit, otherwise false + */ + +bool Os::isGameOver() +{ + return ms_gameOver; +} + +// ---------------------------------------------------------------------- +/** + * Return the number of updates that the have occurred. + * + * @return This value is updated during the Os::update() routine. + */ + +int Os::getNumberOfUpdates() +{ + return ms_numberOfUpdates; +} + +// ---------------------------------------------------------------------- +/** + * Indicate whether or not the application was paused. + * + * @return True if the application was in the background (paused), otherwise false + */ + +bool Os::wasFocusLost() +{ + return ms_wasFocusLost; +} + +// ---------------------------------------------------------------------- +/** + * Return a flag indicating whether we are running a multiprocessor machine or not. + * + * @return True if the machine has more than one processor, false if not. + */ + +bool Os::isMultiprocessor() +{ + return ms_processorCount > 1; +} + +// ---------------------------------------------------------------------- +/** + * Return the number of processors. + * + * @return The number of processors in the machine. + */ + +int Os::getProcessorCount() +{ + return ms_processorCount; +} + +// ---------------------------------------------------------------------- + +bool Os::isMainThread() +{ + // if the Os class hasn't been installed, then assume we are the main thread. + // otherwise, check to see if our thread id is the main thread id + return !ms_installed || (GetCurrentThreadId() == ms_mainThreadId); +} + +// ---------------------------------------------------------------------- +/** + * Terminate the application because of an error condition. + * + * This routine is supported for all platforms. + * + * This routine should not be called directly. The engine and game should use the + * FATAL macro to terminate the application because of an error. + * + * Calling Os::returnFromAbort() will cause the routine to do nothing but return + * immediately. + * + * @see Os::returnFromAbort(), FATAL() + */ + +void Os::abort() +{ + if (!isMainThread()) + { + ms_threadDied = true; + ExitThread(1); + } + + if (!ms_shouldReturnFromAbort) + { + // let the C runtime deal with the abnormal termination + ::abort(); + } +} + +// ---------------------------------------------------------------------- + +void Os::setLostFocusHookFunction(LostFocusHookFunction lostFocusHookFunction) +{ + ms_lostFocusHookFunction = lostFocusHookFunction; +} + +// ---------------------------------------------------------------------- + +void Os::setIsGdiVisibleHookFunction(IsGdiVisibleHookFunction isGdiVisibleHookFunction) +{ + ms_isGdiVisibleHookFunction = isGdiVisibleHookFunction; +} + +// ---------------------------------------------------------------------- + +void Os::setQueueCharacterHookFunction(QueueCharacterHookFunction queueCharacterHookFunction) +{ + ms_queueCharacterHookFunction = queueCharacterHookFunction; +} + +// ---------------------------------------------------------------------- + +void Os::setSetSystemMouseCursorPositionHookFunction(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction) +{ + ms_setSystemMouseCursorPositionHookFunction = setSystemMouseCursorPositionHookFunction; +} + +// ---------------------------------------------------------------------- + +void Os::setSetSystemMouseCursorPositionHookFunction2(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction) +{ + ms_setSystemMouseCursorPositionHookFunction2 = setSystemMouseCursorPositionHookFunction; +} + +// ---------------------------------------------------------------------- + +void Os::setAcquiredFocusHookFunction(AcquiredFocusHookFunction acquiredFocusHookFunction) +{ + ms_acquiredFocusHookFunction = acquiredFocusHookFunction; +} + +// ---------------------------------------------------------------------- + +void Os::setAcquiredFocusHookFunction2(AcquiredFocusHookFunction acquiredFocusHookFunction) +{ + ms_acquiredFocusHookFunction2 = acquiredFocusHookFunction; +} + +// ---------------------------------------------------------------------- + +void Os::setGetHardwareMouseCursorEnabled(GetHardwareMouseCursorEnabled getHardwareMouseCursorEnabled) +{ + ms_getHardwareMouseCursorEnabled = getHardwareMouseCursorEnabled; +} + +// ---------------------------------------------------------------------- + +void Os::setGetOtherAdapterRectsHookFunction(GetOtherAdapterRectsHookFunction getOtherAdapterRectsHookFunction) +{ + ms_getOtherAdapterRectsHookFunction = getOtherAdapterRectsHookFunction; +} + +// ---------------------------------------------------------------------- + +void Os::setWindowPositionChangedHookFunction(WindowPositionChangedHookFunction windowPositionChangedHookFunction) +{ + ms_windowPositionChangedHookFunction = windowPositionChangedHookFunction; +} + +//----------------------------------------------------------------- + +void Os::setDisplayModeChangedHookFunction(DisplayModeChangedHookFunction displayModeChangedHookFunction) +{ + ms_displayModeChangedHookFunction = displayModeChangedHookFunction; +} + +//----------------------------------------------------------------- + +void Os::setInputLanguageChangedHookFunction(InputLanguageChangedHookFunction inputLanguageChangedHookFunction) +{ + ms_inputLanguageChangedHookFunction = inputLanguageChangedHookFunction; +} + +//----------------------------------------------------------------- +// rls - In IME mode, the F5 key can cause the IME pad window to open up. +// This causes the Japanese player to essentially lock-up because of +// context issues. There is probably a better way to handle this, but be +// warned: the SWG input system may not work properly. +void Os::setIMEHookFunction(IMEHookFunction imeHookFunction) +{ + if (ms_IMEHookFunction) + { + UnregisterHotKey(ms_window, ms_hotKeyId); + } + + ms_IMEHookFunction = imeHookFunction; + + // do not install the hotkey fix if the debugger is present. + if (ms_IMEHookFunction && !OsNamespace::IsDebuggerPresent()) + { + RegisterHotKey(ms_window, ms_hotKeyId, 0, VK_F5); + } +} + +//----------------------------------------------------------------- + +void Os::setQueueKeyDownHookFunction(QueueKeyDownHookFunction queueKeyDownHookFunction) +{ + ms_queueKeyDownHookFunction = queueKeyDownHookFunction; +} + +//----------------------------------------------------------------- +/** +* Create the specified directory and all of it's parents. +* @param directory the path to a directory +* @return always true currently +*/ + +bool Os::createDirectories (const char *directory) +{ + //-- construct list of subdirectories all the way down to root + std::stack directoryStack; + + std::string currentDirectory = directory; + + static const char path_seps [] = { '\\', '/', 0 }; + + // build the stack + while (!currentDirectory.empty()) + { + // remove trailing backslash + if (currentDirectory[currentDirectory.size()-1] == '\\' || currentDirectory[currentDirectory.size()-1] == '/') + IGNORE_RETURN(currentDirectory.erase(currentDirectory.size()-1)); + + if (currentDirectory[currentDirectory.size()-1] == ':') + { + // we've hit something like c: + break; + } + + if (!currentDirectory.empty()) + directoryStack.push(currentDirectory); + + // now strip off current directory + const size_t previousDirIndex = currentDirectory.find_last_of (path_seps); + if (static_cast(previousDirIndex) == currentDirectory.npos) + break; + else + IGNORE_RETURN(currentDirectory.erase(previousDirIndex)); + } + + //-- build all directories specified by the initial directory + while (!directoryStack.empty()) + { + // get the directory + currentDirectory = directoryStack.top(); + directoryStack.pop(); + + // try to create it (don't pass any security attributes) + IGNORE_RETURN (CreateDirectory(currentDirectory.c_str(), NULL)); + } + + return true; +} + +// ---------------------------------------------------------------------- +/** + * Write out a file. + * + * The file name and where the file is written is system-dependent. + * + * @param fileName Name of the file to write + * @param data Data buffer to write to the file + */ + +bool Os::writeFile(const char *fileName, const void *data, int length) // Length of the data bufferto write +{ + BOOL result; + HANDLE handle; + DWORD written; + + // open the file for writing + handle = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + + // check if it was opened + if (handle == INVALID_HANDLE_VALUE) + { + WARNING (true, ("Os::writeFile unable to create file [%s] for writing.", fileName)); + return false; + } + + // attempt to write the data + result = WriteFile(handle, data, static_cast(length), &written, NULL); + + // make sure the data was written okay + if (!result || written != static_cast(length)) + { + WARNING (true, ("Os::writeFile error writing file [%s]. Wrote %d, attempted to write %d.", fileName, written, length)); + static_cast(CloseHandle(handle)); + return false; + } + + // close the file + result = CloseHandle(handle); + + // make sure the close was sucessful + if (!result) + { + WARNING (true, ("Os::writeFile error closing file [%s].", fileName)); + return false; + } + + return true; +} + +// ---------------------------------------------------------------------- +/** + * Check to see if any child threads have Fataled. + * + * This routine will + */ + +void Os::checkChildThreads() +{ + FATAL(ms_threadDied, ("child thread died")); +} + +// ---------------------------------------------------------------------- +/** + * Change the priority of this process. + * + */ + +void Os::setProcessPriority(Priority priority) +{ + switch (priority) + { + case P_low: + SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS); + break; + + case P_normal: + SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); + break; + + case P_high: + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); + break; + + default: + DEBUG_FATAL(true, ("Invalid priority")); + break; + } +} + +// ---------------------------------------------------------------------- +/** + * Update the Os subsystem. + * + * This routine is supported for all platforms. + * + * For the Win* platforms, this routine will process the windows message pump. + */ + +bool Os::update() +{ + MSG msg; + int result; + + FloatingPointUnit::update(); + + ms_wasFocusLost = false; + ++ms_numberOfUpdates; + +#if PRODUCTION == 0 + + if (ms_validateGuardPatterns || ms_validateFreePatterns) + { + PROFILER_AUTO_BLOCK_DEFINE ("validate heap"); + MemoryManager::verify(ms_validateGuardPatterns, ms_validateFreePatterns); + } + +#endif + + if (ms_processMessagePump) + { + do + { + checkChildThreads(); + + // while there are messages in the queue + while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) + { + result = GetMessage(&msg, NULL, 0, 0); + + if (result < 0) + { + // error, ignore GetMessage + } + else + // get the message + if (result > 0) + { + static_cast(TranslateMessage(&msg)); + static_cast(DispatchMessage(&msg)); + } + else + { + // WM_QUIT handled here + ms_gameOver = true; + return false; + } + } + + // may need to reprocess the message queue now + } while (handleDebugMenu()); + } + + Clock::update(); + + return true; +} + +// ---------------------------------------------------------------------- +/** + * Formats a message error using GetLastError() and FormatMessge(). + * + * The buffer returned from this function is dynamically allocated to prevent + * issues with this routine being called from multiple threads. The caller + * must delete the buffer when it is done. + * + * @return A dynamically allocated buffer containing the error message + */ + +char *Os::getLastError() +{ + char buffer[2048]; + + const DWORD result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL); + + if (result == 0) + return NULL; + + return DuplicateString(buffer); +} + +// ---------------------------------------------------------------------- + +bool Os::handleDebugMenu() +{ +#if PRODUCTION == 0 + + // pop up the menu if it is wanted and GDI is actually visible + if (ms_wantPopupDebugMenu && ms_isGdiVisibleHookFunction && ms_isGdiVisibleHookFunction()) + { + ms_focused = false; + // unaquire all the dinput devices + if (ms_lostFocusHookFunction) + ms_lostFocusHookFunction(); + + BOOL b; + POINT p; + + // get the upper left corner of the client space in screen coordinates + p.x = 0; + p.y = 0; + b = ClientToScreen(ms_window, &p); + DEBUG_FATAL(!b, ("ClientToScreen failed")); + + typedef std::map Map; + Map map; + + // create the menu + HMENU menu = CreatePopupMenu(); + const char *lastSection.clear(); + HMENU lastSubmenu = NULL; + int index = 1; + DebugFlags::FlagVector::const_iterator end = DebugFlags::ms_flagsSortedByName.end(); + for (DebugFlags::FlagVector::const_iterator i = DebugFlags::ms_flagsSortedByName.begin(); i != end; ++i, ++index) + { + const DebugFlags::Flag &flag = *i; + + // check if we are starting a new section + if (strcmp(lastSection, flag.section) != 0) + { + lastSection = flag.section; + + char buffer[512]; + strcpy(buffer, lastSection); + char *start = buffer; + char *slash = NULL; + lastSubmenu = menu; + while ((slash = strchr(start, '/')) != NULL) + { + *slash = '\0'; + + Map::iterator entry = map.find(buffer); + if (entry == map.end()) + { + const int numberOfItems = GetMenuItemCount(lastSubmenu); + int insertLocation = 0; + for (insertLocation = 0; insertLocation < numberOfItems && GetSubMenu(lastSubmenu, insertLocation); ++insertLocation) + ; + + HMENU newMenu = CreatePopupMenu(); + static_cast(InsertMenu(lastSubmenu, insertLocation, MF_BYPOSITION | MF_POPUP, reinterpret_cast(newMenu), start)); + lastSubmenu = newMenu; + map.insert(Map::value_type(DuplicateString(buffer), lastSubmenu)); + } + else + lastSubmenu = entry->second; + + *slash = '/'; + start = slash + 1; + } + + const int numberOfItems = GetMenuItemCount(lastSubmenu); + int insertLocation = 0; + for (insertLocation = 0; insertLocation < numberOfItems && GetSubMenu(lastSubmenu, insertLocation); ++insertLocation) + ; + + HMENU newMenu = CreatePopupMenu(); + static_cast(InsertMenu(lastSubmenu, insertLocation, MF_BYPOSITION | MF_POPUP, reinterpret_cast(newMenu), start)); + lastSubmenu = newMenu; + map.insert(Map::value_type(DuplicateString(buffer), lastSubmenu)); + } + + // add the current flag to the current menu + static_cast(AppendMenu(lastSubmenu, MF_ENABLED | MF_STRING | (*flag.variable ? MF_CHECKED : MF_UNCHECKED), index, flag.name)); + } + + { + ms_debugKeyIndex = index; + + Map::iterator entry = map.find("SharedDebug"); + DEBUG_FATAL(entry == map.end(), ("Could not find SharedDebug section")); + + HMENU newMenu = CreatePopupMenu(); + static_cast(AppendMenu(entry->second, MF_POPUP, reinterpret_cast(newMenu), "DebugKey")); + lastSubmenu = newMenu; + + DebugKey::FlagVector::const_iterator end = DebugKey::ms_flags.end(); + for (DebugKey::FlagVector::const_iterator i = DebugKey::ms_flags.begin(); i != end; ++i, ++index) + { + // add the current flag to the current menu + const DebugKey::Flag &flag = *i; + static_cast(AppendMenu(lastSubmenu, MF_ENABLED | MF_STRING | (*flag.variable ? MF_CHECKED : MF_UNCHECKED), index, flag.name)); + } + } + + // free the map memory + while (!map.empty()) + { + Map::iterator i = map.begin(); + char *value = i->first; + map.erase(i); + delete [] value; + } + + // pop up the menu at the top corner of the client space + index = TrackPopupMenuEx(menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD | TPM_RIGHTBUTTON, p.x, p.y, ms_window, NULL); + if (index) + { + if (index < ms_debugKeyIndex) + { + bool &value = *DebugFlags::ms_flagsSortedByName[index-1].variable; + value = !value; + } + else + { +#if PRODUCTION == 0 + DebugKey::setCurrentFlag(DebugKey::ms_flags[index - ms_debugKeyIndex].variable); +#endif + } + } + + DestroyMenu(menu); + + // don't want the menu anymore + ms_wantPopupDebugMenu = false; + ms_wasFocusLost = true; + ms_focused = true; + if (ms_acquiredFocusHookFunction2) + ms_acquiredFocusHookFunction2(); + + return true; + } + +#endif + + return false; +} + +// ---------------------------------------------------------------------- + +void Os::enablePopupDebugMenu() +{ +#if PRODUCTION == 0 + ms_allowPopupDebugMenu = true; +#endif +} + +// ---------------------------------------------------------------------- +/** + * Request that the popup debug menu be displayed. + * + * The popup debug menu will only be displayed if the proper config file + * switch has been set. + */ + +void Os::requestPopupDebugMenu() +{ +#if PRODUCTION == 0 + ms_wantPopupDebugMenu = ms_allowPopupDebugMenu; +#endif +} + +bool Os::isNumPadValue(unsigned char asciiChar) +{ + return (asciiChar >= '0' && asciiChar <= '9') || + (asciiChar == '/') || + (asciiChar == '*') || + (asciiChar == '-') || + (asciiChar == '+') || + (asciiChar == '.'); +} + + +// ---------------------------------------------------------------------- +/** + * Check to see if this is a NumPad keypress to be consumed. Enter is the only one not consumed. + */ +bool Os::isNumPadChar(unsigned char asciiChar) +{ + BYTE keyboardstate[256]; + GetKeyboardState( keyboardstate ); + + if (isNumPadValue(asciiChar)) + { + return ( (keyboardstate[VK_NUMPAD1] > 1) || + (keyboardstate[VK_NUMPAD2] > 1) || + (keyboardstate[VK_NUMPAD3] > 1) || + (keyboardstate[VK_NUMPAD4] > 1) || + (keyboardstate[VK_NUMPAD5] > 1) || + (keyboardstate[VK_NUMPAD6] > 1) || + (keyboardstate[VK_NUMPAD7] > 1) || + (keyboardstate[VK_NUMPAD8] > 1) || + (keyboardstate[VK_NUMPAD9] > 1) || + (keyboardstate[VK_NUMPAD0] > 1) || + (keyboardstate[VK_DIVIDE] > 1) || + (keyboardstate[VK_ADD] > 1) || + (keyboardstate[VK_SUBTRACT] > 1) || + (keyboardstate[VK_MULTIPLY] > 1) || + (keyboardstate[VK_DECIMAL] > 1)); + } + return false; +} + +// ---------------------------------------------------------------------- +/** + * Handle window messages. + * + * This routine will process window messages that are passed into the application from + * Windows, likely though the Os::update() routine, but may be from other locations as well. + * + * @param hwnd Handle of window + * @param uMsg Message identifier + * @param wParam First message parameter + * @param lParam Second message parameter + * @see Os::update() + */ + +LRESULT CALLBACK Os::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ +#if 0 + DEBUG_REPORT_LOG_PRINT(true, ("%08d %08x %08x %08x\n", ms_numberOfUpdates, uMsg, wParam, lParam)); +#endif + + if (ms_IMEHookFunction) + { + // Let the IME Manager see and possibly consume message + if (ms_IMEHookFunction(hwnd, uMsg, wParam, lParam) == 0) + { + return 0; + } + } + + switch (uMsg) + { + case WM_ERASEBKGND: + // won't let windows erase the background + return 0; + + case WM_IME_CHAR: + if (ms_queueCharacterHookFunction) + { + const char ansiChars [2] = + { + static_cast(HIBYTE( wParam )), //lint !e1924 // c-style case msvc bug + static_cast(LOBYTE( wParam )) //lint !e1924 // c-style case msvc bug + }; + + wchar_t u; + if (MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, reinterpret_cast(ansiChars), 2, &u, 1)) + ms_queueCharacterHookFunction(0, static_cast(u)); + } + return 0; + + case WM_HOTKEY: + { + if (ms_queueKeyDownHookFunction) + { + ms_queueKeyDownHookFunction(0, MapVirtualKey(HIWORD(lParam), 0)); + } + return 0; + } + case WM_CHAR: + // handle typed string characters + if (ms_queueCharacterHookFunction) + { + //-- the extended bit is bit 24 + const int extended = (lParam & (1 << 24)) != 0; + + if (!extended) + { + int keyCode = (lParam << 8) >> 24; // key code is in bits 16-23 + // cp* == ASCII until 0x80, for which you then need to call the following to get the Unicode value + // from the cp* value. WM_CHAR always returns the values from the windows codepage (cp) used. For US/Europe + // it is cp1252 and for Japan it is cp932. + if (wParam >= 0x80) + { + char cpChar[2]; + wchar_t unicodeChar[2]; + + cpChar[0] = static_cast(wParam); + cpChar[1] = '\0'; + + int result = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cpChar, sizeof(cpChar), unicodeChar, sizeof(unicodeChar)); + + + if (result > 0) + { + ms_queueCharacterHookFunction(keyCode, static_cast(unicodeChar[0])); + } + } + else + { + ms_queueCharacterHookFunction(keyCode, static_cast(wParam)); + } + } + } + return 0; + + case WM_INPUTLANGCHANGE: + { + if (ms_inputLanguageChangedHookFunction) + { + ms_inputLanguageChangedHookFunction(); + } + } + return 0; + + case WM_DESTROY: + // if the main window gets destroyed, it's time to quit + PostQuitMessage(0); + return 0; + + case WM_SYSCOMMAND: + switch (wParam & 0xFFF0) + { + // hack hack hack hack hack + // don't let alt-f4 close the window, but allow clicking on the close X button to close the window + case SC_CLOSE: + if (GetKeyState(VK_F4) && (GetKeyState(VK_MENU) || GetKeyState(VK_RMENU))) + return 0; + break; + + // don't let the monitor get turned off + case SC_MONITORPOWER: + return 0; + + // don't allow the screen saver to come on + case SC_SCREENSAVE: + return 0; + + // don't allow alt-space to open up the window menu + case SC_KEYMENU: + return 0; + + case SC_MOVE: + ClipCursor(NULL); + ms_focused = false; + if (ms_lostFocusHookFunction) + ms_lostFocusHookFunction(); + ms_wasFocusLost = true; + break; + default: + break; + } + break; + + case WM_ENTERSIZEMOVE: + if (ms_getOtherAdapterRectsHookFunction) + { + ms_otherAdapterRects.clear(); + (*ms_getOtherAdapterRectsHookFunction)(ms_otherAdapterRects); + } + break; + + case WM_EXITSIZEMOVE: + ms_focused = true; + if (ms_acquiredFocusHookFunction) + ms_acquiredFocusHookFunction(); + if (ms_acquiredFocusHookFunction2) + ms_acquiredFocusHookFunction2(); + ms_wasFocusLost = true; + if (ms_windowPositionChangedHookFunction) + (*ms_windowPositionChangedHookFunction)(); +#if PRODUCTION == 0 + DebugMonitor::setBehindWindow(ms_window); +#endif + break; + + case WM_MOUSEACTIVATE: + if (hwnd == ms_window) + { + if (LOWORD(lParam) == HTCAPTION) + ms_clickToMove = true; + else if (LOWORD(lParam) == HTCLIENT) + { + ms_focused = true; + if (ms_acquiredFocusHookFunction) + ms_acquiredFocusHookFunction(); + if (ms_acquiredFocusHookFunction2) + ms_acquiredFocusHookFunction2(); + } + } + + break; + + case WM_MOUSEMOVE: + if (ms_focused && hwnd == ms_window) + { + ms_mouseMoveInClient = true; + updateMousePosition(LOWORD(lParam), HIWORD(lParam)); + } + break; + + case WM_NCMOUSEMOVE: + ms_mouseMoveInClient = false; + break; + + case WM_SETCURSOR: + if (!ms_mouseMoveInClient || hwnd != ms_window) + SetCursor(ms_cursorArrow); + else + if (!ms_getHardwareMouseCursorEnabled || !ms_getHardwareMouseCursorEnabled()) + SetCursor(NULL); + break; + + case WM_NCACTIVATE: +#if PRODUCTION == 0 + // hack to handle coming back from the debugger cleanly + if (wParam) + { + //allow game-specific systems a chance to respond to focus changes + DebugMonitor::setBehindWindow(ms_window); + if (ms_lostFocusHookFunction) + ms_lostFocusHookFunction(); + if (ms_acquiredFocusHookFunction) + ms_acquiredFocusHookFunction(); + if (ms_acquiredFocusHookFunction2) + ms_acquiredFocusHookFunction2(); + ms_wasFocusLost = true; + ms_focused = true; + } +#endif + break; + + case WM_ACTIVATE: + if (hwnd == ms_window) + { + if (wParam != WA_INACTIVE) + { + if (ms_clickToMove) + ms_clickToMove = false; + ms_mouseMoveInClient = true; + ms_focused = true; + ms_wasFocusLost = true; + + if (ms_acquiredFocusHookFunction) + ms_acquiredFocusHookFunction(); + if (ms_acquiredFocusHookFunction2) + ms_acquiredFocusHookFunction2(); + } + else + { + ClipCursor(NULL); + ms_focused = false; + if (ms_lostFocusHookFunction) + ms_lostFocusHookFunction(); + } + } + break; + + case WM_ACTIVATEAPP: + if (wParam == FALSE) + { + ClipCursor(NULL); + ms_focused = false; + if (ms_lostFocusHookFunction) + ms_lostFocusHookFunction(); + } + break; + + case WM_DISPLAYCHANGE: + if (ms_displayModeChangedHookFunction) + ms_displayModeChangedHookFunction(); + break; + + default: + break; + } + + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +// ---------------------------------------------------------------------- + +void OsNamespace::updateMousePosition(int x, int y) +{ + if (ms_setSystemMouseCursorPositionHookFunction) + ms_setSystemMouseCursorPositionHookFunction(x, y); + + if (ms_setSystemMouseCursorPositionHookFunction2) + ms_setSystemMouseCursorPositionHookFunction2(x, y); +} + +// ---------------------------------------------------------------------- +/** + * Get an identifier indicating which thread called this function. + */ + +Os::ThreadId Os::getThreadId() +{ + return GetCurrentThreadId(); +} + +// ---------------------------------------------------------------------- +/** + * Get the actual system time, in seconds since the epoch. + * + * Do not use this for most game systems, since it does not take into account + * clock sku, game loop times, etc. + */ +time_t Os::getRealSystemTime() +{ + return time(0); +} + +// ---------------------------------------------------------------------- +/** + * Convert a time in seconds since the epoch to GMT. + * + */ + +void Os::convertTimeToGMT(const time_t &convertTime, tm &zulu) +{ + zulu=*gmtime(&convertTime); // gmtime uses a single static tm structure. Yuck! +} + +// ---------------------------------------------------------------------- +/** + * Convert a tm structure to the time in seconds since the epoch. + * + */ + +time_t Os::convertGMTToTime(const tm &zulu) +{ + return mktime(const_cast(&zulu)); +} + +// ---------------------------------------------------------------------- +/** + * Cause the current thread to suspend for a period of time. Zero delay indicates + * to yield the current time slice. + */ + +void Os::sleep(int ms) +{ + ::Sleep(static_cast(ms)); +} + +// ---------------------------------------------------------------------- +/** + * Assign the given thread a reasonable name (only works for MSDev 6.0 debugger) + * Max 9 characters + * + */ + +void Os::setThreadName(ThreadId threadID, const char* threadName) +{ + //used to give threads reasonable names in the MSDev debugger, + //see http://www.vcdj.com/upload/free/features/vcdj/2001/03mar01/et0103/et0103.asp for more info + struct ThreadNameInfo + { + DWORD dwType; + LPCSTR szName; + DWORD dwThreadID; + DWORD dwFlags; + }; + + ThreadNameInfo info; + info.dwType = 0x1000; //must be this value + info.szName = threadName; + info.dwThreadID = threadID; + info.dwFlags = 0; //unused, reserved for future use + + __try + { + // use the magic exception number MS picked for this purpose + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), reinterpret_cast(&info)); + } + __except (EXCEPTION_CONTINUE_EXECUTION) + { + } +} + +// ---------------------------------------------------------------------- +/** + * Given a base directory and a full file pathname, find the relative path + * needed to get from the source directory to the target. + * + * This command is case sensitive. It does not care whether baseDirectory contains + * a trailing backslash or not. + * + * @param baseDirectory the base directory from which a relative path will be constructed. + * @param targetPathname the full pathname for the file for which we want to generate a relative path + * @param relativePath the string into which the constructed relative path will be returned + */ + +void Os::buildRelativePath(const char *baseDirectory, const char *targetPathname, std::string &relativePath) +{ + NOT_NULL(baseDirectory); + DEBUG_FATAL(!targetPathname || !*targetPathname, ("bad targetPathname, must be non-zero length")); + + const char directorySeparator = '\\'; + const char *const backupDirectoryString = "..\\"; + + std::string workingBaseDirectory(baseDirectory); + + //-- ensure base directory ends in directory separator + if (workingBaseDirectory[workingBaseDirectory.length()-1] != directorySeparator) + workingBaseDirectory += directorySeparator; + + //-- grab the target directory + std::string workingTargetDirectory; + + const char *endOfDirectory = strrchr(targetPathname, static_cast(directorySeparator)); + if (endOfDirectory) + IGNORE_RETURN(workingTargetDirectory.append(targetPathname, static_cast(endOfDirectory - targetPathname + 1))); + + //-- find count of character of match between directory strings + const size_t workingBaseDirectoryLength = workingBaseDirectory.length(); + const size_t workingTargetDirectoryLength = workingTargetDirectory.length(); + + size_t searchIndex = 0; + while ((searchIndex < workingBaseDirectoryLength) && (searchIndex < workingTargetDirectoryLength) && (workingBaseDirectory[searchIndex] == workingTargetDirectory[searchIndex])) + ++searchIndex; + + size_t matchCount = searchIndex; + + //-- if we match into the middle of a directory, back up until the previous directory + if ((matchCount > 0) && (workingBaseDirectory[matchCount - 1] != directorySeparator)) + { + do + { + --matchCount; + } while ((matchCount > 0) && (workingBaseDirectory[matchCount - 1] != directorySeparator)); + } + + //-- if we have no match between directories, the best path is the full path. + if (matchCount < 1) + { + relativePath = targetPathname; + return; + } + + //-- for each directory in base directory not matched, insert a "backup directory" string + relativePath.clear(); + { + for (size_t i = matchCount; i < workingBaseDirectoryLength; ++i) + if (workingBaseDirectory[i] == directorySeparator) + IGNORE_RETURN(relativePath.append(backupDirectoryString)); + } + + //-- for each directory in the target directory not matched, append to result. + // this works out to copying from the match point forward in the target path. + IGNORE_RETURN(relativePath.append(targetPathname + matchCount)); +} + +// ---------------------------------------------------------------------- +/** + * Convert a relative path to an absolute path. + */ +bool Os::getAbsolutePath(const char *relativePath, char *absolutePath, int absolutePathBufferSize) +{ + if (_fullpath(absolutePath, relativePath, static_cast(absolutePathBufferSize)) == NULL) + return false; + + // convert the slashes to be forwards + for (char *convert = absolutePath; *convert; ++convert) + if (*convert == '\\') + *convert = '/'; + + return true; +} + +// ---------------------------------------------------------------------- +/** + * Copy text to the system clipboard. + * + * This routine can be used if the application wants to make some data easily available for pasting (like crash call stacks). + */ + +bool Os::copyTextToClipboard(const char *text) +{ + if (!OpenClipboard(ms_window)) + return false; + + if (!EmptyClipboard()) + return false; + + // need to convert to cr/lf sequences. yuck. + int length = 1; + for (const char *t2 = text; *t2; ++t2, ++length) + { + if (*t2 == '\n') + ++length; + } + + HANDLE memoryHandle = GlobalAlloc(GMEM_MOVEABLE, length); + if (memoryHandle == NULL) + { + CloseClipboard(); + return FALSE; + } + + // lock the handle and copy the text to the buffer. + char *destination = reinterpret_cast(GlobalLock(memoryHandle)); + while (*text) + { + if (*text == '\n') + *(destination++) = '\r'; + *destination++ = *text++; + } + + if (GlobalUnlock(memoryHandle) != 0 || GetLastError() != NO_ERROR) + { + IGNORE_RETURN(GlobalFree(memoryHandle)); + return false; + } + + if (!SetClipboardData(CF_TEXT, memoryHandle)) + return false; + + if (!CloseClipboard()) + return false; + + return true; +} + +// ---------------------------------------------------------------------- + +bool Os::getUserName(char *buffer, int &bufferSize) +{ + NOT_NULL(buffer); + DWORD windowsBufferSize = static_cast(bufferSize); + buffer[0] = '\0'; + bool result = GetUserName(buffer, &windowsBufferSize) == TRUE; + return result; +} + +//----------------------------------------------------------------------- + +Os::OsPID_t Os::getProcessId() +{ + return static_cast(GetCurrentProcessId()); +} + +//---------------------------------------------------------------------- + +bool Os::isFocused() +{ + return ms_focused; +} + +//---------------------------------------------------------------------- + +bool Os::launchBrowser(std::string const & website) +{ + std::string URL("http://"); + if (strncmp(URL.c_str(), website.c_str(),7)!=0) + URL+=website; + else + URL=website; + int result = reinterpret_cast(ShellExecute(NULL, "open", URL.c_str(), NULL, NULL, SW_SHOWNORMAL)); + return (result > 32); +} + + +// ====================================================================== diff --git a/engine/shared/library/sharedFoundation/src/win32/Os.h b/engine/shared/library/sharedFoundation/src/win32/Os.h new file mode 100755 index 00000000..afb3be40 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/Os.h @@ -0,0 +1,152 @@ +// ====================================================================== +// +// Os.h +// +// Portions copyright 1998 Bootprint Entertainment +// Portions copyright 2000-2002 Sony Online Entertainment +// All Rights Reserved +// +// ====================================================================== + +#ifndef INCLUDED_Os_H +#define INCLUDED_Os_H + +// ====================================================================== + +#include + +// ====================================================================== + +class Os +{ +public: + + typedef bool (*IsGdiVisibleHookFunction)(); + typedef void (*LostFocusHookFunction)(); + typedef void (*AcquiredFocusHookFunction)(); + typedef void (*QueueCharacterHookFunction)(int keyboard, int character); + typedef void (*SetSystemMouseCursorPositionHookFunction)(int x, int y); + typedef bool (*GetHardwareMouseCursorEnabled)(); + typedef void (*GetOtherAdapterRectsHookFunction)(stdvector::fwd &); + typedef void (*WindowPositionChangedHookFunction)(); + typedef void (*DisplayModeChangedHookFunction)(); + typedef void (*InputLanguageChangedHookFunction)(); + typedef int (*IMEHookFunction)(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + typedef void (*QueueKeyDownHookFunction)(int keyboard, int character); + + typedef uint ThreadId; + typedef DWORD OsPID_t; + + enum Priority + { + P_high, + P_normal, + P_low + }; + + enum + { + MAX_PATH_LENGTH = 512 + }; + +public: + + static void install(HINSTANCE newInstance, const char *windowName, HICON normalIcon, HICON smallIcon); + static void install(HWND newWindow, bool processMessagePump); + static void install(); + + static bool isGameOver(); + static DLLEXPORT bool isMainThread(); + static bool wasFocusLost(); + static void checkChildThreads(); + + static void setProcessPriority(Priority priority); + + static bool update(); + + static void returnFromAbort(); + static void abort(); + + static void enablePopupDebugMenu(); + static void requestPopupDebugMenu(); + + static bool createDirectories (const char *dirname); + + static bool writeFile(const char *fileName, const void *data, int length); + + static HWND getWindow(); + static bool engineOwnsWindow(); + + static int getNumberOfUpdates(); + + static char *getLastError(); + + static const char *getProgramName(); + static const char *getShortProgramName(); + static const char *getProgramStartupDirectory(); + + static void setIsGdiVisibleHookFunction(IsGdiVisibleHookFunction newGlIsGdiVisible); + static void setLostFocusHookFunction(LostFocusHookFunction lostFocusHookFunction); + static void setQueueCharacterHookFunction(QueueCharacterHookFunction queueCharacterHookFunction); + static void setSetSystemMouseCursorPositionHookFunction(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction); + static void setSetSystemMouseCursorPositionHookFunction2(SetSystemMouseCursorPositionHookFunction setSystemMouseCursorPositionHookFunction); + static void setAcquiredFocusHookFunction(AcquiredFocusHookFunction acquiredFocusHookFunction); + static void setAcquiredFocusHookFunction2(AcquiredFocusHookFunction acquiredFocusHookFunction); + static void setGetHardwareMouseCursorEnabled(GetHardwareMouseCursorEnabled getHardwareMouseCursorEnabled); + static void setGetOtherAdapterRectsHookFunction(GetOtherAdapterRectsHookFunction getOtherAdapterRectsHookFunction); + static void setWindowPositionChangedHookFunction(WindowPositionChangedHookFunction windowPositionChangedHookFunction); + static void setDisplayModeChangedHookFunction(DisplayModeChangedHookFunction displayModeChangedHookFunction); + static void setInputLanguageChangedHookFunction(InputLanguageChangedHookFunction inputLanguageChangedHookFunction); + static void setIMEHookFunction(IMEHookFunction imeHookFunction); + static void setQueueKeyDownHookFunction(QueueKeyDownHookFunction queueKeyDownHookFunction); + + static DLLEXPORT ThreadId getThreadId(); + static void setThreadName(ThreadId threadID, const char* name); + + static void sleep(int ms); + + static time_t getRealSystemTime(); + static void convertTimeToGMT(const time_t &time, tm &zulu); + static time_t convertGMTToTime(const tm &zulu); + + static bool isMultiprocessor(); + static int getProcessorCount(); + + static void buildRelativePath(const char *baseDirectory, const char *targetPathname, std::string &relativePath); + static bool getAbsolutePath(const char *relativePath, char *absolutePath, int absolutePathBufferSize); + + static bool copyTextToClipboard(const char *text); + + static bool getUserName(char *buffer, int &bufferSize); + + static OsPID_t getProcessId(); + + static bool isFocused(); + + static bool launchBrowser(std::string const & website); + static bool isNumPadValue(unsigned char asciiChar); + static bool isNumPadChar(unsigned char asciiChar); + +private: + + Os(); + Os(const Os &); + Os &operator =(const Os &); + +private: + + static void remove(); + static void installCommon(); + + static LRESULT CALLBACK Os::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +private: + +private: + + static bool handleDebugMenu(); +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/PerThreadData.cpp b/engine/shared/library/sharedFoundation/src/win32/PerThreadData.cpp new file mode 100755 index 00000000..7b2d0b58 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/PerThreadData.cpp @@ -0,0 +1,465 @@ +// ====================================================================== +// +// PerThreadData.cpp +// +// Portions copyright 1998 Bootprint Entertainment +// Portions Copyright 2002 Sony Online Entertainment +// All Rights Reserved +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedFoundation/PerThreadData.h" + +#include "sharedSynchronization/RecursiveMutex.h" +#include "sharedSynchronization/Gate.h" + +#include "sharedFoundation/Os.h" + +#include +#include + +// ====================================================================== + +// ====================================================================== +namespace PerThreadDataNamespace +{ + struct Data + { + bool exitChainRunning; + bool exitChainFataling; + ExitChain::Entry *exitChainFirstEntry; + + int debugPrintFlags; + + Gate *fileStreamerReadGate; + + HANDLE watchHandle; + }; + + typedef std::vector DataAllocations; + + // ------------------------------------------------------ + + static char buffer1[sizeof(RecursiveMutex)]; + static char buffer2[sizeof(DataAllocations)]; + + static const DWORD BadSlot = 0xffffffff; + + static DWORD slot = BadSlot; + static RecursiveMutex *criticalSection; + static DataAllocations *dataAllocations; + + // ------------------------------------------------------ + + static void _threadRemove(Data *data); + static void _removeFromList(Data *data); + static void _watchThreads(); + + /*---------------------------------------------------------------------- + * Get access to the per-thread-data. + * + * This routine will verify the per-thread-data subsystem has been installed and the + * threadInstall() function has been called for the current thread. + * + * @return A pointer to the per-thread-data. + */ + inline static Data *_getData(bool allowReturnNull=false) + { + UNREF(allowReturnNull); + + if (slot == BadSlot) + { + DEBUG_FATAL(true && !allowReturnNull, ("not installed")); + return NULL; + } + + Data * const data = reinterpret_cast(TlsGetValue(slot)); + DEBUG_FATAL(!data && !allowReturnNull, ("not installed for this thread")); + return data; + } + + // ------------------------------------------------------ + + inline static void _closeData(Data *data) + { + if (data->fileStreamerReadGate) + { + delete data->fileStreamerReadGate; + data->fileStreamerReadGate=0; + } + if (data->watchHandle) + { + CloseHandle(data->watchHandle); + data->watchHandle=0; + } + } + + // ------------------------------------------------------ + + inline static void _freeData(Data *data) + { + delete data; + } + + // ------------------------------------------------------ +} +using namespace PerThreadDataNamespace; + +// ====================================================================== + +// ====================================================================== +// Install the per-thread-data subsystem +// +// Remarks: +// +// This routine will install the per-thread-data subsystem that is required for several +// other subsystems in the engine. It should be called from the primary thread before +// any other threads have been created. It will also call threadInstall() for the +// primary thread. +// +// See Also: +// +// PerThreadData::remove() + +void PerThreadData::install() +{ + slot = TlsAlloc(); + FATAL(slot == BadSlot, ("TlsAlloc failed")); + + criticalSection = new(buffer1) RecursiveMutex; + dataAllocations = new(buffer2) DataAllocations; + dataAllocations->reserve(8); + threadInstall(); +} + +// ---------------------------------------------------------------------- +/** + * Remove the per-thread-subsystem. + * + * This routine should be called by the primary thread after all other threads have + * terminated, and no other uses of per-thread-data will occur. + * + * @see PerThreadData::install() + */ +void PerThreadData::remove() +{ + criticalSection->enter(); + { + // remove this thread. + threadRemove(); + + // clean up after any threads which didn't clean up after themselves (like the miles sound system) + const DataAllocations::iterator iEnd = dataAllocations->end(); + for (DataAllocations::iterator i = dataAllocations->begin(); i != iEnd; ++i) + { + _closeData(*i); + _freeData(*i); + } + + dataAllocations->clear(); + } + criticalSection->leave(); + + criticalSection->~RecursiveMutex(); + dataAllocations->~vector(); + + memset(buffer1, 0, sizeof(buffer1)); + memset(buffer2, 0, sizeof(buffer2)); + + const BOOL result = TlsFree(slot); + FATAL(!result, ("TlsFree failed")); +} + +// ---------------------------------------------------------------------- +/** + * Create the per-thread-data for a new thread. + * + * This routine should be called in a thread before the first usage of per-thread-data. + * + * If the client is calling this function on a thread that existed before the engine was + * installed, the client should set isNewThread to false. Setting isNewThread to false + * prevents the function from validating that the thread's TLS is NULL. For threads existing + * before the engine is installed, the TLS data for the thread is undefined. + * + * @param isNewThread [IN] true if the thread was created after the engine was installed, false otherwise + * @see PerThreadData::threadRemove() + */ + +void PerThreadData::threadInstall(bool isNewThread) +{ + UNREF(isNewThread); + + DEBUG_FATAL(slot == BadSlot, ("not installed")); + + // only check for already-set data if this is supposed to be a new thread + DEBUG_FATAL(isNewThread && TlsGetValue(slot), ("already installed for this thread")); + + // create the data + Data * const data = new Data; + + // initialize the data + memset(data, 0, sizeof(*data)); + + //create the event for file streaming reads + data->fileStreamerReadGate = new Gate(false); + + // set the data into the thread slot + const BOOL result = TlsSetValue(slot, data); + UNREF(result); + DEBUG_FATAL(!result, ("TlsSetValue failed")); + + criticalSection->enter(); + { + _watchThreads(); + + dataAllocations->push_back(data); + + // This is most likely a thread created by a 3rd party library such as Miles or Bink. + // Add a watch handle to it so we can clean it up. + if (!isNewThread) + { + const HANDLE processHandle = GetCurrentProcess(); + DuplicateHandle(processHandle, GetCurrentThread(), processHandle, &data->watchHandle, 0, FALSE, DUPLICATE_SAME_ACCESS); + } + } + criticalSection->leave(); +} + +// ---------------------------------------------------------------------- + +void PerThreadDataNamespace::_removeFromList(Data *data) +{ + const DataAllocations::iterator iEnd = dataAllocations->end(); + const DataAllocations::iterator i = std::find(dataAllocations->begin(), iEnd, data); + if (i!=iEnd) + { + dataAllocations->erase(i); + } +} + +// ---------------------------------------------------------------------- +// Synchronization is left up to the user +// Unless this is called during shutdown, the critical section +// needs to be entered. +void PerThreadDataNamespace::_watchThreads() +{ + DataAllocations::iterator tiDest = dataAllocations->begin(); + DataAllocations::iterator tiSrc = tiDest; + DataAllocations::iterator tiEnd = dataAllocations->end(); + + while (tiSrc!=tiEnd) + { + Data *const data = *tiSrc; + const HANDLE h = data->watchHandle; + + if (h!=0 && WaitForSingleObject(h, 0)==WAIT_OBJECT_0) + { + _closeData(data); + _freeData(data); + } + else + { + *tiDest++=data; + } + ++tiSrc; + } + + if (tiSrc!=tiDest) + { + const int newSize = tiDest - dataAllocations->begin(); + dataAllocations->resize(newSize); + } +} + +// ---------------------------------------------------------------------- + +void PerThreadDataNamespace::_threadRemove(Data *data) +{ + //close the event used for file streaming reads + _closeData(data); + + _removeFromList(data); + + // free the memory + _freeData(data); +} + +// ---------------------------------------------------------------------- +/** + * Destroy the per-thread-data for a terminating thread. + * + * This routine should be called in a thread after the last usage of per-thread-data. + * + * @see PerThreadData::threadInstall() + */ + +void PerThreadData::threadRemove() +{ + DEBUG_FATAL(slot == BadSlot, ("not installed")); + DEBUG_FATAL(!TlsGetValue(slot), ("thread not installed")); + + // find our thread record and free the memory + criticalSection->enter(); + + _threadRemove(_getData()); + + // wipe the data in the thread slot + const BOOL result = TlsSetValue(slot, NULL); + UNREF(result); + DEBUG_FATAL(!result, ("TlsSetValue failed")); + + criticalSection->leave(); +} + +// ====================================================================== + +// ====================================================================== +// Determine if the per-thread-data is available for this thread +// +// Return value: +// +// True if the per-thread-data is installed correctly, false otherwise +// +// Remarks: +// +// This routine is not intended for general use; it should only be used by the ExitChain class. +// +// -TRF- looks like Win98 does not zero out a new TLS slot for +// threads existing at the time of slot creation. Thus, if you build a +// plugin that only initializes the engine the first time it is +// used, and other threads already exist in the app, those threads +// will contain bogus non-null data in the TLS slot. If the plugin really +// wants to do lazy initialization of the engine, it will need +// to handle calling PerThreadData::threadInstall() for all existing threads +// (except the thread that initialized the engine, which already +// has its PerThreadData::threadInstall() called). + +bool PerThreadData::isThreadInstalled() +{ + return (_getData(true) != NULL); +} + +// ---------------------------------------------------------------------- +/** + * Get the exit chain running flag value. + * + * This routine is not intended for general use; it should only be used by the ExitChain class. + * + * @return True if the exit chain is running, false otherwise. + * @see ExitChain::isRunning() + */ + +bool PerThreadData::getExitChainRunning() +{ + return _getData()->exitChainRunning; +} + +// ---------------------------------------------------------------------- +/** + * Set the exit chain running flag value. + * + * This routine is not intended for general use; it should only be used by the ExitChain class. + * + * @param newValue New value for the exit chain running flag + */ + +void PerThreadData::setExitChainRunning(bool newValue) +{ + _getData()->exitChainRunning = newValue; +} + +// ---------------------------------------------------------------------- +/** + * Get the exit chain fataling flag value. + * + * This routine is not intended for general use; it should only be used by the ExitChain class. + * + * @return True if the exit chain is fataling, false otherwise. + * @see ExitChain::isFataling() + */ + +bool PerThreadData::getExitChainFataling() +{ + return _getData()->exitChainFataling; +} + +// ---------------------------------------------------------------------- +/** + * Set the exit chain fataling flag value. + * + * This routine is not intended for general use; it should only be used by the ExitChain class. + * + * @param newValue New value for the exit chain fataling flag + */ + +void PerThreadData::setExitChainFataling(bool newValue) +{ + _getData()->exitChainFataling = newValue; +} + +// ---------------------------------------------------------------------- +/** + * Get the first entry for the exit chain. + * + * This routine is not intended for general use; it should only be used by the ExitChain class. + * This routine may return NULL. + * + * @return Pointer to the first entry on the exit chain + * @see ExitChain::isFataling() + */ + +ExitChain::Entry *PerThreadData::getExitChainFirstEntry() +{ + return _getData()->exitChainFirstEntry; +} + +// ---------------------------------------------------------------------- +/** + * Set the exit chain fataling flag value. + * + * This routine is not intended for general use; it should only be used by the ExitChain class. + * The parameter to this routine may be NULL. + * + * @param newValue New value for the exit chain first entry + */ + +void PerThreadData::setExitChainFirstEntry(ExitChain::Entry *newValue) +{ + _getData()->exitChainFirstEntry = newValue; +} + +// ---------------------------------------------------------------------- +/** + * Get the debug print flags. + * + * This routine is not intended for general use; it should only be used by the DebugPrint functions. + * + * @return Current value of the debug print flags + */ + +int PerThreadData::getDebugPrintFlags() +{ + return _getData()->debugPrintFlags; +} + +// ---------------------------------------------------------------------- +/** + * Set the debug print flags value. + * + * This routine is not intended for general use; it should only be used by the DebugPrint functions. + */ + +void PerThreadData::setDebugPrintFlags(int newValue) +{ + _getData()->debugPrintFlags = newValue; +} + +// ---------------------------------------------------------------------- + +Gate *PerThreadData::getFileStreamerReadGate() +{ + return _getData()->fileStreamerReadGate; +} + +// ====================================================================== diff --git a/engine/shared/library/sharedFoundation/src/win32/PerThreadData.h b/engine/shared/library/sharedFoundation/src/win32/PerThreadData.h new file mode 100755 index 00000000..e45a4170 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/PerThreadData.h @@ -0,0 +1,57 @@ +// ====================================================================== +// +// PerThreadData.h +// +// Portions copyright 1998 Bootprint Entertainment +// Portions Copyright 2002 Sony Online Entertainment +// All Rights Reserved +// +// ====================================================================== + +#ifndef INCLUDED_PerThreadData_H +#define INCLUDED_PerThreadData_H + +// ====================================================================== + +class Gate; + +#include "sharedFoundation/ExitChain.h" + +// ====================================================================== + +// Provide thread local storage functionality. +// +// This class' purpose is to allow each thread to maintain some storage that is local and private to each thread. +// The system must be installed before use. Each thread that may use per-thread-data will also need to call the +// threadInstall() routine after creation and threadRemove() just before termination of the thread. + +class PerThreadData +{ +public: + + static void install(void); + static void remove(void); + + static void threadInstall(bool isNewThread = true); + static void threadRemove(void); + + static bool isThreadInstalled(void); + + static bool getExitChainRunning(void); + static void setExitChainRunning(bool newValue); + + static bool getExitChainFataling(void); + static void setExitChainFataling(bool newValue); + + static ExitChain::Entry *getExitChainFirstEntry(void); + static void setExitChainFirstEntry(ExitChain::Entry *newValue); + + static int getDebugPrintFlags(void); + static void setDebugPrintFlags(int newValue); + + static Gate *getFileStreamerReadGate(void); +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/PlatformGlue.cpp b/engine/shared/library/sharedFoundation/src/win32/PlatformGlue.cpp new file mode 100755 index 00000000..cf562e00 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/PlatformGlue.cpp @@ -0,0 +1,124 @@ +// ====================================================================== +// +// PlatformGlue.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedFoundation/PlatformGlue.h" + +#include +#include + +// ====================================================================== + +namespace +{ + +// ---------------------------------------------------------------------- + +class GmTimeSection +{ +public: + + GmTimeSection() + { + InitializeCriticalSection(&m_section); + } + + ~GmTimeSection() + { + DeleteCriticalSection(&m_section); + } + + void enter() + { + EnterCriticalSection(&m_section); + } + + void leave() + { + LeaveCriticalSection(&m_section); + } + +private: + CRITICAL_SECTION m_section; +}; + +// ---------------------------------------------------------------------- + +static GmTimeSection s_gmTimeSection; + +// ---------------------------------------------------------------------- + +} + +// ====================================================================== +// Tokenizing a string. +// Like strtok, except re-entrant. + +char *strsep(char **string, const char *delim) +{ + char *result = *string; + + // handle no string specified, or the end of the string + if (result == 0) + return 0; + + // skip leading delimiters + result = result + strspn(result, delim); + + // handle trailing delimiters + if (*result == '\0') + return 0; + + // look for the first delimiter + const int len = strcspn(result, delim); + if (result[len] == '\0') + { + // hit the end of the string + *string = 0; + } + else + { + // terminate the string and return the substring + result[len] = '\0'; + *string = result + len + 1; + } + + return result; +} + +// ---------------------------------------------------------------------- + +int snprintf(char *buffer, size_t count, const char *format, ...) +{ + va_list va; + + va_start(va, format); + const int result = _vsnprintf(buffer, count, format, va); + va_end(va); + + return result; +} + +// ---------------------------------------------------------------------- + +struct tm *gmtime_r(const time_t *timep, struct tm *result) +{ + s_gmTimeSection.enter(); + tm *t = gmtime(timep); + *result = *t; + s_gmTimeSection.leave(); + return result; +} + +// ---------------------------------------------------------------------- + +int finite(double value) +{ + return _finite(value); +} + +// ====================================================================== diff --git a/engine/shared/library/sharedFoundation/src/win32/PlatformGlue.h b/engine/shared/library/sharedFoundation/src/win32/PlatformGlue.h new file mode 100755 index 00000000..7eec7bb5 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/PlatformGlue.h @@ -0,0 +1,32 @@ +// ====================================================================== +// +// PlatformGlue.h +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_PlatformGlue_H +#define INCLUDED_PlatformGlue_H + +// ====================================================================== + +#include + +// ====================================================================== + +char * strsep(char **string, const char *delim); +int snprintf(char *buffer, size_t count, const char *format, ...); +struct tm * gmtime_r(const time_t *timep, struct tm *result); +int finite(double value); + +//Format specifier for non-portable printf +#define UINT64_FORMAT_SPECIFIER "%I64u" +#define INT64_FORMAT_SPECIFIER "%I64i" + +//Constant definition macro for 64 bit values +#define UINT64_LITERAL(a) a ## ui64 +#define INT64_LITERAL(a) a ## i64 + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/ProcessSpawner.cpp b/engine/shared/library/sharedFoundation/src/win32/ProcessSpawner.cpp new file mode 100755 index 00000000..987e9b64 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/ProcessSpawner.cpp @@ -0,0 +1,310 @@ +// +// ProcessSpawner.cpp +// +//------------------------------------------------------------------- + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedFoundation/ProcessSpawner.h" + +#include "sharedFoundation/Os.h" + +#include + +ProcessSpawner::ProcessSpawner() +{ + m_asConsole=false; + hProcess=0; + hOutputRead=0; + hInputWrite=0; + currentLine=currentRead=readBuffer; +} + + +ProcessSpawner::~ProcessSpawner() +{ + if (hProcess) + { + CloseHandle(hProcess); + hProcess=0; + } + if (hOutputRead) + { + CloseHandle(hOutputRead); + hOutputRead=0; + } + if (hInputWrite) + { + CloseHandle(hInputWrite); + hInputWrite=0; + } +} + +bool ProcessSpawner::terminate(unsigned exitCode) +{ + if (!hProcess) + { + return false; + } + return TerminateProcess(hProcess, exitCode)!=0; +} + +bool ProcessSpawner::create(const char *commandLine, const char *startupFolder, bool asConsole) +{ + if (hProcess) + { + return false; + } + + if (!commandLine) + { + return false; + } + + if (!startupFolder) + { + startupFolder=Os::getProgramStartupDirectory(); + } + + m_asConsole=asConsole; + + STARTUPINFO sinfo; + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.cb=sizeof(sinfo); + + HANDLE hOutputWrite=0; + HANDLE hErrorWrite=0; + HANDLE hInputRead=0; + + if (asConsole) + { + SECURITY_ATTRIBUTES sa; + sa.nLength=sizeof(sa); + sa.lpSecurityDescriptor=0; + sa.bInheritHandle=true; + + // ----------------------------------------------------- + + // Create the child output pipe. + HANDLE hOutputReadTmp; + CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0); + + // Create a duplicate of the output write handle for the std error + // write handle. This is necessary in case the child application + // closes one of its std output handles. + DuplicateHandle( + GetCurrentProcess(), hOutputWrite, + GetCurrentProcess(),&hErrorWrite, + 0, + TRUE,DUPLICATE_SAME_ACCESS + ); + + + // Create the child input pipe. + HANDLE hInputWriteTmp; + CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0); + + // Create new output read handle and the input write handles. Set + // the Properties to FALSE. Otherwise, the child inherits the + // properties and, as a result, non-closeable handles to the pipes + // are created. + DuplicateHandle( + GetCurrentProcess(), hOutputReadTmp, + GetCurrentProcess(), &hOutputRead, // Address of new handle. + 0, FALSE, // Make it uninheritable. + DUPLICATE_SAME_ACCESS + ); + + DuplicateHandle( + GetCurrentProcess(), hInputWriteTmp, + GetCurrentProcess(), &hInputWrite, // Address of new handle. + 0,FALSE, // Make it uninheritable. + DUPLICATE_SAME_ACCESS + ); + + + // Close inheritable copies of the handles you do not want to be + // inherited. + CloseHandle(hOutputReadTmp); hOutputReadTmp=0; + CloseHandle(hInputWriteTmp); hInputWriteTmp=0; + + sinfo.dwFlags|=(STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW); + sinfo.hStdError=hErrorWrite; + sinfo.hStdInput=hInputRead; + sinfo.hStdOutput=hOutputWrite; + sinfo.wShowWindow = SW_HIDE; + } + + PROCESS_INFORMATION pinfo; + BOOL result = CreateProcess( + 0, + (char *)commandLine, + 0, + 0, + TRUE, + CREATE_NEW_CONSOLE, + 0, + startupFolder, + &sinfo, + &pinfo + ); + + if (asConsole) + { + // Close pipe handles (do not continue to modify the parent). + // You need to make sure that no handles to the write end of the + // output pipe are maintained in this process or else the pipe will + // not close when the child process exits and the ReadFile will hang. + CloseHandle(hOutputWrite); hOutputWrite=0; + CloseHandle(hErrorWrite); hErrorWrite=0; + CloseHandle(hInputRead); hInputRead=0; + } + + if (result) + { + CloseHandle(pinfo.hThread); + hProcess=pinfo.hProcess; + return true; + } + else + { + // Failed to launch turf + hProcess=0; + return false; + } +} + +bool ProcessSpawner::isFinished(unsigned waitTime) +{ + if (!hProcess) + { + return true; + } + + DWORD waitResult = WaitForSingleObject(hProcess, waitTime); + + return waitResult==WAIT_OBJECT_0; +} + +bool ProcessSpawner::getExitCode(unsigned &o_code) +{ + if (!hProcess) + { + return false; + } + + DWORD exitCode; + BOOL result = GetExitCodeProcess(hProcess, &exitCode); + if (result) + { + o_code=exitCode; + return true; + } + else + { + return false; + } +} + +bool ProcessSpawner::_returnExistingLine(char *buffer, const int bufferSize) +{ + const char *const bufferStop = buffer + bufferSize; + char *iter = currentLine; + while (iter!=currentRead) + { + if (buffer==bufferStop) + { + currentLine=iter; + return true; + } + + if (*iter=='\n') + { + *buffer++=0; + _stepIter(iter); + currentLine=iter; + return true; + } + else + { + *buffer++=*iter; + _stepIter(iter); + } + } + + return false; +} + +bool ProcessSpawner::getOutputString(char *buffer, int bufferSize) +{ + if (_returnExistingLine(buffer, bufferSize)) + { + return true; + } + + // ---------------------------------------------- + + if (!hOutputRead) + { + return false; + } + + DWORD dwAvail = 0; + if (!::PeekNamedPipe(hOutputRead, NULL, 0, NULL, &dwAvail, NULL)) + { + // ERROR + return false; + } + + if (!dwAvail) + { + return false; + } + + DWORD dwRead; + + if (currentRead >= currentLine) + { + const unsigned bufferAvailable = sizeof(readBuffer) - (currentRead - readBuffer); + unsigned toRead = dwAvail; + if (toRead > bufferAvailable) + { + toRead=bufferAvailable; + } + + dwRead=0; + if (!::ReadFile(hOutputRead, currentRead, min(bufferAvailable, dwAvail), &dwRead, NULL) || !dwRead) + { + return false; + } + dwAvail-=dwRead; + currentRead+=dwRead; + if (currentRead==readBuffer+sizeof(readBuffer)) + { + currentRead=readBuffer; + } + } + + if (dwAvail>0) + { + const unsigned bufferAvailable = currentLine - currentRead - 1; + if (bufferAvailable) + { + unsigned toRead = dwAvail; + if (toRead > bufferAvailable) + { + toRead=bufferAvailable; + } + + dwRead=0; + if (!::ReadFile(hOutputRead, currentRead, min(bufferAvailable, dwAvail), &dwRead, NULL) || !dwRead) + { + return false; + } + currentRead+=dwRead; + + DEBUG_FATAL(currentRead>=currentLine, ("")); + } + } + + return _returnExistingLine(buffer, bufferSize); +} diff --git a/engine/shared/library/sharedFoundation/src/win32/ProcessSpawner.h b/engine/shared/library/sharedFoundation/src/win32/ProcessSpawner.h new file mode 100755 index 00000000..ed64750f --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/ProcessSpawner.h @@ -0,0 +1,43 @@ +#ifndef INCLUDED_ProcessSpawner_H +#define INCLUDED_ProcessSpawner_H + +class ProcessSpawner +{ +public: + + ProcessSpawner(); + ~ProcessSpawner(); + + bool create(const char *commandLine, const char *startupFolder=0, bool asConsole=true); + + bool terminate(unsigned exitCode=0); + bool isFinished(unsigned waitTime=0); + bool getExitCode(unsigned &o_code); + + bool getOutputString(char *buffer, int bufferSize); + +protected: + + bool _returnExistingLine(char *buffer, int bufferSize); + + void _stepIter(char *&i) + { + if (i==readBuffer+sizeof(readBuffer)-1) + { + i=readBuffer; + } + else + { + i++; + } + } + + HANDLE hProcess; + HANDLE hOutputRead, hInputWrite; + bool m_asConsole; + char *currentLine, *currentRead, readBuffer[4096]; +}; + +#endif + + diff --git a/engine/shared/library/sharedFoundation/src/win32/RegistryKey.cpp b/engine/shared/library/sharedFoundation/src/win32/RegistryKey.cpp new file mode 100755 index 00000000..a29d0db5 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/RegistryKey.cpp @@ -0,0 +1,918 @@ +// ====================================================================== +// +// RegistryKey.cpp +// Todd Fiala +// +// copyright 1998 Bootprint Entertainment +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedFoundation/RegistryKey.h" + +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/ConfigFile.h" + +#if USE_REGISTRY_EXECUTION_STATISTICS +#include +#include +#endif + +// ====================================================================== + +// keyname for config file parameter containing relative registry path +// for the product + +const char * const RegistryKey::PRODUCT_REGISTRY_PATH_KEYNAME = "ProductRegistryPath"; +const char * const RegistryKey::DEFAULT_PRODUCT_REGISTRY_PATH = "Software\\Sony Online Entertainment\\Default"; + +#if USE_REGISTRY_EXECUTION_STATISTICS +const char * const RegistryKey::STATISTICS_KEYNAME = "Statistics"; +const char * const RegistryKey::STAT_EXEC_STARTED_COUNT_VALUENAME = "StartedExecutions"; +const char * const RegistryKey::STAT_EXEC_INCOMPLETE_COUNT_VALUENAME = "IncompleteExecutions"; +const char * const RegistryKey::STAT_TIME_AVERAGE_VALUENAME = "AverageClockTime"; +const char * const RegistryKey::STAT_TIME_MIN_VALUENAME = "MinimumClockTime"; +const char * const RegistryKey::STAT_TIME_MAX_VALUENAME = "MaximumClockTime"; +const char * const RegistryKey::STAT_TIME_START_VALUENAME = "StartClockTime"; + +#endif + +bool RegistryKey::installed; +bool RegistryKey::setProductKeyPathFromConfig; + +RegistryKey *RegistryKey::usersKey; +RegistryKey *RegistryKey::currentUserKey; +RegistryKey *RegistryKey::classRootKey; +RegistryKey *RegistryKey::localMachineKey; +RegistryKey *RegistryKey::productUserKey; +RegistryKey *RegistryKey::productMachineKey; + +// ====================================================================== +// construct a RegistryKey instance +// +// Remarks: +// This function does not create the underlying registry object. It +// solely attaches such a registry object with a RegistryKey class +// instance. + +RegistryKey::RegistryKey( + HKEY newKeyHandle, // [IN] handle of existing registry key + bool newCloseKeyOnDestroy // [IN] true if RegCloseKey() should be called on key at destruction time + ) : + keyHandle(newKeyHandle), + closeKeyOnDestroy(newCloseKeyOnDestroy) +{ + // -qq- don't know which of these indicates an invalid handle, so check for both + DEBUG_FATAL(!newKeyHandle, ("null newKeyHandle arg")); + DEBUG_FATAL(newKeyHandle == INVALID_HANDLE_VALUE, ("newKeyHandle arg is an invalid handle")); +} + +// ---------------------------------------------------------------------- +/** + * destroy a RegistryKey instance. + */ + +RegistryKey::~RegistryKey(void) +{ + DEBUG_FATAL(!keyHandle, ("null keyHandle")); + + if (closeKeyOnDestroy) + { + const LONG result = RegCloseKey(keyHandle); + UNREF(result); + DEBUG_FATAL(result != ERROR_SUCCESS, ("failed to close registry key, error = %ld\n", result)); + } + keyHandle = 0; +} + +// ---------------------------------------------------------------------- +/** + * enumerate all child subkeys of the current key. + * + * @param context [IN] user-specified context variable passed to callback + * @param callback [IN] function to call for each subkey enumerated + * @see EnumerateKeyCallback, enumerateValues() + */ + +void RegistryKey::enumerateSubkeys(void *context, EnumerateKeyCallback callback) const +{ + const size_t MAX_NAME_LENGTH = 256; + + LONG result; + FILETIME lastModifiedFileTime; + char subkeyName[MAX_NAME_LENGTH]; + DWORD subkeyNameLength; + DWORD index; + + DEBUG_FATAL(!callback, ("null callback arg\n")); + + for ( + index = 0, subkeyNameLength = MAX_NAME_LENGTH; + ERROR_SUCCESS == (result = RegEnumKeyEx(keyHandle, index, subkeyName, &subkeyNameLength, 0, 0, 0, &lastModifiedFileTime)); + ++index, subkeyNameLength = MAX_NAME_LENGTH + ) + { + bool continueEnum = callback(context, subkeyName, &lastModifiedFileTime); + if (!continueEnum) break; + } + + // ensure we finished enumeration cleanly + FATAL( + (result != ERROR_SUCCESS) && (result != ERROR_NO_MORE_ITEMS), + ("failed to enumerate registry subkeys, error = %ld\n", result)); +} + +// ---------------------------------------------------------------------- +/** + * open and return a subkey under this RegistryKey instance. + * + * The function will fail if the specified subkey does not exist. + * + * @param subkeyName [IN] registry path for subkey to open, relative to this RegistryKey instance + * @param accessFlags [IN] flags indicating access granted to the returned RegistryKey + * @return This function returns a RegistryKey instance for the specified + * subkey. + */ + +RegistryKey *RegistryKey::openSubkey(const char *subkeyName, uint32 accessFlags) const +{ + REGSAM samDesired = 0; + LONG result; + HKEY newKey = 0; + + DEBUG_FATAL(!keyHandle, ("null keyHandle")); + DEBUG_FATAL(!subkeyName, ("null subkeyName arg")); + DEBUG_FATAL(!strlen(subkeyName), ("zero-length subkeyName arg")); + + // configure security access desired + if (accessFlags & AF_READ) + samDesired |= KEY_READ; + if (accessFlags & AF_WRITE) + samDesired |= KEY_WRITE; + + // open the key + result = RegOpenKeyEx(keyHandle, subkeyName, 0, samDesired, &newKey); + FATAL(result != ERROR_SUCCESS, ("failed to open registry subkey \"%s\", error = %ld\n", subkeyName, result)); + + // Create the RegistryKey object. Assume the key must be closed upon + // destruction. + return new RegistryKey(newKey, true); +} + +// ---------------------------------------------------------------------- +/** + * create and return a subkey under this RegistryKey instance. + * + * The function will succeed even if the specified subkey + * already exists. + * + * @return This function returns a RegistryKey instance for the specified + * subkey. + */ + +RegistryKey *RegistryKey::createSubkey(const char *subkeyName, uint32 accessFlags) const +{ + REGSAM samDesired = 0; + LONG result; + HKEY newKey = 0; + DWORD disposition; + + DEBUG_FATAL(!keyHandle, ("null keyHandle")); + DEBUG_FATAL(!subkeyName, ("null subkeyName arg")); + DEBUG_FATAL(!strlen(subkeyName), ("zero-length subkeyName arg")); + + // configure security access desired + if (accessFlags & AF_READ) + samDesired |= KEY_READ; + if (accessFlags & AF_WRITE) + samDesired |= KEY_WRITE; + + // open the key + result = RegCreateKeyEx( + keyHandle, + subkeyName, + 0, // reserved + const_cast(""), // class + REG_OPTION_NON_VOLATILE, // options + samDesired, + NULL, // security + &newKey, + &disposition); + FATAL(result != ERROR_SUCCESS, ("failed to create registry subkey \"%s\", error = %ld\n", subkeyName, result)); + + // Create the RegistryKey object. Assume the key must be closed upon + // destruction. + return new RegistryKey(newKey, true); +} + +// ---------------------------------------------------------------------- +/** + * delete a subkey relative to this RegistryKey instance. + * + * Under Windows NT, deleting a key that has subkeys is considered an + * error. Therefore, the client should ensure the target key for + * deletion does not have any subkeys. (Under Windows 9X, deletion of + * the target registry key will automatically delete all subkeys + * underneath the target key.) + */ + +void RegistryKey::deleteSubkey(const char *subkeyName) +{ + DEBUG_FATAL(!keyHandle, ("null keyHandle")); + DEBUG_FATAL(!subkeyName, ("null subkeyName arg")); + DEBUG_FATAL(!strlen(subkeyName), ("zero-length subkeyName arg")); + + IGNORE_RETURN(RegDeleteKey(keyHandle, subkeyName)); +} + +// ---------------------------------------------------------------------- +/** + * test for the existence of a subkey under this RegistryKey instance. + * + * @param subkeyName [IN] registry path for subkey to open, relative to this RegistryKey instance + */ + +bool RegistryKey::subKeyExists(const char *subkeyName) +{ + REGSAM samDesired = KEY_READ; + LONG result; + HKEY newKey = 0; + + DEBUG_FATAL(!keyHandle, ("null keyHandle")); + DEBUG_FATAL(!subkeyName, ("null subkeyName arg")); + DEBUG_FATAL(!strlen(subkeyName), ("zero-length subkeyName arg")); + + // open the key + result = RegOpenKeyEx(keyHandle, subkeyName, 0, samDesired, &newKey); + return (result == ERROR_SUCCESS); +} + +// ---------------------------------------------------------------------- +/** + * enumerate all values under the current key. + * + * @param context [IN] user-specified context variable passed to callback + * @param callback [IN] function to call for each value enumerated + * @see EnumerateValueCallback, enumerateSubkeys() + */ + +void RegistryKey::enumerateValues(void *context, EnumerateValueCallback callback) const +{ + const size_t MAX_NAME_LENGTH = 256; + + LONG result; + char valueName[MAX_NAME_LENGTH]; + DWORD valueNameLength; + DWORD index; + DWORD dataSize; + DWORD valueType; + + DEBUG_FATAL(!callback, ("null callback arg\n")); + + for ( + index = 0, valueNameLength = MAX_NAME_LENGTH, dataSize = 0; + ERROR_SUCCESS == (result = RegEnumValue(keyHandle, index, valueName, &valueNameLength, 0, &valueType, 0, &dataSize)); + ++index, valueNameLength = MAX_NAME_LENGTH, dataSize = 0 + ) + { + bool continueEnum = callback(context, valueName, static_cast(dataSize), valueType); + if (!continueEnum) break; + } + + // ensure we finished enumeration cleanly + FATAL( + (result != ERROR_SUCCESS) && (result != ERROR_NO_MORE_ITEMS), + ("failed to enumerate registry values, error = %ld\n", result)); +} + +// ---------------------------------------------------------------------- +/** + * query if a value exists and how many bytes that value occupies. + * + * The client does can pass null for the valueSize and/or valueType + * parameter if that information is not desired. The value returned + * within the valueSize and valueType parameter is only valid + * if the doesExist parameter is set to true upon function return. + * The value of the valueType parameter is one of the Windows-defined + * REG_* constants provided for use with the Win32 Reg* registry + * API. Common values are REG_BINARY (binary data), REG_DWORD + * (unsigned integral type data) and REG_SZ (C-style zero-terminated + * strings). Consult the Win32 documentation for RegGetValueEx() + * for a description of all the type constants. + * + * @param valueName [IN] name of the value to query + * @param doesExist [OUT] true if value exists under this key, false otherwise + * @param valueSize [OUT] number of bytes occupied by value's data + * @param valueType [OUT] type flag for registry value (see REG_* in RegSetValueEx()) + */ + +void RegistryKey::getValueInfo(const char *valueName, bool *doesExist, uint32 *valueSize, DWORD *valueType) const +{ + LONG result; + DWORD dwSize = 0; + + DEBUG_FATAL(!keyHandle, ("null keyHandle")); + DEBUG_FATAL(!valueName, ("null valueName arg")); + DEBUG_FATAL(!doesExist, ("null doesExist arg")); + DEBUG_FATAL(!strlen(valueName), ("zero-length valueName arg")); + + // get information on the value + result = RegQueryValueEx(keyHandle, valueName, 0, valueType, 0, &dwSize); + + // assume a query failure indicates the value was not found + *doesExist = (result == ERROR_SUCCESS); + if (valueSize) + *valueSize = static_cast(dwSize); +} + +// ---------------------------------------------------------------------- +/** + * set the data for this key's value. + * + * The value of the valueType parameter is one of the Windows-defined + * REG_* constants provided for use with the Win32 Reg* registry + * API. Common values are REG_BINARY (binary data), REG_DWORD + * (unsigned integral type data) and REG_SZ (C-style zero-terminated + * strings). Consult the Win32 documentation for RegGetValueEx() + * for a description of all the type constants. + * + * @param valueName [IN] name of value under which data will be stored + * @param dataPtr [IN] pointer to buffer containing value's data + * @param dataSize [IN] # bytes to store + * @param valueType [IN] type field for value (indicates nature of data stored with value) + */ + +void RegistryKey::setValue(const char *valueName, const void *dataPtr, uint32 dataSize, DWORD valueType) +{ + LONG result; + + DEBUG_FATAL(!keyHandle, ("null keyHandle")); + DEBUG_FATAL(!valueName, ("null valueName arg")); + DEBUG_FATAL(!strlen(valueName), ("zero-length valueName arg")); + DEBUG_FATAL(!dataPtr, ("null dataPtr arg")); + + // get information on the value + result = RegSetValueEx(keyHandle, valueName, 0, valueType, static_cast(dataPtr), static_cast(dataSize)); + FATAL(result != ERROR_SUCCESS, ("failed to set registry value \"%s\", error = %ld\n", valueName, result)); +} + +// ---------------------------------------------------------------------- +/** + * retrieve the data for the this key's value. + * + * The valueType and/or the valueDataSize parameter may be set + * to null if the client doesn't need this information. + * The value of the valueType parameter is one of the Windows-defined + * REG_* constants provided for use with the Win32 Reg* registry + * API. Common values are REG_BINARY (binary data), REG_DWORD + * (unsigned integral type data) and REG_SZ (C-style zero-terminated + * strings). Consult the Win32 documentation for RegGetValueEx() + * for a description of all the type constants. + * + * @param valueName [IN] the name of the value to retrieve + * @param dataPtr [OUT] the buffer where the value's data will be stored + * @param maxDataSize [IN] size of the data buffer in bytes + * @param valueDataSize [OUT] number of bytes retrieved from the named value + * @param valueType [OUT] type field for value's data (see REG_* codes in RegSetValueEx) + */ + +void RegistryKey::getValue(const char *valueName, void *dataPtr, uint32 maxDataSize, uint32 *valueDataSize, DWORD *valueType) const +{ + LONG result; + DWORD dwSize = maxDataSize; + + DEBUG_FATAL(!keyHandle, ("null keyHandle")); + DEBUG_FATAL(!valueName, ("null valueName arg")); + DEBUG_FATAL(!strlen(valueName), ("zero-length valueName arg")); + + // get information on the value + result = RegQueryValueEx(keyHandle, valueName, 0, valueType, static_cast(dataPtr), &dwSize); + FATAL(result != ERROR_SUCCESS, ("failed to read registry value \"%s\", error = %ld\n", valueName, result)); + + // assume a query failure indicates the value was not found + if (valueDataSize) + *valueDataSize = static_cast(dwSize); +} + +// ---------------------------------------------------------------------- +/** + * retrieve a string from of this key's values, returning a default string + * if the value doesn't exist. + * + * The defaultValue arg is required, must be non-null. + * + * If the specified value exists but is not of type REG_SZ, the default + * string will be returned. + * + * This routine will DEBUG_FATAL on null args, even if optional is set. + * Optional only controls whether a FATAL occurs if there is an issue + * retrieving the value. + * + * @param valueName [IN] name of the string value to retrieve + * @param defaultValue [IN] string to return if registry key does not contain thev value + * @param dest [OUT] buffer for returned string + * @param destSize [IN] max number of bytes (including terminating null) that can be placed in dest + * @param optional [IN] if set, the function will return false if there is a problem retrieving the value. otherwise, a DEBUG_FATAL will occur + */ + +bool RegistryKey::getStringValue(const char *valueName, const char *defaultValue, char *dest, DWORD destSize, bool optional) +{ + DEBUG_FATAL(!defaultValue, ("null defaultValue arg")); + DEBUG_FATAL(!dest, ("null dest arg")); + + bool doesExist; + DWORD valueType; + DWORD valueSize; + + // clear out string + memset(dest, 0, static_cast(destSize)); + + // get info on the value + getValueInfo (valueName, &doesExist, &valueSize, &valueType); + if (!doesExist || (valueType != REG_SZ)) + strncpy(dest, defaultValue, destSize-1); + else + { + // value exists and is a string, retrieve it + getValue (valueName, dest, destSize, &valueSize); + if (!valueSize) + { + FATAL(!optional, ("failed to get registry data for key %s\n", valueName)); + return false; + } + + // terminate the string + dest [valueSize] = 0; + } + return true; +} + + +// ---------------------------------------------------------------------- +/** + * delete a value from this registry key. + */ + +void RegistryKey::deleteValue(const char *valueName) +{ + LONG result; + + DEBUG_FATAL(!keyHandle, ("null keyHandle")); + DEBUG_FATAL(!valueName, ("null valueName arg")); + DEBUG_FATAL(!strlen(valueName), ("zero-length valueName arg")); + + result = RegDeleteValue(keyHandle, valueName); + FATAL(result != ERROR_SUCCESS, ("failed to delete registry value \"%s\", error = %ld\n", valueName, result)); +} + +#if USE_REGISTRY_EXECUTION_STATISTICS + +// ---------------------------------------------------------------------- +/** + * updates beginning-of-execution statistics using the values under a + * given key. + * + * Call this function at the beginning of execution of the code + * for which statistics are desired. At the end of execution, + * call updateShutdownKey() to finish generating statistics. + * This function should only be called once per execution, + * and should be followed by a call to updateShutdownKey(). + * If the latter is not called, the next call to updateStartupKey() + * will assume the application terminated abnormally before + * proper shutdown could occur. + */ + +void RegistryKey::updateStartupKey(RegistryKey *key) +{ + bool valueExist; + uint32 valueSize; + DWORD valueType; + DWORD execStartedCount = 0; + clock_t startTime = clock(); + + DEBUG_FATAL(!key, ("null key arg\n")); + + // handle improper shutdown of last run + key->getValueInfo(STAT_TIME_START_VALUENAME, &valueExist); + if (valueExist) + { + // appears the product did not run to completion on last run. + // increment the incomplete run counts + + DWORD execIncompleteCount = 0; + + key->getValueInfo(STAT_EXEC_INCOMPLETE_COUNT_VALUENAME, &valueExist); + if (valueExist) + { + key->getValue(STAT_EXEC_INCOMPLETE_COUNT_VALUENAME, &execIncompleteCount, sizeof(DWORD), &valueSize, &valueType); + DEBUG_FATAL((valueType != REG_DWORD) || (valueSize != sizeof(DWORD)), ("%s key not DWORD type as expected\n", STAT_EXEC_INCOMPLETE_COUNT_VALUENAME)); + } + ++execIncompleteCount; + key->setValue(STAT_EXEC_INCOMPLETE_COUNT_VALUENAME, &execIncompleteCount, sizeof(DWORD), REG_DWORD); + } + + // get the start count + key->getValueInfo(STAT_EXEC_STARTED_COUNT_VALUENAME, &valueExist); + if (valueExist) + { + key->getValue(STAT_EXEC_STARTED_COUNT_VALUENAME, &execStartedCount, sizeof(DWORD), &valueSize, &valueType); + DEBUG_FATAL((valueType != REG_DWORD) || (valueSize != sizeof(DWORD)), ("%s key not DWORD type as expected\n", STAT_EXEC_STARTED_COUNT_VALUENAME)); + } + ++execStartedCount; + + // save the data + key->setValue(STAT_EXEC_STARTED_COUNT_VALUENAME, &execStartedCount, sizeof(DWORD), REG_DWORD); + key->setValue(STAT_TIME_START_VALUENAME, &startTime, sizeof(clock_t)); +} + +#endif + + +#if USE_REGISTRY_EXECUTION_STATISTICS + +// ---------------------------------------------------------------------- +/** + * updates end-of-execution statistics using the values under a given key. + * + * This function should only be called after updateStartupKey() + * has been called on the same key. After this call returns, + * this function should not be called again until another + * call to updateStartupKey() is made. + */ + +void RegistryKey::updateShutdownKey(RegistryKey *key) +{ + bool valueExist; + uint32 valueSize; + DWORD valueType; + clock_t minTime; + clock_t maxTime; + clock_t averageTime = 0; + clock_t startTime; + clock_t stopTime = clock(); + clock_t runTime; + DWORD startExecCount; + DWORD incompleteExecCount = 0; + DWORD completeExecCount; + real averageFraction; + + DEBUG_FATAL(!key, ("null key arg\n")); + + // find the number of complete execution runs of the product + key->getValue(STAT_EXEC_STARTED_COUNT_VALUENAME, &startExecCount, sizeof(DWORD), &valueSize, &valueType); + DEBUG_FATAL((valueSize != sizeof(DWORD)) || (valueType != REG_DWORD), ("invalid start count statistic registry value\n")); + + key->getValueInfo(STAT_EXEC_INCOMPLETE_COUNT_VALUENAME, &valueExist); + if (valueExist) + { + key->getValue(STAT_EXEC_INCOMPLETE_COUNT_VALUENAME, &incompleteExecCount, sizeof(DWORD), &valueSize, &valueType); + DEBUG_FATAL((valueType != REG_DWORD) || (valueSize != sizeof(DWORD)), ("%s expected to be DWORD type, was %lu instead\n", STAT_EXEC_INCOMPLETE_COUNT_VALUENAME, valueType)); + } + completeExecCount = startExecCount - incompleteExecCount; + + // retrieve the start time + key->getValue(STAT_TIME_START_VALUENAME, &startTime, sizeof(clock_t), &valueSize, &valueType); + DEBUG_FATAL((valueSize != sizeof(clock_t)) || (valueType != REG_BINARY), ("invalid start time statistic registry value\n")); + + // -qq- we don't handle clock wraparound + runTime = stopTime - startTime; + minTime = runTime; + maxTime = runTime; + + // calculate average time + key->getValueInfo(STAT_TIME_AVERAGE_VALUENAME, &valueExist); + if (valueExist) + { + key->getValue(STAT_TIME_AVERAGE_VALUENAME, &averageTime, sizeof(clock_t), &valueSize, &valueType); + DEBUG_FATAL((valueSize != sizeof(clock_t)) || (valueType != REG_BINARY), ("invalid average exec time statistic registry value\n")); + } + averageFraction = CONST_REAL(1.0 / completeExecCount); + averageTime = static_cast(( CONST_REAL(averageTime) * (completeExecCount-1) + runTime) * averageFraction); + if (averageTime < 1) + averageTime = 1; + + // check min exec time + key->getValueInfo(STAT_TIME_MIN_VALUENAME, &valueExist); + if (valueExist) + { + clock_t testValue; + key->getValue(STAT_TIME_MIN_VALUENAME, &testValue, sizeof(clock_t), &valueSize, &valueType); + DEBUG_FATAL((valueSize != sizeof(clock_t)) || (valueType != REG_BINARY), ("invalid min exec time statistic registry value\n")); + if (testValue < minTime) + minTime = testValue; + } + + // check for max exec time + key->getValueInfo(STAT_TIME_MAX_VALUENAME, &valueExist); + if (valueExist) + { + clock_t testValue; + key->getValue(STAT_TIME_MAX_VALUENAME, &testValue, sizeof(clock_t), &valueSize, &valueType); + DEBUG_FATAL((valueSize != sizeof(clock_t)) || (valueType != REG_BINARY), ("invalid max exec time statistic registry value\n")); + if (testValue > maxTime) + maxTime = testValue; + } + + // save the data + key->setValue(STAT_TIME_AVERAGE_VALUENAME, &averageTime, sizeof(clock_t)); + key->setValue(STAT_TIME_MIN_VALUENAME, &minTime, sizeof(clock_t)); + key->setValue(STAT_TIME_MAX_VALUENAME, &maxTime, sizeof(clock_t)); + + // delete the start time value + key->deleteValue(STAT_TIME_START_VALUENAME); +} + +#endif + + +#if USE_REGISTRY_EXECUTION_STATISTICS + +// ---------------------------------------------------------------------- +/** + * An EnumValueCallback that prints each value name, type and size + * + * @param valueName name of value + * @param valueSize size of value in bytes + * @param valueTye type of value + */ + +bool RegistryKey::enumValueInfoPrint( + void*, // unused user context + const char *valueName, + uint32 valueSize, + DWORD valueType + ) +{ + char *valueTypeStr; + char buffer[64]; + + switch (valueType) + { + case REG_BINARY: + valueTypeStr = "REG_BINARY"; + break; + case REG_DWORD: + valueTypeStr = "REG_DWORD [little endian]"; + break; + case REG_DWORD_BIG_ENDIAN: + valueTypeStr = "REG_DWORD_BIG_ENDIAN"; + break; + case REG_EXPAND_SZ: + valueTypeStr = "REG_EXPAND_SZ"; + break; + case REG_NONE: + valueTypeStr = "REG_NONE"; + break; + case REG_SZ: + valueTypeStr = "REG_SZ"; + break; + default: + valueTypeStr = buffer; + sprintf(buffer, "", valueType); + break; + } + + DEBUG_PRINT_LOG(true, (" Key: \"%s\", %s, %u bytes\n", valueName, valueTypeStr, valueSize)); + + // continue enumerating + return true; +} + +#endif + + +#if USE_REGISTRY_EXECUTION_STATISTICS + +// ---------------------------------------------------------------------- +/** + * Update per-startup registry values. + * + * This routine is used primarily to test registry read/write + * functionality; however, it does provide statistics related + * to game usage. These include the following statistics on + * a per-game and per-machine basis: + * # times product was executed + * average real-time duration of execution + * minimum execution time + * maximum execution time + * # times product failed to execute to completion + * (i.e. updateRegistryShutdown() never executed---hard crash, stop debugging) + */ + +void RegistryKey::updateStartupStatistics(void) +{ + DEBUG_FATAL(!productUserKey, ("null productUserKey\n")); + DEBUG_FATAL(!productMachineKey, ("null productMachineKey\n")); + + // create required keys + RegistryKey *userStatKey = productUserKey->createSubkey(STATISTICS_KEYNAME); + RegistryKey *machineStatKey = productMachineKey->createSubkey(STATISTICS_KEYNAME); + + FATAL(!userStatKey, ("failed to create user statistics key")); + FATAL(!machineStatKey, ("failed to create machine statistics key")); + + // handle machine stat key + +#if 1 + // print existing machine stat keys + DEBUG_PRINT_LOG(true, ("BEGIN machine stat key enumeration:\n")); + machineStatKey->enumerateValues(0, enumValueInfoPrint); + DEBUG_PRINT_LOG(true, ("END machine stat key enumeration:\n")); +#endif + + updateStartupKey(machineStatKey); + + + // handle user stat key + +#if 1 + // print existing user stat keys + DEBUG_PRINT_LOG(true, ("BEGIN user stat key enumeration:\n")); + userStatKey->enumerateValues(0, enumValueInfoPrint); + DEBUG_PRINT_LOG(true, ("END user stat key enumeration:\n")); +#endif + + updateStartupKey(userStatKey); + + // cleanup + delete machineStatKey; + delete userStatKey; +} + +#endif + + +#if USE_REGISTRY_EXECUTION_STATISTICS + +// ---------------------------------------------------------------------- +/** + * Update per-shutdown registry values. + * + * @see updateRegistryStartup() + */ + +void RegistryKey::updateShutdownStatistics(void) +{ + DEBUG_FATAL(!productUserKey, ("null productUserKey\n")); + DEBUG_FATAL(!productMachineKey, ("null productMachineKey\n")); + + // create required keys + RegistryKey *userStatKey = productUserKey->createSubkey(STATISTICS_KEYNAME); + RegistryKey *machineStatKey = productMachineKey->createSubkey(STATISTICS_KEYNAME); + + FATAL(!userStatKey, ("failed to create user statistics key")); + FATAL(!machineStatKey, ("failed to create machine statistics key")); + + // handle machine stat key + updateShutdownKey(machineStatKey); + + // handle user stat key + updateShutdownKey(userStatKey); + + // cleanup + delete machineStatKey; + delete userStatKey; +} + +#endif + +// ---------------------------------------------------------------------- +/** + * install the RegistryKey class. + * + * After installation, the following predefined keys are available: + * + * usersKey: HKEY_USERS + * currentUserKey: HKEY_CURRENT_USER + * classRootKey: HKEY_CLASSES_ROOT + * localMachineKey: HKEY_LOCAL_MACHINE + * productUserKey: HKEY_CURENT_USER\ + * productMachineKey: HKEY_LOCAL_MACHINE\ + * + * The client is free to create any other keys required. + * + * The product relative registry path is determined by the first of the + * following methods that succeed: + * 1. If the config file key "ProductRegistryPath" is set, that value is + * used for the relative path. If the product relative path is set + * in this manner, the client's attempt to change the product relative + * path via the setProductKey() function will silently fail. + * 2. If the productKeyRelativePath parameter is a non-null positive length + * string, that value is used as the product keys' relative path. + * 3. The default value DEFAULT_PRODUCT_REGISTRY_PATH ("Software\\Bootprint\\Default") + * is used. + * + * RegistryKey::remove() is added to the exit chain. + * + * Do not delete any of the predefined registry keys. + * + * @param productKeyRelativePath [IN] relative registry path for the product keys + * @see setProductKeyPath() + */ + +void RegistryKey::install(const char *productKeyRelativePath) +{ + UNREF(productKeyRelativePath); + char *useRegistryPath = 0; + + DEBUG_FATAL(installed, ("attempted to install RegistryKey when already installed\n")); + installed = true; + + // add to exit chain + ExitChain::add(remove, "RegistryKey::remove", 0, true); + + // if no passed in value, use the default + setProductKeyPathFromConfig = false; + useRegistryPath = DuplicateString(DEFAULT_PRODUCT_REGISTRY_PATH); + + // create the Windows-defined RegistryKeys (these keys don't get closed at object destruction time) + usersKey = new RegistryKey(HKEY_USERS, false); //lint !e1924 // Note -- C-style cast + currentUserKey = new RegistryKey(HKEY_CURRENT_USER, false); //lint !e1924 // Note -- C-style cast + classRootKey = new RegistryKey(HKEY_CLASSES_ROOT, false); //lint !e1924 // Note -- C-style cast + localMachineKey = new RegistryKey(HKEY_LOCAL_MACHINE, false); //lint !e1924 // Note -- C-style cast + + // check for errors --- unnecessary if new cannot return NULL + FATAL( + !usersKey || !currentUserKey || !classRootKey || !localMachineKey, + ("failed to create standard RegistryKey objects")); + + // create/open the product user key + productUserKey = currentUserKey->createSubkey(useRegistryPath, AF_READ | AF_WRITE); + + // create/open the product machine key + productMachineKey = localMachineKey->createSubkey(useRegistryPath, AF_READ); + + delete [] useRegistryPath; + +#if USE_REGISTRY_EXECUTION_STATISTICS + updateStartupStatistics(); +#endif +} + +// ---------------------------------------------------------------------- +/** + * release all resources and state associated with the RegistryKey system. + * + * It is invalid to call any RegistryKey functions other than install() + * after calling remove(). + */ + +void RegistryKey::remove(void) +{ +#if USE_REGISTRY_EXECUTION_STATISTICS + updateShutdownStatistics(); +#endif + + DEBUG_FATAL(!installed, ("attempted to remove RegistryKey when not installed\n")); + installed = false; + + delete productMachineKey; + delete productUserKey; + delete localMachineKey; + delete classRootKey; + delete currentUserKey; + delete usersKey; + + productMachineKey = 0; + productUserKey = 0; + localMachineKey = 0; + classRootKey = 0; + currentUserKey = 0; + usersKey = 0; + +} + +// ---------------------------------------------------------------------- +/** + * reset the path to the product's machine and user keys. + * + * This routine will redefine the following keys: + * productUserKey: HKEY_CURENT_USER\ + * productMachineKey: HKEY_LOCAL_MACHINE\ + * + * If the product key relative paths were specified in the config + * file, this routine will essentially do nothing --- the client + * is not able to ovveride the config file settings. + */ + +void RegistryKey::setProductKeyPath(const char *productKeyRelativePath) +{ + DEBUG_FATAL( + !productKeyRelativePath || !productKeyRelativePath[0], + ("invalid productKeyRelativePath arg\n")); + + // don't allow client to overwrite if path set by config file + if (setProductKeyPathFromConfig) + { + DEBUG_REPORT_LOG_PRINT(true, ("attempted to set product registry key path to '%s' but config file setting will override\n", productKeyRelativePath)); + return; + } + + delete productUserKey; + delete productMachineKey; + + productUserKey = currentUserKey->createSubkey(productKeyRelativePath, AF_READ | AF_WRITE); + productMachineKey = localMachineKey->createSubkey(productKeyRelativePath, AF_READ | AF_WRITE); +} + +// ====================================================================== diff --git a/engine/shared/library/sharedFoundation/src/win32/RegistryKey.h b/engine/shared/library/sharedFoundation/src/win32/RegistryKey.h new file mode 100755 index 00000000..9c885194 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/RegistryKey.h @@ -0,0 +1,270 @@ +#ifndef REGISTRY_KEY_H +#define REGISTRY_KEY_H + +// ====================================================================== +// +// RegistryKey.h +// Todd Fiala +// +// copyright 1998 Bootprint Entertainment +// +// ====================================================================== + +// provide read and write access to the Windows Registry +// +// Remarks: +// +// Each RegistryKey can create or open a subkey relative to that +// key. This process produces another RegistryKey. RegistryKeys +// provide a mechanism to enumerate all the child subkeys and values +// associated with the key. In addition, clients may query for +// the presence, type and size of a specific value, get a specific +// value's data, and set a named value's data and type. +// +// The RegistryKey class provides the client with six RegistryKey +// objects as starting points into the registry. See documentation +// for install() for more info on these starting points. +// +// The client must install() the RegistryKey class before using it. + +class RegistryKey +{ +public: + // ---------------------------------------------------------------------- + // flags used to indicate what type of access (e.g. read, write) should + // be granted when creating or opening a key. + // + // See Also: + // + // createSubkey(), openSubkey() + + enum // AccessFlags + { + AF_READ = BINARY1(0001), // query values, enumerate subkeys + AF_WRITE = BINARY1(0010) // set values, create subkeys + }; + + // ---------------------------------------------------------------------- + // callback prototype for subkey enumeration + // + // Return Value: + // + // A return value of true indicates the enumeration of subkeys should + // continue. A return value of false stops further enumeration of + // subkeys. + // + // Remarks: + // + // The context parameter is specified in the call to + // enumerateSubkeys(). One use for this could be to pass a class + // instance, with the callack defined as a static member function. + // The function can then cast the context to a pointer to class + // instance, allowing the static function to access per-instance + // data explicitly in place of an assumed this pointer. + // + // See Also: + // + // enumerateSubkeys() + + typedef bool (*EnumerateKeyCallback)( + void *context, // [IN] user-specified context variable + const char *keyName, // [IN] name of the key being enumerated + const FILETIME *lastWriteTime // [IN] last time this key was modified + ); + + // ---------------------------------------------------------------------- + // callback prototype for value enumeration + // + // Return Value: + // + // A return value of true indicates the enumeration of values should + // continue. A return value of false stops further enumeration of + // values . + // + // Remarks: + // + // The context parameter is specified in the call to + // enumerateValues(). One use for this could be to pass a class + // instance, with the callack defined as a static member function. + // The function can then cast the context to a pointer to class + // instance, allowing the static function to access per-instance + // data explicitly in place of an assumed this pointer. + // + // See Also: + // + // enumerateValues() + + typedef bool (*EnumerateValueCallback)( + void *context, // [IN] user-specified context variable + const char *valueName, // [IN] name of the value being enumerated + uint32 valueSize, // [IN] number of bytes occupied by this value's data + DWORD valueType // [IN] type of value (one of REG_* as in RegSetValueEx documentation) + ); + +private: + static const char * const PRODUCT_REGISTRY_PATH_KEYNAME; + static const char * const DEFAULT_PRODUCT_REGISTRY_PATH; + +#if USE_REGISTRY_EXECUTION_STATISTICS + static const char * const STATISTICS_KEYNAME; + static const char * const STAT_EXEC_STARTED_COUNT_VALUENAME; + static const char * const STAT_EXEC_INCOMPLETE_COUNT_VALUENAME; + static const char * const STAT_TIME_AVERAGE_VALUENAME; + static const char * const STAT_TIME_MIN_VALUENAME; + static const char * const STAT_TIME_MAX_VALUENAME; + static const char * const STAT_TIME_START_VALUENAME; +#endif + + static bool installed; + static bool setProductKeyPathFromConfig; + + // private instance member variables + HKEY keyHandle; + bool closeKeyOnDestroy; + +private: + // public member variables + static RegistryKey *usersKey; + static RegistryKey *currentUserKey; + static RegistryKey *classRootKey; + static RegistryKey *localMachineKey; + static RegistryKey *productUserKey; + static RegistryKey *productMachineKey; + +private: + // private member functions + static void remove(void); + RegistryKey(HKEY newKeyHandle, bool newCloseKeyOnDestroy); + +#if USE_REGISTRY_EXECUTION_STATISTICS + static void updateStartupKey(RegistryKey *key); + static void updateShutdownKey(RegistryKey *key); + static bool enumValueInfoPrint(void *context, const char *valueName, uint32 valueSize, DWORD valueType); + + static void updateStartupStatistics(void); + static void updateShutdownStatistics(void); +#endif + +private: + // disable: default constructor, copy constructor, assignment operator + // NOTE: last two can be implemented, but must be specially handled + RegistryKey(void); + RegistryKey(const RegistryKey&); + RegistryKey &operator =(const RegistryKey&); + +public: + // public member functions + + static void install(const char *productKeyRelativePath = 0); + static void setProductKeyPath(const char *productKeyRelativePath); + + // pre-defined RegistryKey retrieval + static RegistryKey *getUsersKey(void); + static RegistryKey *getCurrentUserKey(void); + static RegistryKey *getClassRootKey(void); + static RegistryKey *getLocalMachineKey(void); + static RegistryKey *getProductUserKey(void); + static RegistryKey *getProductMachineKey(void); + + ~RegistryKey(void); + + // subkey interface + void enumerateSubkeys(void *context, EnumerateKeyCallback callback) const; + RegistryKey *openSubkey(const char *subkeyName, uint32 accessFlags = AF_READ) const; + RegistryKey *createSubkey(const char *subkeyName, uint32 accessFlags = AF_READ | AF_WRITE) const; + void deleteSubkey(const char *subkeyName); + bool subKeyExists(const char *subkeyName); + + // value interface + void enumerateValues(void *context, EnumerateValueCallback callback) const; + void setValue(const char *valueName, const void *dataPtr, uint32 dataSize, DWORD valueType = REG_BINARY); + void deleteValue(const char *valueName); + + void getValueInfo(const char *valueName, bool *doesExist, uint32 *valueSize = 0, DWORD *valueType = 0) const; + void getValue(const char *valueName, void *dataPtr, uint32 maxDataSize, uint32 *valueDataSize, DWORD *valueType = 0) const; + bool getStringValue(const char *valueName, const char *defaultValue, char *dest, DWORD destSize, bool optional = false); + +}; + +// ====================================================================== +// retrieve a key to the HKEY_USERS registry key with read access + +inline RegistryKey *RegistryKey::getUsersKey(void) +{ + DEBUG_FATAL(!installed, ("Attempted to use RegistryKey when not installed\n")); + return usersKey; +} + +// ---------------------------------------------------------------------- +/** + * retrieve a key to the HKEY_CURRENT_USER registry key with read/write + * access. + */ + +inline RegistryKey *RegistryKey::getCurrentUserKey(void) +{ + DEBUG_FATAL(!installed, ("Attempted to use RegistryKey when not installed\n")); + return currentUserKey; +} + +// ---------------------------------------------------------------------- +/** + * retrieve a key to the HKEY_CLASSES_ROOT registry key with read/write + * access. + */ + +inline RegistryKey *RegistryKey::getClassRootKey(void) +{ + DEBUG_FATAL(!installed, ("Attempted to use RegistryKey when not installed\n")); + return classRootKey; +} + +// ---------------------------------------------------------------------- +/** + * retrieve a key to the HKEY_LOCAL_MACHINE registry key with read/write + * access. + */ + +inline RegistryKey *RegistryKey::getLocalMachineKey(void) +{ + DEBUG_FATAL(!installed, ("Attempted to use RegistryKey when not installed\n")); + return localMachineKey; +} + +// ---------------------------------------------------------------------- +/** + * retrieve a key to the product's user key with read/write access. + * + * The product user key is the root key for storing user-specific + * product-related information. install() describes where this + * information exists in the registry. + * + * @see install(), getProductMachineKey() + */ + +inline RegistryKey *RegistryKey::getProductUserKey(void) +{ + DEBUG_FATAL(!installed, ("Attempted to use RegistryKey when not installed\n")); + return productUserKey; +} + +// ---------------------------------------------------------------------- +/** + * retrieve a key to the product's machine key with read/write access. + * + * The product machine key is the root key for storing machine-specific + * product-related information. install() describes where this + * information exists in the registry. + * + * @see install(), getProductUserKey() + */ + +inline RegistryKey *RegistryKey::getProductMachineKey(void) +{ + DEBUG_FATAL(!installed, ("Attempted to use RegistryKey when not installed\n")); + return productMachineKey; +} + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/SetupSharedFoundation.cpp b/engine/shared/library/sharedFoundation/src/win32/SetupSharedFoundation.cpp new file mode 100755 index 00000000..98889b52 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/SetupSharedFoundation.cpp @@ -0,0 +1,410 @@ +// ====================================================================== +// +// SetupSharedFoundation.cpp +// copyright 1998 Bootprint Entertainment +// copyright 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedFoundation/FirstSharedFoundation.h" +#include "sharedFoundation/SetupSharedFoundation.h" + +#include "sharedDebug/DebugMonitor.h" +#include "sharedDebug/InstallTimer.h" +#include "sharedDebug/Profiler.h" + +#include "sharedFoundation/ApplicationVersion.h" +#include "sharedFoundation/Clock.h" +#include "sharedFoundation/CommandLine.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/ConfigSharedFoundation.h" +#include "sharedFoundation/CrashReportInformation.h" +#include "sharedFoundation/CrcLowerString.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/Production.h" +#include "sharedFoundation/RegistryKey.h" +#include "sharedFoundation/StaticCallbackEntry.h" +#include "sharedFoundation/MemoryBlockManager.h" +#include "sharedFoundation/Watcher.h" +#include "sharedLog/TailFileLogObserver.h" + +#include +#include + +// ====================================================================== + +namespace FatalNamespace +{ + extern char ms_buffer[32 * 1024]; +} + +namespace SetupSharedFoundationNamespace +{ + LONG __stdcall MyUnhandledExceptionFilter(LPEXCEPTION_POINTERS exceptionPointers); + + bool ms_writeMiniDumps; +} + +using namespace SetupSharedFoundationNamespace; + +// ====================================================================== + +LONG __stdcall SetupSharedFoundationNamespace::MyUnhandledExceptionFilter(LPEXCEPTION_POINTERS exceptionPointers) +{ + // make the routine somewhat safe from re-entrance + static bool entered = false; + if (entered) + return EXCEPTION_CONTINUE_SEARCH; + entered = true; + + // log some important information + static char buffer[128]; + sprintf(buffer, "Exception %08x(%d)=code %08x=addr\n", exceptionPointers->ExceptionRecord->ExceptionCode, exceptionPointers->ExceptionRecord->ExceptionCode, exceptionPointers->ExceptionRecord->ExceptionAddress); + OutputDebugString(buffer); + + // write the minidump if we're in here for the first time + static bool ms_alreadyWroteMiniDump = false; + if (ms_writeMiniDumps && !ms_alreadyWroteMiniDump) + { + ms_alreadyWroteMiniDump = true; + + uint64 timestamp; + time_t now; + tm t; + + IGNORE_RETURN(time(&now)); + IGNORE_RETURN(gmtime_r(&now, &t)); + timestamp = t.tm_year+1900; //lint !e732 !e737 !e776 + timestamp *= 100; + timestamp += t.tm_mon+1; //lint !e737 !e776 + timestamp *= 100; + timestamp += static_cast(t.tm_mday); + timestamp *= 100; + timestamp += static_cast(t.tm_hour); + timestamp *= 100; + timestamp += static_cast(t.tm_min); + timestamp *= 100; + timestamp += static_cast(t.tm_sec); + + static char fileName[512]; + + sprintf(fileName, "%s-%s-%I64d.txt", Os::getShortProgramName(), ApplicationVersion::getInternalVersion(), timestamp); + HANDLE const file = CreateFile(fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL); + if (file != INVALID_HANDLE_VALUE) + { + char text1[] = "automated crash dump from "; + DWORD bytesWritten; + WriteFile(file, text1, strlen(text1), &bytesWritten, NULL); + + char const * text2 = Os::getShortProgramName(); + WriteFile(file, text2, strlen(text2), &bytesWritten, NULL); + + char text3[] = " "; + WriteFile(file, text3, strlen(text3), &bytesWritten, NULL); + + char const * text4 = ApplicationVersion::getInternalVersion(); + WriteFile(file, text4, strlen(text4), &bytesWritten, NULL); + + char text5[] = "\n\n\n"; + WriteFile(file, text5, strlen(text5), &bytesWritten, NULL); + + if (exceptionPointers->ExceptionRecord->ExceptionCode == 0x80000003) + { + // write out the fatal buffer + char const * text6 = FatalNamespace::ms_buffer; + WriteFile(file, text6, strlen(text6), &bytesWritten, NULL); + } + else + { + char const * text6 = buffer; + WriteFile(file, text6, strlen(text6), &bytesWritten, NULL); + } + + char text7[] = "\n\n"; + WriteFile(file, text7, strlen(text7), &bytesWritten, NULL); + + char const * text8 = ""; + for (int i = 0; text8; ++i) + { + text8 = CrashReportInformation::getEntry(i); + if (text8) + { + int const text8Length = strlen(text8); + if (text8Length) + WriteFile(file, text8, text8Length, &bytesWritten, NULL); + } + } + + CloseHandle(file); + } + + sprintf(fileName, "%s-%s-%I64d.mdmp", Os::getShortProgramName(), ApplicationVersion::getInternalVersion(), timestamp); + OutputDebugString("Generating minidump "); + OutputDebugString(fileName); + OutputDebugString("\n"); + DebugHelp::writeMiniDump(fileName, exceptionPointers); + + sprintf(fileName, "%s-%s-%I64d.log", Os::getShortProgramName(), ApplicationVersion::getInternalVersion(), timestamp); + TailFileLogObserver::flushAllTailFileLogObservers(fileName); + } + + // tell the Os not to abort so we can rethrow the exception + Os::returnFromAbort(); + + // Let the ExitChain do its job + Fatal("ExceptionHandler invoked"); + + // rethrow the exception so that the debugger can catch it + entered = false; + return EXCEPTION_CONTINUE_SEARCH; //lint !e527 // Unreachable +} + +// ---------------------------------------------------------------------- + +static void setFatalVersionString() +{ + char buffer[256]; + sprintf(buffer, "%s: %s\n", Os::getShortProgramName(), ApplicationVersion::getInternalVersion()); + FatalSetVersionString(buffer); +} + +// ====================================================================== +// Install the engine +// +// Remarks: +// +// The settings in the Data structure will determine which subsystems +// get initialized. + +void SetupSharedFoundation::install(const Data &data) +{ + InstallTimer const installTimer("SetupSharedFoundation::install"); + + DEBUG_REPORT_LOG(true, ("SetupSharedFoundation::install: version %s\n", ApplicationVersion::getInternalVersion())); + + ms_writeMiniDumps = data.writeMiniDumps; + SetUnhandledExceptionFilter(MyUnhandledExceptionFilter); + + // and get the command line stuff in quick so we can make decisions based on the command line settings + CommandLine::install(); + + // feed CommandLine with appropriate strings + if (data.commandLine) + CommandLine::absorbString(data.commandLine); + if (data.argc) + CommandLine::absorbStrings(const_cast(data.argv+1), data.argc-1); + + // load the config file + ConfigFile::install(); + if (data.configFile) + IGNORE_RETURN(ConfigFile::loadFile(data.configFile)); + + // get the post command-line text for the ConfigFile (key-value pairs) + const char *configString = CommandLine::getPostCommandLineString(); + if (configString) + { + IGNORE_RETURN(ConfigFile::loadFromCommandLine(configString)); + } + + // @todo codereorg should this be here? + MemoryManager::registerDebugFlags(); +#if PRODUCTION == 0 + Profiler::registerDebugFlags(); +#endif + FatalInstall(); + + // @todo move these, it's part of sharedDebug. However, sharedDebug is installed before sharedFoundation, but these need the ConfigFile. ugh. +#if PRODUCTION == 0 + DebugMonitor::install(); +#endif + SetWarningStrictFatal(ConfigFile::getKeyBool("SharedDebug", "strict", false)); + + { + ConfigSharedFoundation::Defaults defaults; + defaults.frameRateLimit = data.frameRateLimit; + defaults.demoMode = data.demoMode; + defaults.verboseWarnings = data.verboseWarnings; + ConfigSharedFoundation::install(defaults); + + if (ConfigSharedFoundation::getCauseAccessViolation()) + static_cast(0)[0] = 0; + } + + // @todo codereorg should this be here? +#ifdef _DEBUG + MemoryManager::setReportAllocations (ConfigSharedFoundation::getMemoryManagerReportAllocations ()); +#endif + + MemoryBlockManager::install (ConfigSharedFoundation::getMemoryBlockManagerDebugDumpOnRemove ()); + + ExitChain::install(); + Report::install(); + Clock::install(data.clockUsesSleep, data.clockUsesRecalibrationThread); + CrashReportInformation::install(); + RegistryKey::install(data.productRegistryKey); + + PersistentCrcString::install(); + CrcLowerString::install(); + + WatchedByList::install(); + + if (data.createWindow) + { + DEBUG_FATAL(data.useWindowHandle, ("exactly one of createWindow and useWindowHandle must be true")); + Os::install(data.hInstance, data.windowName, data.windowNormalIcon, data.windowSmallIcon); + } + else + { + if (data.useWindowHandle) + Os::install(data.windowHandle, data.processMessagePump); + else + Os::install(); + } + + StaticCallbackEntry::install(); + + setFatalVersionString(); +} + +// ---------------------------------------------------------------------- +// Call a function with appropriate exception handling +// +// Remarks: +// +// If exception handling has been disabled in the config file, this routine +// will call the callback without exception handling. + +void SetupSharedFoundation::callbackWithExceptionHandling( + void (*callback)(void) // Routine to call with exception handling + ) +{ + callback(); +} + +// ---------------------------------------------------------------------- +// Uninstall the engine +// +// Remarks: +// +// This routine will properly uninstall the engine componenets that were +// installed by SetupSharedFoundation::install(). + +void SetupSharedFoundation::remove(void) +{ + ExitChain::quit(); + + if (!ConfigSharedFoundation::getDemoMode() && GetNumberOfWarnings()) + REPORT(true, Report::RF_print | Report::RF_log | Report::RF_dialog, ("%d warnings logged", GetNumberOfWarnings())); +} + +// ====================================================================== + +SetupSharedFoundation::Data::Data(Defaults defaults) +{ + Zero(*this); + + switch (defaults) + { + case D_console: setupConsoleDefaults(); break; + case D_game: setupGameDefaults(); break; + case D_mfc: setupMfcDefaults(); break; + default: DEBUG_FATAL(true, ("invalid enum value")); + } +} + +// ---------------------------------------------------------------------- + +void SetupSharedFoundation::Data::setupGameDefaults() +{ + createWindow = true; + windowName = NULL; + windowNormalIcon = NULL; + windowSmallIcon = NULL; + hInstance = NULL; + useWindowHandle = false; + processMessagePump = true; + windowHandle = NULL; + clockUsesSleep = false; + clockUsesRecalibrationThread = true; + writeMiniDumps = false; + + commandLine = NULL; + argc = 0; + argv = NULL; + + configFile = NULL; + + productRegistryKey = NULL; + + frameRateLimit = CONST_REAL(0); + + lostFocusCallback = NULL; + + demoMode = false; + verboseWarnings = false; +} + +// ---------------------------------------------------------------------- + +void SetupSharedFoundation::Data::setupConsoleDefaults() +{ + createWindow = false; + windowName = NULL; + windowNormalIcon = NULL; + windowSmallIcon = NULL; + hInstance = NULL; + useWindowHandle = false; + processMessagePump = true; + windowHandle = NULL; + clockUsesSleep = false; + clockUsesRecalibrationThread = false; + writeMiniDumps = false; + + commandLine = NULL; + argc = NULL; + argv = NULL; + + configFile = NULL; + + productRegistryKey = NULL; + + frameRateLimit = CONST_REAL(0); + + lostFocusCallback = NULL; + + demoMode = false; + verboseWarnings = false; +} + +// ---------------------------------------------------------------------- + +void SetupSharedFoundation::Data::setupMfcDefaults() +{ + createWindow = false; + windowName = NULL; + windowNormalIcon = NULL; + windowSmallIcon = NULL; + hInstance = NULL; + useWindowHandle = false; + processMessagePump = true; + windowHandle = NULL; + clockUsesSleep = false; + clockUsesRecalibrationThread = false; + writeMiniDumps = false; + + commandLine = NULL; + argc = 0; + argv = NULL; + + configFile = NULL; + + productRegistryKey = NULL; + + frameRateLimit = CONST_REAL(0); + + demoMode = false; + verboseWarnings = false; +} + +// ====================================================================== diff --git a/engine/shared/library/sharedFoundation/src/win32/SetupSharedFoundation.h b/engine/shared/library/sharedFoundation/src/win32/SetupSharedFoundation.h new file mode 100755 index 00000000..b0675d8f --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/SetupSharedFoundation.h @@ -0,0 +1,99 @@ +// ====================================================================== +// +// SetupSharedFoundation.h +// copyright 1998 Bootprint Entertainment +// copyright 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_SetupSharedFoundation_H +#define INCLUDED_SetupSharedFoundation_H + +// ====================================================================== + +class SetupSharedFoundation +{ +public: + + struct Data + { + typedef void (*LostFocusCallbackFuction)(); + + // window creation stuff + bool createWindow; + const char *windowName; + HICON windowNormalIcon; + HICON windowSmallIcon; + HINSTANCE hInstance; + + // window use stuff + bool useWindowHandle; + bool processMessagePump; + HWND windowHandle; + + bool writeMiniDumps; + + bool clockUsesSleep; + bool clockUsesRecalibrationThread; + + // pointer to command line + const char *commandLine; + int argc; + char **argv; + + // name of the config file to lead + const char *configFile; + + // registry stuff + const char *productRegistryKey; + + real frameRateLimit; + + + bool demoMode; + + bool verboseWarnings; + + LostFocusCallbackFuction lostFocusCallback; + + public: + + enum Defaults + { + D_console, + D_game, + D_mfc + }; + + Data(Defaults defaults); + + private: + + Data(); + + void setupGameDefaults(); + void setupConsoleDefaults(); + void setupMfcDefaults(); + }; + +public: + + typedef void (*MainFunction)(); + +public: + + static void install(const Data &data); + static void remove(void); + + static void callbackWithExceptionHandling(MainFunction mainFunction); + +private: + + SetupSharedFoundation(); + SetupSharedFoundation(const SetupSharedFoundation &); + SetupSharedFoundation &operator =(const SetupSharedFoundation &); +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundation/src/win32/WindowsWrapper.h b/engine/shared/library/sharedFoundation/src/win32/WindowsWrapper.h new file mode 100755 index 00000000..88b64ed5 --- /dev/null +++ b/engine/shared/library/sharedFoundation/src/win32/WindowsWrapper.h @@ -0,0 +1,51 @@ +// ====================================================================== +// +// WindowsWrapper.h +// copyright (c) 1998 Bootprint Entertainment +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_WindowsWrapper_H +#define INCLUDED_WindowsWrapper_H + +// ====================================================================== + +// C4201 nonstandard extension used : nameless struct/union +#pragma warning(disable: 4201) + +// make windows.h more strict in the types of handles +#ifndef STRICT +#define STRICT 1 +#endif + +// trim down the amount of stuff windows.h includes +#define NOGDICAPMASKS +#define NOVIRTUALKEYCODE +#define NOKEYSTATES +#define NORASTEROPS +#define NOATOM +#define NOCOLOR +#define NODRAWTEXT +#define NOMEMMGR +#define NOMETAFILE +#define NOMINMAX +#define NOOPENFILE +#define NOSERVICE +#define NOSOUND +#define NOCOMM +#define NOHELP +#define NOPROFILER +#define NODEFERWINDOWPOS +#define NOMCX +#define WIN32_LEAN_AND_MEAN + +#include +#include + +// reenable warnings disables for windows.h +#pragma warning(default: 4201) + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFoundationTypes/src/win32/FoundationTypesWin32.h b/engine/shared/library/sharedFoundationTypes/src/win32/FoundationTypesWin32.h new file mode 100755 index 00000000..622039d8 --- /dev/null +++ b/engine/shared/library/sharedFoundationTypes/src/win32/FoundationTypesWin32.h @@ -0,0 +1,33 @@ +// PRIVATE. Do not export this header file outside the package. + +// ====================================================================== +// +// FoundationTypesWin32.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_FoundationTypesWin32_H +#define INCLUDED_FoundationTypesWin32_H + +// ====================================================================== +// specify what platform we're running on. + +#define PLATFORM_WIN32 + +// ====================================================================== +// basic types that we assume to be around + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned long uint32; +typedef unsigned __int64 uint64; +typedef signed char int8; +typedef signed short int16; +typedef signed long int32; +typedef signed __int64 int64; +typedef int FILE_HANDLE; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedFractal/src/win32/FirstSharedFractal.cpp b/engine/shared/library/sharedFractal/src/win32/FirstSharedFractal.cpp new file mode 100755 index 00000000..20d5ff2f --- /dev/null +++ b/engine/shared/library/sharedFractal/src/win32/FirstSharedFractal.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstFractal.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedFractal/FirstSharedFractal.h" diff --git a/engine/shared/library/sharedGame/src/win32/FirstSharedGame.cpp b/engine/shared/library/sharedGame/src/win32/FirstSharedGame.cpp new file mode 100755 index 00000000..b95c88bf --- /dev/null +++ b/engine/shared/library/sharedGame/src/win32/FirstSharedGame.cpp @@ -0,0 +1,9 @@ +// ====================================================================== +// +// FirstSharedGame.cpp +// Copyright 2002-2003 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "sharedGame/FirstSharedGame.h" diff --git a/engine/shared/library/sharedImage/src/win32/FirstSharedImage.cpp b/engine/shared/library/sharedImage/src/win32/FirstSharedImage.cpp new file mode 100755 index 00000000..c57c713f --- /dev/null +++ b/engine/shared/library/sharedImage/src/win32/FirstSharedImage.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstImage.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedImage/FirstSharedImage.h" diff --git a/engine/shared/library/sharedIoWin/src/win32/FirstSharedIoWin.cpp b/engine/shared/library/sharedIoWin/src/win32/FirstSharedIoWin.cpp new file mode 100755 index 00000000..52f7b83b --- /dev/null +++ b/engine/shared/library/sharedIoWin/src/win32/FirstSharedIoWin.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstIoWin.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedIoWin/FirstSharedIoWin.h" diff --git a/engine/shared/library/sharedLog/src/win32/StderrLogger.cpp b/engine/shared/library/sharedLog/src/win32/StderrLogger.cpp new file mode 100755 index 00000000..c7efe43d --- /dev/null +++ b/engine/shared/library/sharedLog/src/win32/StderrLogger.cpp @@ -0,0 +1,35 @@ +// ====================================================================== +// +// StderrLogger.cpp +// +// Copyright 2003 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedLog/FirstSharedLog.h" +#include "sharedLog/StderrLogger.h" + +// ====================================================================== + +// Unimplemented for win32 + +// ====================================================================== + +void StderrLogger::install() +{ +} + +// ---------------------------------------------------------------------- + +void StderrLogger::remove() +{ +} + +// ---------------------------------------------------------------------- + +void StderrLogger::update() +{ +} + +// ====================================================================== + diff --git a/engine/shared/library/sharedMath/src/win32/FirstSharedMath.cpp b/engine/shared/library/sharedMath/src/win32/FirstSharedMath.cpp new file mode 100755 index 00000000..5f04bd2a --- /dev/null +++ b/engine/shared/library/sharedMath/src/win32/FirstSharedMath.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstMath.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedMath/FirstSharedMath.h" diff --git a/engine/shared/library/sharedMath/src/win32/SseMath.cpp b/engine/shared/library/sharedMath/src/win32/SseMath.cpp new file mode 100755 index 00000000..11624aab --- /dev/null +++ b/engine/shared/library/sharedMath/src/win32/SseMath.cpp @@ -0,0 +1,430 @@ +// ====================================================================== +// +// SseMath.cpp +// Copyright 2002 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "sharedMath/FirstSharedMath.h" +#include "sharedMath/SseMath.h" + +#include "sharedMath/Transform.h" +#include "sharedMath/Vector.h" + +// ====================================================================== + +#define SSE_ALIGN __declspec(align(16)) +#define SSE_VARIABLE_COUNT 5 + +// ====================================================================== + +namespace +{ + SSE_ALIGN float sseVariable[SSE_VARIABLE_COUNT][4]; +} + +// ====================================================================== +/** + * Retrieve whether the hardware can do SSE math. + * + * @return true if SSE math processing is available; false otherwise. + */ + +bool SseMath::canDoSseMath() +{ +#if 0 + return false; +#else + //-- First check the CPUID instruction. If it raises an exception, + // the CPUID instruction doesn't exist and SSE math support is not available. + bool cpuHasSse = false; + bool cpuHasSaveRestore = false; + + uint32 featureBits; + +#if 0 + bool osSupportsSaveRestore = false; + bool osSimdExceptionSupport = false; + bool x87EmulationDisabled = false; + + uint32 controlRegister4; + uint32 controlRegister0; +#endif + + try + { + __asm { + //-- Get features bits. + mov eax, 1 + cpuid + + mov featureBits, edx + +#if 0 + //-- Get control registers. + mov ecx, CR4 + mov controlRegister4, ecx + + mov ecx, CR0 + mov controlRegister0, ecx +#endif + } + + cpuHasSse = ((featureBits & 0x02000000) != 0); //lint !e530 // featureBits not initialized - yes it is, in the asm + cpuHasSaveRestore = ((featureBits & 0x01000000) != 0); + +#if 0 + osSupportsSaveRestore = ((controlRegister4 & 0x00000200) != 0); + osSimdExceptionSupport = ((controlRegister4 & 0x00000400) != 0); + x87EmulationDisabled = ((controlRegister0 & 0x00000004) == 0); +#endif + } + catch (...) + { //lint !e1775 // catch block does not catch any declared exceptions + } + +#if 1 + return cpuHasSse && cpuHasSaveRestore; +#else + return cpuHasSse && cpuHasSaveRestore && osSupportsSaveRestore && osSimdExceptionSupport && x87EmulationDisabled; +#endif +#endif +} + +// ---------------------------------------------------------------------- + +Vector SseMath::rotateTranslateScale_l2p(const Transform &transform, const Vector &vector, float scale) +{ + // NOTE: technically, my xmm register data contents comments are listing items in reverse order from how INTEL docs list them, left most val is really least significant value. + + __asm { + //-- Keep track of ebx. Client is crashing if I trash this. + push ebx + + //-- Load up matrix. + mov ebx, transform + + movaps xmm0, [ebx + 0] // xmm0 = a1 a2 a3 a4 + movaps xmm1, [ebx + 16] // xmm1 = b1 b2 b3 b4 + movaps xmm2, [ebx + 32] // xmm2 = c1 c2 c3 c4 + } + + //-- Prepare source vector. + sseVariable[0][0] = vector.x; + sseVariable[0][1] = vector.y; + sseVariable[0][2] = vector.z; + sseVariable[0][3] = 1.0f; + + __asm { + //-- Load up the source vector. + mov ebx, offset sseVariable + + movaps xmm3, [ebx] // xmm3 = sx sy sz 1 + + //-- Copy source to workspaces. + movaps xmm4, xmm3 // xmm4 = sx sy sz 1 + movaps xmm5, xmm3 // xmm5 = sx sy sz 1 + } + + //-- Prepare the scale vector. + __asm { + movss xmm6, scale // xmm6 = scale ? ? ? + shufps xmm6, xmm6, 0x00 // xmm6 = scale scale + movlhps xmm6, xmm6 // xmm6 = scale scale scale scale + + //-- Do the transform multiplies. + mulps xmm3, xmm0 // xmm3 = a1*sx a2*sy a3*sz a4 + mulps xmm4, xmm1 // xmm4 = b1*sx b2*sy b3*sz b4 + mulps xmm5, xmm2 // xmm5 = c1*sx c2*sy c3*sz c4 + + //-- Do the scale multiplies. + mulps xmm3, xmm6 // xmm3 = a1*sx*scale a2*sy*scale a3*sz*scale a4*scale + mulps xmm4, xmm6 // xmm4 = b1*sx*scale b2*sy*scale b3*sz*scale b4*scale + mulps xmm5, xmm6 // xmm5 = c1*sx*scale c2*sy*scale c3*sz*scale c4*scale + + //-- Save out data. + movaps [ebx + 32], xmm3 + movaps [ebx + 48], xmm4 + movaps [ebx + 64], xmm5 + + //-- Restore EBX + pop ebx + } + + // @todo consider twizzling/detwizzling to be able to perform add in sse. + return Vector( + sseVariable[2][0] + sseVariable[2][1] + sseVariable[2][2] + sseVariable[2][3], + sseVariable[3][0] + sseVariable[3][1] + sseVariable[3][2] + sseVariable[3][3], + sseVariable[4][0] + sseVariable[4][1] + sseVariable[4][2] + sseVariable[4][3]); +} //lint !e715 // scale/transform not referenced - it's in the asm + +// ---------------------------------------------------------------------- + +Vector SseMath::rotateScale_l2p(const Transform &transform, const Vector &vector, float scale) +{ +#if 0 + // @todo do the real thing. + return transform.rotate_l2p(vector) * scale; +#else + + // NOTE: technically, my xmm register data contents comments are listing items in reverse order from how INTEL docs list them, left most val is really least significant value. + + __asm { + //-- Keep track of ebx. Client is crashing if I trash this. + push ebx + + //-- Load up matrix. + mov ebx, transform + + movaps xmm0, [ebx + 0] // xmm0 = a1 a2 a3 a4 + movaps xmm1, [ebx + 16] // xmm1 = b1 b2 b3 b4 + movaps xmm2, [ebx + 32] // xmm2 = c1 c2 c3 c4 + } + + //-- Prepare source vector. + sseVariable[0][0] = vector.x; + sseVariable[0][1] = vector.y; + sseVariable[0][2] = vector.z; + sseVariable[0][3] = 0.0f; + + __asm { + //-- Load up the source vector. + mov ebx, offset sseVariable + + movaps xmm3, [ebx] // xmm3 = sx sy sz 1 + + //-- Copy source to workspaces. + movaps xmm4, xmm3 // xmm4 = sx sy sz 1 + movaps xmm5, xmm3 // xmm5 = sx sy sz 1 + } + + //-- Prepare the scale vector. + __asm { + movss xmm6, scale // xmm6 = scale ? ? ? + shufps xmm6, xmm6, 0x00 // xmm6 = scale scale + movlhps xmm6, xmm6 // xmm6 = scale scale scale scale + + //-- Do the transform multiplies. + mulps xmm3, xmm0 // xmm3 = a1*sx a2*sy a3*sz 0 + mulps xmm4, xmm1 // xmm4 = b1*sx b2*sy b3*sz 0 + mulps xmm5, xmm2 // xmm5 = c1*sx c2*sy c3*sz 0 + + //-- Do the scale multiplies. + mulps xmm3, xmm6 // xmm3 = a1*sx*scale a2*sy*scale a3*sz*scale 0 + mulps xmm4, xmm6 // xmm4 = b1*sx*scale b2*sy*scale b3*sz*scale 0 + mulps xmm5, xmm6 // xmm5 = c1*sx*scale c2*sy*scale c3*sz*scale 0 + + //-- Save out data. + movaps [ebx + 32], xmm3 + movaps [ebx + 48], xmm4 + movaps [ebx + 64], xmm5 + + //-- Restore EBX + pop ebx + } + + // @todo consider twizzling/detwizzling to be able to perform add in sse. + return Vector( + sseVariable[2][0] + sseVariable[2][1] + sseVariable[2][2], + sseVariable[3][0] + sseVariable[3][1] + sseVariable[3][2], + sseVariable[4][0] + sseVariable[4][1] + sseVariable[4][2]); + +#endif +} //lint !e715 // scale/transform not referenced - it's in the asm + +// ---------------------------------------------------------------------- + +void SseMath::skinPositionNormal_l2p(const Transform &transform, const Vector &sourcePosition, const Vector &sourceNormal, float scale, Vector &destPosition, Vector &destNormal) +{ + // NOTE: technically, my xmm register data contents comments are listing items in reverse order from how INTEL docs list them, left most val is really least significant value. + + __asm { + //-- Keep track of ebx. Client is crashing if I trash this. + push ebx + + //-- Load up matrix. + mov ebx, transform + + movaps xmm0, [ebx + 0] // xmm0 = a1 a2 a3 a4 + movaps xmm1, [ebx + 16] // xmm1 = b1 b2 b3 b4 + movaps xmm2, [ebx + 32] // xmm2 = c1 c2 c3 c4 + } + + //-- Prepare source position. + sseVariable[0][0] = sourcePosition.x; + sseVariable[0][1] = sourcePosition.y; + sseVariable[0][2] = sourcePosition.z; + sseVariable[0][3] = 1.0f; + + __asm { + //-- Load up the source vector. + mov ebx, offset sseVariable + + movaps xmm3, [ebx] // xmm3 = sx sy sz 1 + + //-- Copy source to workspaces. + movaps xmm4, xmm3 // xmm4 = sx sy sz 1 + movaps xmm5, xmm3 // xmm5 = sx sy sz 1 + + //-- Prepare the scale vector. + movss xmm6, scale // xmm6 = scale ? ? ? + shufps xmm6, xmm6, 0x00 // xmm6 = scale scale + movlhps xmm6, xmm6 // xmm6 = scale scale scale scale + + //-- Do the transform multiplies. + mulps xmm3, xmm0 // xmm3 = a1*sx a2*sy a3*sz a4 + mulps xmm4, xmm1 // xmm4 = b1*sx b2*sy b3*sz b4 + mulps xmm5, xmm2 // xmm5 = c1*sx c2*sy c3*sz c4 + + //-- Do the scale multiplies. + mulps xmm3, xmm6 // xmm3 = a1*sx*scale a2*sy*scale a3*sz*scale a4*scale + mulps xmm4, xmm6 // xmm4 = b1*sx*scale b2*sy*scale b3*sz*scale b4*scale + mulps xmm5, xmm6 // xmm5 = c1*sx*scale c2*sy*scale c3*sz*scale c4*scale + + //-- Save out data. + movaps [ebx + 32], xmm3 + movaps [ebx + 48], xmm4 + movaps [ebx + 64], xmm5 + } + + destPosition.x = sseVariable[2][0] + sseVariable[2][1] + sseVariable[2][2] + sseVariable[2][3]; + destPosition.y = sseVariable[3][0] + sseVariable[3][1] + sseVariable[3][2] + sseVariable[3][3]; + destPosition.z = sseVariable[4][0] + sseVariable[4][1] + sseVariable[4][2] + sseVariable[4][3]; + + //-- Prepare source normal. + sseVariable[0][0] = sourceNormal.x; + sseVariable[0][1] = sourceNormal.y; + sseVariable[0][2] = sourceNormal.z; + sseVariable[0][3] = 1.0f; + + __asm { + //-- Load up the source vector. + movaps xmm3, [ebx] // xmm3 = sx sy sz 1 + + //-- Copy source to workspaces. + movaps xmm4, xmm3 // xmm4 = sx sy sz 1 + movaps xmm5, xmm3 // xmm5 = sx sy sz 1 + + //-- Do the transform multiplies. + mulps xmm3, xmm0 // xmm3 = a1*sx a2*sy a3*sz a4 + mulps xmm4, xmm1 // xmm4 = b1*sx b2*sy b3*sz b4 + mulps xmm5, xmm2 // xmm5 = c1*sx c2*sy c3*sz c4 + + //-- Do the scale multiplies. + mulps xmm3, xmm6 // xmm3 = a1*sx*scale a2*sy*scale a3*sz*scale a4*scale + mulps xmm4, xmm6 // xmm4 = b1*sx*scale b2*sy*scale b3*sz*scale b4*scale + mulps xmm5, xmm6 // xmm5 = c1*sx*scale c2*sy*scale c3*sz*scale c4*scale + + //-- Save out data. + movaps [ebx + 32], xmm3 + movaps [ebx + 48], xmm4 + movaps [ebx + 64], xmm5 + + //-- Restore EBX + pop ebx + } + + destNormal.x = sseVariable[2][0] + sseVariable[2][1] + sseVariable[2][2]; + destNormal.y = sseVariable[3][0] + sseVariable[3][1] + sseVariable[3][2]; + destNormal.z = sseVariable[4][0] + sseVariable[4][1] + sseVariable[4][2]; +} //lint !e715 // scale/transform not referenced - it's in the asm + +// ---------------------------------------------------------------------- + +void SseMath::skinPositionNormalAdd_l2p(const Transform &transform, const Vector &sourcePosition, const Vector &sourceNormal, float scale, Vector &destPosition, Vector &destNormal) +{ + // NOTE: technically, my xmm register data contents comments are listing items in reverse order from how INTEL docs list them, left most val is really least significant value. + + __asm { + //-- Keep track of ebx. Client is crashing if I trash this. + push ebx + + //-- Load up matrix. + mov ebx, transform + + movaps xmm0, [ebx + 0] // xmm0 = a1 a2 a3 a4 + movaps xmm1, [ebx + 16] // xmm1 = b1 b2 b3 b4 + movaps xmm2, [ebx + 32] // xmm2 = c1 c2 c3 c4 + } + + //-- Prepare source position. + sseVariable[0][0] = sourcePosition.x; + sseVariable[0][1] = sourcePosition.y; + sseVariable[0][2] = sourcePosition.z; + sseVariable[0][3] = 1.0f; + + __asm { + //-- Load up the source vector. + mov ebx, offset sseVariable + + movaps xmm3, [ebx] // xmm3 = sx sy sz 1 + + //-- Copy source to workspaces. + movaps xmm4, xmm3 // xmm4 = sx sy sz 1 + movaps xmm5, xmm3 // xmm5 = sx sy sz 1 + + //-- Prepare the scale vector. + movss xmm6, scale // xmm6 = scale ? ? ? + shufps xmm6, xmm6, 0x00 // xmm6 = scale scale + movlhps xmm6, xmm6 // xmm6 = scale scale scale scale + + //-- Do the transform multiplies. + mulps xmm3, xmm0 // xmm3 = a1*sx a2*sy a3*sz a4 + mulps xmm4, xmm1 // xmm4 = b1*sx b2*sy b3*sz b4 + mulps xmm5, xmm2 // xmm5 = c1*sx c2*sy c3*sz c4 + + //-- Do the scale multiplies. + mulps xmm3, xmm6 // xmm3 = a1*sx*scale a2*sy*scale a3*sz*scale a4*scale + mulps xmm4, xmm6 // xmm4 = b1*sx*scale b2*sy*scale b3*sz*scale b4*scale + mulps xmm5, xmm6 // xmm5 = c1*sx*scale c2*sy*scale c3*sz*scale c4*scale + + //-- Save out data. + movaps [ebx + 32], xmm3 + movaps [ebx + 48], xmm4 + movaps [ebx + 64], xmm5 + } + + destPosition.x += sseVariable[2][0] + sseVariable[2][1] + sseVariable[2][2] + sseVariable[2][3]; + destPosition.y += sseVariable[3][0] + sseVariable[3][1] + sseVariable[3][2] + sseVariable[3][3]; + destPosition.z += sseVariable[4][0] + sseVariable[4][1] + sseVariable[4][2] + sseVariable[4][3]; + + //-- Prepare source normal. + sseVariable[0][0] = sourceNormal.x; + sseVariable[0][1] = sourceNormal.y; + sseVariable[0][2] = sourceNormal.z; + sseVariable[0][3] = 1.0f; + + __asm { + //-- Load up the source vector. + movaps xmm3, [ebx] // xmm3 = sx sy sz 1 + + //-- Copy source to workspaces. + movaps xmm4, xmm3 // xmm4 = sx sy sz 1 + movaps xmm5, xmm3 // xmm5 = sx sy sz 1 + + //-- Do the transform multiplies. + mulps xmm3, xmm0 // xmm3 = a1*sx a2*sy a3*sz a4 + mulps xmm4, xmm1 // xmm4 = b1*sx b2*sy b3*sz b4 + mulps xmm5, xmm2 // xmm5 = c1*sx c2*sy c3*sz c4 + + //-- Do the scale multiplies. + mulps xmm3, xmm6 // xmm3 = a1*sx*scale a2*sy*scale a3*sz*scale a4*scale + mulps xmm4, xmm6 // xmm4 = b1*sx*scale b2*sy*scale b3*sz*scale b4*scale + mulps xmm5, xmm6 // xmm5 = c1*sx*scale c2*sy*scale c3*sz*scale c4*scale + + //-- Save out data. + movaps [ebx + 32], xmm3 + movaps [ebx + 48], xmm4 + movaps [ebx + 64], xmm5 + + //-- Restore EBX + pop ebx + } + + destNormal.x += sseVariable[2][0] + sseVariable[2][1] + sseVariable[2][2]; + destNormal.y += sseVariable[3][0] + sseVariable[3][1] + sseVariable[3][2]; + destNormal.z += sseVariable[4][0] + sseVariable[4][1] + sseVariable[4][2]; +} //lint !e715 // scale/transform not referenced - it's in the asm + +// ====================================================================== diff --git a/engine/shared/library/sharedMath/src/win32/SseMath.h b/engine/shared/library/sharedMath/src/win32/SseMath.h new file mode 100755 index 00000000..fcbeaef2 --- /dev/null +++ b/engine/shared/library/sharedMath/src/win32/SseMath.h @@ -0,0 +1,58 @@ +// ====================================================================== +// +// SseMath.h +// Copyright 2002 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#ifndef INCLUDED_SseMath_H +#define INCLUDED_SseMath_H + +// ====================================================================== + +class Transform; +class Vector; + +// ====================================================================== +#define MXCSR_FLUSH_TO_ZERO (1<<15) +#define MXCSR_PRECISION_MASK (1<<12) +#define MXCSR_UNDERFLOW_MASK (1<<11) +#define MXCSR_OVERFLOW_MASK (1<<10) +#define MXCSR_DIVIDE_BY_ZERO_MASK (1<< 9) +#define MXCSR_DENORMAL_MASK (1<< 8) + +class SseMath +{ +public: + + static bool canDoSseMath(); + + static Vector rotateTranslateScale_l2p(const Transform &transform, const Vector &vector, float scale); + static Vector rotateScale_l2p(const Transform &transform, const Vector &vector, float scale); + + static void skinPositionNormal_l2p(const Transform &transform, const Vector &position, const Vector &normal, float scale, Vector &destPosition, Vector &destNormal); + static void skinPositionNormalAdd_l2p(const Transform &transform, const Vector &position, const Vector &normal, float scale, Vector &destPosition, Vector &destNormal); + static void prefetch(void const * const sourceData, size_t const objectSize); +}; + +// ---------------------------------------------------------------------- + +inline void SseMath::prefetch(void const * const sourceData, size_t const objectSize) +{ +#if defined(_MSC_VER) + _asm + { + mov esi, sourceData + prefetchnta objectSize[esi] + } +#else + // rls - add linux version here. + UNREF(sourceData); + UNREF(objectSize); +#endif +} + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedMemoryManager/src/win32/OsMemory.cpp b/engine/shared/library/sharedMemoryManager/src/win32/OsMemory.cpp new file mode 100755 index 00000000..a6ad6331 --- /dev/null +++ b/engine/shared/library/sharedMemoryManager/src/win32/OsMemory.cpp @@ -0,0 +1,56 @@ +// ====================================================================== +// +// OsMemory.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedMemoryManager/FirstSharedMemoryManager.h" +#include "sharedMemoryManager/OsMemory.h" + +// ====================================================================== + +void OsMemory::install() +{ +} + +// ---------------------------------------------------------------------- + +void OsMemory::remove() +{ +} + +// ---------------------------------------------------------------------- + +void *OsMemory::reserve(size_t bytes) +{ + return VirtualAlloc(0, bytes, MEM_RESERVE, PAGE_READWRITE); +} + +// ---------------------------------------------------------------------- + +void *OsMemory::commit(void *addr, size_t bytes) +{ + return VirtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE); +} + +// ---------------------------------------------------------------------- + +bool OsMemory::free(void *addr, size_t bytes) +{ + UNREF(bytes); + return VirtualFree(addr, 0, MEM_RELEASE) ? true : false; +} + +// ---------------------------------------------------------------------- + +bool OsMemory::protect(void *addr, size_t bytes, bool allowAccess) +{ + DWORD old; + BOOL result = VirtualProtect(addr, bytes, allowAccess ? PAGE_READWRITE : PAGE_NOACCESS, &old); + return result ? true : false; +} + +// ====================================================================== + diff --git a/engine/shared/library/sharedMemoryManager/src/win32/OsMemory.h b/engine/shared/library/sharedMemoryManager/src/win32/OsMemory.h new file mode 100755 index 00000000..07ff6918 --- /dev/null +++ b/engine/shared/library/sharedMemoryManager/src/win32/OsMemory.h @@ -0,0 +1,29 @@ +// ====================================================================== +// +// OsMemory.h +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_OsMemory_H +#define INCLUDED_OsMemory_H + +// ====================================================================== + +class OsMemory +{ +public: + static void install(); + static void remove(); + + static void * reserve(size_t bytes); + static void * commit(void *addr, size_t bytes); + static bool free(void *addr, size_t bytes); + static bool protect(void *addr, size_t bytes, bool allowAccess); +}; + +// ====================================================================== + +#endif INCLUDED_OsMemory_H + diff --git a/engine/shared/library/sharedMemoryManager/src/win32/OsNewDel.cpp b/engine/shared/library/sharedMemoryManager/src/win32/OsNewDel.cpp new file mode 100755 index 00000000..c6569707 --- /dev/null +++ b/engine/shared/library/sharedMemoryManager/src/win32/OsNewDel.cpp @@ -0,0 +1,211 @@ +// ====================================================================== +// +// OsNewDel.cpp +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedMemoryManager/FirstSharedMemoryManager.h" +#include "sharedMemoryManager/OsNewDel.h" + +// ====================================================================== + +// this is here because MSVC won't call MemoryManager::allocate() from asm directly +static void * __cdecl localAllocate(size_t size, uint32 owner, bool array, bool leakTest) +{ + return MemoryManager::allocate(size, owner, array, leakTest); +} + +// ---------------------------------------------------------------------- + +// We are using the arguments (except for file and line), but MSVC can't tell that. +#pragma warning(disable: 4100) + +// ---------------------------------------------------------------------- + +__declspec(naked) void *operator new(size_t size, MemoryManagerNotALeak) +{ + _asm + { + // setup local call stack + push ebp + mov ebp, esp + + // MemoryManager::alloc(size, [return address], false, false) + push 0 + push 0 + mov eax, dword ptr [ebp+4] + push eax + mov eax, dword ptr [ebp+8] + push eax + call localAllocate + add esp, 12 + + mov esp, ebp + pop ebp + ret + } +} + +// ---------------------------------------------------------------------- + +__declspec(naked) void *operator new(size_t size) +{ + _asm + { + // setup local call stack + push ebp + mov ebp, esp + + // MemoryManager::alloc(size, [return address], false, true) + push 1 + push 0 + mov eax, dword ptr [ebp+4] + push eax + mov eax, dword ptr [ebp+8] + push eax + call localAllocate + add esp, 12 + + mov esp, ebp + pop ebp + ret + } +} + +// ---------------------------------------------------------------------- + +__declspec(naked) void *operator new[](size_t size) +{ + _asm + { + // setup local call stack + push ebp + mov ebp, esp + + // MemoryManager::alloc(size, [return address], true, true) + push 1 + push 1 + mov eax, dword ptr [ebp+4] + push eax + mov eax, dword ptr [ebp+8] + push eax + call localAllocate + add esp, 12 + + mov esp, ebp + pop ebp + ret + } +} + +// ---------------------------------------------------------------------- + +__declspec(naked) void *operator new(size_t size, const char *file, int line) +{ + _asm + { + // setup local call stack + push ebp + mov ebp, esp + + // MemoryManager::alloc(size, [return address], false, true) + push 1 + push 0 + mov eax, dword ptr [ebp+4] + push eax + mov eax, dword ptr [ebp+8] + push eax + call localAllocate + add esp, 12 + + mov esp, ebp + pop ebp + ret + } +} + +// ---------------------------------------------------------------------- + +__declspec(naked) void *operator new[](size_t size, const char *file, int line) +{ + _asm + { + // setup local call stack + push ebp + mov ebp, esp + + // MemoryManager::alloc(size, [return address], true, true) + push 1 + push 1 + mov eax, dword ptr [ebp+4] + push eax + mov eax, dword ptr [ebp+8] + push eax + call localAllocate + add esp, 12 + + mov esp, ebp + pop ebp + ret + } +} + +// ---------------------------------------------------------------------- + +#pragma warning(default: 4100) + +// ---------------------------------------------------------------------- + +void operator delete(void *pointer) +{ + if (pointer) + MemoryManager::free(pointer, false); +} + +// ---------------------------------------------------------------------- + +void operator delete[](void *pointer) +{ + if (pointer) + MemoryManager::free(pointer, true); +} + +// ---------------------------------------------------------------------- + +void operator delete(void *pointer, const char *file, int line) +{ + UNREF(file); + UNREF(line); + + if (pointer) + MemoryManager::free(pointer, false); +} + +// ---------------------------------------------------------------------- + +void operator delete[](void *pointer, const char *file, int line) +{ + UNREF(file); + UNREF(line); + + if (pointer) + MemoryManager::free(pointer, true); +} + +// ====================================================================== +// WARNING!!!!!!! +// +// The init_seg pragma command is used to create certain static objects first, before other static objects are created. +// However, multiple static variables that use the same init_seg category(i.e. compiler) are not guaranteed to destroy in any +// particular order. It is completely random based on how all the linking of static objects occurs. Since this command is being +// used on our memory manager(to overwrite new/delete) - NO OTHER STATIC SHOULD EVER USE INIT_SEG(COMPILER)!!!! This static object +// *MUST* be the final static object that is destroyed. +// +#pragma warning(disable: 4074) +#pragma init_seg(compiler) // ^-Read warning above.-^ +static MemoryManager memoryManager; + +// ====================================================================== + diff --git a/engine/shared/library/sharedMemoryManager/src/win32/OsNewDel.h b/engine/shared/library/sharedMemoryManager/src/win32/OsNewDel.h new file mode 100755 index 00000000..477a6674 --- /dev/null +++ b/engine/shared/library/sharedMemoryManager/src/win32/OsNewDel.h @@ -0,0 +1,52 @@ +// ====================================================================== +// +// OsNewDel.h +// +// Copyright 2002 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_OsNewDel_H +#define INCLUDED_OsNewDel_H + +// ====================================================================== + +enum MemoryManagerNotALeak +{ + MM_notALeak +}; + +void * __cdecl operator new(size_t size, MemoryManagerNotALeak); +void * __cdecl operator new(size_t size); +void * __cdecl operator new[](size_t size); +void * __cdecl operator new(size_t size, char const *file, int line); +void * __cdecl operator new[](size_t size, char const *file, int line); +void * __cdecl operator new(size_t size, void *placement); + +void operator delete(void *pointer); +void operator delete[](void *pointer); +void operator delete(void *pointer, char const *file, int line); +void operator delete[](void *pointer, char const *file, int line); +void operator delete(void *pointer, void *placement); + +#ifndef __PLACEMENT_NEW_INLINE +#define __PLACEMENT_NEW_INLINE + +inline void *operator new(size_t size, void *placement) +{ + static_cast(size); + return placement; +} + +inline void operator delete(void *pointer, void *placement) +{ + static_cast(pointer); + static_cast(placement); +} + +#endif // __PLACEMENT_NEW_INLINE + +// ====================================================================== + +#endif INCLUDED_OsNewDel_H + diff --git a/engine/shared/library/sharedMessageDispatch/src/win32/FirstSharedMessageDispatch.cpp b/engine/shared/library/sharedMessageDispatch/src/win32/FirstSharedMessageDispatch.cpp new file mode 100755 index 00000000..c2403b0f --- /dev/null +++ b/engine/shared/library/sharedMessageDispatch/src/win32/FirstSharedMessageDispatch.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstMessageDispatch.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedMessageDispatch/FirstSharedMessageDispatch.h" diff --git a/engine/shared/library/sharedNetwork/src/win32/Address.cpp b/engine/shared/library/sharedNetwork/src/win32/Address.cpp new file mode 100755 index 00000000..0d4b0b2a --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/Address.cpp @@ -0,0 +1,410 @@ +// Address.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. + +//--------------------------------------------------------------------- + +#include "sharedNetwork/FirstSharedNetwork.h" +#include "sharedNetwork/Address.h" + +#include +#include + +//--------------------------------------------------------------------- +/** + @brief Construct an empty address (INADDR_ANY) + + @author Justin Randall +*/ +Address::Address() : +addr4(new struct sockaddr_in), +hostAddress("0.0.0.0") +{ + memset(addr4, 0, sizeof(struct sockaddr_in)); + addr4->sin_family = AF_INET; +} + +//--------------------------------------------------------------------- +/** + @brief construct an address from a human readable dotted-decimal + host address and port + + Care should be taken when using this constructor. It could potentially + invoke gethostbyname() and block while the resolver returns a + valid ip address. + + @author Justin Randall + + @todo Add a static resolver cache to Address to reduce potential + calls to gethostbyname() +*/ +Address::Address(const std::string & newHostAddress, const unsigned short newHostPort) : +addr4(new struct sockaddr_in), +hostAddress(newHostAddress) +{ + HOSTENT * h; + unsigned long u; + + memset(addr4, 0, sizeof(struct sockaddr_in)); + addr4->sin_port = htons(newHostPort); + addr4->sin_family = AF_INET; + // was an address supplied? + if(hostAddress.size() > 0) + { + // Is the first byte a number? (IP names begin with an alpha) + if(!isdigit(hostAddress[0])) + { + // The first byte is a letter, resolve it + if( (h = gethostbyname(hostAddress.c_str())) != 0) + { + int i = 0; + while (h->h_addr_list[i] != 0) { + memcpy(&addr4->sin_addr, h->h_addr_list[i++], sizeof(addr4->sin_addr)); + //addr4->sin_addr = *(u_long *) h->h_addr_list[i++]; + //printf("\tIP Address #%d: %s\n", i, inet_ntoa(addr)); + } + //memcpy(&addr4->sin_addr, h->h_addr_list[0], sizeof(addr4->sin_addr)); + } + else + { + // boom! grab the entry from the h_addr member instead! + if( (h = gethostbyname(hostAddress.c_str())) != 0) + { + memcpy(&addr4->sin_addr, h->h_addr, sizeof(addr4->sin_addr)); + } + else + { + // no resolution, INADDR_ANY + // could be that the network needs a kick in the ass + memset(&addr4->sin_addr, 0, sizeof(addr4->sin_addr)); + } + } + + // extract IP bytes from ipv4add4 + const unsigned char * ip; + char name[17] = {"\0"}; + + ip = reinterpret_cast(&addr4->sin_addr); + _snprintf(name, 17, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); //lint !e534 + hostAddress = name; + } + else + { + // A dotted decimal ip number string was supplied. Convert for sin_addr + u = inet_addr(hostAddress.c_str()); + memcpy(&addr4->sin_addr, &u, sizeof(addr4->sin_addr)); + } + } + else + { + // nothing was supplied, assign INADDR_ANY + addr4->sin_addr.s_addr = INADDR_ANY; + } + convertFromSockAddr(*addr4); +} + +//--------------------------------------------------------------------- +/** + @brief Address copy constructor + + @author Justin Randall +*/ +Address::Address(const Address & source) : +addr4(new struct sockaddr_in), +hostAddress(source.hostAddress) +{ + *addr4 = *source.addr4; +} + +//--------------------------------------------------------------------- +/** + @brief Constructs an address from a BSD sockaddr structure + + @author Justin Randall +*/ +Address::Address(const struct sockaddr_in & ipv4addr) : +addr4(new struct sockaddr_in), +hostAddress() +{ + convertFromSockAddr(ipv4addr); +} + +//--------------------------------------------------------------------- +/** + @brief Destroy an address + + @author Justin Randall +*/ +Address::~Address() +{ + delete addr4; +} + +//--------------------------------------------------------------------- +/** + @brief Aassign an address to anothe address +*/ +Address & Address::operator = (const Address & rhs) +{ + if(this != &rhs) + { + hostAddress = rhs.hostAddress; + *addr4 = *rhs.addr4; + } + return *this; +} + +//--------------------------------------------------------------------- +/** + @brief Assign an address to a BSD sockaddr_in structure + + @author Justin Randall +*/ +Address & Address::operator = (const struct sockaddr_in & rhs) +{ + convertFromSockAddr(rhs); + return *this; +} + +//--------------------------------------------------------------------- + +void Address::convertFromSockAddr(const struct sockaddr_in & source) +{ + // extract IP bytes from ipv4add4 + const unsigned char * ip; + char name[17] = {"\0"}; + + ip = reinterpret_cast(&source.sin_addr); + _snprintf(name, 17, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); //lint !e534 + hostAddress = name; + if(addr4 != &source) + *addr4 = source; +} + +//--------------------------------------------------------------------- +/** + @brief get a human readable host address + + Example: + \code + void foo(struct sockaddr_in & a) + { + Address b(a); + printf("address = %%s\\n", b.getHostAddress().c_str()); + } + \endcode + + @return A human readable host address string + + @author Justin Randall +*/ +const std::string & Address::getHostAddress() const +{ + return hostAddress; +} + +//--------------------------------------------------------------------- +/** + @brief get the port associated with this address + + Example: + \code + void foo(struct sockaddr_in & a) + { + Address b(a); + printf("port = %%i\\n", b.getHostPort()); + } + \endcode + + @return A human readable port in host-byte order associated with + this address. + + @author Justin Randall +*/ +const unsigned short Address::getHostPort() const +{ + return ntohs(addr4->sin_port); +} + +//--------------------------------------------------------------------- +/** + @brief get the BSD sockaddr describing this address + + Example: + \code + void foo(SOCKET s, unsigned char * d, int l, const Address & a) + { + int t = sizeof(struct sockaddr_in); + sendto(s, s, l, 0, reinterpret_cast(&(a.getSockAddr4())), t); + } + \endcode + + @return a BSD sockaddr that describes this IPv4 address + + @author Justin Randall +*/ +const struct sockaddr_in & Address::getSockAddr4() const +{ + return *addr4; +} + +//--------------------------------------------------------------------- +/** + @brief equality operator + + The equality operator compares the ip address, ip port, + and address family to establish equality. + + Example: + \code + Address a("127.0.0.1", 55443); + Address b; + + b = a; + \endcode + + @return True of the right hand side is equal to this address + + @author Justin Randall +*/ +const bool Address::operator == (const Address & rhs) const +{ + return (addr4->sin_addr.s_addr == rhs.addr4->sin_addr.s_addr && + addr4->sin_family == rhs.addr4->sin_family && + addr4->sin_port == rhs.addr4->sin_port); +} + +//--------------------------------------------------------------------- +/** + @brief less-than comparison operator + + The < comparison operator compares the IP number and port. If + the IP numbers are identical, but the left hand side port is + less than the right hand side port, the operator will return + true. + + @return true if the left hand side's IP number is less than + the right hand side IP number. If the numbers are equal, it + will return true if the left hand side IP port is less + than the right hand side port. Otherwise it returns false. + + @author Justin Randall +*/ +const bool Address::operator < (const Address & rhs) const +{ + return(addr4->sin_addr.s_addr < rhs.addr4->sin_addr.s_addr || + addr4->sin_addr.s_addr == rhs.addr4->sin_addr.s_addr && + addr4->sin_port < rhs.addr4->sin_port); +} + +//--------------------------------------------------------------------- +/** + @brief inequality operator + + Leverages the equality operator, so whenever == returns true, + this returns false, and visa versa. + + @return true if the right hand side is not equal to the left + hand side. False if they are equal. + + @see Adress::operator== + + @author Justin Randall +*/ +const bool Address::operator != (const Address & rhs) const +{ + return(! (rhs == *this)); +} + +//--------------------------------------------------------------------- +/** + @brief greater-than comparison operator + + The > comparison operator compares the IP number and port. If + the IP numbers are identical, but the right hand side port is + lesser than the left hand side port, the operator will return + true. + + @return true if the left hand side's IP number is greater than + the right hand side IP number. If the numbers are equal, it + will return true if the left hand side IP port is greater + than the right hand side port. Otherwise it returns false. + + @author Justin Randall +*/ +const bool Address::operator > (const Address & rhs) const +{ + return(addr4->sin_addr.s_addr > rhs.addr4->sin_addr.s_addr || + addr4->sin_addr.s_addr == rhs.addr4->sin_addr.s_addr && + addr4->sin_port > rhs.addr4->sin_port); +} + +//--------------------------------------------------------------------- +/** + @brief a hash_map support routine + + The STL hash_map (present in most STL implementations) requires + a size_t return from a hash function to identify which bucket + a particular value should reside in. On 32 bit or better platforms + the sockaddr_in.sin_addr.s_addr member is small enough to + qualify as a hash-result, provides reasonably unique values + and is reproducable given an address input. + + Example: + \code + typedef std::hash_map AddressMap; + \endcode + + @return the ip number member of a sockaddr_in struct + + @author Justin Randall +*/ +size_t Address::hashFunction() const +{ + return addr4->sin_addr.s_addr; +} + +//--------------------------------------------------------------------- +/** + @brief STL map support routine + + STL maps (including hash_maps) require unique keys, and therefore + need to compare a key for equality with an existing target. + + The functor uses Address::operator = for the comparison. + + Example: + \code + typedef std::unordered_map AddressMap; + \endcode + + @return true if the left hand side and right hand side are equal + using Address::operator = + @see Address::operator= + +*/ +bool Address::EqualFunction::operator () (const Address & lhs, const Address & rhs) const +{ + return lhs == rhs; +} + +//--------------------------------------------------------------------- +/** + @brief STL hash_map support routine + + The HashFunction::operator() invokes Address::hashFunction to + determine an appropriate hash for the address. + + Example: + \code + typedef std::hash_map AddressMap; + \endcode + + @see Address::hashFunction + + @author Justin Randall +*/ +size_t Address::HashFunction::operator () (const Address & a) const +{ + return a.hashFunction(); +} +//--------------------------------------------------------------------- diff --git a/engine/shared/library/sharedNetwork/src/win32/FirstSharedNetwork.cpp b/engine/shared/library/sharedNetwork/src/win32/FirstSharedNetwork.cpp new file mode 100755 index 00000000..abf6e1d6 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/FirstSharedNetwork.cpp @@ -0,0 +1,9 @@ +// FirstSharedNetwork.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. + +//----------------------------------------------------------------------- + +#include "sharedNetwork/FirstSharedNetwork.h" + +//----------------------------------------------------------------------- + diff --git a/engine/shared/library/sharedNetwork/src/win32/NetworkGetHostName.cpp b/engine/shared/library/sharedNetwork/src/win32/NetworkGetHostName.cpp new file mode 100755 index 00000000..faebb2b9 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/NetworkGetHostName.cpp @@ -0,0 +1,67 @@ +// NetworkGetHostName.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. + +//----------------------------------------------------------------------- + +#include "sharedNetwork/FirstSharedNetwork.h" + +#include "sharedNetwork/Address.h" +#include "sharedNetwork/NetworkHandler.h" + +#include + +//----------------------------------------------------------------------- + +struct HN +{ + HN(); + std::string hostName; +}; + +//----------------------------------------------------------------------- + +HN::HN() +{ + WSADATA wsaData; + int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + char name[512] = {"\0"}; + if(gethostname(name, sizeof(name)) == 0) + { + Address a(name, 0); + hostName = a.getHostAddress();//name; + } +} + +//----------------------------------------------------------------------- + +const std::string & NetworkHandler::getHostName() +{ + static HN hn; + return hn.hostName; +} + +const std::string & NetworkHandler::getHumanReadableHostName() +{ + char name[512] = {"\0"}; + static std::string nameString; + if(nameString.empty()) + { + if(gethostname(name, sizeof(name)) == 0) + { + name[sizeof(name) - 1] = 0; + //hostName = name; + nameString = name; + } + } + return nameString; +} + +//----------------------------------------------------------------------- + +const std::vector > & NetworkHandler::getInterfaceAddresses() +{ + static std::vector > s; + return s; +} + +//----------------------------------------------------------------------- diff --git a/engine/shared/library/sharedNetwork/src/win32/OverlappedTcp.cpp b/engine/shared/library/sharedNetwork/src/win32/OverlappedTcp.cpp new file mode 100755 index 00000000..c79c5b50 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/OverlappedTcp.cpp @@ -0,0 +1,85 @@ +// OverlappedTcp.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "sharedNetwork/FirstSharedNetwork.h" +#include "OverlappedTcp.h" +#include +#include "TcpClient.h" +#include "TcpServer.h" + +//--------------------------------------------------------------------- + +OverlappedTcp::~OverlappedTcp() +{ + delete[] m_acceptData; + delete[] m_recvBuf.buf; +} + +//--------------------------------------------------------------------- + +struct OverlappedFreeList +{ + ~OverlappedFreeList(); + std::vector allOverlapped; + std::vector freeOverlapped; +}; + +//--------------------------------------------------------------------- + +OverlappedFreeList::~OverlappedFreeList() +{ + std::vector::const_iterator i; + for(i = allOverlapped.begin(); i != allOverlapped.end(); ++i) + { + OverlappedTcp * t = (*i); + delete t; + } +} + +//--------------------------------------------------------------------- + +OverlappedFreeList overlappedFreeList; + +//--------------------------------------------------------------------- + +OverlappedTcp * getFreeOverlapped() +{ + OverlappedTcp * result = NULL; + + if(! overlappedFreeList.freeOverlapped.empty()) + { + result = overlappedFreeList.freeOverlapped.back(); + overlappedFreeList.freeOverlapped.pop_back(); + } + else + { + result = new OverlappedTcp; + result->m_bytes = 0; + memset(&result->m_overlapped, 0, sizeof(OVERLAPPED)); + result->m_recvBuf.buf = new char[1024]; + result->m_recvBuf.len = 1024; + result->m_tcpClient = 0; + result->m_tcpServer = 0; + result->m_acceptData = 0; + overlappedFreeList.allOverlapped.push_back(result); + } + return result; +} + +//--------------------------------------------------------------------- + +void releaseOverlapped(OverlappedTcp * o) +{ + o->m_bytes = 0; + o->m_tcpClient = 0; + o->m_tcpServer = 0; + o->m_acceptData = 0; + memset(&o->m_overlapped, 0, sizeof(OVERLAPPED)); + overlappedFreeList.freeOverlapped.push_back(o); +} + +//----------------------------------------------------------------------- + diff --git a/engine/shared/library/sharedNetwork/src/win32/OverlappedTcp.h b/engine/shared/library/sharedNetwork/src/win32/OverlappedTcp.h new file mode 100755 index 00000000..c852ab60 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/OverlappedTcp.h @@ -0,0 +1,47 @@ +// OverlappedTcp.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_OverlappedTcp_H +#define _INCLUDED_OverlappedTcp_H + +//----------------------------------------------------------------------- + +#include + +//----------------------------------------------------------------------- + +class TcpClient; +class TcpServer; + +//----------------------------------------------------------------------- + +struct OverlappedTcp +{ + ~OverlappedTcp(); + OVERLAPPED m_overlapped; + + enum OPERATIONS + { + INVALID, + ACCEPT, + SEND, + RECV + }; + + unsigned char * m_acceptData; // getting peer name during accept + DWORD m_bytes; + enum OPERATIONS m_operation; + const TcpServer * m_tcpServer; + TcpClient * m_tcpClient; // accepted sock when operation is accept + WSABUF m_recvBuf; +}; + +//--------------------------------------------------------------------- + +OverlappedTcp * getFreeOverlapped(); +void releaseOverlapped(OverlappedTcp *); + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_OverlappedTcp_H diff --git a/engine/shared/library/sharedNetwork/src/win32/Sock.cpp b/engine/shared/library/sharedNetwork/src/win32/Sock.cpp new file mode 100755 index 00000000..663f6af4 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/Sock.cpp @@ -0,0 +1,366 @@ +// Sock.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. + +//--------------------------------------------------------------------- + +#include "sharedNetwork/FirstSharedNetwork.h" +#include "sharedNetwork/Sock.h" + +#include + +struct WinsockStartupObject +{ + WinsockStartupObject(); + ~WinsockStartupObject(); +}; + +WinsockStartupObject::WinsockStartupObject() +{ + WSADATA wsaData; + WORD wVersionRequested; + + wVersionRequested = MAKEWORD(2,0); + int err; + err = WSAStartup(wVersionRequested, &wsaData); +} + +WinsockStartupObject::~WinsockStartupObject() +{ + WSACleanup(); +} + +WinsockStartupObject wso; + +//--------------------------------------------------------------------- +/** + @brief construct a Sock + + This constructor sets handle to INVALID_SOCKET, lastError to + Sock::SOCK_NO_ERROR and the bindAddress to the default Address. + + @see Address + + @author Justin Randall +*/ +Sock::Sock() : +handle(INVALID_SOCKET), +lastError(Sock::SOCK_NO_ERROR), +bindAddress() +{ +} + +//--------------------------------------------------------------------- +/** + @brief destroy the Sock object + + checks for a valid socket close. It is an error to close a socket + that will fail a close operation. + + Also resets handle to INVALID_SOCKET + + @author Justin Randall +*/ +Sock::~Sock() +{ + // ensure we don't block, and that pending + // data is sent with a graceful shutdown + int err; + err = closesocket(handle); + if(err == SOCKET_ERROR) + { + OutputDebugString(getLastError().c_str()); + } + handle = INVALID_SOCKET; +} + +//--------------------------------------------------------------------- +/** + @brief Bind the socket to the specified local address +*/ +bool Sock::bind(const Address & newBindAddress) +{ + bool result = false; + + int enable = 1; + setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&enable), sizeof(enable)); + + bindAddress = newBindAddress; + int namelen = sizeof(struct sockaddr_in); + int err = ::bind(handle, reinterpret_cast(&(bindAddress.getSockAddr4())), namelen); + if(err == 0) + { + result = true; + struct sockaddr_in a; + int r; + r = getsockname(handle, reinterpret_cast(&a), &namelen); + bindAddress = a; + } + else + { + result = false; + OutputDebugString(getLastError().c_str()); + OutputDebugString("\n"); + } + return result; +} + +//--------------------------------------------------------------------- +/** + @brief bind the socket to the first available local address + as provided by the operating system. + + This bind call is useful for client sockets, or server sockets that + can report their new address to a locator service. + + @author Justin Randall +*/ +bool Sock::bind() +{ + bool result = false; + struct sockaddr_in a; + int namelen = sizeof(struct sockaddr_in); + memset(&a, 0, sizeof(struct sockaddr_in)); + a.sin_family = AF_INET; + a.sin_port = 0; + a.sin_addr.s_addr = INADDR_ANY; + int err = ::bind(handle, reinterpret_cast(&a), namelen); + if(err == 0) + { + result = true; + int r; + r = getsockname(handle, reinterpret_cast(&a), &namelen); + bindAddress = a; + } + return result; +} + +//--------------------------------------------------------------------- +/** + @brief determine if a socket is ready to receive + + On Win32, select is invoked. On Linux, the poll() system call is + used to deterine readability of a socket. + + @return true if the socket can read data without blocking. + + @author Justin Randall + + @todo Win32 should be using WSAEventSelect and WSAEnumNetworkEvents + if they outperform select. +*/ +bool Sock::canRecv() const +{ + struct timeval tv; + fd_set r; + + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&r); +#pragma warning (disable : 4127) + FD_SET(handle, &r); //lint !e717 // I have no idea why MS makes this a do { .. } while(0); macro?! Pointless. + return (select(1, &r, 0, 0, &tv) > 0); +} + +//--------------------------------------------------------------------- +/** + @brief determine writeability of the socket + + Win32 systems use select, Linux use poll. + + @return true if the socket can send data without blocking. + @author Justin Randall + + @todo Win32 should be using WSAEventSelect and WSAEnumNetworkEvents + if they outperform select. +*/ +bool Sock::canSend() const +{ + struct timeval tv; + fd_set w; + + tv.tv_sec = 0; + tv.tv_usec = 0; + + FD_ZERO(&w); + FD_SET(handle, &w); //lint !e717 // I have no idea why MS makes this a do { .. } while(0); macro?! Pointless. + + return (select(1, 0, &w, 0, &tv) > 0); +} + +//--------------------------------------------------------------------- +/** + @brief determine the number of bytes pending on the socket + + Uses ioctl (ioctlsocket on win32) to determine the number + of bytes pending. + + @return the number of unread bytes pending on the socket + + @author Justin Randall +*/ +const unsigned int Sock::getInputBytesPending() const +{ + unsigned long int bytes = 0; + int err; + err = ioctlsocket(handle, FIONREAD, &bytes); //lint !e1924 (I don't know WHAT Microsoft is doing here!) + return bytes; +} + +//--------------------------------------------------------------------- +/** + @brief determine the error state of the socket + + This routine also sets the lastError member of the Sock object, which + is used to determine common errors (connection failure, connection + closed, connection reset, etc..) + + @return an STL string that describes the error state of the socket, + + @author Justin Randall +*/ +const std::string Sock::getLastError() const +{ + std::string errString; + int iErr = WSAGetLastError(); + + switch(iErr) + { + case WSAENOPROTOOPT: + errString = "Bad protocol option. An unknown, invalid or unsupported option or level was specified in a getsockopt or setsockopt call."; + break; + case WSAENETDOWN: + errString = "The network subsystem has failed."; + break; + case WSAEFAULT: + errString = "The buf parameter is not completely contained in a valid part of the user address space."; + break; + case WSAENOTCONN: + errString = "The socket is not connected."; + lastError = Sock::CONNECTION_FAILED; + break; + case WSAEINTR: + errString = "The (blocking) call was canceled through WSACancelBlockingCall."; + break; + case WSAEINPROGRESS: + errString = "A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function."; + break; + case WSAENETRESET: + errString = "The connection has been broken due to the keep-alive activity detecting a failure while the operation was in progress."; + break; + case WSAENOTSOCK: + errString = "The descriptor is not a socket."; + break; + case WSAEOPNOTSUPP: + errString = "MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, out-of-band data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations."; + break; + case WSAESHUTDOWN: + errString = "The socket has been shut down; it is not possible to recv on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH."; + break; + case WSAEWOULDBLOCK: + errString = "The socket is marked as nonblocking and the receive operation would block."; + break; + case WSAEMSGSIZE: + errString = "The message was too large to fit into the specified buffer and was truncated."; + break; + case WSAEINVAL: + errString = "The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled or (for byte stream sockets only) len was zero or negative."; + break; + case WSAECONNABORTED: + errString = "The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no longer usable."; + lastError = Sock::CONNECTION_RESET; + break; + case WSAETIMEDOUT: + errString = "The connection has been dropped because of a network failure or because the peer system failed to respond."; + break; + case WSAECONNRESET: + errString = "The virtual circuit was reset by the remote side executing a \"hard\" or \"abortive\" close. The application should close the socket as it is no longer usable. On a UDP datagram socket this error would indicate that a previous send operation resulted in an ICMP \"Port Unreachable\" message."; + lastError = Sock::CONNECTION_RESET; + break; + case WSAECONNREFUSED: + errString = "No connection could be made because the target machine actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host - i.e. one with no server application running. "; + lastError = Sock::CONNECTION_FAILED; + break; + default: + errString = "An unknown socket error has occurred."; + break; + } + + return errString; +} + +//----------------------------------------------------------------------- +/** @brief determine the maximum message size that may be sent on this socket +*/ +const unsigned int Sock::getMaxMessageSendSize() const +{ + /* + int maxMsgSize = 400; + int optlen = sizeof(int); + int result = getsockopt(handle, SOL_SOCKET, SO_MAX_MSG_SIZE, reinterpret_cast(&maxMsgSize), &optlen); + if(result != 0) + { + int errCode = WSAGetLastError(); + switch(errCode) + { + case WSANOTINITIALISED: + OutputDebugString("A successful WSAStartup call must occur before using this function. "); + break; + case WSAENETDOWN: + OutputDebugString("The network subsystem has failed. "); + break; + case WSAEFAULT: + OutputDebugString("One of the optval or the optlen parameters is not a valid part of the user address space, or the optlen parameter is too small. "); + case WSAEINPROGRESS: + OutputDebugString("A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. "); + break; + case WSAEINVAL: + OutputDebugString("The level parameter is unknown or invalid. "); + break; + case WSAENOPROTOOPT: + OutputDebugString("The option is unknown or unsupported by the indicated protocol family. "); + break; + case WSAENOTSOCK: + OutputDebugString("The descriptor is not a socket. "); + break; + default: + OutputDebugString("An unknown error occurred while processing getsockopt"); + break; + } + } + */ + return 400; +} + +//--------------------------------------------------------------------- +/** + @brief get a BSD sockaddr struct describing the remote address + of a socket + + @param target a BSD sockaddr struct that will receive the peer + address + @param s the socket to query for the peername + + @author Justin Randall +*/ +void Sock::getPeerName(struct sockaddr_in & target, SOCKET s) +{ + int namelen = sizeof(struct sockaddr_in); + int err; + err = getpeername(s, reinterpret_cast(&(target)), &namelen); +} + +//--------------------------------------------------------------------- +/** @brief a support routine to place the socket in non-blocking mode + + @author Justin Randall +*/ +void Sock::setNonBlocking() const +{ + unsigned long int nb = 1; + int err; + err = ioctlsocket(handle, FIONBIO, &nb); //lint !e569 // loss of precision in the FIONBIO macro, beyond my control + if(err == SOCKET_ERROR) + OutputDebugString(getLastError().c_str()); +} + +//--------------------------------------------------------------------- diff --git a/engine/shared/library/sharedNetwork/src/win32/Sock.h b/engine/shared/library/sharedNetwork/src/win32/Sock.h new file mode 100755 index 00000000..d5dbb028 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/Sock.h @@ -0,0 +1,129 @@ +// ====================================================================== +// +// Sock.h +// +// Copyright 2003 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_Sock_H +#define INCLUDED_Sock_H + +// ====================================================================== + +#include "sharedNetwork/Address.h" + +// ====================================================================== + +const unsigned int SOCK_ERROR = 0xFFFFFFFF; +typedef unsigned int SOCKET; + +/** + @brief a BSD socket abstraction + + Sock abstracts BSD sockets for platform independant operation. It + also provides common socket operations to simplify socket management. + + @see BroadcastSock + @see TcpSock + @see UdpSock + + @author Justin Randall +*/ +class Sock +{ +public: + /** + @brief failure states for a socket + */ + enum ErrorCodes + { + SOCK_NO_ERROR, + CONNECTION_FAILED, + CONNECTION_CLOSED, + CONNECTION_RESET + }; + + Sock(); + virtual ~Sock() = 0; + bool bind(const Address & bindAddress); + bool bind(); + bool canSend() const; + bool canRecv() const; + const Address & getBindAddress() const; + const SOCKET getHandle() const; + const unsigned int getInputBytesPending() const; + const std::string getLastError() const; + const enum ErrorCodes getLastErrorCode() const; + const unsigned int getMaxMessageSendSize() const; + static void getPeerName(struct sockaddr_in & target, SOCKET s); + +private: + // disabled + Sock(const Sock & source); + Sock & operator= (const Sock & source); + +protected: + void setNonBlocking() const; +protected: + int handle; + + /** + @brief support for setting/getting last error from derived + sock classes + */ + mutable enum ErrorCodes lastError; +private: + Address bindAddress; +}; + +//--------------------------------------------------------------------- +/** + @brief return the local address of the socket + + Until a socket is bound, the bind address may be reported as + 0.0.0.0:0 + + @return a const Address reference describing the local address + of the socket. + + @author Justin Randall +*/ +inline const Address & Sock::getBindAddress() const +{ + return bindAddress; +} + +//--------------------------------------------------------------------- +/** + @brief return the platform specific socket handle + + the handle returned is not portable and should only be used locally + for Sock specific operations. + + @author Justin Randall +*/ +inline const SOCKET Sock::getHandle() const +{ + return handle; +} + +//--------------------------------------------------------------------- +/** + @brief get the last error code on the socket + + @return the last error code on the socket + + @see Sock::ErrorCodes + + @author Justin Randall +*/ +inline const enum Sock::ErrorCodes Sock::getLastErrorCode() const +{ + return lastError; +} + +//--------------------------------------------------------------------- + +#endif // _Sock_H + diff --git a/engine/shared/library/sharedNetwork/src/win32/TcpClient.cpp b/engine/shared/library/sharedNetwork/src/win32/TcpClient.cpp new file mode 100755 index 00000000..22c9d992 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/TcpClient.cpp @@ -0,0 +1,631 @@ +// TcpClient.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "sharedNetwork/FirstSharedNetwork.h" +#include "Archive/Archive.h" +#include "Archive/ByteStream.h" +#include "sharedFoundation/Clock.h" +#include "sharedNetwork/Address.h" +#include "sharedNetwork/ConfigSharedNetwork.h" +#include "sharedNetwork/Connection.h" +#include "sharedNetwork/Service.h" +#include "OverlappedTcp.h" +#include "TcpClient.h" +#include +#include + +//----------------------------------------------------------------------- + +const unsigned long KEEPALIVE_MS = 1000; + +//----------------------------------------------------------------------- + +namespace TcpClientNamespace +{ + std::set s_pendingConnectionSends; + std::set s_pendingConnectionRemoves; + std::set s_tcpClients; + QOS s_sqos; + QOS s_gqos; +} + +using namespace TcpClientNamespace; + +//----------------------------------------------------------------------- + +TcpClient::TcpClient(HANDLE parentIOCP) : +m_connectEvent(INVALID_HANDLE_VALUE), +m_socket(), +m_tcpServer(0), +m_localIOCP(INVALID_HANDLE_VALUE), +m_pendingSend(), +m_connection(0), +m_refCount(0), +m_connected(false), +m_ownHandle(false), +m_lastSendTime(0), +m_bindPort(0), +m_rawTCP( false ) +{ + static PROTOENT * p = getprotobyname ("tcp"); + if (p) + { + static int entry = p->p_proto; + m_socket = WSASocket (AF_INET, SOCK_STREAM, entry, NULL, 0, WSA_FLAG_OVERLAPPED); + char optval = 1; + setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval)); + unsigned long opt = 1; + ioctlsocket(m_socket, FIONBIO, &opt); + + struct sockaddr_in bindAddr; + int addrLen = sizeof(struct sockaddr_in); + if(getsockname(m_socket, reinterpret_cast(&bindAddr), &addrLen) == 0) + { + m_bindPort = ntohs(bindAddr.sin_port); + } + + m_localIOCP = CreateIoCompletionPort (reinterpret_cast (m_socket), parentIOCP, 0, 0); + queueReceive(); + } + s_tcpClients.insert(this); +} + +//----------------------------------------------------------------------- + +TcpClient::TcpClient(const std::string & remoteAddress, const unsigned short remotePort) : +m_connectEvent(INVALID_HANDLE_VALUE), +m_socket(), +m_localIOCP(INVALID_HANDLE_VALUE), +m_connection(0), +m_refCount(0), +m_connected(false), +m_ownHandle(true), +m_lastSendTime(0), +m_rawTCP( false ) +{ + static PROTOENT * p = getprotobyname ("tcp"); + if (p) + { + static int entry = p->p_proto; + m_socket = WSASocket (AF_INET, SOCK_STREAM, entry, NULL, 0, WSA_FLAG_OVERLAPPED); + if (m_socket != INVALID_SOCKET) + { + int nameLen = sizeof (struct sockaddr_in); + static WSABUF emptyBuf; + emptyBuf.buf = 0; + emptyBuf.len = 0; + + Address a(remoteAddress, remotePort); + char optval = 1; + setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval)); + unsigned long opt = 1; + ioctlsocket(m_socket, FIONBIO, &opt); + + int result; + result = WSAConnect (m_socket, reinterpret_cast (&a.getSockAddr4 () ), nameLen, 0, &emptyBuf, &s_sqos, &s_gqos); + m_connectEvent = WSACreateEvent (); + WSAEventSelect (m_socket, m_connectEvent, FD_CONNECT); + m_localIOCP = CreateIoCompletionPort (reinterpret_cast (m_socket), 0, 0, 0); + struct sockaddr_in bindAddr; + int addrLen = sizeof(struct sockaddr_in); + if(getsockname(m_socket, reinterpret_cast(&bindAddr), &addrLen) == 0) + { + m_bindPort = ntohs(bindAddr.sin_port); + } + + } + } + s_tcpClients.insert(this); +} + +//----------------------------------------------------------------------- + +TcpClient::~TcpClient() +{ + s_pendingConnectionRemoves.insert(this); + std::set::iterator f = s_tcpClients.find(this); + if(f != s_tcpClients.end()) + s_tcpClients.erase(f); + + closesocket (m_socket); + if(m_ownHandle) + CloseHandle(m_localIOCP); +} + +//----------------------------------------------------------------------- + +void TcpClient::addRef() +{ + m_refCount++; +} + +//----------------------------------------------------------------------- + +unsigned short TcpClient::getBindPort() const +{ + return m_bindPort; +} + +//----------------------------------------------------------------------- + +std::string const &TcpClient::getRemoteAddress() const +{ + // TODO: implement this + static std::string dummy; + return dummy; +} + +//----------------------------------------------------------------------- + +unsigned short TcpClient::getRemotePort() const +{ + // TODO: implement this + return 0; +} + +//----------------------------------------------------------------------- + +void TcpClient::commit(const unsigned char * const buffer, const int bufferLen) +{ + WSABUF wsaBuf; + + // yuck, docs say this is actually going to be const for the send, + // but WSABUF::buf is not const! + wsaBuf.buf = (char *)buffer; + wsaBuf.len = bufferLen; + + OverlappedTcp * op = getFreeOverlapped (); + if (op) + { + op->m_operation = OverlappedTcp::SEND; + op->m_tcpClient = const_cast(this); + int sent; + sent = WSASend (m_socket, &wsaBuf, 1, &op->m_bytes, 0, &op->m_overlapped, NULL); + if(sent == SOCKET_ERROR) + { + int errCode = WSAGetLastError(); + char * err; + if(errCode != WSA_IO_PENDING) + { + switch(errCode) + { + case WSANOTINITIALISED: + err = "A successful WSAStartup must occur before using this function."; + break; + case WSAENETDOWN: + err = "The network subsystem has failed."; + break; + case WSAENOTCONN: + err = "The socket is not connected."; + break; + case WSAEINTR: + err = "The (blocking) call was canceled through WSACancelBlockingCall. \n"; + break; + case WSAEINPROGRESS: + err = "A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. \n"; + break; + case WSAENETRESET: + err = "The connection has been broken due to \"keep-alive\" activity detecting a failure while the operation was in progress."; + break; + case WSAENOTSOCK: + err = "The descriptor is not a socket."; + break; + case WSAEFAULT: + err = "The lpBuffers parameter is not completely contained in a valid part of the user address space."; + break; + case WSAEOPNOTSUPP: + err = "MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, out-of-band data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations."; + break; + case WSAESHUTDOWN: + err = "The socket has been shut down; it is not possible to call WSARecv on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH. \n"; + break; + case WSAEWOULDBLOCK: + err = "Overlapped sockets: There are too many outstanding overlapped I/O requests. Nonoverlapped sockets: The socket is marked as nonblocking and the receive operation cannot be completed immediately. \n"; + break; + case WSAEMSGSIZE: + err = "The message was too large to fit into the specified buffer and (for unreliable protocols only) any trailing portion of the message that did not fit into the buffer has been discarded."; + break; + case WSAEINVAL: + err = "The socket has not been bound (for example, with bind)."; + break; + case WSAECONNABORTED: + err = "The virtual circuit was terminated due to a time-out or other failure. \n"; + break; + case WSAECONNRESET: + err = "The virtual circuit was reset by the remote side. \n"; + break; + case WSAEDISCON: + err = "Socket s is message oriented and the virtual circuit was gracefully closed by the remote side. \n"; + break; + case WSA_IO_PENDING: + err = "An overlapped operation was successfully initiated and completion will be indicated at a later time. \n"; + break; + case WSA_OPERATION_ABORTED: + err = "The overlapped operation has been canceled due to the closure of the socket. \n"; + break; + default: + err = "An unknown error occured while processing WSARecv()."; + break; + } + onConnectionClosed(); + } + } + } +} + +//----------------------------------------------------------------------- + +void TcpClient::flush() +{ + if(m_connected && m_pendingSend.getSize() > 0) + { + // put it on the wire + commit(m_pendingSend.getBuffer(), m_pendingSend.getSize()); + m_pendingSend.clear (); + } +} + +//----------------------------------------------------------------------- + +void TcpClient::flushPendingWrites() +{ + std::set::iterator f; + std::set::iterator i; + for(i = s_pendingConnectionSends.begin(); i != s_pendingConnectionSends.end(); ++i) + { + if(s_pendingConnectionRemoves.empty()) + { + (*i)->flush(); + } + else + { + f = s_pendingConnectionRemoves.find((*i)); + if(f == s_pendingConnectionRemoves.end()) + (*i)->flush(); + } + } + s_pendingConnectionSends.clear(); +} + +//----------------------------------------------------------------------- + +SOCKET TcpClient::getSocket() const +{ + return m_socket; +} + +//----------------------------------------------------------------------- + +void TcpClient::install() +{ + WORD wVersionRequested = MAKEWORD(2,2); + WSADATA wsaData; + WSAStartup(wVersionRequested, &wsaData); + s_sqos.ProviderSpecific.buf = 0; + s_sqos.ProviderSpecific.len = 0; + + s_sqos.ReceivingFlowspec.DelayVariation = 0; + s_sqos.ReceivingFlowspec.Latency = 0; + s_sqos.ReceivingFlowspec.MaxSduSize = 0; + s_sqos.ReceivingFlowspec.MinimumPolicedSize = 0; + s_sqos.ReceivingFlowspec.PeakBandwidth = 0; + s_sqos.ReceivingFlowspec.ServiceType = 0; + s_sqos.ReceivingFlowspec.TokenBucketSize = 0; + s_sqos.ReceivingFlowspec.TokenRate = 0; + + s_sqos.SendingFlowspec.DelayVariation = 0; + s_sqos.SendingFlowspec.Latency = 0; + s_sqos.SendingFlowspec.MaxSduSize = 0; + s_sqos.SendingFlowspec.MinimumPolicedSize = 0; + s_sqos.SendingFlowspec.PeakBandwidth = 0; + s_sqos.SendingFlowspec.ServiceType = 0; + s_sqos.SendingFlowspec.TokenBucketSize = 0; + s_sqos.SendingFlowspec.TokenRate = 0; + + s_gqos.ProviderSpecific.buf = 0; + s_gqos.ProviderSpecific.len = 0; + + s_gqos.ReceivingFlowspec.DelayVariation = 0; + s_gqos.ReceivingFlowspec.Latency = 0; + s_gqos.ReceivingFlowspec.MaxSduSize = 0; + s_gqos.ReceivingFlowspec.MinimumPolicedSize = 0; + s_gqos.ReceivingFlowspec.PeakBandwidth = 0; + s_gqos.ReceivingFlowspec.ServiceType = 0; + s_gqos.ReceivingFlowspec.TokenBucketSize = 0; + s_gqos.ReceivingFlowspec.TokenRate = 0; + + s_gqos.SendingFlowspec.DelayVariation = 0; + s_gqos.SendingFlowspec.Latency = 0; + s_gqos.SendingFlowspec.MaxSduSize = 0; + s_gqos.SendingFlowspec.MinimumPolicedSize = 0; + s_gqos.SendingFlowspec.PeakBandwidth = 0; + s_gqos.SendingFlowspec.ServiceType = 0; + s_gqos.SendingFlowspec.TokenBucketSize = 0; + s_gqos.SendingFlowspec.TokenRate = 0; +} + +//----------------------------------------------------------------------- + +void TcpClient::onConnectionClosed() +{ + m_connected = false; + if(m_connection) + { + NetworkHandler::onTerminate(m_connection); + } +} + +//----------------------------------------------------------------------- + +void TcpClient::onConnectionOpened() +{ + m_connected = true; + queueReceive(); + flush(); + if(m_connection) + m_connection->onConnectionOpened(); +} + +//----------------------------------------------------------------------- + +void TcpClient::onReceive(const unsigned char * const buffer, const int length) +{ + queueReceive(); + if(m_connection) + { + m_connection->receive(buffer, length); + } +} + +//----------------------------------------------------------------------- + +void TcpClient::queryConnect() +{ + bool result = false; + + WSANETWORKEVENTS w; + if (WSAEnumNetworkEvents (m_socket, m_connectEvent, &w) != SOCKET_ERROR) + { + if (w.lNetworkEvents == FD_CONNECT) + { + if (w.iErrorCode[FD_CONNECT_BIT] == 0) + { + CloseHandle (m_connectEvent); + result = true; + onConnectionOpened(); + } + else + { + onConnectionClosed(); + } + } + } +} + +//----------------------------------------------------------------------- + +void TcpClient::queueReceive() +{ + OverlappedTcp * op = getFreeOverlapped(); + op->m_operation = OverlappedTcp::RECV; + op->m_tcpClient = const_cast(this); + DWORD flags = 0; + int result; + result = WSARecv(m_socket, &op->m_recvBuf, 1, &op->m_bytes, &flags, &op->m_overlapped, NULL); + + if(result == SOCKET_ERROR) + { + int errCode = WSAGetLastError(); + char * err; + if(errCode != WSA_IO_PENDING) + { + switch(errCode) + { + case WSANOTINITIALISED: + err = "A successful WSAStartup must occur before using this function."; + break; + case WSAENETDOWN: + err = "The network subsystem has failed."; + break; + case WSAENOTCONN: + err = "The socket is not connected."; + break; + case WSAEINTR: + err = "The (blocking) call was canceled through WSACancelBlockingCall. \n"; + break; + case WSAEINPROGRESS: + err = "A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function. \n"; + break; + case WSAENETRESET: + err = "The connection has been broken due to \"keep-alive\" activity detecting a failure while the operation was in progress."; + break; + case WSAENOTSOCK: + err = "The descriptor is not a socket."; + break; + case WSAEFAULT: + err = "The lpBuffers parameter is not completely contained in a valid part of the user address space."; + break; + case WSAEOPNOTSUPP: + err = "MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, out-of-band data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only send operations."; + break; + case WSAESHUTDOWN: + err = "The socket has been shut down; it is not possible to call WSARecv on a socket after shutdown has been invoked with how set to SD_RECEIVE or SD_BOTH. \n"; + break; + case WSAEWOULDBLOCK: + err = "Overlapped sockets: There are too many outstanding overlapped I/O requests. Nonoverlapped sockets: The socket is marked as nonblocking and the receive operation cannot be completed immediately. \n"; + break; + case WSAEMSGSIZE: + err = "The message was too large to fit into the specified buffer and (for unreliable protocols only) any trailing portion of the message that did not fit into the buffer has been discarded."; + break; + case WSAEINVAL: + err = "The socket has not been bound (for example, with bind)."; + break; + case WSAECONNABORTED: + err = "The virtual circuit was terminated due to a time-out or other failure. \n"; + break; + case WSAECONNRESET: + err = "The virtual circuit was reset by the remote side. \n"; + break; + case WSAEDISCON: + err = "Socket s is message oriented and the virtual circuit was gracefully closed by the remote side. \n"; + break; + case WSA_IO_PENDING: + err = "An overlapped operation was successfully initiated and completion will be indicated at a later time. \n"; + break; + case WSA_OPERATION_ABORTED: + err = "The overlapped operation has been canceled due to the closure of the socket. \n"; + break; + default: + err = "An unknown error occured while processing WSARecv()."; + break; + } + } + } +} + +//----------------------------------------------------------------------- + +void TcpClient::send(const unsigned char * const buffer, const int length) +{ + if (length) + { + m_lastSendTime = Clock::getFrameStartTimeMs(); + s_pendingConnectionSends.insert(this); + if( !m_rawTCP ) + Archive::put(m_pendingSend, length); + m_pendingSend.put(buffer, length); + + static int const tcpMinimumFrame = ConfigSharedNetwork::getTcpMinimumFrame(); + if (static_cast(m_pendingSend.getSize()) >= tcpMinimumFrame) + flush(); + } +} + +//----------------------------------------------------------------------- + +void TcpClient::setConnection(Connection * c) +{ + m_connection = c; +} + +//--------------------------------------------------------------------- + +void TcpClient::update() +{ + OVERLAPPED * overlapped = 0; + OverlappedTcp * op = 0; + unsigned long int bytesTransferred = 0; + unsigned long int completionKey = 0; + bool success = false; + + if (m_connected) + { + unsigned long timeNow = Clock::getFrameStartTimeMs(); + if (timeNow-m_lastSendTime > KEEPALIVE_MS) + { + m_lastSendTime = timeNow; + s_pendingConnectionSends.insert(this); + Archive::put(m_pendingSend, 0); + } + } + + if(! m_connected) + queryConnect(); + + //PlatformTcpClient::queryConnects(); + do + { + success = false; + int ok = GetQueuedCompletionStatus( + m_localIOCP, // completion port of interest + &bytesTransferred, // number of bytes sent or received + &completionKey, + &overlapped, + 0 // timeout immediately if there are no completions + ); + if(ok) + { + op = reinterpret_cast(overlapped); + if(op) + { + switch(op->m_operation) + { + case OverlappedTcp::RECV: + { + if(op->m_tcpClient != 0) + { + if(bytesTransferred > 0) + { + op->m_tcpClient->onReceive((const unsigned char * const)op->m_recvBuf.buf, bytesTransferred); + success = true; + } + } + } + + break; + case OverlappedTcp::SEND: + success = true; + break; + default: + break; + } + releaseOverlapped(op); + } + } + } while(success); +} + +//----------------------------------------------------------------------- + +void TcpClient::setRawTCP( bool bNewValue ) +{ + m_rawTCP = bNewValue; +} + +//----------------------------------------------------------------------- + +void TcpClient::release() +{ + m_refCount--; + if(m_refCount < 1) + { + if(m_connected) + onConnectionClosed(); + delete this; + } +} + +//----------------------------------------------------------------------- + +void TcpClient::remove() +{ + std::set::iterator i; + for(i = s_tcpClients.begin(); i != s_tcpClients.end(); ++i) + { + TcpClient * c = (*i); + delete c; + } + s_tcpClients.clear(); + WSACleanup(); +} + +//----------------------------------------------------------------------- + +void TcpClient::checkKeepalive() +{ + unsigned long const timeNow = Clock::getFrameStartTimeMs(); + if (timeNow-m_lastSendTime > KEEPALIVE_MS) + { + m_lastSendTime = timeNow; + s_pendingConnectionSends.insert(this); + Archive::put(m_pendingSend, 0); + } +} + +//----------------------------------------------------------------------- + diff --git a/engine/shared/library/sharedNetwork/src/win32/TcpClient.h b/engine/shared/library/sharedNetwork/src/win32/TcpClient.h new file mode 100755 index 00000000..a83ec780 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/TcpClient.h @@ -0,0 +1,87 @@ +// TcpClient.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_TcpClient_H +#define _INCLUDED_TcpClient_H + +//----------------------------------------------------------------------- + +#include +#include "Archive/ByteStream.h" +#include + +//----------------------------------------------------------------------- + +class Connection; + +//----------------------------------------------------------------------- + +class TcpClient +{ +public: + explicit TcpClient(HANDLE parentIOCP); + TcpClient(const std::string & address, const unsigned short port); + ~TcpClient(); + + static void install(); + static void remove(); + void send(const unsigned char * const buffer, const int length); + unsigned short getBindPort() const; + std::string const &getRemoteAddress() const; + unsigned short getRemotePort() const; + void setPendingSendAllocatedSizeLimit(unsigned int limit); + + // only used by clients + void update(); + static void flushPendingWrites(); + +protected: + friend TcpServer; + friend Connection; + + void addRef(); + void commit(const unsigned char * const buffer, const int bufferLen); + SOCKET getSocket() const; + void onConnectionClosed(); + void onConnectionOpened(); + void onReceive(const unsigned char * const recvBuf, const int bytes); + void queryConnect(); + void queueReceive(); + void release(); + void setConnection(Connection *); + + void checkKeepalive(); + void setRawTCP( bool bNewValue ); + + +private: + TcpClient & operator = (const TcpClient & rhs); + TcpClient(const TcpClient & source); + void flush (); + + WSAEVENT m_connectEvent; + SOCKET m_socket; + TcpServer * m_tcpServer; + HANDLE m_localIOCP; + Archive::ByteStream m_pendingSend; + Connection * m_connection; + int m_refCount; + bool m_connected; + bool m_ownHandle; + unsigned long m_lastSendTime; + unsigned short m_bindPort; + + bool m_rawTCP; +}; + +//----------------------------------------------------------------------- + +inline void TcpClient::setPendingSendAllocatedSizeLimit(const unsigned int limit) +{ + m_pendingSend.setAllocatedSizeLimit(limit); +} + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_TcpClient_H diff --git a/engine/shared/library/sharedNetwork/src/win32/TcpServer.cpp b/engine/shared/library/sharedNetwork/src/win32/TcpServer.cpp new file mode 100755 index 00000000..17a8f5da --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/TcpServer.cpp @@ -0,0 +1,194 @@ +// TcpServer.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "sharedNetwork/FirstSharedNetwork.h" +#include +#include +#include "sharedNetwork/Address.h" +#include "sharedNetwork/Service.h" +#include "OverlappedTcp.h" +#include "TcpClient.h" +#include "TcpServer.h" + +//----------------------------------------------------------------------- + +TcpServer::TcpServer(Service * service, const std::string & bindAddress, const unsigned short bindPort) : +m_handle(), +m_localIOCP(), +m_pendingConnections(), +m_bindAddress(bindAddress), +m_bindPort(bindPort), +m_service(service) +{ + static PROTOENT * p = getprotobyname("tcp"); + if(p) + { + static int entry = p->p_proto; + m_handle = WSASocket(AF_INET, SOCK_STREAM, entry, NULL, 0, WSA_FLAG_OVERLAPPED); + if(m_handle != INVALID_SOCKET) + { + m_localIOCP = CreateIoCompletionPort(reinterpret_cast(m_handle), 0, 0, 0); + Address a(bindAddress, bindPort); + + int result = bind(m_handle, reinterpret_cast(&a.getSockAddr4()), sizeof(struct sockaddr_in)); + if(result == 0) + { + struct sockaddr_in b; + int addrlen = sizeof(struct sockaddr_in); + getsockname(m_handle, (struct sockaddr *)(&b), &addrlen); + m_bindPort = ntohs(b.sin_port); + result = listen(m_handle, 256); + queueAccept(); + } + } + } +} + +//----------------------------------------------------------------------- + +TcpServer::~TcpServer() +{ + closesocket(m_handle); + CloseHandle(m_localIOCP); +} + +//----------------------------------------------------------------------- + +TcpClient * TcpServer::accept() +{ + TcpClient * result = 0; + if(! m_pendingConnections.empty()) + { + result = m_pendingConnections.back(); + m_pendingConnections.pop_back(); + } + return result; +} + +//----------------------------------------------------------------------- + +const unsigned short TcpServer::getBindPort() const +{ + return m_bindPort; +} + +//----------------------------------------------------------------------- + +void TcpServer::onConnectionClosed(TcpClient *) +{ +} + +//----------------------------------------------------------------------- + +void TcpServer::queueAccept() +{ + OverlappedTcp * op = getFreeOverlapped(); + + // this will contain struct sockaddr data with additional + // book keeping when Windows returns an overlapped + // accept operation (nevermind that +16 or * 2, I don't have the MS + // kb article handy, but it's a gross workaround for the documented + // API and what acceptData really expects to have). + op->m_acceptData = new unsigned char[(sizeof( struct sockaddr_in ) + 16 ) * 2]; + op->m_operation = OverlappedTcp::ACCEPT; + op->m_tcpServer = this; + op->m_tcpClient = new TcpClient(m_localIOCP); + AcceptEx( + m_handle, + op->m_tcpClient->getSocket(), + op->m_acceptData, + 0, + sizeof(struct sockaddr_in) + 16, + sizeof(struct sockaddr_in) + 16, + &op->m_bytes, + &op->m_overlapped); +} + +//----------------------------------------------------------------------- + +void TcpServer::update() +{ + OVERLAPPED * overlapped = 0; + OverlappedTcp * op = 0; + unsigned long int bytesTransferred = 0; + unsigned long int completionKey = 0; + bool success = false; + + do + { + success = false; + int ok = GetQueuedCompletionStatus( + m_localIOCP, // completion port of interest + &bytesTransferred, // number of bytes sent or received + &completionKey, + &overlapped, + 0 // timeout immediately if there are no completions + ); + if(ok) + { + op = reinterpret_cast(overlapped); + if(op) + { + switch(op->m_operation) + { + case OverlappedTcp::ACCEPT: + { + if(op->m_tcpServer == this) + { + if(op->m_acceptData != 0) + { + // Extremely lame hack to keep things safe from Winsock stacktrashing + //struct sockaddr_in local; + //struct sockaddr_in remote; + //memcpy(&local, reinterpret_cast(op->m_acceptData + 10), sizeof(struct sockaddr_in)); + //memcpy(&remote, reinterpret_cast(op->m_acceptData + 38), sizeof(struct sockaddr_in)); + delete[] op->m_acceptData; + TcpClient * newClient = op->m_tcpClient; + newClient->addRef(); + newClient->onConnectionOpened(); + m_pendingConnections.push_back(newClient); + success = true; + queueAccept(); + if(m_service) + { + m_service->onConnectionOpened(newClient); + } + newClient->release(); + } + } + } + break; + case OverlappedTcp::RECV: + { + if(op->m_tcpClient != 0) + { + op->m_tcpClient->onReceive((const unsigned char * const)op->m_recvBuf.buf, bytesTransferred); + } + } + success = true; + break; + case OverlappedTcp::SEND: + success = true; + break; + default: + break; + } + releaseOverlapped(op); + } + } + } while(success); +} + +//----------------------------------------------------------------------- + +const std::string & TcpServer::getBindAddress() const +{ + return m_bindAddress; +} + +//--------------------------------------------------------------------- + + diff --git a/engine/shared/library/sharedNetwork/src/win32/TcpServer.h b/engine/shared/library/sharedNetwork/src/win32/TcpServer.h new file mode 100755 index 00000000..2ae6b934 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/TcpServer.h @@ -0,0 +1,50 @@ +// TcpServer.h +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +#ifndef _INCLUDED_TcpServer_H +#define _INCLUDED_TcpServer_H + +//----------------------------------------------------------------------- + +#include +#include +#include + +//----------------------------------------------------------------------- + +class Service; +class TcpClient; + +//----------------------------------------------------------------------- + +class TcpServer +{ +public: + TcpServer(Service * service, const std::string & bindAddress, const unsigned short bindPort); + ~TcpServer(); + + TcpClient * accept (); + const std::string & getBindAddress () const; + const unsigned short getBindPort () const; + void onConnectionClosed (TcpClient *); + void update (); + +private: + TcpServer & operator = (const TcpServer & rhs); + TcpServer(const TcpServer & source); + + void queueAccept (); + +private: + SOCKET m_handle; + HANDLE m_localIOCP; + std::vector m_pendingConnections; + std::string m_bindAddress; + unsigned short m_bindPort; + Service * m_service; +}; + +//----------------------------------------------------------------------- + +#endif // _INCLUDED_TcpServer_H diff --git a/engine/shared/library/sharedNetwork/src/win32/UdpSock.cpp b/engine/shared/library/sharedNetwork/src/win32/UdpSock.cpp new file mode 100755 index 00000000..05224a37 --- /dev/null +++ b/engine/shared/library/sharedNetwork/src/win32/UdpSock.cpp @@ -0,0 +1,108 @@ +// UdpSock.cpp +// Copyright 2000-02, Sony Online Entertainment Inc., all rights reserved. + +//--------------------------------------------------------------------- + +#include "sharedNetwork/FirstSharedNetwork.h" +#include "sharedNetwork/UdpSock.h" + +#include + +//--------------------------------------------------------------------- +/** + @brief construct a UdpSock object + + Allocates the socket descriptor, sets it to non-blocking mode. + + @author Justin Randall +*/ +UdpSock::UdpSock() : +Sock() +{ + handle = socket(AF_INET, SOCK_DGRAM, 0); + setNonBlocking(); +} + +//--------------------------------------------------------------------- +/** + @brief destroy the UdpSock object + + Doesn't do anything special. + + @author Justin Randall +*/ +UdpSock::~UdpSock() +{ +} + +//--------------------------------------------------------------------- +/** + @brief receive a datagram + + Receives a datagram and populates the outAddr parameter with the + source address of the message. + + Calling Sock::getInputBytesPending can provide a hint before + allocating the user supplied target buffer. + + @param outAddr target Address reference that receives + the message source IP address + @param targetBuffer a user supplied buffer to receive the data. + @param targetBufferSize the size of the user supplied buffer + + @author Justin Randall +*/ +const unsigned int UdpSock::recvFrom(Address & outAddr, void * targetBuffer, const unsigned int bufferSize) const +{ + int fromLen = sizeof(struct sockaddr_in); + struct sockaddr_in addr; + unsigned int result = ::recvfrom(handle, static_cast(targetBuffer), static_cast(bufferSize), 0, reinterpret_cast(&addr), &fromLen); //lint !e732 // MS wants an int, should be unsigned IMO + outAddr = addr; + if(result == SOCK_ERROR) + { + OutputDebugString(getLastError().c_str()); + } + return result; +} + +//--------------------------------------------------------------------- +/** + @brief send a datagram to a remote system + + sendTo sends a datagram to a remote system. + + @param targetAddress System to receive the datagram + @param sourceBuffer A user supplied buffer containint the data + to be sent + @param length The amount of data in the source buffer to + send + + @return The number of bytes sent on success + + @author Justin Randall +*/ +const unsigned int UdpSock::sendTo(const Address & targetAddress, const void * sourceBuffer, const unsigned int length) const +{ + unsigned int bytesSent = 0; + if(canSend()) + { + int toLen = sizeof(struct sockaddr_in); + bytesSent = ::sendto(handle, static_cast(sourceBuffer), static_cast(length), 0, reinterpret_cast(&(targetAddress.getSockAddr4())), toLen); //lint !e732 // MS wants an int, should be unsigned IMO + if(bytesSent != length) + { + OutputDebugString(getLastError().c_str()); + } + } + return bytesSent; +} + +//----------------------------------------------------------------------- + +void UdpSock::enableBroadcast() +{ + char optval = 1; + int err; + err = setsockopt(getHandle(), SOL_SOCKET, SO_BROADCAST, &optval, sizeof(char)); +} + +//--------------------------------------------------------------------- diff --git a/engine/shared/library/sharedNetworkMessages/src/win32/FirstSharedNetworkMessages.cpp b/engine/shared/library/sharedNetworkMessages/src/win32/FirstSharedNetworkMessages.cpp new file mode 100755 index 00000000..a5d2ce4d --- /dev/null +++ b/engine/shared/library/sharedNetworkMessages/src/win32/FirstSharedNetworkMessages.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstNetworkMessages.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedNetworkMessages/FirstSharedNetworkMessages.h" diff --git a/engine/shared/library/sharedObject/src/win32/FirstSharedObject.cpp b/engine/shared/library/sharedObject/src/win32/FirstSharedObject.cpp new file mode 100755 index 00000000..4221af2e --- /dev/null +++ b/engine/shared/library/sharedObject/src/win32/FirstSharedObject.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstObject.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedObject/FirstSharedObject.h" diff --git a/engine/shared/library/sharedPathfinding/src/win32/FirstSharedPathfinding.cpp b/engine/shared/library/sharedPathfinding/src/win32/FirstSharedPathfinding.cpp new file mode 100755 index 00000000..9792c261 --- /dev/null +++ b/engine/shared/library/sharedPathfinding/src/win32/FirstSharedPathfinding.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstSharedPathfinding.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedPathfinding/FirstSharedPathfinding.h" diff --git a/engine/shared/library/sharedRandom/src/win32/FirstSharedRandom.cpp b/engine/shared/library/sharedRandom/src/win32/FirstSharedRandom.cpp new file mode 100755 index 00000000..1ce55673 --- /dev/null +++ b/engine/shared/library/sharedRandom/src/win32/FirstSharedRandom.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstRandom.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedRandom/FirstSharedRandom.h" diff --git a/engine/shared/library/sharedRegex/src/win32/FirstSharedRegex.cpp b/engine/shared/library/sharedRegex/src/win32/FirstSharedRegex.cpp new file mode 100755 index 00000000..d219edf0 --- /dev/null +++ b/engine/shared/library/sharedRegex/src/win32/FirstSharedRegex.cpp @@ -0,0 +1,9 @@ +// ====================================================================== +// +// FirstSharedRegex.cpp +// Copyright 2003 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "sharedRegex/FirstSharedRegex.h" diff --git a/engine/shared/library/sharedRegex/src/win32/RegexServices.cpp b/engine/shared/library/sharedRegex/src/win32/RegexServices.cpp new file mode 100755 index 00000000..c12a1c67 --- /dev/null +++ b/engine/shared/library/sharedRegex/src/win32/RegexServices.cpp @@ -0,0 +1,57 @@ +// ====================================================================== +// +// RegexServices.cpp +// Copyright 2003 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "sharedRegex/FirstSharedRegex.h" +#include "sharedRegex/RegexServices.h" + +// ====================================================================== + +static void * __cdecl localAllocate(size_t size, uint32 owner, bool array, bool leakTest) +{ + return MemoryManager::allocate(size, owner, array, leakTest); +} + +static __declspec(naked) void * regexAllocate(size_t) +{ + _asm + { + // setup local call stack + push ebp + mov ebp, esp + + // MemoryManager::alloc(size, [return address], false, true) + push 1 + push 0 + mov eax, dword ptr [ebp+4] + push eax + mov eax, dword ptr [ebp+8] + push eax + call localAllocate + add esp, 12 + + mov esp, ebp + pop ebp + ret + } +} + +// ---------------------------------------------------------------------- + +void *RegexServices::allocateMemory(size_t byteCount) +{ + return regexAllocate(byteCount); +} + +// ---------------------------------------------------------------------- + +void RegexServices::freeMemory(void *pointer) +{ + MemoryManager::free(pointer, false); +} + +// ====================================================================== diff --git a/engine/shared/library/sharedRegex/src/win32/RegexServices.h b/engine/shared/library/sharedRegex/src/win32/RegexServices.h new file mode 100755 index 00000000..762c80de --- /dev/null +++ b/engine/shared/library/sharedRegex/src/win32/RegexServices.h @@ -0,0 +1,25 @@ +// ====================================================================== +// +// RegexServices.h +// Copyright 2003 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#ifndef INCLUDED_RegexServices_H +#define INCLUDED_RegexServices_H + +// ====================================================================== + +class RegexServices +{ +public: + + static void *allocateMemory(size_t byteCount); + static void freeMemory(void *pointer); + +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedSkillSystem/src/win32/FirstSharedSkillSystem.cpp b/engine/shared/library/sharedSkillSystem/src/win32/FirstSharedSkillSystem.cpp new file mode 100755 index 00000000..0b610d18 --- /dev/null +++ b/engine/shared/library/sharedSkillSystem/src/win32/FirstSharedSkillSystem.cpp @@ -0,0 +1,8 @@ +// FirstSharedSkillSystem.cpp +// Copyright 2000-01, Sony Online Entertainment Inc., all rights reserved. +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "sharedSkillSystem/FirstSharedSkillSystem.h" + diff --git a/engine/shared/library/sharedSynchronization/src/win32/ConditionVariable.cpp b/engine/shared/library/sharedSynchronization/src/win32/ConditionVariable.cpp new file mode 100755 index 00000000..bdcb1a5f --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/ConditionVariable.cpp @@ -0,0 +1,50 @@ +// ====================================================================== +// +// ConditionVariable.cpp +// Acy Stapp +// +// Copyright 6/19/2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedSynchronization/FirstSharedSynchronization.h" +#include "sharedSynchronization/ConditionVariable.h" + +#include "sharedSynchronization/Mutex.h" + +ConditionVariable::ConditionVariable(Mutex &m) +: sem(1), _mutex(m), count(0) +{ +} + +ConditionVariable::~ConditionVariable() +{ +} + +void ConditionVariable::wait() +{ + ++count; + _mutex.leave(); + sem.wait(); + _mutex.enter(); +} + +void ConditionVariable::signal() +{ + if (count) + { + --count; + sem.signal(); + } +} + +void ConditionVariable::broadcast() +{ + if (count) + { + int oldcount = count; + count = 0; + sem.signal(oldcount); + } +} + diff --git a/engine/shared/library/sharedSynchronization/src/win32/ConditionVariable.h b/engine/shared/library/sharedSynchronization/src/win32/ConditionVariable.h new file mode 100755 index 00000000..07ab3034 --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/ConditionVariable.h @@ -0,0 +1,42 @@ +// ====================================================================== +// +// ConditionVariable.h +// Acy Stapp +// +// Copyright 6/19/2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_ConditionVariable_h +#define INCLUDED_ConditionVariable_h + +class Mutex; + +#include "sharedSynchronization/Semaphore.h" + +/* Condition variable semantics follow pthreads semantics. You +must have the mutex locked before calling signal or broadcast. +When wait returns, the mutex is locked and you must unlock it. +*/ + +class ConditionVariable +{ +public: + ConditionVariable(Mutex &m); + ~ConditionVariable(); + void wait(); + // You must own the mutex before calling signal. + void signal(); + void broadcast(); + Mutex &mutex() { return _mutex; } +private: + ConditionVariable(const ConditionVariable &o); + ConditionVariable &operator =(const ConditionVariable &o); + + Semaphore sem; + Mutex &_mutex; + int count; +}; + + +#endif \ No newline at end of file diff --git a/engine/shared/library/sharedSynchronization/src/win32/FirstSharedSynchronization.cpp b/engine/shared/library/sharedSynchronization/src/win32/FirstSharedSynchronization.cpp new file mode 100755 index 00000000..12dd9b70 --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/FirstSharedSynchronization.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstSynchronization.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedSynchronization/FirstSharedSynchronization.h" diff --git a/engine/shared/library/sharedSynchronization/src/win32/Gate.cpp b/engine/shared/library/sharedSynchronization/src/win32/Gate.cpp new file mode 100755 index 00000000..654ab4f6 --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/Gate.cpp @@ -0,0 +1,60 @@ +// ====================================================================== +// +// Gate.cpp +// +// Copyright 2001-2002 Sony Online Entertainment +// All Rights Reserved. +// +// ====================================================================== + +#include "sharedSynchronization/FirstSharedSynchronization.h" +#include "sharedSynchronization/Gate.h" + +// ====================================================================== + +Gate::Gate(bool open) +{ + handle = CreateEvent(0, true, open, 0); + DEBUG_FATAL(handle == NULL, ("CreateEvent failed")); +} + +// ---------------------------------------------------------------------- + +Gate::~Gate() +{ + CloseHandle(handle); +} + +// ---------------------------------------------------------------------- + +void Gate::wait() +{ + int errors = 0; + for (;;) + { + DWORD result = WaitForSingleObject(handle, INFINITE); + if (result == WAIT_OBJECT_0) + return; + + ++errors; + FATAL(errors >= 3, ("WaitForSingleObject failed multiple times")); + } +} + +// ---------------------------------------------------------------------- + +void Gate::close() +{ + const BOOL result = ResetEvent(handle); + FATAL(result == 0, ("ResetEvent failed")); +} + +// ---------------------------------------------------------------------- + +void Gate::open() +{ + const BOOL result = SetEvent(handle); + FATAL(result == 0, ("SetEvent failed")); +} + +// ====================================================================== diff --git a/engine/shared/library/sharedSynchronization/src/win32/Gate.h b/engine/shared/library/sharedSynchronization/src/win32/Gate.h new file mode 100755 index 00000000..a0d3116e --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/Gate.h @@ -0,0 +1,39 @@ +// ====================================================================== +// +// Gate.h +// +// Copyright 2001-2002 Sony Online Entertainment +// All Rights Reseved. +// +// ====================================================================== + +#ifndef INCLUDED_Gate_h +#define INCLUDED_Gate_h + +// ====================================================================== + +class Gate +{ +public: + + Gate(bool initiallyOpen); + ~Gate(); + + void wait(); + + void close(); + void open(); + +private: + + Gate(const Gate &o); + Gate &operator =(const Gate &o); + +private: + + HANDLE handle; +}; + +// ====================================================================== + +#endif \ No newline at end of file diff --git a/engine/shared/library/sharedSynchronization/src/win32/InterlockedInteger.h b/engine/shared/library/sharedSynchronization/src/win32/InterlockedInteger.h new file mode 100755 index 00000000..0489c3f8 --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/InterlockedInteger.h @@ -0,0 +1,52 @@ +// ====================================================================== +// +// InterlockedInteger.h +// Acy Stapp +// +// Copyright 6/19/2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_InterlockedInteger_h +#define INCLUDED_InterlockedInteger_h + +// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +class InterlockedInteger +{ +public: + explicit InterlockedInteger(int initialValue=0); + int operator =(int); // returns prior value (exchange) + int operator ++(); // returns new value + int operator --(); // returns new value + operator int() const { return static_cast(value); } +private: + InterlockedInteger(const InterlockedInteger &o); + InterlockedInteger &operator =(const InterlockedInteger &o); + volatile int value; +}; + +inline InterlockedInteger::InterlockedInteger(int i_value) +: value(i_value) +{ +} + +inline int InterlockedInteger::operator =(int i_value) +{ + long * ptr = (long *)&value; + return static_cast(InterlockedExchange(ptr, static_cast(i_value))); +} + +inline int InterlockedInteger::operator ++() +{ + long * ptr = (long *)&value; + return static_cast(InterlockedIncrement(ptr)); +} + +inline int InterlockedInteger::operator --() +{ + long * ptr = (long *)&value; + return static_cast(InterlockedDecrement(ptr)); +} + +#endif \ No newline at end of file diff --git a/engine/shared/library/sharedSynchronization/src/win32/InterlockedVoidPointer.h b/engine/shared/library/sharedSynchronization/src/win32/InterlockedVoidPointer.h new file mode 100755 index 00000000..eff0a63e --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/InterlockedVoidPointer.h @@ -0,0 +1,45 @@ +// ====================================================================== +// +// InterlockedVoidPointer.h +// Acy Stapp +// +// Copyright 6/19/2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_InterlockedVoidPointer_h +#define INCLUDED_InterlockedVoidPointer_h + +// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +class InterlockedVoidPointer +{ +public: + explicit InterlockedVoidPointer(void * initialValue=0); + void * compareExchange(void * compare, void * exchange); // compare and exchange if same + operator void * () const { return reinterpret_cast(value); } +private: + InterlockedVoidPointer(const InterlockedVoidPointer &o); + InterlockedVoidPointer &operator =(const InterlockedVoidPointer &o); + void * volatile value; +}; + +template +class InterlockedPointer: public InterlockedVoidPointer +{ +public: + explicit InterlockedPointer(T * initialValue): InterlockedVoidPointer(initialValue) {} + operator T * () const { return static_cast(value); } +}; + +inline InterlockedVoidPointer::InterlockedVoidPointer(void * initialValue) +{ + value = initialValue; +} + +inline void * InterlockedVoidPointer::compareExchange(void * compare, void * exchange) +{ + return (void *)InterlockedCompareExchange((void **)&value, exchange, compare); +} + +#endif \ No newline at end of file diff --git a/engine/shared/library/sharedSynchronization/src/win32/Mutex.cpp b/engine/shared/library/sharedSynchronization/src/win32/Mutex.cpp new file mode 100755 index 00000000..557412a7 --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/Mutex.cpp @@ -0,0 +1,53 @@ +// ====================================================================== +// +// Mutex.cpp +// +// Copyright 2001-2002 Sony Online Entertainment +// All Rights Reserved +// +// ====================================================================== + +#include "sharedSynchronization/FirstSharedSynchronization.h" +#include "sharedSynchronization/Mutex.h" + +// ====================================================================== + +void Mutex::install() +{ +} + +// ---------------------------------------------------------------------- + +void Mutex::remove() +{ +} + +// ====================================================================== + +Mutex::Mutex() +{ + InitializeCriticalSection(&m_criticalSection); +} + +// ---------------------------------------------------------------------- + +Mutex::~Mutex() +{ + DeleteCriticalSection(&m_criticalSection); +} + +// ---------------------------------------------------------------------- + +void Mutex::enter() +{ + EnterCriticalSection(&m_criticalSection); +} + +// ---------------------------------------------------------------------- + +void Mutex::leave() +{ + LeaveCriticalSection(&m_criticalSection); +} + +// ====================================================================== diff --git a/engine/shared/library/sharedSynchronization/src/win32/Mutex.h b/engine/shared/library/sharedSynchronization/src/win32/Mutex.h new file mode 100755 index 00000000..579b52c5 --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/Mutex.h @@ -0,0 +1,41 @@ +// ====================================================================== +// +// Mutex.h +// Copyright 2001-2002 Sony Online Entertainment +// All Rights Reserved. +// +// ====================================================================== + +#ifndef INCLUDED_Mutex_H +#define INCLUDED_Mutex_H + +// ====================================================================== + +class Mutex +{ +public: + + static void install(); + static void remove(); + +public: + + Mutex(); + ~Mutex(); + + void enter(); + void leave(); + +private: + + Mutex(const Mutex &); + Mutex &operator =(const Mutex &); + +private: + + CRITICAL_SECTION m_criticalSection; +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedSynchronization/src/win32/RecursiveMutex.cpp b/engine/shared/library/sharedSynchronization/src/win32/RecursiveMutex.cpp new file mode 100755 index 00000000..fa39da6b --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/RecursiveMutex.cpp @@ -0,0 +1,53 @@ +// ====================================================================== +// +// RecursiveMutex.cpp +// +// Copyright 2001-2002 Sony Online Entertainment +// All Rights Reserved +// +// ====================================================================== + +#include "sharedSynchronization/FirstSharedSynchronization.h" +#include "sharedSynchronization/RecursiveMutex.h" + +// ====================================================================== + +void RecursiveMutex::install() +{ +} + +// ---------------------------------------------------------------------- + +void RecursiveMutex::remove() +{ +} + +// ====================================================================== + +RecursiveMutex::RecursiveMutex() +{ + InitializeCriticalSection(&m_criticalSection); +} + +// ---------------------------------------------------------------------- + +RecursiveMutex::~RecursiveMutex() +{ + DeleteCriticalSection(&m_criticalSection); +} + +// ---------------------------------------------------------------------- + +void RecursiveMutex::enter() +{ + EnterCriticalSection(&m_criticalSection); +} + +// ---------------------------------------------------------------------- + +void RecursiveMutex::leave() +{ + LeaveCriticalSection(&m_criticalSection); +} + +// ====================================================================== diff --git a/engine/shared/library/sharedSynchronization/src/win32/RecursiveMutex.h b/engine/shared/library/sharedSynchronization/src/win32/RecursiveMutex.h new file mode 100755 index 00000000..6c056a6c --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/RecursiveMutex.h @@ -0,0 +1,41 @@ +// ====================================================================== +// +// RecursiveMutex.h +// Copyright 2001-2002 Sony Online Entertainment +// All Rights Reserved. +// +// ====================================================================== + +#ifndef INCLUDED_RecursiveMutex_H +#define INCLUDED_RecursiveMutex_H + +// ====================================================================== + +class RecursiveMutex +{ +public: + + static void install(); + static void remove(); + +public: + + RecursiveMutex(); + ~RecursiveMutex(); + + void enter(); + void leave(); + +private: + + RecursiveMutex(const RecursiveMutex &); + RecursiveMutex &operator =(const RecursiveMutex &); + +private: + + CRITICAL_SECTION m_criticalSection; +}; + +// ====================================================================== + +#endif diff --git a/engine/shared/library/sharedSynchronization/src/win32/Semaphore.cpp b/engine/shared/library/sharedSynchronization/src/win32/Semaphore.cpp new file mode 100755 index 00000000..47a385b4 --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/Semaphore.cpp @@ -0,0 +1,37 @@ +// ====================================================================== +// +// Semaphore.cpp +// Acy Stapp +// +// Copyright 6/19/2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedSynchronization/FirstSharedSynchronization.h" +#include "sharedSynchronization/Semaphore.h" + +Semaphore::Semaphore(int count, int initial) +{ + handle = CreateSemaphore(0, initial, count, 0); +} + +Semaphore::~Semaphore() +{ + CloseHandle(handle); +} + +void Semaphore::wait() +{ + WaitForSingleObject(handle, INFINITE); +} + +void Semaphore::wait(unsigned int maxDurationMs) +{ + WaitForSingleObject(handle, maxDurationMs); +} + +void Semaphore::signal(int count) +{ + ReleaseSemaphore(handle, count, 0); +} + diff --git a/engine/shared/library/sharedSynchronization/src/win32/Semaphore.h b/engine/shared/library/sharedSynchronization/src/win32/Semaphore.h new file mode 100755 index 00000000..744743a4 --- /dev/null +++ b/engine/shared/library/sharedSynchronization/src/win32/Semaphore.h @@ -0,0 +1,28 @@ +// ====================================================================== +// +// Semaphore.h +// Acy Stapp +// +// Copyright 6/19/2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_Semaphore_h +#define INCLUDED_Semaphore_h + +class Semaphore +{ +public: + Semaphore(int count=0x7FFFFFFF, int initial=0); + ~Semaphore(); + + void wait(); + void wait(unsigned int maxDurationMs); + void signal(int count=1); +private: + Semaphore(const Semaphore &o); + Semaphore &operator =(const Semaphore &o); + HANDLE handle; +}; + +#endif diff --git a/engine/shared/library/sharedTemplate/src/win32/FirstSharedTemplate.cpp b/engine/shared/library/sharedTemplate/src/win32/FirstSharedTemplate.cpp new file mode 100755 index 00000000..527ba602 --- /dev/null +++ b/engine/shared/library/sharedTemplate/src/win32/FirstSharedTemplate.cpp @@ -0,0 +1 @@ +#include "sharedTemplate/FirstSharedTemplate.h" diff --git a/engine/shared/library/sharedTemplateDefinition/src/win32/FirstSharedTemplateDefinition.cpp b/engine/shared/library/sharedTemplateDefinition/src/win32/FirstSharedTemplateDefinition.cpp new file mode 100755 index 00000000..b156d0fd --- /dev/null +++ b/engine/shared/library/sharedTemplateDefinition/src/win32/FirstSharedTemplateDefinition.cpp @@ -0,0 +1 @@ +#include "sharedTemplateDefinition/FirstSharedTemplateDefinition.h" diff --git a/engine/shared/library/sharedTerrain/src/win32/FirstSharedTerrain.cpp b/engine/shared/library/sharedTerrain/src/win32/FirstSharedTerrain.cpp new file mode 100755 index 00000000..b8b5d9c2 --- /dev/null +++ b/engine/shared/library/sharedTerrain/src/win32/FirstSharedTerrain.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstTerrain.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedTerrain/FirstSharedTerrain.h" diff --git a/engine/shared/library/sharedThread/src/win32/FirstSharedThread.cpp b/engine/shared/library/sharedThread/src/win32/FirstSharedThread.cpp new file mode 100755 index 00000000..44b0e50c --- /dev/null +++ b/engine/shared/library/sharedThread/src/win32/FirstSharedThread.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstThread.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedThread/FirstSharedThread.h" diff --git a/engine/shared/library/sharedThread/src/win32/Thread.cpp b/engine/shared/library/sharedThread/src/win32/Thread.cpp new file mode 100755 index 00000000..2db63ced --- /dev/null +++ b/engine/shared/library/sharedThread/src/win32/Thread.cpp @@ -0,0 +1,179 @@ +// ====================================================================== +// +// Thread.cpp +// Acy Stapp +// +// Copyright6/19/2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedThread/FirstSharedThread.h" +#include "sharedThread/Thread.h" + +#include "sharedFoundation/ExitChain.h" +#include "sharedSynchronization/Mutex.h" +#include "sharedSynchronization/RecursiveMutex.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/PerThreadData.h" +#include + +#include + +class MainThread: public Thread +{ +public: + MainThread(const std::string &name): Thread(name) {} +protected: + void run() {} +private: + MainThread(const MainThread &o); + MainThread &operator =(const MainThread &o); +}; + +int Thread::implindex; +Thread * Thread::mainThread; + +void Thread::install() +{ + DEBUG_FATAL(mainThread, ("Thread::install: already installed")); + + implindex = TlsAlloc(); + mainThread = new MainThread("Main"); + mainThread->attach(); + + ExitChain::add(remove, "Thread::remove"); + + Mutex::install(); + RecursiveMutex::install(); + +} + +void Thread::remove() +{ + DEBUG_FATAL(!mainThread, ("Thread::remove: not installed")); + DEBUG_FATAL(mainThread->refcount > 1, ("Someone still holds the main thread")); + delete mainThread; // can't kill because it would terminate the app + TlsFree(implindex); + + Mutex::remove(); + RecursiveMutex::remove(); + + mainThread = 0; +} + +Thread::Thread() +: refcount(1), name(new std::string) +{ +} + +Thread::Thread(const std::string &i_name) +: refcount(1), name(new std::string(i_name)) +{ +} + +void Thread::start() +{ + handle = (HANDLE) _beginthreadex(0, 0, threadFunc, this, 0, &id); +} + +void Thread::attach() +{ + id = GetCurrentThreadId(); + HANDLE process = GetCurrentProcess(); + DuplicateHandle(process, GetCurrentThread(), process, &handle, 0, FALSE, DUPLICATE_SAME_ACCESS); + + TlsSetValue(implindex, this); + Os::setThreadName(id, name->c_str()); +} + +Thread::~Thread() +{ + CloseHandle(handle); + delete name; +} + +unsigned int Thread::threadFunc(void * i) +{ + Thread * impl = static_cast(i); + TlsSetValue(implindex, impl); + Os::setThreadName(impl->id, impl->name->c_str()); + PerThreadData::threadInstall(true); + impl->run(); + PerThreadData::threadRemove(); + impl->kill(); + return 0; +} + +void Thread::kill() +{ + void * h = getCurrentThread()->handle; + deref(); + if (this == getCurrentThread()) + { + _endthreadex(1); + } + else + { + TerminateThread(h, 1); + } +} + +void Thread::wait() +{ + WaitForSingleObject(handle, INFINITE); +} + +bool Thread::done() +{ + return WaitForSingleObject(handle, 0) == WAIT_OBJECT_0; // WAIT_TIMEOUT if the thread is still active +} + +void Thread::setName(const std::string &i_name) +{ + *name = i_name; + Os::setThreadName(id, name->c_str()); +} + +void Thread::setPriority(ePriority priority) +{ + static int priorities[] = + { + THREAD_PRIORITY_IDLE, + THREAD_PRIORITY_LOWEST, + THREAD_PRIORITY_NORMAL, + THREAD_PRIORITY_HIGHEST, + THREAD_PRIORITY_TIME_CRITICAL + }; + ::SetThreadPriority(handle, priorities[priority]); +} + +void Thread::suspend() +{ + ::SuspendThread(handle); +} + +void Thread::resume() +{ + ::ResumeThread(handle); +} + +const std::string &Thread::getName() const +{ + return *name; +} + +// Make sure the header-only files compile :) + +#if 0 + +#include "sharedSynchronization/CountingSemaphore.h" +#include "sharedSynchronization/BlockingPointer.h" +#include "sharedSynchronization/BlockingQueue.h" +#include "sharedSynchronization/WriteOnce.h" + +Mutex t; +BlockingQueue bqint(t, 0, 0); +BlockingPointer bpint(t, 0, 0); +WriteOnce woint; + +#endif \ No newline at end of file diff --git a/engine/shared/library/sharedThread/src/win32/Thread.h b/engine/shared/library/sharedThread/src/win32/Thread.h new file mode 100755 index 00000000..6d59c27d --- /dev/null +++ b/engine/shared/library/sharedThread/src/win32/Thread.h @@ -0,0 +1,94 @@ +// ====================================================================== +// +// Thread.h +// Acy Stapp +// +// Copyright 6/19/2001 Sony Online Entertainment +// +// ====================================================================== + +#ifndef INCLUDED_Thread_h +#define INCLUDED_Thread_h + +#include "sharedSynchronization/InterlockedInteger.h" + +template class TypedThreadHandle; + +class Thread +{ + // Visual studio fails to compile this valid code + // template friend TypedThreadHandle; +public: + static void install(); + static void remove(); + + Thread(); + Thread(const std::string &i_name); + + void kill(); + bool done(); + void wait(); + + enum ePriority + { + kIdle = 0, + kLow = 1, + kNormal = 2, + kHigh = 3, + kCritical = 4 + }; + void setPriority(ePriority priority); + void suspend(); + void resume(); + + const std::string &getName() const; + void setName(const std::string &i_name); + + static Thread * getCurrentThread(); + static Thread * getMainThread(); +protected: + virtual ~Thread(); + virtual void run()=0; + + HANDLE handle; + unsigned int id; + InterlockedInteger refcount; +public: // should be private:, see above + Thread(const Thread &o); + Thread &operator =(const Thread &o); + + void start(); + void attach(); // pick up the currently running thread + + void ref(); + void deref(); + + std::string *name; + + static int implindex; + static Thread * mainThread; + static unsigned int __stdcall threadFunc(void * data); +}; + +inline void Thread::ref() +{ + ++refcount; +} + +inline void Thread::deref() +{ + if (--refcount == 0) + delete this; +} + +inline Thread * Thread::getCurrentThread() +{ + return static_cast(TlsGetValue(implindex)); +} + +inline Thread * Thread::getMainThread() +{ + return mainThread; +} + +#endif \ No newline at end of file diff --git a/engine/shared/library/sharedUtility/src/win32/FirstSharedUtility.cpp b/engine/shared/library/sharedUtility/src/win32/FirstSharedUtility.cpp new file mode 100755 index 00000000..fde40d23 --- /dev/null +++ b/engine/shared/library/sharedUtility/src/win32/FirstSharedUtility.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstUtility.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "sharedUtility/FirstSharedUtility.h" diff --git a/engine/shared/library/sharedXml/src/win32/core/FirstSharedXml.cpp b/engine/shared/library/sharedXml/src/win32/core/FirstSharedXml.cpp new file mode 100755 index 00000000..0d9c1ae2 --- /dev/null +++ b/engine/shared/library/sharedXml/src/win32/core/FirstSharedXml.cpp @@ -0,0 +1,11 @@ +// ====================================================================== +// +// FirstSharedXml.cpp +// Copyright 2004 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "sharedXml/FirstSharedXml.h" + +// ====================================================================== diff --git a/external/3rd/library/platform/utils/Base/win32/Archive.h b/external/3rd/library/platform/utils/Base/win32/Archive.h new file mode 100755 index 00000000..30ddce43 --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Archive.h @@ -0,0 +1,42 @@ +#ifndef BASE_WIN32_ARCHIVE_H +#define BASE_WIN32_ARCHIVE_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + +#ifdef PACK_BIG_ENDIAN + + inline double byteSwap(double value) { byteReverse64(&value); return value; } + inline float byteSwap(float value) { byteReverse32(&value); return value; } + inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; } + inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; } + inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; } + inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; } + inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; } + inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; } + +#else + + inline double byteSwap(double value) { return value; } + inline float byteSwap(float value) { return value; } + inline uint64 byteSwap(uint64 value) { return value; } + inline int64 byteSwap(int64 value) { return value; } + inline uint32 byteSwap(uint32 value) { return value; } + inline int32 byteSwap(int32 value) { return value; } + inline uint16 byteSwap(uint16 value) { return value; } + inline int16 byteSwap(int16 value) { return value; } + +#endif + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif diff --git a/external/3rd/library/platform/utils/Base/win32/BlockAllocator.cpp b/external/3rd/library/platform/utils/Base/win32/BlockAllocator.cpp new file mode 100755 index 00000000..029946b4 --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/BlockAllocator.cpp @@ -0,0 +1,112 @@ +#include "../BlockAllocator.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + BlockAllocator::BlockAllocator() + { + for(unsigned i = 0; i < 31; i++) + { + m_blocks[i] = NULL; + } + } + + BlockAllocator::~BlockAllocator() + { + // free all allocated memory blocks + for(unsigned i = 0; i < 31; i++) + { + while(m_blocks[i] != NULL) + { + uintptr_t *tmp = m_blocks[i]; + m_blocks[i] = (uintptr_t *)*m_blocks[i]; + free(tmp); + } + } + } + +// Allocate a block that is the next power of two greater than the # of bytes passed. +// 33 bytes yields a 64 byte block of memory and so forth. + + void *BlockAllocator::getBlock(unsigned bytes) + { + unsigned accum = 16, bits = 16; + uintptr_t *handle = NULL; + + // Perform a binary search looking for the highest bit. + + while(bits != 0) + { + // If bytes is less than the bit we're testing for, subtract half + // from the bit value and repeat + if(bytes < (unsigned)(1 << accum)) + { + bits /= 2; + accum -= bits; + } + // If bytes is greater than the bit we're testing for, add half + // from the but value and repeat + else if(bytes > (unsigned)(1 << accum)) + { + bits /= 2; + accum += bits; + } + // Got lucky and hit the value dead on + else + { + break; + } + } + // At this point accum contains the most significant bit index, increment + accum++; + if(accum < 2) + { + accum = 2; + } + + // Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front + // The first integer is the address of the next block of memory when the block is in the allocator + // The second integer is the bit length of the block + // Memory is allocated on 4 byte boundaries to sidestep byte alignment problems + + + // Check if the allocator already has a block of that size + if(m_blocks[accum] == 0) + { + // remove the pre allocated block from the linked list + handle = (uintptr_t *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned)); + handle[1] = accum; + handle[0] = 0; + } + else + { + // Allocate a new block + handle = m_blocks[accum]; + m_blocks[accum] = (uintptr_t *)handle[0]; + handle[0] = 0; + } + // return a pointer that skips over the header used for the allocator's purposes + return(handle + 2); + } + + void BlockAllocator::returnBlock(unsigned *handle) + { + // C++ allows for safe deletion of a NULL pointer + if(handle) + { + // Update the allocator linked list, insert this entry at the head + *(handle - 2) = (uintptr_t)m_blocks[*(handle - 1)]; + // Add this entry to the proper linked list node + m_blocks[*(handle - 1)] = (handle - 2); + } + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + diff --git a/external/3rd/library/platform/utils/Base/win32/Event.cpp b/external/3rd/library/platform/utils/Base/win32/Event.cpp new file mode 100755 index 00000000..12ee8fe7 --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Event.cpp @@ -0,0 +1,44 @@ +//////////////////////////////////////// +// Event.cpp +// +// Purpose: +// 1. Implementation of the CEvent class. +// +// Revisions: +// 07/10/2001 Created +// + + +#if !defined(_MT) +# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_MT)" ) +#else + +#include "Event.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + CEvent::CEvent() + { + mEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + } + + CEvent::~CEvent() + { + if (mEvent) + CloseHandle(mEvent); + } + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // #if defined(_MT) + diff --git a/external/3rd/library/platform/utils/Base/win32/Event.h b/external/3rd/library/platform/utils/Base/win32/Event.h new file mode 100755 index 00000000..5d2bc712 --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Event.h @@ -0,0 +1,92 @@ +//////////////////////////////////////// +// Event.h +// +// Purpose: +// 1. Declair the CEvent class that encapsulates the functionality of a +// single-locking semaphore. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_EVENT_H +#define BASE_WIN32_EVENT_H + +#if defined(_MT) + + + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CEvent + // + // Purpose: + // Encapsulates the functionality of a singal-locking semaphore. + // This class is valuable for thread syncronization when a thead's + // execution needs to be dependent upon another thread. + // + // Public Methods: + // Signal() : Signals a thread that has called Wait() so that it can + // continue execution. This function returns true if the waiting + // thread was signalled successfully, otherwise false is returned. + // Wait() : Halts the calling thread's execution indefinately until + // a Singal() call is made by an external thread. If the thread is + // successfully signalled, the function returns eWAIT_SIGNAL. If + // timeout period expires without a signal, eWAIT_TIMEOUT is returned. + // If the function fails, eWAIT_ERROR is returned. + // + class CEvent + { + public: + CEvent(); + virtual ~CEvent(); + + bool Signal(); + int32 Wait(uint32 timeout = 0); + + public: + enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT }; + private: + HANDLE mEvent; + }; + + inline bool CEvent::Signal() + { + if (mEvent) + return SetEvent(mEvent)!=0; + + return false; + } + + inline int32 CEvent::Wait(uint32 timeout) + { + if (!mEvent) + return CEvent::eWAIT_ERROR; + + DWORD result = WaitForSingleObjectEx(mEvent, timeout ? timeout : INFINITE, FALSE); + if (result == WAIT_OBJECT_0) + return CEvent::eWAIT_SIGNAL; + else if (result == WAIT_TIMEOUT) + return CEvent::eWAIT_TIMEOUT; + else + return CEvent::eWAIT_ERROR; + } + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif // #if defined(_MT) + + +#endif // BASE_WIN32_EVENT_H diff --git a/external/3rd/library/platform/utils/Base/win32/File.cpp b/external/3rd/library/platform/utils/Base/win32/File.cpp new file mode 100755 index 00000000..e6b6ee23 --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/File.cpp @@ -0,0 +1,19 @@ +// File.cpp: implementation of the CFile class. +// +////////////////////////////////////////////////////////////////////// + +#include "File.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CFile::CFile(const char *) +{ + +} + +CFile::~CFile() +{ + +} diff --git a/external/3rd/library/platform/utils/Base/win32/File.h b/external/3rd/library/platform/utils/Base/win32/File.h new file mode 100755 index 00000000..7965427a --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/File.h @@ -0,0 +1,22 @@ +// File.h: interface for the CFile class. +// +////////////////////////////////////////////////////////////////////// + +#ifndef BASE_FILE_H +#define BASE_FILE_H + +#include + +class CFile +{ + public: + CFile(const char *); + virtual ~CFile(); + + bool IsOpen(); + + private: + FILE* mFileHandle; +}; + +#endif // BASE_FILE_H diff --git a/external/3rd/library/platform/utils/Base/win32/Logger.cpp b/external/3rd/library/platform/utils/Base/win32/Logger.cpp new file mode 100755 index 00000000..cf2afcf6 --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Logger.cpp @@ -0,0 +1,385 @@ +#include "../Logger.h" +#include "Mutex.h" + +using namespace std; + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + +const char file_sep = '\\'; + +Logger::Logger(const char *prefix, int level, unsigned size, bool rollDate) +: m_defaultLevel(level), m_defaultSize(size), m_dirPrefix(prefix), m_rollDate(rollDate) +{ + char buf[1024]; + FILE *logDir = NULL; + + logDir = fopen(m_dirPrefix.c_str(), "r+"); + if(errno == ENOENT) + { + cmkdir(m_dirPrefix.c_str(), 0755); + } + else if(logDir != NULL) + { + fclose(logDir); + } + + tm now; + time_t t = time(NULL); + memcpy(&now, localtime(&t), sizeof(tm)); + memcpy(&m_lastDateTime, &now, sizeof(tm)); + if(m_rollDate) + { + sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100)); + } + else + { + sprintf(buf, "%s", m_dirPrefix.c_str()); + } + + logDir = fopen(buf, "r+"); + if(errno == ENOENT) + { + cmkdir(buf, 0755); + } + else if(logDir != NULL) + { + fclose(logDir); + } + m_logPrefix = buf; +} + +Logger::~Logger() +{ + map::iterator iter; + for(iter = m_logTable.begin(); iter != m_logTable.end(); ++iter) + { + log((*iter).first, LOG_FILEONLY, "---=== Log Stopped ===---"); + fflush((*iter).second->file); + fclose((*iter).second->file); + delete((*iter).second); + + } + m_logTable.clear(); +} + +void Logger::flush(unsigned logenum) +{ + map::iterator iter = m_logTable.find(logenum); + + if(iter != m_logTable.end()) + { + LogInfo *info = (*iter).second; + fflush(info->file); + info->used = 0; + } +} + +void Logger::flushAll() +{ + map::iterator iter; + + for(iter = m_logTable.begin(); iter != m_logTable.end(); ++iter) + { + LogInfo *info = (*iter).second; + fflush(info->file); + info->used = 0; + } +} + +void Logger::addLog(const char *id, unsigned logenum, int level, unsigned size) +{ + LogInfo *newLog = new LogInfo; + newLog->filename = m_logPrefix + file_sep + id + ".log"; + newLog->name = id; + newLog->used = 0; + newLog->max = size; + newLog->last = 0; + newLog->level = level; + + m_logTable.insert(pair(logenum, newLog)); + + if(strcmp("stdout", id) == 0) + { + newLog->file = stdout; + } + else if(strcmp("stderr", id) == 0) + { + newLog->file = stderr; + } + else + { + newLog->file = fopen(newLog->filename.c_str(), "a+"); + } + log(logenum, LOG_FILEONLY, "---=== Log Started ===---"); +} + +void Logger::addLog(const char *id, unsigned logenum) +{ + LogInfo *newLog = new LogInfo; + newLog->filename = m_logPrefix + file_sep + id + ".log"; + newLog->name = id; + newLog->used = 0; + newLog->max = m_defaultSize; + newLog->last = 0; + newLog->level = m_defaultLevel; + m_logTable.insert(pair(logenum, newLog)); + + if(strcmp("stdout", id) == 0) + { + newLog->file = stdout; + } + else if(strcmp("stderr", id) == 0) + { + newLog->file = stderr; + } + else + { + newLog->file = fopen(newLog->filename.c_str(), "a+"); + } + log(logenum, LOG_FILEONLY, "---=== Log Started ===---"); + +} + +void Logger::updateLog(unsigned logenum, int level, unsigned size) +{ + map::iterator iter = m_logTable.find(logenum); + + if(iter != m_logTable.end()) + { + (*iter).second->level = level; + (*iter).second->max = size; + } +} + +void Logger::removeLog(unsigned logenum) +{ + map::iterator iter = m_logTable.find(logenum); + + if(iter != m_logTable.end()) + { + log((*iter).first, LOG_FILEONLY, "---=== Log Stopped ===---"); + fflush((*iter).second->file); + fclose((*iter).second->file); + delete((*iter).second); + } +} + +void Logger::logSimple(unsigned logenum, int level, const char *message) +{ + map::iterator iter = m_logTable.find(logenum); + char dateBuffer[256]; + + if(iter == m_logTable.end()) + { + return; + } + time_t t = time(NULL); + LogInfo *info = (*iter).second; + if(level >= info->level) + { + return; + } + if(info->last != t) + { + memcpy(&info->ts, localtime(&t), sizeof(tm)); + info->last = t; + } + + if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday) + { +#if defined(_MT) + rLock.Lock(); +#endif + if(info->ts.tm_mday != m_lastDateTime.tm_mday) + { + memcpy(&m_lastDateTime, &info->ts, sizeof(tm)); + rollDate(t); + } +#if defined(_MT) + rLock.Unlock(); +#endif + } + if(iter != m_logTable.end()) + { + if(info->max > 0) + { + sprintf(dateBuffer, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] " , (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec); + info->used += fputs(dateBuffer, info->file); + info->used += fputs(message, info->file); + fputc('\n', info->file); + if(info->used > info->max) + { + fflush(info->file); + info->used = 0; + } + } + else + { + sprintf(dateBuffer, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] " , (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec); + fputs(dateBuffer, info->file); + fputs(message, info->file); + fputc('\n', info->file); + fflush(info->file); + } + } +} + +void Logger::log(unsigned logenum, int level, const char *message, ...) +{ + char buf[2048]; + char dateBuffer[256]; + va_list varg; + va_start(varg, message); + _vsnprintf(buf, 2047, message, varg); + buf[2047] = 0; + va_end(varg); + + map::iterator iter = m_logTable.find(logenum); + if(iter == m_logTable.end()) + { + return; + } + time_t t = time(NULL); + LogInfo *info = (*iter).second; + + if(level >= info->level) + { + return; + } + + if(level == LOG_FILEONLY && ((info->file == stderr) || (info->file == stdout))) + { + return; + } + if(info->last != t) + { + memcpy(&info->ts, localtime(&t), sizeof(tm)); + info->last = t; + } + if(m_rollDate && info->ts.tm_mday != m_lastDateTime.tm_mday) + { +#if defined(_MT) + rLock.Lock(); +#endif + if(info->ts.tm_mday != m_lastDateTime.tm_mday) + { + memcpy(&m_lastDateTime, &info->ts, sizeof(tm)); + rollDate(t); + } +#if defined(_MT) + rLock.Unlock(); +#endif + } + + if(iter != m_logTable.end()) + { + if(info->max > 0) + { + sprintf(dateBuffer, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] " , (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec); + info->used += fputs(dateBuffer, info->file); + info->used += fputs(buf, info->file); + fputc('\n', info->file); + if(info->used > info->max) + { + fflush(info->file); + info->used = 0; + } + } + else + { + sprintf(dateBuffer, "[%2.2d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d] " , (info->ts.tm_mon + 1), info->ts.tm_mday, (info->ts.tm_year % 100), info->ts.tm_hour, info->ts.tm_min, info->ts.tm_sec); + info->used += fputs(dateBuffer, info->file); + info->used += fputs(buf, info->file); + fputc('\n', info->file); + fflush(info->file); + } + } +} + +void Logger::rollDate(time_t t) +{ + char buf[80]; + FILE *logDir = NULL; + + logDir = fopen(m_dirPrefix.c_str(), "r+"); + if(errno == ENOENT) + { + cmkdir(m_dirPrefix.c_str(), 0755); + } + else if(logDir != NULL) + { + fclose(logDir); + } + + tm now; + memcpy(&now, localtime(&t), sizeof(tm)); + + sprintf(buf, "%s%c%2.2d-%2.2d-%2.2d", m_dirPrefix.c_str(), file_sep, (now.tm_mon + 1), now.tm_mday, (now.tm_year % 100)); + logDir = fopen(buf, "r+"); + + if(errno == ENOENT) + { + cmkdir(buf, 0755); + } + else if(logDir != NULL) + { + fclose(logDir); + } + m_logPrefix = buf; + + map::iterator iter; + for(iter = m_logTable.begin(); iter != m_logTable.end(); ++iter) + { + (*iter).second->filename = m_logPrefix + file_sep + (*iter).second->name.c_str() + ".log"; + fflush((*iter).second->file); + fclose((*iter).second->file); + (*iter).second->file = fopen((*iter).second->filename.c_str(), "a+"); + memcpy(&((*iter).second->ts), &now, sizeof(tm)); + } +} + +// mkdir function that creates intermediate directories +void Logger::cmkdir(const char *dir, int mode) +{ + char dirbuf[128]; + strncpy(dirbuf, dir, 127); + dirbuf[127] = 0; + char *j = dirbuf, *i = dirbuf; + int handle; + + while(*i) + { + if(*i == file_sep) + { + (*i) = 0; + handle = _open(j, O_EXCL); + + if((handle > 0) || (errno != EISDIR && errno != ENOENT && errno != EACCES)) + { + perror("Logger::cmkdir():"); + abort(); + } + _mkdir(j); + _close(handle); + (*i) = file_sep; + } + else if(*(i + 1) == 0) + { + _mkdir(j); + } + i++; + } +} + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + diff --git a/external/3rd/library/platform/utils/Base/win32/Mutex.cpp b/external/3rd/library/platform/utils/Base/win32/Mutex.cpp new file mode 100755 index 00000000..482481e8 --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Mutex.cpp @@ -0,0 +1,40 @@ +//////////////////////////////////////// +// Mutex.cpp +// +// Purpose: +// 1. Implementation of the CMutex class. +// +// Revisions: +// 07/10/2001 Created +// +#if !defined(_MT) +# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_MT)" ) +#else + +#include "Mutex.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +CMutex::CMutex() + { + InitializeCriticalSection(&mCriticalSection); + } + +CMutex::~CMutex() + { + DeleteCriticalSection(&mCriticalSection); + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // #if defined(_MT) + diff --git a/external/3rd/library/platform/utils/Base/win32/Mutex.h b/external/3rd/library/platform/utils/Base/win32/Mutex.h new file mode 100755 index 00000000..66e1c08b --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Mutex.h @@ -0,0 +1,73 @@ +//////////////////////////////////////// +// Mutex.h +// +// Purpose: +// 1. Declair the CMutex class that encapsulates the functionality of a +// mutually-exclusive device. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_MUTEX_H +#define BASE_WIN32_MUTEX_H + +#if defined (_MT) + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CMutex + // + // Purpose: + // Encapsulates the functionality of a mutually-exclusive device. + // This class is valuable for protecting against race conditions + // within threaded applications. The CMutex class can be used to + // only allow a single thread to run within a specified code + // segment at a time. + // + // Public Methods: + // Lock() : Locks the mutex. If the mutex is already locked, the + // operating system will block the calling thread until another + // thread has unlocked the mutex. + // Unlock() : Unlocks the mutex. + // + class CMutex + { + public: + CMutex(); + ~CMutex(); + + void Lock(); + void Unlock(); + private: + CRITICAL_SECTION mCriticalSection; + }; + + inline void CMutex::Lock() + { + EnterCriticalSection(&mCriticalSection); + } + + inline void CMutex::Unlock() + { + LeaveCriticalSection(&mCriticalSection); + } + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // #if defined(_MT) + +#endif // BASE_WIN32_MUTEX_H \ No newline at end of file diff --git a/external/3rd/library/platform/utils/Base/win32/Platform.cpp b/external/3rd/library/platform/utils/Base/win32/Platform.cpp new file mode 100755 index 00000000..3b52563e --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Platform.cpp @@ -0,0 +1,31 @@ +//////////////////////////////////////// +// Platform.cpp +// +// Purpose: +// 1. Implementation of the global functionality declaired in Platform.h. +// +// Revisions: +// 07/10/2001 Created +// + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + + CTimer::CTimer() : + mTimer(0) + { + } + + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/external/3rd/library/platform/utils/Base/win32/Platform.h b/external/3rd/library/platform/utils/Base/win32/Platform.h new file mode 100755 index 00000000..aaee37b7 --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Platform.h @@ -0,0 +1,98 @@ +//////////////////////////////////////// +// Platform.h +// +// Purpose: +// 1. Include relevent system headers that are platform specific. +// 2. Declair global platform specific functionality. +// 3. Include primative type definitions +// +// Global Functions: +// getTimer() : Return the current high resolution clock count. +// getTimerFrequency() : Return the frequency of the high resolution clock. +// sleep() : Voluntarily relinquish timeslice of the calling thread for a +// specified number of milliseconds. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_PLATFORM_H +#define BASE_WIN32_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Types.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + uint64 getTimer(void); + uint64 getTimerFrequency(void); + + inline uint64 getTimer(void) + { + uint64 result; + if (!QueryPerformanceCounter(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline uint64 getTimerFrequency(void) + { + uint64 result; + if (!QueryPerformanceFrequency(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline void sleep(uint32 ms) + { + Sleep(ms); + } + + + class CTimer + { + public: + CTimer(); + + void Set(uint32 seconds); + void Signal(); + bool Expired(); + + private: + uint32 mTimer; + }; + + inline void CTimer::Set(uint32 interval) + { + mTimer = (uint32)time(0) + interval; + } + + inline void CTimer::Signal() + { + mTimer = 0; + } + + inline bool CTimer::Expired() + { + return (mTimer <= (uint32)time(0)); + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif BASE_WIN32_PLATFORM_H \ No newline at end of file diff --git a/external/3rd/library/platform/utils/Base/win32/Thread.cpp b/external/3rd/library/platform/utils/Base/win32/Thread.cpp new file mode 100755 index 00000000..2692e88e --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Thread.cpp @@ -0,0 +1,279 @@ +//////////////////////////////////////// +// Thread.cpp +// +// Purpose: +// 1. Implementation of the CThread class. +// +// Revisions: +// 07/10/2001 Created +// + + +#pragma warning ( disable: 4786 ) + + +#if !defined(_MT) +# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_MT)" ) +#else + +#include +#include +#include "Thread.h" + +using namespace std; + + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + void threadProc(void *threadPtr) + { + CThread &thread = *((CThread*)threadPtr); + thread.mThreadActive = true; + thread.ThreadProc(); + thread.mThreadActive = false; + } + + CThread::CThread() + { + mThreadID = 0; + mThreadActive = false; + mThreadContinue = false; + } + + CThread::~CThread() + { + StopThread(); + } + + void CThread::StartThread() + { + mThreadContinue = true; + mThreadID = _beginthread(threadProc,0,this); + while (!IsThreadActive()) + Base::sleep(1); + } + + int32 CThread::StopThread(int32 timeout) + { + timeout += int(time(0)); + + mThreadContinue = false; + while (mThreadActive && time(0)OnStartup(this); + while (mThreadContinue) + { + mParent->OnIdle(this); + mSemaphore.Wait(mParent->GetTimeOut()*1000); + + if (mFunction) + { + mFunction(mArgument); + mArgument = NULL; + mFunction = NULL; + } + else if (mParent->OnDestory(this)) + mThreadContinue = false; + } + } + + +//////////////////////////////////////////////////////////////////////////////// + + + CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) : + mMutex(), + mIdleMember(), + mBusyMember(), + mNullMember(), + mThreadCount(0), + mMaxThreads(maxThreads), + mMinThreads(minThreads), + mTimeOut(timeout) + { + if (mMaxThreads == 0) mMaxThreads = 1; + if (mMinThreads == 0) mMinThreads = 1; + if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads; + + for (uint32 i=0; i::iterator setIterator; + + //////////////////////////////////////// + // (1) Destory all busy member threads + mMutex.Lock(); + setIterator = mBusyMember.begin(); + while (setIterator != mBusyMember.end()) + (*setIterator++)->Destroy(); + mMutex.Unlock(); + + //////////////////////////////////////// + // (2) Destory all idle member threads + while (mThreadCount) + { + mMutex.Lock(); + setIterator = mIdleMember.begin(); + while (setIterator != mIdleMember.end()) + (*setIterator++)->Destroy(); + mMutex.Unlock(); + + sleep(1); + } + + //////////////////////////////////////// + // (3) Delete the null member threads + mMutex.Lock(); + while (!mNullMember.empty()) + { + delete mNullMember.front(); + mNullMember.pop_front(); + } + mMutex.Unlock(); + } + + bool CThreadPool::Execute(void( __cdecl *function )( void * ), void * arg) + { + mMutex.Lock(); + + //////////////////////////////////////// + // (1) If no idle members, return false to indicate that no threads + // were available. If the thread count is below the max, create + // a new thread. + if (mIdleMember.empty()) + { + if (mThreadCount < mMaxThreads) + new CMember(this); + mMutex.Unlock(); + return false; + } + + //////////////////////////////////////// + // (2) Delete any null member threads. + while (!mNullMember.empty()) + { + delete mNullMember.front(); + mNullMember.pop_front(); + } + + //////////////////////////////////////// + // (3) Move the first idle thread to the busy set and signal the + // thread to execute the specified function. + CMember * member = *(mIdleMember.begin()); + mIdleMember.erase(member); + mBusyMember.insert(member); + member->Execute(function,arg); + + mMutex.Unlock(); + return true; + } + + uint32 CThreadPool::GetTimeOut() + { + return mTimeOut; + } + + void CThreadPool::OnStartup(CMember * member) + { + mMutex.Lock(); + + mThreadCount++; + mIdleMember.insert(member); + + mMutex.Unlock(); + } + + void CThreadPool::OnIdle(CMember * member) + { + mMutex.Lock(); + + mBusyMember.erase(member); + mIdleMember.insert(member); + + mMutex.Unlock(); + } + + bool CThreadPool::OnDestory(CMember * member) + { + set::iterator setIterator; + + mMutex.Lock(); + + bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end(); + if (result) + { + mNullMember.push_back(member); + mIdleMember.erase(setIterator); + mThreadCount--; + } + + mMutex.Unlock(); + + return result; + } + + +//////////////////////////////////////////////////////////////////////////////// + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // #if defined(_MT) + diff --git a/external/3rd/library/platform/utils/Base/win32/Thread.h b/external/3rd/library/platform/utils/Base/win32/Thread.h new file mode 100755 index 00000000..a8338917 --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Thread.h @@ -0,0 +1,144 @@ +//////////////////////////////////////// +// Thread.h +// +// Purpose: +// 1. Declair the CThread class that encapsulates threading functionality. +// This abstract base class in intended to be used to encapsulate +// individual tasks that require threading in derived classes. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_THREAD_H +#define BASE_WIN32_THREAD_H + +#if defined(_MT) + +#pragma warning( disable : 4786) + +#include +#include +#include "Platform.h" +#include "Mutex.h" +#include "Event.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CThread + // + // Purpose: + // Encapsulates threading functionality. Creating classes derived + // from CThread provides an easy way to encapsulate tasks that require + // their own thread. + // + // Public Methods: + // StartThread() : Creates the low-level thread handle and begins executing + // the CThread::ThreadProc() function within the new thread. + // StopThread() : Signals the ThreadProc() function to stop executing using + // the mThreadContinue member variable, and waits for the ThreadProc() + // function to exit. By default, the function will block for a maximum + // of 5 seconds before exiting without the thread halting. + // IsThreadActive() : Returns true if the physical thread is still executing + // within the ThreadProc() function, otherwise it returns false. + // ThreadProc() : Pure-virtual function that will be executed when the StartThread() + // function is called. Derived classes must implement this function. The + // mThreadContinue member variable should be used internal the the ThreadProc() + // function to indicate whether it should continue executing or exit. + // Protected Attributes: + // mThreadContinue : Boolean value indicating to the ThreadProc() function + // whether to continue executing or to exit. If mThreadContinue is true, + // ThreadProc() should continue, otherwise ThreadProc() should exit. It + // left up to the derived class to implement a ThreadProc() function that + // uses the mThreadContinue member. + // + // + class CThread + { + friend void threadProc(void *); + + public: + enum { eSTOP_SUCCESS, eSTOP_TIMEOUT }; + public: + CThread(); + virtual ~CThread(); + + void StartThread(); + int32 StopThread(int32 timeout=5); + bool IsThreadActive() { return mThreadActive; } + + protected: + virtual void ThreadProc() = 0; + + protected: + bool mThreadContinue; + private: + uint32 mThreadID; + bool mThreadActive; + }; + + + class CThreadPool + { + private: + class CMember : public CThread + { + public: + CMember(CThreadPool * parent); + virtual ~CMember(); + + bool Execute(void( __cdecl *function )( void * ), void * arg); + void Destroy(); + + protected: + virtual void ThreadProc(); + + private: + CThreadPool * mParent; + void( __cdecl * mFunction )( void * ); + void * mArgument; + CEvent mSemaphore; + }; + friend class CMember; + + public: + CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60); + ~CThreadPool(); + + bool Execute(void( __cdecl *function )( void * ), void * arg); + + private: + uint32 GetTimeOut(); + void OnStartup(CMember * member); + void OnIdle(CMember * member); + bool OnDestory(CMember * member); + + private: + CMutex mMutex; + std::set mIdleMember; + std::set mBusyMember; + std::list mNullMember; + uint32 mThreadCount; + + uint32 mMaxThreads; + uint32 mMinThreads; + uint32 mTimeOut; + }; + + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // #if defined(_MT) + +#endif // BASE_WIN32_THREAD_H diff --git a/external/3rd/library/platform/utils/Base/win32/Types.h b/external/3rd/library/platform/utils/Base/win32/Types.h new file mode 100755 index 00000000..0c64cb2c --- /dev/null +++ b/external/3rd/library/platform/utils/Base/win32/Types.h @@ -0,0 +1,42 @@ +//////////////////////////////////////// +// Types.h +// +// Purpose: +// 1. Define integer types that are unambiguous with respect to size +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_TYPES_H +#define BASE_WIN32_TYPES_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN 0x80000000 +#define UINT32_MAX 0xFFFFFFFF + +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; + +typedef int int32; +typedef unsigned uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // BASE_WIN32_TYPES_H + diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Archive.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Archive.h new file mode 100755 index 00000000..30ddce43 --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Archive.h @@ -0,0 +1,42 @@ +#ifndef BASE_WIN32_ARCHIVE_H +#define BASE_WIN32_ARCHIVE_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + +#ifdef PACK_BIG_ENDIAN + + inline double byteSwap(double value) { byteReverse64(&value); return value; } + inline float byteSwap(float value) { byteReverse32(&value); return value; } + inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; } + inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; } + inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; } + inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; } + inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; } + inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; } + +#else + + inline double byteSwap(double value) { return value; } + inline float byteSwap(float value) { return value; } + inline uint64 byteSwap(uint64 value) { return value; } + inline int64 byteSwap(int64 value) { return value; } + inline uint32 byteSwap(uint32 value) { return value; } + inline int32 byteSwap(int32 value) { return value; } + inline uint16 byteSwap(uint16 value) { return value; } + inline int16 byteSwap(int16 value) { return value; } + +#endif + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/BlockAllocator.cpp b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/BlockAllocator.cpp new file mode 100755 index 00000000..927c5aef --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/BlockAllocator.cpp @@ -0,0 +1,112 @@ +#include "../BlockAllocator.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + BlockAllocator::BlockAllocator() + { + for(unsigned i = 0; i < 31; i++) + { + m_blocks[i] = NULL; + } + } + + BlockAllocator::~BlockAllocator() + { + // free all allocated memory blocks + for(unsigned i = 0; i < 31; i++) + { + while(m_blocks[i] != NULL) + { + uintptr_t *tmp = m_blocks[i]; + m_blocks[i] = (uintptr_t *)*m_blocks[i]; + free(tmp); + } + } + } + +// Allocate a block that is the next power of two greater than the # of bytes passed. +// 33 bytes yields a 64 byte block of memory and so forth. + + void *BlockAllocator::getBlock(unsigned bytes) + { + unsigned accum = 16, bits = 16; + unsigned *handle = NULL; + + // Perform a binary search looking for the highest bit. + + while(bits != 0) + { + // If bytes is less than the bit we're testing for, subtract half + // from the bit value and repeat + if(bytes < (unsigned)(1 << accum)) + { + bits /= 2; + accum -= bits; + } + // If bytes is greater than the bit we're testing for, add half + // from the but value and repeat + else if(bytes > (unsigned)(1 << accum)) + { + bits /= 2; + accum += bits; + } + // Got lucky and hit the value dead on + else + { + break; + } + } + // At this point accum contains the most significant bit index, increment + accum++; + if(accum < 2) + { + accum = 2; + } + + // Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front + // The first integer is the address of the next block of memory when the block is in the allocator + // The second integer is the bit length of the block + // Memory is allocated on 4 byte boundaries to sidestep byte alignment problems + + + // Check if the allocator already has a block of that size + if(m_blocks[accum] == 0) + { + // remove the pre allocated block from the linked list + handle = (uintptr_t *)calloc(((1 << accum) / 4) + 2, sizeof(uintptr_t)); + handle[1] = accum; + handle[0] = 0; + } + else + { + // Allocate a new block + handle = m_blocks[accum]; + m_blocks[accum] = (uintptr_t *)handle[0]; + handle[0] = 0; + } + // return a pointer that skips over the header used for the allocator's purposes + return(handle + 2); + } + + void BlockAllocator::returnBlock(uintptr_t *handle) + { + // C++ allows for safe deletion of a NULL pointer + if(handle) + { + // Update the allocator linked list, insert this entry at the head + *(handle - 2) = (uintptr_t)m_blocks[*(handle - 1)]; + // Add this entry to the proper linked list node + m_blocks[*(handle - 1)] = (handle - 2); + } + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Event.cpp b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Event.cpp new file mode 100755 index 00000000..12ee8fe7 --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Event.cpp @@ -0,0 +1,44 @@ +//////////////////////////////////////// +// Event.cpp +// +// Purpose: +// 1. Implementation of the CEvent class. +// +// Revisions: +// 07/10/2001 Created +// + + +#if !defined(_MT) +# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_MT)" ) +#else + +#include "Event.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + CEvent::CEvent() + { + mEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + } + + CEvent::~CEvent() + { + if (mEvent) + CloseHandle(mEvent); + } + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // #if defined(_MT) + diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Event.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Event.h new file mode 100755 index 00000000..5d2bc712 --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Event.h @@ -0,0 +1,92 @@ +//////////////////////////////////////// +// Event.h +// +// Purpose: +// 1. Declair the CEvent class that encapsulates the functionality of a +// single-locking semaphore. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_EVENT_H +#define BASE_WIN32_EVENT_H + +#if defined(_MT) + + + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CEvent + // + // Purpose: + // Encapsulates the functionality of a singal-locking semaphore. + // This class is valuable for thread syncronization when a thead's + // execution needs to be dependent upon another thread. + // + // Public Methods: + // Signal() : Signals a thread that has called Wait() so that it can + // continue execution. This function returns true if the waiting + // thread was signalled successfully, otherwise false is returned. + // Wait() : Halts the calling thread's execution indefinately until + // a Singal() call is made by an external thread. If the thread is + // successfully signalled, the function returns eWAIT_SIGNAL. If + // timeout period expires without a signal, eWAIT_TIMEOUT is returned. + // If the function fails, eWAIT_ERROR is returned. + // + class CEvent + { + public: + CEvent(); + virtual ~CEvent(); + + bool Signal(); + int32 Wait(uint32 timeout = 0); + + public: + enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT }; + private: + HANDLE mEvent; + }; + + inline bool CEvent::Signal() + { + if (mEvent) + return SetEvent(mEvent)!=0; + + return false; + } + + inline int32 CEvent::Wait(uint32 timeout) + { + if (!mEvent) + return CEvent::eWAIT_ERROR; + + DWORD result = WaitForSingleObjectEx(mEvent, timeout ? timeout : INFINITE, FALSE); + if (result == WAIT_OBJECT_0) + return CEvent::eWAIT_SIGNAL; + else if (result == WAIT_TIMEOUT) + return CEvent::eWAIT_TIMEOUT; + else + return CEvent::eWAIT_ERROR; + } + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif // #if defined(_MT) + + +#endif // BASE_WIN32_EVENT_H diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/File.cpp b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/File.cpp new file mode 100755 index 00000000..e6b6ee23 --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/File.cpp @@ -0,0 +1,19 @@ +// File.cpp: implementation of the CFile class. +// +////////////////////////////////////////////////////////////////////// + +#include "File.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CFile::CFile(const char *) +{ + +} + +CFile::~CFile() +{ + +} diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/File.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/File.h new file mode 100755 index 00000000..7965427a --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/File.h @@ -0,0 +1,22 @@ +// File.h: interface for the CFile class. +// +////////////////////////////////////////////////////////////////////// + +#ifndef BASE_FILE_H +#define BASE_FILE_H + +#include + +class CFile +{ + public: + CFile(const char *); + virtual ~CFile(); + + bool IsOpen(); + + private: + FILE* mFileHandle; +}; + +#endif // BASE_FILE_H diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Mutex.cpp b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Mutex.cpp new file mode 100755 index 00000000..482481e8 --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Mutex.cpp @@ -0,0 +1,40 @@ +//////////////////////////////////////// +// Mutex.cpp +// +// Purpose: +// 1. Implementation of the CMutex class. +// +// Revisions: +// 07/10/2001 Created +// +#if !defined(_MT) +# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_MT)" ) +#else + +#include "Mutex.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +CMutex::CMutex() + { + InitializeCriticalSection(&mCriticalSection); + } + +CMutex::~CMutex() + { + DeleteCriticalSection(&mCriticalSection); + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // #if defined(_MT) + diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Mutex.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Mutex.h new file mode 100755 index 00000000..66e1c08b --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Mutex.h @@ -0,0 +1,73 @@ +//////////////////////////////////////// +// Mutex.h +// +// Purpose: +// 1. Declair the CMutex class that encapsulates the functionality of a +// mutually-exclusive device. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_MUTEX_H +#define BASE_WIN32_MUTEX_H + +#if defined (_MT) + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CMutex + // + // Purpose: + // Encapsulates the functionality of a mutually-exclusive device. + // This class is valuable for protecting against race conditions + // within threaded applications. The CMutex class can be used to + // only allow a single thread to run within a specified code + // segment at a time. + // + // Public Methods: + // Lock() : Locks the mutex. If the mutex is already locked, the + // operating system will block the calling thread until another + // thread has unlocked the mutex. + // Unlock() : Unlocks the mutex. + // + class CMutex + { + public: + CMutex(); + ~CMutex(); + + void Lock(); + void Unlock(); + private: + CRITICAL_SECTION mCriticalSection; + }; + + inline void CMutex::Lock() + { + EnterCriticalSection(&mCriticalSection); + } + + inline void CMutex::Unlock() + { + LeaveCriticalSection(&mCriticalSection); + } + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // #if defined(_MT) + +#endif // BASE_WIN32_MUTEX_H \ No newline at end of file diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Platform.cpp b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Platform.cpp new file mode 100755 index 00000000..3b52563e --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Platform.cpp @@ -0,0 +1,31 @@ +//////////////////////////////////////// +// Platform.cpp +// +// Purpose: +// 1. Implementation of the global functionality declaired in Platform.h. +// +// Revisions: +// 07/10/2001 Created +// + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + + CTimer::CTimer() : + mTimer(0) + { + } + + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Platform.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Platform.h new file mode 100755 index 00000000..aaee37b7 --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Platform.h @@ -0,0 +1,98 @@ +//////////////////////////////////////// +// Platform.h +// +// Purpose: +// 1. Include relevent system headers that are platform specific. +// 2. Declair global platform specific functionality. +// 3. Include primative type definitions +// +// Global Functions: +// getTimer() : Return the current high resolution clock count. +// getTimerFrequency() : Return the frequency of the high resolution clock. +// sleep() : Voluntarily relinquish timeslice of the calling thread for a +// specified number of milliseconds. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_PLATFORM_H +#define BASE_WIN32_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Types.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + uint64 getTimer(void); + uint64 getTimerFrequency(void); + + inline uint64 getTimer(void) + { + uint64 result; + if (!QueryPerformanceCounter(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline uint64 getTimerFrequency(void) + { + uint64 result; + if (!QueryPerformanceFrequency(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline void sleep(uint32 ms) + { + Sleep(ms); + } + + + class CTimer + { + public: + CTimer(); + + void Set(uint32 seconds); + void Signal(); + bool Expired(); + + private: + uint32 mTimer; + }; + + inline void CTimer::Set(uint32 interval) + { + mTimer = (uint32)time(0) + interval; + } + + inline void CTimer::Signal() + { + mTimer = 0; + } + + inline bool CTimer::Expired() + { + return (mTimer <= (uint32)time(0)); + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif BASE_WIN32_PLATFORM_H \ No newline at end of file diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Thread.cpp b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Thread.cpp new file mode 100755 index 00000000..cfb2c177 --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Thread.cpp @@ -0,0 +1,279 @@ +//////////////////////////////////////// +// Thread.cpp +// +// Purpose: +// 1. Implementation of the CThread class. +// +// Revisions: +// 07/10/2001 Created +// + + +#pragma warning ( disable: 4786 ) + + +#if !defined(_MT) +# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_MT)" ) +#else + +#include +#include +#include "Thread.h" + +using namespace std; + + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + void threadProc(void *threadPtr) + { + CThread &thread = *((CThread*)threadPtr); + thread.mThreadActive = true; + thread.ThreadProc(); + thread.mThreadActive = false; + } + + CThread::CThread() + { + mThreadID = 0; + mThreadActive = false; + mThreadContinue = false; + } + + CThread::~CThread() + { + StopThread(); + } + + void CThread::StartThread() + { + mThreadContinue = true; + mThreadID = _beginthread(threadProc,0,this); + while (!IsThreadActive()) + Base::sleep(1); + } + + int32 CThread::StopThread(int32 timeout) + { + timeout += time(0); + + mThreadContinue = false; + while (mThreadActive && time(0)OnStartup(this); + while (mThreadContinue) + { + mParent->OnIdle(this); + mSemaphore.Wait(mParent->GetTimeOut()*1000); + + if (mFunction) + { + mFunction(mArgument); + mArgument = NULL; + mFunction = NULL; + } + else if (mParent->OnDestory(this)) + mThreadContinue = false; + } + } + + +//////////////////////////////////////////////////////////////////////////////// + + + CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) : + mMutex(), + mIdleMember(), + mBusyMember(), + mNullMember(), + mThreadCount(0), + mMaxThreads(maxThreads), + mMinThreads(minThreads), + mTimeOut(timeout) + { + if (mMaxThreads == 0) mMaxThreads = 1; + if (mMinThreads == 0) mMinThreads = 1; + if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads; + + for (uint32 i=0; i::iterator setIterator; + + //////////////////////////////////////// + // (1) Destory all busy member threads + mMutex.Lock(); + setIterator = mBusyMember.begin(); + while (setIterator != mBusyMember.end()) + (*setIterator++)->Destroy(); + mMutex.Unlock(); + + //////////////////////////////////////// + // (2) Destory all idle member threads + while (mThreadCount) + { + mMutex.Lock(); + setIterator = mIdleMember.begin(); + while (setIterator != mIdleMember.end()) + (*setIterator++)->Destroy(); + mMutex.Unlock(); + + sleep(1); + } + + //////////////////////////////////////// + // (3) Delete the null member threads + mMutex.Lock(); + while (!mNullMember.empty()) + { + delete mNullMember.front(); + mNullMember.pop_front(); + } + mMutex.Unlock(); + } + + bool CThreadPool::Execute(void( __cdecl *function )( void * ), void * arg) + { + mMutex.Lock(); + + //////////////////////////////////////// + // (1) If no idle members, return false to indicate that no threads + // were available. If the thread count is below the max, create + // a new thread. + if (mIdleMember.empty()) + { + if (mThreadCount < mMaxThreads) + new CMember(this); + mMutex.Unlock(); + return false; + } + + //////////////////////////////////////// + // (2) Delete any null member threads. + while (!mNullMember.empty()) + { + delete mNullMember.front(); + mNullMember.pop_front(); + } + + //////////////////////////////////////// + // (3) Move the first idle thread to the busy set and signal the + // thread to execute the specified function. + CMember * member = *(mIdleMember.begin()); + mIdleMember.erase(member); + mBusyMember.insert(member); + member->Execute(function,arg); + + mMutex.Unlock(); + return true; + } + + uint32 CThreadPool::GetTimeOut() + { + return mTimeOut; + } + + void CThreadPool::OnStartup(CMember * member) + { + mMutex.Lock(); + + mThreadCount++; + mIdleMember.insert(member); + + mMutex.Unlock(); + } + + void CThreadPool::OnIdle(CMember * member) + { + mMutex.Lock(); + + mBusyMember.erase(member); + mIdleMember.insert(member); + + mMutex.Unlock(); + } + + bool CThreadPool::OnDestory(CMember * member) + { + set::iterator setIterator; + + mMutex.Lock(); + + bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end(); + if (result) + { + mNullMember.push_back(member); + mIdleMember.erase(setIterator); + mThreadCount--; + } + + mMutex.Unlock(); + + return result; + } + + +//////////////////////////////////////////////////////////////////////////////// + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // #if defined(_MT) + diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Thread.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Thread.h new file mode 100755 index 00000000..a8338917 --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Thread.h @@ -0,0 +1,144 @@ +//////////////////////////////////////// +// Thread.h +// +// Purpose: +// 1. Declair the CThread class that encapsulates threading functionality. +// This abstract base class in intended to be used to encapsulate +// individual tasks that require threading in derived classes. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_THREAD_H +#define BASE_WIN32_THREAD_H + +#if defined(_MT) + +#pragma warning( disable : 4786) + +#include +#include +#include "Platform.h" +#include "Mutex.h" +#include "Event.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CThread + // + // Purpose: + // Encapsulates threading functionality. Creating classes derived + // from CThread provides an easy way to encapsulate tasks that require + // their own thread. + // + // Public Methods: + // StartThread() : Creates the low-level thread handle and begins executing + // the CThread::ThreadProc() function within the new thread. + // StopThread() : Signals the ThreadProc() function to stop executing using + // the mThreadContinue member variable, and waits for the ThreadProc() + // function to exit. By default, the function will block for a maximum + // of 5 seconds before exiting without the thread halting. + // IsThreadActive() : Returns true if the physical thread is still executing + // within the ThreadProc() function, otherwise it returns false. + // ThreadProc() : Pure-virtual function that will be executed when the StartThread() + // function is called. Derived classes must implement this function. The + // mThreadContinue member variable should be used internal the the ThreadProc() + // function to indicate whether it should continue executing or exit. + // Protected Attributes: + // mThreadContinue : Boolean value indicating to the ThreadProc() function + // whether to continue executing or to exit. If mThreadContinue is true, + // ThreadProc() should continue, otherwise ThreadProc() should exit. It + // left up to the derived class to implement a ThreadProc() function that + // uses the mThreadContinue member. + // + // + class CThread + { + friend void threadProc(void *); + + public: + enum { eSTOP_SUCCESS, eSTOP_TIMEOUT }; + public: + CThread(); + virtual ~CThread(); + + void StartThread(); + int32 StopThread(int32 timeout=5); + bool IsThreadActive() { return mThreadActive; } + + protected: + virtual void ThreadProc() = 0; + + protected: + bool mThreadContinue; + private: + uint32 mThreadID; + bool mThreadActive; + }; + + + class CThreadPool + { + private: + class CMember : public CThread + { + public: + CMember(CThreadPool * parent); + virtual ~CMember(); + + bool Execute(void( __cdecl *function )( void * ), void * arg); + void Destroy(); + + protected: + virtual void ThreadProc(); + + private: + CThreadPool * mParent; + void( __cdecl * mFunction )( void * ); + void * mArgument; + CEvent mSemaphore; + }; + friend class CMember; + + public: + CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60); + ~CThreadPool(); + + bool Execute(void( __cdecl *function )( void * ), void * arg); + + private: + uint32 GetTimeOut(); + void OnStartup(CMember * member); + void OnIdle(CMember * member); + bool OnDestory(CMember * member); + + private: + CMutex mMutex; + std::set mIdleMember; + std::set mBusyMember; + std::list mNullMember; + uint32 mThreadCount; + + uint32 mMaxThreads; + uint32 mMinThreads; + uint32 mTimeOut; + }; + + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // #if defined(_MT) + +#endif // BASE_WIN32_THREAD_H diff --git a/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Types.h b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Types.h new file mode 100755 index 00000000..0c64cb2c --- /dev/null +++ b/external/3rd/library/soePlatform/CSAssist/utils/Base/win32/Types.h @@ -0,0 +1,42 @@ +//////////////////////////////////////// +// Types.h +// +// Purpose: +// 1. Define integer types that are unambiguous with respect to size +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_TYPES_H +#define BASE_WIN32_TYPES_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN 0x80000000 +#define UINT32_MAX 0xFFFFFFFF + +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; + +typedef int int32; +typedef unsigned uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // BASE_WIN32_TYPES_H + diff --git a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Archive.h b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Archive.h new file mode 100755 index 00000000..30ddce43 --- /dev/null +++ b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Archive.h @@ -0,0 +1,42 @@ +#ifndef BASE_WIN32_ARCHIVE_H +#define BASE_WIN32_ARCHIVE_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + +#ifdef PACK_BIG_ENDIAN + + inline double byteSwap(double value) { byteReverse64(&value); return value; } + inline float byteSwap(float value) { byteReverse32(&value); return value; } + inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; } + inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; } + inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; } + inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; } + inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; } + inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; } + +#else + + inline double byteSwap(double value) { return value; } + inline float byteSwap(float value) { return value; } + inline uint64 byteSwap(uint64 value) { return value; } + inline int64 byteSwap(int64 value) { return value; } + inline uint32 byteSwap(uint32 value) { return value; } + inline int32 byteSwap(int32 value) { return value; } + inline uint16 byteSwap(uint16 value) { return value; } + inline int16 byteSwap(int16 value) { return value; } + +#endif + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif diff --git a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Platform.cpp b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Platform.cpp new file mode 100755 index 00000000..3b52563e --- /dev/null +++ b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Platform.cpp @@ -0,0 +1,31 @@ +//////////////////////////////////////// +// Platform.cpp +// +// Purpose: +// 1. Implementation of the global functionality declaired in Platform.h. +// +// Revisions: +// 07/10/2001 Created +// + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + + CTimer::CTimer() : + mTimer(0) + { + } + + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Platform.h b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Platform.h new file mode 100755 index 00000000..aaee37b7 --- /dev/null +++ b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Platform.h @@ -0,0 +1,98 @@ +//////////////////////////////////////// +// Platform.h +// +// Purpose: +// 1. Include relevent system headers that are platform specific. +// 2. Declair global platform specific functionality. +// 3. Include primative type definitions +// +// Global Functions: +// getTimer() : Return the current high resolution clock count. +// getTimerFrequency() : Return the frequency of the high resolution clock. +// sleep() : Voluntarily relinquish timeslice of the calling thread for a +// specified number of milliseconds. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_PLATFORM_H +#define BASE_WIN32_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Types.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + uint64 getTimer(void); + uint64 getTimerFrequency(void); + + inline uint64 getTimer(void) + { + uint64 result; + if (!QueryPerformanceCounter(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline uint64 getTimerFrequency(void) + { + uint64 result; + if (!QueryPerformanceFrequency(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline void sleep(uint32 ms) + { + Sleep(ms); + } + + + class CTimer + { + public: + CTimer(); + + void Set(uint32 seconds); + void Signal(); + bool Expired(); + + private: + uint32 mTimer; + }; + + inline void CTimer::Set(uint32 interval) + { + mTimer = (uint32)time(0) + interval; + } + + inline void CTimer::Signal() + { + mTimer = 0; + } + + inline bool CTimer::Expired() + { + return (mTimer <= (uint32)time(0)); + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif BASE_WIN32_PLATFORM_H \ No newline at end of file diff --git a/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Types.h b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Types.h new file mode 100755 index 00000000..0c64cb2c --- /dev/null +++ b/external/3rd/library/soePlatform/CTServiceGameAPI/Base/win32/Types.h @@ -0,0 +1,42 @@ +//////////////////////////////////////// +// Types.h +// +// Purpose: +// 1. Define integer types that are unambiguous with respect to size +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_TYPES_H +#define BASE_WIN32_TYPES_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN 0x80000000 +#define UINT32_MAX 0xFFFFFFFF + +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; + +typedef int int32; +typedef unsigned uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // BASE_WIN32_TYPES_H + diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Archive.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Archive.h new file mode 100755 index 00000000..30ddce43 --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Archive.h @@ -0,0 +1,42 @@ +#ifndef BASE_WIN32_ARCHIVE_H +#define BASE_WIN32_ARCHIVE_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + +#ifdef PACK_BIG_ENDIAN + + inline double byteSwap(double value) { byteReverse64(&value); return value; } + inline float byteSwap(float value) { byteReverse32(&value); return value; } + inline uint64 byteSwap(uint64 value) { byteReverse64(&value); return value; } + inline int64 byteSwap(int64 value) { byteReverse64(&value); return value; } + inline uint32 byteSwap(uint32 value) { byteReverse32(&value); return value; } + inline int32 byteSwap(int32 value) { byteReverse32(&value); return value; } + inline uint16 byteSwap(uint16 value) { byteReverse16(&value); return value; } + inline int16 byteSwap(int16 value) { byteReverse16(&value); return value; } + +#else + + inline double byteSwap(double value) { return value; } + inline float byteSwap(float value) { return value; } + inline uint64 byteSwap(uint64 value) { return value; } + inline int64 byteSwap(int64 value) { return value; } + inline uint32 byteSwap(uint32 value) { return value; } + inline int32 byteSwap(int32 value) { return value; } + inline uint16 byteSwap(uint16 value) { return value; } + inline int16 byteSwap(int16 value) { return value; } + +#endif + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/BlockAllocator.cpp b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/BlockAllocator.cpp new file mode 100755 index 00000000..6762bc2a --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/BlockAllocator.cpp @@ -0,0 +1,112 @@ +#include "../BlockAllocator.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + BlockAllocator::BlockAllocator() + { + for(unsigned i = 0; i < 31; i++) + { + m_blocks[i] = NULL; + } + } + + BlockAllocator::~BlockAllocator() + { + // free all allocated memory blocks + for(unsigned i = 0; i < 31; i++) + { + while(m_blocks[i] != NULL) + { + unsigned *tmp = m_blocks[i]; + m_blocks[i] = (uintptr_t *)*m_blocks[i]; + free(tmp); + } + } + } + +// Allocate a block that is the next power of two greater than the # of bytes passed. +// 33 bytes yields a 64 byte block of memory and so forth. + + void *BlockAllocator::getBlock(unsigned bytes) + { + unsigned accum = 16, bits = 16; + unsigned *handle = NULL; + + // Perform a binary search looking for the highest bit. + + while(bits != 0) + { + // If bytes is less than the bit we're testing for, subtract half + // from the bit value and repeat + if(bytes < (unsigned)(1 << accum)) + { + bits /= 2; + accum -= bits; + } + // If bytes is greater than the bit we're testing for, add half + // from the but value and repeat + else if(bytes > (unsigned)(1 << accum)) + { + bits /= 2; + accum += bits; + } + // Got lucky and hit the value dead on + else + { + break; + } + } + // At this point accum contains the most significant bit index, increment + accum++; + if(accum < 2) + { + accum = 2; + } + + // Note that when memory is actually allocated, 8 extra bytes will be allocated.at the front + // The first integer is the address of the next block of memory when the block is in the allocator + // The second integer is the bit length of the block + // Memory is allocated on 4 byte boundaries to sidestep byte alignment problems + + + // Check if the allocator already has a block of that size + if(m_blocks[accum] == 0) + { + // remove the pre allocated block from the linked list + handle = (unsigned *)calloc(((1 << accum) / 4) + 2, sizeof(unsigned)); + handle[1] = accum; + handle[0] = 0; + } + else + { + // Allocate a new block + handle = m_blocks[accum]; + m_blocks[accum] = (uintptr_t *)handle[0]; + handle[0] = 0; + } + // return a pointer that skips over the header used for the allocator's purposes + return(handle + 2); + } + + void BlockAllocator::returnBlock(uintptr_t *handle) + { + // C++ allows for safe deletion of a NULL pointer + if(handle) + { + // Update the allocator linked list, insert this entry at the head + *(handle - 2) = (uintptr_t)m_blocks[*(handle - 1)]; + // Add this entry to the proper linked list node + m_blocks[*(handle - 1)] = (handle - 2); + } + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Event.cpp b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Event.cpp new file mode 100755 index 00000000..12ee8fe7 --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Event.cpp @@ -0,0 +1,44 @@ +//////////////////////////////////////// +// Event.cpp +// +// Purpose: +// 1. Implementation of the CEvent class. +// +// Revisions: +// 07/10/2001 Created +// + + +#if !defined(_MT) +# pragma message( "Excluding Base::CEvent - requires multi-threaded compile. (_MT)" ) +#else + +#include "Event.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + CEvent::CEvent() + { + mEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); + } + + CEvent::~CEvent() + { + if (mEvent) + CloseHandle(mEvent); + } + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // #if defined(_MT) + diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Event.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Event.h new file mode 100755 index 00000000..5d2bc712 --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Event.h @@ -0,0 +1,92 @@ +//////////////////////////////////////// +// Event.h +// +// Purpose: +// 1. Declair the CEvent class that encapsulates the functionality of a +// single-locking semaphore. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_EVENT_H +#define BASE_WIN32_EVENT_H + +#if defined(_MT) + + + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CEvent + // + // Purpose: + // Encapsulates the functionality of a singal-locking semaphore. + // This class is valuable for thread syncronization when a thead's + // execution needs to be dependent upon another thread. + // + // Public Methods: + // Signal() : Signals a thread that has called Wait() so that it can + // continue execution. This function returns true if the waiting + // thread was signalled successfully, otherwise false is returned. + // Wait() : Halts the calling thread's execution indefinately until + // a Singal() call is made by an external thread. If the thread is + // successfully signalled, the function returns eWAIT_SIGNAL. If + // timeout period expires without a signal, eWAIT_TIMEOUT is returned. + // If the function fails, eWAIT_ERROR is returned. + // + class CEvent + { + public: + CEvent(); + virtual ~CEvent(); + + bool Signal(); + int32 Wait(uint32 timeout = 0); + + public: + enum { eWAIT_ERROR, eWAIT_SIGNAL, eWAIT_TIMEOUT }; + private: + HANDLE mEvent; + }; + + inline bool CEvent::Signal() + { + if (mEvent) + return SetEvent(mEvent)!=0; + + return false; + } + + inline int32 CEvent::Wait(uint32 timeout) + { + if (!mEvent) + return CEvent::eWAIT_ERROR; + + DWORD result = WaitForSingleObjectEx(mEvent, timeout ? timeout : INFINITE, FALSE); + if (result == WAIT_OBJECT_0) + return CEvent::eWAIT_SIGNAL; + else if (result == WAIT_TIMEOUT) + return CEvent::eWAIT_TIMEOUT; + else + return CEvent::eWAIT_ERROR; + } + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif +#endif // #if defined(_MT) + + +#endif // BASE_WIN32_EVENT_H diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/File.cpp b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/File.cpp new file mode 100755 index 00000000..c888e545 --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/File.cpp @@ -0,0 +1,22 @@ +// File.cpp: implementation of the CFile class. +// +////////////////////////////////////////////////////////////////////// + +#include "File.h" + +namespace Base +{ + ////////////////////////////////////////////////////////////////////// + // Construction/Destruction + ////////////////////////////////////////////////////////////////////// + + CFile::CFile(const char *) + { + + } + + CFile::~CFile() + { + + } +} diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/File.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/File.h new file mode 100755 index 00000000..fb15ccf1 --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/File.h @@ -0,0 +1,26 @@ +// File.h: interface for the CFile class. +// +////////////////////////////////////////////////////////////////////// + +#ifndef BASE_FILE_H +#define BASE_FILE_H + +#include + +namespace Base +{ + + class CFile + { + public: + CFile(const char *); + virtual ~CFile(); + + bool IsOpen(); + + private: + FILE* mFileHandle; + }; +} + +#endif // BASE_FILE_H diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Mutex.cpp b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Mutex.cpp new file mode 100755 index 00000000..482481e8 --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Mutex.cpp @@ -0,0 +1,40 @@ +//////////////////////////////////////// +// Mutex.cpp +// +// Purpose: +// 1. Implementation of the CMutex class. +// +// Revisions: +// 07/10/2001 Created +// +#if !defined(_MT) +# pragma message( "Excluding Base::CMutex - requires multi-threaded compile. (_MT)" ) +#else + +#include "Mutex.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +CMutex::CMutex() + { + InitializeCriticalSection(&mCriticalSection); + } + +CMutex::~CMutex() + { + DeleteCriticalSection(&mCriticalSection); + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // #if defined(_MT) + diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Mutex.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Mutex.h new file mode 100755 index 00000000..66e1c08b --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Mutex.h @@ -0,0 +1,73 @@ +//////////////////////////////////////// +// Mutex.h +// +// Purpose: +// 1. Declair the CMutex class that encapsulates the functionality of a +// mutually-exclusive device. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_MUTEX_H +#define BASE_WIN32_MUTEX_H + +#if defined (_MT) + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CMutex + // + // Purpose: + // Encapsulates the functionality of a mutually-exclusive device. + // This class is valuable for protecting against race conditions + // within threaded applications. The CMutex class can be used to + // only allow a single thread to run within a specified code + // segment at a time. + // + // Public Methods: + // Lock() : Locks the mutex. If the mutex is already locked, the + // operating system will block the calling thread until another + // thread has unlocked the mutex. + // Unlock() : Unlocks the mutex. + // + class CMutex + { + public: + CMutex(); + ~CMutex(); + + void Lock(); + void Unlock(); + private: + CRITICAL_SECTION mCriticalSection; + }; + + inline void CMutex::Lock() + { + EnterCriticalSection(&mCriticalSection); + } + + inline void CMutex::Unlock() + { + LeaveCriticalSection(&mCriticalSection); + } + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // #if defined(_MT) + +#endif // BASE_WIN32_MUTEX_H \ No newline at end of file diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Platform.cpp b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Platform.cpp new file mode 100755 index 00000000..3b52563e --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Platform.cpp @@ -0,0 +1,31 @@ +//////////////////////////////////////// +// Platform.cpp +// +// Purpose: +// 1. Implementation of the global functionality declaired in Platform.h. +// +// Revisions: +// 07/10/2001 Created +// + +#include "Platform.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + + CTimer::CTimer() : + mTimer(0) + { + } + + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Platform.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Platform.h new file mode 100755 index 00000000..aaee37b7 --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Platform.h @@ -0,0 +1,98 @@ +//////////////////////////////////////// +// Platform.h +// +// Purpose: +// 1. Include relevent system headers that are platform specific. +// 2. Declair global platform specific functionality. +// 3. Include primative type definitions +// +// Global Functions: +// getTimer() : Return the current high resolution clock count. +// getTimerFrequency() : Return the frequency of the high resolution clock. +// sleep() : Voluntarily relinquish timeslice of the calling thread for a +// specified number of milliseconds. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_PLATFORM_H +#define BASE_WIN32_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "Types.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + uint64 getTimer(void); + uint64 getTimerFrequency(void); + + inline uint64 getTimer(void) + { + uint64 result; + if (!QueryPerformanceCounter(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline uint64 getTimerFrequency(void) + { + uint64 result; + if (!QueryPerformanceFrequency(reinterpret_cast(&result))) + result = 0; + return result; + } + + inline void sleep(uint32 ms) + { + Sleep(ms); + } + + + class CTimer + { + public: + CTimer(); + + void Set(uint32 seconds); + void Signal(); + bool Expired(); + + private: + uint32 mTimer; + }; + + inline void CTimer::Set(uint32 interval) + { + mTimer = (uint32)time(0) + interval; + } + + inline void CTimer::Signal() + { + mTimer = 0; + } + + inline bool CTimer::Expired() + { + return (mTimer <= (uint32)time(0)); + } +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif BASE_WIN32_PLATFORM_H \ No newline at end of file diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Thread.cpp b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Thread.cpp new file mode 100755 index 00000000..9dcbb9a9 --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Thread.cpp @@ -0,0 +1,315 @@ +//////////////////////////////////////// +// Thread.cpp +// +// Purpose: +// 1. Implementation of the CThread class. +// +// Revisions: +// 07/10/2001 Created +// + + +#pragma warning ( disable: 4786 ) + + +#if !defined(_MT) +# pragma message( "Excluding Base::CThread - requires multi-threaded compile. (_MT)" ) +#else + +#include +#include +#include "Thread.h" + +using namespace std; + + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + void threadProc(void *threadPtr) + { + CThread &thread = *((CThread*)threadPtr); + thread.mThreadActive = true; + thread.ThreadProc(); + thread.mThreadActive = false; + } + + CThread::CThread() + { + mThreadID = 0; + mThreadActive = false; + mThreadContinue = false; + } + + CThread::~CThread() + { + StopThread(); + } + + void CThread::StartThread() + { + mThreadContinue = true; + mThreadID = _beginthread(threadProc,0,this); + while (!IsThreadActive()) + Base::sleep(1); + } + + int32 CThread::StopThread(int32 timeout) + { + timeout += time(0); + + mThreadContinue = false; + while (mThreadActive && time(0)OnStartup(this); + while (mThreadContinue) + { + mParent->OnIdle(this); + mSemaphore.Wait(mParent->GetTimeOut()*1000); + + if (mFunction) + { + mFunction(mArgument); + mArgument = NULL; + mFunction = NULL; + } + else if (mParent->OnDestory(this)) + mThreadContinue = false; + } + } + + +//////////////////////////////////////////////////////////////////////////////// + + + CThreadPool::CThreadPool(uint32 maxThreads, uint32 minThreads, uint32 timeout) : + mMutex(), + mIdleMember(), + mBusyMember(), + mNullMember(), + mThreadCount(0), + mMaxThreads(maxThreads), + mMinThreads(minThreads), + mTimeOut(timeout) + { + if (mMaxThreads == 0) mMaxThreads = 1; + if (mMinThreads == 0) mMinThreads = 1; + if (mMinThreads > mMaxThreads) mMinThreads = mMaxThreads; + + for (uint32 i=0; i::iterator setIterator; + + //////////////////////////////////////// + // (1) Destory all busy member threads + mMutex.Lock(); + setIterator = mBusyMember.begin(); + while (setIterator != mBusyMember.end()) + (*setIterator++)->Destroy(); + mMutex.Unlock(); + + //////////////////////////////////////// + // (2) Destory all idle member threads + while (mThreadCount) + { + mMutex.Lock(); + setIterator = mIdleMember.begin(); + while (setIterator != mIdleMember.end()) + (*setIterator++)->Destroy(); + mMutex.Unlock(); + + sleep(1); + } + + //////////////////////////////////////// + // (3) Delete the null member threads + mMutex.Lock(); + while (!mNullMember.empty()) + { + delete mNullMember.front(); + mNullMember.pop_front(); + } + mMutex.Unlock(); + } + + bool CThreadPool::Execute(void( __cdecl *function )( void * ), void * arg, uint32 poolGrowthSize ) + { + mMutex.Lock(); + + //////////////////////////////////////// + // (1) If no idle members, return false to indicate that no threads + // were available. If the thread count is below the max, create + // a new thread. + if (mIdleMember.empty()) + { + if (mThreadCount < mMaxThreads) + { + if (!poolGrowthSize) + poolGrowthSize = mMinThreads; + + if ((mThreadCount + poolGrowthSize) > mMaxThreads) + poolGrowthSize = mMaxThreads - mThreadCount; + + for (uint32 i(0); i < poolGrowthSize; i++) + new CMember(this); + mMutex.Unlock(); + time_t idleTimeout = time(0) + 5; + while(mIdleMember.empty()) + { + if (time(0) >= idleTimeout) + { + return false; + } + Base::sleep(10); + } + mMutex.Lock(); + + } + else + { + mMutex.Unlock(); + return false; + } + } + + //////////////////////////////////////// + // (2) Delete any null member threads. + while (!mNullMember.empty()) + { + delete mNullMember.front(); + mNullMember.pop_front(); + } + + //////////////////////////////////////// + // (3) Move the first idle thread to the busy set and signal the + // thread to execute the specified function. + CMember * member = *(mIdleMember.begin()); + mIdleMember.erase(member); + mBusyMember.insert(member); + member->Execute(function,arg); + + mMutex.Unlock(); + return true; + } + + uint32 CThreadPool::GetTimeOut() + { + return mTimeOut; + } + + void CThreadPool::OnStartup(CMember * member) + { + mMutex.Lock(); + + mThreadCount++; + mIdleMember.insert(member); + + mMutex.Unlock(); + } + + void CThreadPool::OnIdle(CMember * member) + { + mMutex.Lock(); + + mBusyMember.erase(member); + mIdleMember.insert(member); + + mMutex.Unlock(); + } + + bool CThreadPool::OnDestory(CMember * member) + { + set::iterator setIterator; + + mMutex.Lock(); + + bool result = (setIterator = mIdleMember.find(member)) != mIdleMember.end(); + if (result) + { + mNullMember.push_back(member); + mIdleMember.erase(setIterator); + mThreadCount--; + } + + mMutex.Unlock(); + + return result; + } + + SwitchableScopeLock::SwitchableScopeLock(CMutex & mutex, bool isOn) : + mMutex(mutex), + mIsOn(isOn) + { + if(mIsOn) { mMutex.Lock(); } + } + + SwitchableScopeLock::~SwitchableScopeLock() + { + if(mIsOn) { mMutex.Unlock(); } + } + + +//////////////////////////////////////////////////////////////////////////////// + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + + +#endif // #if defined(_MT) + diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Thread.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Thread.h new file mode 100755 index 00000000..cbffabb6 --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Thread.h @@ -0,0 +1,152 @@ +//////////////////////////////////////// +// Thread.h +// +// Purpose: +// 1. Declair the CThread class that encapsulates threading functionality. +// This abstract base class in intended to be used to encapsulate +// individual tasks that require threading in derived classes. +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_THREAD_H +#define BASE_WIN32_THREAD_H + +#if defined(_MT) + +#pragma warning( disable : 4786) + +#include +#include +#include "Platform.h" +#include "Mutex.h" +#include "Event.h" + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + + //////////////////////////////////////// + // Class: + // CThread + // + // Purpose: + // Encapsulates threading functionality. Creating classes derived + // from CThread provides an easy way to encapsulate tasks that require + // their own thread. + // + // Public Methods: + // StartThread() : Creates the low-level thread handle and begins executing + // the CThread::ThreadProc() function within the new thread. + // StopThread() : Signals the ThreadProc() function to stop executing using + // the mThreadContinue member variable, and waits for the ThreadProc() + // function to exit. By default, the function will block for a maximum + // of 5 seconds before exiting without the thread halting. + // IsThreadActive() : Returns true if the physical thread is still executing + // within the ThreadProc() function, otherwise it returns false. + // ThreadProc() : Pure-virtual function that will be executed when the StartThread() + // function is called. Derived classes must implement this function. The + // mThreadContinue member variable should be used internal the the ThreadProc() + // function to indicate whether it should continue executing or exit. + // Protected Attributes: + // mThreadContinue : Boolean value indicating to the ThreadProc() function + // whether to continue executing or to exit. If mThreadContinue is true, + // ThreadProc() should continue, otherwise ThreadProc() should exit. It + // left up to the derived class to implement a ThreadProc() function that + // uses the mThreadContinue member. + // + // + class CThread + { + friend void threadProc(void *); + + public: + enum { eSTOP_SUCCESS, eSTOP_TIMEOUT }; + public: + CThread(); + virtual ~CThread(); + + void StartThread(); + int32 StopThread(int32 timeout=5); + bool IsThreadActive() { return mThreadActive; } + + protected: + virtual void ThreadProc() = 0; + + protected: + bool mThreadContinue; + private: + uint32 mThreadID; + bool mThreadActive; + }; + + + class CThreadPool + { + private: + class CMember : public CThread + { + public: + CMember(CThreadPool * parent); + virtual ~CMember(); + + bool Execute(void( __cdecl *function )( void * ), void * arg); + void Destroy(); + + protected: + virtual void ThreadProc(); + + private: + CThreadPool * mParent; + void( __cdecl * mFunction )( void * ); + void * mArgument; + CEvent mSemaphore; + }; + friend class CMember; + + public: + CThreadPool(uint32 maxThreads, uint32 minThreads=1, uint32 timeout=15*60); + ~CThreadPool(); + + virtual bool Execute(void( __cdecl *function )( void * ), void * arg, uint32 poolGrowthSize = 0); + + private: + uint32 GetTimeOut(); + void OnStartup(CMember * member); + void OnIdle(CMember * member); + bool OnDestory(CMember * member); + + private: + CMutex mMutex; + std::set mIdleMember; + std::set mBusyMember; + std::list mNullMember; + uint32 mThreadCount; + + uint32 mMaxThreads; + uint32 mMinThreads; + uint32 mTimeOut; + }; + + class SwitchableScopeLock + { + public: + SwitchableScopeLock(CMutex & mutex, bool isOn); + ~SwitchableScopeLock(); + private: + CMutex & mMutex; + bool mIsOn; + }; +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // #if defined(_MT) + +#endif // BASE_WIN32_THREAD_H diff --git a/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Types.h b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Types.h new file mode 100755 index 00000000..0c64cb2c --- /dev/null +++ b/external/3rd/library/soePlatform/ChatAPI/utils/Base/win32/Types.h @@ -0,0 +1,42 @@ +//////////////////////////////////////// +// Types.h +// +// Purpose: +// 1. Define integer types that are unambiguous with respect to size +// +// Revisions: +// 07/10/2001 Created +// + +#ifndef BASE_WIN32_TYPES_H +#define BASE_WIN32_TYPES_H + +#ifdef EXTERNAL_DISTRO +namespace NAMESPACE +{ + +#endif +namespace Base +{ + +#define INT32_MAX 0x7FFFFFFF +#define INT32_MIN 0x80000000 +#define UINT32_MAX 0xFFFFFFFF + +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; + +typedef int int32; +typedef unsigned uint32; +typedef __int64 int64; +typedef unsigned __int64 uint64; + +}; +#ifdef EXTERNAL_DISTRO +}; +#endif + +#endif // BASE_WIN32_TYPES_H + diff --git a/external/ours/library/archive/src/win32/ArchiveMutex.cpp b/external/ours/library/archive/src/win32/ArchiveMutex.cpp new file mode 100755 index 00000000..016c070b --- /dev/null +++ b/external/ours/library/archive/src/win32/ArchiveMutex.cpp @@ -0,0 +1,35 @@ +// ====================================================================== +// +// +// Copyright 6/19/2001 Sony Online Entertainment +// +// ====================================================================== + + +#include "FirstArchive.h" +#include "ArchiveMutex.h" + +namespace Archive +{ + +ArchiveMutex::ArchiveMutex() +{ + InitializeCriticalSection(&m_criticalSection); +} + +ArchiveMutex::~ArchiveMutex() +{ + DeleteCriticalSection(&m_criticalSection); +} + +void ArchiveMutex::enter() +{ + EnterCriticalSection(&m_criticalSection); +} + +void ArchiveMutex::leave() +{ + LeaveCriticalSection(&m_criticalSection); +} + +} diff --git a/external/ours/library/archive/src/win32/ArchiveMutex.h b/external/ours/library/archive/src/win32/ArchiveMutex.h new file mode 100755 index 00000000..b453981b --- /dev/null +++ b/external/ours/library/archive/src/win32/ArchiveMutex.h @@ -0,0 +1,27 @@ +#ifndef _ArchiveMutex_H +#define _ArchiveMutex_H + +#include + +namespace Archive +{ + + class ArchiveMutex + { + public: + + ArchiveMutex(); + ~ArchiveMutex(); + void enter(); + void leave(); + + private: + ArchiveMutex(const ArchiveMutex &o); + ArchiveMutex &operator =(const ArchiveMutex &o); + + CRITICAL_SECTION m_criticalSection; + + }; +} + +#endif diff --git a/external/ours/library/archive/src/win32/FirstArchive.cpp b/external/ours/library/archive/src/win32/FirstArchive.cpp new file mode 100755 index 00000000..6e118e67 --- /dev/null +++ b/external/ours/library/archive/src/win32/FirstArchive.cpp @@ -0,0 +1,16 @@ +// FirstArchive.cpp +// copyright 2001 Verant Interactive +// Author: Justin Randall + +//----------------------------------------------------------------------- + +#include "FirstArchive.h" + +//----------------------------------------------------------------------- + +namespace +{ + void supress_warning_LNK4221() + { + } +} diff --git a/external/ours/library/crypto/src/win32/FirstCrypto.cpp b/external/ours/library/crypto/src/win32/FirstCrypto.cpp new file mode 100755 index 00000000..8b9ece1b --- /dev/null +++ b/external/ours/library/crypto/src/win32/FirstCrypto.cpp @@ -0,0 +1 @@ +#include "FirstCrypto.h" diff --git a/external/ours/library/fileInterface/src/win32/FirstFileInterface.cpp b/external/ours/library/fileInterface/src/win32/FirstFileInterface.cpp new file mode 100755 index 00000000..33fdbcbc --- /dev/null +++ b/external/ours/library/fileInterface/src/win32/FirstFileInterface.cpp @@ -0,0 +1 @@ +#include "fileInterface/FirstFileInterface.h" diff --git a/external/ours/library/localization/src/win32/FirstLocalization.cpp b/external/ours/library/localization/src/win32/FirstLocalization.cpp new file mode 100755 index 00000000..c21d66d0 --- /dev/null +++ b/external/ours/library/localization/src/win32/FirstLocalization.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstLocalization.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstLocalization.h" diff --git a/external/ours/library/localizationArchive/src/win32/FirstLocalizationArchive.cpp b/external/ours/library/localizationArchive/src/win32/FirstLocalizationArchive.cpp new file mode 100755 index 00000000..475bd6c7 --- /dev/null +++ b/external/ours/library/localizationArchive/src/win32/FirstLocalizationArchive.cpp @@ -0,0 +1,10 @@ +//====================================================================== +// +// FirstLocalizationArchive.cpp +// copyright (c) 2002 Sony Online Entertainment +// +//====================================================================== + +#include "localizationArchive/FirstLocalizationArchive.h" + +//====================================================================== diff --git a/external/ours/library/unicode/src/win32/FirstUnicode.cpp b/external/ours/library/unicode/src/win32/FirstUnicode.cpp new file mode 100755 index 00000000..176b4e33 --- /dev/null +++ b/external/ours/library/unicode/src/win32/FirstUnicode.cpp @@ -0,0 +1,8 @@ +// ====================================================================== +// +// FirstUnicode.cpp +// copyright (c) 2001 Sony Online Entertainment +// +// ====================================================================== + +#include "FirstUnicode.h" diff --git a/external/ours/library/unicodeArchive/src/win32/FirstUnicodeArchive.cpp b/external/ours/library/unicodeArchive/src/win32/FirstUnicodeArchive.cpp new file mode 100755 index 00000000..4cb0ce59 --- /dev/null +++ b/external/ours/library/unicodeArchive/src/win32/FirstUnicodeArchive.cpp @@ -0,0 +1,12 @@ +//====================================================================== +// +// FirstUnicodeArchive.cpp +// copyright (c) 2002 Sony Online Entertainment +// +//====================================================================== + +#include "unicodeArchive/FirstUnicodeArchive.h" + +//====================================================================== + +//====================================================================== diff --git a/game/server/application/SwgDatabaseServer/src/win32/FirstSwgDatabaseServer.cpp b/game/server/application/SwgDatabaseServer/src/win32/FirstSwgDatabaseServer.cpp new file mode 100755 index 00000000..d815aeca --- /dev/null +++ b/game/server/application/SwgDatabaseServer/src/win32/FirstSwgDatabaseServer.cpp @@ -0,0 +1 @@ +#include "SwgDatabaseServer/FirstSwgDatabaseServer.h" diff --git a/game/server/application/SwgDatabaseServer/src/win32/WinMain.cpp b/game/server/application/SwgDatabaseServer/src/win32/WinMain.cpp new file mode 100755 index 00000000..6e458a7c --- /dev/null +++ b/game/server/application/SwgDatabaseServer/src/win32/WinMain.cpp @@ -0,0 +1,87 @@ +#include "SwgDatabaseServer/FirstSwgDatabaseServer.h" + +#include "serverDatabase/ConfigServerDatabase.h" +#include "serverDatabase/DatabaseProcess.h" + +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFile/TreeFile.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedLog/LogManager.h" +#include "sharedLog/SetupSharedLog.h" +#include "sharedNetwork/NetworkHandler.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "sharedObject/SetupSharedObject.h" +#include "sharedRandom/SetupSharedRandom.h" +#include "sharedThread/SetupSharedThread.h" +#include "SwgDatabaseServer/SwgDatabaseServer.h" + +#include + + +//_____________________________________________________________________ +int main(int argc, char ** argv) +{ + // command line hack + std::string cmdLine; + for(int i = 1; i < argc; ++i) + { + cmdLine += argv[i]; + if(i + 1 < argc) + { + cmdLine += " "; + } + } + + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + // -- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + + setupFoundationData.commandLine = cmdLine.c_str(); + setupFoundationData.createWindow = false; + setupFoundationData.clockUsesSleep = true; + + SetupSharedFoundation::install (setupFoundationData); + + SetupSharedFile::install(false); + SetupSharedRandom::install(int(time(NULL))); + { + SetupSharedObject::Data data; + SetupSharedObject::setupDefaultGameData(data); + SetupSharedObject::install(data); + } + + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + + SetupSharedNetworkMessages::install(); + + SetupSharedLog::install("SwgDatabaseServer"); + + TreeFile::addSearchAbsolute(0); + TreeFile::addSearchPath(".",0); + + //-- setup server + ConfigServerDatabase::install (); + + NetworkHandler::install(); + + SwgDatabaseServer::install(); + + //-- run server + SetupSharedFoundation::callbackWithExceptionHandling(SwgDatabaseServer::runStatic); + + NetworkHandler::remove(); + SetupSharedLog::remove(); + + SetupSharedFoundation::remove(); + SetupSharedThread::remove(); + + return 0; +} + +//_____________________________________________________________________ diff --git a/game/server/application/SwgGameServer/src/win32/FirstSwgGameServer.cpp b/game/server/application/SwgGameServer/src/win32/FirstSwgGameServer.cpp new file mode 100755 index 00000000..9716e6e8 --- /dev/null +++ b/game/server/application/SwgGameServer/src/win32/FirstSwgGameServer.cpp @@ -0,0 +1 @@ +#include "FirstSwgGameServer.h" diff --git a/game/server/application/SwgGameServer/src/win32/WinMain.cpp b/game/server/application/SwgGameServer/src/win32/WinMain.cpp new file mode 100755 index 00000000..5824ddc5 --- /dev/null +++ b/game/server/application/SwgGameServer/src/win32/WinMain.cpp @@ -0,0 +1,553 @@ +#include "FirstSwgGameServer.h" +#include "serverGame/GameServer.h" + +#include "LocalizationManager.h" +#include "serverGame/SetupServerGame.h" +#include "serverGame/ServerWorld.h" +#include "serverGame/ServerObjectTemplate.h" +#include "ServerObjectLint.h" +#include "serverPathfinding/SetupServerPathfinding.h" +#include "serverScript/SetupScript.h" +#include "serverUtility/SetupServerUtility.h" +#include "sharedDebug/SetupSharedDebug.h" +#include "sharedFile/SetupSharedFile.h" +#include "sharedFile/TreeFile.h" +#include "sharedFoundation/ConfigFile.h" +#include "sharedFoundation/ExitChain.h" +#include "sharedFoundation/FormattedString.h" +#include "sharedFoundation/Os.h" +#include "sharedFoundation/SetupSharedFoundation.h" +#include "sharedGame/SetupSharedGame.h" +#include "sharedGame/SharedObjectTemplate.h" +#include "sharedImage/SetupSharedImage.h" +#include "sharedLog/LogManager.h" +#include "sharedLog/SetupSharedLog.h" +#include "sharedMath/SetupSharedMath.h" +#include "sharedNetwork/NetworkHandler.h" +#include "sharedNetwork/SetupSharedNetwork.h" +#include "sharedObject/SetupSharedObject.h" +#include "sharedObject/ObjectTemplateList.h" +#include "sharedRandom/SetupSharedRandom.h" +#include "sharedRegex/SetupSharedRegex.h" +#include "sharedRemoteDebugServer/SharedRemoteDebugServer.h" +#include "sharedTerrain/SetupSharedTerrain.h" +#include "sharedThread/SetupSharedThread.h" +#include "sharedUtility/SetupSharedUtility.h" +#include "sharedNetworkMessages/SetupSharedNetworkMessages.h" +#include "SwgGameServer/SwgGameServer.h" +#include "SwgGameServer/WorldSnapshotParser.h" +#include "swgSharedNetworkMessages/SetupSwgSharedNetworkMessages.h" +#include "swgServerNetworkMessages/SetupSwgServerNetworkMessages.h" + +#include +#include +#include + +#include + +#ifdef _DEBUG +#include "sharedDebug/DataLint.h" +#include "sharedDebug/PerformanceTimer.h" +#include "sharedFoundation/Os.h" +#include "sharedObject/Object.h" +#include "sharedObject/ObjectTemplate.h" + +void runDataLint(char const *responsePath); +void verifyUpdateRanges (const char* filename); +#endif // _DEBUG + +//_____________________________________________________________________ +/* +int WINAPI WinMain( + HINSTANCE hInstance, // handle to current instance + HINSTANCE hPrevInstance, // handle to previous instance + LPSTR lpCmdLine, // pointer to command line + int nCmdShow // show state of window + ) +*/ +int main(int argc, char ** argv) +{ + int i = 0; + +// UNREF(hPrevInstance); +// UNREF(nCmdShow); +//-- setup foundation + SetupSharedFoundation::Data setupFoundationData(SetupSharedFoundation::Data::D_game); + + // command line hack + std::string cmdLine; + for(i = 1; i < argc; ++i) + { + cmdLine += argv[i]; + if(i + 1 < argc) + { + cmdLine += " "; + } + } +// setupFoundationData.hInstance = hInstance; + setupFoundationData.commandLine = cmdLine.c_str(); + setupFoundationData.createWindow = false; + setupFoundationData.clockUsesSleep = true; + + SetupSharedThread::install(); + SetupSharedDebug::install(1024); + + SetupSharedFoundation::install (setupFoundationData); + + SetupServerUtility::install(); + + SetupSharedRegex::install(); + + SetupSharedFile::install(false); + + SetupSharedNetwork::SetupData networkSetupData; + SetupSharedNetwork::getDefaultServerSetupData(networkSetupData); + SetupSharedNetwork::install(networkSetupData); + + SetupSharedMath::install(); + + SetupSharedUtility::Data setupUtilityData; + SetupSharedUtility::setupGameData (setupUtilityData); + SetupSharedUtility::install (setupUtilityData); + + SetupSharedRandom::install(int(time(NULL))); + { + SetupSharedObject::Data data; + SetupSharedObject::setupDefaultGameData(data); + // we want the SlotIdManager initialized, but we don't need the associated hardpoint names on the server. + SetupSharedObject::addSlotIdManagerData(data, false); + // we want movement table information on this server + SetupSharedObject::addMovementTableData(data); + // we want CustomizationData support on this server. + SetupSharedObject::addCustomizationSupportData(data); + // we want POB ejection point override support. + SetupSharedObject::addPobEjectionTransformData(data); + // objects should not automatically alter their children and contents + data.objectsAlterChildrenAndContents = false; + SetupSharedObject::install(data); + } + + SetupSharedLog::install(FormattedString<92>().sprintf("SwgGameServer:%d", Os::getProcessId())); + + TreeFile::addSearchAbsolute(0); + TreeFile::addSearchPath(".",0); + + SetupSharedNetworkMessages::install(); + SetupSwgServerNetworkMessages::install(); + SetupSwgSharedNetworkMessages::install(); + + SetupSharedImage::Data setupImageData; + SetupSharedImage::setupDefaultData (setupImageData); + SetupSharedImage::install (setupImageData); + + SetupSharedGame::Data setupSharedGameData; + setupSharedGameData.setUseMountValidScaleRangeTable(true); + setupSharedGameData.setUseClientCombatManagerSupport(true); + SetupSharedGame::install (setupSharedGameData); + + SetupSharedTerrain::Data setupSharedTerrainData; + SetupSharedTerrain::setupGameData (setupSharedTerrainData); + SetupSharedTerrain::install (setupSharedTerrainData); + + SetupScript::Data setupScriptData; + SetupScript::setupDefaultGameData(setupScriptData); + SetupScript::install(); + + SetupServerPathfinding::install(); + + //-- setup game server + SetupServerGame::install(); + + SharedRemoteDebugServer::install(); + + //-- setup game server + cmdLine.clear(); + // now, the real command line + for(i = 0; i < argc; ++i) + { + cmdLine += argv[i]; + if(i + 1 < argc) + { + cmdLine += " "; + } + } + + + Archive::ByteStream bs; + UNREF(bs); + + NetworkHandler::install(); + SwgGameServer::install(); + GameServer::getInstance().setCommandLine(cmdLine); + +#ifdef _DEBUG + //-- see if the game server is being run in a mode to parse the database dump to create planetary snapshot files + const char* const createWorldSnapshots = ConfigFile::getKeyString("WorldSnapshot", "createWorldSnapshots", 0); + if (createWorldSnapshots) + { + WorldSnapshotParser::createWorldSnapshots (createWorldSnapshots); + } + else + //-- see if the gameserver is to be run in a mode to scan update ranges + if (ConfigFile::getKeyBool ("SwgGameServer", "verifyUpdateRanges", false)) + { + ServerWorld::install (); + verifyUpdateRanges ("../../exe/win32/serverobjecttemplates.txt"); + ServerWorld::remove (); + } + else + if (!ConfigFile::getKeyBool("SwgGameServer/DataLint", "disable", true)) + { + runDataLint("../../exe/win32/DataLintServer.rsp"); + } + else +#endif // _DEBUG + { + //-- run game + SetupSharedFoundation::callbackWithExceptionHandling(GameServer::run); + } + + NetworkHandler::remove(); + SetupServerGame::remove(); + + SharedRemoteDebugServer::remove(); + SetupSharedLog::remove(); + SetupSharedFoundation::remove(); + SetupSharedThread::remove (); + + return 0; +} + +#ifdef _DEBUG + +void verifyUpdateRanges (const char* const filename) +{ + FILE* const infile = fopen (filename, "rt"); + if (!infile) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: response file %s could not be opened\n", filename)); + return; + } + + char serverObjectTemplateName [1024]; + while (fscanf (infile, "%s", serverObjectTemplateName) != EOF) + { + //-- does the name contain test? + if (strstr (serverObjectTemplateName, "test") != 0) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: skipping test object template %s\n", serverObjectTemplateName)); + continue; + } + + if (strstr (serverObjectTemplateName, "e3_") != 0) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: skipping test object template %s\n", serverObjectTemplateName)); + continue; + } + + //-- get the object template + const ObjectTemplate* const objectTemplate = ObjectTemplateList::fetch (serverObjectTemplateName); + if (!objectTemplate) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: %s is not a valid object template\n", serverObjectTemplateName)); + continue; + } + + //-- make sure its a server object template + const ServerObjectTemplate* const serverObjectTemplate = dynamic_cast (objectTemplate); + if (!serverObjectTemplate) + { + objectTemplate->releaseReference (); + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: %s is not a valid server object template\n", serverObjectTemplateName)); + continue; + } + + //-- make sure it has a shared object template + const std::string& sharedObjectTemplateName = serverObjectTemplate->getSharedTemplate (); + if (sharedObjectTemplateName.empty ()) + { + objectTemplate->releaseReference (); + continue; + } + + //-- make sure the shared template exists + const SharedObjectTemplate* const sharedObjectTemplate = safe_cast (ObjectTemplateList::fetch (sharedObjectTemplateName.c_str ())); + if (!sharedObjectTemplate) + { + DEBUG_REPORT_LOG (true, ("verifyUpdateRanges: %s is not a valid shared object template for server object template %s\n", sharedObjectTemplateName.c_str (), serverObjectTemplateName)); + objectTemplate->releaseReference (); + continue; + } + + const float farUpdateRange = serverObjectTemplate->getUpdateRanges (ServerObjectTemplate::UR_far); + DEBUG_REPORT_LOG (true, ("OK:\t%s\t%s\t%1.1f\n", serverObjectTemplateName, sharedObjectTemplateName.c_str (), farUpdateRange)); + objectTemplate->releaseReference (); + } + fclose(infile); +} + +static std::string currentLintedAsset; +static int m_startIndex = 0; +static int m_numberOfFilesToLint = -1; + +//----------------------------------------------------------------------------- +static int ExceptionHandler(LPEXCEPTION_POINTERS exceptionPointers) +{ + UNREF(exceptionPointers); + + static bool entered = false; + + // make the routine safe from re-entrance + + if (entered) + { + return EXCEPTION_CONTINUE_SEARCH; + } + + entered = true; + + // tell the Os not to abort so we can rethrow the exception + + Os::returnFromAbort(); + + // Let the ExitChain do its job + + DataLint::pushAsset(currentLintedAsset.c_str()); + FATAL(true, ("ExceptionHandler invoked - A crash just occured. The asset is bad or it is constructed improperly with DataLint.")); + DataLint::popAsset(); + + // rethrow the exception so that the debugger can catch it + + return EXCEPTION_CONTINUE_SEARCH; //lint !e527 // Unreachable +} + +//----------------------------------------------------------------------------- +static void lintType(char const *filePath, DataLint::AssetType const assetType, bool const skip) +{ + DataLint::setCurrentAssetType(assetType); + + static int assetNumber = 0; + + if (!skip) + { + DEBUG_REPORT_LOG (true, ("%5i Linting file %s... ", assetNumber, filePath)); + + bool failed = false; + + try + { + switch (assetType) + { + case DataLint::AT_objectTemplate: + { + const ObjectTemplate *objectTemplate = ObjectTemplateList::fetch(filePath); + if (objectTemplate) + { + objectTemplate->testValues(); + + // if file has the directory "base" in it's path, don't + // create an object + if (strstr(filePath, "/base/") == NULL) + { + Object* const object = objectTemplate->createObject (); + delete object; + } + + objectTemplate->releaseReference(); + } + else + { + failed = true; + } + } + break; + case DataLint::AT_unSupported: + { + } + break; + + } + + if (failed) + { + DEBUG_REPORT_LOG (true, ("failed\n")); + } + else + { + DEBUG_REPORT_LOG (true, ("ok\n")); + } + } + catch (FatalException const &e) + { + DEBUG_REPORT_LOG (true, ("failed\n")); + + DataLint::logWarning(e.getMessage()); + } + } + + ++assetNumber; +} + +//----------------------------------------------------------------------------- +static void makeMicrosoftHappyAboutObjectUnWinding(char const *filePath, DataLint::AssetType const assetType, bool const skip) +{ + __try + { + lintType(filePath, assetType, skip); + } + __except (ExceptionHandler(GetExceptionInformation())) + { + } +} + +//----------------------------------------------------------------------------- +static void lint(char const *dataTypeString, DataLint::AssetType const assetType) +{ + DataLint::StringPairList stringPairList(DataLint::getList(assetType)); + DataLint::StringPairList::const_iterator dataLintStringListIter = stringPairList.begin(); + + DEBUG_REPORT_LOG_PRINT(1, ("Linting %d %s assets\n", stringPairList.size(), dataTypeString)); + + int currentIndex = 0; + for (; dataLintStringListIter != stringPairList.end(); ++dataLintStringListIter) + { + { + if ((currentIndex % 10) == 0) + { + //-- see if a file exists to abort + + FILE *file = fopen("stoplint.dat", "rt"); + + if (file) + { + fclose(file); + DEBUG_REPORT_LOG_PRINT(1, ("Stopping all DataLint processing for %s.\n", dataTypeString)); + DataLint::logWarning("Forced DataLint stop. Delete \"stoplint.dat\" to DataLint all the assets."); + break; + } + } + } + + char const *filePath = dataLintStringListIter->first.c_str(); + currentLintedAsset = dataLintStringListIter->second.c_str(); + + //DataLint::pushAsset(filePath); + makeMicrosoftHappyAboutObjectUnWinding(filePath, assetType, (currentIndex < m_startIndex)); + //DataLint::popAsset(); + + DataLint::clearAssetStack(); + ++currentIndex; + + if ((m_numberOfFilesToLint != -1) && (currentIndex >= (m_startIndex + m_numberOfFilesToLint))) + { + break; + } + } +} + +//----------------------------------------------------------------------------- +void runDataLint(char const *responsePath) +{ + ServerObjectLint::install(); + ServerWorld::install(); + DataLint::setServerMode(); + + PerformanceTimer performanceTimer; + performanceTimer.start(); + + FILE *fp = fopen(responsePath, "r"); + + if (fp) + { + // Default to start with the first asset + + m_startIndex = ConfigFile::getKeyInt("SwgGameServer/DataLint", "startIndex", 0); + + // Default to lint all assets + + m_numberOfFilesToLint = ConfigFile::getKeyInt("SwgGameServer/DataLint", "numberOfFilesToLint", -1); + + // Verify this is a valid resonse file + + char text[4096]; + fgets(text, sizeof(text), fp); + + if (strstr(text, "Valid DataLint Rsp") == NULL) + { + DEBUG_REPORT_LOG_PRINT(1, ("DataLint: Invalid Rsp file: %s\n", responsePath)); + +#ifdef WIN32 + char text[4096]; + sprintf(text, "Invalid Rsp file specified: %s. Make sure to run DataLintRspBuilder before running DataLint.", responsePath); + MessageBox(NULL, text, "DataLint Error!", MB_OK | MB_ICONERROR); +#endif // WIN32 + } + else + { + DataLint::install(); + + typedef std::vector StringList; + StringList stringList; + stringList.reserve(32768); + + DEBUG_REPORT_LOG_PRINT(1, ("Loading assets to lint from: %s\n", responsePath)); + + while (fgets(text, sizeof(text), fp)) + { + // Remove the newline character + + char *newLineTest = strchr(text, '\n'); + + if (newLineTest) + { + *newLineTest = '\0'; + } + + // Add the files to the master file list + + stringList.push_back(text); + } + + fclose(fp); + + // Add files to data lint + + DEBUG_REPORT_LOG_PRINT(1, ("Adding %d assets to DataLint to be categorized\n", stringList.size())); + + StringList::iterator stringListIter = stringList.begin(); + + for (; stringListIter != stringList.end(); ++stringListIter) + { + DataLint::addFilePath((*stringListIter).c_str()); + } + + if (ConfigFile::getKeyBool("SwgGameServer/DataLint", "objectTemplate", true)) + { + lint("Objects Template", DataLint::AT_objectTemplate); + } + + DataLint::report(); + } + } + else + { + DEBUG_REPORT_LOG_PRINT(1, ("Bad response path specified: %s", responsePath)); + +#ifdef WIN32 + char text[4096]; + sprintf(text, "Bad response file specified: %s. Make sure to run DataLintRspBuilder before running DataLint.", responsePath); + MessageBox(NULL, text, "DataLint Error!", MB_OK | MB_ICONERROR); +#endif // WIN32 + } + + // Dump the time required to data lint + + performanceTimer.stop(); + float const dataLintTime = performanceTimer.getElapsedTime(); + int const seconds = static_cast(dataLintTime) % 60; + int const minutes = (static_cast(dataLintTime) - seconds) / 60; + DEBUG_REPORT_LOG_PRINT(1, ("DateLint took: %dm %ds\n", minutes, seconds)); +} +#endif // _DEBUG + +//_____________________________________________________________________ diff --git a/game/server/library/swgServerNetworkMessages/src/win32/FirstSwgServerNetworkMessages.cpp b/game/server/library/swgServerNetworkMessages/src/win32/FirstSwgServerNetworkMessages.cpp new file mode 100755 index 00000000..ba4d4d4a --- /dev/null +++ b/game/server/library/swgServerNetworkMessages/src/win32/FirstSwgServerNetworkMessages.cpp @@ -0,0 +1,9 @@ +//======================================================================== +// +// FirstSwgServerNetworkMessages.cpp +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#include "swgServerNetworkMessages/FirstSwgServerNetworkMessages.h" diff --git a/game/shared/library/swgSharedNetworkMessages/src/win32/FirstSwgSharedNetworkMessages.cpp b/game/shared/library/swgSharedNetworkMessages/src/win32/FirstSwgSharedNetworkMessages.cpp new file mode 100755 index 00000000..c29a3b43 --- /dev/null +++ b/game/shared/library/swgSharedNetworkMessages/src/win32/FirstSwgSharedNetworkMessages.cpp @@ -0,0 +1,9 @@ +//======================================================================== +// +// FirstSwgSharedNetworkMessages.cpp +// +// copyright 2001 Sony Online Entertainment +// +//======================================================================== + +#include "swgSharedNetworkMessages/FirstSwgSharedNetworkMessages.h" diff --git a/game/shared/library/swgSharedUtility/src/win32/FirstSwgSharedUtility.cpp b/game/shared/library/swgSharedUtility/src/win32/FirstSwgSharedUtility.cpp new file mode 100755 index 00000000..29d94d84 --- /dev/null +++ b/game/shared/library/swgSharedUtility/src/win32/FirstSwgSharedUtility.cpp @@ -0,0 +1,11 @@ +// ====================================================================== +// +// FirstSwgSharedUtility.cpp +// Copyright 2002 Sony Online Entertainment, Inc. +// All Rights Reserved. +// +// ====================================================================== + +#include "swgSharedUtility/FirstSwgSharedUtility.h" + +// ======================================================================