GString SP2::GGeneralEventHandler::ReplaceNextPattern(GString in_sSentence, GString in_ReplacingString, GString in_sPattern) const { UINT32 l_iCurrentPosition = 0; UINT32 l_iStartPosition = 0; bool l_bSuccess = false; for(UINT32 i=0; i<in_sSentence.size(); i++) { if(in_sSentence.at(i) == in_sPattern.at(l_iCurrentPosition)) { if(l_iCurrentPosition == 0) l_iStartPosition = i; l_iCurrentPosition++; if(l_iCurrentPosition == in_sPattern.size()) { l_bSuccess = true; break; } } else { if(l_iCurrentPosition > 0) { l_iCurrentPosition = 0; i = l_iStartPosition + 1; } } } if(l_bSuccess) { GString l_Results; l_Results += in_sSentence.substr(0,l_iStartPosition); l_Results += in_ReplacingString; l_Results += in_sSentence.substr(l_iStartPosition+in_sPattern.size(),in_sSentence.size()); return l_Results; } return L""; }
GCallStack::GCallStack(HANDLE hThread, CONTEXT& c) { if (!_bLockInit) // only init the single instance of the CRITICAL_SECTION 1 time for the many instances of GCallStack { InitializeCriticalSection(&_DbgHelpLock); _bLockInit = true; } DWORD imageType = IMAGE_FILE_MACHINE_I386; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId()); int frameNum = 0; // counts walked frames int MAX_STACK_FRAMES = 7777; // in C# the maximum stack frames imposed by the language is 1000. Arbitrary limit to guarantee no condition of infinate walking in corrupted memory. DWORD offsetFromLine; // tells us line number in the source file #if defined(_LINUX64) || defined(_WIN64) || defined(_IOS) unsigned __int64 offsetFromSymbol; // tells us how far from the symbol we were #else DWORD offsetFromSymbol; // tells us how far from the symbol we were #endif DWORD symOptions; // symbol handler settings IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN ); GString strStackName(MAXNAMELEN + 512); // undecorated method/function name + Source file and line number IMAGEHLP_MODULE Module; IMAGEHLP_LINE Line; STACKFRAME64 s; // in/out stackframe memset( &s, '\0', sizeof s ); // note: converted code from [std::string symSearchPath] to [GString symSearchPath] so it will compile with the _UNICODE build flag - 8/18/2014 GString symSearchPath; #ifdef _UNICODE wchar_t *tt = 0, *p; tt = new wchar_t[TTBUFLEN]; #else char *tt = 0, *p; tt = new char[TTBUFLEN]; #endif // build symbol search path from: symSearchPath = ""; // current directory if (GetCurrentDirectory(TTBUFLEN, tt)) symSearchPath << tt << "; "; // dir with executable if ( GetModuleFileName( 0, tt, TTBUFLEN ) ) { #ifdef _UNICODE for (p = tt + wcslen(tt) - 1; p >= tt; --p) #else for (p = tt + strlen(tt) - 1; p >= tt; --p) // VC6 does not have a _tcsclen() and we still support VC6 #endif { // locate the rightmost path separator if ( *p == '\\' || *p == '/' || *p == ':' ) break; } // if we found one, p is pointing at it; if not, tt only contains an exe name (no path), and p points before its first byte if ( p != tt ) // path sep found? { if ( *p == ':' ) // we leave colons in place ++ p; *p = '\0'; // eliminate the exe name and last path sep symSearchPath << tt << "; "; } } // environment variable _NT_SYMBOL_PATH GString g("_NT_SYMBOL_PATH"); if (GetEnvironmentVariable(g, tt, TTBUFLEN)) symSearchPath << tt << "; "; // environment variable _NT_ALTERNATE_SYMBOL_PATH g = "_NT_ALTERNATE_SYMBOL_PATH"; if (GetEnvironmentVariable(g, tt, TTBUFLEN)) symSearchPath << tt << "; "; // environment variable SYSTEMROOT g = "SYSTEMROOT"; if (GetEnvironmentVariable(g, tt, TTBUFLEN)) symSearchPath << tt << "; "; if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 ); // 8/20/2014 note: In older Windows API's SymInitialize()'s 2nd argument was not defined as "const char *", it was only "char *" // Although "const" was not defined, the API call is "const" in behavior. In newer versions of the Windows API this has been fixed. // In newer versions - SymInitialize's 2nd argument may resolve to either "const char *" OR "const wchar_t *", and in those builds the // GString has a default conversion to the correct string type, however in the older build configurations, GString does not (and should not) // know how to resolve to a "char *" by default, so in that case the preprocessor directive isolates the code needed to convert to "char *" #if defined(_MSC_VER) && _MSC_VER <= 1200 if (!SymInitialize(hProcess, symSearchPath.Buf(), false)) // symSearchPath == (char *) #else if (!SymInitialize(hProcess, symSearchPath, true)) // symSearchPath == (const char *) --OR-- (const wchar_t *) depending on the _UNICODE preprocessor definition #endif { goto tagCleanUp; } symOptions = SymGetOptions(); symOptions |= SYMOPT_LOAD_LINES; symOptions &= ~SYMOPT_UNDNAME; SymSetOptions( symOptions ); enumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() ); // init STACKFRAME for first call, definitions found in ImageHlp.h #ifdef _M_IX86 imageType = IMAGE_FILE_MACHINE_I386; s.AddrPC.Offset = c.Eip; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.Ebp; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Offset = c.Esp; s.AddrStack.Mode = AddrModeFlat; #elif _M_X64 imageType = IMAGE_FILE_MACHINE_AMD64; s.AddrPC.Offset = c.Rip; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.Rsp; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Offset = c.Rsp; s.AddrStack.Mode = AddrModeFlat; #elif _M_IA64 imageType = IMAGE_FILE_MACHINE_IA64; s.AddrPC.Offset = c.StIIP; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.IntSp; s.AddrFrame.Mode = AddrModeFlat; s.AddrBStore.Offset = c.RsBSP; s.AddrBStore.Mode = AddrModeFlat; s.AddrStack.Offset = c.IntSp; s.AddrStack.Mode = AddrModeFlat; #endif memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN ); pSym->SizeOfStruct = IMGSYMLEN; pSym->MaxNameLength = MAXNAMELEN; memset( &Line, '\0', sizeof Line ); Line.SizeOfStruct = sizeof Line; memset( &Module, '\0', sizeof Module ); Module.SizeOfStruct = sizeof Module; offsetFromSymbol = 0; // DbgHelp is single threaded, so acquire a lock. EnterCriticalSection(&_DbgHelpLock); while ( frameNum < MAX_STACK_FRAMES ) { // get next stack frame (StackWalk(), SymFunctionTableAccess(), SymGetModuleBase()) // if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can // assume that either you are done, or that the stack is so hosed that the next deeper frame could not be found. #ifdef _WIN64 if (!StackWalk64(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) #else if (!StackWalk(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL)) #endif break; // Maybe it failed, maybe we have finished walking the stack if ( s.AddrPC.Offset != 0 ) { // Most likely a valid stack rame // show procedure info if ( ! SymGetSymFromAddr64( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) ) { break; } else { // UnDecorateSymbolName() to get the Class::Method or function() name in tyhe callstack strStackName.Empty(); UnDecorateSymbolName(pSym->Name, strStackName._str, MAXNAMELEN, UNDNAME_COMPLETE); strStackName.SetLength(strlen(strStackName._str)); // SymGetLineFromAddr() to get the source.cpp and the line number IMAGEHLP_LINE64 Line; if (SymGetLineFromAddr64(hProcess, s.AddrPC.Offset, &offsetFromLine, &Line) != FALSE) { GString g(Line.FileName); // Line.FileName conains the "c:\Full\Path\TO\Source.cpp" // Builds string "Foo::Bar[Source.cpp]@777" strStackName << "[" << g.StartingAt(g.ReverseFind("\\") + 1) << "]@" << Line.LineNumber; } // add the GString to the GStringList, do not add frame 0 because it will always be GException::GSeception where we divided by 0 if (frameNum > 0) _stk += strStackName; } } else { // base reached SetLastError(0); break; } ++frameNum; } LeaveCriticalSection(&_DbgHelpLock); // de-init symbol handler etc. (SymCleanup()) SymCleanup( hProcess ); free( pSym ); tagCleanUp:; delete [] tt; CloseHandle(hProcess); }