shell32/explorer[1/3]: support different structure sizes in Shell_NotifyIcon (fixes bug #6794)

Mikołaj Zalewski mikolaj at zalewski.pl
Sun Mar 18 07:11:27 CDT 2007


We were always expecting the IE 5.0 structure what could be more than 
what the application send. After this patch it works for older 
structures as well as for newer - I've added Windows XP and Windows 
Vista fields.
-------------- next part --------------
From 708a381b5d889dd76b307b9d2651522f0d15a7f4 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Miko=C5=82aj_Zalewski?= <mikolaj at zalewski.pl>
Date: Sun, 18 Mar 2007 11:49:03 +0100
Subject: [PATCH] shell32/explorer: support different structure sizes in Shell_NotifyIcon

---
 dlls/shell32/systray.c      |   40 +++++++++++++++++++++++++---------------
 include/shellapi.h          |   17 +++++++++++++++++
 programs/explorer/systray.c |   15 ++++++++++-----
 3 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/dlls/shell32/systray.c b/dlls/shell32/systray.c
index 119f17f..8e9f595 100644
--- a/dlls/shell32/systray.c
+++ b/dlls/shell32/systray.c
@@ -45,7 +45,8 @@ static const WCHAR classname[] = /* Shell_TrayWnd */ {'S','h','e','l','l','_','T
 BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid)
 {
     NOTIFYICONDATAW nidW;
-    
+
+    ZeroMemory(&nidW, sizeof(nidW));    
     nidW.cbSize = sizeof(nidW);
     nidW.hWnd   = pnid->hWnd;
     nidW.uID    = pnid->uID;
@@ -54,21 +55,30 @@ BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid)
     nidW.hIcon  = pnid->hIcon;
 
     /* szTip */
-    MultiByteToWideChar(CP_ACP, 0, pnid->szTip, -1, nidW.szTip, sizeof(nidW.szTip)/sizeof(WCHAR));
+    if (pnid->uFlags & NIF_TIP)
+        MultiByteToWideChar(CP_ACP, 0, pnid->szTip, -1, nidW.szTip, sizeof(nidW.szTip)/sizeof(WCHAR));
 
-    nidW.dwState      = pnid->dwState;
-    nidW.dwStateMask  = pnid->dwStateMask;
-
-    /* szInfo */
-    MultiByteToWideChar(CP_ACP, 0, pnid->szInfo, -1,  nidW.szInfo, sizeof(nidW.szInfo)/sizeof(WCHAR));
+    if (pnid->cbSize >= NOTIFYICONDATAA_V2_SIZE)
+    {
+        nidW.dwState      = pnid->dwState;
+        nidW.dwStateMask  = pnid->dwStateMask;
 
-    nidW.u.uTimeout = pnid->u.uTimeout;
+        /* szInfo, szInfoTitle */
+        if (pnid->uFlags & NIF_INFO)
+        {
+            MultiByteToWideChar(CP_ACP, 0, pnid->szInfo, -1,  nidW.szInfo, sizeof(nidW.szInfo)/sizeof(WCHAR));
+            MultiByteToWideChar(CP_ACP, 0, pnid->szInfoTitle, -1, nidW.szInfoTitle, sizeof(nidW.szInfoTitle)/sizeof(WCHAR));
+        }
 
-    /* szInfoTitle */
-    MultiByteToWideChar(CP_ACP, 0, pnid->szInfoTitle, -1, nidW.szInfoTitle, sizeof(nidW.szInfoTitle)/sizeof(WCHAR));
+        nidW.u.uTimeout = pnid->u.uTimeout;
+        nidW.dwInfoFlags = pnid->dwInfoFlags;
+    }
     
-    nidW.dwInfoFlags = pnid->dwInfoFlags;
+    if (pnid->cbSize >= NOTIFYICONDATAA_V3_SIZE)
+        nidW.guidItem = pnid->guidItem;
 
+    if (pnid->cbSize >= sizeof(NOTIFYICONDATAA))
+        nidW.hBalloonIcon = pnid->hBalloonIcon;
     return Shell_NotifyIconW(dwMessage, &nidW);
 }
 
@@ -80,7 +90,7 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
     HWND tray;
     COPYDATASTRUCT cds;
 
-    TRACE("dwMessage = %d\n", dwMessage);
+    TRACE("dwMessage = %d, nid->cbSize=%d\n", dwMessage, nid->cbSize);
 
     tray = FindWindowExW(0, NULL, classname, NULL);
     if (!tray) return FALSE;
@@ -111,7 +121,7 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
 
         cbMaskBits = (bmMask.bmPlanes * bmMask.bmWidth * bmMask.bmHeight * bmMask.bmBitsPixel) / 8;
         cbColourBits = (bmColour.bmPlanes * bmColour.bmWidth * bmColour.bmHeight * bmColour.bmBitsPixel) / 8;
