fix a few memory leaks and cppcheck detected errors - more in bugreport
[client-tools.git] / src / game / client / application / SwgClientSetup / src / win32 / SwgClientSetup.cpp
blob88fa1cf7e48a4258bf0f20d5a1b9e5c35f14c91e
1 // ======================================================================
2 //
3 // SwgClientSetup.cpp
4 // asommers
5 //
6 // copyright 2002, sony online entertainment
7 //
8 // ======================================================================
10 #include "FirstSwgClientSetup.h"
11 #include "SwgClientSetup.h"
13 #include "ClientMachine.h"
14 #include "Crc.h"
15 #include "DialogContact.h"
16 #include "DialogFinish.h"
17 #include "DialogHardwareInformation.h"
18 #include "DialogMinidump.h"
19 #include "DialogProgress.h"
20 #include "DialogRating.h"
21 #include "DialogStationId.h"
22 #include "Options.h"
23 #include "SwgClientSetupDlg.h"
24 #include "MessageBox2.h"
26 #include <io.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <errno.h>
30 #include <algorithm>
31 #include <string>
33 #ifdef _DEBUG
34 #define new DEBUG_NEW
35 #undef THIS_FILE
36 static char THIS_FILE[] = __FILE__;
37 #endif
39 // ======================================================================
41 namespace SwgClientSetupNamespace
43 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
45 TCHAR const * const cms_registryFolder = _T("Software\\Sony Online Entertainment\\StarWarsGalaxies\\SwgClient");
46 TCHAR const * const cms_sendMinidumpsRegistryKey = _T("SendCrashLogs");
47 TCHAR const * const cms_sendHardwareInformationRegistryKey = _T("SendHardwareInformation");
48 TCHAR const * const cms_informationCrcRegistryKey = _T("HardwareInformationCrc");
49 TCHAR const * const cms_hardwareInformationCrcRegistryKey = _T("HardwareInformationCrc");
50 TCHAR const * const cms_lastRatingTimeRegistryKey = _T("LastRatingTime");
51 TCHAR const * const cms_machineRequirementsDisplayCountRegistryKey = _T("MachineRequirementsDisplayCount");
52 TCHAR const * const cms_applicationName = _T("SwgClient_r.exe");
53 char const * const cms_fromEmailAddress = "swgbetatestcrashes@soe.sony.com";
54 char const * const cms_toEmailAddress = "swgbetatestcrashes@soe.sony.com";
55 TCHAR const * const cms_fileNameMask = _T("SwgClient_?.exe-*.*");
56 TCHAR const * const cms_languageStringJapanese = _T("ja");
58 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
60 CString getVersion (CString const & fileName)
62 int const start = fileName.Find ('-', 0) + 1;
63 int const end = fileName.ReverseFind ('-');
65 return fileName.Mid (start, end - start);
68 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
70 int getMajorVersion (CString const & fileName)
72 CString const version = getVersion (fileName);
74 int const end = version.Find ('.', 0);
76 return _ttoi (version.Mid (0, end));
79 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
81 int getMinorVersion (CString const & fileName)
83 CString const version = getVersion (fileName);
85 int const end = version.Find ('.', 0);
87 return _ttoi (version.Mid (end + 1, version.GetLength () - end));
90 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
92 CString getSubject (CString const & fileName)
94 return "automated crash dump " + fileName;
97 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
99 CString getBody (CString const & fileName)
101 CString body;
103 CStdioFile file;
104 if (file.Open (fileName + ".txt", CFile::modeRead | CFile::typeText))
106 CString line;
107 while (file.ReadString (line))
108 body += line + "\n";
110 else
111 body = "automated crash dump\n\nunknown: FATAL 00000000: minidump from options program\n";
113 return body;
116 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
118 CString getCode (CString const & fileName)
120 CString body;
122 CStdioFile file;
123 if (file.Open (fileName + ".txt", CFile::modeRead | CFile::typeText))
125 CString line;
126 while (file.ReadString (line))
128 if (line.Find (_T("Exception")) != -1 || line.Find (_T("FATAL")) != -1)
130 body += line;
132 break;
137 if (body.GetLength () == 0)
138 body = "unknown";
140 return body;
143 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
145 CString getMinidump (CString const & fileName)
147 CString result;
149 CFile file;
150 if (file.Open (fileName + ".mdmp", CFile::modeRead))
151 result += fileName + ".mdmp";
153 return result;
156 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158 CString getLog (CString const & fileName)
160 CString result;
162 CFile file;
163 if (file.Open (fileName + ".log", CFile::modeRead))
164 result += fileName + ".log";
166 return result;
169 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
171 bool registryKeyExists (TCHAR const * const key)
173 CRegKey regKey;
174 regKey.Open (HKEY_CURRENT_USER, cms_registryFolder);
176 DWORD value = 0;
177 #if _MSC_VER < 1300
178 return regKey.QueryValue (value, key) == ERROR_SUCCESS;
179 #else
180 return regKey.QueryDWORDValue (key, value) == ERROR_SUCCESS;
181 #endif
184 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
186 DWORD getRegistryKey (TCHAR const * const key)
188 CRegKey regKey;
189 regKey.Open (HKEY_CURRENT_USER, cms_registryFolder);
191 DWORD value = 0;
192 #if _MSC_VER < 1300
193 regKey.QueryValue (value, key);
194 #else
195 regKey.QueryDWORDValue (key, value);
196 #endif
198 return value;
201 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
203 void setRegistryKey (TCHAR const * const key, DWORD const value)
205 CRegKey regKey;
206 regKey.Create (HKEY_CURRENT_USER, cms_registryFolder);
207 #if _MSC_VER < 1300
208 regKey.SetValue (value, key);
209 #else
210 regKey.SetDWORDValue (key, value);
211 #endif
214 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
216 CString getStationId (CString const & commandLine)
218 int index = commandLine.Find (_T("stationId="));
219 if (index != -1)
221 index = commandLine.Find (_T("="), index);
222 CString result = commandLine.Right (commandLine.GetLength () - index - 1);
223 index = result.Find (_T(" "));
224 if (index != -1)
225 result = result.Left (index);
227 return result;
230 return _T("0");
233 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
235 int getLanguageCode (CString const & commandLine)
237 int index = commandLine.Find (_T("locale="));
238 if (index != -1)
240 index = commandLine.Find (_T("="), index);
241 CString result = commandLine.Right (commandLine.GetLength () - index - 1);
242 index = result.Find (_T(" "));
243 if (index != -1)
244 result = result.Left (index);
246 if (wcsncmp(result, cms_languageStringJapanese, 2) == 0)
247 return cms_languageCodeJapanese;
250 return cms_languageCodeEnglish;
252 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
254 bool hasJumpToLightspeed (CString const & commandLine)
256 int index = commandLine.Find (_T("gameFeatures="));
257 if (index != -1)
259 index = commandLine.Find (_T("="), index);
260 CString result = commandLine.Right (commandLine.GetLength () - index - 1);
261 index = result.Find (_T(" "));
262 if (index != -1)
263 result = result.Left (index);
265 int const gameFeatures = _ttoi(result);
267 return (gameFeatures & 16) != 0;
270 return false;
273 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
275 void RemoveFile(char const * fileName)
277 if (unlink(fileName) == -1 && errno == EACCES)
279 _chmod(fileName, _S_IREAD | _S_IWRITE);
280 unlink(fileName);
285 using namespace SwgClientSetupNamespace;
287 // ======================================================================
289 BEGIN_MESSAGE_MAP(SwgClientSetupApp, CWinApp)
290 //{{AFX_MSG_MAP(SwgClientSetupApp)
291 //}}AFX_MSG
292 ON_COMMAND(ID_HELP, CWinApp::OnHelp)
293 END_MESSAGE_MAP()
295 // ----------------------------------------------------------------------
297 SwgClientSetupApp::SwgClientSetupApp()
301 // ----------------------------------------------------------------------
303 SwgClientSetupApp theApp;
305 // ----------------------------------------------------------------------
307 class CCommandLineInfo2 : public CCommandLineInfo
309 public:
311 CCommandLineInfo2 () :
312 CCommandLineInfo (),
313 m_numberOfParameters(0),
314 m_numberOfErrors(5),
315 m_debugExitPoll(false)
319 virtual void ParseParam(TCHAR const * pszParam, BOOL /*bFlag*/, BOOL /*bLast*/)
321 if (wcsstr(pszParam, _T("locale")) == 0)
322 ++m_numberOfParameters;
324 if (wcsstr(pszParam, _T("Station")) != 0)
325 --m_numberOfErrors;
327 if (wcsstr(pszParam, _T("sessionId")) != 0)
328 --m_numberOfErrors;
330 if (wcsstr(pszParam, _T("stationId")) != 0)
331 --m_numberOfErrors;
333 if (wcsstr(pszParam, _T("subscriptionFeatures")) != 0)
334 --m_numberOfErrors;
336 if (wcsstr(pszParam, _T("gameFeatures")) != 0)
337 --m_numberOfErrors;
339 m_debugExitPoll |= (wcsstr(pszParam, _T("debugExitPoll")) != 0);
342 bool shouldLaunchSwgClient() const
344 return m_numberOfParameters > 0;
347 bool looksValid() const
349 return m_numberOfErrors == 0;
352 bool debugExitPoll() const
354 return m_debugExitPoll;
357 private:
359 int m_numberOfParameters;
360 int m_numberOfErrors;
361 bool m_debugExitPoll;
364 // ----------------------------------------------------------------------
366 BOOL SwgClientSetupApp::InitInstance()
368 MessageBox2::install(cms_registryFolder);
370 // Initialize MFC controls.
371 AfxEnableControlContainer();
373 #if _MSC_VER < 1300
374 #ifdef _AFXDLL
375 Enable3dControls(); // Call this when using MFC in a shared DLL
376 #else
377 Enable3dControlsStatic(); // Call this when linking to MFC statically
378 #endif
379 #endif
382 // Standard initialization
383 HANDLE semaphore = CreateSemaphore(NULL, 0, 1, _T("SwgClientSetupInstanceRunning"));
384 if (GetLastError() == ERROR_ALREADY_EXISTS)
386 CString anotherStr;
387 VERIFY(anotherStr.LoadString(IDS_ANOTHER_INSTANCE));
388 MessageBox(NULL, anotherStr, NULL, MB_OK | MB_ICONSTOP);
389 CloseHandle(semaphore);
390 return FALSE;
393 detectAndSendMinidumps ();
395 ClientMachine::install ();
397 int const langCode = getLanguageCode(AfxGetApp()->m_lpCmdLine);
398 Options::load (langCode);
401 //-- Set the thread locale in order to use the correct string table
402 if (langCode == cms_languageCodeJapanese)
403 SetThreadLocale(MAKELCID(0x0411, SORT_DEFAULT));
404 else
406 //-- English
407 SetThreadLocale(MAKELCID(0x0409, SORT_DEFAULT));
410 //--
411 CCommandLineInfo2 commandLineInfo;
412 ParseCommandLine (commandLineInfo);
414 if (commandLineInfo.shouldLaunchSwgClient())
416 if (!commandLineInfo.looksValid())
419 OutputDebugString(CString("SwgClientSetup command line: ") + m_lpCmdLine + "\n");
421 CString message;
422 VERIFY(message.LoadString(IDS_INVALIDCOMMANDLINE));
423 if (MessageBox(NULL, message, NULL, MB_YESNO | MB_ICONSTOP) == IDNO)
424 return FALSE;
426 if (ClientMachine::getDirectXVersionMajor() < 9 || ClientMachine::getDirectXVersionLetter() < 'c')
428 MessageBox2 messageBox(CString("You have DirectX ") + CString(ClientMachine::getDirectXVersion()) + CString(" installed but DirectX 9.0c is currently required to play Star Wars Galaxies. For upgrade information, please see:\n\n\thttp://starwarsgalaxies.station.sony.com/content.jsp?page=Directx%20Upgrade"));
429 messageBox.setOkayButton("Quit");
430 messageBox.setCancelButton("");
431 messageBox.setWebButton("Go to web page", "http://starwarsgalaxies.station.sony.com/content.jsp?page=Directx%20Upgrade");
432 messageBox.DoModal();
433 return FALSE;
436 unsigned short const vendor = ClientMachine::getVendorIdentifier ();
437 unsigned short const device = ClientMachine::getDeviceIdentifier ();
438 int const driverProduct = ClientMachine::getDeviceDriverProduct();
439 int const driverVersion = ClientMachine::getDeviceDriverVersion ();
440 int const driverSubversion = ClientMachine::getDeviceDriverSubversion ();
441 int const driverBuild = ClientMachine::getDeviceDriverBuild();
443 if (vendor == 0x10de)
445 //NVidia tests
446 if (driverBuild >= 2700 && driverBuild < 2800)
448 MessageBox2 messageBox("The application has detected very old NVidia video card drivers that have known issues that will cause a crash.\nPlease upgrade your video drivers. They may be downloaded from:\n\n\thttp://www.nvidia.com.\n\nWould you like to continue running anyway?");
449 messageBox.setOkayButton("Continue");
450 messageBox.setCancelButton("Quit");
451 messageBox.setWebButton("Go to web page", "http://www.nvidia.com");
452 messageBox.setDoNotShowAgainCheckBox("Do not show this warning again", "NVidia 2700");
453 if (messageBox.DoModal() == IDCANCEL)
454 return false;
456 else if ((device >= 0x0200 && device <= 0x020F) && driverBuild == 5216)
458 MessageBox2 messageBox("The application has detected a card/driver combination that has known issues that cause a crash.\nPlease upgrade your video drivers. They may be downloaded from:\n\n\thttp://www.nvidia.com.\n\nWould you like to continue running anyway?");
459 messageBox.setOkayButton("Continue");
460 messageBox.setCancelButton("Quit");
461 messageBox.setWebButton("Go to web page", "http://www.nvidia.com");
462 messageBox.setDoNotShowAgainCheckBox("Do not show this warning again", "NVidia 5216");
463 if (messageBox.DoModal() == IDCANCEL)
464 return false;
467 else if (vendor == 0x1002)
469 // ATI tests
470 if (driverBuild <= 6467)
472 MessageBox2 messageBox("The application has detected old ATI video card drivers which have known issues that will cause a crash.\nFor more information, please see:\n\n\thttp://starwarsgalaxies.station.sony.com/content.jsp?page=ATI%20Video%20Card%20Driver\n\nWould you like to continue running anyway?");
473 messageBox.setOkayButton("Continue");
474 messageBox.setCancelButton("Quit");
475 messageBox.setWebButton("Go to web page", "http://starwarsgalaxies.station.sony.com/content.jsp?page=ATI%20Video%20Card%20Driver");
476 messageBox.setDoNotShowAgainCheckBox("Do not show this warning again", "ATI Catalyst 4.8");
477 if (messageBox.DoModal() == IDCANCEL)
478 return false;
482 if (!registryKeyExists (cms_sendHardwareInformationRegistryKey))
483 configure ();
485 Options::save ();
487 detectAndSendHardwareInformation ();
489 bool const displayMessage =
490 (ClientMachine::getPhysicalMemorySize () < 500) ||
491 (ClientMachine::getCpuSpeed () < 900) ||
492 (ClientMachine::getVideoMemorySize() < 28);
493 if (displayMessage)
495 int const machineRequirementsDisplayCount = getRegistryKey(cms_machineRequirementsDisplayCountRegistryKey);
496 if (machineRequirementsDisplayCount < 3)
498 CString os = _T("- Windows 98SE/ME/2000/XP");
499 if (os == _T("unsupported"))
500 os += _T(" (detected unsupported)\n");
501 else
502 os += _T("\n");
504 CString memory;
505 VERIFY(memory.LoadString(IDS_512MB_PHYSICAL));
507 CString memoryDetected;
508 VERIFY(memoryDetected.LoadString(IDS_512MB_PHYSICAL_DETECTED));
509 if (ClientMachine::getPhysicalMemorySize () < 500)
510 memory.Format (memoryDetected, ClientMachine::getPhysicalMemorySize ());
512 CString cpu;
513 VERIFY(cpu.LoadString(IDS_900MHZ_PROCESSOR));
514 if (ClientMachine::getCpuSpeed () < 900)
516 if (ClientMachine::getCpuSpeed() == 0)
518 CString detectedUnknown;
519 VERIFY(detectedUnknown.LoadString(IDS_900MHZ_PROCESSOR_DETECTED_UNKNOWN));
520 cpu.Format (detectedUnknown);
522 else
524 CString detectedCpu;
525 VERIFY(detectedCpu.LoadString(IDS_900MHZ_PROCESSOR_DETECTED));
526 cpu.Format (detectedCpu, ClientMachine::getCpuSpeed ());
530 CString videoMemory;
531 VERIFY(videoMemory.LoadString(IDS_32MB_VIDEO_MEMORY));
532 CString videoMemoryTooSmall;
533 VERIFY(videoMemoryTooSmall.LoadString(IDS_32MB_VIDEO_MEMORY_DETECTED));
534 if (ClientMachine::getVideoMemorySize () < 28)
535 videoMemory.Format (videoMemoryTooSmall, ClientMachine::getVideoMemorySize ());
537 CString harshMessage;
538 VERIFY(harshMessage.LoadString(IDS_NOT_MINIMUM));
539 CString niceMessage;
540 VERIFY(niceMessage.LoadString(IDS_NICE_MINIMUM));
541 bool const displayHarshMessage =
542 (hasJumpToLightspeed(AfxGetApp()->m_lpCmdLine) && ClientMachine::getPhysicalMemorySize () < 500) ||
543 (!hasJumpToLightspeed(AfxGetApp()->m_lpCmdLine) && ClientMachine::getPhysicalMemorySize () < 250) ||
544 (ClientMachine::getCpuSpeed () < 900) ||
545 (ClientMachine::getVideoMemorySize() < 28);
547 CString message(displayHarshMessage ? harshMessage : niceMessage);
548 message += os;
549 message += memory;
550 message += cpu;
551 message += videoMemory;
552 CString finalMessageStr;
553 VERIFY(finalMessageStr.LoadString(IDS_FINAL_CONFIG));
554 message += finalMessageStr;
556 CString noChangeStr;
557 VERIFY(noChangeStr.LoadString(IDS_NO_CHANGE_DETECTED));
558 if (machineRequirementsDisplayCount == 2)
559 message += noChangeStr;
561 setRegistryKey(cms_machineRequirementsDisplayCountRegistryKey, machineRequirementsDisplayCount + 1);
563 AfxMessageBox (message, NULL, MB_OK | MB_ICONSTOP);
566 else
567 setRegistryKey(cms_machineRequirementsDisplayCountRegistryKey, 0);
569 //-- spawn cms_applicationName
570 STARTUPINFO si;
571 PROCESS_INFORMATION pi;
573 ZeroMemory (&si, sizeof(si));
574 si.cb = sizeof (si);
575 ZeroMemory (&pi, sizeof(pi));
577 TCHAR commandLine [1024];
578 _stprintf (commandLine, _T("%s %s"), cms_applicationName, AfxGetApp()->m_lpCmdLine);
579 BOOL const result = CreateProcess (cms_applicationName, commandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
580 if (!result)
582 CString error;
583 CString failedStr;
584 VERIFY(failedStr.LoadString(IDS_FAILED_START));
585 error.Format (failedStr, cms_applicationName);
586 AfxMessageBox (error, NULL, MB_ICONERROR | MB_OK);
589 if (semaphore)
591 CloseHandle(semaphore);
592 semaphore = NULL;
595 return FALSE;
598 if (!ClientMachine::getDirectXSupported ())
600 CString directXStr;
601 VERIFY(directXStr.LoadString(IDS_NO_DIRECTX));
602 AfxMessageBox (directXStr);
603 return FALSE;
606 SwgClientSetupDlg dlg;
607 m_pMainWnd = &dlg;
608 int nResponse = dlg.DoModal();
609 if (nResponse == IDOK)
611 if (!Options::save ())
613 CString buffer;
614 CString cantSaveStr;
615 VERIFY(cantSaveStr.LoadString(IDS_CANT_SAVE));
616 buffer.Format (cantSaveStr, Options::getFileName ());
617 AfxMessageBox (buffer);
620 else if (nResponse == IDCANCEL)
624 if (semaphore)
625 CloseHandle(semaphore);
627 // Since the dialog has been closed, return FALSE so that we exit the
628 // application, rather than start the application's message pump.
629 return FALSE;
632 // ======================================================================
634 //int callBlat(int argc, char **argv, char **envp);
636 // ----------------------------------------------------------------------
638 void SwgClientSetupNamespace::sendMail(std::string const & to, std::string const & from, std::string const & subject, std::string const & body, std::vector<std::string> const & attachments)
640 int const numAttachments = attachments.size();
642 const int static_args = 13;
644 int argc = static_args + (2 * numAttachments);
645 char** argv = new char*[argc];
646 int argv_value = 1;
647 argv[argv_value++] = "-to";
648 argv[argv_value++] = const_cast<char*>(to.c_str());
649 argv[argv_value++] = "-subject";
650 argv[argv_value++] = const_cast<char*>(subject.c_str());
651 argv[argv_value++] = "-smtphost";
652 argv[argv_value++] = "mail.station.sony.com";
653 argv[argv_value++] = "-port";
654 argv[argv_value++] = "2525";
655 argv[argv_value++] = "-f";
656 argv[argv_value++] = const_cast<char*>(from.c_str());
657 argv[argv_value++] = "-body";
658 argv[argv_value++] = const_cast<char*>(body.c_str());
660 //iterate through all attachments, building the argv entries for them
661 for(std::vector<std::string>::const_iterator i = attachments.begin(); i != attachments.end(); ++i)
663 argv[argv_value++] = "-attach";
664 argv[argv_value++] = const_cast<char*>(i->c_str());
667 //this doesn't get used, but make sure to send initialized memory anyway
668 char* envp = new char[256];
669 memset(envp, 0, 256);
671 //call into blat to send the mail
672 //callBlat(argc, argv, &envp);
674 //clean up allocated memory
675 delete[] argv;
676 delete[] envp;
679 // ----------------------------------------------------------------------
681 void SwgClientSetupApp::configure ()
683 bool const oldSendMinidumps = getSendMinidumps ();
684 bool const oldSendStationId = Options::getSendStationId ();
685 bool const oldAutomaticallySendHardwareInformation = getAutomaticallySendHardwareInformation ();
686 bool const oldAllowCustomerContact = Options::getAllowCustomerContact ();
688 //-- ask to send minidumps
689 DialogMinidump dialogMinidump;
690 bool cancelled = dialogMinidump.DoModal () == IDCANCEL;
692 //-- if the user did not cancel and they want to send minidumps
693 if (!cancelled)
695 if (getSendMinidumps ())
697 DialogStationId dialogStationId;
698 cancelled = dialogStationId.DoModal () == IDCANCEL;
700 //-- if the user did not cancel, ask to send hardware and contact information
701 if (!cancelled)
703 if (Options::getSendStationId ())
705 DialogHardwareInformation dialogHardwareInformation;
706 cancelled = dialogHardwareInformation.DoModal () == IDCANCEL;
708 if (!cancelled)
710 DialogContact dialogContact;
711 cancelled = dialogContact.DoModal () == IDCANCEL;
714 else
716 setAutomaticallySendHardwareInformation (false);
717 Options::setAllowCustomerContact (false);
721 if (!cancelled)
723 DialogFinish dialogFinish;
724 dialogFinish.DoModal ();
727 else
729 Options::setSendStationId (false);
730 setAutomaticallySendHardwareInformation (false);
731 Options::setAllowCustomerContact (false);
735 if (cancelled)
737 setSendMinidumps (oldSendMinidumps);
738 Options::setSendStationId (oldSendStationId);
739 setAutomaticallySendHardwareInformation (oldAutomaticallySendHardwareInformation);
740 Options::setAllowCustomerContact (oldAllowCustomerContact);
744 // ----------------------------------------------------------------------
746 void SwgClientSetupApp::detectAndSendMinidumps ()
748 typedef std::vector<std::wstring> StringList;
749 StringList fileNameList;
751 //-- find all files in the current directory that end in match SwgClient_r.exe-*.mdmp
752 CFileFind finder;
753 BOOL working = finder.FindFile (cms_fileNameMask);
754 while (working)
756 working = finder.FindNextFile ();
758 if (!finder.IsDots () && !finder.IsDirectory () && finder.MatchesMask (FILE_ATTRIBUTE_ARCHIVE))
760 CString fileName = finder.GetFileName ();
761 int const index = fileName.ReverseFind ('.');
762 fileName = fileName.Left (index);
764 std::wstring const fileNameString(fileName);
765 if (std::find (fileNameList.begin (), fileNameList.end (), fileNameString) == fileNameList.end ())
766 fileNameList.push_back (fileNameString);
770 if (!fileNameList.empty ())
772 bool const sendMinidumps = getSendMinidumps ();
773 if (sendMinidumps)
775 //-- do both the minidump and the
776 DialogProgress * dlg = new DialogProgress ();
777 dlg->Create ();
778 dlg->SetRange (0, fileNameList.size ());
779 dlg->SetStep (1);
780 dlg->SetPos (0);
782 CString name;
783 name.Format (_T("Sending %i log(s)..."), fileNameList.size ());
784 dlg->SetStatus (name);
786 for (size_t i = 0; i < fileNameList.size (); ++i)
788 CString const fileName = fileNameList [i].c_str ();
790 //-- send the minidump
791 std::vector<std::string> attachments;
792 CString const attachment = getMinidump (fileName);
793 if (attachment.GetLength () != 0)
794 attachments.push_back(wideToNarrow(attachment));
795 CString const attachmentLog = getLog (fileName);
796 if(attachmentLog.GetLength() != 0)
797 attachments.push_back(wideToNarrow(attachmentLog));
799 int const majorVersion = getMajorVersion (fileName);
800 int const minorVersion = getMinorVersion (fileName);
801 if (majorVersion >= 100000 || (majorVersion == 0 && minorVersion >= 100000))
802 sendMail (cms_toEmailAddress, cms_fromEmailAddress, wideToNarrow (getSubject (fileName)), wideToNarrow (getBody (fileName)), attachments);
804 dlg->StepIt ();
806 if (dlg->CheckCancelButton ())
807 break;
810 delete dlg;
811 dlg = 0;
814 //-- log the filenames to a file
816 CStdioFile outfile;
817 if (outfile.Open (_T("minidump.log"), CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::typeText))
819 //-- seek to the end of the log file
820 outfile.SeekToEnd ();
822 //-- write the header
823 time_t osTime;
824 time (&osTime);
825 CTime const ctime (osTime);
826 CString const header = ctime.Format(_T("-- %Y-%m-%d %H:%M "));
827 outfile.WriteString (header + (sendMinidumps ? _T("sent") : _T("not sent")) + '\n');
829 //-- write the file
830 for (size_t i = 0; i < fileNameList.size (); ++i)
832 //-- write the file name and the exception or fatal string
833 CString const fileName = fileNameList [i].c_str ();
834 outfile.WriteString (fileName + ".txt " + getCode (fileName) + '\n');
836 std::string const file1(wideToNarrow(fileName) + ".txt");
837 std::string const file2(wideToNarrow(fileName) + ".mdmp");
838 std::string const file3(wideToNarrow(fileName) + ".log");
840 //-- delete the files
841 RemoveFile (file1.c_str());
842 RemoveFile (file2.c_str());
843 RemoveFile (file3.c_str());
846 outfile.WriteString (_T("\n"));
850 CString detectedStr;
851 VERIFY(detectedStr.LoadString(IDS_DETECTED_CRASH));
852 AfxMessageBox (detectedStr, NULL, MB_ICONINFORMATION | MB_OK);
856 // ----------------------------------------------------------------------
858 void SwgClientSetupApp::detectAndSendHardwareInformation ()
860 if (getAutomaticallySendHardwareInformation())
862 DWORD const savedInformationCrc = getRegistryKey(cms_informationCrcRegistryKey);
863 CString const informationString = ClientMachine::getHardwareInformationString() + Options::getInformationString();
864 DWORD const informationCrc = Crc::calculate(wideToNarrow(informationString).c_str());
865 if (informationCrc != savedInformationCrc)
867 CString const stationId = getStationId(AfxGetApp()->m_lpCmdLine);
869 setRegistryKey(cms_informationCrcRegistryKey, informationCrc);
870 CString const subject = _T("machine description from ") + stationId;
871 std::vector<std::string> const attachments;
872 sendMail(cms_toEmailAddress, cms_fromEmailAddress, wideToNarrow(subject), wideToNarrow(informationString), attachments);
877 DWORD const savedHardwareInformationCrc = getRegistryKey(cms_hardwareInformationCrcRegistryKey);
878 CString const hardwareInformationString = ClientMachine::getHardwareInformationString();
879 DWORD const hardwareInformationCrc = Crc::calculate(wideToNarrow(hardwareInformationString).c_str());
880 if (hardwareInformationCrc != savedHardwareInformationCrc)
882 setRegistryKey(cms_hardwareInformationCrcRegistryKey, hardwareInformationCrc);
883 setRegistryKey(cms_machineRequirementsDisplayCountRegistryKey, 0);
888 // ----------------------------------------------------------------------
890 TCHAR const * SwgClientSetupApp::getSendMinidumpsString ()
892 CString sendMinidumpsString;
893 VERIFY(sendMinidumpsString.LoadString(IDS_PLEASE_SEND_LOG));
894 return sendMinidumpsString;
897 // ----------------------------------------------------------------------
899 bool SwgClientSetupApp::getSendMinidumps ()
901 return getRegistryKey (cms_sendMinidumpsRegistryKey) != 0;
904 // ----------------------------------------------------------------------
906 void SwgClientSetupApp::setSendMinidumps (bool const sendMinidumps)
908 setRegistryKey (cms_sendMinidumpsRegistryKey, sendMinidumps ? 1 : 0);
911 // ----------------------------------------------------------------------
913 TCHAR const * SwgClientSetupApp::getSendStationIdString ()
915 CString str;
916 VERIFY(str.LoadString(IDS_SEND_STATION_ID));
917 return str;
920 // ----------------------------------------------------------------------
922 TCHAR const * SwgClientSetupApp::getAutomaticallySendHardwareInformationString ()
924 CString str;
925 VERIFY(str.LoadString(IDS_AUTOMATICALLY_SEND_HARDWARE));
926 return str;
929 // ----------------------------------------------------------------------
930 bool SwgClientSetupApp::getAutomaticallySendHardwareInformation ()
932 return getRegistryKey (cms_sendHardwareInformationRegistryKey) != 0;
935 // ----------------------------------------------------------------------
937 void SwgClientSetupApp::setAutomaticallySendHardwareInformation (bool const automaticallySendHardwareInformation)
939 setRegistryKey (cms_sendHardwareInformationRegistryKey, automaticallySendHardwareInformation ? 1 : 0);
942 // ----------------------------------------------------------------------
944 TCHAR const * SwgClientSetupApp::getAllowContactString ()
946 CString str;
947 VERIFY(str.LoadString(IDS_ALLOW_CONTACT));
948 return str;
951 // ----------------------------------------------------------------------
953 TCHAR const * SwgClientSetupApp::getThankYouString ()
955 CString str;
956 VERIFY(str.LoadString(IDS_THANK_YOU));
957 return str;
960 // ======================================================================