4 * Copyright 1999 Kai Morich <kai.morich@bigfoot.de>
5 * Copyright 2004 Mike Hearn, for CodeWeavers
6 * Copyright 2005 Robert Shearman
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 St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define NONAMELESSUNION
33 #include "shell32_main.h"
35 #include "wine/debug.h"
36 #include "wine/heap.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(systray
);
40 static const WCHAR classname
[] = /* Shell_TrayWnd */ {'S','h','e','l','l','_','T','r','a','y','W','n','d','\0'};
42 struct notify_data
/* platform-independent format for NOTIFYICONDATA */
47 UINT uCallbackMessage
;
56 WCHAR szInfoTitle
[64];
59 /* data for the icon bitmap */
66 /*************************************************************************
67 * Shell_NotifyIcon [SHELL32.296]
68 * Shell_NotifyIconA [SHELL32.297]
70 BOOL WINAPI
Shell_NotifyIconA(DWORD dwMessage
, PNOTIFYICONDATAA pnid
)
75 /* Validate the cbSize as Windows XP does */
76 if (pnid
->cbSize
!= NOTIFYICONDATAA_V1_SIZE
&&
77 pnid
->cbSize
!= NOTIFYICONDATAA_V2_SIZE
&&
78 pnid
->cbSize
!= NOTIFYICONDATAA_V3_SIZE
&&
79 pnid
->cbSize
!= sizeof(NOTIFYICONDATAA
))
81 WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n",
82 pnid
->cbSize
, NOTIFYICONDATAA_V1_SIZE
);
83 cbSize
= NOTIFYICONDATAA_V1_SIZE
;
86 cbSize
= pnid
->cbSize
;
88 ZeroMemory(&nidW
, sizeof(nidW
));
89 nidW
.cbSize
= sizeof(nidW
);
90 nidW
.hWnd
= pnid
->hWnd
;
92 nidW
.uFlags
= pnid
->uFlags
;
93 nidW
.uCallbackMessage
= pnid
->uCallbackMessage
;
94 nidW
.hIcon
= pnid
->hIcon
;
97 if (pnid
->uFlags
& NIF_TIP
)
98 MultiByteToWideChar(CP_ACP
, 0, pnid
->szTip
, -1, nidW
.szTip
, ARRAY_SIZE(nidW
.szTip
));
100 if (cbSize
>= NOTIFYICONDATAA_V2_SIZE
)
102 nidW
.dwState
= pnid
->dwState
;
103 nidW
.dwStateMask
= pnid
->dwStateMask
;
105 /* szInfo, szInfoTitle */
106 if (pnid
->uFlags
& NIF_INFO
)
108 MultiByteToWideChar(CP_ACP
, 0, pnid
->szInfo
, -1, nidW
.szInfo
, ARRAY_SIZE(nidW
.szInfo
));
109 MultiByteToWideChar(CP_ACP
, 0, pnid
->szInfoTitle
, -1, nidW
.szInfoTitle
, ARRAY_SIZE(nidW
.szInfoTitle
));
112 nidW
.u
.uTimeout
= pnid
->u
.uTimeout
;
113 nidW
.dwInfoFlags
= pnid
->dwInfoFlags
;
116 if (cbSize
>= NOTIFYICONDATAA_V3_SIZE
)
117 nidW
.guidItem
= pnid
->guidItem
;
119 if (cbSize
>= sizeof(NOTIFYICONDATAA
))
120 nidW
.hBalloonIcon
= pnid
->hBalloonIcon
;
121 return Shell_NotifyIconW(dwMessage
, &nidW
);
124 /*************************************************************************
125 * Shell_NotifyIconW [SHELL32.298]
127 BOOL WINAPI
Shell_NotifyIconW(DWORD dwMessage
, PNOTIFYICONDATAW nid
)
131 struct notify_data data_buffer
;
132 struct notify_data
*data
= &data_buffer
;
135 TRACE("dwMessage = %d, nid->cbSize=%d\n", dwMessage
, nid
->cbSize
);
137 /* Validate the cbSize so that WM_COPYDATA doesn't crash the application */
138 if (nid
->cbSize
!= NOTIFYICONDATAW_V1_SIZE
&&
139 nid
->cbSize
!= NOTIFYICONDATAW_V2_SIZE
&&
140 nid
->cbSize
!= NOTIFYICONDATAW_V3_SIZE
&&
141 nid
->cbSize
!= sizeof(NOTIFYICONDATAW
))
143 NOTIFYICONDATAW newNid
;
145 WARN("Invalid cbSize (%d) - using only Win95 fields (size=%d)\n",
146 nid
->cbSize
, NOTIFYICONDATAW_V1_SIZE
);
147 CopyMemory(&newNid
, nid
, NOTIFYICONDATAW_V1_SIZE
);
148 newNid
.cbSize
= NOTIFYICONDATAW_V1_SIZE
;
149 return Shell_NotifyIconW(dwMessage
, &newNid
);
152 tray
= FindWindowExW(0, NULL
, classname
, NULL
);
153 if (!tray
) return FALSE
;
155 cds
.dwData
= dwMessage
;
156 cds
.cbData
= sizeof(*data
);
157 memset( data
, 0, sizeof(*data
) );
159 /* FIXME: if statement only needed because we don't support interprocess
161 if (nid
->uFlags
& NIF_ICON
)
167 LONG cbColourBits
= 0;
170 if (!GetIconInfo(nid
->hIcon
, &iconinfo
))
173 if (!GetObjectW(iconinfo
.hbmMask
, sizeof(bmMask
), &bmMask
) ||
174 (iconinfo
.hbmColor
&& !GetObjectW(iconinfo
.hbmColor
, sizeof(bmColour
), &bmColour
)))
176 DeleteObject(iconinfo
.hbmMask
);
177 if (iconinfo
.hbmColor
) DeleteObject(iconinfo
.hbmColor
);
181 cbMaskBits
= (bmMask
.bmPlanes
* bmMask
.bmWidth
* bmMask
.bmHeight
* bmMask
.bmBitsPixel
+ 15) / 16 * 2;
182 if (iconinfo
.hbmColor
)
183 cbColourBits
= (bmColour
.bmPlanes
* bmColour
.bmWidth
* bmColour
.bmHeight
* bmColour
.bmBitsPixel
+ 15) / 16 * 2;
184 cds
.cbData
= sizeof(*data
) + cbMaskBits
+ cbColourBits
;
185 buffer
= heap_alloc(cds
.cbData
);
188 DeleteObject(iconinfo
.hbmMask
);
189 if (iconinfo
.hbmColor
) DeleteObject(iconinfo
.hbmColor
);
193 data
= (struct notify_data
*)buffer
;
194 memset( data
, 0, sizeof(*data
) );
195 buffer
+= sizeof(*data
);
196 GetBitmapBits(iconinfo
.hbmMask
, cbMaskBits
, buffer
);
197 if (!iconinfo
.hbmColor
)
199 data
->width
= bmMask
.bmWidth
;
200 data
->height
= bmMask
.bmHeight
/ 2;
206 data
->width
= bmColour
.bmWidth
;
207 data
->height
= bmColour
.bmHeight
;
208 data
->planes
= bmColour
.bmPlanes
;
209 data
->bpp
= bmColour
.bmBitsPixel
;
210 buffer
+= cbMaskBits
;
211 GetBitmapBits(iconinfo
.hbmColor
, cbColourBits
, buffer
);
212 DeleteObject(iconinfo
.hbmColor
);
214 DeleteObject(iconinfo
.hbmMask
);
218 data
->hWnd
= HandleToLong( nid
->hWnd
);
219 data
->uID
= nid
->uID
;
220 data
->uFlags
= nid
->uFlags
;
221 if (data
->uFlags
& NIF_MESSAGE
)
222 data
->uCallbackMessage
= nid
->uCallbackMessage
;
223 if (data
->uFlags
& NIF_TIP
)
224 lstrcpynW( data
->szTip
, nid
->szTip
, ARRAY_SIZE(data
->szTip
));
225 if (data
->uFlags
& NIF_STATE
)
227 data
->dwState
= nid
->dwState
;
228 data
->dwStateMask
= nid
->dwStateMask
;
230 if (data
->uFlags
& NIF_INFO
)
232 lstrcpynW( data
->szInfo
, nid
->szInfo
, ARRAY_SIZE(data
->szInfo
) );
233 lstrcpynW( data
->szInfoTitle
, nid
->szInfoTitle
, ARRAY_SIZE(data
->szInfoTitle
));
234 data
->u
.uTimeout
= nid
->u
.uTimeout
;
235 data
->dwInfoFlags
= nid
->dwInfoFlags
;
237 if (data
->uFlags
& NIF_GUID
)
238 data
->guidItem
= nid
->guidItem
;
239 if (dwMessage
== NIM_SETVERSION
)
240 data
->u
.uVersion
= nid
->u
.uVersion
;
241 /* FIXME: balloon icon */
244 ret
= SendMessageW(tray
, WM_COPYDATA
, (WPARAM
)nid
->hWnd
, (LPARAM
)&cds
);
245 if (data
!= &data_buffer
) heap_free( data
);
249 /*************************************************************************
250 * Shell_NotifyIconGetRect [SHELL32.@]
252 HRESULT WINAPI
Shell_NotifyIconGetRect(const NOTIFYICONIDENTIFIER
* identifier
, RECT
* icon_location
)
254 FIXME("stub (%p) (%p)\n", identifier
, icon_location
);