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 )
{
/* 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)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
break;
return TranslateAcceleratorW( hWnd, hAccel, msg );
case WM_CHAR:
case WM_SYSCHAR:
{
char ch = LOWORD(wParam);
MSG msgW = *msg;
char ch = LOWORD(msg->wParam);
WCHAR wch;
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:
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 )
{
/* YES, Accel16! */
LPACCEL16 lpAccelTbl;
int i;
ACCEL data[32], *ptr = data;
int i, count;
if (!hWnd || !msg) return 0;
if (!hWnd) return 0;
if (!hAccel || !(lpAccelTbl = (LPACCEL16) LockResource16(HACCEL_16(hAccel))))
{
WARN_(accel)("invalid accel handle=%p\n", hAccel);
if (msg->message != WM_KEYDOWN &&
msg->message != WM_SYSKEYDOWN &&
msg->message != WM_CHAR &&
msg->message != WM_SYSCHAR)
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",
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,
lpAccelTbl[i].fVirt, lpAccelTbl[i].key, lpAccelTbl[i].cmd))
return 1;
} while ((lpAccelTbl[i++].fVirt & 0x80) == 0);
return 0;
ptr[i].fVirt, ptr[i].key, ptr[i].cmd))
break;
}
if (ptr != data) HeapFree( GetProcessHeap(), 0, ptr );
return (i < count);
}

View File

