lsteamclient: Reimplement alloc_callback_wtou(), convert_callback_utow() in manual code using generated table.

And try to handle the case of non-matching Windows callback length
similar to  before commit 6a5d5757ca2fbed232481f4e001114e7ba87560c.

CW-Bug-Id: #23550
This commit is contained in:
Paul Gofman
2024-03-20 19:52:21 -06:00
parent ce08f3ca53
commit 7e98577a74
4 changed files with 333 additions and 500 deletions
+19 -52
View File
@@ -1700,73 +1700,40 @@ with open('unixlib_generated.cpp', 'w') as file:
out(u'}\n')
out(u'\n')
out(u'void *alloc_callback_wtou(int id, void *callback, int *callback_len)\n')
out(u'{\n')
out(u' int len;\n')
out(u'\n')
out(u'#define MAKE_CASE(id, wlen) ((uint64_t)(id) << 48) | ((uint64_t)(wlen) << 24)\n')
out(u' switch (MAKE_CASE(id, *callback_len))\n')
out(u' {\n')
out(u'#ifdef __i386__\n')
values = set()
for cbid, sdkver, abis in sorted(callbacks, key=lambda x: x[0]):
name, value = abis["u32"].name, (cbid, abis["w32"].size)
if name in all_versions[sdkver]: name = all_versions[sdkver][name]
if value not in values:
out(f' case MAKE_CASE({cbid}, {abis["w32"].size}): len = {abis["u32"].size}; break; /* {name} */\n')
else:
out(f' /* case MAKE_CASE({cbid}, {abis["w32"].size}): len = {abis["u32"].size}; break; {name} */\n')
values.add(value)
out(u'#endif\n')
out(u'#ifdef __x86_64__\n')
values = set()
for cbid, sdkver, abis in sorted(callbacks, key=lambda x: x[0]):
name, value = abis["u64"].name, (cbid, abis["w64"].size)
if name in all_versions[sdkver]: name = all_versions[sdkver][name]
if value not in values:
out(f' case MAKE_CASE({cbid}, {abis["w64"].size}): len = {abis["u64"].size}; break; /* {name} */\n')
else:
out(f' /* case MAKE_CASE({cbid}, {abis["w64"].size}): len = {abis["u64"].size}; break; {name} */\n')
values.add(value)
out(u'#endif\n')
out(u' default: return callback;\n')
out(u' }\n')
out(u'#undef MAKE_CASE\n')
out(u'\n')
out(u' callback = malloc( len );\n')
out(u' *callback_len = len;\n')
out(u' return callback;\n')
out(u'}\n')
out(u'\n')
out(u'void convert_callback_utow(int id, void *u_callback, int u_callback_len, void *w_callback, int w_callback_len)\n')
out(u'{\n')
out(u'#define MAKE_CASE(id, wlen, ulen) ((uint64_t)(id) << 48) | ((uint64_t)(wlen) << 24) | (uint64_t)(ulen)\n')
out(u' switch (MAKE_CASE(id, w_callback_len, u_callback_len))\n')
out(u' {\n')
out(u'#ifdef __i386__\n')
out(u'const struct callback_def callback_data[] =\n{\n');
values = set()
for cbid, sdkver, abis in sorted(callbacks, key=lambda x: x[0]):
name, value = abis["u32"].name, (cbid, abis["w32"].size, abis["u32"].size)
if name in all_versions[sdkver]: name = all_versions[sdkver][name]
w_from_u = f'{name}_w_from_u'
if not w_from_u in written_converters:
w_from_u = u'nullptr'
if value not in values:
out(f' case MAKE_CASE({cbid}, {abis["w32"].size}, {abis["u32"].size}): *(w_{name} *)w_callback = *(u_{name} *)u_callback; break;\n')
out(f' {{ {cbid}, {sdkver}, {abis["w32"].size}, {abis["u32"].size}, {w_from_u} }},\n')
else:
out(f' /* case MAKE_CASE({cbid}, {abis["w32"].size}, {abis["u32"].size}): *(w_{name} *)w_callback = *(u_{name} *)u_callback; break; */\n')
out(f' /*{{ {cbid}, {sdkver}, {abis["w32"].size}, {abis["u32"].size}, {w_from_u} }},*/\n')
values.add(value)
out(u'};\n');
out(u'#endif\n')
out(u'#ifdef __x86_64__\n')
out(u'const struct callback_def callback_data[] =\n{\n');
values = set()
for cbid, sdkver, abis in sorted(callbacks, key=lambda x: x[0]):
name, value = abis["u64"].name, (cbid, abis["w64"].size, abis["u64"].size)
if name in all_versions[sdkver]: name = all_versions[sdkver][name]
w_from_u = f'{name}_w_from_u'
if not w_from_u in written_converters:
w_from_u = u'nullptr'
if value not in values:
out(f' case MAKE_CASE({cbid}, {abis["w64"].size}, {abis["u64"].size}): *(w_{name} *)w_callback = *(u_{name} *)u_callback; break;\n')
out(f' {{ {cbid}, {sdkver}, {abis["w64"].size}, {abis["u64"].size}, {w_from_u} }},\n')
else:
out(f' /* case MAKE_CASE({cbid}, {abis["w64"].size}, {abis["u64"].size}): *(w_{name} *)w_callback = *(u_{name} *)u_callback; break; */\n')
out(f' /*{{ {cbid}, {sdkver}, {abis["w64"].size}, {abis["u64"].size}, {w_from_u} }},*/\n')
values.add(value)
out(u'};\n');
out(u'#endif\n')
out(u' default: memcpy( w_callback, u_callback, u_callback_len ); break;\n')
out(u' }\n')
out(u'#undef MAKE_CASE\n')
out(u'}\n')
out(u'const unsigned int callback_data_size = ARRAY_SIZE(callback_data);\n');
+11
View File
@@ -57,6 +57,17 @@ typedef void (W_CDECL *w_void_SteamAPI_PostAPIResultInProcess_t)(void);
u_void_SteamAPI_PostAPIResultInProcess_t manual_convert_DEPRECATED_Set_SteamAPI_CPostAPIResultInProcess__a( w_void_SteamAPI_PostAPIResultInProcess_t );
u_void_SteamAPI_PostAPIResultInProcess_t manual_convert_DEPRECATED_Remove_SteamAPI_CPostAPIResultInProcess__a( w_void_SteamAPI_PostAPIResultInProcess_t );
struct callback_def
{
int id;
int sdkver;
int w_callback_len;
int u_callback_len;
void (*conv_w_from_u)(void *dst, const void *src);
};
extern const struct callback_def callback_data[];
extern const unsigned int callback_data_size;
void callback_message_utow( const u_CallbackMsg_t *u_msg, w_CallbackMsg_t *w_msg );
void *alloc_callback_wtou( int id, void *callback, int *callback_len );
void convert_callback_utow( int id, void *u_callback, int u_callback_len, void *w_callback, int w_callback_len );
+87
View File
@@ -648,3 +648,90 @@ unsigned int steamclient_unix_path_to_dos_path( bool api_result, const char *src
return r;
}
static const struct callback_def *find_first_callback_def_by_id( int id )
{
unsigned int l, r, m;
l = 0;
r = callback_data_size;
while (l < r)
{
m = (l + r) /2;
if (callback_data[m].id == id)
{
while (m && callback_data[m - 1].id == id) --m;
return &callback_data[m];
}
if (id < callback_data[m].id) r = m;
else l = m + 1;
}
return NULL;
}
void *alloc_callback_wtou( int id, void *callback, int *callback_len )
{
const struct callback_def *c, *end, *best;
if (!(c = find_first_callback_def_by_id( id ))) return callback;
end = callback_data + callback_data_size;
best = NULL;
while (c != end && c->id == id)
{
if (c->w_callback_len == *callback_len)
{
best = c;
break;
}
if (!best && *callback_len >= c->w_callback_len) best = c;
++c;
}
if (!best)
{
WARN( "len %d is too small for callback %d.\n", *callback_len, id );
return callback;
}
if (best->w_callback_len != *callback_len)
WARN( "Found len %d for id %d, len %d.\n", best->w_callback_len, id, *callback_len );
*callback_len = best->u_callback_len;
return malloc( *callback_len );
}
void convert_callback_utow(int id, void *u_callback, int u_callback_len, void *w_callback, int w_callback_len)
{
const struct callback_def *c, *end, *best;
if (!(c = find_first_callback_def_by_id( id )))
{
memcpy( w_callback, u_callback, u_callback_len );
return;
}
end = callback_data + callback_data_size;
best = NULL;
while (c != end && c->id == id)
{
if (c->w_callback_len == w_callback_len && c->u_callback_len == u_callback_len)
{
best = c;
break;
}
if (!best && c->u_callback_len == u_callback_len && c->w_callback_len <= w_callback_len)
best = c;
++c;
}
if (!best)
{
ERR( "Could not find id %d, u_callback_len %d, w_callback_len %d.\n", id, u_callback_len, w_callback_len );
memcpy( w_callback, u_callback, std::min(w_callback_len, u_callback_len) );
return;
}
if (best->w_callback_len != w_callback_len || best->u_callback_len != u_callback_len)
WARN( "Found len %d, %d for id %d, len %d, %d.\n", best->w_callback_len, best->u_callback_len,
id, w_callback_len, u_callback_len );
if (best->conv_w_from_u) best->conv_w_from_u( w_callback, u_callback );
else memcpy( w_callback, u_callback, u_callback_len );
}
File diff suppressed because it is too large Load Diff