LIBFILE=$(LIBFILEDIR)\afscred.lib
INCFILES= \
+ AFS_component_version_number.h \
afsp_version.h \
$(INCFILEDIR)\afspext.h \
$(INCFILEDIR)\afsp_version.h
OBJFILES= \
+ $(OUT)\AFS_component_version_number.obj \
$(OUT)\afsfuncs.obj \
$(OUT)\afsplugin.obj \
$(OUT)\main.obj \
$(OUT)\afsnewcreds.obj \
$(OUT)\afsext.obj \
$(OUT)\afshelp.obj \
+ $(OUT)\afsicon.obj \
$(OUT)\dynimport.obj \
$(OUT)\krb5common.obj
$(OUT)\afshelp.obj: afshelp.c
$(PC2OBJ)
+$(OUT)\afsicon.obj: afsicon.c
+ $(PC2OBJ)
+
$(OUT)\dynimport.obj: dynimport.c
$(PC2OBJ)
BOOL
afs_cfg_get_afscreds_shortcut(wchar_t * wpath);
+/* Notificaiton icon functions */
+
+enum notification_icon_state {
+ AFSICON_REPORT_TOKENS,
+ AFSICON_SERVICE_STOPPED,
+ AFSICON_SERVICE_ERROR
+};
+
+void
+afs_icon_set_state(enum notification_icon_state state,
+ khm_handle credset_with_tokens);
+
+void
+afs_remove_icon(void);
+
+
+/* Compatibility */
+#if KH_VERSION_API < 7
+
+#ifdef _WIN64
+#define NIMDLLNAME L"nidmgr64.dll"
+#define API_khui_action_lock "khui_action_lock"
+#define API_khui_action_unlock "khui_action_unlock"
+#define API_khui_refresh_actions "khui_refresh_actions"
+#define API_khui_request_UI_callback "khui_request_UI_callback"
+#else
+#define NIMDLLNAME L"nidmgr32.dll"
+#define API_khui_action_lock "_khui_action_lock@0"
+#define API_khui_action_unlock "_khui_action_unlock@0"
+#define API_khui_refresh_actions "_khui_refresh_actions@0"
+#define API_khui_request_UI_callback "_khui_request_UI_callback@8"
+#endif
+
+extern void
+(KHMAPI * pkhui_action_lock)(void);
+
+extern void
+(KHMAPI * pkhui_action_unlock)(void);
+
+extern void
+(KHMAPI * pkhui_refresh_actions)(void);
+
+typedef khm_int32
+(KHMAPI * khm_ui_callback)(HWND hwnd_main_wnd, void * rock);
+
+extern khm_int32
+(KHMAPI * pkhui_request_UI_callback)(khm_ui_callback cb,
+ void * rock);
+
+#define khui_action_lock (*pkhui_action_lock)
+#define khui_action_unlock (*pkhui_action_unlock)
+#define khui_refresh_actions (*pkhui_refresh_actions)
+#define khui_request_UI_callback (*pkhui_request_UI_callback)
+
+#endif
+
#endif
r = afs_list_tokens_internal();
kcdb_credset_collect(NULL, afs_credset, NULL, afs_credtype_id, NULL);
+ if (r == 0) {
+ afs_icon_set_state(AFSICON_REPORT_TOKENS, afs_credset);
+ } else if (r == -1) {
+ afs_icon_set_state(AFSICON_SERVICE_STOPPED, NULL);
+ } else {
+ afs_icon_set_state(AFSICON_SERVICE_ERROR, NULL);
+ }
+
return r;
}
FILETIME ft;
if (!afs_is_running())
- return 0;
+ return -1;
kcdb_credset_flush(afs_credset);
if (rc = ktc_ListTokens(cellNum, &cellNum, &aserver))
{
if (rc != KTC_NOENT)
- return(0);
+ return(-2);
if (BreakAtEnd == 1)
break;
if (rc = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient))
{
if (rc == KTC_ERROR)
- return(0);
+ return(-3);
continue;
}
--- /dev/null
+
+#define NOSTRSAFE
+#include "afscred.h"
+#include "AFS_component_version_number.h"
+#include <tchar.h>
+#include <shellapi.h>
+#include <strsafe.h>
+#include <assert.h>
+
+static ATOM message_window_class = 0;
+static HWND notifier_window = NULL;
+static volatile BOOL notification_icon_added = FALSE;
+
+#define TOKEN_ICON_ID 1
+#define TOKEN_MESSAGE_ID WM_USER
+
+static LRESULT CALLBACK
+notifier_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uMsg == TOKEN_MESSAGE_ID) {
+ switch (lParam) {
+ case NIN_SELECT:
+ case NIN_KEYSELECT:
+
+ {
+ NOTIFYICONDATA idata;
+ khm_int32 cmd = KHUI_ACTION_OPEN_APP;
+
+ khc_read_int32(NULL, L"CredWindow\\NotificationAction", &cmd);
+
+ khui_action_trigger(cmd, NULL);
+
+ ZeroMemory(&idata, sizeof(idata));
+
+ Shell_NotifyIcon(NIM_SETFOCUS, &idata);
+ }
+ return 0;
+
+ default:
+ return 0;
+ }
+ }
+ return DefWindowProc(hwnd, uMsg, wParam, lParam);
+}
+
+static void
+initialize_if_necessary(void)
+{
+ if (message_window_class == 0) {
+ WNDCLASSEX c = {
+ sizeof(WNDCLASSEX), /* cbSize */
+ 0, /* style */
+ notifier_wnd_proc, /* lpfnWndProc */
+ 0, /* cbClsExtra */
+ 0, /* cbWndExtra */
+ hInstance, /* hinstance */
+ NULL, /* hIcon */
+ NULL, /* hCursor */
+ NULL, /* hbrBackground */
+ NULL, /* lpszMenuName */
+ L"OpenAFSTokenStateIconNotifier", /* lpszClassName */
+ NULL, /* hIconSm */
+ };
+
+ message_window_class = RegisterClassEx(&c);
+ }
+
+ if (notifier_window == NULL && message_window_class != 0) {
+ notifier_window = CreateWindow(MAKEINTATOM(message_window_class),
+ L"OpenAFSTokenStateIconNotifierWindow",
+ 0, 0, 0, 0, 0,
+ HWND_MESSAGE,
+ NULL,
+ hInstance,
+ NULL);
+ }
+
+ assert(notifier_window != NULL);
+
+ if (!notification_icon_added && notifier_window != NULL) {
+ NOTIFYICONDATA idata;
+
+ ZeroMemory(&idata, sizeof(idata));
+
+ idata.cbSize = sizeof(idata);
+ idata.hWnd = notifier_window;
+ idata.uID = TOKEN_ICON_ID;
+ idata.uFlags = NIF_ICON | NIF_MESSAGE;
+ idata.uCallbackMessage = TOKEN_MESSAGE_ID;
+ idata.hIcon = (HICON) LoadImage(hResModule, MAKEINTRESOURCE(IDI_CRED_NONE),
+ IMAGE_ICON, 0, 0,
+ LR_DEFAULTSIZE | LR_DEFAULTCOLOR | LR_SHARED);
+ notification_icon_added = Shell_NotifyIcon(NIM_ADD, &idata);
+
+ idata.cbSize = sizeof(idata);
+ idata.uVersion = NOTIFYICON_VERSION;
+
+ Shell_NotifyIcon(NIM_SETVERSION, &idata);
+
+ assert(notification_icon_added);
+ }
+}
+
+void
+afs_remove_icon(void)
+{
+ NOTIFYICONDATA idata;
+ wchar_t buf[ARRAYLENGTH(idata.szTip)];
+
+ ZeroMemory(&idata, sizeof(idata));
+
+ idata.cbSize = sizeof(idata);
+ idata.hWnd = notifier_window;
+ idata.uID = TOKEN_ICON_ID;
+ Shell_NotifyIcon(NIM_DELETE, &idata);
+ notification_icon_added = FALSE;
+}
+
+static void
+set_tooltip_and_icon(UINT tooltip_text, const wchar_t * postfix, UINT icon_id)
+{
+ NOTIFYICONDATA idata;
+ wchar_t buf[ARRAYLENGTH(idata.szTip)];
+
+ ZeroMemory(&idata, sizeof(idata));
+
+ idata.cbSize = sizeof(idata);
+ idata.hWnd = notifier_window;
+ idata.uID = TOKEN_ICON_ID;
+ idata.uFlags = NIF_ICON | NIF_TIP;
+ idata.hIcon = (HICON) LoadImage(hResModule, MAKEINTRESOURCE(icon_id),
+ IMAGE_ICON, 0, 0,
+ LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
+ if (tooltip_text != 0) {
+ LoadString(hResModule, tooltip_text, buf, ARRAYLENGTH(buf));
+ }
+ StringCbPrintf(idata.szTip, sizeof(idata.szTip),
+ L"%s%s%s%s",
+ (tooltip_text != 0)? buf : L"",
+ (postfix != NULL)? postfix : L"",
+ (tooltip_text != 0 || postfix != NULL)? L"\n": L"",
+ _T(AFS_VERINFO_BUILD));
+
+ Shell_NotifyIcon(NIM_MODIFY, &idata);
+}
+
+struct state_data {
+ enum notification_icon_state state;
+ khm_handle credset;
+};
+
+#define COLLECT_STR_LEN 256
+
+static khm_int32 KHMAPI
+collect_cell_names(khm_handle cred, void * rock)
+{
+ wchar_t *str = (wchar_t *) rock;
+ wchar_t cell[KCDB_MAXCCH_NAME] = L"";
+ FILETIME ft_now;
+ FILETIME ft_expire;
+ khm_size cb;
+
+ cb = sizeof(ft_expire);
+ if (KHM_FAILED(kcdb_cred_get_attr(cred, KCDB_ATTR_EXPIRE, NULL, &ft_expire, &cb)))
+ return KHM_ERROR_SUCCESS;
+
+ GetSystemTimeAsFileTime(&ft_now);
+ if (CompareFileTime(&ft_now, &ft_expire) >= 0)
+ return KHM_ERROR_SUCCESS;
+
+ cb = sizeof(cell);
+
+ if (KHM_SUCCEEDED(kcdb_cred_get_attr(cred, afs_attr_cell, NULL, cell, &cb)) &&
+ cell[0]) {
+ StringCchCat(str, COLLECT_STR_LEN, cell);
+ StringCchCat(str, COLLECT_STR_LEN, L"\n");
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+static khm_int32 KHMAPI
+set_state_from_ui_thread(HWND hwnd_main, void * stuff)
+{
+ struct state_data * d = (struct state_data *) stuff;
+
+ initialize_if_necessary();
+
+ switch (d->state) {
+ case AFSICON_REPORT_TOKENS:
+ {
+ wchar_t cells[COLLECT_STR_LEN] = L"";
+
+ kcdb_credset_apply(d->credset, collect_cell_names, cells);
+
+ if (cells[0] == L'\0') {
+ set_tooltip_and_icon(IDS_CRED_TT_NONE, NULL, IDI_CRED_NONE);
+ break;
+ }
+
+ set_tooltip_and_icon(0, cells, IDI_CRED_OK);
+ }
+ break;
+
+ case AFSICON_SERVICE_STOPPED:
+ set_tooltip_and_icon(IDS_CRED_TT_NOS, NULL, IDI_CRED_SVCSTOP);
+ break;
+
+ case AFSICON_SERVICE_ERROR:
+ set_tooltip_and_icon(IDS_CRED_TT_SERR, NULL, IDI_CRED_BROKEN);
+ break;
+
+ default:
+ assert(FALSE);
+ }
+
+ return KHM_ERROR_SUCCESS;
+}
+
+void
+afs_icon_set_state(enum notification_icon_state state,
+ khm_handle credset_with_tokens)
+{
+ struct state_data d;
+
+#if KH_VERSION_API < 7
+ if (pkhui_request_UI_callback == NULL)
+ return;
+#endif
+
+ d.state = state;
+ d.credset = credset_with_tokens;
+
+ if (notification_icon_added) {
+ set_state_from_ui_thread(NULL, &d);
+ } else {
+ khui_request_UI_callback(set_state_from_ui_thread, &d);
+ }
+}
HMODULE hm_netidmgr;
/* declarations from version 7 of the API */
-KHMEXP void
+void
(KHMAPI * pkhui_action_lock)(void);
-KHMEXP void
+void
(KHMAPI * pkhui_action_unlock)(void);
-KHMEXP void
+void
(KHMAPI * pkhui_refresh_actions)(void);
typedef khm_int32
(KHMAPI * khm_ui_callback)(HWND hwnd_main_wnd, void * rock);
-KHMEXP khm_int32
+khm_int32
(KHMAPI * pkhui_request_UI_callback)(khm_ui_callback cb,
void * rock);
-#define khui_action_lock (*pkhui_action_lock)
-#define khui_action_unlock (*pkhui_action_unlock)
-#define khui_refresh_actions (*pkhui_refresh_actions)
-#define khui_request_UI_callback (*pkhui_request_UI_callback)
-
#endif
/* AFS plugin callback */
switch(msg_subtype) {
case KMSG_SYSTEM_INIT:
+
+ /* If we are building against an older SDK, we should try to
+ load newer APIs if it's available at run-time. */
+#if KH_VERSION_API < 7
+ do {
+ khm_version libver;
+ khm_ui_4 apiver;
+
+ khm_get_lib_version(&libver, &apiver);
+
+ if (apiver < 7)
+ break;
+
+ hm_netidmgr = LoadLibrary(NIMDLLNAME);
+
+ if (hm_netidmgr == NULL)
+ break;
+
+ pkhui_action_lock = (void (KHMAPI *)(void))
+ GetProcAddress(hm_netidmgr, API_khui_action_lock);
+ pkhui_action_unlock = (void (KHMAPI *)(void))
+ GetProcAddress(hm_netidmgr, API_khui_action_unlock);
+ pkhui_refresh_actions = (void (KHMAPI *)(void))
+ GetProcAddress(hm_netidmgr, API_khui_refresh_actions);
+ pkhui_request_UI_callback = (khm_int32 (KHMAPI *)(khm_ui_callback, void *))
+ GetProcAddress(hm_netidmgr, API_khui_request_UI_callback);
+
+ } while (FALSE);
+#endif
+
+ /* Add the icon now. On NIM v2.x, doing so after tokens were
+ reported may result in a deadlock as we try to switch to
+ the UI thread and the UI thread is blocked on a resource
+ request to this plug-in. */
+ afs_icon_set_state(AFSICON_SERVICE_STOPPED, NULL);
+
/* Perform critical registrations and data structure
initalization */
{
wchar_t long_desc[KHUI_MAXCCH_LONG_DESC];
#if KH_VERSION_API < 7
-
- khm_version libver;
- khm_ui_4 apiver;
-
- khm_get_lib_version(&libver, &apiver);
-
- if (apiver < 7)
- goto no_custom_help;
-
- hm_netidmgr = LoadLibrary(L"nidmgr32.dll");
-
- if (hm_netidmgr == NULL)
- goto no_custom_help;
-
- pkhui_action_lock = (void (KHMAPI *)(void))
- GetProcAddress(hm_netidmgr, "_khui_action_lock@0");
- pkhui_action_unlock = (void (KHMAPI *)(void))
- GetProcAddress(hm_netidmgr, "_khui_action_unlock@0");
- pkhui_refresh_actions = (void (KHMAPI *)(void))
- GetProcAddress(hm_netidmgr, "_khui_refresh_actions@0");
- pkhui_request_UI_callback = (khm_int32 (KHMAPI *)(khm_ui_callback, void *))
- GetProcAddress(hm_netidmgr, "_khui_request_UI_callback@8");
-
if (pkhui_action_lock == NULL ||
pkhui_action_unlock == NULL ||
pkhui_refresh_actions == NULL ||
pkhui_request_UI_callback == NULL)
goto no_custom_help;
-
#endif
+
kmq_create_subscription(afs_plugin_cb, &h_sub);
LoadString(hResModule, IDS_ACTION_AFS_HELP,
case KMSG_SYSTEM_EXIT:
+ afs_remove_icon();
+
/* Try to remove the AFS plug-in action from Help menu if it
was successfully registered. Also, delete the action. */
if (action_id_afs_help != 0) {
// TEXTINCLUDE
//
-1 TEXTINCLUDE
+1 TEXTINCLUDE
BEGIN
"..\\..\\langres.h\0"
END
-2 TEXTINCLUDE
+2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
-3 TEXTINCLUDE
+3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
//
#ifdef APSTUDIO_INVOKED
-GUIDELINES DESIGNINFO
+GUIDELINES DESIGNINFO
BEGIN
IDD_NC_AFS, DIALOG
BEGIN
IDI_NC_NEW ICON "..\\..\\images\\nc_new.ico"
IDI_NC_EXIST ICON "..\\..\\images\\nc_exist.ico"
IDI_NC_NOTOWNED ICON "..\\..\\images\\nc_notowned.ico"
+IDI_CRED_BROKEN ICON "..\\..\\images\\creds_broke.ico"
+IDI_CRED_NONE ICON "..\\..\\images\\creds_none.ico"
+IDI_CRED_OK ICON "..\\..\\images\\creds_ok.ico"
+IDI_CRED_SVCSTOP ICON "..\\..\\images\\creds_stopped.ico"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
-STRINGTABLE
+STRINGTABLE
BEGIN
IDS_AFS_SHORT_DESC "AFS credentials"
IDS_AFS_LONG_DESC "AFS credentials"
IDS_NC_REALM_AUTO "(Automatic)"
END
-STRINGTABLE
+STRINGTABLE
BEGIN
IDS_NC_TT_NO_CELL "You have not specified an AFS cell to authenticate to."
IDS_NC_TT_CANT_ADD "Can't add a new token"
- IDS_NC_TT_MALFORMED_CELL
+ IDS_NC_TT_MALFORMED_CELL
"The cell name you specified contains invalid characters."
IDS_NC_TT_NO_REALM "You have not specified a Kerberos realm to use to obtain tokesn for the cell."
IDS_NC_AUTO "(Auto)"
- IDS_NC_TT_MALFORMED_REALM
+ IDS_NC_TT_MALFORMED_REALM
"The realm name you entered contains invalid characters."
IDS_NC_TT_CANT_UPDATE "Can't update token"
IDS_AFS_CREDTEXT_DIS "<p><a id=""SwitchPanel"" param=""AfsCred""><b>AFS</b></a><tab>: AFS is disabled. (click <a id=""AfsCred:Enable"">here</a> to enable)</p>"
IDS_ATTR_CLIENT_PRINC_SHORT_DESC "Client Principal"
END
-STRINGTABLE
+STRINGTABLE
BEGIN
IDS_ATTR_SERVER_PRINC_SHORT_DESC "Server Principal"
IDS_DEF_LOCATION "AFS Cache Manager"
IDS_NC_TT_CONFLICTM "Credentials for cell %s are already listed for identity %s.\nDo you want to keep the credentials for other identities as well as this one?"
END
-STRINGTABLE
+STRINGTABLE
BEGIN
IDS_NC_TT_DETAILS "Details about credential"
IDS_NC_TT_CONFLICTD "This credential already exists under a different identity."
IDS_ERR_GENERAL "Credentials could not be obtained for cell %1!S!."
IDS_ACTION_AFS_HELP "AFS"
IDS_ACTION_AFS_HELP_TT "Display documentation for the OpenAFS plug-in"
+ IDS_CRED_TT_NONE "No AFS tokens"
+ IDS_CRED_TT_TOK "Tokens for "
+ IDS_CRED_TT_NOS "OpenAFS service has not been started."
+END
+
+STRINGTABLE
+BEGIN
+ IDS_CRED_TT_SERR "OpenAFS service cannot be reached."
END
#endif // English (U.S.) resources
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
-// Used by C:\work\openafs.1.5\src\Winnt\netidmgr_plugin\lang\en_us\langres.rc
+// Used by C:\work\openafs-git\src\Winnt\netidmgr_plugin\lang\en_us\langres.rc
//
#define IDS_AFS_SHORT_DESC 101
#define IDS_AFS_LONG_DESC 102
#define IDS_NC_REALM_AUTO 111
#define IDI_NC_NOTOWNED 111
#define IDS_NC_TT_NO_CELL 112
+#define IDI_CRED_BROKEN 112
#define IDS_NC_TT_CANT_ADD 113
+#define IDI_CRED_NONE 113
#define IDS_NC_TT_MALFORMED_CELL 114
+#define IDI_CRED_OK 114
#define IDS_NC_TT_NO_REALM 115
+#define IDI_CRED_SVCSTOP 115
#define IDS_NC_AUTO 116
#define IDS_NC_TT_MALFORMED_REALM 117
#define IDS_NC_TT_CANT_UPDATE 118
#define IDS_ERR_GENERAL 154
#define IDS_ACTION_AFS_HELP 155
#define IDS_ACTION_AFS_HELP_TT 156
+#define IDS_CRED_TT_NONE 157
+#define IDS_CRED_TT_TOK 158
+#define IDS_CRED_TT_NOS 159
+#define IDS_CRED_TT_SERR 160
#define IDC_NCAFS_OBTAIN 1001
#define IDC_NCAFS_TOKENLIST 1002
#define IDC_NCAFS_CELL 1004
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 112
+#define _APS_NEXT_RESOURCE_VALUE 116
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1024
#define _APS_NEXT_SYMED_VALUE 101