| Index: tools/goopdump/process_commandline.cc
|
| diff --git a/tools/goopdump/process_commandline.cc b/tools/goopdump/process_commandline.cc
|
| deleted file mode 100644
|
| index 62976f6224b9b2e3265a58c28b3fb5f0d354e1ad..0000000000000000000000000000000000000000
|
| --- a/tools/goopdump/process_commandline.cc
|
| +++ /dev/null
|
| @@ -1,278 +0,0 @@
|
| -// Copyright 2008-2009 Google Inc.
|
| -//
|
| -// Licensed under the Apache License, Version 2.0 (the "License");
|
| -// you may not use this file except in compliance with the License.
|
| -// You may obtain a copy of the License at
|
| -//
|
| -// http://www.apache.org/licenses/LICENSE-2.0
|
| -//
|
| -// Unless required by applicable law or agreed to in writing, software
|
| -// distributed under the License is distributed on an "AS IS" BASIS,
|
| -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -// See the License for the specific language governing permissions and
|
| -// limitations under the License.
|
| -// ========================================================================
|
| -
|
| -#include "omaha/tools/goopdump/process_commandline.h"
|
| -
|
| -#include "omaha/common/debug.h"
|
| -#include "omaha/common/error.h"
|
| -#include "omaha/common/scoped_any.h"
|
| -#include "omaha/common/utils.h"
|
| -
|
| -namespace omaha {
|
| -
|
| -namespace {
|
| -
|
| -typedef const wchar_t* (__stdcall *GetCommandLineWFunc)();
|
| -
|
| -const DWORD kMaxInjectSize = 4096;
|
| -const DWORD kCmdLineBufferSize = 2000;
|
| -
|
| -struct SharedBlock {
|
| - DWORD last_error; // Last error from remote thread.
|
| - GetCommandLineWFunc get_commandline_w_ptr; // Address of GetCommandLineW().
|
| - wchar_t cmd_line_buffer[kCmdLineBufferSize]; // The command line buffer.
|
| -};
|
| -
|
| -// A number of assumptions are made:
|
| -// * The target process is a Win32 process.
|
| -// * Kernel32.dll is loaded at same address in each process (safe).
|
| -// * InjectFunction() is shorter than kMaxInjectSize
|
| -// * InjectFunction() does not rely on the C/C++ runtime.
|
| -// * Compiler option /GZ is not used. (If it is, the compiler generates calls to
|
| -// functions which are not injected into the target. The runtime_checks()
|
| -// pragma below removes this for debug builds which will have /GZ enabled by
|
| -// default.
|
| -
|
| -#pragma runtime_checks("", off)
|
| -
|
| -DWORD __stdcall InjectFunction(SharedBlock* shared_block) {
|
| - const wchar_t* source = shared_block->get_commandline_w_ptr();
|
| - wchar_t* target = &shared_block->cmd_line_buffer[0];
|
| - wchar_t* end = &shared_block->cmd_line_buffer[
|
| - arraysize(shared_block->cmd_line_buffer) - 1];
|
| - if (source == 0 || target == 0 || end == 0) {
|
| - shared_block->last_error = ERROR_INVALID_DATA;
|
| - return 0;
|
| - }
|
| -
|
| - // This is effectively a wcscpy but we can't use library functions since this
|
| - // code will be injected into the target process space and we can't make
|
| - // assumptions about what's linked into that process.
|
| - for (; *source != 0 && target < end; ++source, ++target) {
|
| - *target = *source;
|
| - }
|
| -
|
| - *target = 0;
|
| - shared_block->last_error = 0;
|
| -
|
| - return 0;
|
| -}
|
| -
|
| -#pragma runtime_checks("", restore)
|
| -
|
| -// Internal helper function to deal with the logic of injecting the
|
| -// function/data into the process without the memory alloc/free since we don't
|
| -// have smart pointers to handle VirtualAllocEx.
|
| -HRESULT GetCommandLineFromHandleWithMemory(HANDLE process_handle,
|
| - void* function_memory,
|
| - SharedBlock* shared_block,
|
| - CString* command_line) {
|
| - ASSERT1(process_handle);
|
| - ASSERT1(function_memory);
|
| - ASSERT1(shared_block);
|
| -
|
| - // Copy function into other process.
|
| - if (!::WriteProcessMemory(process_handle,
|
| - function_memory,
|
| - &InjectFunction,
|
| - kMaxInjectSize,
|
| - 0)) {
|
| - return HRESULTFromLastError();
|
| - }
|
| -
|
| - // Initialize data area for remote process.
|
| - scoped_library hmodule_kernel32(::LoadLibrary(L"kernel32.dll"));
|
| - if (!hmodule_kernel32) {
|
| - return HRESULTFromLastError();
|
| - }
|
| -
|
| - SharedBlock shared_block_local;
|
| - shared_block_local.last_error = 0;
|
| - if (!GPA(get(hmodule_kernel32),
|
| - "GetCommandLineW",
|
| - &shared_block_local.get_commandline_w_ptr)) {
|
| - return HRESULTFromLastError();
|
| - }
|
| -
|
| - shared_block_local.cmd_line_buffer[0] = L'\0';
|
| -
|
| - if (!::WriteProcessMemory(process_handle,
|
| - shared_block,
|
| - &shared_block_local,
|
| - sizeof(shared_block_local),
|
| - 0)) {
|
| - return HRESULTFromLastError();
|
| - }
|
| -
|
| - // Create the remote thread.
|
| - scoped_handle remote_thread;
|
| - reset(remote_thread, ::CreateRemoteThread(
|
| - process_handle,
|
| - 0,
|
| - 0,
|
| - reinterpret_cast<LPTHREAD_START_ROUTINE>(function_memory),
|
| - shared_block,
|
| - 0,
|
| - NULL));
|
| - if (!remote_thread) {
|
| - return HRESULTFromLastError();
|
| - }
|
| -
|
| - const DWORD kWaitTimeoutMs = 3000;
|
| - DWORD wait_result = ::WaitForSingleObject(get(remote_thread), kWaitTimeoutMs);
|
| - switch (wait_result) {
|
| - case WAIT_TIMEOUT:
|
| - return HRESULT_FROM_WIN32(ERROR_TIMEOUT);
|
| - case WAIT_FAILED:
|
| - return HRESULTFromLastError();
|
| - case WAIT_OBJECT_0:
|
| - // This might just have worked, pick up the result.
|
| - if (!::ReadProcessMemory(process_handle,
|
| - shared_block,
|
| - &shared_block_local,
|
| - sizeof(shared_block_local),
|
| - 0)) {
|
| - return HRESULTFromLastError();
|
| - }
|
| - if (shared_block_local.last_error == 0) {
|
| - *command_line = shared_block_local.cmd_line_buffer;
|
| - } else {
|
| - return HRESULT_FROM_WIN32(shared_block_local.last_error);
|
| - }
|
| - break;
|
| - default:
|
| - return HRESULTFromLastError();
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -// Allocates memory in a remote process given the process handle.
|
| -// Returns a block of memory for the function that will be injected and a block
|
| -// of memory to store results in that we copy back out.
|
| -HRESULT AllocateProcessMemory(HANDLE process_handle,
|
| - void** function_memory,
|
| - void** shared_block) {
|
| - ASSERT1(process_handle);
|
| - ASSERT1(function_memory);
|
| - ASSERT1(shared_block);
|
| -
|
| - *function_memory = ::VirtualAllocEx(process_handle,
|
| - 0,
|
| - kMaxInjectSize,
|
| - MEM_COMMIT,
|
| - PAGE_EXECUTE_READWRITE);
|
| - if (!(*function_memory)) {
|
| - return HRESULTFromLastError();
|
| - }
|
| -
|
| - *shared_block = ::VirtualAllocEx(process_handle,
|
| - 0,
|
| - sizeof(SharedBlock),
|
| - MEM_COMMIT,
|
| - PAGE_READWRITE);
|
| - if (!(*shared_block)) {
|
| - ::VirtualFreeEx(process_handle, *function_memory, 0, MEM_RELEASE);
|
| - *function_memory = NULL;
|
| - return HRESULTFromLastError();
|
| - }
|
| -
|
| - return S_OK;
|
| -}
|
| -
|
| -HRESULT GetCommandLineFromHandle(HANDLE process_handle, CString* command_line) {
|
| - ASSERT1(command_line);
|
| - ASSERT1(process_handle != NULL);
|
| -
|
| - void* function_memory = NULL;
|
| - void* shared_block = NULL;
|
| -
|
| - HRESULT hr = AllocateProcessMemory(process_handle,
|
| - &function_memory,
|
| - &shared_block);
|
| -
|
| - if (SUCCEEDED(hr) && function_memory && shared_block) {
|
| - hr = GetCommandLineFromHandleWithMemory(
|
| - process_handle,
|
| - function_memory,
|
| - reinterpret_cast<SharedBlock*>(shared_block),
|
| - command_line);
|
| - }
|
| -
|
| - if (function_memory) {
|
| - ::VirtualFreeEx(process_handle, function_memory, 0, MEM_RELEASE);
|
| - function_memory = NULL;
|
| - }
|
| -
|
| - if (shared_block) {
|
| - ::VirtualFreeEx(process_handle, shared_block, 0, MEM_RELEASE);
|
| - shared_block = NULL;
|
| - }
|
| -
|
| - return hr;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -HRESULT GetProcessCommandLine(DWORD process_id, CString* command_line) {
|
| - ASSERT1(command_line);
|
| -
|
| - EnableDebugPrivilege();
|
| - scoped_handle process_handle;
|
| - reset(process_handle, ::OpenProcess(PROCESS_CREATE_THREAD |
|
| - PROCESS_VM_OPERATION |
|
| - PROCESS_VM_WRITE |
|
| - PROCESS_VM_READ,
|
| - FALSE,
|
| - process_id));
|
| - if (!valid(process_handle)) {
|
| - return HRESULTFromLastError();
|
| - }
|
| - return GetCommandLineFromHandle(get(process_handle), command_line);
|
| -}
|
| -
|
| -bool EnableDebugPrivilege() {
|
| - scoped_handle token;
|
| -
|
| - if (!::OpenProcessToken(::GetCurrentProcess(),
|
| - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
| - address(token))) {
|
| - return false;
|
| - }
|
| -
|
| - LUID se_debug_name_value = {0};
|
| - if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &se_debug_name_value)) {
|
| - return false;
|
| - }
|
| -
|
| - TOKEN_PRIVILEGES token_privs = {0};
|
| - token_privs.PrivilegeCount = 1;
|
| - token_privs.Privileges[0].Luid = se_debug_name_value;
|
| - token_privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
| -
|
| - if (!::AdjustTokenPrivileges(get(token),
|
| - FALSE,
|
| - &token_privs,
|
| - sizeof(token_privs),
|
| - NULL,
|
| - NULL)) {
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -} // namespace omaha
|
| -
|
|
|