~ubuntu-branches/ubuntu/precise/krb5/precise-updates

« back to all changes in this revision

Viewing changes to src/windows/identity/ui/main.c

  • Committer: Package Import Robot
  • Author(s): Sam Hartman
  • Date: 2011-12-01 19:34:41 UTC
  • mfrom: (28.1.14 sid)
  • Revision ID: package-import@ubuntu.com-20111201193441-9tipg3aru1jsidyv
Tags: 1.10+dfsg~alpha1-6
* Fix segfault with unknown hostnames in krb5_sname_to_principal,
  Closes: #650671
* Indicate that this library breaks libsmbclient versions that depend on
  krb5_locate_kdc, Closes: #650603, #650611

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (c) 2005 Massachusetts Institute of Technology
3
 
 *
4
 
 * Copyright (2) 2007 Secure Endpoints Inc.
5
 
 *
6
 
 * Permission is hereby granted, free of charge, to any person
7
 
 * obtaining a copy of this software and associated documentation
8
 
 * files (the "Software"), to deal in the Software without
9
 
 * restriction, including without limitation the rights to use, copy,
10
 
 * modify, merge, publish, distribute, sublicense, and/or sell copies
11
 
 * of the Software, and to permit persons to whom the Software is
12
 
 * furnished to do so, subject to the following conditions:
13
 
 *
14
 
 * The above copyright notice and this permission notice shall be
15
 
 * included in all copies or substantial portions of the Software.
16
 
 *
17
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21
 
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22
 
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23
 
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
 
 * SOFTWARE.
25
 
 */
26
 
 
27
 
/* $Id$ */
28
 
 
29
 
#include<shlwapi.h>
30
 
#include<khmapp.h>
31
 
#include<netidmgr_intver.h>
32
 
 
33
 
/* used for the command-line help dialog */
34
 
#include<richedit.h>
35
 
 
36
 
#if DEBUG
37
 
#include<assert.h>
38
 
 
39
 
#if defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL)
40
 
/* needed for writing out leaked allocation and handle report */
41
 
#include<stdio.h>
42
 
#endif
43
 
 
44
 
#endif
45
 
 
46
 
HINSTANCE khm_hInstance;
47
 
const wchar_t * khm_facility = L"NetIDMgr";
48
 
int khm_nCmdShow;
49
 
khm_ui_4 khm_commctl_version = 0;
50
 
 
51
 
khm_startup_options khm_startup;
52
 
 
53
 
const khm_version app_version = {KH_VERSION_LIST};
54
 
 
55
 
HRESULT hr_coinitialize = S_OK;
56
 
 
57
 
#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL))
58
 
 
59
 
KHMEXP void KHMAPI khcint_dump_handles(FILE * f);
60
 
KHMEXP void KHMAPI perf_dump(FILE * f);
61
 
KHMEXP void KHMAPI kmqint_dump(FILE * f);
62
 
 
63
 
#endif
64
 
 
65
 
void khm_init_gui(void) {
66
 
 
67
 
    hr_coinitialize = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
68
 
 
69
 
    khui_init_actions();
70
 
    khui_init_rescache();
71
 
    khui_init_menu();
72
 
    khui_init_toolbar();
73
 
    khm_init_notifier();
74
 
    khm_init_config();
75
 
    khm_init_debug();
76
 
    khm_init_taskbar_funcs();
77
 
}
78
 
 
79
 
void khm_exit_gui(void) {
80
 
    khm_exit_taskbar_funcs();
81
 
    khm_exit_debug();
82
 
    khm_exit_config();
83
 
    khm_exit_notifier();
84
 
    khui_exit_toolbar();
85
 
    khui_exit_menu();
86
 
    khui_exit_rescache();
87
 
    khui_exit_actions();
88
 
 
89
 
    if (hr_coinitialize == S_OK ||
90
 
        hr_coinitialize == S_FALSE) {
91
 
        CoUninitialize();
92
 
    }
93
 
}
94
 
 
95
 
/* This is passed into EnumResourceLanguages().  This returns the
96
 
   language ID of the first resource of the type and name that's
97
 
   passed into it.  For the resources types we care about, we only
98
 
   expect there to be one resource for a given name.  At the moment we
99
 
   don't support resource modules that contain resources for multiple
100
 
   languages. */
101
 
BOOL CALLBACK
102
 
khm_enum_res_lang_proc_first(HANDLE hModule,
103
 
                             LPCTSTR lpszType,
104
 
                             LPCTSTR lpszName,
105
 
                             WORD wIDLanguage,
106
 
                             LONG_PTR lParam)
107
 
{
108
 
    WORD * plangid = (WORD *) lParam;
109
 
 
110
 
    *plangid = wIDLanguage;
111
 
 
112
 
    return FALSE;
113
 
}
114
 
 
115
 
#define KHM_RTF_RESOURCE L"KHMRTFRESOURCE"
116
 
 
117
 
INT_PTR CALLBACK
118
 
khm_cmdline_dlg_proc(HWND hwnd,
119
 
                     UINT uMsg,
120
 
                     WPARAM wParam,
121
 
                     LPARAM lParam)
122
 
