aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llappviewerwin32.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:45:19 -0500
committerJacek Antonelli2008-08-15 23:45:19 -0500
commitb235c59d60472f818a9142c0886b95a0ff4191d7 (patch)
treed323c55587584b19cc43a03f58a178823f12d3cd /linden/indra/newview/llappviewerwin32.cpp
parentSecond Life viewer sources 1.18.5.3 (diff)
downloadmeta-impy-b235c59d60472f818a9142c0886b95a0ff4191d7.zip
meta-impy-b235c59d60472f818a9142c0886b95a0ff4191d7.tar.gz
meta-impy-b235c59d60472f818a9142c0886b95a0ff4191d7.tar.bz2
meta-impy-b235c59d60472f818a9142c0886b95a0ff4191d7.tar.xz
Second Life viewer sources 1.18.6.0-RC
Diffstat (limited to 'linden/indra/newview/llappviewerwin32.cpp')
-rw-r--r--linden/indra/newview/llappviewerwin32.cpp461
1 files changed, 461 insertions, 0 deletions
diff --git a/linden/indra/newview/llappviewerwin32.cpp b/linden/indra/newview/llappviewerwin32.cpp
new file mode 100644
index 0000000..814c209
--- /dev/null
+++ b/linden/indra/newview/llappviewerwin32.cpp
@@ -0,0 +1,461 @@
1/**
2 * @file llappviewerwin32.cpp
3 * @brief The LLAppViewerWin32 class definitions
4 *
5 * $LicenseInfo:firstyear=2007&license=viewergpl$
6 *
7 * Copyright (c) 2007, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2
16 *
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
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlife.com/developers/opensource/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32#include "llviewerprecompiledheaders.h"
33
34#include "llappviewerwin32.h"
35
36#include "llmemtype.h"
37
38#include "llwindowwin32.cpp" // *FIX: for setting gIconResource.
39#include "res/resource.h" // *FIX: for setting gIconResource.
40
41#include <fcntl.h> //_O_APPEND
42#include <io.h> //_open_osfhandle()
43#include <errorrep.h> // for AddERExcludedApplicationA()
44#include <process.h> // _spawnl()
45#include <tchar.h> // For TCHAR support
46
47#include "llviewercontrol.h"
48#include "lldxhardware.h"
49
50#include "llweb.h"
51#include "llsecondlifeurls.h"
52
53#include "llwindebug.h"
54
55#include "llviewernetwork.h"
56#include "llmd5.h"
57
58void fill_args(int& argc, char** argv, const S32 max_args, LPSTR cmd_line)
59{
60 char *token = NULL;
61 if( cmd_line[0] == '\"' )
62 {
63 // Exe name is enclosed in quotes
64 token = strtok( cmd_line, "\"" );
65 argv[argc++] = token;
66 token = strtok( NULL, " \t," );
67 }
68 else
69 {
70 // Exe name is not enclosed in quotes
71 token = strtok( cmd_line, " \t," );
72 }
73
74 while( (token != NULL) && (argc < max_args) )
75 {
76 argv[argc++] = token;
77 /* Get next token: */
78 if (*(token + strlen(token) + 1) == '\"') /* Flawfinder: ignore*/
79 {
80 token = strtok( NULL, "\"");
81 }
82 else
83 {
84 token = strtok( NULL, " \t," );
85 }
86 }
87}
88
89// *NOTE:Mani - this code is stolen from LLApp, where its never actually used.
90LONG WINAPI viewer_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop)
91{
92 // Translate the signals/exceptions into cross-platform stuff
93 // Windows implementation
94 llinfos << "Entering Windows Exception Handler..." << llendl;
95
96 // Make sure the user sees something to indicate that the app crashed.
97 LONG retval;
98
99 if (LLApp::isError())
100 {
101 llwarns << "Got another fatal signal while in the error handler, die now!" << llendl;
102 retval = EXCEPTION_EXECUTE_HANDLER;
103 return retval;
104 }
105
106 // Generate a minidump if we can.
107 // Before we wake the error thread...
108 // Which will start the crash reporting.
109 LLWinDebug::handleException(exception_infop);
110
111 // Flag status to error, so thread_error starts its work
112 LLApp::setError();
113
114 // Block in the exception handler until the app has stopped
115 // This is pretty sketchy, but appears to work just fine
116 while (!LLApp::isStopped())
117 {
118 ms_sleep(10);
119 }
120
121 //
122 // At this point, we always want to exit the app. There's no graceful
123 // recovery for an unhandled exception.
124 //
125 // Just kill the process.
126 retval = EXCEPTION_EXECUTE_HANDLER;
127 return retval;
128}
129
130int APIENTRY WinMain(HINSTANCE hInstance,
131 HINSTANCE hPrevInstance,
132 LPSTR lpCmdLine,
133 int nCmdShow)
134{
135 LLMemType mt1(LLMemType::MTYPE_STARTUP);
136
137 // *FIX: global
138 gIconResource = MAKEINTRESOURCE(IDI_LL_ICON);
139
140 // In Win32, we need to generate argc and argv ourselves...
141 // Note: GetCommandLine() returns a potentially return a LPTSTR
142 // which can resolve to a LPWSTR (unicode string).
143 // (That's why it's different from lpCmdLine which is a LPSTR.)
144 // We don't currently do unicode, so call the non-unicode version
145 // directly.
146 LPSTR cmd_line_including_exe_name = GetCommandLineA();
147
148 const S32 MAX_ARGS = 100;
149 int argc = 0;
150 char* argv[MAX_ARGS]; /* Flawfinder: ignore */
151
152 fill_args(argc, argv, MAX_ARGS, cmd_line_including_exe_name);
153
154 LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32();
155
156 // *FIX:Mani This method is poorly named, since the exception
157 // is now handled by LLApp.
158 bool ok = LLWinDebug::setupExceptionHandler();
159
160 // Actually here's the exception setup.
161 LPTOP_LEVEL_EXCEPTION_FILTER prev_filter;
162 prev_filter = SetUnhandledExceptionFilter(viewer_windows_exception_handler);
163 if (!prev_filter)
164 {
165 llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with NULL!" << llendl;
166 ok = FALSE;
167 }
168 if (prev_filter != LLWinDebug::handleException)
169 {
170 llwarns << "Our exception handler (" << (void *)LLWinDebug::handleException << ") replaced with " << prev_filter << "!" << llendl;
171 ok = FALSE;
172 }
173
174 viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
175
176 ok = viewer_app_ptr->tempStoreCommandOptions(argc, argv);
177 if(!ok)
178 {
179 llwarns << "Unable to parse command line." << llendl;
180 return -1;
181 }
182
183 ok = viewer_app_ptr->init();
184 if(!ok)
185 {
186 llwarns << "Application init failed." << llendl;
187 return -1;
188 }
189
190 // Run the application main loop
191 if(!LLApp::isQuitting())
192 {
193 viewer_app_ptr->mainLoop();
194 }
195
196 if (!LLApp::isError())
197 {
198 //
199 // We don't want to do cleanup here if the error handler got called -
200 // the assumption is that the error handler is responsible for doing
201 // app cleanup if there was a problem.
202 //
203 viewer_app_ptr->cleanup();
204 }
205 delete viewer_app_ptr;
206 viewer_app_ptr = NULL;
207 return 0;
208}
209
210void LLAppViewerWin32::disableWinErrorReporting()
211{
212 const char win_xp_string[] = "Microsoft Windows XP";
213 BOOL is_win_xp = ( getOSInfo().getOSString().substr(0, strlen(win_xp_string) ) == win_xp_string ); /* Flawfinder: ignore*/
214 if( is_win_xp )
215 {
216 // Note: we need to use run-time dynamic linking, because load-time dynamic linking will fail
217 // on systems that don't have the library installed (all non-Windows XP systems)
218 HINSTANCE fault_rep_dll_handle = LoadLibrary(L"faultrep.dll"); /* Flawfinder: ignore */
219 if( fault_rep_dll_handle )
220 {
221 pfn_ADDEREXCLUDEDAPPLICATIONA pAddERExcludedApplicationA = (pfn_ADDEREXCLUDEDAPPLICATIONA) GetProcAddress(fault_rep_dll_handle, "AddERExcludedApplicationA");
222 if( pAddERExcludedApplicationA )
223 {
224
225 // Strip the path off the name
226 const char* executable_name = gDirUtilp->getExecutableFilename().c_str();
227
228 if( 0 == pAddERExcludedApplicationA( executable_name ) )
229 {
230 U32 error_code = GetLastError();
231 llinfos << "AddERExcludedApplication() failed with error code " << error_code << llendl;
232 }
233 else
234 {
235 llinfos << "AddERExcludedApplication() success for " << executable_name << llendl;
236 }
237 }
238 FreeLibrary( fault_rep_dll_handle );
239 }
240 }
241}
242
243const S32 MAX_CONSOLE_LINES = 500;
244
245void create_console()
246{
247 int h_con_handle;
248 long l_std_handle;
249
250 CONSOLE_SCREEN_BUFFER_INFO coninfo;
251 FILE *fp;
252
253 // allocate a console for this app
254 AllocConsole();
255
256 // set the screen buffer to be big enough to let us scroll text
257 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
258 coninfo.dwSize.Y = MAX_CONSOLE_LINES;
259 SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
260
261 // redirect unbuffered STDOUT to the console
262 l_std_handle = (long)GetStdHandle(STD_OUTPUT_HANDLE);
263 h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
264 fp = _fdopen( h_con_handle, "w" );
265 *stdout = *fp;
266 setvbuf( stdout, NULL, _IONBF, 0 );
267
268 // redirect unbuffered STDIN to the console
269 l_std_handle = (long)GetStdHandle(STD_INPUT_HANDLE);
270 h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
271 fp = _fdopen( h_con_handle, "r" );
272 *stdin = *fp;
273 setvbuf( stdin, NULL, _IONBF, 0 );
274
275 // redirect unbuffered STDERR to the console
276 l_std_handle = (long)GetStdHandle(STD_ERROR_HANDLE);
277 h_con_handle = _open_osfhandle(l_std_handle, _O_TEXT);
278 fp = _fdopen( h_con_handle, "w" );
279 *stderr = *fp;
280 setvbuf( stderr, NULL, _IONBF, 0 );
281}
282
283LLAppViewerWin32::LLAppViewerWin32()
284{
285}
286
287LLAppViewerWin32::~LLAppViewerWin32()
288{
289}
290
291bool LLAppViewerWin32::init()
292{
293 // Platform specific initialization.
294
295 // Turn off Windows XP Error Reporting
296 // (Don't send our data to Microsoft--at least until we are Logo approved and have a way
297 // of getting the data back from them.)
298 //
299 llinfos << "Turning off Windows error reporting." << llendl;
300 disableWinErrorReporting();
301
302 return LLAppViewer::init();
303}
304
305bool LLAppViewerWin32::cleanup()
306{
307 bool result = LLAppViewer::cleanup();
308
309 gDXHardware.cleanup();
310
311 return result;
312}
313
314bool LLAppViewerWin32::initWindow()
315{
316 // pop up debug console if necessary
317 if (gUseConsole && gSavedSettings.getBOOL("ShowConsoleWindow"))
318 {
319 create_console();
320 }
321
322 return LLAppViewer::initWindow();
323}
324
325void write_debug_dx(const char* str)
326{
327 LLString value = gDebugInfo["DXInfo"].asString();
328 value += str;
329 gDebugInfo["DXInfo"] = value;
330}
331
332void write_debug_dx(const std::string& str)
333{
334 write_debug_dx(str.c_str());
335}
336
337bool LLAppViewerWin32::initHardwareTest()
338{
339 //
340 // Do driver verification and initialization based on DirectX
341 // hardware polling and driver versions
342 //
343 if (gProbeHardware)
344 {
345 BOOL vram_only = !gSavedSettings.getBOOL("ProbeHardwareOnStartup");
346
347 LLSplashScreen::update("Detecting hardware...");
348
349 llinfos << "Attempting to poll DirectX for hardware info" << llendl;
350 gDXHardware.setWriteDebugFunc(write_debug_dx);
351 BOOL probe_ok = gDXHardware.getInfo(vram_only);
352
353 if (!probe_ok
354 && gSavedSettings.getWarning("AboutDirectX9"))
355 {
356 llinfos << "DirectX probe failed, alerting user." << llendl;
357
358 // Warn them that runnin without DirectX 9 will
359 // not allow us to tell them about driver issues
360 std::ostringstream msg;
361 msg <<
362 LLAppViewer::instance()->getSecondLifeTitle() << " is unable to detect DirectX 9.0b or greater.\n"
363 "\n" <<
364 LLAppViewer::instance()->getSecondLifeTitle() << " uses DirectX to detect hardware and/or\n"
365 "outdated drivers that can cause stability problems,\n"
366 "poor performance and crashes. While you can run\n" <<
367 LLAppViewer::instance()->getSecondLifeTitle() << " without it, we highly recommend running\n"
368 "with DirectX 9.0b\n"
369 "\n"
370 "Do you wish to continue?\n";
371 S32 button = OSMessageBox(
372 msg.str().c_str(),
373 "Warning",
374 OSMB_YESNO);
375 if (OSBTN_NO== button)
376 {
377 llinfos << "User quitting after failed DirectX 9 detection" << llendl;
378 LLWeb::loadURLExternal(DIRECTX_9_URL);
379 return false;
380 }
381 gSavedSettings.setWarning("AboutDirectX9", FALSE);
382 }
383 llinfos << "Done polling DirectX for hardware info" << llendl;
384
385 // Only probe once after installation
386 gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
387
388 // Disable so debugger can work
389 std::ostringstream splash_msg;
390 splash_msg << "Loading " << LLAppViewer::instance()->getSecondLifeTitle() << "...";
391
392 LLSplashScreen::update(splash_msg.str().c_str());
393 }
394
395 if (!LLWinDebug::setupExceptionHandler())
396 {
397 llwarns << " Someone took over my exception handler (post hardware probe)!" << llendl;
398 }
399
400 gGLManager.mVRAM = gDXHardware.getVRAM();
401 llinfos << "Detected VRAM: " << gGLManager.mVRAM << llendl;
402
403 return true;
404}
405
406void LLAppViewerWin32::handleCrashReporting()
407{
408 // Windows only behaivor. Spawn win crash reporter.
409 std::string exe_path = gDirUtilp->getAppRODataDir();
410 exe_path += gDirUtilp->getDirDelimiter();
411 exe_path += "win_crash_logger.exe";
412
413 std::string arg_string = "-user ";
414 arg_string += gGridName;
415
416 switch(getCrashBehavior())
417 {
418 case CRASH_BEHAVIOR_ASK:
419 default:
420 arg_string += " -dialog ";
421 _spawnl(_P_NOWAIT, exe_path.c_str(), exe_path.c_str(), arg_string.c_str(), NULL);
422 break;
423
424 case CRASH_BEHAVIOR_ALWAYS_SEND:
425 _spawnl(_P_NOWAIT, exe_path.c_str(), exe_path.c_str(), arg_string.c_str(), NULL);
426 break;
427
428 case CRASH_BEHAVIOR_NEVER_SEND:
429 break;
430 }
431}
432
433std::string LLAppViewerWin32::generateSerialNumber()
434{
435 char serial_md5[MD5HEX_STR_SIZE]; // Flawfinder: ignore
436 serial_md5[0] = 0;
437
438 DWORD serial = 0;
439 DWORD flags = 0;
440 BOOL success = GetVolumeInformation(
441 L"C:\\",
442 NULL, // volume name buffer
443 0, // volume name buffer size
444 &serial, // volume serial
445 NULL, // max component length
446 &flags, // file system flags
447 NULL, // file system name buffer
448 0); // file system name buffer size
449 if (success)
450 {
451 LLMD5 md5;
452 md5.update( (unsigned char*)&serial, sizeof(DWORD));
453 md5.finalize();
454 md5.hex_digest(serial_md5);
455 }
456 else
457 {
458 llwarns << "GetVolumeInformation failed" << llendl;
459 }
460 return serial_md5;
461} \ No newline at end of file