summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2018-03-31 00:29:33 -0700
committerGitHub <noreply@github.com>2018-03-31 00:29:33 -0700
commitc05eeefbb63cf7f9a466a7371bd44d3254806f03 (patch)
treeb0f688af865656fba94f5a59a0dd6b3f2dba9663
parent42ae2c03de22d32f96890077e109e1f9e57451d1 (diff)
downloadcoreclr-c05eeefbb63cf7f9a466a7371bd44d3254806f03.tar.gz
coreclr-c05eeefbb63cf7f9a466a7371bd44d3254806f03.tar.bz2
coreclr-c05eeefbb63cf7f9a466a7371bd44d3254806f03.zip
Delete dead code to support OSes prior to Windows 7 (#17367)
-rw-r--r--src/debug/di/process.cpp50
-rw-r--r--src/debug/ee/debugger.cpp3
-rw-r--r--src/inc/msodw.h550
-rw-r--r--src/inc/ostype.h77
-rw-r--r--src/utilcode/util_nodependencies.cpp112
-rw-r--r--src/vm/ceemain.cpp15
-rw-r--r--src/vm/crossgencompile.cpp7
-rw-r--r--src/vm/dwreport.cpp2055
-rw-r--r--src/vm/dwreport.h4
-rw-r--r--src/vm/eepolicy.cpp2
-rw-r--r--src/vm/excep.cpp212
-rw-r--r--src/vm/i386/cgencpu.h4
-rw-r--r--src/vm/i386/cgenx86.cpp67
-rw-r--r--src/vm/threads.cpp2
-rw-r--r--src/vm/vars.cpp7
-rw-r--r--src/vm/vars.hpp4
-rw-r--r--src/zap/zapper.cpp4
17 files changed, 72 insertions, 3103 deletions
diff --git a/src/debug/di/process.cpp b/src/debug/di/process.cpp
index 533a420f47..4356a8f7f4 100644
--- a/src/debug/di/process.cpp
+++ b/src/debug/di/process.cpp
@@ -11582,54 +11582,6 @@ void CordbProcess::HandleSyncCompleteRecieved()
#ifdef FEATURE_INTEROP_DEBUGGING
-// Get a Thread's _user_ starting address (the real starting address may be some
-// OS shim.)
-// This may return NULL for the Async-Break thread.
-void* GetThreadUserStartAddr(const DEBUG_EVENT* pCreateThreadEvent)
-{
- // On Win7 and above, we can trust the lpStartAddress field of the CREATE_THREAD_DEBUG_EVENT
- // to be the user start address (the actual OS start address is an implementation detail that
- // doesn't need to be exposed to users). Note that we are assuming that the target process
- // is running on Win7 if mscordbi is. If we ever have some remoting scenario where the target
- // can run on a different windows machine with a different OS version we will need a way to
- // determine the target's OS version
- if(RunningOnWin7())
- {
- return pCreateThreadEvent->u.CreateThread.lpStartAddress;
- }
-
- // On pre-Win7 OSes, we rely on an OS implementation detail to get the real user thread start:
- // it exists in EAX at thread start time.
- // Note that for a brief period of time there was a GetThreadStartInformation API in Longhorn
- // we could use for this, but it was removed during the Longhorn reset.
- HANDLE hThread = pCreateThreadEvent->u.CreateThread.hThread;
-#if defined(DBG_TARGET_X86)
- // Grab the thread's context.
- DT_CONTEXT c;
- c.ContextFlags = DT_CONTEXT_FULL;
- BOOL succ = DbiGetThreadContext(hThread, &c);
-
- if (succ)
- {
- return (void*) c.Eax;
- }
-#elif defined(DBG_TARGET_AMD64)
- DT_CONTEXT c;
- c.ContextFlags = DT_CONTEXT_FULL;
- BOOL succ = DbiGetThreadContext(hThread, &c);
-
- if (succ)
- {
- return (void*) c.Rcx;
- }
-#else
- PORTABILITY_ASSERT("port GetThreadUserStartAddr");
-#endif
-
- return NULL;
-}
-
-
//---------------------------------------------------------------------------------------
//
// Get (create if needed) the unmanaged thread for an unmanaged debug event.
@@ -11706,7 +11658,7 @@ CordbUnmanagedThread * CordbProcess::GetUnmanagedThreadFromEvent(const DEBUG_EVE
UpdateRightSideDCB();
if ((this->GetDCB()->m_helperThreadStartAddr != NULL) && (pUnmanagedThread != NULL))
{
- void * pStartAddr = GetThreadUserStartAddr(pEvent);
+ void * pStartAddr = pEvent->u.CreateThread.lpStartAddress;
if (pStartAddr == this->GetDCB()->m_helperThreadStartAddr)
{
diff --git a/src/debug/ee/debugger.cpp b/src/debug/ee/debugger.cpp
index 8363b1f658..1e69d2b1a9 100644
--- a/src/debug/ee/debugger.cpp
+++ b/src/debug/ee/debugger.cpp
@@ -13525,8 +13525,7 @@ void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRec
// On Win7 WatsonLastChance returns CONTINUE_SEARCH for unhandled exceptions execpt stack overflow, and
// lets OS launch debuggers for us. Before the unhandled exception reaches the OS, CLR UEF has already
// processed this unhandled exception. Thus, we should not call into CLR UEF again if it is the case.
- if (RunningOnWin7() &&
- pThread &&
+ if (pThread &&
(pThread->HasThreadStateNC(Thread::TSNC_ProcessedUnhandledException) ||
pThread->HasThreadStateNC(Thread::TSNC_AppDomainContainUnhandled) ||
fSOException))
diff --git a/src/inc/msodw.h b/src/inc/msodw.h
index d0745d2551..a1acc2f16f 100644
--- a/src/inc/msodw.h
+++ b/src/inc/msodw.h
@@ -13,455 +13,7 @@
#pragma pack(push, msodw_h)
#pragma pack(4)
-#define DW_TIMEOUT_VALUE 20000
-#define DW_MUTEX_TIMEOUT DW_TIMEOUT_VALUE / 2
-#define DW_NOTIFY_TIMEOUT 120000 // 2 minutes
-
-#define DW_CURRENT_VERSION 0x00020000
-
-#define DW_MAX_ASSERT_CCH 1024
-#define DW_MAX_PATH 260
-#define DW_APPNAME_LENGTH 56
-#define DW_MAX_ERROR_CWC 260 // must be at least max_path
-#define DW_MAX_REGSUBPATH 200
-#define DW_MAX_CALLSTACK 16
-#define DW_MAX_EVENTSOURCE DW_MAX_PATH
-#define DW_MAX_PIDREGKEY DW_MAX_PATH
#define DW_MAX_BUCKETPARAM_CWC 255
-#define DW_MAX_USERDOCS_CWC 1024
-
-// return values for DW process
-#define DW_RETVAL_SUCCESS 0
-#define DW_RETVAL_FAILURE 1
-#define DW_RETVAL_DEBUG 16
-
-#define DW_ALLMODULES L"*\0"
-#define DW_NOTAG 0
-
-// this is added to the command line of the restarted app if fDweTagCommandLine is set
-#define DW_CMDLINE_TAG "Watson=1"
-
-// The following are the fields that can be specified in a manifest file to
-// launch DW in a file based reporting mode.
-// The following are required UI fields.
-#define DW_MANIFEST_GENERAL_APPNAME L"General_AppName="
-#define DW_MANIFEST_MAIN_INTRO_BOLD L"Main_Intro_Bold="
-#define DW_MANIFEST_QUEUED_EVENTDESCRIPTION L"Queued_EventDescription=" // this will only be shown if the report is queued
-
-// The following are required reporting fields.
-#define DW_MANIFEST_LCID L"UI LCID="
-#define DW_MANIFEST_VERSION L"Version=" // set this to DW_CURRENT_VERSION defined in this file
-
-// There are two ways to specify your bucket parameters.
-// The first is to fill in as many of these as you need,
-// and let DW construct URLs and UNC paths for you.
-#define DW_MANIFEST_EVENTTYPE L"EventType="
-#define DW_MANIFEST_P1 L"P1="
-#define DW_MANIFEST_P2 L"P2="
-#define DW_MANIFEST_P3 L"P3="
-#define DW_MANIFEST_P4 L"P4="
-#define DW_MANIFEST_P5 L"P5="
-#define DW_MANIFEST_P6 L"P6="
-#define DW_MANIFEST_P7 L"P7="
-#define DW_MANIFEST_P8 L"P8="
-#define DW_MANIFEST_P9 L"P9="
-#define DW_MANIFEST_P10 L"P10="
-
-// Alternatively, you can spell it all out for us.
-#define DW_MANIFEST_URL1 L"Stage1URL="
-#define DW_MANIFEST_URL2 L"Stage2URL="
-#define DW_MANIFEST_ERRORSUBPATH L"ErrorSubPath="
-
-// The following are optional; DW has default behavior for all of these.
-// These are UI fields (see UserInterfaceBlock for documentation if not listed below)
-#define DW_MANIFEST_GENERAL_REPORTEE L"General_Reportee="
-
-#define DW_MANIFEST_MAIN_CAPTION L"Main_Caption="
-#define DW_MANIFEST_MAIN_ICONFILE L"Main_IconFile=" // otherwise, no icon
-#define DW_MANIFEST_MAIN_INTRO_REG L"Main_Intro_Reg=" // otherwise DAL collapses space
-#define DW_MANIFEST_MAIN_CHECKBOX L"Main_CheckBox="
-#define DW_MANIFEST_MAIN_PLEA_BOLD L"Main_Plea_Bold="
-#define DW_MANIFEST_MAIN_PLEA_REG L"Main_Plea_Reg=" // otherwise DAL collapses space
-#define DW_MANIFEST_MAIN_DETAILSLINK L"Main_DetailsLink="
-#define DW_MANIFEST_MAIN_REPORTBTN L"Main_ReportBtn="
-#define DW_MANIFEST_MAIN_NOREPORTBTN L"Main_NoReportBtn="
-#define DW_MANIFEST_MAIN_ALWAYSREPORTBTN L"Main_AlwaysReportBtn="
-#define DW_MANIFEST_MAIN_QUEUEBTN L"Main_QueueBtn="
-#define DW_MANIFEST_MAIN_NOQUEUEBTN L"Main_NoQueueBtn="
-#define DW_MANIFEST_MAIN_QUEUETEXT L"Main_QueueText="
-#define DW_MANIFEST_MAIN_FEEDBACKLINK L"Main_FeedbackLink="
-
-#define DW_MANIFEST_DETAILS_CAPTION L"Details_Caption="
-#define DW_MANIFEST_DETAILS_PRE_HEADER L"Details_Pre_Header="
-#define DW_MANIFEST_DETAILS_PRE_BODY L"Details_Pre_Body="
-#define DW_MANIFEST_DETAILS_SIG_HEADER L"Details_Sig_Header="
-#define DW_MANIFEST_DETAILS_SIG_BODY L"Details_Sig_Body="
-#define DW_MANIFEST_DETAILS_POST_HEADER L"Details_Post_Header="
-#define DW_MANIFEST_DETAILS_POST_BODY L"Details_Post_Body=" // pretty similar to exception mode, but calls out DigPid too.
-#define DW_MANIFEST_DETAILS_TECHLINK L"Details_TechLink="
-#define DW_MANIFEST_DETAILS_DCPLINK L"Details_DCPLink="
-
-#define DW_MANIFEST_TECH_CAPTION L"Tech_Caption="
-#define DW_MANIFEST_TECH_FILES_HEADER L"Tech_Files_Header="
-
-#define DW_MANIFEST_TRANSFER_CAPTION L"Transfer_Caption="
-#define DW_MANIFEST_TRANSFER_1CHECK L"Transfer_1check="
-#define DW_MANIFEST_TRANSFER_2CHECK L"Transfer_2check="
-#define DW_MANIFEST_TRANSFER_3CHECK L"Transfer_3check="
-#define DW_MANIFEST_TRANSFER_STATUS_INPROGRESS L"Transfer_Status_InProgress="
-#define DW_MANIFEST_TRANSFER_STATUS_DONE L"Transfer_Status_Done="
-#define DW_MANIFEST_TRANSFER_CHECKBOX L"Transfer_Checkbox="
-
-#define DW_MANIFEST_SECONDLEVEL_CAPTION L"SecondLevel_Caption="
-#define DW_MANIFEST_SECONDLEVEL_PRE L"SecondLevel_Pre="
-#define DW_MANIFEST_SECONDLEVEL_POST L"SecondLevel_Post="
-
-#define DW_MANIFEST_FINAL_CAPTION L"Final_Caption="
-#define DW_MANIFEST_FINAL_TEXT L"Final_Text="
-#define DW_MANIFEST_FINAL_TEXT_USERCANCEL L"Final_Text_UserCancel="
-#define DW_MANIFEST_FINAL_LINK L"Final_Link="
-#define DW_MANIFEST_FINAL_LINK_SURVEY L"Final_Link_Survey="
-
-#define DW_MANIFEST_STANDBY_CAPTION L"Standby_Caption="
-#define DW_MANIFEST_STANDBY_BODY L"Standby_Body="
-
-// These are reporting fields.
-#define DW_MANIFEST_RFLAGS L"ReportingFlags="
-#define DW_MANIFEST_UFLAGS L"UIFlags="
-#define DW_MANIFEST_LFLAGS L"LoggingFlags="
-#define DW_MANIFEST_MFLAGS L"MiscFlags="
-#define DW_MANIFEST_BRAND L"Brand="
-#define DW_MANIFEST_EVENTSOURCE L"EventLogSource="
-#define DW_MANIFEST_EVENTID L"EventID="
-#define DW_MANIFEST_DIGPIDPATH L"DigPidRegPath="
-#define DW_MANIFEST_CHECKBOX_REGKEY L"CheckBoxRegKey="
-#define DW_MANIFEST_CUSTOM_QUERY_STRING_ELEMENTS L"CustomQueryStringElements="
-
-// DW expects at least one of these to be set.
-#define DW_MANIFEST_DELETABLEFILES L"FilesToDelete="
-#define DW_MANIFEST_NONDELETABLEFILES L"FilesToKeep="
-
-// These may be optionally set, and will be used on second-level data requests.
-#define DW_MANIFEST_USERFILES L"UserDocs="
-#define DW_MANIFEST_HEAP L"Heap="
-
-
-#define DW_X(X) L##X
-#define DW_Y(X) DW_X(X)
-
-// Seperator for file lists (Manifest DataFiles and Exception Additional Files)
-#define DW_FILESEPA '|'
-#define DW_FILESEP DW_Y(DW_FILESEPA)
-
-#define DW_OMIT_SECTION L"NIL"
-#define DW_APPNAME_TOKEN L"%General_AppName%"
-#define DW_REPORTEE_TOKEN L"%General_Reportee%"
-
-// the following is required for queued information file only
-#define DW_QR_VERSION L"QueueVer="
-#define DW_QR_DATE L"Date="
-#define DW_QR_TIME L"Time="
-#define DW_QR_REPORTSIZE L"ReportSize="
-#define DW_QR_BYTES L"Bytes="
-#define DW_QR_KILOBYTES L"Kilobytes="
-#define DW_QR_MEGABYTES L"Megabytes="
-#define DW_QR_MOREINFO L"MoreInfo="
-#define DW_QR_BP0 L"BP0="
-#define DW_QR_BP1 L"BP1="
-#define DW_QR_BP2 L"BP2="
-#define DW_QR_BP3 L"BP3="
-#define DW_QR_BP4 L"BP4="
-#define DW_QR_BP5 L"BP5="
-#define DW_QR_BP6 L"BP6="
-#define DW_QR_BP7 L"BP7="
-#define DW_QR_BP8 L"BP8="
-#define DW_QR_BP9 L"BP9="
-#define DW_QR_BP10 L"BP10="
-#define DW_QR_CBP L"CBP="
-#define DW_QR_DWVER0 L"DWVer0="
-#define DW_QR_DWVER1 L"DWVer1="
-#define DW_QR_DWVER2 L"DWVer2="
-#define DW_QR_DWVER3 L"DWVer3="
-#define DW_QR_MODE L"QueueMode="
-
-
-// shared reg values between DW and DW COM EXE
-#define DEFAULT_SUBPATH L"Microsoft\\PCHealth\\ErrorReporting\\DW"
-#define QUEUE_REG_SUBPATH L"Software\\" DEFAULT_SUBPATH
-#define QUEUE_REG_OKTOREPORT_VALUE L"OkToReportFromTheseQueues"
-#define WATSON_INSTALLED_REG_SUBPATH QUEUE_REG_SUBPATH L"\\Installed"
-#define WATSON_INSTALLED_REG_SUBPATH_IA64 L"Software\\Wow6432Node\\"DEFAULT_SUBPATH L"\\Installed"
-#define WATSON_INSTALLED_REG_VAL L"DW0200" // keep in sync with %MSI%\src\sdl\shared\watson.sreg
-#define WATSON_INSTALLED_REG_VAL_IA64 L"DW0201" // keep in sync with %MSI%\src\sdl\shared\watson.sreg
-
-// names for the Watson exes
-#define DW_EXEA "dw20.exe"
-#define DW_EXE DW_Y(DW_EXEA)
-#define DW_COM_EXEA "dwtrig20.exe"
-#define DW_COM_EXE DW_Y(DW_COM_EXEA)
-
-// the following option is used to exec DW to set the trigger for queued reporting
-// ie Run 'dw20 -k <queue number>'
-#define OPTSQRTA 'k' // queued reporting trigger
-#define OPTSQRT DW_Y(OPTSQRTA)
-
-// the following option is used to exec DW in queued reporting mode
-// ie Run 'dw20 -q <queue types to report from>'
-#define OPTQRMA 'q' // queued reporting mode
-#define OPTQRM DW_Y(OPTQRMA)
-
-// the following option is used to exec the DW COM EXE to trigger queued reporting after a delay time
-// ie Run 'dwtrig20 -t'
-#define OPTQRTA 't' // queued reporting trigger
-#define OPTQRT DW_Y(OPTQRTA)
-
-// the following option is used to exec the DW COM EXE to trigger queued reporting immediately
-// ie Run 'dwtrig20 -f <queue types to report from>'
-#define OPTQRFA 'f' // force queued reporting
-#define OPTQRF DW_Y(OPTQRFA)
-
-#define C_QUEUE_TYPES 3
-
-enum // EQueueTypes
-{
- dwqueueMin = 0x00000001,
-
- // all the queues types
- // these must be consecutive
- // (valid range for queue types is 0x00000001 - 0x00008000, 16 total)
- dwqueueRegular = 0x00000001,
- dwqueueSignOff = 0x00000002,
- dwqueueHeadless = 0x00000004,
- // next valid queue type: 0x00000008
-
- // the maximum dwqueueMax is 0x00008000
- dwqueueMax = 0x00000004,
-
- // triggering flags (valid range for triggers is 0x00010000 - 0x08000000, 12 total)
- dwtriggerAtLogon = 0x00010000,
- dwtriggerAtConnectionMade = 0x00020000,
-
- // special flags (valid range for special flags is 0x1000000 - 0x80000000, 4 total)
- dwqueueAnyAdmin = 0x10000000, // Admin queue
-
- // flag combinations
- dwqueueTypes = 0x00000007, // Regular | SignOff | Headless
-};
-
-enum // EQueuedReportingDialogResults
-{
- qrdrCancel = 0x00000001,
- qrdrLater = 0x00000002,
- qrdrDone = 0x00000004,
-};
-
-
-#ifdef DEBUG
-enum // AssertActionCodes
-{
- DwAssertActionFail = 0,
- DwAssertActionDebug,
- DwAssertActionIgnore,
- DwAssertActionAlwaysIgnore,
- DwAssertActionIgnoreAll,
- DwAssertActionQuit,
-};
-#endif
-
-// Caller is the app that has experienced an exception and launches DW
-
-enum // ECrashTimeDialogStates // msoctds
-{
- msoctdsNull = 0x00000000,
- msoctdsQuit = 0x00000001,
- msoctdsRestart = 0x00000002,
- msoctdsRecover = 0x00000004,
- msoctdsUnused = 0x00000008,
- msoctdsDebug = 0x00000010,
-};
-
-#define MSODWRECOVERQUIT (msoctdsRecover | msoctdsQuit)
-#define MSODWRESTARTQUIT (msoctdsRestart | msoctdsQuit)
-#define MSODWRESPONSES (msoctdsQuit | msoctdsRestart | msoctdsRecover)
-
-// THIS IS PHASED OUT -- DON'T USE
-enum // EMsoCrashHandlerFlags // msochf
-{
- msochfNull = 0x00000000,
- msochfCheckboxOff = 0x00000001,
-
- msochfUnused = msoctdsUnused, // THESE MUST BE THE SAME 0x8
- msochfCanRecoverDocuments = msoctdsRecover, // 0x4
-
- msochfObsoleteCanDebug = 0x00010001, // not used anymore
- msochfCannotSneakyDebug = 0x00010002, // The "hidden" debug feature won't work
- msochfDefaultDontReport = 0x00010004,
- msochReportingDisabled = 0x00010008, // User cannot change default reporting choice
-};
-
-
-//
-enum // EMsoCrashHandlerResults // msochr
-{
- msochrNotHandled = msoctdsNull,
- msochrUnused = msoctdsUnused,
- msochrDebug = msoctdsDebug,
- msochrRecoverDocuments = msoctdsRecover,
- msochrRestart = msoctdsRestart,
- msochrQuit = msoctdsQuit,
-};
-
-enum // EDwReportingFlags
-{
- fDwrDeleteFiles = 0x00000001, // delete "files to delete" after use (plus heap, minidump, manifest).
- fDwrIgnoreHKCU = 0x00000002, // Only look at HKLM. If you do not set this, we will look at both HKCU and HKLM.
- fDwrForceOfflineMode = 0x00000008, // DW will force the report to be queued
- fDwrForceToAdminQueue = 0x00000004 | fDwrForceOfflineMode, // DW will force the report to be queued on the Admin queue
- fDwrDenyOfflineMode = 0x00000010, // DW will not allow report to be queued
- fDwrNoHeapCollection = 0x00000020, // DW will not gather the heap.
- fDwrNoSecondLevelCollection = 0x00000040 | fDwrNoHeapCollection, // DW will not send any second level data, including the heap
- fDwrNeverUpload = 0x00000080, // don't report
- fDwrDontPromptIfCantReport = 0x00000100, // DW will not show any UI if we're not going to report.
- fDwrNoDefaultCabLimit = 0x00000200, // DW under CER won't use 5 as the fallback but unlimited instead (policy still overrides)
-};
-
-enum // EDwUIFlags
-{
- fDwuNoEventUI = 0x00000001, // DW will always try to send headless, regardless of DWAllowHeadless
- // Having no UI reporting from the queue means that there is no UI at the time of the event
- fDwuNoQueueUI = 0x00000002 | fDwuNoEventUI, // DW will put the report in the headless queue with no UI
- fDwuShowFeedbackLink = 0x00000004, // Show the "Why should I report" link.
- fDwuUseIE = 0x00000008, // always launch w/ IE
-
- // DO NOT use this flag. It doesn't work. Instead customize by using the UserInterfaceBlock.
- fDwuUseLitePlea = 0x00000010, // DW won't suggest product change in report plea
-
- fDwuManifestDebug = 0x00000020, // DW will provide a debug button in manifest mode
- fDwuDenySuspend = 0x00000040, // DW will keep powersave mode from suspending it, until transfer is complete.
-};
-
-enum // EDwLoggingFlags
-{
- fDwlNoParameterLog = 0x00000001, // DW won't log the initial parameters
- fDwlNoBucketLog = 0x00000002, // DW won't log the bucket ID and the bucket parameters
- fDwlResponseLog = 0x00000004, // log the resolved response, including extra args, to the event log with event 1010.
-};
-
-enum // EDwExceptionModeFlags
-{
- fDweCheckSig = 0x00000001, // checks the signatures of the App/Mod list
- fDweTagCommandLine = 0x00000002, // adds DW_CMDLINE_TAG to command line when restarting apps.
- fDweDefaultQuit = 0x00000004, // In exception mode, DW will default the restart/recover box to off. Doesn't affect regkey-based checkboxes.
- fDweKeepMinidump = 0x00000008, // Don't delete the minidump when we're done using it.
- fDweIgnoreAeDebug = 0x00000010, // Don't check AeDebug to determine whether or not to show the Debug button.
- fDweGatherHeapAsMdmp = 0x00000020, // Use the minidump API to gather the heap, rather than the minimal version we build directly
- fDweReleaseBeforeCabbing = 0x00000040, // Release the thread doing the dump and cab the files in the background.
-};
-
-enum // EDwMiscFlags
-{
- fDwmOfficeDigPID = 0x00000001, // use custom internal code to figure out what SKU of Office is installed
- fDwmOfficeSQMReporting = 0x00000002, // DW should collect SQM data and save it for Office to upload (if QMEnabled reg key is set).
- fDwmContainsOnlyAnonymousData = 0x00000003, // DW does nothing with this flag, but the LH shim will recognize it. It should be used in rare
- // circumstances when the silent report is known to contain NO PII.
-};
-
-
-typedef struct _AssertBlock
-{
- // for Assert communication
- DWORD dwTag; // [in] AssertTag
- char szAssert[DW_MAX_ASSERT_CCH]; // [in] Sz from the assert
- int AssertActionCode; // [out] action code to take
-
- DWORD cdwCallstack; // The number of actual callstack entries
- DWORD rgdwCallstack[DW_MAX_CALLSTACK]; // Callstack
-
-} AssertBlock;
-
-typedef struct _UserInterfaceBlock
-{
- // THIS ITEM IS REQUIRED. We do not go find your executable name to use instead.
- WCHAR wzGeneral_AppName[DW_APPNAME_LENGTH];
-
- // everything below this point is optional
- WCHAR wzGeneral_Reportee[DW_APPNAME_LENGTH]; // on whose behalf we request the report; otherwise "Microsoft"
-
- WCHAR wzMain_Caption[DW_MAX_ERROR_CWC]; // otherwise <General_AppName>
- WCHAR wzMain_IconFile[DW_MAX_PATH]; // otherwise pulled from executable
- WCHAR wzMain_Intro_Bold[DW_MAX_ERROR_CWC]; // otherwise "<General_AppName> has encountered a problem and needs to close. We are sorry for the inconvenience."
- WCHAR wzMain_Intro_Reg[DW_MAX_ERROR_CWC]; // various defaults, usually "Please tell <General_Reportee> about this problem"
- WCHAR wzMain_Checkbox[DW_MAX_ERROR_CWC]; // otherwise "Don't show me this again"
- WCHAR wzMain_Plea_Bold[DW_MAX_ERROR_CWC]; // otherwise "Please tell <General_Reportee> about this problem" ("NIL" means skip whole string)
- WCHAR wzMain_Plea_Reg[DW_MAX_ERROR_CWC]; // otherwise "We have created an error report that you can send to help us improve <General_AppName>. We will treat this report as confidential and anonymous."
- WCHAR wzMain_DetailsLink[DW_MAX_ERROR_CWC]; // otherwise "See what data this error report contains."
- WCHAR wzMain_ReportBtn[DW_APPNAME_LENGTH]; // otherwise "&Send Error Report"
- WCHAR wzMain_NoReportBtn[DW_APPNAME_LENGTH]; // otherwise "&Don't Send"
- WCHAR wzMain_AlwaysReportBtn[DW_APPNAME_LENGTH];// otherwise "&Send Error Report"
- WCHAR wzMain_QueueBtn[DW_APPNAME_LENGTH]; // otherwise "&Send Report Later"
- WCHAR wzMain_NoQueueBtn[DW_APPNAME_LENGTH]; // otherwise "&Don't Report"
- WCHAR wzMain_QueueText[DW_MAX_ERROR_CWC]; // otherwise "You cannot send this error report now because you are not connected...."
- WCHAR wzMain_FeedbackLink[DW_MAX_ERROR_CWC]; // otherwise "Why should I report to %General_Reportee%?"
-
- WCHAR wzDetails_Caption[DW_MAX_ERROR_CWC]; // otherwise <General_AppName>
- WCHAR wzDetails_Pre_Header[DW_MAX_ERROR_CWC]; // otherwise "Error Details"
- WCHAR wzDetails_Pre_Body[DW_MAX_ERROR_CWC]; // otherwise "foo" ("NIL" means delete whole Pre section)
- WCHAR wzDetails_Sig_Header[DW_MAX_ERROR_CWC]; // otherwise "Error Signature"
- WCHAR wzDetails_Sig_Body[DW_MAX_ERROR_CWC]; // otherwise constructed by DW from bucket params from stage 2 URL ("NIL" means delete whole Sig section)
- WCHAR wzDetails_Post_Header[DW_MAX_ERROR_CWC]; // otherwise "Reporting Details"
- WCHAR wzDetails_Post_Body[DW_MAX_ERROR_CWC]; // otherwise "This error report includes:..." ("NIL" means delete whole Post section)
- WCHAR wzDetails_TechLink[DW_MAX_ERROR_CWC]; // otherwise "View the contents of this error report"
- WCHAR wzDetails_DCPLink[DW_MAX_ERROR_CWC]; // otherwise "Read our Data Collection Policy"
-
- WCHAR wzTech_Caption[DW_MAX_ERROR_CWC]; // otherwise "Error Report Contents"
- WCHAR wzTech_MDump_Header[DW_MAX_ERROR_CWC]; // otherwise "The following information about your process will be reported...."
- WCHAR wzTech_Files_Header[DW_MAX_ERROR_CWC]; // otherwise "The following files will be included in this error report."
-
- WCHAR wzTransfer_Caption[DW_MAX_ERROR_CWC]; // otherwise "Error Reporting"
- WCHAR wzTransfer_1Check[DW_MAX_ERROR_CWC]; // otherwise "Preparing error report"
- WCHAR wzTransfer_2Check[DW_MAX_ERROR_CWC]; // otherwise "Connecting to server"
- WCHAR wzTransfer_3Check[DW_MAX_ERROR_CWC]; // otherwise "Checking for the status of this problem"
- WCHAR wzTransfer_Status_InProgress[DW_MAX_ERROR_CWC]; // otherwise "Transferring report..."
- WCHAR wzTransfer_Status_Done[DW_MAX_ERROR_CWC]; // otherwise "Reporting Completed. Thank you!"
- WCHAR wzTransfer_Checkbox[DW_MAX_ERROR_CWC]; // otherwise "Close When Done"
-
- WCHAR wzSecondLevel_Caption[DW_MAX_ERROR_CWC]; // otherwise "More Information"
- WCHAR wzSecondLevel_Pre[DW_MAX_ERROR_CWC]; // otherwise "In order to correctly diagnose this problem the following information...."
- WCHAR wzSecondLevel_Post[DW_MAX_ERROR_CWC]; // otherwise "Please click "Cancel" if you do not wish to share this information" (May also contain "Your files may contain sensitive information")
-
- WCHAR wzFinal_Caption[DW_MAX_ERROR_CWC]; // otherwise "Reporting"
- WCHAR wzFinal_Text[DW_MAX_ERROR_CWC]; // otherwise "Thank you for taking the time to report this problem."
- WCHAR wzFinal_Text_UserCancel[DW_MAX_ERROR_CWC]; // otherwise "Reporting stopped on user cancel."
- WCHAR wzFinal_Link[DW_MAX_ERROR_CWC]; // otherwise "Get more information about preventing this problem in the future."
- WCHAR wzFinal_Link_Survey[DW_MAX_ERROR_CWC]; // otherwise "Provide additional information about this problem via a short questionnaire."
-
- WCHAR wzStandby_Caption[DW_MAX_ERROR_CWC]; // otherwise "Power Management"
- WCHAR wzStandby_Body[DW_MAX_ERROR_CWC]; // otherwise "Windows cannot go on standby because <General_AppName> has experienced..."
-
- WCHAR wzDialup_Caption[DW_MAX_ERROR_CWC]; // otherwise "Active Internet Connection Required"
- WCHAR wzDialup_Body[DW_MAX_ERROR_CWC]; // otherwise "In order to report this problem, you must connect to the Internet. Please start your connection before continuing."
-
- WCHAR wzHangup_Caption[DW_MAX_ERROR_CWC]; // otherwise "Finished Reporting"
- WCHAR wzHangup_Body[DW_MAX_ERROR_CWC]; // otherwise "Reporting has finished. You may close your Internet connection now."
- WCHAR wzHangup_Body_UserCancel[DW_MAX_ERROR_CWC]; // otherwise "Reporting has been cancelled. You may close your Internet connection now."
-
- WCHAR wzQueued_EventDescription[DW_MAX_ERROR_CWC]; // otherwise "Application Error"
-
-} UserInterfaceBlock;
-
-
-typedef struct _CustomMinidumpBlock
-{
- BOOL fCustomMinidump;
- DWORD dwMinidumpType;
- BOOL fOnlyThisThread;
- DWORD dwThisThreadFlags;
- DWORD dwOtherThreadFlags;
- DWORD dwThisThreadExFlags;
- DWORD dwOtherThreadExFlags;
- DWORD dwPreferredModuleFlags;
- DWORD dwOtherModuleFlags;
-} CustomMinidumpBlock;
typedef struct _GenericModeBlock
{
@@ -479,107 +31,5 @@ typedef struct _GenericModeBlock
WCHAR wzP10[DW_MAX_BUCKETPARAM_CWC];
} GenericModeBlock;
-
-typedef struct _DWSharedMem20
-{
- DWORD dwSize; // should be set to size of DWSharedMem
- DWORD dwVersion; // callers should set this to DWCurrentVersion as in this header
-
- DWORD pid; // Process Id of caller
- DWORD tid; // Id of excepting thread
- DWORD_PTR eip; // EIP of the excepting instruction
- PEXCEPTION_POINTERS pep; // Exception pointers given to the callee's
- // exception handler
- HANDLE hEventDone; // event DW signals when done
- // caller will also signal this if it things
- // DW has hung and restarts itself
- HANDLE hEventNotifyDone; // App sets when it's done w/ notifcation phase
- HANDLE hEventAlive; // heartbeat event DW signals per EVENT_TIMEOUT
- HANDLE hMutex; // to protect the signaling of EventDone
- HANDLE hProc; // handle to the calling process
-
- DWORD bfDWRFlags; // controls caller-specific behaviors wrt REPORTING
- DWORD bfDWUFlags; // controls caller-specific behaviors wrt UI
- DWORD bfDWLFlags; // controls caller-specific behaviors wrt LOGGING
- DWORD bfDWEFlags; // controls caller-specific behaviors wrt EXCEPTION MODE SPECIFICS
- DWORD bfDWMFlags; // controls caller-specific behaviors wrt MISCELLANEOUS THINGS
-
- LCID lcidUI; // will try this UI langauge if non-zero
- // next DW will use the system LCID,
- // and if it can't find an intl dll for that,
- // will fall back on US English (1033)
-
- DWORD bfmsoctdsOffer; // bitfield of user choices to offer
- // note that you must specify two of:
- // Quit, Restart, Recover, Ignore
- // The Debug choice is independent
- DWORD bfmsoctdsNotify; // bitfield of user choices for which the
- // app wants control back instead of simply being
- // terminated by DW. The app will then be
- // responsible for pinging DW (if desired) with
- // hEventAlive and for notify DW it's ok to
- // terminate the app w/ hEventDone
-
- DWORD bfmsoctdsLetRun; // bitfield of user choices for which the
- // app wants control back instead of being
- // terminated by DW. DW can then safely ignore
- // the app and exit.
-
- WCHAR wzEventLogSource[DW_MAX_EVENTSOURCE]; // Set this as your source if you want to log events.
-
- WCHAR wzModuleFileName[DW_MAX_PATH]; // The result of GetModuleFileName(NULL)
-
- char szPIDRegKey[DW_MAX_PIDREGKEY]; // name of the key that holds the PID
- // can be used by the Server for
- // spoof-detection
- char szBrand[DW_APPNAME_LENGTH]; // passed as a param to Privacy Policy link
- char szCustomQueryStringElements[DW_MAX_PATH]; // passsed as param to Privacy Policy Link and Response Link
-
- char szCheckBoxRegKey[DW_MAX_PATH]; // If we get a key, we should show the
- // "Never send reports for this type of event" checkbox.
- // That string can be overridden in the UIB.
-
- WCHAR wzDotDataDlls[DW_MAX_PATH]; // contains the list of DLLs, terminated
- // by '\0' characters, that DW will
- // collect the .data sections into the
- // full minidump version
- // e.g. "mso9.dll\0outllib.dll\0"
-
- WCHAR wzFilesToDelete[1024]; // File list, seperated by DW_FILESEP
- // each of these files gets added to the
- // cab at upload time
- // These are files that we will delete
- // if fDwrDeleteFiles is sent.
-
- WCHAR wzFilesToKeep[1024]; // File list, seperated by DW_FILESEP
- // each of these files gets added to the
- // cab at upload time
- // These are files that we will NOT delete
- // if fDwrDeleteFiles is sent.
-
- WCHAR wzUserDocs[DW_MAX_USERDOCS_CWC]; // File list, seperated by DW_FILESEP
- // each of these files gets added to the
- // cab at upload time IFF we get a second-level request for them.
- // These are files that we will NOT delete
- // if fDwrDeleteFiles is sent.
-
- UserInterfaceBlock uib; // encapsulates UI override data. You must set the appname in here.
- AssertBlock ab; // encapsulates assert-tag data
- GenericModeBlock gmb; // encapsulates custom bucket parameters for generic mode
- CustomMinidumpBlock cmb; // encapsulates customization info for minidump gathering
-
- // OUTPARAMS
- DWORD msoctdsResult; // result from crash-time dialog
- BOOL fReportProblem; // did user approve reporting?
- WCHAR wzMinidumpLocation[DW_MAX_PATH]; // when fDweKeepMinidump is set, we write its name here.
- // it is available for access once hEventDone is signaled.
-
- // DYNAMIC INPARAMS used during recovery conversation for DW's UI
- int iPingCurrent; // current count for the recovery progress bar
- int iPingEnd; // index for the end of the recovery progress bar
-
-} DWSharedMem20, DWSharedMem;
-
-
#pragma pack(pop, msodw_h)
#endif // MSODW_H
diff --git a/src/inc/ostype.h b/src/inc/ostype.h
index c18d05a5f6..f17afb1d6f 100644
--- a/src/inc/ostype.h
+++ b/src/inc/ostype.h
@@ -24,17 +24,11 @@
//*****************************************************************************
typedef enum {
RUNNING_ON_STATUS_UNINITED = 0,
- RUNNING_ON_WINNT5 = 1,
- RUNNING_ON_WINXP = 2,
- RUNNING_ON_WIN2003 = 3, // _WIN64 can assume that all OSes that we're running on will be WIN2003+
- RUNNING_ON_VISTA = 4,
- RUNNING_ON_WIN7 = 5,
- RUNNING_ON_WIN8 = 6
+ RUNNING_ON_WIN7 = 1,
+ RUNNING_ON_WIN8 = 2
} RunningOnStatusEnum;
extern RunningOnStatusEnum gRunningOnStatus;
-extern BOOL gExInfoAvailable;
-extern BOOL gExInfoIsServer;
void InitRunningOnVersionStatus();
@@ -53,43 +47,12 @@ void InitWinRTStatus();
#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM
//*****************************************************************************
-//
-// List of currently supported platforms:
-//
-// Win2000 - not supported
-// WinXP - not supported
-// Win2k3 - not supported
-// Vista - desktop, CoreCLR
-// Win7 - desktop, CoreCLR
-// Win8 - desktop, CoreCLR on CoreSystem, ARM
-//
-//*****************************************************************************
-
-//*****************************************************************************
-// Returns true if you are running on Windows 7 or newer.
-//*****************************************************************************
-inline BOOL RunningOnWin7()
-{
- WRAPPER_NO_CONTRACT;
-#if defined(_ARM_) || defined(FEATURE_CORESYSTEM)
- return TRUE;
-#else
- if (gRunningOnStatus == RUNNING_ON_STATUS_UNINITED)
- {
- InitRunningOnVersionStatus();
- }
-
- return (gRunningOnStatus >= RUNNING_ON_WIN7) ? TRUE : FALSE;
-#endif
-}
-
-//*****************************************************************************
// Returns true if you are running on Windows 8 or newer.
//*****************************************************************************
inline BOOL RunningOnWin8()
{
WRAPPER_NO_CONTRACT;
-#if defined(_ARM_) || defined(CROSSGEN_COMPILE)
+#if (!defined(_X86_) && !defined(_AMD64_)) || defined(CROSSGEN_COMPILE)
return TRUE;
#else
if (gRunningOnStatus == RUNNING_ON_STATUS_UNINITED)
@@ -101,40 +64,6 @@ inline BOOL RunningOnWin8()
#endif
}
-//*****************************************************************************
-// Returns true if extra information is available
-//*****************************************************************************
-inline BOOL ExOSInfoAvailable()
-{
- WRAPPER_NO_CONTRACT;
- if (gRunningOnStatus == RUNNING_ON_STATUS_UNINITED)
- {
- InitRunningOnVersionStatus();
- }
-
- return gExInfoAvailable;
-}
-
-//*****************************************************************************
-// Returns true if we're running on a server OS. Requires ExOSInfoAvailable()
-// to be TRUE
-//*****************************************************************************
-inline BOOL ExOSInfoRunningOnServer()
-{
- WRAPPER_NO_CONTRACT;
- /*
- @TODO: _ASSERTE not available here...
- _ASSERTE(ExOSInfoAvailable() &&
- "You should only call this after making sure ExOSInfoAvailable() returned TRUE");
- */
- if (gRunningOnStatus == RUNNING_ON_STATUS_UNINITED)
- {
- InitRunningOnVersionStatus();
- }
-
- return gExInfoIsServer;
-}
-
#ifdef FEATURE_COMINTEROP
#ifdef FEATURE_CORESYSTEM
diff --git a/src/utilcode/util_nodependencies.cpp b/src/utilcode/util_nodependencies.cpp
index 7ce3c83036..387ccbe071 100644
--- a/src/utilcode/util_nodependencies.cpp
+++ b/src/utilcode/util_nodependencies.cpp
@@ -18,11 +18,9 @@
#if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) || defined(_DEBUG)
RunningOnStatusEnum gRunningOnStatus = RUNNING_ON_STATUS_UNINITED;
-BOOL gExInfoAvailable = FALSE;
-BOOL gExInfoIsServer = TRUE;
#define NON_SUPPORTED_PLATFORM_MSGBOX_TITLE W("Platform not supported")
-#define NON_SUPPORTED_PLATFORM_MSGBOX_TEXT W("The minimum supported platform is Windows 2000")
+#define NON_SUPPORTED_PLATFORM_MSGBOX_TEXT W("The minimum supported platform is Windows 7")
#define NON_SUPPORTED_PLATFORM_TERMINATE_ERROR_CODE 0xBAD1BAD1
//*****************************************************************************
@@ -81,84 +79,6 @@ void InitRunningOnVersionStatus ()
goto CHECK_SUPPORTED;
}
-
- ZeroMemory(&sVer, sizeof(OSVERSIONINFOEX));
- sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
- sVer.dwMajorVersion = 6;
- sVer.dwPlatformId = VER_PLATFORM_WIN32_NT;
-
-
- dwlConditionMask = 0;
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_PLATFORMID, VER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_MAJORVERSION, VER_GREATER_EQUAL);
-
- if(VerifyVersionInfo(&sVer, CLR_VER_MAJORVERSION | CLR_VER_PLATFORMID, dwlConditionMask))
- {
- gRunningOnStatus = RUNNING_ON_VISTA;
- fSupportedPlatform = TRUE;
- goto CHECK_SUPPORTED;
- }
-
-
- ZeroMemory(&sVer, sizeof(OSVERSIONINFOEX));
- sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
- sVer.dwMajorVersion = 5;
- sVer.dwMinorVersion = 2;
- sVer.dwPlatformId = VER_PLATFORM_WIN32_NT;
-
-
- dwlConditionMask = 0;
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_PLATFORMID, VER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_MAJORVERSION, VER_GREATER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_MINORVERSION, VER_GREATER_EQUAL);
-
- if(VerifyVersionInfo(&sVer, CLR_VER_MAJORVERSION | CLR_VER_PLATFORMID | CLR_VER_MINORVERSION, dwlConditionMask))
- {
- gRunningOnStatus = RUNNING_ON_WIN2003;
- fSupportedPlatform = TRUE;
- goto CHECK_SUPPORTED;
- }
-
- sVer.dwMajorVersion = 5;
- sVer.dwMinorVersion = 1;
- sVer.dwPlatformId = VER_PLATFORM_WIN32_NT;
-
- dwlConditionMask = 0;
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_PLATFORMID, VER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_MAJORVERSION, VER_GREATER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_MINORVERSION, VER_GREATER_EQUAL);
-
- if(VerifyVersionInfo(&sVer, CLR_VER_MAJORVERSION | CLR_VER_PLATFORMID | CLR_VER_MINORVERSION, dwlConditionMask))
- {
- gRunningOnStatus = RUNNING_ON_WINXP;
- fSupportedPlatform = TRUE;
- goto CHECK_SUPPORTED;
- }
-
-
-
- ZeroMemory(&sVer, sizeof(OSVERSIONINFOEX));
- sVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
-
- sVer.dwMajorVersion = 5;
- sVer.dwMinorVersion = 0;
- sVer.dwPlatformId = VER_PLATFORM_WIN32_NT;
-
-
- dwlConditionMask = 0;
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_PLATFORMID, VER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_MAJORVERSION, VER_GREATER_EQUAL);
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_MINORVERSION, VER_GREATER_EQUAL);
-
- if(VerifyVersionInfo(&sVer, CLR_VER_MAJORVERSION | CLR_VER_PLATFORMID | CLR_VER_MINORVERSION, dwlConditionMask))
- {
- gRunningOnStatus = RUNNING_ON_WINNT5;
- fSupportedPlatform = TRUE;
- goto CHECK_SUPPORTED;
- }
-
CHECK_SUPPORTED:
if (!fSupportedPlatform)
@@ -170,36 +90,6 @@ CHECK_SUPPORTED:
TerminateProcess(GetCurrentProcess(), NON_SUPPORTED_PLATFORM_TERMINATE_ERROR_CODE);
}
- gExInfoAvailable = 0;
- gExInfoIsServer = 0;
-
- OSVERSIONINFOEX sVerX;
- ZeroMemory(&sVerX, sizeof(OSVERSIONINFOEX));
- sVerX.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- sVerX.wProductType = VER_NT_DOMAIN_CONTROLLER;
-
- dwlConditionMask = 0;
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_PRODUCT_TYPE, VER_EQUAL);
-
- if(VerifyVersionInfo(&sVerX, CLR_VER_PRODUCT_TYPE, dwlConditionMask))
- {
- gExInfoIsServer = 1;
- }
-
-
- ZeroMemory(&sVerX, sizeof(OSVERSIONINFOEX));
- sVerX.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- sVerX.wProductType = VER_NT_SERVER;
-
- dwlConditionMask = 0;
- VER_SET_CONDITION(dwlConditionMask, CLR_VER_PRODUCT_TYPE, VER_EQUAL);
-
- if(VerifyVersionInfo(&sVerX, CLR_VER_PRODUCT_TYPE, dwlConditionMask))
- {
- gExInfoIsServer = 1;
- }
-
- gExInfoAvailable = 1;
#else // FEATURE_PAL
// UNIXTODO: Do we need version checks for Linux?
#endif // FEATURE_PAL
diff --git a/src/vm/ceemain.cpp b/src/vm/ceemain.cpp
index 20b579af9a..0f2efd64c0 100644
--- a/src/vm/ceemain.cpp
+++ b/src/vm/ceemain.cpp
@@ -910,19 +910,8 @@ void EEStartupHelper(COINITIEE fFlags)
#ifndef CROSSGEN_COMPILE
-#ifndef FEATURE_PAL
- // Watson initialization must precede InitializeDebugger() and InstallUnhandledExceptionFilter()
- // because on CoreCLR when Waston is enabled, debugging service needs to be enabled and UEF will be used.
- if (!InitializeWatson(fFlags))
- {
- IfFailGo(E_FAIL);
- }
-
- // Note: In Windows 7, the OS will take over the job of error reporting, and so most
- // of our watson code should not be used. In such cases, we will however still need
- // to provide some services to windows error reporting, such as computing bucket
- // parameters for a managed unhandled exception.
- if (RunningOnWin7() && IsWatsonEnabled() && !RegisterOutOfProcessWatsonCallbacks())
+#ifndef FEATURE_PAL
+ if (!RegisterOutOfProcessWatsonCallbacks())
{
IfFailGo(E_FAIL);
}
diff --git a/src/vm/crossgencompile.cpp b/src/vm/crossgencompile.cpp
index f608afcad4..47894bfbdd 100644
--- a/src/vm/crossgencompile.cpp
+++ b/src/vm/crossgencompile.cpp
@@ -255,13 +255,6 @@ PCODE MethodDesc::TryGetMultiCallableAddrOfCode(CORINFO_ACCESS_FLAGS accessFlags
return 0x321;
}
-#ifdef _TARGET_X86_
-BOOL Runtime_Test_For_SSE2()
-{
- return TRUE;
-}
-#endif
-
#ifdef _TARGET_AMD64_
INT32 rel32UsingJumpStub(INT32 UNALIGNED * pRel32, PCODE target, MethodDesc *pMethod,
LoaderAllocator *pLoaderAllocator /* = NULL */, bool throwOnOutOfMemoryWithinRange /*= true*/)
diff --git a/src/vm/dwreport.cpp b/src/vm/dwreport.cpp
index 57d67e7c22..0890f3f334 100644
--- a/src/vm/dwreport.cpp
+++ b/src/vm/dwreport.cpp
@@ -27,75 +27,13 @@
#include "utilcode.h"
#include "../dlls/mscorrc/resource.h" // for resource ids
-#include "imagehlp.h"
-
EFaultRepRetVal DoReportFault(EXCEPTION_POINTERS * pExceptionInfo);
-// Should the CLR use Watson to report fatal errors and unhandled exceptions?
-static BOOL g_watsonErrorReportingEnabled = FALSE;
// Variables to control launching Watson only once, but making all threads wait for that single launch to finish.
LONG g_watsonAlreadyLaunched = 0; // Used to note that another thread has done Watson.
-HandleHolder g_hWatsonCompletionEvent = NULL; // Used to signal that Watson has finished.
-
-const WCHAR kErrorReportingPoliciesKey[] = W("SOFTWARE\\Policies\\Microsoft\\PCHealth\\ErrorReporting");
-const WCHAR kErrorReportingKey[] = W("SOFTWARE\\Microsoft\\PCHealth\\ErrorReporting");
-
-const WCHAR kShowUIValue[] = W("ShowUI");
-const WCHAR kForceQueueModeValue[] = W("ForceQueueMode");
-const WCHAR kDoReportValue[] = W("DoReport");
-const WCHAR kAllOrNoneValue[] = W("AllOrNone");
-const WCHAR kIncludeMSAppsValue[] = W("IncludeMicrosoftApps");
-const WCHAR kIncludeWindowsAppsValue[] = W("IncludeWindowsApps");
-const WCHAR kExclusionListKey[] = W("SOFTWARE\\Microsoft\\PCHealth\\ErrorReporting\\ExclusionList");
-const WCHAR kInclusionListKey[] = W("SOFTWARE\\Microsoft\\PCHealth\\ErrorReporting\\InclusionList");
-const WCHAR kExclusionListSubKey[] = W("\\ExclusionList");
-const WCHAR kInclusionListSubKey[] = W("\\InclusionList");
-
-
-// Default values for various registry keys
-const DWORD kDefaultShowUIValue = 1;
-const DWORD kDefaultForceQueueModeValue = 0;
-const DWORD kDefaultDoReportValue = 1;
-const DWORD kDefaultAllOrNoneValue = 1;
-const DWORD kDefaultExclusionValue = 0;
-const DWORD kDefaultInclusionValue = 0;
-const DWORD kDefaultIncludeMSAppsValue = 1;
-const DWORD kDefaultIncludeWindowsAppsValue = 1;
-
-// Default value for the default debugger and auto debugger attach settings.
-const BOOL kDefaultDebuggerIsWatson = FALSE;
-const BOOL kDefaultAutoValue = FALSE;
-
-// When debugging the watson process itself, the faulting process will spin
-// waiting for Watson to signal various events. If these waits time out, the
-// faulting process will go ahead and exit, which is sub-optimal if you need to
-// inspect the faulting process with the debugger at the same time. In debug
-// builds, use a longer wait time, since watson may be stopped under the
-// debugger for a while.
-
-#ifdef _DEBUG
-const DWORD kDwWaitTime = DW_TIMEOUT_VALUE * 1000;
-#else
-const DWORD kDwWaitTime = DW_TIMEOUT_VALUE;
-#endif
-
-#ifdef _TARGET_X86_
- const DWORD kWatsonRegKeyOptions = 0;
-#else
- const DWORD kWatsonRegKeyOptions = KEY_WOW64_32KEY;
-#endif
-
-const WCHAR kWatsonPath[] = WATSON_INSTALLED_REG_SUBPATH;
-#if defined(_TARGET_X86_)
-const WCHAR kWatsonValue[] = WATSON_INSTALLED_REG_VAL;
-#else
-const WCHAR kWatsonValue[] = WATSON_INSTALLED_REG_VAL_IA64;
-#endif
-const WCHAR* kWatsonImageNameOnLonghorn = W("\\dw20.exe");
-
typedef HMODULE (*AcquireLibraryHandleFn)(LPCWSTR);
template <AcquireLibraryHandleFn AcquireLibraryHandleFnPtr, bool RequiresFree>
@@ -143,43 +81,11 @@ typedef SimpleModuleHolder<CLRLoadLibrary, true> WerModuleHolder;
BOOL IsWatsonEnabled()
{
LIMITED_METHOD_CONTRACT;
- return g_watsonErrorReportingEnabled;
+ return TRUE;
}
//------------------------------------------------------------------------------
// Description
-// Initializes watson global critsec and event. Records whether run via
-// managed .exe.
-//
-// Parameters
-// fFlags -- the COINITIEE flags used to start the runtime.
-//
-// Returns
-// TRUE -- always
-//------------------------------------------------------------------------------
-BOOL InitializeWatson(COINITIEE fFlags)
-{
- LIMITED_METHOD_CONTRACT;
-
- // Watson is enabled for all SKUs
- g_watsonErrorReportingEnabled = TRUE;
-
- LOG((LF_EH, LL_INFO10, "InitializeWatson: %s\n", g_watsonErrorReportingEnabled ? "enabled" : "disabled"));
-
- if (!IsWatsonEnabled())
- {
- return TRUE;
- }
-
- // Create the event that all-but-the-first threads will wait on (the first thread
- // will set the event when Watson is done.)
- g_hWatsonCompletionEvent = WszCreateEvent(NULL, TRUE /*manual reset*/, FALSE /*initial state*/, NULL);
- return (g_hWatsonCompletionEvent != NULL);
-
-} // BOOL InitializeWatson()
-
-//------------------------------------------------------------------------------
-// Description
// Register out-of-process Watson callbacks provided in DAC dll for WIN7 or later
//
// Parameters
@@ -199,7 +105,6 @@ BOOL RegisterOutOfProcessWatsonCallbacks()
{
NOTHROW;
GC_NOTRIGGER;
- PRECONDITION(RunningOnWin7());
}
CONTRACTL_END;
@@ -272,85 +177,9 @@ BOOL RegisterOutOfProcessWatsonCallbacks()
}
//------------------------------------------------------------------------------
-// CreateWatsonSharedMemory
-//
// Description
-//
-// Creates a shared memory block for communication with Watson
-//
-// Parameters
-// hWatsonSharedMemory -- [out] The handle to the watson shared memory.
-// ppWatsonSharedMemory -- [out] A pointer to the Watson shared memory.
-// Returns
-// S_OK -- if the function complete normally.
-// FALSE -- otherwise
-// Exceptions
-// None
-//------------------------------------------------------------------------------
-HRESULT CreateWatsonSharedMemory(HANDLE* hWatsonSharedMemory,
- DWSharedMem** ppWatsonSharedMemory);
-
//------------------------------------------------------------------------------
// Description
-// Alerts the host that the thread is leaving the runtime, and sleeps
-// waiting for an object to be signalled
-//
-// Parameters
-// handle -- the handle to wait on
-// timeout -- the length of time to wait
-//
-// Returns
-// DWORD -- The return value from WaitForSingleObject
-//
-// Exceptions
-// None
-//
-// Notes
-// winwrap.h prevents us from using SetEvent by including
-// #define SetEvent Dont_Use_SetEvent
-// This is because using SetEvent within the runtime will result in poor
-// interaction with any sort of host process (e.g. SQL). We can use the
-// SetEvent/WaitForSingleObject primitives as long as we do some other work to
-// make sure the host understands.
-//------------------------------------------------------------------------------
-#undef SetEvent
-DWORD ClrWaitForSingleObject(HANDLE handle, DWORD timeout)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- SO_TOLERANT;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- CONTRACT_VIOLATION(ThrowsViolation);
-
- return WaitForSingleObject(handle, timeout);
-} // DWORD ClrWaitForSingleObject()
-
-//------------------------------------------------------------------------------
-// Helper class to set an event in destructor -- allows setting an event on the
-// way out of a function.
-//
-// Used to synchronize multiple threads with unhandled exceptions -- only the
-// first will run Watson, and all the rest will wait on the first one to be
-// done.
-//------------------------------------------------------------------------------
-class SettingEventHolder
-{
-public:
- SettingEventHolder(HANDLE &event) : m_event(event), m_bSetIt(FALSE) { LIMITED_METHOD_CONTRACT; }
- ~SettingEventHolder() { LIMITED_METHOD_CONTRACT; if (m_bSetIt && m_event) SetEvent(m_event); }
- void EnableSetting() { LIMITED_METHOD_CONTRACT; m_bSetIt = TRUE; }
- DWORD DoWait(DWORD timeout=INFINITE_TIMEOUT) { WRAPPER_NO_CONTRACT; return m_event ? ClrWaitForSingleObject(m_event, timeout) : 0; }
-
-private:
- HANDLE m_event; // The event to set
- BOOL m_bSetIt; // If true, set event in destructor.
-};
-
HRESULT DwGetFileVersionInfo(
__in_z LPCWSTR wszFilePath,
USHORT& major,
@@ -381,168 +210,6 @@ HRESULT DwGetFileVersionInfo(
return result;
}
-enum MicrosoftAppTypes
-{
- MicrosoftAppTypesNone = 0,
- MicrosoftAppTypesWindows = 0x1,
- MicrosoftAppTypesOther = 0x2
-};
-
-inline void SetMSFTApp(DWORD &AppType) { LIMITED_METHOD_CONTRACT; AppType |= MicrosoftAppTypesOther; }
-inline void SetMSFTWindowsApp(DWORD &AppType) { LIMITED_METHOD_CONTRACT; AppType |= MicrosoftAppTypesWindows; }
-
-inline BOOL IsMSFTApp(DWORD AppType) { LIMITED_METHOD_CONTRACT; return (AppType & MicrosoftAppTypesOther) ? TRUE : FALSE; }
-inline BOOL IsMSFTWindowsApp(DWORD AppType) { LIMITED_METHOD_CONTRACT; return (AppType & MicrosoftAppTypesWindows) ? TRUE : FALSE; }
-
-
-//------------------------------------------------------------------------------
-// Description
-// Determine if the application is a Microsoft application.
-//
-// Parameters
-// wszFilePath Path to a file to exctract the information from
-// pAppTypes [out] Put MicrosoftAppTypes here.
-//
-// Returns
-// S_OK If the function succeede
-// E_XXXX Failure result.
-//
-// Exceptions
-// None
-//------------------------------------------------------------------------------
-HRESULT DwCheckCompany( // S_OK or error.
- __in_z LPWSTR wszFilePath, // Path to the executable.
- DWORD* pAppTypes) // Non-microsoft, microsoft, microsoft windows.
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- //
- // Note that this code is equivalent to FusionGetFileVersionInfo, found in fusion\asmcache\asmcache.cpp
- //
-
- HRESULT hr = S_OK; // result of some operation
- DWORD dwHandle = 0;
- DWORD bufSize = 0; // Size of allocation for VersionInfo.
- DWORD ret;
-
- // Avoid confusion
- *pAppTypes = MicrosoftAppTypesNone;
-
- // Find the buffer size for the version info structure we need to create
- EX_TRY
- {
- bufSize = GetFileVersionInfoSizeW(wszFilePath, &dwHandle);
- if (!bufSize)
- {
- hr = HRESULT_FROM_GetLastErrorNA();
- }
- }
- EX_CATCH
- {
- hr = E_OUTOFMEMORY;
- }
- EX_END_CATCH(SwallowAllExceptions);
- if (!bufSize)
- {
- return hr;
- }
-
- // Allocate the buffer for the version info structure
- // _alloca() can't return NULL -- raises STATUS_STACK_OVERFLOW.
- BYTE* pVersionInfoBuffer = reinterpret_cast< BYTE* >(_alloca(bufSize));
-
- // Extract the version information blob. The version information
- // contains much more than the actual item of interest.
- {
- // If the previoud GetFileVersionInfoSizeW succeeds, version.dll has been loaded
- // in the process, and delay load of GetFileVersionInfoW will not throw.
- CONTRACT_VIOLATION(ThrowsViolation);
- ret = GetFileVersionInfoW(wszFilePath, dwHandle, bufSize, pVersionInfoBuffer);
-
- if (!ret)
- {
- return HRESULT_FROM_GetLastErrorNA();
- }
- }
-
- // Extract the actual CompanyName and compare it to "Microsoft" and
- // "MicrosoftWindows"
-
- // Get the language and codepage for the version info.
- UINT size = 0;
- struct
- {
- WORD language;
- WORD codePage;
- }* translation;
-
- {
- // If the previoud GetFileVersionInfoSizeW succeeds, version.dll has been loaded
- // in the process, and delay load of GetFileVersionInfoW will not throw.
- CONTRACT_VIOLATION(ThrowsViolation);
- ret = VerQueryValueW(pVersionInfoBuffer, W("\\VarFileInfo\\Translation"),
- reinterpret_cast< void **>(&translation), &size);
-
- if (!ret || size == 0)
- {
- return HRESULT_FROM_GetLastErrorNA();
- }
- }
-
- // Build the query key for the language-specific company name resource.
- WCHAR buf[64]; //----+----1----+----2----+----3----+----4
- _snwprintf_s(buf, NumItems(buf), _TRUNCATE, W("\\StringFileInfo\\%04x%04x\\CompanyName"),
- translation->language, translation->codePage);
-
- // Get the company name.
- WCHAR *name;
- {
- // If the previoud GetFileVersionInfoSizeW succeeds, version.dll has been loaded
- // in the process, and delay load of GetFileVersionInfoW will not throw.
- CONTRACT_VIOLATION(ThrowsViolation);
- ret = VerQueryValueW(pVersionInfoBuffer, buf,
- reinterpret_cast< void** >(&name), &size);
- }
-
- // If there is company name info, check it.
- if (ret != 0 && size != 0 && wcsstr(name, W("Microsoft")))
- {
- SetMSFTApp(*pAppTypes);
- }
-
-
- // Now build the query key for the language-specific product name resource.
- _snwprintf_s(buf, NumItems(buf), _TRUNCATE, W("\\StringFileInfo\\%04x%04x\\ProductName"),
- translation->language, translation->codePage);
-
- // Get the product name.
- {
- // If the previoud GetFileVersionInfoSizeW succeeds, version.dll has been loaded
- // in the process, and delay load of GetFileVersionInfoW will not throw.
- CONTRACT_VIOLATION(ThrowsViolation);
- ret = VerQueryValueW(pVersionInfoBuffer, buf,
- reinterpret_cast< void** >(&name), &size);
- }
-
- // If there is product name info, check it.
- if (ret != 0 && size != 0 && wcsstr(name, W("Microsoft\x0ae Windows\x0ae")))
- {
- SetMSFTWindowsApp(*pAppTypes);
- }
-
- return S_OK;
-
-} // HRESULT DwCheckCompany()
-
-
-//------------------------------------------------------------------------------
-// Description
// Read the description from the resource section.
//
// Parameters
@@ -797,914 +464,6 @@ int DwGetAssemblyVersion( // Number of characters written.
} // int DwGetAssemblyVersion()
-
-//------------------------------------------------------------------------------
-// CLRWatsonHelper class
-//
-// Certain registry keys affect the behavior of watson. In particulary, they
-// control
-// o whether or not a Watson report should result in UI popups
-// o which debugger should be used to JIT attach to the faulting process
-// o whether error reports should be sent at all.
-// This class is a holder for static functions that access these registry keys
-// to determine the proper settings.
-//
-//------------------------------------------------------------------------------
-class CLRWatsonHelper
-{
-public:
- enum WHDebugAction
- {
- WHDebug_InvalidValue,
- WHDebug_AutoLaunch,
- WHDebug_AskToLaunch,
- WHDebug_DontLaunch
- } m_debugAction;
-
- enum WHReportAction
- {
- WHReport_InvalidValue,
- WHReport_AutoQueue,
- WHReport_AskToSend,
- WHReport_DontSend
- } m_reportAction;
-
- enum WHDialogAction
- {
- WHDialog_InvalidValue,
- WHDialog_OkToPopup,
- WHDialog_DontPopup
- } m_dialogAction;
-
- CLRWatsonHelper()
- : m_debugAction(WHDebug_InvalidValue),
- m_reportAction(WHReport_InvalidValue),
- m_dialogAction(WHDialog_InvalidValue)
- { LIMITED_METHOD_CONTRACT; }
-
- void Init(BOOL bIsManagedFault, TypeOfReportedError tore);
-
- // Does the current interactive USER have sufficient permissions to
- // launch Watson or a debugger against this PROCESS?
- BOOL CurrentUserHasSufficientPermissions();
-
- // Should a debugger automatically, or should the user be queried for a debugger?
- BOOL ShouldDebug();
-
- // Should a managed debugger be launched, without even asking?
- BOOL ShouldAutoAttach();
-
- // Should Watson include a "Debug" button?
- BOOL ShouldOfferDebug();
-
- // Should a Watson report be generated?
- BOOL ShouldReport();
-
- // Should there be a popup? Possibly with only "quit"?
- BOOL ShouldShowUI();
-
- // If a Watson report is generated, should it be auto-queued?
- // (vs asking the user what to do about it)
- BOOL ShouldQueueReport();
-
-private:
- // Looks in HKCU/Software/Policies/Microsoft/PCHealth/ErrorReporting
- // then in HKLM/ " " " " "
- // then in HKCU/SOftware/Microsoft/PCHealth/ErrorReporting
- // then in HKLM/ " " " "
- static int GetPCHealthConfigLong( // Return value from registry or default.
- LPCWSTR szName, // Name of value to get.
- int iDefault); // Default value to return if not found.
-
- // Like above, but searches for a subkey with the given value.
- static BOOL GetPCHealthConfigSubKeyLong(// Return value from registry or default.
- LPCWSTR szSubKey, // Name of the subkey.
- LPCWSTR szName, // Name of value to get.
- int iDefault, // Default value to return if not found.
- DWORD *pValue); // Put value here.
-
- void AssertValid()
- {
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(m_debugAction != WHDebug_InvalidValue);
- _ASSERTE(m_reportAction != WHReport_InvalidValue);
- _ASSERTE(m_dialogAction != WHDialog_InvalidValue);
- }
-
-}; // class CLRWatsonHelper
-
-//------------------------------------------------------------------------------
-// Description
-// Initialization for watson helper class.
-//
-// Parameters
-// bIsManagedFault - true if EXCEPTION_COMPLUS or fault from jitted code.
-// - false otherwise
-//
-//
-// Notes:
-// - Launches and Pops always happen to the same session in which the
-// process is running.
-// - This function computes what actions should happen, but doesn't do any.
-//
-// This routine returns which actions should be taken given the current registry
-// settings and environment. It implements the following matrix:
-//
-// <<-- AutoLaunch -->>
-// TRUE FALSE
-// Interactive process A3 B2
-// Non-interactive process A3 C1
-//
-// Action codes:
-// A - Auto attach debugger
-// B - Ask to attach debugger
-// C - Don't attach debugger
-//
-// 1 - Auto Queue Watson report
-// 2 - Ask to Send Watson report
-// 3 - Don't send Watson report
-//
-//
-// CLRWatsonHelper::Init
-//------------------------------------------------------------------------------
-void CLRWatsonHelper::Init(
- BOOL bIsManagedFault, // Is the fault in question from managed code?
- TypeOfReportedError tore) // What sort of error is this?
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // Initialize returned values
- WHDebugAction tmpDebugAction = WHDebug_InvalidValue;
- WHReportAction tmpReportAction = WHReport_InvalidValue;
- WHDialogAction tmpDialogAction = WHDialog_InvalidValue;
-
- // First run the matrix, then later provide the over-rides
- BOOL fRunningInteractive = RunningInteractive();
-
- if (fRunningInteractive)
- {
- // Interactive services and interactive apps running as LocalSystem are considered non-interactive
- // so that we don't display any UI for them. Note that we should check the process token (and not the
- // thread token if the thread is impersonating a user) to determine if the app is running as LocalSystem.
- // This is because Watson displays UI for us and Watson is run by calling CreateProcess. CreateProcess
- // always creates child processes using the process token.
-
- BOOL fLocalSystemOrService;
- if (RunningAsLocalSystemOrService(fLocalSystemOrService) != ERROR_SUCCESS)
- {
- // Err on the side of caution; treat the app as non-interactive
- fRunningInteractive = FALSE;
- }
- else if (fLocalSystemOrService)
- {
- fRunningInteractive = FALSE;
- }
- }
-
- BOOL bAutoLaunch = FALSE;
- SString ssDummy;
-
- GetDebuggerSettingInfo(ssDummy, &bAutoLaunch);
-
- if (bAutoLaunch)
- {
- tmpDebugAction = WHDebug_AutoLaunch;
- tmpReportAction = WHReport_DontSend;
- tmpDialogAction = WHDialog_DontPopup;
- }
- else
- {
- if (fRunningInteractive)
- {
- tmpDebugAction = WHDebug_AskToLaunch;
- tmpReportAction = WHReport_AskToSend;
- tmpDialogAction = WHDialog_OkToPopup;
- }
- else
- {
- // Non-interactive process
- tmpDebugAction = WHDebug_DontLaunch;
- tmpReportAction = WHReport_AutoQueue;
- tmpDialogAction = WHDialog_DontPopup;
- }
- }
-
- // If this is a breakpoint, never send a report.
- if (tore.IsBreakpoint())
- tmpReportAction = WHReport_DontSend;
-
- // Store off the results.
- m_debugAction = tmpDebugAction;
- m_reportAction = tmpReportAction;
- m_dialogAction = tmpDialogAction;
-
- // Done. Log some stuff in debug mode.
- #if defined(_DEBUG)
- {
- char *(rda[]) = {"InvalidValue", "AutoDebug", "AskToDebug", "DontDebug"};
- char *(rwa[]) = {"InvalidValue", "AutoQueue", "AskToSend", "DontSend"};
- char *(rdlga[]) = {"InvalidValue", "OkToPopup", "DontPopup"};
- LOG((LF_EH, LL_INFO100, "CLR Watson: debug action: %s\n", rda[m_debugAction]));
- LOG((LF_EH, LL_INFO100, "CLR Watson: report action: %s\n", rwa[m_reportAction]));
- LOG((LF_EH, LL_INFO100, "CLR Watson: dialog action: %s\n", rdlga[m_dialogAction]));
- #define LB(expr) LOG((LF_EH, LL_INFO100, "CLR Watson: " #expr ": %s\n", ((expr) ? "true" : "false") ))
- LB(CurrentUserHasSufficientPermissions());
- LB(ShouldDebug());
- LB(ShouldAutoAttach());
- LB(ShouldOfferDebug());
- LB(ShouldReport());
- LB(ShouldQueueReport());
- #undef LB
- }
- #endif
-
-} // void CLRWatsonHelper::Init()
-
-
-//------------------------------------------------------------------------------
-// CurrentUserHasSufficientPermissions
-//
-// Determines if the user logged in has the correct permissions to launch Watson.
-//
-// Parameters:
-// None.
-//
-// Returns:
-// TRUE if the user has sufficient permissions, else FALSE
-//------------------------------------------------------------------------------
-BOOL CLRWatsonHelper::CurrentUserHasSufficientPermissions()
-{
- // TODO! Implement!
- return TRUE;
-} // BOOL CLRWatsonHelper::CurrentUserHasSufficientPermissions()
-
-
-
-//------------------------------------------------------------------------------
-// Description
-// Determines whether we will show Watson at all.
-//
-// Parameters
-// none
-//
-// Returns
-// TRUE -- If Watson should show UI.
-// FALSE -- Otherwise
-//------------------------------------------------------------------------------
-BOOL CLRWatsonHelper::ShouldShowUI()
-{
- WRAPPER_NO_CONTRACT;
-
- AssertValid();
-
- return (m_dialogAction == WHDialog_OkToPopup);
-} // BOOL CLRWatsonHelper::ShouldShowUI()
-
-//------------------------------------------------------------------------------
-// Description
-// Determines whether a debugger will (or may be) launched. True if there
-// is an auto-launch debugger, or if we will ask the user.
-//
-// Parameters
-// none
-//
-// Returns
-// TRUE -- If a debugger might be attached.
-// FALSE -- Otherwise
-//------------------------------------------------------------------------------
-BOOL CLRWatsonHelper::ShouldDebug()
-{
- LIMITED_METHOD_CONTRACT;
-
- return ShouldOfferDebug() || ShouldAutoAttach();
-} // BOOL CLRWatsonHelper::ShouldDebug()
-
-//------------------------------------------------------------------------------
-// Description
-// Determines whether or not the Debug button should be present in the
-// Watson dialog
-//
-// Parameters
-// none
-//
-// Returns
-// TRUE -- if the Debug button should be displayed
-// FALSE -- otherwise
-//
-// Notes
-// This means "is there an appropriate debugger registered for auto attach?"
-//------------------------------------------------------------------------------
-BOOL CLRWatsonHelper::ShouldOfferDebug()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- AssertValid();
-
- // Permission check.
- if (!CurrentUserHasSufficientPermissions())
- {
- return FALSE;
- }
-
- // Check based on DbgJitDebugLaunchSetting & interactivity.
- if (m_debugAction != WHDebug_AskToLaunch)
- {
- // Don't ask the user about debugging. Do or don't debug; but don't ask.
- return FALSE;
- }
-
- SString ssDebuggerString;
- GetDebuggerSettingInfo(ssDebuggerString, NULL);
-
- // If there is no debugger installed, don't offer to debug, since we can't.
- if (ssDebuggerString.IsEmpty())
- {
- return FALSE;
- }
-
- return TRUE;
-
-} // BOOL CLRWatsonHelper::ShouldOfferDebug()
-
-//------------------------------------------------------------------------------
-//
-// ShouldAutoAttach
-//
-// Description
-// Determines whether or not a debugger should be launched
-// automatically, without prompting the user.
-//
-// Parameters
-// None.
-//
-// Returns
-// TRUE -- If a debugger should be auto-attached.
-// FALSE -- Otherwise
-//
-//------------------------------------------------------------------------------
-BOOL CLRWatsonHelper::ShouldAutoAttach()
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- AssertValid();
-
- // Permissions check.
- if (!CurrentUserHasSufficientPermissions())
- {
- return FALSE;
- }
-
- return (m_debugAction == WHDebug_AutoLaunch);
-} // BOOL CLRWatsonHelper::ShouldAutoAttach()
-
-
-//------------------------------------------------------------------------------
-// Description
-// Returns whether a Watson report should be generated.
-//
-// Parameters
-// none
-//
-// Returns
-// TRUE - a Watson report should be generated (with a minidump).
-// FALSE - don't generate a report.
-//
-//------------------------------------------------------------------------------
-BOOL CLRWatsonHelper::ShouldReport()
-{
- WRAPPER_NO_CONTRACT;
-
- AssertValid();
-
- // If we queue or ask, we should generate.
- return (m_reportAction == WHReport_AutoQueue) || (m_reportAction == WHReport_AskToSend);
-
-} // BOOL CLRWatsonHelper::ShouldReport()
-
-
-//------------------------------------------------------------------------------
-// Description
-// If a Watson report is generated, returns whether it should be auto-queued.
-// (vs asking the user what to do about it)
-//
-// Parameters
-// none
-//
-// Returns
-// TRUE - any Watson report should be be queued.
-// FALSE - any Watson report is posed to the user for "send" or "don't send".
-//
-//------------------------------------------------------------------------------
-BOOL CLRWatsonHelper::ShouldQueueReport()
-{
- WRAPPER_NO_CONTRACT;
-
- AssertValid();
-
- // If we queue a report.
- return (m_reportAction == WHReport_AutoQueue);
-
-} // BOOL CLRWatsonHelper::ShouldQueueReport()
-
-//------------------------------------------------------------------------------
-// Description
-// Reads a PCHealth configuration LONG value from the registry.
-//
-// Parameters
-// szName -- name of the value
-// iDefault -- default value, if not found
-//
-// Returns
-// The value read, or default if no value found.
-//
-// Exceptions
-// None
-//
-// NOtes:
-// Looks in HKCU/Software/Policies/Microsoft/PCHealth/ErrorReporting
-// then in HKLM/ " " " " "
-// then in HKCU/SOftware/Microsoft/PCHealth/ErrorReporting
-// then in HKLM/ " " " "
-//------------------------------------------------------------------------------
-int CLRWatsonHelper::GetPCHealthConfigLong( // Return value from registry or default.
- LPCTSTR szName, // Name of value to get.
- int iDefault) // Default value to return if not found.
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- long iValue; // Actual value from registry.
-
- // Try HKCR policy key
- if (GetRegistryLongValue(HKEY_CURRENT_USER, kErrorReportingPoliciesKey, szName, &iValue, FALSE))
- return iValue;
-
- // Try HKLM policy key
- if (GetRegistryLongValue(HKEY_LOCAL_MACHINE, kErrorReportingPoliciesKey, szName, &iValue, FALSE))
- return iValue;
-
- // Try HKCR key
- if (GetRegistryLongValue(HKEY_CURRENT_USER, kErrorReportingKey, szName, &iValue, FALSE))
- return iValue;
-
- // Try HKLM key
- if (GetRegistryLongValue(HKEY_LOCAL_MACHINE, kErrorReportingKey, szName, &iValue, FALSE))
- return iValue;
-
- // None of them had value -- return default.
- return iDefault;
-} // long CLRWatsonHelper::GetPCHealthConfigLong()
-
-//------------------------------------------------------------------------------
-// Description
-// Reads a PCHealth configuration LONG value from the registry, from a
-// given subkey.
-//
-// Parameters
-// szSubKey -- name of the subkey.
-// szName -- name of the value
-// iDefault -- default value, if not found
-// pValue -- put value here.
-//
-// Returns
-// TRUE - a value was found in the registry
-// FALSE - no value found.
-//
-// Exceptions
-// None
-//
-// NOtes:
-// Looks in HKCU/Software/Policies/Microsoft/PCHealth/ErrorReporting
-// then in HKLM/ " " " " "
-// then in HKCU/SOftware/Microsoft/PCHealth/ErrorReporting
-// then in HKLM/ " " " "
-//------------------------------------------------------------------------------
-BOOL CLRWatsonHelper::GetPCHealthConfigSubKeyLong( // Return value from registry or default.
- LPCWSTR szSubKey, // Name of the subkey.
- LPCWSTR szName, // Name of value to get.
- int iDefault, // Default value to return if not found.
- DWORD *pValue) // Put the value (registry or default) here.
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- long iValue; // Actual value from registry.
-
- // Only one thread will *ever* enter this function, so it is safe to use a static
- // buffer. We know the the longest strings we will want to catenate. Size
- // the buffer appropriately, and we're set.
- static WCHAR rcBuf[lengthof(kErrorReportingPoliciesKey) + lengthof(kInclusionListSubKey) + 3];
-
- _ASSERT( (wcslen(kErrorReportingPoliciesKey) + wcslen(szSubKey) + 1) < lengthof(rcBuf));
-
- // Try HKCR policy key
- wcscpy_s(rcBuf, COUNTOF(rcBuf), kErrorReportingPoliciesKey);
- wcsncat_s(rcBuf, COUNTOF(rcBuf), szSubKey, lengthof(rcBuf)-wcslen(rcBuf)-1);
-
- if (GetRegistryLongValue(HKEY_CURRENT_USER, rcBuf, szName, &iValue, FALSE))
- {
- *pValue = iValue;
- return TRUE;
- }
-
- // Try the HKLM policy key
- if (GetRegistryLongValue(HKEY_LOCAL_MACHINE, rcBuf, szName, &iValue, FALSE))
- {
- *pValue = iValue;
- return TRUE;
- }
-
- // Try HKCR key
- wcscpy_s(rcBuf, COUNTOF(rcBuf), kErrorReportingKey);
- wcsncat_s(rcBuf, COUNTOF(rcBuf), szSubKey, lengthof(rcBuf)-wcslen(rcBuf)-1);
-
- if (GetRegistryLongValue(HKEY_CURRENT_USER, rcBuf, szName, &iValue, FALSE))
- {
- *pValue = iValue;
- return TRUE;
- }
-
- // Try HKLM key
- if (GetRegistryLongValue(HKEY_LOCAL_MACHINE, rcBuf, szName, &iValue, FALSE))
- {
- *pValue = iValue;
- return TRUE;
- }
-
- // None of them had value -- return default.
- *pValue = iDefault;
- return FALSE;
-} // long CLRWatsonHelper::GetPCHealthConfigLong()
-
-
-//------------------------------------------------------------------------------
-//------------------------------------------------------------------------------
-HRESULT CreateWatsonSharedMemory(
- HANDLE *hWatsonSharedMemory,
- DWSharedMem **ppWatsonSharedMemory)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- // Watson needs to inherit the shared memory block, so we have to set up
- // security attributes to make that happens.
- SECURITY_ATTRIBUTES securityAttributes;
- memset(&securityAttributes, 0, sizeof(securityAttributes));
- securityAttributes.nLength = sizeof(securityAttributes);
- securityAttributes.bInheritHandle = TRUE;
-
- _ASSERTE(NULL != hWatsonSharedMemory);
- _ASSERTE(NULL != ppWatsonSharedMemory);
-
- *hWatsonSharedMemory = NULL;
- *ppWatsonSharedMemory = NULL;
-
- // In cases where we have to return form this function with a failure, we
- // need to clean up the handle. Use a holder to take care of that for us.
- HandleHolder hTemp =
- WszCreateFileMapping(INVALID_HANDLE_VALUE,
- &securityAttributes,
- PAGE_READWRITE,
- 0,
- sizeof(DWSharedMem),
- NULL);
-
- if (hTemp == NULL)
- {
- return HRESULT_FROM_GetLastErrorNA();
- }
-
- DWSharedMem* pTemp =
- static_cast< DWSharedMem* >(CLRMapViewOfFile(hTemp,
- FILE_MAP_ALL_ACCESS,
- 0,
- 0,
- sizeof(DWSharedMem)));
-
- if (NULL == pTemp)
- {
- return HRESULT_FROM_GetLastErrorNA();
- }
-
- memset(pTemp, 0, sizeof(DWSharedMem));
- *hWatsonSharedMemory = hTemp;
- *ppWatsonSharedMemory = pTemp;
-
- // We're ready to exit normally and pass the IPC block's handle back to our
- // caller, so we don't want to close it.
- hTemp.SuppressRelease();
-
- return S_OK;
-} // HRESULT CreateWatsonSharedMemory()
-
-
-
-const WCHAR* kWatsonImageNameOnVista = W("\\dw20.exe");
-
-//------------------------------------------------------------------------------
-// Description
-// A helper function to launch the Watson process and wait for it to
-// complete
-// Parameters
-// hWatsonSharedMemory
-// Handle to the shared memory block to pass to Watson. This handle
-// must be inheritable.
-// hEventAlive
-// hEventDone
-// hMutex
-// Returns
-// true - If watson executed normally
-// false - if watson was unable to launch, reported an error, or
-// appeared to hang/crash
-//------------------------------------------------------------------------------
-BOOL RunWatson(
- HANDLE hWatsonSharedMemory,
- HANDLE hEventAlive,
- HANDLE hEventDone,
- HANDLE hMutex)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- PRECONDITION(!RunningOnWin7());
- }
- CONTRACTL_END;
-
- // Since we're doing our own error reporting, we don't want to pop up the
- // OS Watson dialog/GPF Dialog. Supress it now.
-
- PROCESS_INFORMATION processInformation;
- STARTUPINFOW startupInfo;
- memset(&startupInfo, 0, sizeof(STARTUPINFOW));
- startupInfo.cb = sizeof(STARTUPINFOW);
-
- HRESULT hr = S_OK;
- PathString watsonAppName;
- PathString watsonCommandLine;
- EX_TRY
- {
- do
- {
-
-
-
-
- {
- HKEYHolder hKey;
- // Look for key \\HKLM\Software\Microsoft\PCHealth\ErrorReporting\DW\Installed"
- DWORD ret = WszRegOpenKeyEx(HKEY_LOCAL_MACHINE,
- kWatsonPath,
- 0,
- KEY_READ | kWatsonRegKeyOptions,
- &hKey);
-
- if (ERROR_SUCCESS != ret)
- {
- hr = E_FAIL;
- break;
- }
-
-
- // Look in ...\DW\Installed for dw0200 (dw0201 on ia64). This will be
- // the full path to the executable.
-
- ClrRegReadString(hKey, kWatsonValue, watsonAppName);
-
-
- COUNT_T len = watsonCommandLine.GetCount();
- WCHAR* buffer = watsonCommandLine.OpenUnicodeBuffer(len);
- _snwprintf_s(buffer,
- len,
- _TRUNCATE,
- W("dw20.exe -x -s %lu"),
- PtrToUlong(hWatsonSharedMemory));
- watsonCommandLine.CloseBuffer();
-
- }
- } while (false);
- }
- EX_CATCH_HRESULT(hr);
-
-
- if (hr != S_OK)
- {
- return false;
- }
-
- {
- BOOL ret = WszCreateProcess(watsonAppName,
- watsonCommandLine,
- NULL,
- NULL,
- TRUE,
- NULL,
- NULL,
- NULL,
- &startupInfo,
- &processInformation);
-
- if (FALSE == ret)
- {
- //
- // Watson failed to start up.
- //
- // This can happen if e.g. Watson wasn't installed on the machine.
- //
- return FALSE;
- }
- }
-
-
-
- // Wait for watson to finish.
- //
- // This code was more-or-less pasted directly out of the test app for
- // watson, found at
- //
- // \\redist\redist\Watson\dw20_latest\neutral\retail\0\testcrash.cpp
-
- // These handles need to live until we're done waiting for the watson
- // process to finish execution.
- HandleHolder hProcess(processInformation.hProcess);
- HandleHolder hThread(processInformation.hThread);
-
-
- BOOL watsonSignalledCompletion = FALSE, bDWRunning = TRUE;
-
- while (bDWRunning)
- {
- if (WAIT_OBJECT_0 == ClrWaitForSingleObject(hEventAlive,
- kDwWaitTime))
- {
- // Okay, Watson's still pinging us; see if it's finished.
- if (WAIT_OBJECT_0 == ClrWaitForSingleObject(hEventDone, 1))
- {
- bDWRunning = FALSE;
- watsonSignalledCompletion = TRUE;
- }
-
- // If watson is finished (i.e. has signaled hEventDone),
- // bDWRunning is false and we'll fall out of the loop. If
- // watson isn't finished, we'll go back to waiting for the
- // next ping on hEventAlive
- continue;
- }
-
- // we timed-out waiting for DW to respond.
- DWORD dw = WaitForSingleObject(hMutex, DW_TIMEOUT_VALUE);
-
- if (WAIT_TIMEOUT == dw)
- {
- // either DW's hung or crashed, we must carry on. Let watson
- // no that we're giving up on watson, in case it comes back
- // from the hang.
- SetEvent(hEventDone);
- bDWRunning = FALSE;
- }
- else if (WAIT_ABANDONED == dw)
- {
- // The mutex was abandoned, which means Watson crashed on
- // us.
- bDWRunning = FALSE;
-
- ReleaseMutex(hMutex);
- }
- else
- {
- // Check one last time to see if Watson has woken up.
- if (WAIT_OBJECT_0 != ClrWaitForSingleObject(hEventAlive, 1))
- {
- // Nope. hasn't woken up. Give up on Watson
- SetEvent(hEventDone);
- bDWRunning = FALSE;
- }
- else
- {
- // Oh, it HAS woken up! See if it's finished as well.
- if (WAIT_OBJECT_0 == ClrWaitForSingleObject(hEventDone, 1))
- {
- bDWRunning = FALSE;
- watsonSignalledCompletion = TRUE;
- }
- }
-
- ReleaseMutex(hMutex);
- }
- }
-
- // Go ahead and bail if Watson didn't exit for some reason.
- if (!watsonSignalledCompletion)
- {
- return FALSE;
- }
-
- // We're now done with hProcess and hThread, it's safe to let the
- // HandleHolders destroy them now.
- //
- // We don't need to wait for the Watson process to exit; once it's signalled
- // "hEventDone" it's safe to assume that Watson will not try communicating
- // with us anymore and we have succeeded.
- return true;
-} // BOOL RunWatson()
-
-
-//
-// Constants used to control various aspects of Watson's behavior.
-//
-
-
-// Flags controlling the minidump Watson creates.
-const DWORD kMiniDumpType = MiniDumpNormal;
-const DWORD kThreadWriteFlags = ThreadWriteThread | ThreadWriteContext | ThreadWriteStack;
-const DWORD kModuleWriteFlags = ModuleWriteModule; // | ModuleWriteDataSeg ?
-
-
-
-// Reporting. The defaults are fine here
-const DWORD kReportingFlags = 0;
-
-//
-// Enable these flags if the report should be queued (i.e., if no UI should be
-// shown, but a report should still be sent).
-//
-
-// Enable these flags are for bfDWRFlags
-const DWORD kQueuingReportingFlags = fDwrForceToAdminQueue | fDwrIgnoreHKCU;
-
-// Enable these flags in the bfDWUFlags field
-const DWORD kQueuingUIFlags = fDwuNoEventUI;
-
-//
-// No reporting flags. Enable these flags if an error report should not be sent.
-//
-
-// Enable these flags in bfDWRFlags if a report is not to be sent.
-const DWORD kNoReportFlags = fDwrNeverUpload;
-
-
-// UI Flags
-//
-// We need to use the light plea, since we may be reporting faults for
-// Non-Microsoft software (if some random 3rd party app throws an exception, we
-// can't really promise that their error report will be used to fix the
-// problem).
-//
-const DWORD kUIFlags = fDwuDenySuspend | fDwuShowFeedbackLink;
-
-// Exception mode flags. By default, the "restart" and "recover" buttons are
-// checked. We need to turn that behavior off. We also need to use the
-// minidump API to gather the heap dump, in order to get a managed-aware
-// minidump. Finally, release the dumping thread before doing the cabbing
-// for performance reasons.
-const DWORD kExceptionModeFlags = fDweDefaultQuit | fDweGatherHeapAsMdmp | fDweReleaseBeforeCabbing;
-
-// "Miscellaneous" flags. These flags are only used by Office.
-const DWORD kMiscFlags = 0;
-
-// Flags to control which buttons are available on the Watson dialog.
-//
-// We will only display the "Send Error Report" and "Don't Send" buttons
-// available -- we're not going to make the "restart" or "recover" checkboxes
-// available by default.
-const DWORD kOfferFlags = msoctdsQuit;
-
-//------------------------------------------------------------------------------
-// Description
// Returns the IP of the instruction that caused the exception to occur.
// For managed exceptions this may not match the Exceptions contained in
// the exception record.
@@ -2160,477 +919,6 @@ HRESULT GetBucketParametersForCurrentException(
} // HRESULT GetBucketParametersForCurrentException()
-//------------------------------------------------------------------------------
-// Description
-//
-// Parameters
-// pExceptionInfo -- information about the exception that caused the error.
-// If the error is not the result of an exception, pass NULL for this
-// parameter
-// tore -- Information about the fault
-// pThread -- Thread object for faulting thread, could be NULL
-// dwThreadID -- OS Thread ID for faulting thread
-//
-// Returns
-// FaultReportResult -- enumeration indicating the
-// FaultReportResultAbort -- if Watson could not execute normally
-// FaultReportResultDebug -- if Watson executed normally, and the user
-// chose to debug the process
-// FaultReportResultQuit -- if Watson executed normally, and the user
-// chose to end the process (e.g. pressed "Send Error Report" or
-// "Don't Send").
-//
-// Exceptions
-// None.
-//------------------------------------------------------------------------------
-#ifdef _PREFAST_
-#pragma warning(push)
-#pragma warning(disable:21000) // Suppress PREFast warning about overly large function
-#endif
-FaultReportResult DoFaultReportWorker( // Was Watson attempted, successful? Run debugger?
- EXCEPTION_POINTERS *pExceptionInfo, // Information about the fault.
- TypeOfReportedError tore, // What sort of error is this?
- Thread *pThread, // Thread object for faulting thread, could be NULL
- DWORD dwThreadID) // OS Thread ID for faulting thread
-{
- WRAPPER_NO_CONTRACT;
-
- _ASSERTE(!RunningOnWin7());
-
- LOG((LF_EH, LL_INFO100, "DoFaultReportWorker: at sp %p ...\n", GetCurrentSP()));
-
- if (!IsWatsonEnabled())
- {
- return FaultReportResultQuit;
- }
-
- // If we've already tried to report a Watson crash once, we don't really
- // want to pester the user about this exception. This can occur in certain
- // pathological programs.
- // For events other than user breakpoint, we only want to report once.
- // For user breakpoints, report whenever the thread wants to.
- if (!tore.IsUserBreakpoint())
- {
- // If Watson already launched (say, on another thread)...
- if (FastInterlockCompareExchange(&g_watsonAlreadyLaunched, 1, 0) != 0)
- {
- // wait until Watson process is completed
- ClrWaitForSingleObject(g_hWatsonCompletionEvent, INFINITE_TIMEOUT);
- return FaultReportResultQuit;
- }
- }
-
- // Assume an unmanaged fault until we determine otherwise.
- BOOL bIsManagedFault = FALSE;
-
- // IF we don't have an ExceptionInfo, what does that mean?
- if (pExceptionInfo)
- {
- if (IsExceptionFromManagedCode(pExceptionInfo->ExceptionRecord))
- {
- // This is a managed fault.
- bIsManagedFault = TRUE;
- }
- }
-
- // Figure out what we should do.
- CLRWatsonHelper policy;
- policy.Init(bIsManagedFault, tore);
-
- if (policy.ShouldAutoAttach())
- {
- return FaultReportResultDebug;
- }
-
- // Is there anything for Watson to do? (Either report, or ask about debugging?)
- if ((!policy.ShouldReport()) && (!policy.ShouldOfferDebug()) && (!policy.ShouldShowUI()))
- {
- // Hmm ... we're not supposed to report anything or pop up a dialog. In
- // this case, we can stop right now.
- return FaultReportResultQuit;
- }
-
- HANDLE hWatsonSharedMemory;
- DWSharedMem *pWatsonSharedMemory;
- {
- HRESULT hr = CreateWatsonSharedMemory(&hWatsonSharedMemory,
- &pWatsonSharedMemory);
- if (FAILED(hr))
- {
- return FaultReportResultAbort;
- }
- }
-
- // Some basic bookkeeping for Watson
- pWatsonSharedMemory->dwSize = sizeof(DWSharedMem);
- pWatsonSharedMemory->dwVersion = DW_CURRENT_VERSION;
- pWatsonSharedMemory->pid = GetCurrentProcessId();
- pWatsonSharedMemory->tid = dwThreadID;
- _snwprintf_s(pWatsonSharedMemory->wzEventLogSource,
- NumItems(pWatsonSharedMemory->wzEventLogSource),
- _TRUNCATE,
- W(".NET Runtime %0d.%0d Error Reporting"),
- VER_MAJORVERSION,
- VER_MINORVERSION);
- pWatsonSharedMemory->eip = (pExceptionInfo) ? reinterpret_cast< DWORD_PTR >(pExceptionInfo->ExceptionRecord->ExceptionAddress) : NULL;
-
- // If we set exception pointers, the debugger will automatically do a .ecxr on them. SO,
- // don't set the pointers unless it really is an exception and we have a
- // a good context record
- if (tore.IsException() ||
- (tore.IsFatalError() && pExceptionInfo && pExceptionInfo->ContextRecord &&
- (pExceptionInfo->ContextRecord->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
- )
- {
- pWatsonSharedMemory->pep = pExceptionInfo;
- }
- else
- {
- pWatsonSharedMemory->pep = NULL;
- }
-
- // Handles to kernel objects that Watson uses.
- //
- // We're expecting these handles to be valid until the Watson child process
- // has run to completion. Make sure these holders stay in scope until after
- // the call to RunWatson
-
- HandleHolder hEventDone(NULL),
- hEventNotifyDone(NULL),
- hEventAlive(NULL),
- hMutex(NULL),
- hProc(NULL),
- sharedMemoryHolder(hWatsonSharedMemory);
- {
- // SECURITY_ATTRIBUTES so the handles can be inherited (by Watson).
- SECURITY_ATTRIBUTES securityAttributes =
- { sizeof(SECURITY_ATTRIBUTES), NULL, true };
-
- hEventDone = WszCreateEvent(&securityAttributes, FALSE, FALSE, NULL);
- if (hEventDone == NULL)
- {
- LOG((LF_EH, LL_INFO100, "CLR Watson: WszCreateEvent returned error, GetLastError(): %#x\n", GetLastError()));
- return FaultReportResultAbort;
- }
- pWatsonSharedMemory->hEventDone = hEventDone;
-
-
- hEventNotifyDone = WszCreateEvent(&securityAttributes, FALSE, FALSE, NULL);
- if (hEventNotifyDone == NULL)
- {
- LOG((LF_EH, LL_INFO100, "CLR Watson: WszCreateEvent returned error, GetLastError(): %#x\n", GetLastError()));
- return FaultReportResultAbort;
- }
- pWatsonSharedMemory->hEventNotifyDone = hEventNotifyDone;
-
-
- hEventAlive = WszCreateEvent(&securityAttributes, FALSE, FALSE, NULL);
- if (hEventAlive == NULL)
- {
- LOG((LF_EH, LL_INFO100, "CLR Watson: WszCreateEvent returned error, GetLastError(): %#x\n", GetLastError()));
- return FaultReportResultAbort;
- }
- pWatsonSharedMemory->hEventAlive = hEventAlive;
-
-
- hMutex = WszCreateMutex(&securityAttributes, FALSE, NULL);
- if (hMutex == NULL)
- {
- LOG((LF_EH, LL_INFO100, "CLR Watson: WszCreateEvent returned error, GetLastError(): %#x\n", GetLastError()));
- return FaultReportResultAbort;
- }
- pWatsonSharedMemory->hMutex = hMutex;
- }
-
- // During error reporting we need to do dump collection, freeze threads inside the process, read memory blocks
- // (if you register memory), read stuff from the PEB, create remote threads for recovery. So it needs quite a
- // lot of permissions; we end up with PROCESS_ALL_ACCESS to satisfy all required permissions.
- hProc = OpenProcess(PROCESS_ALL_ACCESS,
- TRUE,
- pWatsonSharedMemory->pid);
- if (hProc == NULL)
- {
- LOG((LF_EH, LL_INFO100, "CLR Watson: OpenProcess returned error, GetLastError(): %#x\n", GetLastError()));
- return FaultReportResultAbort;
- }
-
- pWatsonSharedMemory->hProc = hProc;
-
-
- // Flags to control reporting, queuing, etc.
- DWORD reportingFlags = kReportingFlags; // 0
- DWORD uiFlags = kUIFlags; // fDwuDenySuspend | fDwuShowFeedbackLink
- DWORD dwEflags = kExceptionModeFlags; // fDweDefaultQuit | fDweGatherHeapAsMdmp
-
- // Reporting flags...
- if (policy.ShouldQueueReport())
- { // If we should queue a report,
- // turn on kQueueingReportingFlags, which is fDwrForceToAdminQueue | fDwrIgnoreHKCU
- reportingFlags |= kQueuingReportingFlags;
- }
- else
- if (!policy.ShouldReport())
- { // We shouldn't report at all,
- // turn on kNoReportFlags, which is fDwrNeverUpload, which means "don't report"
- reportingFlags |= kNoReportFlags;
- }
- else
- {
- // Ask to report.
- }
-
- // Offer flags...
- DWORD offerFlags = kOfferFlags; // msoctdsQuit
- if (policy.ShouldOfferDebug())
- { // Turn on msoctdsDebug, which adds "Debug" button.
- offerFlags |= msoctdsDebug;
- }
- else
- { // No debug, so ignore aeDebug
- dwEflags |= fDweIgnoreAeDebug;
- }
-
- // UI flags...
- if (policy.ShouldQueueReport() && !policy.ShouldOfferDebug())
- { // Queue report headlessly. Turn on kQueueingUIFlags, which is fDwuNoEventUI.
- uiFlags |= kQueuingUIFlags;
- }
-
- pWatsonSharedMemory->bfmsoctdsOffer = offerFlags; // From above
- pWatsonSharedMemory->bfDWRFlags = reportingFlags; // From above
- pWatsonSharedMemory->bfDWUFlags = uiFlags; // From above
- pWatsonSharedMemory->bfDWEFlags = dwEflags; // From above
- pWatsonSharedMemory->bfDWMFlags = kMiscFlags; // 0
-
- // We're going to rely on Watson's default localization behavior.
- pWatsonSharedMemory->lcidUI = 0;
-
- // By default, Watson will terminate the process after snapping a
- // minidump. Notify & LetRun flags disable that.
- pWatsonSharedMemory->bfmsoctdsNotify = msoctdsNull;
- pWatsonSharedMemory->bfmsoctdsLetRun = offerFlags;
-
- {
- PathString wzModuleFileName;
- DWORD dwRet = WszGetModuleFileName(NULL,
- wzModuleFileName);
- BaseBucketParamsManager::CopyStringToBucket(pWatsonSharedMemory->wzModuleFileName, NumItems(pWatsonSharedMemory->wzModuleFileName), wzModuleFileName);
-
- _ASSERTE(0 != dwRet);
- if (0 == dwRet)
- {
- LOG((LF_EH, LL_INFO100, "CLR Watson: WszGetModuleFileName returned error, GetLastError(): %#x\n", GetLastError()));
- return FaultReportResultAbort;
- }
- }
-
- // We're going capture the same minidump information for all modules, so set wzDotDataDlls to "*"
- if (sizeof(DW_ALLMODULES) <= sizeof(pWatsonSharedMemory->wzDotDataDlls))
- {
- memcpy(pWatsonSharedMemory->wzDotDataDlls, DW_ALLMODULES, sizeof(DW_ALLMODULES));
- }
- else
- {
- // Assert, but go on
- _ASSERTE(sizeof(DW_ALLMODULES) <= sizeof(pWatsonSharedMemory->wzDotDataDlls));
- pWatsonSharedMemory->wzDotDataDlls[0] = 0;
- }
-
- // UI Customization
- //
- // The only UI customization we perform is to set the App Name. Currently we
- // do this just by using the executable name.
- //
- {
- PathString buf; // Buffer for path for description.
- LPCWSTR pName ; // Pointer to filename or description.
- int size; // Size of description.
- HMODULE hModule; // Handle to module.
- DWORD result; // Return code
-
- // Get module name.
- hModule = WszGetModuleHandle(NULL);
- result = WszGetModuleFileName(hModule, buf);
-
- if (result == 0)
- { // Couldn't get module name. This should never happen.
- pName = W("<<unknown>>");
- }
- else
- { // re-use the buf for pathname and description.
- size = DwGetAppDescription(buf, buf);
- pName = buf.GetUnicode();
- // If the returned size was zero, buf wasn't changed, and still contains the path.
- // find just the filename part.
- if (size == 0)
- { // Look for final '\'
- pName = wcsrchr(buf, W('\\'));
- // If found, skip it; if not, point to full name.
- pName = pName ? pName+1 : (LPCWSTR)buf;
- }
- }
-
- wcsncpy_s(pWatsonSharedMemory->uib.wzGeneral_AppName,
- COUNTOF(pWatsonSharedMemory->uib.wzGeneral_AppName),
- pName,
- _TRUNCATE);
-
- // For breakpoint, need to customize the "We're sorry..." message
- if (tore.IsBreakpoint())
- {
- LCID lcid = 0;
- // Get the message.
- StackSString sszMain_Intro_Bold;
- StackSString sszMain_Intro_Reg;
- EX_TRY
- {
- sszMain_Intro_Bold.LoadResource(CCompRC::Debugging, IDS_WATSON_DEBUG_BREAK_INTRO_BOLD);
- sszMain_Intro_Reg.LoadResource(CCompRC::Debugging, IDS_WATSON_DEBUG_BREAK_INTRO_REG);
- // Try to determine the language used for the above resources
- // At the moment this OS call is a heuristic which should match most of the time. But the
- // CLR is starting to support languages that don't even have LCIDs, so this may not always
- // be correct (and there may be NO LCID we can pass to watson). Long term, the correct fix
- // here is to get out of the game of making watson policy / UI decisions. This is happening
- // for Windows 7.
- lcid = GetThreadLocale();
- }
- EX_CATCH
- {
- // Just don't customize.
- }
- EX_END_CATCH(SwallowAllExceptions)
-
- // If we were able to get a string, set it.
- if (sszMain_Intro_Reg.GetCount() > 0)
- {
- // Instead of "<app.exe> has encountered an error and nees to close...", say
- // "<app.exe> has encountered a user-defined breakpoint."
- wcsncpy_s(pWatsonSharedMemory->uib.wzMain_Intro_Bold, COUNTOF(pWatsonSharedMemory->uib.wzMain_Intro_Bold), sszMain_Intro_Bold, _TRUNCATE);
- // Instead of "If you were in the middle of something...", say
- // "A breakpoint in an application indicates a program error..."
- wcsncpy_s(pWatsonSharedMemory->uib.wzMain_Intro_Reg, COUNTOF(pWatsonSharedMemory->uib.wzMain_Intro_Reg), sszMain_Intro_Reg, _TRUNCATE);
-
- pWatsonSharedMemory->bfDWUFlags = fDwuDenySuspend;
-
- pWatsonSharedMemory->lcidUI = lcid;
- }
- }
-
- }
-
- // Get the bucket parameters.
- switch (tore.GetType())
- {
- case TypeOfReportedError::NativeThreadUnhandledException:
- // Let Watson provide the buckets for a native thread.
- break;
- case TypeOfReportedError::UnhandledException:
- case TypeOfReportedError::FatalError:
- case TypeOfReportedError::UserBreakpoint:
- case TypeOfReportedError::NativeBreakpoint:
- // For managed exception or exceptions that come from managed code, we get the managed bucket parameters,
- // which will be displayed in the "details" section on any UI.
- //
- // Otherwise, use the unmanaged IP to bucket.
- if (bIsManagedFault)
- {
- RetrieveManagedBucketParameters(pExceptionInfo?pExceptionInfo->ExceptionRecord:NULL, &pWatsonSharedMemory->gmb, tore, pThread);
- }
- break;
- default:
- _ASSERTE(!"Unexpected TypeOfReportedException");
- break;
- }
-
- // dwThisThreadExFlags and dwOtherThreadExFlags are only used on IA64.
- CustomMinidumpBlock cmb =
- {
- TRUE, // fCustomMinidump
- kMiniDumpType, // dwMinidumpType : MiniDumpNormal
- FALSE, // fOnlyThisThread
- kThreadWriteFlags, // dwThisThreadFlags : ThreadWriteThread | ThreadWriteContext | ThreadWriteStack
- kThreadWriteFlags, // dwOtherThreadFlags
- 0, // dwThisThreadExFlags
- 0, // dwOtherThreadExFlags
- kModuleWriteFlags, // dwPreferredModuleFlags
- kModuleWriteFlags // dwOtherModuleFlags.
- };
-
- pWatsonSharedMemory->cmb = cmb;
-
- // At this point, the IPC block is all ready to go
- BOOL result = false;
- // There are two calls to RunWatson below. We want the second call to execute iff
- // secondInvocation is true.
- BOOL secondInvocation = true;
-
-
- EX_TRY
- {
- bool fRunWatson = false;
-#if defined(_TARGET_X86_)
- bool fGuardPagePresent = false;
-
- // There is an unfortunate side effect of calling ReadProcessMemory() out-of-process on IA64 WOW.
- // On all platforms (IA64 native & WOW64, AMD64 native & WOW64, and x86 native), if we call
- // ReadProcessMemory() out-of-process on a page with PAGE_GUARD protection, the read operation
- // fails as expected. However, on IA64 WOW64 only, the PAGE_GUARD protection is removed after
- // the read operation. Even IA64 native preserves the PAGE_GUARD protection.
- // See VSW 451447 for more information.
- if ((pThread != NULL) && pThread->DetermineIfGuardPagePresent())
- {
- fGuardPagePresent = true;
- }
-#endif // _TARGET_X86_
-
- if (secondInvocation)
- {
- fRunWatson = true;
- result = RunWatson(hWatsonSharedMemory,
- pWatsonSharedMemory->hEventAlive,
- pWatsonSharedMemory->hEventDone,
- pWatsonSharedMemory->hMutex);
- }
-
-#if defined(_TARGET_X86_)
- if (fRunWatson && fGuardPagePresent)
- {
- // This shouldn't cause a problem because guard pages are present in the first place.
- _ASSERTE(pThread != NULL);
- pThread->RestoreGuardPage();
- }
-#endif // _TARGET_X86_
- }
- EX_CATCH
- {
- // We couldn't wait around for watson to execute for some reason.
- result = false;
- }
- EX_END_CATCH(SwallowAllExceptions)
-
- // It's now safe to close all the synchronization and process handles.
-
- if (!result)
- {
- // Hmmm ... watson couldn't execute correctly.
- return FaultReportResultAbort;
- }
-
- LOG((LF_EH, LL_INFO100, "CLR Watson: returned 0x%x\n", pWatsonSharedMemory->msoctdsResult));
-
- // If user clicked "Debug"
- if (msoctdsDebug == pWatsonSharedMemory->msoctdsResult)
- {
- return FaultReportResultDebug;
- }
-
- // No debugging, successful completion.
- return FaultReportResultQuit;
-} // FaultReportResult DoFaultReportWorker()
-#ifdef _PREFAST_
-#pragma warning(pop)
-#endif
-
class WatsonThreadData {
public:
@@ -2650,188 +938,7 @@ class WatsonThreadData {
FaultReportResult result; // Result of invoking Watson
};
-class WatsonSOExceptionAddress {
- public:
-
- WatsonSOExceptionAddress()
- {
- m_SystemMethod = NULL;
- m_UserMethod = NULL;
- }
-
- SLOT m_SystemMethod; // IP in the first method on the stack which is in a system module
- SLOT m_UserMethod; // IP in the first method on the stack which is in a non-system module
-};
-
-//------------------------------------------------------------------------------
-// Description
-// This function is the stack walk callback for a thread that hit a soft SO (i.e., a SO caused by a
-// failed stack probe).
-//
-// Parameters
-// pCf -- A pointer to the current CrawlFrame
-// data - A pointer to WatsonSOExceptionAddress instance
-//
-// Returns:
-// SWA_ABORT to stop the stack crawl
-// SWA_CONTINUE to continue crawling the stack
-//
-// Exceptions
-// None.
-//------------------------------------------------------------------------------
-StackWalkAction WatsonSOStackCrawlCallback(CrawlFrame* pCf, void* pParam)
-{
- WRAPPER_NO_CONTRACT;
-
- _ASSERTE(pParam != NULL);
- WatsonSOExceptionAddress *pData = (WatsonSOExceptionAddress *) pParam;
-
- SLOT ip;
-
- if (pCf->IsFrameless())
- {
- ip = (PBYTE)GetControlPC(pCf->GetRegisterSet());
- }
- else
- {
- ip = (SLOT) pCf->GetFrame()->GetIP();
- }
-
- MethodDesc *pMD = pCf->GetFunction();
-
- if (pMD != NULL)
- {
- if (pMD->GetModule()->IsSystem())
- {
- if (pData->m_SystemMethod == NULL)
- {
- pData->m_SystemMethod = ip;
- }
- return SWA_CONTINUE;
- }
- else
- {
- _ASSERTE(pData->m_UserMethod == NULL);
- pData->m_UserMethod = ip;
- return SWA_ABORT;
- }
- }
- else
- {
- return SWA_CONTINUE;
- }
-
-}// WatsonSOCrawlCallBack
-
-//------------------------------------------------------------------------------
-// Description
-// Wrapper function for DoFaultReport. This function is called for SOs.
-// It sets up the ExceptionInfo appropriately for soft SOs (caused by
-// failed stack probes) before callign DoFaultReport.
-//
-// Parameters
-// pParam -- A pointer to a WatsonThreadData instance
-//
-// Exceptions
-// None.
-//------------------------------------------------------------------------------
-DWORD WINAPI DoFaultReportWorkerCallback(LPVOID pParam)
-{
- WRAPPER_NO_CONTRACT;
-
- _ASSERTE(pParam != NULL);
-
- WatsonThreadData* pData = (WatsonThreadData*) pParam;
-
- EXCEPTION_POINTERS ExceptionInfo;
- EXCEPTION_RECORD ExceptionRecord;
- PEXCEPTION_POINTERS pExceptionInfo = pData->pExceptionInfo;
-
- if (IsSOExceptionCode(pExceptionInfo->ExceptionRecord->ExceptionCode))
- {
- EX_TRY
- {
- if (ShouldLogInEventLog())
- {
- EventReporter reporter(EventReporter::ERT_StackOverflow);
- reporter.Report();
- }
- }
- EX_CATCH
- {
- }
- EX_END_CATCH(SwallowAllExceptions);
- }
-
- // The purpose of the loop below is to avoid deadlocks during the abnormal process termination.
- // We will try to acquire the lock for 100 times to see whether we can successfully grap it. If we
- // can, then we can setup the thread and report the fault without worrying about the deadlock.
- // Otherwise we won't report the fault. It's still possible that we can enter the critical section
- // and report the fault without having deadlocks after this spin, but compared to the risky of
- // having deadlock, we still prefer not to report the fault if we can't get the lock after spin.
- BOOL isThreadSetup = false;
- for (int i = 0; i < 100; i++)
- {
- if (ThreadStore::CanAcquireLock())
- {
- SetupThread();
- isThreadSetup = true;
- break;
- }
- __SwitchToThread(30, CALLER_LIMITS_SPINNING);
- }
-
- if (isThreadSetup)
- {
- GCX_COOP();
-
- if (pData->pThread != NULL && pExceptionInfo != NULL &&
- pExceptionInfo->ContextRecord == NULL &&
- pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW &&
- pExceptionInfo->ExceptionRecord->ExceptionAddress == 0)
- {
- // In the case of a soft SO on a managed thread, we set the ExceptionAddress to one of the following
- //
- // 1. The first method on the stack that is in a non-system module.
- // 2. Failing that, the first method on the stack that is in a system module
-
- CONTEXT ContextRecord;
- memset(&ContextRecord, 0, sizeof(CONTEXT));
-
- ExceptionInfo.ContextRecord = &ContextRecord; // To display the "Send" button, dw20 wants a non-NULL pointer
- ExceptionRecord = *(pExceptionInfo->ExceptionRecord);
- ExceptionInfo.ExceptionRecord = &ExceptionRecord;
- pExceptionInfo = &ExceptionInfo;
-
- WatsonSOExceptionAddress WatsonExceptionAddresses;
-
- pData->pThread->StackWalkFrames(
- WatsonSOStackCrawlCallback,
- &WatsonExceptionAddresses,
- FUNCTIONSONLY|ALLOW_ASYNC_STACK_WALK);
-
- if (WatsonExceptionAddresses.m_UserMethod != NULL)
- {
- pExceptionInfo->ExceptionRecord->ExceptionAddress = WatsonExceptionAddresses.m_UserMethod;
- }
- else if (WatsonExceptionAddresses.m_SystemMethod != NULL)
- {
- pExceptionInfo->ExceptionRecord->ExceptionAddress = WatsonExceptionAddresses.m_SystemMethod;
- }
-
- }
- pData->result = DoFaultReportWorker(
- pExceptionInfo,
- pData->tore,
- pData->pThread,
- pData->dwThreadID);
- }
-
-
- return 0;
-
-} // void DoFaultReportFavorWorker()
DWORD WINAPI ResetWatsonBucketsCallbackForStackOverflow(LPVOID pParam)
{
@@ -2840,7 +947,6 @@ DWORD WINAPI ResetWatsonBucketsCallbackForStackOverflow(LPVOID pParam)
THROWS;
GC_TRIGGERS;
PRECONDITION(IsWatsonEnabled());
- PRECONDITION(RunningOnWin7());
PRECONDITION(pParam != NULL);
}
CONTRACTL_END;
@@ -2886,7 +992,6 @@ void ResetWatsonBucketsFavorWorker(void * pParam)
NOTHROW;
GC_NOTRIGGER;
PRECONDITION(IsWatsonEnabled());
- PRECONDITION(RunningOnWin7());
PRECONDITION(pParam != NULL);
}
CONTRACTL_END;
@@ -2905,41 +1010,6 @@ void ResetWatsonBucketsFavorWorker(void * pParam)
}
-//------------------------------------------------------------------------------
-// Description
-// This function is called by the Debugger thread in response to a favor
-// posted to it by the faulting thread. The faulting thread uses the
-// Debugger thread to invoke Watson in the case of stack overflows.
-// Since the debugger thread doesn't have a managed Thread object,
-// it cannot be directly used to call DoFaultReport. Instead, this function
-// spawns a worker thread and waits for it to complete.
-//
-// Parameters
-// pParam -- A pointer to a WatsonThreadData instance
-//
-// Exceptions
-// None.
-//------------------------------------------------------------------------------
-void DoFaultReportFavorWorker(void* pParam)
-{
- WRAPPER_NO_CONTRACT;
-
- _ASSERTE(pParam != NULL);
-
- HANDLE hThread = NULL;
- DWORD dwThreadId;
-
- hThread = ::CreateThread(NULL, 0, DoFaultReportWorkerCallback, pParam, 0, &dwThreadId);
- if (hThread != NULL)
- {
- WaitForSingleObject(hThread, INFINITE);
- CloseHandle(hThread);
- }
-
- return;
-
-} // void DoFaultReportFavorWorker()
-
//----------------------------------------------------------------------------
// CreateThread() callback to invoke native Watson or put up our fake Watson
// dialog depending on m_fDoReportFault value.
@@ -3019,129 +1089,6 @@ VOID WINAPI DoFaultReportDoFavorCallback(LPVOID pFaultReportInfoAsVoid)
}
}
-
-
-//------------------------------------------------------------------------------
-// Description
-//
-// Parameters
-// pExceptionInfo -- information about the exception that caused the error.
-// If the error is not the result of an exception, pass NULL for this
-// parameter
-// tore -- Information about the fault
-// Returns
-// FaultReportResult -- enumeration indicating the
-// FaultReportResultAbort -- if Watson could not execute normally
-// FaultReportResultDebug -- if Watson executed normally, and the user
-// chose to debug the process
-// FaultReportResultQuit -- if Watson executed normally, and the user
-// chose to end the process (e.g. pressed "Send Error Report" or
-// "Don't Send").
-//
-// Exceptions
-// None.
-//------------------------------------------------------------------------------
-FaultReportResult DoFaultReport( // Was Watson attempted, successful? Run debugger?
- EXCEPTION_POINTERS *pExceptionInfo, // Information about the fault.
- TypeOfReportedError tore) // What sort of error is this?
-{
- WRAPPER_NO_CONTRACT;
-
- _ASSERTE(!RunningOnWin7());
-
- LOG((LF_EH, LL_INFO100, "DoFaultReport: at sp %p ...\n", GetCurrentSP()));
-
- Thread *pThread = GetThread();
-
- // If watson isn't available (eg. in Silverlight), then use a simple dialog box instead
- if (!IsWatsonEnabled())
- {
- if (!pThread)
- {
- return FaultReportResultAbort;
- }
-
- // Since the StackOverflow handler also calls us, we must keep our stack budget
- // to a minimum. Thus, we will launch a thread to do the actual work.
- FaultReportInfo fri;
- fri.m_fDoReportFault = FALSE;
- fri.m_pExceptionInfo = pExceptionInfo;
- fri.m_threadid = GetCurrentThreadId();
- // DoFaultCreateThreadReportCallback will overwrite this - if it doesn't, we'll assume it failed.
- fri.m_faultReportResult = FaultReportResultAbort;
-
- GCX_PREEMP();
-
-
- if (pExceptionInfo->ExceptionRecord->ExceptionCode != STATUS_STACK_OVERFLOW)
- {
- DoFaultReportCreateThreadCallback(&fri);
- }
- else
- {
- // Stack overflow case - we don't have enough stack on our own thread so let the debugger
- // helper thread do the work.
- if (!g_pDebugInterface || FAILED(g_pDebugInterface->RequestFavor(DoFaultReportDoFavorCallback, &fri)))
- {
- // If we can't initialize the debugger helper thread or we are running on the debugger helper
- // thread, give it up. We don't have enough stack space.
-
- }
- }
-
- return fri.m_faultReportResult;
- }
-
-
- // Check if the current thread has the permission to open a process handle of the current process.
- // If not, the current thread may have been impersonated, we have to launch Watson from a new thread as in SO case.
- BOOL fOpenProcessFailed = FALSE;
- if (pExceptionInfo->ExceptionRecord->ExceptionCode != STATUS_STACK_OVERFLOW)
- {
- HandleHolder hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, GetCurrentProcessId());
- fOpenProcessFailed = hProcess == NULL;
- }
-
- if ((pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW) || fOpenProcessFailed)
- {
-
- WatsonThreadData* pData = new(nothrow) WatsonThreadData(
- pExceptionInfo,
- tore,
- pThread,
- GetCurrentThreadId(),
- FaultReportResultAbort); // default result
-
- if (pData == NULL)
- {
- return FaultReportResultAbort;
- }
-
- GCX_PREEMP();
-
- if (!g_pDebugInterface ||
- // When GC is in progress and current thread is either a GC thread or a managed
- // thread under Coop mode, this will let the new generated DoFaultReportCallBack
- // thread trigger a deadlock. So in this case, we should directly abort the fault
- // report to avoid the deadlock.
- ((IsGCThread() || pThread->PreemptiveGCDisabled()) && GCHeapUtilities::IsGCInProgress()) ||
- FAILED(g_pDebugInterface->RequestFavor(DoFaultReportFavorWorker, pData)))
- {
- // If we can't initialize the debugger helper thread or we are running on the debugger helper
- // thread, return without invoking Watson. We don't have enough stack space.
-
- delete pData;
- return FaultReportResultAbort;
- }
-
- FaultReportResult ret = pData->result;
- delete pData;
- return ret;
- }
-
- return DoFaultReportWorker(pExceptionInfo, tore, GetThread(), GetCurrentThreadId());
-} // FaultReportResult DoFaultReport()
-
// look at the type of the contract failure. if it's a precondition then we want to blame the caller
// of the method that originated the ContractException not just the first non-contract runtime frame.
// if this isn't a ContractException then we default to Invariant which won't skip the extra frame.
diff --git a/src/vm/dwreport.h b/src/vm/dwreport.h
index 77ed0fd35a..a9d804631d 100644
--- a/src/vm/dwreport.h
+++ b/src/vm/dwreport.h
@@ -52,8 +52,6 @@ FaultReportResult DoFaultReport( // Was Watson attempted, successful?
EXCEPTION_POINTERS *pExceptionInfo, // Information about the fault.
TypeOfReportedError tore); // What sort of error is reported.
-BOOL InitializeWatson(COINITIEE fFlags);
-BOOL InitializeWatsonVersionInfo(LPCSTR pVer);
BOOL IsWatsonEnabled();
BOOL RegisterOutOfProcessWatsonCallbacks();
@@ -81,8 +79,6 @@ void ResetWatsonBucketsFavorWorker(void * pParam);
extern LONG g_watsonAlreadyLaunched;
-extern HandleHolder g_hWatsonCompletionEvent;
-
//----------------------------------------------------------------------------
// Passes data between DoFaultReport and DoFaultReportCallback
//----------------------------------------------------------------------------
diff --git a/src/vm/eepolicy.cpp b/src/vm/eepolicy.cpp
index e15af92bfc..574943a40e 100644
--- a/src/vm/eepolicy.cpp
+++ b/src/vm/eepolicy.cpp
@@ -1472,7 +1472,7 @@ void DECLSPEC_NORETURN EEPolicy::HandleFatalStackOverflow(EXCEPTION_POINTERS *pE
}
#ifndef FEATURE_PAL
- if (RunningOnWin7() && IsWatsonEnabled() && (g_pDebugInterface != NULL))
+ if (IsWatsonEnabled() && (g_pDebugInterface != NULL))
{
_ASSERTE(pExceptionInfo != NULL);
diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp
index 3ba3d05a82..9cb1296204 100644
--- a/src/vm/excep.cpp
+++ b/src/vm/excep.cpp
@@ -126,7 +126,6 @@ BOOL __stdcall IsExceptionFromManagedCodeCallback(EXCEPTION_RECORD * pExceptionR
SO_TOLERANT;
SUPPORTS_DAC;
PRECONDITION(CheckPointer(pExceptionRecord));
- PRECONDITION(!RunningOnWin7());
} CONTRACTL_END;
// If we can't enter the EE, done.
@@ -4083,49 +4082,6 @@ void DisableOSWatson(void)
LOG((LF_EH, LL_INFO100, "DisableOSWatson: SetErrorMode = 0x%x\n", lastErrorMode | SEM_NOGPFAULTERRORBOX));
}
-
-
-//----------------------------------------------------------------------------
-//
-// RaiseFailFastExceptionOnWin7 - invoke RaiseFailFastException on Win7
-//
-// Arguments:
-// pExceptionRecord - pointer to exception record
-// pContext - pointer to exception context
-//
-// Return Value:
-// None
-//
-// Note:
-// RaiseFailFastException will not return unless a debugger is attached
-// and the user chooses to keep going.
-//
-//----------------------------------------------------------------------------
-void RaiseFailFastExceptionOnWin7(PEXCEPTION_RECORD pExceptionRecord, PCONTEXT pContext)
-{
- LIMITED_METHOD_CONTRACT;
- _ASSERTE(RunningOnWin7());
-
-#ifndef FEATURE_CORESYSTEM
- typedef void (WINAPI * RaiseFailFastExceptionFnPtr)(PEXCEPTION_RECORD, PCONTEXT, DWORD);
- RaiseFailFastExceptionFnPtr RaiseFailFastException;
-
- HINSTANCE hKernel32 = WszGetModuleHandle(WINDOWS_KERNEL32_DLLNAME_W);
- if (hKernel32 == NULL)
- return;
-
- RaiseFailFastException = (RaiseFailFastExceptionFnPtr)GetProcAddress(hKernel32, "RaiseFailFastException");
- if (RaiseFailFastException == NULL)
- return;
-#endif
-
- // enable preemptive mode before call into OS to allow runtime suspend to finish
- GCX_PREEMP();
-
- STRESS_LOG0(LF_CORDB,LL_INFO10, "D::RFFE: About to call RaiseFailFastException\n");
- RaiseFailFastException(pExceptionRecord, pContext, 0);
- STRESS_LOG0(LF_CORDB,LL_INFO10, "D::RFFE: Return from RaiseFailFastException\n");
-}
#endif // !FEATURE_PAL
//------------------------------------------------------------------------------
@@ -4196,133 +4152,83 @@ LONG WatsonLastChance( // EXCEPTION_CONTINUE_SEARCH, _CONTINUE_
LOG((LF_EH, LL_INFO10, "WatsonLastChance: Debugger not attached at sp %p ...\n", GetCurrentSP()));
#ifndef FEATURE_PAL
- BOOL bRunDoFaultReport = TRUE;
FaultReportResult result = FaultReportResultQuit;
- if (RunningOnWin7())
+ BOOL fSOException = FALSE;
+
+ if ((pExceptionInfo != NULL) &&
+ (pExceptionInfo->ExceptionRecord != NULL) &&
+ (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW))
{
- BOOL fSOException = FALSE;
+ fSOException = TRUE;
+ }
- if ((pExceptionInfo != NULL) &&
- (pExceptionInfo->ExceptionRecord != NULL) &&
- (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW))
- {
- fSOException = TRUE;
- }
+ if (g_pDebugInterface)
+ {
+ // we are about to let the OS trigger jit attach, however we need to synchronize with our
+ // own jit attach that we might be doing on another thread
+ // PreJitAttach races this thread against any others which might be attaching and if some other
+ // thread is doing it then we wait for its attach to complete first
+ g_pDebugInterface->PreJitAttach(TRUE, FALSE, FALSE);
+ }
- if (g_pDebugInterface)
+ // Let unhandled excpetions except stack overflow go to the OS
+ if (tore.IsUnhandledException() && !fSOException)
+ {
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else if (tore.IsUserBreakpoint())
+ {
+ DoReportFault(pExceptionInfo);
+ }
+ else
+ {
+ BOOL fWatsonAlreadyLaunched = FALSE;
+ if (FastInterlockCompareExchange(&g_watsonAlreadyLaunched, 1, 0) != 0)
{
- // we are about to let the OS trigger jit attach, however we need to synchronize with our
- // own jit attach that we might be doing on another thread
- // PreJitAttach races this thread against any others which might be attaching and if some other
- // thread is doing it then we wait for its attach to complete first
- g_pDebugInterface->PreJitAttach(TRUE, FALSE, FALSE);
+ fWatsonAlreadyLaunched = TRUE;
}
- // Let unhandled excpetions except stack overflow go to the OS
- if (tore.IsUnhandledException() && !fSOException)
- {
- return EXCEPTION_CONTINUE_SEARCH;
- }
- else if (tore.IsUserBreakpoint())
- {
- DoReportFault(pExceptionInfo);
- }
- else
+ // Logic to avoid double prompt if more than one threads calling into WatsonLastChance
+ if (!fWatsonAlreadyLaunched)
{
- BOOL fWatsonAlreadyLaunched = FALSE;
- if (FastInterlockCompareExchange(&g_watsonAlreadyLaunched, 1, 0) != 0)
+ // EEPolicy::HandleFatalStackOverflow pushes a FaultingExceptionFrame on the stack after SO
+ // exception. Our hijack code runs in the exception context, and overwrites the stack space
+ // after SO excpetion, so we need to pop up this frame before invoking RaiseFailFast.
+ // This cumbersome code should be removed once SO synchronization is moved to be completely
+ // out-of-process.
+ if (fSOException && pThread && pThread->GetFrame() != FRAME_TOP)
{
- fWatsonAlreadyLaunched = TRUE;
+ GCX_COOP(); // Must be cooperative to modify frame chain.
+ pThread->GetFrame()->Pop(pThread);
}
- // Logic to avoid double prompt if more than one threads calling into WatsonLastChance
- if (!fWatsonAlreadyLaunched)
- {
- // EEPolicy::HandleFatalStackOverflow pushes a FaultingExceptionFrame on the stack after SO
- // exception. Our hijack code runs in the exception context, and overwrites the stack space
- // after SO excpetion, so we need to pop up this frame before invoking RaiseFailFast.
- // This cumbersome code should be removed once SO synchronization is moved to be completely
- // out-of-process.
- if (fSOException && pThread && pThread->GetFrame() != FRAME_TOP)
- {
- GCX_COOP(); // Must be cooperative to modify frame chain.
- pThread->GetFrame()->Pop(pThread);
- }
-
- LOG((LF_EH, LL_INFO10, "D::WLC: Call RaiseFailFastExceptionOnWin7\n"));
- RaiseFailFastExceptionOnWin7(pExceptionInfo == NULL ? NULL : pExceptionInfo->ExceptionRecord,
- pExceptionInfo == NULL ? NULL : pExceptionInfo->ContextRecord);
- STRESS_LOG0(LF_CORDB,LL_INFO10, "D::WLC: Return from RaiseFailFastExceptionOnWin7\n");
- }
- }
-
- if (g_pDebugInterface)
- {
- // if execution resumed here then we may or may not be attached
- // either way we need to end the attach process and unblock any other
- // threads which were waiting for the attach here to complete
- g_pDebugInterface->PostJitAttach();
- }
+ LOG((LF_EH, LL_INFO10, "D::WLC: Call RaiseFailFastExceptionOnWin7\n"));
+ // enable preemptive mode before call into OS to allow runtime suspend to finish
+ GCX_PREEMP();
- if (IsDebuggerPresent())
- {
- result = FaultReportResultDebug;
- jitAttachRequested = FALSE;
+ STRESS_LOG0(LF_CORDB, LL_INFO10, "D::RFFE: About to call RaiseFailFastException\n");
+ RaiseFailFastException(pExceptionInfo == NULL ? NULL : pExceptionInfo->ExceptionRecord,
+ pExceptionInfo == NULL ? NULL : pExceptionInfo->ContextRecord,
+ 0);
+ STRESS_LOG0(LF_CORDB, LL_INFO10, "D::RFFE: Return from RaiseFailFastException\n");
}
}
- else
+
+ if (g_pDebugInterface)
{
- // If we've got a fatal error but Watson isn't enabled, then fall back to old-style non-managed-aware
- // error reporting using faultrep to try and ensure we get an error report about this fatal error.
- if (!IsWatsonEnabled() && tore.IsFatalError() && (pExceptionInfo != NULL))
- {
- EFaultRepRetVal r = DoReportFault(pExceptionInfo);
- if (r != frrvErr && r != frrvErrNoDW && r != frrvErrTimeout)
- {
- // Once native Watson is sucessfully launched, we should not try to launch
- // our fake Watson dailog box.
- bRunDoFaultReport = FALSE;
- }
- }
+ // if execution resumed here then we may or may not be attached
+ // either way we need to end the attach process and unblock any other
+ // threads which were waiting for the attach here to complete
+ g_pDebugInterface->PostJitAttach();
+ }
- if (bRunDoFaultReport)
- {
- // http://devdiv/sites/docs/NetFX4/CLR/Specs/Developer%20Services/Error%20Reporting/WER%20SxS%20DCR.doc
- //
- // Watson SxS support for Desktop CLR
- //
- // For an unhandled exception thrown from native code, the first runtime that encounters the
- // unhandled native exception will report Watson if it is allowed by Watson SxS manager to do
- // Watson. If more than one runtimes attempt to report Watson concurrently, only one runtims
- // will be bestowed to report Watson. The result is that at most one Watson report will be
- // submitted for a process.
- //
- // To coordinate Watson reporting among runtimes in a process, Watson SxS manager, which is part
- // of the shim, will provide a new set of APIs, and keeps a status of whether a Watson report
- // has been submitted for a process.
- //
- // Each runtime registers an exception claiming callack with Watson SxS manager at startup.
- // Watson SxS manager provide an exception claiming API, which iterators through registerd
- // exception claiming callbacks to determine if an exception is thrown by one of registered
- // runtimes.
- //
- // Before a runtime goes to process Watson for an unhandled exception, it first asks Waston SxS
- // manager if a Watson report has already been submitted for the current process. If so, it
- // will not try to do Watson. If not, it checks if the unhandled exception is thrown by itself.
- // If true, it will report Watson only when Watson SxS manager allows it to do Watson.
- //
- // If the unhandled exception is not thrown by itself, it will invoke Watson SxS manager's exception
- // claiming API to determine if the unhandled exception was thrown by another runtime which is
- // responsible for reporting Watson. If true, it will not try to do Watson. If none of runtimes
- // in the process claims the ownership of the unhandled exception, it will report Watson only when
- // Watson SxS manager allows it to do Watson.
- result = DoFaultReport(pExceptionInfo, tore);
-
- // Set the event to indicate that Watson processing is completed. Other threads can continue.
- UnsafeSetEvent(g_hWatsonCompletionEvent);
- }
+
+ if (IsDebuggerPresent())
+ {
+ result = FaultReportResultDebug;
+ jitAttachRequested = FALSE;
}
switch(result)
diff --git a/src/vm/i386/cgencpu.h b/src/vm/i386/cgencpu.h
index ffdfb82b14..f1bdd0f73f 100644
--- a/src/vm/i386/cgencpu.h
+++ b/src/vm/i386/cgencpu.h
@@ -44,8 +44,6 @@ EXTERN_C void STDCALL PInvokeStackImbalanceHelper(void);
EXTERN_C void SinglecastDelegateInvokeStub();
#endif // FEATURE_STUBS_AS_IL
-BOOL Runtime_Test_For_SSE2();
-
#ifdef CROSSGEN_COMPILE
#define GetEEFuncEntryPoint(pfn) 0x1001
#else
@@ -61,7 +59,7 @@ BOOL Runtime_Test_For_SSE2();
// #define CPU_X86_STEPPING(cpuType) (((cpuType) & 0x000F) )
#define CPU_X86_USE_CMOV(cpuFeat) ((cpuFeat & 0x00008001) == 0x00008001)
-#define CPU_X86_USE_SSE2(cpuFeat) (((cpuFeat & 0x04000000) == 0x04000000) && Runtime_Test_For_SSE2())
+#define CPU_X86_USE_SSE2(cpuFeat) ((cpuFeat & 0x04000000) == 0x04000000)
// Values for CPU_X86_FAMILY(cpuType)
#define CPU_X86_486 4
diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp
index 492cec4668..e222607a60 100644
--- a/src/vm/i386/cgenx86.cpp
+++ b/src/vm/i386/cgenx86.cpp
@@ -84,73 +84,6 @@ void ClearRegDisplayArgumentAndScratchRegisters(REGDISPLAY * pRD)
#ifndef DACCESS_COMPILE
-//=============================================================================
-// Runtime test to see if the OS has enabled support for the SSE2 instructions
-//
-//
-BOOL Runtime_Test_For_SSE2()
-{
-#ifdef FEATURE_CORESYSTEM
- return TRUE;
-#else
-
- BOOL result = IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE);
-
- if (result == FALSE)
- return FALSE;
-
- // **********************************************************************
- // *** ***
- // *** IMPORTANT NOTE: ***
- // *** ***
- // *** All of these RunningOnXXX APIs return true when ***
- // *** the OS that you are running on is that OS or later. ***
- // *** For example RunningOnWin2003() will return true ***
- // *** when you are running on Win2k3, Vista, Win7 or later. ***
- // *** ***
- // **********************************************************************
-
-
- // Windows 7 and later should alwys be using SSE2 instructions
- // this is true for both for native and Wow64
- //
- if (RunningOnWin7())
- return TRUE;
-
- if (RunningInWow64())
- {
- // There is an issue with saving/restoring the SSE2 registers under wow64
- // So we figure out if we are running on an impacted OS and Service Pack level
- // See DevDiv Bugs 89587 for the wow64 bug.
- //
-
- _ASSERTE(ExOSInfoAvailable()); // This is always available on Vista and later
-
- //
- // The issue is fixed in Windows Server 2008 or Vista/SP1
- //
- // It is not fixed in Vista/RTM, so check for that case
- //
- if ((ExOSInfoRunningOnServer() == FALSE))
- {
- OSVERSIONINFOEX osvi;
-
- ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- osvi.wServicePackMajor = 0;
-
- DWORDLONG dwlConditionMask = 0;
- VER_SET_CONDITION( dwlConditionMask, CLR_VER_SERVICEPACKMAJOR, VER_EQUAL);
-
- if (VerifyVersionInfo(&osvi, CLR_VER_SERVICEPACKMAJOR, dwlConditionMask))
- result = FALSE;
- }
- }
-
- return result;
-#endif
-}
-
//---------------------------------------------------------------
// Returns the type of CPU (the value of x of x86)
// (Please note, that it returns 6 for P5-II)
diff --git a/src/vm/threads.cpp b/src/vm/threads.cpp
index 928f20a095..283c6299ca 100644
--- a/src/vm/threads.cpp
+++ b/src/vm/threads.cpp
@@ -8828,7 +8828,7 @@ static void ManagedThreadBase_DispatchInner(ManagedThreadCallState *pCallState)
// This also implies that there will be no exception object marshalling (and it may not be required after all)
// as well and once the holder reverts the AD context, the LastThrownObject in Thread will be set to NULL.
#ifndef FEATURE_PAL
- BOOL fSetupEHAtTransition = !(RunningOnWin7());
+ BOOL fSetupEHAtTransition = FALSE;
#else // !FEATURE_PAL
BOOL fSetupEHAtTransition = TRUE;
#endif // !FEATURE_PAL
diff --git a/src/vm/vars.cpp b/src/vm/vars.cpp
index 92eff4217f..04437f9964 100644
--- a/src/vm/vars.cpp
+++ b/src/vm/vars.cpp
@@ -28,11 +28,6 @@ const char g_psBaseLibrary[] = CoreLibName_IL_A;
const char g_psBaseLibraryName[] = CoreLibName_A;
const char g_psBaseLibrarySatelliteAssemblyName[] = CoreLibSatelliteName_A;
-#ifdef FEATURE_COMINTEROP
-const WCHAR g_pwBaseLibraryTLB[] = CoreLibName_TLB_W;
-const char g_psBaseLibraryTLB[] = CoreLibName_TLB_A;
-#endif // FEATURE_COMINTEROP
-
Volatile<LONG> g_TrapReturningThreads;
HINSTANCE g_pMSCorEE;
@@ -249,8 +244,6 @@ LPWSTR g_pCachedModuleFileName = 0;
//
HINSTANCE g_hInstShim = NULL;
-char g_Version[] = VER_PRODUCTVERSION_STR;
-
#endif // #ifndef DACCESS_COMPILE
#ifdef DACCESS_COMPILE
diff --git a/src/vm/vars.hpp b/src/vm/vars.hpp
index 58dbe0e86a..69540c7f39 100644
--- a/src/vm/vars.hpp
+++ b/src/vm/vars.hpp
@@ -579,10 +579,6 @@ EXTERN const char g_psBaseLibrary[];
EXTERN const char g_psBaseLibraryName[];
EXTERN const char g_psBaseLibrarySatelliteAssemblyName[];
-#ifdef FEATURE_COMINTEROP
-EXTERN const WCHAR g_pwBaseLibraryTLB[];
-EXTERN const char g_psBaseLibraryTLB[];
-#endif // FEATURE_COMINTEROP
#endif // DACCESS_COMPILE
//
diff --git a/src/zap/zapper.cpp b/src/zap/zapper.cpp
index 59d05a08de..b7dc540e09 100644
--- a/src/zap/zapper.cpp
+++ b/src/zap/zapper.cpp
@@ -782,15 +782,13 @@ void Zapper::CleanupAssembly()
// To be used with GetSpecificCpuInfo()
#ifdef _TARGET_X86_
-BOOL Runtime_Test_For_SSE2();
-
#define CPU_X86_FAMILY(cpuType) (((cpuType) & 0x0F00) >> 8)
#define CPU_X86_MODEL(cpuType) (((cpuType) & 0x00F0) >> 4)
// Stepping is masked out by GetSpecificCpuInfo()
// #define CPU_X86_STEPPING(cpuType) (((cpuType) & 0x000F) )
#define CPU_X86_USE_CMOV(cpuFeat) ((cpuFeat & 0x00008001) == 0x00008001)
-#define CPU_X86_USE_SSE2(cpuFeat) (((cpuFeat & 0x04000000) == 0x04000000) && Runtime_Test_For_SSE2())
+#define CPU_X86_USE_SSE2(cpuFeat) ((cpuFeat & 0x04000000) == 0x04000000)
// Values for CPU_X86_FAMILY(cpuType)
#define CPU_X86_486 4