Search code examples
c++winapivisual-c++sehstructured-exception

The 'get' equivalent of _set_se_translator?


I need to translate structured exceptions manually, using the current translator.

How do I 'get' the value someone has set by _set_se_translator?


Solution

  • Better (new) way

    I didn't realize this at first, but the SE translator is thread-local, not process-wide.

    So this is actually the best (and easiest) solution:

    _se_translator_function _get_se_translator(void) {
        _se_translator_function translator = _set_se_translator(NULL);  // temporary
        _set_se_translator(translator);  // Restore the old value
        return translator;
    }
    

    Hacky (old) way

    There is no direct way to do this, but if you're going to risk some incompatibility and delve into the Visual C runtime's internals, you can hack up a solution like this:

    _se_translator_function __cdecl _get_se_translator(void) {
        unsigned char const *p = (unsigned char const *)(&__uncaught_exception);
        struct _tiddata {
            unsigned long _tid;
            void *_thandle;
            int _terrno; unsigned long _tdoserrno;
            unsigned int _fpds;
            unsigned long _holdrand;
            char *_token; wchar_t *_wtoken;
            unsigned char *_mtoken;
            char *_errmsg; wchar_t *_werrmsg;
            char *_namebuf0; wchar_t *_wnamebuf0;
            char *_namebuf1; wchar_t *_wnamebuf1;
            char *_asctimebuf; wchar_t *_wasctimebuf;
            void *_gmtimebuf;
            char *_cvtbuf;
            unsigned char _con_ch_buf[5];
            unsigned short _ch_buf_used;
            void *_initaddr; void *_initarg;
            void *_pxcptacttab;
            void *_tpxcptinfoptrs;
            int _tfpecode;
            void *ptmbcinfo; void *ptlocinfo;
            int _ownlocale;
            unsigned long _NLG_dwCode;
            void *_terminate; void *_unexpected;
            _se_translator_function _translator;
        };
        if (p[0] == 0x48) /* sub RSP, 0x28 */ { p += 4; }  // x64 only
        if (p[0] == 0xE8) /* call _getpid */ { ++p; }  // must be true
        void const *_getptd = p + *(long *)p + sizeof(long);
        return ((struct _tiddata *(__cdecl *)(void))_getptd)()->_translator;
    }