From 4c2c3effb5ca12c19378ade785064843f3f1bfc3 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 30 Mar 2010 21:26:26 +0200 Subject: [PATCH] shell32: Pack the systray data structure to allow crossing 32/64 boundaries. --- dlls/shell32/systray.c | 89 ++++++++++++++++++++++++++----------- programs/explorer/systray.c | 87 +++++++++++++++++++++--------------- 2 files changed, 114 insertions(+), 62 deletions(-) diff --git a/dlls/shell32/systray.c b/dlls/shell32/systray.c index 7743ce9e24b..3e0b5acfadf 100644 --- a/dlls/shell32/systray.c +++ b/dlls/shell32/systray.c @@ -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; } diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c index 9be95bb8d2c..027596a8409 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -21,6 +21,7 @@ #include #define UNICODE +#define NONAMELESSUNION #define _WIN32_IE 0x500 #include #include @@ -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; }