Mikołaj Zalewski : shell32/explorer: Support different structure sizes in Shell_NotifyIcon.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Mar 19 08:17:43 CDT 2007


Module: wine
Branch: master
Commit: cdf06864e22ed45ecc8e6905bc187f6417603bc0
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=cdf06864e22ed45ecc8e6905bc187f6417603bc0

Author: Mikołaj Zalewski <mikolaj at zalewski.pl>
Date:   Sun Mar 18 11:49:03 2007 +0100

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..1020b3c 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..b93d209 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;




More information about the wine-cvs mailing list