748 lines
20 KiB
C
748 lines
20 KiB
C
|
/******************************************************************************
|
||
|
|
||
|
Copyright (c) 2001 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
faulth.c
|
||
|
|
||
|
Abstract:
|
||
|
Implements fault reporting functions
|
||
|
|
||
|
Revision History:
|
||
|
Much of this code taken from admin\pchealth\client\faultrep
|
||
|
|
||
|
******************************************************************************/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <winver.h>
|
||
|
#include <ntverp.h>
|
||
|
#include <errorrep.h>
|
||
|
#include "util.h"
|
||
|
#include "faulth.h"
|
||
|
|
||
|
//#define TEST_WATSON 1
|
||
|
|
||
|
static LPWSTR
|
||
|
plstrcpynW(
|
||
|
LPWSTR lpString1,
|
||
|
LPCWSTR lpString2,
|
||
|
int iMaxLength
|
||
|
)
|
||
|
{
|
||
|
LPWSTR src,dst;
|
||
|
|
||
|
__try {
|
||
|
src = (LPWSTR)lpString2;
|
||
|
dst = lpString1;
|
||
|
|
||
|
if ( iMaxLength ) {
|
||
|
while(iMaxLength && *src){
|
||
|
*dst++ = *src++;
|
||
|
iMaxLength--;
|
||
|
}
|
||
|
if ( iMaxLength ) {
|
||
|
*dst = '\0';
|
||
|
}
|
||
|
else {
|
||
|
dst--;
|
||
|
*dst = '\0';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return lpString1;
|
||
|
}
|
||
|
|
||
|
#define sizeofSTRW(wsz) sizeof(wsz) / sizeof(wsz[0])
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Global stuff
|
||
|
|
||
|
#ifdef TEST_WATSON
|
||
|
const CHAR c_szDWDefServerI[] = "officewatson";
|
||
|
#else
|
||
|
const CHAR c_szDWDefServerI[] = "watson.microsoft.com";
|
||
|
#endif
|
||
|
const CHAR c_szDWBrand[] = "WINDOWS";
|
||
|
const WCHAR c_wzDWDefAppName[] = L"Application";
|
||
|
const CHAR c_wszDWCmdLineU[] = "%s\\dwwin.exe -x -s %lu";
|
||
|
#define c_DWDefaultLCID 1033
|
||
|
|
||
|
_inline DWORD RolloverSubtract(DWORD dwA, DWORD dwB)
|
||
|
{
|
||
|
return (dwA >= dwB) ? (dwA - dwB) : (dwA + ((DWORD)-1 - dwB));
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
MyGetModuleFileNameA(
|
||
|
IN HMODULE Module,
|
||
|
OUT PSTR Buffer,
|
||
|
IN DWORD BufferLength
|
||
|
)
|
||
|
{
|
||
|
DWORD d = GetModuleFileNameA(Module, Buffer, BufferLength);
|
||
|
Buffer[BufferLength - 1] = 0;
|
||
|
return d < BufferLength ? d : 0;
|
||
|
}
|
||
|
|
||
|
#ifdef TEST_WATSON
|
||
|
HANDLE hFaultLog = INVALID_HANDLE_VALUE;
|
||
|
char *c_wszLogFileName = "faulth.log";
|
||
|
|
||
|
// Need to synchroize this?
|
||
|
static DebugLog(char *pszMessage, ...)
|
||
|
{
|
||
|
va_list arglist;
|
||
|
|
||
|
if( !pszMessage)
|
||
|
return 0;
|
||
|
|
||
|
va_start(arglist,pszMessage);
|
||
|
|
||
|
if (hFaultLog != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
SYSTEMTIME st;
|
||
|
DWORD cb, cbWritten;
|
||
|
char szMsg[512];
|
||
|
|
||
|
GetSystemTime(&st);
|
||
|
cb = wsprintf(szMsg,
|
||
|
"%02d-%02d-%04d %02d:%02d:%02d ",
|
||
|
st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond
|
||
|
);
|
||
|
WriteFile(hFaultLog, szMsg, cb, &cbWritten, NULL);
|
||
|
/*cb = FormatMessageA(
|
||
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
|
||
|
pszMessage,
|
||
|
0,0,
|
||
|
szMsg,
|
||
|
0,
|
||
|
&arglist
|
||
|
);*/
|
||
|
cb = wsprintf(szMsg, pszMessage, &arglist);
|
||
|
WriteFile(hFaultLog, szMsg, cb, &cbWritten, NULL);
|
||
|
}
|
||
|
va_end(arglist);
|
||
|
return 1;
|
||
|
}
|
||
|
#else
|
||
|
|
||
|
#define DebugLog(x)
|
||
|
|
||
|
#endif
|
||
|
|
||
|
HINSTANCE g_hInstance = NULL;
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// DllMain
|
||
|
|
||
|
// **************************************************************************
|
||
|
|
||
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
|
||
|
{
|
||
|
switch(dwReason)
|
||
|
{
|
||
|
case DLL_PROCESS_ATTACH:
|
||
|
g_hInstance = hInstance;
|
||
|
//DisableThreadLibraryCalls(hInstance);
|
||
|
break;
|
||
|
|
||
|
case DLL_PROCESS_DETACH:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
static
|
||
|
EFaultRepRetVal
|
||
|
StartDWException(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN LPEXCEPTION_POINTERS pep,
|
||
|
IN DWORD dwOpt,
|
||
|
IN DWORD dwFlags,
|
||
|
IN DWORD dwTimeToWait)
|
||
|
{
|
||
|
SECURITY_ATTRIBUTES sa;
|
||
|
PROCESS_INFORMATION pi;
|
||
|
EFaultRepRetVal frrvRet = frrvErrNoDW;
|
||
|
DWSharedMem15 *pdwsm = NULL;
|
||
|
STARTUPINFOA si;
|
||
|
HRESULT hr = NOERROR;
|
||
|
HANDLE hevDone = NULL, hevAlive = NULL, hmut = NULL;
|
||
|
HANDLE hfmShared = NULL, hProc = NULL;
|
||
|
HANDLE rghWait[2];
|
||
|
DWORD dw, dwStart;
|
||
|
BOOL fDWRunning = TRUE;
|
||
|
char szCmdLine[MAX_PATH], szDir[MAX_PATH];
|
||
|
char szModuleFileName[DW_MAX_PATH];
|
||
|
char *pch;
|
||
|
|
||
|
|
||
|
VALIDATEPARM(hr, (pep == NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
// we need the following things to be inheritable, so create a SD that
|
||
|
// says it can be.
|
||
|
ZeroMemory(&sa, sizeof(sa));
|
||
|
sa.nLength = sizeof(sa);
|
||
|
sa.bInheritHandle = TRUE;
|
||
|
|
||
|
// create the necessary events & mutexes
|
||
|
hevDone = CreateEvent(&sa, FALSE, FALSE, NULL);
|
||
|
TESTBOOL(hr, (hevDone != NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
hevAlive = CreateEvent(&sa, FALSE, FALSE, NULL);
|
||
|
TESTBOOL(hr, (hevAlive != NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
hmut = CreateMutex(&sa, FALSE, NULL);
|
||
|
TESTBOOL(hr, (hmut != NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
TESTBOOL(hr, DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(),
|
||
|
GetCurrentProcess(), &hProc,
|
||
|
PROCESS_ALL_ACCESS, TRUE, 0));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
// create the shared memory region & map it
|
||
|
hfmShared = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0,
|
||
|
sizeof(DWSharedMem), NULL);
|
||
|
TESTBOOL(hr, (hfmShared != NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
pdwsm = (DWSharedMem *)MapViewOfFile(hfmShared,
|
||
|
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0,
|
||
|
0);
|
||
|
TESTBOOL(hr, (pdwsm != NULL));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
|
||
|
// populate all the stuff that DW needs
|
||
|
ZeroMemory(pdwsm, sizeof(DWSharedMem15));
|
||
|
|
||
|
pdwsm->dwSize = sizeof(DWSharedMem15);
|
||
|
pdwsm->pid = GetCurrentProcessId();
|
||
|
pdwsm->tid = GetCurrentThreadId();
|
||
|
pdwsm->eip = (DWORD_PTR)pep->ExceptionRecord->ExceptionAddress;
|
||
|
pdwsm->pep = pep;
|
||
|
pdwsm->hEventDone = hevDone;
|
||
|
pdwsm->hEventNotifyDone = NULL;
|
||
|
pdwsm->hEventAlive = hevAlive;
|
||
|
pdwsm->hMutex = hmut;
|
||
|
pdwsm->hProc = hProc;
|
||
|
pdwsm->bfDWBehaviorFlags = dwFlags;
|
||
|
pdwsm->msoctdsResult = msoctdsNull;
|
||
|
pdwsm->fReportProblem = FALSE;
|
||
|
pdwsm->bfmsoctdsOffer = msoctdsQuit;
|
||
|
pdwsm->bfmsoctdsNotify = 0;
|
||
|
if (dwOpt == 1)
|
||
|
pdwsm->bfmsoctdsOffer |= msoctdsDebug;
|
||
|
pdwsm->bfmsoctdsLetRun = pdwsm->bfmsoctdsOffer;
|
||
|
pdwsm->iPingCurrent = 0;
|
||
|
pdwsm->iPingEnd = 0;
|
||
|
pdwsm->lcidUI = 1033;
|
||
|
|
||
|
lstrcpynA( pdwsm->szServer, This->szURL, DW_MAX_SERVERNAME);
|
||
|
lstrcpynA( pdwsm->szBrand, c_szDWBrand, DW_APPNAME_LENGTH);
|
||
|
MyGetModuleFileNameA( NULL, szModuleFileName, DW_MAX_PATH);
|
||
|
MultiByteToWideChar( CP_ACP, 0, szModuleFileName, -1, pdwsm->wzModuleFileName, DW_MAX_PATH);
|
||
|
|
||
|
plstrcpynW( pdwsm->wzFormalAppName, This->wzAppName, DW_APPNAME_LENGTH);
|
||
|
plstrcpynW( pdwsm->wzAdditionalFile, This->wzAdditionalFiles, DW_MAX_ADDFILES);
|
||
|
plstrcpynW( pdwsm->wzErrorText, This->wzErrorText, DW_MAX_ERROR_CWC);
|
||
|
|
||
|
// create the process
|
||
|
|
||
|
if (!MyGetModuleFileNameA( g_hInstance, szDir, MAX_PATH) ||
|
||
|
!(pch = strrchr (szDir, '\\'))) {
|
||
|
goto done;
|
||
|
}
|
||
|
*pch = '\0';
|
||
|
wsprintf( szCmdLine, c_wszDWCmdLineU, szDir, hfmShared);
|
||
|
DebugLog( "CommandLine ");
|
||
|
DebugLog( szCmdLine);
|
||
|
DebugLog( "CurrentDir ");
|
||
|
DebugLog( szDir);
|
||
|
|
||
|
ZeroMemory(&si, sizeof(si));
|
||
|
ZeroMemory(&pi, sizeof(pi));
|
||
|
|
||
|
si.cb = sizeof(si);
|
||
|
si.lpDesktop = "Winsta0\\Default";
|
||
|
|
||
|
TESTBOOL(hr, CreateProcessA(NULL, szCmdLine, NULL, NULL, TRUE,
|
||
|
CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS,
|
||
|
NULL, szDir, &si, &pi));
|
||
|
if (FAILED(hr))
|
||
|
goto done;
|
||
|
|
||
|
// don't need the thread handle & we gotta close it, so close it now
|
||
|
CloseHandle(pi.hThread);
|
||
|
|
||
|
// assume we succeed from here on...
|
||
|
frrvRet = frrvOk;
|
||
|
|
||
|
rghWait[0] = hevAlive;
|
||
|
rghWait[1] = pi.hProcess;
|
||
|
|
||
|
dwStart = GetTickCount();
|
||
|
while(fDWRunning)
|
||
|
{
|
||
|
// gotta periodically get the Alive signal from DW.
|
||
|
switch(WaitForMultipleObjects(2, rghWait, FALSE, 120000))
|
||
|
{
|
||
|
case WAIT_OBJECT_0:
|
||
|
if (WaitForSingleObject(hevDone, 0) == WAIT_OBJECT_0)
|
||
|
fDWRunning = FALSE;
|
||
|
|
||
|
if (dwTimeToWait != (DWORD)-1 &&
|
||
|
RolloverSubtract(GetTickCount(), dwStart) > dwTimeToWait)
|
||
|
{
|
||
|
frrvRet = frrvErrTimeout;
|
||
|
fDWRunning = FALSE;
|
||
|
}
|
||
|
|
||
|
continue;
|
||
|
|
||
|
case WAIT_OBJECT_0 + 1:
|
||
|
fDWRunning = FALSE;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch(WaitForSingleObject(hmut, DW_TIMEOUT_VALUE))
|
||
|
{
|
||
|
// yay! we got the mutex. Try to detemine if DW finally responded
|
||
|
// while we were grabbing the mutex.
|
||
|
case WAIT_OBJECT_0:
|
||
|
switch(WaitForMultipleObjects(2, rghWait, FALSE, 0))
|
||
|
{
|
||
|
// If it hasn't responded, tell it to go away & fall thru
|
||
|
// into the 'it died' case.
|
||
|
case WAIT_TIMEOUT:
|
||
|
SetEvent(hevDone);
|
||
|
|
||
|
// It died. Clean up.
|
||
|
case WAIT_OBJECT_0 + 1:
|
||
|
fDWRunning = FALSE;
|
||
|
frrvRet = frrvErrNoDW;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// ok, it responded. Is it done?
|
||
|
if (WaitForSingleObject(hevDone, 0) == WAIT_OBJECT_0)
|
||
|
fDWRunning = FALSE;
|
||
|
|
||
|
ReleaseMutex(hmut);
|
||
|
break;
|
||
|
|
||
|
// if the wait was abandoned, it means DW has gone to the great bit
|
||
|
// bucket in the sky without cleaning up. So release the mutex and
|
||
|
// fall into the default case
|
||
|
case WAIT_ABANDONED:
|
||
|
ReleaseMutex(hmut);
|
||
|
|
||
|
// if we timed out or otherwise failed, just die.
|
||
|
default:
|
||
|
frrvRet = frrvErrNoDW;
|
||
|
fDWRunning = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (frrvRet != frrvOk)
|
||
|
{
|
||
|
CloseHandle(pi.hProcess);
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
// if user told us to debug, return that back to the
|
||
|
if (pdwsm->msoctdsResult == msoctdsDebug)
|
||
|
frrvRet = frrvLaunchDebugger;
|
||
|
|
||
|
// if we're going to launch Dr. Watson, wait for the DW process to die.
|
||
|
// Give it 5 minutes. If the user doesn't hit close by then, just return
|
||
|
// anyway...
|
||
|
if (dwOpt == (DWORD)-1)
|
||
|
{
|
||
|
if (WaitForSingleObject(pi.hProcess, 300000) == WAIT_TIMEOUT)
|
||
|
frrvRet = frrvErrTimeout;
|
||
|
}
|
||
|
|
||
|
CloseHandle(pi.hProcess);
|
||
|
|
||
|
done:
|
||
|
// preserve the error code so that the following calls don't overwrite it
|
||
|
dw = GetLastError();
|
||
|
|
||
|
if (pdwsm != NULL)
|
||
|
UnmapViewOfFile(pdwsm);
|
||
|
if (hfmShared != NULL)
|
||
|
CloseHandle(hfmShared);
|
||
|
if (hevDone != NULL)
|
||
|
CloseHandle(hevDone);
|
||
|
if (hevAlive != NULL)
|
||
|
CloseHandle(hevAlive);
|
||
|
if (hmut != NULL)
|
||
|
CloseHandle(hmut);
|
||
|
if (hProc != NULL)
|
||
|
CloseHandle(hProc);
|
||
|
|
||
|
SetLastError(dw);
|
||
|
|
||
|
return frrvRet;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
EFaultRepRetVal
|
||
|
FaultHandler(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN EXCEPTION_POINTERS *pep,
|
||
|
IN DWORD dwOpt)
|
||
|
{
|
||
|
|
||
|
EFaultRepRetVal frrvRet = frrvErrNoDW;
|
||
|
DWORD dwFlags = 0;
|
||
|
char wszFile[MAX_PATH], *pwsz;
|
||
|
|
||
|
DebugLog("Inside FaultHandler\r\n");
|
||
|
MyGetModuleFileNameA(NULL, wszFile, sizeof(wszFile)/sizeof(wszFile[0]));
|
||
|
|
||
|
// Find last backslash
|
||
|
for(pwsz = wszFile + strlen(wszFile);
|
||
|
pwsz >= wszFile && *pwsz != '\\';
|
||
|
pwsz--);
|
||
|
|
||
|
// Should never happen
|
||
|
if (pwsz < wszFile)
|
||
|
goto done;
|
||
|
|
||
|
if (*pwsz == '\\')
|
||
|
pwsz++;
|
||
|
|
||
|
// Don't want to debug dwwin.exe itself.
|
||
|
if (_stricmp(pwsz, "dwwin.exe") == 0
|
||
|
// || _stricmp(pwsz, "dumprep.exe") == 0
|
||
|
)
|
||
|
goto done;
|
||
|
|
||
|
frrvRet = StartDWException(This, pep, dwOpt, dwFlags, -1);
|
||
|
|
||
|
done:
|
||
|
return frrvRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
static
|
||
|
BOOL
|
||
|
FAULTHIsSupported(
|
||
|
IN PSETUP_FAULT_HANDLER This
|
||
|
)
|
||
|
{
|
||
|
BOOL useExtendedInfo;
|
||
|
DWORD dwServicePack;
|
||
|
DWORD dwVersion,dwTemp,dwInfoSize;
|
||
|
char *pInfo;
|
||
|
VS_FIXEDFILEINFO *VsInfo;
|
||
|
UINT DataLength;
|
||
|
union {
|
||
|
OSVERSIONINFO Normal;
|
||
|
OSVERSIONINFOEX Ex;
|
||
|
} Ovi;
|
||
|
|
||
|
DebugLog("Inside FAULTHIsSupported\r\n");
|
||
|
if ( !This) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
useExtendedInfo = TRUE;
|
||
|
Ovi.Ex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||
|
if (!GetVersionEx((OSVERSIONINFO *)&Ovi.Ex) ) {
|
||
|
//
|
||
|
// EX size not available; try the normal one
|
||
|
//
|
||
|
|
||
|
Ovi.Normal.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
if (!GetVersionEx((OSVERSIONINFO *)&Ovi.Normal) ) {
|
||
|
DebugLog("Inside FAULTHIsSupported:Could not get os version!\r\n");
|
||
|
return(FALSE);
|
||
|
}
|
||
|
useExtendedInfo = FALSE;
|
||
|
}
|
||
|
if (useExtendedInfo) {
|
||
|
dwServicePack = Ovi.Ex.wServicePackMajor * 100 + Ovi.Ex.wServicePackMinor;
|
||
|
} else {
|
||
|
dwServicePack = 0;
|
||
|
}
|
||
|
dwVersion = Ovi.Normal.dwMajorVersion * 100 + Ovi.Normal.dwMinorVersion;
|
||
|
switch (Ovi.Normal.dwPlatformId) {
|
||
|
case VER_PLATFORM_WIN32s:
|
||
|
DebugLog("Inside FAULTHIsSupported:Unsupported win32s!\r\n");
|
||
|
return(FALSE);
|
||
|
break;
|
||
|
case VER_PLATFORM_WIN32_WINDOWS:
|
||
|
if( dwVersion < 410) {
|
||
|
DebugLog("Inside FAULTHIsSupported:Unsupported win9x!\r\n");
|
||
|
return(FALSE);
|
||
|
}
|
||
|
break;
|
||
|
case VER_PLATFORM_WIN32_NT:
|
||
|
if( dwVersion < 400) {
|
||
|
DebugLog("Inside FAULTHIsSupported:Unsupported winNT!\r\n");
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
if( dwVersion == 400 && dwServicePack < 500) {
|
||
|
DebugLog("Inside FAULTHIsSupported:Unsupported ServicePack!\r\n");
|
||
|
return(FALSE);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
// Test for wininet.dll from ie 4.01.
|
||
|
dwInfoSize = GetFileVersionInfoSize( FAULTH_WININET_NAME, &dwTemp );
|
||
|
if( !dwInfoSize) {
|
||
|
DebugLog("Inside FAULTHIsSupported:Could not find wininet.dll or determine version.");
|
||
|
return( FALSE);
|
||
|
}
|
||
|
|
||
|
pInfo = HeapAlloc( GetProcessHeap(), 0, dwInfoSize);
|
||
|
|
||
|
if( !pInfo ||
|
||
|
!GetFileVersionInfo( FAULTH_WININET_NAME, dwTemp, dwInfoSize, pInfo) ||
|
||
|
!VerQueryValue( pInfo, "\\", &VsInfo, &DataLength))
|
||
|
{
|
||
|
DebugLog("Inside FAULTHIsSupported:Could not find wininet.dll or get version.");
|
||
|
HeapFree( GetProcessHeap(), 0, pInfo);
|
||
|
return( FALSE);
|
||
|
}
|
||
|
if( VsInfo->dwFileVersionMS < FAULTH_WININET_MIN_MS ||
|
||
|
((VsInfo->dwFileVersionMS == FAULTH_WININET_MIN_MS) && (VsInfo->dwFileVersionLS < FAULTH_WININET_MIN_LS))) {
|
||
|
DebugLog("Inside FAULTHIsSupported:Require a more recent wininet.dll.");
|
||
|
HeapFree( GetProcessHeap(), 0, pInfo);
|
||
|
return( FALSE);
|
||
|
}
|
||
|
HeapFree( GetProcessHeap(), 0, pInfo);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FAULTHSetURLA(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN PCSTR pszURL
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHSetURLA\r\n");
|
||
|
if (This && pszURL){
|
||
|
lstrcpynA( This->szURL, pszURL, DW_MAX_SERVERNAME);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FAULTHSetURLW(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN PCWSTR pwzURL
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHSetURLW\r\n");
|
||
|
if (This && pwzURL){
|
||
|
WideCharToMultiByte( CP_ACP, 0, pwzURL, -1, This->szURL, DW_MAX_SERVERNAME, NULL, NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FAULTHSetErrorTextA(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN PCSTR pszErrorText
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHSetErrorTextA\r\n");
|
||
|
if (This && pszErrorText){
|
||
|
MultiByteToWideChar( CP_ACP, 0, pszErrorText, -1, This->wzErrorText, DW_MAX_ERROR_CWC);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FAULTHSetErrorTextW(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN PCWSTR pwzErrorText
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHSetErrorTextW\r\n");
|
||
|
if (This && pwzErrorText){
|
||
|
plstrcpynW( This->wzErrorText, pwzErrorText, DW_MAX_ERROR_CWC);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FAULTHSetAdditionalFilesA(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN PCSTR pszAdditionalFiles
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHSetAdditionalFilesA\r\n");
|
||
|
if (This && pszAdditionalFiles){
|
||
|
MultiByteToWideChar( CP_ACP, 0, pszAdditionalFiles, -1, This->wzAdditionalFiles, DW_MAX_ADDFILES);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FAULTHSetAdditionalFilesW(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN PCWSTR pwzAdditionalFiles
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHSetAdditionalFilesW\r\n");
|
||
|
if (This && pwzAdditionalFiles){
|
||
|
plstrcpynW( This->wzAdditionalFiles, pwzAdditionalFiles, DW_MAX_ADDFILES);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FAULTHSetAppNameA(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN PCSTR pszAppName
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHAppNameA\r\n");
|
||
|
if (This && pszAppName){
|
||
|
MultiByteToWideChar( CP_ACP, 0, pszAppName, -1, This->wzAppName, DW_APPNAME_LENGTH);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FAULTHSetAppNameW(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN PCWSTR pwzAppName
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHAppNameW\r\n");
|
||
|
if (This && pwzAppName){
|
||
|
plstrcpynW( This->wzAppName, pwzAppName, DW_APPNAME_LENGTH);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FAULTHSetLCID(
|
||
|
IN PSETUP_FAULT_HANDLER This,
|
||
|
IN LCID lcid
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHSetLCID\r\n");
|
||
|
if (This){
|
||
|
This->lcid = lcid;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static
|
||
|
VOID
|
||
|
FAULTHInit(
|
||
|
IN PSETUP_FAULT_HANDLER This
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHInit\r\n");
|
||
|
if( This){
|
||
|
This->SetURLA = FAULTHSetURLA;
|
||
|
This->SetURLW = FAULTHSetURLW;
|
||
|
This->SetAppNameA = FAULTHSetAppNameA;
|
||
|
This->SetAppNameW = FAULTHSetAppNameW;
|
||
|
This->SetErrorTextA = FAULTHSetErrorTextA;
|
||
|
This->SetErrorTextW = FAULTHSetErrorTextW;
|
||
|
This->SetAdditionalFilesA = FAULTHSetAdditionalFilesA;
|
||
|
This->SetAdditionalFilesW = FAULTHSetAdditionalFilesW;
|
||
|
This->SetLCID = FAULTHSetLCID;
|
||
|
This->IsSupported = FAULTHIsSupported;
|
||
|
This->Report = FaultHandler;
|
||
|
This->bDebug = FALSE;
|
||
|
FAULTHSetURLA(This, c_szDWDefServerI);
|
||
|
FAULTHSetAppNameW(This, c_wzDWDefAppName);
|
||
|
FAULTHSetAdditionalFilesW(This, L"");
|
||
|
FAULTHSetErrorTextW(This,L"");
|
||
|
FAULTHSetLCID(This,c_DWDefaultLCID);
|
||
|
}
|
||
|
#ifdef TEST_WATSON
|
||
|
{
|
||
|
char szFile[MAX_PATH], *pwsz;
|
||
|
|
||
|
GetSystemDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0]));
|
||
|
szFile[3] = '\0';
|
||
|
strcat(szFile, c_wszLogFileName);
|
||
|
hFaultLog = CreateFileA(szFile, GENERIC_WRITE,
|
||
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
||
|
NULL, OPEN_ALWAYS, 0, NULL);
|
||
|
|
||
|
if (hFaultLog != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
SYSTEMTIME st;
|
||
|
DWORD cb, cbWritten;
|
||
|
char szMsg[512];
|
||
|
|
||
|
GetSystemTime(&st);
|
||
|
cb = wsprintf(szMsg,
|
||
|
"%02d-%02d-%04d %02d:%02d:%02d Initalization\r\n",
|
||
|
st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute,
|
||
|
st.wSecond);
|
||
|
SetFilePointer(hFaultLog, 0, NULL, FILE_END);
|
||
|
WriteFile(hFaultLog, szMsg, cb, &cbWritten, NULL);
|
||
|
}
|
||
|
}
|
||
|
DebugLog("exiting FAULTHInit\r\n");
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
PSETUP_FAULT_HANDLER APIENTRY
|
||
|
FAULTHCreate( VOID)
|
||
|
{
|
||
|
PSETUP_FAULT_HANDLER This = NULL;
|
||
|
|
||
|
DebugLog("Inside FAULTHCreate\r\n");
|
||
|
This = HeapAlloc( GetProcessHeap(), 0, sizeof(SETUP_FAULT_HANDLER));
|
||
|
|
||
|
if( This) {
|
||
|
FAULTHInit( This);
|
||
|
}
|
||
|
|
||
|
DebugLog("exiting FAULTCreate\r\n");
|
||
|
return This;
|
||
|
}
|
||
|
|
||
|
VOID APIENTRY
|
||
|
FAULTHDelete(
|
||
|
IN PSETUP_FAULT_HANDLER This
|
||
|
)
|
||
|
{
|
||
|
DebugLog("Inside FAULTHDelete\r\n");
|
||
|
if( This) {
|
||
|
HeapFree( GetProcessHeap(), 0, This);
|
||
|
}
|
||
|
#ifdef TEST_WATSON
|
||
|
if (hFaultLog != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle(hFaultLog);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|