1 // -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- 2 // leash/LeashUICommandHandler.cpp - implements IUICommandHandler interfaces 3 // 4 // Copyright (C) 2014 by the Massachusetts Institute of Technology. 5 // All rights reserved. 6 // 7 // Redistribution and use in source and binary forms, with or without 8 // modification, are permitted provided that the following conditions 9 // are met: 10 // 11 // * Redistributions of source code must retain the above copyright 12 // notice, this list of conditions and the following disclaimer. 13 // 14 // * Redistributions in binary form must reproduce the above copyright 15 // notice, this list of conditions and the following disclaimer in 16 // the documentation and/or other materials provided with the 17 // distribution. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 // COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 30 // OF THE POSSIBILITY OF SUCH DAMAGE. 31 32 // This file contains the class implementation of the leash implementation 33 // of the UICommandHandler interface. Its primary responsibility is 34 // to accept UI events (i.e., button presses) and perform the 35 // corresponding actions to the leash data structures and display 36 // presentation. 37 38 #include <UIRibbon.h> 39 #include <UIRibbonPropertyHelpers.h> 40 #include "kfwribbon.h" 41 #include "LeashUICommandHandler.h" 42 #include "resource.h" 43 44 #include <loadfuncs-leash.h> 45 46 // Allowing mixed-case realms has both a machine and user-specific knob, 47 // and thus needs a function to manage it. 48 extern DWORD Leash_get_default_uppercaserealm(); 49 extern DECL_FUNC_PTR(Leash_get_default_uppercaserealm); 50 51 HRESULT 52 LeashUICommandHandler::CreateInstance(IUICommandHandler **out, HWND hwnd) 53 { 54 LeashUICommandHandler *handler; 55 56 if (out == NULL) 57 return E_POINTER; 58 59 handler = new LeashUICommandHandler(); 60 handler->mainwin = hwnd; 61 *out = static_cast<IUICommandHandler *>(handler); 62 return S_OK; 63 } 64 65 ULONG 66 LeashUICommandHandler::AddRef() 67 { 68 return InterlockedIncrement(&refcnt); 69 } 70 71 ULONG 72 LeashUICommandHandler::Release() 73 { 74 LONG tmp; 75 76 tmp = InterlockedDecrement(&refcnt); 77 if (tmp == 0) 78 delete this; 79 return tmp; 80 } 81 82 HRESULT 83 LeashUICommandHandler::QueryInterface(REFIID iid, void **ppv) 84 { 85 if (ppv == NULL) 86 return E_POINTER; 87 88 if (iid == __uuidof(IUnknown)) { 89 *ppv = static_cast<IUnknown*>(this); 90 } else if (iid == __uuidof(IUICommandHandler)) { 91 *ppv = static_cast<IUICommandHandler*>(this); 92 } else { 93 *ppv = NULL; 94 return E_NOINTERFACE; 95 } 96 97 AddRef(); 98 return S_OK; 99 } 100 101 // Called by the framework when a control is activated that may require 102 // an action to be taken, such as a button being pressed or a checkbox 103 // state flipped. (It is not called when the user changes tabs on the 104 // ribbon.) Just proxy these commands through to the existing MFC 105 // handlers by sendding the appropriate message to the main window. 106 // Action only needs to be taken on the EXECUTE verb, so we can 107 // ignore the additional properties surrounding the action, which would 108 // be relevant for other verbs. 109 // 110 // The commandIds are taken from the XML ribbon description. 111 HRESULT 112 LeashUICommandHandler::Execute(UINT32 commandId, UI_EXECUTIONVERB verb, 113 const PROPERTYKEY *key, 114 const PROPVARIANT *currentValue, 115 IUISimplePropertySet *commandExecutionProperties) 116 { 117 if (verb != UI_EXECUTIONVERB_EXECUTE) 118 return E_NOTIMPL; 119 120 switch(commandId) { 121 case cmdGetTicketButton: 122 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_INIT_TICKET, 1), 0); 123 break; 124 case cmdRenewTicketButton: 125 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_RENEW_TICKET, 1), 0); 126 break; 127 case cmdDestroyTicketButton: 128 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_DESTROY_TICKET, 1), 129 0); 130 break; 131 case cmdMakeDefaultButton: 132 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_MAKE_DEFAULT, 1), 133 0); 134 break; 135 case cmdChangePasswordButton: 136 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_CHANGE_PASSWORD, 1), 137 0); 138 break; 139 case cmdIssuedCheckBox: 140 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_TIME_ISSUED, 1), 0); 141 break; 142 case cmdRenewUntilCheckBox: 143 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_RENEWABLE_UNTIL, 1), 144 0); 145 break; 146 case cmdValidUntilCheckBox: 147 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_VALID_UNTIL, 1), 0); 148 break; 149 case cmdEncTypeCheckBox: 150 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_ENCRYPTION_TYPE, 1), 151 0); 152 break; 153 case cmdFlagsCheckBox: 154 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_SHOW_TICKET_FLAGS, 155 1), 0); 156 break; 157 case cmdCcacheNameCheckBox: 158 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_CCACHE_NAME, 1), 0); 159 break; 160 case cmdAutoRenewCheckBox: 161 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_AUTO_RENEW, 1), 0); 162 break; 163 case cmdExpireAlarmCheckBox: 164 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_LOW_TICKET_ALARM, 165 1), 0); 166 break; 167 case cmdDestroyOnExitCheckBox: 168 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_KILL_TIX_ONEXIT, 1), 169 0); 170 break; 171 case cmdMixedCaseCheckBox: 172 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_UPPERCASE_REALM, 1), 173 0); 174 break; 175 case cmdHelp: 176 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(ID_HELP_LEASH32, 1), 0); 177 break; 178 case cmdAbout: 179 // ID_APP_ABOUT (0xe140) is defined in afxres.h, an MFC header 180 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(0xe140, 1), 0); 181 break; 182 case cmdExit: 183 // Save Ribbon customizations here, since this is the only 184 // path to a clean exit from the application. 185 if (app != NULL) 186 app->SaveRibbonState(); 187 // ID_APP_EXIT (0xe141) is defined in afxres.h, an MFC header 188 SendMessage(mainwin, WM_COMMAND, MAKEWPARAM(0xe141, 1), 0); 189 break; 190 default: 191 // Lots of commands we don't need to pass on 192 return S_OK; 193 } 194 return S_OK; 195 } 196 197 // Looks up a given registry key in this application's Settings space 198 // (analogous to CWinApp::GetProfileInt()), converting it to a 199 // (boolean) PROPVARIANT which is returned in *out. Uses the given 200 // default value if the registry key cannot be loaded. 201 static HRESULT 202 RegKeyToProperty(const char *regkey, bool default, PROPVARIANT *out) 203 { 204 DWORD bsize = sizeof(DWORD), enabled; 205 LONG code; 206 207 code = RegGetValue(HKEY_CURRENT_USER, 208 "Software\\MIT\\MIT Kerberos\\Settings", 209 regkey, RRF_RT_DWORD, NULL, &enabled, 210 &bsize); 211 if (code == ERROR_FILE_NOT_FOUND) { 212 code = ERROR_SUCCESS; 213 enabled = default ? 1 : 0; 214 } 215 if (FAILED(code) || bsize != sizeof(enabled)) 216 return E_FAIL; 217 return UIInitPropertyFromBoolean(UI_PKEY_BooleanValue, enabled, out); 218 } 219 220 // Called by the framework when the value of a property needs to be 221 // re-evaluated, e.g., if it has been explicitly invalidated, or at 222 // program startup. This is the way to specify the initial/default 223 // state for ribbon elements which have state, such as checkboxes. 224 // The registry values which are modified by the MFC checkbox 225 // action handlers can be read directly from here in order to present 226 // a consistent visual interface. The MFC handlers only write to the 227 // registry when a value is changed, though, so we must duplicate 228 // the default values which are hardcoded in CLeashView::sm_viewColumns[] 229 // and elsewhere in LeashView.cpp. 230 HRESULT 231 LeashUICommandHandler::UpdateProperty(UINT32 commandId, REFPROPERTYKEY key, 232 const PROPVARIANT *currentValue, 233 PROPVARIANT *newValue) 234 { 235 if (key != UI_PKEY_BooleanValue) 236 return E_NOTIMPL; 237 238 // These default values duplicate those hardcoded in 239 // CLeashView::sm_viewColumns[] and elsewhere in LeashView.cpp. 240 switch(commandId) { 241 case cmdIssuedCheckBox: 242 return RegKeyToProperty("Issued", false, newValue); 243 case cmdRenewUntilCheckBox: 244 return RegKeyToProperty("Renewable Until", false, newValue); 245 case cmdValidUntilCheckBox: 246 return RegKeyToProperty("Valid Until", true, newValue); 247 case cmdEncTypeCheckBox: 248 return RegKeyToProperty("Encryption Type", false, newValue); 249 case cmdFlagsCheckBox: 250 return RegKeyToProperty("Flags", false, newValue); 251 case cmdCcacheNameCheckBox: 252 return RegKeyToProperty("Credential Cache", false, newValue); 253 case cmdAutoRenewCheckBox: 254 return RegKeyToProperty("AutoRenewTickets", true, newValue); 255 case cmdExpireAlarmCheckBox: 256 return RegKeyToProperty("LowTicketAlarm", true, newValue); 257 case cmdDestroyOnExitCheckBox: 258 return RegKeyToProperty("DestroyTicketsOnExit", false, newValue); 259 case cmdMixedCaseCheckBox: 260 return UIInitPropertyFromBoolean(UI_PKEY_BooleanValue, 261 pLeash_get_default_uppercaserealm(), newValue); 262 default: 263 return E_NOTIMPL; 264 } 265 266 return E_NOTIMPL; 267 } 268