1c2c66affSColin Finck /*
2c2c66affSColin Finck * Copyright 2004 Martin Fuchs
3131678a0SHermès Bélusca-Maïto * Copyright 2018 Hermes Belusca-Maito
4c2c66affSColin Finck *
5c2c66affSColin Finck * Pass on icon notification messages to the systray implementation
6c2c66affSColin Finck * in the currently running shell.
7c2c66affSColin Finck *
8c2c66affSColin Finck * This library is free software; you can redistribute it and/or
9c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
10c2c66affSColin Finck * License as published by the Free Software Foundation; either
11c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
12c2c66affSColin Finck *
13c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
14c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
15c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16c2c66affSColin Finck * Lesser General Public License for more details.
17c2c66affSColin Finck *
18c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
19c2c66affSColin Finck * License along with this library; if not, write to the Free Software
20c2c66affSColin Finck * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21c2c66affSColin Finck */
22c2c66affSColin Finck
23c2c66affSColin Finck #include "precomp.h"
24c2c66affSColin Finck
25fe4704faSHermès Bélusca-Maïto WINE_DEFAULT_DEBUG_CHANNEL(shell_notify);
26c2c66affSColin Finck
27c2c66affSColin Finck /*************************************************************************
28c2c66affSColin Finck * Shell_NotifyIcon [SHELL32.296]
29c2c66affSColin Finck * Shell_NotifyIconA [SHELL32.297]
30c2c66affSColin Finck */
Shell_NotifyIconA(DWORD dwMessage,PNOTIFYICONDATAA pnid)31c2c66affSColin Finck BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid)
32c2c66affSColin Finck {
33c2c66affSColin Finck NOTIFYICONDATAW nidW;
34131678a0SHermès Bélusca-Maïto DWORD cbSize, dwValidFlags;
35c2c66affSColin Finck
36131678a0SHermès Bélusca-Maïto /* Initialize and capture the basic data fields */
37c2c66affSColin Finck ZeroMemory(&nidW, sizeof(nidW));
38131678a0SHermès Bélusca-Maïto nidW.cbSize = sizeof(nidW); // Use a default size for the moment
39c2c66affSColin Finck nidW.hWnd = pnid->hWnd;
40c2c66affSColin Finck nidW.uID = pnid->uID;
41c2c66affSColin Finck nidW.uFlags = pnid->uFlags;
42c2c66affSColin Finck nidW.uCallbackMessage = pnid->uCallbackMessage;
43c2c66affSColin Finck nidW.hIcon = pnid->hIcon;
44c2c66affSColin Finck
45131678a0SHermès Bélusca-Maïto /* Validate the structure size and the flags */
46131678a0SHermès Bélusca-Maïto cbSize = pnid->cbSize;
47131678a0SHermès Bélusca-Maïto dwValidFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
48131678a0SHermès Bélusca-Maïto if (cbSize == sizeof(NOTIFYICONDATAA))
49131678a0SHermès Bélusca-Maïto {
50131678a0SHermès Bélusca-Maïto nidW.cbSize = sizeof(nidW);
51131678a0SHermès Bélusca-Maïto dwValidFlags |= NIF_STATE | NIF_INFO | NIF_GUID /* | NIF_REALTIME | NIF_SHOWTIP */;
52131678a0SHermès Bélusca-Maïto }
53131678a0SHermès Bélusca-Maïto else if (cbSize == NOTIFYICONDATAA_V3_SIZE)
54131678a0SHermès Bélusca-Maïto {
55131678a0SHermès Bélusca-Maïto nidW.cbSize = NOTIFYICONDATAW_V3_SIZE;
56131678a0SHermès Bélusca-Maïto dwValidFlags |= NIF_STATE | NIF_INFO | NIF_GUID;
57131678a0SHermès Bélusca-Maïto }
58131678a0SHermès Bélusca-Maïto else if (cbSize == NOTIFYICONDATAA_V2_SIZE)
59131678a0SHermès Bélusca-Maïto {
60131678a0SHermès Bélusca-Maïto nidW.cbSize = NOTIFYICONDATAW_V2_SIZE;
61131678a0SHermès Bélusca-Maïto dwValidFlags |= NIF_STATE | NIF_INFO;
62131678a0SHermès Bélusca-Maïto }
63131678a0SHermès Bélusca-Maïto else // if cbSize == NOTIFYICONDATAA_V1_SIZE or something else
64131678a0SHermès Bélusca-Maïto {
65131678a0SHermès Bélusca-Maïto if (cbSize != NOTIFYICONDATAA_V1_SIZE)
66131678a0SHermès Bélusca-Maïto {
67131678a0SHermès Bélusca-Maïto WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n",
68131678a0SHermès Bélusca-Maïto cbSize, NOTIFYICONDATAA_V1_SIZE);
69131678a0SHermès Bélusca-Maïto cbSize = NOTIFYICONDATAA_V1_SIZE;
70131678a0SHermès Bélusca-Maïto }
71131678a0SHermès Bélusca-Maïto nidW.cbSize = NOTIFYICONDATAW_V1_SIZE;
72131678a0SHermès Bélusca-Maïto }
73131678a0SHermès Bélusca-Maïto nidW.uFlags &= dwValidFlags;
74131678a0SHermès Bélusca-Maïto
75131678a0SHermès Bélusca-Maïto /* Capture the other data fields */
76131678a0SHermès Bélusca-Maïto
77131678a0SHermès Bélusca-Maïto if (nidW.uFlags & NIF_TIP)
78131678a0SHermès Bélusca-Maïto {
79131678a0SHermès Bélusca-Maïto /*
80131678a0SHermès Bélusca-Maïto * Depending on the size of the NOTIFYICONDATA structure
81131678a0SHermès Bélusca-Maïto * we should convert part of, or all the szTip string.
82131678a0SHermès Bélusca-Maïto */
83131678a0SHermès Bélusca-Maïto if (cbSize <= NOTIFYICONDATAA_V1_SIZE)
84131678a0SHermès Bélusca-Maïto {
85131678a0SHermès Bélusca-Maïto #define NIDV1_TIP_SIZE_A (NOTIFYICONDATAA_V1_SIZE - FIELD_OFFSET(NOTIFYICONDATAA, szTip))/sizeof(CHAR)
86131678a0SHermès Bélusca-Maïto MultiByteToWideChar(CP_ACP, 0, pnid->szTip, NIDV1_TIP_SIZE_A,
87131678a0SHermès Bélusca-Maïto nidW.szTip, _countof(nidW.szTip));
88131678a0SHermès Bélusca-Maïto /* Truncate the string */
89131678a0SHermès Bélusca-Maïto nidW.szTip[NIDV1_TIP_SIZE_A - 1] = 0;
90131678a0SHermès Bélusca-Maïto #undef NIDV1_TIP_SIZE_A
91131678a0SHermès Bélusca-Maïto }
92131678a0SHermès Bélusca-Maïto else
93131678a0SHermès Bélusca-Maïto {
94131678a0SHermès Bélusca-Maïto MultiByteToWideChar(CP_ACP, 0, pnid->szTip, -1,
95131678a0SHermès Bélusca-Maïto nidW.szTip, _countof(nidW.szTip));
96131678a0SHermès Bélusca-Maïto }
97131678a0SHermès Bélusca-Maïto }
98c2c66affSColin Finck
99c2c66affSColin Finck if (cbSize >= NOTIFYICONDATAA_V2_SIZE)
100c2c66affSColin Finck {
101c2c66affSColin Finck nidW.dwState = pnid->dwState;
102c2c66affSColin Finck nidW.dwStateMask = pnid->dwStateMask;
103c2c66affSColin Finck nidW.uTimeout = pnid->uTimeout;
104c2c66affSColin Finck nidW.dwInfoFlags = pnid->dwInfoFlags;
105131678a0SHermès Bélusca-Maïto
106131678a0SHermès Bélusca-Maïto if (nidW.uFlags & NIF_INFO)
107131678a0SHermès Bélusca-Maïto {
108131678a0SHermès Bélusca-Maïto MultiByteToWideChar(CP_ACP, 0, pnid->szInfo, -1,
109131678a0SHermès Bélusca-Maïto nidW.szInfo, _countof(nidW.szInfo));
110131678a0SHermès Bélusca-Maïto MultiByteToWideChar(CP_ACP, 0, pnid->szInfoTitle, -1,
111131678a0SHermès Bélusca-Maïto nidW.szInfoTitle, _countof(nidW.szInfoTitle));
112c2c66affSColin Finck }
113131678a0SHermès Bélusca-Maïto }
114131678a0SHermès Bélusca-Maïto
115131678a0SHermès Bélusca-Maïto if ((cbSize >= NOTIFYICONDATAA_V3_SIZE) && (nidW.uFlags & NIF_GUID))
116131678a0SHermès Bélusca-Maïto nidW.guidItem = pnid->guidItem;
117c2c66affSColin Finck
118c2c66affSColin Finck if (cbSize >= sizeof(NOTIFYICONDATAA))
119c2c66affSColin Finck nidW.hBalloonIcon = pnid->hBalloonIcon;
120131678a0SHermès Bélusca-Maïto
121131678a0SHermès Bélusca-Maïto /* Call the unicode function */
122c2c66affSColin Finck return Shell_NotifyIconW(dwMessage, &nidW);
123c2c66affSColin Finck }
124c2c66affSColin Finck
125c2c66affSColin Finck /*************************************************************************
126c2c66affSColin Finck * Shell_NotifyIconW [SHELL32.298]
127c2c66affSColin Finck */
Shell_NotifyIconW(DWORD dwMessage,PNOTIFYICONDATAW pnid)128c2c66affSColin Finck BOOL WINAPI Shell_NotifyIconW(DWORD dwMessage, PNOTIFYICONDATAW pnid)
129c2c66affSColin Finck {
130131678a0SHermès Bélusca-Maïto BOOL ret = FALSE;
131131678a0SHermès Bélusca-Maïto HWND hShellTrayWnd;
132131678a0SHermès Bélusca-Maïto DWORD cbSize, dwValidFlags;
133131678a0SHermès Bélusca-Maïto TRAYNOTIFYDATAW tnid;
134131678a0SHermès Bélusca-Maïto COPYDATASTRUCT data;
135c2c66affSColin Finck
136131678a0SHermès Bélusca-Maïto /* Find a handle to the shell tray window */
137131678a0SHermès Bélusca-Maïto hShellTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL);
138131678a0SHermès Bélusca-Maïto if (!hShellTrayWnd)
139131678a0SHermès Bélusca-Maïto return FALSE; // None found, bail out
140131678a0SHermès Bélusca-Maïto
141131678a0SHermès Bélusca-Maïto /* Validate the structure size and the flags */
142131678a0SHermès Bélusca-Maïto cbSize = pnid->cbSize;
143131678a0SHermès Bélusca-Maïto dwValidFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
144131678a0SHermès Bélusca-Maïto if (cbSize == sizeof(NOTIFYICONDATAW))
145131678a0SHermès Bélusca-Maïto {
146131678a0SHermès Bélusca-Maïto dwValidFlags |= NIF_STATE | NIF_INFO | NIF_GUID /* | NIF_REALTIME | NIF_SHOWTIP */;
147131678a0SHermès Bélusca-Maïto }
148131678a0SHermès Bélusca-Maïto else if (cbSize == NOTIFYICONDATAW_V3_SIZE)
149131678a0SHermès Bélusca-Maïto {
150131678a0SHermès Bélusca-Maïto dwValidFlags |= NIF_STATE | NIF_INFO | NIF_GUID;
151131678a0SHermès Bélusca-Maïto }
152131678a0SHermès Bélusca-Maïto else if (cbSize == NOTIFYICONDATAW_V2_SIZE)
153131678a0SHermès Bélusca-Maïto {
154131678a0SHermès Bélusca-Maïto dwValidFlags |= NIF_STATE | NIF_INFO;
155131678a0SHermès Bélusca-Maïto }
156131678a0SHermès Bélusca-Maïto else // if cbSize == NOTIFYICONDATAW_V1_SIZE or something else
157131678a0SHermès Bélusca-Maïto {
158131678a0SHermès Bélusca-Maïto if (cbSize != NOTIFYICONDATAW_V1_SIZE)
159c2c66affSColin Finck {
160c2c66affSColin Finck WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n",
161131678a0SHermès Bélusca-Maïto cbSize, NOTIFYICONDATAW_V1_SIZE);
1625ecabcceSHermès Bélusca-Maïto cbSize = NOTIFYICONDATAW_V1_SIZE;
163c2c66affSColin Finck }
164131678a0SHermès Bélusca-Maïto }
165c2c66affSColin Finck
166131678a0SHermès Bélusca-Maïto /* Build the data structure */
167131678a0SHermès Bélusca-Maïto ZeroMemory(&tnid, sizeof(tnid));
168131678a0SHermès Bélusca-Maïto tnid.dwSignature = NI_NOTIFY_SIG;
169131678a0SHermès Bélusca-Maïto tnid.dwMessage = dwMessage;
170131678a0SHermès Bélusca-Maïto
171131678a0SHermès Bélusca-Maïto /* Copy only the needed data, everything else is zeroed out */
172131678a0SHermès Bélusca-Maïto CopyMemory(&tnid.nid, pnid, cbSize);
173131678a0SHermès Bélusca-Maïto /* Adjust the size (the NOTIFYICONDATA structure is the full-fledged one) and the flags */
174131678a0SHermès Bélusca-Maïto tnid.nid.cbSize = sizeof(tnid.nid);
175131678a0SHermès Bélusca-Maïto tnid.nid.uFlags &= dwValidFlags;
176131678a0SHermès Bélusca-Maïto
177131678a0SHermès Bélusca-Maïto /* Be sure the szTip member (that could be cut-off) is correctly NULL-terminated */
178131678a0SHermès Bélusca-Maïto if (tnid.nid.uFlags & NIF_TIP)
179131678a0SHermès Bélusca-Maïto {
180131678a0SHermès Bélusca-Maïto if (cbSize <= NOTIFYICONDATAW_V1_SIZE)
181131678a0SHermès Bélusca-Maïto {
182131678a0SHermès Bélusca-Maïto #define NIDV1_TIP_SIZE_W (NOTIFYICONDATAW_V1_SIZE - FIELD_OFFSET(NOTIFYICONDATAW, szTip))/sizeof(WCHAR)
183131678a0SHermès Bélusca-Maïto tnid.nid.szTip[NIDV1_TIP_SIZE_W - 1] = 0;
184131678a0SHermès Bélusca-Maïto #undef NIDV1_TIP_SIZE_W
185131678a0SHermès Bélusca-Maïto }
186131678a0SHermès Bélusca-Maïto else
187131678a0SHermès Bélusca-Maïto {
188131678a0SHermès Bélusca-Maïto tnid.nid.szTip[_countof(tnid.nid.szTip) - 1] = 0;
189131678a0SHermès Bélusca-Maïto }
190131678a0SHermès Bélusca-Maïto }
191131678a0SHermès Bélusca-Maïto
192131678a0SHermès Bélusca-Maïto /* Be sure the info strings are correctly NULL-terminated */
193131678a0SHermès Bélusca-Maïto if (tnid.nid.uFlags & NIF_INFO)
194131678a0SHermès Bélusca-Maïto {
195131678a0SHermès Bélusca-Maïto tnid.nid.szInfo[_countof(tnid.nid.szInfo) - 1] = 0;
196131678a0SHermès Bélusca-Maïto tnid.nid.szInfoTitle[_countof(tnid.nid.szInfoTitle) - 1] = 0;
197131678a0SHermès Bélusca-Maïto }
198131678a0SHermès Bélusca-Maïto
199131678a0SHermès Bélusca-Maïto /* Send the data */
200*10d1afeaSjimtabor data.dwData = TABDMC_NOTIFY;
201131678a0SHermès Bélusca-Maïto data.cbData = sizeof(tnid);
202131678a0SHermès Bélusca-Maïto data.lpData = &tnid;
203131678a0SHermès Bélusca-Maïto if (SendMessageW(hShellTrayWnd, WM_COPYDATA, (WPARAM)pnid->hWnd, (LPARAM)&data))
204131678a0SHermès Bélusca-Maïto ret = TRUE;
205131678a0SHermès Bélusca-Maïto
206131678a0SHermès Bélusca-Maïto return ret;
207c2c66affSColin Finck }
208