aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/win_updater
diff options
context:
space:
mode:
authorJacek Antonelli2009-11-19 04:19:06 -0600
committerJacek Antonelli2009-11-19 04:19:06 -0600
commit1d443b7a94ed6f9ef1d408caef72fcbc0b1ee427 (patch)
treee09ccbc010e326a48fd91ba15b58afd7fb836b3f /linden/indra/win_updater
parentFixed minor formatting issue in MANIFESTO.txt. (diff)
parentFixed CMake setting errors (diff)
downloadmeta-impy-1d443b7a94ed6f9ef1d408caef72fcbc0b1ee427.zip
meta-impy-1d443b7a94ed6f9ef1d408caef72fcbc0b1ee427.tar.gz
meta-impy-1d443b7a94ed6f9ef1d408caef72fcbc0b1ee427.tar.bz2
meta-impy-1d443b7a94ed6f9ef1d408caef72fcbc0b1ee427.tar.xz
Merge remote branch 'mccabe/1.3.0-next' into next
Conflicts: linden/indra/cmake/00-Common.cmake linden/indra/newview/skins/default/xui/de/floater_about.xml linden/indra/newview/skins/default/xui/fr/floater_about.xml linden/indra/newview/skins/default/xui/ja/floater_about.xml linden/indra/newview/skins/default/xui/ko/floater_about.xml linden/indra/newview/skins/default/xui/zh/floater_about.xml linden/install.xml
Diffstat (limited to 'linden/indra/win_updater')
-rw-r--r--linden/indra/win_updater/CMakeLists.txt11
-rw-r--r--linden/indra/win_updater/updater.cpp288
2 files changed, 175 insertions, 124 deletions
diff --git a/linden/indra/win_updater/CMakeLists.txt b/linden/indra/win_updater/CMakeLists.txt
index 6379d7c..dedb7cf 100644
--- a/linden/indra/win_updater/CMakeLists.txt
+++ b/linden/indra/win_updater/CMakeLists.txt
@@ -21,10 +21,15 @@ list(APPEND win_updater_SOURCE_FILES ${win_updater_HEADER_FILES})
21 21
22add_executable(windows-updater WIN32 ${win_updater_SOURCE_FILES}) 22add_executable(windows-updater WIN32 ${win_updater_SOURCE_FILES})
23 23
24target_link_libraries(windows-updater wininet) 24target_link_libraries(windows-updater
25 wininet
26 user32
27 gdi32
28 shell32
29 )
25 30
26set_target_properties(windows-updater 31set_target_properties(windows-updater
27 PROPERTIES 32 PROPERTIES
28 LINK_FLAGS "/NODEFAULTLIB:MSVCRT" 33 LINK_FLAGS "/NODEFAULTLIB:LIBCMT"
29 LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;MSVCRTD\"" 34 LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\""
30 ) 35 )
diff --git a/linden/indra/win_updater/updater.cpp b/linden/indra/win_updater/updater.cpp
index 9d57880..5031270 100644
--- a/linden/indra/win_updater/updater.cpp
+++ b/linden/indra/win_updater/updater.cpp
@@ -17,7 +17,8 @@
17 * There are special exceptions to the terms and conditions of the GPL as 17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception 18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or 19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception 20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 * 22 *
22 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -33,10 +34,19 @@
33// Usage: updater -url <url> 34// Usage: updater -url <url>
34// 35//
35 36
36#include "linden_common.h" 37// We use dangerous fopen, strtok, mbstowcs, sprintf
38// which generates warnings on VC2005.
39// *TODO: Switch to fopen_s, strtok_s, etc.
40#define _CRT_SECURE_NO_DEPRECATE
37 41
38#include <windows.h> 42#include <windows.h>
39#include <wininet.h> 43#include <wininet.h>
44#include <stdio.h>
45#include <string>
46#include <iostream>
47#include <stdexcept>
48#include <sstream>
49#include <fstream>
40 50
41#define BUFSIZE 8192 51#define BUFSIZE 8192
42 52
@@ -44,16 +54,19 @@ int gTotalBytesRead = 0;
44DWORD gTotalBytes = -1; 54DWORD gTotalBytes = -1;
45HWND gWindow = NULL; 55HWND gWindow = NULL;
46WCHAR gProgress[256]; 56WCHAR gProgress[256];
47char* gUpdateURL; 57char* gUpdateURL = NULL;
48 58
49#if _DEBUG 59#if _DEBUG
50FILE* logfile = 0; 60std::ofstream logfile;
61#define DEBUG(expr) logfile << expr << std::endl
62#else
63#define DEBUG(expr) /**/
51#endif 64#endif
52 65
53char* wchars_to_utf8chars(WCHAR* in_chars) 66char* wchars_to_utf8chars(const WCHAR* in_chars)
54{ 67{
55 int tlen = 0; 68 int tlen = 0;
56 WCHAR* twc = in_chars; 69 const WCHAR* twc = in_chars;
57 while (*twc++ != 0) 70 while (*twc++ != 0)
58 { 71 {
59 tlen++; 72 tlen++;
@@ -76,103 +89,128 @@ char* wchars_to_utf8chars(WCHAR* in_chars)
76 return res; 89 return res;
77} 90}
78 91
79int WINAPI get_url_into_file(WCHAR *uri, char *path, int *cancelled) 92class Fetcher
93{
94public:
95 Fetcher(const std::wstring& uri)
96 {
97 // These actions are broken out as separate methods not because it
98 // makes the code clearer, but to avoid triggering AntiVir and
99 // McAfee-GW-Edition virus scanners (DEV-31680).
100 mInet = openInet();
101 mDownload = openUrl(uri);
102 }
103
104 ~Fetcher()
105 {
106 DEBUG("Calling InternetCloseHandle");
107 InternetCloseHandle(mDownload);
108 InternetCloseHandle(mInet);
109 }
110
111 unsigned long read(char* buffer, size_t bufflen) const;
112
113 DWORD getTotalBytes() const
114 {
115 DWORD totalBytes;
116 DWORD sizeof_total_bytes = sizeof(totalBytes);
117 HttpQueryInfo(mDownload, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
118 &totalBytes, &sizeof_total_bytes, NULL);
119 return totalBytes;
120 }
121
122 struct InetError: public std::runtime_error
123 {
124 InetError(const std::string& what): std::runtime_error(what) {}
125 };
126
127private:
128 // We test results from a number of different MS functions with different
129 // return types -- but the common characteristic is that 0 (i.e. (! result))
130 // means an error of some kind.
131 template <typename RESULT>
132 static RESULT check(const std::string& desc, RESULT result)
133 {
134 if (result)
135 {
136 // success, show caller
137 return result;
138 }
139 DWORD err = GetLastError();
140 std::ostringstream out;
141 out << desc << " Failed: " << err;
142 DEBUG(out.str());
143 throw InetError(out.str());
144 }
145
146 HINTERNET openUrl(const std::wstring& uri) const;
147 HINTERNET openInet() const;
148
149 HINTERNET mInet, mDownload;
150};
151
152HINTERNET Fetcher::openInet() const
153{
154 DEBUG("Calling InternetOpen");
155 // Init wininet subsystem
156 return check("InternetOpen",
157 InternetOpen(L"LindenUpdater", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0));
158}
159
160HINTERNET Fetcher::openUrl(const std::wstring& uri) const
161{
162 DEBUG("Calling InternetOpenUrl: " << wchars_to_utf8chars(uri.c_str()));
163 return check("InternetOpenUrl",
164 InternetOpenUrl(mInet, uri.c_str(), NULL, 0, INTERNET_FLAG_NEED_FILE, NULL));
165}
166
167unsigned long Fetcher::read(char* buffer, size_t bufflen) const
168{
169 unsigned long bytes_read = 0;
170 DEBUG("Calling InternetReadFile");
171 check("InternetReadFile",
172 InternetReadFile(mDownload, buffer, bufflen, &bytes_read));
173 return bytes_read;
174}
175
176int WINAPI get_url_into_file(const std::wstring& uri, const std::string& path, int *cancelled)
80{ 177{
81 int success = FALSE; 178 int success = FALSE;
82 *cancelled = FALSE; 179 *cancelled = FALSE;
83 180
84 HINTERNET hinet, hdownload; 181 DEBUG("Opening '" << path << "'");
85 char data[BUFSIZE]; /* Flawfinder: ignore */
86 unsigned long bytes_read;
87
88#if _DEBUG
89 fprintf(logfile,"Opening '%s'\n",path);
90 fflush(logfile);
91#endif
92 182
93 FILE* fp = fopen(path, "wb"); /* Flawfinder: ignore */ 183 FILE* fp = fopen(path.c_str(), "wb"); /* Flawfinder: ignore */
94 184
95 if (!fp) 185 if (!fp)
96 { 186 {
97#if _DEBUG 187 DEBUG("Failed to open '" << path << "'");
98 fprintf(logfile,"Failed to open '%s'\n",path);
99 fflush(logfile);
100#endif
101 return success;
102 }
103
104#if _DEBUG
105 fprintf(logfile,"Calling InternetOpen\n");
106 fflush(logfile);
107#endif
108 // Init wininet subsystem
109 hinet = InternetOpen(L"LindenUpdater", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
110 if (hinet == NULL)
111 {
112 return success; 188 return success;
113 } 189 }
114 190
115#if _DEBUG 191 // Note, ctor can throw, since it uses check() function.
116 fprintf(logfile,"Calling InternetOpenUrl: %s\n",wchars_to_utf8chars(uri)); 192 Fetcher fetcher(uri);
117 fflush(logfile); 193 gTotalBytes = fetcher.getTotalBytes();
118#endif
119 hdownload = InternetOpenUrl(hinet, uri, NULL, 0, INTERNET_FLAG_NEED_FILE, NULL);
120 if (hdownload == NULL)
121 {
122#if _DEBUG
123 DWORD err = GetLastError();
124 fprintf(logfile,"InternetOpenUrl Failed: %d\n",err);
125 fflush(logfile);
126#endif
127 return success;
128 }
129 194
130 DWORD sizeof_total_bytes = sizeof(gTotalBytes); 195/*==========================================================================*|
131 HttpQueryInfo(hdownload, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &gTotalBytes, &sizeof_total_bytes, NULL); 196 // nobody uses total_bytes?!? What's this doing here?
132
133 DWORD total_bytes = 0; 197 DWORD total_bytes = 0;
134 success = InternetQueryDataAvailable(hdownload, &total_bytes, 0, 0); 198 success = check("InternetQueryDataAvailable",
135 if (success == FALSE) 199 InternetQueryDataAvailable(hdownload, &total_bytes, 0, 0));
136 { 200|*==========================================================================*/
137#if _DEBUG
138 DWORD err = GetLastError();
139 fprintf(logfile,"InternetQueryDataAvailable Failed: %d bytes Err:%d\n",total_bytes,err);
140 fflush(logfile);
141#endif
142 return success;
143 }
144 201
145 success = FALSE; 202 success = FALSE;
146 while(!success && !(*cancelled)) 203 while(!success && !(*cancelled))
147 { 204 {
148 MSG msg; 205 char data[BUFSIZE]; /* Flawfinder: ignore */
149 206 unsigned long bytes_read = fetcher.read(data, sizeof(data));
150#if _DEBUG
151 fprintf(logfile,"Calling InternetReadFile\n");
152 fflush(logfile);
153#endif
154 if (!InternetReadFile(hdownload, data, BUFSIZE, &bytes_read))
155 {
156#if _DEBUG
157 fprintf(logfile,"InternetReadFile Failed.\n");
158 fflush(logfile);
159#endif
160 // ...an error occurred
161 return FALSE;
162 }
163 207
164#if _DEBUG
165 if (!bytes_read) 208 if (!bytes_read)
166 { 209 {
167 fprintf(logfile,"InternetReadFile Read 0 bytes.\n"); 210 DEBUG("InternetReadFile Read " << bytes_read << " bytes.");
168 fflush(logfile);
169 } 211 }
170#endif
171 212
172#if _DEBUG 213 DEBUG("Reading Data, bytes_read = " << bytes_read);
173 fprintf(logfile,"Reading Data, bytes_read = %d\n",bytes_read);
174 fflush(logfile);
175#endif
176 214
177 if (bytes_read == 0) 215 if (bytes_read == 0)
178 { 216 {
@@ -195,25 +233,17 @@ int WINAPI get_url_into_file(WCHAR *uri, char *path, int *cancelled)
195 233
196 } 234 }
197 235
198#if _DEBUG 236 DEBUG("Calling InvalidateRect");
199 fprintf(logfile,"Calling InvalidateRect\n");
200 fflush(logfile);
201#endif
202 237
203 // Mark the window as needing redraw (of the whole thing) 238 // Mark the window as needing redraw (of the whole thing)
204 InvalidateRect(gWindow, NULL, TRUE); 239 InvalidateRect(gWindow, NULL, TRUE);
205 240
206 // Do the redraw 241 // Do the redraw
207#if _DEBUG 242 DEBUG("Calling UpdateWindow");
208 fprintf(logfile,"Calling UpdateWindow\n");
209 fflush(logfile);
210#endif
211 UpdateWindow(gWindow); 243 UpdateWindow(gWindow);
212 244
213#if _DEBUG 245 DEBUG("Calling PeekMessage");
214 fprintf(logfile,"Calling PeekMessage\n"); 246 MSG msg;
215 fflush(logfile);
216#endif
217 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 247 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
218 { 248 {
219 TranslateMessage(&msg); 249 TranslateMessage(&msg);
@@ -227,15 +257,7 @@ int WINAPI get_url_into_file(WCHAR *uri, char *path, int *cancelled)
227 } 257 }
228 } 258 }
229 259
230#if _DEBUG
231 fprintf(logfile,"Calling InternetCloseHandle\n");
232 fclose(logfile);
233#endif
234
235 fclose(fp); 260 fclose(fp);
236 InternetCloseHandle(hdownload);
237 InternetCloseHandle(hinet);
238
239 return success; 261 return success;
240} 262}
241 263
@@ -301,9 +323,8 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
301 char* argv[MAX_ARGS]; /* Flawfinder: ignore */ 323 char* argv[MAX_ARGS]; /* Flawfinder: ignore */
302 324
303#if _DEBUG 325#if _DEBUG
304 logfile = _wfopen(TEXT("updater.log"),TEXT("wt")); 326 logfile.open("updater.log", std::ios_base::out);
305 fprintf(logfile,"Parsing command arguments\n"); 327 DEBUG("Parsing command arguments");
306 fflush(logfile);
307#endif 328#endif
308 329
309 char *token = NULL; 330 char *token = NULL;
@@ -341,10 +362,7 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
341 // Process command line arguments 362 // Process command line arguments
342 // 363 //
343 364
344#if _DEBUG 365 DEBUG("Processing command arguments");
345 fprintf(logfile,"Processing command arguments\n");
346 fflush(logfile);
347#endif
348 366
349 // 367 //
350 // Parse the command line arguments 368 // Parse the command line arguments
@@ -352,8 +370,7 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
352 int parse_args_result = parse_args(argc, argv); 370 int parse_args_result = parse_args(argc, argv);
353 371
354 WNDCLASSEX wndclassex = { 0 }; 372 WNDCLASSEX wndclassex = { 0 };
355 DEVMODE dev_mode = { 0 }; 373 //DEVMODE dev_mode = { 0 };
356 char update_exec_path[MAX_PATH]; /* Flawfinder: ignore */
357 374
358 const int WINDOW_WIDTH = 250; 375 const int WINDOW_WIDTH = 250;
359 const int WINDOW_HEIGHT = 100; 376 const int WINDOW_HEIGHT = 100;
@@ -371,7 +388,7 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
371 RegisterClassEx(&wndclassex); 388 RegisterClassEx(&wndclassex);
372 389
373 // Get the size of the screen 390 // Get the size of the screen
374 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode); 391 //EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
375 392
376 gWindow = CreateWindowEx(NULL, win_class_name, 393 gWindow = CreateWindowEx(NULL, win_class_name,
377 L"Second Life Updater", 394 L"Second Life Updater",
@@ -402,26 +419,34 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
402 } 419 }
403 420
404 // Can't feed GetTempPath into GetTempFile directly 421 // Can't feed GetTempPath into GetTempFile directly
405 if (0 == GetTempPathA(MAX_PATH - 14, update_exec_path)) 422 char temp_path[MAX_PATH]; /* Flawfinder: ignore */
423 if (0 == GetTempPathA(sizeof(temp_path), temp_path))
406 { 424 {
407 MessageBox(gWindow, L"Problem with GetTempPath()", 425 MessageBox(gWindow, L"Problem with GetTempPath()",
408 L"Error", MB_OK); 426 L"Error", MB_OK);
409 return 1; 427 return 1;
410 } 428 }
411 strcat(update_exec_path, "Second_Life_Updater.exe"); 429 std::string update_exec_path(temp_path);
430 update_exec_path.append("Second_Life_Updater.exe");
412 431
413 WCHAR update_uri[4096]; 432 WCHAR update_uri[4096];
414 mbstowcs(update_uri, gUpdateURL, 4096); 433 mbstowcs(update_uri, gUpdateURL, sizeof(update_uri));
415 434
416 int success = 0; 435 int success = 0;
417 int cancelled = 0; 436 int cancelled = 0;
418 437
419 // Actually do the download 438 // Actually do the download
420#if _DEBUG 439 try
421 fprintf(logfile,"Calling get_url_into_file\n"); 440 {
422 fflush(logfile); 441 DEBUG("Calling get_url_into_file");
423#endif 442 success = get_url_into_file(update_uri, update_exec_path, &cancelled);
424 success = get_url_into_file(update_uri, update_exec_path, &cancelled); 443 }
444 catch (const Fetcher::InetError& e)
445 {
446 (void)e;
447 success = FALSE;
448 DEBUG("Caught: " << e.what());
449 }
425 450
426 // WinInet can't tell us if we got a 404 or not. Therefor, we check 451 // WinInet can't tell us if we got a 404 or not. Therefor, we check
427 // for the size of the downloaded file, and assume that our installer 452 // for the size of the downloaded file, and assume that our installer
@@ -461,10 +486,31 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
461 // L"Download Complete", 486 // L"Download Complete",
462 // MB_OK); 487 // MB_OK);
463 488
464 if (32 >= (int) ShellExecuteA(gWindow, "open", update_exec_path, NULL, 489/*==========================================================================*|
490 // DEV-31680: ShellExecuteA() causes McAfee-GW-Edition and AntiVir
491 // scanners to flag this executable as a probable virus vector.
492 // Less than or equal to 32 means failure
493 if (32 >= (int) ShellExecuteA(gWindow, "open", update_exec_path.c_str(), NULL,
465 "C:\\", SW_SHOWDEFAULT)) 494 "C:\\", SW_SHOWDEFAULT))
495|*==========================================================================*/
496 // from http://msdn.microsoft.com/en-us/library/ms682512(VS.85).aspx
497 STARTUPINFOA si;
498 PROCESS_INFORMATION pi;
499 ZeroMemory(&si, sizeof(si));
500 si.cb = sizeof(si);
501 ZeroMemory(&pi, sizeof(pi));
502
503 if (! CreateProcessA(update_exec_path.c_str(), // executable file
504 NULL, // command line
505 NULL, // process cannot be inherited
506 NULL, // thread cannot be inherited
507 FALSE, // do not inherit existing handles
508 0, // process creation flags
509 NULL, // inherit parent's environment
510 NULL, // inherit parent's current dir
511 &si, // STARTUPINFO
512 &pi)) // PROCESS_INFORMATION
466 { 513 {
467 // Less than or equal to 32 means failure
468 MessageBox(gWindow, L"Update failed. Please try again later.", NULL, MB_OK); 514 MessageBox(gWindow, L"Update failed. Please try again later.", NULL, MB_OK);
469 return 1; 515 return 1;
470 } 516 }