[SHELL32]
authorThomas Faber <thomas.faber@reactos.org>
Thu, 31 Oct 2013 16:21:57 +0000 (16:21 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Thu, 31 Oct 2013 16:21:57 +0000 (16:21 +0000)
- Handle invalid cbSize in Shell_NotifyIcon[AW]. Patch by Ivan Rodionov.
- Use FIELD_OFFSET for variable-length structure
CORE-7164

svn path=/trunk/; revision=60804

reactos/dll/win32/shell32/systray.cpp

index 3c83420..6fc578f 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "precomp.h"
 
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
 /* copy data structure for tray notifications */
 typedef struct TrayNotifyCDS_Dummy {
     DWORD    cookie;
@@ -29,13 +31,13 @@ typedef struct TrayNotifyCDS_Dummy {
 } TrayNotifyCDS_Dummy;
 
 /* The only difference between Shell_NotifyIconA and Shell_NotifyIconW is the call to SendMessageA/W. */
-static BOOL SHELL_NotifyIcon(DWORD dwMessage, void* pnid, HWND nid_hwnd, int nid_size, BOOL unicode)
+static BOOL SHELL_NotifyIcon(DWORD dwMessage, void* pnid, HWND nid_hwnd, DWORD nid_size, BOOL unicode)
 {
     HWND hwnd;
     COPYDATASTRUCT data;
 
     BOOL ret = FALSE;
-    int len = sizeof(TrayNotifyCDS_Dummy) - sizeof(DWORD) + nid_size;
+    int len = FIELD_OFFSET(TrayNotifyCDS_Dummy, nicon_data) + nid_size;
 
     TrayNotifyCDS_Dummy* pnotify_data = (TrayNotifyCDS_Dummy*) alloca(len);
 
@@ -61,7 +63,21 @@ static BOOL SHELL_NotifyIcon(DWORD dwMessage, void* pnid, HWND nid_hwnd, int nid
  */
 BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid)
 {
-    return SHELL_NotifyIcon(dwMessage, pnid, pnid->hWnd, pnid->cbSize, FALSE);
+    DWORD cbSize;
+
+    /* Validate the cbSize as Windows XP does */
+    if (pnid->cbSize != NOTIFYICONDATAA_V1_SIZE &&
+        pnid->cbSize != NOTIFYICONDATAA_V2_SIZE &&
+        pnid->cbSize != sizeof(NOTIFYICONDATAA))
+    {
+        WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n",
+            pnid->cbSize, NOTIFYICONDATAA_V1_SIZE);
+        cbSize = NOTIFYICONDATAA_V1_SIZE;
+    }
+    else
+        cbSize = pnid->cbSize;
+
+    return SHELL_NotifyIcon(dwMessage, pnid, pnid->hWnd, cbSize, FALSE);
 }
 
 /*************************************************************************
@@ -69,5 +85,19 @@ BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid)
  */
 BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW pnid)
 {
-    return SHELL_NotifyIcon(dwMessage, pnid, pnid->hWnd, pnid->cbSize, TRUE);
+    DWORD cbSize;
+
+    /* Validate the cbSize so that WM_COPYDATA doesn't crash the application */
+    if (pnid->cbSize != NOTIFYICONDATAW_V1_SIZE &&
+        pnid->cbSize != NOTIFYICONDATAW_V2_SIZE &&
+        pnid->cbSize != sizeof(NOTIFYICONDATAW))
+    {
+        WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n",
+            pnid->cbSize, NOTIFYICONDATAW_V1_SIZE);
+        cbSize = NOTIFYICONDATAA_V1_SIZE;
+    }
+    else
+        cbSize = pnid->cbSize;
+
+    return SHELL_NotifyIcon(dwMessage, pnid, pnid->hWnd, cbSize, TRUE);
 }