Clean minidump code
This commit is contained in:
parent
458ae5f2aa
commit
0c978d9980
@ -8,37 +8,36 @@ using namespace Utils;
|
|||||||
|
|
||||||
namespace Components
|
namespace Components
|
||||||
{
|
{
|
||||||
BitMessage* BitMessage::Singleton = NULL;
|
BitMRC* BitMessage::BMClient;
|
||||||
|
|
||||||
BitMessage::BitMessage()
|
BitMessage::BitMessage()
|
||||||
{
|
{
|
||||||
if (Singleton != NULL)
|
|
||||||
throw new std::runtime_error("Only one instance of BitMessage allowed at the same time.");
|
|
||||||
|
|
||||||
Singleton = this;
|
|
||||||
|
|
||||||
Logger::Print("Initializing BitMessage...\n");
|
Logger::Print("Initializing BitMessage...\n");
|
||||||
this->BMClient = new BitMRC(BITMESSAGE_OBJECT_STORAGE_FILENAME, BITMESSAGE_KEYS_FILENAME);
|
|
||||||
this->BMClient->init();
|
|
||||||
this->BMClient->defaultTTL = 1 * 60 * 60; // 1 hour
|
|
||||||
|
|
||||||
if (this->BMClient->PrivAddresses.empty())
|
BitMessage::BMClient = new BitMRC(BITMESSAGE_OBJECT_STORAGE_FILENAME, BITMESSAGE_KEYS_FILENAME);
|
||||||
|
BitMessage::BMClient->init();
|
||||||
|
BitMessage::BMClient->defaultTTL = 1 * 60 * 60; // 1 hour
|
||||||
|
|
||||||
|
if (BitMessage::BMClient->PrivAddresses.empty())
|
||||||
{
|
{
|
||||||
if (!this->InitAddr())
|
if (!this->InitAddr())
|
||||||
{
|
{
|
||||||
// Generate a random address ready to use
|
// Generate a random address ready to use
|
||||||
throw std::runtime_error("Failed to prepare source address for exception handling");
|
throw std::runtime_error("Failed to prepare source address for exception handling");
|
||||||
}
|
}
|
||||||
this->BMClient->save();
|
|
||||||
|
BitMessage::BMClient->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->BMClient->start();
|
BitMessage::BMClient->start();
|
||||||
|
|
||||||
Command::Add("bm_send", [](Command::Params params) {
|
Command::Add("bm_send", [](Command::Params params)
|
||||||
|
{
|
||||||
if (params.Length() < 3) return;
|
if (params.Length() < 3) return;
|
||||||
|
|
||||||
ustring pubAddrString;
|
ustring pubAddrString;
|
||||||
pubAddrString.fromString(params[1]);
|
pubAddrString.fromString(params[1]);
|
||||||
|
|
||||||
PubAddr pubAddr;
|
PubAddr pubAddr;
|
||||||
if (pubAddr.loadAddr(pubAddrString))
|
if (pubAddr.loadAddr(pubAddrString))
|
||||||
{
|
{
|
||||||
@ -46,7 +45,7 @@ namespace Components
|
|||||||
msg.fromString(params.Join(2));
|
msg.fromString(params.Join(2));
|
||||||
|
|
||||||
Logger::Print("Sending message (this may take a while)...\n");
|
Logger::Print("Sending message (this may take a while)...\n");
|
||||||
Singleton->BMClient->sendMessage(msg, pubAddr, Singleton->BMClient->PrivAddresses[0]);
|
BitMessage::BMClient->sendMessage(msg, pubAddr, BitMessage::BMClient->PrivAddresses[0]);
|
||||||
Logger::Print("Message sent.\n");
|
Logger::Print("Message sent.\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -54,86 +53,105 @@ namespace Components
|
|||||||
Logger::Print("Address not correct!\n");
|
Logger::Print("Address not correct!\n");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Command::Add("bm_sendb", [](Command::Params params) {
|
|
||||||
|
Command::Add("bm_sendb", [](Command::Params params)
|
||||||
|
{
|
||||||
if (params.Length() < 2) return;
|
if (params.Length() < 2) return;
|
||||||
|
|
||||||
ustring msg;
|
ustring msg;
|
||||||
msg.appendVarString(params.Join(1));
|
msg.appendVarString(params.Join(1));
|
||||||
Logger::Print("Sending broadcast...\n");
|
Logger::Print("Sending broadcast...\n");
|
||||||
Singleton->BMClient->sendBroadcast(msg, Singleton->BMClient->PrivAddresses[0]);
|
BitMessage::BMClient->sendBroadcast(msg, BitMessage::BMClient->PrivAddresses[0]);
|
||||||
Logger::Print("Broadcast done.\n");
|
Logger::Print("Broadcast done.\n");
|
||||||
});
|
});
|
||||||
Command::Add("bm_check_messages", [](Command::Params) {
|
|
||||||
while (Singleton->BMClient->new_messages.size() > 0)
|
Command::Add("bm_check_messages", [](Command::Params)
|
||||||
|
{
|
||||||
|
while (BitMessage::BMClient->new_messages.size() > 0)
|
||||||
{
|
{
|
||||||
auto msg = Singleton->BMClient->new_messages.pop();
|
auto msg = BitMessage::BMClient->new_messages.pop();
|
||||||
Logger::Print("New message:\nFrom: %s\nTo: %s\nMessage:\n%s\n", msg.from.c_str(), msg.to.c_str(), msg.info.c_str());
|
Logger::Print("New message:\nFrom: %s\nTo: %s\nMessage:\n%s\n", msg.from.data(), msg.to.data(), msg.info.data());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Command::Add("bm_check_connections", [](Command::Params) {
|
|
||||||
std::shared_lock<std::shared_timed_mutex> mlock(Singleton->BMClient->mutex_nodes);
|
|
||||||
|
|
||||||
for (auto& node : Singleton->BMClient->Nodes)
|
Command::Add("bm_check_connections", [](Command::Params)
|
||||||
|
{
|
||||||
|
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_nodes);
|
||||||
|
|
||||||
|
for (auto& node : BitMessage::BMClient->Nodes)
|
||||||
{
|
{
|
||||||
switch (node->state) {
|
switch (node->state) {
|
||||||
case 0: // Not connected
|
case 0: // Not connected
|
||||||
Logger::Print("%s: Disconnected\n", node->Ip.c_str());
|
Logger::Print("%s: Disconnected\n", node->Ip.data());
|
||||||
break;
|
break;
|
||||||
case 1: // Connecting
|
case 1: // Connecting
|
||||||
Logger::Print("%s: Connecting\n", node->Ip.c_str());
|
Logger::Print("%s: Connecting\n", node->Ip.data());
|
||||||
break;
|
break;
|
||||||
case 2: // Connected
|
case 2: // Connected
|
||||||
Logger::Print("%s: Connected\n", node->Ip.c_str());
|
Logger::Print("%s: Connected\n", node->Ip.data());
|
||||||
break;
|
break;
|
||||||
case 3: // Reconnecting
|
case 3: // Reconnecting
|
||||||
Logger::Print("%s: Reconnecting\n", node->Ip.c_str());
|
Logger::Print("%s: Reconnecting\n", node->Ip.data());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mlock.unlock();
|
mlock.unlock();
|
||||||
});
|
});
|
||||||
Command::Add("bm_check_privatekey", [](Command::Params) {
|
|
||||||
std::shared_lock<std::shared_timed_mutex> mlock(Singleton->BMClient->mutex_priv);
|
|
||||||
|
|
||||||
if (Singleton->BMClient->PrivAddresses.empty()) {
|
Command::Add("bm_check_privatekey", [](Command::Params)
|
||||||
|
{
|
||||||
|
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_priv);
|
||||||
|
|
||||||
|
if (BitMessage::BMClient->PrivAddresses.empty())
|
||||||
|
{
|
||||||
Logger::Print("No private key\n");
|
Logger::Print("No private key\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
for (auto& addr : Singleton->BMClient->PrivAddresses)
|
{
|
||||||
|
for (auto& addr : BitMessage::BMClient->PrivAddresses)
|
||||||
{
|
{
|
||||||
Logger::Print("%s\n", addr.getAddress().c_str());
|
Logger::Print("%s\n", addr.getAddress().data());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mlock.unlock();
|
mlock.unlock();
|
||||||
});
|
});
|
||||||
Command::Add("bm_check_publickey", [](Command::Params) {
|
|
||||||
std::shared_lock<std::shared_timed_mutex> mlock(Singleton->BMClient->mutex_pub);
|
|
||||||
|
|
||||||
if (Singleton->BMClient->PubAddresses.empty()) {
|
Command::Add("bm_check_publickey", [](Command::Params)
|
||||||
|
{
|
||||||
|
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_pub);
|
||||||
|
|
||||||
|
if (BitMessage::BMClient->PubAddresses.empty())
|
||||||
|
{
|
||||||
Logger::Print("No public key\n");
|
Logger::Print("No public key\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
for (auto& addr : Singleton->BMClient->PubAddresses)
|
for (auto& addr : BitMessage::BMClient->PubAddresses)
|
||||||
{
|
{
|
||||||
Logger::Print("%s (waiting for public key: %s)\n", addr.getAddress().c_str(), addr.waitingPubKey() ? "yes" : "no");
|
Logger::Print("%s (waiting for public key: %s)\n", addr.getAddress().data(), addr.waitingPubKey() ? "yes" : "no");
|
||||||
}
|
}
|
||||||
|
|
||||||
mlock.unlock();
|
mlock.unlock();
|
||||||
});
|
});
|
||||||
Command::Add("bm_save", [](Command::Params) {
|
|
||||||
Singleton->Save();
|
Command::Add("bm_save", [](Command::Params)
|
||||||
|
{
|
||||||
|
BitMessage::Save();
|
||||||
});
|
});
|
||||||
Command::Add("bm_address_public", [](Command::Params params) {
|
|
||||||
|
Command::Add("bm_address_public", [](Command::Params params)
|
||||||
|
{
|
||||||
if (params.Length() < 2) return;
|
if (params.Length() < 2) return;
|
||||||
|
|
||||||
ustring addre;
|
ustring addre;
|
||||||
addre.fromString(params.Join(1));
|
addre.fromString(params.Join(1));
|
||||||
|
|
||||||
PubAddr address;
|
PubAddr address;
|
||||||
if (address.loadAddr(addre))
|
if (address.loadAddr(addre))
|
||||||
{
|
{
|
||||||
Logger::Print("Asking public key!\n");
|
Logger::Print("Asking public key!\n");
|
||||||
Singleton->BMClient->getPubKey(address);
|
BitMessage::BMClient->getPubKey(address);
|
||||||
Logger::Print("Asked! check publickey for news on that address!\n");
|
Logger::Print("Asked! check publickey for news on that address!\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -141,7 +159,9 @@ namespace Components
|
|||||||
Logger::Print("Address not correct!\n");
|
Logger::Print("Address not correct!\n");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Command::Add("bm_address_broadcast", [](Command::Params params) {
|
|
||||||
|
Command::Add("bm_address_broadcast", [](Command::Params params)
|
||||||
|
{
|
||||||
if (params.Length() < 2) return;
|
if (params.Length() < 2) return;
|
||||||
|
|
||||||
ustring addre;
|
ustring addre;
|
||||||
@ -150,7 +170,7 @@ namespace Components
|
|||||||
if (address.loadAddr(addre))
|
if (address.loadAddr(addre))
|
||||||
{
|
{
|
||||||
Logger::Print("Adding subscription!\n");
|
Logger::Print("Adding subscription!\n");
|
||||||
Singleton->BMClient->addSubscription(address);
|
BitMessage::BMClient->addSubscription(address);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -161,13 +181,13 @@ namespace Components
|
|||||||
|
|
||||||
BitMessage::~BitMessage()
|
BitMessage::~BitMessage()
|
||||||
{
|
{
|
||||||
Singleton = NULL;
|
delete BitMessage::BMClient;
|
||||||
delete this->BMClient;
|
BitMessage::BMClient = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitMessage::SetDefaultTTL(time_t ttl)
|
void BitMessage::SetDefaultTTL(time_t ttl)
|
||||||
{
|
{
|
||||||
this->BMClient->defaultTTL = ttl;
|
BitMessage::BMClient->defaultTTL = ttl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitMessage::RequestPublicKey(std::string targetAddress)
|
bool BitMessage::RequestPublicKey(std::string targetAddress)
|
||||||
@ -184,17 +204,17 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Request public key!
|
// Request public key!
|
||||||
this->BMClient->getPubKey(pubAddr);
|
BitMessage::BMClient->getPubKey(pubAddr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PubAddr* BitMessage::FindPublicKey(PubAddr address)
|
PubAddr* BitMessage::FindPublicKey(PubAddr address)
|
||||||
{
|
{
|
||||||
std::shared_lock<std::shared_timed_mutex> mlock(Singleton->BMClient->mutex_pub);
|
std::shared_lock<std::shared_timed_mutex> mlock(BitMessage::BMClient->mutex_pub);
|
||||||
|
|
||||||
PubAddr* retval = nullptr;
|
PubAddr* retval = nullptr;
|
||||||
|
|
||||||
for (auto& pubKey : BMClient->PubAddresses)
|
for (auto& pubKey : BitMessage::BMClient->PubAddresses)
|
||||||
{
|
{
|
||||||
if (pubKey.getVersion() == address.getVersion()) //check same version
|
if (pubKey.getVersion() == address.getVersion()) //check same version
|
||||||
{
|
{
|
||||||
@ -206,6 +226,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mlock.unlock();
|
mlock.unlock();
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
@ -233,17 +254,19 @@ namespace Components
|
|||||||
(!resolvedAddress->waitingPubKey() && resolvedAddress->getPubEncryptionKey().empty()))
|
(!resolvedAddress->waitingPubKey() && resolvedAddress->getPubEncryptionKey().empty()))
|
||||||
{
|
{
|
||||||
// Request public key
|
// Request public key
|
||||||
this->BMClient->getPubKey(address);
|
BitMessage::BMClient->getPubKey(address);
|
||||||
resolvedAddress = FindPublicKey(address);
|
resolvedAddress = FindPublicKey(address);
|
||||||
}
|
}
|
||||||
this->Save();
|
|
||||||
|
BitMessage::Save();
|
||||||
|
|
||||||
// TODO: Wait for public key by using signaling in BitMRC, needs to be done directly in the fork.
|
// TODO: Wait for public key by using signaling in BitMRC, needs to be done directly in the fork.
|
||||||
while (resolvedAddress->waitingPubKey())
|
while (resolvedAddress->waitingPubKey())
|
||||||
{
|
{
|
||||||
sleep(1500);
|
std::this_thread::sleep_for(1500ms);
|
||||||
}
|
}
|
||||||
this->Save();
|
|
||||||
|
BitMessage::Save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -262,7 +285,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Subscribe!
|
// Subscribe!
|
||||||
this->BMClient->addSubscription(pubAddr);
|
BitMessage::BMClient->addSubscription(pubAddr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,9 +309,14 @@ namespace Components
|
|||||||
// Send the message
|
// Send the message
|
||||||
// TODO - Set mutex on priv when accessing first private address
|
// TODO - Set mutex on priv when accessing first private address
|
||||||
if (ttl > 0)
|
if (ttl > 0)
|
||||||
this->BMClient->sendMessage(messageU, pubAddr, this->BMClient->PrivAddresses[0], ttl);
|
{
|
||||||
|
BitMessage::BMClient->sendMessage(messageU, pubAddr, BitMessage::BMClient->PrivAddresses[0], ttl);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
this->BMClient->sendMessage(messageU, pubAddr, this->BMClient->PrivAddresses[0]);
|
{
|
||||||
|
BitMessage::BMClient->sendMessage(messageU, pubAddr, BitMessage::BMClient->PrivAddresses[0]);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,27 +328,34 @@ namespace Components
|
|||||||
|
|
||||||
// TODO - Set mutex on priv when accessing first private address
|
// TODO - Set mutex on priv when accessing first private address
|
||||||
if (ttl > 0)
|
if (ttl > 0)
|
||||||
this->BMClient->sendBroadcast(messageU, this->BMClient->PrivAddresses[0], ttl);
|
{
|
||||||
|
BitMessage::BMClient->sendBroadcast(messageU, BitMessage::BMClient->PrivAddresses[0], ttl);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
this->BMClient->sendBroadcast(messageU, this->BMClient->PrivAddresses[0]);
|
{
|
||||||
|
BitMessage::BMClient->sendBroadcast(messageU, BitMessage::BMClient->PrivAddresses[0]);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BitMessage::InitAddr()
|
bool BitMessage::InitAddr()
|
||||||
{
|
{
|
||||||
Logger::Print("Generating BM address...\n");
|
Logger::Print("Generating BM address...\n");
|
||||||
|
|
||||||
Addr myAddress;
|
Addr myAddress;
|
||||||
if (!myAddress.generateRandom())
|
if (!myAddress.generateRandom())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
BMClient->addAddr(myAddress);
|
|
||||||
|
BitMessage::BMClient->addAddr(myAddress);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitMessage::Save()
|
void BitMessage::Save()
|
||||||
{
|
{
|
||||||
BMClient->save();
|
BitMessage::BMClient->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,20 +17,19 @@ namespace Components
|
|||||||
const char* GetName() { return "BitMessage"; };
|
const char* GetName() { return "BitMessage"; };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void SetDefaultTTL(time_t ttl);
|
static void SetDefaultTTL(time_t ttl);
|
||||||
bool RequestPublicKey(std::string targetAddress);
|
static bool RequestPublicKey(std::string targetAddress);
|
||||||
bool WaitForPublicKey(std::string targetAddress);
|
static bool WaitForPublicKey(std::string targetAddress);
|
||||||
bool Subscribe(std::string targetAddress);
|
static bool Subscribe(std::string targetAddress);
|
||||||
bool SendMsg(std::string targetAddress, std::string message, time_t ttl = 0);
|
static bool SendMsg(std::string targetAddress, std::string message, time_t ttl = 0);
|
||||||
bool SendBroadcast(std::string message, time_t ttl = 0);
|
static bool SendBroadcast(std::string message, time_t ttl = 0);
|
||||||
void Save();
|
static void Save();
|
||||||
|
|
||||||
static BitMessage* Singleton;
|
static BitMRC* BMClient;
|
||||||
BitMRC* BMClient;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PubAddr* FindPublicKey(PubAddr addr);
|
static PubAddr* FindPublicKey(PubAddr addr);
|
||||||
bool InitAddr();
|
static bool InitAddr();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,8 +20,8 @@ namespace Components
|
|||||||
return EXCEPTION_CONTINUE_EXECUTION;
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto minidump = MinidumpUpload::Singleton->CreateQueuedMinidump(ExceptionInfo);
|
auto minidump = MinidumpUpload::CreateQueuedMinidump(ExceptionInfo);
|
||||||
if (minidump == NULL)
|
if (!minidump)
|
||||||
{
|
{
|
||||||
OutputDebugStringA("Failed to create new minidump!");
|
OutputDebugStringA("Failed to create new minidump!");
|
||||||
Utils::OutputDebugLastError();
|
Utils::OutputDebugLastError();
|
||||||
@ -31,14 +31,13 @@ namespace Components
|
|||||||
delete minidump;
|
delete minidump;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ExceptionInfo->ExceptionRecord->ExceptionCode)
|
if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW)
|
||||||
{
|
{
|
||||||
case EXCEPTION_STACK_OVERFLOW:
|
|
||||||
Logger::Error("Termination because of a stack overflow.\n");
|
Logger::Error("Termination because of a stack overflow.\n");
|
||||||
break;
|
}
|
||||||
default:
|
else
|
||||||
|
{
|
||||||
Logger::Error("Fatal error (0x%08X) at 0x%08X.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
|
Logger::Error("Fatal error (0x%08X) at 0x%08X.", ExceptionInfo->ExceptionRecord->ExceptionCode, ExceptionInfo->ExceptionRecord->ExceptionAddress);
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
|
//TerminateProcess(GetCurrentProcess(), ExceptionInfo->ExceptionRecord->ExceptionCode);
|
||||||
@ -118,71 +117,51 @@ namespace Components
|
|||||||
auto oldHandler = Exception::Hook();
|
auto oldHandler = Exception::Hook();
|
||||||
Logger::Print("Old exception handler was 0x%010X.\n", oldHandler);
|
Logger::Print("Old exception handler was 0x%010X.\n", oldHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable:4740) // flow in or out of inline asm code suppresses global optimization
|
#pragma warning(disable:4740) // flow in or out of inline asm code suppresses global optimization
|
||||||
Command::Add("debug_minidump", [](Command::Params)
|
Command::Add("debug_minidump", [](Command::Params)
|
||||||
{
|
{
|
||||||
// The following code was taken from VC++ 8.0 CRT (invarg.c: line 104)
|
// The following code was taken from VC++ 8.0 CRT (invarg.c: line 104)
|
||||||
|
|
||||||
EXCEPTION_RECORD ExceptionRecord;
|
|
||||||
CONTEXT ContextRecord;
|
CONTEXT ContextRecord;
|
||||||
memset(&ContextRecord, 0, sizeof(CONTEXT));
|
EXCEPTION_RECORD ExceptionRecord;
|
||||||
|
ZeroMemory(&ContextRecord, sizeof(CONTEXT));
|
||||||
|
|
||||||
#ifdef _X86_
|
__asm
|
||||||
|
{
|
||||||
|
mov [ContextRecord.Eax], eax
|
||||||
|
mov [ContextRecord.Ecx], ecx
|
||||||
|
mov [ContextRecord.Edx], edx
|
||||||
|
mov [ContextRecord.Ebx], ebx
|
||||||
|
mov [ContextRecord.Esi], esi
|
||||||
|
mov [ContextRecord.Edi], edi
|
||||||
|
mov word ptr [ContextRecord.SegSs], ss
|
||||||
|
mov word ptr [ContextRecord.SegCs], cs
|
||||||
|
mov word ptr [ContextRecord.SegDs], ds
|
||||||
|
mov word ptr [ContextRecord.SegEs], es
|
||||||
|
mov word ptr [ContextRecord.SegFs], fs
|
||||||
|
mov word ptr [ContextRecord.SegGs], gs
|
||||||
|
|
||||||
__asm {
|
|
||||||
mov dword ptr[ContextRecord.Eax], eax
|
|
||||||
mov dword ptr[ContextRecord.Ecx], ecx
|
|
||||||
mov dword ptr[ContextRecord.Edx], edx
|
|
||||||
mov dword ptr[ContextRecord.Ebx], ebx
|
|
||||||
mov dword ptr[ContextRecord.Esi], esi
|
|
||||||
mov dword ptr[ContextRecord.Edi], edi
|
|
||||||
mov word ptr[ContextRecord.SegSs], ss
|
|
||||||
mov word ptr[ContextRecord.SegCs], cs
|
|
||||||
mov word ptr[ContextRecord.SegDs], ds
|
|
||||||
mov word ptr[ContextRecord.SegEs], es
|
|
||||||
mov word ptr[ContextRecord.SegFs], fs
|
|
||||||
mov word ptr[ContextRecord.SegGs], gs
|
|
||||||
pushfd
|
pushfd
|
||||||
pop[ContextRecord.EFlags]
|
pop [ContextRecord.EFlags]
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextRecord.ContextFlags = CONTEXT_CONTROL;
|
ContextRecord.ContextFlags = CONTEXT_CONTROL;
|
||||||
#pragma warning(push)
|
ContextRecord.Eip = reinterpret_cast<DWORD>(_ReturnAddress());
|
||||||
#pragma warning(disable:4311)
|
ContextRecord.Esp = reinterpret_cast<DWORD>(_AddressOfReturnAddress());
|
||||||
ContextRecord.Eip = (ULONG)_ReturnAddress();
|
ContextRecord.Ebp = *reinterpret_cast<DWORD*>(_AddressOfReturnAddress()) - 1;
|
||||||
ContextRecord.Esp = (ULONG)_AddressOfReturnAddress();
|
|
||||||
#pragma warning(pop)
|
|
||||||
ContextRecord.Ebp = *((ULONG *)_AddressOfReturnAddress() - 1);
|
|
||||||
|
|
||||||
|
|
||||||
#elif defined (_IA64_) || defined (_AMD64_)
|
|
||||||
|
|
||||||
/* Need to fill up the Context in IA64 and AMD64. */
|
|
||||||
RtlCaptureContext(&ContextRecord);
|
|
||||||
|
|
||||||
#else /* defined (_IA64_) || defined (_AMD64_) */
|
|
||||||
|
|
||||||
ZeroMemory(&ContextRecord, sizeof(ContextRecord));
|
|
||||||
|
|
||||||
#endif /* defined (_IA64_) || defined (_AMD64_) */
|
|
||||||
|
|
||||||
ZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD));
|
ZeroMemory(&ExceptionRecord, sizeof(EXCEPTION_RECORD));
|
||||||
|
|
||||||
ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT;
|
ExceptionRecord.ExceptionCode = EXCEPTION_BREAKPOINT;
|
||||||
ExceptionRecord.ExceptionAddress = _ReturnAddress();
|
ExceptionRecord.ExceptionAddress = _ReturnAddress();
|
||||||
|
|
||||||
|
EXCEPTION_POINTERS eptr;
|
||||||
|
eptr.ExceptionRecord = &ExceptionRecord;
|
||||||
|
eptr.ContextRecord = &ContextRecord;
|
||||||
|
|
||||||
EXCEPTION_RECORD* pExceptionRecord = new EXCEPTION_RECORD;
|
Exception::ExceptionFilter(&eptr);
|
||||||
memcpy(pExceptionRecord, &ExceptionRecord, sizeof(EXCEPTION_RECORD));
|
|
||||||
CONTEXT* pContextRecord = new CONTEXT;
|
|
||||||
memcpy(pContextRecord, &ContextRecord, sizeof(CONTEXT));
|
|
||||||
|
|
||||||
auto eptr = new EXCEPTION_POINTERS;
|
|
||||||
eptr->ExceptionRecord = pExceptionRecord;
|
|
||||||
eptr->ContextRecord = pContextRecord;
|
|
||||||
|
|
||||||
Exception::ExceptionFilter(eptr);
|
|
||||||
});
|
});
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ namespace Components
|
|||||||
if (!this->EnsureFileMapping()) return false;
|
if (!this->EnsureFileMapping()) return false;
|
||||||
|
|
||||||
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
|
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
|
||||||
if (pBuf == NULL)
|
if (!pBuf)
|
||||||
{
|
{
|
||||||
Utils::OutputDebugLastError();
|
Utils::OutputDebugLastError();
|
||||||
throw new std::runtime_error("Could not read minidump.");
|
throw new std::runtime_error("Could not read minidump.");
|
||||||
@ -54,7 +54,7 @@ namespace Components
|
|||||||
if (!this->EnsureFileMapping()) return false;
|
if (!this->EnsureFileMapping()) return false;
|
||||||
|
|
||||||
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
|
auto pBuf = MapViewOfFile(this->mapFileHandle, FILE_MAP_READ, 0, 0, 0);
|
||||||
if (pBuf == NULL)
|
if (!pBuf)
|
||||||
{
|
{
|
||||||
Utils::OutputDebugLastError();
|
Utils::OutputDebugLastError();
|
||||||
throw new std::runtime_error("Could not read minidump.");
|
throw new std::runtime_error("Could not read minidump.");
|
||||||
@ -80,7 +80,7 @@ namespace Components
|
|||||||
Minidump* Minidump::Create(std::string path, LPEXCEPTION_POINTERS exceptionInfo, int type)
|
Minidump* Minidump::Create(std::string path, LPEXCEPTION_POINTERS exceptionInfo, int type)
|
||||||
{
|
{
|
||||||
Minidump* minidump = Minidump::Initialize(path);
|
Minidump* minidump = Minidump::Initialize(path);
|
||||||
if (minidump == NULL) return minidump;
|
if (!minidump) return minidump;
|
||||||
|
|
||||||
// Do the dump generation
|
// Do the dump generation
|
||||||
MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), exceptionInfo, FALSE };
|
MINIDUMP_EXCEPTION_INFORMATION ex = { GetCurrentThreadId(), exceptionInfo, FALSE };
|
||||||
@ -88,15 +88,15 @@ namespace Components
|
|||||||
{
|
{
|
||||||
Utils::OutputDebugLastError();
|
Utils::OutputDebugLastError();
|
||||||
delete minidump;
|
delete minidump;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SetFilePointer(minidump->fileHandle, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
if (SetFilePointer(minidump->fileHandle, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
|
||||||
{
|
{
|
||||||
Utils::OutputDebugLastError();
|
Utils::OutputDebugLastError();
|
||||||
delete minidump;
|
delete minidump;
|
||||||
DeleteFileA(path.c_str());
|
DeleteFileA(path.data());
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return minidump;
|
return minidump;
|
||||||
@ -104,8 +104,7 @@ namespace Components
|
|||||||
|
|
||||||
Minidump* Minidump::Open(std::string path)
|
Minidump* Minidump::Open(std::string path)
|
||||||
{
|
{
|
||||||
Minidump* minidump = Minidump::Initialize(path, FILE_SHARE_READ);
|
return Minidump::Initialize(path, FILE_SHARE_READ);
|
||||||
return minidump;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Minidump::EnsureFileMapping()
|
bool Minidump::EnsureFileMapping()
|
||||||
@ -126,14 +125,15 @@ namespace Components
|
|||||||
{
|
{
|
||||||
Minidump* minidump = new Minidump();
|
Minidump* minidump = new Minidump();
|
||||||
|
|
||||||
minidump->fileHandle = CreateFileA(path.c_str(),
|
minidump->fileHandle = CreateFileA(path.data(),
|
||||||
GENERIC_WRITE | GENERIC_READ, fileShare,
|
GENERIC_WRITE | GENERIC_READ, fileShare,
|
||||||
NULL, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, NULL);
|
NULL, (fileShare & FILE_SHARE_WRITE) > 0 ? OPEN_ALWAYS : OPEN_EXISTING, NULL, NULL);
|
||||||
|
|
||||||
if (minidump->fileHandle == NULL || minidump->fileHandle == INVALID_HANDLE_VALUE)
|
if (minidump->fileHandle == NULL || minidump->fileHandle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
Utils::OutputDebugLastError();
|
Utils::OutputDebugLastError();
|
||||||
delete minidump;
|
delete minidump;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return minidump;
|
return minidump;
|
||||||
@ -141,11 +141,11 @@ namespace Components
|
|||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#pragma region Minidump uploader class implementation
|
#pragma region Minidump uploader class implementation
|
||||||
MinidumpUpload* MinidumpUpload::Singleton = NULL;
|
|
||||||
|
|
||||||
const std::string MinidumpUpload::queuedMinidumpsFolder = "minidumps\\";
|
const std::string MinidumpUpload::queuedMinidumpsFolder = "minidumps\\";
|
||||||
|
|
||||||
#ifdef DISABLE_BITMESSAGE
|
#ifdef DISABLE_BITMESSAGE
|
||||||
const std::vector<std::string> MinidumpUpload::targetUrls = {
|
const std::vector<std::string> MinidumpUpload::targetUrls =
|
||||||
|
{
|
||||||
"https://reich.io/upload.php",
|
"https://reich.io/upload.php",
|
||||||
"https://hitlers.kz/upload.php"
|
"https://hitlers.kz/upload.php"
|
||||||
};
|
};
|
||||||
@ -156,11 +156,6 @@ namespace Components
|
|||||||
|
|
||||||
MinidumpUpload::MinidumpUpload()
|
MinidumpUpload::MinidumpUpload()
|
||||||
{
|
{
|
||||||
if (Singleton != NULL)
|
|
||||||
throw new std::runtime_error("Can only create one instance at a time.");
|
|
||||||
|
|
||||||
Singleton = this;
|
|
||||||
|
|
||||||
#if !defined(DEBUG) || defined(FORCE_MINIDUMP_UPLOAD)
|
#if !defined(DEBUG) || defined(FORCE_MINIDUMP_UPLOAD)
|
||||||
this->uploadThread = std::thread([&]() { this->UploadQueuedMinidumps(); });
|
this->uploadThread = std::thread([&]() { this->UploadQueuedMinidumps(); });
|
||||||
#endif
|
#endif
|
||||||
@ -168,8 +163,6 @@ namespace Components
|
|||||||
|
|
||||||
MinidumpUpload::~MinidumpUpload()
|
MinidumpUpload::~MinidumpUpload()
|
||||||
{
|
{
|
||||||
Singleton = NULL;
|
|
||||||
|
|
||||||
if (this->uploadThread.joinable())
|
if (this->uploadThread.joinable())
|
||||||
{
|
{
|
||||||
this->uploadThread.join();
|
this->uploadThread.join();
|
||||||
@ -178,9 +171,14 @@ namespace Components
|
|||||||
|
|
||||||
bool MinidumpUpload::EnsureQueuedMinidumpsFolderExists()
|
bool MinidumpUpload::EnsureQueuedMinidumpsFolderExists()
|
||||||
{
|
{
|
||||||
BOOL success = CreateDirectoryA(queuedMinidumpsFolder.c_str(), NULL);
|
BOOL success = CreateDirectoryA(MinidumpUpload::queuedMinidumpsFolder.data(), NULL);
|
||||||
if (success != TRUE) success = GetLastError() == ERROR_ALREADY_EXISTS;
|
|
||||||
return success == TRUE;
|
if (success != TRUE)
|
||||||
|
{
|
||||||
|
success = (GetLastError() == ERROR_ALREADY_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (success == TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Minidump* MinidumpUpload::CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType)
|
Minidump* MinidumpUpload::CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType)
|
||||||
@ -206,7 +204,7 @@ namespace Components
|
|||||||
|
|
||||||
// Combine with queuedMinidumpsFolder
|
// Combine with queuedMinidumpsFolder
|
||||||
char filename[MAX_PATH];
|
char filename[MAX_PATH];
|
||||||
PathCombineA(filename, queuedMinidumpsFolder.c_str(), Utils::String::VA("%s-" VERSION_STR "-%s.dmp", exeFileName, filenameFriendlyTime));
|
PathCombineA(filename, MinidumpUpload::queuedMinidumpsFolder.data(), Utils::String::VA("%s-" VERSION_STR "-%s.dmp", exeFileName, filenameFriendlyTime));
|
||||||
|
|
||||||
// Generate the dump
|
// Generate the dump
|
||||||
return Minidump::Create(filename, exceptionInfo, minidumpType);
|
return Minidump::Create(filename, exceptionInfo, minidumpType);
|
||||||
@ -217,28 +215,28 @@ namespace Components
|
|||||||
#ifndef DISABLE_BITMESSAGE
|
#ifndef DISABLE_BITMESSAGE
|
||||||
// Preload public key for our target that will receive minidumps
|
// Preload public key for our target that will receive minidumps
|
||||||
Logger::Print("About to send request for public key for minidump upload address.\n");
|
Logger::Print("About to send request for public key for minidump upload address.\n");
|
||||||
if (!BitMessage::Singleton->RequestPublicKey(MinidumpUpload::targetAddress))
|
if (!BitMessage::RequestPublicKey(MinidumpUpload::targetAddress))
|
||||||
{
|
{
|
||||||
Logger::Error("Failed to request public key for minidump collection address.\n");
|
Logger::Error("Failed to request public key for minidump collection address.\n");
|
||||||
}
|
}
|
||||||
Logger::Print("Waiting for public key for minidump upload address.\n");
|
Logger::Print("Waiting for public key for minidump upload address.\n");
|
||||||
if (!BitMessage::Singleton->WaitForPublicKey(MinidumpUpload::targetAddress))
|
if (!BitMessage::WaitForPublicKey(MinidumpUpload::targetAddress))
|
||||||
{
|
{
|
||||||
Logger::Error("Failed to fetch public key for minidump collection address.\n");
|
Logger::Error("Failed to fetch public key for minidump collection address.\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check if folder exists
|
// Check if folder exists
|
||||||
if (!PathIsDirectoryA(queuedMinidumpsFolder.c_str()))
|
if (!PathIsDirectoryA(MinidumpUpload::queuedMinidumpsFolder.data()))
|
||||||
{
|
{
|
||||||
// Nothing to upload
|
// Nothing to upload
|
||||||
Logger::Print("No minidumps to upload.\n");
|
Logger::Print("No minidumps to upload.\n");
|
||||||
return PathFileExistsA(queuedMinidumpsFolder.c_str()) == FALSE;
|
return PathFileExistsA(MinidumpUpload::queuedMinidumpsFolder.data()) == FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk through directory and search for valid minidumps
|
// Walk through directory and search for valid minidumps
|
||||||
WIN32_FIND_DATAA ffd;
|
WIN32_FIND_DATAA ffd;
|
||||||
HANDLE hFind = FindFirstFileA(Utils::String::VA("%s\\*.dmp", queuedMinidumpsFolder), &ffd);
|
HANDLE hFind = FindFirstFileA(Utils::String::VA("%s\\*.dmp", MinidumpUpload::queuedMinidumpsFolder), &ffd);
|
||||||
if (hFind != INVALID_HANDLE_VALUE)
|
if (hFind != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
@ -247,12 +245,12 @@ namespace Components
|
|||||||
continue; // ignore directory
|
continue; // ignore directory
|
||||||
|
|
||||||
char fullPath[MAX_PATH_SIZE];
|
char fullPath[MAX_PATH_SIZE];
|
||||||
PathCombineA(fullPath, queuedMinidumpsFolder.c_str(), ffd.cFileName);
|
PathCombineA(fullPath, MinidumpUpload::queuedMinidumpsFolder.data(), ffd.cFileName);
|
||||||
|
|
||||||
// Try to open this minidump
|
// Try to open this minidump
|
||||||
Logger::Print("Trying to upload %s...\n", fullPath);
|
Logger::Print("Trying to upload %s...\n", fullPath);
|
||||||
auto minidump = Minidump::Open(fullPath);
|
auto minidump = Minidump::Open(fullPath);
|
||||||
if (minidump == NULL)
|
if (!minidump)
|
||||||
{
|
{
|
||||||
Logger::Print("Couldn't open minidump.\n");
|
Logger::Print("Couldn't open minidump.\n");
|
||||||
continue; // file can't be opened
|
continue; // file can't be opened
|
||||||
@ -297,16 +295,16 @@ namespace Components
|
|||||||
|
|
||||||
std::string compressedMinidump = minidump->ToString();
|
std::string compressedMinidump = minidump->ToString();
|
||||||
|
|
||||||
Logger::Print("Compressing minidump %s (currently %d bytes)...\n", id.c_str(), compressedMinidump.size());
|
Logger::Print("Compressing minidump %s (currently %d bytes)...\n", id.data(), compressedMinidump.size());
|
||||||
compressedMinidump = Utils::Compression::ZLib::Compress(compressedMinidump);
|
compressedMinidump = Utils::Compression::ZLib::Compress(compressedMinidump);
|
||||||
|
|
||||||
#ifndef DISABLE_BASE128
|
#ifndef DISABLE_BASE128
|
||||||
Logger::Print("Encoding minidump %s (currently %d bytes)...\n", id.c_str(), compressedMinidump.size());
|
Logger::Print("Encoding minidump %s (currently %d bytes)...\n", id.data(), compressedMinidump.size());
|
||||||
extraHeaders["Encoding"] = "base128";
|
extraHeaders["Encoding"] = "base128";
|
||||||
compressedMinidump = Utils::String::EncodeBase128(compressedMinidump);
|
compressedMinidump = Utils::String::EncodeBase128(compressedMinidump);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Logger::Print("Minidump %s now prepared for uploading (currently %d bytes)...\n", id.c_str(), compressedMinidump.size());
|
Logger::Print("Minidump %s now prepared for uploading (currently %d bytes)...\n", id.data(), compressedMinidump.size());
|
||||||
|
|
||||||
#ifdef DISABLE_BITMESSAGE
|
#ifdef DISABLE_BITMESSAGE
|
||||||
for (auto& targetUrl : targetUrls)
|
for (auto& targetUrl : targetUrls)
|
||||||
@ -348,19 +346,19 @@ namespace Components
|
|||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
// BitMessage has a max msg size that is somewhere around 220 KB, split it up as necessary!
|
// BitMessage has a max msg size that is somewhere around 220 KB, split it up as necessary!
|
||||||
auto totalParts = compressedMinidump.size() / this->maxSegmentSize + 1;
|
auto totalParts = compressedMinidump.size() / MinidumpUpload::maxSegmentSize + 1;
|
||||||
extraHeaders.insert({ "Parts", Utils::String::VA("%d",totalParts) });
|
extraHeaders.insert({ "Parts", Utils::String::VA("%d",totalParts) });
|
||||||
|
|
||||||
for (size_t offset = 0; offset < compressedMinidump.size(); offset += this->maxSegmentSize)
|
for (size_t offset = 0; offset < compressedMinidump.size(); offset += MinidumpUpload::maxSegmentSize)
|
||||||
{
|
{
|
||||||
auto extraPartHeaders = extraHeaders;
|
auto extraPartHeaders = extraHeaders;
|
||||||
|
|
||||||
auto part = compressedMinidump.substr(offset, std::min(this->maxSegmentSize, compressedMinidump.size() - offset));
|
auto part = compressedMinidump.substr(offset, std::min(MinidumpUpload::maxSegmentSize, compressedMinidump.size() - offset));
|
||||||
auto partNum = offset / this->maxSegmentSize + 1;
|
auto partNum = offset / MinidumpUpload::maxSegmentSize + 1;
|
||||||
extraPartHeaders.insert({ "Part", Utils::String::VA("%d", partNum) });
|
extraPartHeaders.insert({ "Part", Utils::String::VA("%d", partNum) });
|
||||||
|
|
||||||
Logger::Print("Uploading minidump %s (part %d out of %d, %d bytes)...\n", id.c_str(), partNum, totalParts, part.size());
|
Logger::Print("Uploading minidump %s (part %d out of %d, %d bytes)...\n", id.data(), partNum, totalParts, part.size());
|
||||||
BitMessage::Singleton->SendMsg(MinidumpUpload::targetAddress, MinidumpUpload::Encode(part, extraPartHeaders));
|
BitMessage::SendMsg(MinidumpUpload::targetAddress, MinidumpUpload::Encode(part, extraPartHeaders));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -43,16 +43,14 @@ namespace Components
|
|||||||
~MinidumpUpload();
|
~MinidumpUpload();
|
||||||
|
|
||||||
// Uploads the given minidump.
|
// Uploads the given minidump.
|
||||||
bool Upload(Minidump* minidump);
|
static bool Upload(Minidump* minidump);
|
||||||
|
|
||||||
// Generates a new minidump and saves it to the folder for queued minidumps.
|
// Generates a new minidump and saves it to the folder for queued minidumps.
|
||||||
Minidump* CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType = MiniDumpTiny);
|
static Minidump* CreateQueuedMinidump(LPEXCEPTION_POINTERS exceptionInfo, int minidumpType = MiniDumpTiny);
|
||||||
|
|
||||||
// Browses the folder for queued minidumps and uploads each queued minidump.
|
// Browses the folder for queued minidumps and uploads each queued minidump.
|
||||||
// On Release builds this will also delete every successfully uploaded minidump.
|
// On Release builds this will also delete every successfully uploaded minidump.
|
||||||
bool UploadQueuedMinidumps();
|
static bool UploadQueuedMinidumps();
|
||||||
|
|
||||||
static MinidumpUpload* Singleton;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::thread uploadThread;
|
std::thread uploadThread;
|
||||||
|
@ -120,46 +120,50 @@ namespace Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Encodes a given string in Base64
|
// Encodes a given string in Base64
|
||||||
std::string EncodeBase64(const char* input, const unsigned long inputSize) {
|
std::string EncodeBase64(const char* input, const unsigned long inputSize)
|
||||||
|
{
|
||||||
unsigned long outlen = long(inputSize + (inputSize / 3.0) + 16);
|
unsigned long outlen = long(inputSize + (inputSize / 3.0) + 16);
|
||||||
unsigned char* outbuf = new unsigned char[outlen]; //Reserve output memory
|
unsigned char* outbuf = new unsigned char[outlen]; //Reserve output memory
|
||||||
base64_encode((unsigned char*)input, inputSize, outbuf, &outlen);
|
base64_encode(reinterpret_cast<unsigned char*>(const_cast<char*>(input)), inputSize, outbuf, &outlen);
|
||||||
std::string ret((char*)outbuf, outlen);
|
std::string ret((char*)outbuf, outlen);
|
||||||
delete[] outbuf;
|
delete[] outbuf;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodes a given string in Base64
|
// Encodes a given string in Base64
|
||||||
std::string EncodeBase64(const std::string& input) {
|
std::string EncodeBase64(const std::string& input)
|
||||||
return EncodeBase64(input.c_str(), input.size());
|
{
|
||||||
|
return EncodeBase64(input.data(), input.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISABLE_BASE128
|
#ifndef DISABLE_BASE128
|
||||||
// Encodes a given string in Base128
|
// Encodes a given string in Base128
|
||||||
std::string EncodeBase128(const std::string& input) {
|
std::string EncodeBase128(const std::string& input)
|
||||||
auto encoder = new base128();
|
{
|
||||||
|
base128 encoder;
|
||||||
|
|
||||||
void* inbuffer = const_cast<char*>(input.data());
|
void* inbuffer = const_cast<char*>(input.data());
|
||||||
char* buffer = encoder->encode(inbuffer, input.size());
|
char* buffer = encoder.encode(inbuffer, input.size());
|
||||||
/*
|
/*
|
||||||
Interesting to see that the buffer returned by the encoder is not a standalone string copy
|
Interesting to see that the buffer returned by the encoder is not a standalone string copy
|
||||||
but instead is a pointer to the internal "encoded" field of the encoder. So if you deinitialize
|
but instead is a pointer to the internal "encoded" field of the encoder. So if you deinitialize
|
||||||
the encoder that string will probably become garbage.
|
the encoder that string will probably become garbage.
|
||||||
*/
|
*/
|
||||||
std::string retval(buffer);
|
std::string retval(buffer);
|
||||||
delete encoder;
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Generates a UUID and returns the string representation of it
|
// Generates a UUID and returns the string representation of it
|
||||||
std::string GenerateUUIDString() {
|
std::string GenerateUUIDString()
|
||||||
|
{
|
||||||
// Generate UUID data
|
// Generate UUID data
|
||||||
UUID uuid;
|
UUID uuid;
|
||||||
UuidCreate(&uuid);
|
UuidCreate(&uuid);
|
||||||
|
|
||||||
// Convert to string representation
|
// Convert to string representation
|
||||||
char* strdata = NULL;
|
char* strdata = nullptr;
|
||||||
UuidToStringA(&uuid, (RPC_CSTR*)&strdata);
|
UuidToStringA(&uuid, reinterpret_cast<RPC_CSTR*>(&strdata));
|
||||||
return std::string(strdata);
|
return std::string(strdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user