From: Sergei Chernyadyev serg.cherniadjev@gmail.com
--- dlls/shell32/systray.c | 22 +++++++++++++++++++--- programs/explorer/systray.c | 25 ++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 4 deletions(-)
diff --git a/dlls/shell32/systray.c b/dlls/shell32/systray.c index 9cbecedcfef..c74d0178b10 100644 --- a/dlls/shell32/systray.c +++ b/dlls/shell32/systray.c @@ -61,6 +61,7 @@ struct notify_data /* platform-independent format for NOTIFYICONDATA */ WCHAR szInfoTitle[64]; DWORD dwInfoFlags; GUID guidItem; + struct notify_data_icon balloon_icon_info; /* balloon icon bitmap info */ BYTE icon_data[]; };
@@ -181,9 +182,9 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid) COPYDATASTRUCT cds; struct notify_data data_buffer; struct notify_data *data = &data_buffer; - ICONINFO icon_info = { 0 }; - BITMAP mask, color; - LONG mask_size = 0, color_size = 0; + ICONINFO icon_info = { 0 }, balloon_icon_info = { 0 }; + BITMAP mask, color, balloon_mask, balloon_color; + LONG mask_size = 0, color_size = 0, balloon_mask_size = 0, balloon_color_size = 0; BOOL ret;
TRACE("dwMessage = %ld, nid->cbSize=%ld\n", dwMessage, nid->cbSize); @@ -219,9 +220,15 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid) if (nid->uFlags & NIF_ICON) GetIconInfo( nid->hIcon, &icon_info );
+ if ((nid->uFlags & NIF_INFO) && (nid->dwInfoFlags & NIIF_ICONMASK) == NIIF_USER) + GetIconInfo( nid->hBalloonIcon, &balloon_icon_info ); + get_bitmap_info( &icon_info, &mask, &color, &mask_size, &color_size ); cds.cbData += mask_size + color_size;
+ get_bitmap_info( &balloon_icon_info, &balloon_mask, &balloon_color, &balloon_mask_size, &balloon_color_size ); + cds.cbData += balloon_mask_size + balloon_color_size; + if (cds.cbData > sizeof(*data)) { BYTE *buffer; @@ -230,6 +237,8 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid) { if (icon_info.hbmMask) DeleteObject( icon_info.hbmMask ); if (icon_info.hbmColor) DeleteObject( icon_info.hbmColor ); + if (balloon_icon_info.hbmMask) DeleteObject( balloon_icon_info.hbmMask ); + if (balloon_icon_info.hbmColor) DeleteObject( balloon_icon_info.hbmColor ); SetLastError(E_OUTOFMEMORY); return FALSE; } @@ -243,6 +252,13 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid) fill_icon_info( &mask, &color, mask_size, color_size, &icon_info, &data->icon_info, buffer ); buffer += mask_size + color_size; } + + if (balloon_icon_info.hbmMask) + { + fill_icon_info( &balloon_mask, &balloon_color, balloon_mask_size, balloon_color_size, + &balloon_icon_info, &data->balloon_icon_info, buffer ); + buffer += mask_size + color_size; + } }
data->hWnd = HandleToLong( nid->hWnd ); diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c index 6337faad633..7f4d2002d81 100644 --- a/programs/explorer/systray.c +++ b/programs/explorer/systray.c @@ -63,6 +63,7 @@ struct notify_data /* platform-independent format for NOTIFYICONDATA */ WCHAR szInfoTitle[64]; DWORD dwInfoFlags; GUID guidItem; + struct notify_data_icon balloon_icon_info; /* balloon icon bitmap info */ BYTE icon_data[]; };
@@ -729,7 +730,10 @@ static BOOL modify_icon( struct icon *icon, NOTIFYICONDATAW *nid ) lstrcpynW( icon->info_title, nid->szInfoTitle, ARRAY_SIZE( icon->info_title )); icon->info_flags = nid->dwInfoFlags; icon->info_timeout = max(min(nid->uTimeout, BALLOON_SHOW_MAX_TIMEOUT), BALLOON_SHOW_MIN_TIMEOUT); - icon->info_icon = nid->hBalloonIcon; + + if (icon->info_icon) DestroyIcon( icon->info_icon ); + icon->info_icon = CopyIcon( nid->hBalloonIcon ); + update_balloon( icon ); } if (icon->state & NIS_HIDDEN) hide_icon( icon ); @@ -883,8 +887,26 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds) } nid.hIcon = CreateIcon(NULL, data->icon_info.width, data->icon_info.height, data->icon_info.planes, data->icon_info.bpp, icon_data, icon_data + cbMaskBits); + icon_data += cbMaskBits + cbColourBits; }
+ if ((nid.uFlags & NIF_INFO) && (nid.dwInfoFlags & NIIF_ICONMASK) == NIIF_USER) + { + /* Balloon icon */ + LONG cbMaskBits; + LONG cbColourBits; + + cbMaskBits = (data->balloon_icon_info.width * data->balloon_icon_info.height + 15) / 16 * 2; + cbColourBits = (data->balloon_icon_info.planes * data->balloon_icon_info.width * data->balloon_icon_info.height * data->balloon_icon_info.bpp + 15) / 16 * 2; + + if (cds->cbData < ((char*)icon_data - (char*)data) + cbMaskBits + cbColourBits) + { + ERR( "buffer underflow\n" ); + return FALSE; + } + nid.hBalloonIcon = CreateIcon(NULL, data->balloon_icon_info.width, data->balloon_icon_info.height, data->balloon_icon_info.planes, data->balloon_icon_info.bpp, + icon_data, icon_data + cbMaskBits); + } /* try forwarding to the display driver first */ if (cds->dwData == NIM_ADD || !(icon = get_icon( nid.hWnd, nid.uID ))) { @@ -919,6 +941,7 @@ static BOOL handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
done: if (nid.hIcon) DestroyIcon( nid.hIcon ); + if (nid.hBalloonIcon) DestroyIcon( nid.hBalloonIcon ); sync_taskbar_buttons(); return ret; }