1 /* 2 * Copyright 2004 Martin Fuchs 3 * 4 * Pass on icon notification messages to the systray implementation 5 * in the currently running shell. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 #include "precomp.h" 23 24 WINE_DEFAULT_DEBUG_CHANNEL(shell); 25 26 /* copy data structure for tray notifications */ 27 typedef struct TrayNotifyCDS_Dummy { 28 DWORD cookie; 29 DWORD notify_code; 30 DWORD nicon_data[1]; // placeholder for NOTIFYICONDATA structure 31 } TrayNotifyCDS_Dummy; 32 33 /* The only difference between Shell_NotifyIconA and Shell_NotifyIconW is the call to SendMessageA/W. */ 34 static BOOL SHELL_NotifyIcon(DWORD dwMessage, void* pnid, HWND nid_hwnd, DWORD nid_size, BOOL unicode) 35 { 36 HWND hwnd; 37 COPYDATASTRUCT data; 38 39 BOOL ret = FALSE; 40 int len = FIELD_OFFSET(TrayNotifyCDS_Dummy, nicon_data) + nid_size; 41 42 TrayNotifyCDS_Dummy* pnotify_data = (TrayNotifyCDS_Dummy*) alloca(len); 43 44 pnotify_data->cookie = 1; 45 pnotify_data->notify_code = dwMessage; 46 memcpy(&pnotify_data->nicon_data, pnid, nid_size); 47 48 data.dwData = 1; 49 data.cbData = len; 50 data.lpData = pnotify_data; 51 52 for(hwnd = 0; (hwnd = FindWindowExW(0, hwnd, L"Shell_TrayWnd", NULL)); ) 53 if ((unicode ? SendMessageW : SendMessageA)(hwnd, WM_COPYDATA, (WPARAM)nid_hwnd, (LPARAM)&data)) 54 ret = TRUE; 55 56 return ret; 57 } 58 59 60 /************************************************************************* 61 * Shell_NotifyIcon [SHELL32.296] 62 * Shell_NotifyIconA [SHELL32.297] 63 */ 64 BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid) 65 { 66 NOTIFYICONDATAW nidW; 67 DWORD cbSize; 68 69 /* Validate the cbSize as Windows XP does */ 70 if (pnid->cbSize != NOTIFYICONDATAA_V1_SIZE && 71 pnid->cbSize != NOTIFYICONDATAA_V2_SIZE && 72 pnid->cbSize != sizeof(NOTIFYICONDATAA)) 73 { 74 WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n", 75 pnid->cbSize, NOTIFYICONDATAA_V1_SIZE); 76 cbSize = NOTIFYICONDATAA_V1_SIZE; 77 } 78 else 79 cbSize = pnid->cbSize; 80 81 ZeroMemory(&nidW, sizeof(nidW)); 82 nidW.cbSize = sizeof(nidW); 83 nidW.hWnd = pnid->hWnd; 84 nidW.uID = pnid->uID; 85 nidW.uFlags = pnid->uFlags; 86 nidW.uCallbackMessage = pnid->uCallbackMessage; 87 nidW.hIcon = pnid->hIcon; 88 89 /* szTip */ 90 if (pnid->uFlags & NIF_TIP) 91 MultiByteToWideChar(CP_ACP, 0, pnid->szTip, -1, nidW.szTip, _countof(nidW.szTip)); 92 93 if (cbSize >= NOTIFYICONDATAA_V2_SIZE) 94 { 95 nidW.dwState = pnid->dwState; 96 nidW.dwStateMask = pnid->dwStateMask; 97 98 /* szInfo, szInfoTitle */ 99 if (pnid->uFlags & NIF_INFO) 100 { 101 MultiByteToWideChar(CP_ACP, 0, pnid->szInfo, -1, nidW.szInfo, _countof(nidW.szInfo)); 102 MultiByteToWideChar(CP_ACP, 0, pnid->szInfoTitle, -1, nidW.szInfoTitle, _countof(nidW.szInfoTitle)); 103 } 104 105 nidW.uTimeout = pnid->uTimeout; 106 nidW.dwInfoFlags = pnid->dwInfoFlags; 107 } 108 109 if (cbSize >= sizeof(NOTIFYICONDATAA)) 110 nidW.hBalloonIcon = pnid->hBalloonIcon; 111 return Shell_NotifyIconW(dwMessage, &nidW); 112 } 113 114 /************************************************************************* 115 * Shell_NotifyIconW [SHELL32.298] 116 */ 117 BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW pnid) 118 { 119 DWORD cbSize; 120 121 /* Validate the cbSize so that WM_COPYDATA doesn't crash the application */ 122 if (pnid->cbSize != NOTIFYICONDATAW_V1_SIZE && 123 pnid->cbSize != NOTIFYICONDATAW_V2_SIZE && 124 pnid->cbSize != sizeof(NOTIFYICONDATAW)) 125 { 126 WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n", 127 pnid->cbSize, NOTIFYICONDATAW_V1_SIZE); 128 cbSize = NOTIFYICONDATAA_V1_SIZE; 129 } 130 else 131 cbSize = pnid->cbSize; 132 133 return SHELL_NotifyIcon(dwMessage, pnid, pnid->hWnd, cbSize, TRUE); 134 } 135