[runtime] Make helper to set MonoError directly from MonoClass error
[mono.git] / mono / utils / mono-error.c
1 /*
2  * mono-error.c: Error handling code
3  *
4  * Authors:
5  *      Rodrigo Kumpera    (rkumpera@novell.com)
6  * Copyright 2009 Novell, Inc (http://www.novell.com)
7  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
8  */
9 #include <glib.h>
10
11 #include "mono-error.h"
12 #include "mono-error-internals.h"
13
14 #include <mono/metadata/exception.h>
15 #include <mono/metadata/debug-helpers.h>
16 #include <mono/metadata/object-internals.h>
17
18 #define set_error_messagev() do { \
19         if (!(error->full_message = g_strdup_vprintf (msg_format, args))) \
20                         error->flags |= MONO_ERROR_INCOMPLETE; \
21 } while (0)
22
23 #define set_error_message() do { \
24         va_list args; \
25         va_start (args, msg_format); \
26         set_error_messagev();        \
27         va_end (args); \
28 } while (0)
29
30 static void
31 mono_error_set_generic_errorv (MonoError *oerror, const char *name_space, const char *name, const char *msg_format, va_list args);
32
33 static gboolean
34 is_managed_exception (MonoErrorInternal *error)
35 {
36         return (error->error_code == MONO_ERROR_EXCEPTION_INSTANCE);
37 }
38
39 static void
40 mono_error_prepare (MonoErrorInternal *error)
41 {
42         /* mono_error_set_* after a mono_error_cleanup without an intervening init */
43         g_assert (error->error_code != MONO_ERROR_CLEANUP_CALLED_SENTINEL);
44         if (error->error_code != MONO_ERROR_NONE)
45                 return;
46
47         error->type_name = error->assembly_name = error->member_name = error->full_message = error->exception_name_space = error->exception_name = error->full_message_with_fields = error->first_argument = NULL;
48         error->exn.klass = NULL;
49 }
50
51 static MonoClass*
52 get_class (MonoErrorInternal *error)
53 {
54         MonoClass *klass = NULL;
55         if (is_managed_exception (error))
56                 klass = mono_object_class (mono_gchandle_get_target (error->exn.instance_handle));
57         else
58                 klass = error->exn.klass;
59         return klass;
60 }
61
62 static const char*
63 get_type_name (MonoErrorInternal *error)
64 {
65         if (error->type_name)
66                 return error->type_name;
67         MonoClass *klass = get_class (error);
68         if (klass)
69                 return klass->name;
70         return "<unknown type>";
71 }
72
73 static const char*
74 get_assembly_name (MonoErrorInternal *error)
75 {
76         if (error->assembly_name)
77                 return error->assembly_name;
78         MonoClass *klass = get_class (error);
79         if (klass && klass->image)
80                 return klass->image->name;
81         return "<unknown assembly>";
82 }
83
84 void
85 mono_error_init_flags (MonoError *oerror, unsigned short flags)
86 {
87         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
88         g_assert (sizeof (MonoError) == sizeof (MonoErrorInternal));
89
90         error->error_code = MONO_ERROR_NONE;
91         error->flags = flags;
92 }
93
94 /**
95  * mono_error_init:
96  * @error: Pointer to MonoError struct to initialize
97  *
98  * Any function which takes a MonoError for purposes of reporting an error
99  * is required to call either this or mono_error_init_flags on entry.
100  */
101 void
102 mono_error_init (MonoError *error)
103 {
104         mono_error_init_flags (error, 0);
105 }
106
107 void
108 mono_error_cleanup (MonoError *oerror)
109 {
110         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
111         short int orig_error_code = error->error_code;
112         gboolean free_strings = error->flags & MONO_ERROR_FREE_STRINGS;
113         gboolean has_instance_handle = is_managed_exception (error);
114
115         /* Two cleanups in a row without an intervening init. */
116         g_assert (orig_error_code != MONO_ERROR_CLEANUP_CALLED_SENTINEL);
117
118         /* Mark it as cleaned up. */
119         error->error_code = MONO_ERROR_CLEANUP_CALLED_SENTINEL;
120         error->flags = 0;
121
122         if (orig_error_code == MONO_ERROR_NONE)
123                 return;
124
125
126         if (has_instance_handle)
127                 mono_gchandle_free (error->exn.instance_handle);
128
129
130         g_free ((char*)error->full_message);
131         g_free ((char*)error->full_message_with_fields);
132         error->full_message = NULL;
133         error->full_message_with_fields = NULL;
134         if (!free_strings) //no memory was allocated
135                 return;
136
137         g_free ((char*)error->type_name);
138         g_free ((char*)error->assembly_name);
139         g_free ((char*)error->member_name);
140         g_free ((char*)error->exception_name_space);
141         g_free ((char*)error->exception_name);
142         g_free ((char*)error->first_argument);
143         error->type_name = error->assembly_name = error->member_name = error->exception_name_space = error->exception_name = error->first_argument = NULL;
144         error->exn.klass = NULL;
145
146 }
147
148 gboolean
149 mono_error_ok (MonoError *error)
150 {
151         return error->error_code == MONO_ERROR_NONE;
152 }
153
154 void
155 mono_error_assert_ok_pos (MonoError *error, const char* filename, int lineno)
156 {
157         if (mono_error_ok (error))
158                 return;
159
160         g_error ("%s:%d: %s\n", filename, lineno, mono_error_get_message (error));
161 }
162
163 unsigned short
164 mono_error_get_error_code (MonoError *error)
165 {
166         return error->error_code;
167 }
168
169 /*Return a pointer to the internal error message, might be NULL.
170 Caller should not release it.*/
171 const char*
172 mono_error_get_message (MonoError *oerror)
173 {
174         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
175         if (error->error_code == MONO_ERROR_NONE)
176                 return NULL;
177         if (error->full_message_with_fields)
178                 return error->full_message_with_fields;
179
180         error->full_message_with_fields = g_strdup_printf ("%s assembly:%s type:%s member:%s",
181                 error->full_message,
182                 get_assembly_name (error),
183                 get_type_name (error),
184                 error->member_name ? error->member_name : "<none>");
185
186         return error->full_message_with_fields ? error->full_message_with_fields : error->full_message;
187 }
188
189 /*
190  * Inform that this error has heap allocated strings.
191  * The strings will be duplicated if @dup_strings is TRUE
192  * otherwise they will just be free'd in mono_error_cleanup.
193  */
194 void
195 mono_error_dup_strings (MonoError *oerror, gboolean dup_strings)
196 {
197 #define DUP_STR(field) do { if (error->field) {\
198         if (!(error->field = g_strdup (error->field))) \
199                 error->flags |= MONO_ERROR_INCOMPLETE; \
200         }} while (0);
201
202         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
203         error->flags |= MONO_ERROR_FREE_STRINGS;
204
205         if (dup_strings) {
206                 DUP_STR (type_name);
207                 DUP_STR (assembly_name);
208                 DUP_STR (member_name);
209                 DUP_STR (exception_name_space);
210                 DUP_STR (exception_name);
211                 DUP_STR (first_argument);
212         }
213 #undef DUP_STR
214 }
215
216 void
217 mono_error_set_error (MonoError *oerror, int error_code, const char *msg_format, ...)
218 {
219         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
220         mono_error_prepare (error);
221
222         error->error_code = error_code;
223         set_error_message ();
224 }
225
226 static void
227 mono_error_set_assembly_name (MonoError *oerror, const char *assembly_name)
228 {
229         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
230         g_assert (error->error_code != MONO_ERROR_NONE);
231
232         error->assembly_name = assembly_name;
233 }
234
235 static void
236 mono_error_set_member_name (MonoError *oerror, const char *member_name)
237 {
238         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
239
240         error->member_name = member_name;
241 }
242
243 static void
244 mono_error_set_type_name (MonoError *oerror, const char *type_name)
245 {
246         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
247
248         error->type_name = type_name;
249 }
250
251 static void
252 mono_error_set_class (MonoError *oerror, MonoClass *klass)
253 {
254         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
255
256         if (is_managed_exception (error))
257                 return;
258         error->exn.klass = klass;       
259 }
260
261 static void
262 mono_error_set_corlib_exception (MonoError *oerror, const char *name_space, const char *name)
263 {
264         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
265
266         error->exception_name_space = name_space;
267         error->exception_name = name;
268 }
269
270
271 void
272 mono_error_set_assembly_load (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
273 {
274         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
275         mono_error_prepare (error);
276
277         error->error_code = MONO_ERROR_FILE_NOT_FOUND;
278         mono_error_set_assembly_name (oerror, assembly_name);
279
280         set_error_message ();
281 }
282
283
284 void
285 mono_error_set_assembly_load_simple (MonoError *oerror, const char *assembly_name, gboolean refection_only)
286 {
287         if (refection_only)
288                 mono_error_set_assembly_load (oerror, assembly_name, "Cannot resolve dependency to assembly because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.");
289         else
290                 mono_error_set_assembly_load (oerror, assembly_name, "Could not load file or assembly or one of its dependencies.");
291 }
292
293 void
294 mono_error_set_type_load_class (MonoError *oerror, MonoClass *klass, const char *msg_format, ...)
295 {
296         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
297         mono_error_prepare (error);
298
299         error->error_code = MONO_ERROR_TYPE_LOAD;
300         mono_error_set_class (oerror, klass);
301         set_error_message ();
302 }
303
304 /*
305  * Different than other functions, this one here assumes that type_name and assembly_name to have been allocated just for us.
306  * Which means mono_error_cleanup will free them.
307  */
308 void
309 mono_error_set_type_load_name (MonoError *oerror, const char *type_name, const char *assembly_name, const char *msg_format, ...)
310 {
311         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
312         mono_error_prepare (error);
313
314         error->error_code = MONO_ERROR_TYPE_LOAD;
315         mono_error_set_type_name (oerror, type_name);
316         mono_error_set_assembly_name (oerror, assembly_name);
317         mono_error_dup_strings (oerror, FALSE);
318         set_error_message ();
319 }
320
321 void
322 mono_error_set_method_load (MonoError *oerror, MonoClass *klass, const char *method_name, const char *msg_format, ...)
323 {
324         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
325         mono_error_prepare (error);
326
327         error->error_code = MONO_ERROR_MISSING_METHOD;
328         mono_error_set_class (oerror, klass);
329         mono_error_set_member_name (oerror, method_name);
330         set_error_message ();
331 }
332
333 void
334 mono_error_set_field_load (MonoError *oerror, MonoClass *klass, const char *field_name, const char *msg_format, ...)
335 {
336         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
337         mono_error_prepare (error);
338
339         error->error_code = MONO_ERROR_MISSING_FIELD;
340         mono_error_set_class (oerror, klass);
341         mono_error_set_member_name (oerror, field_name);
342         set_error_message ();   
343 }
344
345 void
346 mono_error_set_bad_image_name (MonoError *oerror, const char *assembly_name, const char *msg_format, ...)
347 {
348         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
349         mono_error_prepare (error);
350
351         error->error_code = MONO_ERROR_BAD_IMAGE;
352         mono_error_set_assembly_name (oerror, assembly_name);
353         set_error_message ();
354 }
355
356 void
357 mono_error_set_bad_image (MonoError *oerror, MonoImage *image, const char *msg_format, ...)
358 {
359         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
360         mono_error_prepare (error);
361
362         error->error_code = MONO_ERROR_BAD_IMAGE;
363         error->assembly_name = image ? mono_image_get_name (image) : "<no_image>";
364         set_error_message ();
365 }
366
367 void
368 mono_error_set_generic_errorv (MonoError *oerror, const char *name_space, const char *name, const char *msg_format, va_list args)
369 {
370         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
371         mono_error_prepare (error);
372
373         error->error_code = MONO_ERROR_GENERIC;
374         mono_error_set_corlib_exception (oerror, name_space, name);
375         set_error_messagev ();
376 }
377
378 void
379 mono_error_set_generic_error (MonoError *oerror, const char * name_space, const char *name, const char *msg_format, ...)
380 {
381         va_list args;
382         va_start (args, msg_format);
383         mono_error_set_generic_errorv (oerror, name_space, name, msg_format, args);
384         va_end (args);
385 }
386
387 /**
388  * mono_error_set_not_implemented:
389  *
390  * System.NotImplementedException
391  */
392 void
393 mono_error_set_not_implemented (MonoError *oerror, const char *msg_format, ...)
394 {
395         va_list args;
396         va_start (args, msg_format);
397         mono_error_set_generic_errorv (oerror, "System", "NotImplementedException", msg_format, args);
398         va_end (args);
399 }
400
401 /**
402  * mono_error_set_execution_engine:
403  *
404  * System.ExecutionEngineException
405  */
406 void
407 mono_error_set_execution_engine (MonoError *oerror, const char *msg_format, ...)
408 {
409         va_list args;
410         va_start (args, msg_format);
411         mono_error_set_generic_errorv (oerror, "System", "ExecutionEngineException", msg_format, args);
412         va_end (args);
413 }
414
415 /**
416  * mono_error_set_not_supported:
417  *
418  * System.NotSupportedException
419  */
420 void
421 mono_error_set_not_supported (MonoError *oerror, const char *msg_format, ...)
422 {
423         va_list args;
424         va_start (args, msg_format);
425         mono_error_set_generic_errorv (oerror, "System", "NotSupportedException", msg_format, args);
426         va_end (args);
427 }
428
429 /**
430  * mono_error_set_invalid_operation:
431  *
432  * System.InvalidOperationException
433  */
434 void
435 mono_error_set_invalid_operation (MonoError *oerror, const char *msg_format, ...)
436 {
437         va_list args;
438         va_start (args, msg_format);
439         mono_error_set_generic_errorv (oerror, "System", "InvalidOperationException", msg_format, args);
440         va_end (args);
441 }
442
443 void
444 mono_error_set_invalid_program (MonoError *oerror, const char *msg_format, ...)
445 {
446         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
447
448         mono_error_prepare (error);
449         error->error_code = MONO_ERROR_INVALID_PROGRAM;
450
451         set_error_message ();
452 }
453
454 void
455 mono_error_set_exception_instance (MonoError *oerror, MonoException *exc)
456 {
457         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
458
459         mono_error_prepare (error);
460         error->error_code = MONO_ERROR_EXCEPTION_INSTANCE;
461         error->exn.instance_handle = mono_gchandle_new (exc ? &exc->object : NULL, FALSE);
462 }
463
464 void
465 mono_error_set_out_of_memory (MonoError *oerror, const char *msg_format, ...)
466 {
467         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
468         mono_error_prepare (error);
469
470         error->error_code = MONO_ERROR_OUT_OF_MEMORY;
471
472         set_error_message ();
473 }
474
475 void
476 mono_error_set_argument (MonoError *oerror, const char *argument, const char *msg_format, ...)
477 {
478         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
479         mono_error_prepare (error);
480
481         error->error_code = MONO_ERROR_ARGUMENT;
482         error->first_argument = argument;
483
484         set_error_message ();
485 }
486
487 void
488 mono_error_set_argument_null (MonoError *oerror, const char *argument, const char *msg_format, ...)
489 {
490         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
491         mono_error_prepare (error);
492
493         error->error_code = MONO_ERROR_ARGUMENT_NULL;
494         error->first_argument = argument;
495
496         set_error_message ();
497 }
498
499 void
500 mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char *msg_format, ...)
501 {
502         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
503         mono_error_prepare (error);
504
505         error->error_code = MONO_ERROR_NOT_VERIFIABLE;
506         if (method) {
507                 mono_error_set_class (oerror, method->klass);
508                 mono_error_set_member_name (oerror, mono_method_full_name (method, 1));
509         }
510
511         set_error_message ();
512 }
513
514
515 static MonoString*
516 get_type_name_as_mono_string (MonoErrorInternal *error, MonoDomain *domain, MonoError *error_out)
517 {
518         MonoString* res = NULL;
519
520         if (error->type_name) {
521                 res = mono_string_new (domain, error->type_name);
522                 
523         } else {
524                 MonoClass *klass = get_class (error);
525                 if (klass) {
526                         char *name = mono_type_full_name (&klass->byval_arg);
527                         if (name) {
528                                 res = mono_string_new (domain, name);
529                                 g_free (name);
530                         }
531                 }
532         }
533         if (!res)
534                 mono_error_set_out_of_memory (error_out, "Could not allocate type name");
535         return res;
536 }
537
538 static void
539 set_message_on_exception (MonoException *exception, MonoErrorInternal *error, MonoError *error_out)
540 {
541         MonoString *msg = mono_string_new (mono_domain_get (), error->full_message);
542         if (msg)
543                 MONO_OBJECT_SETREF (exception, message, msg);
544         else
545                 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
546 }
547
548 /*Can fail with out-of-memory*/
549 MonoException*
550 mono_error_prepare_exception (MonoError *oerror, MonoError *error_out)
551 {
552         MonoErrorInternal *error = (MonoErrorInternal*)oerror;
553
554         MonoException* exception = NULL;
555         MonoString *assembly_name = NULL, *type_name = NULL, *method_name = NULL, *field_name = NULL, *msg = NULL;
556         MonoDomain *domain = mono_domain_get ();
557
558         mono_error_init (error_out);
559
560         switch (error->error_code) {
561         case MONO_ERROR_NONE:
562                 return NULL;
563
564         case MONO_ERROR_MISSING_METHOD:
565                 if ((error->type_name || error->exn.klass) && error->member_name) {
566                         type_name = get_type_name_as_mono_string (error, domain, error_out);
567                         if (!mono_error_ok (error_out))
568                                 break;
569
570                         method_name = mono_string_new (domain, error->member_name);
571                         if (!method_name) {
572                                 mono_error_set_out_of_memory (error_out, "Could not allocate method name");
573                                 break;
574                         }
575
576                         exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingMethodException", type_name, method_name);
577                         if (exception)
578                                 set_message_on_exception (exception, error, error_out);
579                 } else {
580                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", error->full_message);
581                 }
582                 break;
583
584         case MONO_ERROR_MISSING_FIELD:
585                 if ((error->type_name || error->exn.klass) && error->member_name) {
586                         type_name = get_type_name_as_mono_string (error, domain, error_out);
587                         if (!mono_error_ok (error_out))
588                                 break;
589                         
590                         field_name = mono_string_new (domain, error->member_name);
591                         if (!field_name) {
592                                 mono_error_set_out_of_memory (error_out, "Could not allocate field name");
593                                 break;
594                         }
595                         
596                         exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "MissingFieldException", type_name, field_name);
597                         if (exception)
598                                 set_message_on_exception (exception, error, error_out);
599                 } else {
600                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", error->full_message);
601                 }
602                 break;
603
604         case MONO_ERROR_TYPE_LOAD:
605                 if ((error->type_name && error->assembly_name) || error->exn.klass) {
606                         type_name = get_type_name_as_mono_string (error, domain, error_out);
607                         if (!mono_error_ok (error_out))
608                                 break;
609
610                         if (error->assembly_name) {
611                                 assembly_name = mono_string_new (domain, error->assembly_name);
612                                 if (!assembly_name) {
613                                         mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
614                                         break;
615                                 }
616                         }
617
618                         exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System", "TypeLoadException", type_name, assembly_name);
619                         if (exception)
620                                 set_message_on_exception (exception, error, error_out);
621                 } else {
622                         exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", error->full_message);
623                 }
624                 break;
625
626         case MONO_ERROR_FILE_NOT_FOUND:
627         case MONO_ERROR_BAD_IMAGE:
628                 if (error->assembly_name) {
629                         msg = mono_string_new (domain, error->full_message);
630                         if (!msg) {
631                                 mono_error_set_out_of_memory (error_out, "Could not allocate message");
632                                 break;
633                         }
634
635                         if (error->assembly_name) {
636                                 assembly_name = mono_string_new (domain, error->assembly_name);
637                                 if (!assembly_name) {
638                                         mono_error_set_out_of_memory (error_out, "Could not allocate assembly name");
639                                         break;
640                                 }
641                         }
642
643                         if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
644                                 exception = mono_exception_from_name_two_strings (mono_get_corlib (), "System.IO", "FileNotFoundException", msg, assembly_name);
645                         else
646                                 exception = mono_exception_from_name_two_strings (mono_defaults.corlib, "System", "BadImageFormatException", msg, assembly_name);
647                 } else {
648                         if (error->error_code == MONO_ERROR_FILE_NOT_FOUND)
649                                 exception = mono_exception_from_name_msg (mono_get_corlib (), "System.IO", "FileNotFoundException", error->full_message);
650                         else
651                                 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System", "BadImageFormatException", error->full_message);
652                 }
653                 break;
654
655         case MONO_ERROR_OUT_OF_MEMORY:
656                 exception = mono_get_exception_out_of_memory ();
657                 break;
658
659         case MONO_ERROR_ARGUMENT:
660                 exception = mono_get_exception_argument (error->first_argument, error->full_message);
661                 break;
662
663         case MONO_ERROR_ARGUMENT_NULL:
664                 exception = mono_get_exception_argument_null (error->first_argument);
665                 break;
666
667         case MONO_ERROR_NOT_VERIFIABLE: {
668                 char *type_name = NULL, *message;
669                 if (error->exn.klass) {
670                         type_name = mono_type_get_full_name (error->exn.klass);
671                         if (!type_name) {
672                                 mono_error_set_out_of_memory (error_out, "Could not allocate message");
673                                 break;
674                         }
675                 }
676                 message = g_strdup_printf ("Error in %s:%s %s", type_name, error->member_name, error->full_message);
677                 if (!message) {
678                         g_free (type_name);
679                         mono_error_set_out_of_memory (error_out, "Could not allocate message");
680                         break;  
681                 }
682                 exception = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", message);
683                 g_free (message);
684                 g_free (type_name);
685                 break;
686         }
687         case MONO_ERROR_GENERIC:
688                 if (!error->exception_name_space || !error->exception_name)
689                         mono_error_set_execution_engine (error_out, "MonoError with generic error but no exception name was supplied");
690                 else
691                         exception = mono_exception_from_name_msg (mono_defaults.corlib, error->exception_name_space, error->exception_name, error->full_message);
692                 break;
693
694         case MONO_ERROR_EXCEPTION_INSTANCE:
695                 exception = (MonoException*) mono_gchandle_get_target (error->exn.instance_handle);
696                 break;
697
698         case MONO_ERROR_CLEANUP_CALLED_SENTINEL:
699                 mono_error_set_execution_engine (error_out, "MonoError reused after mono_error_cleanup");
700                 break;
701
702         case MONO_ERROR_INVALID_PROGRAM: {
703                 gboolean lacks_message = error->flags & MONO_ERROR_INCOMPLETE;
704                 if (lacks_message)
705                         return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
706                 else
707                         return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", error->full_message);
708         }
709         default:
710                 mono_error_set_execution_engine (error_out, "Invalid error-code %d", error->error_code);
711         }
712
713         if (!mono_error_ok (error_out))
714                 return NULL;
715         if (!exception)
716                 mono_error_set_out_of_memory (error_out, "Could not allocate exception object");
717         return exception;
718 }
719
720 /*
721 Convert this MonoError to an exception if it's faulty or return NULL.
722 The error object is cleant after.
723 */
724
725 MonoException*
726 mono_error_convert_to_exception (MonoError *target_error)
727 {
728         MonoError error;
729         MonoException *ex;
730
731         if (mono_error_ok (target_error))
732                 return NULL;
733
734         ex = mono_error_prepare_exception (target_error, &error);
735         if (!mono_error_ok (&error)) {
736                 MonoError second_chance;
737                 /*Try to produce the exception for the second error. FIXME maybe we should log about the original one*/
738                 ex = mono_error_prepare_exception (&error, &second_chance);
739
740                 g_assert (mono_error_ok (&second_chance)); /*We can't reasonable handle double faults, maybe later.*/
741                 mono_error_cleanup (&error);
742         }
743         mono_error_cleanup (target_error);
744         return ex;
745 }
746
747 void
748 mono_error_move (MonoError *dest, MonoError *src)
749 {
750         memcpy (dest, src, sizeof (MonoErrorInternal));
751         mono_error_init (src);
752 }