aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/win_updater
diff options
context:
space:
mode:
authorJacek Antonelli2009-05-24 02:59:02 -0500
committerJacek Antonelli2009-05-24 02:59:08 -0500
commit811454f47ea1f3c5cb8971f0fed0959b18bd0747 (patch)
tree1b8689df2dc8857cdc5a956a5233d5bf94b5c8d7 /linden/indra/win_updater
parentSecond Life viewer sources 1.23.0-RC (diff)
downloadmeta-impy-811454f47ea1f3c5cb8971f0fed0959b18bd0747.zip
meta-impy-811454f47ea1f3c5cb8971f0fed0959b18bd0747.tar.gz
meta-impy-811454f47ea1f3c5cb8971f0fed0959b18bd0747.tar.bz2
meta-impy-811454f47ea1f3c5cb8971f0fed0959b18bd0747.tar.xz
Second Life viewer sources 1.23.1-RC
Diffstat (limited to 'linden/indra/win_updater')
-rw-r--r--linden/indra/win_updater/updater.cpp273
1 files changed, 157 insertions, 116 deletions
diff --git a/linden/indra/win_updater/updater.cpp b/linden/indra/win_updater/updater.cpp
index e7adaf3..3937351 100644
--- a/linden/indra/win_updater/updater.cpp
+++ b/linden/indra/win_updater/updater.cpp
@@ -42,6 +42,11 @@
42#include <windows.h> 42#include <windows.h>
43#include <wininet.h> 43#include <wininet.h>
44#include <stdio.h> 44#include <stdio.h>
45#include <string>
46#include <iostream>
47#include <stdexcept>
48#include <sstream>
49#include <fstream>
45 50
46#define BUFSIZE 8192 51#define BUFSIZE 8192
47 52
@@ -52,13 +57,16 @@ WCHAR gProgress[256];
52char* gUpdateURL = NULL; 57char* gUpdateURL = NULL;
53 58
54#if _DEBUG 59#if _DEBUG
55FILE* logfile = 0; 60std::ofstream logfile;
61#define DEBUG(expr) logfile << expr << std::endl
62#else
63#define DEBUG(expr) /**/
56#endif 64#endif
57 65
58char* wchars_to_utf8chars(WCHAR* in_chars) 66char* wchars_to_utf8chars(const WCHAR* in_chars)
59{ 67{
60 int tlen = 0; 68 int tlen = 0;
61 WCHAR* twc = in_chars; 69 const WCHAR* twc = in_chars;
62 while (*twc++ != 0) 70 while (*twc++ != 0)
63 { 71 {
64 tlen++; 72 tlen++;
@@ -81,103 +89,128 @@ char* wchars_to_utf8chars(WCHAR* in_chars)
81 return res; 89 return res;
82} 90}
83 91
84int 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)
85{ 177{
86 int success = FALSE; 178 int success = FALSE;
87 *cancelled = FALSE; 179 *cancelled = FALSE;
88 180
89 HINTERNET hinet, hdownload; 181 DEBUG("Opening '" << path << "'");
90 char data[BUFSIZE]; /* Flawfinder: ignore */
91 unsigned long bytes_read;
92
93#if _DEBUG
94 fprintf(logfile,"Opening '%s'\n",path);
95 fflush(logfile);
96#endif
97 182
98 FILE* fp = fopen(path, "wb"); /* Flawfinder: ignore */ 183 FILE* fp = fopen(path.c_str(), "wb"); /* Flawfinder: ignore */
99 184
100 if (!fp) 185 if (!fp)
101 { 186 {
102#if _DEBUG 187 DEBUG("Failed to open '" << path << "'");
103 fprintf(logfile,"Failed to open '%s'\n",path);
104 fflush(logfile);
105#endif
106 return success;
107 }
108
109#if _DEBUG
110 fprintf(logfile,"Calling InternetOpen\n");
111 fflush(logfile);
112#endif
113 // Init wininet subsystem
114 hinet = InternetOpen(L"LindenUpdater", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
115 if (hinet == NULL)
116 {
117 return success; 188 return success;
118 } 189 }
119 190
120#if _DEBUG 191 // Note, ctor can throw, since it uses check() function.
121 fprintf(logfile,"Calling InternetOpenUrl: %s\n",wchars_to_utf8chars(uri)); 192 Fetcher fetcher(uri);
122 fflush(logfile); 193 gTotalBytes = fetcher.getTotalBytes();
123#endif
124 hdownload = InternetOpenUrl(hinet, uri, NULL, 0, INTERNET_FLAG_NEED_FILE, NULL);
125 if (hdownload == NULL)
126 {
127#if _DEBUG
128 DWORD err = GetLastError();
129 fprintf(logfile,"InternetOpenUrl Failed: %d\n",err);
130 fflush(logfile);
131#endif
132 return success;
133 }
134 194
135 DWORD sizeof_total_bytes = sizeof(gTotalBytes); 195/*==========================================================================*|
136 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?
137
138 DWORD total_bytes = 0; 197 DWORD total_bytes = 0;
139 success = InternetQueryDataAvailable(hdownload, &total_bytes, 0, 0); 198 success = check("InternetQueryDataAvailable",
140 if (success == FALSE) 199 InternetQueryDataAvailable(hdownload, &total_bytes, 0, 0));
141 { 200|*==========================================================================*/
142#if _DEBUG
143 DWORD err = GetLastError();
144 fprintf(logfile,"InternetQueryDataAvailable Failed: %d bytes Err:%d\n",total_bytes,err);
145 fflush(logfile);
146#endif
147 return success;
148 }
149 201
150 success = FALSE; 202 success = FALSE;
151 while(!success && !(*cancelled)) 203 while(!success && !(*cancelled))
152 { 204 {
153 MSG msg; 205 char data[BUFSIZE]; /* Flawfinder: ignore */
154 206 unsigned long bytes_read = fetcher.read(data, sizeof(data));
155#if _DEBUG
156 fprintf(logfile,"Calling InternetReadFile\n");
157 fflush(logfile);
158#endif
159 if (!InternetReadFile(hdownload, data, BUFSIZE, &bytes_read))
160 {
161#if _DEBUG
162 fprintf(logfile,"InternetReadFile Failed.\n");
163 fflush(logfile);
164#endif
165 // ...an error occurred
166 return FALSE;
167 }
168 207
169#if _DEBUG
170 if (!bytes_read) 208 if (!bytes_read)
171 { 209 {
172 fprintf(logfile,"InternetReadFile Read 0 bytes.\n"); 210 DEBUG("InternetReadFile Read " << bytes_read << " bytes.");
173 fflush(logfile);
174 } 211 }
175#endif
176 212
177#if _DEBUG 213 DEBUG("Reading Data, bytes_read = " << bytes_read);
178 fprintf(logfile,"Reading Data, bytes_read = %d\n",bytes_read);
179 fflush(logfile);
180#endif
181 214
182 if (bytes_read == 0) 215 if (bytes_read == 0)
183 { 216 {
@@ -200,25 +233,17 @@ int WINAPI get_url_into_file(WCHAR *uri, char *path, int *cancelled)
200 233
201 } 234 }
202 235
203#if _DEBUG 236 DEBUG("Calling InvalidateRect");
204 fprintf(logfile,"Calling InvalidateRect\n");
205 fflush(logfile);
206#endif
207 237
208 // Mark the window as needing redraw (of the whole thing) 238 // Mark the window as needing redraw (of the whole thing)
209 InvalidateRect(gWindow, NULL, TRUE); 239 InvalidateRect(gWindow, NULL, TRUE);
210 240
211 // Do the redraw 241 // Do the redraw
212#if _DEBUG 242 DEBUG("Calling UpdateWindow");
213 fprintf(logfile,"Calling UpdateWindow\n");
214 fflush(logfile);
215#endif
216 UpdateWindow(gWindow); 243 UpdateWindow(gWindow);
217 244
218#if _DEBUG 245 DEBUG("Calling PeekMessage");
219 fprintf(logfile,"Calling PeekMessage\n"); 246 MSG msg;
220 fflush(logfile);
221#endif
222 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 247 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
223 { 248 {
224 TranslateMessage(&msg); 249 TranslateMessage(&msg);
@@ -232,15 +257,7 @@ int WINAPI get_url_into_file(WCHAR *uri, char *path, int *cancelled)
232 } 257 }
233 } 258 }
234 259
235#if _DEBUG
236 fprintf(logfile,"Calling InternetCloseHandle\n");
237 fclose(logfile);
238#endif
239
240 fclose(fp); 260 fclose(fp);
241 InternetCloseHandle(hdownload);
242 InternetCloseHandle(hinet);
243
244 return success; 261 return success;
245} 262}
246 263
@@ -306,9 +323,8 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
306 char* argv[MAX_ARGS]; /* Flawfinder: ignore */ 323 char* argv[MAX_ARGS]; /* Flawfinder: ignore */
307 324
308#if _DEBUG 325#if _DEBUG
309 logfile = _wfopen(TEXT("updater.log"),TEXT("wt")); 326 logfile.open("updater.log", std::ios_base::out);
310 fprintf(logfile,"Parsing command arguments\n"); 327 DEBUG("Parsing command arguments");
311 fflush(logfile);
312#endif 328#endif
313 329
314 char *token = NULL; 330 char *token = NULL;
@@ -346,10 +362,7 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
346 // Process command line arguments 362 // Process command line arguments
347 // 363 //
348 364
349#if _DEBUG 365 DEBUG("Processing command arguments");
350 fprintf(logfile,"Processing command arguments\n");
351 fflush(logfile);
352#endif
353 366
354 // 367 //
355 // Parse the command line arguments 368 // Parse the command line arguments
@@ -358,7 +371,6 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
358 371
359 WNDCLASSEX wndclassex = { 0 }; 372 WNDCLASSEX wndclassex = { 0 };
360 //DEVMODE dev_mode = { 0 }; 373 //DEVMODE dev_mode = { 0 };
361 char update_exec_path[MAX_PATH]; /* Flawfinder: ignore */
362 374
363 const int WINDOW_WIDTH = 250; 375 const int WINDOW_WIDTH = 250;
364 const int WINDOW_HEIGHT = 100; 376 const int WINDOW_HEIGHT = 100;
@@ -407,26 +419,34 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
407 } 419 }
408 420
409 // Can't feed GetTempPath into GetTempFile directly 421 // Can't feed GetTempPath into GetTempFile directly
410 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))
411 { 424 {
412 MessageBox(gWindow, L"Problem with GetTempPath()", 425 MessageBox(gWindow, L"Problem with GetTempPath()",
413 L"Error", MB_OK); 426 L"Error", MB_OK);
414 return 1; 427 return 1;
415 } 428 }
416 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");
417 431
418 WCHAR update_uri[4096]; 432 WCHAR update_uri[4096];
419 mbstowcs(update_uri, gUpdateURL, 4096); 433 mbstowcs(update_uri, gUpdateURL, sizeof(update_uri));
420 434
421 int success = 0; 435 int success = 0;
422 int cancelled = 0; 436 int cancelled = 0;
423 437
424 // Actually do the download 438 // Actually do the download
425#if _DEBUG 439 try
426 fprintf(logfile,"Calling get_url_into_file\n"); 440 {
427 fflush(logfile); 441 DEBUG("Calling get_url_into_file");
428#endif 442 success = get_url_into_file(update_uri, update_exec_path, &cancelled);
429 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 }
430 450
431 // 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
432 // 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
@@ -466,10 +486,31 @@ WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nSho
466 // L"Download Complete", 486 // L"Download Complete",
467 // MB_OK); 487 // MB_OK);
468 488
469 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,
470 "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
471 { 513 {
472 // Less than or equal to 32 means failure
473 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);
474 return 1; 515 return 1;
475 } 516 }