aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/win_updater/updater.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/win_updater/updater.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/win_updater/updater.cpp')
-rw-r--r--linden/indra/win_updater/updater.cpp546
1 files changed, 546 insertions, 0 deletions
diff --git a/linden/indra/win_updater/updater.cpp b/linden/indra/win_updater/updater.cpp
new file mode 100644
index 0000000..20e41a8
--- /dev/null
+++ b/linden/indra/win_updater/updater.cpp
@@ -0,0 +1,546 @@
1/**
2 * @file updater.cpp
3 * @brief Windows auto-updater
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28//
29// Usage: updater -userserver <server> [-name <window_title>] [-program <program_name>] [-silent]
30//
31
32#include <windows.h>
33#include <wininet.h>
34
35#include <stdio.h>
36#include "llfile.h"
37
38#define BUFSIZE 8192
39
40int gTotalBytesRead = 0;
41HWND gWindow = NULL;
42WCHAR gProgress[256];
43char* gUserServer;
44char* gProgramName;
45char* gProductName;
46bool gIsSilent;
47
48#if _DEBUG
49FILE* logfile = 0;
50#endif
51
52char* wchars_to_utf8chars(WCHAR* in_chars)
53{
54 int tlen = 0;
55 WCHAR* twc = in_chars;
56 while (*twc++ != 0)
57 {
58 tlen++;
59 }
60 char* outchars = new char[tlen];
61 char* res = outchars;
62 for (int i=0; i<tlen; i++)
63 {
64 int cur_char = (int)(*in_chars++);
65 if (cur_char < 0x80)
66 {
67 *outchars++ = (char)cur_char;
68 }
69 else
70 {
71 *outchars++ = '?';
72 }
73 }
74 *outchars = 0;
75 return res;
76}
77
78int WINAPI get_url_into_file(WCHAR *uri, char *path, int *cancelled)
79{
80 int success = FALSE;
81 *cancelled = FALSE;
82
83 HINTERNET hinet, hdownload;
84 char data[BUFSIZE];
85 unsigned long bytes_read;
86
87#if _DEBUG
88 fprintf(logfile,"Opening '%s'\n",path);
89 fflush(logfile);
90#endif
91
92 FILE *fp = fopen(path, "wb");
93
94 if (!fp)
95 {
96#if _DEBUG
97 fprintf(logfile,"Failed to open '%s'\n",path);
98 fflush(logfile);
99#endif
100 return success;
101 }
102
103#if _DEBUG
104 fprintf(logfile,"Calling InternetOpen\n");
105 fflush(logfile);
106#endif
107 // Init wininet subsystem
108 hinet = InternetOpen(L"LindenUpdater", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
109 if (hinet == NULL)
110 {
111 return success;
112 }
113
114#if _DEBUG
115 fprintf(logfile,"Calling InternetOpenUrl: %s\n",wchars_to_utf8chars(uri));
116 fflush(logfile);
117#endif
118 hdownload = InternetOpenUrl(hinet, uri, NULL, 0, INTERNET_FLAG_NEED_FILE, NULL);
119 if (hdownload == NULL)
120 {
121#if _DEBUG
122 DWORD err = GetLastError();
123 fprintf(logfile,"InternetOpenUrl Failed: %d\n",err);
124 fflush(logfile);
125#endif
126 return success;
127 }
128
129 DWORD total_bytes = 0;
130 success = InternetQueryDataAvailable(hdownload, &total_bytes, 0, 0);
131 if (success == FALSE)
132 {
133#if _DEBUG
134 DWORD err = GetLastError();
135 fprintf(logfile,"InternetQueryDataAvailable Failed: %d bytes\n",total_bytes);
136 fflush(logfile);
137#endif
138 return success;
139 }
140
141 success = FALSE;
142 while(!success && !(*cancelled))
143 {
144 MSG msg;
145
146#if _DEBUG
147 fprintf(logfile,"Calling InternetReadFile\n");
148 fflush(logfile);
149#endif
150 if (!InternetReadFile(hdownload, data, BUFSIZE, &bytes_read))
151 {
152#if _DEBUG
153 fprintf(logfile,"InternetReadFile Failed.\n");
154 fflush(logfile);
155#endif
156 // ...an error occurred
157 return FALSE;
158 }
159
160#if _DEBUG
161 if (!bytes_read)
162 {
163 fprintf(logfile,"InternetReadFile Read 0 bytes.\n");
164 fflush(logfile);
165 }
166#endif
167
168 if (!data)
169 {
170#if _DEBUG
171 fprintf(logfile,"InternetReadFile Returned NULL data, bytes_read = %d.\n",bytes_read);
172 fflush(logfile);
173#endif
174 // ...an error occurred
175 return FALSE;
176 }
177
178#if _DEBUG
179 fprintf(logfile,"Reading Data, bytes_read = %d\n",bytes_read);
180 fflush(logfile);
181#endif
182
183 if (bytes_read == 0)
184 {
185 // If InternetFileRead returns TRUE AND bytes_read == 0
186 // we've successfully downloaded the entire file
187 wsprintf(gProgress, L"Download complete.");
188 success = TRUE;
189 }
190 else
191 {
192 // write what we've got, then continue
193 fwrite(data, sizeof(char), bytes_read, fp);
194
195 gTotalBytesRead += int(bytes_read);
196
197 wsprintf(gProgress, L"Downloaded: %dK", gTotalBytesRead / 1024);
198 }
199
200#if _DEBUG
201 fprintf(logfile,"Calling InvalidateRect\n");
202 fflush(logfile);
203#endif
204
205 // Mark the window as needing redraw (of the whole thing)
206 InvalidateRect(gWindow, NULL, TRUE);
207
208 // Do the redraw
209#if _DEBUG
210 fprintf(logfile,"Calling UpdateWindow\n");
211 fflush(logfile);
212#endif
213 UpdateWindow(gWindow);
214
215#if _DEBUG
216 fprintf(logfile,"Calling PeekMessage\n");
217 fflush(logfile);
218#endif
219 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
220 {
221 TranslateMessage(&msg);
222 DispatchMessage(&msg);
223
224 if (msg.message == WM_QUIT)
225 {
226 // bail out, user cancelled
227 *cancelled = TRUE;
228 }
229 }
230 }
231
232#if _DEBUG
233 fprintf(logfile,"Calling InternetCloseHandle\n");
234 fclose(logfile);
235#endif
236
237 fclose(fp);
238 InternetCloseHandle(hdownload);
239 InternetCloseHandle(hinet);
240
241 return success;
242}
243
244LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
245{
246 HDC hdc; // Drawing context
247 PAINTSTRUCT ps;
248
249 switch(message)
250 {
251 case WM_PAINT:
252 {
253 hdc = BeginPaint(hwnd, &ps);
254
255 RECT rect;
256 GetClientRect(hwnd, &rect);
257 DrawText(hdc, gProgress, -1, &rect,
258 DT_SINGLELINE | DT_CENTER | DT_VCENTER);
259
260 EndPaint(hwnd, &ps);
261 return 0;
262 }
263 case WM_CLOSE:
264 case WM_DESTROY:
265 // Get out of full screen
266 // full_screen_mode(false);
267 PostQuitMessage(0);
268 return 0;
269 }
270 return DefWindowProc(hwnd, message, wparam, lparam);
271}
272
273#define win_class_name L"FullScreen"
274#define UPDATE_URIBASE L"http://secondlife.com/update.php?userserver="
275
276int parse_args(int argc, char **argv)
277{
278 // Check for old-type arguments.
279 if (2 == argc)
280 {
281 gUserServer = argv[1];
282 return 0;
283 }
284
285 int j;
286
287 for (j = 1; j < argc; j++)
288 {
289 if ((!strcmp(argv[j], "-userserver")) && (++j < argc))
290 {
291 gUserServer = argv[j];
292 }
293 else if ((!strcmp(argv[j], "-name")) && (++j < argc))
294 {
295 gProductName = argv[j];
296 }
297 else if ((!strcmp(argv[j], "-program")) && (++j < argc))
298 {
299 gProgramName = argv[j];
300 }
301 else if (!strcmp(argv[j], "-silent"))
302 {
303 gIsSilent = true;
304 }
305 }
306
307 // If nothing was set, let the caller know.
308 if (!gUserServer && !gProductName && !gProgramName && !gIsSilent)
309 {
310 return 1;
311 }
312 return 0;
313}
314
315int WINAPI
316WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
317{
318 // Parse the command line.
319 LPSTR cmd_line_including_exe_name = GetCommandLineA();
320
321 const int MAX_ARGS = 100;
322 int argc = 0;
323 char *argv[MAX_ARGS];
324
325#if _DEBUG
326 logfile = _wfopen(TEXT("updater.log"),TEXT("wt"));
327 fprintf(logfile,"Parsing command arguments\n");
328 fflush(logfile);
329#endif
330
331 char *token = NULL;
332 if( cmd_line_including_exe_name[0] == '\"' )
333 {
334 // Exe name is enclosed in quotes
335 token = strtok( cmd_line_including_exe_name, "\"" );
336 argv[argc++] = token;
337 token = strtok( NULL, " \t," );
338 }
339 else
340 {
341 // Exe name is not enclosed in quotes
342 token = strtok( cmd_line_including_exe_name, " \t," );
343 }
344
345 while( (token != NULL) && (argc < MAX_ARGS) )
346 {
347 argv[argc++] = token;
348 /* Get next token: */
349 if (*(token + strlen(token) + 1) == '\"')
350 {
351 token = strtok( NULL, "\"");
352 }
353 else
354 {
355 token = strtok( NULL, " \t," );
356 }
357 }
358
359 gUserServer = NULL;
360 gProgramName = NULL;
361 gProductName = NULL;
362 gIsSilent = false;
363
364 /////////////////////////////////////////
365 //
366 // Process command line arguments
367 //
368
369#if _DEBUG
370 fprintf(logfile,"Processing command arguments\n");
371 fflush(logfile);
372#endif
373
374 //
375 // Parse the command line arguments
376 //
377 int parse_args_result = parse_args(argc, argv);
378 WCHAR window_title[2048];
379 if (gProductName)
380 {
381 mbstowcs(window_title, gProductName, 2048);
382 wcscat(window_title, L" Updater");
383 }
384 else
385 {
386 mbstowcs(window_title, "Second Life Updater", 2048);
387 }
388
389 WNDCLASSEX wndclassex = { 0 };
390 DEVMODE dev_mode = { 0 };
391 char update_exec_path[MAX_PATH];
392 char *ptr;
393 WCHAR update_uri[4096];
394
395 const int WINDOW_WIDTH = 250;
396 const int WINDOW_HEIGHT = 100;
397
398 wsprintf(gProgress, L"Connecting...");
399
400 /* Init the WNDCLASSEX */
401 wndclassex.cbSize = sizeof(WNDCLASSEX);
402 wndclassex.style = CS_HREDRAW | CS_VREDRAW;
403 wndclassex.hInstance = hInstance;
404 wndclassex.lpfnWndProc = WinProc;
405 wndclassex.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
406 wndclassex.lpszClassName = win_class_name;
407
408 RegisterClassEx(&wndclassex);
409
410 // Get the size of the screen
411 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode);
412
413 gWindow = CreateWindowEx(NULL, win_class_name,
414 window_title,
415 WS_OVERLAPPEDWINDOW,
416 CW_USEDEFAULT,
417 CW_USEDEFAULT,
418 WINDOW_WIDTH,
419 WINDOW_HEIGHT,
420 NULL, NULL, hInstance, NULL);
421
422 ShowWindow(gWindow, nShowCmd);
423 UpdateWindow(gWindow);
424
425 if (parse_args_result)
426 {
427 MessageBox(gWindow,
428 L"Usage: updater -userserver <server> [-name <window_title>] [-program <program_name>] [-silent]",
429 L"Usage", MB_OK);
430 return parse_args_result;
431 }
432
433 // Did we get a userserver to work with?
434 if (!gUserServer)
435 {
436 MessageBox(gWindow, L"Please specify the IP address of the userserver on the command line",
437 L"Error", MB_OK);
438 return 1;
439 }
440
441 // Can't feed GetTempPath into GetTempFile directly
442 if (0 == GetTempPathA(MAX_PATH - 14, update_exec_path))
443 {
444 MessageBox(gWindow, L"Problem with GetTempPath()",
445 L"Error", MB_OK);
446 return 1;
447 }
448 if (0 == GetTempFileNameA(update_exec_path, NULL, 0, update_exec_path))
449 {
450 MessageBox(gWindow, L"Problem with GetTempFileName()",
451 L"Error", MB_OK);
452 return 1;
453 }
454 // Hack hack hack
455 ptr = strrchr(update_exec_path, '.');
456 *(ptr + 1) = 'e';
457 *(ptr + 2) = 'x';
458 *(ptr + 3) = 'e';
459 *(ptr + 4) = 0;
460 wcscpy(update_uri, UPDATE_URIBASE);
461 WCHAR wcmdline[2048];
462 mbstowcs(wcmdline, gUserServer, 2048);
463 wcscat(update_uri, wcmdline);
464
465 int success;
466 int cancelled;
467
468 // Actually do the download
469#if _DEBUG
470 fprintf(logfile,"Calling get_url_into_file\n");
471 fflush(logfile);
472#endif
473 success = get_url_into_file(update_uri, update_exec_path, &cancelled);
474
475 // WinInet can't tell us if we got a 404 or not. Therefor, we check
476 // for the size of the downloaded file, and assume that our installer
477 // will always be greater than 1MB.
478 if (gTotalBytesRead < (1024 * 1024) && ! cancelled)
479 {
480 MessageBox(gWindow,
481 L"The Second Life auto-update has failed.\n"
482 L"The problem may be caused by other software installed \n"
483 L"on your computer, such as a firewall.\n"
484 L"Please visit http://secondlife.com/download/ \n"
485 L"to download the latest version of Second Life.\n",
486 NULL, MB_OK);
487 return 1;
488 }
489
490 if (cancelled)
491 {
492 // silently exit
493 return 0;
494 }
495
496 if (!success)
497 {
498 MessageBox(gWindow,
499 L"Second Life download failed.\n"
500 L"Please try again later.",
501 NULL, MB_OK);
502 return 1;
503 }
504
505 // Construct some parameters.
506 char params[2048];
507 if (gIsSilent && gProgramName)
508 {
509 sprintf(params, "/S /P=\"%s\"", gProgramName);
510 }
511 else if (gProgramName)
512 {
513 sprintf(params, "/P=\"%s\"", gProgramName);
514 }
515 else if (gIsSilent)
516 {
517 sprintf(params, "/S");
518 }
519 else
520 {
521 params[0] = '\0';
522 }
523
524 if (32 >= (int) ShellExecuteA(gWindow, "open", update_exec_path, params,
525 "C:\\", SW_SHOWDEFAULT))
526 {
527 // No shit: less than or equal to 32 means failure
528 MessageBox(gWindow, L"ShellExecute failed. Please try again later.", NULL, MB_OK);
529 return 1;
530 }
531
532 if (gIsSilent && gProductName)
533 {
534 WCHAR message[2048];
535 WCHAR wproduct[2048];
536 mbstowcs(wproduct, gProductName, 2048);
537
538 wsprintf(message,
539 L"Updating %s. %s will automatically start once the update is complete. This may take a minute...",
540 wproduct, wproduct);
541
542 MessageBox(gWindow, message, L"Download Complete", MB_OK);
543 }
544
545 return 0;
546}