{
123
 
    switch(uMsg) {
124
 
    case WM_INITDIALOG:
125
 
        {
126
 
            WORD langID = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
127
 
            HRSRC h_resinfo = NULL;
128
 
            HGLOBAL h_resource = NULL;
129
 
            LPVOID h_resmem = NULL;
130
 
            SETTEXTEX ste;
131
 
 
132
 
            SetDlgItemText(hwnd, IDC_PRODUCT,
133
 
                           TEXT(KH_VERSTR_PRODUCT_1033));
134
 
#ifdef OVERRIDE_COPYRIGHT
135
 
            SetDlgItemText(hwnd, IDC_COPYRIGHT,
136
 
                           TEXT(KH_VERSTR_COPYRIGHT_1033));
137
 
#endif
138
 
 
139
 
            EnumResourceLanguages(khm_hInstance,
140
 
                                  KHM_RTF_RESOURCE,
141
 
                                  MAKEINTRESOURCE(IDR_CMDLINERTF),
142
 
                                  khm_enum_res_lang_proc_first,
143
 
                                  (LONG_PTR) &langID);
144
 
 
145
 
            h_resinfo = FindResourceEx(khm_hInstance,
146
 
                                       KHM_RTF_RESOURCE,
147
 
                                       MAKEINTRESOURCE(IDR_CMDLINERTF),
148
 
                                       langID);
149
 
            if (h_resinfo == NULL)
150
 
                goto init_failed;
151
 
 
152
 
            h_resource = LoadResource(khm_hInstance, h_resinfo);
153
 
            if (h_resinfo == NULL)
154
 
                goto init_failed;
155
 
 
156
 
            h_resmem = LockResource(h_resource);
157
 
            if (h_resmem == NULL)
158
 
                goto init_failed;
159
 
 
160
 
            ste.flags = ST_DEFAULT;
161
 
            ste.codepage = CP_ACP;
162
 
 
163
 
            SendDlgItemMessage(hwnd, IDC_CONTENT, EM_SETTEXTEX, (WPARAM) &ste, (LPARAM) h_resmem);
164
 
        init_failed:
165
 
            /* none of the above handles need to be freed. */
166
 
 
167
 
            return TRUE;
168
 
        }
169
 
        break;
170
 
 
171
 
    case WM_COMMAND:
172
 
 
173
 
        if (wParam == MAKEWPARAM(IDOK, BN_CLICKED)) {
174
 
            EndDialog(hwnd, KHM_ERROR_EXIT);
175
 
        }
176
 
 
177
 
        return TRUE;
178
 
 
179
 
    case WM_CLOSE:
180
 
 
181
 
        EndDialog(hwnd, KHM_ERROR_EXIT);
182
 
 
183
 
        return TRUE;
184
 
    }
185
 
 
186
 
    return FALSE;
187
 
}
188
 
 
189
 
void khm_show_commandline_help(void) {
190
 
    HMODULE hm_richedit;
191
 
 
192
 
    hm_richedit = LoadLibrary(L"riched20.dll");
193
 
    if (hm_richedit == NULL)
194
 
        return;
195
 
 
196
 
    DialogBox(khm_hInstance, MAKEINTRESOURCE(IDD_CMDLINE),
197
 
              NULL, khm_cmdline_dlg_proc);
198
 
 
199
 
    FreeLibrary(hm_richedit);
200
 
}
201
 
 
202
 
void khm_parse_commandline(void) {
203
 
    LPWSTR wcmdline;
204
 
    LPWSTR * wargs;
205
 
    int      wargc;
206
 
    int i;
207
 
 
208
 
    ZeroMemory(&khm_startup, sizeof(khm_startup));
209
 
 
210
 
    wcmdline = GetCommandLine();
211
 
    wargs = CommandLineToArgvW(wcmdline, &wargc);
212
 
 
213
 
    for (i=1; i<wargc; i++) {
214
 
        if (!wcscmp(wargs[i], L"-i") ||
215
 
            !wcscmp(wargs[i], L"--kinit") ||
216
 
            !wcscmp(wargs[i], L"-kinit")) {
217
 
            khm_startup.init = TRUE;
218
 
            khm_startup.exit = TRUE;
219
 
            khm_startup.no_main_window = TRUE;
220
 
            khm_startup.display |= SOPTS_DISPLAY_NODEF;
221
 
        }
222
 
        else if (!wcscmp(wargs[i], L"-m") ||
223
 
                 !wcscmp(wargs[i], L"--import") ||
224
 
                 !wcscmp(wargs[i], L"-import")) {
225
 
            khm_startup.import = TRUE;
226
 
            khm_startup.exit = TRUE;
227
 
            khm_startup.no_main_window = TRUE;
228
 
            khm_startup.display |= SOPTS_DISPLAY_NODEF;
229
 
        }
230
 
        else if (!wcscmp(wargs[i], L"-r") ||
231
 
                 !wcscmp(wargs[i], L"--renew") ||
232
 
                 !wcscmp(wargs[i], L"-renew")) {
233
 
            khm_startup.renew = TRUE;
234
 
            khm_startup.exit = TRUE;
235
 
            khm_startup.no_main_window = TRUE;
236
 
            khm_startup.display |= SOPTS_DISPLAY_NODEF;
237
 
        }
238
 
        else if (!wcscmp(wargs[i], L"-d") ||
239
 
                 !wcscmp(wargs[i], L"--destroy") ||
240
 
                 !wcscmp(wargs[i], L"-destroy")) {
241
 
            khm_startup.destroy = TRUE;
242
 
            khm_startup.exit = TRUE;
243
 
            khm_startup.no_main_window = TRUE;
244
 
            khm_startup.display |= SOPTS_DISPLAY_NODEF;
245
 
        }
246
 
        else if (!wcscmp(wargs[i], L"-a") ||
247
 
                 !wcscmp(wargs[i], L"--autoinit") ||
248
 
                 !wcscmp(wargs[i], L"-autoinit")) {
249
 
            khm_startup.autoinit = TRUE;
250
 
            khm_startup.display |= SOPTS_DISPLAY_NODEF;
251
 
        }
252
 
        else if (!wcscmp(wargs[i], L"-x") ||
253
 
                 !wcscmp(wargs[i], L"--exit") ||
254
 
                 !wcscmp(wargs[i], L"-exit")) {
255
 
            khm_startup.exit = TRUE;
256
 
            khm_startup.remote_exit = TRUE;
257
 
            khm_startup.no_main_window = TRUE;
258
 
            khm_startup.display |= SOPTS_DISPLAY_NODEF;
259
 
        }
260
 
        else if (!wcscmp(wargs[i], L"--minimized")) {
261
 
            khm_startup.no_main_window = TRUE;
262
 
            khm_startup.display |= SOPTS_DISPLAY_NODEF;
263
 
        }
264
 
        else if (!wcscmp(wargs[i], L"--show")) {
265
 
            if (khm_startup.display & SOPTS_DISPLAY_HIDE) {
266
 
                khm_show_commandline_help();
267
 
                khm_startup.error_exit = TRUE;
268
 
                break;
269
 
            }
270
 
 
271
 
            khm_startup.display |= (SOPTS_DISPLAY_SHOW | SOPTS_DISPLAY_NODEF);
272
 
        }
273
 
        else if (!wcscmp(wargs[i], L"--hide")) {
274
 
            if (khm_startup.display & SOPTS_DISPLAY_SHOW) {
275
 
                khm_show_commandline_help();
276
 
                khm_startup.error_exit = TRUE;
277
 
                break;
278
 
            }
279
 
 
280
 
            khm_startup.display |= (SOPTS_DISPLAY_HIDE | SOPTS_DISPLAY_NODEF);
281
 
            khm_startup.no_main_window = TRUE;
282
 
        }
283
 
        else {
284
 
            khm_show_commandline_help();
285
 
 
286
 
            khm_startup.error_exit = TRUE;
287
 
            break;
288
 
        }
289
 
    }
290
 
 
291
 
    /* special: always enable renew when other options aren't specified */
292
 
    if (!khm_startup.exit &&
293
 
        !khm_startup.destroy &&
294
 
        !khm_startup.init &&
295
 
        !khm_startup.remote_exit &&
296
 
        !khm_startup.display)
297
 
        khm_startup.renew = TRUE;
298
 
}
299
 
 
300
 
