| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <windows.h> |
| 6 #include <stdio.h> |
| 7 #include <stdlib.h> |
| 8 #include <string> |
| 9 |
| 10 using namespace std; |
| 11 |
| 12 // Don't use stderr for errors because VS has large buffers on them, leading |
| 13 // to confusing error output. |
| 14 static void Fatal(const char* msg) |
| 15 { |
| 16 fprintf(stdout, "supalink fatal error: %s\n", msg); |
| 17 exit(1); |
| 18 } |
| 19 |
| 20 static string ErrorMessageToString(DWORD err) |
| 21 { |
| 22 LPTSTR msgBuf = NULL; |
| 23 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, |
| 24 NULL, |
| 25 err, |
| 26 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
| 27 (LPTSTR)&msgBuf, |
| 28 0, |
| 29 NULL); |
| 30 string ret(msgBuf); |
| 31 LocalFree(msgBuf); |
| 32 return ret; |
| 33 } |
| 34 |
| 35 |
| 36 static void Fallback(const char* msg = 0) |
| 37 { |
| 38 if (msg) |
| 39 { |
| 40 fprintf(stdout, |
| 41 "supalink failed (%s), trying to fallback to standard link.\n", |
| 42 msg); |
| 43 fprintf(stdout, "Original command line: %s\n", GetCommandLine()); |
| 44 fflush(stdout); |
| 45 } |
| 46 |
| 47 STARTUPINFO startupInfo = { sizeof(STARTUPINFO) }; |
| 48 PROCESS_INFORMATION processInfo; |
| 49 DWORD exitCode; |
| 50 |
| 51 string origCmd(GetCommandLine()); |
| 52 |
| 53 const char* searchFor[] = { |
| 54 "link.exe\" ", |
| 55 "LINK.EXE\" ", |
| 56 "link.EXE\" ", |
| 57 "link\" ", |
| 58 "LINK\" ", |
| 59 "link.exe ", |
| 60 "LINK.EXE ", |
| 61 "link.EXE ", |
| 62 "link ", |
| 63 "LINK ", |
| 64 }; |
| 65 string cmd; |
| 66 string replaceWith = "link.exe.supalink_orig.exe"; |
| 67 for (size_t i = 0; i < sizeof(searchFor) / sizeof(searchFor[0]); ++i) |
| 68 { |
| 69 string linkexe = searchFor[i]; |
| 70 string::size_type at = origCmd.find(linkexe, 0); |
| 71 if (at == string::npos) |
| 72 continue; |
| 73 if (linkexe[linkexe.size() - 2] == '"') |
| 74 replaceWith += "\" "; |
| 75 else |
| 76 replaceWith += " "; |
| 77 cmd = origCmd.replace(at, linkexe.size(), replaceWith); |
| 78 break; |
| 79 } |
| 80 if (cmd == "") |
| 81 { |
| 82 fprintf(stdout, "Original run '%s'\n", origCmd.c_str()); |
| 83 Fatal("Couldn't find link.exe (or similar) in command line"); |
| 84 } |
| 85 |
| 86 if (getenv("SUPALINK_DEBUG")) |
| 87 { |
| 88 fprintf(stdout, " running '%s'\n", cmd.c_str()); |
| 89 fflush(stdout); |
| 90 } |
| 91 if (!CreateProcess(NULL, |
| 92 (LPSTR)cmd.c_str(), |
| 93 NULL, |
| 94 NULL, |
| 95 TRUE, |
| 96 0, |
| 97 NULL, |
| 98 NULL, |
| 99 &startupInfo, &processInfo)) |
| 100 { |
| 101 string error = ErrorMessageToString(GetLastError()); |
| 102 Fatal(error.c_str()); |
| 103 } |
| 104 WaitForSingleObject(processInfo.hProcess, INFINITE); |
| 105 GetExitCodeProcess(processInfo.hProcess, &exitCode); |
| 106 CloseHandle(processInfo.hProcess); |
| 107 CloseHandle(processInfo.hThread); |
| 108 exit(exitCode); |
| 109 } |
| 110 |
| 111 wstring SlurpFile(const char* path) |
| 112 { |
| 113 FILE* f = fopen(path, "rb, ccs=UNICODE"); |
| 114 if (!f) Fallback("couldn't read file"); |
| 115 fseek(f, 0, SEEK_END); |
| 116 long len = ftell(f); |
| 117 rewind(f); |
| 118 wchar_t* data = (wchar_t*)malloc(len); |
| 119 fread(data, 1, len, f); |
| 120 fclose(f); |
| 121 wstring ret(data, len/sizeof(wchar_t)); |
| 122 free(data); |
| 123 return ret; |
| 124 } |
| 125 |
| 126 void DumpFile(const char* path, wstring& contents) |
| 127 { |
| 128 FILE* f = fopen(path, "wb, ccs=UTF-16LE"); |
| 129 if (!f) Fallback("couldn't write file"); |
| 130 |
| 131 fwrite(contents.c_str(), sizeof(wchar_t), contents.size(), f); |
| 132 if (ferror(f)) Fatal("failed during response rewrite"); |
| 133 fclose(f); |
| 134 } |
| 135 |
| 136 // Input command line is assumed to be of the form: |
| 137 // |
| 138 // link.exe @C:\src\...\RSP00003045884740.rsp /NOLOGO /ERRORREPORT:PROMPT |
| 139 // |
| 140 // Specifically, we parse & hack the contents of argv[1] and pass the rest |
| 141 // onwards. |
| 142 // |
| 143 // %REALLINK%.supalink_orig.exe |
| 144 int main(int argc, char** argv) |
| 145 { |
| 146 ULONGLONG startTime = 0, endTime; |
| 147 //fprintf(stderr, "GetCommandLine(): '%s'\n", GetCommandLine()); |
| 148 //fflush(stderr); |
| 149 |
| 150 int rspFileIndex = -1; |
| 151 |
| 152 if (argc < 2) |
| 153 Fallback("too few commmand line args"); |
| 154 |
| 155 for (int i = 1; i < argc; ++i) |
| 156 { |
| 157 if (argv[i][0] == '@') |
| 158 { |
| 159 rspFileIndex = i; |
| 160 break; |
| 161 } |
| 162 } |
| 163 |
| 164 if (rspFileIndex == -1) |
| 165 Fallback("couldn't find a response file in argv"); |
| 166 |
| 167 if (getenv("SUPALINK_DEBUG")) |
| 168 startTime = GetTickCount64(); |
| 169 |
| 170 wstring rsp = SlurpFile(&argv[rspFileIndex][1]); |
| 171 |
| 172 // The first line of this file is all we try to fix. It's a bunch of |
| 173 // quoted space separated items. Simplest thing seems to be replacing " " |
| 174 // with "\n". So, just slurp the file, replace, spit it out to the same |
| 175 // file and continue on our way. |
| 176 |
| 177 // Took about .5s when using the naive .replace loop to replace " " with |
| 178 // "\r\n" so write the silly loop instead. |
| 179 wstring fixed; |
| 180 fixed.reserve(rsp.size() * 2); |
| 181 |
| 182 for (const wchar_t* s = rsp.c_str(); *s;) |
| 183 { |
| 184 if (*s == '"' && *(s + 1) == ' ' && *(s + 2) == '"') |
| 185 { |
| 186 fixed += L"\"\r\n\""; |
| 187 s += 3; |
| 188 } |
| 189 else |
| 190 { |
| 191 fixed += *s++; |
| 192 } |
| 193 } |
| 194 |
| 195 DumpFile(&argv[rspFileIndex][1], fixed); |
| 196 |
| 197 if (getenv("SUPALINK_DEBUG")) |
| 198 { |
| 199 string backupCopy(&argv[rspFileIndex][1]); |
| 200 backupCopy += ".copy"; |
| 201 DumpFile(backupCopy.c_str(), fixed); |
| 202 |
| 203 endTime = GetTickCount64(); |
| 204 |
| 205 fprintf(stdout, |
| 206 " took %.2fs to modify @rsp file\n", |
| 207 (endTime - startTime) / 1000.0); |
| 208 } |
| 209 |
| 210 Fallback(); |
| 211 } |
| OLD | NEW |