bcc82c108bf62991c66c9ce2e2508a99fc731c80
[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             if (d != NULL) {
89                 PFREE(d);
90                 SetWindowLongPtr(hwnd, DWLP_USER, 0);
91             }
92         }
93         return TRUE;
94
95     case WM_COMMAND:
96         {
97             d = (afs_ids_dlg_data *) (LONG_PTR)
98                 GetWindowLongPtr(hwnd, DWLP_USER);
99
100             if (d == NULL)
101                 return FALSE;
102
103             if (wParam == MAKEWPARAM(IDC_CFG_OBTAIN, BN_CLICKED)) {
104                 d->afs_enabled =
105                     (IsDlgButtonChecked(hwnd, IDC_CFG_OBTAIN) ==
106                      BST_CHECKED);
107                 khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_MODIFIED,
108                                         KHUI_CNFLAG_MODIFIED);
109                 return TRUE;
110             }
111         }
112         return FALSE;
113
114     case KHUI_WM_CFG_NOTIFY:
115         {
116             d = (afs_ids_dlg_data *) (LONG_PTR)
117                 GetWindowLongPtr(hwnd, DWLP_USER);
118
119             if (d == NULL)
120                 return FALSE;
121
122             if (HIWORD(wParam) == WMCFG_APPLY) {
123                 khm_int32 t;
124
125                 if (KHM_FAILED(khc_read_int32(csp_params,
126                                               L"AFSEnabled", &t)) ||
127                     !!t != !!d->afs_enabled) {
128                     khc_write_int32(csp_params, L"AFSEnabled",
129                                     !!d->afs_enabled);
130
131                     khui_cfg_set_flags_inst(&d->cfg,
132                                             KHUI_CNFLAG_APPLIED,
133                                             KHUI_CNFLAG_APPLIED |
134                                             KHUI_CNFLAG_MODIFIED);
135                 } else {
136                     khui_cfg_set_flags_inst(&d->cfg,
137                                             0,
138                                             KHUI_CNFLAG_MODIFIED);
139                 }
140             }
141         }
142         return TRUE;
143     }
144
145     return FALSE;
146 }
147
148 INT_PTR CALLBACK
149 afs_cfg_id_proc(HWND hwnd,
150                 UINT uMsg,
151                 WPARAM wParam,
152                 LPARAM lParam) {
153
154     switch(uMsg) {
155
156     case WM_INITDIALOG:
157         {
158             INT_PTR rv;
159             afs_dlg_data * d;
160             wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
161             khm_size cb;
162
163             rv = afs_dlg_proc(hwnd, uMsg, wParam, 0);
164
165             d = (afs_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
166 #ifdef DEBUG
167             assert(d != NULL);
168 #endif
169             if (d == NULL)
170                 return rv;
171
172             d->cfg = *((khui_config_init_data *) lParam);
173
174             idname[0] = L'\0';
175             cb = sizeof(idname);
176             khui_cfg_get_name(d->cfg.ctx_node, idname, &cb);
177
178             d->ident = NULL;
179             kcdb_identity_create(idname, 0, &d->ident);
180
181 #ifdef DEBUG
182             assert(d->ident);
183 #endif
184
185             d->config_dlg = TRUE;
186
187             afs_cred_get_identity_creds(&d->creds, d->ident, &d->afs_enabled);
188
189             afs_dlg_proc(hwnd, KHUI_WM_NC_NOTIFY,
190                          MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);
191
192             return rv;
193         }
194         break;                  /* not reached */
195
196     case WM_DESTROY:
197         {
198             afs_dlg_data * d;
199
200             d = (afs_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
201 #ifdef DEBUG
202             assert(d && d->ident);
203 #endif
204             if (d && d->ident) {
205                 kcdb_identity_release(d->ident);
206             }
207
208             return afs_dlg_proc(hwnd, uMsg, wParam, lParam);
209         }
210         break;                  /* not reached */
211
212     case KHUI_WM_CFG_NOTIFY:
213         {
214             afs_dlg_data * d;
215
216             d = (afs_dlg_data *) (LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
217
218             if (d == NULL)
219                 return TRUE;
220
221             if (HIWORD(wParam) == WMCFG_APPLY) {
222                 afs_cred_write_ident_data(d);
223             }
224         }
225         return TRUE;
226
227     default:
228         return afs_dlg_proc(hwnd, uMsg, wParam, lParam);
229     }
230 }
231
232 static void
233 set_service_status(HWND hwnd) {
234     static DWORD wait_start = 0;
235     DWORD status = 0;
236     DWORD wait_hint = 0;
237     unsigned int i;
238     wchar_t status_strings_csv[1024];
239     wchar_t status_strings_ms[1024];
240     khm_size cb;
241     wchar_t *t;
242
243     GetServiceStatus(NULL,
244                      TRANSARCAFSDAEMON,
245                      &status, &wait_hint);
246
247     LoadString(hResModule, IDS_CFG_SVCSTATUS,
248                status_strings_csv, ARRAYLENGTH(status_strings_csv));
249
250     cb = sizeof(status_strings_ms);
251     csv_to_multi_string(status_strings_ms, &cb, status_strings_csv);
252
253     for(i=0, t = status_strings_ms; t && *t && *t != L' ';
254         t = multi_string_next(t), i++) {
255         if (i == status)
256             break;
257     }
258
259     if (!t || !*t)
260         t = status_strings_ms;  /* the first one is "unknown". */
261
262     SetDlgItemText(hwnd, IDC_CFG_STATUS, t);
263
264     if (status != SERVICE_RUNNING) {
265         HWND hw;
266
267         hw = GetDlgItem(hwnd, IDC_CFG_STOP);
268         if (hw == GetFocus())
269             SetFocus(GetNextDlgTabItem(hwnd, hw, FALSE));
270
271         EnableWindow(hw, FALSE);
272     } else {
273         EnableWindow(GetDlgItem(hwnd, IDC_CFG_STOP), TRUE);
274     }
275
276     if (status != SERVICE_STOPPED &&
277         status != SERVICE_PAUSED) {
278         HWND hw;
279
280         hw = GetDlgItem(hwnd, IDC_CFG_START);
281         if (hw == GetFocus())
282             SetFocus(GetNextDlgTabItem(hwnd, hw, FALSE));
283
284         EnableWindow(hw, FALSE);
285     } else {
286         EnableWindow(GetDlgItem(hwnd, IDC_CFG_START), TRUE);
287     }
288
289     if (status == SERVICE_START_PENDING ||
290         status == SERVICE_STOP_PENDING) {
291         HWND hw;
292         DWORD now;
293         int progress;
294
295         hw = GetDlgItem(hwnd, IDC_CFG_PROGRESS);
296 #ifdef DEBUG
297         assert(hw);
298 #endif
299         if (!IsWindowVisible(hw))
300             ShowWindow(hw, SW_SHOW);
301
302         if (wait_start == 0)
303             wait_start = GetTickCount();
304
305         now = GetTickCount();
306
307         if (now + wait_hint != wait_start)
308             progress = (now - wait_start) * 100 /
309                 (now + wait_hint - wait_start);
310         else
311             progress = 0;
312
313         SendMessage(hw, PBM_SETPOS, progress, 0);
314
315         SetTimer(hwnd, 1, 500, NULL);
316     } else {
317         HWND hw;
318
319         hw = GetDlgItem(hwnd, IDC_CFG_PROGRESS);
320 #ifdef DEBUG
321         assert(hw);
322 #endif
323         wait_start = 0;
324         if (IsWindowVisible(hw))
325             ShowWindow(hw, SW_HIDE);
326     }
327 }
328
329 void
330 afs_cfg_show_last_error(HWND hwnd, wchar_t * prefix, DWORD code) {
331     DWORD r;
332     wchar_t * err_desc = NULL;
333     wchar_t title[64];
334     wchar_t msg[1024];
335     wchar_t tmp[128];
336
337     r = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
338                       FORMAT_MESSAGE_IGNORE_INSERTS |
339                       FORMAT_MESSAGE_FROM_SYSTEM,
340                       NULL,
341                       code,
342                       0,
343                       (LPWSTR) &err_desc,
344                       0,
345                       NULL);
346
347     if (r == 0 || err_desc == NULL)
348         return;
349
350     LoadString(hResModule, IDS_PLUGIN_DESC,
351                title, ARRAYLENGTH(title));
352     if (prefix == NULL)
353         tmp[0] = L'\0';
354     else if (IS_INTRESOURCE(prefix))
355         LoadString(hResModule, (UINT)(UINT_PTR) prefix,
356                    tmp, ARRAYLENGTH(tmp));
357     else
358         StringCbCopy(tmp, sizeof(tmp), prefix);
359
360     StringCbPrintf(msg, sizeof(msg), L"%s%s",
361                    tmp, err_desc);
362
363     MessageBox(hwnd, msg, title, MB_OK | MB_APPLMODAL);
364
365     LocalFree(err_desc);
366 }
367
368 #define SCNAME_AFSCREDS L"AFS Credentials.lnk"
369
370 BOOL
371 afs_cfg_get_afscreds_shortcut(wchar_t * wpath) {
372     HRESULT hr;
373     BOOL shortcut_found = FALSE;
374
375     hr = SHGetFolderPath(NULL, CSIDL_COMMON_STARTUP,
376                          NULL, SHGFP_TYPE_CURRENT,
377                          wpath);
378     if (FAILED(hr))
379         goto _noshortcut;
380
381     if (!PathAppend(wpath, SCNAME_AFSCREDS)) {
382         goto _noshortcut;
383     }
384
385     if (PathFileExists(wpath)) {
386         shortcut_found = TRUE;
387     }
388
389  _noshortcut:
390
391     return shortcut_found;
392 }
393
394 INT_PTR CALLBACK
395 afs_cfg_main_proc(HWND hwnd,
396                   UINT uMsg,
397                   WPARAM wParam,
398                   LPARAM lParam) {
399     switch(uMsg) {
400     case WM_INITDIALOG:
401         {
402             wchar_t imagepath[MAX_PATH];
403             wchar_t blockname[MAX_PATH];
404             HKEY service_key;
405             LONG l;
406             DWORD cb;
407             DWORD dummy;
408             LPVOID ver_info;
409             wchar_t * value;
410
411             struct LANGANDCODEPATH {
412                 WORD wLanguage;
413                 WORD wCodePage;
414             } *translations;
415
416 #pragma warning(push)
417 #pragma warning(disable: 4244)
418             SetWindowLongPtr(hwnd, DWLP_USER, (DWORD_PTR) lParam);
419 #pragma warning(pop)
420
421             /* Try to figure out if afscreds.exe is on the startup
422                group for all users. */
423             {
424                 khm_handle csp_afscred = NULL;
425                 khm_int32 disable = FALSE;
426
427                 if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME,
428                                                         0,
429                                                         &csp_afscred))) {
430
431                     khc_read_int32(csp_afscred, L"Disableafscreds",
432                                    &disable);
433
434                     khc_close_space(csp_afscred);
435                 }
436
437                 if (!disable) {
438                     CheckDlgButton(hwnd, IDC_CFG_STARTAFSCREDS,
439                                    BST_UNCHECKED);
440                 } else {
441                     CheckDlgButton(hwnd, IDC_CFG_STARTAFSCREDS,
442                                    BST_CHECKED);
443                 }
444             }
445
446             l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
447                              L"SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon",
448                              0,
449                              KEY_READ,
450                              &service_key);
451
452             if (l != ERROR_SUCCESS)
453                 goto _set_status;
454
455             cb = sizeof(imagepath);
456             l = RegQueryValueEx(service_key,
457                                 L"ImagePath",
458                                 NULL, NULL,
459                                 (LPBYTE) imagepath,
460                                 (DWORD *)&cb);
461             if (l != ERROR_SUCCESS)
462                 goto _close_key;
463
464             PathUnquoteSpaces(imagepath);
465
466             dummy = 1;
467             cb = GetFileVersionInfoSize(imagepath, &dummy);
468             if (cb == 0 || dummy)
469                 goto _close_key;
470
471             ver_info = malloc(cb);
472 #ifdef DEBUG
473             assert(ver_info);
474 #endif
475             if (!ver_info)
476                 goto _close_key;
477
478             if (!GetFileVersionInfo(imagepath,
479                                     0, cb, ver_info))
480                 goto _free_buffer;
481
482             cb = 0;
483             if (!VerQueryValue(ver_info, 
484                                L"\\VarFileInfo\\Translation",
485                                (LPVOID*) &translations,
486                                (PUINT)&cb) ||
487                 cb == 0)
488                 goto _free_buffer;
489
490             StringCbPrintf(blockname, sizeof(blockname),
491                            L"\\StringFileInfo\\%04x%04x\\FileVersion",
492                            translations[0].wLanguage,
493                            translations[0].wCodePage);
494
495             if (!VerQueryValue(ver_info,
496                                blockname,
497                                (LPVOID*) &value,
498                                (PUINT)&cb) ||
499                 cb == 0)
500                 goto _free_buffer;
501
502             SetDlgItemText(hwnd, IDC_CFG_VERSION, value);
503
504             StringCbPrintf(blockname, sizeof(blockname),
505                            L"\\StringFileInfo\\%04x%04x\\CompanyName",
506                            translations[0].wLanguage,
507                            translations[0].wCodePage);
508
509             if (!VerQueryValue(ver_info,
510                                blockname,
511                                (LPVOID*) &value,
512                                (PUINT)&cb) ||
513                 cb == 0)
514                 goto _free_buffer;
515
516             SetDlgItemText(hwnd, IDC_CFG_COMPANY, value);
517
518         _free_buffer:
519             free(ver_info);
520         _close_key:
521             RegCloseKey(service_key);
522         _set_status:
523             set_service_status(hwnd);
524         }
525         return FALSE;
526
527     case WM_COMMAND:
528         switch(wParam) {
529         case MAKEWPARAM(IDC_CFG_STOP, BN_CLICKED):
530             {
531                 DWORD r;
532
533                 r = ServiceControl(NULL, TRANSARCAFSDAEMON, SERVICE_STOPPED);
534
535                 if (r)
536                     afs_cfg_show_last_error(hwnd,
537                                             MAKEINTRESOURCE(IDS_CFG_CANTSTOP),
538                                             r);
539                 else
540                     set_service_status(hwnd);
541             }
542             break;
543
544         case MAKEWPARAM(IDC_CFG_START,BN_CLICKED):
545             {
546                 DWORD r;
547                 r = ServiceControl(NULL, TRANSARCAFSDAEMON, SERVICE_RUNNING);
548
549                 if (r)
550                     afs_cfg_show_last_error(hwnd,
551                                             MAKEINTRESOURCE(IDS_CFG_CANTSTART),
552                                             r);
553                 else
554                     set_service_status(hwnd);
555             }
556             break;
557
558         case MAKEWPARAM(IDC_CFG_CPL, BN_CLICKED):
559             if (32 >= (LRESULT) ShellExecute (NULL, NULL, 
560                                               L"AFS_CONFIG.EXE", NULL,
561                                               NULL, SW_SHOW)) {
562                 MessageBox(NULL, 
563                            L"Can't find file AFS_CONFIG.EXE", 
564                            L"Error", MB_OK);
565             }
566             break;
567
568         case MAKEWPARAM(IDC_CFG_STARTAFSCREDS, BN_CLICKED):
569             {
570                 khui_config_node node;
571
572                 node = (khui_config_node) (DWORD_PTR)
573                     GetWindowLongPtr(hwnd, DWLP_USER);
574
575                 if (node != NULL) {
576                     khui_cfg_set_flags(node,
577                                        KHUI_CNFLAG_MODIFIED,
578                                        KHUI_CNFLAG_MODIFIED);
579                 }
580             }
581             break;
582         }
583         return TRUE;
584
585     case KHUI_WM_CFG_NOTIFY:
586         {
587             if (HIWORD(wParam) == WMCFG_APPLY) {
588                 wchar_t wpath[MAX_PATH];
589                 int dlg_state;
590                 khui_config_node node;
591                 khm_handle csp_afscred = NULL;
592                 khm_int32 disable = FALSE;
593
594                 node = (khui_config_node) (DWORD_PTR)
595                     GetWindowLongPtr(hwnd, DWLP_USER);
596
597 #ifdef DEBUG
598                 assert(node != NULL);
599 #endif
600                 if (node == NULL)
601                     break;
602
603                 kmm_get_plugin_config(AFS_PLUGIN_NAME, KHM_PERM_WRITE,
604                                       &csp_afscred);
605
606                 if (csp_afscred)
607                     khc_read_int32(csp_afscred, L"Disableafscreds",
608                                    &disable);
609
610                 dlg_state = IsDlgButtonChecked(hwnd, IDC_CFG_STARTAFSCREDS);
611
612                 if (!!disable !=
613                     (dlg_state == BST_CHECKED)) {
614                     if (csp_afscred)
615                         khc_write_int32(csp_afscred,
616                                         L"Disableafscreds",
617                                         (dlg_state == BST_CHECKED));
618
619                     khui_cfg_set_flags(node,
620                                        KHUI_CNFLAG_APPLIED,
621                                        KHUI_CNFLAG_MODIFIED |
622                                        KHUI_CNFLAG_APPLIED);
623                 } else {
624                     khui_cfg_set_flags(node, 0,
625                                        KHUI_CNFLAG_MODIFIED);
626                 }
627
628                 if (dlg_state == BST_CHECKED &&
629                     afs_cfg_get_afscreds_shortcut(wpath)) {
630
631                     DeleteFile(wpath);
632                 }
633             }
634         }
635         return TRUE;
636
637     case WM_TIMER:
638         if (wParam == 1) {
639             KillTimer(hwnd, 1);
640             set_service_status(hwnd);
641         }
642         break;
643
644     case WM_DESTROY:
645         return FALSE;
646
647     case WM_HELP:
648         {
649             static const DWORD ctx_help[] = {
650                 IDC_CFG_STATUS, IDH_SVCSTATUS,
651                 IDC_CFG_STOP, IDH_SVCSTOP,
652                 IDC_CFG_START, IDH_SVCSTART,
653                 IDC_CFG_VERSION, IDH_SVCVERSION,
654                 IDC_CFG_COMPANY, IDH_SVCCOMPANY,
655                 IDC_CFG_CPL, IDH_SVCCPL,
656                 IDC_CFG_STARTAFSCREDS, IDH_STARTAFSCREDS,
657                 0
658             };
659
660             LPHELPINFO hlp;
661
662             hlp = (LPHELPINFO) lParam;
663
664             if (hlp->iContextType != HELPINFO_WINDOW)
665                 break;
666
667             afs_html_help(hlp->hItemHandle, L"::/popups_cfg.txt",
668                           HH_TP_HELP_WM_HELP, (DWORD_PTR) ctx_help);
669         }
670         return TRUE;
671     }
672     return FALSE;
673 }