void khm_register_window_classes(void) {
301
 
    INITCOMMONCONTROLSEX ics;
302
 
 
303
 
    ZeroMemory(&ics, sizeof(ics));
304
 
    ics.dwSize = sizeof(ics);
305
 
    ics.dwICC =
306
 
        ICC_COOL_CLASSES |
307
 
        ICC_BAR_CLASSES |
308
 
        ICC_DATE_CLASSES |
309
 
        ICC_HOTKEY_CLASS |
310
 
        ICC_LISTVIEW_CLASSES |
311
 
        ICC_TAB_CLASSES |
312
 
        ICC_INTERNET_CLASSES |
313
 
#if (_WIN32_WINNT >= 0x501)
314
 
        ((IS_COMMCTL6())?
315
 
         ICC_LINK_CLASS |
316
 
         ICC_STANDARD_CLASSES :
317
 
         0) |
318
 
#endif
319
 
        0;
320
 
 
321
 
    InitCommonControlsEx(&ics);
322
 
 
323
 
    khm_register_main_wnd_class();
324
 
    khm_register_credwnd_class();
325
 
    khm_register_htwnd_class();
326
 
    khm_register_passwnd_class();
327
 
    khm_register_newcredwnd_class();
328
 
    khm_register_propertywnd_class();
329
 
}
330
 
 
331
 
void khm_unregister_window_classes(void) {
332
 
    khm_unregister_main_wnd_class();
333
 
    khm_unregister_credwnd_class();
334
 
    khm_unregister_htwnd_class();
335
 
    khm_unregister_passwnd_class();
336
 
    khm_unregister_newcredwnd_class();
337
 
    khm_unregister_propertywnd_class();
338
 
}
339
 
 
340
 
 
341
 
/* we support up to 16 simutaneous dialogs.  In reality, more than two
342
 
   is pretty unlikely.  Property sheets are special and are handled
343
 
   separately. */
344
 
#define MAX_UI_DIALOGS 16
345
 
 
346
 
typedef struct tag_khui_dialog {
347
 
    HWND hwnd;
348
 
    HWND hwnd_next;
349
 
    BOOL active;
350
 
} khui_dialog;
351
 
 
352
 
static khui_dialog khui_dialogs[MAX_UI_DIALOGS];
353
 
static int n_khui_dialogs = 0;
354
 
static HWND khui_modal_dialog = NULL;
355
 
static BOOL khui_main_window_active;
356
 
 
357
 
/* should only be called from the UI thread */
358
 
void khm_add_dialog(HWND dlg) {
359
 
    if(n_khui_dialogs < MAX_UI_DIALOGS - 1) {
360
 
        khui_dialogs[n_khui_dialogs].hwnd = dlg;
361
 
        khui_dialogs[n_khui_dialogs].hwnd_next = NULL;
362
 
        khui_dialogs[n_khui_dialogs].active = TRUE;
363
 
        n_khui_dialogs++;
364
 
    } else {
365
 
#if DEBUG
366
 
          assert(FALSE);
367
 
#endif
368
 
    }
369
 
}
370
 
 
371
 
/* should only be called from the UI thread */
372
 
