2015-11-25 10:22:00 -06:00
// 25 november 2015
2015-11-25 10:56:37 -06:00
# ifdef __cplusplus
# error msbuild is being dumb and making this a C++ file
# endif
2015-11-25 13:38:40 -06:00
# include "unmanaged.h"
2015-11-25 10:22:00 -06:00
2015-11-25 13:38:40 -06:00
// TODO this won't work if initAlloc() failed
# define initErrorFormat L"error %s: %s%s%s %I32u (0x%I32X)%s"
# define initErrorArgs wmessage, sysmsg, beforele, label, value, value, afterle
static const char * initerr ( const char * message , const WCHAR * label , DWORD value )
{
2015-11-25 14:46:57 -06:00
// TODO
return " " ;
#if 0
2015-11-25 13:38:40 -06:00
WCHAR * sysmsg ;
BOOL hassysmsg ;
WCHAR * beforele ;
WCHAR * afterle ;
int n ;
WCHAR * wmessage ;
WCHAR * wstr ;
const char * str ;
if ( FormatMessageW ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS , NULL , value , 0 , ( LPWSTR ) ( & sysmsg ) , 0 , NULL ) ! = 0 ) {
hassysmsg = TRUE ;
beforele = L " ( " ;
afterle = L " ) " ;
} else {
hassysmsg = FALSE ;
sysmsg = L " " ;
beforele = L " " ;
afterle = L " " ;
}
wmessage = toUTF16 ( message ) ;
n = _scwprintf ( initErrorFormat , initErrorArgs ) ;
wstr = ( WCHAR * ) uiAlloc ( ( n + 1 ) * sizeof ( WCHAR ) , " WCHAR[] " ) ;
snwprintf ( wstr , n + 1 , initErrorFormat , initErrorArgs ) ;
str = toUTF8 ( wstr ) ;
uiFree ( wstr ) ;
if ( hassysmsg )
if ( LocalFree ( sysmsg ) ! = NULL )
logLastError ( " error freeing system message in loadLastError() " ) ;
uiFree ( wmessage ) ;
return str ;
2015-11-25 14:46:57 -06:00
# endif
2015-11-25 13:38:40 -06:00
}
static const char * loadLastError ( const char * message )
{
return initerr ( message , L " GetLastError() = = " , GetLastError()) ;
}
static const char * loadHRESULT ( const char * message , HRESULT hr )
{
return initerr ( message , L " HRESULT " , ( DWORD ) hr ) ;
}
// On the subject of CoInitialize(), or why this isn't in main.cpp:
2015-11-25 10:22:00 -06:00
// If we don't set up the current thread otherwise, the first time .net tries to call out to unmanaged code, it will automatically set up a MTA for COM.
// This is not what we want; we need a STA instead.
// Since we're not in control of main(), we can't stick a [STAThread] on it, so we have to do it ourselves.
// This is a separate .c file for two reasons:
// 1) To avoid the unmanaged jump that a call to CoInitialize() would do (it seems to detect a call to CoInitialize()/CoInitializeEx() but let's not rely on it)
// 2) To avoid mixing Windows API headers with .net
// See also http://stackoverflow.com/questions/24348205/how-do-i-solve-this-com-issue-in-c
2015-11-25 13:38:40 -06:00
uiInitOptions options ;
2015-11-25 10:22:00 -06:00
2015-11-25 13:38:40 -06:00
const char * uiInit ( uiInitOptions * o )
2015-11-25 10:22:00 -06:00
{
HRESULT hr ;
2015-11-25 13:38:40 -06:00
options = * o ;
if ( initAlloc ( ) = = 0 )
return loadLastError ( " error initializing memory allocations " ) ;
2015-11-25 10:22:00 -06:00
// TODO https://msdn.microsoft.com/en-us/library/5s8ee185%28v=vs.71%29.aspx use CoInitializeEx()?
hr = CoInitialize ( NULL ) ;
if ( hr ! = S_OK & & hr ! = S_FALSE )
2015-11-25 13:38:40 -06:00
return loadHRESULT ( " initializing COM " , hr ) ;
2015-11-25 10:22:00 -06:00
// now do the rest of initialization on the managed side
initWPF ( ) ;
2015-11-25 13:38:40 -06:00
return NULL ;
2015-11-25 10:22:00 -06:00
}
void uiUninit ( void )
{
uninitWPF ( ) ;
CoUninitialize ( ) ;
2015-11-25 13:38:40 -06:00
uninitAlloc ( ) ;
}
void uiFreeInitError ( const char * err )
{
uiFree ( ( void * ) err ) ;
2015-11-25 10:22:00 -06:00
}