diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index 0e4a93b9d72..80f6bf52ebb 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -63,6 +63,7 @@ struct wow_handlers16 { LRESULT (*button_proc)(HWND,UINT,WPARAM,LPARAM,BOOL); LRESULT (*combo_proc)(HWND,UINT,WPARAM,LPARAM,BOOL); + LRESULT (*edit_proc)(HWND,UINT,WPARAM,LPARAM,BOOL); LRESULT (*listbox_proc)(HWND,UINT,WPARAM,LPARAM,BOOL); }; @@ -70,6 +71,7 @@ struct wow_handlers32 { LRESULT (*button_proc)(HWND,UINT,WPARAM,LPARAM,BOOL); LRESULT (*combo_proc)(HWND,UINT,WPARAM,LPARAM,BOOL); + LRESULT (*edit_proc)(HWND,UINT,WPARAM,LPARAM,BOOL); LRESULT (*listbox_proc)(HWND,UINT,WPARAM,LPARAM,BOOL); }; @@ -77,6 +79,7 @@ extern struct wow_handlers16 wow_handlers DECLSPEC_HIDDEN; extern LRESULT ButtonWndProc_common(HWND,UINT,WPARAM,LPARAM,BOOL) DECLSPEC_HIDDEN; extern LRESULT ComboWndProc_common(HWND,UINT,WPARAM,LPARAM,BOOL) DECLSPEC_HIDDEN; +extern LRESULT EditWndProc_common(HWND,UINT,WPARAM,LPARAM,BOOL) DECLSPEC_HIDDEN; extern LRESULT ListBoxWndProc_common(HWND,UINT,WPARAM,LPARAM,BOOL) DECLSPEC_HIDDEN; extern void register_wow_handlers(void) DECLSPEC_HIDDEN; diff --git a/dlls/user32/edit.c b/dlls/user32/edit.c index 09acf948e70..4b73ec7c7d9 100644 --- a/dlls/user32/edit.c +++ b/dlls/user32/edit.c @@ -249,90 +249,6 @@ static HBRUSH EDIT_NotifyCtlColor(EDITSTATE *es, HDC hdc) } -/********************************************************************** - * Support for word break proc thunks - */ - -#define MAX_THUNKS 32 - -#include -static struct word_break_thunk -{ - BYTE popl_eax; /* popl %eax (return address) */ - BYTE pushl_proc16; /* pushl proc16 */ - EDITWORDBREAKPROC16 proc16; - BYTE pushl_eax; /* pushl %eax */ - BYTE jmp; /* ljmp call_word_break_proc16 */ - DWORD callback; -} *word_break_thunks; -#include - -/********************************************************************** - * call_word_break_proc16 - */ -static INT16 CALLBACK call_word_break_proc16( SEGPTR proc16, LPSTR text, INT index, INT count, INT action ) -{ - SEGPTR segptr; - WORD args[5]; - DWORD result; - - segptr = MapLS( text ); - args[4] = SELECTOROF(segptr); - args[3] = OFFSETOF(segptr); - args[2] = index; - args[1] = count; - args[0] = action; - WOWCallback16Ex( proc16, WCB16_PASCAL, sizeof(args), args, &result ); - UnMapLS( segptr ); - return LOWORD(result); -} - -/****************************************************************** - * add_word_break_thunk - */ -static struct word_break_thunk *add_word_break_thunk( EDITWORDBREAKPROC16 proc16 ) -{ - struct word_break_thunk *thunk; - - if (!word_break_thunks) - { - word_break_thunks = VirtualAlloc( NULL, MAX_THUNKS * sizeof(*thunk), - MEM_COMMIT, PAGE_EXECUTE_READWRITE ); - if (!word_break_thunks) return NULL; - - for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++) - { - thunk->popl_eax = 0x58; /* popl %eax */ - thunk->pushl_proc16 = 0x68; /* pushl proc16 */ - thunk->pushl_eax = 0x50; /* pushl %eax */ - thunk->jmp = 0xe9; /* jmp call_word_break_proc16 */ - thunk->callback = (char *)call_word_break_proc16 - (char *)(&thunk->callback + 1); - } - } - for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++) - if (thunk->proc16 == proc16) return thunk; - - for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++) - { - if (thunk->proc16) continue; - thunk->proc16 = proc16; - return thunk; - } - FIXME("Out of word break thunks\n"); - return NULL; -} - -/****************************************************************** - * get_word_break_thunk - */ -static EDITWORDBREAKPROC16 get_word_break_thunk( EDITWORDBREAKPROCA proc ) -{ - struct word_break_thunk *thunk = (struct word_break_thunk *)proc; - if (word_break_thunks && thunk >= word_break_thunks && thunk < &word_break_thunks[MAX_THUNKS]) - return thunk->proc16; - return NULL; -} - /********************************************************************* * * EDIT_WordBreakProc @@ -1174,66 +1090,6 @@ static inline void text_buffer_changed(EDITSTATE *es) es->text_length = (UINT)-1; } -#define GWW_HANDLE16 sizeof(EDITSTATE*) - -/********************************************************************* - * EDIT_LockBuffer16 - */ -static void EDIT_LockBuffer16(EDITSTATE *es) -{ - STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); - HLOCAL16 hloc16 = GetWindowWord( es->hwndSelf, GWW_HANDLE16 ); - HANDLE16 oldDS; - HLOCAL hloc32; - UINT size; - - if (!hloc16) return; - if (!(hloc32 = es->hloc32A)) return; - - oldDS = stack16->ds; - stack16->ds = GetWindowLongPtrW( es->hwndSelf, GWLP_HINSTANCE ); - size = LocalSize16(hloc16); - if (LocalReAlloc( hloc32, size, LMEM_MOVEABLE )) - { - char *text = MapSL( LocalLock16( hloc16 )); - char *dest = LocalLock( hloc32 ); - memcpy( dest, text, size ); - LocalUnlock( hloc32 ); - LocalUnlock16( hloc16 ); - } - stack16->ds = oldDS; - -} - -/********************************************************************* - * EDIT_UnlockBuffer16 - * - */ -static void EDIT_UnlockBuffer16(EDITSTATE *es) -{ - STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); - HLOCAL16 hloc16 = GetWindowWord( es->hwndSelf, GWW_HANDLE16 ); - HANDLE16 oldDS; - HLOCAL hloc32; - UINT size; - - if (!hloc16) return; - if (!(hloc32 = es->hloc32A)) return; - size = LocalSize( hloc32 ); - - oldDS = stack16->ds; - stack16->ds = GetWindowLongPtrW( es->hwndSelf, GWLP_HINSTANCE ); - if (LocalReAlloc16( hloc16, size, LMEM_MOVEABLE )) - { - char *text = LocalLock( hloc32 ); - char *dest = MapSL( LocalLock16( hloc16 )); - memcpy( dest, text, size ); - LocalUnlock( hloc32 ); - LocalUnlock16( hloc16 ); - } - stack16->ds = oldDS; -} - /********************************************************************* * * EDIT_LockBuffer @@ -1256,8 +1112,6 @@ static void EDIT_LockBuffer(EDITSTATE *es) if(!es->hloc32W) return; - EDIT_LockBuffer16(es); - if(es->hloc32A) { CHAR *textA = LocalLock(es->hloc32A); @@ -1345,7 +1199,6 @@ static void EDIT_UnlockBuffer(EDITSTATE *es, BOOL force) LocalUnlock(es->hloc32W); es->text = NULL; - EDIT_UnlockBuffer16(es); } else { ERR("no buffer ... please report\n"); @@ -2452,73 +2305,6 @@ static HLOCAL EDIT_EM_GetHandle(EDITSTATE *es) } -/********************************************************************* - * - * EM_GETHANDLE16 - * - * Hopefully this won't fire back at us. - * We always start with a buffer in 32 bit linear memory. - * However, with this message a 16 bit application requests - * a handle of 16 bit local heap memory, where it expects to find - * the text. - * It's a pitty that from this moment on we have to use this - * local heap, because applications may rely on the handle - * in the future. - * - * In this function we'll try to switch to local heap. - */ -static HLOCAL16 EDIT_EM_GetHandle16( HWND hwnd ) -{ - CHAR *textA; - UINT alloc_size; - HLOCAL hloc; - STACK16FRAME* stack16; - HANDLE16 oldDS; - HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 ); - - if (hloc16) return hloc16; - - if (!(hloc = (HLOCAL)SendMessageA( hwnd, EM_GETHANDLE, 0, 0 ))) return 0; - alloc_size = LocalSize( hloc ); - - stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); - oldDS = stack16->ds; - stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ); - - if (!LocalHeapSize16()) { - - if (!LocalInit16(stack16->ds, 0, GlobalSize16(stack16->ds))) { - ERR("could not initialize local heap\n"); - goto done; - } - TRACE("local heap initialized\n"); - } - - TRACE("Allocating 16-bit ANSI alias buffer\n"); - if (!(hloc16 = LocalAlloc16(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size))) { - ERR("could not allocate new 16 bit buffer\n"); - goto done; - } - - if (!(textA = MapSL(LocalLock16( hloc16)))) { - ERR("could not lock new 16 bit buffer\n"); - LocalFree16(hloc16); - hloc16 = 0; - goto done; - } - memcpy( textA, LocalLock( hloc ), alloc_size ); - LocalUnlock( hloc ); - LocalUnlock16( hloc16 ); - SetWindowWord( hwnd, GWW_HANDLE16, hloc16 ); - - TRACE("Returning %04X, LocalSize() = %d\n", hloc16, alloc_size); - -done: - stack16->ds = oldDS; - return hloc16; -} - - /********************************************************************* * * EM_GETLINE @@ -2865,46 +2651,6 @@ static void EDIT_EM_SetHandle(EDITSTATE *es, HLOCAL hloc) } -/********************************************************************* - * - * EM_SETHANDLE16 - * - * FIXME: ES_LOWERCASE, ES_UPPERCASE, ES_OEMCONVERT, ES_NUMBER ??? - * - */ -static void EDIT_EM_SetHandle16( HWND hwnd, HLOCAL16 hloc16 ) -{ - STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); - HINSTANCE16 hInstance = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ); - HANDLE16 oldDS = stack16->ds; - HLOCAL hloc32; - INT count; - CHAR *text; - - if (!(GetWindowLongW( hwnd, GWL_STYLE ) & ES_MULTILINE)) return; - - if (!hloc16) { - WARN("called with NULL handle\n"); - return; - } - - stack16->ds = hInstance; - count = LocalSize16(hloc16); - text = MapSL(LocalLock16(hloc16)); - if ((hloc32 = LocalAlloc(LMEM_MOVEABLE, count))) - { - memcpy( LocalLock(hloc32), text, count ); - LocalUnlock(hloc32); - LocalUnlock16(hloc16); - SetWindowWord( hwnd, GWW_HANDLE16, hloc16 ); - } - stack16->ds = oldDS; - - if (hloc32) SendMessageA( hwnd, EM_SETHANDLE, (WPARAM)hloc32, 0 ); - else ERR("Could not allocate new buffer\n"); -} - - /********************************************************************* * * EM_SETLIMITTEXT @@ -4651,7 +4397,6 @@ static LRESULT EDIT_WM_Create(EDITSTATE *es, LPCWSTR name) static LRESULT EDIT_WM_NCDestroy(EDITSTATE *es) { LINEDEF *pc, *pp; - HLOCAL16 hloc16 = GetWindowWord( es->hwndSelf, GWW_HANDLE16 ); if (es->hloc32W) { LocalFree(es->hloc32W); @@ -4659,17 +4404,6 @@ static LRESULT EDIT_WM_NCDestroy(EDITSTATE *es) if (es->hloc32A) { LocalFree(es->hloc32A); } - if (hloc16) { - STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); - HANDLE16 oldDS = stack16->ds; - - stack16->ds = GetWindowLongPtrW( es->hwndSelf, GWLP_HINSTANCE ); - while (LocalUnlock16(hloc16)) ; - LocalFree16(hloc16); - stack16->ds = oldDS; - SetWindowWord( es->hwndSelf, GWW_HANDLE16, 0 ); - } - pc = es->first_line_def; while (pc) { @@ -4701,8 +4435,7 @@ static inline LRESULT DefWindowProcT(HWND hwnd, UINT msg, WPARAM wParam, LPARAM * The messages are in the order of the actual integer values * (which can be found in include/windows.h) */ -static LRESULT EditWndProc_common( HWND hwnd, UINT msg, - WPARAM wParam, LPARAM lParam, BOOL unicode ) +LRESULT EditWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode ) { EDITSTATE *es = (EDITSTATE *)GetWindowLongPtrW( hwnd, 0 ); LRESULT result = 0; @@ -5242,140 +4975,13 @@ static LRESULT EditWndProc_common( HWND hwnd, UINT msg, } -/********************************************************************* - * EditWndProc_wrapper16 - */ -static LRESULT EditWndProc_wrapper16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode ) -{ - static const UINT msg16_offset = EM_GETSEL16 - EM_GETSEL; - LRESULT result; - - switch (msg) - { - case EM_SCROLL16: - case EM_SCROLLCARET16: - case EM_GETMODIFY16: - case EM_SETMODIFY16: - case EM_GETLINECOUNT16: - case EM_GETTHUMB16: - case EM_LINELENGTH16: - case EM_LIMITTEXT16: - case EM_CANUNDO16: - case EM_UNDO16: - case EM_FMTLINES16: - case EM_LINEFROMCHAR16: - case EM_SETPASSWORDCHAR16: - case EM_EMPTYUNDOBUFFER16: - case EM_SETREADONLY16: - case EM_GETPASSWORDCHAR16: - /* these messages missing from specs */ - case WM_USER+15: - case WM_USER+16: - case WM_USER+19: - case WM_USER+26: - msg -= msg16_offset; - break; - case EM_GETSEL16: - wParam = 0; - lParam = 0; - msg -= msg16_offset; - break; - case EM_REPLACESEL16: - case EM_GETLINE16: - lParam = (LPARAM)MapSL(lParam); - msg -= msg16_offset; - break; - case EM_LINESCROLL16: - wParam = (INT)(SHORT)HIWORD(lParam); - lParam = (INT)(SHORT)LOWORD(lParam); - msg -= msg16_offset; - break; - case EM_LINEINDEX16: - if ((INT16)wParam == -1) wParam = (WPARAM)-1; - msg -= msg16_offset; - break; - case EM_SETSEL16: - if ((short)LOWORD(lParam) == -1) - { - wParam = -1; - lParam = 0; - } - else - { - wParam = LOWORD(lParam); - lParam = HIWORD(lParam); - } - msg -= msg16_offset; - break; - case EM_GETRECT16: - if (lParam) - { - RECT rect; - RECT16 *r16 = MapSL(lParam); - EditWndProc_common( hwnd, msg - msg16_offset, wParam, (LPARAM)&rect, FALSE ); - r16->left = rect.left; - r16->top = rect.top; - r16->right = rect.right; - r16->bottom = rect.bottom; - } - return 0; - case EM_SETRECT16: - case EM_SETRECTNP16: - if (lParam) - { - RECT rect; - RECT16 *r16 = MapSL(lParam); - rect.left = r16->left; - rect.top = r16->top; - rect.right = r16->right; - rect.bottom = r16->bottom; - EditWndProc_common( hwnd, msg - msg16_offset, wParam, (LPARAM)&rect, FALSE ); - } - return 0; - case EM_SETHANDLE16: - EDIT_EM_SetHandle16( hwnd, (HLOCAL16)wParam ); - break; - case EM_GETHANDLE16: - result = EDIT_EM_GetHandle16( hwnd ); - break; - case EM_SETTABSTOPS16: - { - INT16 *tabs16 = MapSL(lParam); - INT i, count = wParam, *tabs = NULL; - if (count > 0) - { - if (!(tabs = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*tabs) ))) return 0; - for (i = 0; i < count; i++) tabs[i] = tabs16[i]; - } - result = EditWndProc_common( hwnd, msg - msg16_offset, count, (LPARAM)tabs, FALSE ); - HeapFree( GetProcessHeap(), 0, tabs ); - return result; - } - case EM_GETFIRSTVISIBLELINE16: - if (!(GetWindowLongW( hwnd, GWL_STYLE ) & ES_MULTILINE)) return 0; - msg -= msg16_offset; - break; - case EM_SETWORDBREAKPROC16: - { - struct word_break_thunk *thunk = add_word_break_thunk( (EDITWORDBREAKPROC16)lParam ); - return EditWndProc_common( hwnd, EM_SETWORDBREAKPROC, wParam, (LPARAM)thunk, FALSE ); - } - case EM_GETWORDBREAKPROC16: - result = EditWndProc_common( hwnd, EM_GETWORDBREAKPROC, wParam, lParam, FALSE ); - return (LRESULT)get_word_break_thunk( (EDITWORDBREAKPROCA)result ); - default: - return EditWndProc_common( hwnd, msg, wParam, lParam, unicode ); - } - return EditWndProc_common( hwnd, msg, wParam, lParam, FALSE ); -} - /********************************************************************* * * EditWndProc (USER32.@) */ LRESULT WINAPI EditWndProcA(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - return EditWndProc_wrapper16(hWnd, uMsg, wParam, lParam, FALSE); + return wow_handlers.edit_proc(hWnd, uMsg, wParam, lParam, FALSE); } /********************************************************************* @@ -5384,7 +4990,7 @@ LRESULT WINAPI EditWndProcA(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) */ static LRESULT WINAPI EditWndProcW(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - return EditWndProc_wrapper16(hWnd, uMsg, wParam, lParam, TRUE); + return wow_handlers.edit_proc(hWnd, uMsg, wParam, lParam, TRUE); } /********************************************************************* diff --git a/dlls/user32/msg16.c b/dlls/user32/msg16.c index 8c3af196ed2..2ebb133d0eb 100644 --- a/dlls/user32/msg16.c +++ b/dlls/user32/msg16.c @@ -88,6 +88,91 @@ static LRESULT defdlg_proc_callback( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp, } +/********************************************************************** + * Support for Edit word break proc thunks + */ + +#define MAX_THUNKS 32 + +#include +static struct word_break_thunk +{ + BYTE popl_eax; /* popl %eax (return address) */ + BYTE pushl_proc16; /* pushl proc16 */ + EDITWORDBREAKPROC16 proc16; + BYTE pushl_eax; /* pushl %eax */ + BYTE jmp; /* ljmp call_word_break_proc16 */ + DWORD callback; +} *word_break_thunks; +#include + +/********************************************************************** + * call_word_break_proc16 + */ +static INT16 CALLBACK call_word_break_proc16( SEGPTR proc16, LPSTR text, INT index, INT count, INT action ) +{ + SEGPTR segptr; + WORD args[5]; + DWORD result; + + segptr = MapLS( text ); + args[4] = SELECTOROF(segptr); + args[3] = OFFSETOF(segptr); + args[2] = index; + args[1] = count; + args[0] = action; + WOWCallback16Ex( proc16, WCB16_PASCAL, sizeof(args), args, &result ); + UnMapLS( segptr ); + return LOWORD(result); +} + +/****************************************************************** + * add_word_break_thunk + */ +static struct word_break_thunk *add_word_break_thunk( EDITWORDBREAKPROC16 proc16 ) +{ + struct word_break_thunk *thunk; + + if (!word_break_thunks) + { + word_break_thunks = VirtualAlloc( NULL, MAX_THUNKS * sizeof(*thunk), + MEM_COMMIT, PAGE_EXECUTE_READWRITE ); + if (!word_break_thunks) return NULL; + + for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++) + { + thunk->popl_eax = 0x58; /* popl %eax */ + thunk->pushl_proc16 = 0x68; /* pushl proc16 */ + thunk->pushl_eax = 0x50; /* pushl %eax */ + thunk->jmp = 0xe9; /* jmp call_word_break_proc16 */ + thunk->callback = (char *)call_word_break_proc16 - (char *)(&thunk->callback + 1); + } + } + for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++) + if (thunk->proc16 == proc16) return thunk; + + for (thunk = word_break_thunks; thunk < &word_break_thunks[MAX_THUNKS]; thunk++) + { + if (thunk->proc16) continue; + thunk->proc16 = proc16; + return thunk; + } + FIXME("Out of word break thunks\n"); + return NULL; +} + +/****************************************************************** + * get_word_break_thunk + */ +static EDITWORDBREAKPROC16 get_word_break_thunk( EDITWORDBREAKPROCA proc ) +{ + struct word_break_thunk *thunk = (struct word_break_thunk *)proc; + if (word_break_thunks && thunk >= word_break_thunks && thunk < &word_break_thunks[MAX_THUNKS]) + return thunk->proc16; + return NULL; +} + + /*********************************************************************** * SendMessage (USER.111) */ @@ -684,6 +769,284 @@ static LRESULT combo_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, } +#define GWW_HANDLE16 sizeof(void*) + +static void edit_lock_buffer( HWND hwnd ) +{ + STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 ); + HANDLE16 oldDS; + HLOCAL hloc32; + UINT size; + + if (!hloc16) return; + if (!(hloc32 = (HLOCAL)wow_handlers32.edit_proc( hwnd, EM_GETHANDLE, 0, 0, FALSE ))) return; + + oldDS = stack16->ds; + stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ); + size = LocalSize16(hloc16); + if (LocalReAlloc( hloc32, size, LMEM_MOVEABLE )) + { + char *text = MapSL( LocalLock16( hloc16 )); + char *dest = LocalLock( hloc32 ); + memcpy( dest, text, size ); + LocalUnlock( hloc32 ); + LocalUnlock16( hloc16 ); + } + stack16->ds = oldDS; + +} + +static void edit_unlock_buffer( HWND hwnd ) +{ + STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 ); + HANDLE16 oldDS; + HLOCAL hloc32; + UINT size; + + if (!hloc16) return; + if (!(hloc32 = (HLOCAL)wow_handlers32.edit_proc( hwnd, EM_GETHANDLE, 0, 0, FALSE ))) return; + size = LocalSize( hloc32 ); + + oldDS = stack16->ds; + stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ); + if (LocalReAlloc16( hloc16, size, LMEM_MOVEABLE )) + { + char *text = LocalLock( hloc32 ); + char *dest = MapSL( LocalLock16( hloc16 )); + memcpy( dest, text, size ); + LocalUnlock( hloc32 ); + LocalUnlock16( hloc16 ); + } + stack16->ds = oldDS; +} + +static HLOCAL16 edit_get_handle( HWND hwnd ) +{ + CHAR *textA; + UINT alloc_size; + HLOCAL hloc; + STACK16FRAME* stack16; + HANDLE16 oldDS; + HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 ); + + if (hloc16) return hloc16; + + if (!(hloc = (HLOCAL)wow_handlers32.edit_proc( hwnd, EM_GETHANDLE, 0, 0, FALSE ))) return 0; + alloc_size = LocalSize( hloc ); + + stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + oldDS = stack16->ds; + stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ); + + if (!LocalHeapSize16()) + { + if (!LocalInit16(stack16->ds, 0, GlobalSize16(stack16->ds))) + { + ERR("could not initialize local heap\n"); + goto done; + } + } + + if (!(hloc16 = LocalAlloc16(LMEM_MOVEABLE | LMEM_ZEROINIT, alloc_size))) + { + ERR("could not allocate new 16 bit buffer\n"); + goto done; + } + + if (!(textA = MapSL(LocalLock16( hloc16)))) + { + ERR("could not lock new 16 bit buffer\n"); + LocalFree16(hloc16); + hloc16 = 0; + goto done; + } + memcpy( textA, LocalLock( hloc ), alloc_size ); + LocalUnlock( hloc ); + LocalUnlock16( hloc16 ); + SetWindowWord( hwnd, GWW_HANDLE16, hloc16 ); + +done: + stack16->ds = oldDS; + return hloc16; +} + +static void edit_set_handle( HWND hwnd, HLOCAL16 hloc16 ) +{ + STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + HINSTANCE16 hInstance = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ); + HANDLE16 oldDS = stack16->ds; + HLOCAL hloc32; + INT count; + CHAR *text; + + if (!(GetWindowLongW( hwnd, GWL_STYLE ) & ES_MULTILINE)) return; + if (!hloc16) return; + + stack16->ds = hInstance; + count = LocalSize16(hloc16); + text = MapSL(LocalLock16(hloc16)); + if ((hloc32 = LocalAlloc(LMEM_MOVEABLE, count))) + { + memcpy( LocalLock(hloc32), text, count ); + LocalUnlock(hloc32); + LocalUnlock16(hloc16); + SetWindowWord( hwnd, GWW_HANDLE16, hloc16 ); + } + stack16->ds = oldDS; + + if (hloc32) wow_handlers32.edit_proc( hwnd, EM_SETHANDLE, (WPARAM)hloc32, 0, FALSE ); +} + +static void edit_destroy_handle( HWND hwnd ) +{ + HLOCAL16 hloc16 = GetWindowWord( hwnd, GWW_HANDLE16 ); + if (hloc16) + { + STACK16FRAME* stack16 = MapSL(PtrToUlong(NtCurrentTeb()->WOW32Reserved)); + HANDLE16 oldDS = stack16->ds; + + stack16->ds = GetWindowLongPtrW( hwnd, GWLP_HINSTANCE ); + while (LocalUnlock16(hloc16)) ; + LocalFree16(hloc16); + stack16->ds = oldDS; + SetWindowWord( hwnd, GWW_HANDLE16, 0 ); + } +} + +/********************************************************************* + * edit_proc16 + */ +static LRESULT edit_proc16( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode ) +{ + static const UINT msg16_offset = EM_GETSEL16 - EM_GETSEL; + LRESULT result = 0; + + edit_lock_buffer( hwnd ); + switch (msg) + { + case EM_SCROLL16: + case EM_SCROLLCARET16: + case EM_GETMODIFY16: + case EM_SETMODIFY16: + case EM_GETLINECOUNT16: + case EM_GETTHUMB16: + case EM_LINELENGTH16: + case EM_LIMITTEXT16: + case EM_CANUNDO16: + case EM_UNDO16: + case EM_FMTLINES16: + case EM_LINEFROMCHAR16: + case EM_SETPASSWORDCHAR16: + case EM_EMPTYUNDOBUFFER16: + case EM_SETREADONLY16: + case EM_GETPASSWORDCHAR16: + /* these messages missing from specs */ + case WM_USER+15: + case WM_USER+16: + case WM_USER+19: + case WM_USER+26: + result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE ); + break; + case EM_GETSEL16: + result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, 0, 0, FALSE ); + break; + case EM_REPLACESEL16: + case EM_GETLINE16: + result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, (LPARAM)MapSL(lParam), FALSE ); + break; + case EM_LINESCROLL16: + result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, (INT)(SHORT)HIWORD(lParam), + (INT)(SHORT)LOWORD(lParam), FALSE ); + break; + case EM_LINEINDEX16: + if ((INT16)wParam == -1) wParam = (WPARAM)-1; + result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE ); + break; + case EM_SETSEL16: + if ((short)LOWORD(lParam) == -1) + { + wParam = -1; + lParam = 0; + } + else + { + wParam = LOWORD(lParam); + lParam = HIWORD(lParam); + } + result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE ); + break; + case EM_GETRECT16: + if (lParam) + { + RECT rect; + RECT16 *r16 = MapSL(lParam); + wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, (LPARAM)&rect, FALSE ); + r16->left = rect.left; + r16->top = rect.top; + r16->right = rect.right; + r16->bottom = rect.bottom; + } + break; + case EM_SETRECT16: + case EM_SETRECTNP16: + if (lParam) + { + RECT rect; + RECT16 *r16 = MapSL(lParam); + rect.left = r16->left; + rect.top = r16->top; + rect.right = r16->right; + rect.bottom = r16->bottom; + wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, (LPARAM)&rect, FALSE ); + } + break; + case EM_SETHANDLE16: + edit_set_handle( hwnd, (HLOCAL16)wParam ); + break; + case EM_GETHANDLE16: + result = edit_get_handle( hwnd ); + break; + case EM_SETTABSTOPS16: + { + INT16 *tabs16 = MapSL(lParam); + INT i, count = wParam, *tabs = NULL; + if (count > 0) + { + if (!(tabs = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*tabs) ))) return 0; + for (i = 0; i < count; i++) tabs[i] = tabs16[i]; + } + result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, count, (LPARAM)tabs, FALSE ); + HeapFree( GetProcessHeap(), 0, tabs ); + break; + } + case EM_GETFIRSTVISIBLELINE16: + if (!(GetWindowLongW( hwnd, GWL_STYLE ) & ES_MULTILINE)) break; + result = wow_handlers32.edit_proc( hwnd, msg - msg16_offset, wParam, lParam, FALSE ); + break; + case EM_SETWORDBREAKPROC16: + { + struct word_break_thunk *thunk = add_word_break_thunk( (EDITWORDBREAKPROC16)lParam ); + result = wow_handlers32.edit_proc( hwnd, EM_SETWORDBREAKPROC, wParam, (LPARAM)thunk, FALSE ); + break; + } + case EM_GETWORDBREAKPROC16: + result = wow_handlers32.edit_proc( hwnd, EM_GETWORDBREAKPROC, wParam, lParam, FALSE ); + result = (LRESULT)get_word_break_thunk( (EDITWORDBREAKPROCA)result ); + break; + case WM_NCDESTROY: + edit_destroy_handle( hwnd ); + return wow_handlers32.edit_proc( hwnd, msg, wParam, lParam, unicode ); /* no unlock on destroy */ + default: + result = wow_handlers32.edit_proc( hwnd, msg, wParam, lParam, unicode ); + break; + } + edit_unlock_buffer( hwnd ); + return result; +} + + /*********************************************************************** * listbox_proc16 */ @@ -802,6 +1165,7 @@ void register_wow_handlers(void) { button_proc16, combo_proc16, + edit_proc16, listbox_proc16, }; diff --git a/dlls/user32/winproc.c b/dlls/user32/winproc.c index 3a9fc77791f..0a91a586578 100644 --- a/dlls/user32/winproc.c +++ b/dlls/user32/winproc.c @@ -2390,6 +2390,7 @@ void WINAPI UserRegisterWowHandlers( const struct wow_handlers16 *new, struct wo { orig->button_proc = ButtonWndProc_common; orig->combo_proc = ComboWndProc_common; + orig->edit_proc = EditWndProc_common; orig->listbox_proc = ListBoxWndProc_common; wow_handlers = *new; @@ -2399,5 +2400,6 @@ struct wow_handlers16 wow_handlers = { ButtonWndProc_common, ComboWndProc_common, + EditWndProc_common, ListBoxWndProc_common, };