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
CreateInstance(IUICommandHandler ** out,HWND hwnd)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
AddRef()66 LeashUICommandHandler::AddRef()
67 {
68 return InterlockedIncrement(&refcnt);
69 }
70
71 ULONG
Release()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
QueryInterface(REFIID iid,void ** ppv)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
Execute(UINT32 commandId,UI_EXECUTIONVERB verb,const PROPERTYKEY * key,const PROPVARIANT * currentValue,IUISimplePropertySet * commandExecutionProperties)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
RegKeyToProperty(const char * regkey,bool default,PROPVARIANT * out)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
UpdateProperty(UINT32 commandId,REFPROPERTYKEY key,const PROPVARIANT * currentValue,PROPVARIANT * newValue)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