| /* |
| * Window procedure callbacks |
| * |
| * Copyright 1995 Martin von Loewis |
| * Copyright 1996 Alexandre Julliard |
| */ |
| |
| #include <stdio.h> |
| #include "windows.h" |
| #include "callback.h" |
| #include "heap.h" |
| #include "ldt.h" |
| #include "stackframe.h" |
| #include "string32.h" |
| #include "struct32.h" |
| #include "win.h" |
| #include "winproc.h" |
| |
| |
| typedef struct |
| { |
| WNDPROC32 func; /* 32-bit function, or 0 if free */ |
| unsigned int count : 30; /* Reference count, or next free if func==0 */ |
| WINDOWPROCTYPE type : 2; /* Function type */ |
| } WINDOWPROC; |
| |
| #define NB_WINPROCS 1024 /* Must be < 64K; 1024 should be enough for now */ |
| |
| static WINDOWPROC winProcs[NB_WINPROCS]; |
| static int lastWinProc = 0; |
| static int freeWinProc = NB_WINPROCS; |
| |
| /* Check if a win proc was created by WINPROC_AllocWinProc */ |
| #define IS_ALLOCATED_WINPROC(func) (HIWORD(func) == 0xffff) |
| |
| /********************************************************************** |
| * WINPROC_AllocWinProc |
| * |
| * Allocate a new window procedure. |
| */ |
| WNDPROC16 WINPROC_AllocWinProc( WNDPROC32 func, WINDOWPROCTYPE type ) |
| { |
| WINDOWPROC *proc; |
| if (!func) return (WNDPROC16)0; /* Null win proc remains null */ |
| if (IS_ALLOCATED_WINPROC(func)) /* Already allocated? */ |
| { |
| if (LOWORD(func) >= NB_WINPROCS) return (WNDPROC16)0; |
| proc = &winProcs[LOWORD(func)]; |
| if (!proc->func) return (WNDPROC16)0; |
| proc->count++; |
| return (WNDPROC16)func; |
| } |
| if (freeWinProc < NB_WINPROCS) /* There is a free entry */ |
| { |
| proc = &winProcs[freeWinProc]; |
| proc->func = func; |
| func = (WNDPROC32)MAKELONG( freeWinProc, 0xffff ); |
| freeWinProc = proc->count; /* Next free entry */ |
| proc->count = 1; |
| proc->type = type; |
| return (WNDPROC16)func; |
| } |
| if (lastWinProc < NB_WINPROCS) /* There's a free entry at the end */ |
| { |
| proc = &winProcs[lastWinProc]; |
| proc->func = func; |
| func = (WNDPROC32)MAKELONG( lastWinProc, 0xffff ); |
| lastWinProc++; |
| proc->count = 1; |
| proc->type = type; |
| return (WNDPROC16)func; |
| } |
| fprintf( stderr, "WINPROC_AllocWinProc: out of window procedures.\n" |
| "Please augment NB_WINPROCS in winproc.c\n" ); |
| return (WNDPROC16)0; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_GetWinProcType |
| * |
| * Return the type of a window procedure. |
| */ |
| WINDOWPROCTYPE WINPROC_GetWinProcType( WNDPROC16 func ) |
| { |
| WORD id = LOWORD(func); |
| if (!IS_ALLOCATED_WINPROC(func)) return WIN_PROC_16; |
| if ((id >= NB_WINPROCS) || !winProcs[id].func) return WIN_PROC_INVALID; |
| return winProcs[id].type; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_GetWinProcFunc |
| * |
| * Return the 32-bit window procedure for a winproc. |
| */ |
| WNDPROC32 WINPROC_GetWinProcFunc( WNDPROC16 func ) |
| { |
| WORD id = LOWORD(func); |
| if (!IS_ALLOCATED_WINPROC(func)) return NULL; |
| if (id >= NB_WINPROCS) return NULL; |
| return winProcs[id].func; |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_FreeWinProc |
| * |
| * Free a window procedure. |
| */ |
| void WINPROC_FreeWinProc( WNDPROC16 func ) |
| { |
| WORD id = LOWORD(func); |
| if (!IS_ALLOCATED_WINPROC(func)) return; |
| if ((id >= NB_WINPROCS) || !winProcs[id].func) |
| { |
| fprintf( stderr, "WINPROC_FreeWinProc: invalid proc %08x\n", |
| (UINT32)func ); |
| return; |
| } |
| if (--winProcs[id].count == 0) |
| { |
| winProcs[id].func = 0; |
| winProcs[id].count = freeWinProc; |
| freeWinProc = id; |
| } |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProc32ATo32W |
| * |
| * Call a window procedure, translating args from Ansi to Unicode. |
| */ |
| static LRESULT WINPROC_CallProc32ATo32W( WNDPROC32 func, HWND32 hwnd, |
| UINT32 msg, WPARAM32 wParam, |
| LPARAM lParam ) |
| { |
| LRESULT result; |
| |
| switch(msg) |
| { |
| case WM_GETTEXT: |
| { |
| LPWSTR str = (LPWSTR)HeapAlloc(SystemHeap,0,wParam*sizeof(WCHAR)); |
| if (!str) return 0; |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str ); |
| STRING32_UniToAnsi( (LPSTR)lParam, str ); |
| HeapFree( SystemHeap, 0, str ); |
| return strlen( (LPSTR)lParam ) + 1; |
| } |
| |
| case WM_SETTEXT: |
| { |
| LPWSTR str = STRING32_DupAnsiToUni( (LPCSTR)lParam ); |
| if (!str) return 0; |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str ); |
| free( str ); |
| } |
| return result; |
| |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { |
| CREATESTRUCT32W cs = *(CREATESTRUCT32W *)lParam; |
| cs.lpszName = STRING32_DupAnsiToUni( (LPCSTR)cs.lpszName ); |
| cs.lpszClass = STRING32_DupAnsiToUni( (LPCSTR)cs.lpszName ); |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&cs ); |
| free( (LPVOID)cs.lpszName ); |
| free( (LPVOID)cs.lpszClass ); |
| } |
| return result; |
| |
| default: /* No translation needed */ |
| return CallWndProc32( func, hwnd, msg, wParam, lParam ); |
| } |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProc32WTo32A |
| * |
| * Call a window procedure, translating args from Unicode to Ansi. |
| */ |
| static LRESULT WINPROC_CallProc32WTo32A( WNDPROC32 func, HWND32 hwnd, |
| UINT32 msg, WPARAM32 wParam, |
| LPARAM lParam ) |
| { |
| LRESULT result; |
| |
| switch(msg) |
| { |
| case WM_GETTEXT: |
| { |
| LPSTR str = (LPSTR)HeapAlloc( SystemHeap, 0, wParam ); |
| if (!str) return 0; |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str ); |
| STRING32_AnsiToUni( (LPWSTR)lParam, str ); |
| HeapFree( SystemHeap, 0, str ); |
| return STRING32_lstrlenW( (LPWSTR)lParam ) + 1; /* FIXME? */ |
| } |
| |
| case WM_SETTEXT: |
| { |
| LPSTR str = STRING32_DupUniToAnsi( (LPCWSTR)lParam ); |
| if (!str) return 0; |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)str ); |
| free( str ); |
| } |
| return result; |
| |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { |
| CREATESTRUCT32A cs = *(CREATESTRUCT32A *)lParam; |
| cs.lpszName = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName ); |
| cs.lpszClass = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName ); |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&cs ); |
| free( (LPVOID)cs.lpszName ); |
| free( (LPVOID)cs.lpszClass ); |
| } |
| return result; |
| |
| default: /* No translation needed */ |
| return CallWndProc32( func, hwnd, msg, wParam, lParam ); |
| } |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProc16To32A |
| * |
| * Call a 32-bit window procedure, translating the 16-bit args. |
| */ |
| static LRESULT WINPROC_CallProc16To32A(WNDPROC32 func, HWND16 hwnd, UINT16 msg, |
| WPARAM16 wParam, LPARAM lParam ) |
| { |
| LRESULT result; |
| |
| switch(msg) |
| { |
| case WM_ACTIVATE: |
| case WM_CHARTOITEM: |
| case WM_COMMAND: |
| case WM_HSCROLL: |
| case WM_VKEYTOITEM: |
| case WM_VSCROLL: |
| return CallWndProc32( func, hwnd, msg, |
| MAKEWPARAM( wParam, HIWORD(lParam) ), |
| (LPARAM)(HWND32)LOWORD(lParam) ); |
| case WM_CTLCOLOR: |
| return CallWndProc32( func, hwnd, WM_CTLCOLORMSGBOX + HIWORD(lParam), |
| (WPARAM32)(HDC32)wParam, |
| (LPARAM)(HWND32)LOWORD(lParam) ); |
| case WM_DRAWITEM: |
| { |
| DRAWITEMSTRUCT16*dis16 = (DRAWITEMSTRUCT16*)PTR_SEG_TO_LIN(lParam); |
| DRAWITEMSTRUCT32 dis; |
| dis.CtlType = dis16->CtlType; |
| dis.CtlID = dis16->CtlID; |
| dis.itemID = dis16->itemID; |
| dis.itemAction = dis16->itemAction; |
| dis.itemState = dis16->itemState; |
| dis.hwndItem = dis16->hwndItem; |
| dis.hDC = dis16->hDC; |
| dis.itemData = dis16->itemData; |
| CONV_RECT16TO32( &dis16->rcItem, &dis.rcItem ); |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&dis ); |
| /* We don't bother to translate it back */ |
| } |
| return result; |
| |
| case WM_GETMINMAXINFO: |
| { |
| MINMAXINFO32 mmi; |
| STRUCT32_MINMAXINFO16to32( (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam), |
| &mmi ); |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&mmi); |
| STRUCT32_MINMAXINFO32to16( &mmi, |
| (MINMAXINFO16 *)PTR_SEG_TO_LIN(lParam)); |
| } |
| return result; |
| |
| case WM_GETTEXT: |
| return CallWndProc32( func, hwnd, msg, wParam, |
| (LPARAM)PTR_SEG_TO_LIN(lParam) ); |
| case WM_MDISETMENU: |
| return CallWndProc32( func, hwnd, msg, |
| (WPARAM32)(HMENU32)LOWORD(lParam), |
| (LPARAM)(HMENU32)HIWORD(lParam) ); |
| case WM_MENUCHAR: |
| case WM_MENUSELECT: |
| return CallWndProc32( func, hwnd, msg, |
| MAKEWPARAM( wParam, LOWORD(lParam) ), |
| (LPARAM)(HMENU32)HIWORD(lParam) ); |
| case WM_NCCALCSIZE: |
| { |
| NCCALCSIZE_PARAMS16 *pnc16; |
| NCCALCSIZE_PARAMS32 nc; |
| WINDOWPOS32 wp; |
| |
| pnc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam); |
| CONV_RECT16TO32( &pnc16->rgrc[0], &nc.rgrc[0] ); |
| if (wParam) |
| { |
| CONV_RECT16TO32( &pnc16->rgrc[1], &nc.rgrc[1] ); |
| CONV_RECT16TO32( &pnc16->rgrc[2], &nc.rgrc[2] ); |
| STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(pnc16->lppos), |
| &wp ); |
| nc.lppos = ℘ |
| } |
| |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&nc ); |
| |
| pnc16 = (NCCALCSIZE_PARAMS16 *)PTR_SEG_TO_LIN(lParam); |
| CONV_RECT32TO16( &nc.rgrc[0], &pnc16->rgrc[0] ); |
| if (wParam) |
| { |
| CONV_RECT32TO16( &nc.rgrc[1], &pnc16->rgrc[1] ); |
| CONV_RECT32TO16( &nc.rgrc[2], &pnc16->rgrc[2] ); |
| STRUCT32_WINDOWPOS32to16( nc.lppos, |
| (WINDOWPOS16 *)PTR_SEG_TO_LIN(pnc16->lppos)); |
| } |
| } |
| return result; |
| |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { |
| CREATESTRUCT16 *pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam); |
| CREATESTRUCT32A cs; |
| |
| STRUCT32_CREATESTRUCT16to32A( pcs16, &cs ); |
| /* FIXME: Unicode */ |
| cs.lpszName = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName); |
| cs.lpszClass = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass); |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&cs ); |
| pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam); |
| STRUCT32_CREATESTRUCT32Ato16( &cs, pcs16 ); |
| |
| if (cs.lpszName != (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName)) |
| fprintf( stderr, "CallWindowProc16: WM_NCCREATE(%04x) changed lpszName (%p->%p), please report.\n", |
| msg, (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName), cs.lpszName); |
| if (cs.lpszClass != (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass)) |
| fprintf( stderr, "CallWindowProc16: WM_NCCREATE(%04x) changed lpszClass (%p->%p), please report.\n", |
| msg, (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass), cs.lpszClass); |
| } |
| return result; |
| |
| case WM_PARENTNOTIFY: |
| if ((wParam == WM_CREATE) || (wParam == WM_DESTROY)) |
| return CallWndProc32( func, hwnd, msg, |
| MAKEWPARAM( wParam, HIWORD(lParam) ), |
| (LPARAM)(HWND32)LOWORD(lParam) ); |
| else return CallWndProc32( func, hwnd, msg, |
| MAKEWPARAM( wParam, 0 /* FIXME? */ ), |
| lParam ); |
| case WM_SETTEXT: |
| /* FIXME: Unicode */ |
| return CallWndProc32( func, hwnd, msg, wParam, |
| (LPARAM)PTR_SEG_TO_LIN(lParam) ); |
| |
| case WM_WINDOWPOSCHANGING: |
| case WM_WINDOWPOSCHANGED: |
| { |
| WINDOWPOS32 wp; |
| STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam), |
| &wp ); |
| result = CallWndProc32( func, hwnd, msg, wParam, (LPARAM)&wp ); |
| STRUCT32_WINDOWPOS32to16( &wp, |
| (WINDOWPOS16 *)PTR_SEG_TO_LIN(lParam) ); |
| } |
| return result; |
| |
| case WM_ASKCBFORMATNAME: |
| case WM_COMPAREITEM: |
| case WM_DELETEITEM: |
| case WM_DEVMODECHANGE: |
| case WM_MDIACTIVATE: |
| case WM_MDICREATE: |
| case WM_MEASUREITEM: |
| case WM_PAINTCLIPBOARD: |
| case WM_SIZECLIPBOARD: |
| case WM_WININICHANGE: |
| fprintf( stderr, "CallWindowProc16To32: message %04x needs translation\n", msg ); |
| |
| default: /* No translation needed */ |
| return CallWndProc32( func, hwnd, msg, (WPARAM32)wParam, lParam ); |
| } |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProc16To32W |
| * |
| * Call a 32-bit window procedure, translating the 16-bit args. |
| */ |
| static LRESULT WINPROC_CallProc16To32W(WNDPROC32 func, HWND16 hwnd, UINT16 msg, |
| WPARAM16 wParam, LPARAM lParam ) |
| { |
| LRESULT result = 0; |
| |
| switch(msg) |
| { |
| case WM_GETTEXT: |
| case WM_SETTEXT: |
| return WINPROC_CallProc32ATo32W( func, hwnd, msg, wParam, |
| (LPARAM)PTR_SEG_TO_LIN(lParam) ); |
| |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { |
| CREATESTRUCT16 *pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam); |
| CREATESTRUCT32A cs; |
| |
| STRUCT32_CREATESTRUCT16to32A( pcs16, &cs ); |
| cs.lpszName = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszName); |
| cs.lpszClass = (LPCSTR)PTR_SEG_TO_LIN(pcs16->lpszClass); |
| result = WINPROC_CallProc32ATo32W( func, hwnd, msg, wParam, |
| (LPARAM)&cs ); |
| pcs16 = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam); |
| STRUCT32_CREATESTRUCT32Ato16( &cs, pcs16 ); |
| } |
| return result; |
| |
| default: /* No Unicode translation needed */ |
| return WINPROC_CallProc16To32A( func, hwnd, msg, wParam, lParam ); |
| } |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProc32ATo16 |
| * |
| * Call a 16-bit window procedure, translating the 32-bit args. |
| */ |
| static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, WORD ds, HWND32 hwnd, |
| UINT32 msg, WPARAM32 wParam, |
| LPARAM lParam ) |
| { |
| LRESULT result; |
| |
| switch(msg) |
| { |
| case WM_ACTIVATE: |
| case WM_CHARTOITEM: |
| case WM_COMMAND: |
| case WM_HSCROLL: |
| case WM_VKEYTOITEM: |
| case WM_VSCROLL: |
| return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| MAKELPARAM( (HWND16)lParam, HIWORD(wParam) ) ); |
| |
| case WM_CTLCOLORMSGBOX: |
| case WM_CTLCOLOREDIT: |
| case WM_CTLCOLORLISTBOX: |
| case WM_CTLCOLORBTN: |
| case WM_CTLCOLORDLG: |
| case WM_CTLCOLORSCROLLBAR: |
| case WM_CTLCOLORSTATIC: |
| return CallWndProc16( func, ds, hwnd, WM_CTLCOLOR, (WPARAM16)wParam, |
| MAKELPARAM( (HWND16)lParam, |
| (WORD)msg - WM_CTLCOLORMSGBOX ) ); |
| case WM_DRAWITEM: |
| { |
| DRAWITEMSTRUCT32 *dis32 = (DRAWITEMSTRUCT32 *)lParam; |
| DRAWITEMSTRUCT16 *dis = SEGPTR_NEW(DRAWITEMSTRUCT16); |
| if (!dis) return 0; |
| dis->CtlType = (UINT16)dis32->CtlType; |
| dis->CtlID = (UINT16)dis32->CtlID; |
| dis->itemID = (UINT16)dis32->itemID; |
| dis->itemAction = (UINT16)dis32->itemAction; |
| dis->itemState = (UINT16)dis32->itemState; |
| dis->hwndItem = (HWND16)dis32->hwndItem; |
| dis->hDC = (HDC16)dis32->hDC; |
| dis->itemData = dis32->itemData; |
| CONV_RECT32TO16( &dis32->rcItem, &dis->rcItem ); |
| result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| (LPARAM)SEGPTR_GET(dis) ); |
| /* We don't bother to translate it back */ |
| SEGPTR_FREE(dis); |
| } |
| return result; |
| |
| case WM_GETMINMAXINFO: |
| { |
| MINMAXINFO16 *mmi = SEGPTR_NEW(MINMAXINFO16); |
| if (!mmi) return 0; |
| STRUCT32_MINMAXINFO32to16( (MINMAXINFO32 *)lParam, mmi ); |
| result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| (LPARAM)SEGPTR_GET(mmi) ); |
| STRUCT32_MINMAXINFO16to32( mmi, (MINMAXINFO32 *)lParam ); |
| SEGPTR_FREE(mmi); |
| } |
| return result; |
| |
| case WM_GETTEXT: |
| { |
| LPSTR str; |
| wParam = MIN( wParam, 0xff80 ); /* Size must be < 64K */ |
| if (!(str = SEGPTR_ALLOC( wParam ))) return 0; |
| result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| (LPARAM)SEGPTR_GET(str) ); |
| if (result > 0) memcpy( (LPSTR)lParam, str, result ); |
| SEGPTR_FREE(str); |
| } |
| return result; |
| |
| case WM_MDISETMENU: |
| return CallWndProc16( func, ds, hwnd, msg, TRUE /* FIXME? */, |
| MAKELPARAM( (HMENU16)LOWORD(lParam), |
| (HMENU16)HIWORD(lParam) ) ); |
| case WM_MENUCHAR: |
| case WM_MENUSELECT: |
| return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)LOWORD(wParam), |
| MAKELPARAM( HIWORD(wParam), (HMENU16)lParam ) ); |
| case WM_NCCALCSIZE: |
| { |
| NCCALCSIZE_PARAMS32 *nc32 = (NCCALCSIZE_PARAMS32 *)lParam; |
| NCCALCSIZE_PARAMS16 *nc; |
| WINDOWPOS16 *wp = NULL; |
| |
| if (!(nc = SEGPTR_NEW(NCCALCSIZE_PARAMS16))) return 0; |
| CONV_RECT32TO16( &nc32->rgrc[0], &nc->rgrc[0] ); |
| if (wParam) |
| { |
| CONV_RECT32TO16( &nc32->rgrc[1], &nc->rgrc[1] ); |
| CONV_RECT32TO16( &nc32->rgrc[2], &nc->rgrc[2] ); |
| if (!(wp = SEGPTR_NEW(WINDOWPOS16))) |
| { |
| SEGPTR_FREE(nc); |
| return 0; |
| } |
| STRUCT32_WINDOWPOS32to16( nc32->lppos, wp ); |
| nc->lppos = SEGPTR_GET(wp); |
| } |
| result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| (LPARAM)SEGPTR_GET(nc) ); |
| CONV_RECT16TO32( &nc->rgrc[0], &nc32->rgrc[0] ); |
| if (wParam) |
| { |
| CONV_RECT16TO32( &nc->rgrc[1], &nc32->rgrc[1] ); |
| CONV_RECT16TO32( &nc->rgrc[2], &nc32->rgrc[2] ); |
| STRUCT32_WINDOWPOS16to32( (WINDOWPOS16 *)PTR_SEG_TO_LIN(nc->lppos), |
| nc32->lppos ); |
| SEGPTR_FREE(wp); |
| } |
| SEGPTR_FREE(nc); |
| } |
| return result; |
| |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { |
| CREATESTRUCT16 *cs; |
| CREATESTRUCT32A *cs32 = (CREATESTRUCT32A *)lParam; |
| LPSTR name, cls; |
| |
| if (!(cs = SEGPTR_NEW(CREATESTRUCT16))) return 0; |
| STRUCT32_CREATESTRUCT32Ato16( cs32, cs ); |
| name = SEGPTR_STRDUP( cs32->lpszName ); |
| cls = SEGPTR_STRDUP( cs32->lpszClass ); |
| cs->lpszName = SEGPTR_GET(name); |
| cs->lpszClass = SEGPTR_GET(cls); |
| result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| (LPARAM)SEGPTR_GET(cs) ); |
| STRUCT32_CREATESTRUCT16to32A( cs, cs32 ); |
| if (PTR_SEG_TO_LIN(cs->lpszName) != name) |
| cs32->lpszName = (LPCSTR)PTR_SEG_TO_LIN( cs->lpszName ); |
| if (PTR_SEG_TO_LIN(cs->lpszClass) != cls) |
| cs32->lpszClass = (LPCSTR)PTR_SEG_TO_LIN( cs->lpszClass ); |
| SEGPTR_FREE(name); |
| SEGPTR_FREE(cls); |
| SEGPTR_FREE(cs); |
| } |
| return result; |
| |
| case WM_PARENTNOTIFY: |
| if ((wParam == WM_CREATE) || (wParam == WM_DESTROY)) |
| return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| MAKELPARAM( (HWND16)lParam, LOWORD(wParam))); |
| case WM_SETTEXT: |
| { |
| LPSTR str = SEGPTR_STRDUP( (LPSTR)lParam ); |
| if (!str) return 0; |
| result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| (LPARAM)SEGPTR_GET(str) ); |
| SEGPTR_FREE(str); |
| } |
| return result; |
| |
| case WM_WINDOWPOSCHANGING: |
| case WM_WINDOWPOSCHANGED: |
| { |
| WINDOWPOS16 *wp; |
| if (!(wp = SEGPTR_NEW(WINDOWPOS16))) return 0; |
| STRUCT32_WINDOWPOS32to16( (WINDOWPOS32 *)lParam, wp ); |
| result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| (LPARAM)SEGPTR_GET(wp) ); |
| STRUCT32_WINDOWPOS16to32( wp, (WINDOWPOS32 *)lParam ); |
| SEGPTR_FREE(wp); |
| } |
| return result; |
| |
| case WM_ASKCBFORMATNAME: |
| case WM_COMPAREITEM: |
| case WM_DELETEITEM: |
| case WM_DEVMODECHANGE: |
| case WM_MDIACTIVATE: |
| case WM_MDICREATE: |
| case WM_MEASUREITEM: |
| case WM_PAINTCLIPBOARD: |
| case WM_SIZECLIPBOARD: |
| case WM_WININICHANGE: |
| fprintf( stderr, "CallWindowProc32To16: message %04x needs translation\n", msg ); |
| |
| default: /* No translation needed */ |
| return CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, lParam ); |
| } |
| } |
| |
| |
| /********************************************************************** |
| * WINPROC_CallProc32WTo16 |
| * |
| * Call a 16-bit window procedure, translating the 32-bit args. |
| */ |
| static LRESULT WINPROC_CallProc32WTo16( WNDPROC16 func, WORD ds, HWND32 hwnd, |
| UINT32 msg, WPARAM32 wParam, |
| LPARAM lParam ) |
| { |
| LRESULT result; |
| |
| switch(msg) |
| { |
| case WM_GETTEXT: |
| { |
| LPSTR str; |
| wParam = MIN( wParam, 0xff80 ); /* Size must be < 64K */ |
| if (!(str = SEGPTR_ALLOC( wParam ))) return 0; |
| result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| (LPARAM)SEGPTR_GET(str) ); |
| if (result > 0) STRING32_AnsiToUni( (LPWSTR)lParam, str ); |
| SEGPTR_FREE(str); |
| } |
| return result; |
| |
| case WM_NCCREATE: |
| case WM_CREATE: |
| { |
| CREATESTRUCT32A cs = *(CREATESTRUCT32A *)lParam; |
| cs.lpszName = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName ); |
| cs.lpszClass = STRING32_DupUniToAnsi( (LPCWSTR)cs.lpszName ); |
| result = WINPROC_CallProc32ATo16( func, ds, hwnd, msg, wParam, |
| (LPARAM)&cs ); |
| free( (LPVOID)cs.lpszName ); |
| free( (LPVOID)cs.lpszClass ); |
| } |
| return result; |
| |
| case WM_SETTEXT: |
| { |
| LPSTR str = SEGPTR_ALLOC( STRING32_lstrlenW( (LPWSTR)lParam ) ); |
| if (!str) return 0; |
| STRING32_UniToAnsi( str, (LPWSTR)lParam ); |
| result = CallWndProc16( func, ds, hwnd, msg, (WPARAM16)wParam, |
| (LPARAM)SEGPTR_GET(str) ); |
| SEGPTR_FREE(str); |
| } |
| return result; |
| |
| default: /* No Unicode translation needed */ |
| return WINPROC_CallProc32ATo16( func, ds, hwnd, msg, wParam, lParam ); |
| } |
| } |
| |
| |
| /********************************************************************** |
| * CallWindowProc16 (USER.122) |
| */ |
| LRESULT CallWindowProc16( WNDPROC16 func, HWND16 hwnd, UINT16 msg, |
| WPARAM16 wParam, LPARAM lParam ) |
| { |
| WND *wndPtr; |
| |
| switch(WINPROC_GetWinProcType(func)) |
| { |
| case WIN_PROC_16: |
| wndPtr = WIN_FindWndPtr( hwnd ); |
| return CallWndProc16( (FARPROC)func, |
| wndPtr ? wndPtr->hInstance : CURRENT_DS, |
| hwnd, msg, wParam, lParam ); |
| case WIN_PROC_32A: |
| return WINPROC_CallProc16To32A( WINPROC_GetWinProcFunc(func), |
| hwnd, msg, wParam, lParam ); |
| case WIN_PROC_32W: |
| return WINPROC_CallProc16To32W( WINPROC_GetWinProcFunc(func), |
| hwnd, msg, wParam, lParam ); |
| default: |
| fprintf(stderr, "CallWindowProc16: invalid func %08x\n", (UINT32)func); |
| return 0; |
| } |
| } |
| |
| |
| /********************************************************************** |
| * CallWindowProc32A (USER32.17) |
| */ |
| LRESULT CallWindowProc32A( WNDPROC32 func, HWND32 hwnd, UINT32 msg, |
| WPARAM32 wParam, LPARAM lParam ) |
| { |
| WND *wndPtr; |
| |
| switch(WINPROC_GetWinProcType( (WNDPROC16)func )) |
| { |
| case WIN_PROC_16: |
| wndPtr = WIN_FindWndPtr( hwnd ); |
| return WINPROC_CallProc32ATo16( (FARPROC)func, |
| wndPtr ? wndPtr->hInstance : CURRENT_DS, |
| hwnd, msg, wParam, lParam ); |
| case WIN_PROC_32A: |
| return CallWndProc32( WINPROC_GetWinProcFunc( (WNDPROC16)func ), |
| hwnd, msg, wParam, lParam ); |
| case WIN_PROC_32W: |
| return WINPROC_CallProc32ATo32W(WINPROC_GetWinProcFunc((WNDPROC16)func), |
| hwnd, msg, wParam, lParam ); |
| default: |
| fprintf(stderr,"CallWindowProc32A: invalid func %08x\n",(UINT32)func); |
| return 0; |
| } |
| } |
| |
| |
| /********************************************************************** |
| * CallWindowProc32W (USER32.18) |
| */ |
| LRESULT CallWindowProc32W( WNDPROC32 func, HWND32 hwnd, UINT32 msg, |
| WPARAM32 wParam, LPARAM lParam ) |
| { |
| WND *wndPtr; |
| |
| switch(WINPROC_GetWinProcType( (WNDPROC16)func )) |
| { |
| case WIN_PROC_16: |
| wndPtr = WIN_FindWndPtr( hwnd ); |
| return WINPROC_CallProc32WTo16( (FARPROC)func, |
| wndPtr ? wndPtr->hInstance : CURRENT_DS, |
| hwnd, msg, wParam, lParam ); |
| case WIN_PROC_32A: |
| return WINPROC_CallProc32WTo32A(WINPROC_GetWinProcFunc((WNDPROC16)func), |
| hwnd, msg, wParam, lParam ); |
| case WIN_PROC_32W: |
| return CallWndProc32( WINPROC_GetWinProcFunc( (WNDPROC16)func ), |
| hwnd, msg, wParam, lParam ); |
| default: |
| fprintf(stderr,"CallWindowProc32W: invalid func %08x\n",(UINT32)func); |
| return 0; |
| } |
| } |