void khm_enter_modal(HWND hwnd) {
373
 
    int i;
374
 
 
375
 
    if (khui_modal_dialog) {
376
 
 
377
 
        /* we are already in a modal loop. */
378
 
 
379
 
#ifdef DEBUG
380
 
        assert(hwnd != khui_modal_dialog);
381
 
#endif
382
 
 
383
 
        for (i=0; i < n_khui_dialogs; i++) {
384
 
            if (khui_dialogs[i].hwnd == khui_modal_dialog) {
385
 
                khui_dialogs[i].active = TRUE;
386
 
                EnableWindow(khui_modal_dialog, FALSE);
387
 
                break;
388
 
            }
389
 
        }
390
 
 
391
 
#ifdef DEBUG
392
 
        assert(i < n_khui_dialogs);
393
 
#endif
394
 
 
395
 
        for (i=0; i < n_khui_dialogs; i++) {
396
 
            if (khui_dialogs[i].hwnd == hwnd) {
397
 
                khui_dialogs[i].hwnd_next = khui_modal_dialog;
398
 
                break;
399
 
            }
400
 
        }
401
 
 
402
 
#ifdef DEBUG
403
 
        assert(i < n_khui_dialogs);
404
 
#endif
405
 
 
406
 
        khui_modal_dialog = hwnd;
407
 
 
408
 
    } else {
409
 
 
410
 
        /* we are entering a modal loop.  preserve the active state of
411
 
           the overlapped dialogs and proceed with the modal
412
 
           dialog. */
413
 
 
414
 
        for (i=0; i < n_khui_dialogs; i++) {
415
 
            if(khui_dialogs[i].hwnd != hwnd) {
416
 
                khui_dialogs[i].active = IsWindowEnabled(khui_dialogs[i].hwnd);
417
 
                EnableWindow(khui_dialogs[i].hwnd, FALSE);
418
 
            }
419
 
        }
420
 
 
421
 
        khui_main_window_active = khm_is_main_window_active();
422
 
        EnableWindow(khm_hwnd_main, FALSE);
423
 
 
424
 
        khui_modal_dialog = hwnd;
425
 
 
426
 
        SetForegroundWindow(hwnd);
427
 
    }
428
 
}
429
 
 
430
 
/* should only be called from the UI thread */
431
 
void khm_leave_modal(void) {
432
 
    int i;
433
 
 
434
 
    for (i=0; i < n_khui_dialogs; i++) {
435
 
        if (khui_dialogs[i].hwnd == khui_modal_dialog)
436
 
            break;
437
 
    }
438
 
 
439
 
#ifdef DEBUG
440
 
    assert(i < n_khui_dialogs);
441
 
#endif
442
 
 
443
 
    if (i < n_khui_dialogs && khui_dialogs[i].hwnd_next) {
444
 
 
445
 
        /* we need to proceed to the next one down the modal dialog
446
 
           chain.  We are not exiting a modal loop. */
447
 
 
448
 
        khui_modal_dialog = khui_dialogs[i].hwnd_next;
449
 
        khui_dialogs[i].hwnd_next = FALSE;
450
 
 
451
 
        EnableWindow(khui_modal_dialog, TRUE);
452
 
 
453
 
    } else {
454
 
 
455
 
        HWND last_dialog = NULL;
456
 
 
457
 
        /* we are exiting a modal loop. */
458
 
 
459
 
        for (i=0; i < n_khui_dialogs; i++) {
460
 
            if(khui_dialogs[i].hwnd != khui_modal_dialog) {
461
 
                EnableWindow(khui_dialogs[i].hwnd, khui_dialogs[i].active);
462
 
                last_dialog = khui_dialogs[i].hwnd;
463
 
            }
464
 
        }
465
 
 
466
 
        EnableWindow(khm_hwnd_main, TRUE);
467
 
 
468
 
        khui_modal_dialog = NULL;
469
 
 
470
 
        if(last_dialog)
471
 
            SetActiveWindow(last_dialog);
472
 
        else
473
 
            SetActiveWindow(khm_hwnd_main);
474
 
    }
475
 
}
476
 
 
477
 
/* should only be called from the UI thread */
478
 
void khm_del_dialog(HWND dlg) {
479
 
    int i;
480
 
    for(i=0;i < n_khui_dialogs; i++) {
481
 
        if(khui_dialogs[i].hwnd == dlg)
482
 
            break;
483
 
    }
484
 
 
485
 
    if(i < n_khui_dialogs)
486
 
        n_khui_dialogs--;
487
 
    else
488
 
        return;
489
 
 
490
 
    for(;i < n_khui_dialogs; i++) {
491
 
        khui_dialogs[i] = khui_dialogs[i+1];
492
 
    }
493
 
}
494
 
 
495
 
BOOL khm_check_dlg_message(LPMSG pmsg) {
496
 
    int i;
497
 
    BOOL found = FALSE;
498
 
    for(i=0;i<n_khui_dialogs;i++) {
499
 
        if(IsDialogMessage(khui_dialogs[i].hwnd, pmsg)) {
500
 
            found = TRUE;
501
 
            break;
502
 
        }
503
 
    }
504
 
 
505
 
    return found;
506
 
}
507
 
 
508
 
BOOL khm_is_dialog_active(void) {
509
 
    HWND hwnd;
510
 
    int i;
511
 
 
512
 
    hwnd = GetForegroundWindow();
513
 
 
514
 
    for (i=0; i<n_khui_dialogs; i++) {
515
 
        if (khui_dialogs[i].hwnd == hwnd)
516
 
            return TRUE;
517
 
    }
518
 
 
519
 
    return FALSE;
520
 
}
521
 
 
522
 
/* We support at most 256 property sheets simultaneously.  256
523
 
   property sheets should be enough for everybody. */
