mirror of
https://github.com/reactos/wine.git
synced 2024-11-28 22:20:26 +00:00
shell32: Pack the systray data structure to allow crossing 32/64 boundaries.
This commit is contained in:
parent
3cd9f97149
commit
4c2c3effb5
@ -38,6 +38,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(systray);
|
||||
|
||||
static const WCHAR classname[] = /* Shell_TrayWnd */ {'S','h','e','l','l','_','T','r','a','y','W','n','d','\0'};
|
||||
|
||||
struct notify_data /* platform-independent format for NOTIFYICONDATA */
|
||||
{
|
||||
LONG hWnd;
|
||||
UINT uID;
|
||||
UINT uFlags;
|
||||
UINT uCallbackMessage;
|
||||
WCHAR szTip[128];
|
||||
DWORD dwState;
|
||||
DWORD dwStateMask;
|
||||
WCHAR szInfo[256];
|
||||
union {
|
||||
UINT uTimeout;
|
||||
UINT uVersion;
|
||||
} u;
|
||||
WCHAR szInfoTitle[64];
|
||||
DWORD dwInfoFlags;
|
||||
GUID guidItem;
|
||||
/* data for the icon bitmap */
|
||||
UINT width;
|
||||
UINT height;
|
||||
UINT planes;
|
||||
UINT bpp;
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
* Shell_NotifyIcon [SHELL32.296]
|
||||
* Shell_NotifyIconA [SHELL32.297]
|
||||
@ -103,7 +127,8 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
|
||||
{
|
||||
HWND tray;
|
||||
COPYDATASTRUCT cds;
|
||||
char *buffer = NULL;
|
||||
struct notify_data data_buffer;
|
||||
struct notify_data *data = &data_buffer;
|
||||
BOOL ret;
|
||||
|
||||
TRACE("dwMessage = %d, nid->cbSize=%d\n", dwMessage, nid->cbSize);
|
||||
@ -127,6 +152,8 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
|
||||
if (!tray) return FALSE;
|
||||
|
||||
cds.dwData = dwMessage;
|
||||
cds.cbData = sizeof(*data);
|
||||
memset( data, 0, sizeof(*data) );
|
||||
|
||||
/* FIXME: if statement only needed because we don't support interprocess
|
||||
* icon handles */
|
||||
@ -137,6 +164,7 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
|
||||
BITMAP bmColour;
|
||||
LONG cbMaskBits;
|
||||
LONG cbColourBits;
|
||||
char *buffer;
|
||||
|
||||
if (!GetIconInfo(nid->hIcon, &iconinfo))
|
||||
goto noicon;
|
||||
@ -149,9 +177,9 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
|
||||
goto noicon;
|
||||
}
|
||||
|
||||
cbMaskBits = (bmMask.bmPlanes * bmMask.bmWidth * bmMask.bmHeight * bmMask.bmBitsPixel) / 8;
|
||||
cbColourBits = (bmColour.bmPlanes * bmColour.bmWidth * bmColour.bmHeight * bmColour.bmBitsPixel) / 8;
|
||||
cds.cbData = nid->cbSize + 2*sizeof(BITMAP) + cbMaskBits + cbColourBits;
|
||||
cbMaskBits = (bmMask.bmPlanes * bmMask.bmWidth * bmMask.bmHeight * bmMask.bmBitsPixel + 15) / 16 * 2;
|
||||
cbColourBits = (bmColour.bmPlanes * bmColour.bmWidth * bmColour.bmHeight * bmColour.bmBitsPixel + 15) / 16 * 2;
|
||||
cds.cbData = sizeof(*data) + cbMaskBits + cbColourBits;
|
||||
buffer = HeapAlloc(GetProcessHeap(), 0, cds.cbData);
|
||||
if (!buffer)
|
||||
{
|
||||
@ -159,38 +187,47 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
|
||||
DeleteObject(iconinfo.hbmColor);
|
||||
return FALSE;
|
||||
}
|
||||
cds.lpData = buffer;
|
||||
|
||||
memcpy(buffer, nid, nid->cbSize);
|
||||
buffer += nid->cbSize;
|
||||
memcpy(buffer, &bmMask, sizeof(bmMask));
|
||||
buffer += sizeof(bmMask);
|
||||
memcpy(buffer, &bmColour, sizeof(bmColour));
|
||||
buffer += sizeof(bmColour);
|
||||
data = (struct notify_data *)buffer;
|
||||
memset( data, 0, sizeof(*data) );
|
||||
data->width = bmColour.bmWidth;
|
||||
data->height = bmColour.bmHeight;
|
||||
data->planes = bmColour.bmPlanes;
|
||||
data->bpp = bmColour.bmBitsPixel;
|
||||
buffer += sizeof(*data);
|
||||
GetBitmapBits(iconinfo.hbmMask, cbMaskBits, buffer);
|
||||
buffer += cbMaskBits;
|
||||
GetBitmapBits(iconinfo.hbmColor, cbColourBits, buffer);
|
||||
|
||||
/* Reset pointer to allocated block so it can be freed later.
|
||||
* Note that cds.lpData cannot be passed to HeapFree since it
|
||||
* points to nid when no icon info is found. */
|
||||
buffer = cds.lpData;
|
||||
|
||||
DeleteObject(iconinfo.hbmMask);
|
||||
DeleteObject(iconinfo.hbmColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
noicon:
|
||||
cds.cbData = nid->cbSize;
|
||||
cds.lpData = nid;
|
||||
data->hWnd = HandleToLong( nid->hWnd );
|
||||
data->uID = nid->uID;
|
||||
data->uFlags = nid->uFlags;
|
||||
if (data->uFlags & NIF_MESSAGE)
|
||||
data->uCallbackMessage = nid->uCallbackMessage;
|
||||
if (data->uFlags & NIF_TIP)
|
||||
lstrcpynW( data->szTip, nid->szTip, sizeof(data->szTip)/sizeof(WCHAR) );
|
||||
if (data->uFlags & NIF_STATE)
|
||||
{
|
||||
data->dwState = nid->dwState;
|
||||
data->dwStateMask = nid->dwStateMask;
|
||||
}
|
||||
if (data->uFlags & NIF_INFO)
|
||||
{
|
||||
lstrcpynW( data->szInfo, nid->szInfo, sizeof(data->szInfo)/sizeof(WCHAR) );
|
||||
lstrcpynW( data->szInfoTitle, nid->szInfoTitle, sizeof(data->szInfoTitle)/sizeof(WCHAR) );
|
||||
data->u.uTimeout = nid->u.uTimeout;
|
||||
data->dwInfoFlags = nid->dwInfoFlags;
|
||||
}
|
||||
if (data->uFlags & NIF_GUID)
|
||||
data->guidItem = nid->guidItem;
|
||||
/* FIXME: balloon icon */
|
||||
|
||||
cds.lpData = data;
|
||||
ret = SendMessageW(tray, WM_COPYDATA, (WPARAM)nid->hWnd, (LPARAM)&cds);
|
||||
|
||||
/* FIXME: if statement only needed because we don't support interprocess
|
||||
* icon handles */
|
||||
HeapFree(GetProcessHeap(), 0, buffer);
|
||||
|
||||
if (data != &data_buffer) HeapFree( GetProcessHeap(), 0, data );
|
||||
return ret;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <assert.h>
|
||||
|
||||
#define UNICODE
|
||||
#define NONAMELESSUNION
|
||||
#define _WIN32_IE 0x500
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
@ -35,6 +36,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(systray);
|
||||
#define IS_OPTION_FALSE(ch) \
|
||||
((ch) == 'n' || (ch) == 'N' || (ch) == 'f' || (ch) == 'F' || (ch) == '0')
|
||||
|
||||
struct notify_data /* platform-independent format for NOTIFYICONDATA */
|
||||
{
|
||||
LONG hWnd;
|
||||
UINT uID;
|
||||
UINT uFlags;
|
||||
UINT uCallbackMessage;
|
||||
WCHAR szTip[128];
|
||||
DWORD dwState;
|
||||
DWORD dwStateMask;
|
||||
WCHAR szInfo[256];
|
||||
union {
|
||||
UINT uTimeout;
|
||||
UINT uVersion;
|
||||
} u;
|
||||
WCHAR szInfoTitle[64];
|
||||
DWORD dwInfoFlags;
|
||||
GUID guidItem;
|
||||
/* data for the icon bitmap */
|
||||
UINT width;
|
||||
UINT height;
|
||||
UINT planes;
|
||||
UINT bpp;
|
||||
};
|
||||
|
||||
static int (CDECL *wine_notify_icon)(DWORD,NOTIFYICONDATAW *);
|
||||
|
||||
/* an individual systray icon, unpacked from the NOTIFYICONDATA and always in unicode */
|
||||
@ -346,52 +371,46 @@ static void cleanup_destroyed_windows(void)
|
||||
static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
|
||||
{
|
||||
struct icon *icon = NULL;
|
||||
const struct notify_data *data;
|
||||
NOTIFYICONDATAW nid;
|
||||
DWORD cbSize;
|
||||
int ret = FALSE;
|
||||
|
||||
if (cds->cbData < NOTIFYICONDATAW_V1_SIZE) return FALSE;
|
||||
cbSize = ((PNOTIFYICONDATAW)cds->lpData)->cbSize;
|
||||
if (cbSize < NOTIFYICONDATAW_V1_SIZE) return FALSE;
|
||||
if (cds->cbData < sizeof(*data)) return FALSE;
|
||||
data = cds->lpData;
|
||||
|
||||
ZeroMemory(&nid, sizeof(nid));
|
||||
memcpy(&nid, cds->lpData, min(sizeof(nid), cbSize));
|
||||
nid.cbSize = sizeof(nid);
|
||||
nid.hWnd = LongToHandle( data->hWnd );
|
||||
nid.uID = data->uID;
|
||||
nid.uFlags = data->uFlags;
|
||||
nid.uCallbackMessage = data->uCallbackMessage;
|
||||
nid.hIcon = 0;
|
||||
nid.dwState = data->dwState;
|
||||
nid.dwStateMask = data->dwStateMask;
|
||||
nid.u.uTimeout = data->u.uTimeout;
|
||||
nid.dwInfoFlags = data->dwInfoFlags;
|
||||
nid.guidItem = data->guidItem;
|
||||
lstrcpyW( nid.szTip, data->szTip );
|
||||
lstrcpyW( nid.szInfo, data->szInfo );
|
||||
lstrcpyW( nid.szInfoTitle, data->szInfoTitle );
|
||||
nid.hBalloonIcon = 0;
|
||||
|
||||
/* FIXME: if statement only needed because we don't support interprocess
|
||||
* icon handles */
|
||||
if ((nid.uFlags & NIF_ICON) && (cds->cbData >= nid.cbSize + 2 * sizeof(BITMAP)))
|
||||
if ((nid.uFlags & NIF_ICON) && cds->cbData > sizeof(*data))
|
||||
{
|
||||
LONG cbMaskBits;
|
||||
LONG cbColourBits;
|
||||
BITMAP bmMask;
|
||||
BITMAP bmColour;
|
||||
const char *buffer = cds->lpData;
|
||||
const char *buffer = (const char *)(data + 1);
|
||||
|
||||
buffer += nid.cbSize;
|
||||
cbMaskBits = (data->width * data->height + 15) / 16 * 2;
|
||||
cbColourBits = (data->planes * data->width * data->height * data->bpp + 15) / 16 * 2;
|
||||
|
||||
memcpy(&bmMask, buffer, sizeof(bmMask));
|
||||
buffer += sizeof(bmMask);
|
||||
memcpy(&bmColour, buffer, sizeof(bmColour));
|
||||
buffer += sizeof(bmColour);
|
||||
|
||||
cbMaskBits = (bmMask.bmPlanes * bmMask.bmWidth * bmMask.bmHeight * bmMask.bmBitsPixel) / 8;
|
||||
cbColourBits = (bmColour.bmPlanes * bmColour.bmWidth * bmColour.bmHeight * bmColour.bmBitsPixel) / 8;
|
||||
|
||||
if (cds->cbData < nid.cbSize + 2 * sizeof(BITMAP) + cbMaskBits + cbColourBits)
|
||||
if (cds->cbData < sizeof(*data) + cbMaskBits + cbColourBits)
|
||||
{
|
||||
WINE_ERR("buffer underflow\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
if ((bmColour.bmWidth != bmMask.bmWidth) || (bmColour.bmHeight != bmMask.bmHeight))
|
||||
{
|
||||
WINE_ERR("colour and mask bitmaps aren't consistent\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nid.hIcon = CreateIcon(NULL, bmColour.bmWidth, bmColour.bmHeight,
|
||||
bmColour.bmPlanes, bmColour.bmBitsPixel,
|
||||
nid.hIcon = CreateIcon(NULL, data->width, data->height, data->planes, data->bpp,
|
||||
buffer, buffer + cbMaskBits);
|
||||
}
|
||||
|
||||
@ -400,7 +419,7 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
|
||||
{
|
||||
if (wine_notify_icon && ((ret = wine_notify_icon( cds->dwData, &nid )) != -1))
|
||||
{
|
||||
if (nid.uFlags & NIF_ICON) DestroyIcon( nid.hIcon );
|
||||
if (nid.hIcon) DestroyIcon( nid.hIcon );
|
||||
return ret;
|
||||
}
|
||||
ret = FALSE;
|
||||
@ -422,11 +441,7 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
|
||||
break;
|
||||
}
|
||||
|
||||
/* FIXME: if statement only needed because we don't support interprocess
|
||||
* icon handles */
|
||||
if (nid.uFlags & NIF_ICON)
|
||||
DestroyIcon(nid.hIcon);
|
||||
|
||||
if (nid.hIcon) DestroyIcon( nid.hIcon );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user