4 #include "AFS_component_version_number.h"
12 static ATOM message_window_class
= 0;
13 static HWND notifier_window
= NULL
;
14 static volatile BOOL notification_icon_added
= FALSE
;
16 #define TOKEN_ICON_ID 1
17 #define TOKEN_MESSAGE_ID WM_USER
20 get_default_notifier_action(void)
22 khm_int32 cmd
= KHUI_ACTION_OPEN_APP
;
24 khc_read_int32(NULL
, L
"CredWindow\\NotificationAction", &cmd
);
30 get_release_notes(wchar_t rpath
[MAX_PATH
])
33 HKEY hk_client
= NULL
;
34 wchar_t cpath
[MAX_PATH
];
37 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
38 L
"Software\\TransarcCorporation\\AFS Client\\CurrentVersion",
39 0, KEY_READ
, &hk_client
) != ERROR_SUCCESS
)
42 cb_data
= sizeof(cpath
);
43 if (RegQueryValueEx(hk_client
, L
"PathName", NULL
, NULL
, (LPBYTE
) cpath
, &cb_data
) != ERROR_SUCCESS
)
46 cpath
[min(cb_data
, MAX_PATH
- 1)] = L
'\0';
48 if (!PathRemoveFileSpec(cpath
))
51 if (!PathAppend(cpath
, L
"Documentation"))
54 if (!PathAppend(cpath
, L
"ReleaseNotes.chm"))
57 if (!PathCanonicalize(rpath
, cpath
))
60 if (!PathFileExists(rpath
))
67 RegCloseKey(hk_client
);
78 cmd
= get_default_notifier_action();
80 khui_action_trigger(cmd
, NULL
);
82 ZeroMemory(&idata
, sizeof(idata
));
84 Shell_NotifyIcon(NIM_SETFOCUS
, &idata
);
88 prepare_context_menu(HMENU hmenu
)
92 wchar_t relnotes
[MAX_PATH
];
94 cmd
= get_default_notifier_action();
96 if (cmd
== KHUI_ACTION_NEW_CRED
)
97 LoadString(hResModule
, IDS_ACT_NEW
, caption
, ARRAYLENGTH(caption
));
99 LoadString(hResModule
, IDS_ACT_OPEN
, caption
, ARRAYLENGTH(caption
));
101 ModifyMenu(hmenu
, ID_DEFAULT
, MF_STRING
|MF_BYCOMMAND
, ID_DEFAULT
, caption
);
102 SetMenuDefaultItem(hmenu
, ID_DEFAULT
, FALSE
);
104 if (!get_release_notes(relnotes
))
105 RemoveMenu(hmenu
, ID_RELEASENOTES
, MF_BYCOMMAND
);
109 handle_context_menu(void)
117 hMenuBar
= LoadMenu(hResModule
, MAKEINTRESOURCE(IDR_CTXMENU
));
118 hMenu
= GetSubMenu(hMenuBar
, 0);
121 prepare_context_menu(hMenu
);
122 TrackPopupMenu(hMenu
, TPM_NONOTIFY
, pt
.x
, pt
.y
, 0, notifier_window
, NULL
);
126 NOTIFYICONDATA idata
;
127 ZeroMemory(&idata
, sizeof(idata
));
128 Shell_NotifyIcon(NIM_SETFOCUS
, &idata
);
132 static LRESULT CALLBACK
133 notifier_wnd_proc(HWND hwnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
135 if (uMsg
== TOKEN_MESSAGE_ID
) {
144 handle_context_menu();
151 else if (uMsg
== WM_COMMAND
) {
152 switch (LOWORD(wParam
)) {
157 cmd
= get_default_notifier_action();
159 khui_action_trigger(cmd
, NULL
);
165 afs_html_help(notifier_window
, L
"::/html/welcome.htm", HH_DISPLAY_TOPIC
, 0);
169 case ID_RELEASENOTES
:
171 wchar_t relnotes
[MAX_PATH
];
173 if (get_release_notes(relnotes
))
174 HtmlHelp(GetDesktopWindow(), relnotes
, HH_DISPLAY_TOC
, 0);
179 return DefWindowProc(hwnd
, uMsg
, wParam
, lParam
);
183 initialize_if_necessary(void)
185 if (message_window_class
== 0) {
187 sizeof(WNDCLASSEX
), /* cbSize */
189 notifier_wnd_proc
, /* lpfnWndProc */
192 NULL
, /* hinstance */
195 NULL
, /* hbrBackground */
196 NULL
, /* lpszMenuName */
197 L
"OpenAFSTokenStateIconNotifier", /* lpszClassName */
201 c
.hInstance
= hInstance
;
202 message_window_class
= RegisterClassEx(&c
);
205 if (notifier_window
== NULL
&& message_window_class
!= 0) {
206 notifier_window
= CreateWindow(MAKEINTATOM(message_window_class
),
207 L
"OpenAFSTokenStateIconNotifierWindow",
215 assert(notifier_window
!= NULL
);
217 if (!notification_icon_added
&& notifier_window
!= NULL
) {
218 NOTIFYICONDATA idata
;
220 ZeroMemory(&idata
, sizeof(idata
));
222 idata
.cbSize
= sizeof(idata
);
223 idata
.hWnd
= notifier_window
;
224 idata
.uID
= TOKEN_ICON_ID
;
225 idata
.uFlags
= NIF_ICON
| NIF_MESSAGE
;
226 idata
.uCallbackMessage
= TOKEN_MESSAGE_ID
;
227 idata
.hIcon
= (HICON
) LoadImage(hResModule
, MAKEINTRESOURCE(IDI_CRED_NONE
),
229 LR_DEFAULTSIZE
| LR_DEFAULTCOLOR
| LR_SHARED
);
230 notification_icon_added
= Shell_NotifyIcon(NIM_ADD
, &idata
);
232 idata
.cbSize
= sizeof(idata
);
233 idata
.uVersion
= NOTIFYICON_VERSION
;
235 Shell_NotifyIcon(NIM_SETVERSION
, &idata
);
237 assert(notification_icon_added
);
242 afs_remove_icon(void)
244 NOTIFYICONDATA idata
;
246 ZeroMemory(&idata
, sizeof(idata
));
248 idata
.cbSize
= sizeof(idata
);
249 idata
.hWnd
= notifier_window
;
250 idata
.uID
= TOKEN_ICON_ID
;
251 Shell_NotifyIcon(NIM_DELETE
, &idata
);
252 notification_icon_added
= FALSE
;
256 set_tooltip_and_icon(UINT tooltip_text
, const wchar_t * postfix
, UINT icon_id
)
258 NOTIFYICONDATA idata
;
259 wchar_t buf
[ARRAYLENGTH(idata
.szTip
)];
261 ZeroMemory(&idata
, sizeof(idata
));
263 idata
.cbSize
= sizeof(idata
);
264 idata
.hWnd
= notifier_window
;
265 idata
.uID
= TOKEN_ICON_ID
;
266 idata
.uFlags
= NIF_ICON
| NIF_TIP
;
267 idata
.hIcon
= (HICON
) LoadImage(hResModule
, MAKEINTRESOURCE(icon_id
),
269 LR_DEFAULTCOLOR
| LR_DEFAULTSIZE
| LR_SHARED
);
270 if (tooltip_text
!= 0) {
271 LoadString(hResModule
, tooltip_text
, buf
, ARRAYLENGTH(buf
));
273 StringCbPrintf(idata
.szTip
, sizeof(idata
.szTip
),
275 (tooltip_text
!= 0)? buf
: L
"",
276 (postfix
!= NULL
)? postfix
: L
"",
277 (tooltip_text
!= 0 || postfix
!= NULL
)? L
"\n": L
"",
278 _T(AFS_VERINFO_BUILD
));
280 Shell_NotifyIcon(NIM_MODIFY
, &idata
);
284 enum notification_icon_state state
;
288 #define COLLECT_STR_LEN 256
290 static khm_int32 KHMAPI
291 collect_cell_names(khm_handle cred
, void * rock
)
293 wchar_t *str
= (wchar_t *) rock
;
294 wchar_t cell
[KCDB_MAXCCH_NAME
] = L
"";
299 cb
= sizeof(ft_expire
);
300 if (KHM_FAILED(kcdb_cred_get_attr(cred
, KCDB_ATTR_EXPIRE
, NULL
, &ft_expire
, &cb
)))
301 return KHM_ERROR_SUCCESS
;
303 GetSystemTimeAsFileTime(&ft_now
);
304 if (CompareFileTime(&ft_now
, &ft_expire
) >= 0)
305 return KHM_ERROR_SUCCESS
;
309 if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred
, afs_attr_cell
, NULL
, cell
, &cb
)) &&
311 StringCchCat(str
, COLLECT_STR_LEN
, cell
);
312 StringCchCat(str
, COLLECT_STR_LEN
, L
"\n");
315 return KHM_ERROR_SUCCESS
;
318 static khm_int32 KHMAPI
319 set_state_from_ui_thread(HWND hwnd_main
, void * stuff
)
321 struct state_data
* d
= (struct state_data
*) stuff
;
323 initialize_if_necessary();
326 case AFSICON_REPORT_TOKENS
:
328 wchar_t cells
[COLLECT_STR_LEN
] = L
"";
330 kcdb_credset_apply(d
->credset
, collect_cell_names
, cells
);
332 if (cells
[0] == L
'\0') {
333 set_tooltip_and_icon(IDS_CRED_TT_NONE
, NULL
, IDI_CRED_NONE
);
337 set_tooltip_and_icon(0, cells
, IDI_CRED_OK
);
341 case AFSICON_SERVICE_STOPPED
:
342 set_tooltip_and_icon(IDS_CRED_TT_NOS
, NULL
, IDI_CRED_SVCSTOP
);
345 case AFSICON_SERVICE_ERROR
:
346 set_tooltip_and_icon(IDS_CRED_TT_SERR
, NULL
, IDI_CRED_BROKEN
);
353 (void) hwnd_main
; /* unreferenced */
355 return KHM_ERROR_SUCCESS
;
359 afs_icon_set_state(enum notification_icon_state state
,
360 khm_handle credset_with_tokens
)
364 #if KH_VERSION_API < 7
365 if (pkhui_request_UI_callback
== NULL
)
370 d
.credset
= credset_with_tokens
;
372 if (notification_icon_added
) {
373 set_state_from_ui_thread(NULL
, &d
);
375 khui_request_UI_callback(set_state_from_ui_thread
, &d
);