524
 
#define MAX_UI_PROPSHEETS 256
525
 
 
526
 
khui_property_sheet *_ui_propsheets[MAX_UI_PROPSHEETS];
527
 
int _n_ui_propsheets = 0;
528
 
 
529
 
void khm_add_property_sheet(khui_property_sheet * s) {
530
 
    if(_n_ui_propsheets < MAX_UI_PROPSHEETS)
531
 
        _ui_propsheets[_n_ui_propsheets++] = s;
532
 
    else {
533
 
#ifdef DEBUG
534
 
        assert(FALSE);
535
 
#endif
536
 
    }
537
 
}
538
 
 
539
 
void khm_del_property_sheet(khui_property_sheet * s) {
540
 
    int i;
541
 
 
542
 
    for(i=0;i < _n_ui_propsheets; i++) {
543
 
        if(_ui_propsheets[i] == s)
544
 
            break;
545
 
    }
546
 
 
547
 
    if(i < _n_ui_propsheets)
548
 
        _n_ui_propsheets--;
549
 
    else
550
 
        return;
551
 
 
552
 
    for(;i < _n_ui_propsheets; i++) {
553
 
        _ui_propsheets[i] = _ui_propsheets[i+1];
554
 
    }
555
 
}
556
 
 
557
 
BOOL khm_check_ps_message(LPMSG pmsg) {
558
 
    int i;
559
 
    khui_property_sheet * ps;
560
 
    for(i=0;i<_n_ui_propsheets;i++) {
561
 
        if(khui_ps_check_message(_ui_propsheets[i], pmsg)) {
562
 
            if(_ui_propsheets[i]->status == KHUI_PS_STATUS_DONE) {
563
 
                ps = _ui_propsheets[i];
564
 
 
565
 
                ps->status = KHUI_PS_STATUS_DESTROY;
566
 
                kmq_post_message(KMSG_CRED, KMSG_CRED_PP_END, 0, (void *) ps);
567
 
 
568
 
                return TRUE;
569
 
            }
570
 
            return TRUE;
571
 
        }
572
 
    }
573
 
 
574
 
    return FALSE;
575
 
}
576
 
 
577
 
static HACCEL ha_menu;
578
 
 
579
 
WPARAM khm_message_loop_int(khm_boolean * p_exit) {
580
 
    int r;
581
 
    MSG msg;
582
 
 
583
 
    while((r = GetMessage(&msg, NULL, 0,0)) &&
584
 
          (p_exit == NULL || *p_exit)) {
585
 
        if(r == -1)
586
 
            break;
587
 
        if(!khm_check_dlg_message(&msg) &&
588
 
           !khm_check_ps_message(&msg) &&
589
 
           !TranslateAccelerator(khm_hwnd_main, ha_menu, &msg)) {
590
 
            TranslateMessage(&msg);
591
 
            DispatchMessage(&msg);
592
 
        }
593
 
    }
594
 
 
595
 
    return msg.wParam;
596
 
}
597
 
 
598
 
WPARAM khm_message_loop(void) {
599
 
    WPARAM w;
600
 
    ha_menu = khui_create_global_accel_table();
601
 
    w = khm_message_loop_int(NULL);
602
 
    DestroyAcceleratorTable(ha_menu);
603
 
    return w;
604
 
}
605
 
 
606
 
/* Handles all context closures which have a signalled error state.
607
 
   If the context is a top level context, then the errors are
608
 
   displayed. */
609
 
void KHMAPI
610
 
khm_err_ctx_completion_handler(enum kherr_ctx_event evt,
611
 
                               kherr_context * c) {
612
 
    kherr_event * e;
613
 
    khui_alert * a;
614
 
 
615
 
    /* we only handle top level contexts here.  For others, we allow
616
 
       the child contexts to fold upward silently. */
617
 
    if (c->parent || !kherr_is_error_i(c))
618
 
        return;
619
 
 
620
 
    for(e = kherr_get_first_event(c);
621
 
        e;
622
 
        e = kherr_get_next_event(e)) {
623
 
 
624
 
        if (e->severity != KHERR_ERROR && e->severity != KHERR_WARNING)
625
 
            continue;
626
 
 
627
 
        kherr_evaluate_event(e);
628
 
 
629
 
        /* we only report errors if there is enough information to
630
 
           present a message. */
631
 
        if (e->short_desc && e->long_desc) {
632
 
 
633
 
            khui_alert_create_empty(&a);
634
 
 
635
 
            khui_alert_set_severity(a, e->severity);
636
 
            khui_alert_set_title(a, e->short_desc);
637
 
            khui_alert_set_message(a, e->long_desc);
638
 
            if (e->suggestion)
639
 
                khui_alert_set_suggestion(a, e->suggestion);
640
 
 
641
 
            khui_alert_queue(a);
642
 
 
643
 
            khui_alert_release(a);
644
 
        }
645
 
    }
646
 
}
647
 
 
648
 
static wchar_t helpfile[MAX_PATH] = L"";
649
 
 
650
 
