Mikołaj Zalewski : shell32: Handle invalid cbSize in Shell_NotifyIcon[AW].
Alexandre Julliard
julliard at wine.codeweavers.com
Fri May 11 07:28:00 CDT 2007
Module: wine
Branch: master
Commit: 44e3200a8d0912e3b7509b3ac6c2446deb7a4c71
URL: http://source.winehq.org/git/wine.git/?a=commit;h=44e3200a8d0912e3b7509b3ac6c2446deb7a4c71
Author: Mikołaj Zalewski <mikolaj at zalewski.pl>
Date: Wed May 9 23:47:36 2007 +0200
shell32: Handle invalid cbSize in Shell_NotifyIcon[AW].
---
dlls/shell32/systray.c | 37 ++++++++++++--
dlls/shell32/tests/Makefile.in | 5 +-
dlls/shell32/tests/systray.c | 106 ++++++++++++++++++++++++++++++++++++++++
programs/explorer/systray.c | 2 +-
4 files changed, 143 insertions(+), 7 deletions(-)
diff --git a/dlls/shell32/systray.c b/dlls/shell32/systray.c
index 824eeb9..2258eb9 100644
--- a/dlls/shell32/systray.c
+++ b/dlls/shell32/systray.c
@@ -45,6 +45,20 @@ static const WCHAR classname[] = /* Shell_TrayWnd */ {'S','h','e','l','l','_','T
BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid)
{
NOTIFYICONDATAW nidW;
+ INT cbSize;
+
+ /* Validate the cbSize as Windows XP does */
+ if (pnid->cbSize != NOTIFYICONDATAA_V1_SIZE &&
+ pnid->cbSize != NOTIFYICONDATAA_V2_SIZE &&
+ pnid->cbSize != NOTIFYICONDATAA_V3_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;
ZeroMemory(&nidW, sizeof(nidW));
nidW.cbSize = sizeof(nidW);
@@ -58,7 +72,7 @@ BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid)
if (pnid->uFlags & NIF_TIP)
MultiByteToWideChar(CP_ACP, 0, pnid->szTip, -1, nidW.szTip, sizeof(nidW.szTip)/sizeof(WCHAR));
- if (pnid->cbSize >= NOTIFYICONDATAA_V2_SIZE)
+ if (cbSize >= NOTIFYICONDATAA_V2_SIZE)
{
nidW.dwState = pnid->dwState;
nidW.dwStateMask = pnid->dwStateMask;
@@ -74,10 +88,10 @@ BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid)
nidW.dwInfoFlags = pnid->dwInfoFlags;
}
- if (pnid->cbSize >= NOTIFYICONDATAA_V3_SIZE)
+ if (cbSize >= NOTIFYICONDATAA_V3_SIZE)
nidW.guidItem = pnid->guidItem;
- if (pnid->cbSize >= sizeof(NOTIFYICONDATAA))
+ if (cbSize >= sizeof(NOTIFYICONDATAA))
nidW.hBalloonIcon = pnid->hBalloonIcon;
return Shell_NotifyIconW(dwMessage, &nidW);
}
@@ -93,6 +107,21 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
TRACE("dwMessage = %d, nid->cbSize=%d\n", dwMessage, nid->cbSize);
+ /* Validate the cbSize so that WM_COPYDATA doesn't crash the application */
+ if (nid->cbSize != NOTIFYICONDATAW_V1_SIZE &&
+ nid->cbSize != NOTIFYICONDATAW_V2_SIZE &&
+ nid->cbSize != NOTIFYICONDATAW_V3_SIZE &&
+ nid->cbSize != sizeof(NOTIFYICONDATAW))
+ {
+ NOTIFYICONDATAW newNid;
+
+ WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n",
+ nid->cbSize, NOTIFYICONDATAW_V1_SIZE);
+ CopyMemory(&newNid, nid, NOTIFYICONDATAW_V1_SIZE);
+ newNid.cbSize = NOTIFYICONDATAW_V1_SIZE;
+ return Shell_NotifyIconW(dwMessage, &newNid);
+ }
+
tray = FindWindowExW(0, NULL, classname, NULL);
if (!tray) return FALSE;
@@ -131,7 +160,7 @@ BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW nid)
}
cds.lpData = buffer;
- memcpy(buffer, nid, sizeof(*nid));
+ memcpy(buffer, nid, nid->cbSize);
buffer += nid->cbSize;
memcpy(buffer, &bmMask, sizeof(bmMask));
buffer += sizeof(bmMask);
diff --git a/dlls/shell32/tests/Makefile.in b/dlls/shell32/tests/Makefile.in
index 94b0c85..f66b34d 100644
--- a/dlls/shell32/tests/Makefile.in
+++ b/dlls/shell32/tests/Makefile.in
@@ -3,7 +3,7 @@ TOPOBJDIR = ../../..
SRCDIR = @srcdir@
VPATH = @srcdir@
TESTDLL = shell32.dll
-IMPORTS = shell32 ole32 oleaut32 shlwapi advapi32 kernel32
+IMPORTS = shell32 ole32 oleaut32 shlwapi user32 gdi32 advapi32 kernel32
EXTRALIBS = -luuid
CTESTS = \
@@ -13,7 +13,8 @@ CTESTS = \
shlexec.c \
shlfileop.c \
shlfolder.c \
- string.c
+ string.c \
+ systray.c
@MAKE_TEST_RULES@
diff --git a/dlls/shell32/tests/systray.c b/dlls/shell32/tests/systray.c
new file mode 100644
index 0000000..e6d72a9
--- /dev/null
+++ b/dlls/shell32/tests/systray.c
@@ -0,0 +1,106 @@
+/* Unit tests for systray
+ *
+ * Copyright 2007 Mikolaj Zalewski
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#define _WIN32_IE 0x600
+#include <assert.h>
+#include <stdarg.h>
+
+#include <windows.h>
+
+#include "wine/test.h"
+
+
+static HWND hMainWnd;
+
+void test_cbsize()
+{
+ NOTIFYICONDATAW nidW;
+ NOTIFYICONDATAA nidA;
+
+ ZeroMemory(&nidW, sizeof(nidW));
+ nidW.cbSize = NOTIFYICONDATAW_V1_SIZE;
+ nidW.hWnd = hMainWnd;
+ nidW.uID = 1;
+ nidW.uFlags = NIF_ICON|NIF_MESSAGE;
+ nidW.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ nidW.uCallbackMessage = WM_USER+17;
+ ok(Shell_NotifyIconW(NIM_ADD, &nidW), "NIM_ADD failed!\n");
+
+ /* using an invalid cbSize does work */
+ nidW.cbSize = 3;
+ nidW.hWnd = hMainWnd;
+ nidW.uID = 1;
+ ok(Shell_NotifyIconW(NIM_DELETE, &nidW), "NIM_DELETE failed!\n");
+ /* as icon doesn't exist anymore - now there will be an error */
+ nidW.cbSize = sizeof(nidW);
+ /* wine currently doesn't return error code put prints an ERR(...) */
+ todo_wine ok(!Shell_NotifyIconW(NIM_DELETE, &nidW), "The icon was not deleted\n");
+
+ /* same for Shell_NotifyIconA */
+ ZeroMemory(&nidA, sizeof(nidA));
+ nidA.cbSize = NOTIFYICONDATAA_V1_SIZE;
+ nidA.hWnd = hMainWnd;
+ nidA.uID = 1;
+ nidA.uFlags = NIF_ICON|NIF_MESSAGE;
+ nidA.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ nidA.uCallbackMessage = WM_USER+17;
+ ok(Shell_NotifyIconA(NIM_ADD, &nidA), "NIM_ADD failed!\n");
+
+ /* using an invalid cbSize does work */
+ nidA.cbSize = 3;
+ nidA.hWnd = hMainWnd;
+ nidA.uID = 1;
+ ok(Shell_NotifyIconA(NIM_DELETE, &nidA), "NIM_DELETE failed!\n");
+ /* as icon doesn't exist anymore - now there will be an error */
+ nidA.cbSize = sizeof(nidA);
+ /* wine currently doesn't return error code put prints an ERR(...) */
+ todo_wine ok(!Shell_NotifyIconA(NIM_DELETE, &nidA), "The icon was not deleted\n");
+}
+
+START_TEST(systray)
+{
+ WNDCLASSA wc;
+ MSG msg;
+ RECT rc;
+
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandleA(NULL);
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_IBEAM));
+ wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "MyTestWnd";
+ wc.lpfnWndProc = DefWindowProc;
+ RegisterClassA(&wc);
+
+ hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
+ GetClientRect(hMainWnd, &rc);
+ ShowWindow(hMainWnd, SW_SHOW);
+
+ test_cbsize();
+
+ PostQuitMessage(0);
+ while(GetMessageA(&msg,0,0,0)) {
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+ DestroyWindow(hMainWnd);
+}
diff --git a/programs/explorer/systray.c b/programs/explorer/systray.c
index b93d209..1814bce 100644
--- a/programs/explorer/systray.c
+++ b/programs/explorer/systray.c
@@ -290,7 +290,7 @@ static void delete_icon(const NOTIFYICONDATAW *nid)
if (!icon)
{
- WINE_ERR("invalid tray icon ID specified: %ud\n", nid->uID);
+ WINE_ERR("invalid tray icon ID specified: %u\n", nid->uID);
return;
}
More information about the wine-cvs
mailing list