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