HWND khm_html_help(HWND hwnd, wchar_t * suffix,
651
 
                   UINT command, DWORD_PTR data) {
652
 
 
653
 
    wchar_t gpath[MAX_PATH + MAX_PATH];
654
 
 
655
 
    if (!*helpfile) {
656
 
        DWORD dw;
657
 
        wchar_t ppath[MAX_PATH];
658
 
 
659
 
        dw = GetModuleFileName(NULL, ppath, ARRAYLENGTH(ppath));
660
 
 
661
 
        if (dw == 0) {
662
 
            StringCbCopy(helpfile, sizeof(helpfile), NIDM_HELPFILE);
663
 
        } else {
664
 
            PathRemoveFileSpec(ppath);
665
 
            PathAppend(ppath, NIDM_HELPFILE);
666
 
            StringCbCopy(helpfile, sizeof(helpfile), ppath);
667
 
        }
668
 
    }
669
 
 
670
 
    StringCbCopy(gpath, sizeof(gpath), helpfile);
671
 
 
672
 
    if (suffix)
673
 
        StringCbCat(gpath, sizeof(gpath), suffix);
674
 
 
675
 
    return HtmlHelp(hwnd, gpath, command, data);
676
 
}
677
 
 
678
 
void khm_load_default_modules(void) {
679
 
    kmm_load_default_modules();
680
 
}
681
 
 
682
 
int khm_compare_version(const khm_version * v1, const khm_version * v2) {
683
 
 
684
 
    if (v1->major != v2->major)
685
 
        return ((int)v1->major) - ((int)v2->major);
686
 
 
687
 
    if (v1->minor != v2->minor)
688
 
        return ((int)v1->minor) - ((int)v2->minor);
689
 
 
690
 
    if (v1->patch != v2->patch)
691
 
        return ((int)v1->patch) - ((int)v2->patch);
692
 
 
693
 
    return ((int)v1->aux - ((int)v2->aux));
694
 
}
695
 
 
696
 
int WINAPI WinMain(HINSTANCE hInstance,
697
 
                   HINSTANCE hPrevInstance,
698
 
                   LPSTR lpCmdLine,
699
 
                   int nCmdShow)
700
 
{
701
 
    int rv = 0;
702
 
    HANDLE h_appmutex;
703
 
    BOOL slave = FALSE;
704
 
    int mutex_retries = 5;
705
 
 
706
 
    khm_hInstance = hInstance;
707
 
    khm_nCmdShow = nCmdShow;
708
 
 
709
 
    khm_parse_commandline();
710
 
 
711
 
    if (khm_startup.error_exit)
712
 
        return 0;
713
 
 
714
 
 _retry_mutex:
715
 
 
716
 
    if (--mutex_retries < 0)
717
 
        return 2;
718
 
 
719
 
    h_appmutex = CreateMutex(NULL, FALSE, L"Local\\NetIDMgr_GlobalAppMutex");
720
 
    if (h_appmutex == NULL)
721
 
        return 5;
722
 
    if (GetLastError() == ERROR_ALREADY_EXISTS)
723
 
        slave = TRUE;
724
 
 
725
 
    khc_load_schema(NULL, schema_uiconfig);
726
 
 
727
 
 _start_app:
728
 
 
729
 
    if(!slave) {
730
 
 
731
 
        PDESCTHREAD(L"UI", L"App");
732
 
 
733
 
        /* set this so that we don't accidently invoke an API that
734
 
           inadvertently puts up the new creds dialog at an
735
 
           inopportune moment, like, say, during the new creds dialog
736
 
           is open.  This only affects this process, and any child
737
 
           processes started by plugins. */
738
 
        SetEnvironmentVariable(L"KERBEROSLOGIN_NEVER_PROMPT", L"1");
739
 
 
740
 
        khm_version_init();
741
 
 
742
 
        khm_commctl_version = khm_get_commctl_version(NULL);
743
 
 
744
 
        /* we only open a main window if this is the only instance
745
 
           of the application that is running. */
746
 
        kmq_init();
747
 
        khm_init_gui();
748
 
        kmm_init();
749
 
 
750
 
        kmq_set_completion_handler(KMSG_CRED, kmsg_cred_completion);
751
 
 
752
 
        kherr_add_ctx_handler(khm_err_ctx_completion_handler,
753
 
                              KHERR_CTX_END,
754
 
                              0);
755
 
 
756
 
        /* load the standard plugins */
757
 
        khm_load_default_modules();
758
 
 
759
 
        khm_register_window_classes();
760
 
 
761
 
        khm_init_request_daemon();
762
 
 
763
 
        khm_create_main_window();
764
 
 
765
 
        if (!khm_startup.no_main_window &&
766
 
            nCmdShow != SW_SHOWMINNOACTIVE &&
767
 
            nCmdShow != SW_MINIMIZE &&
768
 
            nCmdShow != SW_SHOWMINIMIZED) {
769
 
 
770
 
            khm_show_main_window();
771
 
        }
772
 
 
773
 
        khm_refresh_config();
774
 
 
775
 
        rv = (int) khm_message_loop();
776
 
 
777
 
        kmq_set_completion_handler(KMSG_CRED, NULL);
778
 
 
779
 
        khm_exit_request_daemon();
780
 
 
781
 
        kmm_exit();
782
 
        khm_exit_gui();
783
 
        khm_unregister_window_classes();
784
 
        kmq_exit();
785
 
 
786
 
        CloseHandle(h_appmutex);
787
 
    } else {
788
 
 
789
 
        /* There is an instance of NetIDMgr already running. */
790
 
 
791
 
        HWND hwnd = NULL;
792
 
        int retries = 5;
793
 
        HANDLE hmap;
794
 
        wchar_t mapname[256];
795
 
        DWORD tid;
796
 
        void * xfer;
797
 
        khm_query_app_version query_app_version;
798
 
        khm_version v;
799
 
        BOOL use_cmd_v1 = FALSE;
800
 
        khm_size cb = 0;
801
 
 
802
 
        CloseHandle(h_appmutex);
803
 
 
804
 
        while (hwnd == NULL && retries) {
805
 
            hwnd = FindWindowEx(NULL, NULL, KHUI_MAIN_WINDOW_CLASS, NULL);
806
 
 
807
 
            if (hwnd)
808
 
                break;
809
 
 
810
 
            retries--;
811
 
 
812
 
            /* if the app was just starting, we might have to wait
813
 
               till the main window is created. */
814
 
 
815
 
            Sleep(1000);
816
 
        }
817
 
 
818
 
        if (!hwnd) {
819
 
 
820
 
            /* if the app was just exiting, we might see the mutex but
821
 
               not the window.  We go back and check if the mutex is
822
 
               still there. */
823
 
 
824
 
            goto _retry_mutex;
825
 
        }
826
 
 
827
 
        /* first check if the remote instance supports a version
828
 
           query */
829
 
 
830
 
        StringCbPrintf(mapname, sizeof(mapname),
831
 
                       QUERY_APP_VER_MAP_FMT,
832
 
                       (tid = GetCurrentThreadId()));
833
 
 
834
 
        hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
835
 
                                 NULL,
836
 
                                 PAGE_READWRITE,
837
 
                                 0,
838
 
                                 4096,
839
 
                                 mapname);
840
 
 
841
 
        if (hmap == NULL)
842
 
            return 3;
843
 
 
844
 
        xfer = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0,
845
 
                             sizeof(query_app_version));
