1a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 2a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// found in the LICENSE file. 4a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 5a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <windows.h> 6a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <shlwapi.h> 7a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 8a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <stdio.h> 9a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <stdlib.h> 10a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 11a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <algorithm> 12a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <iterator> 13a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <string> 14a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include <vector> 15a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 16a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef SPLIT_LINK_SCRIPT_PATH 17a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#error SPLIT_LINK_SCRIPT_PATH must be defined as the path to "split_link.py". 18a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif 19a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 20a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#ifndef PYTHON_PATH 21a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#error PYTHON_PATH must be defined to be the path to the python binary. 22a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#endif 23a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 24a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define WIDEN2(x) L ## x 25a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define WIDEN(x) WIDEN2(x) 26a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define WPYTHON_PATH WIDEN(PYTHON_PATH) 27a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#define WSPLIT_LINK_SCRIPT_PATH WIDEN(SPLIT_LINK_SCRIPT_PATH) 28a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 29a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)using namespace std; 30a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 31a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Don't use stderr for errors because VS has large buffers on them, leading 32a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// to confusing error output. 33a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static void Fatal(const wchar_t* msg) { 34a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wprintf(L"split_link fatal error: %s\n", msg); 35a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) exit(1); 36a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 37a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 38a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static wstring ErrorMessageToString(DWORD err) { 39a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wchar_t* msg_buf = NULL; 40a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DWORD rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 41a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) FORMAT_MESSAGE_FROM_SYSTEM, 42a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) NULL, 43a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) err, 44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 45a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) reinterpret_cast<LPTSTR>(&msg_buf), 46a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 0, 47a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) NULL); 48a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!rc) 49a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return L"unknown error"; 50a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wstring ret(msg_buf); 51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LocalFree(msg_buf); 52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return ret; 53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static void ArgvQuote(const std::wstring& argument, 56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) std::wstring* command_line) { 57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Don't quote unless we actually need to. 58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!argument.empty() && 59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) argument.find_first_of(L" \t\n\v\"") == argument.npos) { 60a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) command_line->append(argument); 61a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else { 62a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) command_line->push_back(L'"'); 63a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for (std::wstring::const_iterator it = argument.begin();; ++it) { 64a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) int num_backslashes = 0; 65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) while (it != argument.end() && *it == L'\\') { 66a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ++it; 67a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ++num_backslashes; 68a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 69a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (it == argument.end()) { 70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Escape all backslashes, but let the terminating double quotation 71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // mark we add below be interpreted as a metacharacter. 72a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) command_line->append(num_backslashes * 2, L'\\'); 73a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 74a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else if (*it == L'"') { 75a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Escape all backslashes and the following double quotation mark. 76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) command_line->append(num_backslashes * 2 + 1, L'\\'); 77a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) command_line->push_back(*it); 78a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else { 79a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Backslashes aren't special here. 80a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) command_line->append(num_backslashes, L'\\'); 81a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) command_line->push_back(*it); 82a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 83a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 84a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) command_line->push_back(L'"'); 85a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 86a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 87a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 88a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Does the opposite of CommandLineToArgvW. Suitable for CreateProcess, but 89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// not for cmd.exe. |args| should include the program name as argv[0]. 90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// See http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx 91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static wstring BuildCommandLine(const vector<wstring>& args) { 92a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) std::wstring result; 93a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for (size_t i = 0; i < args.size(); ++i) { 94a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ArgvQuote(args[i], &result); 95a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (i < args.size() - 1) { 96a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) result += L" "; 97a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 98a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 99a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return result; 100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 101a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static void RunLinker(const vector<wstring>& prefix, const wchar_t* msg) { 103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (msg) { 104a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wprintf(L"split_link failed (%s), trying to fallback to standard link.\n", 105a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) msg); 106a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wprintf(L"Original command line: %s\n", GetCommandLine()); 107a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) fflush(stdout); 108a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 109a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 110a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) STARTUPINFO startup_info = { sizeof(STARTUPINFO) }; 111a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) PROCESS_INFORMATION process_info; 112a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DWORD exit_code; 113a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) GetStartupInfo(&startup_info); 115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (getenv("SPLIT_LINK_DEBUG")) { 117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wprintf(L" original command line '%s'\n", GetCommandLine()); 118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) fflush(stdout); 119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) int num_args; 122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LPWSTR* args = CommandLineToArgvW(GetCommandLine(), &num_args); 123a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!args) 124a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fatal(L"Couldn't parse command line."); 125a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) vector<wstring> argv; 126a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) argv.insert(argv.end(), prefix.begin(), prefix.end()); 127a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for (int i = 1; i < num_args; ++i) // Skip old argv[0]. 128a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) argv.push_back(args[i]); 129a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LocalFree(args); 130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wstring cmd = BuildCommandLine(argv); 132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (getenv("SPLIT_LINK_DEBUG")) { 134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wprintf(L" running '%s'\n", cmd.c_str()); 135a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) fflush(stdout); 136a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 137a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!CreateProcess(NULL, 13803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) &cmd[0], 139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) NULL, 140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) NULL, 141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) TRUE, 142a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 0, 143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) NULL, 144a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) NULL, 145a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) &startup_info, &process_info)) { 146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wstring error = ErrorMessageToString(GetLastError()); 147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fatal(error.c_str()); 148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 149a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CloseHandle(process_info.hThread); 150a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) WaitForSingleObject(process_info.hProcess, INFINITE); 151a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) GetExitCodeProcess(process_info.hProcess, &exit_code); 152a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CloseHandle(process_info.hProcess); 153a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) exit(exit_code); 154a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 155a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 156a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static void Fallback(const wchar_t* msg) { 157a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wchar_t original_link[1024]; 158a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DWORD type; 159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DWORD size = sizeof(original_link); 160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (SHGetValue(HKEY_CURRENT_USER, 161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) L"Software\\Chromium\\split_link_installed", 162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) NULL, 163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) &type, 164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) original_link, 165a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) &size) != ERROR_SUCCESS || type != REG_SZ) { 166a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fatal(L"Couldn't retrieve linker location from " 167a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) L"HKCU\\Software\\Chromium\\split_link_installed."); 168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (getenv("SPLIT_LINK_DEBUG")) { 170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wprintf(L" got original linker '%s'\n", original_link); 171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) fflush(stdout); 172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) vector<wstring> link_binary; 174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) link_binary.push_back(original_link); 175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) RunLinker(link_binary, msg); 176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 178a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static void Fallback() { 179a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fallback(NULL); 180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 181a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 182a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static unsigned char* SlurpFile(const wchar_t* path, size_t* length) { 183a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) HANDLE file = CreateFile( 184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (file == INVALID_HANDLE_VALUE) 186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fallback(L"couldn't open file"); 187a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) LARGE_INTEGER file_size; 188a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!GetFileSizeEx(file, &file_size)) 189a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fallback(L"couldn't get file size"); 190a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) *length = static_cast<size_t>(file_size.QuadPart); 191a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) unsigned char* buffer = static_cast<unsigned char*>(malloc(*length)); 192a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DWORD bytes_read = 0; 193a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!ReadFile(file, buffer, *length, &bytes_read, NULL)) 194a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fallback(L"couldn't read file"); 195a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return buffer; 196a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 197a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 198a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)static bool SplitLinkRequested(const wchar_t* rsp_path) { 199a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) size_t length; 200a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) unsigned char* data = SlurpFile(rsp_path, &length); 201a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) bool flag_found = false; 202a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (data[0] == 0xff && data[1] == 0xfe) { 203a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // UTF-16LE 204a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wstring wide(reinterpret_cast<wchar_t*>(&data[2]), 205a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) length / sizeof(wchar_t) - 1); 206a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) flag_found = wide.find(L"/splitlink") != wide.npos; 207a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } else { 208a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) string narrow(reinterpret_cast<char*>(data), length); 209a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) flag_found = narrow.find("/splitlink") != narrow.npos; 210a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 211a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) free(data); 212a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return flag_found; 213a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 214a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 215a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// If /splitlink is on the command line, delegate to split_link.py, otherwise 216a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// fallback to standard linker. 217a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)int wmain(int argc, wchar_t** argv) { 218a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) int rsp_file_index = -1; 219a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 220a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (argc < 2) 221a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fallback(); 222a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 223a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) for (int i = 1; i < argc; ++i) { 224a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (argv[i][0] == L'@') { 225a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) rsp_file_index = i; 226a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) break; 227a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 228a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 229a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 230a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (rsp_file_index == -1) 231a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fallback(L"couldn't find a response file in argv"); 232a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 233a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (getenv("SPLIT_LINK_DEBUG")) { 234a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wstring backup_copy(&argv[rsp_file_index][1]); 235a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) backup_copy += L".copy"; 236a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wchar_t buf[1024]; 237a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) swprintf(buf, 238a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) sizeof(buf), 239a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) L"copy %s %s", 240a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) &argv[rsp_file_index][1], 241a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) backup_copy.c_str()); 242a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (_wsystem(buf) == 0) 243a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wprintf(L"Saved original rsp as %s\n", backup_copy.c_str()); 244a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) else 245a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) wprintf(L"'%s' failed.", buf); 246a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 247a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 248a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (SplitLinkRequested(&argv[rsp_file_index][1])) { 249a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) vector<wstring> link_binary; 250a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) link_binary.push_back(WPYTHON_PATH); 251a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) link_binary.push_back(WSPLIT_LINK_SCRIPT_PATH); 252a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) RunLinker(link_binary, NULL); 253a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 254a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 255a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Otherwise, run regular linker silently. 256a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) Fallback(); 257a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 258