{"id":203,"date":"2007-11-20T13:32:02","date_gmt":"2007-11-20T18:32:02","guid":{"rendered":"http:\/\/www.nynaeve.net\/?p=203"},"modified":"2019-12-13T17:43:58","modified_gmt":"2019-12-13T22:43:58","slug":"a-catalog-of-ntdll-kernel-mode-to-user-mode-callbacks-part-4-kiraiseuserexceptiondispatcher","status":"publish","type":"post","link":"http:\/\/www.nynaeve.net\/?p=203","title":{"rendered":"A catalog of NTDLL kernel mode to user mode callbacks, part 4: KiRaiseUserExceptionDispatcher"},"content":{"rendered":"<p>The <a title=\"A catalog of NTDLL kernel mode to user mode callbacks, part 3: KiUserApcDispatcher\">previous post<\/a> in this series outlined how <em>KiUserApcDispatcher<\/em> operates for the purposes of enabling user mode APCs.  Unlike <em>KiUserExceptionDispatcher<\/em>, which is expected to modify the return information from the context of an interrupt (or exception) in kernel mode, KiUserApcDispatcher is intended to operate on the return context of an active system call.<\/p>\n<p>In this vein, the third kernel mode to user mode NTDLL &#8220;callback&#8221; that we shall be investigating, <em>KiRaiseUserExceptionDispatcher<\/em>, is fairly similar.  Although in some respects akin to KiUserExceptionDispatcher, at least relating to raising an exception in user mode on the behalf of a kernel mode caller, the KiRaiseUserExceptionDispatcher &#8220;callback&#8221; really has more in common with KiUserApcDispatcher from a usage and implementation standpoint.  It also so happens that the implementation of this callback routine, which is quite simple, is completely <a title=\"KiRaiseUserExceptionDispatcher\" href=\"http:\/\/www.nynaeve.net\/Code\/KiRaiseUserExceptionDispatcher.c\">representable in C<\/a>, as a standard calling convention is used.<\/p>\n<p>KiRaiseUserExceptionDispatcher is used if a system call wishes to raise an exception in user mode instead of simply return an NTSTATUS, as is the standard convention.  It simply constructs a standard exception record using a supplied status code (which must be written to a well-known location in the current thread&#8217;s TEB beforehand), and passes the exception to <em>RtlRaiseException<\/em> (the same routine that is used internally by the Win32 <a title=\"RaiseException\" href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms680552.aspx\">RaiseException<\/a> API).<\/p>\n<p>This is a fairly atypical scenario, as most errors (including bad pointer parameters) will simply result in an appropriate status code being returned by the system call, such as STATUS_ACCESS_VIOLATION.<\/p>\n<p>The one place the <em>does<\/em> currently use the services of KiRaiseUserExceptionDispatcher is <em>NtClose<\/em>, the system service responsible for closing handles (which implements the Win32 <a title=\"CloseHandle\" href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms724211.aspx\">CloseHandle<\/a> API).  When a debugger is attached to a process and a <em>protected handle<\/em> (as set by a call to <a title=\"SetHandleInformation\" href=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms724935.aspx\">SetHandleInformation<\/a> with <em>HANDLE_FLAG_PROTECT_FROM_CLOSE<\/em>) is passed to NtClose, then a STATUS_HANDLE_NOT_CLOSABLE exception is raised to user mode via KiRaiseUserExceptionDispatcher.  For example, one might see the following when trying to close a protected handle with a debugger attached:<\/p>\n<pre>\r\n(2600.1994): Unknown exception - code c0000235 (first chance)\r\n(2600.1994): Unknown exception - code c0000235 (second chance)\r\nntdll!KiRaiseUserExceptionDispatcher+0x3a:\r\n00000000`776920e7 8b8424c0000000  mov eax,dword ptr [rsp+0C0h]\r\n0:000&gt; !error c0000235\r\nError code: (NTSTATUS) 0xc0000235 (3221226037) - NtClose was\r\ncalled on a handle that was protected from close via\r\nNtSetInformationObject.\r\n0:000&gt; k\r\nRetAddr           Call Site\r\n00000000`7746dadd ntdll!KiRaiseUserExceptionDispatcher+0x3a\r\n00000000`01001955 kernel32!CloseHandle+0x29\r\n00000000`01001e60 TestApp!wmain+0x35\r\n00000000`7746cdcd TestApp!__tmainCRTStartup+0x120\r\n00000000`7768c6e1 kernel32!BaseThreadInitThunk+0xd\r\n00000000`00000000 ntdll!RtlUserThreadStart+0x1d\r\n<\/pre>\n<p>The exception can be manually continued in a debugger to allow the program to operate after this occurs, though such a bad handle reference is typically indicative of a serious bug.<\/p>\n<p>A similar behavior is activated if a program is being debugged under <a title=\"Application Verifier\" href=\"http:\/\/www.microsoft.com\/technet\/prodtechnol\/windows\/appcompatibility\/appverifier.mspx\">Application Verifier<\/a> and an invalid handle is closed.  This behavior of raising an exception on a bad handle closure attempt is intended as a debugging aid, since most programs do not bother to check the return value of CloseHandle.<\/p>\n<p>Incidentally, bad kernel handle closure references like this in kernel mode will result in a bugcheck instead of simply raising an exception that can be caught.  Drivers do not have the &#8220;luxury&#8221; of continuing when they touch a bad handle, except when probing a user handle, of course.  (Old versions of <a title=\"Process Explorer\" href=\"http:\/\/www.microsoft.com\/technet\/sysinternals\/utilities\/processexplorer.mspx\">Process Explorer<\/a> used to bring down the box with a bugcheck due to this, for instance, if you tried to close a protected handle.  This bug has fortunately since been fixed.)<\/p>\n<p>Next time, we&#8217;ll take a look at <em>KiUserCallbackDispatcher<\/em>, which is used to a great degree by win32k.sys.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The previous post in this series outlined how KiUserApcDispatcher operates for the purposes of enabling user mode APCs. Unlike KiUserExceptionDispatcher, which is expected to modify the return information from the context of an interrupt (or exception) in kernel mode, KiUserApcDispatcher is intended to operate on the return context of an active system call. In this [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[10,5],"tags":[30,17,29],"_links":{"self":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/203"}],"collection":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=203"}],"version-history":[{"count":1,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/203\/revisions"}],"predecessor-version":[{"id":518,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/203\/revisions\/518"}],"wp:attachment":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=203"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}