mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 17:47:16 +00:00
win32u: Convert inter-process messages to Unicode.
Based on user32 WINPROC_CallProcWtoA. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53744
This commit is contained in:
parent
2b0cd25b5f
commit
d222dcc2a4
|
@ -3619,6 +3619,60 @@ CPTABLEINFO *get_cptable( WORD cp )
|
|||
return &tables[i];
|
||||
}
|
||||
|
||||
/* Based on NlsValidateLocale */
|
||||
const NLS_LOCALE_DATA *get_locale_data( LCID lcid )
|
||||
{
|
||||
static const NLS_LOCALE_HEADER *locale_table;
|
||||
static const NLS_LOCALE_LCID_INDEX *lcids_index;
|
||||
int min = 0, max;
|
||||
|
||||
if (!locale_table)
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
void *addr;
|
||||
LCID lcid;
|
||||
NTSTATUS status;
|
||||
static struct
|
||||
{
|
||||
UINT ctypes;
|
||||
UINT unknown1;
|
||||
UINT unknown2;
|
||||
UINT unknown3;
|
||||
UINT locales;
|
||||
UINT charmaps;
|
||||
UINT geoids;
|
||||
UINT scripts;
|
||||
} *header;
|
||||
|
||||
status = NtInitializeNlsFiles( &addr, &lcid, &size );
|
||||
if (status)
|
||||
{
|
||||
ERR( "Failed to load nls file\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (InterlockedCompareExchangePointer( (void **)&header, addr, NULL ))
|
||||
NtUnmapViewOfSection( GetCurrentProcess(), addr );
|
||||
|
||||
locale_table = (const NLS_LOCALE_HEADER *)((char *)header + header->locales);
|
||||
lcids_index = (const NLS_LOCALE_LCID_INDEX *)((char *)locale_table + locale_table->lcids_offset);
|
||||
}
|
||||
|
||||
max = locale_table->nb_lcids - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int pos = (min + max) / 2;
|
||||
if (lcid < lcids_index[pos].id) max = pos - 1;
|
||||
else if (lcid > lcids_index[pos].id) min = pos + 1;
|
||||
else
|
||||
{
|
||||
ULONG offset = locale_table->locales_offset + pos * locale_table->locale_size;
|
||||
return (const NLS_LOCALE_DATA *)((const char *)locale_table + offset);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DWORD win32u_wctomb( CPTABLEINFO *info, char *dst, DWORD dstlen, const WCHAR *src, DWORD srclen )
|
||||
{
|
||||
DWORD ret;
|
||||
|
@ -3665,6 +3719,34 @@ DWORD win32u_mbtowc( CPTABLEINFO *info, WCHAR *dst, DWORD dstlen, const char *sr
|
|||
return ret / sizeof(WCHAR);
|
||||
}
|
||||
|
||||
DWORD win32u_mbtowc_size( CPTABLEINFO *info, const char *src, DWORD srclen )
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
if (info->CodePage == CP_UTF8)
|
||||
{
|
||||
RtlUTF8ToUnicodeN( NULL, 0, &ret, src, srclen );
|
||||
ret /= sizeof(WCHAR);
|
||||
}
|
||||
else if (info->DBCSCodePage)
|
||||
{
|
||||
for (ret = 0; srclen; srclen--, src++, ret++)
|
||||
{
|
||||
if (info->DBCSOffsets[(unsigned char)*src] && srclen > 1)
|
||||
{
|
||||
src++;
|
||||
srclen--;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = srclen;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL wc_to_index( UINT cp, WCHAR wc, unsigned char *dst, BOOL allow_default )
|
||||
{
|
||||
const CPTABLEINFO *info;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#define WIN32_NO_STATUS
|
||||
#include "win32u_private.h"
|
||||
#include "ntuser_private.h"
|
||||
#include "winnls.h"
|
||||
#include "hidusage.h"
|
||||
#include "dbt.h"
|
||||
#include "dde.h"
|
||||
|
@ -2521,6 +2522,17 @@ static LRESULT send_inter_thread_message( const struct send_message_info *info,
|
|||
return retrieve_reply( info, reply_size, res_ptr );
|
||||
}
|
||||
|
||||
static LRESULT send_inter_thread_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
|
||||
LRESULT *result, void *arg )
|
||||
{
|
||||
struct send_message_info *info = arg;
|
||||
info->hwnd = hwnd;
|
||||
info->msg = msg;
|
||||
info->wparam = wp;
|
||||
info->lparam = lp;
|
||||
return send_inter_thread_message( info, result );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* send_internal_message_timeout
|
||||
*
|
||||
|
@ -2835,6 +2847,268 @@ static BOOL process_packed_message( struct send_message_info *info, LRESULT *res
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static inline void *get_buffer( void *static_buffer, size_t size, size_t need )
|
||||
{
|
||||
if (size >= need) return static_buffer;
|
||||
return malloc( need );
|
||||
}
|
||||
|
||||
static inline void free_buffer( void *static_buffer, void *buffer )
|
||||
{
|
||||
if (buffer != static_buffer) free( buffer );
|
||||
}
|
||||
|
||||
typedef LRESULT (*winproc_callback_t)( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp,
|
||||
LRESULT *result, void *arg );
|
||||
|
||||
/**********************************************************************
|
||||
* test_lb_for_string
|
||||
*
|
||||
* Return TRUE if the lparam is a string
|
||||
*/
|
||||
static inline BOOL test_lb_for_string( HWND hwnd, UINT msg )
|
||||
{
|
||||
DWORD style = get_window_long( hwnd, GWL_STYLE );
|
||||
if (msg <= CB_MSGMAX)
|
||||
return (!(style & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE)) || (style & CBS_HASSTRINGS));
|
||||
else
|
||||
return (!(style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE)) || (style & LBS_HASSTRINGS));
|
||||
|
||||
}
|
||||
|
||||
static CPTABLEINFO *get_input_codepage( void )
|
||||
{
|
||||
const NLS_LOCALE_DATA *locale;
|
||||
HKL hkl = NtUserGetKeyboardLayout( 0 );
|
||||
CPTABLEINFO *ret = NULL;
|
||||
|
||||
locale = get_locale_data( LOWORD(hkl) );
|
||||
if (locale && locale->idefaultansicodepage != CP_UTF8)
|
||||
ret = get_cptable( locale->idefaultansicodepage );
|
||||
return ret ? ret : &ansi_cp;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* map_wparam_AtoW
|
||||
*
|
||||
* Convert the wparam of an ASCII message to Unicode.
|
||||
*/
|
||||
static BOOL map_wparam_AtoW( UINT message, WPARAM *wparam, enum wm_char_mapping mapping )
|
||||
{
|
||||
char ch[2];
|
||||
WCHAR wch[2];
|
||||
|
||||
wch[0] = wch[1] = 0;
|
||||
switch(message)
|
||||
{
|
||||
case WM_CHARTOITEM:
|
||||
case EM_SETPASSWORDCHAR:
|
||||
case WM_DEADCHAR:
|
||||
case WM_SYSCHAR:
|
||||
case WM_SYSDEADCHAR:
|
||||
case WM_MENUCHAR:
|
||||
ch[0] = LOBYTE(*wparam);
|
||||
ch[1] = HIBYTE(*wparam);
|
||||
win32u_mbtowc( get_input_codepage(), wch, 2, ch, 2 );
|
||||
*wparam = MAKEWPARAM(wch[0], wch[1]);
|
||||
break;
|
||||
|
||||
case WM_IME_CHAR:
|
||||
ch[0] = HIBYTE(*wparam);
|
||||
ch[1] = LOBYTE(*wparam);
|
||||
if (ch[0]) win32u_mbtowc( get_input_codepage(), wch, 2, ch, 2 );
|
||||
else win32u_mbtowc( get_input_codepage(), wch, 1, ch + 1, 1 );
|
||||
*wparam = MAKEWPARAM(wch[0], HIWORD(*wparam));
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* call_messageAtoW
|
||||
*
|
||||
* Call a window procedure, translating args from Ansi to Unicode.
|
||||
*/
|
||||
LRESULT call_messageAtoW( winproc_callback_t callback, HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam, LRESULT *result, void *arg, enum wm_char_mapping mapping )
|
||||
{
|
||||
LRESULT ret = 0;
|
||||
|
||||
TRACE( "(hwnd=%p,msg=%s,wp=%#lx,lp=%#lx)\n", hwnd, debugstr_msg_name( msg, hwnd ),
|
||||
(long)wparam, (long)lparam );
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case WM_MDICREATE:
|
||||
{
|
||||
WCHAR *ptr, buffer[512];
|
||||
DWORD title_lenA = 0, title_lenW = 0, class_lenA = 0, class_lenW = 0;
|
||||
MDICREATESTRUCTA *csA = (MDICREATESTRUCTA *)lparam;
|
||||
MDICREATESTRUCTW csW;
|
||||
|
||||
memcpy( &csW, csA, sizeof(csW) );
|
||||
|
||||
if (!IS_INTRESOURCE(csA->szTitle))
|
||||
{
|
||||
title_lenA = strlen(csA->szTitle) + 1;
|
||||
title_lenW = win32u_mbtowc_size( &ansi_cp, csA->szTitle, title_lenA );
|
||||
}
|
||||
if (!IS_INTRESOURCE(csA->szClass))
|
||||
{
|
||||
class_lenA = strlen(csA->szClass) + 1;
|
||||
class_lenW = win32u_mbtowc_size( &ansi_cp, csA->szClass, class_lenA );
|
||||
}
|
||||
|
||||
if (!(ptr = get_buffer( buffer, sizeof(buffer), (title_lenW + class_lenW) * sizeof(WCHAR) )))
|
||||
break;
|
||||
|
||||
if (title_lenW)
|
||||
{
|
||||
csW.szTitle = ptr;
|
||||
win32u_mbtowc( &ansi_cp, ptr, title_lenW, csA->szTitle, title_lenA );
|
||||
}
|
||||
if (class_lenW)
|
||||
{
|
||||
csW.szClass = ptr + title_lenW;
|
||||
win32u_mbtowc( &ansi_cp, ptr + title_lenW, class_lenW, csA->szClass, class_lenA );
|
||||
}
|
||||
ret = callback( hwnd, msg, wparam, (LPARAM)&csW, result, arg );
|
||||
free_buffer( buffer, ptr );
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_GETTEXT:
|
||||
case WM_ASKCBFORMATNAME:
|
||||
{
|
||||
WCHAR *ptr, buffer[512];
|
||||
LPSTR str = (LPSTR)lparam;
|
||||
DWORD len = wparam * sizeof(WCHAR);
|
||||
|
||||
if (!(ptr = get_buffer( buffer, sizeof(buffer), len ))) break;
|
||||
ret = callback( hwnd, msg, wparam, (LPARAM)ptr, result, arg );
|
||||
if (wparam)
|
||||
{
|
||||
len = 0;
|
||||
len = *result ? win32u_wctomb( &ansi_cp, str, wparam - 1, ptr, *result ) : 0;
|
||||
str[len] = 0;
|
||||
*result = len;
|
||||
}
|
||||
free_buffer( buffer, ptr );
|
||||
}
|
||||
break;
|
||||
|
||||
case LB_ADDSTRING:
|
||||
case LB_INSERTSTRING:
|
||||
case LB_FINDSTRING:
|
||||
case LB_FINDSTRINGEXACT:
|
||||
case LB_SELECTSTRING:
|
||||
case CB_ADDSTRING:
|
||||
case CB_INSERTSTRING:
|
||||
case CB_FINDSTRING:
|
||||
case CB_FINDSTRINGEXACT:
|
||||
case CB_SELECTSTRING:
|
||||
if (!lparam || !test_lb_for_string( hwnd, msg ))
|
||||
{
|
||||
ret = callback( hwnd, msg, wparam, lparam, result, arg );
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case WM_SETTEXT:
|
||||
case WM_WININICHANGE:
|
||||
case WM_DEVMODECHANGE:
|
||||
case CB_DIR:
|
||||
case LB_DIR:
|
||||
case LB_ADDFILE:
|
||||
case EM_REPLACESEL:
|
||||
if (!lparam)
|
||||
{
|
||||
ret = callback( hwnd, msg, wparam, lparam, result, arg );
|
||||
}
|
||||
else
|
||||
{
|
||||
WCHAR *ptr, buffer[512];
|
||||
LPCSTR strA = (LPCSTR)lparam;
|
||||
DWORD lenW, lenA = strlen(strA) + 1;
|
||||
|
||||
lenW = win32u_mbtowc_size( &ansi_cp, strA, lenA );
|
||||
if ((ptr = get_buffer( buffer, sizeof(buffer), lenW * sizeof(WCHAR) )))
|
||||
{
|
||||
win32u_mbtowc( &ansi_cp, ptr, lenW, strA, lenA );
|
||||
ret = callback( hwnd, msg, wparam, (LPARAM)ptr, result, arg );
|
||||
free_buffer( buffer, ptr );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EM_GETLINE:
|
||||
{
|
||||
WCHAR *ptr, buffer[512];
|
||||
WORD len = *(WORD *)lparam;
|
||||
|
||||
if (!(ptr = get_buffer( buffer, sizeof(buffer), len * sizeof(WCHAR) ))) break;
|
||||
*((WORD *)ptr) = len; /* store the length */
|
||||
ret = callback( hwnd, msg, wparam, (LPARAM)ptr, result, arg );
|
||||
if (*result)
|
||||
{
|
||||
DWORD reslen;
|
||||
reslen = win32u_wctomb( &ansi_cp, (char *)lparam, len, ptr, *result );
|
||||
if (reslen < len) ((LPSTR)lparam)[reslen] = 0;
|
||||
*result = reslen;
|
||||
}
|
||||
free_buffer( buffer, ptr );
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_GETDLGCODE:
|
||||
if (lparam)
|
||||
{
|
||||
MSG newmsg = *(MSG *)lparam;
|
||||
if (map_wparam_AtoW( newmsg.message, &newmsg.wParam, WMCHAR_MAP_NOMAPPING ))
|
||||
ret = callback( hwnd, msg, wparam, (LPARAM)&newmsg, result, arg );
|
||||
}
|
||||
else ret = callback( hwnd, msg, wparam, lparam, result, arg );
|
||||
break;
|
||||
|
||||
case WM_CHARTOITEM:
|
||||
case WM_MENUCHAR:
|
||||
case WM_DEADCHAR:
|
||||
case WM_SYSCHAR:
|
||||
case WM_SYSDEADCHAR:
|
||||
case EM_SETPASSWORDCHAR:
|
||||
case WM_IME_CHAR:
|
||||
if (map_wparam_AtoW( msg, &wparam, mapping ))
|
||||
ret = callback( hwnd, msg, wparam, lparam, result, arg );
|
||||
break;
|
||||
|
||||
case WM_GETTEXTLENGTH:
|
||||
case CB_GETLBTEXTLEN:
|
||||
case LB_GETTEXTLEN:
|
||||
ret = callback( hwnd, msg, wparam, lparam, result, arg );
|
||||
if (*result >= 0)
|
||||
{
|
||||
WCHAR *ptr, buffer[512];
|
||||
LRESULT res;
|
||||
DWORD len = *result + 1;
|
||||
/* Determine respective GETTEXT message */
|
||||
UINT msg_get_text = msg == WM_GETTEXTLENGTH ? WM_GETTEXT :
|
||||
(msg == CB_GETLBTEXTLEN ? CB_GETLBTEXT : LB_GETTEXT);
|
||||
/* wparam differs between the messages */
|
||||
WPARAM wp = msg == WM_GETTEXTLENGTH ? len : wparam;
|
||||
|
||||
if (!(ptr = get_buffer( buffer, sizeof(buffer), len * sizeof(WCHAR) ))) break;
|
||||
|
||||
res = send_message( hwnd, msg_get_text, wp, (LPARAM)ptr );
|
||||
*result = win32u_wctomb_size( &ansi_cp, ptr, res );
|
||||
free_buffer( buffer, ptr );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = callback( hwnd, msg, wparam, lparam, result, arg );
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* process_message
|
||||
|
@ -2871,7 +3145,13 @@ static BOOL process_message( struct send_message_info *info, DWORD_PTR *res_ptr,
|
|||
{
|
||||
if (dest_pid != GetCurrentProcessId() && (info->type == MSG_ASCII || info->type == MSG_UNICODE))
|
||||
info->type = MSG_OTHER_PROCESS;
|
||||
ret = send_inter_thread_message( info, &result );
|
||||
|
||||
/* MSG_ASCII can be sent unconverted except for WM_CHAR; everything else needs to be Unicode */
|
||||
if (ansi && (info->type != MSG_ASCII || info->msg == WM_CHAR))
|
||||
ret = call_messageAtoW( send_inter_thread_callback, info->hwnd, info->msg,
|
||||
info->wparam, info->lparam, &result, info, info->wm_char );
|
||||
else
|
||||
ret = send_inter_thread_message( info, &result );
|
||||
}
|
||||
else if (info->type != MSG_OTHER_PROCESS)
|
||||
{
|
||||
|
|
|
@ -339,7 +339,6 @@ extern int add_gdi_face( const WCHAR *family_name, const WCHAR *second_name,
|
|||
DWORD ntmflags, DWORD version, DWORD flags,
|
||||
const struct bitmap_font_size *size ) DECLSPEC_HIDDEN;
|
||||
extern UINT font_init(void) DECLSPEC_HIDDEN;
|
||||
extern CPTABLEINFO *get_cptable( WORD cp ) DECLSPEC_HIDDEN;
|
||||
extern const struct font_backend_funcs *init_freetype_lib(void) DECLSPEC_HIDDEN;
|
||||
|
||||
/* opentype.c */
|
||||
|
|
|
@ -453,11 +453,14 @@ static inline WCHAR win32u_towupper( WCHAR ch )
|
|||
|
||||
extern CPTABLEINFO ansi_cp DECLSPEC_HIDDEN;
|
||||
|
||||
CPTABLEINFO *get_cptable( WORD cp ) DECLSPEC_HIDDEN;
|
||||
const NLS_LOCALE_DATA *get_locale_data( LCID lcid ) DECLSPEC_HIDDEN;
|
||||
DWORD win32u_mbtowc( CPTABLEINFO *info, WCHAR *dst, DWORD dstlen, const char *src,
|
||||
DWORD srclen ) DECLSPEC_HIDDEN;
|
||||
DWORD win32u_wctomb( CPTABLEINFO *info, char *dst, DWORD dstlen, const WCHAR *src,
|
||||
DWORD srclen ) DECLSPEC_HIDDEN;
|
||||
DWORD win32u_wctomb_size( CPTABLEINFO *info, const WCHAR *src, DWORD srclen ) DECLSPEC_HIDDEN;
|
||||
DWORD win32u_mbtowc_size( CPTABLEINFO *info, const char *src, DWORD srclen ) DECLSPEC_HIDDEN;
|
||||
|
||||
static inline WCHAR *win32u_wcsdup( const WCHAR *str )
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue