user32: Reimplement accelerator functions to use 32-bit user handles instead of 16-bit functions.

This commit is contained in:
Alexandre Julliard 2009-10-15 17:35:06 +02:00
parent a187b43ddd
commit a7adbf7849
3 changed files with 148 additions and 233 deletions

View File

@ -5344,52 +5344,26 @@ static BOOL translate_accelerator( HWND hWnd, UINT message, WPARAM wParam, LPARA
*/ */
INT WINAPI TranslateAcceleratorA( HWND hWnd, HACCEL hAccel, LPMSG msg ) INT WINAPI TranslateAcceleratorA( HWND hWnd, HACCEL hAccel, LPMSG msg )
{ {
/* YES, Accel16! */
LPACCEL16 lpAccelTbl;
int i;
WPARAM wParam;
if (!hWnd || !msg) return 0;
if (!hAccel || !(lpAccelTbl = (LPACCEL16) LockResource16(HACCEL_16(hAccel))))
{
WARN_(accel)("invalid accel handle=%p\n", hAccel);
return 0;
}
wParam = msg->wParam;
switch (msg->message) switch (msg->message)
{ {
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_SYSKEYDOWN: case WM_SYSKEYDOWN:
break; return TranslateAcceleratorW( hWnd, hAccel, msg );
case WM_CHAR: case WM_CHAR:
case WM_SYSCHAR: case WM_SYSCHAR:
{ {
char ch = LOWORD(wParam); MSG msgW = *msg;
char ch = LOWORD(msg->wParam);
WCHAR wch; WCHAR wch;
MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1); MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wch, 1);
wParam = MAKEWPARAM(wch, HIWORD(wParam)); msgW.wParam = MAKEWPARAM(wch, HIWORD(msg->wParam));
return TranslateAcceleratorW( hWnd, hAccel, &msgW );
} }
break;
default: default:
return 0; return 0;
} }
TRACE_(accel)("hAccel %p, hWnd %p, msg->hwnd %p, msg->message %04x, wParam %08lx, lParam %08lx\n",
hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
i = 0;
do
{
if (translate_accelerator( hWnd, msg->message, wParam, msg->lParam,
lpAccelTbl[i].fVirt, lpAccelTbl[i].key, lpAccelTbl[i].cmd))
return 1;
} while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
return 0;
} }
/********************************************************************** /**********************************************************************
@ -5397,39 +5371,32 @@ INT WINAPI TranslateAcceleratorA( HWND hWnd, HACCEL hAccel, LPMSG msg )
*/ */
INT WINAPI TranslateAcceleratorW( HWND hWnd, HACCEL hAccel, LPMSG msg ) INT WINAPI TranslateAcceleratorW( HWND hWnd, HACCEL hAccel, LPMSG msg )
{ {
/* YES, Accel16! */ ACCEL data[32], *ptr = data;
LPACCEL16 lpAccelTbl; int i, count;
int i;
if (!hWnd || !msg) return 0; if (!hWnd) return 0;
if (!hAccel || !(lpAccelTbl = (LPACCEL16) LockResource16(HACCEL_16(hAccel)))) if (msg->message != WM_KEYDOWN &&
{ msg->message != WM_SYSKEYDOWN &&
WARN_(accel)("invalid accel handle=%p\n", hAccel); msg->message != WM_CHAR &&
msg->message != WM_SYSCHAR)
return 0; return 0;
}
switch (msg->message)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_CHAR:
case WM_SYSCHAR:
break;
default:
return 0;
}
TRACE_(accel)("hAccel %p, hWnd %p, msg->hwnd %p, msg->message %04x, wParam %08lx, lParam %08lx\n", TRACE_(accel)("hAccel %p, hWnd %p, msg->hwnd %p, msg->message %04x, wParam %08lx, lParam %08lx\n",
hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam); hAccel,hWnd,msg->hwnd,msg->message,msg->wParam,msg->lParam);
i = 0;
do if (!(count = CopyAcceleratorTableW( hAccel, NULL, 0 ))) return 0;
if (count > sizeof(data)/sizeof(data[0]))
{
if (!(ptr = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ptr) ))) return 0;
}
count = CopyAcceleratorTableW( hAccel, ptr, count );
for (i = 0; i < count; i++)
{ {
if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam, if (translate_accelerator( hWnd, msg->message, msg->wParam, msg->lParam,
lpAccelTbl[i].fVirt, lpAccelTbl[i].key, lpAccelTbl[i].cmd)) ptr[i].fVirt, ptr[i].key, ptr[i].cmd))
return 1; break;
} while ((lpAccelTbl[i++].fVirt & 0x80) == 0); }
if (ptr != data) HeapFree( GetProcessHeap(), 0, ptr );
return 0; return (i < count);
} }

View File

@ -2,7 +2,7 @@
* USER resource functions * USER resource functions
* *
* Copyright 1993 Robert J. Amstadt * Copyright 1993 Robert J. Amstadt
* Copyright 1995 Alexandre Julliard * Copyright 1995, 2009 Alexandre Julliard
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -30,6 +30,7 @@
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "wownt32.h" #include "wownt32.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "user_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(resource); WINE_DEFAULT_DEBUG_CHANNEL(resource);
WINE_DECLARE_DEBUG_CHANNEL(accel); WINE_DECLARE_DEBUG_CHANNEL(accel);
@ -41,7 +42,15 @@ typedef struct
WORD key; WORD key;
WORD cmd; WORD cmd;
WORD pad; WORD pad;
} PE_ACCEL, *LPPE_ACCEL; } PE_ACCEL;
/* the accelerator user object */
struct accelerator
{
struct user_object obj;
unsigned int count;
PE_ACCEL table[1];
};
/********************************************************************** /**********************************************************************
* LoadAccelerators [USER.177] * LoadAccelerators [USER.177]
@ -63,50 +72,28 @@ HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, LPCSTR lpTableName)
/********************************************************************** /**********************************************************************
* LoadAcceleratorsW (USER32.@) * LoadAcceleratorsW (USER32.@)
* The image layout seems to look like this (not 100% sure):
* 00: WORD type type of accelerator
* 02: WORD event
* 04: WORD IDval
* 06: WORD pad (to DWORD boundary)
*/ */
HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName) HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance, LPCWSTR name)
{ {
HRSRC hRsrc; struct accelerator *accel;
HACCEL hMem; const PE_ACCEL *table;
HACCEL16 hRetval=0; HRSRC rsrc;
DWORD size; HACCEL handle;
DWORD count;
if (HIWORD(lpTableName)) if (!(rsrc = FindResourceW( instance, name, (LPWSTR)RT_ACCELERATOR ))) return 0;
TRACE_(accel)("%p '%s'\n", instance, (const char *)( lpTableName ) ); table = LoadResource( instance, rsrc );
else count = SizeofResource( instance, rsrc ) / sizeof(*table);
TRACE_(accel)("%p 0x%04x\n", instance, LOWORD(lpTableName) ); if (!count) return 0;
accel = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct accelerator, table[count] ));
if (!(hRsrc = FindResourceW( instance, lpTableName, (LPWSTR)RT_ACCELERATOR ))) if (!accel) return 0;
{ accel->count = count;
WARN_(accel)("couldn't find accelerator table resource\n"); memcpy( accel->table, table, count * sizeof(*table) );
} else { if (!(handle = alloc_user_handle( &accel->obj, USER_ACCEL )))
hMem = LoadResource( instance, hRsrc ); HeapFree( GetProcessHeap(), 0, accel );
size = SizeofResource( instance, hRsrc ); return handle;
if(size>=sizeof(PE_ACCEL)) TRACE_(accel)("%p %s returning %p\n", instance, debugstr_w(name), handle );
{ return handle;
LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
LPACCEL16 accel16;
int i,nrofaccells = size/sizeof(PE_ACCEL);
hRetval = GlobalAlloc16(0,sizeof(ACCEL16)*nrofaccells);
accel16 = (LPACCEL16)GlobalLock16(hRetval);
for (i=0;i<nrofaccells;i++) {
accel16[i].fVirt = accel_table[i].fVirt & 0x7f;
accel16[i].key = accel_table[i].key;
if( !(accel16[i].fVirt & FVIRTKEY) )
accel16[i].key &= 0x00ff;
accel16[i].cmd = accel_table[i].cmd;
}
accel16[i-1].fVirt |= 0x80;
}
}
TRACE_(accel)("returning HACCEL %p\n", hRsrc);
return HACCEL_32(hRetval);
} }
/*********************************************************************** /***********************************************************************
@ -133,165 +120,119 @@ HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
/********************************************************************** /**********************************************************************
* CopyAcceleratorTableA (USER32.@) * CopyAcceleratorTableA (USER32.@)
*/ */
INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries) INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT count)
{ {
return CopyAcceleratorTableW(src, dst, entries); char ch;
int i, ret = CopyAcceleratorTableW( src, dst, count );
if (ret && dst)
{
for (i = 0; i < ret; i++)
{
if (dst[i].fVirt & FVIRTKEY) continue;
WideCharToMultiByte( CP_ACP, 0, &dst[i].key, 1, &ch, 1, NULL, NULL );
dst[i].key = ch;
}
}
return ret;
} }
/********************************************************************** /**********************************************************************
* CopyAcceleratorTableW (USER32.@) * CopyAcceleratorTableW (USER32.@)
*
* By mortene@pvv.org 980321
*/ */
INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst, INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst, INT count)
INT entries)
{ {
int i,xsize; struct accelerator *accel;
LPACCEL16 accel = (LPACCEL16)GlobalLock16(HACCEL_16(src)); int i;
BOOL done = FALSE;
/* Do parameter checking to avoid the explosions and the screaming if (!(accel = get_user_handle_ptr( src, USER_ACCEL ))) return 0;
as far as possible. */ if (accel == OBJ_OTHER_PROCESS)
if((dst && (entries < 1)) || (src == NULL) || !accel) { {
WARN_(accel)("Application sent invalid parameters (%p %p %d).\n", FIXME( "other process handle %p?\n", src );
src, dst, entries); return 0;
return 0;
}
xsize = GlobalSize16(HACCEL_16(src))/sizeof(ACCEL16);
if (xsize<entries) entries=xsize;
i=0;
while(!done) {
/* Spit out some debugging information. */
TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
i, accel[i].fVirt, accel[i].key, accel[i].cmd);
/* Copy data to the destination structure array (if dst == NULL,
we're just supposed to count the number of entries). */
if(dst) {
dst[i].fVirt = accel[i].fVirt&0x7f;
dst[i].key = accel[i].key;
dst[i].cmd = accel[i].cmd;
/* Check if we've reached the end of the application supplied
accelerator table. */
if(i+1 == entries)
done = TRUE;
} }
if (dst)
/* The highest order bit seems to mark the end of the accelerator {
resource table, but not always. Use GlobalSize() check too. */ if (count > accel->count) count = accel->count;
if((accel[i].fVirt & 0x80) != 0) done = TRUE; for (i = 0; i < count; i++)
{
i++; dst[i].fVirt = accel->table[i].fVirt & 0x7f;
} dst[i].key = accel->table[i].key;
dst[i].cmd = accel->table[i].cmd;
return i; }
}
else count = accel->count;
release_user_handle_ptr( accel );
return count;
} }
/********************************************************************* /*********************************************************************
* CreateAcceleratorTableA (USER32.@) * CreateAcceleratorTableA (USER32.@)
*
* By mortene@pvv.org 980321
*/ */
HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries) HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT count)
{ {
HACCEL hAccel; struct accelerator *accel;
LPACCEL16 accel; HACCEL handle;
int i; int i;
/* Do parameter checking just in case someone's trying to be if (count < 1)
funny. */ {
if(cEntries < 1) { SetLastError( ERROR_INVALID_PARAMETER );
WARN_(accel)("Application sent invalid parameters (%p %d).\n", return 0;
lpaccel, cEntries); }
SetLastError(ERROR_INVALID_PARAMETER); accel = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct accelerator, table[count] ));
return NULL; if (!accel) return 0;
} accel->count = count;
for (i = 0; i < count; i++)
/* Allocate memory and copy the table. */ {
hAccel = HACCEL_32(GlobalAlloc16(0,cEntries*sizeof(ACCEL16))); accel->table[i].fVirt = lpaccel[i].fVirt;
accel->table[i].cmd = lpaccel[i].cmd;
TRACE_(accel)("handle %p\n", hAccel); if (!(lpaccel[i].fVirt & FVIRTKEY))
if(!hAccel) { {
ERR_(accel)("Out of memory.\n"); char ch = lpaccel[i].key;
SetLastError(ERROR_NOT_ENOUGH_MEMORY); MultiByteToWideChar( CP_ACP, 0, &ch, 1, &accel->table[i].key, 1 );
return NULL; }
} else accel->table[i].key = lpaccel[i].key;
accel = GlobalLock16(HACCEL_16(hAccel)); }
for (i=0;i<cEntries;i++) { if (!(handle = alloc_user_handle( &accel->obj, USER_ACCEL )))
accel[i].fVirt = lpaccel[i].fVirt&0x7f; HeapFree( GetProcessHeap(), 0, accel );
accel[i].key = lpaccel[i].key; TRACE_(accel)("returning %p\n", handle );
if( !(accel[i].fVirt & FVIRTKEY) ) return handle;
accel[i].key &= 0x00ff;
accel[i].cmd = lpaccel[i].cmd;
}
/* Set the end-of-table terminator. */
accel[cEntries-1].fVirt |= 0x80;
TRACE_(accel)("Allocated accelerator handle %p with %d entries\n", hAccel,cEntries);
return hAccel;
} }
/********************************************************************* /*********************************************************************
* CreateAcceleratorTableW (USER32.@) * CreateAcceleratorTableW (USER32.@)
*
*
*/ */
HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries) HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT count)
{ {
HACCEL hAccel; struct accelerator *accel;
LPACCEL16 accel; HACCEL handle;
int i; int i;
char ckey;
/* Do parameter checking just in case someone's trying to be if (count < 1)
funny. */ {
if(cEntries < 1) { SetLastError( ERROR_INVALID_PARAMETER );
WARN_(accel)("Application sent invalid parameters (%p %d).\n", return 0;
lpaccel, cEntries); }
SetLastError(ERROR_INVALID_PARAMETER); accel = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct accelerator, table[count] ));
return NULL; if (!accel) return 0;
} accel->count = count;
for (i = 0; i < count; i++)
/* Allocate memory and copy the table. */ {
hAccel = HACCEL_32(GlobalAlloc16(0,cEntries*sizeof(ACCEL16))); accel->table[i].fVirt = lpaccel[i].fVirt;
accel->table[i].key = lpaccel[i].key;
TRACE_(accel)("handle %p\n", hAccel); accel->table[i].cmd = lpaccel[i].cmd;
if(!hAccel) { }
ERR_(accel)("Out of memory.\n"); if (!(handle = alloc_user_handle( &accel->obj, USER_ACCEL )))
SetLastError(ERROR_NOT_ENOUGH_MEMORY); HeapFree( GetProcessHeap(), 0, accel );
return NULL; TRACE_(accel)("returning %p\n", handle );
} return handle;
accel = GlobalLock16(HACCEL_16(hAccel));
for (i=0;i<cEntries;i++) {
accel[i].fVirt = lpaccel[i].fVirt&0x7f;
if( !(accel[i].fVirt & FVIRTKEY) ) {
ckey = (char) lpaccel[i].key;
if(!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, &accel[i].key, 1))
WARN_(accel)("Error converting ASCII accelerator table to Unicode\n");
}
else
accel[i].key = lpaccel[i].key;
accel[i].cmd = lpaccel[i].cmd;
}
/* Set the end-of-table terminator. */
accel[cEntries-1].fVirt |= 0x80;
TRACE_(accel)("Allocated accelerator handle %p\n", hAccel);
return hAccel;
} }
/****************************************************************************** /******************************************************************************
* DestroyAcceleratorTable [USER32.@] * DestroyAcceleratorTable [USER32.@]
* Destroys an accelerator table * Destroys an accelerator table
* *
* NOTES
* By mortene@pvv.org 980321
*
* PARAMS * PARAMS
* handle [I] Handle to accelerator table * handle [I] Handle to accelerator table
* *
@ -301,9 +242,15 @@ HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
*/ */
BOOL WINAPI DestroyAcceleratorTable( HACCEL handle ) BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
{ {
if( !handle ) struct accelerator *accel;
if (!(accel = free_user_handle( handle, USER_ACCEL ))) return FALSE;
if (accel == OBJ_OTHER_PROCESS)
{
FIXME( "other process handle %p?\n", accel );
return FALSE; return FALSE;
return !GlobalFree16(HACCEL_16(handle)); }
return HeapFree( GetProcessHeap(), 0, accel );
} }
/********************************************************************** /**********************************************************************

View File

@ -128,6 +128,7 @@ enum user_obj_type
{ {
USER_WINDOW = 1, /* window */ USER_WINDOW = 1, /* window */
USER_MENU, /* menu */ USER_MENU, /* menu */
USER_ACCEL, /* accelerator */
USER_DWP /* DeferWindowPos structure */ USER_DWP /* DeferWindowPos structure */
}; };