From 5ea2ab75db847e7506f4e9e6f6b370f65cc1bb39 Mon Sep 17 00:00:00 2001 From: erikchen Date: Fri, 25 Sep 2015 15:34:31 -0700 Subject: [PATCH] Make SharedMemoryHandle a class on windows. This CL is intended to be a refactor and should not introduce any behavior changes. Previously, SharedMemoryhandle was typedefed to HANDLE. Making it a class allows us to add metainformation about the process in which the HANDLE is valid. This will be used in the future by Chrome's IPC system to automatically duplicate HANDLEs into their destination process. BUG=493414, 535028 Review URL: https://codereview.chromium.org/1320783002 Cr-Commit-Position: refs/heads/master@{#350932} --- base/base.gypi | 1 + base/memory/BUILD.gn | 1 + base/memory/shared_memory_handle.h | 47 ++++++++++++- base/memory/shared_memory_handle_win.cc | 68 +++++++++++++++++++ base/memory/shared_memory_unittest.cc | 22 ++---- base/memory/shared_memory_win.cc | 40 +++++------ components/mus/gles2/command_buffer_driver.cc | 4 +- components/nacl/loader/nacl_ipc_adapter.cc | 2 +- .../renderer/print_web_view_helper_pdf_win.cc | 2 +- .../compositor/software_output_device_win.cc | 2 +- .../renderer_host/render_process_host_impl.cc | 7 +- content/common/dwrite_font_platform_win.cc | 12 ++-- content/common/gpu/client/gpu_channel_host.cc | 6 -- content/common/sandbox_init_win.cc | 11 ++- content/common/sandbox_win.cc | 4 +- content/gpu/gpu_child_thread.cc | 12 ++-- content/plugin/webplugin_proxy.cc | 11 ++- content/ppapi_plugin/ppapi_thread.cc | 5 +- .../video_capture_message_filter_unittest.cc | 4 +- .../npapi/webplugin_delegate_proxy.cc | 8 +-- .../pepper/pepper_platform_audio_input.cc | 2 +- .../pepper/pepper_platform_audio_output.cc | 2 +- ipc/ipc_channel_posix.cc | 3 +- ipc/ipc_channel_posix_unittest.cc | 24 +++---- ipc/ipc_channel_win.cc | 3 +- ipc/ipc_message_utils.cc | 57 +++++++++++++++- ipc/ipc_message_utils.h | 8 +-- mojo/gles2/command_buffer_client_impl.cc | 2 +- ppapi/proxy/ppb_image_data_proxy.cc | 7 +- remoting/host/desktop_session_agent.cc | 2 +- remoting/host/desktop_session_proxy.cc | 9 ++- sandbox/win/src/handle_inheritance_test.cc | 6 +- sandbox/win/src/policy_target_test.cc | 4 +- sandbox/win/tests/common/controller.cc | 10 +-- ui/gfx/blit_unittest.cc | 6 +- ui/surface/transport_dib.h | 4 -- ui/surface/transport_dib_win.cc | 16 ++--- 37 files changed, 300 insertions(+), 134 deletions(-) create mode 100644 base/memory/shared_memory_handle_win.cc diff --git a/base/base.gypi b/base/base.gypi index 43d4a2c2bdc00a..10ee5e994fb0ac 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -361,6 +361,7 @@ 'memory/shared_memory_android.cc', 'memory/shared_memory_handle.h', 'memory/shared_memory_handle_mac.cc', + 'memory/shared_memory_handle_win.cc', 'memory/shared_memory_mac.cc', 'memory/shared_memory_nacl.cc', 'memory/shared_memory_posix.cc', diff --git a/base/memory/BUILD.gn b/base/memory/BUILD.gn index 9c5d0a052a8a2b..cf5b09733572f8 100644 --- a/base/memory/BUILD.gn +++ b/base/memory/BUILD.gn @@ -37,6 +37,7 @@ source_set("memory") { "shared_memory_android.cc", "shared_memory_handle.h", "shared_memory_handle_mac.cc", + "shared_memory_handle_win.cc", "shared_memory_mac.cc", "shared_memory_nacl.cc", "shared_memory_posix.cc", diff --git a/base/memory/shared_memory_handle.h b/base/memory/shared_memory_handle.h index 01a7f75273dd61..493694d2aa7b51 100644 --- a/base/memory/shared_memory_handle.h +++ b/base/memory/shared_memory_handle.h @@ -9,6 +9,7 @@ #if defined(OS_WIN) #include +#include "base/process/process_handle.h" #elif defined(OS_MACOSX) #include #include "base/base_export.h" @@ -25,10 +26,50 @@ class Pickle; // SharedMemoryHandle is a platform specific type which represents // the underlying OS handle to a shared memory segment. -#if defined(OS_WIN) -typedef HANDLE SharedMemoryHandle; -#elif defined(OS_POSIX) && !defined(OS_MACOSX) +#if defined(OS_POSIX) && !defined(OS_MACOSX) typedef FileDescriptor SharedMemoryHandle; +#elif defined(OS_WIN) +class BASE_EXPORT SharedMemoryHandle { + public: + // The default constructor returns an invalid SharedMemoryHandle. + SharedMemoryHandle(); + SharedMemoryHandle(HANDLE h, base::ProcessId pid); + + // Standard copy constructor. The new instance shares the underlying OS + // primitives. + SharedMemoryHandle(const SharedMemoryHandle& handle); + + // Standard assignment operator. The updated instance shares the underlying + // OS primitives. + SharedMemoryHandle& operator=(const SharedMemoryHandle& handle); + + // Comparison operators. + bool operator==(const SharedMemoryHandle& handle) const; + bool operator!=(const SharedMemoryHandle& handle) const; + + // Closes the underlying OS resources. + void Close() const; + + // Whether the underlying OS primitive is valid. + bool IsValid() const; + + // Whether |pid_| is the same as the current process's id. + bool BelongsToCurrentProcess() const; + + // Whether handle_ needs to be duplicated into the destination process when + // an instance of this class is passed over a Chrome IPC channel. + bool NeedsBrokering() const; + + HANDLE GetHandle() const; + base::ProcessId GetPID() const; + + private: + HANDLE handle_; + + // The process in which |handle_| is valid and can be used. If |handle_| is + // invalid, this will be kNullProcessId. + base::ProcessId pid_; +}; #else class BASE_EXPORT SharedMemoryHandle { public: diff --git a/base/memory/shared_memory_handle_win.cc b/base/memory/shared_memory_handle_win.cc new file mode 100644 index 00000000000000..571e4ef108569d --- /dev/null +++ b/base/memory/shared_memory_handle_win.cc @@ -0,0 +1,68 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/shared_memory_handle.h" + +#include "base/logging.h" + +namespace base { + +SharedMemoryHandle::SharedMemoryHandle() + : handle_(nullptr), pid_(kNullProcessId) {} + +SharedMemoryHandle::SharedMemoryHandle(HANDLE h, base::ProcessId pid) + : handle_(h), pid_(pid) {} + +SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) + : handle_(handle.handle_), pid_(handle.pid_) {} + +SharedMemoryHandle& SharedMemoryHandle::operator=( + const SharedMemoryHandle& handle) { + if (this == &handle) + return *this; + + handle_ = handle.handle_; + pid_ = handle.pid_; + return *this; +} + +bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const { + // Invalid handles are always equal. + if (!IsValid() && !handle.IsValid()) + return true; + + return handle_ == handle.handle_ && pid_ == handle.pid_; +} + +bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const { + return !(*this == handle); +} + +void SharedMemoryHandle::Close() const { + DCHECK(handle_ != nullptr); + DCHECK(BelongsToCurrentProcess()); + ::CloseHandle(handle_); +} + +bool SharedMemoryHandle::IsValid() const { + return handle_ != nullptr; +} + +bool SharedMemoryHandle::BelongsToCurrentProcess() const { + return pid_ == base::GetCurrentProcId(); +} + +bool SharedMemoryHandle::NeedsBrokering() const { + return false; +} + +HANDLE SharedMemoryHandle::GetHandle() const { + return handle_; +} + +base::ProcessId SharedMemoryHandle::GetPID() const { + return pid_; +} + +} // namespace base diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc index 0c09a5c44d5454..291a55e358eb50 100644 --- a/base/memory/shared_memory_unittest.cc +++ b/base/memory/shared_memory_unittest.cc @@ -369,28 +369,20 @@ TEST(SharedMemoryTest, ShareReadOnly) { EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size())); #elif defined(OS_WIN) - EXPECT_EQ(NULL, MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, 0)) + EXPECT_EQ(NULL, MapViewOfFile(handle.GetHandle(), FILE_MAP_WRITE, 0, 0, 0)) << "Shouldn't be able to map memory writable."; HANDLE temp_handle; - BOOL rv = ::DuplicateHandle(GetCurrentProcess(), - handle, - GetCurrentProcess(), - &temp_handle, - FILE_MAP_ALL_ACCESS, - false, - 0); + BOOL rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(), + GetCurrentProcess(), &temp_handle, + FILE_MAP_ALL_ACCESS, false, 0); EXPECT_EQ(FALSE, rv) << "Shouldn't be able to duplicate the handle into a writable one."; if (rv) win::ScopedHandle writable_handle(temp_handle); - rv = ::DuplicateHandle(GetCurrentProcess(), - handle, - GetCurrentProcess(), - &temp_handle, - FILE_MAP_READ, - false, - 0); + rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(), + GetCurrentProcess(), &temp_handle, FILE_MAP_READ, + false, 0); EXPECT_EQ(TRUE, rv) << "Should be able to duplicate the handle into a readable one."; if (rv) diff --git a/base/memory/shared_memory_win.cc b/base/memory/shared_memory_win.cc index 5f706fe6485986..3eef9a94d33dc5 100644 --- a/base/memory/shared_memory_win.cc +++ b/base/memory/shared_memory_win.cc @@ -45,11 +45,12 @@ SharedMemory::SharedMemory(const std::wstring& name) } SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) - : mapped_file_(handle), + : mapped_file_(handle.GetHandle()), mapped_size_(0), memory_(NULL), read_only_(read_only), requested_size_(0) { + DCHECK(!handle.IsValid() || handle.BelongsToCurrentProcess()); } SharedMemory::SharedMemory(const SharedMemoryHandle& handle, @@ -60,11 +61,9 @@ SharedMemory::SharedMemory(const SharedMemoryHandle& handle, memory_(NULL), read_only_(read_only), requested_size_(0) { - ::DuplicateHandle(process, handle, - GetCurrentProcess(), &mapped_file_, - read_only_ ? FILE_MAP_READ : FILE_MAP_READ | - FILE_MAP_WRITE, - FALSE, 0); + ::DuplicateHandle( + process, handle.GetHandle(), GetCurrentProcess(), &mapped_file_, + read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, FALSE, 0); } SharedMemory::~SharedMemory() { @@ -74,18 +73,17 @@ SharedMemory::~SharedMemory() { // static bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { - return handle != NULL; + return handle.IsValid(); } // static SharedMemoryHandle SharedMemory::NULLHandle() { - return NULL; + return SharedMemoryHandle(); } // static void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { - DCHECK(handle != NULL); - ::CloseHandle(handle); + handle.Close(); } // static @@ -98,13 +96,15 @@ size_t SharedMemory::GetHandleLimit() { // static SharedMemoryHandle SharedMemory::DuplicateHandle( const SharedMemoryHandle& handle) { + DCHECK(handle.BelongsToCurrentProcess()); + HANDLE duped_handle; ProcessHandle process = GetCurrentProcess(); - SharedMemoryHandle duped_handle; - BOOL success = ::DuplicateHandle(process, handle, process, &duped_handle, 0, - FALSE, DUPLICATE_SAME_ACCESS); + BOOL success = + ::DuplicateHandle(process, handle.GetHandle(), process, &duped_handle, 0, + FALSE, DUPLICATE_SAME_ACCESS); if (success) - return duped_handle; - return NULLHandle(); + return SharedMemoryHandle(duped_handle, GetCurrentProcId()); + return SharedMemoryHandle(); } bool SharedMemory::CreateAndMapAnonymous(size_t size) { @@ -230,7 +230,7 @@ bool SharedMemory::ShareToProcessCommon(ProcessHandle process, SharedMemoryHandle* new_handle, bool close_self, ShareMode share_mode) { - *new_handle = 0; + *new_handle = SharedMemoryHandle(); DWORD access = FILE_MAP_READ; DWORD options = 0; HANDLE mapped_file = mapped_file_; @@ -245,7 +245,7 @@ bool SharedMemory::ShareToProcessCommon(ProcessHandle process, } if (process == GetCurrentProcess() && close_self) { - *new_handle = mapped_file; + *new_handle = SharedMemoryHandle(mapped_file, base::GetCurrentProcId()); return true; } @@ -253,20 +253,20 @@ bool SharedMemory::ShareToProcessCommon(ProcessHandle process, access, FALSE, options)) { return false; } - *new_handle = result; + *new_handle = SharedMemoryHandle(result, base::GetProcId(process)); return true; } void SharedMemory::Close() { if (mapped_file_ != NULL) { - CloseHandle(mapped_file_); + ::CloseHandle(mapped_file_); mapped_file_ = NULL; } } SharedMemoryHandle SharedMemory::handle() const { - return mapped_file_; + return SharedMemoryHandle(mapped_file_, base::GetCurrentProcId()); } } // namespace base diff --git a/components/mus/gles2/command_buffer_driver.cc b/components/mus/gles2/command_buffer_driver.cc index d634fcb21b23ca..a03a357f1a24d0 100644 --- a/components/mus/gles2/command_buffer_driver.cc +++ b/components/mus/gles2/command_buffer_driver.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/macros.h" #include "base/memory/shared_memory.h" +#include "base/process/process_handle.h" #include "components/mus/gles2/command_buffer_type_conversions.h" #include "components/mus/gles2/gpu_memory_tracker.h" #include "components/mus/gles2/gpu_state.h" @@ -243,7 +244,8 @@ void CommandBufferDriver::CreateImage(int32_t id, } #if defined(OS_WIN) - gfx_handle.handle = platform_handle; + gfx_handle.handle = + base::SharedMemoryHandle(platform_handle, base::GetCurrentProcId()); #else gfx_handle.handle = base::FileDescriptor(platform_handle, false); #endif diff --git a/components/nacl/loader/nacl_ipc_adapter.cc b/components/nacl/loader/nacl_ipc_adapter.cc index f0b765874c9871..568d3a4e06fa98 100644 --- a/components/nacl/loader/nacl_ipc_adapter.cc +++ b/components/nacl/loader/nacl_ipc_adapter.cc @@ -545,7 +545,7 @@ bool NaClIPCAdapter::RewriteMessage(const IPC::Message& msg, uint32_t type) { uint32_t size = iter->size(); nacl_desc.reset(new NaClDescWrapper(NaClDescImcShmMake( #if defined(OS_WIN) - shm_handle, + shm_handle.GetHandle(), #else base::SharedMemory::GetFdFromSharedMemoryHandle(shm_handle), #endif diff --git a/components/printing/renderer/print_web_view_helper_pdf_win.cc b/components/printing/renderer/print_web_view_helper_pdf_win.cc index b82bf207e2c560..56acc7484d2e80 100644 --- a/components/printing/renderer/print_web_view_helper_pdf_win.cc +++ b/components/printing/renderer/print_web_view_helper_pdf_win.cc @@ -111,7 +111,7 @@ bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame* frame, printed_page_params.content_area = content_area_in_dpi[i]; Send(new PrintHostMsg_DidPrintPage(routing_id(), printed_page_params)); // Send the rest of the pages with an invalid metafile handle. - printed_page_params.metafile_data_handle = nullptr; + printed_page_params.metafile_data_handle = base::SharedMemoryHandle(); } return true; } diff --git a/content/browser/compositor/software_output_device_win.cc b/content/browser/compositor/software_output_device_win.cc index 098da8279c7f94..7f3df8799bf747 100644 --- a/content/browser/compositor/software_output_device_win.cc +++ b/content/browser/compositor/software_output_device_win.cc @@ -114,7 +114,7 @@ SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) { if (!contents_) { HANDLE shared_section = NULL; if (backing_) - shared_section = backing_->GetSharedMemory()->handle(); + shared_section = backing_->GetSharedMemory()->handle().GetHandle(); contents_ = skia::AdoptRef(skia::CreatePlatformCanvas( viewport_pixel_size_.width(), viewport_pixel_size_.height(), true, shared_section, skia::CRASH_ON_FAILURE)); diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 46e6ac99c8a1d0..1b79e3d7d6a311 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -744,13 +744,12 @@ scoped_ptr RenderProcessHostImpl::CreateChannelProxy( VLOG(1) << "Mojo Channel is enabled on host"; return IPC::ChannelProxy::Create( - IPC::ChannelMojo::CreateServerFactory( - mojo_task_runner, channel_id), + IPC::ChannelMojo::CreateServerFactory(mojo_task_runner, channel_id), this, runner.get()); } - return IPC::ChannelProxy::Create( - channel_id, IPC::Channel::MODE_SERVER, this, runner.get()); + return IPC::ChannelProxy::Create(channel_id, IPC::Channel::MODE_SERVER, this, + runner.get()); } void RenderProcessHostImpl::CreateMessageFilters() { diff --git a/content/common/dwrite_font_platform_win.cc b/content/common/dwrite_font_platform_win.cc index f2b4bd93b6043f..033a8e63f242fb 100644 --- a/content/common/dwrite_font_platform_win.cc +++ b/content/common/dwrite_font_platform_win.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -937,10 +938,13 @@ bool FontCollectionLoader::LoadCacheFile() { if (font_cache_handle_string.empty()) return false; - base::SharedMemoryHandle font_cache_handle = NULL; - base::StringToUint(font_cache_handle_string, - reinterpret_cast(&font_cache_handle)); - DCHECK(font_cache_handle); + unsigned int handle_uint; + base::StringToUint(font_cache_handle_string, &handle_uint); + DCHECK(handle_uint); + if (handle_uint > static_cast(std::numeric_limits::max())) + return false; + base::SharedMemoryHandle font_cache_handle(LongToHandle(handle_uint), + base::GetCurrentProcId()); base::SharedMemory* shared_mem = new base::SharedMemory( font_cache_handle, true); diff --git a/content/common/gpu/client/gpu_channel_host.cc b/content/common/gpu/client/gpu_channel_host.cc index 6b1706cdbb614f..a87051af7dff62 100644 --- a/content/common/gpu/client/gpu_channel_host.cc +++ b/content/common/gpu/client/gpu_channel_host.cc @@ -334,14 +334,8 @@ base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess( return base::SharedMemory::NULLHandle(); peer_pid = channel_->GetPeerPID(); } -#if defined(OS_WIN) - bool success = - BrokerDuplicateHandle(source_handle, peer_pid, &target_handle, - FILE_GENERIC_READ | FILE_GENERIC_WRITE, 0); -#elif defined(OS_MACOSX) bool success = BrokerDuplicateSharedMemoryHandle(source_handle, peer_pid, &target_handle); -#endif if (!success) return base::SharedMemory::NULLHandle(); diff --git a/content/common/sandbox_init_win.cc b/content/common/sandbox_init_win.cc index 3f80f33700973c..e1c07c940ab76a 100644 --- a/content/common/sandbox_init_win.cc +++ b/content/common/sandbox_init_win.cc @@ -46,8 +46,15 @@ bool BrokerDuplicateSharedMemoryHandle( const base::SharedMemoryHandle& source_handle, base::ProcessId target_process_id, base::SharedMemoryHandle* target_handle) { - return BrokerDuplicateHandle(source_handle, target_process_id, target_handle, - 0, DUPLICATE_SAME_ACCESS); + HANDLE duped_handle; + if (!BrokerDuplicateHandle(source_handle.GetHandle(), target_process_id, + &duped_handle, + FILE_GENERIC_READ | FILE_GENERIC_WRITE, 0)) { + return false; + } + + *target_handle = base::SharedMemoryHandle(duped_handle, target_process_id); + return true; } } // namespace content diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc index 4d6071a2e0096f..5860239b4cf0b5 100644 --- a/content/common/sandbox_win.cc +++ b/content/common/sandbox_win.cc @@ -733,8 +733,8 @@ base::Process StartSandboxedProcess( base::SharedMemory direct_write_font_cache_section; if (direct_write_font_cache_section.Open(name, true)) { - void* shared_handle = - policy->AddHandleToShare(direct_write_font_cache_section.handle()); + void* shared_handle = policy->AddHandleToShare( + direct_write_font_cache_section.handle().GetHandle()); cmd_line->AppendSwitchASCII(switches::kFontCacheSharedHandle, base::UintToString(reinterpret_cast(shared_handle))); } diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc index c6c1e3137bd79e..e40928cd82a696 100644 --- a/content/gpu/gpu_child_thread.cc +++ b/content/gpu/gpu_child_thread.cc @@ -257,12 +257,12 @@ void GpuChildThread::OnInitialize() { // Defer creation of the render thread. This is to prevent it from handling // IPC messages before the sandbox has been enabled and all other necessary // initialization has succeeded. - gpu_channel_manager_.reset(new GpuChannelManager( - channel(), watchdog_thread_.get(), - base::ThreadTaskRunnerHandle::Get().get(), - ChildProcess::current()->io_task_runner(), - ChildProcess::current()->GetShutDownEvent(), - sync_point_manager_, gpu_memory_buffer_factory_)); + gpu_channel_manager_.reset( + new GpuChannelManager(channel(), watchdog_thread_.get(), + base::ThreadTaskRunnerHandle::Get().get(), + ChildProcess::current()->io_task_runner(), + ChildProcess::current()->GetShutDownEvent(), + sync_point_manager_, gpu_memory_buffer_factory_)); #if defined(USE_OZONE) ui::OzonePlatform::GetInstance() diff --git a/content/plugin/webplugin_proxy.cc b/content/plugin/webplugin_proxy.cc index dbfb39e7de59e2..22e1890b031385 100644 --- a/content/plugin/webplugin_proxy.cc +++ b/content/plugin/webplugin_proxy.cc @@ -418,14 +418,11 @@ void WebPluginProxy::CreateCanvasFromHandle( const TransportDIB::Handle& dib_handle, const gfx::Rect& window_rect, skia::RefPtr* canvas) { - *canvas = skia::AdoptRef( - skia::CreatePlatformCanvas(window_rect.width(), - window_rect.height(), - true, - dib_handle, - skia::RETURN_NULL_ON_FAILURE)); + *canvas = skia::AdoptRef(skia::CreatePlatformCanvas( + window_rect.width(), window_rect.height(), true, dib_handle.GetHandle(), + skia::RETURN_NULL_ON_FAILURE)); // The canvas does not own the section so we need to close it now. - CloseHandle(dib_handle); + dib_handle.Close(); } void WebPluginProxy::SetWindowlessBuffers( diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc index 4d8938724ebd42..2200a758db94dd 100644 --- a/content/ppapi_plugin/ppapi_thread.cc +++ b/content/ppapi_plugin/ppapi_thread.cc @@ -208,7 +208,10 @@ base::SharedMemoryHandle PpapiThread::ShareSharedMemoryHandleWithRemote( #if defined(OS_WIN) if (peer_handle_.IsValid()) { DCHECK(is_broker_); - return IPC::GetFileHandleForProcess(handle, peer_handle_.Get(), false); + IPC::PlatformFileForTransit platform_file = IPC::GetFileHandleForProcess( + handle.GetHandle(), peer_handle_.Get(), false); + base::ProcessId pid = base::GetProcId(peer_handle_.Get()); + return base::SharedMemoryHandle(platform_file, pid); } #endif diff --git a/content/renderer/media/video_capture_message_filter_unittest.cc b/content/renderer/media/video_capture_message_filter_unittest.cc index 6c5dee7eba494b..b1193c1ebe1f10 100644 --- a/content/renderer/media/video_capture_message_filter_unittest.cc +++ b/content/renderer/media/video_capture_message_filter_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/memory/shared_memory.h" +#include "base/process/process_handle.h" #include "content/common/media/video_capture_messages.h" #include "content/renderer/media/video_capture_message_filter.h" #include "ipc/ipc_test_sink.h" @@ -96,7 +97,8 @@ TEST(VideoCaptureMessageFilterTest, Basic) { // VideoCaptureMsg_NewBuffer const base::SharedMemoryHandle handle = #if defined(OS_WIN) - reinterpret_cast(10); + base::SharedMemoryHandle(reinterpret_cast(10), + base::GetCurrentProcId()); #else base::SharedMemoryHandle(10, true); #endif diff --git a/content/renderer/npapi/webplugin_delegate_proxy.cc b/content/renderer/npapi/webplugin_delegate_proxy.cc index 22d2799625fc31..edd39bdad7c29c 100644 --- a/content/renderer/npapi/webplugin_delegate_proxy.cc +++ b/content/renderer/npapi/webplugin_delegate_proxy.cc @@ -501,10 +501,7 @@ static void CopySharedMemoryHandleForMessage( *handle_out = base::SharedMemory::DuplicateHandle(handle_in); #elif defined(OS_WIN) // On Windows we need to duplicate the handle for the plugin process. - *handle_out = NULL; - BrokerDuplicateHandle(handle_in, peer_pid, handle_out, - FILE_MAP_READ | FILE_MAP_WRITE, 0); - DCHECK(*handle_out != NULL); + BrokerDuplicateSharedMemoryHandle(handle_in, peer_pid, handle_out); #else #error Shared memory copy not implemented. #endif @@ -645,7 +642,8 @@ bool WebPluginDelegateProxy::CreateSharedBitmap( #else canvas->reset(skia::CreatePlatformCanvas( plugin_rect_.width(), plugin_rect_.height(), true, - (*memory)->shared_memory()->handle(), skia::RETURN_NULL_ON_FAILURE)); + (*memory)->shared_memory()->handle().GetHandle(), + skia::RETURN_NULL_ON_FAILURE)); #endif return !!canvas->get(); } diff --git a/content/renderer/pepper/pepper_platform_audio_input.cc b/content/renderer/pepper/pepper_platform_audio_input.cc index 390e9cd6039659..a6dc53a2bb853a 100644 --- a/content/renderer/pepper/pepper_platform_audio_input.cc +++ b/content/renderer/pepper/pepper_platform_audio_input.cc @@ -84,7 +84,7 @@ void PepperPlatformAudioInput::OnStreamCreated( int length, int total_segments) { #if defined(OS_WIN) - DCHECK(handle); + DCHECK(handle.IsValid()); DCHECK(socket_handle); #else DCHECK(base::SharedMemory::IsHandleValid(handle)); diff --git a/content/renderer/pepper/pepper_platform_audio_output.cc b/content/renderer/pepper/pepper_platform_audio_output.cc index f5ae3ba0d2b393..1edf45b35f12dd 100644 --- a/content/renderer/pepper/pepper_platform_audio_output.cc +++ b/content/renderer/pepper/pepper_platform_audio_output.cc @@ -83,7 +83,7 @@ void PepperPlatformAudioOutput::OnStreamCreated( base::SyncSocket::Handle socket_handle, int length) { #if defined(OS_WIN) - DCHECK(handle); + DCHECK(handle.IsValid()); DCHECK(socket_handle); #else DCHECK(base::SharedMemory::IsHandleValid(handle)); diff --git a/ipc/ipc_channel_posix.cc b/ipc/ipc_channel_posix.cc index ea41f10c85aba7..3f5771bc1b67e3 100644 --- a/ipc/ipc_channel_posix.cc +++ b/ipc/ipc_channel_posix.cc @@ -1020,8 +1020,7 @@ void ChannelPosix::ResetSafely(base::ScopedFD* fd) { scoped_ptr Channel::Create(const IPC::ChannelHandle& channel_handle, Mode mode, Listener* listener) { - return make_scoped_ptr( - new ChannelPosix(channel_handle, mode, listener)); + return make_scoped_ptr(new ChannelPosix(channel_handle, mode, listener)); } // static diff --git a/ipc/ipc_channel_posix_unittest.cc b/ipc/ipc_channel_posix_unittest.cc index 964d79e6dd1bc0..99bd68b5e3fc36 100644 --- a/ipc/ipc_channel_posix_unittest.cc +++ b/ipc/ipc_channel_posix_unittest.cc @@ -201,8 +201,8 @@ TEST_F(IPCChannelPosixTest, BasicListen) { IPC::ChannelHandle handle(kChannelName); SetUpSocket(&handle, IPC::Channel::MODE_NAMED_SERVER); unlink(handle.name.c_str()); - scoped_ptr channel(new IPC::ChannelPosix( - handle, IPC::Channel::MODE_NAMED_SERVER, NULL)); + scoped_ptr channel( + new IPC::ChannelPosix(handle, IPC::Channel::MODE_NAMED_SERVER, NULL)); ASSERT_TRUE(channel->Connect()); ASSERT_TRUE(channel->AcceptsConnections()); ASSERT_FALSE(channel->HasAcceptedConnection()); @@ -229,8 +229,8 @@ TEST_F(IPCChannelPosixTest, BasicConnected) { // Make sure that we can use the socket that is created for us by // a standard channel. - scoped_ptr channel2(new IPC::ChannelPosix( - socket_name, IPC::Channel::MODE_SERVER, NULL)); + scoped_ptr channel2( + new IPC::ChannelPosix(socket_name, IPC::Channel::MODE_SERVER, NULL)); ASSERT_TRUE(channel2->Connect()); ASSERT_FALSE(channel2->AcceptsConnections()); } @@ -362,8 +362,8 @@ TEST_F(IPCChannelPosixTest, MAYBE_ResetState) { TEST_F(IPCChannelPosixTest, BadChannelName) { // Test empty name IPC::ChannelHandle handle(""); - scoped_ptr channel(new IPC::ChannelPosix( - handle, IPC::Channel::MODE_NAMED_SERVER, NULL)); + scoped_ptr channel( + new IPC::ChannelPosix(handle, IPC::Channel::MODE_NAMED_SERVER, NULL)); ASSERT_FALSE(channel->Connect()); // Test name that is too long. @@ -376,8 +376,8 @@ TEST_F(IPCChannelPosixTest, BadChannelName) { "leading-edge_processes"; EXPECT_GE(strlen(kTooLongName), IPC::kMaxSocketNameLength); IPC::ChannelHandle handle2(kTooLongName); - scoped_ptr channel2(new IPC::ChannelPosix( - handle2, IPC::Channel::MODE_NAMED_SERVER, NULL)); + scoped_ptr channel2( + new IPC::ChannelPosix(handle2, IPC::Channel::MODE_NAMED_SERVER, NULL)); EXPECT_FALSE(channel2->Connect()); } @@ -428,8 +428,8 @@ TEST_F(IPCChannelPosixTest, DoubleServer) { IPCChannelPosixTestListener listener(false); IPCChannelPosixTestListener listener2(false); IPC::ChannelHandle chan_handle(GetConnectionSocketName()); - scoped_ptr channel(new IPC::ChannelPosix( - chan_handle, IPC::Channel::MODE_SERVER, &listener)); + scoped_ptr channel( + new IPC::ChannelPosix(chan_handle, IPC::Channel::MODE_SERVER, &listener)); scoped_ptr channel2(new IPC::ChannelPosix( chan_handle, IPC::Channel::MODE_SERVER, &listener2)); ASSERT_TRUE(channel->Connect()); @@ -440,8 +440,8 @@ TEST_F(IPCChannelPosixTest, BadMode) { // Test setting up two servers with a bad mode. IPCChannelPosixTestListener listener(false); IPC::ChannelHandle chan_handle(GetConnectionSocketName()); - scoped_ptr channel(new IPC::ChannelPosix( - chan_handle, IPC::Channel::MODE_NONE, &listener)); + scoped_ptr channel( + new IPC::ChannelPosix(chan_handle, IPC::Channel::MODE_NONE, &listener)); ASSERT_FALSE(channel->Connect()); } diff --git a/ipc/ipc_channel_win.cc b/ipc/ipc_channel_win.cc index 909fa8dfd77a36..e758d944d9ef77 100644 --- a/ipc/ipc_channel_win.cc +++ b/ipc/ipc_channel_win.cc @@ -571,8 +571,7 @@ void ChannelWin::OnIOCompleted( scoped_ptr Channel::Create(const IPC::ChannelHandle& channel_handle, Mode mode, Listener* listener) { - return scoped_ptr( - new ChannelWin(channel_handle, mode, listener)); + return scoped_ptr(new ChannelWin(channel_handle, mode, listener)); } // static diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc index 5e615c33f9b7ed..5c0c49344988b9 100644 --- a/ipc/ipc_message_utils.cc +++ b/ipc/ipc_message_utils.cc @@ -20,12 +20,13 @@ #include "ipc/ipc_platform_file_attachment_posix.h" #endif -#if defined(OS_MACOSX) && !defined(OS_IOS) +#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) #include "base/memory/shared_memory_handle.h" -#endif // defined(OS_MACOSX) && !defined(OS_IOS) +#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) #if defined(OS_WIN) #include +#include "ipc/handle_win.h" #endif namespace IPC { @@ -592,6 +593,58 @@ void ParamTraits::Log(const param_type& p, ParamTraits::Log(p.GetFileDescriptor(), l); } } +#elif defined(OS_WIN) +void ParamTraits::Write(Message* m, + const param_type& p) { + // Longs on windows are 32 bits. + uint32_t pid = p.GetPID(); + m->WriteUInt32(pid); + m->WriteBool(p.NeedsBrokering()); + + if (p.NeedsBrokering()) { + HandleWin handle_win(p.GetHandle(), HandleWin::DUPLICATE); + ParamTraits::Write(m, handle_win); + } else { + m->WriteInt(HandleToLong(p.GetHandle())); + } +} + +bool ParamTraits::Read(const Message* m, + base::PickleIterator* iter, + param_type* r) { + uint32_t pid_int; + if (!iter->ReadUInt32(&pid_int)) + return false; + base::ProcessId pid = pid_int; + + bool needs_brokering; + if (!iter->ReadBool(&needs_brokering)) + return false; + + if (needs_brokering) { + HandleWin handle_win; + if (!ParamTraits::Read(m, iter, &handle_win)) + return false; + *r = base::SharedMemoryHandle(handle_win.get_handle(), pid); + return true; + } + + int handle_int; + if (!iter->ReadInt(&handle_int)) + return false; + HANDLE handle = LongToHandle(handle_int); + *r = base::SharedMemoryHandle(handle, pid); + return true; +} + +void ParamTraits::Log(const param_type& p, + std::string* l) { + LogParam(p.GetPID(), l); + l->append(" "); + LogParam(p.GetHandle(), l); + l->append(" needs brokering: "); + LogParam(p.NeedsBrokering(), l); +} #endif // defined(OS_MACOSX) && !defined(OS_IOS) void ParamTraits::Write(Message* m, const param_type& p) { diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h index d0c1f721bcc39a..45f424d7633705 100644 --- a/ipc/ipc_message_utils.h +++ b/ipc/ipc_message_utils.h @@ -62,9 +62,9 @@ class TimeTicks; class TraceTicks; struct FileDescriptor; -#if defined(OS_MACOSX) && !defined(OS_IOS) +#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) class SharedMemoryHandle; -#endif // defined(OS_MACOSX) && !defined(OS_IOS) +#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) } namespace IPC { @@ -484,7 +484,7 @@ struct IPC_EXPORT ParamTraits { }; #endif // defined(OS_POSIX) -#if defined(OS_MACOSX) && !defined(OS_IOS) +#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) template <> struct IPC_EXPORT ParamTraits { typedef base::SharedMemoryHandle param_type; @@ -492,7 +492,7 @@ struct IPC_EXPORT ParamTraits { static bool Read(const Message* m, base::PickleIterator* iter, param_type* r); static void Log(const param_type& p, std::string* l); }; -#endif +#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) template <> struct IPC_EXPORT ParamTraits { diff --git a/mojo/gles2/command_buffer_client_impl.cc b/mojo/gles2/command_buffer_client_impl.cc index b34d438078400d..c4c228a310bba4 100644 --- a/mojo/gles2/command_buffer_client_impl.cc +++ b/mojo/gles2/command_buffer_client_impl.cc @@ -272,7 +272,7 @@ int32_t CommandBufferClientImpl::CreateImage(ClientBuffer buffer, base::SharedMemoryHandle dupd_handle = base::SharedMemory::DuplicateHandle(handle.handle); #if defined(OS_WIN) - HANDLE platform_handle = dupd_handle; + HANDLE platform_handle = dupd_handle.GetHandle(); #else int platform_handle = dupd_handle.fd; #endif diff --git a/ppapi/proxy/ppb_image_data_proxy.cc b/ppapi/proxy/ppb_image_data_proxy.cc index ed15bb6a1172af..5df31456df279f 100644 --- a/ppapi/proxy/ppb_image_data_proxy.cc +++ b/ppapi/proxy/ppb_image_data_proxy.cc @@ -375,7 +375,8 @@ PlatformImageData::PlatformImageData(const HostResource& resource, ImageHandle handle) : ImageData(resource, PPB_ImageData_Shared::PLATFORM, desc) { #if defined(OS_WIN) - transport_dib_.reset(TransportDIB::CreateWithHandle(handle)); + transport_dib_.reset(TransportDIB::CreateWithHandle( + base::SharedMemoryHandle(handle, base::GetCurrentProcId()))); #else transport_dib_.reset(TransportDIB::Map(handle)); #endif // defined(OS_WIN) @@ -627,7 +628,11 @@ void PPB_ImageData_Proxy::OnHostMsgCreatePlatform( desc, &image_handle, &byte_count); result->SetHostResource(instance, resource); if (resource) { +#if defined(OS_WIN) + *result_image_handle = image_handle.GetHandle(); +#else *result_image_handle = image_handle; +#endif } else { *result_image_handle = PlatformImageData::NullHandle(); } diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc index 9d7b2df25211b3..840d58831da186 100644 --- a/remoting/host/desktop_session_agent.cc +++ b/remoting/host/desktop_session_agent.cc @@ -88,7 +88,7 @@ class DesktopSessionAgent::SharedBuffer : public webrtc::SharedMemory { : SharedMemory(memory->memory(), size, #if defined(OS_WIN) - memory->handle(), + memory->handle().GetHandle(), #else base::SharedMemory::GetFdFromSharedMemoryHandle( memory->handle()), diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc index ba098f69e62243..27e8af6b5c5cd0 100644 --- a/remoting/host/desktop_session_proxy.cc +++ b/remoting/host/desktop_session_proxy.cc @@ -55,7 +55,7 @@ class DesktopSessionProxy::IpcSharedBufferCore if (!shared_memory_.Map(size)) { LOG(ERROR) << "Failed to map a shared buffer: id=" << id #if defined(OS_WIN) - << ", handle=" << handle + << ", handle=" << handle.GetHandle() #else << ", handle.fd=" << base::SharedMemory::GetFdFromSharedMemoryHandle(handle) @@ -69,7 +69,7 @@ class DesktopSessionProxy::IpcSharedBufferCore void* memory() { return shared_memory_.memory(); } webrtc::SharedMemory::Handle handle() { #if defined(OS_WIN) - return shared_memory_.handle(); + return shared_memory_.handle().GetHandle(); #else return base::SharedMemory::GetFdFromSharedMemoryHandle( shared_memory_.handle()); @@ -484,7 +484,12 @@ void DesktopSessionProxy::OnCreateSharedBuffer( uint32 size) { DCHECK(caller_task_runner_->BelongsToCurrentThread()); +#if defined(OS_WIN) + base::SharedMemoryHandle shm_handle = + base::SharedMemoryHandle(handle, base::GetCurrentProcId()); +#else base::SharedMemoryHandle shm_handle = base::SharedMemoryHandle(handle); +#endif scoped_refptr shared_buffer = new IpcSharedBufferCore(id, shm_handle, desktop_process_.Handle(), size); diff --git a/sandbox/win/src/handle_inheritance_test.cc b/sandbox/win/src/handle_inheritance_test.cc index 95a369a4dc171a..1a411b543b4138 100644 --- a/sandbox/win/src/handle_inheritance_test.cc +++ b/sandbox/win/src/handle_inheritance_test.cc @@ -56,7 +56,7 @@ SBOX_TESTS_COMMAND int HandleInheritanceTests_ValidInheritedHandle(int argc, wchar_t **argv) { if (argc != 1) return SBOX_TEST_FAILED_TO_RUN_TEST; - base::SharedMemoryHandle handle = nullptr; + HANDLE handle = nullptr; base::StringToUint(argv[0], reinterpret_cast(&handle)); // This handle we inherited must be both valid and closeable. @@ -79,8 +79,8 @@ TEST(HandleInheritanceTests, InheritByValue) { ASSERT_TRUE(test_shared_memory.Map(0)); TestRunner runner; - void *shared_handle = - runner.GetPolicy()->AddHandleToShare(test_shared_memory.handle()); + void* shared_handle = runner.GetPolicy()->AddHandleToShare( + test_shared_memory.handle().GetHandle()); std::string command_line = "HandleInheritanceTests_ValidInheritedHandle " + diff --git a/sandbox/win/src/policy_target_test.cc b/sandbox/win/src/policy_target_test.cc index 4395a4f0d22a68..bb1f0b2ba38fd2 100644 --- a/sandbox/win/src/policy_target_test.cc +++ b/sandbox/win/src/policy_target_test.cc @@ -376,8 +376,8 @@ TEST(PolicyTargetTest, ShareHandleTest) { GetModuleFileNameW(NULL, prog_name, MAX_PATH); TargetPolicy* policy = broker->CreatePolicy(); - void* shared_handle = policy->AddHandleToShare( - read_only_view.handle()); + void* shared_handle = + policy->AddHandleToShare(read_only_view.handle().GetHandle()); base::string16 arguments(L"\""); arguments += prog_name; diff --git a/sandbox/win/tests/common/controller.cc b/sandbox/win/tests/common/controller.cc index 4f90fb4f051798..8d3e29dd9600bf 100644 --- a/sandbox/win/tests/common/controller.cc +++ b/sandbox/win/tests/common/controller.cc @@ -8,6 +8,7 @@ #include "base/memory/shared_memory.h" #include "base/process/process.h" +#include "base/process/process_handle.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" #include "base/win/windows_version.h" @@ -304,11 +305,12 @@ int DispatchCall(int argc, wchar_t **argv) { // If the caller shared a shared memory handle with us attempt to open it // in read only mode and sleep infinitely if we succeed. if (0 == _wcsicmp(argv[3], L"shared_memory_handle")) { - base::SharedMemoryHandle shared_handle = NULL; - base::StringToUint( - argv[4], reinterpret_cast(&shared_handle)); - if (shared_handle == NULL) + HANDLE raw_handle = nullptr; + base::StringToUint(argv[4], reinterpret_cast(&raw_handle)); + if (raw_handle == nullptr) return SBOX_TEST_INVALID_PARAMETER; + base::SharedMemoryHandle shared_handle(raw_handle, + base::GetCurrentProcId()); base::SharedMemory read_only_view(shared_handle, true); if (!read_only_view.Map(0)) return SBOX_TEST_INVALID_PARAMETER; diff --git a/ui/gfx/blit_unittest.cc b/ui/gfx/blit_unittest.cc index 4dc814806b6677..4f154f965ea857 100644 --- a/ui/gfx/blit_unittest.cc +++ b/ui/gfx/blit_unittest.cc @@ -149,9 +149,9 @@ TEST(Blit, WithSharedMemory) { base::SharedMemory shared_mem; ASSERT_TRUE(shared_mem.CreateAnonymous(kCanvasWidth * kCanvasHeight)); base::SharedMemoryHandle section = shared_mem.handle(); - skia::RefPtr canvas = skia::AdoptRef( - skia::CreatePlatformCanvas(kCanvasWidth, kCanvasHeight, true, section, - skia::RETURN_NULL_ON_FAILURE)); + skia::RefPtr canvas = skia::AdoptRef(skia::CreatePlatformCanvas( + kCanvasWidth, kCanvasHeight, true, section.GetHandle(), + skia::RETURN_NULL_ON_FAILURE)); ASSERT_TRUE(canvas); shared_mem.Close(); diff --git a/ui/surface/transport_dib.h b/ui/surface/transport_dib.h index c2321448df3a99..a166238bc07883 100644 --- a/ui/surface/transport_dib.h +++ b/ui/surface/transport_dib.h @@ -26,11 +26,7 @@ class SURFACE_EXPORT TransportDIB { // A Handle is the type which can be sent over the wire so that the remote // side can map the transport DIB. -#if defined(OS_WIN) - typedef HANDLE Handle; -#else // OS_POSIX typedef base::SharedMemoryHandle Handle; -#endif // Returns a default, invalid handle, that is meant to indicate a missing // Transport DIB. diff --git a/ui/surface/transport_dib_win.cc b/ui/surface/transport_dib_win.cc index e8d36adbd5a545..af55af284349ca 100644 --- a/ui/surface/transport_dib_win.cc +++ b/ui/surface/transport_dib_win.cc @@ -20,10 +20,8 @@ TransportDIB::TransportDIB() TransportDIB::~TransportDIB() { } -TransportDIB::TransportDIB(HANDLE handle) - : shared_memory_(handle, false /* read write */), - size_(0) { -} +TransportDIB::TransportDIB(base::SharedMemoryHandle handle) + : shared_memory_(handle, false /* read write */), size_(0) {} // static TransportDIB* TransportDIB::Create(size_t size, uint32 sequence_num) { @@ -55,7 +53,7 @@ TransportDIB* TransportDIB::CreateWithHandle(Handle handle) { // static bool TransportDIB::is_valid_handle(Handle dib) { - return dib != NULL; + return dib.IsValid(); } skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) { @@ -66,9 +64,9 @@ skia::PlatformCanvas* TransportDIB::GetPlatformCanvas(int w, int h) { // We can't check the canvas size before mapping, but it's safe because // Windows will fail to map the section if the dimensions of the canvas // are too large. - skia::PlatformCanvas* canvas = - skia::CreatePlatformCanvas(w, h, true, shared_memory_.handle(), - skia::RETURN_NULL_ON_FAILURE); + skia::PlatformCanvas* canvas = skia::CreatePlatformCanvas( + w, h, true, shared_memory_.handle().GetHandle(), + skia::RETURN_NULL_ON_FAILURE); // Calculate the size for the memory region backing the canvas. if (canvas) @@ -85,7 +83,7 @@ bool TransportDIB::Map() { if (!shared_memory_.Map(0 /* map whole shared memory segment */)) { LOG(ERROR) << "Failed to map transport DIB" - << " handle:" << shared_memory_.handle() + << " handle:" << shared_memory_.handle().GetHandle() << " error:" << ::GetLastError(); return false; }