wined3d: Use surface_blt_to_drawable() in IWineD3DSurfaceImpl_BltOverride().
[wine/multimedia.git] / dlls / ntdll / exception.c
blob4d2f759c5e14bd99cec4d55874d2d268d2b726f1
1 /*
2 * NT exception handling routines
4 * Copyright 1999 Turchanov Sergey
5 * Copyright 1999 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <assert.h>
26 #include <errno.h>
27 #include <signal.h>
28 #include <stdarg.h>
30 #include "ntstatus.h"
31 #define WIN32_NO_STATUS
32 #include "windef.h"
33 #include "winternl.h"
34 #include "wine/exception.h"
35 #include "wine/server.h"
36 #include "wine/list.h"
37 #include "wine/debug.h"
38 #include "excpt.h"
39 #include "ntdll_misc.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(seh);
43 typedef struct
45 struct list entry;
46 PVECTORED_EXCEPTION_HANDLER func;
47 } VECTORED_HANDLER;
49 static struct list vectored_handlers = LIST_INIT(vectored_handlers);
51 static RTL_RWLOCK vectored_handlers_lock;
53 /**********************************************************************
54 * exceptions_init
56 * Initialize read/write lock used by the vectored exception handling.
58 void exceptions_init(void)
60 RtlInitializeResource(&vectored_handlers_lock);
63 /**********************************************************************
64 * wait_suspend
66 * Wait until the thread is no longer suspended.
68 void wait_suspend( CONTEXT *context )
70 LARGE_INTEGER timeout;
71 int saved_errno = errno;
72 context_t server_context;
74 context_to_server( &server_context, context );
76 /* store the context we got at suspend time */
77 SERVER_START_REQ( set_thread_context )
79 req->handle = wine_server_obj_handle( GetCurrentThread() );
80 req->suspend = 1;
81 wine_server_add_data( req, &server_context, sizeof(server_context) );
82 wine_server_call( req );
84 SERVER_END_REQ;
86 /* wait with 0 timeout, will only return once the thread is no longer suspended */
87 timeout.QuadPart = 0;
88 NTDLL_wait_for_multiple_objects( 0, NULL, SELECT_INTERRUPTIBLE, &timeout, 0 );
90 /* retrieve the new context */
91 SERVER_START_REQ( get_thread_context )
93 req->handle = wine_server_obj_handle( GetCurrentThread() );
94 req->suspend = 1;
95 wine_server_set_reply( req, &server_context, sizeof(server_context) );
96 wine_server_call( req );
98 SERVER_END_REQ;
100 context_from_server( context, &server_context );
101 errno = saved_errno;
105 /**********************************************************************
106 * send_debug_event
108 * Send an EXCEPTION_DEBUG_EVENT event to the debugger.
110 NTSTATUS send_debug_event( EXCEPTION_RECORD *rec, int first_chance, CONTEXT *context )
112 NTSTATUS ret;
113 DWORD i;
114 HANDLE handle = 0;
115 client_ptr_t params[EXCEPTION_MAXIMUM_PARAMETERS];
116 context_t server_context;
118 if (!NtCurrentTeb()->Peb->BeingDebugged) return 0; /* no debugger present */
120 for (i = 0; i < min( rec->NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS ); i++)
121 params[i] = rec->ExceptionInformation[i];
123 context_to_server( &server_context, context );
125 SERVER_START_REQ( queue_exception_event )
127 req->first = first_chance;
128 req->code = rec->ExceptionCode;
129 req->flags = rec->ExceptionFlags;
130 req->record = wine_server_client_ptr( rec->ExceptionRecord );
131 req->address = wine_server_client_ptr( rec->ExceptionAddress );
132 req->len = i * sizeof(params[0]);
133 wine_server_add_data( req, params, req->len );
134 wine_server_add_data( req, &server_context, sizeof(server_context) );
135 if (!wine_server_call( req )) handle = wine_server_ptr_handle( reply->handle );
137 SERVER_END_REQ;
138 if (!handle) return 0;
140 NTDLL_wait_for_multiple_objects( 1, &handle, SELECT_INTERRUPTIBLE, NULL, 0 );
142 SERVER_START_REQ( get_exception_status )
144 req->handle = wine_server_obj_handle( handle );
145 wine_server_set_reply( req, &server_context, sizeof(server_context) );
146 ret = wine_server_call( req );
148 SERVER_END_REQ;
149 if (ret >= 0) context_from_server( context, &server_context );
150 return ret;
154 /**********************************************************************
155 * call_vectored_handlers
157 * Call the vectored handlers chain.
159 LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context )
161 struct list *ptr;
162 LONG ret = EXCEPTION_CONTINUE_SEARCH;
163 EXCEPTION_POINTERS except_ptrs;
165 except_ptrs.ExceptionRecord = rec;
166 except_ptrs.ContextRecord = context;
168 RtlAcquireResourceShared( &vectored_handlers_lock, TRUE );
169 LIST_FOR_EACH( ptr, &vectored_handlers )
171 VECTORED_HANDLER *handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry );
172 TRACE( "calling handler at %p code=%x flags=%x\n",
173 handler->func, rec->ExceptionCode, rec->ExceptionFlags );
174 ret = handler->func( &except_ptrs );
175 TRACE( "handler at %p returned %x\n", handler->func, ret );
176 if (ret == EXCEPTION_CONTINUE_EXECUTION) break;
178 RtlReleaseResource( &vectored_handlers_lock );
179 return ret;
183 /*******************************************************************
184 * raise_status
186 * Implementation of RtlRaiseStatus with a specific exception record.
188 void raise_status( NTSTATUS status, EXCEPTION_RECORD *rec )
190 EXCEPTION_RECORD ExceptionRec;
192 ExceptionRec.ExceptionCode = status;
193 ExceptionRec.ExceptionFlags = EH_NONCONTINUABLE;
194 ExceptionRec.ExceptionRecord = rec;
195 ExceptionRec.NumberParameters = 0;
196 for (;;) RtlRaiseException( &ExceptionRec ); /* never returns */
200 /***********************************************************************
201 * RtlRaiseStatus (NTDLL.@)
203 * Raise an exception with ExceptionCode = status
205 void WINAPI RtlRaiseStatus( NTSTATUS status )
207 raise_status( status, NULL );
211 /*******************************************************************
212 * RtlAddVectoredExceptionHandler (NTDLL.@)
214 PVOID WINAPI RtlAddVectoredExceptionHandler( ULONG first, PVECTORED_EXCEPTION_HANDLER func )
216 VECTORED_HANDLER *handler = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler) );
217 if (handler)
219 handler->func = func;
220 RtlAcquireResourceExclusive( &vectored_handlers_lock, TRUE );
221 if (first) list_add_head( &vectored_handlers, &handler->entry );
222 else list_add_tail( &vectored_handlers, &handler->entry );
223 RtlReleaseResource( &vectored_handlers_lock );
225 return handler;
229 /*******************************************************************
230 * RtlRemoveVectoredExceptionHandler (NTDLL.@)
232 ULONG WINAPI RtlRemoveVectoredExceptionHandler( PVOID handler )
234 struct list *ptr;
235 ULONG ret = FALSE;
237 RtlAcquireResourceExclusive( &vectored_handlers_lock, TRUE );
238 LIST_FOR_EACH( ptr, &vectored_handlers )
240 VECTORED_HANDLER *curr_handler = LIST_ENTRY( ptr, VECTORED_HANDLER, entry );
241 if (curr_handler == handler)
243 list_remove( ptr );
244 ret = TRUE;
245 break;
248 RtlReleaseResource( &vectored_handlers_lock );
249 if (ret) RtlFreeHeap( GetProcessHeap(), 0, handler );
250 return ret;
254 /*************************************************************
255 * __wine_spec_unimplemented_stub
257 * ntdll-specific implementation to avoid depending on kernel functions.
258 * Can be removed once ntdll.spec no longer contains stubs.
260 void __wine_spec_unimplemented_stub( const char *module, const char *function )
262 EXCEPTION_RECORD record;
264 record.ExceptionCode = EXCEPTION_WINE_STUB;
265 record.ExceptionFlags = EH_NONCONTINUABLE;
266 record.ExceptionRecord = NULL;
267 record.ExceptionAddress = __wine_spec_unimplemented_stub;
268 record.NumberParameters = 2;
269 record.ExceptionInformation[0] = (ULONG_PTR)module;
270 record.ExceptionInformation[1] = (ULONG_PTR)function;
271 for (;;) RtlRaiseException( &record );