OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 #include <windows.h> | 8 #include <windows.h> |
9 | 9 |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "native_client/src/include/nacl_string.h" | 12 #include "native_client/src/include/nacl_string.h" |
13 #include "native_client/src/include/portability.h" | 13 #include "native_client/src/include/portability.h" |
14 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" | 14 #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" |
15 #include "native_client/src/trusted/desc/nacl_desc_base.h" | 15 #include "native_client/src/trusted/desc/nacl_desc_base.h" |
16 | 16 |
17 // Use a predefined symbol to get a handle to the current module. | 17 // Use a predefined symbol to get a handle to the current module. |
18 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx | 18 // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx |
19 // @IGNORE_LINES_FOR_CODE_HYGIENE[1] | 19 // @IGNORE_LINES_FOR_CODE_HYGIENE[1] |
20 extern "C" IMAGE_DOS_HEADER __ImageBase; | 20 extern "C" IMAGE_DOS_HEADER __ImageBase; |
21 | 21 |
22 using std::vector; | 22 using std::vector; |
23 | 23 |
24 namespace nacl { | 24 namespace nacl { |
25 | 25 |
26 SelLdrLauncher::~SelLdrLauncher() { | 26 SelLdrLauncherStandalone::~SelLdrLauncherStandalone() { |
27 CloseHandlesAfterLaunch(); | 27 CloseHandlesAfterLaunch(); |
28 #if defined(NACL_STANDALONE) | |
29 if (kInvalidHandle != child_process_) { | 28 if (kInvalidHandle != child_process_) { |
30 // Ensure child process (service runtime) is kaput. NB: we might | 29 // Ensure child process (service runtime) is kaput. NB: we might |
31 // close the command channel (or use the hard_shutdown RPC) rather | 30 // close the command channel (or use the hard_shutdown RPC) rather |
32 // than killing the process to allow the service runtime to do | 31 // than killing the process to allow the service runtime to do |
33 // clean up, but the plugin should be responsible for that and we | 32 // clean up, but the plugin should be responsible for that and we |
34 // shouldn't introduce any timeout wait in a dtor. Currently, | 33 // shouldn't introduce any timeout wait in a dtor. Currently, |
35 // ServiceRuntime::Shutdown kills the subprocess before closing | 34 // ServiceRuntime::Shutdown kills the subprocess before closing |
36 // the command channel, so we aren't providing the opportunity for | 35 // the command channel, so we aren't providing the opportunity for |
37 // a more graceful shutdown. | 36 // a more graceful shutdown. |
38 KillChildProcess(); | 37 KillChildProcess(); |
39 CloseHandle(child_process_); | 38 CloseHandle(child_process_); |
40 } | 39 } |
41 #endif | |
42 if (kInvalidHandle != channel_) { | |
43 Close(channel_); | |
44 } | |
45 } | 40 } |
46 | 41 |
47 nacl::string SelLdrLauncher::GetSelLdrPathName() { | 42 nacl::string SelLdrLauncherStandalone::GetSelLdrPathName() { |
48 char buffer[FILENAME_MAX]; | 43 char buffer[FILENAME_MAX]; |
49 // Currently only the Chrome build uses the gyp-generated binaries, and | 44 // Currently only the Chrome build uses the gyp-generated binaries, |
50 // Chrome does not start sel_ldr by means of SelLdrLauncher. So we only | 45 // and Chrome does not start sel_ldr by means of |
51 // refer to sel_ldr.exe here. | 46 // SelLdrLauncherStandalone. So we only refer to sel_ldr.exe here. |
52 const char* const kSelLdrBasename = "\\sel_ldr.exe"; | 47 const char* const kSelLdrBasename = "\\sel_ldr.exe"; |
53 GetPluginDirectory(buffer, sizeof(buffer)); | 48 GetPluginDirectory(buffer, sizeof(buffer)); |
54 return nacl::string(buffer) + kSelLdrBasename; | 49 return nacl::string(buffer) + kSelLdrBasename; |
55 } | 50 } |
56 | 51 |
57 nacl::string SelLdrLauncher::GetSelLdrBootstrapPathName() { | 52 nacl::string SelLdrLauncherStandalone::GetSelLdrBootstrapPathName() { |
58 return nacl::string(NACL_NO_FILE_PATH); | 53 return nacl::string(NACL_NO_FILE_PATH); |
59 } | 54 } |
60 | 55 |
61 // TODO(sehr): document what this is supposed to do exactly | 56 // TODO(sehr): document what this is supposed to do exactly |
62 // NOTE: this may be buggy, e.g. how is \\ handled? | 57 // NOTE: this may be buggy, e.g. how is \\ handled? |
63 static nacl::string Escape(nacl::string s) { | 58 static nacl::string Escape(nacl::string s) { |
64 nacl::string result; | 59 nacl::string result; |
65 for (size_t i = 0; i < s.size(); ++i) { | 60 for (size_t i = 0; i < s.size(); ++i) { |
66 if (s[i] == '"') { | 61 if (s[i] == '"') { |
67 result += "\\\""; | 62 result += "\\\""; |
68 } else if (s[i] == '\\' && i + 1 < s.size() && s[i + 1] == '"') { | 63 } else if (s[i] == '\\' && i + 1 < s.size() && s[i + 1] == '"') { |
69 result += "\\\\\\\""; | 64 result += "\\\\\\\""; |
70 ++i; | 65 ++i; |
71 } else { | 66 } else { |
72 result.push_back(s[i]); | 67 result.push_back(s[i]); |
73 } | 68 } |
74 } | 69 } |
75 | 70 |
76 return result; | 71 return result; |
77 } | 72 } |
78 | 73 |
79 Handle SelLdrLauncher::CreateBootstrapSocket(nacl::string* dest_fd) { | 74 Handle SelLdrLauncherStandalone::CreateBootstrapSocket(nacl::string* dest_fd) { |
80 Handle pair[2]; | 75 Handle pair[2]; |
81 if (SocketPair(pair) == -1) { | 76 if (SocketPair(pair) == -1) { |
82 return kInvalidHandle; | 77 return kInvalidHandle; |
83 } | 78 } |
84 | 79 |
85 // Transfer pair[1] to child_process_ by inheritance. | 80 // Transfer pair[1] to child_process_ by inheritance. |
86 // TODO(mseaborn): We could probably use SetHandleInformation() to | 81 // TODO(mseaborn): We could probably use SetHandleInformation() to |
87 // set HANDLE_FLAG_INHERIT rather than duplicating the handle and | 82 // set HANDLE_FLAG_INHERIT rather than duplicating the handle and |
88 // closing the original. But for now, we do the same as in | 83 // closing the original. But for now, we do the same as in |
89 // LaunchFromCommandLine() below. | 84 // LaunchFromCommandLine() below. |
90 Handle channel; | 85 Handle channel; |
91 if (!DuplicateHandle(GetCurrentProcess(), pair[1], | 86 if (!DuplicateHandle(GetCurrentProcess(), pair[1], |
92 GetCurrentProcess(), &channel, | 87 GetCurrentProcess(), &channel, |
93 0, TRUE, DUPLICATE_SAME_ACCESS)) { | 88 0, TRUE, DUPLICATE_SAME_ACCESS)) { |
94 Close(pair[0]); | 89 Close(pair[0]); |
95 Close(pair[1]); | 90 Close(pair[1]); |
96 return kInvalidHandle; | 91 return kInvalidHandle; |
97 } | 92 } |
98 Close(pair[1]); | 93 Close(pair[1]); |
99 close_after_launch_.push_back(channel); | 94 close_after_launch_.push_back(channel); |
100 | 95 |
101 *dest_fd = ToString(reinterpret_cast<uintptr_t>(channel)); | 96 *dest_fd = ToString(reinterpret_cast<uintptr_t>(channel)); |
102 return pair[0]; | 97 return pair[0]; |
103 } | 98 } |
104 | 99 |
105 #if defined(NACL_STANDALONE) | 100 bool SelLdrLauncherStandalone::StartViaCommandLine( |
106 bool SelLdrLauncher::StartViaCommandLine( | |
107 const vector<nacl::string>& prefix, | 101 const vector<nacl::string>& prefix, |
108 const vector<nacl::string>& sel_ldr_argv, | 102 const vector<nacl::string>& sel_ldr_argv, |
109 const vector<nacl::string>& app_argv) { | 103 const vector<nacl::string>& app_argv) { |
110 // Set up the command line. | 104 // Set up the command line. |
111 InitCommandLine(prefix, sel_ldr_argv, app_argv); | 105 InitCommandLine(prefix, sel_ldr_argv, app_argv); |
112 STARTUPINFOA startup_info; | 106 STARTUPINFOA startup_info; |
113 PROCESS_INFORMATION process_infomation; | 107 PROCESS_INFORMATION process_infomation; |
114 | 108 |
115 vector<nacl::string> command; | 109 vector<nacl::string> command; |
116 BuildCommandLine(&command); | 110 BuildCommandLine(&command); |
(...skipping 17 matching lines...) Expand all Loading... |
134 &startup_info, | 128 &startup_info, |
135 &process_infomation)) { | 129 &process_infomation)) { |
136 return false; | 130 return false; |
137 } | 131 } |
138 | 132 |
139 CloseHandlesAfterLaunch(); | 133 CloseHandlesAfterLaunch(); |
140 CloseHandle(process_infomation.hThread); | 134 CloseHandle(process_infomation.hThread); |
141 child_process_ = process_infomation.hProcess; | 135 child_process_ = process_infomation.hProcess; |
142 return true; | 136 return true; |
143 } | 137 } |
144 #endif | |
145 | 138 |
146 bool SelLdrLauncher::KillChildProcess() { | 139 bool SelLdrLauncherStandalone::KillChildProcess() { |
147 #if defined(NACL_STANDALONE) | |
148 if (kInvalidHandle == child_process_) | 140 if (kInvalidHandle == child_process_) |
149 return false; | 141 return false; |
150 return 0 != TerminateProcess(child_process_, 9); | 142 return 0 != TerminateProcess(child_process_, 9); |
151 // 9 is the exit code for the child_process_. The value is actually not | 143 // 9 is the exit code for the child_process_. The value is actually not |
152 // material, since (currently) the launcher does not collect/report it. | 144 // material, since (currently) the launcher does not collect/report it. |
153 #else | |
154 return false; | |
155 #endif | |
156 } | 145 } |
157 | 146 |
158 void PluginSelLdrLocator::GetDirectory(char* buffer, size_t len) { | 147 void PluginSelLdrLocator::GetDirectory(char* buffer, size_t len) { |
159 // __ImageBase is in the current module, which could be a .dll or .exe | 148 // __ImageBase is in the current module, which could be a .dll or .exe |
160 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); | 149 HMODULE this_module = reinterpret_cast<HMODULE>(&__ImageBase); |
161 // NOTE: casting down to DWORD is safe the integer will become smaller | 150 // NOTE: casting down to DWORD is safe the integer will become smaller |
162 // at worst | 151 // at worst |
163 GetModuleFileNameA(this_module, buffer, static_cast<DWORD>(len)); | 152 GetModuleFileNameA(this_module, buffer, static_cast<DWORD>(len)); |
164 char* path_end = strrchr(buffer, '\\'); | 153 char* path_end = strrchr(buffer, '\\'); |
165 if (NULL != path_end) { | 154 if (NULL != path_end) { |
166 *path_end = '\0'; | 155 *path_end = '\0'; |
167 } | 156 } |
168 } | 157 } |
169 | 158 |
170 } // namespace nacl | 159 } // namespace nacl |
OLD | NEW |