2 * Copyright 2004 Martin Fuchs
3 * Copyright 2018 Hermes Belusca-Maito
5 * Pass on icon notification messages to the systray implementation
6 * in the currently running shell.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 WINE_DEFAULT_DEBUG_CHANNEL(shell_notify
);
27 /*************************************************************************
28 * Shell_NotifyIcon [SHELL32.296]
29 * Shell_NotifyIconA [SHELL32.297]
31 BOOL WINAPI
Shell_NotifyIconA(DWORD dwMessage
, PNOTIFYICONDATAA pnid
)
34 DWORD cbSize
, dwValidFlags
;
36 /* Initialize and capture the basic data fields */
37 ZeroMemory(&nidW
, sizeof(nidW
));
38 nidW
.cbSize
= sizeof(nidW
); // Use a default size for the moment
39 nidW
.hWnd
= pnid
->hWnd
;
41 nidW
.uFlags
= pnid
->uFlags
;
42 nidW
.uCallbackMessage
= pnid
->uCallbackMessage
;
43 nidW
.hIcon
= pnid
->hIcon
;
45 /* Validate the structure size and the flags */
46 cbSize
= pnid
->cbSize
;
47 dwValidFlags
= NIF_MESSAGE
| NIF_ICON
| NIF_TIP
;
48 if (cbSize
== sizeof(NOTIFYICONDATAA
))
50 nidW
.cbSize
= sizeof(nidW
);
51 dwValidFlags
|= NIF_STATE
| NIF_INFO
| NIF_GUID
/* | NIF_REALTIME | NIF_SHOWTIP */;
53 else if (cbSize
== NOTIFYICONDATAA_V3_SIZE
)
55 nidW
.cbSize
= NOTIFYICONDATAW_V3_SIZE
;
56 dwValidFlags
|= NIF_STATE
| NIF_INFO
| NIF_GUID
;
58 else if (cbSize
== NOTIFYICONDATAA_V2_SIZE
)
60 nidW
.cbSize
= NOTIFYICONDATAW_V2_SIZE
;
61 dwValidFlags
|= NIF_STATE
| NIF_INFO
;
63 else // if cbSize == NOTIFYICONDATAA_V1_SIZE or something else
65 if (cbSize
!= NOTIFYICONDATAA_V1_SIZE
)
67 WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n",
68 cbSize
, NOTIFYICONDATAA_V1_SIZE
);
69 cbSize
= NOTIFYICONDATAA_V1_SIZE
;
71 nidW
.cbSize
= NOTIFYICONDATAW_V1_SIZE
;
73 nidW
.uFlags
&= dwValidFlags
;
75 /* Capture the other data fields */
77 if (nidW
.uFlags
& NIF_TIP
)
80 * Depending on the size of the NOTIFYICONDATA structure
81 * we should convert part of, or all the szTip string.
83 if (cbSize
<= NOTIFYICONDATAA_V1_SIZE
)
85 #define NIDV1_TIP_SIZE_A (NOTIFYICONDATAA_V1_SIZE - FIELD_OFFSET(NOTIFYICONDATAA, szTip))/sizeof(CHAR)
86 MultiByteToWideChar(CP_ACP
, 0, pnid
->szTip
, NIDV1_TIP_SIZE_A
,
87 nidW
.szTip
, _countof(nidW
.szTip
));
88 /* Truncate the string */
89 nidW
.szTip
[NIDV1_TIP_SIZE_A
- 1] = 0;
90 #undef NIDV1_TIP_SIZE_A
94 MultiByteToWideChar(CP_ACP
, 0, pnid
->szTip
, -1,
95 nidW
.szTip
, _countof(nidW
.szTip
));
99 if (cbSize
>= NOTIFYICONDATAA_V2_SIZE
)
101 nidW
.dwState
= pnid
->dwState
;
102 nidW
.dwStateMask
= pnid
->dwStateMask
;
103 nidW
.uTimeout
= pnid
->uTimeout
;
104 nidW
.dwInfoFlags
= pnid
->dwInfoFlags
;
106 if (nidW
.uFlags
& NIF_INFO
)
108 MultiByteToWideChar(CP_ACP
, 0, pnid
->szInfo
, -1,
109 nidW
.szInfo
, _countof(nidW
.szInfo
));
110 MultiByteToWideChar(CP_ACP
, 0, pnid
->szInfoTitle
, -1,
111 nidW
.szInfoTitle
, _countof(nidW
.szInfoTitle
));
115 if ((cbSize
>= NOTIFYICONDATAA_V3_SIZE
) && (nidW
.uFlags
& NIF_GUID
))
116 nidW
.guidItem
= pnid
->guidItem
;
118 if (cbSize
>= sizeof(NOTIFYICONDATAA
))
119 nidW
.hBalloonIcon
= pnid
->hBalloonIcon
;
121 /* Call the unicode function */
122 return Shell_NotifyIconW(dwMessage
, &nidW
);
125 /*************************************************************************
126 * Shell_NotifyIconW [SHELL32.298]
128 BOOL WINAPI
Shell_NotifyIconW(DWORD dwMessage
, PNOTIFYICONDATAW pnid
)
132 DWORD cbSize
, dwValidFlags
;
133 TRAYNOTIFYDATAW tnid
;
136 /* Find a handle to the shell tray window */
137 hShellTrayWnd
= FindWindowW(L
"Shell_TrayWnd", NULL
);
139 return FALSE
; // None found, bail out
141 /* Validate the structure size and the flags */
142 cbSize
= pnid
->cbSize
;
143 dwValidFlags
= NIF_MESSAGE
| NIF_ICON
| NIF_TIP
;
144 if (cbSize
== sizeof(NOTIFYICONDATAW
))
146 dwValidFlags
|= NIF_STATE
| NIF_INFO
| NIF_GUID
/* | NIF_REALTIME | NIF_SHOWTIP */;
148 else if (cbSize
== NOTIFYICONDATAW_V3_SIZE
)
150 dwValidFlags
|= NIF_STATE
| NIF_INFO
| NIF_GUID
;
152 else if (cbSize
== NOTIFYICONDATAW_V2_SIZE
)
154 dwValidFlags
|= NIF_STATE
| NIF_INFO
;
156 else // if cbSize == NOTIFYICONDATAW_V1_SIZE or something else
158 if (cbSize
!= NOTIFYICONDATAW_V1_SIZE
)
160 WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n",
161 cbSize
, NOTIFYICONDATAW_V1_SIZE
);
162 cbSize
= NOTIFYICONDATAW_V1_SIZE
;
166 /* Build the data structure */
167 ZeroMemory(&tnid
, sizeof(tnid
));
168 tnid
.dwSignature
= NI_NOTIFY_SIG
;
169 tnid
.dwMessage
= dwMessage
;
171 /* Copy only the needed data, everything else is zeroed out */
172 CopyMemory(&tnid
.nid
, pnid
, cbSize
);
173 /* Adjust the size (the NOTIFYICONDATA structure is the full-fledged one) and the flags */
174 tnid
.nid
.cbSize
= sizeof(tnid
.nid
);
175 tnid
.nid
.uFlags
&= dwValidFlags
;
177 /* Be sure the szTip member (that could be cut-off) is correctly NULL-terminated */
178 if (tnid
.nid
.uFlags
& NIF_TIP
)
180 if (cbSize
<= NOTIFYICONDATAW_V1_SIZE
)
182 #define NIDV1_TIP_SIZE_W (NOTIFYICONDATAW_V1_SIZE - FIELD_OFFSET(NOTIFYICONDATAW, szTip))/sizeof(WCHAR)
183 tnid
.nid
.szTip
[NIDV1_TIP_SIZE_W
- 1] = 0;
184 #undef NIDV1_TIP_SIZE_W
188 tnid
.nid
.szTip
[_countof(tnid
.nid
.szTip
) - 1] = 0;
192 /* Be sure the info strings are correctly NULL-terminated */
193 if (tnid
.nid
.uFlags
& NIF_INFO
)
195 tnid
.nid
.szInfo
[_countof(tnid
.nid
.szInfo
) - 1] = 0;
196 tnid
.nid
.szInfoTitle
[_countof(tnid
.nid
.szInfoTitle
) - 1] = 0;
201 data
.cbData
= sizeof(tnid
);
203 if (SendMessageW(hShellTrayWnd
, WM_COPYDATA
, (WPARAM
)pnid
->hWnd
, (LPARAM
)&data
))