summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authoralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-16 21:28:11 +0000
committeralexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-16 21:28:11 +0000
commit773632872a2738c85cb4e29fdd300de02316fe26 (patch)
tree596d5a382f08e1577a660f1c43eb590a9150b3b6 /base
parent3a49e50f07b102c5fa01da330ad8ce17fd3535c9 (diff)
downloadchromium_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.cc4
-rw-r--r--base/message_loop.h3
-rw-r--r--base/message_pump_win.cc51
-rw-r--r--base/message_pump_win.h19
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