-        cds.cbData = sizeof(*nid) + 2*sizeof(BITMAP) + cbMaskBits + cbColourBits;
+        cds.cbData = nid->cbSize + 2*sizeof(BITMAP) + cbMaskBits + cbColourBits;
         buffer = HeapAlloc(GetProcessHeap(), 0, cds.cbData);
         if (!buffer)
         {
@@ -122,7 +132,7 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
         cds.lpData = buffer;
 
         memcpy(buffer, nid, sizeof(*nid));
-        buffer += sizeof(*nid);
+        buffer += nid->cbSize;
         memcpy(buffer, &bmMask, sizeof(bmMask));
         buffer += sizeof(bmMask);
         memcpy(buffer, &bmColour, sizeof(bmColour));
@@ -138,7 +148,7 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
     else
     {
 noicon:
-        cds.cbData = sizeof(*nid);
+        cds.cbData = nid->cbSize;
         cds.lpData = nid;
     }
 
diff --git a/include/shellapi.h b/include/shellapi.h
index ea7ec4b..bddf4d2 100644
--- a/include/shellapi.h
+++ b/include/shellapi.h
@@ -363,6 +363,8 @@ typedef struct _NOTIFYICONDATAA
 	} DUMMYUNIONNAME;
 	CHAR szInfoTitle[64];
 	DWORD dwInfoFlags;
+	GUID guidItem;
+	HICON hBalloonIcon;
 } NOTIFYICONDATAA, *PNOTIFYICONDATAA;
 
 typedef struct _NOTIFYICONDATAW
@@ -382,6 +384,8 @@ typedef struct _NOTIFYICONDATAW
 	} DUMMYUNIONNAME;
 	WCHAR szInfoTitle[64];
 	DWORD dwInfoFlags;
+	GUID guidItem;
+	HICON hBalloonIcon;
 } NOTIFYICONDATAW, *PNOTIFYICONDATAW;
 
 DECL_WINELIB_TYPE_AW(NOTIFYICONDATA)
@@ -392,6 +396,19 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW lpData);
 
 #define Shell_NotifyIcon WINELIB_NAME_AW(Shell_NotifyIcon)
 
+/* pre IE 5.0 */
+#define NOTIFYICONDATAA_V1_SIZE FIELD_OFFSET(NOTIFYICONDATAA, szTip[64])
+#define NOTIFYICONDATAW_V1_SIZE FIELD_OFFSET(NOTIFYICONDATAW, szTip[64])
+
+/* pre Window XP */
+#define NOTIFYICONDATAA_V2_SIZE FIELD_OFFSET(NOTIFYICONDATAA, guidItem)
+#define NOTIFYICONDATAW_V2_SIZE FIELD_OFFSET(NOTIFYICONDATAW, guidItem)
+
+/* pre Window Vista */
+#define NOTIFYICONDATAA_V3_SIZE FIELD_OFFSET(NOTIFYICONDATAA, hBalloonIcon)
+#define NOTIFYICONDATAW_V3_SIZE FIELD_OFFSET(NOTIFYICONDATAW, hBalloonIcon)
+
+
 /******************************************
  * Links
  */
diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c
index ee2a1aa..980b052 100644
--- a/programs/explorer/systray.c
+++ b/programs/explorer/systray.c
@@ -301,13 +301,18 @@ static void delete_icon(const NOTIFYICONDATAW *nid)
 static void handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
 {
     NOTIFYICONDATAW nid;
+    DWORD cbSize;
 
-    if (cds->cbData < sizeof(nid)) return;
-    memcpy(&nid, cds->lpData, sizeof(nid));
+    if (cds->cbData < NOTIFYICONDATAW_V1_SIZE) return;
+    cbSize = ((PNOTIFYICONDATA)cds->lpData)->cbSize;
+    if (cbSize < NOTIFYICONDATAW_V1_SIZE) return;
+    
+    ZeroMemory(&nid, sizeof(nid));
+    memcpy(&nid, cds->lpData, min(sizeof(nid), cbSize));
 
     /* FIXME: if statement only needed because we don't support interprocess
      * icon handles */
-    if ((nid.uFlags & NIF_ICON) && (cds->cbData >= sizeof(nid) + 2 * sizeof(BITMAP)))
+    if ((nid.uFlags & NIF_ICON) && (cds->cbData >= nid.cbSize + 2 * sizeof(BITMAP)))
     {
         LONG cbMaskBits;
         LONG cbColourBits;
@@ -315,7 +320,7 @@ static void handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
         BITMAP bmColour;
         const char *buffer = cds->lpData;
 
-        buffer += sizeof(nid);
+        buffer += nid.cbSize;
 
         memcpy(&bmMask, buffer, sizeof(bmMask));
         buffer += sizeof(bmMask);
@@ -325,7 +330,7 @@ static void handle_incoming(HWND hwndSource, COPYDATASTRUCT *cds)
         cbMaskBits = (bmMask.bmPlanes * bmMask.bmWidth * bmMask.bmHeight * bmMask.bmBitsPixel) / 8;
         cbColourBits = (bmColour.bmPlanes * bmColour.bmWidth * bmColour.bmHeight * bmColour.bmBitsPixel) / 8;
 
-        if (cds->cbData < sizeof(nid) + 2 * sizeof(BITMAP) + cbMaskBits + cbColourBits)
+        if (cds->cbData < nid.cbSize + 2 * sizeof(BITMAP) + cbMaskBits + cbColourBits)
         {
             WINE_ERR("buffer underflow\n");
             return;
-- 
1.4.4.2


More information about the wine-patches mailing list