xref: /reactos/dll/win32/shell32/systray.cpp (revision 10d1afea)
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