//-------------------------------------------------------------- /// Generates XML that describes the injected processes and which /// plugins were injected. /// \return string containing the XML //-------------------------------------------------------------- gtASCIIString ProcessTracker::GetProcessesXML() { std::unordered_map< DWORD, gtASCIIString > procXMLMap; this->UpdateListOfInjectedProcesses(); ProcessInfoList injectedProcesses = this->GetListOfInjectedProcesses(); WrapperMap wrappers = GetWrapperMap(); // the strPlatform is named this way to match options in the client. #ifdef X64 gtASCIIString strPlatform = "Win64"; #else gtASCIIString strPlatform = "Win32"; #endif #ifndef CODEXL_GRAPHICS if (injectedProcesses.empty() == true) { LogConsole(logERROR, "There are no processes running which have been injected with the GPU PerfStudio server plugin\n"); LogConsole(logERROR, "Please ensure that the server has the same bitness as the target application\n"); LogConsole(logERROR, "For example, use the 64-bit GPU PerfStudio server with a 64-bit application\n"); } #endif for (ProcessInfoList::iterator procIter = injectedProcesses.begin(); procIter != injectedProcesses.end(); ++procIter) { DWORD pid = procIter->th32ProcessID; // only add the process info if it wasn't already found. if (procXMLMap.find(pid) == procXMLMap.end()) { // insert new process and the process info gtASCIIString tmpString = XML("Name", XMLEscape(procIter->szExeFile).asCharArray()); tmpString += XML("PID", pid); tmpString += XML("Path", XMLEscape(procIter->szPath).asCharArray()); tmpString += XML("Platform", strPlatform.asCharArray()); procXMLMap[ pid ] = tmpString; // if this process is the one that was launched, then we know what the args and working directory were. // we could probably get the actual args and working dir from MicroDLL if it is a different app though, which // would be the case if this app uses a launcher app. if (m_injectedAppName.compare(procIter->szPath) == 0) { tmpString = XML("Args", XMLEscape(m_injectedAppArgs.c_str()).asCharArray()); tmpString += XML("WDir", XMLEscape(m_injectedAppDir.c_str()).asCharArray()); procXMLMap[ pid ] += tmpString.asCharArray(); } } // add an API node for each of the wrappers that are injected into the app for (WrapperMap::const_iterator wrapperIter = wrappers.begin(); wrapperIter != wrappers.end(); ++wrapperIter) { // List of plugin extensions to check for. On Windows, test for 32 and 64 bit plugins. // On linux, just check for the plugin corresponding to the server bitness static const char* pluginExtensions[] = { #ifdef WIN32 GDT_DEBUG_SUFFIX GDT_BUILD_SUFFIX "." DLL_EXTENSION, "-x64" GDT_DEBUG_SUFFIX GDT_BUILD_SUFFIX "." DLL_EXTENSION #else GDT_PROJECT_SUFFIX "." DLL_EXTENSION #endif }; int numPlugins = sizeof(pluginExtensions) / sizeof(pluginExtensions[0]); for (int loop = 0; loop < numPlugins; loop++) { // check to see if this wrapper is in the application gtASCIIString strPluginName = wrapperIter->second.strPluginName; if (SG_GET_BOOL(OptionDllReplacement) == false) { strPluginName += pluginExtensions[loop]; } if (IsLibraryLoadedInProcess(pid, strPluginName.asCharArray(), NULL)) { bool attached = false; if (g_activeWrappersMap.find(FormatText("%lu/%s", pid, wrapperIter->first.c_str()).asCharArray()) != g_activeWrappersMap.end()) { // the pid/plugin string was listed in the active wrappers map, so the plugin must be active. attached = true; } procXMLMap[pid] += XMLAttrib("API", FormatText("attached='%s'", attached ? "TRUE" : "FALSE").asCharArray(), wrapperIter->second.strPluginShortDesc.asCharArray()); } } } } // concatenate the process XML and additional info gtASCIIString xml; for (std::unordered_map< DWORD, gtASCIIString >::iterator iterP = procXMLMap.begin(); iterP != procXMLMap.end(); iterP++) { xml += XML("Process", (iterP->second).asCharArray()); } gtASCIIString out = XMLHeader(); out += XML("ProcessList", xml.asCharArray()); return out; }
//-------------------------------------------------------------------------- /// Allows the application to send a response for this command. /// If the server is streaming data, setting pData to NULL will closer the connection /// \param pData the data to respond with, /// \param uBytes if ContentType is JPEG, specifies the number of bytes in /// the image; ignored otherwise //-------------------------------------------------------------------------- void CommandResponse::Send(const char* pData, unsigned int uBytes) { // send the data back to all received requests for (std::list< CommunicationID >::const_iterator iRequestID = m_requestIDs.begin(); iRequestID != m_requestIDs.end(); ++iRequestID) { if (m_bStreamingEnabled == true) { //server wants to close the connection? if (pData == NULL) { SendResponse(*iRequestID, "", NULL, 0, m_bStreamingEnabled); m_bStreamingEnabled = false; continue; } } // string which is used to add tags around XML and HTML responses string strResponse; bool bResult = false; switch (m_eContentType) { case CONTENT_XML: { strResponse += XMLHeader().asCharArray(); strResponse += "<XML src='"; strResponse += GetURL(); strResponse += "'>"; strResponse += (char*) pData; strResponse += "</XML>"; bResult = SendResponse(*iRequestID, "text/xml", strResponse.c_str(), (unsigned int) strResponse.size(), m_bStreamingEnabled); m_eResponseState = SENT_RESPONSE; break; } case CONTENT_HTML: { strResponse += "<HTML>"; strResponse += (char*) pData; strResponse += "</HTML>"; bResult = SendResponse(*iRequestID, "text/html", strResponse.c_str(), (unsigned int) strResponse.size(), m_bStreamingEnabled); m_eResponseState = SENT_RESPONSE; break; } case CONTENT_TEXT: { bResult = SendResponse(*iRequestID, "text/plain", (char*) pData, (unsigned int) strlen((char*) pData), m_bStreamingEnabled); m_eResponseState = SENT_RESPONSE; break; } case CONTENT_PNG: { bResult = SendResponse(*iRequestID, "image/png", (char*) pData, uBytes, m_bStreamingEnabled); m_eResponseState = SENT_RESPONSE; break; } case CONTENT_JPG: { bResult = SendResponse(*iRequestID, "image/jpeg", (char*) pData, uBytes, m_bStreamingEnabled); m_eResponseState = SENT_RESPONSE; break; } case CONTENT_BMP: { bResult = SendResponse(*iRequestID, "image/bmp", (char*) pData, uBytes, m_bStreamingEnabled); m_eResponseState = SENT_RESPONSE; break; } case CONTENT_DDS: { bResult = SendResponse(*iRequestID, "application/dds", (char*) pData, uBytes, m_bStreamingEnabled); m_eResponseState = SENT_RESPONSE; break; } case CONTENT_PEF: { bResult = SendResponse(*iRequestID, "bytes/pef", (char*) pData, uBytes, m_bStreamingEnabled); m_eResponseState = SENT_RESPONSE; break; } case CONTENT_SCO: { bResult = SendResponse(*iRequestID, "bytes/sco", (char*) pData, uBytes, m_bStreamingEnabled); m_eResponseState = SENT_RESPONSE; break; } case CONTENT_REQUEST: default: { SendError("Attempted to send without setting ContentType"); m_eResponseState = SENT_RESPONSE; break; } } if (bResult == false) { m_bStreamingEnabled = false; m_eResponseState = ERROR_SENDING_RESPONSE; } } if (m_bStreamingEnabled == false) { // we sent a response and the request was not for streaming data, so unset the request m_requestIDs.clear(); } }