f121007a73f2884432d72139fb09abc5c9c023be
[openafs.git] / src / WINNT / netidmgr_plugin / afsconfigdlg.c
1 /*
2  * Copyright (c) 2005,2006 Secure Endpoints Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 /* $Id$ */
26
27 #include<afscred.h>
28 #include<kherror.h>
29 #include<khuidefs.h>
30 #include<commctrl.h>
31 #include<help/afsplhlp.h>
32 #include<htmlhelp.h>
33
34 /* disable the 'name was marked as deprecated' warnings.  These get
35    issued for Str?Cat? and Str?Cpy? functions.  We don't use those
36    anyway. */
37 #pragma warning(push)
38 #pragma warning(disable: 4995)
39 #include<shlwapi.h>
40 #include<shlobj.h>
41 #pragma warning(pop)
42
43 #include<assert.h>
44
45 typedef struct tag_afs_ids_dlg_data {
46     khui_config_init_data cfg;
47
48     khm_boolean afs_enabled;
49 } afs_ids_dlg_data;
50
51 INT_PTR CALLBACK
52 afs_cfg_ids_proc(HWND hwnd,
53                  UINT uMsg,
54                  WPARAM wParam,
55                  LPARAM lParam) {
56
57     afs_ids_dlg_data * d = NULL;
58
59     switch(uMsg) {
60     case WM_INITDIALOG:
61         {
62             khm_int32 t = 1;
63
64             d = PMALLOC(sizeof(*d));
65             ZeroMemory(d, sizeof(*d));
66
67 #pragma warning(push)
68 #pragma warning(disable: 4244)
69             SetWindowLongPtr(hwnd, DWLP_USER, (LONG_PTR) d);
70 #pragma warning(pop)
71
72             d->cfg = *((khui_config_init_data *) lParam);
73
74             khc_read_int32(csp_params, L"AFSEnabled", &t);
75
76             d->afs_enabled = !!t;
77
78             CheckDlgButton(hwnd, IDC_CFG_OBTAIN,
79                            (d->afs_enabled)? BST_CHECKED: BST_UNCHECKED);
80         }
81         return FALSE;
82
83     case WM_DESTROY:
84         {
85             d = (afs_ids_dlg_data *) (LONG_PTR)
86                 GetWindowLongPtr(hwnd, DWLP_USER);
87
88             PFREE(d);
89         }
90         return TRUE;
91
92     case WM_COMMAND:
93         {
94             d = (afs_ids_dlg_data *) (LONG_PTR)
95                 GetWindowLongPtr(hwnd, DWLP_USER);
96
97             if (wParam == MAKEWPARAM(IDC_CFG_OBTAIN, BN_CLICKED)) {
98                 d->afs_enabled =
99                     (IsDlgButtonChecked(hwnd, IDC_CFG_OBTAIN) ==
100                      BST_CHECKED);
101                 khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_MODIFIED,
102                                         KHUI_CNFLAG_MODIFIED);
103                 return TRUE;
104             }
105         }
106         return FALSE;
107
108     case KHUI_WM_CFG_NOTIFY:
109         {
110             d = (afs_ids_dlg_data *) (LONG_PTR)
111                 GetWindowLongPtr(hwnd, DWLP_USER);
112
113             if (HIWORD(wParam) == WMCFG_APPLY) {
114                 khm_int32 t;
115
116                 if (KHM_FAILED(khc_read_int32(csp_params,
117                                               L"AFSEnabled", &t)) ||
118                     !!t != !!d->afs_enabled) {
119                     khc_write_int32(csp_params, L"AFSEnabled",
120                                     !!d->afs_enabled);
121
122                     khui_cfg_set_flags_inst(&d->cfg,
123                                             KHUI_CNFLAG_APPLIED,
124                                             KHUI_CNFLAG_APPLIED |
125                                             KHUI_CNFLAG_MODIFIED);
126                 } else {
127                     khui_cfg_set_flags_inst(&d->cfg,
128                                             0,
129                                             KHUI_CNFLAG_MODIFIED);
130                 }
131             }
132         }
133         return TRUE;
134     }
135
136     return FALSE;
137 }
138
139 INT_PTR CALLBACK
140 afs_cfg_id_proc(HWND hwnd,
141                 UINT uMsg,
142                 WPARAM wParam,
143                 LPARAM lParam) {
144
145     switch(uMsg) {
146
147     case WM_INITDIALOG:
148         {
149             INT_PTR rv;
150             afs_dlg_data * d;
151             wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
152             khm_size cb;
153
154             rv = afs_dlg_proc(hwnd, uMsg, wParam, 0);
155
156             d = (afs_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
157
158             d->cfg = *((khui_config_init_data *) lParam);
159
160             idname[0] = L'\0';
161             cb = sizeof(idname);
162             khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
163
164             d->ident = NULL;
165             kcdb_identity_create(idname, 0, &d->ident);
166
167 #ifdef DEBUG
168             assert(d->ident);
169 #endif
170
171             d->config_dlg = TRUE;
172
173             afs_cred_get_identity_creds(&d->creds, d->ident, &d->afs_enabled);
174
175             afs_dlg_proc(hwnd, KHUI_WM_NC_NOTIFY,
176                          MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);
177
178             return rv;
179         }
180         break;                  /* not reached */
181
182     case WM_DESTROY:
183         {
184             afs_dlg_data * d;
185
186             d = (afs_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
187 #ifdef DEBUG
188             assert(d && d->ident);
189 #endif
190             kcdb_identity_release(d->ident);
191
192             return afs_dlg_proc(hwnd, uMsg, wParam, lParam);
193         }
194         break;                  /* not reached */
195
196     case KHUI_WM_CFG_NOTIFY:
197         {
198             afs_dlg_data * d;
199
200             d = (afs_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
201
202             if (HIWORD(wParam) == WMCFG_APPLY) {
203                 afs_cred_write_ident_data(d);
204             }
205         }
206         return TRUE;
207
208     default:
209         return afs_dlg_proc(hwnd, uMsg, wParam, lParam);
210     }
211 }
212
213 static void
214 set_service_status(HWND hwnd) {
215     static DWORD wait_start = 0;
216     DWORD status = 0;
217     DWORD wait_hint = 0;
218     int i;
219     wchar_t status_strings_csv[1024];
220     wchar_t status_strings_ms[1024];
221     khm_size cb;
222     wchar_t *t;
223
224     GetServiceStatus(NULL,
225                      TRANSARCAFSDAEMON,
226                      &status, &wait_hint);
227
228     LoadString(hResModule, IDS_CFG_SVCSTATUS,
229                status_strings_csv, ARRAYLENGTH(status_strings_csv));
230
231     cb = sizeof(status_strings_ms);
232     csv_to_multi_string(status_strings_ms, &cb, status_strings_csv);
233
234     for(i=0, t = status_strings_ms; t && *t && *t != L' ';
235         t = multi_string_next(t), i++) {
236         if (i == status)
237             break;
238     }
239
240     if (!t || !*t)
241         t = status_strings_ms;  /* the first one is "unknown". */
242
243     SetDlgItemText(hwnd, IDC_CFG_STATUS, t);
244
245     if (status != SERVICE_RUNNING) {
246         HWND hw;
247
248         hw = GetDlgItem(hwnd, IDC_CFG_STOP);
249         if (hw == GetFocus())
250             SetFocus(GetNextDlgTabItem(hwnd, hw, FALSE));
251
252         EnableWindow(hw, FALSE);
253     } else {
254         EnableWindow(GetDlgItem(hwnd, IDC_CFG_STOP), TRUE);
255     }
256
257     if (status != SERVICE_STOPPED &&
258         status != SERVICE_PAUSED) {
259         HWND hw;
260
261         hw = GetDlgItem(hwnd, IDC_CFG_START);
262         if (hw == GetFocus())
263             SetFocus(GetNextDlgTabItem(hwnd, hw, FALSE));
264
265         EnableWindow(hw, FALSE);
266     } else {
267         EnableWindow(GetDlgItem(hwnd, IDC_CFG_START), TRUE);
268     }
269
270     if (status == SERVICE_START_PENDING ||
271         status == SERVICE_STOP_PENDING) {
272         HWND hw;
273         DWORD now;
274         int progress;
275
276         hw = GetDlgItem(hwnd, IDC_CFG_PROGRESS);
277 #ifdef DEBUG
278         assert(hw);
279 #endif
280         if (!IsWindowVisible(hw))
281             ShowWindow(hw, SW_SHOW);
282
283         if (wait_start == 0)
284             wait_start = GetTickCount();
285
286         now = GetTickCount();
287
288         if (now + wait_hint != wait_start)
289             progress = (now - wait_start) * 100 /
290                 (now + wait_hint - wait_start);
291         else
292             progress = 0;
293
294         SendMessage(hw, PBM_SETPOS, progress, 0);
295
296         SetTimer(hwnd, 1, 500, NULL);
297     } else {
298         HWND hw;
299
300         hw = GetDlgItem(hwnd, IDC_CFG_PROGRESS);
301 #ifdef DEBUG
302         assert(hw);
303 #endif
304         wait_start = 0;
305         if (IsWindowVisible(hw))
306             ShowWindow(hw, SW_HIDE);
307     }
308 }
309
310 void
311 afs_cfg_show_last_error(HWND hwnd, wchar_t * prefix, DWORD code) {
312     DWORD r;
313     wchar_t * err_desc = NULL;
314     wchar_t title[64];
315     wchar_t msg[1024];
316     wchar_t tmp[128];
317
318     r = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
319                       FORMAT_MESSAGE_IGNORE_INSERTS |
320                       FORMAT_MESSAGE_FROM_SYSTEM,
321                       NULL,
322                       code,
323                       0,
324                       (LPWSTR) &err_desc,
325                       0,
326                       NULL);
327
328     if (r == 0 || err_desc == NULL)
329         return;
330
331     LoadString(hResModule, IDS_PLUGIN_DESC,
332                title, ARRAYLENGTH(title));
333     if (prefix == NULL)
334         tmp[0] = L'\0';
335     else if (IS_INTRESOURCE(prefix))
336         LoadString(hResModule, (UINT)(UINT_PTR) prefix,
337                    tmp, ARRAYLENGTH(tmp));
338     else
339         StringCbCopy(tmp, sizeof(tmp), prefix);
340
341     StringCbPrintf(msg, sizeof(msg), L"%s%s",
342                    tmp, err_desc);
343
344     MessageBox(hwnd, msg, title, MB_OK | MB_APPLMODAL);
345
346     LocalFree(err_desc);
347 }
348
349 #define SCNAME_AFSCREDS L"AFS Credentials.lnk"
350
351 BOOL
352 afs_cfg_get_afscreds_shortcut(wchar_t * wpath) {
353     HRESULT hr;
354     BOOL shortcut_found = FALSE;
355
356     hr = SHGetFolderPath(NULL, CSIDL_COMMON_STARTUP,
357                          NULL, SHGFP_TYPE_CURRENT,
358                          wpath);
359     if (FAILED(hr))
360         goto _noshortcut;
361
362     if (!PathAppend(wpath, SCNAME_AFSCREDS)) {
363         goto _noshortcut;
364     }
365
366     if (PathFileExists(wpath)) {
367         shortcut_found = TRUE;
368     }
369
370  _noshortcut:
371
372     return shortcut_found;
373 }
374
375 INT_PTR CALLBACK
376 afs_cfg_main_proc(HWND hwnd,
377                   UINT uMsg,
378                   WPARAM wParam,
379                   LPARAM lParam) {
380     switch(uMsg) {
381     case WM_INITDIALOG:
382         {
383             wchar_t imagepath[MAX_PATH];
384             wchar_t blockname[MAX_PATH];
385             HKEY service_key;
386             LONG l;
387             DWORD cb;
388             DWORD dummy;
389             LPVOID ver_info;
390             wchar_t * value;
391
392             struct LANGANDCODEPATH {
393                 WORD wLanguage;
394                 WORD wCodePage;
395             } *translations;
396
397 #pragma warning(push)
398 #pragma warning(disable: 4244)
399             SetWindowLongPtr(hwnd, DWLP_USER, (DWORD_PTR) lParam);
400 #pragma warning(pop)
401
402             /* Try to figure out if afscreds.exe is on the startup
403                group for all users. */
404             {
405                 khm_handle csp_afscred = NULL;
406                 khm_int32 disable = FALSE;
407
408                 if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME,
409                                                         0,
410                                                         &csp_afscred))) {
411
412                     khc_read_int32(csp_afscred, L"Disableafscreds",
413                                    &disable);
414
415                     khc_close_space(csp_afscred);
416                 }
417
418                 if (!disable) {
419                     CheckDlgButton(hwnd, IDC_CFG_STARTAFSCREDS,
420                                    BST_UNCHECKED);
421                 } else {
422                     CheckDlgButton(hwnd, IDC_CFG_STARTAFSCREDS,
423                                    BST_CHECKED);
424                 }
425             }
426
427             l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
428                              L"SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon",
429                              0,
430                              KEY_READ,
431                              &service_key);
432
433             if (l != ERROR_SUCCESS)
434                 goto _set_status;
435
436             cb = sizeof(imagepath);
437             l = RegQueryValueEx(service_key,
438                                 L"ImagePath",
439                                 NULL, NULL,
440                                 (LPBYTE) imagepath,
441                                 &cb);
442             if (l != ERROR_SUCCESS)
443                 goto _close_key;
444
445             PathUnquoteSpaces(imagepath);
446
447             dummy = 1;
448             cb = GetFileVersionInfoSize(imagepath, &dummy);
449             if (cb == 0 || dummy)
450                 goto _close_key;
451
452             ver_info = malloc(cb);
453 #ifdef DEBUG
454             assert(ver_info);
455 #endif
456             if (!ver_info)
457                 goto _close_key;
458
459             if (!GetFileVersionInfo(imagepath,
460                                     0, cb, ver_info))
461                 goto _free_buffer;
462
463             cb = 0;
464             if (!VerQueryValue(ver_info, 
465                                L"\\VarFileInfo\\Translation",
466                                (LPVOID*) &translations,
467                                &cb) ||
468                 cb == 0)
469                 goto _free_buffer;
470
471             StringCbPrintf(blockname, sizeof(blockname),
472                            L"\\StringFileInfo\\%04x%04x\\FileVersion",
473                            translations[0].wLanguage,
474                            translations[0].wCodePage);
475
476             if (!VerQueryValue(ver_info,
477                                blockname,
478                                (LPVOID*) &value,
479                                &cb) ||
480                 cb == 0)
481                 goto _free_buffer;
482
483             SetDlgItemText(hwnd, IDC_CFG_VERSION, value);
484
485             StringCbPrintf(blockname, sizeof(blockname),
486                            L"\\StringFileInfo\\%04x%04x\\CompanyName",
487                            translations[0].wLanguage,
488                            translations[0].wCodePage);
489
490             if (!VerQueryValue(ver_info,
491                                blockname,
492                                (LPVOID*) &value,
493                                &cb) ||
494                 cb == 0)
495                 goto _free_buffer;
496
497             SetDlgItemText(hwnd, IDC_CFG_COMPANY, value);
498
499         _free_buffer:
500             free(ver_info);
501         _close_key:
502             RegCloseKey(service_key);
503         _set_status:
504             set_service_status(hwnd);
505         }
506         return FALSE;
507
508     case WM_COMMAND:
509         switch(wParam) {
510         case MAKEWPARAM(IDC_CFG_STOP, BN_CLICKED):
511             {
512                 DWORD r;
513
514                 r = ServiceControl(NULL, TRANSARCAFSDAEMON, SERVICE_STOPPED);
515
516                 if (r)
517                     afs_cfg_show_last_error(hwnd,
518                                             MAKEINTRESOURCE(IDS_CFG_CANTSTOP),
519                                             r);
520                 else
521                     set_service_status(hwnd);
522             }
523             break;
524
525         case MAKEWPARAM(IDC_CFG_START,BN_CLICKED):
526             {
527                 DWORD r;
528                 r = ServiceControl(NULL, TRANSARCAFSDAEMON, SERVICE_RUNNING);
529
530                 if (r)
531                     afs_cfg_show_last_error(hwnd,
532                                             MAKEINTRESOURCE(IDS_CFG_CANTSTART),
533                                             r);
534                 else
535                     set_service_status(hwnd);
536             }
537             break;
538
539         case MAKEWPARAM(IDC_CFG_CPL, BN_CLICKED):
540             if (32 >= (LRESULT) ShellExecute (NULL, NULL, 
541                                               L"AFS_CONFIG.EXE", NULL,
542                                               NULL, SW_SHOW)) {
543                 MessageBox(NULL, 
544                            L"Can't find file AFS_CONFIG.EXE", 
545                            L"Error", MB_OK);
546             }
547             break;
548
549         case MAKEWPARAM(IDC_CFG_STARTAFSCREDS, BN_CLICKED):
550             {
551                 khui_config_node node;
552
553                 node = (khui_config_node) (DWORD_PTR)
554                     GetWindowLongPtr(hwnd, DWLP_USER);
555
556                 khui_cfg_set_flags(node,
557                                    KHUI_CNFLAG_MODIFIED,
558                                    KHUI_CNFLAG_MODIFIED);
559             }
560             break;
561         }
562         return TRUE;
563
564     case KHUI_WM_CFG_NOTIFY:
565         {
566             if (HIWORD(wParam) == WMCFG_APPLY) {
567                 wchar_t wpath[MAX_PATH];
568                 int dlg_state;
569                 khui_config_node node;
570                 khm_handle csp_afscred = NULL;
571                 khm_int32 disable = FALSE;
572
573                 node = (khui_config_node) (DWORD_PTR)
574                     GetWindowLongPtr(hwnd, DWLP_USER);
575
576                 kmm_get_plugin_config(AFS_PLUGIN_NAME, KHM_PERM_WRITE,
577                                       &csp_afscred);
578
579                 if (csp_afscred)
580                     khc_read_int32(csp_afscred, L"Disableafscreds",
581                                    &disable);
582
583                 dlg_state = IsDlgButtonChecked(hwnd, IDC_CFG_STARTAFSCREDS);
584
585                 if (!!disable !=
586                     (dlg_state == BST_CHECKED)) {
587                     if (csp_afscred)
588                         khc_write_int32(csp_afscred,
589                                         L"Disableafscreds",
590                                         (dlg_state == BST_CHECKED));
591
592                     khui_cfg_set_flags(node,
593                                        KHUI_CNFLAG_APPLIED,
594                                        KHUI_CNFLAG_MODIFIED |
595                                        KHUI_CNFLAG_APPLIED);
596                 } else {
597                     khui_cfg_set_flags(node, 0,
598                                        KHUI_CNFLAG_MODIFIED);
599                 }
600
601                 if (dlg_state == BST_CHECKED &&
602                     afs_cfg_get_afscreds_shortcut(wpath)) {
603
604                     DeleteFile(wpath);
605                 }
606             }
607         }
608         return TRUE;
609
610     case WM_TIMER:
611         if (wParam == 1) {
612             KillTimer(hwnd, 1);
613             set_service_status(hwnd);
614         }
615         break;
616
617     case WM_DESTROY:
618         return FALSE;
619
620     case WM_HELP:
621         {
622             static const DWORD ctx_help[] = {
623                 IDC_CFG_STATUS, IDH_SVCSTATUS,
624                 IDC_CFG_STOP, IDH_SVCSTOP,
625                 IDC_CFG_START, IDH_SVCSTART,
626                 IDC_CFG_VERSION, IDH_SVCVERSION,
627                 IDC_CFG_COMPANY, IDH_SVCCOMPANY,
628                 IDC_CFG_CPL, IDH_SVCCPL,
629                 IDC_CFG_STARTAFSCREDS, IDH_STARTAFSCREDS,
630                 0
631             };
632
633             LPHELPINFO hlp;
634
635             hlp = (LPHELPINFO) lParam;
636
637             if (hlp->iContextType != HELPINFO_WINDOW)
638                 break;
639
640             afs_html_help(hlp->hItemHandle, L"::/popups_cfg.txt",
641                           HH_TP_HELP_WM_HELP, (DWORD_PTR) ctx_help);
642         }
643         return TRUE;
644     }
645     return FALSE;
646 }