Index: third_party/mojo/src/mojo/edk/system/raw_channel_win.cc |
diff --git a/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc b/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc |
deleted file mode 100644 |
index b25453f7e7b2f670ad29419673e8c3ca18480651..0000000000000000000000000000000000000000 |
--- a/third_party/mojo/src/mojo/edk/system/raw_channel_win.cc |
+++ /dev/null |
@@ -1,636 +0,0 @@ |
-// Copyright 2013 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 "third_party/mojo/src/mojo/edk/system/raw_channel.h" |
- |
-#include <windows.h> |
- |
-#include "base/bind.h" |
-#include "base/lazy_instance.h" |
-#include "base/location.h" |
-#include "base/logging.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/message_loop/message_loop.h" |
-#include "base/process/process.h" |
-#include "base/synchronization/lock.h" |
-#include "base/win/windows_version.h" |
-#include "mojo/public/cpp/system/macros.h" |
-#include "third_party/mojo/src/mojo/edk/embedder/platform_handle.h" |
- |
-namespace mojo { |
-namespace system { |
- |
-namespace { |
- |
-struct MOJO_ALIGNAS(8) SerializedHandle { |
- DWORD handle_pid; |
- HANDLE handle; |
-}; |
- |
-class VistaOrHigherFunctions { |
- public: |
- VistaOrHigherFunctions(); |
- |
- bool is_vista_or_higher() const { return is_vista_or_higher_; } |
- |
- BOOL SetFileCompletionNotificationModes(HANDLE handle, UCHAR flags) { |
- return set_file_completion_notification_modes_(handle, flags); |
- } |
- |
- BOOL CancelIoEx(HANDLE handle, LPOVERLAPPED overlapped) { |
- return cancel_io_ex_(handle, overlapped); |
- } |
- |
- private: |
- using SetFileCompletionNotificationModesFunc = BOOL(WINAPI*)(HANDLE, UCHAR); |
- using CancelIoExFunc = BOOL(WINAPI*)(HANDLE, LPOVERLAPPED); |
- |
- bool is_vista_or_higher_; |
- SetFileCompletionNotificationModesFunc |
- set_file_completion_notification_modes_; |
- CancelIoExFunc cancel_io_ex_; |
-}; |
- |
-VistaOrHigherFunctions::VistaOrHigherFunctions() |
- : is_vista_or_higher_(base::win::GetVersion() >= base::win::VERSION_VISTA), |
- set_file_completion_notification_modes_(nullptr), |
- cancel_io_ex_(nullptr) { |
- if (!is_vista_or_higher_) |
- return; |
- |
- HMODULE module = GetModuleHandleW(L"kernel32.dll"); |
- set_file_completion_notification_modes_ = |
- reinterpret_cast<SetFileCompletionNotificationModesFunc>( |
- GetProcAddress(module, "SetFileCompletionNotificationModes")); |
- DCHECK(set_file_completion_notification_modes_); |
- |
- cancel_io_ex_ = |
- reinterpret_cast<CancelIoExFunc>(GetProcAddress(module, "CancelIoEx")); |
- DCHECK(cancel_io_ex_); |
-} |
- |
-base::LazyInstance<VistaOrHigherFunctions> g_vista_or_higher_functions = |
- LAZY_INSTANCE_INITIALIZER; |
- |
-class RawChannelWin final : public RawChannel { |
- public: |
- RawChannelWin(embedder::ScopedPlatformHandle handle); |
- ~RawChannelWin() override; |
- |
- // |RawChannel| public methods: |
- size_t GetSerializedPlatformHandleSize() const override; |
- |
- private: |
- // RawChannelIOHandler receives OS notifications for I/O completion. It must |
- // be created on the I/O thread. |
- // |
- // It manages its own destruction. Destruction happens on the I/O thread when |
- // all the following conditions are satisfied: |
- // - |DetachFromOwnerNoLock()| has been called; |
- // - there is no pending read; |
- // - there is no pending write. |
- class RawChannelIOHandler : public base::MessageLoopForIO::IOHandler { |
- public: |
- RawChannelIOHandler(RawChannelWin* owner, |
- embedder::ScopedPlatformHandle handle); |
- |
- HANDLE handle() const { return handle_.get().handle; } |
- |
- // The following methods are only called by the owner on the I/O thread. |
- bool pending_read() const; |
- base::MessageLoopForIO::IOContext* read_context(); |
- // Instructs the object to wait for an |OnIOCompleted()| notification. |
- void OnPendingReadStarted(); |
- |
- // The following methods are only called by the owner under |
- // |owner_->write_lock()|. |
- bool pending_write_no_lock() const; |
- base::MessageLoopForIO::IOContext* write_context_no_lock(); |
- // Instructs the object to wait for an |OnIOCompleted()| notification. |
- void OnPendingWriteStartedNoLock(size_t platform_handles_written); |
- |
- // |base::MessageLoopForIO::IOHandler| implementation: |
- // Must be called on the I/O thread. It could be called before or after |
- // detached from the owner. |
- void OnIOCompleted(base::MessageLoopForIO::IOContext* context, |
- DWORD bytes_transferred, |
- DWORD error) override; |
- |
- // Must be called on the I/O thread under |owner_->write_lock()|. |
- // After this call, the owner must not make any further calls on this |
- // object, and therefore the object is used on the I/O thread exclusively |
- // (if it stays alive). |
- void DetachFromOwnerNoLock(scoped_ptr<ReadBuffer> read_buffer, |
- scoped_ptr<WriteBuffer> write_buffer); |
- |
- private: |
- ~RawChannelIOHandler() override; |
- |
- // Returns true if |owner_| has been reset and there is not pending read or |
- // write. |
- // Must be called on the I/O thread. |
- bool ShouldSelfDestruct() const; |
- |
- // Must be called on the I/O thread. It may be called before or after |
- // detaching from the owner. |
- void OnReadCompleted(DWORD bytes_read, DWORD error); |
- // Must be called on the I/O thread. It may be called before or after |
- // detaching from the owner. |
- void OnWriteCompleted(DWORD bytes_written, DWORD error); |
- |
- embedder::ScopedPlatformHandle handle_; |
- |
- // |owner_| is reset on the I/O thread under |owner_->write_lock()|. |
- // Therefore, it may be used on any thread under lock; or on the I/O thread |
- // without locking. |
- RawChannelWin* owner_; |
- |
- // The following members must be used on the I/O thread. |
- scoped_ptr<ReadBuffer> preserved_read_buffer_after_detach_; |
- scoped_ptr<WriteBuffer> preserved_write_buffer_after_detach_; |
- bool suppress_self_destruct_; |
- |
- bool pending_read_; |
- base::MessageLoopForIO::IOContext read_context_; |
- |
- // The following members must be used under |owner_->write_lock()| while the |
- // object is still attached to the owner, and only on the I/O thread |
- // afterwards. |
- bool pending_write_; |
- size_t platform_handles_written_; |
- base::MessageLoopForIO::IOContext write_context_; |
- |
- MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelIOHandler); |
- }; |
- |
- // |RawChannel| private methods: |
- IOResult Read(size_t* bytes_read) override; |
- IOResult ScheduleRead() override; |
- embedder::ScopedPlatformHandleVectorPtr GetReadPlatformHandles( |
- size_t num_platform_handles, |
- const void* platform_handle_table) override; |
- IOResult WriteNoLock(size_t* platform_handles_written, |
- size_t* bytes_written) override; |
- IOResult ScheduleWriteNoLock() override; |
- void OnInit() override; |
- void OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, |
- scoped_ptr<WriteBuffer> write_buffer) override; |
- |
- // Passed to |io_handler_| during initialization. |
- embedder::ScopedPlatformHandle handle_; |
- |
- RawChannelIOHandler* io_handler_; |
- |
- const bool skip_completion_port_on_success_; |
- |
- MOJO_DISALLOW_COPY_AND_ASSIGN(RawChannelWin); |
-}; |
- |
-RawChannelWin::RawChannelIOHandler::RawChannelIOHandler( |
- RawChannelWin* owner, |
- embedder::ScopedPlatformHandle handle) |
- : handle_(handle.Pass()), |
- owner_(owner), |
- suppress_self_destruct_(false), |
- pending_read_(false), |
- pending_write_(false), |
- platform_handles_written_(0) { |
- memset(&read_context_.overlapped, 0, sizeof(read_context_.overlapped)); |
- read_context_.handler = this; |
- memset(&write_context_.overlapped, 0, sizeof(write_context_.overlapped)); |
- write_context_.handler = this; |
- |
- owner_->message_loop_for_io()->RegisterIOHandler(handle_.get().handle, this); |
-} |
- |
-RawChannelWin::RawChannelIOHandler::~RawChannelIOHandler() { |
- DCHECK(ShouldSelfDestruct()); |
-} |
- |
-bool RawChannelWin::RawChannelIOHandler::pending_read() const { |
- DCHECK(owner_); |
- DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
- return pending_read_; |
-} |
- |
-base::MessageLoopForIO::IOContext* |
-RawChannelWin::RawChannelIOHandler::read_context() { |
- DCHECK(owner_); |
- DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
- return &read_context_; |
-} |
- |
-void RawChannelWin::RawChannelIOHandler::OnPendingReadStarted() { |
- DCHECK(owner_); |
- DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
- DCHECK(!pending_read_); |
- pending_read_ = true; |
-} |
- |
-bool RawChannelWin::RawChannelIOHandler::pending_write_no_lock() const { |
- DCHECK(owner_); |
- owner_->write_lock().AssertAcquired(); |
- return pending_write_; |
-} |
- |
-base::MessageLoopForIO::IOContext* |
-RawChannelWin::RawChannelIOHandler::write_context_no_lock() { |
- DCHECK(owner_); |
- owner_->write_lock().AssertAcquired(); |
- return &write_context_; |
-} |
- |
-void RawChannelWin::RawChannelIOHandler::OnPendingWriteStartedNoLock( |
- size_t platform_handles_written) { |
- DCHECK(owner_); |
- owner_->write_lock().AssertAcquired(); |
- DCHECK(!pending_write_); |
- pending_write_ = true; |
- platform_handles_written_ = platform_handles_written; |
-} |
- |
-void RawChannelWin::RawChannelIOHandler::OnIOCompleted( |
- base::MessageLoopForIO::IOContext* context, |
- DWORD bytes_transferred, |
- DWORD error) { |
- DCHECK(!owner_ || |
- base::MessageLoop::current() == owner_->message_loop_for_io()); |
- |
- // Suppress self-destruction inside |OnReadCompleted()|, etc. (in case they |
- // result in a call to |Shutdown()|). |
- bool old_suppress_self_destruct = suppress_self_destruct_; |
- suppress_self_destruct_ = true; |
- |
- if (context == &read_context_) |
- OnReadCompleted(bytes_transferred, error); |
- else if (context == &write_context_) |
- OnWriteCompleted(bytes_transferred, error); |
- else |
- NOTREACHED(); |
- |
- // Maybe allow self-destruction again. |
- suppress_self_destruct_ = old_suppress_self_destruct; |
- |
- if (ShouldSelfDestruct()) |
- delete this; |
-} |
- |
-void RawChannelWin::RawChannelIOHandler::DetachFromOwnerNoLock( |
- scoped_ptr<ReadBuffer> read_buffer, |
- scoped_ptr<WriteBuffer> write_buffer) { |
- DCHECK(owner_); |
- DCHECK_EQ(base::MessageLoop::current(), owner_->message_loop_for_io()); |
- owner_->write_lock().AssertAcquired(); |
- |
- // If read/write is pending, we have to retain the corresponding buffer. |
- if (pending_read_) |
- preserved_read_buffer_after_detach_ = read_buffer.Pass(); |
- if (pending_write_) |
- preserved_write_buffer_after_detach_ = write_buffer.Pass(); |
- |
- owner_ = nullptr; |
- if (ShouldSelfDestruct()) |
- delete this; |
-} |
- |
-bool RawChannelWin::RawChannelIOHandler::ShouldSelfDestruct() const { |
- if (owner_ || suppress_self_destruct_) |
- return false; |
- |
- // Note: Detached, hence no lock needed for |pending_write_|. |
- return !pending_read_ && !pending_write_; |
-} |
- |
-void RawChannelWin::RawChannelIOHandler::OnReadCompleted(DWORD bytes_read, |
- DWORD error) { |
- DCHECK(!owner_ || |
- base::MessageLoop::current() == owner_->message_loop_for_io()); |
- DCHECK(suppress_self_destruct_); |
- |
- CHECK(pending_read_); |
- pending_read_ = false; |
- if (!owner_) |
- return; |
- |
- // Note: |OnReadCompleted()| may detach us from |owner_|. |
- if (error == ERROR_SUCCESS) { |
- DCHECK_GT(bytes_read, 0u); |
- owner_->OnReadCompleted(IO_SUCCEEDED, bytes_read); |
- } else if (error == ERROR_BROKEN_PIPE) { |
- DCHECK_EQ(bytes_read, 0u); |
- owner_->OnReadCompleted(IO_FAILED_SHUTDOWN, 0); |
- } else { |
- DCHECK_EQ(bytes_read, 0u); |
- LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error); |
- owner_->OnReadCompleted(IO_FAILED_UNKNOWN, 0); |
- } |
-} |
- |
-void RawChannelWin::RawChannelIOHandler::OnWriteCompleted(DWORD bytes_written, |
- DWORD error) { |
- DCHECK(!owner_ || |
- base::MessageLoop::current() == owner_->message_loop_for_io()); |
- DCHECK(suppress_self_destruct_); |
- |
- if (!owner_) { |
- // No lock needed. |
- CHECK(pending_write_); |
- pending_write_ = false; |
- return; |
- } |
- |
- { |
- base::AutoLock locker(owner_->write_lock()); |
- CHECK(pending_write_); |
- pending_write_ = false; |
- } |
- |
- // Note: |OnWriteCompleted()| may detach us from |owner_|. |
- if (error == ERROR_SUCCESS) { |
- // Reset |platform_handles_written_| before calling |OnWriteCompleted()| |
- // since that function may call back to this class and set it again. |
- size_t local_platform_handles_written_ = platform_handles_written_; |
- platform_handles_written_ = 0; |
- owner_->OnWriteCompleted(IO_SUCCEEDED, local_platform_handles_written_, |
- bytes_written); |
- } else if (error == ERROR_BROKEN_PIPE) { |
- owner_->OnWriteCompleted(IO_FAILED_SHUTDOWN, 0, 0); |
- } else { |
- LOG(WARNING) << "WriteFile: " << logging::SystemErrorCodeToString(error); |
- owner_->OnWriteCompleted(IO_FAILED_UNKNOWN, 0, 0); |
- } |
-} |
- |
-RawChannelWin::RawChannelWin(embedder::ScopedPlatformHandle handle) |
- : handle_(handle.Pass()), |
- io_handler_(nullptr), |
- skip_completion_port_on_success_( |
- g_vista_or_higher_functions.Get().is_vista_or_higher()) { |
- DCHECK(handle_.is_valid()); |
-} |
- |
-RawChannelWin::~RawChannelWin() { |
- DCHECK(!io_handler_); |
-} |
- |
-size_t RawChannelWin::GetSerializedPlatformHandleSize() const { |
- return sizeof(SerializedHandle); |
-} |
- |
-RawChannel::IOResult RawChannelWin::Read(size_t* bytes_read) { |
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
- DCHECK(io_handler_); |
- DCHECK(!io_handler_->pending_read()); |
- |
- char* buffer = nullptr; |
- size_t bytes_to_read = 0; |
- read_buffer()->GetBuffer(&buffer, &bytes_to_read); |
- |
- BOOL result = |
- ReadFile(io_handler_->handle(), buffer, static_cast<DWORD>(bytes_to_read), |
- nullptr, &io_handler_->read_context()->overlapped); |
- if (!result) { |
- DWORD error = GetLastError(); |
- if (error == ERROR_BROKEN_PIPE) |
- return IO_FAILED_SHUTDOWN; |
- if (error != ERROR_IO_PENDING) { |
- LOG(WARNING) << "ReadFile: " << logging::SystemErrorCodeToString(error); |
- return IO_FAILED_UNKNOWN; |
- } |
- } |
- |
- if (result && skip_completion_port_on_success_) { |
- DWORD bytes_read_dword = 0; |
- BOOL get_size_result = GetOverlappedResult( |
- io_handler_->handle(), &io_handler_->read_context()->overlapped, |
- &bytes_read_dword, FALSE); |
- DPCHECK(get_size_result); |
- *bytes_read = bytes_read_dword; |
- return IO_SUCCEEDED; |
- } |
- |
- // If the read is pending or the read has succeeded but we don't skip |
- // completion port on success, instruct |io_handler_| to wait for the |
- // completion packet. |
- // |
- // TODO(yzshen): It seems there isn't document saying that all error cases |
- // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion |
- // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| |
- // will crash so we will learn about it. |
- |
- io_handler_->OnPendingReadStarted(); |
- return IO_PENDING; |
-} |
- |
-RawChannel::IOResult RawChannelWin::ScheduleRead() { |
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
- DCHECK(io_handler_); |
- DCHECK(!io_handler_->pending_read()); |
- |
- size_t bytes_read = 0; |
- IOResult io_result = Read(&bytes_read); |
- if (io_result == IO_SUCCEEDED) { |
- DCHECK(skip_completion_port_on_success_); |
- |
- // We have finished reading successfully. Queue a notification manually. |
- io_handler_->OnPendingReadStarted(); |
- // |io_handler_| won't go away before the task is run, so it is safe to use |
- // |base::Unretained()|. |
- message_loop_for_io()->PostTask( |
- FROM_HERE, base::Bind(&RawChannelIOHandler::OnIOCompleted, |
- base::Unretained(io_handler_), |
- base::Unretained(io_handler_->read_context()), |
- static_cast<DWORD>(bytes_read), ERROR_SUCCESS)); |
- return IO_PENDING; |
- } |
- |
- return io_result; |
-} |
- |
-embedder::ScopedPlatformHandleVectorPtr RawChannelWin::GetReadPlatformHandles( |
- size_t num_platform_handles, |
- const void* platform_handle_table) { |
- // TODO(jam): this code will have to be updated once it's used in a sandbox |
- // and the receiving process doesn't have duplicate permission for the |
- // receiver. Once there's a broker and we have a connection to it (possibly |
- // through ConnectionManager), then we can make a sync IPC to it here to get a |
- // token for this handle, and it will duplicate the handle to is process. Then |
- // we pass the token to the receiver, which will then make a sync call to the |
- // broker to get a duplicated handle. This will also allow us to avoid leaks |
- // of the handle if the receiver dies, since the broker can notice that. |
- DCHECK_GT(num_platform_handles, 0u); |
- embedder::ScopedPlatformHandleVectorPtr rv( |
- new embedder::PlatformHandleVector()); |
- |
- const SerializedHandle* serialization_data = |
- static_cast<const SerializedHandle*>(platform_handle_table); |
- for (size_t i = 0; i < num_platform_handles; i++) { |
- DWORD pid = serialization_data->handle_pid; |
- HANDLE source_handle = serialization_data->handle; |
- serialization_data ++; |
- base::Process sender = |
- base::Process::OpenWithAccess(pid, PROCESS_DUP_HANDLE); |
- DCHECK(sender.IsValid()); |
- HANDLE target_handle = NULL; |
- BOOL dup_result = |
- DuplicateHandle(sender.Handle(), source_handle, |
- base::GetCurrentProcessHandle(), &target_handle, 0, |
- FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); |
- DCHECK(dup_result); |
- rv->push_back(embedder::PlatformHandle(target_handle)); |
- } |
- return rv.Pass(); |
-} |
- |
-RawChannel::IOResult RawChannelWin::WriteNoLock( |
- size_t* platform_handles_written, |
- size_t* bytes_written) { |
- write_lock().AssertAcquired(); |
- |
- DCHECK(io_handler_); |
- DCHECK(!io_handler_->pending_write_no_lock()); |
- |
- size_t num_platform_handles = 0; |
- if (write_buffer_no_lock()->HavePlatformHandlesToSend()) { |
- // Since we're not sure which process might ultimately deserialize this |
- // message, we can't duplicate the handle now. Instead, write the process ID |
- // and handle now and let the receiver duplicate it. |
- embedder::PlatformHandle* platform_handles; |
- void* serialization_data_temp; |
- write_buffer_no_lock()->GetPlatformHandlesToSend( |
- &num_platform_handles, &platform_handles, &serialization_data_temp); |
- SerializedHandle* serialization_data = |
- static_cast<SerializedHandle*>(serialization_data_temp); |
- DCHECK_GT(num_platform_handles, 0u); |
- DCHECK(platform_handles); |
- |
- DWORD current_process_id = base::GetCurrentProcId(); |
- for (size_t i = 0; i < num_platform_handles; i++) { |
- serialization_data->handle_pid = current_process_id; |
- serialization_data->handle = platform_handles[i].handle; |
- serialization_data++; |
- platform_handles[i] = embedder::PlatformHandle(); |
- } |
- } |
- |
- std::vector<WriteBuffer::Buffer> buffers; |
- write_buffer_no_lock()->GetBuffers(&buffers); |
- DCHECK(!buffers.empty()); |
- |
- // TODO(yzshen): Handle multi-segment writes more efficiently. |
- DWORD bytes_written_dword = 0; |
- BOOL result = |
- WriteFile(io_handler_->handle(), buffers[0].addr, |
- static_cast<DWORD>(buffers[0].size), &bytes_written_dword, |
- &io_handler_->write_context_no_lock()->overlapped); |
- if (!result) { |
- DWORD error = GetLastError(); |
- if (error == ERROR_BROKEN_PIPE) |
- return IO_FAILED_SHUTDOWN; |
- if (error != ERROR_IO_PENDING) { |
- LOG(WARNING) << "WriteFile: " << logging::SystemErrorCodeToString(error); |
- return IO_FAILED_UNKNOWN; |
- } |
- } |
- |
- if (result && skip_completion_port_on_success_) { |
- *platform_handles_written = num_platform_handles; |
- *bytes_written = bytes_written_dword; |
- return IO_SUCCEEDED; |
- } |
- |
- // If the write is pending or the write has succeeded but we don't skip |
- // completion port on success, instruct |io_handler_| to wait for the |
- // completion packet. |
- // |
- // TODO(yzshen): it seems there isn't document saying that all error cases |
- // (other than ERROR_IO_PENDING) are guaranteed to *not* queue a completion |
- // packet. If we do get one for errors, |RawChannelIOHandler::OnIOCompleted()| |
- // will crash so we will learn about it. |
- |
- io_handler_->OnPendingWriteStartedNoLock(num_platform_handles); |
- return IO_PENDING; |
-} |
- |
-RawChannel::IOResult RawChannelWin::ScheduleWriteNoLock() { |
- write_lock().AssertAcquired(); |
- |
- DCHECK(io_handler_); |
- DCHECK(!io_handler_->pending_write_no_lock()); |
- |
- size_t platform_handles_written = 0; |
- size_t bytes_written = 0; |
- IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written); |
- if (io_result == IO_SUCCEEDED) { |
- DCHECK(skip_completion_port_on_success_); |
- |
- // We have finished writing successfully. Queue a notification manually. |
- io_handler_->OnPendingWriteStartedNoLock(platform_handles_written); |
- // |io_handler_| won't go away before that task is run, so it is safe to use |
- // |base::Unretained()|. |
- message_loop_for_io()->PostTask( |
- FROM_HERE, |
- base::Bind(&RawChannelIOHandler::OnIOCompleted, |
- base::Unretained(io_handler_), |
- base::Unretained(io_handler_->write_context_no_lock()), |
- static_cast<DWORD>(bytes_written), ERROR_SUCCESS)); |
- return IO_PENDING; |
- } |
- |
- return io_result; |
-} |
- |
-void RawChannelWin::OnInit() { |
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
- |
- DCHECK(handle_.is_valid()); |
- if (skip_completion_port_on_success_) { |
- // I don't know how this can fail (unless |handle_| is bad, in which case |
- // it's a bug in our code). |
- CHECK(g_vista_or_higher_functions.Get().SetFileCompletionNotificationModes( |
- handle_.get().handle, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)); |
- } |
- |
- DCHECK(!io_handler_); |
- io_handler_ = new RawChannelIOHandler(this, handle_.Pass()); |
-} |
- |
-void RawChannelWin::OnShutdownNoLock(scoped_ptr<ReadBuffer> read_buffer, |
- scoped_ptr<WriteBuffer> write_buffer) { |
- DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io()); |
- DCHECK(io_handler_); |
- |
- write_lock().AssertAcquired(); |
- |
- if (io_handler_->pending_read() || io_handler_->pending_write_no_lock()) { |
- // |io_handler_| will be alive until pending read/write (if any) completes. |
- // Call |CancelIoEx()| or |CancelIo()| so that resources can be freed up as |
- // soon as possible. |
- // Note: |CancelIo()| only cancels read/write requests started from this |
- // thread. |
- if (g_vista_or_higher_functions.Get().is_vista_or_higher()) { |
- g_vista_or_higher_functions.Get().CancelIoEx(io_handler_->handle(), |
- nullptr); |
- } else { |
- CancelIo(io_handler_->handle()); |
- } |
- } |
- |
- io_handler_->DetachFromOwnerNoLock(read_buffer.Pass(), write_buffer.Pass()); |
- io_handler_ = nullptr; |
-} |
- |
-} // namespace |
- |
-// ----------------------------------------------------------------------------- |
- |
-// Static factory method declared in raw_channel.h. |
-// static |
-scoped_ptr<RawChannel> RawChannel::Create( |
- embedder::ScopedPlatformHandle handle) { |
- return make_scoped_ptr(new RawChannelWin(handle.Pass())); |
-} |
- |
-} // namespace system |
-} // namespace mojo |