aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/shared')
-rw-r--r--src/server/shared/Common.h12
-rw-r--r--src/server/shared/CompilerDefs.h6
-rw-r--r--src/server/shared/Containers.h28
-rw-r--r--src/server/shared/DataStores/DBCFileLoader.h3
-rw-r--r--src/server/shared/DataStores/DBCStore.h7
-rw-r--r--src/server/shared/Database/AdhocStatement.cpp4
-rw-r--r--src/server/shared/Database/DatabaseWorker.h5
-rw-r--r--src/server/shared/Database/DatabaseWorkerPool.h25
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp58
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h54
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.cpp12
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.h7
-rw-r--r--src/server/shared/Database/Implementation/WorldDatabase.cpp6
-rw-r--r--src/server/shared/Database/MySQLConnection.h6
-rw-r--r--src/server/shared/Database/PreparedStatement.h6
-rw-r--r--src/server/shared/Database/QueryHolder.cpp3
-rw-r--r--src/server/shared/Database/QueryResult.h5
-rw-r--r--src/server/shared/Database/SQLOperation.h4
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.cpp460
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.h163
-rw-r--r--src/server/shared/Define.h8
-rw-r--r--src/server/shared/Dynamic/HashNamespace.h119
-rw-r--r--src/server/shared/Dynamic/LinkedList.h15
-rw-r--r--src/server/shared/Dynamic/LinkedReference/Reference.h4
-rw-r--r--src/server/shared/Dynamic/ObjectRegistry.h2
-rw-r--r--src/server/shared/Dynamic/UnorderedMap.h72
-rw-r--r--src/server/shared/Dynamic/UnorderedSet.h66
-rw-r--r--src/server/shared/Logging/Appender.h5
-rw-r--r--src/server/shared/Logging/AppenderFile.cpp18
-rw-r--r--src/server/shared/Logging/Log.cpp3
-rw-r--r--src/server/shared/Logging/Log.h54
-rw-r--r--src/server/shared/Packets/ByteBuffer.cpp7
-rw-r--r--src/server/shared/Packets/ByteBuffer.h21
-rw-r--r--src/server/shared/Threading/Callback.h6
-rw-r--r--src/server/shared/Utilities/ByteConverter.h4
-rw-r--r--src/server/shared/Utilities/Util.cpp12
-rw-r--r--src/server/shared/Utilities/Util.h343
37 files changed, 1075 insertions, 558 deletions
diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h
index 5dea589da25..f49bbf0bada 100644
--- a/src/server/shared/Common.h
+++ b/src/server/shared/Common.h
@@ -61,7 +61,7 @@
#include "Define.h"
-#include "Dynamic/UnorderedMap.h"
+#include <unordered_map>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -71,12 +71,6 @@
#include <signal.h>
#include <assert.h>
-#if PLATFORM == PLATFORM_WINDOWS
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
#include <set>
#include <list>
#include <string>
@@ -114,8 +108,6 @@
#include <float.h>
-#define I32FMT "%08I32X"
-#define I64FMT "%016I64X"
#define snprintf _snprintf
#define atoll _atoi64
#define vsnprintf _vsnprintf
@@ -126,8 +118,6 @@
#define stricmp strcasecmp
#define strnicmp strncasecmp
-#define I32FMT "%08X"
-#define I64FMT "%016llX"
#endif
diff --git a/src/server/shared/CompilerDefs.h b/src/server/shared/CompilerDefs.h
index 71b20a4d175..2c2d7ea861d 100644
--- a/src/server/shared/CompilerDefs.h
+++ b/src/server/shared/CompilerDefs.h
@@ -55,10 +55,4 @@
# error "FATAL ERROR: Unknown compiler."
#endif
-#if defined(__cplusplus) && __cplusplus == 201103L
-# define COMPILER_HAS_CPP11_SUPPORT 1
-#else
-# define COMPILER_HAS_CPP11_SUPPORT 0
-#endif
-
#endif
diff --git a/src/server/shared/Containers.h b/src/server/shared/Containers.h
index d6ba98e4ed4..9121fbe2a97 100644
--- a/src/server/shared/Containers.h
+++ b/src/server/shared/Containers.h
@@ -64,6 +64,34 @@ namespace Trinity
std::advance(it, urand(0, container.size() - 1));
return *it;
}
+
+ /**
+ * @fn bool Trinity::Containers::Intersects(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
+ *
+ * @brief Checks if two SORTED containers have a common element
+ *
+ * @param first1 Iterator pointing to start of the first container
+ * @param last1 Iterator pointing to end of the first container
+ * @param first2 Iterator pointing to start of the second container
+ * @param last2 Iterator pointing to end of the second container
+ *
+ * @return true if containers have a common element, false otherwise.
+ */
+ template<class Iterator1, class Iterator2>
+ bool Intersects(Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
+ {
+ while (first1 != last1 && first2 != last2)
+ {
+ if (*first1 < *first2)
+ ++first1;
+ else if (*first2 < *first1)
+ ++first2;
+ else
+ return true;
+ }
+
+ return false;
+ }
}
//! namespace Containers
}
diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h
index c5194d20530..a665bc49c9c 100644
--- a/src/server/shared/DataStores/DBCFileLoader.h
+++ b/src/server/shared/DataStores/DBCFileLoader.h
@@ -106,5 +106,8 @@ class DBCFileLoader
uint32 *fieldsOffset;
unsigned char *data;
unsigned char *stringTable;
+
+ DBCFileLoader(DBCFileLoader const& right) = delete;
+ DBCFileLoader& operator=(DBCFileLoader const& right) = delete;
};
#endif
diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h
index 78f7bb28580..08b8d810b8b 100644
--- a/src/server/shared/DataStores/DBCStore.h
+++ b/src/server/shared/DataStores/DBCStore.h
@@ -63,6 +63,10 @@ struct SqlDbc
}
}
}
+
+private:
+ SqlDbc(SqlDbc const& right) = delete;
+ SqlDbc& operator=(SqlDbc const& right) = delete;
};
template<class T>
@@ -291,6 +295,9 @@ class DBCStorage
T* dataTable;
StringPoolList stringPoolList;
+
+ DBCStorage(DBCStorage const& right) = delete;
+ DBCStorage& operator=(DBCStorage const& right) = delete;
};
#endif
diff --git a/src/server/shared/Database/AdhocStatement.cpp b/src/server/shared/Database/AdhocStatement.cpp
index 15732f20849..896fefde5b7 100644
--- a/src/server/shared/Database/AdhocStatement.cpp
+++ b/src/server/shared/Database/AdhocStatement.cpp
@@ -42,13 +42,13 @@ bool BasicStatementTask::Execute()
if (m_has_result)
{
ResultSet* result = m_conn->Query(m_sql);
- if (!result || !result->GetRowCount())
+ if (!result || !result->GetRowCount() || !result->NextRow())
{
delete result;
m_result.set(QueryResult(NULL));
return false;
}
- result->NextRow();
+
m_result.set(QueryResult(result));
return true;
}
diff --git a/src/server/shared/Database/DatabaseWorker.h b/src/server/shared/Database/DatabaseWorker.h
index 14e92924ed2..dc883dd3428 100644
--- a/src/server/shared/Database/DatabaseWorker.h
+++ b/src/server/shared/Database/DatabaseWorker.h
@@ -18,6 +18,7 @@
#ifndef _WORKERTHREAD_H
#define _WORKERTHREAD_H
+#include "Define.h"
#include <ace/Task.h>
#include <ace/Activation_Queue.h>
@@ -33,9 +34,11 @@ class DatabaseWorker : protected ACE_Task_Base
int wait() { return ACE_Task_Base::wait(); }
private:
- DatabaseWorker() : ACE_Task_Base() { }
ACE_Activation_Queue* m_queue;
MySQLConnection* m_conn;
+
+ DatabaseWorker(DatabaseWorker const& right) = delete;
+ DatabaseWorker& operator=(DatabaseWorker const& right) = delete;
};
#endif
diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h
index 6c2e961d2ad..9c56c75bf71 100644
--- a/src/server/shared/Database/DatabaseWorkerPool.h
+++ b/src/server/shared/Database/DatabaseWorkerPool.h
@@ -49,9 +49,10 @@ class DatabaseWorkerPool
{
public:
/* Activity state */
- DatabaseWorkerPool() :
- _queue(new ACE_Activation_Queue())
+ DatabaseWorkerPool() : _connectionInfo(NULL)
{
+ _messageQueue = new ACE_Message_Queue<ACE_SYNCH>(8 * 1024 * 1024, 8 * 1024 * 1024);
+ _queue = new ACE_Activation_Queue(_messageQueue);
memset(_connectionCount, 0, sizeof(_connectionCount));
_connections.resize(IDX_SIZE);
@@ -66,7 +67,7 @@ class DatabaseWorkerPool
bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads)
{
bool res = true;
- _connectionInfo = MySQLConnectionInfo(infoString);
+ _connectionInfo = new MySQLConnectionInfo(infoString);
TC_LOG_INFO("sql.driver", "Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.",
GetDatabaseName(), async_threads, synch_threads);
@@ -75,7 +76,7 @@ class DatabaseWorkerPool
_connections[IDX_ASYNC].resize(async_threads);
for (uint8 i = 0; i < async_threads; ++i)
{
- T* t = new T(_queue, _connectionInfo);
+ T* t = new T(_queue, *_connectionInfo);
res &= t->Open();
if (res) // only check mysql version if connection is valid
WPFatal(mysql_get_server_version(t->GetHandle()) >= MIN_MYSQL_SERVER_VERSION, "TrinityCore does not support MySQL versions below 5.1");
@@ -87,7 +88,7 @@ class DatabaseWorkerPool
_connections[IDX_SYNCH].resize(synch_threads);
for (uint8 i = 0; i < synch_threads; ++i)
{
- T* t = new T(_connectionInfo);
+ T* t = new T(*_connectionInfo);
res &= t->Open();
_connections[IDX_SYNCH][i] = t;
++_connectionCount[IDX_SYNCH];
@@ -98,7 +99,7 @@ class DatabaseWorkerPool
(_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
else
TC_LOG_ERROR("sql.driver", "DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile "
- "for specific errors.", GetDatabaseName());
+ "for specific errors. Read wiki at http://collab.kpsn.org/display/tc/TrinityCore+Home", GetDatabaseName());
return res;
}
@@ -132,8 +133,12 @@ class DatabaseWorkerPool
//! Deletes the ACE_Activation_Queue object and its underlying ACE_Message_Queue
delete _queue;
+ delete _messageQueue;
TC_LOG_INFO("sql.driver", "All connections on DatabasePool '%s' closed.", GetDatabaseName());
+
+ delete _connectionInfo;
+ _connectionInfo = NULL;
}
/**
@@ -232,13 +237,12 @@ class DatabaseWorkerPool
ResultSet* result = conn->Query(sql);
conn->Unlock();
- if (!result || !result->GetRowCount())
+ if (!result || !result->GetRowCount() || !result->NextRow())
{
delete result;
return QueryResult(NULL);
}
- result->NextRow();
return QueryResult(result);
}
@@ -508,7 +512,7 @@ class DatabaseWorkerPool
char const* GetDatabaseName() const
{
- return _connectionInfo.database.c_str();
+ return _connectionInfo->database.c_str();
}
private:
@@ -519,10 +523,11 @@ class DatabaseWorkerPool
IDX_SIZE
};
+ ACE_Message_Queue<ACE_SYNCH>* _messageQueue; //! Message Queue used by ACE_Activation_Queue
ACE_Activation_Queue* _queue; //! Queue shared by async worker threads.
std::vector< std::vector<T*> > _connections;
uint32 _connectionCount[2]; //! Counter of MySQL connections;
- MySQLConnectionInfo _connectionInfo;
+ MySQLConnectionInfo* _connectionInfo;
};
#endif
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index aa7c2e96fba..24e61e7399a 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -59,18 +59,10 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender, level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH);
- PrepareStatement(CHAR_DEL_QUEST_STATUS_DAILY, "DELETE FROM character_queststatus_daily", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_QUEST_STATUS_WEEKLY, "DELETE FROM character_queststatus_weekly", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_QUEST_STATUS_MONTHLY, "DELETE FROM character_queststatus_monthly", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_QUEST_STATUS_SEASONAL, "DELETE FROM character_queststatus_seasonal WHERE event = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_QUEST_STATUS_DAILY_CHAR, "DELETE FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_QUEST_STATUS_WEEKLY_CHAR, "DELETE FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_QUEST_STATUS_MONTHLY_CHAR, "DELETE FROM character_queststatus_monthly WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_QUEST_STATUS_SEASONAL_CHAR, "DELETE FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC);
+
PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM, "DELETE FROM character_battleground_random", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_BATTLEGROUND_RANDOM, "INSERT INTO character_battleground_random (guid) VALUES (?)", CONNECTION_ASYNC);
- // Start LoginQueryHolder content
PrepareStatement(CHAR_SEL_CHARACTER, "SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
"position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, "
"resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, instance_mode_mask, "
@@ -85,14 +77,24 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, explored, timer, mobcount1, mobcount2, mobcount3, mobcount4, "
"itemcount1, itemcount2, itemcount3, itemcount4, playercount FROM character_queststatus WHERE guid = ? AND status <> 0", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_DAILYQUESTSTATUS, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_WEEKLYQUESTSTATUS, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_MONTHLYQUESTSTATUS, "SELECT quest FROM character_queststatus_monthly WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_SEL_CHARACTER_SEASONALQUESTSTATUS, "SELECT quest, event FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHARACTER_DAILYQUESTSTATUS, "INSERT INTO character_queststatus_daily (guid, quest, time) VALUES (?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS, "INSERT INTO character_queststatus_weekly (guid, quest) VALUES (?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHARACTER_MONTHLYQUESTSTATUS, "INSERT INTO character_queststatus_monthly (guid, quest) VALUES (?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_CHARACTER_SEASONALQUESTSTATUS, "INSERT INTO character_queststatus_seasonal (guid, quest, event) VALUES (?, ?, ?)", CONNECTION_ASYNC);
+
+ PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_MONTHLY, "SELECT quest FROM character_queststatus_monthly WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_SEASONAL, "SELECT quest, event FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_WEEKLY, "DELETE FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_MONTHLY, "DELETE FROM character_queststatus_monthly WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_QUESTSTATUS_SEASONAL, "DELETE FROM character_queststatus_seasonal WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_QUESTSTATUS_DAILY, "INSERT INTO character_queststatus_daily (guid, quest, time) VALUES (?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_QUESTSTATUS_WEEKLY, "INSERT INTO character_queststatus_weekly (guid, quest) VALUES (?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_QUESTSTATUS_MONTHLY, "INSERT INTO character_queststatus_monthly (guid, quest) VALUES (?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHARACTER_QUESTSTATUS_SEASONAL, "INSERT INTO character_queststatus_seasonal (guid, quest, event) VALUES (?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_WEEKLY, "DELETE FROM character_queststatus_weekly", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_MONTHLY, "DELETE FROM character_queststatus_monthly", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT, "DELETE FROM character_queststatus_seasonal WHERE event = ?", CONNECTION_ASYNC);
+
PrepareStatement(CHAR_SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_INVENTORY, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, bag, slot, "
"item, itemEntry FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid WHERE ci.guid = ? ORDER BY bag, slot", CONNECTION_ASYNC);
@@ -120,7 +122,6 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_BANNED, "SELECT guid FROM character_banned WHERE guid = ? AND active = 1", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUSREW, "SELECT quest FROM character_queststatus_rewarded WHERE guid = ? AND active = 1", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_ACCOUNT_INSTANCELOCKTIMES, "SELECT instanceId, releaseTime FROM account_instance_times WHERE accountId = ?", CONNECTION_ASYNC);
- // End LoginQueryHolder content
PrepareStatement(CHAR_SEL_CHARACTER_ACTIONS_SPEC, "SELECT button, action, type FROM character_action WHERE guid = ? AND spec = ? ORDER BY button", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_MAILITEMS, "SELECT creatorGuid, giftCreatorGuid, count, duration, charges, flags, enchantments, randomPropertyId, durability, playedTime, text, item_guid, itemEntry, owner_guid FROM mail_items mi JOIN item_instance ii ON mi.item_guid = ii.guid WHERE mail_id = ?", CONNECTION_SYNCH);
@@ -375,7 +376,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_PETITION_NAME, "UPDATE petition SET name = ? WHERE petitionguid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_PETITION_SIGNATURE, "INSERT INTO petition_sign (ownerguid, petitionguid, playerguid, player_account) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ACCOUNT_ONLINE, "UPDATE characters SET online = 0 WHERE account = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_INS_GROUP, "INSERT INTO groups (guid, leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_GROUP, "INSERT INTO groups (guid, leaderGuid, lootMethod, looterGuid, lootThreshold, icon1, icon2, icon3, icon4, icon5, icon6, icon7, icon8, groupType, difficulty, raiddifficulty, masterLooterGuid) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_GROUP_MEMBER, "INSERT INTO group_member (guid, memberGuid, memberFlags, subgroup, roles) VALUES(?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GROUP_MEMBER, "DELETE FROM group_member WHERE memberGuid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GROUP_INSTANCE_PERM_BINDING, "DELETE FROM group_instance WHERE guid = ? AND instance = ?", CONNECTION_ASYNC);
@@ -389,7 +390,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_INVALID_SPELL_TALENTS, "DELETE FROM character_talent WHERE spell = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_INVALID_SPELL_SPELLS, "DELETE FROM character_spell WHERE spell = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_DELETE_INFO, "UPDATE characters SET deleteInfos_Name = name, deleteInfos_Account = account, deleteDate = UNIX_TIMESTAMP(), name = '', account = 0 WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_RESTORE_DELETE_INFO, "UPDATE characters SET name = ?, account = ?, deleteDate = NULL, deleteInfos_Name = NULL, deleteInfos_Account = NULL WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_RESTORE_DELETE_INFO, "UPDATE characters SET name = ?, account = ?, deleteDate = NULL, deleteInfos_Name = NULL, deleteInfos_Account = NULL WHERE deleteDate IS NOT NULL AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ZONE, "UPDATE characters SET zone = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_LEVEL, "UPDATE characters SET level = ?, xp = 0 WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA, "DELETE FROM character_achievement_progress WHERE criteria = ?", CONNECTION_ASYNC);
@@ -463,7 +464,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS, "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_REPUTATION_BY_FACTION, "DELETE FROM character_reputation WHERE guid = ? AND faction = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_REPUTATION_BY_FACTION, "INSERT INTO character_reputation (guid, faction, standing, flags) VALUES (?, ?, ? , ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UPD_CHAR_ARENA_POINTS, "UPDATE characters SET arenaPoints = (arenaPoints + ?) WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_ADD_CHAR_ARENA_POINTS, "UPDATE characters SET arenaPoints = (arenaPoints + ?) WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_ITEM_REFUND_INSTANCE, "DELETE FROM item_refund_instance WHERE item_guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_ITEM_REFUND_INSTANCE, "INSERT INTO item_refund_instance (item_guid, player_guid, paidMoney, paidExtendedCost) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GROUP, "DELETE FROM groups WHERE guid = ?", CONNECTION_ASYNC);
@@ -515,12 +516,11 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER, "DELETE FROM guild_eventlog WHERE PlayerGuid1 = ? OR PlayerGuid2 = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_GUILD_BANK_EVENTLOG_BY_PLAYER, "DELETE FROM guild_bank_eventlog WHERE PlayerGuid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_GLYPHS, "DELETE FROM character_glyphs WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_DAILY, "DELETE FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_TALENT, "DELETE FROM character_talent WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SKILLS, "DELETE FROM character_skills WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_HONOR_POINTS, "UPDATE characters SET totalHonorPoints = ? WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_ARENA_POINTS, "UPDATE characters SET arenaPoints = ? WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_MONEY, "UPDATE characters SET money = ? WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_HONOR_POINTS, "UPDATE characters SET totalHonorPoints = ? WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_ARENA_POINTS, "UPDATE characters SET arenaPoints = ? WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_MONEY, "UPDATE characters SET money = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_ACTION, "INSERT INTO character_action (guid, spec, button, action, type) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_ACTION, "UPDATE character_action SET action = ?, type = ? WHERE guid = ? AND button = ? AND spec = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC, "DELETE FROM character_action WHERE guid = ? and button = ? and spec = ?", CONNECTION_ASYNC);
@@ -536,7 +536,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST, "UPDATE character_queststatus_rewarded SET active = 0 WHERE quest = ? AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SKILL_BY_SKILL, "DELETE FROM character_skills WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_SKILLS, "INSERT INTO character_skills (guid, skill, value, max) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_SKILLS, "UPDATE character_skills SET value = ?, max = ? WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_SKILLS, "UPDATE character_skills SET value = ?, max = ? WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_SPELL, "INSERT INTO character_spell (guid, spell, active, disabled) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_STATS, "DELETE FROM character_stats WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_STATS, "INSERT INTO character_stats (guid, maxhealth, maxpower1, maxpower2, maxpower3, maxpower4, maxpower5, maxpower6, maxpower7, strength, agility, stamina, intellect, spirit, "
@@ -576,7 +576,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHAR_PETS, "SELECT id FROM character_pet WHERE owner = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME_BY_OWNER, "DELETE FROM character_pet_declinedname WHERE owner = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_PET_DECLINEDNAME, "DELETE FROM character_pet_declinedname WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_ADD_CHAR_PET_DECLINEDNAME, "INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHAR_PET_DECLINEDNAME, "INSERT INTO character_pet_declinedname (id, owner, genitive, dative, accusative, instrumental, prepositional) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_PET_AURA, "SELECT caster_guid, spell, effect_mask, recalculate_mask, stackcount, amount0, amount1, amount2, base_amount0, base_amount1, base_amount2, maxduration, remaintime, remaincharges FROM pet_aura WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PET_SPELL, "SELECT spell, active FROM pet_spell WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_PET_SPELL_COOLDOWN, "SELECT spell, time FROM pet_spell_cooldown WHERE guid = ?", CONNECTION_SYNCH);
@@ -595,8 +595,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT, "SELECT id, entry, owner, modelid, level, exp, Reactstate, slot, name, renamed, curhealth, curmana, curhappiness, abdata, savetime, CreatedBySpell, PetType FROM character_pet WHERE owner = ? AND slot = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_DEL_CHAR_PET_BY_OWNER, "DELETE FROM character_pet WHERE owner = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_PET_NAME, "UPDATE character_pet SET name = ?, renamed = 1 WHERE owner = ? AND id = ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID, "UPDATE character_pet SET slot = ? WHERE owner = ? AND slot = ? AND id <> ?", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UDP_CHAR_PET_SLOT_BY_SLOT, "UPDATE character_pet SET slot = ? WHERE owner = ? AND slot = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID, "UPDATE character_pet SET slot = ? WHERE owner = ? AND slot = ? AND id <> ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHAR_PET_SLOT_BY_SLOT, "UPDATE character_pet SET slot = ? WHERE owner = ? AND slot = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_PET_SLOT_BY_ID, "UPDATE character_pet SET slot = ? WHERE owner = ? AND id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_PET_BY_ID, "DELETE FROM character_pet WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_PET_BY_SLOT, "DELETE FROM character_pet WHERE owner = ? AND (slot = ? OR slot > ?)", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index 6768e4a197f..98d7fe231f1 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -71,14 +71,7 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHARACTER_NAME_DATA,
CHAR_SEL_CHAR_POSITION_XYZ,
CHAR_SEL_CHAR_POSITION,
- CHAR_DEL_QUEST_STATUS_DAILY,
- CHAR_DEL_QUEST_STATUS_WEEKLY,
- CHAR_DEL_QUEST_STATUS_MONTHLY,
- CHAR_DEL_QUEST_STATUS_SEASONAL,
- CHAR_DEL_QUEST_STATUS_DAILY_CHAR,
- CHAR_DEL_QUEST_STATUS_WEEKLY_CHAR,
- CHAR_DEL_QUEST_STATUS_MONTHLY_CHAR,
- CHAR_DEL_QUEST_STATUS_SEASONAL_CHAR,
+
CHAR_DEL_BATTLEGROUND_RANDOM,
CHAR_INS_BATTLEGROUND_RANDOM,
@@ -88,14 +81,24 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHARACTER_AURAS,
CHAR_SEL_CHARACTER_SPELL,
CHAR_SEL_CHARACTER_QUESTSTATUS,
- CHAR_SEL_CHARACTER_DAILYQUESTSTATUS,
- CHAR_SEL_CHARACTER_WEEKLYQUESTSTATUS,
- CHAR_SEL_CHARACTER_MONTHLYQUESTSTATUS,
- CHAR_SEL_CHARACTER_SEASONALQUESTSTATUS,
- CHAR_INS_CHARACTER_DAILYQUESTSTATUS,
- CHAR_INS_CHARACTER_WEEKLYQUESTSTATUS,
- CHAR_INS_CHARACTER_MONTHLYQUESTSTATUS,
- CHAR_INS_CHARACTER_SEASONALQUESTSTATUS,
+
+ CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY,
+ CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY,
+ CHAR_SEL_CHARACTER_QUESTSTATUS_MONTHLY,
+ CHAR_SEL_CHARACTER_QUESTSTATUS_SEASONAL,
+ CHAR_DEL_CHARACTER_QUESTSTATUS_DAILY,
+ CHAR_DEL_CHARACTER_QUESTSTATUS_WEEKLY,
+ CHAR_DEL_CHARACTER_QUESTSTATUS_MONTHLY,
+ CHAR_DEL_CHARACTER_QUESTSTATUS_SEASONAL,
+ CHAR_INS_CHARACTER_QUESTSTATUS_DAILY,
+ CHAR_INS_CHARACTER_QUESTSTATUS_WEEKLY,
+ CHAR_INS_CHARACTER_QUESTSTATUS_MONTHLY,
+ CHAR_INS_CHARACTER_QUESTSTATUS_SEASONAL,
+ CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_DAILY,
+ CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_WEEKLY,
+ CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_MONTHLY,
+ CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT,
+
CHAR_SEL_CHARACTER_REPUTATION,
CHAR_SEL_CHARACTER_INVENTORY,
CHAR_SEL_CHARACTER_ACTIONS,
@@ -326,7 +329,7 @@ enum CharacterDatabaseStatements
CHAR_DEL_INVALID_SPELL_SPELLS,
CHAR_DEL_INVALID_SPELL_TALENTS,
CHAR_UPD_DELETE_INFO,
- CHAR_UDP_RESTORE_DELETE_INFO,
+ CHAR_UPD_RESTORE_DELETE_INFO,
CHAR_UPD_ZONE,
CHAR_UPD_LEVEL,
CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA,
@@ -399,7 +402,7 @@ enum CharacterDatabaseStatements
CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS,
CHAR_DEL_CHAR_REPUTATION_BY_FACTION,
CHAR_INS_CHAR_REPUTATION_BY_FACTION,
- CHAR_UPD_CHAR_ARENA_POINTS,
+ CHAR_UPD_ADD_CHAR_ARENA_POINTS,
CHAR_DEL_ITEM_REFUND_INSTANCE,
CHAR_INS_ITEM_REFUND_INSTANCE,
CHAR_DEL_GROUP,
@@ -451,12 +454,11 @@ enum CharacterDatabaseStatements
CHAR_DEL_GUILD_EVENTLOG_BY_PLAYER,
CHAR_DEL_GUILD_BANK_EVENTLOG_BY_PLAYER,
CHAR_DEL_CHAR_GLYPHS,
- CHAR_DEL_CHAR_QUESTSTATUS_DAILY,
CHAR_DEL_CHAR_TALENT,
CHAR_DEL_CHAR_SKILLS,
- CHAR_UDP_CHAR_HONOR_POINTS,
- CHAR_UDP_CHAR_ARENA_POINTS,
- CHAR_UDP_CHAR_MONEY,
+ CHAR_UPD_CHAR_HONOR_POINTS,
+ CHAR_UPD_CHAR_ARENA_POINTS,
+ CHAR_UPD_CHAR_MONEY,
CHAR_INS_CHAR_ACTION,
CHAR_UPD_CHAR_ACTION,
CHAR_DEL_CHAR_ACTION_BY_BUTTON_SPEC,
@@ -472,7 +474,7 @@ enum CharacterDatabaseStatements
CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST,
CHAR_DEL_CHAR_SKILL_BY_SKILL,
CHAR_INS_CHAR_SKILLS,
- CHAR_UDP_CHAR_SKILLS,
+ CHAR_UPD_CHAR_SKILLS,
CHAR_INS_CHAR_SPELL,
CHAR_DEL_CHAR_STATS,
CHAR_INS_CHAR_STATS,
@@ -516,10 +518,10 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHAR_PET_BY_ENTRY_AND_SLOT_2,
CHAR_SEL_CHAR_PET_BY_SLOT,
CHAR_DEL_CHAR_PET_DECLINEDNAME,
- CHAR_ADD_CHAR_PET_DECLINEDNAME,
+ CHAR_INS_CHAR_PET_DECLINEDNAME,
CHAR_UPD_CHAR_PET_NAME,
- CHAR_UDP_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID,
- CHAR_UDP_CHAR_PET_SLOT_BY_SLOT,
+ CHAR_UPD_CHAR_PET_SLOT_BY_SLOT_EXCLUDE_ID,
+ CHAR_UPD_CHAR_PET_SLOT_BY_SLOT,
CHAR_UPD_CHAR_PET_SLOT_BY_ID,
CHAR_DEL_CHAR_PET_BY_ID,
CHAR_DEL_CHAR_PET_BY_SLOT,
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp
index de1e5b992e6..488ff18dca4 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp
@@ -69,6 +69,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_UPD_MUTE_TIME, "UPDATE account SET mutetime = ? , mutereason = ? , muteby = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_MUTE_TIME_LOGIN, "UPDATE account SET mutetime = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_LAST_IP, "UPDATE account SET last_ip = ? WHERE username = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_UPD_LAST_ATTEMPT_IP, "UPDATE account SET last_attempt_ip = ? WHERE username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_ACCOUNT_ONLINE, "UPDATE account SET online = 1 WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_UPTIME_PLAYERS, "UPDATE uptime SET uptime = ?, maxplayers = ? WHERE realmid = ? AND starttime = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_OLD_LOGS, "DELETE FROM logs WHERE (time + ?) < ?", CONNECTION_ASYNC);
@@ -90,12 +91,21 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_ACCOUNT_RECRUITER, "SELECT 1 FROM account WHERE recruiter = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BANS, "SELECT 1 FROM account_banned WHERE id = ? AND active = 1 UNION SELECT 1 FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_WHOIS, "SELECT username, email, last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_LAST_ATTEMPT_IP, "SELECT last_attempt_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_LAST_IP, "SELECT last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL, "SELECT allowedSecurityLevel from realmlist WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationCountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_AUTOBROADCAST, "SELECT id, weight, text FROM autobroadcast WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_GET_EMAIL_BY_ID, "SELECT email FROM account WHERE id = ?", CONNECTION_SYNCH);
-
+ // 0: uint32, 1: uint32, 2: uint8, 3: uint32, 4: string // Complete name: "Login_Insert_AccountLoginDeLete_IP_Logging"
+ PrepareStatement(LOGIN_INS_ALDL_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES (?, ?, ?, (SELECT last_ip FROM account WHERE id = ?), ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
+ // 0: uint32, 1: uint32, 2: uint8, 3: uint32, 4: string // Complete name: "Login_Insert_FailedAccountLogin_IP_Logging"
+ PrepareStatement(LOGIN_INS_FACL_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES (?, ?, ?, (SELECT last_attempt_ip FROM account WHERE id = ?), ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
+ // 0: uint32, 1: uint32, 2: uint8, 3: string, 4: string // Complete name: "Login_Insert_CharacterDelete_IP_Logging"
+ PrepareStatement(LOGIN_INS_CHAR_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES (?, ?, ?, ?, ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
+ // 0: string, 1: string, 2: string // Complete name: "Login_Insert_Failed_Account_Login_due_password_IP_Logging"
+ PrepareStatement(LOGIN_INS_FALP_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES ((SELECT id FROM account WHERE username = ?), 0, 1, ?, ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, "SELECT gmlevel, RealmID FROM account_access WHERE id = ? and (RealmID = ? OR RealmID = -1) ORDER BY gmlevel desc", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS, "SELECT permissionId, granted FROM rbac_account_permissions WHERE accountId = ? AND (realmId = ? OR realmId = -1) ORDER BY permissionId, realmId", CONNECTION_SYNCH);
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h
index 01f9fd973b6..604e9d39551 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.h
+++ b/src/server/shared/Database/Implementation/LoginDatabase.h
@@ -89,6 +89,7 @@ enum LoginDatabaseStatements
LOGIN_UPD_MUTE_TIME,
LOGIN_UPD_MUTE_TIME_LOGIN,
LOGIN_UPD_LAST_IP,
+ LOGIN_UPD_LAST_ATTEMPT_IP,
LOGIN_UPD_ACCOUNT_ONLINE,
LOGIN_UPD_UPTIME_PLAYERS,
LOGIN_DEL_OLD_LOGS,
@@ -114,7 +115,13 @@ enum LoginDatabaseStatements
LOGIN_DEL_ACCOUNT,
LOGIN_SEL_IP2NATION_COUNTRY,
LOGIN_SEL_AUTOBROADCAST,
+ LOGIN_SEL_LAST_ATTEMPT_IP,
+ LOGIN_SEL_LAST_IP,
LOGIN_GET_EMAIL_BY_ID,
+ LOGIN_INS_ALDL_IP_LOGGING,
+ LOGIN_INS_FACL_IP_LOGGING,
+ LOGIN_INS_CHAR_IP_LOGGING,
+ LOGIN_INS_FALP_IP_LOGGING,
LOGIN_SEL_ACCOUNT_ACCESS_BY_ID,
LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS,
diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp
index 644d3b330fb..d0e9c463ad7 100644
--- a/src/server/shared/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp
@@ -25,7 +25,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_QUEST_POOLS, "SELECT entry, pool_entry FROM pool_quest", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_CRELINKED_RESPAWN, "DELETE FROM linked_respawn WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_REP_CREATURE_LINKED_RESPAWN, "REPLACE INTO linked_respawn (guid, linkedGuid) VALUES (?, ?)", CONNECTION_ASYNC);
- PrepareStatement(WORLD_SEL_CREATURE_TEXT, "SELECT entry, groupid, id, text, type, language, probability, emote, duration, sound FROM creature_text", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_SEL_CREATURE_TEXT, "SELECT entry, groupid, id, text, type, language, probability, emote, duration, sound, BroadcastTextID FROM creature_text", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_SMART_SCRIPTS, "SELECT entryorguid, source_type, id, link, event_type, event_phase_mask, event_chance, event_flags, event_param1, event_param2, event_param3, event_param4, action_type, action_param1, action_param2, action_param3, action_param4, action_param5, action_param6, target_type, target_param1, target_param2, target_param3, target_x, target_y, target_z, target_o FROM smart_scripts ORDER BY entryorguid, source_type, id, link", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_SMARTAI_WP, "SELECT entry, pointid, position_x, position_y, position_z FROM waypoints ORDER BY entry, pointid", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_GAMEOBJECT, "DELETE FROM gameobject WHERE guid = ?", CONNECTION_ASYNC);
@@ -38,7 +38,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_DEL_NPC_VENDOR, "DELETE FROM npc_vendor WHERE entry = ? AND item = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_NPC_VENDOR_REF, "SELECT item, maxcount, incrtime, ExtendedCost FROM npc_vendor WHERE entry = ? ORDER BY slot ASC", CONNECTION_SYNCH);
PrepareStatement(WORLD_UPD_CREATURE_MOVEMENT_TYPE, "UPDATE creature SET MovementType = ? WHERE guid = ?", CONNECTION_ASYNC);
- PrepareStatement(WORLD_UPD_CREATURE_FACTION, "UPDATE creature_template SET faction_A = ?, faction_H = ? WHERE entry = ?", CONNECTION_ASYNC);
+ PrepareStatement(WORLD_UPD_CREATURE_FACTION, "UPDATE creature_template SET faction = ? WHERE entry = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_NPCFLAG, "UPDATE creature_template SET npcflag = ? WHERE entry = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_POSITION, "UPDATE creature SET position_x = ?, position_y = ?, position_z = ?, orientation = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_SPAWN_DISTANCE, "UPDATE creature SET spawndist = ?, MovementType = ? WHERE guid = ?", CONNECTION_ASYNC);
@@ -76,7 +76,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, permission, help FROM command", CONNECTION_SYNCH);
- PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
+ PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
diff --git a/src/server/shared/Database/MySQLConnection.h b/src/server/shared/Database/MySQLConnection.h
index 161f459a7ad..512df7c16c7 100644
--- a/src/server/shared/Database/MySQLConnection.h
+++ b/src/server/shared/Database/MySQLConnection.h
@@ -38,8 +38,7 @@ enum ConnectionFlags
struct MySQLConnectionInfo
{
- MySQLConnectionInfo() { }
- MySQLConnectionInfo(const std::string& infoString)
+ explicit MySQLConnectionInfo(std::string const& infoString)
{
Tokenizer tokens(infoString, ';');
@@ -132,6 +131,9 @@ class MySQLConnection
MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging)
ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements)
ACE_Thread_Mutex m_Mutex;
+
+ MySQLConnection(MySQLConnection const& right) = delete;
+ MySQLConnection& operator=(MySQLConnection const& right) = delete;
};
#endif
diff --git a/src/server/shared/Database/PreparedStatement.h b/src/server/shared/Database/PreparedStatement.h
index 6a4d03bfb4d..6afb309db2c 100644
--- a/src/server/shared/Database/PreparedStatement.h
+++ b/src/server/shared/Database/PreparedStatement.h
@@ -101,6 +101,9 @@ class PreparedStatement
MySQLPreparedStatement* m_stmt;
uint32 m_index;
std::vector<PreparedStatementData> statement_data; //- Buffer of parameters, not tied to MySQL in any way yet
+
+ PreparedStatement(PreparedStatement const& right) = delete;
+ PreparedStatement& operator=(PreparedStatement const& right) = delete;
};
//- Class of which the instances are unique per MySQLConnection
@@ -145,6 +148,9 @@ class MySQLPreparedStatement
uint32 m_paramCount;
std::vector<bool> m_paramsSet;
MYSQL_BIND* m_bind;
+
+ MySQLPreparedStatement(MySQLPreparedStatement const& right) = delete;
+ MySQLPreparedStatement& operator=(MySQLPreparedStatement const& right) = delete;
};
typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture;
diff --git a/src/server/shared/Database/QueryHolder.cpp b/src/server/shared/Database/QueryHolder.cpp
index 0c80f70acd2..7b4105ee076 100644
--- a/src/server/shared/Database/QueryHolder.cpp
+++ b/src/server/shared/Database/QueryHolder.cpp
@@ -89,10 +89,9 @@ QueryResult SQLQueryHolder::GetResult(size_t index)
if (index < m_queries.size())
{
ResultSet* result = m_queries[index].second.qresult;
- if (!result || !result->GetRowCount())
+ if (!result || !result->GetRowCount() || !result->NextRow())
return QueryResult(NULL);
- result->NextRow();
return QueryResult(result);
}
else
diff --git a/src/server/shared/Database/QueryResult.h b/src/server/shared/Database/QueryResult.h
index 74320aeba19..4795fef4a4c 100644
--- a/src/server/shared/Database/QueryResult.h
+++ b/src/server/shared/Database/QueryResult.h
@@ -55,6 +55,9 @@ class ResultSet
void CleanUp();
MYSQL_RES* _result;
MYSQL_FIELD* _fields;
+
+ ResultSet(ResultSet const& right) = delete;
+ ResultSet& operator=(ResultSet const& right) = delete;
};
typedef Trinity::AutoPtr<ResultSet, ACE_Thread_Mutex> QueryResult;
@@ -100,6 +103,8 @@ class PreparedResultSet
void CleanUp();
bool _NextRow();
+ PreparedResultSet(PreparedResultSet const& right) = delete;
+ PreparedResultSet& operator=(PreparedResultSet const& right) = delete;
};
typedef Trinity::AutoPtr<PreparedResultSet, ACE_Thread_Mutex> PreparedQueryResult;
diff --git a/src/server/shared/Database/SQLOperation.h b/src/server/shared/Database/SQLOperation.h
index 2c404c131ae..6f933a051e3 100644
--- a/src/server/shared/Database/SQLOperation.h
+++ b/src/server/shared/Database/SQLOperation.h
@@ -69,6 +69,10 @@ class SQLOperation : public ACE_Method_Request
virtual void SetConnection(MySQLConnection* con) { m_conn = con; }
MySQLConnection* m_conn;
+
+ private:
+ SQLOperation(SQLOperation const& right) = delete;
+ SQLOperation& operator=(SQLOperation const& right) = delete;
};
#endif
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp
index fcbfa221d6a..350a258f455 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.cpp
+++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp
@@ -29,15 +29,23 @@
inline LPTSTR ErrorMessage(DWORD dw)
{
LPVOID lpMsgBuf;
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- dw,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0, NULL);
- return (LPTSTR)lpMsgBuf;
+ DWORD formatResult = FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dw,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0, NULL);
+ if (formatResult != 0)
+ return (LPTSTR)lpMsgBuf;
+ else
+ {
+ LPTSTR msgBuf = (LPTSTR)LocalAlloc(LPTR, 30);
+ sprintf(msgBuf, "Unknown error: %u", dw);
+ return msgBuf;
+ }
+
}
//============================== Global Variables =============================
@@ -51,6 +59,8 @@ LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter;
HANDLE WheatyExceptionReport::m_hReportFile;
HANDLE WheatyExceptionReport::m_hDumpFile;
HANDLE WheatyExceptionReport::m_hProcess;
+SymbolPairs WheatyExceptionReport::symbols;
+std::stack<SymbolDetail> WheatyExceptionReport::symbolDetails;
// Declare global instance of class
WheatyExceptionReport g_WheatyExceptionReport;
@@ -78,6 +88,7 @@ WheatyExceptionReport::~WheatyExceptionReport()
{
if (m_previousFilter)
SetUnhandledExceptionFilter(m_previousFilter);
+ ClearSymbols();
}
//===========================================================
@@ -498,12 +509,12 @@ PEXCEPTION_POINTERS pExceptionInfo)
WriteStackDetails(&trashableContext, true, NULL);
printTracesForAllThreads(true);
- _tprintf(_T("========================\r\n"));
+ /*_tprintf(_T("========================\r\n"));
_tprintf(_T("Global Variables\r\n"));
SymEnumSymbols(GetCurrentProcess(),
(UINT_PTR)GetModuleHandle(szFaultingModule),
- 0, EnumerateSymbolsCallback, 0);
+ 0, EnumerateSymbolsCallback, 0);*/
// #endif // X86 Only!
SymCleanup(GetCurrentProcess());
@@ -757,17 +768,21 @@ ULONG /*SymbolSize*/,
PVOID UserContext)
{
- char szBuffer[8192];
+ char szBuffer[WER_LARGE_BUFFER_SIZE];
+ memset(szBuffer, 0, sizeof(szBuffer));
__try
{
+ ClearSymbols();
if (FormatSymbolValue(pSymInfo, (STACKFRAME64*)UserContext,
szBuffer, sizeof(szBuffer)))
- _tprintf(_T("\t%s\r\n"), szBuffer);
+ _tprintf(_T("%s"), szBuffer);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
- _tprintf(_T("punting on symbol %s\r\n"), pSymInfo->Name);
+ _tprintf(_T("punting on symbol %s, partial output:\r\n"), pSymInfo->Name);
+ if (szBuffer[0] != '\0')
+ _tprintf(_T("%s"), szBuffer);
}
return TRUE;
@@ -786,12 +801,6 @@ unsigned /*cbBuffer*/)
{
char * pszCurrBuffer = pszBuffer;
- // Indicate if the variable is a local or parameter
- if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER)
- pszCurrBuffer += sprintf(pszCurrBuffer, "Parameter ");
- else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL)
- pszCurrBuffer += sprintf(pszCurrBuffer, "Local ");
-
// If it's a function, don't do anything.
if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK
return false;
@@ -813,19 +822,25 @@ unsigned /*cbBuffer*/)
// return false;
}
else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER)
- {
return false; // Don't try to report register variable
- }
else
{
pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable
}
+ pszCurrBuffer = PushSymbolDetail(pszCurrBuffer);
+
+ // Indicate if the variable is a local or parameter
+ if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER)
+ symbolDetails.top().Prefix = "Parameter ";
+ else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL)
+ symbolDetails.top().Prefix = "Local ";
+
// Determine if the variable is a user defined type (UDT). IF so, bHandled
// will return true.
bool bHandled;
pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, pSym->ModBase, pSym->TypeIndex,
- 0, pVariable, bHandled, pSym->Name, "");
+ 0, pVariable, bHandled, pSym->Name, "", false, true);
if (!bHandled)
{
@@ -833,15 +848,19 @@ unsigned /*cbBuffer*/)
// variable. Based on the size, we're assuming it's a char, WORD, or
// DWORD.
BasicType basicType = GetBasicType(pSym->TypeIndex, pSym->ModBase);
- pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]);
+ if (symbolDetails.top().Type.empty())
+ symbolDetails.top().Type = rgBaseType[basicType];
// Emit the variable name
- pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", pSym->Name);
+ if (pSym->Name[0] != '\0')
+ symbolDetails.top().Name = pSym->Name;
- pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, pSym->Size,
- (PVOID)pVariable);
+ char buffer[50];
+ FormatOutputValue(buffer, basicType, pSym->Size, (PVOID)pVariable, sizeof(buffer));
+ symbolDetails.top().Value = buffer;
}
+ pszCurrBuffer = PopSymbolDetail(pszCurrBuffer);
return true;
}
@@ -857,11 +876,16 @@ DWORD dwTypeIndex,
unsigned nestingLevel,
DWORD_PTR offset,
bool & bHandled,
-char* Name,
-char* suffix)
+const char* Name,
+char* /*suffix*/,
+bool newSymbol,
+bool logChildren)
{
bHandled = false;
+ if (newSymbol)
+ pszCurrBuffer = PushSymbolDetail(pszCurrBuffer);
+
DWORD typeTag;
if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMTAG, &typeTag))
return pszCurrBuffer;
@@ -872,20 +896,53 @@ char* suffix)
if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME,
&pwszTypeName))
{
- pszCurrBuffer += sprintf(pszCurrBuffer, " %ls", pwszTypeName);
+ // handle special cases
+ if (wcscmp(pwszTypeName, L"std::basic_string<char,std::char_traits<char>,std::allocator<char> >") == 0)
+ {
+ LocalFree(pwszTypeName);
+ symbolDetails.top().Type = "std::string";
+ char buffer[50];
+ FormatOutputValue(buffer, btStdString, 0, (PVOID)offset, sizeof(buffer));
+ symbolDetails.top().Value = buffer;
+ if (Name != NULL && Name[0] != '\0')
+ symbolDetails.top().Name = Name;
+ bHandled = true;
+ return pszCurrBuffer;
+ }
+
+ char buffer[200];
+ wcstombs(buffer, pwszTypeName, sizeof(buffer));
+ buffer[199] = '\0';
+ if (Name != NULL && Name[0] != '\0')
+ {
+ symbolDetails.top().Type = buffer;
+ symbolDetails.top().Name = Name;
+ }
+ else if (buffer[0] != '\0')
+ symbolDetails.top().Name = buffer;
+
LocalFree(pwszTypeName);
}
+ else if (Name != NULL && Name[0] != '\0')
+ symbolDetails.top().Name = Name;
- if (strlen(suffix) > 0)
- pszCurrBuffer += sprintf(pszCurrBuffer, "%s", suffix);
+ if (!StoreSymbol(dwTypeIndex, offset))
+ {
+ // Skip printing address and base class if it has been printed already
+ if (typeTag == SymTagBaseClass)
+ bHandled = true;
+ return pszCurrBuffer;
+ }
+ DWORD innerTypeID;
switch (typeTag)
{
case SymTagPointerType:
- DWORD innerTypeID;
if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID))
{
- pszCurrBuffer += sprintf(pszCurrBuffer, " %s", Name);
+ if (Name != NULL && Name[0] != '\0')
+ symbolDetails.top().Name = Name;
+
BOOL isReference;
SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_IS_REFERENCE, &isReference);
@@ -893,34 +950,146 @@ char* suffix)
memset(addressStr, 0, sizeof(addressStr));
if (isReference)
- addressStr[0] = '&';
+ symbolDetails.top().Suffix += "&";
else
- addressStr[0] = '*';
+ symbolDetails.top().Suffix += "*";
+
+ // Try to dereference the pointer in a try/except block since it might be invalid
+ DWORD_PTR address = DereferenceUnsafePointer(offset);
+
+ char buffer[50];
+ FormatOutputValue(buffer, btVoid, sizeof(PVOID), (PVOID)offset, sizeof(buffer));
+ symbolDetails.top().Value = buffer;
+
+ if (nestingLevel >= WER_MAX_NESTING_LEVEL)
+ logChildren = false;
+
+ // no need to log any children since the address is invalid anyway
+ if (address == NULL || address == DWORD_PTR(-1))
+ logChildren = false;
- DWORD_PTR address = *(PDWORD_PTR)offset;
- if (address == NULL)
+ pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1,
+ address, bHandled, Name, addressStr, false, logChildren);
+
+ if (!bHandled)
{
- pwszTypeName;
- if (SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_SYMNAME,
- &pwszTypeName))
+ BasicType basicType = GetBasicType(dwTypeIndex, modBase);
+ if (symbolDetails.top().Type.empty())
+ symbolDetails.top().Type = rgBaseType[basicType];
+
+ if (address == NULL)
+ symbolDetails.top().Value = "NULL";
+ else if (address == DWORD_PTR(-1))
+ symbolDetails.top().Value = "<Unable to read memory>";
+ else
{
- pszCurrBuffer += sprintf(pszCurrBuffer, " %ls", pwszTypeName);
- LocalFree(pwszTypeName);
+ // Get the size of the child member
+ ULONG64 length;
+ SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_LENGTH, &length);
+ char buffer[50];
+ FormatOutputValue(buffer, basicType, length, (PVOID)address, sizeof(buffer));
+ symbolDetails.top().Value = buffer;
}
-
- pszCurrBuffer += sprintf(pszCurrBuffer, "%s = NULL", addressStr);
-
bHandled = true;
return pszCurrBuffer;
}
+ else if (address == NULL)
+ symbolDetails.top().Value = "NULL";
+ else if (address == DWORD_PTR(-1))
+ {
+ symbolDetails.top().Value = "<Unable to read memory>";
+ bHandled = true;
+ return pszCurrBuffer;
+ }
+ }
+ break;
+ case SymTagData:
+ if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID))
+ {
+ DWORD innerTypeTag;
+ if (!SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_SYMTAG, &innerTypeTag))
+ break;
+
+ switch (innerTypeTag)
+ {
+ case SymTagUDT:
+ if (nestingLevel >= WER_MAX_NESTING_LEVEL)
+ logChildren = false;
+ pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1,
+ offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
+ break;
+ case SymTagPointerType:
+ if (Name != NULL && Name[0] != '\0')
+ symbolDetails.top().Name = Name;
+ pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1,
+ offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
+ break;
+ case SymTagArrayType:
+ pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1,
+ offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case SymTagArrayType:
+ if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID))
+ {
+ symbolDetails.top().HasChildren = true;
+
+ BasicType basicType = btNoType;
+ pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1,
+ offset, bHandled, Name, "", false, false);
+
+ // Set Value back to an empty string since the Array object itself has no value, only its elements have
+ symbolDetails.top().Value = "";
+
+ DWORD elementsCount;
+ if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_COUNT, &elementsCount))
+ symbolDetails.top().Suffix += "[" + std::to_string(elementsCount) + "]";
else
+ symbolDetails.top().Suffix += "[<unknown count>]";
+
+ if (!bHandled)
{
- FormatOutputValue(&addressStr[1], btVoid, sizeof(PVOID), (PVOID)offset);
- pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1,
- address, bHandled, "", addressStr);
+ basicType = GetBasicType(dwTypeIndex, modBase);
+ if (symbolDetails.top().Type.empty())
+ symbolDetails.top().Type = rgBaseType[basicType];
+ bHandled = true;
}
+
+ // Get the size of the child member
+ ULONG64 length;
+ SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_LENGTH, &length);
+
+ char buffer[50];
+ switch (basicType)
+ {
+ case btChar:
+ case btStdString:
+ FormatOutputValue(buffer, basicType, length, (PVOID)offset, sizeof(buffer));
+ symbolDetails.top().Value = buffer;
+ break;
+ default:
+ for (DWORD index = 0; index < elementsCount && index < WER_MAX_ARRAY_ELEMENTS_COUNT; index++)
+ {
+ pszCurrBuffer = PushSymbolDetail(pszCurrBuffer);
+ symbolDetails.top().Suffix += "[" + std::to_string(index) + "]";
+ FormatOutputValue(buffer, basicType, length, (PVOID)(offset + length * index), sizeof(buffer));
+ symbolDetails.top().Value = buffer;
+ pszCurrBuffer = PopSymbolDetail(pszCurrBuffer);
+ }
+ break;
+ }
+
+ return pszCurrBuffer;
}
break;
+ case SymTagBaseType:
+ break;
+ case SymTagEnum:
+ return pszCurrBuffer;
default:
break;
}
@@ -937,7 +1106,7 @@ char* suffix)
// TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this.
struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS
{
- ULONG MoreChildIds[1024];
+ ULONG MoreChildIds[1024*2];
FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);}
} children;
@@ -951,26 +1120,37 @@ char* suffix)
return pszCurrBuffer;
}
- // Append a line feed
- pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n");
-
// Iterate through each of the children
for (unsigned i = 0; i < dwChildrenCount; i++)
{
DWORD symTag;
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_SYMTAG, &symTag);
- if (symTag == SymTagFunction || symTag == SymTagTypedef)
+ if (symTag == SymTagFunction ||
+ symTag == SymTagEnum ||
+ symTag == SymTagTypedef ||
+ symTag == SymTagVTable)
continue;
- // Add appropriate indentation level (since this routine is recursive)
- for (unsigned j = 0; j <= nestingLevel+1; j++)
- pszCurrBuffer += sprintf(pszCurrBuffer, "\t");
+ // Ignore static fields
+ DWORD dataKind;
+ SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_DATAKIND, &dataKind);
+ if (dataKind == DataIsStaticLocal ||
+ dataKind == DataIsGlobal ||
+ dataKind == DataIsStaticMember)
+ continue;
+
+
+ symbolDetails.top().HasChildren = true;
+ if (!logChildren)
+ {
+ bHandled = false;
+ return pszCurrBuffer;
+ }
// Recurse for each of the child types
bool bHandled2;
BasicType basicType = GetBasicType(children.ChildId[i], modBase);
- pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]);
// Get the offset of the child member, relative to its parent
DWORD dwMemberOffset;
@@ -982,11 +1162,14 @@ char* suffix)
pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase,
children.ChildId[i], nestingLevel+1,
- dwFinalOffset, bHandled2, ""/*Name */, "");
+ dwFinalOffset, bHandled2, ""/*Name */, "", true, true);
// If the child wasn't a UDT, format it appropriately
if (!bHandled2)
{
+ if (symbolDetails.top().Type.empty())
+ symbolDetails.top().Type = rgBaseType[basicType];
+
// Get the real "TypeId" of the child. We need this for the
// SymGetTypeInfo(TI_GET_TYPEID) call below.
DWORD typeId;
@@ -997,78 +1180,88 @@ char* suffix)
ULONG64 length;
SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_LENGTH, &length);
- // BasicType basicType = GetBasicType(children.ChildId[i], modBase);
- //
- // pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]);
- //
- // Emit the variable name
- // pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", Name);
-
- pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType,
- length, (PVOID)dwFinalOffset);
-
- pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n");
+ char buffer[50];
+ FormatOutputValue(buffer, basicType, length, (PVOID)dwFinalOffset, sizeof(buffer));
+ symbolDetails.top().Value = buffer;
}
+
+ pszCurrBuffer = PopSymbolDetail(pszCurrBuffer);
}
bHandled = true;
return pszCurrBuffer;
}
-char * WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer,
+void WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer,
BasicType basicType,
DWORD64 length,
-PVOID pAddress)
+PVOID pAddress,
+size_t bufferSize)
{
__try
{
- // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!)
- if (length == 1)
- pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PBYTE)pAddress);
- else if (length == 2)
- pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PWORD)pAddress);
- else if (length == 4)
+ switch (basicType)
{
- if (basicType == btFloat)
+ case btChar:
{
- pszCurrBuffer += sprintf(pszCurrBuffer, " = %f", *(PFLOAT)pAddress);
+ if (strlen((char*)pAddress) > bufferSize - 6)
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", bufferSize - 6, (char*)pAddress);
+ else
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\"%s\"", (char*)pAddress);
+ break;
}
- else if (basicType == btChar)
+ case btStdString:
{
- if (!IsBadStringPtr(*(PSTR*)pAddress, 32))
+ std::string* value = static_cast<std::string*>(pAddress);
+ if (value->length() > bufferSize - 6)
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", bufferSize - 6, value->c_str());
+ else
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\"%s\"", value->c_str());
+ break;
+ }
+ default:
+ // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!)
+ if (length == 1)
+ pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PBYTE)pAddress);
+ else if (length == 2)
+ pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PWORD)pAddress);
+ else if (length == 4)
{
- pszCurrBuffer += sprintf(pszCurrBuffer, " = \"%.31s\"",
- *(PSTR*)pAddress);
+ if (basicType == btFloat)
+ pszCurrBuffer += sprintf(pszCurrBuffer, "%f", *(PFLOAT)pAddress);
+ else
+ pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PDWORD)pAddress);
+ }
+ else if (length == 8)
+ {
+ if (basicType == btFloat)
+ {
+ pszCurrBuffer += sprintf(pszCurrBuffer, "%lf",
+ *(double *)pAddress);
+ }
+ else
+ pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X",
+ *(DWORD64*)pAddress);
}
else
- pszCurrBuffer += sprintf(pszCurrBuffer, " = %X",
- *(PDWORD)pAddress);
- }
- else
- pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PDWORD)pAddress);
- }
- else if (length == 8)
- {
- if (basicType == btFloat)
- {
- pszCurrBuffer += sprintf(pszCurrBuffer, " = %lf",
- *(double *)pAddress);
- }
- else
- pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X",
- *(DWORD64*)pAddress);
+ {
+ #if _WIN64
+ pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X", (DWORD64*)pAddress);
+ #else
+ pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", (PDWORD)pAddress);
+ #endif
+ }
+ break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
#if _WIN64
- pszCurrBuffer += sprintf(pszCurrBuffer, " <Unable to read memory> = %I64X", (DWORD64*)pAddress);
+ pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X <Unable to read memory>", (DWORD64*)pAddress);
#else
- pszCurrBuffer += sprintf(pszCurrBuffer, " <Unable to read memory> = %X", (PDWORD)pAddress);
+ pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X <Unable to read memory>", (PDWORD)pAddress);
#endif
}
-
- return pszCurrBuffer;
}
BasicType
@@ -1096,13 +1289,25 @@ WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase)
return btNoType;
}
+DWORD_PTR WheatyExceptionReport::DereferenceUnsafePointer(DWORD_PTR address)
+{
+ __try
+ {
+ return *(PDWORD_PTR)address;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER)
+ {
+ return DWORD_PTR(-1);
+ }
+}
+
//============================================================================
// Helper function that writes to the report file, and allows the user to use
// printf style formating
//============================================================================
int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...)
{
- TCHAR szBuff[8192];
+ TCHAR szBuff[WER_LARGE_BUFFER_SIZE];
int retValue;
DWORD cbWritten;
va_list argptr;
@@ -1116,4 +1321,49 @@ int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...)
return retValue;
}
+bool WheatyExceptionReport::StoreSymbol(DWORD type, DWORD_PTR offset)
+{
+ return symbols.insert(SymbolPair(type, offset)).second;
+}
+
+void WheatyExceptionReport::ClearSymbols()
+{
+ symbols.clear();
+ while (!symbolDetails.empty())
+ symbolDetails.pop();
+}
+
+char* WheatyExceptionReport::PushSymbolDetail(char* pszCurrBuffer)
+{
+ // Log current symbol and then add another to the stack to keep the hierarchy format
+ pszCurrBuffer = PrintSymbolDetail(pszCurrBuffer);
+ symbolDetails.emplace();
+ return pszCurrBuffer;
+}
+
+char* WheatyExceptionReport::PopSymbolDetail(char* pszCurrBuffer)
+{
+ pszCurrBuffer = PrintSymbolDetail(pszCurrBuffer);
+ symbolDetails.pop();
+ return pszCurrBuffer;
+}
+
+char* WheatyExceptionReport::PrintSymbolDetail(char* pszCurrBuffer)
+{
+ if (symbolDetails.empty())
+ return pszCurrBuffer;
+
+ // Don't log anything if has been logged already or if it's empty
+ if (symbolDetails.top().Logged || symbolDetails.top().empty())
+ return pszCurrBuffer;
+
+ // Add appropriate indentation level (since this routine is recursive)
+ for (size_t i = 0; i < symbolDetails.size(); i++)
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\t");
+
+ pszCurrBuffer += sprintf(pszCurrBuffer, "%s\r\n", symbolDetails.top().ToString().c_str());
+
+ return pszCurrBuffer;
+}
+
#endif // _WIN32
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h
index 48894a5db91..9137b91aac9 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.h
+++ b/src/server/shared/Debugging/WheatyExceptionReport.h
@@ -4,13 +4,14 @@
#if PLATFORM == PLATFORM_WINDOWS && !defined(__MINGW32__)
#include <dbghelp.h>
+#include <set>
+#include <stdlib.h>
+#include <stack>
+#define countof _countof
-#if _MSC_VER < 1400
-# define countof(array) (sizeof(array) / sizeof(array[0]))
-#else
-# include <stdlib.h>
-# define countof _countof
-#endif // _MSC_VER < 1400
+#define WER_MAX_ARRAY_ELEMENTS_COUNT 10
+#define WER_MAX_NESTING_LEVEL 5
+#define WER_LARGE_BUFFER_SIZE 1024 * 128
enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK
{
@@ -31,43 +32,112 @@ enum BasicType // Stolen from CVCON
btComplex = 28,
btBit = 29,
btBSTR = 30,
- btHresult = 31
+ btHresult = 31,
+
+ // Custom types
+ btStdString = 101
+};
+
+enum DataKind // Stolen from CVCONST.H in the DIA 2.0 SDK
+{
+ DataIsUnknown,
+ DataIsLocal,
+ DataIsStaticLocal,
+ DataIsParam,
+ DataIsObjectPtr,
+ DataIsFileStatic,
+ DataIsGlobal,
+ DataIsMember,
+ DataIsStaticMember,
+ DataIsConstant
};
const char* const rgBaseType[] =
{
- " <user defined> ", // btNoType = 0,
- " void ", // btVoid = 1,
- " char* ", // btChar = 2,
- " wchar_t* ", // btWChar = 3,
- " signed char ",
- " unsigned char ",
- " int ", // btInt = 6,
- " unsigned int ", // btUInt = 7,
- " float ", // btFloat = 8,
- " <BCD> ", // btBCD = 9,
- " bool ", // btBool = 10,
- " short ",
- " unsigned short ",
- " long ", // btLong = 13,
- " unsigned long ", // btULong = 14,
- " __int8 ",
- " __int16 ",
- " __int32 ",
- " __int64 ",
- " __int128 ",
- " unsigned __int8 ",
- " unsigned __int16 ",
- " unsigned __int32 ",
- " unsigned __int64 ",
- " unsigned __int128 ",
- " <currency> ", // btCurrency = 25,
- " <date> ", // btDate = 26,
- " VARIANT ", // btVariant = 27,
- " <complex> ", // btComplex = 28,
- " <bit> ", // btBit = 29,
- " BSTR ", // btBSTR = 30,
- " HRESULT " // btHresult = 31
+ "<user defined>", // btNoType = 0,
+ "void", // btVoid = 1,
+ "char",//char* // btChar = 2,
+ "wchar_t*", // btWChar = 3,
+ "signed char",
+ "unsigned char",
+ "int", // btInt = 6,
+ "unsigned int", // btUInt = 7,
+ "float", // btFloat = 8,
+ "<BCD>", // btBCD = 9,
+ "bool", // btBool = 10,
+ "short",
+ "unsigned short",
+ "long", // btLong = 13,
+ "unsigned long", // btULong = 14,
+ "int8",
+ "int16",
+ "int32",
+ "int64",
+ "int128",
+ "uint8",
+ "uint16",
+ "uint32",
+ "uint64",
+ "uint128",
+ "<currency>", // btCurrency = 25,
+ "<date>", // btDate = 26,
+ "VARIANT", // btVariant = 27,
+ "<complex>", // btComplex = 28,
+ "<bit>", // btBit = 29,
+ "BSTR", // btBSTR = 30,
+ "HRESULT" // btHresult = 31
+};
+
+struct SymbolPair
+{
+ SymbolPair(DWORD type, DWORD_PTR offset)
+ {
+ _type = type;
+ _offset = offset;
+ }
+
+ bool operator<(const SymbolPair& other) const
+ {
+ return _offset < other._offset ||
+ (_offset == other._offset && _type < other._type);
+ }
+
+ DWORD _type;
+ DWORD_PTR _offset;
+};
+typedef std::set<SymbolPair> SymbolPairs;
+
+struct SymbolDetail
+{
+ SymbolDetail() : Prefix(), Type(), Suffix(), Name(), Value(), Logged(false), HasChildren(false) {}
+
+ std::string ToString()
+ {
+ Logged = true;
+ std::string formatted = Prefix + Type + Suffix;
+ if (!Name.empty())
+ {
+ if (!formatted.empty())
+ formatted += " ";
+ formatted += Name;
+ }
+ if (!Value.empty())
+ formatted += " = " + Value;
+ return formatted;
+ }
+
+ bool empty() const
+ {
+ return Value.empty() && !HasChildren;
+ }
+
+ std::string Prefix;
+ std::string Type;
+ std::string Suffix;
+ std::string Name;
+ std::string Value;
+ bool Logged;
+ bool HasChildren;
};
class WheatyExceptionReport
@@ -100,14 +170,18 @@ class WheatyExceptionReport
static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *, char * pszBuffer, unsigned cbBuffer);
- static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool &, char*, char*);
+ static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool &, const char*, char*, bool, bool);
- static char * FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress);
+ static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize);
static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase);
+ static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
static int __cdecl _tprintf(const TCHAR * format, ...);
+ static bool StoreSymbol(DWORD type , DWORD_PTR offset);
+ static void ClearSymbols();
+
// Variables used by the class
static TCHAR m_szLogFileName[MAX_PATH];
static TCHAR m_szDumpFileName[MAX_PATH];
@@ -115,6 +189,13 @@ class WheatyExceptionReport
static HANDLE m_hReportFile;
static HANDLE m_hDumpFile;
static HANDLE m_hProcess;
+ static SymbolPairs symbols;
+ static std::stack<SymbolDetail> symbolDetails;
+
+ static char* PushSymbolDetail(char* pszCurrBuffer);
+ static char* PopSymbolDetail(char* pszCurrBuffer);
+ static char* PrintSymbolDetail(char* pszCurrBuffer);
+
};
extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class
diff --git a/src/server/shared/Define.h b/src/server/shared/Define.h
index 27973694818..e43853e5bb0 100644
--- a/src/server/shared/Define.h
+++ b/src/server/shared/Define.h
@@ -70,14 +70,6 @@
# define ATTR_DEPRECATED
#endif //COMPILER == COMPILER_GNU
-#if COMPILER_HAS_CPP11_SUPPORT
-# define OVERRIDE override
-# define FINAL final
-#else
-# define OVERRIDE
-# define FINAL
-#endif //COMPILER_HAS_CPP11_SUPPORT
-
#define UI64FMTD ACE_UINT64_FORMAT_SPECIFIER
#define UI64LIT(N) ACE_UINT64_LITERAL(N)
diff --git a/src/server/shared/Dynamic/HashNamespace.h b/src/server/shared/Dynamic/HashNamespace.h
deleted file mode 100644
index 0e95332c05f..00000000000
--- a/src/server/shared/Dynamic/HashNamespace.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_HASH_NAMESPACE_H
-#define TRINITY_HASH_NAMESPACE_H
-
-#include "Define.h"
-
-#if COMPILER_HAS_CPP11_SUPPORT
-# define HASH_NAMESPACE_START namespace std {
-# define HASH_NAMESPACE_END }
-#elif defined(_STLPORT_VERSION)
-# define HASH_NAMESPACE_START namespace std {
-# define HASH_NAMESPACE_END }
-#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1600 // VS100
-# define HASH_NAMESPACE_START namespace std {
-# define HASH_NAMESPACE_END }
-#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1500 && _HAS_TR1
-# define HASH_NAMESPACE_START namespace std { namespace tr1 {
-# define HASH_NAMESPACE_END } }
-#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1300
-# define HASH_NAMESPACE_START namespace stdext {
-# define HASH_NAMESPACE_END }
-
-#if !_HAS_TRADITIONAL_STL
-#ifndef HASH_NAMESPACE
-#define HASH_NAMESPACE
-#else
-
-// can be not used by some platforms, so provide fake forward
-HASH_NAMESPACE_START
-
-template<class K>
-class hash
-{
-public:
- size_t operator() (K const&);
-};
-
-HASH_NAMESPACE_END
-
-#endif
-#endif
-
-#elif COMPILER == COMPILER_INTEL
-# define HASH_NAMESPACE_START namespace std {
-# define HASH_NAMESPACE_END }
-#elif COMPILER == COMPILER_GNU && defined(__clang__) && defined(_LIBCPP_VERSION)
-# define HASH_NAMESPACE_START namespace std {
-# define HASH_NAMESPACE_END }
-#elif COMPILER == COMPILER_GNU && GCC_VERSION > 40200
-# define HASH_NAMESPACE_START namespace std { namespace tr1 {
-# define HASH_NAMESPACE_END } }
-#elif COMPILER == COMPILER_GNU && GCC_VERSION >= 30000
-# define HASH_NAMESPACE_START namespace __gnu_cxx {
-# define HASH_NAMESPACE_END }
-
-#include <ext/hash_fun.h>
-#include <string>
-
-HASH_NAMESPACE_START
-
-template<>
-class hash<unsigned long long>
-{
-public:
- size_t operator()(const unsigned long long &__x) const { return (size_t)__x; }
-};
-
-template<typename T>
-class hash<T *>
-{
-public:
- size_t operator()(T * const &__x) const { return (size_t)__x; }
-};
-
-template<> struct hash<std::string>
-{
- size_t operator()(const std::string &__x) const
- {
- return hash<char const*>()(__x.c_str());
- }
-};
-
-HASH_NAMESPACE_END
-
-#else
-# define HASH_NAMESPACE_START namespace std {
-# define HASH_NAMESPACE_END }
-#endif
-
-#if COMPILER != COMPILER_MICROSOFT
-
-// Visual Studio use non standard hash calculation function, so provide fake forward for other
-HASH_NAMESPACE_START
-
-template<class K>
-size_t hash_value(K const&);
-
-HASH_NAMESPACE_END
-
-#endif
-
-#endif
diff --git a/src/server/shared/Dynamic/LinkedList.h b/src/server/shared/Dynamic/LinkedList.h
index 72d035c2cb6..402aaf3d40c 100644
--- a/src/server/shared/Dynamic/LinkedList.h
+++ b/src/server/shared/Dynamic/LinkedList.h
@@ -33,8 +33,8 @@ class LinkedListElement
LinkedListElement* iNext;
LinkedListElement* iPrev;
public:
- LinkedListElement(): iNext(NULL), iPrev(NULL) { }
- ~LinkedListElement() { delink(); }
+ LinkedListElement() : iNext(NULL), iPrev(NULL) { }
+ virtual ~LinkedListElement() { delink(); }
bool hasNext() const { return(iNext && iNext->iNext != NULL); }
bool hasPrev() const { return(iPrev && iPrev->iPrev != NULL); }
@@ -73,6 +73,10 @@ class LinkedListElement
iNext->iPrev = pElem;
iNext = pElem;
}
+
+ private:
+ LinkedListElement(LinkedListElement const&);
+ LinkedListElement& operator=(LinkedListElement const&);
};
//============================================
@@ -83,6 +87,7 @@ class LinkedListHead
LinkedListElement iFirst;
LinkedListElement iLast;
uint32 iSize;
+
public:
LinkedListHead(): iSize(0)
{
@@ -92,6 +97,8 @@ class LinkedListHead
iLast.iPrev = &iFirst;
}
+ virtual ~LinkedListHead() { }
+
bool isEmpty() const { return(!iFirst.iNext->isInList()); }
LinkedListElement * getFirst() { return(isEmpty() ? NULL : iFirst.iNext); }
@@ -239,6 +246,10 @@ class LinkedListHead
};
typedef Iterator<LinkedListElement> iterator;
+
+ private:
+ LinkedListHead(LinkedListHead const&);
+ LinkedListHead& operator=(LinkedListHead const&);
};
//============================================
diff --git a/src/server/shared/Dynamic/LinkedReference/Reference.h b/src/server/shared/Dynamic/LinkedReference/Reference.h
index 1ba41f1f454..83a1dd155b1 100644
--- a/src/server/shared/Dynamic/LinkedReference/Reference.h
+++ b/src/server/shared/Dynamic/LinkedReference/Reference.h
@@ -94,6 +94,10 @@ template <class TO, class FROM> class Reference : public LinkedListElement
TO* getTarget() const { return iRefTo; }
FROM* GetSource() const { return iRefFrom; }
+
+ private:
+ Reference(Reference const&);
+ Reference& operator=(Reference const&);
};
//=====================================================
diff --git a/src/server/shared/Dynamic/ObjectRegistry.h b/src/server/shared/Dynamic/ObjectRegistry.h
index 4b17b2fc558..be7ce00ac05 100644
--- a/src/server/shared/Dynamic/ObjectRegistry.h
+++ b/src/server/shared/Dynamic/ObjectRegistry.h
@@ -20,12 +20,12 @@
#define TRINITY_OBJECTREGISTRY_H
#include "Define.h"
-#include "Dynamic/UnorderedMap.h"
#include <ace/Singleton.h>
#include <string>
#include <vector>
#include <map>
+#include <unordered_map>
/** ObjectRegistry holds all registry item of the same type
*/
diff --git a/src/server/shared/Dynamic/UnorderedMap.h b/src/server/shared/Dynamic/UnorderedMap.h
deleted file mode 100644
index f97c4830c75..00000000000
--- a/src/server/shared/Dynamic/UnorderedMap.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_UNORDERED_MAP_H
-#define TRINITY_UNORDERED_MAP_H
-
-#include "HashNamespace.h"
-
-#if COMPILER_HAS_CPP11_SUPPORT
-# include <unordered_map>
-#elif COMPILER == COMPILER_INTEL
-# include <ext/hash_map>
-#elif COMPILER == COMPILER_GNU && defined(__clang__) && defined(_LIBCPP_VERSION)
-# include <unordered_map>
-#elif COMPILER == COMPILER_GNU && GCC_VERSION > 40200
-# include <tr1/unordered_map>
-#elif COMPILER == COMPILER_GNU && GCC_VERSION >= 30000
-# include <ext/hash_map>
-#elif COMPILER == COMPILER_MICROSOFT && ((_MSC_VER >= 1500 && _HAS_TR1) || _MSC_VER >= 1700) // VC9.0 SP1 and later
-# include <unordered_map>
-#else
-# include <hash_map>
-#endif
-
-#ifdef _STLPORT_VERSION
-# define UNORDERED_MAP std::hash_map
-# define UNORDERED_MULTIMAP std::hash_multimap
-#elif COMPILER_HAS_CPP11_SUPPORT
-# define UNORDERED_MAP std::unordered_map
-# define UNORDERED_MULTIMAP std::unordered_multimap
-#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1600 // VS100
-# define UNORDERED_MAP std::tr1::unordered_map
-# define UNORDERED_MULTIMAP std::tr1::unordered_multimap
-#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1500 && _HAS_TR1
-# define UNORDERED_MAP std::tr1::unordered_map
-# define UNORDERED_MULTIMAP std::tr1::unordered_multimap
-#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1300
-# define UNORDERED_MAP stdext::hash_map
-# define UNORDERED_MULTIMAP stdext::hash_multimap
-#elif COMPILER == COMPILER_INTEL
-# define UNORDERED_MAP std::hash_map
-# define UNORDERED_MULTIMAP std::hash_multimap
-#elif COMPILER == COMPILER_GNU && defined(__clang__) && defined(_LIBCPP_VERSION)
-# define UNORDERED_MAP std::unordered_map
-# define UNORDERED_MULTIMAP std::unordered_multimap
-#elif COMPILER == COMPILER_GNU && GCC_VERSION > 40200
-# define UNORDERED_MAP std::tr1::unordered_map
-# define UNORDERED_MULTIMAP std::tr1::unordered_multimap
-#elif COMPILER == COMPILER_GNU && GCC_VERSION >= 30000
-# define UNORDERED_MAP __gnu_cxx::hash_map
-# define UNORDERED_MULTIMAP __gnu_cxx::hash_multimap
-#else
-# define UNORDERED_MAP std::hash_map
-# define UNORDERED_MULTIMAP std::hash_multimap
-#endif
-
-#endif
diff --git a/src/server/shared/Dynamic/UnorderedSet.h b/src/server/shared/Dynamic/UnorderedSet.h
deleted file mode 100644
index 0e084698c47..00000000000
--- a/src/server/shared/Dynamic/UnorderedSet.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_UNORDERED_SET_H
-#define TRINITY_UNORDERED_SET_H
-
-#include "HashNamespace.h"
-
-#if COMPILER_HAS_CPP11_SUPPORT
-# include <unordered_set>
-#elif COMPILER == COMPILER_INTEL
-# include <ext/hash_set>
-#elif COMPILER == COMPILER_GNU && defined(__clang__) && defined(_LIBCPP_VERSION)
-# include <unordered_set>
-#elif COMPILER == COMPILER_GNU && GCC_VERSION > 40200
-# include <tr1/unordered_set>
-#elif COMPILER == COMPILER_GNU && GCC_VERSION >= 30000
-# include <ext/hash_set>
-#elif COMPILER == COMPILER_MICROSOFT && ((_MSC_VER >= 1500 && _HAS_TR1) || _MSC_VER >= 1700) // VC9.0 SP1 and later
-# include <unordered_set>
-#else
-# include <hash_set>
-#endif
-
-#ifdef _STLPORT_VERSION
-# define UNORDERED_SET std::hash_set
-using std::hash_set;
-#elif COMPILER_HAS_CPP11_SUPPORT
-# define UNORDERED_SET std::unordered_set
-#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1600 // VS100
-# define UNORDERED_SET std::tr1::unordered_set
-#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1500 && _HAS_TR1
-# define UNORDERED_SET std::tr1::unordered_set
-#elif COMPILER == COMPILER_MICROSOFT && _MSC_VER >= 1300
-# define UNORDERED_SET stdext::hash_set
-using stdext::hash_set;
-#elif COMPILER == COMPILER_INTEL
-# define UNORDERED_SET std::hash_set
-using std::hash_set;
-#elif COMPILER == COMPILER_GNU && defined(__clang__) && defined(_LIBCPP_VERSION)
-# define UNORDERED_SET std::unordered_set
-#elif COMPILER == COMPILER_GNU && GCC_VERSION > 40200
-# define UNORDERED_SET std::tr1::unordered_set
-#elif COMPILER == COMPILER_GNU && GCC_VERSION >= 30000
-# define UNORDERED_SET __gnu_cxx::hash_set
-#else
-# define UNORDERED_SET std::hash_set
-using std::hash_set;
-#endif
-
-#endif
diff --git a/src/server/shared/Logging/Appender.h b/src/server/shared/Logging/Appender.h
index b373f0459c9..84d0dc14eca 100644
--- a/src/server/shared/Logging/Appender.h
+++ b/src/server/shared/Logging/Appender.h
@@ -20,8 +20,7 @@
#include "Define.h"
#include <time.h>
-#include "Dynamic/UnorderedMap.h"
-
+#include <unordered_map>
#include <string>
// Values assigned have their equivalent in enum ACE_Log_Priority
@@ -105,6 +104,6 @@ class Appender
AppenderFlags flags;
};
-typedef UNORDERED_MAP<uint8, Appender*> AppenderMap;
+typedef std::unordered_map<uint8, Appender*> AppenderMap;
#endif
diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp
index b9c2fd7339d..f2532ad8bb8 100644
--- a/src/server/shared/Logging/AppenderFile.cpp
+++ b/src/server/shared/Logging/AppenderFile.cpp
@@ -16,6 +16,7 @@
*/
#include "AppenderFile.h"
+#include "Common.h"
#if PLATFORM == PLATFORM_WINDOWS
# include <Windows.h>
@@ -33,7 +34,8 @@ AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, co
dynamicName = std::string::npos != filename.find("%s");
backup = (_flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0;
- logfile = !dynamicName ? OpenFile(_filename, _mode, mode == "w" && backup) : NULL;
+ if (!dynamicName)
+ logfile = OpenFile(_filename, _mode, mode == "w" && backup);
}
AppenderFile::~AppenderFile()
@@ -49,7 +51,15 @@ void AppenderFile::_write(LogMessage const& message)
{
char namebuf[TRINITY_PATH_MAX];
snprintf(namebuf, TRINITY_PATH_MAX, filename.c_str(), message.param1.c_str());
- logfile = OpenFile(namebuf, mode, backup || exceedMaxSize);
+ // always use "a" with dynamic name otherwise it could delete the log we wrote in last _write() call
+ FILE* file = OpenFile(namebuf, "a", backup || exceedMaxSize);
+ if (!file)
+ return;
+ fprintf(file, "%s%s", message.prefix.c_str(), message.text.c_str());
+ fflush(file);
+ fileSize += uint64(message.Size());
+ fclose(file);
+ return;
}
else if (exceedMaxSize)
logfile = OpenFile(filename, "w", true);
@@ -60,9 +70,6 @@ void AppenderFile::_write(LogMessage const& message)
fprintf(logfile, "%s%s", message.prefix.c_str(), message.text.c_str());
fflush(logfile);
fileSize += uint64(message.Size());
-
- if (dynamicName)
- CloseFile();
}
FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mode, bool backup)
@@ -74,6 +81,7 @@ FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mod
std::string newName(fullName);
newName.push_back('.');
newName.append(LogMessage::getTimeStr(time(NULL)));
+ std::replace(newName.begin(), newName.end(), ':', '-');
rename(fullName.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore
}
diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp
index d7d70e7d4ea..dc9bda62bfb 100644
--- a/src/server/shared/Logging/Log.cpp
+++ b/src/server/shared/Logging/Log.cpp
@@ -267,7 +267,7 @@ void Log::vlog(std::string const& filter, LogLevel level, char const* str, va_li
write(new LogMessage(level, filter, text));
}
-void Log::write(LogMessage* msg)
+void Log::write(LogMessage* msg) const
{
Logger const* logger = GetLoggerByType(msg->type);
msg->text.append("\n");
@@ -376,7 +376,6 @@ void Log::Close()
delete worker;
worker = NULL;
loggers.clear();
- cachedLoggers.clear();
for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
{
delete it->second;
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index dcac93e5a60..a118e6e8773 100644
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -23,8 +23,8 @@
#include "Appender.h"
#include "Logger.h"
#include "LogWorker.h"
-#include "Dynamic/UnorderedMap.h"
+#include <unordered_map>
#include <string>
#include <ace/Singleton.h>
@@ -34,8 +34,7 @@ class Log
{
friend class ACE_Singleton<Log, ACE_Thread_Mutex>;
- typedef UNORDERED_MAP<std::string, Logger> LoggerMap;
- typedef UNORDERED_MAP<std::string, Logger const*> CachedLoggerContainer;
+ typedef std::unordered_map<std::string, Logger> LoggerMap;
private:
Log();
@@ -44,7 +43,7 @@ class Log
public:
void LoadFromConfig();
void Close();
- bool ShouldLog(std::string const& type, LogLevel level);
+ bool ShouldLog(std::string const& type, LogLevel level) const;
bool SetLogLevel(std::string const& name, char const* level, bool isLogger = true);
void outMessage(std::string const& f, LogLevel level, char const* str, ...) ATTR_PRINTF(4, 5);
@@ -57,9 +56,9 @@ class Log
private:
static std::string GetTimestampStr();
void vlog(std::string const& f, LogLevel level, char const* str, va_list argptr);
- void write(LogMessage* msg);
+ void write(LogMessage* msg) const;
- Logger const* GetLoggerByType(std::string const& type);
+ Logger const* GetLoggerByType(std::string const& type) const;
Appender* GetAppenderByName(std::string const& name);
uint8 NextAppenderId();
void CreateAppenderFromConfig(std::string const& name);
@@ -69,7 +68,6 @@ class Log
AppenderMap appenders;
LoggerMap loggers;
- CachedLoggerContainer cachedLoggers;
uint8 AppenderId;
std::string m_logsDir;
@@ -78,36 +76,24 @@ class Log
LogWorker* worker;
};
-inline Logger const* Log::GetLoggerByType(std::string const& originalType)
+inline Logger const* Log::GetLoggerByType(std::string const& type) const
{
- // Check if already cached
- CachedLoggerContainer::const_iterator itCached = cachedLoggers.find(originalType);
- if (itCached != cachedLoggers.end())
- return itCached->second;
-
- Logger const* logger = NULL;
- std::string type(originalType);
-
- do
- {
- // Search for the logger "type.subtype"
- LoggerMap::const_iterator it = loggers.find(type);
- if (it == loggers.end())
- {
- // Search for the logger "type", if our logger contains '.', otherwise search for LOGGER_ROOT
- size_t found = type.find_last_of(".");
- type = found != std::string::npos ? type.substr(0, found) : LOGGER_ROOT;
- }
- else
- logger = &(it->second);
- }
- while (!logger);
-
- cachedLoggers[type] = logger;
- return logger;
+ LoggerMap::const_iterator it = loggers.find(type);
+ if (it != loggers.end())
+ return &(it->second);
+
+ if (type == LOGGER_ROOT)
+ return NULL;
+
+ std::string parentLogger = LOGGER_ROOT;
+ size_t found = type.find_last_of(".");
+ if (found != std::string::npos)
+ parentLogger = type.substr(0,found);
+
+ return GetLoggerByType(parentLogger);
}
-inline bool Log::ShouldLog(std::string const& type, LogLevel level)
+inline bool Log::ShouldLog(std::string const& type, LogLevel level) const
{
// TODO: Use cache to store "Type.sub1.sub2": "Type" equivalence, should
// Speed up in cases where requesting "Type.sub1.sub2" but only configured
diff --git a/src/server/shared/Packets/ByteBuffer.cpp b/src/server/shared/Packets/ByteBuffer.cpp
index b8cb5215665..f446592e922 100644
--- a/src/server/shared/Packets/ByteBuffer.cpp
+++ b/src/server/shared/Packets/ByteBuffer.cpp
@@ -27,11 +27,10 @@ ByteBufferPositionException::ByteBufferPositionException(bool add, size_t pos,
size_t size, size_t valueSize)
{
std::ostringstream ss;
- ACE_Stack_Trace trace;
ss << "Attempted to " << (add ? "put" : "get") << " value with size: "
<< valueSize << " in ByteBuffer (pos: " << pos << " size: " << size
- << ")\n\n" << trace.c_str();
+ << ")";
message().assign(ss.str());
}
@@ -40,12 +39,10 @@ ByteBufferSourceException::ByteBufferSourceException(size_t pos, size_t size,
size_t valueSize)
{
std::ostringstream ss;
- ACE_Stack_Trace trace;
ss << "Attempted to put a "
<< (valueSize > 0 ? "NULL-pointer" : "zero-sized value")
- << " in ByteBuffer (pos: " << pos << " size: " << size << ")\n\n"
- << trace.c_str();
+ << " in ByteBuffer (pos: " << pos << " size: " << size << ")";
message().assign(ss.str());
}
diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index 33d33519c8f..11e835566e9 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -31,6 +31,7 @@
#include <vector>
#include <cstring>
#include <time.h>
+#include <math.h>
// Root of ByteBuffer exception hierarchy
class ByteBufferException : public std::exception
@@ -85,6 +86,8 @@ class ByteBuffer
{
}
+ virtual ~ByteBuffer() { }
+
void clear()
{
_storage.clear();
@@ -239,12 +242,16 @@ class ByteBuffer
ByteBuffer &operator>>(float &value)
{
value = read<float>();
+ if (!std::isfinite(value))
+ throw ByteBufferException();
return *this;
}
ByteBuffer &operator>>(double &value)
{
value = read<double>();
+ if (!std::isfinite(value))
+ throw ByteBufferException();
return *this;
}
@@ -375,9 +382,19 @@ class ByteBuffer
return *this;
}
- uint8 * contents() { return &_storage[0]; }
+ uint8 * contents()
+ {
+ if (_storage.empty())
+ throw ByteBufferException();
+ return &_storage[0];
+ }
- const uint8 *contents() const { return &_storage[0]; }
+ const uint8 *contents() const
+ {
+ if (_storage.empty())
+ throw ByteBufferException();
+ return &_storage[0];
+ }
size_t size() const { return _storage.size(); }
bool empty() const { return _storage.empty(); }
diff --git a/src/server/shared/Threading/Callback.h b/src/server/shared/Threading/Callback.h
index b074ff49c3c..c48546bbf5c 100644
--- a/src/server/shared/Threading/Callback.h
+++ b/src/server/shared/Threading/Callback.h
@@ -109,6 +109,9 @@ class QueryCallback
ACE_Future<Result> _result;
ParamType _param;
uint8 _stage;
+
+ QueryCallback(QueryCallback const& right) = delete;
+ QueryCallback& operator=(QueryCallback const& right) = delete;
};
template <typename Result, typename ParamType1, typename ParamType2, bool chain = false>
@@ -201,6 +204,9 @@ class QueryCallback_2
ParamType1 _param_1;
ParamType2 _param_2;
uint8 _stage;
+
+ QueryCallback_2(QueryCallback_2 const& right) = delete;
+ QueryCallback_2& operator=(QueryCallback_2 const& right) = delete;
};
#endif \ No newline at end of file
diff --git a/src/server/shared/Utilities/ByteConverter.h b/src/server/shared/Utilities/ByteConverter.h
index bf1342a10e4..8eebb05bb13 100644
--- a/src/server/shared/Utilities/ByteConverter.h
+++ b/src/server/shared/Utilities/ByteConverter.h
@@ -47,9 +47,13 @@ namespace ByteConverter
#if TRINITY_ENDIAN == TRINITY_BIGENDIAN
template<typename T> inline void EndianConvert(T& val) { ByteConverter::apply<T>(&val); }
template<typename T> inline void EndianConvertReverse(T&) { }
+template<typename T> inline void EndianConvertPtr(void* val) { ByteConverter::apply<T>(val); }
+template<typename T> inline void EndianConvertPtrReverse(void*) { }
#else
template<typename T> inline void EndianConvert(T&) { }
template<typename T> inline void EndianConvertReverse(T& val) { ByteConverter::apply<T>(&val); }
+template<typename T> inline void EndianConvertPtr(void*) { }
+template<typename T> inline void EndianConvertPtrReverse(void* val) { ByteConverter::apply<T>(val); }
#endif
template<typename T> void EndianConvert(T*); // will generate link error
diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp
index 499ad0502b7..28bbe831a69 100644
--- a/src/server/shared/Utilities/Util.cpp
+++ b/src/server/shared/Utilities/Util.cpp
@@ -510,6 +510,9 @@ void vutf8printf(FILE* out, const char *str, va_list* ap)
wchar_t wtemp_buf[32*1024];
size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap);
+ //vsnprintf returns -1 if the buffer is too small
+ if (temp_len == size_t(-1))
+ temp_len = 32*1024-1;
size_t wtemp_len = 32*1024-1;
Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
@@ -544,3 +547,12 @@ std::string ByteArrayToHexStr(uint8 const* bytes, uint32 arrayLen, bool reverse
return ss.str();
}
+
+uint32 EventMap::GetTimeUntilEvent(uint32 eventId) const
+{
+ for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr)
+ if (eventId == (itr->second & 0x0000FFFF))
+ return itr->first - _time;
+
+ return std::numeric_limits<uint32>::max();
+}
diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h
index b086a28134c..648edf39abe 100644
--- a/src/server/shared/Utilities/Util.h
+++ b/src/server/shared/Utilities/Util.h
@@ -26,6 +26,7 @@
#include <string>
#include <vector>
#include <list>
+#include <map>
#include <ace/INET_Addr.h>
// Searcher for map of structs
@@ -565,4 +566,346 @@ bool CompareValues(ComparisionType type, T val1, T val2)
}
}
+class EventMap
+{
+ /**
+ * Internal storage type.
+ * Key: Time as uint32 when the event should occur.
+ * Value: The event data as uint32.
+ *
+ * Structure of event data:
+ * - Bit 0 - 15: Event Id.
+ * - Bit 16 - 23: Group
+ * - Bit 24 - 31: Phase
+ * - Pattern: 0xPPGGEEEE
+ */
+ typedef std::multimap<uint32, uint32> EventStore;
+
+ public:
+ EventMap() : _time(0), _phase(0), _lastEvent(0) { }
+
+ /**
+ * @name Reset
+ * @brief Removes all scheduled events and resets time and phase.
+ */
+ void Reset()
+ {
+ _eventMap.clear();
+ _time = 0;
+ _phase = 0;
+ }
+
+ /**
+ * @name Update
+ * @brief Updates the timer of the event map.
+ * @param time Value to be added to time.
+ */
+ void Update(uint32 time)
+ {
+ _time += time;
+ }
+
+ /**
+ * @name GetTimer
+ * @return Current timer value.
+ */
+ uint32 GetTimer() const
+ {
+ return _time;
+ }
+
+ /**
+ * @name GetPhaseMask
+ * @return Active phases as mask.
+ */
+ uint8 GetPhaseMask() const
+ {
+ return _phase;
+ }
+
+ /**
+ * @name Empty
+ * @return True, if there are no events scheduled.
+ */
+ bool Empty() const
+ {
+ return _eventMap.empty();
+ }
+
+ /**
+ * @name SetPhase
+ * @brief Sets the phase of the map (absolute).
+ * @param phase Phase which should be set. Values: 1 - 8. 0 resets phase.
+ */
+ void SetPhase(uint8 phase)
+ {
+ if (!phase)
+ _phase = 0;
+ else if (phase <= 8)
+ _phase = (1 << (phase - 1));
+ }
+
+ /**
+ * @name AddPhase
+ * @brief Activates the given phase (bitwise).
+ * @param phase Phase which should be activated. Values: 1 - 8
+ */
+ void AddPhase(uint8 phase)
+ {
+ if (phase && phase <= 8)
+ _phase |= (1 << (phase - 1));
+ }
+
+ /**
+ * @name RemovePhase
+ * @brief Deactivates the given phase (bitwise).
+ * @param phase Phase which should be deactivated. Values: 1 - 8.
+ */
+ void RemovePhase(uint8 phase)
+ {
+ if (phase && phase <= 8)
+ _phase &= ~(1 << (phase - 1));
+ }
+
+ /**
+ * @name ScheduleEvent
+ * @brief Creates new event entry in map.
+ * @param eventId The id of the new event.
+ * @param time The time in milliseconds until the event occurs.
+ * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group.
+ * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases.
+ */
+ void ScheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0)
+ {
+ if (group && group <= 8)
+ eventId |= (1 << (group + 15));
+
+ if (phase && phase <= 8)
+ eventId |= (1 << (phase + 23));
+
+ _eventMap.insert(EventStore::value_type(_time + time, eventId));
+ }
+
+ /**
+ * @name RescheduleEvent
+ * @brief Cancels the given event and reschedules it.
+ * @param eventId The id of the event.
+ * @param time The time in milliseconds until the event occurs.
+ * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group.
+ * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases.
+ */
+ void RescheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0)
+ {
+ CancelEvent(eventId);
+ ScheduleEvent(eventId, time, group, phase);
+ }
+
+ /**
+ * @name RepeatEvent
+ * @brief Repeats the mostly recently executed event.
+ * @param time Time until the event occurs.
+ */
+ void Repeat(uint32 time)
+ {
+ _eventMap.insert(EventStore::value_type(_time + time, _lastEvent));
+ }
+
+ /**
+ * @name RepeatEvent
+ * @brief Repeats the mostly recently executed event.
+ * @param time Time until the event occurs. Equivalent to Repeat(urand(minTime, maxTime).
+ */
+ void Repeat(uint32 minTime, uint32 maxTime)
+ {
+ Repeat(urand(minTime, maxTime));
+ }
+
+ /**
+ * @name ExecuteEvent
+ * @brief Returns the next event to execute and removes it from map.
+ * @return Id of the event to execute.
+ */
+ uint32 ExecuteEvent()
+ {
+ while (!Empty())
+ {
+ EventStore::iterator itr = _eventMap.begin();
+
+ if (itr->first > _time)
+ return 0;
+ else if (_phase && (itr->second & 0xFF000000) && !((itr->second >> 24) & _phase))
+ _eventMap.erase(itr);
+ else
+ {
+ uint32 eventId = (itr->second & 0x0000FFFF);
+ _lastEvent = itr->second; // include phase/group
+ _eventMap.erase(itr);
+ return eventId;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * @name DelayEvents
+ * @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0.
+ * @param delay Amount of delay.
+ */
+ void DelayEvents(uint32 delay)
+ {
+ _time = delay < _time ? _time - delay : 0;
+ }
+
+ /**
+ * @name DelayEvents
+ * @brief Delay all events of the same group.
+ * @param delay Amount of delay.
+ * @param group Group of the events.
+ */
+ void DelayEvents(uint32 delay, uint32 group)
+ {
+ if (!group || group > 8 || Empty())
+ return;
+
+ EventStore delayed;
+
+ for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();)
+ {
+ if (itr->second & (1 << (group + 15)))
+ {
+ delayed.insert(EventStore::value_type(itr->first + delay, itr->second));
+ _eventMap.erase(itr++);
+ }
+ else
+ ++itr;
+ }
+
+ _eventMap.insert(delayed.begin(), delayed.end());
+ }
+
+ /**
+ * @name CancelEvent
+ * @brief Cancels all events of the specified id.
+ * @param eventId Event id to cancel.
+ */
+ void CancelEvent(uint32 eventId)
+ {
+ if (Empty())
+ return;
+
+ for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();)
+ {
+ if (eventId == (itr->second & 0x0000FFFF))
+ _eventMap.erase(itr++);
+ else
+ ++itr;
+ }
+ }
+
+ /**
+ * @name CancelEventGroup
+ * @brief Cancel events belonging to specified group.
+ * @param group Group to cancel.
+ */
+ void CancelEventGroup(uint32 group)
+ {
+ if (!group || group > 8 || Empty())
+ return;
+
+ for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();)
+ {
+ if (itr->second & (1 << (group + 15)))
+ _eventMap.erase(itr++);
+ else
+ ++itr;
+ }
+ }
+
+ /**
+ * @name GetNextEventTime
+ * @brief Returns closest occurence of specified event.
+ * @param eventId Wanted event id.
+ * @return Time of found event.
+ */
+ uint32 GetNextEventTime(uint32 eventId) const
+ {
+ if (Empty())
+ return 0;
+
+ for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr)
+ if (eventId == (itr->second & 0x0000FFFF))
+ return itr->first;
+
+ return 0;
+ }
+
+ /**
+ * @name GetNextEventTime
+ * @return Time of next event.
+ */
+ uint32 GetNextEventTime() const
+ {
+ return Empty() ? 0 : _eventMap.begin()->first;
+ }
+
+ /**
+ * @name IsInPhase
+ * @brief Returns wether event map is in specified phase or not.
+ * @param phase Wanted phase.
+ * @return True, if phase of event map contains specified phase.
+ */
+ bool IsInPhase(uint8 phase)
+ {
+ return phase <= 8 && (!phase || _phase & (1 << (phase - 1)));
+ }
+
+ /**
+ * @name GetTimeUntilEvent
+ * @brief Returns time in milliseconds until next event.
+ * @param Id of the event.
+ * @return Time of next event.
+ */
+ uint32 GetTimeUntilEvent(uint32 eventId) const;
+
+ private:
+ /**
+ * @name _time
+ * @brief Internal timer.
+ *
+ * This does not represent the real date/time value.
+ * It's more like a stopwatch: It can run, it can be stopped,
+ * it can be resetted and so on. Events occur when this timer
+ * has reached their time value. Its value is changed in the
+ * Update method.
+ */
+ uint32 _time;
+
+ /**
+ * @name _phase
+ * @brief Phase mask of the event map.
+ *
+ * Contains the phases the event map is in. Multiple
+ * phases from 1 to 8 can be set with SetPhase or
+ * AddPhase. RemovePhase deactives a phase.
+ */
+ uint8 _phase;
+
+ /**
+ * @name _eventMap
+ * @brief Internal event storage map. Contains the scheduled events.
+ *
+ * See typedef at the beginning of the class for more
+ * details.
+ */
+ EventStore _eventMap;
+
+
+ /**
+ * @name _lastEvent
+ * @brief Stores information on the most recently executed event
+ */
+ uint32 _lastEvent;
+};
+
#endif