2 * Copyright (c) 2005 Massachusetts Institute of Technology
3 * Copyright (c) 2007 Secure Endpoints Inc.
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use, copy,
9 * modify, merge, publish, distribute, sublicense, and/or sell copies
10 * of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 /* Include the OEMRESOURCE constants for locating standard icon
35 ATOM khui_newcredwnd_cls;
39 nc_position_credtext(khui_nc_wnd_data * d);
41 /* Common dialog procedure used by the main credential panel
42 (IDD_NC_NEWCRED) and the button bar (IDC_NC_BBAR). */
45 nc_layout_main_panel(khui_nc_wnd_data * d);
48 nc_layout_new_cred_window(khui_nc_wnd_data * d);
50 static INT_PTR CALLBACK
51 nc_common_dlg_proc(HWND hwnd,
61 d = (khui_nc_wnd_data *) lParam;
64 #pragma warning(disable: 4244)
65 SetWindowLongPtr(hwnd, DWLP_USER, lParam);
68 if (d->nc->subtype == KMSG_CRED_PASSWORD) {
69 ShowWindow(GetDlgItem(hwnd, IDC_NC_ADVANCED),
79 ctrl_id = LOWORD(wParam);
80 if (ctrl_id < KHUI_CW_ID_MIN ||
81 ctrl_id > KHUI_CW_ID_MAX) {
82 /* pump it to the parent */
83 PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam);
85 } /* else we allow the message to fall through and get
86 passed into the identity provider's message
91 case KHUI_WM_NC_NOTIFY:
94 d = (khui_nc_wnd_data *)(LONG_PTR)
95 GetWindowLongPtr(hwnd, DWLP_USER);
97 /* message sent by parent to notify us of something */
98 switch(HIWORD(wParam)) {
99 case WMNC_DIALOG_EXPAND:
101 case WMNC_UPDATE_LAYOUT:
102 if(hwnd == d->dlg_main) {
104 nc_layout_main_panel(d);
114 /* check if we have a wnd_data, and if so pass the message on to
115 the identity provider callback. */
117 khui_nc_wnd_data * d;
119 d = (khui_nc_wnd_data *) (LONG_PTR)
120 GetWindowLongPtr(hwnd, DWLP_USER);
122 /* TODO: filter out and forward only the messages that
123 originated or pertain to the identity selection
125 if (d && d->nc && d->nc->ident_cb) {
126 return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg,
135 nc_notify_clear(khui_nc_wnd_data * d) {
137 if (d->notif_type == NC_NOTIFY_NONE)
138 /* there are no notifications anyway. */
141 if (d->hwnd_notif_label)
142 DestroyWindow(d->hwnd_notif_label);
144 if (d->hwnd_notif_aux)
145 DestroyWindow(d->hwnd_notif_aux);
147 d->hwnd_notif_label = NULL;
148 d->hwnd_notif_aux = NULL;
150 SetRectEmpty(&d->r_notif);
152 d->notif_type = NC_NOTIFY_NONE;
154 /* Note that we must call nc_layout_main_panel() after calling
155 this to adjust the layout of the main panel. However we aren't
156 calling it here since we might want to add another set of
157 notifications or make other changes to the main panel content
158 before calling nc_layout_main_panel(). */
162 nc_notify_marquee(khui_nc_wnd_data * d, const wchar_t * label) {
164 #if (_WIN32_IE >= 0x0600)
177 /* Clear the notification area. We only support one notification
185 #if (_WIN32_IE >= 0x0600)
187 /* We can only show the marquee control if the comctl32 DLL is
188 version 6.0 or later. Otherwise we only show the label. */
190 if (FAILED(StringCchLength(label, KHUI_MAXCCH_SHORT_DESC, &length))) {
194 length = KHUI_MAXCCH_SHORT_DESC;
197 /* See how big the notification control needs to be. */
199 hdc = GetDC(d->dlg_main);
204 GetTextExtentPoint32(hdc, label, (int) length, &label_size);
206 ReleaseDC(d->dlg_main, hdc);
208 CopyRect(&r_row, &d->r_row);
210 if (label_size.cx > d->r_e_label.right - d->r_e_label.left) {
211 /* using an entire row */
212 CopyRect(&r_label, &d->r_row);
213 CopyRect(&r_mq, &d->r_n_input);
214 OffsetRect(&r_mq, 0, r_row.bottom - r_row.top);
215 r_row.bottom += r_row.bottom - r_row.top;
216 } else if (label_size.cx > d->r_n_label.right - d->r_n_label.left) {
217 /* using large labels */
218 CopyRect(&r_label, &d->r_e_label);
219 CopyRect(&r_mq, &d->r_e_input);
222 CopyRect(&r_label, &d->r_n_label);
223 CopyRect(&r_mq, &d->r_n_input);
226 InflateRect(&r_mq, 0, - ((r_mq.bottom - r_mq.top) / 4));
228 #else /* _WIN32_IE < 0x0600 */
230 /* We are just showing the label */
231 CopyRect(&r_row, &d->r_row);
232 CopyRect(&r_label, &r_row);
235 #endif /* _WIN32_IE >= 0x0600 */
240 if (IsRectEmpty(&d->r_custprompt)) {
241 y = d->r_idspec.bottom;
243 y = d->r_custprompt.bottom;
246 OffsetRect(&r_row, d->r_area.left, y);
247 OffsetRect(&r_label, r_row.left, r_row.top);
248 OffsetRect(&r_mq, r_row.left, r_row.top);
251 hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
253 hdefer = BeginDeferWindowPos(2);
256 hwnd = CreateWindowEx(0,
259 WS_CHILD | SS_ENDELLIPSIS,
260 r_label.left, r_label.top,
261 r_label.right - r_label.left,
262 r_label.bottom - r_label.top,
266 assert(hwnd != NULL);
268 SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
270 DeferWindowPos(hdefer, hwnd, NULL,
272 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
273 SWP_NOSIZE | SWP_SHOWWINDOW);
275 d->hwnd_notif_label = hwnd;
277 /* and the marquee */
279 #if (_WIN32_IE >= 0x0600)
281 /* unfortunately, the marquee is only available on comctl32
282 version 6.0 or later. On previous versions, we only display
283 the message label. */
285 hwnd = CreateWindowEx(0,
288 WS_CHILD | PBS_MARQUEE,
290 r_mq.right - r_mq.left,
291 r_mq.bottom - r_mq.top,
295 assert(hwnd != NULL);
298 SendMessage(hwnd, PBM_SETMARQUEE, TRUE, 100);
300 DeferWindowPos(hdefer, hwnd, NULL,
302 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
303 SWP_NOSIZE | SWP_SHOWWINDOW);
305 d->hwnd_notif_aux = hwnd;
307 #endif /* _WIN32_IE >= 0x0600 */
309 EndDeferWindowPos(hdefer);
311 CopyRect(&d->r_notif, &r_row);
313 d->notif_type = NC_NOTIFY_MARQUEE;
315 /* Note that we must call nc_layout_main_panel() after calling
316 this to adjust the layout of the main panel. However we aren't
317 calling it here since we might want to add another set of
318 notifications or make other changes to the main panel content
319 before calling nc_layout_main_panel(). */
323 nc_notify_message(khui_nc_wnd_data * d,
324 kherr_severity severity,
325 const wchar_t * message) {
340 icon_size.cx = GetSystemMetrics(SM_CXSMICON);
341 icon_size.cy = GetSystemMetrics(SM_CYSMICON);
345 icon_res = MAKEINTRESOURCE(OIC_INFORMATION);
349 icon_res = MAKEINTRESOURCE(OIC_WARNING);
353 icon_res = MAKEINTRESOURCE(OIC_ERROR);
360 if (icon_res != NULL) {
361 h_icon = (HICON) LoadImage(NULL,
366 LR_DEFAULTCOLOR | LR_SHARED);
371 CopyRect(&r_row, &d->r_row);
373 #define CENTERVALUE(w,v) ((w)/2 - (v)/2)
376 0, CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy),
378 CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy) + icon_size.cy);
382 CopyRect(&r_label, &r_row);
383 OffsetRect(&r_label, -r_label.left, -r_label.top);
384 r_label.left += (icon_size.cx * 3) / 2;
389 if (IsRectEmpty(&d->r_custprompt)) {
390 y = d->r_idspec.bottom;
392 y = d->r_custprompt.bottom;
395 OffsetRect(&r_row, d->r_area.left, y);
396 OffsetRect(&r_label, r_row.left, r_row.top);
397 OffsetRect(&r_icon, r_row.left, r_row.top);
400 hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
402 hdefer = BeginDeferWindowPos(2);
404 hwnd = CreateWindowEx(0,
407 WS_CHILD | SS_ENDELLIPSIS | SS_CENTER,
408 r_label.left, r_label.top,
409 r_label.right - r_label.left,
410 r_label.bottom - r_label.top,
414 assert(hwnd != NULL);
416 SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
418 DeferWindowPos(hdefer, hwnd, NULL,
420 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
421 SWP_NOSIZE | SWP_SHOWWINDOW);
423 d->hwnd_notif_label = hwnd;
425 hwnd = CreateWindowEx(0,
429 #if (_WIN32_IE >= 0x0600)
435 r_icon.left, r_icon.top,
436 r_icon.right - r_icon.left,
437 r_icon.bottom - r_icon.top,
441 assert(hwnd != NULL);
445 SendMessage(hwnd, STM_SETICON, (WPARAM) h_icon, 0);
447 DeferWindowPos(hdefer, hwnd, NULL,
449 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
450 SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOZORDER);
452 d->hwnd_notif_aux = hwnd;
454 EndDeferWindowPos(hdefer);
456 CopyRect(&d->r_notif, &r_row);
458 d->notif_type = NC_NOTIFY_MESSAGE;
460 /* Note that we must call nc_layout_main_panel() after calling
461 this to adjust the layout of the main panel. However we aren't
462 calling it here since we might want to add another set of
463 notifications or make other changes to the main panel content
464 before calling nc_layout_main_panel(). */
468 nc_layout_main_panel(khui_nc_wnd_data * d)
474 RECT r_used; /* extent used by identity specifiers,
475 custom prompts and notificaiton
478 RECT r_wmain; /* extents of the main window in screen
483 r_main.bottom = NCDLG_HEIGHT;
484 r_main.right = NCDLG_WIDTH;
486 MapDialogRect(d->dlg_main, &r_main);
488 CopyRect(&r_used, &d->r_idspec);
490 GetWindowRect(d->dlg_main, &r_wmain);
492 hdwp = BeginDeferWindowPos(7);
494 /* check if the notification area and the custom prompt area are
497 if (d->notif_type != NC_NOTIFY_NONE) {
501 CopyRect(&r, &d->r_custprompt);
503 if (IsRectEmpty(&d->r_custprompt)) {
504 /* if there are no custom prompts, then the notification
505 area should be immediately below the identitify
508 delta_y = d->r_idspec.bottom - d->r_notif.top;
510 /* otherwise, the notification area should be immediately
511 below the custom prompt area */
513 delta_y = d->r_custprompt.bottom - d->r_notif.top;
520 if (d->hwnd_notif_label) {
521 GetWindowRect(d->hwnd_notif_label, &r_lbl);
522 OffsetRect(&r_lbl, -r_wmain.left, delta_y - r_wmain.top);
524 DeferWindowPos(hdwp, d->hwnd_notif_label, NULL,
525 r_lbl.left, r_lbl.top, 0, 0,
526 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
527 SWP_NOZORDER | SWP_NOSIZE);
530 if (d->hwnd_notif_aux) {
531 GetWindowRect(d->hwnd_notif_aux, &r_aux);
532 OffsetRect(&r_aux, -r_wmain.left, delta_y - r_wmain.top);
534 DeferWindowPos(hdwp, d->hwnd_notif_aux, NULL,
535 r_aux.left, r_aux.top, 0, 0,
536 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
537 SWP_NOZORDER | SWP_NOSIZE);
540 OffsetRect(&d->r_notif, 0, delta_y);
544 if (!IsRectEmpty(&d->r_custprompt)) {
545 r_used.bottom = max(d->r_custprompt.bottom,
549 if (!IsRectEmpty(&d->r_notif)) {
550 r_used.bottom = max(d->r_notif.bottom,
554 if (d->nc->mode == KHUI_NC_MODE_MINI) {
560 hw = GetDlgItem(d->dlg_main, IDOK);
564 GetWindowRect(hw, &r_ok);
565 OffsetRect(&r_ok, -r_wmain.left, -r_ok.top + r_used.bottom);
567 DeferWindowPos(hdwp, hw, NULL,
568 r_ok.left, r_ok.top, 0, 0,
569 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
570 SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
572 hw = GetDlgItem(d->dlg_main, IDCANCEL);
576 GetWindowRect(hw, &r_cancel);
577 OffsetRect(&r_cancel, -r_wmain.left, -r_cancel.top + r_used.bottom);
579 DeferWindowPos(hdwp, hw, NULL,
580 r_cancel.left, r_cancel.top, 0, 0,
581 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
582 SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
584 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
588 GetWindowRect(hw, &r_advanced);
589 OffsetRect(&r_advanced, -r_wmain.left, -r_advanced.top + r_used.bottom);
591 DeferWindowPos(hdwp, hw, NULL,
592 r_advanced.left, r_advanced.top, 0, 0,
593 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
594 SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
596 /* and now update the extents of the main panel */
597 r_main.bottom = r_used.bottom + (r_ok.bottom - r_ok.top) + d->r_area.top;
599 CopyRect(&d->r_main, &r_main);
605 hw = GetDlgItem(d->dlg_main, IDOK);
609 if (IsWindowVisible(hw))
610 DeferWindowPos(hdwp, hw, NULL,
612 SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
613 SWP_NOOWNERZORDER | SWP_NOZORDER);
615 hw = GetDlgItem(d->dlg_main, IDCANCEL);
619 if (IsWindowVisible(hw))
620 DeferWindowPos(hdwp, hw, NULL,
622 SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
623 SWP_NOOWNERZORDER | SWP_NOZORDER);
625 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
629 if (IsWindowVisible(hw))
630 DeferWindowPos(hdwp, hw, NULL,
632 SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
633 SWP_NOOWNERZORDER | SWP_NOZORDER);
635 d->r_credtext.top = r_used.bottom;
637 CopyRect(&d->r_main, &r_main);
640 /* now update the layout of the credentials text window */
642 hw_ct = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);
643 hw_ct_label = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);
645 assert(hw_ct != NULL);
646 assert(hw_ct_label != NULL);
649 if (d->nc->mode == KHUI_NC_MODE_MINI ||
650 d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {
652 /* either we aren't supposed to show the credentials text
653 window, or we don't have enough room. */
654 if (IsWindowVisible(hw_ct) || IsWindowVisible(hw_ct_label)) {
656 DeferWindowPos(hdwp, hw_ct, NULL,
658 SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
659 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
661 DeferWindowPos(hdwp, hw_ct_label, NULL,
663 SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
664 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
672 d->r_credtext.left + d->r_n_input.left, /* x */
673 d->r_credtext.top, /* y */
674 d->r_n_input.right - d->r_n_input.left, /* width */
675 d->r_credtext.bottom - d->r_credtext.top, /* height */
676 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
677 SWP_NOZORDER | SWP_SHOWWINDOW);
681 d->r_credtext.left + d->r_n_label.left, /* x */
682 d->r_credtext.top, /* y */
683 d->r_n_label.right - d->r_n_label.left, /* width */
684 d->r_n_label.bottom - d->r_n_label.top, /* height */
685 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
686 SWP_NOZORDER | SWP_SHOWWINDOW);
689 EndDeferWindowPos(hdwp);
691 /* NOTE: although we updated d->r_main, if the new credentials
692 window is in mini mode, we must call
693 nc_layout_new_cred_window() to adjust the size of the new
694 credentials window to fit the main panel. We don't do it here
695 because we need to keep these two operations separate. */
698 /* Credential type panel comparison function. Tabs are sorted based
699 on the following criteria:
701 1) By ordinal - Panels with ordinal -1 will be ranked after panels
702 whose ordinal is not -1.
704 2) By name - Case insensitive comparison of the name. If the panel
705 does not have a name (i.e. the ->name member is NULL, it will be
706 ranked after panels which have a name.
709 nc_tab_sort_func(const void * v1, const void * v2)
711 /* v1 and v2 and of type : khui_new_creds_by_type ** */
712 khui_new_creds_by_type *t1, *t2;
714 t1 = *((khui_new_creds_by_type **) v1);
715 t2 = *((khui_new_creds_by_type **) v2);
717 if(t1->ordinal != -1) {
718 if(t2->ordinal != -1) {
719 if(t1->ordinal == t2->ordinal) {
720 if (t1->name && t2->name)
721 return _wcsicmp(t1->name, t2->name);
729 /* safe to convert to an int here */
730 return (int) (t1->ordinal - t2->ordinal);
735 if(t2->ordinal != -1)
737 else if (t1->name && t2->name)
738 return wcscmp(t1->name, t2->name);
749 nc_notify_types(khui_new_creds * c, UINT uMsg,
750 WPARAM wParam, LPARAM lParam, BOOL sync)
754 for(i=0; i<c->n_types; i++) {
756 if (c->types[i]->hwnd_panel == NULL)
760 SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
762 PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
767 nc_clear_password_fields(khui_nc_wnd_data * d)
770 khm_boolean need_sync = FALSE;
772 khui_cw_lock_nc(d->nc);
774 for (i=0; i < d->nc->n_prompts; i++) {
775 if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) &&
776 d->nc->prompts[i]->hwnd_edit) {
777 SetWindowText(d->nc->prompts[i]->hwnd_edit,
783 khui_cw_unlock_nc(d->nc);
786 khui_cw_sync_prompt_values(d->nc);
790 /* used by nc_enable_controls */
792 struct nc_enum_wnd_data {
793 khui_nc_wnd_data * d;
799 nc_enum_wnd_proc(HWND hwnd,
802 struct nc_enum_wnd_data * wd;
804 wd = (struct nc_enum_wnd_data *) lParam;
806 EnableWindow(hwnd, wd->enable);
812 nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable)
814 struct nc_enum_wnd_data wd;
816 ZeroMemory(&wd, sizeof(wd));
821 EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd);
824 #define NC_MAXCCH_CREDTEXT 16384
825 #define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))
828 nc_update_credtext(khui_nc_wnd_data * d)
830 wchar_t * ctbuf = NULL;
832 BOOL okEnable = FALSE;
833 BOOL validId = FALSE;
837 ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);
839 assert(ctbuf != NULL);
841 LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);
842 StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);
844 nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
845 MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc, TRUE);
847 /* hopefully all the types have updated their credential texts */
849 /* if the dialog is in the mini mode, we have to display
850 exceptions using a notification. */
851 if (d->nc->mode == KHUI_NC_MODE_MINI) {
852 BOOL need_layout = FALSE;
853 if (d->nc->n_identities == 0) {
855 /* There are no identities selected. We don't show any
856 notifications here. */
857 if (d->notif_type != NC_NOTIFY_NONE) {
864 wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
866 wchar_t msg[ARRAYLENGTH(format) + ARRAYLENGTH(id_name)];
870 kcdb_identity_get_flags(d->nc->identities[0], &flags);
872 cbbuf = sizeof(id_name);
873 kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
875 if (flags & KCDB_IDENT_FLAG_INVALID) {
877 /* identity is invalid */
878 LoadString(khm_hInstance, IDS_NCN_IDENT_INVALID,
879 format, ARRAYLENGTH(format));
880 StringCbPrintf(msg, sizeof(msg), format, id_name);
882 nc_notify_message(d, KHERR_ERROR, msg);
886 } else if ((flags & KCDB_IDENT_FLAG_VALID) ||
887 d->nc->subtype == KMSG_CRED_PASSWORD) {
888 /* special case: If we are going to change the
889 password, we don't expect the identity provider to
890 validate the identity in real time. As such, we
891 assume that the identity is valid. */
893 /* identity is valid */
894 if (d->notif_type != NC_NOTIFY_NONE) {
899 } else if (flags & KCDB_IDENT_FLAG_UNKNOWN) {
902 LoadString(khm_hInstance, IDS_NCN_IDENT_UNKNOWN,
903 format, ARRAYLENGTH(format));
904 StringCbPrintf(msg, sizeof(msg), format, id_name);
906 nc_notify_message(d, KHERR_WARNING, msg);
913 LoadString(khm_hInstance, IDS_NCN_IDENT_CHECKING,
914 format, ARRAYLENGTH(format));
915 StringCbPrintf(msg, sizeof(msg), format, id_name);
917 nc_notify_marquee(d, msg);
925 nc_layout_main_panel(d);
926 nc_layout_new_cred_window(d);
930 if(d->nc->n_identities == 1) {
931 wchar_t main_fmt[256];
933 wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
934 wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
938 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE,
939 main_fmt, (int) ARRAYLENGTH(main_fmt));
941 cbbuf = sizeof(id_name);
942 kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
944 kcdb_identity_get_flags(d->nc->identities[0], &flags);
946 if (flags & KCDB_IDENT_FLAG_INVALID) {
947 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
948 id_fmt, (int) ARRAYLENGTH(id_fmt));
949 } else if(flags & KCDB_IDENT_FLAG_VALID) {
950 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
951 id_fmt, (int) ARRAYLENGTH(id_fmt));
952 } else if(flags & KCDB_IDENT_FLAG_UNKNOWN) {
953 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
954 id_fmt, (int) ARRAYLENGTH(id_fmt));
955 } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {
956 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING,
957 id_fmt, (int) ARRAYLENGTH(id_fmt));
959 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
960 id_fmt, (int) ARRAYLENGTH(id_fmt));
963 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
965 StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
966 main_fmt, id_string);
968 if (flags & KCDB_IDENT_FLAG_VALID) {
969 if (flags & KCDB_IDENT_FLAG_DEFAULT)
970 LoadString(khm_hInstance, IDS_NC_ID_DEF,
971 id_string, ARRAYLENGTH(id_string));
972 else if (d->nc->set_default)
973 LoadString(khm_hInstance, IDS_NC_ID_WDEF,
974 id_string, ARRAYLENGTH(id_string));
976 LoadString(khm_hInstance, IDS_NC_ID_NDEF,
977 id_string, ARRAYLENGTH(id_string));
979 StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t),
983 } else if(d->nc->n_identities > 1) {
985 khm_size cb_ids_string;
987 wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
989 wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
991 wchar_t main_fmt[256];
994 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY,
995 main_fmt, (int) ARRAYLENGTH(main_fmt));
997 /* we are going to concatenate all the identity names into
998 a comma separated string */
1000 /* d->nc->n_identities is at least 2 */
1001 ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
1002 (d->nc->n_identities - 1));
1004 (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
1005 (d->nc->n_identities - 1);
1007 assert(ids_string != NULL);
1015 for(i=1; i<d->nc->n_identities; i++) {
1017 StringCbCat(ids_string, cb_ids_string, L",");
1022 cbbuf = sizeof(id_name);
1023 kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);
1024 kcdb_identity_get_flags(d->nc->identities[i], &flags);
1025 if(flags & KCDB_IDENT_FLAG_INVALID) {
1026 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
1027 id_fmt, (int) ARRAYLENGTH(id_fmt));
1028 } else if(flags & KCDB_IDENT_FLAG_VALID) {
1029 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
1030 id_fmt, (int) ARRAYLENGTH(id_fmt));
1032 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
1033 id_fmt, (int) ARRAYLENGTH(id_fmt));
1036 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
1037 StringCbCat(ids_string, cb_ids_string, id_string);
1040 cbbuf = sizeof(id_name);
1041 kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
1042 kcdb_identity_get_flags(d->nc->identities[0], &flags);
1043 if(flags & KCDB_IDENT_FLAG_INVALID) {
1044 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
1045 id_fmt, (int) ARRAYLENGTH(id_fmt));
1046 } else if(flags & KCDB_IDENT_FLAG_VALID) {
1047 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
1048 id_fmt, (int) ARRAYLENGTH(id_fmt));
1050 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
1051 id_fmt, (int) ARRAYLENGTH(id_fmt));
1053 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
1055 StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
1056 main_fmt, id_string, ids_string);
1061 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE,
1062 buf, (int)(NC_MAXCCH_CREDTEXT - cch));
1065 /* now, append the credtext string from each of the cred types */
1071 cb = NC_MAXCB_CREDTEXT;
1074 for(i=0; i<d->nc->n_types; i++) {
1075 if(d->nc->types[i]->credtext != NULL) {
1076 StringCbCatEx(buf, cb,
1077 d->nc->types[i]->credtext,
1084 SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);
1088 /* so depending on whether the primary identity was found to be
1089 invalid, we need to disable the Ok button and set the title to
1092 if(d->nc->n_identities > 0) {
1093 khm_int32 flags = 0;
1095 if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0],
1097 (flags & KCDB_IDENT_FLAG_VALID)) {
1102 if (d->nc->window_title == NULL) {
1104 wchar_t wpostfix[256];
1105 wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];
1108 cbsize = sizeof(wtitle);
1109 kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);
1111 if (d->nc->subtype == KMSG_CRED_PASSWORD)
1112 LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,
1113 wpostfix, (int) ARRAYLENGTH(wpostfix));
1115 LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS,
1116 wpostfix, (int) ARRAYLENGTH(wpostfix));
1118 StringCbCat(wtitle, sizeof(wtitle), wpostfix);
1120 SetWindowText(d->nc->hwnd, wtitle);
1122 wchar_t wtitle[256];
1124 if (d->nc->subtype == KMSG_CRED_PASSWORD)
1125 LoadString(khm_hInstance, IDS_WT_PASSWORD,
1126 wtitle, (int) ARRAYLENGTH(wtitle));
1128 LoadString(khm_hInstance, IDS_WT_NEW_CREDS,
1129 wtitle, (int) ARRAYLENGTH(wtitle));
1131 SetWindowText(d->nc->hwnd, wtitle);
1135 if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) {
1137 d->nc->subtype == KMSG_CRED_PASSWORD) {
1138 /* TODO: check if all the required fields have valid values
1139 before enabling the Ok button */
1143 hw = GetDlgItem(d->dlg_main, IDOK);
1144 EnableWindow(hw, okEnable);
1145 hw = GetDlgItem(d->dlg_bb, IDOK);
1146 EnableWindow(hw, okEnable);
1151 nc_layout_new_cred_window(khui_nc_wnd_data * ncd) {
1161 r_main.right = NCDLG_WIDTH;
1162 r_main.bottom = NCDLG_HEIGHT;
1164 MapDialogRect(ncd->dlg_main, &r_main);
1166 hdefer = BeginDeferWindowPos(5);
1168 if (c->mode == KHUI_NC_MODE_MINI) {
1170 if (IsWindowVisible(ncd->tab_wnd)) {
1171 DeferWindowPos(hdefer,
1175 SWP_NOMOVE | SWP_NOOWNERZORDER |
1176 SWP_NOSIZE | SWP_NOZORDER);
1179 if (IsWindowVisible(ncd->dlg_bb)) {
1180 DeferWindowPos(hdefer,
1184 SWP_NOMOVE | SWP_NOOWNERZORDER |
1185 SWP_NOSIZE | SWP_NOZORDER);
1188 DeferWindowPos(hdefer, ncd->dlg_main, NULL,
1189 r_main.left, r_main.top,
1190 r_main.right - r_main.left,
1191 r_main.bottom - r_main.top,
1192 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1193 SWP_NOZORDER | SWP_SHOWWINDOW);
1195 /* note that the ncd->r_main.bottom may not be the same as
1196 r_main.bottom because ncd->r_main.bottom is set dynamically
1197 depending on custom controls. ncd->r_main is valid only
1198 once nc_layout_main_panel() is called.*/
1199 CopyRect(&ncd->r_required, &ncd->r_main);
1207 /* calculate the size of the tab control so that it fits
1208 snugly around the expanded main panel. */
1209 CopyRect(&r_tabctrl, &r_main);
1210 TabCtrl_AdjustRect(ncd->tab_wnd, TRUE, &r_tabctrl);
1212 if (r_tabctrl.left < 0 ||
1213 r_tabctrl.top < 0) {
1215 OffsetRect(&r_tabctrl,
1216 (r_tabctrl.left < 0)? -r_tabctrl.left : 0,
1217 (r_tabctrl.top < 0)? -r_tabctrl.top : 0);
1222 assert(r_tabctrl.left == 0);
1223 assert(r_tabctrl.top == 0);
1226 OffsetRect(&r_tabctrl, 0, ncd->r_area.top);
1228 /* and now calculate the rectangle where the main panel should
1229 be inside the tab control. */
1230 CopyRect(&r_displayarea, &r_tabctrl);
1231 TabCtrl_AdjustRect(ncd->tab_wnd, FALSE, &r_displayarea);
1233 DeferWindowPos(hdefer,
1234 ncd->tab_wnd, HWND_BOTTOM,
1235 r_tabctrl.left, r_tabctrl.top,
1236 r_tabctrl.right - r_tabctrl.left,
1237 r_tabctrl.bottom - r_tabctrl.top,
1238 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1241 /* we have to place the button bar just to the right of the
1245 r_bbar.right = NCDLG_BBAR_WIDTH;
1246 r_bbar.bottom = NCDLG_BBAR_HEIGHT;
1248 MapDialogRect(ncd->dlg_main, &r_bbar);
1250 OffsetRect(&r_bbar, r_tabctrl.right, 0);
1252 DeferWindowPos(hdefer,
1254 r_bbar.left, r_bbar.top,
1255 r_bbar.right - r_bbar.left,
1256 r_bbar.bottom - r_bbar.top,
1257 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1258 SWP_NOZORDER | SWP_SHOWWINDOW);
1260 /* move the main panel inside the tab control... */
1261 DeferWindowPos(hdefer,
1262 ncd->dlg_main, NULL,
1263 r_displayarea.left, r_displayarea.top,
1264 r_displayarea.right - r_displayarea.left,
1265 r_displayarea.bottom - r_displayarea.top,
1266 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1268 (ncd->current_panel == 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
1270 /* and also move all the credential type panels (if they have
1271 been created) inside the tab control too. */
1274 for (i=0; i < c->n_types; i++) {
1275 if (c->types[i]->hwnd_panel != NULL) {
1276 DeferWindowPos(hdefer,
1277 c->types[i]->hwnd_panel, NULL,
1278 r_displayarea.left, r_displayarea.top,
1279 r_displayarea.right - r_displayarea.left,
1280 r_displayarea.bottom - r_displayarea.top,
1281 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1283 (ncd->current_panel == c->types[i]->ordinal ?
1284 SWP_SHOWWINDOW : SWP_HIDEWINDOW));
1288 khui_cw_unlock_nc(c);
1290 /* then update the required size of the new credentials
1292 ncd->r_required.left = 0;
1293 ncd->r_required.top = 0;
1294 ncd->r_required.right = r_bbar.right;
1295 ncd->r_required.bottom = max(r_tabctrl.bottom, r_bbar.bottom) + ncd->r_area.top;
1298 /* commit all the window moves, resizes and hides/shows we did*/
1299 EndDeferWindowPos(hdefer);
1301 /* now we have to see if the client area of the new credentials
1302 window is the right size. */
1304 GetClientRect(c->hwnd, &r_ncdialog);
1308 ((r_ncdialog.right - r_ncdialog.left !=
1309 ncd->r_required.right - ncd->r_required.left)
1313 (r_ncdialog.bottom - r_ncdialog.top !=
1314 ncd->r_required.bottom - ncd->r_required.top))
1318 /* we don't bother if the new creds window is already in the
1319 process of changing the size. */
1320 !ncd->size_changing) {
1322 /* if not, notify the window that the size needs adjusting. */
1323 if (IsWindowVisible(c->hwnd))
1324 PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
1325 MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
1327 SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
1328 MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
1332 #define CW_PARAM DWLP_USER
1335 nc_handle_wm_create(HWND hwnd,
1342 khui_nc_wnd_data * ncd;
1348 lpc = (LPCREATESTRUCT) lParam;
1350 ncd = PMALLOC(sizeof(*ncd));
1351 ZeroMemory(ncd, sizeof(*ncd));
1353 c = (khui_new_creds *) lpc->lpCreateParams;
1358 assert(c->subtype == KMSG_CRED_NEW_CREDS ||
1359 c->subtype == KMSG_CRED_PASSWORD);
1362 #pragma warning(push)
1363 #pragma warning(disable: 4244)
1364 SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);
1365 #pragma warning(pop)
1367 /* first, create the tab control that will house the main dialog
1368 panel as well as the plug-in specific panels */
1369 ncd->tab_wnd = CreateWindowEx(0, /* extended style */
1371 L"TabControloxxrz", /* window name */
1372 TCS_HOTTRACK | TCS_RAGGEDRIGHT |
1373 TCS_SINGLELINE | TCS_TABS |
1374 WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS,
1375 0, 0, 100, 100, /* x,y,width height.
1380 (HMENU) IDC_NC_TABS,
1385 assert(ncd->tab_wnd != NULL);
1388 /* try to create the main dialog panel */
1390 ncd->dlg_main = CreateDialogParam(khm_hInstance,
1391 MAKEINTRESOURCE(IDD_NC_NEWCRED),
1396 assert(ncd->dlg_main != NULL);
1399 hf_main = (HFONT) SendMessage(ncd->dlg_main, WM_GETFONT, 0, 0);
1401 SendMessage(ncd->tab_wnd, WM_SETFONT, (WPARAM) hf_main, FALSE);
1409 /* During the operation of the new credentials window, we will
1410 need to dynamically change the layout of the controls as a
1411 result of custom prompting from credentials providers and
1412 identity selectors from identity providers. In order to
1413 guide the dynamic layout, we pick out a few metrics from
1414 the dialog template for the main panel. The metrics come
1415 from hidden STATIC controls in the dialog template. */
1417 GetWindowRect(ncd->dlg_main, &r_main);
1419 /* IDC_NC_TPL_PANEL spans the full extent of the dialog that
1420 we can populate with custom controls. */
1421 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL);
1425 GetWindowRect(hw, &r_area);
1426 OffsetRect(&r_area,-r_main.left, -r_main.top);
1427 CopyRect(&ncd->r_area, &r_area);
1429 /* IDC_NC_TPL_ROW spans the extent of a row of normal sized
1430 custom controls. A row of custom controls typicall consist
1431 of a text label and an input control. */
1432 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW);
1436 GetWindowRect(hw, &r);
1437 CopyRect(&r_row, &r);
1438 OffsetRect(&r,-r.left, -r.top);
1439 CopyRect(&ncd->r_row, &r);
1441 /* IDC_NC_TPL_LABEL spans the extent that a normal sized
1442 label. The control overlaps IDC_NC_TPL_ROW so we can get
1443 coordinates relative to the row extents. */
1444 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL);
1448 GetWindowRect(hw, &r);
1449 OffsetRect(&r,-r_row.left, -r_row.top);
1450 CopyRect(&ncd->r_n_label, &r);
1452 /* IDC_NC_TPL_INPUT spans the extent of a normal sized input
1453 control in a custom control row. The control overlaps
1454 IDC_NC_TPL_ROW so we can get relative coordinates. */
1455 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT);
1459 GetWindowRect(hw, &r);
1460 OffsetRect(&r, -r_row.left, -r_row.top);
1461 CopyRect(&ncd->r_n_input, &r);
1463 /* IDC_NC_TPL_ROW_LG spans the extent of a row of large sized
1465 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG);
1469 GetWindowRect(hw, &r_row);
1471 /* IDC_NC_TPL_LABEL_LG is a large sized label. The control
1472 overlaps IDC_NC_TPL_ROW_LG. */
1473 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG);
1477 GetWindowRect(hw, &r);
1478 OffsetRect(&r, -r_row.left, -r_row.top);
1479 CopyRect(&ncd->r_e_label, &r);
1481 /* IDC_NC_TPL_INPUT_LG is a large sized input control.
1482 Overlaps IDC_NC_TPL_ROW_LG. */
1483 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG);
1487 GetWindowRect(hw, &r);
1488 OffsetRect(&r, -r_row.left, -r_row.top);
1489 CopyRect(&ncd->r_e_input, &r);
1491 CopyRect(&ncd->r_credtext, &ncd->r_area);
1492 CopyRect(&ncd->r_idspec, &ncd->r_area);
1494 ncd->r_idspec.bottom = ncd->r_idspec.top;
1496 /* And finally the credential text window. The only metric we
1497 take from here is the Y coordinate of the bottom of the
1498 control since the actual size and position of the
1499 credentials window will change depending on the custom
1500 controls being displayed. */
1501 hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT);
1505 GetWindowRect(hw, &r);
1506 OffsetRect(&r, -r_main.left, -r_main.top);
1507 ncd->r_credtext.bottom = r.bottom;
1510 /* if the mode is 'mini'*/
1514 if(c->mode == KHUI_NC_MODE_MINI) {
1515 r.right = NCDLG_WIDTH;
1516 r.bottom = NCDLG_HEIGHT;
1518 r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;
1519 r.bottom = NCDLG_BBAR_HEIGHT;
1522 MapDialogRect(ncd->dlg_main, &r);
1524 /* position the new credentials dialog */
1525 width = r.right - r.left;
1526 height = r.bottom - r.top;
1528 /* adjust width and height to accomodate NC area */
1532 GetWindowRect(hwnd, &wr);
1533 GetClientRect(hwnd, &cr);
1535 /* the non-client and client areas have already been calculated
1536 at this point. We just use the difference to adjust the width
1538 width += (wr.right - wr.left) - (cr.right - cr.left);
1539 height += (wr.bottom - wr.top) - (cr.bottom - cr.top);
1542 /* if the parent window is visible, we center the new credentials
1543 dialog over the parent. Otherwise, we center it on the primary
1546 if (IsWindowVisible(lpc->hwndParent)) {
1547 GetWindowRect(lpc->hwndParent, &r);
1549 if(!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &r, 0)) {
1550 /* failover to the window coordinates */
1551 GetWindowRect(lpc->hwndParent, &r);
1554 x = (r.right + r.left)/2 - width / 2;
1555 y = (r.top + r.bottom)/2 - height / 2;
1557 MoveWindow(hwnd, x, y, width, height, FALSE);
1559 ncd->dlg_bb = CreateDialogParam(khm_hInstance,
1560 MAKEINTRESOURCE(IDD_NC_BBAR),
1566 assert(ncd->dlg_bb);
1569 /* Call the identity provider callback to set the identity
1570 selector controls. These controls need to be there before we
1571 layout the main panel. */
1572 c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main);
1574 if (c->mode == KHUI_NC_MODE_EXPANDED) {
1575 SendMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY,
1576 MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
1578 /* we don't call nc_layout_main_panel() if the dialog is
1579 expanded because posting WMNC_DIALOG_EXPAND to the main
1580 panel results in it getting called anyway. */
1581 nc_layout_main_panel(ncd);
1584 nc_layout_new_cred_window(ncd);
1586 /* add this to the dialog chain */
1587 khm_add_dialog(hwnd);
1592 /* add a control row supplied by an identity provider */
1594 nc_add_control_row(khui_nc_wnd_data * d,
1597 khui_control_size size)
1605 hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
1606 SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);
1607 SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);
1609 CopyRect(&r_row, &d->r_row);
1610 OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);
1612 if (size == KHUI_CTRLSIZE_SMALL) {
1613 CopyRect(&r_label, &d->r_n_label);
1614 CopyRect(&r_input, &d->r_n_input);
1615 OffsetRect(&r_label, r_row.left, r_row.top);
1616 OffsetRect(&r_input, r_row.left, r_row.top);
1617 } else if (size == KHUI_CTRLSIZE_HALF) {
1618 CopyRect(&r_label, &d->r_e_label);
1619 CopyRect(&r_input, &d->r_e_input);
1620 OffsetRect(&r_label, r_row.left, r_row.top);
1621 OffsetRect(&r_input, r_row.left, r_row.top);
1622 } else if (size == KHUI_CTRLSIZE_FULL) {
1623 CopyRect(&r_label, &d->r_n_label);
1624 r_label.right = d->r_row.right;
1625 CopyRect(&r_input, &d->r_n_input);
1626 OffsetRect(&r_input, r_row.left, r_row.top);
1627 OffsetRect(&r_input, 0, r_input.bottom);
1628 r_row.bottom += r_input.bottom;
1629 OffsetRect(&r_label, r_row.left, r_row.top);
1631 SetRectEmpty(&r_label);
1632 SetRectEmpty(&r_input);
1639 hdefer = BeginDeferWindowPos(2);
1642 DeferWindowPos(hdefer, label,
1643 ((d->hwnd_last_idspec != NULL)?
1644 d->hwnd_last_idspec:
1646 r_label.left, r_label.top,
1647 r_label.right - r_label.left,
1648 r_label.bottom - r_label.top,
1649 SWP_NOACTIVATE | SWP_NOOWNERZORDER);
1652 DeferWindowPos(hdefer, input,
1653 (label ? label : ((d->hwnd_last_idspec != NULL)?
1654 d->hwnd_last_idspec:
1656 r_input.left, r_input.top,
1657 r_input.right - r_input.left,
1658 r_input.bottom - r_input.top,
1659 SWP_NOACTIVATE | SWP_NOOWNERZORDER);
1661 EndDeferWindowPos(hdefer);
1663 d->hwnd_last_idspec = (input ? input : label);
1665 d->r_idspec.bottom = r_row.bottom;
1667 /* we don't update the layout of the main panel yet, since these
1668 control additions happen before the main panel is displayed. A
1669 call to nc_layout_main_panel() will be made before the main
1670 panel is shown anyway. */
1676 nc_handle_wm_destroy(HWND hwnd,
1681 khui_nc_wnd_data * d;
1683 /* remove self from dialog chain */
1684 khm_del_dialog(hwnd);
1686 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1688 d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);
1690 if (d->hwnd_notif_label)
1691 DestroyWindow(d->hwnd_notif_label);
1692 if (d->hwnd_notif_aux)
1693 DestroyWindow(d->hwnd_notif_aux);
1696 DestroyWindow(d->dlg_bb);
1698 DestroyWindow(d->dlg_main);
1709 nc_handle_wm_command(HWND hwnd,
1714 khui_nc_wnd_data * d;
1716 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1718 switch(HIWORD(wParam)) {
1720 switch(LOWORD(wParam)) {
1723 d->nc->result = KHUI_NC_RESULT_PROCESS;
1728 /* the default value for d->nc->result is set to
1729 KHUI_NC_RESULT_CANCEL */
1730 d->nc->response = KHUI_NC_RESPONSE_PROCESSING;
1732 nc_enable_controls(d, FALSE);
1734 nc_notify_types(d->nc,
1736 MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS),
1740 khui_cw_sync_prompt_values(d->nc);
1742 khm_cred_dispatch_process_message(d->nc);
1744 /* we won't know whether to abort or not until we get
1745 feedback from the plugins, even if the command was
1750 hw = GetDlgItem(d->dlg_main, IDOK);
1751 EnableWindow(hw, FALSE);
1752 hw = GetDlgItem(d->dlg_main, IDCANCEL);
1753 EnableWindow(hw, FALSE);
1754 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
1755 EnableWindow(hw, FALSE);
1756 hw = GetDlgItem(d->dlg_bb, IDOK);
1757 EnableWindow(hw, FALSE);
1758 hw = GetDlgItem(d->dlg_bb, IDCANCEL);
1759 EnableWindow(hw, FALSE);
1764 khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID);
1768 case IDC_NC_ADVANCED:
1769 /* the Options button in the main window was clicked. we
1770 respond by expanding the dialog. */
1771 PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
1772 MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
1775 case IDC_NC_CREDTEXT: /* credtext link activated */
1777 khui_htwnd_link * l;
1778 wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];
1779 wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];
1782 l = (khui_htwnd_link *) lParam;
1784 /* do we have a valid link? */
1785 if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))
1786 return TRUE; /* nope */
1788 StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);
1789 sid[l->id_len] = L'\0'; /* just make sure */
1791 if(l->param != NULL &&
1792 l->param_len < ARRAYLENGTH(sparam) &&
1795 StringCchCopyN(sparam, ARRAYLENGTH(sparam),
1796 l->param, l->param_len);
1797 sparam[l->param_len] = L'\0';
1803 /* If the ID is of the form '<credtype>:<link_tag>'
1804 and <credtype> is a valid name of a credentials
1805 type that is participating in the credentials
1806 acquisition process, then we forward the message to
1807 the panel that is providing the UI for that cred
1808 type. We also switch to that panel first, unless
1809 the link is of the form '<credtype>:!<link_tag>'. */
1811 colon = wcschr(sid, L':');
1812 if (colon != NULL) {
1814 khui_new_creds_by_type * t;
1817 if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&
1818 KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){
1821 if (t->ordinal != d->current_panel &&
1822 *(colon + 1) != L'!')
1825 MAKEWPARAM(t->ordinal,
1826 WMNC_DIALOG_SWITCH_PANEL),
1829 return SendMessage(t->hwnd_panel,
1831 MAKEWPARAM(0, WMNC_CREDTEXT_LINK),
1838 /* if it was for us, then we need to process the message */
1839 if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {
1841 khui_new_creds_by_type * t;
1843 if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam,
1845 KHM_SUCCEEDED(khui_cw_find_type(d->nc,
1847 if (t->ordinal != d->current_panel)
1850 MAKEWPARAM(t->ordinal,
1851 WMNC_DIALOG_SWITCH_PANEL),
1854 } else if (!_wcsicmp(sid, L"NotDef")) {
1855 d->nc->set_default = FALSE;
1856 nc_update_credtext(d);
1857 } else if (!_wcsicmp(sid, L"MakeDef")) {
1858 d->nc->set_default = TRUE;
1859 nc_update_credtext(d);
1865 case NC_BN_SET_DEF_ID:
1867 d->nc->set_default =
1868 (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID)
1880 static LRESULT nc_handle_wm_moving(HWND hwnd,
1885 khui_nc_wnd_data * d;
1887 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1889 nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
1890 MAKEWPARAM(0, WMNC_DIALOG_MOVE), (LPARAM) d->nc, TRUE);
1895 static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
1900 khui_nc_wnd_data * d;
1903 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1905 switch(HIWORD(wParam)) {
1907 case WMNC_DIALOG_SWITCH_PANEL:
1908 id = LOWORD(wParam);
1909 if(id >= 0 && id <= (int) d->nc->n_types) {
1910 /* one of the tab buttons were pressed */
1911 if(d->current_panel == id) {
1912 return TRUE; /* nothing to do */
1915 d->current_panel = id;
1917 TabCtrl_SetCurSel(d->tab_wnd, id);
1920 if(d->nc->mode == KHUI_NC_MODE_EXPANDED) {
1921 nc_layout_new_cred_window(d);
1927 case WMNC_DIALOG_EXPAND:
1928 /* we are switching from basic to advanced or vice versa */
1930 if (d->nc->mode == KHUI_NC_MODE_EXPANDED) {
1931 d->nc->mode = KHUI_NC_MODE_MINI;
1933 d->nc->mode = KHUI_NC_MODE_EXPANDED;
1936 /* if we are switching to the advanced mode, we clear any
1937 notifications because we now have a credential text area
1939 if (d->nc->mode == KHUI_NC_MODE_EXPANDED)
1942 nc_layout_main_panel(d);
1944 nc_layout_new_cred_window(d);
1948 case WMNC_DIALOG_SETUP:
1950 if(d->nc->n_types > 0) {
1952 for(i=0; i < d->nc->n_types;i++) {
1954 if (d->nc->types[i]->dlg_proc == NULL) {
1955 d->nc->types[i]->hwnd_panel = NULL;
1957 /* Create the dialog panel */
1958 d->nc->types[i]->hwnd_panel =
1959 CreateDialogParam(d->nc->types[i]->h_module,
1960 d->nc->types[i]->dlg_template,
1962 d->nc->types[i]->dlg_proc,
1966 assert(d->nc->types[i]->hwnd_panel);
1974 case WMNC_DIALOG_ACTIVATE:
1976 wchar_t wname[KCDB_MAXCCH_NAME];
1980 /* About to activate the window. We should add all the
1981 panels to the tab control. */
1984 assert(d->tab_wnd != NULL);
1987 ZeroMemory(&tabitem, sizeof(tabitem));
1989 tabitem.mask = TCIF_PARAM | TCIF_TEXT;
1991 LoadString(khm_hInstance, IDS_NC_IDENTITY,
1992 wname, ARRAYLENGTH(wname));
1994 tabitem.pszText = wname;
1995 tabitem.lParam = 0; /* ordinal */
1997 TabCtrl_InsertItem(d->tab_wnd, 0, &tabitem);
1999 khui_cw_lock_nc(d->nc);
2001 if(d->nc->n_types > 0) {
2004 /* We should sort the tabs first. See
2005 nc_tab_sort_func() for sort criteria. */
2008 sizeof(*(d->nc->types)),
2011 for(i=0; i < d->nc->n_types;i++) {
2013 d->nc->types[i]->ordinal = i + 1;
2015 if(d->nc->types[i]->name)
2016 tabitem.pszText = d->nc->types[i]->name;
2020 cbsize = sizeof(wname);
2023 (kcdb_credtype_describe
2024 (d->nc->types[i]->type,
2036 tabitem.pszText = wname;
2040 tabitem.lParam = d->nc->types[i]->ordinal;
2042 TabCtrl_InsertItem(d->tab_wnd, d->nc->types[i]->ordinal,
2047 khui_cw_unlock_nc(d->nc);
2049 nc_update_credtext(d);
2051 TabCtrl_SetCurSel(d->tab_wnd, 0); /* the first selected
2055 /* bring the window to the top, if necessary */
2056 if (KHM_SUCCEEDED(khc_read_int32(NULL,
2057 L"CredWindow\\Windows\\NewCred\\ForceToTop",
2061 /* it used to be that the above condition also called
2062 !khm_is_dialog_active() to find out whether there
2063 was a dialog active. If there was, we wouldn't try
2064 to bring the new cred window to the foreground. But
2065 that was not the behavior we want. */
2067 /* if the main window is not visible, then the SetWindowPos()
2068 call is sufficient to bring the new creds window to the
2069 top. However, if the main window is visible but not
2070 active, the main window needs to be activated before a
2071 child window can be activated. */
2072 khm_activate_main_window();
2074 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
2075 (SWP_NOMOVE | SWP_NOSIZE));
2078 ShowWindow(hwnd, SW_SHOWNOACTIVATE);
2080 /* we don't enable animations until a specific timeout
2081 elapses after showing the window. We don't need to
2082 animate any size changes if the user has barely had a
2083 chance to notice the original size. This prevents the
2084 new cred window from appearing in an animated state. */
2085 SetTimer(hwnd, NC_TIMER_ENABLEANIMATE, ENABLEANIMATE_TIMEOUT, NULL);
2089 if (d->nc->n_identities == 0)
2095 case WMNC_IDENTITY_CHANGE:
2097 BOOL okEnable = FALSE;
2099 nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
2100 MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), (LPARAM) d->nc,
2103 if (d->nc->subtype == KMSG_CRED_NEW_CREDS &&
2104 d->nc->n_identities > 0 &&
2105 d->nc->identities[0]) {
2108 kcdb_identity_get_flags(d->nc->identities[0], &f);
2110 if (!(f & KCDB_IDENT_FLAG_DEFAULT)) {
2111 d->nc->set_default = FALSE;
2115 nc_update_credtext(d);
2120 case WMNC_TYPE_STATE:
2122 case WMNC_UPDATE_CREDTEXT:
2123 nc_update_credtext(d);
2126 case WMNC_CLEAR_PROMPTS:
2130 khui_cw_lock_nc(d->nc);
2132 if(d->hwnd_banner != NULL) {
2133 DestroyWindow(d->hwnd_banner);
2134 d->hwnd_banner = NULL;
2137 if(d->hwnd_name != NULL) {
2138 DestroyWindow(d->hwnd_name);
2139 d->hwnd_name = NULL;
2142 for(i=0;i<d->nc->n_prompts;i++) {
2143 if(!(d->nc->prompts[i]->flags &
2144 KHUI_NCPROMPT_FLAG_STOCK)) {
2145 if(d->nc->prompts[i]->hwnd_static != NULL)
2146 DestroyWindow(d->nc->prompts[i]->hwnd_static);
2148 if(d->nc->prompts[i]->hwnd_edit != NULL)
2149 DestroyWindow(d->nc->prompts[i]->hwnd_edit);
2152 d->nc->prompts[i]->hwnd_static = NULL;
2153 d->nc->prompts[i]->hwnd_edit = NULL;
2156 khui_cw_unlock_nc(d->nc);
2158 SetRectEmpty(&d->r_custprompt);
2160 nc_layout_main_panel(d);
2162 nc_layout_new_cred_window(d);
2166 case WMNC_SET_PROMPTS:
2173 BOOL use_large_lables = FALSE;
2175 /* we assume that WMNC_CLEAR_PROMPTS has already been
2179 assert(IsRectEmpty(&d->r_custprompt));
2182 khui_cw_lock_nc(d->nc);
2185 /* special case, we have one prompt and it is a password
2186 prompt. very common */
2187 if(d->nc->n_prompts == 1 &&
2188 d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
2190 hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);
2191 EnableWindow(hw, TRUE);
2193 d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;
2194 d->nc->prompts[0]->hwnd_edit = hw;
2195 d->nc->prompts[0]->hwnd_static = NULL; /* don't care */
2197 khui_cw_unlock_nc(d->nc);
2201 /* for everything else */
2203 y = d->r_idspec.bottom;
2205 d->r_custprompt.left = d->r_area.left;
2206 d->r_custprompt.right = d->r_area.right;
2207 d->r_custprompt.top = y;
2209 hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
2211 if (d->nc->pname != NULL) {
2217 SS_SUNKEN | WS_CHILD,
2220 d->r_n_label.bottom - d->r_n_label.top,
2230 SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);
2231 ShowWindow(hw, SW_SHOW);
2233 y += d->r_n_label.bottom - d->r_n_label.top;
2236 if (d->nc->banner != NULL) {
2244 d->r_row.right, d->r_row.bottom,
2252 d->hwnd_banner = hw;
2253 SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);
2254 ShowWindow(hw, SW_SHOW);
2255 y += d->r_row.bottom;
2258 hw_prev = d->hwnd_last_idspec;
2260 hdc = GetWindowDC(d->dlg_main);
2261 hfold = SelectObject(hdc,hf);
2263 /* first do a trial run and see if we should use the
2264 larger text labels or not. This is so that all the
2265 labels and input controls align properly. */
2266 for (i=0; i < d->nc->n_prompts; i++) {
2267 if (d->nc->prompts[i]->prompt != NULL) {
2270 GetTextExtentPoint32(hdc,
2271 d->nc->prompts[i]->prompt,
2272 (int) wcslen(d->nc->prompts[i]->prompt),
2275 if(s.cx >= d->r_n_label.right - d->r_n_label.left) {
2276 use_large_lables = TRUE;
2282 for(i=0; i<d->nc->n_prompts; i++) {
2287 if(d->nc->prompts[i]->prompt != NULL) {
2288 GetTextExtentPoint32(hdc,
2289 d->nc->prompts[i]->prompt,
2290 (int) wcslen(d->nc->prompts[i]->prompt),
2292 if(s.cx < d->r_n_label.right - d->r_n_label.left &&
2293 !use_large_lables) {
2294 CopyRect(&pr, &d->r_n_label);
2295 CopyRect(&er, &d->r_n_input);
2296 dy = d->r_row.bottom;
2298 d->r_e_label.right - d->r_e_label.left) {
2299 CopyRect(&pr, &d->r_e_label);
2300 CopyRect(&er, &d->r_e_input);
2301 dy = d->r_row.bottom;
2303 /* oops. the prompt doesn't fit in our
2304 controls. we need to use up two lines */
2306 pr.right = d->r_row.right;
2308 pr.bottom = d->r_n_label.bottom -
2310 CopyRect(&er, &d->r_n_input);
2311 OffsetRect(&er, 0, pr.bottom);
2312 dy = er.bottom + (d->r_row.bottom -
2313 d->r_n_input.bottom);
2317 CopyRect(&er, &d->r_n_input);
2318 dy = d->r_row.bottom;
2321 if(IsRectEmpty(&pr)) {
2322 d->nc->prompts[i]->hwnd_static = NULL;
2324 OffsetRect(&pr, d->r_area.left, y);
2329 d->nc->prompts[i]->prompt,
2332 pr.right - pr.left, pr.bottom - pr.top,
2341 SendMessage(hw, WM_SETFONT,
2342 (WPARAM) hf, (LPARAM) TRUE);
2344 SetWindowPos(hw, hw_prev,
2346 SWP_NOACTIVATE | SWP_NOMOVE |
2347 SWP_NOOWNERZORDER | SWP_NOSIZE |
2350 d->nc->prompts[i]->hwnd_static = hw;
2354 OffsetRect(&er, d->r_area.left, y);
2359 (d->nc->prompts[i]->def ?
2360 d->nc->prompts[i]->def : L""),
2361 WS_CHILD | WS_TABSTOP |
2363 ((d->nc->prompts[i]->flags &
2364 KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0),
2366 er.right - er.left, er.bottom - er.top,
2376 SendMessage(hw, WM_SETFONT,
2377 (WPARAM) hf, (LPARAM) TRUE);
2379 SetWindowPos(hw, hw_prev,
2381 SWP_NOACTIVATE | SWP_NOMOVE |
2382 SWP_NOOWNERZORDER | SWP_NOSIZE |
2385 SendMessage(hw, EM_SETLIMITTEXT,
2386 KHUI_MAXCCH_PROMPT_VALUE -1,
2389 d->nc->prompts[i]->hwnd_edit = hw;
2396 if (d->nc->n_prompts > 0 &&
2397 d->nc->prompts[0]->hwnd_edit) {
2399 PostMessage(d->dlg_main, WM_NEXTDLGCTL,
2400 (WPARAM) d->nc->prompts[0]->hwnd_edit,
2401 MAKELPARAM(TRUE, 0));
2405 SelectObject(hdc, hfold);
2406 ReleaseDC(d->dlg_main, hdc);
2408 khui_cw_unlock_nc(d->nc);
2410 d->r_custprompt.bottom = y;
2412 if (d->r_custprompt.bottom == d->r_custprompt.top)
2413 SetRectEmpty(&d->r_custprompt);
2415 nc_layout_main_panel(d);
2417 nc_layout_new_cred_window(d);
2421 case WMNC_DIALOG_PROCESS_COMPLETE:
2423 khui_new_creds * nc;
2427 nc->response &= ~KHUI_NC_RESPONSE_PROCESSING;
2429 if(nc->response & KHUI_NC_RESPONSE_NOEXIT) {
2432 nc_enable_controls(d, TRUE);
2435 nc->result = KHUI_NC_RESULT_CANCEL;
2437 hw = GetDlgItem(d->dlg_main, IDOK);
2438 EnableWindow(hw, TRUE);
2439 hw = GetDlgItem(d->dlg_main, IDCANCEL);
2440 EnableWindow(hw, TRUE);
2441 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
2442 EnableWindow(hw, TRUE);
2443 hw = GetDlgItem(d->dlg_bb, IDOK);
2444 EnableWindow(hw, TRUE);
2445 hw = GetDlgItem(d->dlg_bb, IDCANCEL);
2446 EnableWindow(hw, TRUE);
2448 nc_clear_password_fields(d);
2453 DestroyWindow(hwnd);
2455 kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);
2459 /* MUST be called with SendMessage */
2460 case WMNC_ADD_CONTROL_ROW:
2462 khui_control_row * row;
2464 row = (khui_control_row *) lParam;
2471 nc_add_control_row(d, row->label, row->input, row->size);
2475 case WMNC_UPDATE_LAYOUT:
2483 /* We are already adjusting the size of the window. The
2484 next time the timer fires, it will notice if the target
2485 size has changed. */
2486 if (d->size_changing)
2489 GetClientRect(hwnd, &r_client);
2491 if ((r_client.right - r_client.left ==
2492 d->r_required.right - d->r_required.left) &&
2493 (r_client.bottom - r_client.top ==
2494 d->r_required.bottom - d->r_required.top)) {
2496 /* the window is already at the right size */
2501 if (!IsWindowVisible(hwnd)) {
2502 /* The window is not visible yet. There's no need to
2503 animate anything. */
2507 } else if (KHM_FAILED(khc_read_int32(NULL,
2508 L"CredWindow\\Windows\\NewCred\\AnimateSizeChanges",
2516 /* if we aren't animating the window resize, then we just
2517 do it in one call. */
2518 if (!animate || !d->animation_enabled) {
2521 CopyRect(&r_window, &d->r_required);
2522 AdjustWindowRectEx(&r_window, NC_WINDOW_STYLES, FALSE,
2523 NC_WINDOW_EX_STYLES);
2525 SetWindowPos(hwnd, NULL, 0, 0,
2526 r_window.right - r_window.left,
2527 r_window.bottom - r_window.top,
2528 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
2534 if (KHM_FAILED(khc_read_int32(NULL,
2535 L"CredWindow\\Windows\\NewCred\\AnimationSteps",
2540 steps = NC_SZ_STEPS_DEF;
2543 if (steps < NC_SZ_STEPS_MIN)
2544 steps = NC_SZ_STEPS_MIN;
2545 else if (steps > NC_SZ_STEPS_MAX)
2546 steps = NC_SZ_STEPS_MAX;
2550 if (KHM_FAILED(khc_read_int32(NULL,
2551 L"CredWindow\\Windows\\NewCred\\AnimationStepTimeout",
2556 timeout = NC_SZ_TIMEOUT_DEF;
2559 if (timeout < NC_SZ_TIMEOUT_MIN)
2560 timeout = NC_SZ_TIMEOUT_MIN;
2561 else if (timeout > NC_SZ_TIMEOUT_MAX)
2562 timeout = NC_SZ_TIMEOUT_MAX;
2566 CopyRect(&d->sz_ch_source, &r_client);
2567 OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
2568 CopyRect(&d->sz_ch_target, &d->r_required);
2569 OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
2570 d->sz_ch_increment = 0;
2571 d->sz_ch_max = steps;
2572 d->sz_ch_timeout = timeout;
2573 d->size_changing = TRUE;
2575 SetTimer(hwnd, NC_TIMER_SIZER, timeout, NULL);
2578 } /* switch(HIWORD(wParam)) */
2583 static LRESULT nc_handle_wm_timer(HWND hwnd,
2587 khui_nc_wnd_data * d;
2589 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2591 if (wParam == NC_TIMER_SIZER) {
2595 /* are we done with this sizing operation? */
2596 if (!d->size_changing ||
2597 d->sz_ch_increment >= d->sz_ch_max) {
2599 d->size_changing = FALSE;
2600 KillTimer(hwnd, NC_TIMER_SIZER);
2604 /* have the requirements changed while we were processing the
2605 sizing operation? */
2606 if ((d->r_required.right - d->r_required.left !=
2607 d->sz_ch_target.right)
2611 (d->r_required.bottom - d->r_required.top !=
2612 d->sz_ch_target.bottom)) {
2614 /* the target size has changed. we need to restart the
2615 sizing operation. */
2619 GetClientRect(hwnd, &r_client);
2621 CopyRect(&d->sz_ch_source, &r_client);
2622 OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
2623 CopyRect(&d->sz_ch_target, &d->r_required);
2624 OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
2625 d->sz_ch_increment = 0;
2627 /* leave the other fields alone */
2630 assert(d->sz_ch_max >= NC_SZ_STEPS_MIN);
2631 assert(d->sz_ch_max <= NC_SZ_STEPS_MAX);
2632 assert(d->sz_ch_timeout >= NC_SZ_TIMEOUT_MIN);
2633 assert(d->sz_ch_timeout <= NC_SZ_TIMEOUT_MAX);
2634 assert(d->size_changing);
2638 /* we are going to do the next increment */
2639 d->sz_ch_increment ++;
2641 /* now, figure out the size of the client area for this
2647 #define PROPORTION(v1, v2, i, s) (((v1) * ((s) - (i)) + (v2) * (i)) / (s))
2649 r_now.right = PROPORTION(d->sz_ch_source.right, d->sz_ch_target.right,
2650 d->sz_ch_increment, d->sz_ch_max);
2652 r_now.bottom = PROPORTION(d->sz_ch_source.bottom, d->sz_ch_target.bottom,
2653 d->sz_ch_increment, d->sz_ch_max);
2659 long dx = (r_now.right - d->sz_ch_target.right) *
2660 (d->sz_ch_source.right - d->sz_ch_target.right);
2662 long dy = (r_now.bottom - d->sz_ch_target.bottom) *
2663 (d->sz_ch_source.bottom - d->sz_ch_target.bottom);
2665 if (dx < 0 || dy < 0) {
2666 KillTimer(hwnd, NC_TIMER_SIZER);
2669 SetTimer(hwnd, NC_TIMER_SIZER, d->sz_ch_timeout, NULL);
2674 AdjustWindowRectEx(&r_now, NC_WINDOW_STYLES, FALSE,
2675 NC_WINDOW_EX_STYLES);
2677 SetWindowPos(hwnd, NULL,
2679 r_now.right - r_now.left,
2680 r_now.bottom - r_now.top,
2681 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
2684 /* and now we wait for the next timer message */
2687 } else if (wParam == NC_TIMER_ENABLEANIMATE) {
2689 d->animation_enabled = TRUE;
2690 KillTimer(hwnd, NC_TIMER_ENABLEANIMATE);
2696 static LRESULT nc_handle_wm_notify(HWND hwnd,
2702 khui_nc_wnd_data * d;
2704 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2705 nmhdr = (LPNMHDR) lParam;
2707 if (nmhdr->code == TCN_SELCHANGE) {
2708 /* the current tab has changed. */
2712 idx = TabCtrl_GetCurSel(d->tab_wnd);
2713 ZeroMemory(&tcitem, sizeof(tcitem));
2715 tcitem.mask = TCIF_PARAM;
2716 TabCtrl_GetItem(d->tab_wnd, idx, &tcitem);
2718 d->current_panel = (int) tcitem.lParam;
2720 nc_layout_new_cred_window(d);
2728 static LRESULT nc_handle_wm_help(HWND hwnd,
2732 static DWORD ctxids[] = {
2733 NC_TS_CTRL_ID_MIN, IDH_NC_TABMAIN,
2734 NC_TS_CTRL_ID_MIN + 1, IDH_NC_TABBUTTON,
2735 NC_TS_CTRL_ID_MIN + 2, IDH_NC_TABBUTTON,
2736 NC_TS_CTRL_ID_MIN + 3, IDH_NC_TABBUTTON,
2737 NC_TS_CTRL_ID_MIN + 4, IDH_NC_TABBUTTON,
2738 NC_TS_CTRL_ID_MIN + 5, IDH_NC_TABBUTTON,
2739 NC_TS_CTRL_ID_MIN + 6, IDH_NC_TABBUTTON,
2740 NC_TS_CTRL_ID_MIN + 7, IDH_NC_TABBUTTON,
2742 IDCANCEL, IDH_NC_CANCEL,
2743 IDC_NC_HELP, IDH_NC_HELP,
2744 IDC_NC_ADVANCED, IDH_NC_ADVANCED,
2745 IDC_NC_CREDTEXT, IDH_NC_CREDWND,
2752 khui_nc_wnd_data * d;
2754 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2756 hlp = (HELPINFO *) lParam;
2758 if (d->nc->subtype != KMSG_CRED_NEW_CREDS &&
2759 d->nc->subtype != KMSG_CRED_PASSWORD)
2762 if (hlp->iContextType != HELPINFO_WINDOW)
2765 if (hlp->hItemHandle != NULL &&
2766 hlp->hItemHandle != hwnd) {
2770 hw_ctrl =hlp->hItemHandle;
2772 id = GetWindowLong(hw_ctrl, GWL_ID);
2773 for (i=0; ctxids[i] != 0; i += 2)
2774 if (ctxids[i] == id)
2778 hw = khm_html_help(hw_ctrl,
2779 ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
2780 L"::popups_newcreds.txt":
2781 L"::popups_password.txt"),
2783 (DWORD_PTR) ctxids);
2787 khm_html_help(hwnd, NULL, HH_HELP_CONTEXT,
2788 ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
2789 IDH_ACTION_NEW_ID: IDH_ACTION_PASSWD_ID));
2795 static LRESULT CALLBACK nc_window_proc(HWND hwnd,
2802 return nc_handle_wm_create(hwnd, uMsg, wParam, lParam);
2805 return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam);
2808 return nc_handle_wm_command(hwnd, uMsg, wParam, lParam);
2811 return nc_handle_wm_notify(hwnd, uMsg, wParam, lParam);
2815 return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam);
2818 return nc_handle_wm_timer(hwnd, uMsg, wParam, lParam);
2821 return nc_handle_wm_help(hwnd, uMsg, wParam, lParam);
2823 case KHUI_WM_NC_NOTIFY:
2824 return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam);
2827 /* Note that this is technically a dialog box */
2828 return DefDlgProc(hwnd, uMsg, wParam, lParam);
2831 void khm_register_newcredwnd_class(void)
2835 wcx.cbSize = sizeof(wcx);
2836 wcx.style = CS_DBLCLKS | CS_OWNDC;
2837 wcx.lpfnWndProc = nc_window_proc;
2839 wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);
2840 wcx.hInstance = khm_hInstance;
2841 wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
2842 wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
2843 wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
2844 wcx.lpszMenuName = NULL;
2845 wcx.lpszClassName = KHUI_NEWCREDWND_CLASS;
2848 khui_newcredwnd_cls = RegisterClassEx(&wcx);
2851 void khm_unregister_newcredwnd_class(void)
2853 UnregisterClass((LPWSTR) khui_newcredwnd_cls, khm_hInstance);
2856 HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c)
2858 wchar_t wtitle[256];
2861 if (c->window_title == NULL) {
2862 if (c->subtype == KMSG_CRED_PASSWORD)
2863 LoadString(khm_hInstance,
2866 ARRAYLENGTH(wtitle));
2868 LoadString(khm_hInstance,
2871 ARRAYLENGTH(wtitle));
2874 hwnd = CreateWindowEx(NC_WINDOW_EX_STYLES,
2875 MAKEINTATOM(khui_newcredwnd_cls),
2876 ((c->window_title)?c->window_title: wtitle),
2878 0,0,400,400, /* bogus values. the window
2879 is going to resize and
2888 assert(hwnd != NULL);
2891 /* note that the window is not visible yet. That's because, at
2892 this point we don't know what the panels are */
2897 void khm_prep_newcredwnd(HWND hwnd)
2899 SendMessage(hwnd, KHUI_WM_NC_NOTIFY,
2900 MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);
2903 void khm_show_newcredwnd(HWND hwnd)
2905 /* add all the panels in and prep UI */
2906 PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
2907 MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 0);