| Index: sandbox/win/src/process_thread_interception.cc
|
| diff --git a/sandbox/win/src/process_thread_interception.cc b/sandbox/win/src/process_thread_interception.cc
|
| index e6c8c2e9180c91b96164791b67de1081998b2be4..37c5e1cdf3c299279d8322a5010208a638b0c4df 100644
|
| --- a/sandbox/win/src/process_thread_interception.cc
|
| +++ b/sandbox/win/src/process_thread_interception.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "sandbox/win/src/process_thread_interception.h"
|
|
|
| +#include "base/win/windows_version.h"
|
| #include "sandbox/win/src/crosscall_client.h"
|
| #include "sandbox/win/src/ipc_tags.h"
|
| #include "sandbox/win/src/policy_params.h"
|
| @@ -401,4 +402,87 @@ BOOL WINAPI TargetCreateProcessA(CreateProcessAFunction orig_CreateProcessA,
|
| return FALSE;
|
| }
|
|
|
| +// GetThreadId is not available on WINXP. So we'll
|
| +// load it on-the-fly.
|
| +const wchar_t kKernel32DllName[] = L"Kernel32.dll";
|
| +typedef DWORD(WINAPI* GetThreadIdFunc)(HANDLE Thread);
|
| +
|
| +HANDLE WINAPI TargetCreateThread(CreateThreadFunction orig_CreateThread,
|
| + LPSECURITY_ATTRIBUTES thread_attributes,
|
| + SIZE_T stack_size,
|
| + LPTHREAD_START_ROUTINE start_address,
|
| + PVOID parameter,
|
| + DWORD creation_flags,
|
| + LPDWORD thread_id) {
|
| + HANDLE hThread = NULL;
|
| +
|
| + TargetServices* target_services = SandboxFactory::GetTargetServices();
|
| + if (NULL == target_services ||
|
| + target_services->GetState()->IsCsrssConnected()) {
|
| + hThread = orig_CreateThread(thread_attributes, stack_size, start_address,
|
| + parameter, creation_flags, thread_id);
|
| + if (hThread) {
|
| + return hThread;
|
| + }
|
| + }
|
| + static GetThreadIdFunc GetThreadId_func = NULL;
|
| +
|
| + if (NULL == target_services)
|
| + return NULL;
|
| +
|
| + // We don't trust that the IPC can work this early.
|
| + if (!target_services->GetState()->InitCalled())
|
| + return NULL;
|
| +
|
| + DWORD original_error = ::GetLastError();
|
| +
|
| + do {
|
| + if (NULL != thread_id &&
|
| + !ValidParameter(thread_id, sizeof(*thread_id), WRITE))
|
| + break;
|
| +
|
| + void* memory = GetGlobalIPCMemory();
|
| + if (NULL == memory)
|
| + break;
|
| +
|
| + SharedMemIPCClient ipc(memory);
|
| + CrossCallReturn answer = {0};
|
| +
|
| + ResultCode code =
|
| + CrossCall(ipc, IPC_CREATETHREAD_TAG, (LPVOID)thread_attributes,
|
| + (LPVOID)stack_size, (LPVOID)start_address, (LPVOID)parameter,
|
| + (DWORD)creation_flags, &answer);
|
| +
|
| + if (SBOX_ALL_OK != code)
|
| + break;
|
| +
|
| + ::SetLastError(answer.win32_result);
|
| + if (ERROR_SUCCESS != answer.win32_result) {
|
| + return NULL;
|
| + }
|
| +
|
| + if (thread_id != NULL) {
|
| + // GetThreadId is not available on WINXP. Set thread_id to 0, as this is
|
| + // what is returned in the event of a failure.
|
| + *thread_id = 0;
|
| + if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
|
| + if (!GetThreadId_func) {
|
| + HMODULE kernel32_dll = ::GetModuleHandle(kKernel32DllName);
|
| + if (!kernel32_dll)
|
| + break;
|
| + GetThreadId_func = reinterpret_cast<GetThreadIdFunc>(
|
| + GetProcAddress(kernel32_dll, "GetThreadId"));
|
| + if (!GetThreadId_func)
|
| + break;
|
| + }
|
| + *thread_id = GetThreadId_func(answer.handle);
|
| + }
|
| + }
|
| + return answer.handle;
|
| + } while (false);
|
| +
|
| + ::SetLastError(original_error);
|
| + return NULL;
|
| +}
|
| +
|
| } // namespace sandbox
|
|
|