diff options
author | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-16 21:28:11 +0000 |
---|---|---|
committer | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-16 21:28:11 +0000 |
commit | 773632872a2738c85cb4e29fdd300de02316fe26 (patch) | |
tree | 596d5a382f08e1577a660f1c43eb590a9150b3b6 /base | |
parent | 3a49e50f07b102c5fa01da330ad8ce17fd3535c9 (diff) | |
download | chromium_src-773632872a2738c85cb4e29fdd300de02316fe26.zip chromium_src-773632872a2738c85cb4e29fdd300de02316fe26.tar.gz chromium_src-773632872a2738c85cb4e29fdd300de02316fe26.tar.bz2 |
[Chromoting] Launch the host process elevated via ShellExecuteEx().
The host process is launched in in two steps now. An instance of remote_service.exe is launched in a user session (CreateProcessAsUser) and then it launches the host requesting elevation (ShellExecuteEx). This is needed because Windows 8 refuses to inject Alt+Tab unless uiAccess='true' is specified in the manifest, which in its turn requires ShellExecuteEx() to be used.
Lifetime of launched processes is controlled by assigning them to a job object.
Message loop changes are required to be able to process job object notifications on the I/O message loop.
BUG=135217
Review URL: https://chromiumcodereview.appspot.com/10831271
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@151973 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/message_loop.cc | 4 | ||||
-rw-r--r-- | base/message_loop.h | 3 | ||||
-rw-r--r-- | base/message_pump_win.cc | 51 | ||||
-rw-r--r-- | base/message_pump_win.h | 19 |
4 files changed, 72 insertions, 5 deletions
diff --git a/base/message_loop.cc b/base/message_loop.cc index 7cadede..32994bf 100644 --- a/base/message_loop.cc +++ b/base/message_loop.cc @@ -751,6 +751,10 @@ void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) { pump_io()->RegisterIOHandler(file, handler); } +bool MessageLoopForIO::RegisterJobObject(HANDLE job, IOHandler* handler) { + return pump_io()->RegisterJobObject(job, handler); +} + bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) { return pump_io()->WaitForIOCompletion(timeout, filter); } diff --git a/base/message_loop.h b/base/message_loop.h index 2ff963f..b54ca85 100644 --- a/base/message_loop.h +++ b/base/message_loop.h @@ -631,7 +631,8 @@ class BASE_EXPORT MessageLoopForIO : public MessageLoop { #if defined(OS_WIN) // Please see MessagePumpWin for definitions of these methods. - void RegisterIOHandler(HANDLE file_handle, IOHandler* handler); + void RegisterIOHandler(HANDLE file, IOHandler* handler); + bool RegisterJobObject(HANDLE job, IOHandler* handler); bool WaitForIOCompletion(DWORD timeout, IOHandler* filter); protected: diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc index 2b2a10e..40118da 100644 --- a/base/message_pump_win.cc +++ b/base/message_pump_win.cc @@ -475,11 +475,26 @@ void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle, IOHandler* handler) { - ULONG_PTR key = reinterpret_cast<ULONG_PTR>(handler); + ULONG_PTR key = HandlerToKey(handler, true); HANDLE port = CreateIoCompletionPort(file_handle, port_, key, 1); DPCHECK(port); } +bool MessagePumpForIO::RegisterJobObject(HANDLE job_handle, + IOHandler* handler) { + // Job object notifications use the OVERLAPPED pointer to carry the message + // data. Mark the completion key correspondingly, so we will not try to + // convert OVERLAPPED* to IOContext*. + ULONG_PTR key = HandlerToKey(handler, false); + JOBOBJECT_ASSOCIATE_COMPLETION_PORT info; + info.CompletionKey = reinterpret_cast<void*>(key); + info.CompletionPort = port_; + return SetInformationJobObject(job_handle, + JobObjectAssociateCompletionPortInformation, + &info, + sizeof(info)) != FALSE; +} + //----------------------------------------------------------------------------- // MessagePumpForIO private: @@ -546,12 +561,16 @@ bool MessagePumpForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) { return true; } - if (item.context->handler) { + // If |item.has_valid_io_context| is false then |item.context| does not point + // to a context structure, and so should not be dereferenced, although it may + // still hold valid non-pointer data. + if (!item.has_valid_io_context || item.context->handler) { if (filter && item.handler != filter) { // Save this item for later completed_io_.push_back(item); } else { - DCHECK_EQ(item.context->handler, item.handler); + DCHECK(!item.has_valid_io_context || + (item.context->handler == item.handler)); WillProcessIOEvent(); item.handler->OnIOCompleted(item.context, item.bytes_transfered, item.error); @@ -577,7 +596,7 @@ bool MessagePumpForIO::GetIOItem(DWORD timeout, IOItem* item) { item->bytes_transfered = 0; } - item->handler = reinterpret_cast<IOHandler*>(key); + item->handler = KeyToHandler(key, &item->has_valid_io_context); item->context = reinterpret_cast<IOContext*>(overlapped); return true; } @@ -623,4 +642,28 @@ void MessagePumpForIO::DidProcessIOEvent() { FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent()); } +// static +ULONG_PTR MessagePumpForIO::HandlerToKey(IOHandler* handler, + bool has_valid_io_context) { + ULONG_PTR key = reinterpret_cast<ULONG_PTR>(handler); + + // |IOHandler| is at least pointer-size aligned, so the lowest two bits are + // always cleared. We use the lowest bit to distinguish completion keys with + // and without the associated |IOContext|. + DCHECK((key & 1) == 0); + + // Mark the completion key as context-less. + if (!has_valid_io_context) + key = key | 1; + return key; +} + +// static +MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( + ULONG_PTR key, + bool* has_valid_io_context) { + *has_valid_io_context = ((key & 1) == 0); + return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); +} + } // namespace base diff --git a/base/message_pump_win.h b/base/message_pump_win.h index e778e01..fd46198 100644 --- a/base/message_pump_win.h +++ b/base/message_pump_win.h @@ -296,6 +296,12 @@ class BASE_EXPORT MessagePumpForIO : public MessagePumpWin { // |handler| must be valid as long as there is pending IO for the given file. void RegisterIOHandler(HANDLE file_handle, IOHandler* handler); + // Register the handler to be used to process job events. The registration + // persists as long as the job object is live, so |handler| must be valid + // until the job object is destroyed. Returns true if the registration + // succeeded, and false otherwise. + bool RegisterJobObject(HANDLE job_handle, IOHandler* handler); + // Waits for the next IO completion that should be processed by |filter|, for // up to |timeout| milliseconds. Return true if any IO operation completed, // regardless of the involved handler, and false if the timeout expired. If @@ -316,6 +322,11 @@ class BASE_EXPORT MessagePumpForIO : public MessagePumpWin { IOContext* context; DWORD bytes_transfered; DWORD error; + + // In some cases |context| can be a non-pointer value casted to a pointer. + // |has_valid_io_context| is true if |context| is a valid IOContext + // pointer, and false otherwise. + bool has_valid_io_context; }; virtual void DoRunLoop(); @@ -326,6 +337,14 @@ class BASE_EXPORT MessagePumpForIO : public MessagePumpWin { void WillProcessIOEvent(); void DidProcessIOEvent(); + // Converts an IOHandler pointer to a completion port key. + // |has_valid_io_context| specifies whether completion packets posted to + // |handler| will have valid OVERLAPPED pointers. + static ULONG_PTR HandlerToKey(IOHandler* handler, bool has_valid_io_context); + + // Converts a completion port key to an IOHandler pointer. + static IOHandler* KeyToHandler(ULONG_PTR key, bool* has_valid_io_context); + // The completion port associated with this thread. win::ScopedHandle port_; // This list will be empty almost always. It stores IO completions that have |