opengl32: Implement wow64 thunk for glGetString (et al.).

This is a bit tricky because the strings are supposed to be static, but
we also cannot return the unix strings directly either.

So instead we keep track, on the unix side, of known unix / wow64 string
associations, and return the known wow64 string if the unix string was
already requested before.

If the string wasn't found, the syscall returns STATUS_BUFFER_TOO_SMALL,
and the PE side allocates the required memory, calling the syscall once
again with the wow64 string pointer to copy the string to.

On concurrent calls, the syscall may return a different wow64 string, in
which case the PE side uses it instead and frees the one it allocated.

Lastly, the PE side also keeps record of wow64 strings it had allocated,
so that we can free them on process detach. The unix side also does some
cleanup of its mapping buffer, as there's no guarantee that it will be
completely unloaded.
This commit is contained in:
Rémi Bernon 2022-11-18 07:22:14 +01:00 committed by Alexandre Julliard
parent 66f6cc5965
commit 17abb6f4e7
6 changed files with 436 additions and 153 deletions

View file

@ -162,9 +162,15 @@ my %manual_win_functions =
);
my %manual_win_thunks =
(
"glGetString" => 1,
"glGetStringi" => 1,
"wglGetCurrentReadDCARB" => 1,
"wglGetExtensionsStringARB" => 1,
"wglGetExtensionsStringEXT" => 1,
"wglGetPixelFormat" => 1,
"wglGetProcAddress" => 1,
"wglQueryCurrentRendererStringWINE" => 1,
"wglQueryRendererStringWINE" => 1,
"wglSwapBuffers" => 1,
);
my %manual_wow64_thunks =
@ -172,6 +178,8 @@ my %manual_wow64_thunks =
"glClientWaitSync" => 1,
"glDeleteSync" => 1,
"glFenceSync" => 1,
"glGetString" => 1,
"glGetStringi" => 1,
"glGetSynciv" => 1,
"glIsSync" => 1,
"glPathGlyphIndexRangeNV" => 1,
@ -180,10 +188,15 @@ my %manual_wow64_thunks =
"wglCreateContextAttribsARB" => 1,
"wglCreatePbufferARB" => 1,
"wglDeleteContext" => 1,
"wglGetExtensionsStringARB" => 1,
"wglGetExtensionsStringEXT" => 1,
"wglGetPbufferDCARB" => 1,
"wglGetProcAddress" => 1,
"wglGetProcAddress" => 1,
"wglMakeContextCurrentARB" => 1,
"wglMakeCurrent" => 1,
"wglQueryCurrentRendererStringWINE" => 1,
"wglQueryRendererStringWINE" => 1,
);
my %pointer_array_count =
(
@ -967,6 +980,7 @@ foreach (sort keys %ext_functions)
print OUT "enum unix_funcs\n";
print OUT "{\n";
print OUT " unix_thread_attach,\n";
print OUT " unix_process_detach,\n";
foreach (sort keys %wgl_functions)
{
next if defined $manual_win_functions{$_};
@ -1090,6 +1104,7 @@ print OUT "WINE_DEFAULT_DEBUG_CHANNEL(wgl);\n";
print OUT "#endif\n\n";
print OUT "extern NTSTATUS thread_attach( void *args ) DECLSPEC_HIDDEN;\n";
print OUT "extern NTSTATUS process_detach( void *args ) DECLSPEC_HIDDEN;\n";
foreach (sort keys %wgl_functions)
{
next if defined $manual_win_functions{$_};
@ -1135,6 +1150,7 @@ foreach (sort keys %ext_functions)
print OUT "const unixlib_entry_t __wine_unix_call_funcs[] =\n";
print OUT "{\n";
print OUT " &thread_attach,\n";
print OUT " &process_detach,\n";
foreach (sort keys %wgl_functions)
{
next if defined $manual_win_functions{$_};
@ -1155,6 +1171,7 @@ print OUT "\n";
print OUT "#ifdef _WIN64\n\n";
print OUT "typedef ULONG PTR32;\n\n";
print OUT "extern NTSTATUS wow64_process_detach( void *args ) DECLSPEC_HIDDEN;\n";
foreach (sort keys %wgl_functions)
{
next if defined $manual_win_functions{$_};
@ -1196,6 +1213,7 @@ foreach (sort keys %ext_functions)
print OUT "\nconst unixlib_entry_t __wine_unix_call_wow64_funcs[] =\n";
print OUT "{\n";
print OUT " &thread_attach,\n";
print OUT " &wow64_process_detach,\n";
foreach (sort keys %wgl_functions)
{
next if defined $manual_win_functions{$_};

View file

@ -1018,15 +1018,6 @@ void WINAPI glGetPolygonStipple( GLubyte *mask )
if ((status = UNIX_CALL( glGetPolygonStipple, &args ))) WARN( "glGetPolygonStipple returned %#lx\n", status );
}
const GLubyte * WINAPI glGetString( GLenum name )
{
struct glGetString_params args = { .name = name, };
NTSTATUS status;
TRACE( "name %d\n", name );
if ((status = UNIX_CALL( glGetString, &args ))) WARN( "glGetString returned %#lx\n", status );
return args.ret;
}
void WINAPI glGetTexEnvfv( GLenum target, GLenum pname, GLfloat *params )
{
struct glGetTexEnvfv_params args = { .target = target, .pname = pname, .params = params, };
@ -9914,15 +9905,6 @@ static GLushort WINAPI glGetStageIndexNV( GLenum shadertype )
return args.ret;
}
static const GLubyte * WINAPI glGetStringi( GLenum name, GLuint index )
{
struct glGetStringi_params args = { .name = name, .index = index, };
NTSTATUS status;
TRACE( "name %d, index %d\n", name, index );
if ((status = UNIX_CALL( glGetStringi, &args ))) WARN( "glGetStringi returned %#lx\n", status );
return args.ret;
}
static GLuint WINAPI glGetSubroutineIndex( GLuint program, GLenum shadertype, const GLchar *name )
{
struct glGetSubroutineIndex_params args = { .program = program, .shadertype = shadertype, .name = name, };
@ -24334,24 +24316,6 @@ static void WINAPI wglFreeMemoryNV( void *pointer )
if ((status = UNIX_CALL( wglFreeMemoryNV, &args ))) WARN( "wglFreeMemoryNV returned %#lx\n", status );
}
static const char * WINAPI wglGetExtensionsStringARB( HDC hdc )
{
struct wglGetExtensionsStringARB_params args = { .hdc = hdc, };
NTSTATUS status;
TRACE( "hdc %p\n", hdc );
if ((status = UNIX_CALL( wglGetExtensionsStringARB, &args ))) WARN( "wglGetExtensionsStringARB returned %#lx\n", status );
return args.ret;
}
static const char * WINAPI wglGetExtensionsStringEXT(void)
{
struct wglGetExtensionsStringEXT_params args = {0};
NTSTATUS status;
TRACE( "\n" );
if ((status = UNIX_CALL( wglGetExtensionsStringEXT, &args ))) WARN( "wglGetExtensionsStringEXT returned %#lx\n", status );
return args.ret;
}
static HDC WINAPI wglGetPbufferDCARB( HPBUFFERARB hPbuffer )
{
struct wglGetPbufferDCARB_params args = { .hPbuffer = hPbuffer, };
@ -24406,15 +24370,6 @@ static BOOL WINAPI wglQueryCurrentRendererIntegerWINE( GLenum attribute, GLuint
return args.ret;
}
static const GLchar * WINAPI wglQueryCurrentRendererStringWINE( GLenum attribute )
{
struct wglQueryCurrentRendererStringWINE_params args = { .attribute = attribute, };
NTSTATUS status;
TRACE( "attribute %d\n", attribute );
if ((status = UNIX_CALL( wglQueryCurrentRendererStringWINE, &args ))) WARN( "wglQueryCurrentRendererStringWINE returned %#lx\n", status );
return args.ret;
}
static BOOL WINAPI wglQueryPbufferARB( HPBUFFERARB hPbuffer, int iAttribute, int *piValue )
{
struct wglQueryPbufferARB_params args = { .hPbuffer = hPbuffer, .iAttribute = iAttribute, .piValue = piValue, };
@ -24433,15 +24388,6 @@ static BOOL WINAPI wglQueryRendererIntegerWINE( HDC dc, GLint renderer, GLenum a
return args.ret;
}
static const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute )
{
struct wglQueryRendererStringWINE_params args = { .dc = dc, .renderer = renderer, .attribute = attribute, };
NTSTATUS status;
TRACE( "dc %p, renderer %d, attribute %d\n", dc, renderer, attribute );
if ((status = UNIX_CALL( wglQueryRendererStringWINE, &args ))) WARN( "wglQueryRendererStringWINE returned %#lx\n", status );
return args.ret;
}
static int WINAPI wglReleasePbufferDCARB( HPBUFFERARB hPbuffer, HDC hDC )
{
struct wglReleasePbufferDCARB_params args = { .hPbuffer = hPbuffer, .hDC = hDC, };
@ -24487,7 +24433,12 @@ static BOOL WINAPI wglSwapIntervalEXT( int interval )
return args.ret;
}
extern const GLubyte * WINAPI glGetStringi( GLenum name, GLuint index ) DECLSPEC_HIDDEN;
extern HDC WINAPI wglGetCurrentReadDCARB(void) DECLSPEC_HIDDEN;
extern const char * WINAPI wglGetExtensionsStringARB( HDC hdc ) DECLSPEC_HIDDEN;
extern const char * WINAPI wglGetExtensionsStringEXT(void) DECLSPEC_HIDDEN;
extern const GLchar * WINAPI wglQueryCurrentRendererStringWINE( GLenum attribute ) DECLSPEC_HIDDEN;
extern const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute ) DECLSPEC_HIDDEN;
const void *extension_procs[] =
{
glAccumxOES,

View file

@ -23,6 +23,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(wgl);
#endif
extern NTSTATUS thread_attach( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS process_detach( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wgl_wglCopyContext( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wgl_wglCreateContext( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wgl_wglDeleteContext( void *args ) DECLSPEC_HIDDEN;
@ -24058,7 +24059,7 @@ static NTSTATUS ext_wglGetCurrentReadDCARB( void *args )
return STATUS_SUCCESS;
}
static NTSTATUS ext_wglGetExtensionsStringARB( void *args )
NTSTATUS ext_wglGetExtensionsStringARB( void *args )
{
struct wglGetExtensionsStringARB_params *params = args;
const struct opengl_funcs *funcs = get_dc_funcs( params->hdc );
@ -24067,7 +24068,7 @@ static NTSTATUS ext_wglGetExtensionsStringARB( void *args )
return STATUS_SUCCESS;
}
static NTSTATUS ext_wglGetExtensionsStringEXT( void *args )
NTSTATUS ext_wglGetExtensionsStringEXT( void *args )
{
struct wglGetExtensionsStringEXT_params *params = args;
const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
@ -24109,7 +24110,7 @@ static NTSTATUS ext_wglQueryCurrentRendererIntegerWINE( void *args )
return STATUS_SUCCESS;
}
static NTSTATUS ext_wglQueryCurrentRendererStringWINE( void *args )
NTSTATUS ext_wglQueryCurrentRendererStringWINE( void *args )
{
struct wglQueryCurrentRendererStringWINE_params *params = args;
const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;
@ -24126,7 +24127,7 @@ static NTSTATUS ext_wglQueryRendererIntegerWINE( void *args )
return STATUS_SUCCESS;
}
static NTSTATUS ext_wglQueryRendererStringWINE( void *args )
NTSTATUS ext_wglQueryRendererStringWINE( void *args )
{
struct wglQueryRendererStringWINE_params *params = args;
const struct opengl_funcs *funcs = get_dc_funcs( params->dc );
@ -24155,6 +24156,7 @@ static NTSTATUS ext_wglSwapIntervalEXT( void *args )
const unixlib_entry_t __wine_unix_call_funcs[] =
{
&thread_attach,
&process_detach,
&wgl_wglCopyContext,
&wgl_wglCreateContext,
&wgl_wglDeleteContext,
@ -27201,6 +27203,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
typedef ULONG PTR32;
extern NTSTATUS wow64_process_detach( void *args ) DECLSPEC_HIDDEN;
static NTSTATUS wow64_wgl_wglCopyContext( void *args )
{
struct
@ -28186,21 +28189,6 @@ static NTSTATUS wow64_gl_glGetPolygonStipple( void *args )
return status;
}
static NTSTATUS wow64_gl_glGetString( void *args )
{
struct
{
GLenum name;
PTR32 ret;
} *params32 = args;
struct glGetString_params params =
{
.name = params32->name,
};
FIXME( "params32 %p, params %p stub!\n", params32, &params );
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS wow64_gl_glGetTexEnvfv( void *args )
{
struct
@ -41037,23 +41025,6 @@ static NTSTATUS wow64_ext_glGetSharpenTexFuncSGIS( void *args )
return status;
}
static NTSTATUS wow64_ext_glGetStringi( void *args )
{
struct
{
GLenum name;
GLuint index;
PTR32 ret;
} *params32 = args;
struct glGetStringi_params params =
{
.name = params32->name,
.index = params32->index,
};
FIXME( "params32 %p, params %p stub!\n", params32, &params );
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS wow64_ext_glGetSubroutineIndex( void *args )
{
struct
@ -60631,34 +60602,6 @@ static NTSTATUS wow64_ext_wglGetCurrentReadDCARB( void *args )
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS wow64_ext_wglGetExtensionsStringARB( void *args )
{
struct
{
PTR32 hdc;
PTR32 ret;
} *params32 = args;
struct wglGetExtensionsStringARB_params params =
{
.hdc = ULongToPtr(params32->hdc),
};
FIXME( "params32 %p, params %p stub!\n", params32, &params );
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS wow64_ext_wglGetExtensionsStringEXT( void *args )
{
struct
{
PTR32 ret;
} *params32 = args;
struct wglGetExtensionsStringEXT_params params =
{
};
FIXME( "params32 %p, params %p stub!\n", params32, &params );
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS wow64_ext_wglGetPixelFormatAttribfvARB( void *args )
{
struct
@ -60732,21 +60675,6 @@ static NTSTATUS wow64_ext_wglQueryCurrentRendererIntegerWINE( void *args )
return status;
}
static NTSTATUS wow64_ext_wglQueryCurrentRendererStringWINE( void *args )
{
struct
{
GLenum attribute;
PTR32 ret;
} *params32 = args;
struct wglQueryCurrentRendererStringWINE_params params =
{
.attribute = params32->attribute,
};
FIXME( "params32 %p, params %p stub!\n", params32, &params );
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS wow64_ext_wglQueryPbufferARB( void *args )
{
struct
@ -60791,25 +60719,6 @@ static NTSTATUS wow64_ext_wglQueryRendererIntegerWINE( void *args )
return status;
}
static NTSTATUS wow64_ext_wglQueryRendererStringWINE( void *args )
{
struct
{
PTR32 dc;
GLint renderer;
GLenum attribute;
PTR32 ret;
} *params32 = args;
struct wglQueryRendererStringWINE_params params =
{
.dc = ULongToPtr(params32->dc),
.renderer = params32->renderer,
.attribute = params32->attribute,
};
FIXME( "params32 %p, params %p stub!\n", params32, &params );
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS wow64_ext_wglReleasePbufferDCARB( void *args )
{
struct
@ -60890,21 +60799,28 @@ extern NTSTATUS wow64_wgl_wglCreateContext( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_wgl_wglDeleteContext( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_wgl_wglGetProcAddress( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_wgl_wglMakeCurrent( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_gl_glGetString( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_glClientWaitSync( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_glDeleteSync( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_glFenceSync( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_glGetStringi( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_glGetSynciv( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_glIsSync( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_glPathGlyphIndexRangeNV( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_glWaitSync( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_wglCreateContextAttribsARB( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_wglCreatePbufferARB( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_wglGetExtensionsStringARB( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_wglGetExtensionsStringEXT( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_wglGetPbufferDCARB( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_wglMakeContextCurrentARB( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_wglQueryCurrentRendererStringWINE( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS wow64_ext_wglQueryRendererStringWINE( void *args ) DECLSPEC_HIDDEN;
const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
{
&thread_attach,
&wow64_process_detach,
&wow64_wgl_wglCopyContext,
&wow64_wgl_wglCreateContext,
&wow64_wgl_wglDeleteContext,

View file

@ -1055,6 +1055,11 @@ NTSTATUS WINAPI thread_attach( void *args )
return STATUS_SUCCESS;
}
NTSTATUS WINAPI process_detach( void *args )
{
return STATUS_SUCCESS;
}
#ifdef _WIN64
typedef ULONG PTR32;
@ -1066,6 +1071,47 @@ extern NTSTATUS ext_glGetSynciv( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS ext_glIsSync( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS ext_glPathGlyphIndexRangeNV( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS ext_glWaitSync( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS ext_wglGetExtensionsStringARB( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS ext_wglGetExtensionsStringEXT( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS ext_wglQueryCurrentRendererStringWINE( void *args ) DECLSPEC_HIDDEN;
extern NTSTATUS ext_wglQueryRendererStringWINE( void *args ) DECLSPEC_HIDDEN;
struct wow64_string_entry
{
const char *str;
PTR32 wow64_str;
};
static struct wow64_string_entry *wow64_strings;
static SIZE_T wow64_strings_count;
static PTR32 find_wow64_string( const char *str, PTR32 wow64_str )
{
void *tmp;
SIZE_T i;
pthread_mutex_lock( &wgl_lock );
for (i = 0; i < wow64_strings_count; i++) if (wow64_strings[i].str == str) break;
if (i == wow64_strings_count && (tmp = realloc( wow64_strings, (i + 1) * sizeof(*wow64_strings) )))
{
wow64_strings = tmp;
wow64_strings[i].str = str;
wow64_strings[i].wow64_str = 0;
wow64_strings_count += 1;
}
if (i == wow64_strings_count) ERR( "Failed to allocate memory for wow64 strings\n" );
else if (wow64_strings[i].wow64_str) wow64_str = wow64_strings[i].wow64_str;
else if (wow64_str)
{
strcpy( UlongToPtr(wow64_str), (char *)str );
wow64_strings[i].wow64_str = wow64_str;
}
pthread_mutex_unlock( &wgl_lock );
return wow64_str;
}
static inline void update_teb32_context(void)
{
@ -1234,6 +1280,56 @@ NTSTATUS wow64_wgl_wglGetProcAddress( void *args )
return STATUS_SUCCESS;
}
NTSTATUS wow64_gl_glGetString( void *args )
{
struct
{
GLenum name;
PTR32 ret;
} *params32 = args;
struct glGetString_params params =
{
.name = params32->name,
};
NTSTATUS status;
if ((status = gl_glGetString( &params ))) return status;
if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
{
params32->ret = strlen( (char *)params.ret ) + 1;
return STATUS_BUFFER_TOO_SMALL;
}
return STATUS_SUCCESS;
}
NTSTATUS wow64_ext_glGetStringi( void *args )
{
struct
{
GLenum name;
GLuint index;
PTR32 ret;
} *params32 = args;
struct glGetStringi_params params =
{
.name = params32->name,
.index = params32->index,
};
NTSTATUS status;
if ((status = ext_glGetStringi( &params ))) return status;
if (!(params32->ret = find_wow64_string( (char *)params.ret, params32->ret )))
{
params32->ret = strlen( (char *)params.ret ) + 1;
return STATUS_BUFFER_TOO_SMALL;
}
return STATUS_SUCCESS;
}
NTSTATUS wow64_ext_glPathGlyphIndexRangeNV( void *args )
{
struct
@ -1261,6 +1357,104 @@ NTSTATUS wow64_ext_glPathGlyphIndexRangeNV( void *args )
return status;
}
NTSTATUS wow64_ext_wglGetExtensionsStringARB( void *args )
{
struct
{
PTR32 hdc;
PTR32 ret;
} *params32 = args;
struct wglGetExtensionsStringARB_params params =
{
.hdc = ULongToPtr(params32->hdc),
};
NTSTATUS status;
if ((status = ext_wglGetExtensionsStringARB( &params ))) return status;
if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
{
params32->ret = strlen( params.ret ) + 1;
return STATUS_BUFFER_TOO_SMALL;
}
return STATUS_SUCCESS;
}
NTSTATUS wow64_ext_wglGetExtensionsStringEXT( void *args )
{
struct
{
PTR32 ret;
} *params32 = args;
struct wglGetExtensionsStringEXT_params params =
{
};
NTSTATUS status;
if ((status = ext_wglGetExtensionsStringEXT( &params ))) return status;
if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
{
params32->ret = strlen( params.ret ) + 1;
return STATUS_BUFFER_TOO_SMALL;
}
return STATUS_SUCCESS;
}
NTSTATUS wow64_ext_wglQueryCurrentRendererStringWINE( void *args )
{
struct
{
GLenum attribute;
PTR32 ret;
} *params32 = args;
struct wglQueryCurrentRendererStringWINE_params params =
{
.attribute = params32->attribute,
};
NTSTATUS status;
if ((status = ext_wglQueryCurrentRendererStringWINE( &params ))) return status;
if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
{
params32->ret = strlen( params.ret ) + 1;
return STATUS_BUFFER_TOO_SMALL;
}
return STATUS_SUCCESS;
}
NTSTATUS wow64_ext_wglQueryRendererStringWINE( void *args )
{
struct
{
PTR32 dc;
GLint renderer;
GLenum attribute;
PTR32 ret;
} *params32 = args;
struct wglQueryRendererStringWINE_params params =
{
.dc = ULongToPtr(params32->dc),
.renderer = params32->renderer,
.attribute = params32->attribute,
};
NTSTATUS status;
if ((status = ext_wglQueryRendererStringWINE( &params ))) return status;
if (!(params32->ret = find_wow64_string( params.ret, params32->ret )))
{
params32->ret = strlen( params.ret ) + 1;
return STATUS_BUFFER_TOO_SMALL;
}
return STATUS_SUCCESS;
}
NTSTATUS wow64_ext_glClientWaitSync( void *args )
{
struct wgl_handle *handle;
@ -1446,4 +1640,17 @@ NTSTATUS wow64_ext_glWaitSync( void *args )
return status;
}
NTSTATUS WINAPI wow64_process_detach( void *args )
{
NTSTATUS status;
if ((status = process_detach( NULL ))) return status;
free( wow64_strings );
wow64_strings = NULL;
wow64_strings_count = 0;
return STATUS_SUCCESS;
}
#endif

View file

@ -22294,6 +22294,7 @@ struct wglSwapIntervalEXT_params
enum unix_funcs
{
unix_thread_attach,
unix_process_detach,
unix_wglCopyContext,
unix_wglCreateContext,
unix_wglDeleteContext,

View file

@ -38,10 +38,50 @@
WINE_DEFAULT_DEBUG_CHANNEL(wgl);
WINE_DECLARE_DEBUG_CHANNEL(fps);
unixlib_handle_t unixlib_handle;
unixlib_handle_t unixlib_handle = 0;
static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
#ifndef _WIN64
static char **wow64_strings;
static SIZE_T wow64_strings_count;
static CRITICAL_SECTION wow64_cs;
static CRITICAL_SECTION_DEBUG wow64_cs_debug =
{
0, 0, &wow64_cs,
{ &wow64_cs_debug.ProcessLocksList, &wow64_cs_debug.ProcessLocksList },
0, 0, { (DWORD_PTR)(__FILE__ ": wow64_cs") }
};
static CRITICAL_SECTION wow64_cs = { &wow64_cs_debug, -1, 0, 0, 0, 0 };
static void append_wow64_string( char *str )
{
char **tmp;
EnterCriticalSection( &wow64_cs );
if (!(tmp = realloc( wow64_strings, (wow64_strings_count + 1) * sizeof(*wow64_strings) )))
ERR( "Failed to allocate memory for wow64 strings\n" );
else
{
wow64_strings = tmp;
wow64_strings[wow64_strings_count] = str;
wow64_strings_count += 1;
}
LeaveCriticalSection( &wow64_cs );
}
static void cleanup_wow64_strings(void)
{
while (wow64_strings_count--) free( wow64_strings[wow64_strings_count] );
free( wow64_strings );
}
#endif
/***********************************************************************
* wglGetCurrentReadDCARB
*
@ -858,6 +898,144 @@ GLint WINAPI glDebugEntry( GLint unknown1, GLint unknown2 )
return 0;
}
const GLubyte * WINAPI glGetStringi( GLenum name, GLuint index )
{
struct glGetStringi_params args =
{
.name = name,
.index = index,
};
NTSTATUS status;
#ifndef _WIN64
GLubyte *wow64_str = NULL;
#endif
TRACE( "name %d, index %d\n", name, index );
#ifndef _WIN64
if (UNIX_CALL( glGetStringi, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
#endif
if ((status = UNIX_CALL( glGetStringi, &args ))) WARN( "glGetStringi returned %#lx\n", status );
#ifndef _WIN64
if (args.ret != wow64_str) free( wow64_str );
else if (args.ret) append_wow64_string( (char *)args.ret );
#endif
return args.ret;
}
/***********************************************************************
* glGetString (OPENGL32.@)
*/
const GLubyte * WINAPI glGetString( GLenum name )
{
struct glGetString_params args = { .name = name, };
NTSTATUS status;
#ifndef _WIN64
GLubyte *wow64_str = NULL;
#endif
TRACE( "name %d\n", name );
#ifndef _WIN64
if (UNIX_CALL( glGetString, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
#endif
if ((status = UNIX_CALL( glGetString, &args ))) WARN( "glGetString returned %#lx\n", status );
#ifndef _WIN64
if (args.ret != wow64_str) free( wow64_str );
else if (args.ret) append_wow64_string( (char *)args.ret );
#endif
return args.ret;
}
const char * WINAPI wglGetExtensionsStringARB( HDC hdc )
{
struct wglGetExtensionsStringARB_params args = { .hdc = hdc, };
NTSTATUS status;
#ifndef _WIN64
char *wow64_str = NULL;
#endif
TRACE( "hdc %p\n", hdc );
#ifndef _WIN64
if (UNIX_CALL( wglGetExtensionsStringARB, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
#endif
if ((status = UNIX_CALL( wglGetExtensionsStringARB, &args ))) WARN( "wglGetExtensionsStringARB returned %#lx\n", status );
#ifndef _WIN64
if (args.ret != wow64_str) free( wow64_str );
else if (args.ret) append_wow64_string( wow64_str );
#endif
return args.ret;
}
const char * WINAPI wglGetExtensionsStringEXT(void)
{
struct wglGetExtensionsStringEXT_params args = {0};
NTSTATUS status;
#ifndef _WIN64
char *wow64_str = NULL;
#endif
TRACE( "\n" );
#ifndef _WIN64
if (UNIX_CALL( wglGetExtensionsStringEXT, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
#endif
if ((status = UNIX_CALL( wglGetExtensionsStringEXT, &args ))) WARN( "wglGetExtensionsStringEXT returned %#lx\n", status );
#ifndef _WIN64
if (args.ret != wow64_str) free( wow64_str );
else if (args.ret) append_wow64_string( wow64_str );
#endif
return args.ret;
}
const GLchar * WINAPI wglQueryCurrentRendererStringWINE( GLenum attribute )
{
struct wglQueryCurrentRendererStringWINE_params args = { .attribute = attribute, };
NTSTATUS status;
#ifndef _WIN64
char *wow64_str = NULL;
#endif
TRACE( "attribute %d\n", attribute );
#ifndef _WIN64
if (UNIX_CALL( wglQueryCurrentRendererStringWINE, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
#endif
if ((status = UNIX_CALL( wglQueryCurrentRendererStringWINE, &args ))) WARN( "wglQueryCurrentRendererStringWINE returned %#lx\n", status );
#ifndef _WIN64
if (args.ret != wow64_str) free( wow64_str );
else if (args.ret) append_wow64_string( wow64_str );
#endif
return args.ret;
}
const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute )
{
struct wglQueryRendererStringWINE_params args =
{
.dc = dc,
.renderer = renderer,
.attribute = attribute,
};
NTSTATUS status;
#ifndef _WIN64
char *wow64_str = NULL;
#endif
TRACE( "dc %p, renderer %d, attribute %d\n", dc, renderer, attribute );
#ifndef _WIN64
if (UNIX_CALL( wglQueryCurrentRendererStringWINE, &args ) == STATUS_BUFFER_TOO_SMALL) args.ret = wow64_str = malloc( (size_t)args.ret );
#endif
if ((status = UNIX_CALL( wglQueryRendererStringWINE, &args ))) WARN( "wglQueryRendererStringWINE returned %#lx\n", status );
#ifndef _WIN64
if (args.ret != wow64_str) free( wow64_str );
else if (args.ret) append_wow64_string( wow64_str );
#endif
return args.ret;
}
static BOOL WINAPI call_opengl_debug_message_callback( struct wine_gl_debug_message_params *params, ULONG size )
{
params->user_callback( params->source, params->type, params->id, params->severity,
@ -893,6 +1071,18 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
if (!unixlib_handle) return TRUE;
if ((status = UNIX_CALL( process_detach, NULL )))
{
WARN( "Failed to detach opengl32 unixlib, status %#lx\n", status );
return FALSE;
}
#ifndef _WIN64
cleanup_wow64_strings();
#endif
return TRUE;
}
return TRUE;
}