michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "InjectCrashReporter.h" michael@0: #include "nsDirectoryServiceUtils.h" michael@0: #include "nsDirectoryServiceDefs.h" michael@0: #include "client/windows/crash_generation/crash_generation_client.h" michael@0: #include "nsExceptionHandler.h" michael@0: #include "LoadLibraryRemote.h" michael@0: #include "nsWindowsHelpers.h" michael@0: michael@0: using google_breakpad::CrashGenerationClient; michael@0: using CrashReporter::GetChildNotificationPipe; michael@0: michael@0: namespace mozilla { michael@0: michael@0: InjectCrashRunnable::InjectCrashRunnable(DWORD pid) michael@0: : mPID(pid) michael@0: { michael@0: nsCOMPtr dll; michael@0: nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(dll)); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: dll->Append(NS_LITERAL_STRING("breakpadinjector.dll")); michael@0: dll->GetPath(mInjectorPath); michael@0: } michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: InjectCrashRunnable::Run() michael@0: { michael@0: if (mInjectorPath.IsEmpty()) michael@0: return NS_OK; michael@0: michael@0: nsAutoHandle hProcess( michael@0: OpenProcess(PROCESS_CREATE_THREAD | michael@0: PROCESS_QUERY_INFORMATION | michael@0: PROCESS_DUP_HANDLE | michael@0: PROCESS_VM_OPERATION | michael@0: PROCESS_VM_WRITE | michael@0: PROCESS_VM_READ, FALSE, mPID)); michael@0: if (!hProcess) { michael@0: NS_WARNING("Unable to open remote process handle for crashreporter injection."); michael@0: return NS_OK; michael@0: } michael@0: michael@0: void* proc = LoadRemoteLibraryAndGetAddress(hProcess, mInjectorPath.get(), michael@0: "Start"); michael@0: if (!proc) { michael@0: NS_WARNING("Unable to inject crashreporter DLL."); michael@0: return NS_OK; michael@0: } michael@0: michael@0: HANDLE hRemotePipe = michael@0: CrashGenerationClient::DuplicatePipeToClientProcess( michael@0: NS_ConvertASCIItoUTF16(GetChildNotificationPipe()).get(), michael@0: hProcess); michael@0: if (INVALID_HANDLE_VALUE == hRemotePipe) { michael@0: NS_WARNING("Unable to duplicate crash reporter pipe to process."); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsAutoHandle hThread(CreateRemoteThread(hProcess, nullptr, 0, michael@0: (LPTHREAD_START_ROUTINE) proc, michael@0: (void*) hRemotePipe, 0, nullptr)); michael@0: if (!hThread) { michael@0: NS_WARNING("Unable to CreateRemoteThread"); michael@0: michael@0: // We have to close the remote pipe or else our crash generation client michael@0: // will be stuck unable to accept other remote requests. michael@0: HANDLE toClose = INVALID_HANDLE_VALUE; michael@0: if (DuplicateHandle(hProcess, hRemotePipe, ::GetCurrentProcess(), michael@0: &toClose, 0, FALSE, michael@0: DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { michael@0: CloseHandle(toClose); michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: } // namespace mozilla