846
 
 
847
 
        ZeroMemory(&query_app_version, sizeof(query_app_version));
848
 
 
849
 
        if (xfer) {
850
 
            query_app_version.magic = KHM_QUERY_APP_VER_MAGIC;
851
 
            query_app_version.code = KHM_ERROR_NOT_IMPLEMENTED;
852
 
            query_app_version.ver_caller = app_version;
853
 
 
854
 
            query_app_version.request_swap = TRUE;
855
 
 
856
 
            memcpy(xfer, &query_app_version, sizeof(query_app_version));
857
 
 
858
 
            SendMessage(hwnd, WM_KHUI_QUERY_APP_VERSION,
859
 
                        0, (LPARAM) tid);
860
 
 
861
 
            memcpy(&query_app_version, xfer, sizeof(query_app_version));
862
 
 
863
 
            UnmapViewOfFile(xfer);
864
 
            xfer = NULL;
865
 
        }
866
 
 
867
 
        CloseHandle(hmap);
868
 
        hmap = NULL;
869
 
 
870
 
        if (query_app_version.magic != KHM_QUERY_APP_VER_MAGIC ||
871
 
            query_app_version.code != KHM_ERROR_SUCCESS) {
872
 
 
873
 
            /* We managed to communicate with the remote instance, but
874
 
               it didn't send us useful information.  The remote
875
 
               instance is not running an actual NetIDMgr instance.
876
 
               However, it owns a top level window that was registered
877
 
               with our classname.  This instance won't function
878
 
               properly if we let it proceed.
879
 
            */
880
 
 
881
 
            wchar_t error_msg[1024];
882
 
            wchar_t error_title[256];
883
 
 
884
 
            LoadString(khm_hInstance, IDS_REMOTE_FAIL_TITLE,
885
 
                       error_title, ARRAYLENGTH(error_title));
886
 
            LoadString(khm_hInstance, IDS_REMOTE_FAIL,
887
 
                       error_msg, ARRAYLENGTH(error_msg));
888
 
 
889
 
            MessageBox(NULL, error_msg, error_title,
890
 
                       MB_OK);
891
 
 
892
 
            goto done_with_remote;
893
 
        }
894
 
 
895
 
        if (query_app_version.code == KHM_ERROR_SUCCESS &&
896
 
            query_app_version.request_swap) {
897
 
            /* the request for swap was granted.  We can now
898
 
               initialize our instance as the master instance. */
899
 
 
900
 
            slave = FALSE;
901
 
            goto _start_app;
902
 
        }
903
 
 
904
 
        /* Now we can work on sending the command-line to the remote
905
 
           instance.  However we need to figure out which version of
906
 
           the startup structure it supports. */
907
 
        v.major = 1;
908
 
        v.minor = 2;
909
 
        v.patch = 0;
910
 
        v.aux = 0;
911
 
 
912
 
        if (khm_compare_version(&query_app_version.ver_remote, &app_version) == 0 ||
913
 
            khm_compare_version(&query_app_version.ver_remote, &v) > 0)
914
 
            use_cmd_v1 = FALSE;
915
 
        else
916
 
            use_cmd_v1 = TRUE;
917
 
 
918
 
        StringCbPrintf(mapname, sizeof(mapname),
919
 
                       COMMANDLINE_MAP_FMT,
920
 
                       (tid = GetCurrentThreadId()));
921
 
 
922
 
        cb = max(sizeof(khm_startup_options_v1),
923
 
                 sizeof(khm_startup_options_v2));
924
 
 
925
 
        cb = UBOUNDSS(cb, 4096, 4096);
926
 
 
927
 
#ifdef DEBUG
928
 
        assert(cb >= 4096);
929
 
#endif
930
 
 
931
 
        hmap = CreateFileMapping(INVALID_HANDLE_VALUE,
932
 
                                 NULL,
933
 
                                 PAGE_READWRITE,
934
 
                                 0,
935
 
                                 (DWORD) cb,
936
 
                                 mapname);
937
 
 
938
 
        if (hmap == NULL)
939
 
            return 3;
940
 
 
941
 
        /* make the call */
