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 { | |
jam
2011/09/27 22:10:34
nit: brace bracket after function, see style guide
| |
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; | |
jam
2011/09/27 22:10:34
msg_buf (see style guide)
| |
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); | |
jam
2011/09/27 22:10:34
use reinterpret_cast (see style guide)
| |
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 |