Release 960521
Tue May 21 14:06:07 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [controls/button.c]
Made ButtonWndProc a 32-bit window procedure.
* [controls/desktop.c]
Made DesktopWndProc a 32-bit window procedure.
Added handling of WM_SETCURSOR.
* [controls/menu.c]
Allocate menu items and strings on the 32-bit system heap.
Implemented Win32 versions for ChangeMenu, InsertMenu, ModifyMenu,
AppendMenu and LoadMenuIndirect.
* [controls/widgets.c]
Added possibility to have 32-bit built-in classes.
* [files/drive.c]
Implemented GetLogicalDrive() and GetLogicalDriveStrings().
* [misc/spy.c] [include/spy.h]
Added support for spying Win32 messages.
* [loader/builtin.c]
Fixed bug in -dll option parsing.
* [memory/local.c]
Added back the change by Huw D. M. Davies to free the block in
LocalRealloc() before allocating the new one.
* [objects/bitmap.c] [objects/cursoricon.c] [objects/oembitmap.c]
Fixed bug in bitmap size that caused memory corruption for 24bpp.
* [windows/defwnd.c]
Implemented Win32 version of DefWindowProc().
* [windows/dialog.c]
Implemented Win32 version of SendDlgItemMessage,
Get/SetDlgItemText and Get/SetDlgItemInt.
* [windows/mdi.c]
Implemented Win32 version of DefFrameProc() and DefMDIChildProc().
Don't make a copy of the OBM bitmaps for every MDI window.
* [windows/message.c]
Implemented Win32 version of SendMessage().
* [windows/winproc.c] [windows/class.c] [windows/win.c]
New scheme for 32-bit window procedures to replace aliases. All
32-bit window procedure get a 16-bit address pointing to a
WINDOWPROC structure.
Implemented Ansi<->Unicode translation for CallWindowProc().
Added translation of WM_DRAWITEM between Win16 and Win32.
* [windows/win.c] [include/callback.h]
Added ugly hack to build CREATESTRUCT on the stack when sending
WM_NCCREATE.
Implemented Win32 version of Get/SetWindowWord/Long and
Get/SetWindowText.
Fri May 17 10:20:16 1996 Albrecht Kleine <kleine@ak.sax.de>
* [controls/button.c]
Avoid gray text on gray background in disabled push buttons
using a b/w raster and some raster operations (PatBlt,BitBlt).
* [objects/text.c]
DrawText(): don't draw an underbar anymore if DT_CALCRECT is set.
diff --git a/windows/winproc.c b/windows/winproc.c
index 6e25b20..16ce933 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -7,21 +7,233 @@
#include <stdio.h>
#include "windows.h"
-#include "alias.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_CallProc16To32
+ * 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_CallProc16To32( WNDPROC32 func, HWND16 hwnd, UINT16 msg,
+static LRESULT WINPROC_CallProc16To32A(WNDPROC32 func, HWND16 hwnd, UINT16 msg,
WPARAM16 wParam, LPARAM lParam )
{
LRESULT result;
@@ -41,6 +253,24 @@
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;
@@ -53,7 +283,6 @@
return result;
case WM_GETTEXT:
- /* FIXME: Unicode */
return CallWndProc32( func, hwnd, msg, wParam,
(LPARAM)PTR_SEG_TO_LIN(lParam) );
case WM_MDISETMENU:
@@ -148,7 +377,6 @@
case WM_COMPAREITEM:
case WM_DELETEITEM:
case WM_DEVMODECHANGE:
- case WM_DRAWITEM:
case WM_MDIACTIVATE:
case WM_MDICREATE:
case WM_MEASUREITEM:
@@ -164,13 +392,52 @@
/**********************************************************************
- * WINPROC_CallProc32To16
+ * 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_CallProc32To16( WNDPROC16 func, WORD ds, HWND32 hwnd,
- UINT32 msg, WPARAM32 wParam,
- LPARAM lParam )
+static LRESULT WINPROC_CallProc32ATo16( WNDPROC16 func, WORD ds, HWND32 hwnd,
+ UINT32 msg, WPARAM32 wParam,
+ LPARAM lParam )
{
LRESULT result;
@@ -195,6 +462,27 @@
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);
@@ -319,7 +607,6 @@
case WM_COMPAREITEM:
case WM_DELETEITEM:
case WM_DEVMODECHANGE:
- case WM_DRAWITEM:
case WM_MDIACTIVATE:
case WM_MDICREATE:
case WM_MEASUREITEM:
@@ -335,29 +622,85 @@
/**********************************************************************
+ * 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 )
{
- FUNCTIONALIAS *a;
+ WND *wndPtr;
- /* check if we have something better than 16 bit relays */
- if (!ALIAS_UseAliases || !(a=ALIAS_LookupAlias((DWORD)func)) ||
- (!a->wine && !a->win32))
+ switch(WINPROC_GetWinProcType(func))
{
- WND *wndPtr = WIN_FindWndPtr( hwnd );
+ 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;
}
-
- if(a->wine)
- return ((LONG(*)(WORD,WORD,WORD,LONG))(a->wine))
- (hwnd,msg,wParam,lParam);
-
- return WINPROC_CallProc16To32( (WNDPROC32)a->win32, hwnd, msg,
- wParam, lParam );
}
@@ -367,30 +710,25 @@
LRESULT CallWindowProc32A( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
WPARAM32 wParam, LPARAM lParam )
{
- FUNCTIONALIAS *a = NULL;
WND *wndPtr;
- WORD ds;
- /* check if we have something better than 16 bit relays */
- if (ALIAS_UseAliases && (a=ALIAS_LookupAlias((DWORD)func)) &&
- (a->wine || a->win32))
+ switch(WINPROC_GetWinProcType( (WNDPROC16)func ))
{
- /* FIXME: Unicode */
- if (a->wine)
- return ((WNDPROC32)a->wine)(hwnd,msg,wParam,lParam);
- else return CallWndProc32( func, hwnd, msg, wParam, lParam );
- }
- wndPtr = WIN_FindWndPtr( hwnd );
- ds = wndPtr ? wndPtr->hInstance : CURRENT_DS;
-
- if (!a)
- {
- fprintf( stderr, "CallWindowProc32A: no alias for %p\n", 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;
}
-
- return WINPROC_CallProc32To16( (WNDPROC16)a->win16, ds, hwnd, msg,
- wParam, lParam );
}
@@ -400,6 +738,23 @@
LRESULT CallWindowProc32W( WNDPROC32 func, HWND32 hwnd, UINT32 msg,
WPARAM32 wParam, LPARAM lParam )
{
- /* FIXME: Unicode translation */
- return CallWindowProc32A( func, hwnd, msg, wParam, 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;
+ }
}