diff --git a/relay32/relay386.c b/relay32/relay386.c index 7da06f15d4a..7b9742bec80 100644 --- a/relay32/relay386.c +++ b/relay32/relay386.c @@ -70,7 +70,7 @@ typedef struct DWORD callfrom32 WINE_PACKED; /* RELAY_CallFrom32 relative addr */ BYTE ret; /* 0xc2 ret $n or 0xc3 ret */ WORD args; /* nb of args to remove from the stack */ - FARPROC orig; /* original entry point */ + void *orig; /* original entry point */ DWORD argtypes; /* argument types */ } DEBUG_ENTRY_POINT; @@ -166,10 +166,11 @@ static inline void RELAY_PrintArgs( int *args, int nb_args, unsigned int typemas * (esp+4) ret_addr * (esp) return addr to relay code */ -static int RELAY_CallFrom32( int ret_addr, ... ) +static LONGLONG RELAY_CallFrom32( int ret_addr, ... ) { - int ret; + LONGLONG ret; char buffer[80]; + BOOL ret64; int *args = &ret_addr + 1; /* Relay addr is the return address for this function */ @@ -182,6 +183,7 @@ static int RELAY_CallFrom32( int ret_addr, ... ) DPRINTF( "Call %s(", buffer ); RELAY_PrintArgs( args, nb_args, relay->argtypes ); DPRINTF( ") ret=%08x fs=%04x\n", ret_addr, __get_fs() ); + ret64 = (relay->argtypes & 0x80000000) && (nb_args < 16); /* the user driver functions may be called with the window lock held */ if (memcmp( buffer, "x11drv.", 7 ) && memcmp( buffer, "ttydrv.", 7 )) @@ -189,7 +191,7 @@ static int RELAY_CallFrom32( int ret_addr, ... ) if (relay->ret == 0xc3) /* cdecl */ { - LRESULT (*cfunc)() = (LRESULT(*)())relay->orig; + LONGLONG (*cfunc)() = relay->orig; switch(nb_args) { case 0: ret = cfunc(); break; @@ -232,7 +234,7 @@ static int RELAY_CallFrom32( int ret_addr, ... ) } else /* stdcall */ { - FARPROC func = relay->orig; + LONGLONG (WINAPI *func)() = relay->orig; switch(nb_args) { case 0: ret = func(); break; @@ -273,8 +275,12 @@ static int RELAY_CallFrom32( int ret_addr, ... ) assert(FALSE); } } - DPRINTF( "Ret %s() retval=%08x ret=%08x fs=%04x\n", - buffer, ret, ret_addr, __get_fs() ); + if (ret64) + DPRINTF( "Ret %s() retval=%08x%08x ret=%08x fs=%04x\n", + buffer, (UINT)(ret >> 32), (UINT)ret, ret_addr, __get_fs() ); + else + DPRINTF( "Ret %s() retval=%08x ret=%08x fs=%04x\n", + buffer, (UINT)ret, ret_addr, __get_fs() ); if (memcmp( buffer, "x11drv.", 7 ) && memcmp( buffer, "ttydrv.", 7 )) SYSLEVEL_CheckNotLevel( 2 ); diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 622fb245ab3..7f03b23519d 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -43,6 +43,7 @@ typedef enum TYPE_INTERRUPT, /* interrupt handler function (Win16) */ TYPE_STUB, /* unimplemented stub */ TYPE_STDCALL, /* stdcall function (Win32) */ + TYPE_STDCALL64, /* stdcall function with 64-bit return (Win32) */ TYPE_CDECL, /* cdecl function (Win32) */ TYPE_VARARGS, /* varargs function (Win32) */ TYPE_EXTERN, /* external symbol (Win32) */ @@ -75,7 +76,7 @@ typedef struct typedef struct { int n_args; - char arg_types[32]; + char arg_types[17]; char link_name[80]; } ORD_FUNCTION; diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c index 93332f9d182..44c3314fc4b 100644 --- a/tools/winebuild/parser.c +++ b/tools/winebuild/parser.c @@ -38,6 +38,7 @@ static const char * const TypeNames[TYPE_NBTYPES] = "interrupt", /* TYPE_INTERRUPT */ "stub", /* TYPE_STUB */ "stdcall", /* TYPE_STDCALL */ + "stdcall64", /* TYPE_STDCALL64 */ "cdecl", /* TYPE_CDECL */ "varargs", /* TYPE_VARARGS */ "extern", /* TYPE_EXTERN */ @@ -167,7 +168,7 @@ static void ParseExportFunction( ORDDEF *odp ) switch(SpecType) { case SPEC_WIN16: - if (odp->type == TYPE_STDCALL) + if (odp->type == TYPE_STDCALL || odp->type == TYPE_STDCALL64) fatal_error( "'stdcall' not supported for Win16\n" ); if (odp->type == TYPE_VARARGS) fatal_error( "'varargs' not supported for Win16\n" ); @@ -183,7 +184,7 @@ static void ParseExportFunction( ORDDEF *odp ) token = GetToken(); if (*token != '(') fatal_error( "Expected '(' got '%s'\n", token ); - for (i = 0; i < sizeof(odp->u.func.arg_types)-1; i++) + for (i = 0; i < sizeof(odp->u.func.arg_types); i++) { token = GetToken(); if (*token == ')') @@ -206,7 +207,7 @@ static void ParseExportFunction( ORDDEF *odp ) else if (!strcmp(token, "double")) { odp->u.func.arg_types[i++] = 'l'; - odp->u.func.arg_types[i] = 'l'; + if (i < sizeof(odp->u.func.arg_types)) odp->u.func.arg_types[i] = 'l'; } else fatal_error( "Unknown variable type '%s'\n", token ); @@ -372,6 +373,7 @@ static void ParseOrdinal(int ordinal) case TYPE_PASCAL_16: case TYPE_PASCAL: case TYPE_STDCALL: + case TYPE_STDCALL64: case TYPE_VARARGS: case TYPE_CDECL: ParseExportFunction( odp ); diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 413c1411739..f685a001ffc 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -149,6 +149,7 @@ static void output_exports( FILE *outfile, int nr_exports, int nr_names, int fwd fprintf( outfile, "%s", odp->u.ext.link_name ); break; case TYPE_STDCALL: + case TYPE_STDCALL64: case TYPE_VARARGS: case TYPE_CDECL: fprintf( outfile, "%s", odp->u.func.link_name); @@ -220,6 +221,7 @@ static void output_exports( FILE *outfile, int nr_exports, int nr_names, int fwd ORDDEF *odp = Ordinals[i]; if (odp && ((odp->type == TYPE_STDCALL) || + (odp->type == TYPE_STDCALL64) || (odp->type == TYPE_CDECL) || (odp->type == TYPE_REGISTER))) { @@ -232,6 +234,9 @@ static void output_exports( FILE *outfile, int nr_exports, int nr_names, int fwd switch(odp->type) { + case TYPE_STDCALL64: + if (j < 16) mask |= 0x80000000; + /* fall through */ case TYPE_STDCALL: fprintf( outfile, " { 0xe9, { 0,0,0,0 }, 0xc2, 0x%04x, %s, 0x%08x }", strlen(odp->u.func.arg_types) * sizeof(int), @@ -310,6 +315,7 @@ void BuildSpec32File( FILE *outfile ) fprintf( outfile, "extern void %s();\n", odp->u.ext.link_name ); break; case TYPE_STDCALL: + case TYPE_STDCALL64: case TYPE_VARARGS: case TYPE_CDECL: fprintf( outfile, "extern void %s();\n", odp->u.func.link_name );