@ -2,7 +2,7 @@
* USER resource functions
*
* 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
* modify it under the terms of the GNU Lesser General Public
@ -30,6 +30,7 @@
#include "wine/winuser16.h"
#include "wownt32.h"
#include "wine/debug.h"
#include "user_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(resource);
WINE_DECLARE_DEBUG_CHANNEL(accel);
@ -41,7 +42,15 @@ typedef struct
WORD key;
WORD cmd;
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]
@ -63,50 +72,28 @@ HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, LPCSTR lpTableName)
/**********************************************************************
* 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;
HACCEL hMem;
HACCEL16 hRetval=0;
DWORD size;
struct accelerator *accel;
const PE_ACCEL *table;
HRSRC rsrc;
HACCEL handle;
DWORD count;
if (HIWORD(lpTableName))
TRACE_(accel)("%p '%s'\n", instance, (const char *)( lpTableName ) );
else
TRACE_(accel)("%p 0x%04x\n", instance, LOWORD(lpTableName) );
if (!(hRsrc = FindResourceW( instance, lpTableName, (LPWSTR)RT_ACCELERATOR )))
{
WARN_(accel)("couldn't find accelerator table resource\n");
} else {
hMem = LoadResource( instance, hRsrc );
size = SizeofResource( instance, hRsrc );
if(size>=sizeof(PE_ACCEL))
{
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);
if (!(rsrc = FindResourceW( instance, name, (LPWSTR)RT_ACCELERATOR ))) return 0;
table = LoadResource( instance, rsrc );
count = SizeofResource( instance, rsrc ) / sizeof(*table);
if (!count) return 0;
accel = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct accelerator, table[count] ));
if (!accel) return 0;
accel->count = count;
memcpy( accel->table, table, count * sizeof(*table) );
if (!(handle = alloc_user_handle( &accel->obj, USER_ACCEL )))
HeapFree( GetProcessHeap(), 0, accel );
return handle;
TRACE_(accel)("%p %s returning %p\n", instance, debugstr_w(name), handle );
return handle;
}
/***********************************************************************
@ -133,165 +120,119 @@ HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
/**********************************************************************
* 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.@)
*
* By mortene@pvv.org 980321
*/
INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst,
INT entries)
INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst, INT count)
{
int i,xsize;
LPACCEL16 accel = (LPACCEL16)GlobalLock16(HACCEL_16(src));
BOOL done = FALSE;
struct accelerator *accel;
int i;
/* Do parameter checking to avoid the explosions and the screaming
as far as possible. */
if((dst && (entries < 1)) || (src == NULL) || !accel) {
WARN_(accel)("Application sent invalid parameters (%p %p %d).\n",
src, dst, entries);
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 (!(accel = get_user_handle_ptr( src, USER_ACCEL ))) return 0;
if (accel == OBJ_OTHER_PROCESS)
{
FIXME( "other process handle %p?\n", src );
return 0;
}
/* The highest order bit seems to mark the end of the accelerator
resource table, but not always. Use GlobalSize() check too. */
if((accel[i].fVirt & 0x80) != 0) done = TRUE;
i++;
}
return i;
if (dst)
{
if (count > accel->count) count = accel->count;
for (i = 0; i < count; i++)
{
dst[i].fVirt = accel->table[i].fVirt & 0x7f;
dst[i].key = accel->table[i].key;
dst[i].cmd = accel->table[i].cmd;
}
}
else count = accel->count;
release_user_handle_ptr( accel );
return count;
}
/*********************************************************************
* CreateAcceleratorTableA (USER32.@)
*
* By mortene@pvv.org 980321
*/
HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT count)
{
HACCEL hAccel;
LPACCEL16 accel;
int i;
struct accelerator *accel;
HACCEL handle;
int i;
/* Do parameter checking just in case someone's trying to be
funny. */
if(cEntries < 1) {
WARN_(accel)("Application sent invalid parameters (%p %d).\n",
lpaccel, cEntries);
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Allocate memory and copy the table. */
hAccel = HACCEL_32(GlobalAlloc16(0,cEntries*sizeof(ACCEL16)));
TRACE_(accel)("handle %p\n", hAccel);
if(!hAccel) {
ERR_(accel)("Out of memory.\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
accel = GlobalLock16(HACCEL_16(hAccel));
for (i=0;i<cEntries;i++) {
accel[i].fVirt = lpaccel[i].fVirt&0x7f;
accel[i].key = lpaccel[i].key;
if( !(accel[i].fVirt & FVIRTKEY) )
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;
if (count < 1)
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
accel = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct accelerator, table[count] ));
if (!accel) return 0;
accel->count = count;
for (i = 0; i < count; i++)
{
accel->table[i].fVirt = lpaccel[i].fVirt;
accel->table[i].cmd = lpaccel[i].cmd;
if (!(lpaccel[i].fVirt & FVIRTKEY))
{
char ch = lpaccel[i].key;
MultiByteToWideChar( CP_ACP, 0, &ch, 1, &accel->table[i].key, 1 );
}
else accel->table[i].key = lpaccel[i].key;
}
if (!(handle = alloc_user_handle( &accel->obj, USER_ACCEL )))
HeapFree( GetProcessHeap(), 0, accel );
TRACE_(accel)("returning %p\n", handle );
return handle;
}
/*********************************************************************
* CreateAcceleratorTableW (USER32.@)
*
*
*/
HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT count)
{
HACCEL hAccel;
LPACCEL16 accel;
int i;
char ckey;
struct accelerator *accel;
HACCEL handle;
int i;
/* Do parameter checking just in case someone's trying to be
funny. */
if(cEntries < 1) {
WARN_(accel)("Application sent invalid parameters (%p %d).\n",
lpaccel, cEntries);
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Allocate memory and copy the table. */
hAccel = HACCEL_32(GlobalAlloc16(0,cEntries*sizeof(ACCEL16)));
TRACE_(accel)("handle %p\n", hAccel);
if(!hAccel) {
ERR_(accel)("Out of memory.\n");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
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;
if (count < 1)
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
accel = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct accelerator, table[count] ));
if (!accel) return 0;
accel->count = count;
for (i = 0; i < count; i++)
{
accel->table[i].fVirt = lpaccel[i].fVirt;
accel->table[i].key = lpaccel[i].key;
accel->table[i].cmd = lpaccel[i].cmd;
}
if (!(handle = alloc_user_handle( &accel->obj, USER_ACCEL )))
HeapFree( GetProcessHeap(), 0, accel );
TRACE_(accel)("returning %p\n", handle );
return handle;
}
/******************************************************************************
* DestroyAcceleratorTable [USER32.@]
* Destroys an accelerator table
*
* NOTES
* By mortene@pvv.org 980321
*
* PARAMS
* handle [I] Handle to accelerator table
*
@ -301,9 +242,15 @@ HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
*/
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 !GlobalFree16(HACCEL_16(handle));
}
return HeapFree( GetProcessHeap(), 0, accel );
}
/**********************************************************************

View File

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