xref: /freebsd/crypto/krb5/src/windows/leash/LeashUICommandHandler.cpp (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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