void ProcessSolution(UI& ui, const doctor_dump::HaveSolutionResponse& solution) { m_log.Info(_T("Process solution...")); switch (solution.type) { case ns4__HaveSolutionResponse_SolutionType__Url: if (!solution.askConfirmation || ui.AskGetSolution(CSolutionDlg::Read)) { CAtlStringW url = solution.url.c_str(); url.Replace(L"{ClientID}", solution.clientID.c_str()); url.Replace(L"{ProblemID}", ToString(solution.problemID)); url.Replace(L"{DumpGroupID}", ToString(solution.dumpGroupID)); url.Replace(L"{DumpID}", ToString(solution.dumpID)); if (url.Find(L"http://") == 0 || url.Find(L"https://") == 0) ShellExecute(NULL, _T("open"), CW2CT(url), NULL, NULL, SW_SHOWNORMAL); } break; #ifdef REMOTE_CODE_DOWNLOAD_AND_EXECUTION case ns4__HaveSolutionResponse_SolutionType__Exe: if (!solution.askConfirmation || ui.AskGetSolution(CSolutionDlg::Install)) { CAtlFile hFile(CreateFile(m_patch, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)); if (hFile == INVALID_HANDLE_VALUE) throw runtime_error("failed to create solution.exe file"); if (FAILED(hFile.Write(&solution.exe[0], static_cast<DWORD>(solution.exe.size())))) throw runtime_error("failed to write solution.exe file"); hFile.Close(); STARTUPINFO si = {}; si.cb = sizeof(si); PROCESS_INFORMATION pi = {}; if (!CreateProcess(NULL, m_patch.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) throw runtime_error("failed to start solution.exe"); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } break; #endif default: throw runtime_error("Unknown SolutionType"); } }
boolean CNetRequestImpl::readHeaders(Hashtable<String,String>& oHeaders) { oHeaders.clear(); CAtlStringW strHeaders; DWORD dwLen = 0; DWORD nIndex = 0; if( !HttpQueryInfo( hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, null, &dwLen, &nIndex) ) { DWORD dwErr = ::GetLastError(); if ( dwErr != ERROR_INSUFFICIENT_BUFFER ) { pszErrFunction = L"HttpQueryInfo"; return false; } } if( !HttpQueryInfo( hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, strHeaders.GetBuffer(dwLen), &dwLen, &nIndex) ) { pszErrFunction = L"HttpQueryInfo"; return false; } strHeaders.ReleaseBuffer(); int nStart = 0; for(int nEnd = strHeaders.Find(L"\r\n", nStart); nEnd > 0; nStart = nEnd+2, nEnd = strHeaders.Find(L"\r\n", nStart) ) { CAtlStringW strHeader = strHeaders.Mid(nStart, nEnd-nStart); int nSep = strHeader.Find(':'); if (nSep < 0 ) continue; CAtlStringW strName = strHeader.Mid(0, nSep); strName.Trim(); strName.MakeLower(); CAtlStringW strValue = strHeader.Mid(nSep+1); strValue.Trim(); oHeaders.put(common::convertToStringA(strName.GetString()),common::convertToStringA(strValue.GetString())); } return true; }
bool Process(Params& params) { HANDLE hProcess = params.Process; DWORD dwProcessId = params.ProcessId; MINIDUMP_EXCEPTION_INFORMATION* pExceptInfo = ¶ms.ExceptInfo; bool wasAssert = !!params.WasAssert; m_dumpWriter.Init(m_config.DbgHelpPath); // we need to get CrashInfo before writing the dumps, since dumps writing will change WorkingSet m_crashInfo.reset(new CrashInfo(hProcess)); InitPathes(); UI ui(m_config); ui.ShowInitialProgressWindow(wasAssert); PrepareMiniDump(hProcess, dwProcessId, pExceptInfo); if (m_config.ServiceMode) { PrepareFullDump(hProcess, dwProcessId, pExceptInfo, true); TerminateProcess(hProcess, E_FAIL); // It is necessary for DUMPPARSER to terminate app, because it should process our dump, and it could not do it since it crashes. CloseHandle(hProcess); hProcess = NULL; } doctor_dump::Application app; app.applicationGUID = m_config.ApplicationGUID; app.v[0] = m_config.V[0]; app.v[1] = m_config.V[1]; app.v[2] = m_config.V[2]; app.v[3] = m_config.V[3]; app.hotfix = m_config.Hotfix; app.processName = m_config.ProcessName; m_log.Info(_T("App %d.%d.%d.%d %ls"), app.v[0], app.v[1], app.v[2], app.v[3], app.applicationGUID); doctor_dump::DumpAdditionalInfo addInfo; addInfo.crashDate = time(NULL); addInfo.PCID = GetUserPCID(); addInfo.submitterID = m_config.SubmitterID; addInfo.group = CA2W(params.Group); addInfo.description = m_config.CustomInfo; std::unique_ptr<doctor_dump::Response> response = m_dumpUploader.Hello(app, (LPCWSTR)m_config.AppName, (LPCWSTR)m_config.Company, addInfo); while (1) { switch (response->GetResponseType()) { case doctor_dump::Response::HaveSolutionResponseType: ProcessSolution(ui, static_cast<doctor_dump::HaveSolutionResponse&>(*response)); goto finish; case doctor_dump::Response::NeedMiniDumpResponseType: response = m_dumpUploader.UploadMiniDump(response->context, app, addInfo, (LPCWSTR)m_miniDumpZipFile); break; case doctor_dump::Response::NeedFullDumpResponseType: if (!ui.AskSendFullDump()) { response = m_dumpUploader.RejectedToSendAdditionalInfo(response->context, app, response->dumpID); break; } ui.ShowFullDumpUploadProgressWindow(); if (!m_config.ServiceMode) { auto& resp = static_cast<doctor_dump::NeedFullDumpResponse&>(*response); m_config.FullDumpType = m_config.FullDumpType & (~resp.restrictedDumpType); PrepareFullDump(hProcess, dwProcessId, pExceptInfo, resp.attachUserInfo); CloseHandle(hProcess); hProcess = NULL; } SetEvent(params.ReportReady); response = m_dumpUploader.UploadFullDump(response->context, app, response->dumpID, (LPCWSTR)m_fullDumpZipFile, &ui); break; case doctor_dump::Response::NeedMoreInfoResponseType: if (!ui.AskSendFullDump()) { response = m_dumpUploader.RejectedToSendAdditionalInfo(response->context, app, response->dumpID); break; } ui.ShowFullDumpUploadProgressWindow(); PrepareAdditionalInfo(static_cast<doctor_dump::NeedMoreInfoResponse&>(*response), hProcess, dwProcessId); response = m_dumpUploader.UploadAdditionalInfo(response->context, app, response->dumpID, (LPCWSTR)m_infoFile, &ui); break; case doctor_dump::Response::ErrorResponseType: throw runtime_error((const char*)CW2A(static_cast<doctor_dump::ErrorResponse&>(*response).error.c_str())); case doctor_dump::Response::StopResponseType: default: goto finish; } } finish: if (!m_config.ServiceMode && !response->urlToProblem.empty() && m_config.OpenProblemInBrowser) { CAtlStringW url = response->urlToProblem.c_str(); if (url.Find(L"http://") == 0 || url.Find(L"https://") == 0) ShellExecuteW(NULL, _T("open"), url, NULL, NULL, SW_SHOWNORMAL); } return true; }