547 lines
18 KiB
C++
547 lines
18 KiB
C++
#include "StdAfx.h"
|
|
#include "DumpProcess.h"
|
|
|
|
|
|
|
|
//funtion정보를 알기위해서 사용됨
|
|
#include "ProcessManager.h"
|
|
|
|
bool CDumpProcess::LoadFile( const TCHAR* SymbolName )
|
|
{
|
|
//디코딩이 되지 않았다면 로드 되지 않음!
|
|
// if (!decodeDumpfile(SymbolName))
|
|
// {
|
|
// return false;
|
|
// }
|
|
|
|
if(!ReadDumpFile(SymbolName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if(pMapping_)
|
|
{
|
|
UnmapViewOfFile(pMapping_);
|
|
}
|
|
|
|
if(handleMap_)
|
|
{
|
|
CloseHandle(handleMap_);
|
|
}
|
|
|
|
if(handleFile_ != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(handleFile_);
|
|
}
|
|
|
|
|
|
//로드 했으니깐 인코딩!
|
|
// if (!decodeDumpfile(SymbolName))
|
|
// {
|
|
// return false;
|
|
// }
|
|
|
|
return true;
|
|
}
|
|
|
|
void CDumpProcess::Clean()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
bool CDumpProcess::ReadDumpFile( const TCHAR* FileName )
|
|
{
|
|
//파일 핸들 생성.
|
|
handleFile_ = CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
|
|
NULL,NULL);
|
|
if( handleFile_ == NULL || handleFile_ == INVALID_HANDLE_VALUE)
|
|
return false;
|
|
|
|
handleMap_ = CreateFileMapping(handleFile_,NULL,PAGE_READONLY,0,0,NULL);
|
|
if(handleMap_ == NULL)
|
|
return false;
|
|
|
|
pMapping_ = (byte*)MapViewOfFile(handleMap_,FILE_MAP_READ,0,0,0);
|
|
|
|
if (memcmp(pMapping_,"MDMP",4) != 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return OnReadDmpFile();
|
|
}
|
|
|
|
|
|
//사용하지 않는 메소드!!!!!!!!!!!!
|
|
bool CDumpProcess::OnSearch( DWORD ExceptionAddr , sExceptionInfomation& ExceptionInfo )
|
|
{
|
|
assert(0 && L"CDumpProcess::OnSearch Not Use CDumpProcess");
|
|
return false;
|
|
}
|
|
|
|
bool CDumpProcess::OnSearch( const char* ExceptionAddr,sExceptionInfomation& ExceptionInfo )
|
|
{
|
|
assert(0 && L"CDumpProcess::OnSearch Not Use CDumpProcess");
|
|
return false;
|
|
}
|
|
|
|
bool CDumpProcess::OnReadDmpFile()
|
|
{
|
|
if(!OnReadMiscInfo())
|
|
return false;
|
|
|
|
if(!OnReadMoudleInfo())
|
|
return false;
|
|
|
|
if(!OnReadSystemInfo())
|
|
return false;
|
|
|
|
if(!OnReadCrashInfo())
|
|
return false;
|
|
|
|
if(!OnReadMemoryInfo())
|
|
return false;
|
|
|
|
if(!OnReadThreadInfo())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CDumpProcess::OnReadMiscInfo()
|
|
{
|
|
MINIDUMP_MISC_INFO* pMiscInfo = (MINIDUMP_MISC_INFO*)GetDumpInfo(MiscInfoStream);
|
|
|
|
if(!pMiscInfo)
|
|
return false;
|
|
|
|
if (pMiscInfo->Flags1 & MINIDUMP_MISC1_PROCESS_TIMES)
|
|
{
|
|
ProcessTime_ = pMiscInfo->ProcessCreateTime;
|
|
UserTime_ = pMiscInfo->ProcessUserTime;
|
|
KerenlTime_ = pMiscInfo->ProcessKernelTime;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CDumpProcess::OnReadMoudleInfo()
|
|
{
|
|
MINIDUMP_MODULE_LIST* pModuleinfo = (MINIDUMP_MODULE_LIST*)GetDumpInfo(ModuleListStream);
|
|
MINIDUMP_MODULE* pModule = NULL;
|
|
MINIDUMP_STRING* pModuleString = NULL;
|
|
|
|
if(!pModuleinfo)
|
|
return false;
|
|
|
|
//모듈의 갯수는 0개보다 커야됨.
|
|
if(pModuleinfo->NumberOfModules > 0)
|
|
{
|
|
pModule = &pModuleinfo->Modules[0];
|
|
|
|
//이런경우가 있을지 모르겠지만... 모듈정보는 생성되었지만 모듈이 없을수 있나?
|
|
if(!pModule)
|
|
return false;
|
|
|
|
//처음 모듈 정보만!
|
|
pModuleString = (MINIDUMP_STRING*)((char*)pMapping_ + pModule->ModuleNameRva);
|
|
_tcsncpy(stringModuleName_,pModuleString->Buffer,sizeof(TCHAR)*256);
|
|
|
|
DumpModule_.reserve(pModuleinfo->NumberOfModules);
|
|
|
|
for (size_t index = 0 ; index < pModuleinfo->NumberOfModules ; ++index)
|
|
{
|
|
DumpModule_.push_back(pModuleinfo->Modules[index]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CDumpProcess::OnReadCrashInfo()
|
|
{
|
|
MINIDUMP_EXCEPTION_STREAM* pExceptionStream =
|
|
(MINIDUMP_EXCEPTION_STREAM*)GetDumpInfo(ExceptionStream);
|
|
|
|
if(!pExceptionStream)
|
|
return false;
|
|
|
|
ExcpetionStreamPointer_ = pExceptionStream;
|
|
|
|
ExceptionCode_ = pExceptionStream->ExceptionRecord.ExceptionCode;
|
|
ExceptionAddr_ = pExceptionStream->ExceptionRecord.ExceptionAddress;
|
|
|
|
ExceptionInfo_ = pExceptionStream->ExceptionRecord;
|
|
|
|
//예외가 난 쓰레드 정보를 받기위해서!
|
|
ThreadContext_ = pExceptionStream->ThreadContext;
|
|
ThreadId_ = pExceptionStream->ThreadId;
|
|
|
|
FIndExceptionCode(ExceptionCode_);
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CDumpProcess::OnReadSystemInfo()
|
|
{
|
|
MINIDUMP_SYSTEM_INFO* pSystemInfo = (MINIDUMP_SYSTEM_INFO*)GetDumpInfo(SystemInfoStream);
|
|
|
|
if(!pSystemInfo)
|
|
return false;
|
|
|
|
ProcessorArchitecture_ = pSystemInfo->ProcessorArchitecture;
|
|
ProcessorLevel_ = pSystemInfo->ProcessorLevel;
|
|
ProcessorRevision_ = pSystemInfo->ProcessorRevision;
|
|
|
|
MajorVersion_ = pSystemInfo->MajorVersion;
|
|
MinorVersion_ = pSystemInfo->MinorVersion;
|
|
BuildNumber_ = pSystemInfo->BuildNumber;
|
|
PlatformId_ = pSystemInfo->PlatformId;
|
|
|
|
return true;
|
|
}
|
|
|
|
//메모리 정렬에 사용
|
|
bool Compare(const MINIDUMP_MEMORY_DESCRIPTOR& a,const MINIDUMP_MEMORY_DESCRIPTOR& b )
|
|
{
|
|
return a.StartOfMemoryRange < b.StartOfMemoryRange;
|
|
}
|
|
|
|
bool CDumpProcess::OnReadMemoryInfo()
|
|
{
|
|
MINIDUMP_MEMORY_LIST* pMemList = (MINIDUMP_MEMORY_LIST*)GetDumpInfo(MemoryListStream);
|
|
|
|
if (!pMemList)
|
|
return false;
|
|
|
|
DumpMemory_.reserve(pMemList->NumberOfMemoryRanges);
|
|
|
|
for (size_t index = 0 ; index < pMemList->NumberOfMemoryRanges ; ++index)
|
|
{
|
|
const byte* ptrISRange = (byte*)pMapping_ + pMemList->MemoryRanges[index].Memory.Rva;
|
|
UINT sizeIsRange = pMemList->MemoryRanges[index].Memory.DataSize;
|
|
|
|
if(!IsBadReadPtr(ptrISRange,sizeIsRange) )
|
|
{
|
|
DumpMemory_.push_back(pMemList->MemoryRanges[index]);
|
|
}
|
|
}
|
|
|
|
MINIDUMP_MEMORY64_LIST* pMemList64 = (MINIDUMP_MEMORY64_LIST*)GetDumpInfo(Memory64ListStream);
|
|
|
|
if (pMemList64)
|
|
{
|
|
DumpMemory_.reserve(pMemList64->NumberOfMemoryRanges);
|
|
|
|
UINT rav = pMemList64->BaseRva;
|
|
for (size_t index = 0 ; index < pMemList64->NumberOfMemoryRanges ; ++index)
|
|
{
|
|
MINIDUMP_MEMORY_DESCRIPTOR memoryDescriptor;
|
|
|
|
memoryDescriptor.StartOfMemoryRange = pMemList64->MemoryRanges[index].StartOfMemoryRange;
|
|
memoryDescriptor.Memory.DataSize = pMemList64->MemoryRanges[index].DataSize;
|
|
memoryDescriptor.Memory.Rva = rav;
|
|
|
|
rav += memoryDescriptor.Memory.DataSize;
|
|
|
|
DumpMemory_.push_back(memoryDescriptor);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
std::sort(DumpMemory_.begin(),DumpMemory_.end(),Compare);
|
|
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CDumpProcess::OnReadThreadInfo()
|
|
{
|
|
MINIDUMP_THREAD_LIST* pThreadList = (MINIDUMP_THREAD_LIST*)GetDumpInfo(ThreadListStream);
|
|
MINIDUMP_THREAD* pThread = NULL;
|
|
|
|
if(!pThreadList)
|
|
return false;
|
|
|
|
if(pThreadList->NumberOfThreads > 0)
|
|
{
|
|
for (int threadID = 0 ; threadID < pThreadList->NumberOfThreads ; ++threadID )
|
|
{
|
|
pThread = &pThreadList->Threads[threadID];
|
|
|
|
//이 쓰레드가 예외가 난 스레드이다!
|
|
if(pThread->ThreadId == ThreadId_)
|
|
break;
|
|
}
|
|
|
|
|
|
//이런경우가 있을지 모르겠지만... 모듈정보는 생성되었지만 모듈이 없을수 있나?
|
|
if(!pThread)
|
|
return false;
|
|
|
|
//콜 스텍 메모리 재구성
|
|
//데이터를 읽을때는 4바이트로 정렬되도록 조정
|
|
UINT stackAddr = UINT(pThread->Stack.StartOfMemoryRange);
|
|
UINT stacksize = pThread->Stack.Memory.DataSize;
|
|
|
|
if ((stackAddr % 4) != 0)
|
|
{
|
|
int addr = 4 - (stackAddr % 4);
|
|
stackAddr += addr;
|
|
stacksize -= addr;
|
|
}
|
|
|
|
UINT LastFrameAddrSave = 0;
|
|
UINT LastFrameValueSave = 0;
|
|
bool LastFrameLinked = false;
|
|
|
|
//스텍을 읽으면서 확인 작업.
|
|
CONTEXT ThreadContext;
|
|
|
|
|
|
const CONTEXT* ctx = (const CONTEXT*)(pMapping_ + pThread->ThreadContext.Rva);
|
|
if(!IsBadReadPtr(ctx,sizeof(CONTEXT)))
|
|
{
|
|
ThreadContext = *ctx;
|
|
LastFrameValueSave = ThreadContext.Ebp;
|
|
}
|
|
|
|
UINT stackaddrEnd = stackAddr + stacksize;
|
|
for (UINT addr = stackAddr ; addr < stackaddrEnd ; addr += 4)
|
|
{
|
|
UINT value;
|
|
if (ReadMemoryValue(addr,&value) == false)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (value >= stackAddr && value < stackAddr)
|
|
{
|
|
LastFrameLinked = (LastFrameValueSave == addr);
|
|
LastFrameAddrSave = addr;
|
|
LastFrameValueSave = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
PVOID CDumpProcess::GetDumpInfo( ULONG Type )
|
|
{
|
|
if(!pMapping_)
|
|
return NULL;
|
|
|
|
ULONG Size = 0;
|
|
void* pStream = NULL;
|
|
MINIDUMP_DIRECTORY* pDir = NULL;
|
|
|
|
if (!MiniDumpReadDumpStream((PVOID)pMapping_,Type,&pDir,&pStream,&Size))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return pStream;
|
|
}
|
|
|
|
void CDumpProcess::OnExceptionCause( DWORD exceptioncuase,TCHAR* String,size_t Size )
|
|
{
|
|
struct ExceptionNames
|
|
{
|
|
DWORD ExceptionCode;
|
|
TCHAR ExceptionName[256];
|
|
};
|
|
}
|
|
|
|
//메모리 정렬에 사용
|
|
bool Compare2(const MINIDUMP_MEMORY_DESCRIPTOR& a,const MINIDUMP_MEMORY_DESCRIPTOR& b )
|
|
{
|
|
if(a.StartOfMemoryRange < b.StartOfMemoryRange)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
int CDumpProcess::ReadMemory( int addr, int size, byte* buffer )
|
|
{
|
|
UINT CurrentAddr = addr;
|
|
int LeftSize = size;
|
|
|
|
while (LeftSize > 0)
|
|
{
|
|
//메모리 중에서 현재 메모리를 가진 아이템을 찾는다.
|
|
MINIDUMP_MEMORY_DESCRIPTOR valueMemory;
|
|
valueMemory.StartOfMemoryRange = CurrentAddr;
|
|
|
|
std::vector<MINIDUMP_MEMORY_DESCRIPTOR>::iterator iterMem =
|
|
std::lower_bound(DumpMemory_.begin(),DumpMemory_.end(),valueMemory,Compare2);
|
|
|
|
|
|
if(iterMem == DumpMemory_.begin())
|
|
break;
|
|
|
|
iterMem--;
|
|
|
|
int posInRange = CurrentAddr - UINT(iterMem->StartOfMemoryRange);
|
|
int availableInRange = iterMem->Memory.DataSize - posInRange;
|
|
|
|
if (availableInRange <= 0)
|
|
break;
|
|
|
|
if (LeftSize <= availableInRange)
|
|
{
|
|
memcpy(buffer + (CurrentAddr - addr) ,
|
|
pMapping_ + (iterMem->Memory.Rva + posInRange),
|
|
LeftSize);
|
|
|
|
CurrentAddr += LeftSize;
|
|
LeftSize = 0;
|
|
}
|
|
else
|
|
{
|
|
memcpy(buffer + (CurrentAddr - addr) ,
|
|
pMapping_ + (iterMem->Memory.Rva + posInRange),
|
|
availableInRange);
|
|
|
|
CurrentAddr += availableInRange;
|
|
LeftSize -= availableInRange;
|
|
}
|
|
}
|
|
|
|
return size - LeftSize;
|
|
}
|
|
|
|
void CDumpProcess::OnInitation()
|
|
{
|
|
|
|
}
|
|
|
|
void CDumpProcess::FIndExceptionCode( DWORD ExceptionCode )
|
|
{
|
|
switch (ExceptionCode)
|
|
{
|
|
case STATUS_WAIT_0: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_WAIT_0")); break;
|
|
case STATUS_ABANDONED_WAIT_0: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ABANDONED_WAIT_0")); break;
|
|
case STATUS_USER_APC: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_USER_APC")); break;
|
|
case STATUS_TIMEOUT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_TIMEOUT")); break;
|
|
case STATUS_PENDING: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_PENDING")); break;
|
|
case DBG_EXCEPTION_HANDLED: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_EXCEPTION_HANDLED")); break;
|
|
case DBG_CONTINUE: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_CONTINUE")); break;
|
|
case STATUS_SEGMENT_NOTIFICATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SEGMENT_NOTIFICATION")); break;
|
|
case DBG_TERMINATE_THREAD: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_TERMINATE_THREAD")); break;
|
|
case DBG_TERMINATE_PROCESS: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_TERMINATE_PROCESS")); break;
|
|
case DBG_CONTROL_C: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_CONTROL_C")); break;
|
|
case DBG_CONTROL_BREAK: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_CONTROL_BREAK")); break;
|
|
case DBG_COMMAND_EXCEPTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_COMMAND_EXCEPTION")); break;
|
|
case STATUS_GUARD_PAGE_VIOLATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_GUARD_PAGE_VIOLATION")); break;
|
|
case STATUS_DATATYPE_MISALIGNMENT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_DATATYPE_MISALIGNMENT")); break;
|
|
case STATUS_BREAKPOINT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_BREAKPOINT")); break;
|
|
case STATUS_SINGLE_STEP: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SINGLE_STEP")); break;
|
|
case DBG_EXCEPTION_NOT_HANDLED: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("DBG_EXCEPTION_NOT_HANDLED")); break;
|
|
case STATUS_ACCESS_VIOLATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ACCESS_VIOLATION")); break;
|
|
case STATUS_IN_PAGE_ERROR: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_IN_PAGE_ERROR")); break;
|
|
case STATUS_INVALID_HANDLE: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INVALID_HANDLE")); break;
|
|
case STATUS_NO_MEMORY: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_NO_MEMORY")); break;
|
|
case STATUS_ILLEGAL_INSTRUCTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ILLEGAL_INSTRUCTION")); break;
|
|
case STATUS_NONCONTINUABLE_EXCEPTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_NONCONTINUABLE_EXCEPTION")); break;
|
|
case STATUS_INVALID_DISPOSITION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INVALID_DISPOSITION")); break;
|
|
case STATUS_ARRAY_BOUNDS_EXCEEDED: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_ARRAY_BOUNDS_EXCEEDED")); break;
|
|
case STATUS_FLOAT_DENORMAL_OPERAND: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_DENORMAL_OPERAND")); break;
|
|
case STATUS_FLOAT_DIVIDE_BY_ZERO: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_DIVIDE_BY_ZERO")); break;
|
|
case STATUS_FLOAT_INEXACT_RESULT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_INEXACT_RESULT")); break;
|
|
case STATUS_FLOAT_INVALID_OPERATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_INVALID_OPERATION")); break;
|
|
case STATUS_FLOAT_OVERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_OVERFLOW")); break;
|
|
case STATUS_FLOAT_STACK_CHECK: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_STACK_CHECK")); break;
|
|
case STATUS_FLOAT_UNDERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_UNDERFLOW")); break;
|
|
case STATUS_INTEGER_DIVIDE_BY_ZERO: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INTEGER_DIVIDE_BY_ZERO")); break;
|
|
case STATUS_INTEGER_OVERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_INTEGER_OVERFLOW")); break;
|
|
case STATUS_PRIVILEGED_INSTRUCTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_PRIVILEGED_INSTRUCTION")); break;
|
|
case STATUS_STACK_OVERFLOW: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_STACK_OVERFLOW")); break;
|
|
case STATUS_CONTROL_C_EXIT: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_CONTROL_C_EXIT")); break;
|
|
case STATUS_FLOAT_MULTIPLE_FAULTS: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_MULTIPLE_FAULTS")); break;
|
|
case STATUS_FLOAT_MULTIPLE_TRAPS: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_FLOAT_MULTIPLE_TRAPS")); break;
|
|
case STATUS_REG_NAT_CONSUMPTION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_REG_NAT_CONSUMPTION")); break;
|
|
case STATUS_SXS_EARLY_DEACTIVATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SXS_EARLY_DEACTIVATION")); break;
|
|
case STATUS_SXS_INVALID_DEACTIVATION: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("STATUS_SXS_INVALID_DEACTIVATION")); break;
|
|
|
|
case 0xE06D7363: _stprintf_s(stringExceptionCause_, 256, _T("%s"), _T("Microsoft C++ Exception")); break;
|
|
default: _stprintf_s(stringExceptionCause_, 256, _T("0x%08X"), ExceptionCode);
|
|
}
|
|
}
|
|
|
|
TCHAR* CDumpProcess::GetVersion(const _TCHAR* filename)
|
|
{
|
|
TCHAR* string_buffer;
|
|
const int kVersion_Depth = 15; //strlen("120104_0410.dmp")
|
|
|
|
string_buffer = _tcsstr(_tcslwr((_TCHAR*)filename), L"sungame_");
|
|
|
|
int string_length = 0;
|
|
if (string_buffer)
|
|
{
|
|
string_length = (int)_tcslen(string_buffer);
|
|
}
|
|
|
|
if (string_length - kVersion_Depth >= 0)
|
|
{
|
|
_TCHAR* string_pointer = string_buffer + (string_length - kVersion_Depth);
|
|
wsprintf(version_string, L"webzen@%d", _tstoi(string_pointer));
|
|
}
|
|
else
|
|
{
|
|
wsprintf(version_string, L"webzen@version");
|
|
}
|
|
|
|
return version_string;
|
|
}
|
|
|
|
bool CDumpProcess::decodeDumpfile( const TCHAR* DumpNmae )
|
|
{
|
|
AuMD5Encrypt Decoder;
|
|
|
|
std::fstream file;
|
|
|
|
file.open(DumpNmae, std::ios::in | std::ios::out | std::ios::binary);
|
|
if (!file)
|
|
{
|
|
MessageBox(NULL,L"파일을 열수 없습니다",L"오류",MB_OK);
|
|
return false;
|
|
}
|
|
|
|
file.seekg(0, std::ios::end);
|
|
size_t size = file.tellg();
|
|
char* buffer = new char[size];
|
|
|
|
file.seekg(0, std::ios::beg);
|
|
file.read(buffer, (unsigned int)size);
|
|
|
|
TCHAR* VersionString = GetVersion(DumpNmae);
|
|
char TempVersion[256];
|
|
|
|
WideCharToMultiByte ( CP_ACP, 0, VersionString, -1, TempVersion, 256, NULL, NULL );
|
|
|
|
if (!Decoder.DecryptString(TempVersion, buffer, (unsigned int)size))
|
|
{
|
|
TCHAR ErrorData[256];
|
|
wsprintf(ErrorData,L"DecryptString 에러(%s)",DumpNmae);
|
|
MessageBox(NULL,ErrorData,L"오류",MB_OK);
|
|
return false;
|
|
}
|
|
|
|
file.seekp(0, std::ios::beg);
|
|
file.write(buffer, (unsigned int)size);
|
|
|
|
file.close();
|
|
|
|
if (buffer)
|
|
{
|
|
delete[] buffer;
|
|
}
|
|
|
|
return true;
|
|
} |