Chromium Code Reviews| Index: tools/win/supalink/supalink.cpp |
| diff --git a/tools/win/supalink/supalink.cpp b/tools/win/supalink/supalink.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0c26227b2a156870ac5050ed2e415072853dc1c1 |
| --- /dev/null |
| +++ b/tools/win/supalink/supalink.cpp |
| @@ -0,0 +1,189 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include <windows.h> |
| +#include <stdio.h> |
| +#include <stdlib.h> |
| +#include <string> |
| + |
| +using namespace std; |
| + |
| +// Don't use stderr for errors because VS has large buffers on them, leading |
| +// to confusing error output. |
| +static void Fatal(const char* msg) { |
| + fprintf(stdout, "supalink fatal error: %s\n", msg); |
|
M-A Ruel
2011/09/27 23:21:33
why not wprintf() then?
scottmg
2011/09/28 00:19:38
Done.
|
| + exit(1); |
| +} |
| + |
| +static string ErrorMessageToString(DWORD err) { |
|
M-A Ruel
2011/09/27 23:21:33
wstring
scottmg
2011/09/28 00:19:38
Done.
|
| + LPTSTR msg_buf = NULL; |
|
M-A Ruel
2011/09/27 23:21:33
wchar_t*
scottmg
2011/09/28 00:19:38
Done.
|
| + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, |
| + NULL, |
| + err, |
| + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
| + (LPTSTR)&msg_buf, |
|
M-A Ruel
2011/09/27 23:21:33
reinterpret_cast<>()
scottmg
2011/09/28 00:19:38
Done.
|
| + 0, |
| + NULL); |
| + string ret(msg_buf); |
| + LocalFree(msg_buf); |
| + return ret; |
| +} |
| + |
| + |
| +static void Fallback(const char* msg = 0) { |
|
M-A Ruel
2011/09/27 23:21:33
wchar_t
scottmg
2011/09/28 00:19:38
Done.
|
| + if (msg) { |
| + fprintf(stdout, |
|
M-A Ruel
2011/09/27 23:21:33
same
scottmg
2011/09/28 00:19:38
Done.
|
| + "supalink failed (%s), trying to fallback to standard link.\n", |
| + msg); |
| + fprintf(stdout, "Original command line: %s\n", GetCommandLine()); |
| + fflush(stdout); |
| + } |
| + |
| + STARTUPINFO startup_info = { sizeof(STARTUPINFO) }; |
| + PROCESS_INFORMATION process_info; |
| + DWORD exit_code; |
| + |
| + string orig_cmd(GetCommandLine()); |
| + |
| + const char* search_for[] = { |
|
M-A Ruel
2011/09/27 23:21:33
Move to const global
scottmg
2011/09/28 00:19:38
Done.
|
| + "link.exe\" ", |
| + "LINK.EXE\" ", |
| + "link.EXE\" ", |
| + "link\" ", |
| + "LINK\" ", |
| + "link.exe ", |
| + "LINK.EXE ", |
| + "link.EXE ", |
| + "link ", |
| + "LINK ", |
| + }; |
| + string cmd; |
| + string replace_with = "link.exe.supalink_orig.exe"; |
| + for (size_t i = 0; i < sizeof(search_for) / sizeof(search_for[0]); ++i) { |
| + string linkexe = search_for[i]; |
| + string::size_type at = orig_cmd.find(linkexe, 0); |
| + if (at == string::npos) |
| + continue; |
| + if (linkexe[linkexe.size() - 2] == '"') |
| + replace_with += "\" "; |
| + else |
| + replace_with += " "; |
| + cmd = orig_cmd.replace(at, linkexe.size(), replace_with); |
| + break; |
| + } |
| + if (cmd == "") { |
| + fprintf(stdout, "Original run '%s'\n", orig_cmd.c_str()); |
| + Fatal("Couldn't find link.exe (or similar) in command line"); |
| + } |
| + |
| + if (getenv("SUPALINK_DEBUG")) { |
| + fprintf(stdout, " running '%s'\n", cmd.c_str()); |
| + fflush(stdout); |
| + } |
| + if (!CreateProcess(NULL, |
| + (LPSTR)cmd.c_str(), |
|
M-A Ruel
2011/09/27 23:21:33
same
scottmg
2011/09/28 00:19:38
Done.
|
| + NULL, |
| + NULL, |
| + TRUE, |
| + 0, |
| + NULL, |
| + NULL, |
| + &startup_info, &process_info)) { |
| + string error = ErrorMessageToString(GetLastError()); |
| + Fatal(error.c_str()); |
| + } |
| + WaitForSingleObject(process_info.hProcess, INFINITE); |
| + GetExitCodeProcess(process_info.hProcess, &exit_code); |
| + CloseHandle(process_info.hProcess); |
| + CloseHandle(process_info.hThread); |
| + exit(exit_code); |
| +} |
| + |
| +wstring SlurpFile(const char* path) { |
|
M-A Ruel
2011/09/27 23:21:33
so I'll stop here but make the project unicode ple
scottmg
2011/09/28 00:19:38
Done.
|
| + FILE* f = fopen(path, "rb, ccs=UNICODE"); |
| + if (!f) Fallback("couldn't read file"); |
| + fseek(f, 0, SEEK_END); |
| + long len = ftell(f); |
| + rewind(f); |
| + wchar_t* data = reinterpret_cast<wchar_t*>(malloc(len)); |
| + fread(data, 1, len, f); |
| + fclose(f); |
| + wstring ret(data, len/sizeof(wchar_t)); |
| + free(data); |
| + return ret; |
| +} |
| + |
| +void DumpFile(const char* path, wstring& contents) { |
| + FILE* f = fopen(path, "wb, ccs=UTF-16LE"); |
| + if (!f) Fallback("couldn't write file"); |
| + |
| + fwrite(contents.c_str(), sizeof(wchar_t), contents.size(), f); |
| + if (ferror(f)) Fatal("failed during response rewrite"); |
| + fclose(f); |
| +} |
| + |
| +// Input command line is assumed to be of the form: |
| +// |
| +// link.exe @C:\src\...\RSP00003045884740.rsp /NOLOGO /ERRORREPORT:PROMPT |
| +// |
| +// Specifically, we parse & hack the contents of argv[1] and pass the rest |
| +// onwards. |
| +int main(int argc, char** argv) { |
| + ULONGLONG start_time = 0, end_time; |
| + |
| + int rsp_file_index = -1; |
| + |
| + if (argc < 2) |
| + Fallback("too few commmand line args"); |
| + |
| + for (int i = 1; i < argc; ++i) { |
| + if (argv[i][0] == '@') { |
| + rsp_file_index = i; |
| + break; |
| + } |
| + } |
| + |
| + if (rsp_file_index == -1) |
| + Fallback("couldn't find a response file in argv"); |
| + |
| + if (getenv("SUPALINK_DEBUG")) |
| + start_time = GetTickCount64(); |
| + |
| + wstring rsp = SlurpFile(&argv[rsp_file_index][1]); |
| + |
| + // The first line of this file is all we try to fix. It's a bunch of |
| + // quoted space separated items. Simplest thing seems to be replacing " " |
| + // with "\n". So, just slurp the file, replace, spit it out to the same |
| + // file and continue on our way. |
| + |
| + // Took about .5s when using the naive .replace loop to replace " " with |
| + // "\r\n" so write the silly loop instead. |
| + wstring fixed; |
| + fixed.reserve(rsp.size() * 2); |
| + |
| + for (const wchar_t* s = rsp.c_str(); *s;) { |
| + if (*s == '"' && *(s + 1) == ' ' && *(s + 2) == '"') { |
| + fixed += L"\"\r\n\""; |
| + s += 3; |
| + } else { |
| + fixed += *s++; |
| + } |
| + } |
| + |
| + DumpFile(&argv[rsp_file_index][1], fixed); |
| + |
| + if (getenv("SUPALINK_DEBUG")) { |
| + string backup_copy(&argv[rsp_file_index][1]); |
| + backup_copy += ".copy"; |
| + DumpFile(backup_copy.c_str(), fixed); |
| + |
| + end_time = GetTickCount64(); |
| + |
| + fprintf(stdout, |
| + " took %.2fs to modify @rsp file\n", |
| + (end_time - start_time) / 1000.0); |
| + } |
| + |
| + Fallback(); |
| +} |