Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

735 lines
20 KiB

  1. /******************************************************************************
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. faulth.c
  5. Abstract:
  6. Implements fault reporting functions
  7. Revision History:
  8. Much of this code taken from admin\pchealth\client\faultrep
  9. ******************************************************************************/
  10. #include <windows.h>
  11. #include <winver.h>
  12. #include <ntverp.h>
  13. #include <errorrep.h>
  14. #include "util.h"
  15. #include "faulth.h"
  16. //#define TEST_WATSON 1
  17. static LPWSTR
  18. plstrcpynW(
  19. LPWSTR lpString1,
  20. LPCWSTR lpString2,
  21. int iMaxLength
  22. )
  23. {
  24. LPWSTR src,dst;
  25. __try {
  26. src = (LPWSTR)lpString2;
  27. dst = lpString1;
  28. if ( iMaxLength ) {
  29. while(iMaxLength && *src){
  30. *dst++ = *src++;
  31. iMaxLength--;
  32. }
  33. if ( iMaxLength ) {
  34. *dst = '\0';
  35. }
  36. else {
  37. dst--;
  38. *dst = '\0';
  39. }
  40. }
  41. }
  42. __except (EXCEPTION_EXECUTE_HANDLER) {
  43. return NULL;
  44. }
  45. return lpString1;
  46. }
  47. #define sizeofSTRW(wsz) sizeof(wsz) / sizeof(wsz[0])
  48. ///////////////////////////////////////////////////////////////////////////////
  49. // Global stuff
  50. #ifdef TEST_WATSON
  51. const CHAR c_szDWDefServerI[] = "officewatson";
  52. #else
  53. const CHAR c_szDWDefServerI[] = "watson.microsoft.com";
  54. #endif
  55. const CHAR c_szDWBrand[] = "WINDOWS";
  56. const WCHAR c_wzDWDefAppName[] = L"Application";
  57. const CHAR c_wszDWCmdLineU[] = "%s\\dwwin.exe -x -s %lu";
  58. #define c_DWDefaultLCID 1033
  59. _inline DWORD RolloverSubtract(DWORD dwA, DWORD dwB)
  60. {
  61. return (dwA >= dwB) ? (dwA - dwB) : (dwA + ((DWORD)-1 - dwB));
  62. }
  63. #ifdef TEST_WATSON
  64. HANDLE hFaultLog = INVALID_HANDLE_VALUE;
  65. char *c_wszLogFileName = "faulth.log";
  66. // Need to synchroize this?
  67. static DebugLog(char *pszMessage, ...)
  68. {
  69. va_list arglist;
  70. if( !pszMessage)
  71. return 0;
  72. va_start(arglist,pszMessage);
  73. if (hFaultLog != INVALID_HANDLE_VALUE)
  74. {
  75. SYSTEMTIME st;
  76. DWORD cb, cbWritten;
  77. char szMsg[512];
  78. GetSystemTime(&st);
  79. cb = wsprintf(szMsg,
  80. "%02d-%02d-%04d %02d:%02d:%02d ",
  81. st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond
  82. );
  83. WriteFile(hFaultLog, szMsg, cb, &cbWritten, NULL);
  84. /*cb = FormatMessageA(
  85. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  86. pszMessage,
  87. 0,0,
  88. szMsg,
  89. 0,
  90. &arglist
  91. );*/
  92. cb = wsprintf(szMsg, pszMessage, &arglist);
  93. WriteFile(hFaultLog, szMsg, cb, &cbWritten, NULL);
  94. }
  95. va_end(arglist);
  96. return 1;
  97. }
  98. #else
  99. #define DebugLog(x)
  100. #endif
  101. HINSTANCE g_hInstance = NULL;
  102. ///////////////////////////////////////////////////////////////////////////////
  103. // DllMain
  104. // **************************************************************************
  105. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  106. {
  107. switch(dwReason)
  108. {
  109. case DLL_PROCESS_ATTACH:
  110. g_hInstance = hInstance;
  111. //DisableThreadLibraryCalls(hInstance);
  112. break;
  113. case DLL_PROCESS_DETACH:
  114. break;
  115. }
  116. return TRUE;
  117. }
  118. static
  119. EFaultRepRetVal
  120. StartDWException(
  121. IN PSETUP_FAULT_HANDLER This,
  122. IN LPEXCEPTION_POINTERS pep,
  123. IN DWORD dwOpt,
  124. IN DWORD dwFlags,
  125. IN DWORD dwTimeToWait)
  126. {
  127. SECURITY_ATTRIBUTES sa;
  128. PROCESS_INFORMATION pi;
  129. EFaultRepRetVal frrvRet = frrvErrNoDW;
  130. DWSharedMem15 *pdwsm = NULL;
  131. STARTUPINFOA si;
  132. HRESULT hr = NOERROR;
  133. HANDLE hevDone = NULL, hevAlive = NULL, hmut = NULL;
  134. HANDLE hfmShared = NULL, hProc = NULL;
  135. HANDLE rghWait[2];
  136. DWORD dw, dwStart;
  137. BOOL fDWRunning = TRUE;
  138. char szCmdLine[MAX_PATH], szDir[MAX_PATH];
  139. char szModuleFileName[DW_MAX_PATH];
  140. char *pch;
  141. VALIDATEPARM(hr, (pep == NULL));
  142. if (FAILED(hr))
  143. goto done;
  144. // we need the following things to be inheritable, so create a SD that
  145. // says it can be.
  146. ZeroMemory(&sa, sizeof(sa));
  147. sa.nLength = sizeof(sa);
  148. sa.bInheritHandle = TRUE;
  149. // create the necessary events & mutexes
  150. hevDone = CreateEvent(&sa, FALSE, FALSE, NULL);
  151. TESTBOOL(hr, (hevDone != NULL));
  152. if (FAILED(hr))
  153. goto done;
  154. hevAlive = CreateEvent(&sa, FALSE, FALSE, NULL);
  155. TESTBOOL(hr, (hevAlive != NULL));
  156. if (FAILED(hr))
  157. goto done;
  158. hmut = CreateMutex(&sa, FALSE, NULL);
  159. TESTBOOL(hr, (hmut != NULL));
  160. if (FAILED(hr))
  161. goto done;
  162. TESTBOOL(hr, DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(),
  163. GetCurrentProcess(), &hProc,
  164. PROCESS_ALL_ACCESS, TRUE, 0));
  165. if (FAILED(hr))
  166. goto done;
  167. // create the shared memory region & map it
  168. hfmShared = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0,
  169. sizeof(DWSharedMem), NULL);
  170. TESTBOOL(hr, (hfmShared != NULL));
  171. if (FAILED(hr))
  172. goto done;
  173. pdwsm = (DWSharedMem *)MapViewOfFile(hfmShared,
  174. FILE_MAP_READ | FILE_MAP_WRITE, 0, 0,
  175. 0);
  176. TESTBOOL(hr, (pdwsm != NULL));
  177. if (FAILED(hr))
  178. goto done;
  179. // populate all the stuff that DW needs
  180. ZeroMemory(pdwsm, sizeof(DWSharedMem15));
  181. pdwsm->dwSize = sizeof(DWSharedMem15);
  182. pdwsm->pid = GetCurrentProcessId();
  183. pdwsm->tid = GetCurrentThreadId();
  184. pdwsm->eip = (DWORD_PTR)pep->ExceptionRecord->ExceptionAddress;
  185. pdwsm->pep = pep;
  186. pdwsm->hEventDone = hevDone;
  187. pdwsm->hEventNotifyDone = NULL;
  188. pdwsm->hEventAlive = hevAlive;
  189. pdwsm->hMutex = hmut;
  190. pdwsm->hProc = hProc;
  191. pdwsm->bfDWBehaviorFlags = dwFlags;
  192. pdwsm->msoctdsResult = msoctdsNull;
  193. pdwsm->fReportProblem = FALSE;
  194. pdwsm->bfmsoctdsOffer = msoctdsQuit;
  195. pdwsm->bfmsoctdsNotify = 0;
  196. if (dwOpt == 1)
  197. pdwsm->bfmsoctdsOffer |= msoctdsDebug;
  198. pdwsm->bfmsoctdsLetRun = pdwsm->bfmsoctdsOffer;
  199. pdwsm->iPingCurrent = 0;
  200. pdwsm->iPingEnd = 0;
  201. pdwsm->lcidUI = 1033;
  202. lstrcpynA( pdwsm->szServer, This->szURL, DW_MAX_SERVERNAME);
  203. lstrcpynA( pdwsm->szBrand, c_szDWBrand, DW_APPNAME_LENGTH);
  204. GetModuleFileNameA( NULL, szModuleFileName, DW_MAX_PATH);
  205. MultiByteToWideChar( CP_ACP, 0, szModuleFileName, -1, pdwsm->wzModuleFileName, DW_MAX_PATH);
  206. plstrcpynW( pdwsm->wzFormalAppName, This->wzAppName, DW_APPNAME_LENGTH);
  207. plstrcpynW( pdwsm->wzAdditionalFile, This->wzAdditionalFiles, DW_MAX_ADDFILES);
  208. plstrcpynW( pdwsm->wzErrorText, This->wzErrorText, DW_MAX_ERROR_CWC);
  209. // create the process
  210. if (!GetModuleFileNameA( g_hInstance, szDir, MAX_PATH) ||
  211. !(pch = strrchr (szDir, '\\'))) {
  212. goto done;
  213. }
  214. *pch = '\0';
  215. wsprintf( szCmdLine, c_wszDWCmdLineU, szDir, hfmShared);
  216. DebugLog( "CommandLine ");
  217. DebugLog( szCmdLine);
  218. DebugLog( "CurrentDir ");
  219. DebugLog( szDir);
  220. ZeroMemory(&si, sizeof(si));
  221. ZeroMemory(&pi, sizeof(pi));
  222. si.cb = sizeof(si);
  223. si.lpDesktop = "Winsta0\\Default";
  224. TESTBOOL(hr, CreateProcessA(NULL, szCmdLine, NULL, NULL, TRUE,
  225. CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
  226. NULL, szDir, &si, &pi));
  227. if (FAILED(hr))
  228. goto done;
  229. // don't need the thread handle & we gotta close it, so close it now
  230. CloseHandle(pi.hThread);
  231. // assume we succeed from here on...
  232. frrvRet = frrvOk;
  233. rghWait[0] = hevAlive;
  234. rghWait[1] = pi.hProcess;
  235. dwStart = GetTickCount();
  236. while(fDWRunning)
  237. {
  238. // gotta periodically get the Alive signal from DW.
  239. switch(WaitForMultipleObjects(2, rghWait, FALSE, 120000))
  240. {
  241. case WAIT_OBJECT_0:
  242. if (WaitForSingleObject(hevDone, 0) == WAIT_OBJECT_0)
  243. fDWRunning = FALSE;
  244. if (dwTimeToWait != (DWORD)-1 &&
  245. RolloverSubtract(GetTickCount(), dwStart) > dwTimeToWait)
  246. {
  247. frrvRet = frrvErrTimeout;
  248. fDWRunning = FALSE;
  249. }
  250. continue;
  251. case WAIT_OBJECT_0 + 1:
  252. fDWRunning = FALSE;
  253. continue;
  254. }
  255. switch(WaitForSingleObject(hmut, DW_TIMEOUT_VALUE))
  256. {
  257. // yay! we got the mutex. Try to detemine if DW finally responded
  258. // while we were grabbing the mutex.
  259. case WAIT_OBJECT_0:
  260. switch(WaitForMultipleObjects(2, rghWait, FALSE, 0))
  261. {
  262. // If it hasn't responded, tell it to go away & fall thru
  263. // into the 'it died' case.
  264. case WAIT_TIMEOUT:
  265. SetEvent(hevDone);
  266. // It died. Clean up.
  267. case WAIT_OBJECT_0 + 1:
  268. fDWRunning = FALSE;
  269. frrvRet = frrvErrNoDW;
  270. continue;
  271. }
  272. // ok, it responded. Is it done?
  273. if (WaitForSingleObject(hevDone, 0) == WAIT_OBJECT_0)
  274. fDWRunning = FALSE;
  275. ReleaseMutex(hmut);
  276. break;
  277. // if the wait was abandoned, it means DW has gone to the great bit
  278. // bucket in the sky without cleaning up. So release the mutex and
  279. // fall into the default case
  280. case WAIT_ABANDONED:
  281. ReleaseMutex(hmut);
  282. // if we timed out or otherwise failed, just die.
  283. default:
  284. frrvRet = frrvErrNoDW;
  285. fDWRunning = FALSE;
  286. break;
  287. }
  288. }
  289. if (frrvRet != frrvOk)
  290. {
  291. CloseHandle(pi.hProcess);
  292. goto done;
  293. }
  294. // if user told us to debug, return that back to the
  295. if (pdwsm->msoctdsResult == msoctdsDebug)
  296. frrvRet = frrvLaunchDebugger;
  297. // if we're going to launch Dr. Watson, wait for the DW process to die.
  298. // Give it 5 minutes. If the user doesn't hit close by then, just return
  299. // anyway...
  300. if (dwOpt == (DWORD)-1)
  301. {
  302. if (WaitForSingleObject(pi.hProcess, 300000) == WAIT_TIMEOUT)
  303. frrvRet = frrvErrTimeout;
  304. }
  305. CloseHandle(pi.hProcess);
  306. done:
  307. // preserve the error code so that the following calls don't overwrite it
  308. dw = GetLastError();
  309. if (pdwsm != NULL)
  310. UnmapViewOfFile(pdwsm);
  311. if (hfmShared != NULL)
  312. CloseHandle(hfmShared);
  313. if (hevDone != NULL)
  314. CloseHandle(hevDone);
  315. if (hevAlive != NULL)
  316. CloseHandle(hevAlive);
  317. if (hmut != NULL)
  318. CloseHandle(hmut);
  319. if (hProc != NULL)
  320. CloseHandle(hProc);
  321. SetLastError(dw);
  322. return frrvRet;
  323. }
  324. static
  325. EFaultRepRetVal
  326. FaultHandler(
  327. IN PSETUP_FAULT_HANDLER This,
  328. IN EXCEPTION_POINTERS *pep,
  329. IN DWORD dwOpt)
  330. {
  331. EFaultRepRetVal frrvRet = frrvErrNoDW;
  332. DWORD dwFlags = 0;
  333. char wszFile[MAX_PATH], *pwsz;
  334. DebugLog("Inside FaultHandler\r\n");
  335. GetModuleFileNameA(NULL, wszFile, sizeof(wszFile)/sizeof(wszFile[0]));
  336. // Find last backslash
  337. for(pwsz = wszFile + strlen(wszFile);
  338. pwsz >= wszFile && *pwsz != L'\\';
  339. pwsz--);
  340. // Should never happen
  341. if (pwsz < wszFile)
  342. goto done;
  343. if (*pwsz == L'\\')
  344. pwsz++;
  345. // Don't want to debug dwwin.exe itself.
  346. if (_stricmp(pwsz, "dwwin.exe") == 0
  347. // || _stricmp(pwsz, "dumprep.exe") == 0
  348. )
  349. goto done;
  350. frrvRet = StartDWException(This, pep, dwOpt, dwFlags, -1);
  351. done:
  352. return frrvRet;
  353. }
  354. static
  355. BOOL
  356. FAULTHIsSupported(
  357. IN PSETUP_FAULT_HANDLER This
  358. )
  359. {
  360. BOOL useExtendedInfo;
  361. DWORD dwServicePack;
  362. DWORD dwVersion,dwTemp,dwInfoSize;
  363. char *pInfo;
  364. VS_FIXEDFILEINFO *VsInfo;
  365. UINT DataLength;
  366. union {
  367. OSVERSIONINFO Normal;
  368. OSVERSIONINFOEX Ex;
  369. } Ovi;
  370. DebugLog("Inside FAULTHIsSupported\r\n");
  371. if ( !This) {
  372. return(FALSE);
  373. }
  374. useExtendedInfo = TRUE;
  375. Ovi.Ex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  376. if (!GetVersionEx((OSVERSIONINFO *)&Ovi.Ex) ) {
  377. //
  378. // EX size not available; try the normal one
  379. //
  380. Ovi.Normal.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  381. if (!GetVersionEx((OSVERSIONINFO *)&Ovi.Normal) ) {
  382. DebugLog("Inside FAULTHIsSupported:Could not get os version!\r\n");
  383. return(FALSE);
  384. }
  385. useExtendedInfo = FALSE;
  386. }
  387. if (useExtendedInfo) {
  388. dwServicePack = Ovi.Ex.wServicePackMajor * 100 + Ovi.Ex.wServicePackMinor;
  389. } else {
  390. dwServicePack = 0;
  391. }
  392. dwVersion = Ovi.Normal.dwMajorVersion * 100 + Ovi.Normal.dwMinorVersion;
  393. switch (Ovi.Normal.dwPlatformId) {
  394. case VER_PLATFORM_WIN32s:
  395. DebugLog("Inside FAULTHIsSupported:Unsupported win32s!\r\n");
  396. return(FALSE);
  397. break;
  398. case VER_PLATFORM_WIN32_WINDOWS:
  399. if( dwVersion < 410) {
  400. DebugLog("Inside FAULTHIsSupported:Unsupported win9x!\r\n");
  401. return(FALSE);
  402. }
  403. break;
  404. case VER_PLATFORM_WIN32_NT:
  405. if( dwVersion < 400) {
  406. DebugLog("Inside FAULTHIsSupported:Unsupported winNT!\r\n");
  407. return(FALSE);
  408. }
  409. if( dwVersion == 400 && dwServicePack < 500) {
  410. DebugLog("Inside FAULTHIsSupported:Unsupported ServicePack!\r\n");
  411. return(FALSE);
  412. }
  413. break;
  414. default:
  415. return(FALSE);
  416. }
  417. // Test for wininet.dll from ie 4.01.
  418. dwInfoSize = GetFileVersionInfoSize( FAULTH_WININET_NAME, &dwTemp );
  419. if( !dwInfoSize) {
  420. DebugLog("Inside FAULTHIsSupported:Could not find wininet.dll or determine version.");
  421. return( FALSE);
  422. }
  423. pInfo = HeapAlloc( GetProcessHeap(), 0, dwInfoSize);
  424. if( !pInfo ||
  425. !GetFileVersionInfo( FAULTH_WININET_NAME, dwTemp, dwInfoSize, pInfo) ||
  426. !VerQueryValue( pInfo, "\\", &VsInfo, &DataLength))
  427. {
  428. DebugLog("Inside FAULTHIsSupported:Could not find wininet.dll or get version.");
  429. HeapFree( GetProcessHeap(), 0, pInfo);
  430. return( FALSE);
  431. }
  432. if( VsInfo->dwFileVersionMS < FAULTH_WININET_MIN_MS ||
  433. ((VsInfo->dwFileVersionMS == FAULTH_WININET_MIN_MS) && (VsInfo->dwFileVersionLS < FAULTH_WININET_MIN_LS))) {
  434. DebugLog("Inside FAULTHIsSupported:Require a more recent wininet.dll.");
  435. HeapFree( GetProcessHeap(), 0, pInfo);
  436. return( FALSE);
  437. }
  438. HeapFree( GetProcessHeap(), 0, pInfo);
  439. return(TRUE);
  440. }
  441. static
  442. void
  443. FAULTHSetURLA(
  444. IN PSETUP_FAULT_HANDLER This,
  445. IN PCSTR pszURL
  446. )
  447. {
  448. DebugLog("Inside FAULTHSetURLA\r\n");
  449. if (This && pszURL){
  450. lstrcpynA( This->szURL, pszURL, DW_MAX_SERVERNAME);
  451. }
  452. }
  453. static
  454. void
  455. FAULTHSetURLW(
  456. IN PSETUP_FAULT_HANDLER This,
  457. IN PCWSTR pwzURL
  458. )
  459. {
  460. DebugLog("Inside FAULTHSetURLW\r\n");
  461. if (This && pwzURL){
  462. WideCharToMultiByte( CP_ACP, 0, pwzURL, -1, This->szURL, DW_MAX_SERVERNAME, NULL, NULL);
  463. }
  464. }
  465. static
  466. void
  467. FAULTHSetErrorTextA(
  468. IN PSETUP_FAULT_HANDLER This,
  469. IN PCSTR pszErrorText
  470. )
  471. {
  472. DebugLog("Inside FAULTHSetErrorTextA\r\n");
  473. if (This && pszErrorText){
  474. MultiByteToWideChar( CP_ACP, 0, pszErrorText, -1, This->wzErrorText, DW_MAX_ERROR_CWC);
  475. }
  476. }
  477. static
  478. void
  479. FAULTHSetErrorTextW(
  480. IN PSETUP_FAULT_HANDLER This,
  481. IN PCWSTR pwzErrorText
  482. )
  483. {
  484. DebugLog("Inside FAULTHSetErrorTextW\r\n");
  485. if (This && pwzErrorText){
  486. plstrcpynW( This->wzErrorText, pwzErrorText, DW_MAX_ERROR_CWC);
  487. }
  488. }
  489. static
  490. void
  491. FAULTHSetAdditionalFilesA(
  492. IN PSETUP_FAULT_HANDLER This,
  493. IN PCSTR pszAdditionalFiles
  494. )
  495. {
  496. DebugLog("Inside FAULTHSetAdditionalFilesA\r\n");
  497. if (This && pszAdditionalFiles){
  498. MultiByteToWideChar( CP_ACP, 0, pszAdditionalFiles, -1, This->wzAdditionalFiles, DW_MAX_ADDFILES);
  499. }
  500. }
  501. static
  502. void
  503. FAULTHSetAdditionalFilesW(
  504. IN PSETUP_FAULT_HANDLER This,
  505. IN PCWSTR pwzAdditionalFiles
  506. )
  507. {
  508. DebugLog("Inside FAULTHSetAdditionalFilesW\r\n");
  509. if (This && pwzAdditionalFiles){
  510. plstrcpynW( This->wzAdditionalFiles, pwzAdditionalFiles, DW_MAX_ADDFILES);
  511. }
  512. }
  513. static
  514. void
  515. FAULTHSetAppNameA(
  516. IN PSETUP_FAULT_HANDLER This,
  517. IN PCSTR pszAppName
  518. )
  519. {
  520. DebugLog("Inside FAULTHAppNameA\r\n");
  521. if (This && pszAppName){
  522. MultiByteToWideChar( CP_ACP, 0, pszAppName, -1, This->wzAppName, DW_APPNAME_LENGTH);
  523. }
  524. }
  525. static
  526. void
  527. FAULTHSetAppNameW(
  528. IN PSETUP_FAULT_HANDLER This,
  529. IN PCWSTR pwzAppName
  530. )
  531. {
  532. DebugLog("Inside FAULTHAppNameW\r\n");
  533. if (This && pwzAppName){
  534. plstrcpynW( This->wzAppName, pwzAppName, DW_APPNAME_LENGTH);
  535. }
  536. }
  537. static
  538. void
  539. FAULTHSetLCID(
  540. IN PSETUP_FAULT_HANDLER This,
  541. IN LCID lcid
  542. )
  543. {
  544. DebugLog("Inside FAULTHSetLCID\r\n");
  545. if (This){
  546. This->lcid = lcid;
  547. }
  548. }
  549. static
  550. VOID
  551. FAULTHInit(
  552. IN PSETUP_FAULT_HANDLER This
  553. )
  554. {
  555. DebugLog("Inside FAULTHInit\r\n");
  556. if( This){
  557. This->SetURLA = FAULTHSetURLA;
  558. This->SetURLW = FAULTHSetURLW;
  559. This->SetAppNameA = FAULTHSetAppNameA;
  560. This->SetAppNameW = FAULTHSetAppNameW;
  561. This->SetErrorTextA = FAULTHSetErrorTextA;
  562. This->SetErrorTextW = FAULTHSetErrorTextW;
  563. This->SetAdditionalFilesA = FAULTHSetAdditionalFilesA;
  564. This->SetAdditionalFilesW = FAULTHSetAdditionalFilesW;
  565. This->SetLCID = FAULTHSetLCID;
  566. This->IsSupported = FAULTHIsSupported;
  567. This->Report = FaultHandler;
  568. This->bDebug = FALSE;
  569. FAULTHSetURLA(This, c_szDWDefServerI);
  570. FAULTHSetAppNameW(This, c_wzDWDefAppName);
  571. FAULTHSetAdditionalFilesW(This, L"");
  572. FAULTHSetErrorTextW(This,L"");
  573. FAULTHSetLCID(This,c_DWDefaultLCID);
  574. }
  575. #ifdef TEST_WATSON
  576. {
  577. char szFile[MAX_PATH], *pwsz;
  578. GetSystemDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0]));
  579. szFile[3] = '\0';
  580. strcat(szFile, c_wszLogFileName);
  581. hFaultLog = CreateFileA(szFile, GENERIC_WRITE,
  582. FILE_SHARE_WRITE | FILE_SHARE_READ,
  583. NULL, OPEN_ALWAYS, 0, NULL);
  584. if (hFaultLog != INVALID_HANDLE_VALUE)
  585. {
  586. SYSTEMTIME st;
  587. DWORD cb, cbWritten;
  588. char szMsg[512];
  589. GetSystemTime(&st);
  590. cb = wsprintf(szMsg,
  591. "%02d-%02d-%04d %02d:%02d:%02d Initalization\r\n",
  592. st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute,
  593. st.wSecond);
  594. SetFilePointer(hFaultLog, 0, NULL, FILE_END);
  595. WriteFile(hFaultLog, szMsg, cb, &cbWritten, NULL);
  596. }
  597. }
  598. DebugLog("exiting FAULTHInit\r\n");
  599. #endif
  600. }
  601. PSETUP_FAULT_HANDLER APIENTRY
  602. FAULTHCreate( VOID)
  603. {
  604. PSETUP_FAULT_HANDLER This = NULL;
  605. DebugLog("Inside FAULTHCreate\r\n");
  606. This = HeapAlloc( GetProcessHeap(), 0, sizeof(SETUP_FAULT_HANDLER));
  607. if( This) {
  608. FAULTHInit( This);
  609. }
  610. DebugLog("exiting FAULTCreate\r\n");
  611. return This;
  612. }
  613. VOID APIENTRY
  614. FAULTHDelete(
  615. IN PSETUP_FAULT_HANDLER This
  616. )
  617. {
  618. DebugLog("Inside FAULTHDelete\r\n");
  619. if( This) {
  620. HeapFree( GetProcessHeap(), 0, This);
  621. }
  622. #ifdef TEST_WATSON
  623. if (hFaultLog != INVALID_HANDLE_VALUE) {
  624. CloseHandle(hFaultLog);
  625. }
  626. #endif
  627. }