942
 
 
943
 
        if (!use_cmd_v1) {
944
 
            /* use the v2 structure */
945
 
            khm_startup_options_v3 opt;
946
 
            khm_startup_options_v3 *xferopt;
947
 
 
948
 
            ZeroMemory(&opt, sizeof(opt));
949
 
 
950
 
            opt.v2opt.magic = STARTUP_OPTIONS_MAGIC;
951
 
 
952
 
            opt.v2opt.init = khm_startup.init;
953
 
            opt.v2opt.import = khm_startup.import;
954
 
            opt.v2opt.renew = khm_startup.renew;
955
 
            opt.v2opt.destroy = khm_startup.destroy;
956
 
            opt.v2opt.autoinit = khm_startup.autoinit;
957
 
            opt.v2opt.remote_exit = khm_startup.remote_exit;
958
 
            opt.remote_display = khm_startup.display;
959
 
 
960
 
            opt.v2opt.code = KHM_ERROR_NOT_IMPLEMENTED;
961
 
 
962
 
            /* check if we can use the v3 options structure.  This
963
 
               should be possible for 1.3.1 and above. */
964
 
            v.major = 1; v.minor = 3; v.patch = 1; v.aux = 0;
965
 
            if (khm_compare_version(&query_app_version.ver_remote, &app_version) == 0 ||
966
 
                khm_compare_version(&query_app_version.ver_remote, &v) >= 0) {
967
 
 
968
 
                opt.v2opt.cb_size = sizeof(opt);
969
 
 
970
 
            } else {
971
 
 
972
 
                opt.v2opt.cb_size = sizeof(opt.v2opt);
973
 
 
974
 
            }
975
 
 
976
 
            xfer = MapViewOfFile(hmap,
977
 
                                 FILE_MAP_WRITE,
978
 
                                 0, 0,
979
 
                                 opt.v2opt.cb_size);
980
 
 
981
 
            xferopt = (khm_startup_options_v3 *) xfer;
982
 
 
983
 
            if (xfer) {
984
 
                memcpy(xfer, &opt, opt.v2opt.cb_size);
985
 
 
986
 
                SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V2,
987
 
                            0, (LPARAM) tid);
988
 
 
989
 
                /* If it looks like the request was not processed, and
990
 
                   we were using a v3 request, fail-over to a v2
991
 
                   request. */
992
 
                if (xferopt->v2opt.code == KHM_ERROR_NOT_IMPLEMENTED &&
993
 
                    opt.v2opt.cb_size == sizeof(opt)) {
994
 
 
995
 
                    opt.v2opt.cb_size = sizeof(opt.v2opt);
996
 
                    memcpy(xfer, &opt, opt.v2opt.cb_size);
997
 
 
998
 
                    SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V2,
999
 
                                0, (LPARAM) tid);
1000
 
                }
1001
 
 
1002
 
                /* if it still looks like the request was not
1003
 
                   processed, we failover to a v1 call */
1004
 
                if (xferopt->v2opt.code == KHM_ERROR_NOT_IMPLEMENTED) {
1005
 
                    use_cmd_v1 = TRUE;
1006
 
                } else {
1007
 
                    memcpy(&opt, xfer, opt.v2opt.cb_size);
1008
 
                }
1009
 
 
1010
 
                UnmapViewOfFile(xfer);
1011
 
                xfer = NULL;
1012
 
            }
1013
 
        }
1014
 
 
1015
 
        if (use_cmd_v1) {
1016
 
            /* use the v1 structure */
1017
 
 
1018
 
            khm_startup_options_v1 v1opt;
1019
 
 
1020
 
            ZeroMemory(&v1opt, sizeof(v1opt));
1021
 
 
1022
 
            v1opt.init = khm_startup.init;
1023
 
            v1opt.import = khm_startup.import;
1024
 
            v1opt.renew = khm_startup.renew;
1025
 
            v1opt.destroy = khm_startup.destroy;
1026
 
            v1opt.autoinit = khm_startup.autoinit;
1027
 
 
1028
 
            xfer = MapViewOfFile(hmap,
1029
 
                                 FILE_MAP_WRITE,
1030
 
                                 0, 0,
1031
 
                                 sizeof(v1opt));
1032
 
 
1033
 
            if (xfer) {
1034
 
                memcpy(xfer, &v1opt, sizeof(v1opt));
1035
 
 
1036
 
                SendMessage(hwnd, WM_KHUI_ASSIGN_COMMANDLINE_V1,
1037
 
                            0, (LPARAM) tid);
1038
 
 
1039
 
                UnmapViewOfFile(xfer);
1040
 
                xfer = NULL;
1041
 
            }
1042
 
        }
1043
 
 
1044
 
    done_with_remote:
1045
 
 
1046
 
        if (hmap)
1047
 
            CloseHandle(hmap);
1048
 
    }
1049
 
 
1050
 
#if defined(DEBUG) && (defined(KH_BUILD_PRIVATE) || defined(KH_BUILD_SPECIAL))
1051
 
    {
1052
 
        FILE * f = NULL;
1053
 
 
1054
 
#if _MSC_VER >= 1400 && __STDC_WANT_SECURE_LIB__
1055
 
        if (fopen_s(&f, "memleak.txt", "w") != 0)
1056
 
            goto done_with_dump;
1057
 
#else
1058
 
        f = fopen("memleak.txt", "w");
1059
 
        if (f == NULL)
1060
 
            goto done_with_dump;
1061
 
#endif
1062
 
 
1063
 
        perf_dump(f);
1064
 
        khcint_dump_handles(f);
1065
 
        kmqint_dump(f);
1066
 
 
1067
 
        fclose(f);
1068
 
 
1069
 
    done_with_dump:
1070
 
        ;
1071
 
    }
1072
 
#endif
1073
 
 
1074
 
    return rv;
1075
 
}