dw.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. //===========================================================================//
  2. // Copyright (C) Microsoft Corporation. All rights reserved. //
  3. //===========================================================================//
  4. #include <windows.h>
  5. #include <stdio.h>
  6. #include "msodw.h"
  7. #include "utilities.h"
  8. #include "..\resource.h"
  9. #include <gameos.hpp>
  10. long _stdcall ProcessException( EXCEPTION_POINTERS* ep );
  11. extern HWND hWindow;
  12. void EnterWindowMode();
  13. #define EXTERNAL
  14. //--------------------------------------------------------------------------------------------
  15. //DW Exception Code for MC2.
  16. //
  17. // Simple, really. Setup the exception filter by calling InitDW.
  18. // After DW is inited, ANY exception which occurs in ANY thread will be handed
  19. // to DW first. Any problem with running DW OR when DW ends, the GameOS exception handler
  20. // will triggered to give even more data to the user.
  21. //
  22. //--------------------------------------------------------------------------------------------
  23. char WatsonCrashMessage[4096];
  24. //Will be allocated below.
  25. WCHAR *WatsonCrashMessageUnicode = NULL;
  26. /*
  27. * AnsiToUnicode converts the ANSI string pszA to a Unicode string
  28. * and returns the Unicode string through ppszW. Space for the
  29. * the converted string is allocated by AnsiToUnicode.
  30. */
  31. HRESULT __fastcall AnsiToUnicode(LPCSTR pszA, LPOLESTR* ppszW)
  32. {
  33. ULONG cCharacters;
  34. DWORD dwError;
  35. // If input is null then just return the same.
  36. if (NULL == pszA)
  37. {
  38. *ppszW = NULL;
  39. return NOERROR;
  40. }
  41. // Determine number of wide characters to be allocated for the
  42. // Unicode string.
  43. cCharacters = strlen(pszA)+1;
  44. // Use of the OLE allocator is required if the resultant Unicode
  45. // string will be passed to another COM component and if that
  46. // component will free it. Otherwise you can use your own allocator.
  47. *ppszW = (LPOLESTR)malloc(cCharacters*2);
  48. if (NULL == *ppszW)
  49. return E_OUTOFMEMORY;
  50. // Covert to Unicode.
  51. if (0 == MultiByteToWideChar(CP_ACP, 0, pszA, cCharacters,
  52. *ppszW, cCharacters))
  53. {
  54. dwError = GetLastError();
  55. free(*ppszW);
  56. *ppszW = NULL;
  57. return HRESULT_FROM_WIN32(dwError);
  58. }
  59. return NOERROR;
  60. }
  61. //----------------------------------------------------------------------------
  62. // ORIGINAL source from testCrash.cpp.
  63. // %%Function: DwHandleException
  64. // %%Contact: MRuhlen
  65. // Calls DW in the event of an exception
  66. // Calls GameOS exception handler AFTER DW has had a crack at it.
  67. //----------------------------------------------------------------------------
  68. LONG WINAPI DwExceptionFilter(LPEXCEPTION_POINTERS pep)
  69. {
  70. EXCEPTION_RECORD *per;
  71. HANDLE hFileMap;
  72. DWSharedMem *pdwsm;
  73. SECURITY_ATTRIBUTES sa;
  74. //------------------------------------------------------------------------------------------------------------
  75. // we keep local copies of these in case another thread is trashing memory
  76. // it much more likely to trash the heap than our stack
  77. HANDLE hEventDone; // event DW signals when done
  78. HANDLE hEventAlive; // heartbeat event DW signals per EVENT_TIMEOUT
  79. HANDLE hMutex; // to protect the signaling of EventDone
  80. char szCommandLine[MAX_PATH * 2];
  81. DWORD dw;
  82. BOOL fDwRunning;
  83. STARTUPINFO si;
  84. PROCESS_INFORMATION pi;
  85. //------------------------------------------------------------------------------------------------------------
  86. // init - Check if we just hit a breakpoint. If so, continue execution. Debugger will take care of itself.
  87. per = pep->ExceptionRecord;
  88. if (EXCEPTION_BREAKPOINT == per->ExceptionCode)
  89. return 0;
  90. //------------------------------------------------------------------------------------------------------------
  91. // create shared memory
  92. memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
  93. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  94. sa.bInheritHandle = TRUE;
  95. hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, sizeof(DWSharedMem), NULL);
  96. if (hFileMap == NULL)
  97. {
  98. //At this point, call the GameOS exception handler and convert the pep to the data they need!
  99. ProcessException(pep);
  100. return 1;
  101. }
  102. pdwsm = (DWSharedMem *) MapViewOfFile(hFileMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  103. if (pdwsm == NULL)
  104. {
  105. //At this point, call the GameOS exception handler and convert the pep to the data they need!
  106. ProcessException(pep);
  107. return 1;
  108. }
  109. memset(pdwsm, 0, sizeof(DWSharedMem));
  110. hEventAlive = CreateEvent(&sa, FALSE, FALSE, NULL);
  111. hEventDone = CreateEvent(&sa, FALSE, FALSE, NULL);
  112. hMutex = CreateMutex(&sa, FALSE, NULL);
  113. if (!DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &pdwsm->hProc, PROCESS_ALL_ACCESS, TRUE, 0))
  114. {
  115. //At this point, call the GameOS exception handler and convert the pep to the data they need!
  116. ProcessException(pep);
  117. return 1;
  118. }
  119. if (hEventAlive == NULL || hEventDone == NULL || hMutex == NULL || pdwsm->hProc == NULL)
  120. {
  121. //At this point, call the GameOS exception handler and convert the pep to the data they need!
  122. ProcessException(pep);
  123. return 1;
  124. }
  125. //------------------------------------------------------------------------------------------------------------
  126. // setup interface structure
  127. pdwsm->pid = GetCurrentProcessId();
  128. pdwsm->tid = GetCurrentThreadId();
  129. pdwsm->hEventAlive = hEventAlive;
  130. pdwsm->hEventDone = hEventDone;
  131. pdwsm->hMutex = hMutex;
  132. pdwsm->dwSize = sizeof(DWSharedMem);
  133. pdwsm->pep = pep;
  134. pdwsm->eip = (DWORD) pep->ExceptionRecord->ExceptionAddress;
  135. pdwsm->bfmsoctdsOffer = msoctdsQuit;
  136. pdwsm->bfmsoctdsLetRun = msoctdsQuit;
  137. pdwsm->bfDWBehaviorFlags = fDwCheckSig;
  138. strcpy(pdwsm->szFormalAppName, Environment.applicationName);
  139. strcpy(pdwsm->szInformalAppName, "MechCommander 2");
  140. strcpy(pdwsm->szRegSubPath, "Software\\Microsoft\\Microsoft Games\\");
  141. strcat(pdwsm->szRegSubPath, Environment.applicationName);
  142. // strcpy(pdwsm->szLCIDKeyValue, "");
  143. // strcpy(pdwsm->szPIDRegKey, "HKLM\\Software\\Microsoft\\Internet Explorer\\Registration\\DigitalProductID");
  144. #if defined(FINAL) || defined(EXTERNAL)
  145. strcpy(pdwsm->szServer, "watson.microsoft.com");
  146. #else
  147. strcpy(pdwsm->szServer, "officewatson");
  148. #endif
  149. wcscpy(pdwsm->wzErrorMessage, WatsonCrashMessageUnicode);
  150. //Leave this alone? No idea what it does. Not in Docs.
  151. // OK, I kinda know now. These are DLLs that Watson can check for goodness at crash time.
  152. // COOL, because the end user might have mucked with the EXE or data and this allows us to
  153. // report that information back to the server.
  154. memcpy(pdwsm->wzDotDataDlls, L"mc2res.dll\0editores.dll\0", 24 * sizeof(WCHAR));
  155. GetModuleFileNameA(NULL, pdwsm->szModuleFileName, DW_MAX_PATH);
  156. //Additional Files for MechCommander? Should there be any? Log files, etc.
  157. // ok, now we don't want to accidently change this
  158. memset(&si, 0, sizeof(STARTUPINFO));
  159. si.cb = sizeof(STARTUPINFO);
  160. memset(&pi, 0, sizeof(PROCESS_INFORMATION));
  161. wsprintfA(szCommandLine, "dw -x -s %u", (DWORD) hFileMap);
  162. //Check if we are in fullScreen mode. If so, switch back to WindowMode to insure DW screen comes up.
  163. if(Environment.fullScreen && hWindow )
  164. EnterWindowMode();
  165. if (CreateProcessA(NULL, szCommandLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
  166. {
  167. fDwRunning = TRUE;
  168. while (fDwRunning)
  169. {
  170. if (WaitForSingleObject(hEventAlive, DW_TIMEOUT_VALUE * 100) == WAIT_OBJECT_0)
  171. {
  172. if (WaitForSingleObject(hEventDone, 1) == WAIT_OBJECT_0)
  173. {
  174. fDwRunning = FALSE;
  175. }
  176. continue;
  177. }
  178. // we timed-out waiting for DW to respond, try to quit
  179. dw = WaitForSingleObject(hMutex, DW_TIMEOUT_VALUE);
  180. if (dw == WAIT_TIMEOUT)
  181. {
  182. fDwRunning = FALSE; // either DW's hung or crashed, we must carry on
  183. }
  184. else if (dw == WAIT_ABANDONED)
  185. {
  186. fDwRunning = FALSE;
  187. ReleaseMutex(hMutex);
  188. }
  189. else
  190. {
  191. // DW has not woken up?
  192. if (WaitForSingleObject(hEventAlive, 1) != WAIT_OBJECT_0)
  193. // tell DW we're through waiting for it's sorry self
  194. {
  195. SetEvent(hEventDone);
  196. fDwRunning = FALSE;
  197. }
  198. else
  199. {
  200. // are we done
  201. if (WaitForSingleObject(hEventDone, 1) == WAIT_OBJECT_0)
  202. fDwRunning = FALSE;
  203. }
  204. ReleaseMutex(hMutex);
  205. }
  206. }
  207. #if 0
  208. // did we get attached?
  209. // Again, do NOT term the current APP. Late GameOS have its shot at the exception.
  210. if (WaitForSingleObject(hEventDBAttach, 1) == WAIT_OBJECT_0)
  211. {
  212. // yes, die
  213. MessageBox(NULL, "DB Attach ", "out", MB_OK);
  214. CloseHandle(hEventAlive);
  215. CloseHandle(hEventDone);
  216. CloseHandle(hMutex);
  217. TerminateProcess(GetCurrentProcess(), 0);
  218. }
  219. #endif
  220. // no, clean up
  221. CloseHandle(hEventAlive);
  222. CloseHandle(hEventDone);
  223. CloseHandle(hMutex);
  224. } // end if CreateProcess succeeded
  225. UnmapViewOfFile(pdwsm);
  226. CloseHandle(hFileMap);
  227. //At this point, call the GameOS exception handler and convert the pep to the data they need!
  228. ProcessException(pep);
  229. return 1;
  230. }
  231. //----------------------------------------------------------------------------
  232. void InitDW (void)
  233. {
  234. cLoadString(IDS_WATSON_CRASH_MSG,WatsonCrashMessage,4095);
  235. AnsiToUnicode(WatsonCrashMessage,&WatsonCrashMessageUnicode);
  236. SetUnhandledExceptionFilter(DwExceptionFilter);
  237. }
  238. //----------------------------------------------------------------------------