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 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.
| |
16 exit(1); | |
17 } | |
18 | |
19 static string ErrorMessageToString(DWORD err) { | |
M-A Ruel
2011/09/27 23:21:33
wstring
scottmg
2011/09/28 00:19:38
Done.
| |
20 LPTSTR msg_buf = NULL; | |
M-A Ruel
2011/09/27 23:21:33
wchar_t*
scottmg
2011/09/28 00:19:38
Done.
| |
21 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, | |
22 NULL, | |
23 err, | |
24 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
25 (LPTSTR)&msg_buf, | |
M-A Ruel
2011/09/27 23:21:33
reinterpret_cast<>()
scottmg
2011/09/28 00:19:38
Done.
| |
26 0, | |
27 NULL); | |
28 string ret(msg_buf); | |
29 LocalFree(msg_buf); | |
30 return ret; | |
31 } | |
32 | |
33 | |
34 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.
| |
35 if (msg) { | |
36 fprintf(stdout, | |
M-A Ruel
2011/09/27 23:21:33
same
scottmg
2011/09/28 00:19:38
Done.
| |
37 "supalink failed (%s), trying to fallback to standard link.\n", | |
38 msg); | |
39 fprintf(stdout, "Original command line: %s\n", GetCommandLine()); | |
40 fflush(stdout); | |
41 } | |
42 | |
43 STARTUPINFO startup_info = { sizeof(STARTUPINFO) }; | |
44 PROCESS_INFORMATION process_info; | |
45 DWORD exit_code; | |
46 | |
47 string orig_cmd(GetCommandLine()); | |
48 | |
49 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.
| |
50 "link.exe\" ", | |
51 "LINK.EXE\" ", | |
52 "link.EXE\" ", | |
53 "link\" ", | |
54 "LINK\" ", | |
55 "link.exe ", | |
56 "LINK.EXE ", | |
57 "link.EXE ", | |
58 "link ", | |
59 "LINK ", | |
60 }; | |
61 string cmd; | |
62 string replace_with = "link.exe.supalink_orig.exe"; | |
63 for (size_t i = 0; i < sizeof(search_for) / sizeof(search_for[0]); ++i) { | |
64 string linkexe = search_for[i]; | |
65 string::size_type at = orig_cmd.find(linkexe, 0); | |
66 if (at == string::npos) | |
67 continue; | |
68 if (linkexe[linkexe.size() - 2] == '"') | |
69 replace_with += "\" "; | |
70 else | |
71 replace_with += " "; | |
72 cmd = orig_cmd.replace(at, linkexe.size(), replace_with); | |
73 break; | |
74 } | |
75 if (cmd == "") { | |
76 fprintf(stdout, "Original run '%s'\n", orig_cmd.c_str()); | |
77 Fatal("Couldn't find link.exe (or similar) in command line"); | |
78 } | |
79 | |
80 if (getenv("SUPALINK_DEBUG")) { | |
81 fprintf(stdout, " running '%s'\n", cmd.c_str()); | |
82 fflush(stdout); | |
83 } | |
84 if (!CreateProcess(NULL, | |
85 (LPSTR)cmd.c_str(), | |
M-A Ruel
2011/09/27 23:21:33
same
scottmg
2011/09/28 00:19:38
Done.
| |
86 NULL, | |
87 NULL, | |
88 TRUE, | |
89 0, | |
90 NULL, | |
91 NULL, | |
92 &startup_info, &process_info)) { | |
93 string error = ErrorMessageToString(GetLastError()); | |
94 Fatal(error.c_str()); | |
95 } | |
96 WaitForSingleObject(process_info.hProcess, INFINITE); | |
97 GetExitCodeProcess(process_info.hProcess, &exit_code); | |
98 CloseHandle(process_info.hProcess); | |
99 CloseHandle(process_info.hThread); | |
100 exit(exit_code); | |
101 } | |
102 | |
103 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.
| |
104 FILE* f = fopen(path, "rb, ccs=UNICODE"); | |
105 if (!f) Fallback("couldn't read file"); | |
106 fseek(f, 0, SEEK_END); | |
107 long len = ftell(f); | |
108 rewind(f); | |
109 wchar_t* data = reinterpret_cast<wchar_t*>(malloc(len)); | |
110 fread(data, 1, len, f); | |
111 fclose(f); | |
112 wstring ret(data, len/sizeof(wchar_t)); | |
113 free(data); | |
114 return ret; | |
115 } | |
116 | |
117 void DumpFile(const char* path, wstring& contents) { | |
118 FILE* f = fopen(path, "wb, ccs=UTF-16LE"); | |
119 if (!f) Fallback("couldn't write file"); | |
120 | |
121 fwrite(contents.c_str(), sizeof(wchar_t), contents.size(), f); | |
122 if (ferror(f)) Fatal("failed during response rewrite"); | |
123 fclose(f); | |
124 } | |
125 | |
126 // Input command line is assumed to be of the form: | |
127 // | |
128 // link.exe @C:\src\...\RSP00003045884740.rsp /NOLOGO /ERRORREPORT:PROMPT | |
129 // | |
130 // Specifically, we parse & hack the contents of argv[1] and pass the rest | |
131 // onwards. | |
132 int main(int argc, char** argv) { | |
133 ULONGLONG start_time = 0, end_time; | |
134 | |
135 int rsp_file_index = -1; | |
136 | |
137 if (argc < 2) | |
138 Fallback("too few commmand line args"); | |
139 | |
140 for (int i = 1; i < argc; ++i) { | |
141 if (argv[i][0] == '@') { | |
142 rsp_file_index = i; | |
143 break; | |
144 } | |
145 } | |
146 | |
147 if (rsp_file_index == -1) | |
148 Fallback("couldn't find a response file in argv"); | |
149 | |
150 if (getenv("SUPALINK_DEBUG")) | |
151 start_time = GetTickCount64(); | |
152 | |
153 wstring rsp = SlurpFile(&argv[rsp_file_index][1]); | |
154 | |
155 // The first line of this file is all we try to fix. It's a bunch of | |
156 // quoted space separated items. Simplest thing seems to be replacing " " | |
157 // with "\n". So, just slurp the file, replace, spit it out to the same | |
158 // file and continue on our way. | |
159 | |
160 // Took about .5s when using the naive .replace loop to replace " " with | |
161 // "\r\n" so write the silly loop instead. | |
162 wstring fixed; | |
163 fixed.reserve(rsp.size() * 2); | |
164 | |
165 for (const wchar_t* s = rsp.c_str(); *s;) { | |
166 if (*s == '"' && *(s + 1) == ' ' && *(s + 2) == '"') { | |
167 fixed += L"\"\r\n\""; | |
168 s += 3; | |
169 } else { | |
170 fixed += *s++; | |
171 } | |
172 } | |
173 | |
174 DumpFile(&argv[rsp_file_index][1], fixed); | |
175 | |
176 if (getenv("SUPALINK_DEBUG")) { | |
177 string backup_copy(&argv[rsp_file_index][1]); | |
178 backup_copy += ".copy"; | |
179 DumpFile(backup_copy.c_str(), fixed); | |
180 | |
181 end_time = GetTickCount64(); | |
182 | |
183 fprintf(stdout, | |
184 " took %.2fs to modify @rsp file\n", | |
185 (end_time - start_time) / 1000.0); | |
186 } | |
187 | |
188 Fallback(); | |
189 } | |
OLD | NEW |