Quantcast
Viewing all articles
Browse latest Browse all 29128

MFC application crashes in Windows 8 touch Devices.

Recently we had a chance to debug an issue where an application was only crashing in Windows 8 Touch devices , it crashed with EXCEPTION_CODE: (NTSTATUS) 0xc000041d - An unhandled exception was encountered during a user callback. . As usual we had taken full memory dumps for the application . From the dumps I saw that the crash was coming from tiptsf which is Touch Keyboard and Handwriting Panel Text Services Framework.  On more search I found out an immediate work around which is to manually stop Touch Keyboard and Handwriting Panel Service . However if we open on screen keyboard, the service would automatically start and the application would crash again. For doing this,
Go through the following steps:

  1. Go to Manage --> Services and Application-->Services`.
  2. Double click on Touch Keyboard and Handwriting Panel Service.
  3. In Startup type .. .
  4. Click the small arrow and go to Manual.
  5. Click stop service.

We do not recommend you to stop the service rather go for a code addition which would be a permanent and a better solution . Now coming back to the reason this blog was pursued .

Since we had the repro , We collected time travel traces (available internally) and did some analysis. Before I proceed with the debugging startegy used to debug here , I want to point out the resolution.

The resolution is to implement the below functions in your application specifically in CFormView derivative.

acchittest
acclocation
get_accDescription
get_accHelp
get_accKeyboardShortcut
get_accName
get_accRole
get_accSelection
get_accState
get_accValue

Here is the link which speaks about the acclocation and all the above functions , http://msdn.microsoft.com/en-us/library/windows/desktop/dd318472(v=vs.85).aspx .
Please override them in CFormView derivative. After overriding the functions , our application stopped crashing on Windows 8 Touch Devices .

If you are interested in knowing how we debugged it , continue reading .
Below is the call stack for the crash .  We also see that oleacc!AccWrap_Base::accLocation  is happening which further leads to a _purecall. In case you are wondering what is a _purecall , please refer http://msdn.microsoft.com/en-us/library/ff798096.aspx . Essentially it will be called if any function is not implemented in the derived class. The bloggives you good examples on when we see such behvior.

ChildEBP RetAddr
010df060 773a0f7b kernelbase!RaiseException
010df074 783edeb8 msvcrt!_purecall+0x11
010df0a8 783ee21e mfc90!CWnd::accLocation+0x28
010df0fc 00872079 mfc90!CWnd::GetAccessibilityLocation+0x31
010df120 783ed8e5 viewswitch!CFormView::accLocation+0x39
010df174 783ef675 mfc90!CWnd::XAccessible::accLocation+0x43
010df1a8 7490269e mfc90!ATL::IAccessibleProxyImpl<ATL::CAccessibleProxy>::accLocation+0x53
(Inline) -------- oleacc!AccWrap_Base::accLocation+0x49
010df2c0 73db6375 oleacc!AccWrap_LocationEtcFix::accLocation+0x65
010df344 73db658d tiptsf!CARET::UpdateMSAAEditFieldState+0x81
010df37c 73db3a59 tiptsf!CARET::UpdateEditFieldState+0x31
010df820 73db1b2a tiptsf!CARET::_ProcessCaretEvents+0x34e
010df840 7672a259 tiptsf!CARET::ProcessCaretEvents+0x69
010df880 77a92c92 user32!__ClientCallWinEventProc+0x2e
010df888 77a92c92 ntdll!KiUserCallbackDispatcher+0x2e
010df8b4 783eb0ee ntdll!KiUserCallbackDispatcher+0x2e
010df8c4 00871643 mfc90!CWnd::DestroyWindow+0x4e
010df8fc 00871907 viewswitch!CViewSwitchApp::CreateView+0xc3
010df924 0087150e viewswitch!CViewSwitchApp::GoToView2+0xa7
010df954 00871338 viewswitch!CViewSwitchApp::InitApp+0xce
010df9b0 783f71c7 viewswitch!CViewSwitchApp::InitInstance+0x118
010df9c4 00872c6e mfc90!AfxWinMain+0x49
010dfa54 774e8543 viewswitch!__tmainCRTStartup+0x140
010dfa60 77aabf39 kernel32!BaseThreadInitThunk+0xe
010dfaa4 77aabf0c ntdll!__RtlUserThreadStart+0x72
010dfabc 00000000 ntdll!_RtlUserThreadStart+0x1b

Let’s dump cwnd and we can see that m_pStdobject is a member of CWND .

0:000> dt cwnd
viewswitch!CWnd
   +0x000 __VFN_table : Ptr32
   =00870000 classCObject     : CRuntimeClass
   =00870000 classCCmdTarget  : CRuntimeClass
   =00870000 _commandEntries  : [0] AFX_OLECMDMAP_ENTRY
   =00870000 commandMap       : AFX_OLECMDMAP
   =00870000 _dispatchEntries : [0] AFX_DISPMAP_ENTRY
   =00870000 _dispatchEntryCount : Uint4B
   =00870000 _dwStockPropMask : Uint4B
   =00870000 dispatchMap      : AFX_DISPMAP
   =00870000 _connectionEntries : [0] AFX_CONNECTIONMAP_ENTRY
   =00870000 connectionMap    : AFX_CONNECTIONMAP
   =00870000 _interfaceEntries : [0] AFX_INTERFACEMAP_ENTRY
   =00870000 interfaceMap     : AFX_INTERFACEMAP
   =00870000 _eventsinkEntries : [0] AFX_EVENTSINKMAP_ENTRY
   =00870000 _eventsinkEntryCount : Uint4B
   =00870000 eventsinkMap     : AFX_EVENTSINKMAP
   +0x004 m_dwRef          : Int4B
   +0x008 m_pOuterUnknown  : Ptr32 IUnknown
   +0x00c m_xInnerUnknown  : Uint4B
   +0x010 m_xDispatch      : CCmdTarget::XDispatch
   +0x014 m_bResultExpected : Int4B
   +0x018 m_xConnPtContainer : CCmdTarget::XConnPtContainer
   +0x01c m_pModuleState   : Ptr32 AFX_MODULE_STATE
   =00870000 classCWnd        : CRuntimeClass
   +0x020 m_hWnd           : Ptr32 HWND__
   =00870000 wndTop           : CWnd
   =00870000 wndBottom        : CWnd
   =00870000 wndTopMost       : CWnd
   =00870000 wndNoTopMost     : CWnd
   +0x024 m_bEnableActiveAccessibility : Bool
   +0x028 m_pStdObject     : Ptr32 IAccessible
   =00870000 m_pfnNotifyWinEvent : (null)
   +0x02c m_pProxy         : Ptr32 IAccessibleProxy
   =00870000 _interfaceEntries : [0] AFX_INTERFACEMAP_ENTRY
   =00870000 interfaceMap     : AFX_INTERFACEMAP
   +0x030 m_xAccessible    : CWnd::XAccessible
   +0x034 m_xAccessibleServer : CWnd::XAccessibleServer
   +0x038 m_hWndOwner      : Ptr32 HWND__
   +0x03c m_nFlags         : Uint4B
   +0x040 m_pfnSuper       : Ptr32     long
   =00870000 m_nMsgDragList   : Uint4B
   +0x044 m_nModalResult   : Int4B
   +0x048 m_pDropTarget    : Ptr32 COleDropTarget
   +0x04c m_pCtrlCont      : Ptr32 COleControlContainer
   +0x050 m_pCtrlSite      : Ptr32 COleControlSite

So from above we know that IAccessible is part of Cwnd. CAccessible implements IAccessible, please refer to the source code of atlmfc which is available at C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\atlmfc .Let’s travel to the point at which the pure call is getting invoked.

eax=010df104 ebx=01539d18 ecx=01539d18 edx=038b5cab esi=010df114 edi=010df0d0
eip=783ee219 esp=010df0b0 ebp=010df0fc iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000206
mfc90!CWnd::GetAccessibilityLocation+0x2c:
783ee219 e872fcffff      call    mfc90!CWnd::accLocation (783ede90)

Let’s try to see if the function is implemented by CAccessible, details are below.

0:000> ?? this->m_pStdObject
struct IAccessible * 0x01376b58
   +0x000 lpVtbl           : 0x74902a88 IDispatchVtbl

Dumping out the vtable to see the functions which are overridden.

0:000> dds 0x74902a88
74902a88  749032a9 oleacc!CAccessible::QueryInterface
74902a8c  749033a4 oleacc!CProgressBar::AddRef
74902a90  74903085 oleacc!CAccessible::Release
74902a94  74929c35 oleacc!CAccessible::GetTypeInfoCount
74902a98  74929c60 oleacc!CAccessible::GetTypeInfo
74902a9c  74929cba oleacc!CAccessible::GetIDsOfNames
74902aa0  74929ce9 oleacc!CAccessible::Invoke
74902aa4  7491d390 oleacc!CAccessible::get_accParent
74902aa8  7491b87d oleacc!CAccessible::get_accChildCount
74902aac  74904713 oleacc!CAccessible::get_accChild
74902ab0  7491f9f1 oleacc!purecall
74902ab4  74929d22 oleacc!CAccessible::get_accDefaultAction
74902ab8  74929d22 oleacc!CAccessible::get_accDefaultAction
74902abc  7491f9f1 oleacc!purecall
74902ac0  7491f9f1 oleacc!purecall
74902ac4  74929d22 oleacc!CAccessible::get_accDefaultAction
74902ac8  74929d53 oleacc!CAccessible::get_accHelpTopic
74902acc  74929d22 oleacc!CAccessible::get_accDefaultAction
74902ad0  74929d8d oleacc!CAccessible::get_accFocus
74902ad4  74929d8d oleacc!CAccessible::get_accFocus
74902ad8  74929d22 oleacc!CAccessible::get_accDefaultAction
74902adc  74929b53 oleacc!CAccessible::accSelect
74902ae0  7491f9f1 oleacc!purecall
74902ae4  74929b90 oleacc!CAccessible::accNavigate
74902ae8  7491f9f1 oleacc!purecall
74902aec  74929c0d oleacc!CAccessible::accDoDefaultAction
74902af0  74929da6 oleacc!CAccessible::put_accValue
74902af4  74929da6 oleacc!CAccessible::put_accValue
74902af8  7490b099 oleacc!CListBoxFrame::`scalar deleting destructor'
74902afc  74903e7f oleacc!CAccessible::ValidateChild+0x41
74902b00  74903e3e oleacc!CAccessible::ValidateChild
74902b04  74929dce oleacc!CAccessible::GetPatternProvider

The above list does not have accLocation  and other functions . Since we are seeing that our application is calling accocation after which it crashes with a _purecall. Once we implemented this function, application started crashing at some other functions which are listed below .Our suggestion would be to override acclocation and all other functions from the below link which are not implemented namely , 

acchittest
acclocation
get_accDescription
get_accHelp
get_accKeyboardShortcut
get_accName
get_accRole
get_accSelection
get_accState
get_accValue

Here is the link which speaks about the acclocation and all the above functions , http://msdn.microsoft.com/en-us/library/windows/desktop/dd318472(v=vs.85).aspx .
Please override them in CFormView derivative. After overriding the functions , our application stopped crashing on Windows 8 Touch Devices .

 

Image may be NSFW.
Clik here to view.

Viewing all articles
Browse latest Browse all 29128

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>