| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/host/win/launch_process_with_token.h" | 5 #include "remoting/host/win/launch_process_with_token.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <winternl.h> | 8 #include <winternl.h> |
| 9 | 9 |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/scoped_native_library.h" | 12 #include "base/scoped_native_library.h" |
| 13 #include "base/stringprintf.h" | 13 #include "base/stringprintf.h" |
| 14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "base/win/scoped_handle.h" | 15 #include "base/win/scoped_handle.h" |
| 16 #include "base/win/scoped_process_information.h" | 16 #include "base/win/scoped_process_information.h" |
| 17 #include "base/win/windows_version.h" | 17 #include "base/win/windows_version.h" |
| 18 | 18 |
| 19 using base::win::ScopedHandle; | 19 using base::win::ScopedHandle; |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 const wchar_t kCreateProcessDefaultPipeNameFormat[] = | 23 const char kCreateProcessDefaultPipeNameFormat[] = |
| 24 L"\\\\.\\Pipe\\TerminalServer\\SystemExecSrvr\\%d"; | 24 "\\\\.\\Pipe\\TerminalServer\\SystemExecSrvr\\%d"; |
| 25 | 25 |
| 26 // Undocumented WINSTATIONINFOCLASS value causing | 26 // Undocumented WINSTATIONINFOCLASS value causing |
| 27 // winsta!WinStationQueryInformationW() to return the name of the pipe for | 27 // winsta!WinStationQueryInformationW() to return the name of the pipe for |
| 28 // requesting cross-session process creation. | 28 // requesting cross-session process creation. |
| 29 const WINSTATIONINFOCLASS kCreateProcessPipeNameClass = | 29 const WINSTATIONINFOCLASS kCreateProcessPipeNameClass = |
| 30 static_cast<WINSTATIONINFOCLASS>(0x21); | 30 static_cast<WINSTATIONINFOCLASS>(0x21); |
| 31 | 31 |
| 32 const int kPipeBusyWaitTimeoutMs = 2000; | 32 const int kPipeBusyWaitTimeoutMs = 2000; |
| 33 const int kPipeConnectMaxAttempts = 3; | 33 const int kPipeConnectMaxAttempts = 3; |
| 34 | 34 |
| 35 // The minimum and maximum delays between attempts to inject host process into | 35 // The minimum and maximum delays between attempts to inject host process into |
| 36 // a session. | 36 // a session. |
| 37 const int kMaxLaunchDelaySeconds = 60; | 37 const int kMaxLaunchDelaySeconds = 60; |
| 38 const int kMinLaunchDelaySeconds = 1; | 38 const int kMinLaunchDelaySeconds = 1; |
| 39 | 39 |
| 40 // Name of the default session desktop. | 40 // Name of the default session desktop. |
| 41 wchar_t kDefaultDesktopName[] = L"winsta0\\default"; | 41 const char kDefaultDesktopName[] = "winsta0\\default"; |
| 42 | 42 |
| 43 // Requests the execution server to create a process in the specified session | 43 // Requests the execution server to create a process in the specified session |
| 44 // using the default (i.e. Winlogon) token. This routine relies on undocumented | 44 // using the default (i.e. Winlogon) token. This routine relies on undocumented |
| 45 // OS functionality and will likely not work on anything but XP or W2K3. | 45 // OS functionality and will likely not work on anything but XP or W2K3. |
| 46 bool CreateRemoteSessionProcess( | 46 bool CreateRemoteSessionProcess( |
| 47 uint32 session_id, | 47 uint32 session_id, |
| 48 const std::wstring& application_name, | 48 const FilePath::StringType& application_name, |
| 49 const std::wstring& command_line, | 49 const CommandLine::StringType& command_line, |
| 50 PROCESS_INFORMATION* process_information_out) | 50 PROCESS_INFORMATION* process_information_out) |
| 51 { | 51 { |
| 52 DCHECK(base::win::GetVersion() == base::win::VERSION_XP); | 52 DCHECK(base::win::GetVersion() == base::win::VERSION_XP); |
| 53 | 53 |
| 54 std::wstring pipe_name; | 54 string16 pipe_name; |
| 55 | 55 |
| 56 // Use winsta!WinStationQueryInformationW() to determine the process creation | 56 // Use winsta!WinStationQueryInformationW() to determine the process creation |
| 57 // pipe name for the session. | 57 // pipe name for the session. |
| 58 FilePath winsta_path(base::GetNativeLibraryName(UTF8ToUTF16("winsta"))); | 58 FilePath winsta_path(base::GetNativeLibraryName(UTF8ToUTF16("winsta"))); |
| 59 base::ScopedNativeLibrary winsta(winsta_path); | 59 base::ScopedNativeLibrary winsta(winsta_path); |
| 60 if (winsta.is_valid()) { | 60 if (winsta.is_valid()) { |
| 61 PWINSTATIONQUERYINFORMATIONW win_station_query_information = | 61 PWINSTATIONQUERYINFORMATIONW win_station_query_information = |
| 62 static_cast<PWINSTATIONQUERYINFORMATIONW>( | 62 static_cast<PWINSTATIONQUERYINFORMATIONW>( |
| 63 winsta.GetFunctionPointer("WinStationQueryInformationW")); | 63 winsta.GetFunctionPointer("WinStationQueryInformationW")); |
| 64 if (win_station_query_information) { | 64 if (win_station_query_information) { |
| 65 wchar_t name[MAX_PATH]; | 65 wchar_t name[MAX_PATH]; |
| 66 ULONG name_length; | 66 ULONG name_length; |
| 67 if (win_station_query_information(0, | 67 if (win_station_query_information(0, |
| 68 session_id, | 68 session_id, |
| 69 kCreateProcessPipeNameClass, | 69 kCreateProcessPipeNameClass, |
| 70 name, | 70 name, |
| 71 sizeof(name), | 71 sizeof(name), |
| 72 &name_length)) { | 72 &name_length)) { |
| 73 pipe_name.assign(name); | 73 pipe_name.assign(name); |
| 74 } | 74 } |
| 75 } | 75 } |
| 76 } | 76 } |
| 77 | 77 |
| 78 // Use the default pipe name if we couldn't query its name. | 78 // Use the default pipe name if we couldn't query its name. |
| 79 if (pipe_name.empty()) { | 79 if (pipe_name.empty()) { |
| 80 pipe_name = StringPrintf(kCreateProcessDefaultPipeNameFormat, session_id); | 80 pipe_name = UTF8ToUTF16( |
| 81 StringPrintf(kCreateProcessDefaultPipeNameFormat, session_id)); |
| 81 } | 82 } |
| 82 | 83 |
| 83 // Try to connect to the named pipe. | 84 // Try to connect to the named pipe. |
| 84 base::win::ScopedHandle pipe; | 85 base::win::ScopedHandle pipe; |
| 85 for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { | 86 for (int i = 0; i < kPipeConnectMaxAttempts; ++i) { |
| 86 pipe.Set(CreateFile(pipe_name.c_str(), | 87 pipe.Set(CreateFile(pipe_name.c_str(), |
| 87 GENERIC_READ | GENERIC_WRITE, | 88 GENERIC_READ | GENERIC_WRITE, |
| 88 0, | 89 0, |
| 89 NULL, | 90 NULL, |
| 90 OPEN_EXISTING, | 91 OPEN_EXISTING, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 104 if (!WaitNamedPipe(pipe_name.c_str(), kPipeBusyWaitTimeoutMs)) { | 105 if (!WaitNamedPipe(pipe_name.c_str(), kPipeBusyWaitTimeoutMs)) { |
| 105 break; | 106 break; |
| 106 } | 107 } |
| 107 } | 108 } |
| 108 | 109 |
| 109 if (!pipe.IsValid()) { | 110 if (!pipe.IsValid()) { |
| 110 LOG_GETLASTERROR(ERROR) << "Failed to connect to '" << pipe_name << "'"; | 111 LOG_GETLASTERROR(ERROR) << "Failed to connect to '" << pipe_name << "'"; |
| 111 return false; | 112 return false; |
| 112 } | 113 } |
| 113 | 114 |
| 114 std::wstring desktop_name(kDefaultDesktopName); | 115 string16 desktop_name(UTF8ToUTF16(kDefaultDesktopName)); |
| 115 | 116 |
| 116 // |CreateProcessRequest| structure passes the same parameters to | 117 // |CreateProcessRequest| structure passes the same parameters to |
| 117 // the execution server as CreateProcessAsUser() function does. Strings are | 118 // the execution server as CreateProcessAsUser() function does. Strings are |
| 118 // stored as wide strings immediately after the structure. String pointers are | 119 // stored as wide strings immediately after the structure. String pointers are |
| 119 // represented as byte offsets to string data from the beginning of | 120 // represented as byte offsets to string data from the beginning of |
| 120 // the structure. | 121 // the structure. |
| 121 struct CreateProcessRequest { | 122 struct CreateProcessRequest { |
| 122 DWORD size; | 123 DWORD size; |
| 123 DWORD process_id; | 124 DWORD process_id; |
| 124 BOOL use_default_token; | 125 BOOL use_default_token; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 | 238 |
| 238 *process_information_out = response.process_information; | 239 *process_information_out = response.process_information; |
| 239 return true; | 240 return true; |
| 240 } | 241 } |
| 241 | 242 |
| 242 } // namespace | 243 } // namespace |
| 243 | 244 |
| 244 namespace remoting { | 245 namespace remoting { |
| 245 | 246 |
| 246 bool LaunchProcessWithToken(const FilePath& binary, | 247 bool LaunchProcessWithToken(const FilePath& binary, |
| 247 const std::wstring& command_line, | 248 const CommandLine::StringType& command_line, |
| 248 HANDLE user_token, | 249 HANDLE user_token, |
| 249 base::Process* process_out) { | 250 base::Process* process_out) { |
| 250 std::wstring application_name = binary.value(); | 251 FilePath::StringType application_name = binary.value(); |
| 251 | 252 |
| 252 base::win::ScopedProcessInformation process_info; | 253 base::win::ScopedProcessInformation process_info; |
| 253 STARTUPINFOW startup_info; | 254 STARTUPINFOW startup_info; |
| 254 | 255 |
| 256 string16 desktop_name(UTF8ToUTF16(kDefaultDesktopName)); |
| 257 |
| 255 memset(&startup_info, 0, sizeof(startup_info)); | 258 memset(&startup_info, 0, sizeof(startup_info)); |
| 256 startup_info.cb = sizeof(startup_info); | 259 startup_info.cb = sizeof(startup_info); |
| 257 startup_info.lpDesktop = kDefaultDesktopName; | 260 startup_info.lpDesktop = const_cast<char16*>(desktop_name.c_str()); |
| 258 | 261 |
| 259 BOOL result = CreateProcessAsUser(user_token, | 262 BOOL result = CreateProcessAsUser(user_token, |
| 260 application_name.c_str(), | 263 application_name.c_str(), |
| 261 const_cast<LPWSTR>(command_line.c_str()), | 264 const_cast<LPWSTR>(command_line.c_str()), |
| 262 NULL, | 265 NULL, |
| 263 NULL, | 266 NULL, |
| 264 FALSE, | 267 FALSE, |
| 265 0, | 268 0, |
| 266 NULL, | 269 NULL, |
| 267 NULL, | 270 NULL, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 "Failed to launch a process with a user token"; | 304 "Failed to launch a process with a user token"; |
| 302 return false; | 305 return false; |
| 303 } | 306 } |
| 304 | 307 |
| 305 CHECK(process_info.IsValid()); | 308 CHECK(process_info.IsValid()); |
| 306 process_out->set_handle(process_info.TakeProcessHandle()); | 309 process_out->set_handle(process_info.TakeProcessHandle()); |
| 307 return true; | 310 return true; |
| 308 } | 311 } |
| 309 | 312 |
| 310 } // namespace remoting | 313 } // namespace remoting |
| OLD | NEW |