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
33 #if _WIN32_WINNT >= 0x0501
38 ATOM khui_newcredwnd_cls;
42 nc_position_credtext(khui_nc_wnd_data * d);
44 /* Common dialog procedure used by the main credential panel
45 (IDD_NC_NEWCRED) and the button bar (IDC_NC_BBAR). */
48 nc_layout_main_panel(khui_nc_wnd_data * d);
51 nc_layout_new_cred_window(khui_nc_wnd_data * d);
53 static INT_PTR CALLBACK
54 nc_common_dlg_proc(HWND hwnd,
64 d = (khui_nc_wnd_data *) lParam;
67 #pragma warning(disable: 4244)
68 SetWindowLongPtr(hwnd, DWLP_USER, lParam);
71 if (d->nc->subtype == KMSG_CRED_PASSWORD) {
72 ShowWindow(GetDlgItem(hwnd, IDC_NC_ADVANCED),
82 ctrl_id = LOWORD(wParam);
83 if (ctrl_id < KHUI_CW_ID_MIN ||
84 ctrl_id > KHUI_CW_ID_MAX) {
85 /* pump it to the parent */
86 PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam);
88 } /* else we allow the message to fall through and get
89 passed into the identity provider's message
94 case KHUI_WM_NC_NOTIFY:
97 d = (khui_nc_wnd_data *)(LONG_PTR)
98 GetWindowLongPtr(hwnd, DWLP_USER);
102 /* message sent by parent to notify us of something */
103 switch(HIWORD(wParam)) {
104 case WMNC_DIALOG_EXPAND:
106 case WMNC_UPDATE_LAYOUT:
107 if(hwnd == d->dlg_main) {
109 nc_layout_main_panel(d);
119 /* check if we have a wnd_data, and if so pass the message on to
120 the identity provider callback. */
122 khui_nc_wnd_data * d;
124 d = (khui_nc_wnd_data *) (LONG_PTR)
125 GetWindowLongPtr(hwnd, DWLP_USER);
127 /* TODO: filter out and forward only the messages that
128 originated or pertain to the identity selection
130 if (d && d->nc && d->nc->ident_cb) {
131 return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg,
140 nc_notify_clear(khui_nc_wnd_data * d) {
142 if (d->notif_type == NC_NOTIFY_NONE)
143 /* there are no notifications anyway. */
146 if (d->hwnd_notif_label)
147 DestroyWindow(d->hwnd_notif_label);
149 if (d->hwnd_notif_aux)
150 DestroyWindow(d->hwnd_notif_aux);
152 d->hwnd_notif_label = NULL;
153 d->hwnd_notif_aux = NULL;
155 SetRectEmpty(&d->r_notif);
157 d->notif_type = NC_NOTIFY_NONE;
159 /* Note that we must call nc_layout_main_panel() after calling
160 this to adjust the layout of the main panel. However we aren't
161 calling it here since we might want to add another set of
162 notifications or make other changes to the main panel content
163 before calling nc_layout_main_panel(). */
167 nc_notify_marquee(khui_nc_wnd_data * d, const wchar_t * label) {
169 #if (_WIN32_IE >= 0x0600)
182 /* Clear the notification area. We only support one notification
190 #if (_WIN32_IE >= 0x0600)
192 /* We can only show the marquee control if the comctl32 DLL is
193 version 6.0 or later. Otherwise we only show the label. */
195 if (FAILED(StringCchLength(label, KHUI_MAXCCH_SHORT_DESC, &length))) {
199 length = KHUI_MAXCCH_SHORT_DESC;
202 /* See how big the notification control needs to be. */
204 hdc = GetDC(d->dlg_main);
209 GetTextExtentPoint32(hdc, label, (int) length, &label_size);
211 ReleaseDC(d->dlg_main, hdc);
213 CopyRect(&r_row, &d->r_row);
215 if (label_size.cx > d->r_e_label.right - d->r_e_label.left) {
216 /* using an entire row */
217 CopyRect(&r_label, &d->r_row);
218 CopyRect(&r_mq, &d->r_n_input);
219 OffsetRect(&r_mq, 0, r_row.bottom - r_row.top);
220 r_row.bottom += r_row.bottom - r_row.top;
221 } else if (label_size.cx > d->r_n_label.right - d->r_n_label.left) {
222 /* using large labels */
223 CopyRect(&r_label, &d->r_e_label);
224 CopyRect(&r_mq, &d->r_e_input);
227 CopyRect(&r_label, &d->r_n_label);
228 CopyRect(&r_mq, &d->r_n_input);
231 InflateRect(&r_mq, 0, - ((r_mq.bottom - r_mq.top) / 4));
233 #else /* _WIN32_IE < 0x0600 */
235 /* We are just showing the label */
236 CopyRect(&r_row, &d->r_row);
237 CopyRect(&r_label, &r_row);
240 #endif /* _WIN32_IE >= 0x0600 */
245 if (IsRectEmpty(&d->r_custprompt)) {
246 y = d->r_idspec.bottom;
248 y = d->r_custprompt.bottom;
251 OffsetRect(&r_row, d->r_area.left, y);
252 OffsetRect(&r_label, r_row.left, r_row.top);
253 OffsetRect(&r_mq, r_row.left, r_row.top);
256 hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
258 hdefer = BeginDeferWindowPos(2);
261 hwnd = CreateWindowEx(0,
264 WS_CHILD | SS_ENDELLIPSIS,
265 r_label.left, r_label.top,
266 r_label.right - r_label.left,
267 r_label.bottom - r_label.top,
271 assert(hwnd != NULL);
273 SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
275 DeferWindowPos(hdefer, hwnd, NULL,
277 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
278 SWP_NOSIZE | SWP_SHOWWINDOW);
280 d->hwnd_notif_label = hwnd;
282 /* and the marquee */
284 #if (_WIN32_IE >= 0x0600)
286 /* unfortunately, the marquee is only available on comctl32
287 version 6.0 or later. On previous versions, we only display
288 the message label. */
290 hwnd = CreateWindowEx(0,
293 WS_CHILD | PBS_MARQUEE,
295 r_mq.right - r_mq.left,
296 r_mq.bottom - r_mq.top,
300 assert(hwnd != NULL);
303 SendMessage(hwnd, PBM_SETMARQUEE, TRUE, 100);
305 DeferWindowPos(hdefer, hwnd, NULL,
307 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
308 SWP_NOSIZE | SWP_SHOWWINDOW);
310 d->hwnd_notif_aux = hwnd;
312 #endif /* _WIN32_IE >= 0x0600 */
314 EndDeferWindowPos(hdefer);
316 CopyRect(&d->r_notif, &r_row);
318 d->notif_type = NC_NOTIFY_MARQUEE;
320 /* Note that we must call nc_layout_main_panel() after calling
321 this to adjust the layout of the main panel. However we aren't
322 calling it here since we might want to add another set of
323 notifications or make other changes to the main panel content
324 before calling nc_layout_main_panel(). */
328 nc_notify_message(khui_nc_wnd_data * d,
329 kherr_severity severity,
330 const wchar_t * message) {
345 icon_size.cx = GetSystemMetrics(SM_CXSMICON);
346 icon_size.cy = GetSystemMetrics(SM_CYSMICON);
350 icon_res = MAKEINTRESOURCE(OIC_INFORMATION);
354 icon_res = MAKEINTRESOURCE(OIC_WARNING);
358 icon_res = MAKEINTRESOURCE(OIC_ERROR);
365 if (icon_res != NULL) {
366 h_icon = (HICON) LoadImage(NULL,
371 LR_DEFAULTCOLOR | LR_SHARED);
376 CopyRect(&r_row, &d->r_row);
378 #define CENTERVALUE(w,v) ((w)/2 - (v)/2)
381 0, CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy),
383 CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy) + icon_size.cy);
387 CopyRect(&r_label, &r_row);
388 OffsetRect(&r_label, -r_label.left, -r_label.top);
389 r_label.left += (icon_size.cx * 3) / 2;
394 if (IsRectEmpty(&d->r_custprompt)) {
395 y = d->r_idspec.bottom;
397 y = d->r_custprompt.bottom;
400 OffsetRect(&r_row, d->r_area.left, y);
401 OffsetRect(&r_label, r_row.left, r_row.top);
402 OffsetRect(&r_icon, r_row.left, r_row.top);
405 hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
407 hdefer = BeginDeferWindowPos(2);
409 hwnd = CreateWindowEx(0,
412 WS_CHILD | SS_ENDELLIPSIS | SS_CENTER,
413 r_label.left, r_label.top,
414 r_label.right - r_label.left,
415 r_label.bottom - r_label.top,
419 assert(hwnd != NULL);
421 SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
423 DeferWindowPos(hdefer, hwnd, NULL,
425 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
426 SWP_NOSIZE | SWP_SHOWWINDOW);
428 d->hwnd_notif_label = hwnd;
430 hwnd = CreateWindowEx(0,
434 #if (_WIN32_IE >= 0x0600)
440 r_icon.left, r_icon.top,
441 r_icon.right - r_icon.left,
442 r_icon.bottom - r_icon.top,
446 assert(hwnd != NULL);
450 SendMessage(hwnd, STM_SETICON, (WPARAM) h_icon, 0);
452 DeferWindowPos(hdefer, hwnd, NULL,
454 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
455 SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOZORDER);
457 d->hwnd_notif_aux = hwnd;
459 EndDeferWindowPos(hdefer);
461 CopyRect(&d->r_notif, &r_row);
463 d->notif_type = NC_NOTIFY_MESSAGE;
465 /* Note that we must call nc_layout_main_panel() after calling
466 this to adjust the layout of the main panel. However we aren't
467 calling it here since we might want to add another set of
468 notifications or make other changes to the main panel content
469 before calling nc_layout_main_panel(). */
473 nc_layout_main_panel(khui_nc_wnd_data * d)
479 RECT r_used; /* extent used by identity specifiers,
480 custom prompts and notificaiton
483 RECT r_wmain; /* extents of the main window in screen
488 r_main.bottom = NCDLG_HEIGHT;
489 r_main.right = NCDLG_WIDTH;
491 MapDialogRect(d->dlg_main, &r_main);
493 CopyRect(&r_used, &d->r_idspec);
495 GetWindowRect(d->dlg_main, &r_wmain);
497 hdwp = BeginDeferWindowPos(7);
499 /* check if the notification area and the custom prompt area are
502 if (d->notif_type != NC_NOTIFY_NONE) {
506 CopyRect(&r, &d->r_custprompt);
508 if (IsRectEmpty(&d->r_custprompt)) {
509 /* if there are no custom prompts, then the notification
510 area should be immediately below the identitify
513 delta_y = d->r_idspec.bottom - d->r_notif.top;
515 /* otherwise, the notification area should be immediately
516 below the custom prompt area */
518 delta_y = d->r_custprompt.bottom - d->r_notif.top;
525 if (d->hwnd_notif_label) {
526 GetWindowRect(d->hwnd_notif_label, &r_lbl);
527 OffsetRect(&r_lbl, -r_wmain.left, delta_y - r_wmain.top);
529 DeferWindowPos(hdwp, d->hwnd_notif_label, NULL,
530 r_lbl.left, r_lbl.top, 0, 0,
531 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
532 SWP_NOZORDER | SWP_NOSIZE);
535 if (d->hwnd_notif_aux) {
536 GetWindowRect(d->hwnd_notif_aux, &r_aux);
537 OffsetRect(&r_aux, -r_wmain.left, delta_y - r_wmain.top);
539 DeferWindowPos(hdwp, d->hwnd_notif_aux, NULL,
540 r_aux.left, r_aux.top, 0, 0,
541 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
542 SWP_NOZORDER | SWP_NOSIZE);
545 OffsetRect(&d->r_notif, 0, delta_y);
549 if (!IsRectEmpty(&d->r_custprompt)) {
550 r_used.bottom = max(d->r_custprompt.bottom,
554 if (!IsRectEmpty(&d->r_notif)) {
555 r_used.bottom = max(d->r_notif.bottom,
559 if (d->nc->mode == KHUI_NC_MODE_MINI) {
565 hw = GetDlgItem(d->dlg_main, IDOK);
569 GetWindowRect(hw, &r_ok);
570 OffsetRect(&r_ok, -r_wmain.left, -r_ok.top + r_used.bottom);
572 DeferWindowPos(hdwp, hw, NULL,
573 r_ok.left, r_ok.top, 0, 0,
574 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
575 SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
577 hw = GetDlgItem(d->dlg_main, IDCANCEL);
581 GetWindowRect(hw, &r_cancel);
582 OffsetRect(&r_cancel, -r_wmain.left, -r_cancel.top + r_used.bottom);
584 DeferWindowPos(hdwp, hw, NULL,
585 r_cancel.left, r_cancel.top, 0, 0,
586 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
587 SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
589 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
593 GetWindowRect(hw, &r_advanced);
594 OffsetRect(&r_advanced, -r_wmain.left, -r_advanced.top + r_used.bottom);
596 DeferWindowPos(hdwp, hw, NULL,
597 r_advanced.left, r_advanced.top, 0, 0,
598 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
599 SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
601 /* and now update the extents of the main panel */
602 r_main.bottom = r_used.bottom + (r_ok.bottom - r_ok.top) + d->r_area.top;
604 CopyRect(&d->r_main, &r_main);
610 hw = GetDlgItem(d->dlg_main, IDOK);
614 if (IsWindowVisible(hw))
615 DeferWindowPos(hdwp, hw, NULL,
617 SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
618 SWP_NOOWNERZORDER | SWP_NOZORDER);
620 hw = GetDlgItem(d->dlg_main, IDCANCEL);
624 if (IsWindowVisible(hw))
625 DeferWindowPos(hdwp, hw, NULL,
627 SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
628 SWP_NOOWNERZORDER | SWP_NOZORDER);
630 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
634 if (IsWindowVisible(hw))
635 DeferWindowPos(hdwp, hw, NULL,
637 SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
638 SWP_NOOWNERZORDER | SWP_NOZORDER);
640 d->r_credtext.top = r_used.bottom;
642 CopyRect(&d->r_main, &r_main);
645 /* now update the layout of the credentials text window */
647 hw_ct = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);
648 hw_ct_label = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);
650 assert(hw_ct != NULL);
651 assert(hw_ct_label != NULL);
654 if (d->nc->mode == KHUI_NC_MODE_MINI ||
655 d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {
657 /* either we aren't supposed to show the credentials text
658 window, or we don't have enough room. */
659 if (IsWindowVisible(hw_ct) || IsWindowVisible(hw_ct_label)) {
661 DeferWindowPos(hdwp, hw_ct, NULL,
663 SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
664 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
666 DeferWindowPos(hdwp, hw_ct_label, NULL,
668 SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
669 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
677 d->r_credtext.left + d->r_n_input.left, /* x */
678 d->r_credtext.top, /* y */
679 d->r_n_input.right - d->r_n_input.left, /* width */
680 d->r_credtext.bottom - d->r_credtext.top, /* height */
681 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
682 SWP_NOZORDER | SWP_SHOWWINDOW);
686 d->r_credtext.left + d->r_n_label.left, /* x */
687 d->r_credtext.top, /* y */
688 d->r_n_label.right - d->r_n_label.left, /* width */
689 d->r_n_label.bottom - d->r_n_label.top, /* height */
690 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
691 SWP_NOZORDER | SWP_SHOWWINDOW);
694 EndDeferWindowPos(hdwp);
696 /* NOTE: although we updated d->r_main, if the new credentials
697 window is in mini mode, we must call
698 nc_layout_new_cred_window() to adjust the size of the new
699 credentials window to fit the main panel. We don't do it here
700 because we need to keep these two operations separate. */
703 /* Credential type panel comparison function. Tabs are sorted based
704 on the following criteria:
706 1) By ordinal - Panels with ordinal -1 will be ranked after panels
707 whose ordinal is not -1.
709 2) By name - Case insensitive comparison of the name. If the panel
710 does not have a name (i.e. the ->name member is NULL, it will be
711 ranked after panels which have a name.
714 nc_tab_sort_func(const void * v1, const void * v2)
716 /* v1 and v2 and of type : khui_new_creds_by_type ** */
717 khui_new_creds_by_type *t1, *t2;
719 t1 = *((khui_new_creds_by_type **) v1);
720 t2 = *((khui_new_creds_by_type **) v2);
722 if(t1->ordinal != -1) {
723 if(t2->ordinal != -1) {
724 if(t1->ordinal == t2->ordinal) {
725 if (t1->name && t2->name)
726 return _wcsicmp(t1->name, t2->name);
734 /* safe to convert to an int here */
735 return (int) (t1->ordinal - t2->ordinal);
740 if(t2->ordinal != -1)
742 else if (t1->name && t2->name)
743 return wcscmp(t1->name, t2->name);
754 nc_notify_types(khui_new_creds * c, UINT uMsg,
755 WPARAM wParam, LPARAM lParam, BOOL sync)
759 for(i=0; i<c->n_types; i++) {
761 if (c->types[i]->hwnd_panel == NULL)
765 SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
767 PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
772 nc_clear_password_fields(khui_nc_wnd_data * d)
775 khm_boolean need_sync = FALSE;
777 khui_cw_lock_nc(d->nc);
779 for (i=0; i < d->nc->n_prompts; i++) {
780 if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) &&
781 d->nc->prompts[i]->hwnd_edit) {
782 SetWindowText(d->nc->prompts[i]->hwnd_edit,
788 khui_cw_unlock_nc(d->nc);
791 khui_cw_sync_prompt_values(d->nc);
795 /* used by nc_enable_controls */
797 struct nc_enum_wnd_data {
798 khui_nc_wnd_data * d;
804 nc_enum_wnd_proc(HWND hwnd,
807 struct nc_enum_wnd_data * wd;
809 wd = (struct nc_enum_wnd_data *) lParam;
811 EnableWindow(hwnd, wd->enable);
817 nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable)
819 struct nc_enum_wnd_data wd;
821 ZeroMemory(&wd, sizeof(wd));
826 EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd);
829 #define NC_MAXCCH_CREDTEXT 16384
830 #define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))
833 nc_update_credtext(khui_nc_wnd_data * d)
835 wchar_t * ctbuf = NULL;
837 BOOL okEnable = FALSE;
838 BOOL validId = FALSE;
842 ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);
844 assert(ctbuf != NULL);
846 LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);
847 StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);
849 nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
850 MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc, TRUE);
852 /* hopefully all the types have updated their credential texts */
854 /* if the dialog is in the mini mode, we have to display
855 exceptions using a notification. */
856 if (d->nc->mode == KHUI_NC_MODE_MINI) {
857 BOOL need_layout = FALSE;
858 if (d->nc->n_identities == 0) {
860 /* There are no identities selected. We don't show any
861 notifications here. */
862 if (d->notif_type != NC_NOTIFY_NONE) {
869 wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
871 wchar_t msg[ARRAYLENGTH(format) + ARRAYLENGTH(id_name)];
875 kcdb_identity_get_flags(d->nc->identities[0], &flags);
877 cbbuf = sizeof(id_name);
878 kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
880 if (flags & KCDB_IDENT_FLAG_INVALID) {
882 /* identity is invalid */
883 LoadString(khm_hInstance, IDS_NCN_IDENT_INVALID,
884 format, ARRAYLENGTH(format));
885 StringCbPrintf(msg, sizeof(msg), format, id_name);
887 nc_notify_message(d, KHERR_ERROR, msg);
891 } else if ((flags & KCDB_IDENT_FLAG_VALID) ||
892 d->nc->subtype == KMSG_CRED_PASSWORD) {
893 /* special case: If we are going to change the
894 password, we don't expect the identity provider to
895 validate the identity in real time. As such, we
896 assume that the identity is valid. */
898 /* identity is valid */
899 if (d->notif_type != NC_NOTIFY_NONE) {
904 } else if (flags & KCDB_IDENT_FLAG_UNKNOWN) {
907 LoadString(khm_hInstance, IDS_NCN_IDENT_UNKNOWN,
908 format, ARRAYLENGTH(format));
909 StringCbPrintf(msg, sizeof(msg), format, id_name);
911 nc_notify_message(d, KHERR_WARNING, msg);
918 LoadString(khm_hInstance, IDS_NCN_IDENT_CHECKING,
919 format, ARRAYLENGTH(format));
920 StringCbPrintf(msg, sizeof(msg), format, id_name);
922 nc_notify_marquee(d, msg);
930 nc_layout_main_panel(d);
931 nc_layout_new_cred_window(d);
935 if(d->nc->n_identities == 1) {
936 wchar_t main_fmt[256];
938 wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
939 wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
943 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE,
944 main_fmt, (int) ARRAYLENGTH(main_fmt));
946 cbbuf = sizeof(id_name);
947 kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
949 kcdb_identity_get_flags(d->nc->identities[0], &flags);
951 if (flags & KCDB_IDENT_FLAG_INVALID) {
952 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
953 id_fmt, (int) ARRAYLENGTH(id_fmt));
954 } else if(flags & KCDB_IDENT_FLAG_VALID) {
955 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
956 id_fmt, (int) ARRAYLENGTH(id_fmt));
957 } else if(flags & KCDB_IDENT_FLAG_UNKNOWN) {
958 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
959 id_fmt, (int) ARRAYLENGTH(id_fmt));
960 } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {
961 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING,
962 id_fmt, (int) ARRAYLENGTH(id_fmt));
964 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
965 id_fmt, (int) ARRAYLENGTH(id_fmt));
968 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
970 StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
971 main_fmt, id_string);
973 if (flags & KCDB_IDENT_FLAG_VALID) {
974 if (flags & KCDB_IDENT_FLAG_DEFAULT)
975 LoadString(khm_hInstance, IDS_NC_ID_DEF,
976 id_string, ARRAYLENGTH(id_string));
977 else if (d->nc->set_default)
978 LoadString(khm_hInstance, IDS_NC_ID_WDEF,
979 id_string, ARRAYLENGTH(id_string));
981 LoadString(khm_hInstance, IDS_NC_ID_NDEF,
982 id_string, ARRAYLENGTH(id_string));
984 StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t),
988 } else if(d->nc->n_identities > 1) {
990 khm_size cb_ids_string;
992 wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
994 wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
996 wchar_t main_fmt[256];
999 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY,
1000 main_fmt, (int) ARRAYLENGTH(main_fmt));
1002 /* we are going to concatenate all the identity names into
1003 a comma separated string */
1005 /* d->nc->n_identities is at least 2 */
1006 ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
1007 (d->nc->n_identities - 1));
1009 (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
1010 (d->nc->n_identities - 1);
1012 assert(ids_string != NULL);
1020 for(i=1; i<d->nc->n_identities; i++) {
1022 StringCbCat(ids_string, cb_ids_string, L",");
1027 cbbuf = sizeof(id_name);
1028 kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);
1029 kcdb_identity_get_flags(d->nc->identities[i], &flags);
1030 if(flags & KCDB_IDENT_FLAG_INVALID) {
1031 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
1032 id_fmt, (int) ARRAYLENGTH(id_fmt));
1033 } else if(flags & KCDB_IDENT_FLAG_VALID) {
1034 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
1035 id_fmt, (int) ARRAYLENGTH(id_fmt));
1037 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
1038 id_fmt, (int) ARRAYLENGTH(id_fmt));
1041 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
1042 StringCbCat(ids_string, cb_ids_string, id_string);
1045 cbbuf = sizeof(id_name);
1046 kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
1047 kcdb_identity_get_flags(d->nc->identities[0], &flags);
1048 if(flags & KCDB_IDENT_FLAG_INVALID) {
1049 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
1050 id_fmt, (int) ARRAYLENGTH(id_fmt));
1051 } else if(flags & KCDB_IDENT_FLAG_VALID) {
1052 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
1053 id_fmt, (int) ARRAYLENGTH(id_fmt));
1055 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
1056 id_fmt, (int) ARRAYLENGTH(id_fmt));
1058 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
1060 StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
1061 main_fmt, id_string, ids_string);
1066 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE,
1067 buf, (int)(NC_MAXCCH_CREDTEXT - cch));
1070 /* now, append the credtext string from each of the cred types */
1076 cb = NC_MAXCB_CREDTEXT;
1079 for(i=0; i<d->nc->n_types; i++) {
1080 if(d->nc->types[i]->credtext != NULL) {
1081 StringCbCatEx(buf, cb,
1082 d->nc->types[i]->credtext,
1089 SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);
1093 /* so depending on whether the primary identity was found to be
1094 invalid, we need to disable the Ok button and set the title to
1097 if(d->nc->n_identities > 0) {
1098 khm_int32 flags = 0;
1100 if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0],
1102 (flags & KCDB_IDENT_FLAG_VALID)) {
1107 if (d->nc->window_title == NULL) {
1109 wchar_t wpostfix[256];
1110 wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];
1113 cbsize = sizeof(wtitle);
1114 kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);
1116 if (d->nc->subtype == KMSG_CRED_PASSWORD)
1117 LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,
1118 wpostfix, (int) ARRAYLENGTH(wpostfix));
1120 LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS,
1121 wpostfix, (int) ARRAYLENGTH(wpostfix));
1123 StringCbCat(wtitle, sizeof(wtitle), wpostfix);
1125 SetWindowText(d->nc->hwnd, wtitle);
1127 wchar_t wtitle[256];
1129 if (d->nc->subtype == KMSG_CRED_PASSWORD)
1130 LoadString(khm_hInstance, IDS_WT_PASSWORD,
1131 wtitle, (int) ARRAYLENGTH(wtitle));
1133 LoadString(khm_hInstance, IDS_WT_NEW_CREDS,
1134 wtitle, (int) ARRAYLENGTH(wtitle));
1136 SetWindowText(d->nc->hwnd, wtitle);
1140 if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) {
1142 d->nc->subtype == KMSG_CRED_PASSWORD) {
1143 /* TODO: check if all the required fields have valid values
1144 before enabling the Ok button */
1148 hw = GetDlgItem(d->dlg_main, IDOK);
1149 EnableWindow(hw, okEnable);
1150 hw = GetDlgItem(d->dlg_bb, IDOK);
1151 EnableWindow(hw, okEnable);
1156 nc_layout_new_cred_window(khui_nc_wnd_data * ncd) {
1166 r_main.right = NCDLG_WIDTH;
1167 r_main.bottom = NCDLG_HEIGHT;
1169 MapDialogRect(ncd->dlg_main, &r_main);
1171 hdefer = BeginDeferWindowPos(5);
1173 if (c->mode == KHUI_NC_MODE_MINI) {
1175 if (IsWindowVisible(ncd->tab_wnd)) {
1176 DeferWindowPos(hdefer,
1180 SWP_NOMOVE | SWP_NOOWNERZORDER |
1181 SWP_NOSIZE | SWP_NOZORDER);
1184 if (IsWindowVisible(ncd->dlg_bb)) {
1185 DeferWindowPos(hdefer,
1189 SWP_NOMOVE | SWP_NOOWNERZORDER |
1190 SWP_NOSIZE | SWP_NOZORDER);
1193 DeferWindowPos(hdefer, ncd->dlg_main, NULL,
1194 r_main.left, r_main.top,
1195 r_main.right - r_main.left,
1196 r_main.bottom - r_main.top,
1197 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1198 SWP_NOZORDER | SWP_SHOWWINDOW);
1200 /* note that the ncd->r_main.bottom may not be the same as
1201 r_main.bottom because ncd->r_main.bottom is set dynamically
1202 depending on custom controls. ncd->r_main is valid only
1203 once nc_layout_main_panel() is called.*/
1204 CopyRect(&ncd->r_required, &ncd->r_main);
1212 /* calculate the size of the tab control so that it fits
1213 snugly around the expanded main panel. */
1214 CopyRect(&r_tabctrl, &r_main);
1215 TabCtrl_AdjustRect(ncd->tab_wnd, TRUE, &r_tabctrl);
1217 if (r_tabctrl.left < 0 ||
1218 r_tabctrl.top < 0) {
1220 OffsetRect(&r_tabctrl,
1221 (r_tabctrl.left < 0)? -r_tabctrl.left : 0,
1222 (r_tabctrl.top < 0)? -r_tabctrl.top : 0);
1227 assert(r_tabctrl.left == 0);
1228 assert(r_tabctrl.top == 0);
1231 OffsetRect(&r_tabctrl, 0, ncd->r_area.top);
1233 /* and now calculate the rectangle where the main panel should
1234 be inside the tab control. */
1235 CopyRect(&r_displayarea, &r_tabctrl);
1236 TabCtrl_AdjustRect(ncd->tab_wnd, FALSE, &r_displayarea);
1238 DeferWindowPos(hdefer,
1239 ncd->tab_wnd, HWND_BOTTOM,
1240 r_tabctrl.left, r_tabctrl.top,
1241 r_tabctrl.right - r_tabctrl.left,
1242 r_tabctrl.bottom - r_tabctrl.top,
1243 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1246 /* we have to place the button bar just to the right of the
1250 r_bbar.right = NCDLG_BBAR_WIDTH;
1251 r_bbar.bottom = NCDLG_BBAR_HEIGHT;
1253 MapDialogRect(ncd->dlg_main, &r_bbar);
1255 OffsetRect(&r_bbar, r_tabctrl.right, 0);
1257 DeferWindowPos(hdefer,
1259 r_bbar.left, r_bbar.top,
1260 r_bbar.right - r_bbar.left,
1261 r_bbar.bottom - r_bbar.top,
1262 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1263 SWP_NOZORDER | SWP_SHOWWINDOW);
1265 /* move the main panel inside the tab control... */
1266 DeferWindowPos(hdefer,
1267 ncd->dlg_main, NULL,
1268 r_displayarea.left, r_displayarea.top,
1269 r_displayarea.right - r_displayarea.left,
1270 r_displayarea.bottom - r_displayarea.top,
1271 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1273 (ncd->current_panel == 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
1275 /* and also move all the credential type panels (if they have
1276 been created) inside the tab control too. */
1279 for (i=0; i < c->n_types; i++) {
1280 if (c->types[i]->hwnd_panel != NULL) {
1281 DeferWindowPos(hdefer,
1282 c->types[i]->hwnd_panel, NULL,
1283 r_displayarea.left, r_displayarea.top,
1284 r_displayarea.right - r_displayarea.left,
1285 r_displayarea.bottom - r_displayarea.top,
1286 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1288 (ncd->current_panel == c->types[i]->ordinal ?
1289 SWP_SHOWWINDOW : SWP_HIDEWINDOW));
1293 khui_cw_unlock_nc(c);
1295 /* then update the required size of the new credentials
1297 ncd->r_required.left = 0;
1298 ncd->r_required.top = 0;
1299 ncd->r_required.right = r_bbar.right;
1300 ncd->r_required.bottom = max(r_tabctrl.bottom, r_bbar.bottom) + ncd->r_area.top;
1303 /* commit all the window moves, resizes and hides/shows we did*/
1304 EndDeferWindowPos(hdefer);
1306 /* now we have to see if the client area of the new credentials
1307 window is the right size. */
1309 GetClientRect(c->hwnd, &r_ncdialog);
1313 ((r_ncdialog.right - r_ncdialog.left !=
1314 ncd->r_required.right - ncd->r_required.left)
1318 (r_ncdialog.bottom - r_ncdialog.top !=
1319 ncd->r_required.bottom - ncd->r_required.top))
1323 /* we don't bother if the new creds window is already in the
1324 process of changing the size. */
1325 !ncd->size_changing) {
1327 /* if not, notify the window that the size needs adjusting. */
1328 if (IsWindowVisible(c->hwnd))
1329 PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
1330 MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
1332 SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
1333 MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
1337 #define CW_PARAM DWLP_USER
1340 nc_handle_wm_create(HWND hwnd,
1347 khui_nc_wnd_data * ncd;
1353 lpc = (LPCREATESTRUCT) lParam;
1355 ncd = PMALLOC(sizeof(*ncd));
1356 ZeroMemory(ncd, sizeof(*ncd));
1358 c = (khui_new_creds *) lpc->lpCreateParams;
1363 assert(c->subtype == KMSG_CRED_NEW_CREDS ||
1364 c->subtype == KMSG_CRED_PASSWORD);
1367 #pragma warning(push)
1368 #pragma warning(disable: 4244)
1369 SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);
1370 #pragma warning(pop)
1372 /* first, create the tab control that will house the main dialog
1373 panel as well as the plug-in specific panels */
1374 ncd->tab_wnd = CreateWindowEx(0, /* extended style */
1376 L"TabControloxxrz", /* window name */
1377 TCS_HOTTRACK | TCS_RAGGEDRIGHT |
1378 TCS_SINGLELINE | TCS_TABS |
1379 WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS,
1380 0, 0, 100, 100, /* x,y,width height.
1385 (HMENU) IDC_NC_TABS,
1390 assert(ncd->tab_wnd != NULL);
1393 /* try to create the main dialog panel */
1395 ncd->dlg_main = CreateDialogParam(khm_hInstance,
1396 MAKEINTRESOURCE(IDD_NC_NEWCRED),
1401 assert(ncd->dlg_main != NULL);
1404 hf_main = (HFONT) SendMessage(ncd->dlg_main, WM_GETFONT, 0, 0);
1406 SendMessage(ncd->tab_wnd, WM_SETFONT, (WPARAM) hf_main, FALSE);
1408 #if _WIN32_WINNT >= 0x0501
1409 EnableThemeDialogTexture(ncd->dlg_main,
1419 /* During the operation of the new credentials window, we will
1420 need to dynamically change the layout of the controls as a
1421 result of custom prompting from credentials providers and
1422 identity selectors from identity providers. In order to
1423 guide the dynamic layout, we pick out a few metrics from
1424 the dialog template for the main panel. The metrics come
1425 from hidden STATIC controls in the dialog template. */
1427 GetWindowRect(ncd->dlg_main, &r_main);
1429 /* IDC_NC_TPL_PANEL spans the full extent of the dialog that
1430 we can populate with custom controls. */
1431 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL);
1435 GetWindowRect(hw, &r_area);
1436 OffsetRect(&r_area,-r_main.left, -r_main.top);
1437 CopyRect(&ncd->r_area, &r_area);
1439 /* IDC_NC_TPL_ROW spans the extent of a row of normal sized
1440 custom controls. A row of custom controls typicall consist
1441 of a text label and an input control. */
1442 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW);
1446 GetWindowRect(hw, &r);
1447 CopyRect(&r_row, &r);
1448 OffsetRect(&r,-r.left, -r.top);
1449 CopyRect(&ncd->r_row, &r);
1451 /* IDC_NC_TPL_LABEL spans the extent that a normal sized
1452 label. The control overlaps IDC_NC_TPL_ROW so we can get
1453 coordinates relative to the row extents. */
1454 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL);
1458 GetWindowRect(hw, &r);
1459 OffsetRect(&r,-r_row.left, -r_row.top);
1460 CopyRect(&ncd->r_n_label, &r);
1462 /* IDC_NC_TPL_INPUT spans the extent of a normal sized input
1463 control in a custom control row. The control overlaps
1464 IDC_NC_TPL_ROW so we can get relative coordinates. */
1465 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT);
1469 GetWindowRect(hw, &r);
1470 OffsetRect(&r, -r_row.left, -r_row.top);
1471 CopyRect(&ncd->r_n_input, &r);
1473 /* IDC_NC_TPL_ROW_LG spans the extent of a row of large sized
1475 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG);
1479 GetWindowRect(hw, &r_row);
1481 /* IDC_NC_TPL_LABEL_LG is a large sized label. The control
1482 overlaps IDC_NC_TPL_ROW_LG. */
1483 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG);
1487 GetWindowRect(hw, &r);
1488 OffsetRect(&r, -r_row.left, -r_row.top);
1489 CopyRect(&ncd->r_e_label, &r);
1491 /* IDC_NC_TPL_INPUT_LG is a large sized input control.
1492 Overlaps IDC_NC_TPL_ROW_LG. */
1493 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG);
1497 GetWindowRect(hw, &r);
1498 OffsetRect(&r, -r_row.left, -r_row.top);
1499 CopyRect(&ncd->r_e_input, &r);
1501 CopyRect(&ncd->r_credtext, &ncd->r_area);
1502 CopyRect(&ncd->r_idspec, &ncd->r_area);
1504 ncd->r_idspec.bottom = ncd->r_idspec.top;
1506 /* And finally the credential text window. The only metric we
1507 take from here is the Y coordinate of the bottom of the
1508 control since the actual size and position of the
1509 credentials window will change depending on the custom
1510 controls being displayed. */
1511 hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT);
1515 GetWindowRect(hw, &r);
1516 OffsetRect(&r, -r_main.left, -r_main.top);
1517 ncd->r_credtext.bottom = r.bottom;
1520 /* if the mode is 'mini'*/
1524 if(c->mode == KHUI_NC_MODE_MINI) {
1525 r.right = NCDLG_WIDTH;
1526 r.bottom = NCDLG_HEIGHT;
1528 r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;
1529 r.bottom = NCDLG_BBAR_HEIGHT;
1532 MapDialogRect(ncd->dlg_main, &r);
1534 /* position the new credentials dialog */
1535 width = r.right - r.left;
1536 height = r.bottom - r.top;
1538 /* adjust width and height to accomodate NC area */
1542 GetWindowRect(hwnd, &wr);
1543 GetClientRect(hwnd, &cr);
1545 /* the non-client and client areas have already been calculated
1546 at this point. We just use the difference to adjust the width
1548 width += (wr.right - wr.left) - (cr.right - cr.left);
1549 height += (wr.bottom - wr.top) - (cr.bottom - cr.top);
1552 /* if the parent window is visible, we center the new credentials
1553 dialog over the parent. Otherwise, we center it on the primary
1556 if (IsWindowVisible(lpc->hwndParent)) {
1557 GetWindowRect(lpc->hwndParent, &r);
1559 if(!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &r, 0)) {
1560 /* failover to the window coordinates */
1561 GetWindowRect(lpc->hwndParent, &r);
1564 x = (r.right + r.left)/2 - width / 2;
1565 y = (r.top + r.bottom)/2 - height / 2;
1567 MoveWindow(hwnd, x, y, width, height, FALSE);
1569 ncd->dlg_bb = CreateDialogParam(khm_hInstance,
1570 MAKEINTRESOURCE(IDD_NC_BBAR),
1576 assert(ncd->dlg_bb);
1579 /* Call the identity provider callback to set the identity
1580 selector controls. These controls need to be there before we
1581 layout the main panel. */
1582 c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main);
1584 if (c->mode == KHUI_NC_MODE_EXPANDED) {
1585 SendMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY,
1586 MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
1588 /* we don't call nc_layout_main_panel() if the dialog is
1589 expanded because posting WMNC_DIALOG_EXPAND to the main
1590 panel results in it getting called anyway. */
1591 nc_layout_main_panel(ncd);
1594 nc_layout_new_cred_window(ncd);
1596 /* add this to the dialog chain */
1597 khm_add_dialog(hwnd);
1602 /* add a control row supplied by an identity provider */
1604 nc_add_control_row(khui_nc_wnd_data * d,
1607 khui_control_size size)
1615 hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
1616 SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);
1617 SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);
1619 CopyRect(&r_row, &d->r_row);
1620 OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);
1622 if (size == KHUI_CTRLSIZE_SMALL) {
1623 CopyRect(&r_label, &d->r_n_label);
1624 CopyRect(&r_input, &d->r_n_input);
1625 OffsetRect(&r_label, r_row.left, r_row.top);
1626 OffsetRect(&r_input, r_row.left, r_row.top);
1627 } else if (size == KHUI_CTRLSIZE_HALF) {
1628 CopyRect(&r_label, &d->r_e_label);
1629 CopyRect(&r_input, &d->r_e_input);
1630 OffsetRect(&r_label, r_row.left, r_row.top);
1631 OffsetRect(&r_input, r_row.left, r_row.top);
1632 } else if (size == KHUI_CTRLSIZE_FULL) {
1633 CopyRect(&r_label, &d->r_n_label);
1634 r_label.right = d->r_row.right;
1635 CopyRect(&r_input, &d->r_n_input);
1636 OffsetRect(&r_input, r_row.left, r_row.top);
1637 OffsetRect(&r_input, 0, r_input.bottom);
1638 r_row.bottom += r_input.bottom;
1639 OffsetRect(&r_label, r_row.left, r_row.top);
1641 SetRectEmpty(&r_label);
1642 SetRectEmpty(&r_input);
1649 hdefer = BeginDeferWindowPos(2);
1652 DeferWindowPos(hdefer, label,
1653 ((d->hwnd_last_idspec != NULL)?
1654 d->hwnd_last_idspec:
1656 r_label.left, r_label.top,
1657 r_label.right - r_label.left,
1658 r_label.bottom - r_label.top,
1659 SWP_NOACTIVATE | SWP_NOOWNERZORDER);
1662 DeferWindowPos(hdefer, input,
1663 (label ? label : ((d->hwnd_last_idspec != NULL)?
1664 d->hwnd_last_idspec:
1666 r_input.left, r_input.top,
1667 r_input.right - r_input.left,
1668 r_input.bottom - r_input.top,
1669 SWP_NOACTIVATE | SWP_NOOWNERZORDER);
1671 EndDeferWindowPos(hdefer);
1673 d->hwnd_last_idspec = (input ? input : label);
1675 d->r_idspec.bottom = r_row.bottom;
1677 /* we don't update the layout of the main panel yet, since these
1678 control additions happen before the main panel is displayed. A
1679 call to nc_layout_main_panel() will be made before the main
1680 panel is shown anyway. */
1686 nc_handle_wm_destroy(HWND hwnd,
1691 khui_nc_wnd_data * d;
1693 /* remove self from dialog chain */
1694 khm_del_dialog(hwnd);
1696 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1700 d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);
1702 if (d->hwnd_notif_label)
1703 DestroyWindow(d->hwnd_notif_label);
1704 if (d->hwnd_notif_aux)
1705 DestroyWindow(d->hwnd_notif_aux);
1708 DestroyWindow(d->dlg_bb);
1710 DestroyWindow(d->dlg_main);
1716 SetWindowLongPtr(hwnd, CW_PARAM, 0);
1722 nc_handle_wm_command(HWND hwnd,
1727 khui_nc_wnd_data * d;
1729 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1733 switch(HIWORD(wParam)) {
1735 switch(LOWORD(wParam)) {
1738 d->nc->result = KHUI_NC_RESULT_PROCESS;
1743 /* the default value for d->nc->result is set to
1744 KHUI_NC_RESULT_CANCEL */
1745 d->nc->response = KHUI_NC_RESPONSE_PROCESSING;
1747 nc_enable_controls(d, FALSE);
1749 nc_notify_types(d->nc,
1751 MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS),
1755 khui_cw_sync_prompt_values(d->nc);
1757 khm_cred_dispatch_process_message(d->nc);
1759 /* we won't know whether to abort or not until we get
1760 feedback from the plugins, even if the command was
1765 hw = GetDlgItem(d->dlg_main, IDOK);
1766 EnableWindow(hw, FALSE);
1767 hw = GetDlgItem(d->dlg_main, IDCANCEL);
1768 EnableWindow(hw, FALSE);
1769 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
1770 EnableWindow(hw, FALSE);
1771 hw = GetDlgItem(d->dlg_bb, IDOK);
1772 EnableWindow(hw, FALSE);
1773 hw = GetDlgItem(d->dlg_bb, IDCANCEL);
1774 EnableWindow(hw, FALSE);
1779 khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID);
1783 case IDC_NC_ADVANCED:
1784 /* the Options button in the main window was clicked. we
1785 respond by expanding the dialog. */
1786 PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
1787 MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
1790 case IDC_NC_CREDTEXT: /* credtext link activated */
1792 khui_htwnd_link * l;
1793 wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];
1794 wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];
1797 l = (khui_htwnd_link *) lParam;
1799 /* do we have a valid link? */
1800 if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))
1801 return TRUE; /* nope */
1803 StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);
1804 sid[l->id_len] = L'\0'; /* just make sure */
1806 if(l->param != NULL &&
1807 l->param_len < ARRAYLENGTH(sparam) &&
1810 StringCchCopyN(sparam, ARRAYLENGTH(sparam),
1811 l->param, l->param_len);
1812 sparam[l->param_len] = L'\0';
1818 /* If the ID is of the form '<credtype>:<link_tag>'
1819 and <credtype> is a valid name of a credentials
1820 type that is participating in the credentials
1821 acquisition process, then we forward the message to
1822 the panel that is providing the UI for that cred
1823 type. We also switch to that panel first, unless
1824 the link is of the form '<credtype>:!<link_tag>'. */
1826 colon = wcschr(sid, L':');
1827 if (colon != NULL) {
1829 khui_new_creds_by_type * t;
1832 if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&
1833 KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){
1836 if (t->ordinal != d->current_panel &&
1837 *(colon + 1) != L'!')
1840 MAKEWPARAM(t->ordinal,
1841 WMNC_DIALOG_SWITCH_PANEL),
1844 return SendMessage(t->hwnd_panel,
1846 MAKEWPARAM(0, WMNC_CREDTEXT_LINK),
1853 /* if it was for us, then we need to process the message */
1854 if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {
1856 khui_new_creds_by_type * t;
1858 if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam,
1860 KHM_SUCCEEDED(khui_cw_find_type(d->nc,
1862 if (t->ordinal != d->current_panel)
1865 MAKEWPARAM(t->ordinal,
1866 WMNC_DIALOG_SWITCH_PANEL),
1869 } else if (!_wcsicmp(sid, L"NotDef")) {
1870 d->nc->set_default = FALSE;
1871 nc_update_credtext(d);
1872 } else if (!_wcsicmp(sid, L"MakeDef")) {
1873 d->nc->set_default = TRUE;
1874 nc_update_credtext(d);
1880 case NC_BN_SET_DEF_ID:
1882 d->nc->set_default =
1883 (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID)
1895 static LRESULT nc_handle_wm_moving(HWND hwnd,
1900 khui_nc_wnd_data * d;
1902 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1906 nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
1907 MAKEWPARAM(0, WMNC_DIALOG_MOVE), (LPARAM) d->nc, TRUE);
1912 static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
1917 khui_nc_wnd_data * d;
1920 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1924 switch(HIWORD(wParam)) {
1926 case WMNC_DIALOG_SWITCH_PANEL:
1927 id = LOWORD(wParam);
1928 if(id >= 0 && id <= (int) d->nc->n_types) {
1929 /* one of the tab buttons were pressed */
1930 if(d->current_panel == id) {
1931 return TRUE; /* nothing to do */
1934 d->current_panel = id;
1936 TabCtrl_SetCurSel(d->tab_wnd, id);
1939 if(d->nc->mode == KHUI_NC_MODE_EXPANDED) {
1940 nc_layout_new_cred_window(d);
1946 case WMNC_DIALOG_EXPAND:
1947 /* we are switching from basic to advanced or vice versa */
1949 if (d->nc->mode == KHUI_NC_MODE_EXPANDED) {
1951 if (d->current_panel != 0) {
1952 d->current_panel = 0;
1953 TabCtrl_SetCurSel(d->tab_wnd, 0);
1954 nc_layout_new_cred_window(d);
1957 d->nc->mode = KHUI_NC_MODE_MINI;
1959 d->nc->mode = KHUI_NC_MODE_EXPANDED;
1962 /* if we are switching to the advanced mode, we clear any
1963 notifications because we now have a credential text area
1965 if (d->nc->mode == KHUI_NC_MODE_EXPANDED)
1968 nc_layout_main_panel(d);
1970 nc_layout_new_cred_window(d);
1974 case WMNC_DIALOG_SETUP:
1976 if(d->nc->n_types > 0) {
1978 for(i=0; i < d->nc->n_types;i++) {
1980 if (d->nc->types[i]->dlg_proc == NULL) {
1981 d->nc->types[i]->hwnd_panel = NULL;
1983 /* Create the dialog panel */
1984 d->nc->types[i]->hwnd_panel =
1985 CreateDialogParam(d->nc->types[i]->h_module,
1986 d->nc->types[i]->dlg_template,
1988 d->nc->types[i]->dlg_proc,
1992 assert(d->nc->types[i]->hwnd_panel);
1994 #if _WIN32_WINNT >= 0x0501
1995 if (d->nc->types[i]->hwnd_panel) {
1996 EnableThemeDialogTexture(d->nc->types[i]->hwnd_panel,
2006 case WMNC_DIALOG_ACTIVATE:
2008 wchar_t wname[KCDB_MAXCCH_NAME];
2012 /* About to activate the window. We should add all the
2013 panels to the tab control. */
2016 assert(d->tab_wnd != NULL);
2019 ZeroMemory(&tabitem, sizeof(tabitem));
2021 tabitem.mask = TCIF_PARAM | TCIF_TEXT;
2023 LoadString(khm_hInstance, IDS_NC_IDENTITY,
2024 wname, ARRAYLENGTH(wname));
2026 tabitem.pszText = wname;
2027 tabitem.lParam = 0; /* ordinal */
2029 TabCtrl_InsertItem(d->tab_wnd, 0, &tabitem);
2031 khui_cw_lock_nc(d->nc);
2033 if(d->nc->n_types > 0) {
2036 /* We should sort the tabs first. See
2037 nc_tab_sort_func() for sort criteria. */
2040 sizeof(*(d->nc->types)),
2043 for(i=0; i < d->nc->n_types;i++) {
2045 d->nc->types[i]->ordinal = i + 1;
2047 if(d->nc->types[i]->name)
2048 tabitem.pszText = d->nc->types[i]->name;
2052 cbsize = sizeof(wname);
2055 (kcdb_credtype_describe
2056 (d->nc->types[i]->type,
2068 tabitem.pszText = wname;
2072 tabitem.lParam = d->nc->types[i]->ordinal;
2074 TabCtrl_InsertItem(d->tab_wnd, d->nc->types[i]->ordinal,
2079 khui_cw_unlock_nc(d->nc);
2081 nc_update_credtext(d);
2083 TabCtrl_SetCurSel(d->tab_wnd, 0); /* the first selected
2087 /* we don't enable animations until a specific timeout
2088 elapses after showing the window. We don't need to
2089 animate any size changes if the user has barely had a
2090 chance to notice the original size. This prevents the
2091 new cred window from appearing in an animated state. */
2092 SetTimer(hwnd, NC_TIMER_ENABLEANIMATE, ENABLEANIMATE_TIMEOUT, NULL);
2094 ShowWindow(hwnd, SW_SHOWNORMAL);
2096 /* bring the window to the top, if necessary */
2097 if (KHM_SUCCEEDED(khc_read_int32(NULL,
2098 L"CredWindow\\Windows\\NewCred\\ForceToTop",
2105 /* it used to be that the above condition also called
2106 !khm_is_dialog_active() to find out whether there
2107 was a dialog active. If there was, we wouldn't try
2108 to bring the new cred window to the foreground. But
2109 that was not the behavior we want. */
2111 /* if the main window is not visible, then the SetWindowPos()
2112 call is sufficient to bring the new creds window to the
2113 top. However, if the main window is visible but not
2114 active, the main window needs to be activated before a
2115 child window can be activated. */
2117 SetActiveWindow(hwnd);
2119 sfw = SetForegroundWindow(hwnd);
2124 ZeroMemory(&fi, sizeof(fi));
2126 fi.cbSize = sizeof(fi);
2128 fi.dwFlags = FLASHW_ALL;
2130 fi.dwTimeout = 0; /* use the default cursor blink rate */
2134 d->flashing_enabled = TRUE;
2141 if (d->nc->n_identities == 0)
2147 case WMNC_IDENTITY_CHANGE:
2149 BOOL okEnable = FALSE;
2151 nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
2152 MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), (LPARAM) d->nc,
2155 if (d->nc->subtype == KMSG_CRED_NEW_CREDS &&
2156 d->nc->n_identities > 0 &&
2157 d->nc->identities[0]) {
2160 kcdb_identity_get_flags(d->nc->identities[0], &f);
2162 if (!(f & KCDB_IDENT_FLAG_DEFAULT)) {
2163 d->nc->set_default = FALSE;
2167 nc_update_credtext(d);
2172 case WMNC_TYPE_STATE:
2174 case WMNC_UPDATE_CREDTEXT:
2175 nc_update_credtext(d);
2178 case WMNC_CLEAR_PROMPTS:
2182 khui_cw_lock_nc(d->nc);
2184 if(d->hwnd_banner != NULL) {
2185 DestroyWindow(d->hwnd_banner);
2186 d->hwnd_banner = NULL;
2189 if(d->hwnd_name != NULL) {
2190 DestroyWindow(d->hwnd_name);
2191 d->hwnd_name = NULL;
2194 for(i=0;i<d->nc->n_prompts;i++) {
2195 if(!(d->nc->prompts[i]->flags &
2196 KHUI_NCPROMPT_FLAG_STOCK)) {
2197 if(d->nc->prompts[i]->hwnd_static != NULL)
2198 DestroyWindow(d->nc->prompts[i]->hwnd_static);
2200 if(d->nc->prompts[i]->hwnd_edit != NULL)
2201 DestroyWindow(d->nc->prompts[i]->hwnd_edit);
2204 d->nc->prompts[i]->hwnd_static = NULL;
2205 d->nc->prompts[i]->hwnd_edit = NULL;
2208 khui_cw_unlock_nc(d->nc);
2210 SetRectEmpty(&d->r_custprompt);
2212 nc_layout_main_panel(d);
2214 nc_layout_new_cred_window(d);
2218 case WMNC_SET_PROMPTS:
2225 BOOL use_large_lables = FALSE;
2227 /* we assume that WMNC_CLEAR_PROMPTS has already been
2231 assert(IsRectEmpty(&d->r_custprompt));
2234 khui_cw_lock_nc(d->nc);
2237 /* special case, we have one prompt and it is a password
2238 prompt. very common */
2239 if(d->nc->n_prompts == 1 &&
2240 d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
2242 hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);
2243 EnableWindow(hw, TRUE);
2245 d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;
2246 d->nc->prompts[0]->hwnd_edit = hw;
2247 d->nc->prompts[0]->hwnd_static = NULL; /* don't care */
2249 khui_cw_unlock_nc(d->nc);
2253 /* for everything else */
2255 y = d->r_idspec.bottom;
2257 d->r_custprompt.left = d->r_area.left;
2258 d->r_custprompt.right = d->r_area.right;
2259 d->r_custprompt.top = y;
2261 hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
2263 if (d->nc->pname != NULL) {
2269 SS_SUNKEN | WS_CHILD,
2272 d->r_n_label.bottom - d->r_n_label.top,
2282 SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);
2283 ShowWindow(hw, SW_SHOW);
2285 y += d->r_n_label.bottom - d->r_n_label.top;
2288 if (d->nc->banner != NULL) {
2296 d->r_row.right, d->r_row.bottom,
2304 d->hwnd_banner = hw;
2305 SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);
2306 ShowWindow(hw, SW_SHOW);
2307 y += d->r_row.bottom;
2310 hw_prev = d->hwnd_last_idspec;
2312 hdc = GetWindowDC(d->dlg_main);
2313 hfold = SelectObject(hdc,hf);
2315 /* first do a trial run and see if we should use the
2316 larger text labels or not. This is so that all the
2317 labels and input controls align properly. */
2318 for (i=0; i < d->nc->n_prompts; i++) {
2319 if (d->nc->prompts[i]->prompt != NULL) {
2322 GetTextExtentPoint32(hdc,
2323 d->nc->prompts[i]->prompt,
2324 (int) wcslen(d->nc->prompts[i]->prompt),
2327 if(s.cx >= d->r_n_label.right - d->r_n_label.left) {
2328 use_large_lables = TRUE;
2334 for(i=0; i<d->nc->n_prompts; i++) {
2339 if(d->nc->prompts[i]->prompt != NULL) {
2340 GetTextExtentPoint32(hdc,
2341 d->nc->prompts[i]->prompt,
2342 (int) wcslen(d->nc->prompts[i]->prompt),
2344 if(s.cx < d->r_n_label.right - d->r_n_label.left &&
2345 !use_large_lables) {
2346 CopyRect(&pr, &d->r_n_label);
2347 CopyRect(&er, &d->r_n_input);
2348 dy = d->r_row.bottom;
2350 d->r_e_label.right - d->r_e_label.left) {
2351 CopyRect(&pr, &d->r_e_label);
2352 CopyRect(&er, &d->r_e_input);
2353 dy = d->r_row.bottom;
2355 /* oops. the prompt doesn't fit in our
2356 controls. we need to use up two lines */
2358 pr.right = d->r_row.right;
2360 pr.bottom = d->r_n_label.bottom -
2362 CopyRect(&er, &d->r_n_input);
2363 OffsetRect(&er, 0, pr.bottom);
2364 dy = er.bottom + (d->r_row.bottom -
2365 d->r_n_input.bottom);
2369 CopyRect(&er, &d->r_n_input);
2370 dy = d->r_row.bottom;
2373 if(IsRectEmpty(&pr)) {
2374 d->nc->prompts[i]->hwnd_static = NULL;
2376 OffsetRect(&pr, d->r_area.left, y);
2381 d->nc->prompts[i]->prompt,
2384 pr.right - pr.left, pr.bottom - pr.top,
2393 SendMessage(hw, WM_SETFONT,
2394 (WPARAM) hf, (LPARAM) TRUE);
2396 SetWindowPos(hw, hw_prev,
2398 SWP_NOACTIVATE | SWP_NOMOVE |
2399 SWP_NOOWNERZORDER | SWP_NOSIZE |
2402 d->nc->prompts[i]->hwnd_static = hw;
2406 OffsetRect(&er, d->r_area.left, y);
2411 (d->nc->prompts[i]->def ?
2412 d->nc->prompts[i]->def : L""),
2413 WS_CHILD | WS_TABSTOP |
2415 ((d->nc->prompts[i]->flags &
2416 KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0),
2418 er.right - er.left, er.bottom - er.top,
2428 SendMessage(hw, WM_SETFONT,
2429 (WPARAM) hf, (LPARAM) TRUE);
2431 SetWindowPos(hw, hw_prev,
2433 SWP_NOACTIVATE | SWP_NOMOVE |
2434 SWP_NOOWNERZORDER | SWP_NOSIZE |
2437 SendMessage(hw, EM_SETLIMITTEXT,
2438 KHUI_MAXCCH_PROMPT_VALUE -1,
2441 d->nc->prompts[i]->hwnd_edit = hw;
2448 if (d->nc->n_prompts > 0 &&
2449 d->nc->prompts[0]->hwnd_edit) {
2451 PostMessage(d->dlg_main, WM_NEXTDLGCTL,
2452 (WPARAM) d->nc->prompts[0]->hwnd_edit,
2453 MAKELPARAM(TRUE, 0));
2457 SelectObject(hdc, hfold);
2458 ReleaseDC(d->dlg_main, hdc);
2460 khui_cw_unlock_nc(d->nc);
2462 d->r_custprompt.bottom = y;
2464 if (d->r_custprompt.bottom == d->r_custprompt.top)
2465 SetRectEmpty(&d->r_custprompt);
2467 nc_layout_main_panel(d);
2469 nc_layout_new_cred_window(d);
2473 case WMNC_DIALOG_PROCESS_COMPLETE:
2475 khui_new_creds * nc;
2479 nc->response &= ~KHUI_NC_RESPONSE_PROCESSING;
2481 if(nc->response & KHUI_NC_RESPONSE_NOEXIT) {
2484 nc_enable_controls(d, TRUE);
2487 nc->result = KHUI_NC_RESULT_CANCEL;
2489 hw = GetDlgItem(d->dlg_main, IDOK);
2490 EnableWindow(hw, TRUE);
2491 hw = GetDlgItem(d->dlg_main, IDCANCEL);
2492 EnableWindow(hw, TRUE);
2493 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
2494 EnableWindow(hw, TRUE);
2495 hw = GetDlgItem(d->dlg_bb, IDOK);
2496 EnableWindow(hw, TRUE);
2497 hw = GetDlgItem(d->dlg_bb, IDCANCEL);
2498 EnableWindow(hw, TRUE);
2500 nc_clear_password_fields(d);
2505 DestroyWindow(hwnd);
2507 kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);
2511 /* MUST be called with SendMessage */
2512 case WMNC_ADD_CONTROL_ROW:
2514 khui_control_row * row;
2516 row = (khui_control_row *) lParam;
2523 nc_add_control_row(d, row->label, row->input, row->size);
2527 case WMNC_UPDATE_LAYOUT:
2535 /* We are already adjusting the size of the window. The
2536 next time the timer fires, it will notice if the target
2537 size has changed. */
2538 if (d->size_changing)
2541 GetClientRect(hwnd, &r_client);
2543 if ((r_client.right - r_client.left ==
2544 d->r_required.right - d->r_required.left) &&
2545 (r_client.bottom - r_client.top ==
2546 d->r_required.bottom - d->r_required.top)) {
2548 /* the window is already at the right size */
2553 if (!IsWindowVisible(hwnd)) {
2554 /* The window is not visible yet. There's no need to
2555 animate anything. */
2559 } else if (KHM_FAILED(khc_read_int32(NULL,
2560 L"CredWindow\\Windows\\NewCred\\AnimateSizeChanges",
2568 /* if we aren't animating the window resize, then we just
2569 do it in one call. */
2570 if (!animate || !d->animation_enabled) {
2573 CopyRect(&r_window, &d->r_required);
2574 AdjustWindowRectEx(&r_window, NC_WINDOW_STYLES, FALSE,
2575 NC_WINDOW_EX_STYLES);
2577 SetWindowPos(hwnd, NULL, 0, 0,
2578 r_window.right - r_window.left,
2579 r_window.bottom - r_window.top,
2580 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
2586 if (KHM_FAILED(khc_read_int32(NULL,
2587 L"CredWindow\\Windows\\NewCred\\AnimationSteps",
2592 steps = NC_SZ_STEPS_DEF;
2595 if (steps < NC_SZ_STEPS_MIN)
2596 steps = NC_SZ_STEPS_MIN;
2597 else if (steps > NC_SZ_STEPS_MAX)
2598 steps = NC_SZ_STEPS_MAX;
2602 if (KHM_FAILED(khc_read_int32(NULL,
2603 L"CredWindow\\Windows\\NewCred\\AnimationStepTimeout",
2608 timeout = NC_SZ_TIMEOUT_DEF;
2611 if (timeout < NC_SZ_TIMEOUT_MIN)
2612 timeout = NC_SZ_TIMEOUT_MIN;
2613 else if (timeout > NC_SZ_TIMEOUT_MAX)
2614 timeout = NC_SZ_TIMEOUT_MAX;
2618 CopyRect(&d->sz_ch_source, &r_client);
2619 OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
2620 CopyRect(&d->sz_ch_target, &d->r_required);
2621 OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
2622 d->sz_ch_increment = 0;
2623 d->sz_ch_max = steps;
2624 d->sz_ch_timeout = timeout;
2625 d->size_changing = TRUE;
2627 SetTimer(hwnd, NC_TIMER_SIZER, timeout, NULL);
2630 } /* switch(HIWORD(wParam)) */
2635 static LRESULT nc_handle_wm_timer(HWND hwnd,
2639 khui_nc_wnd_data * d;
2641 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2645 if (wParam == NC_TIMER_SIZER) {
2649 /* are we done with this sizing operation? */
2650 if (!d->size_changing ||
2651 d->sz_ch_increment >= d->sz_ch_max) {
2653 d->size_changing = FALSE;
2654 KillTimer(hwnd, NC_TIMER_SIZER);
2658 /* have the requirements changed while we were processing the
2659 sizing operation? */
2660 if ((d->r_required.right - d->r_required.left !=
2661 d->sz_ch_target.right)
2665 (d->r_required.bottom - d->r_required.top !=
2666 d->sz_ch_target.bottom)) {
2668 /* the target size has changed. we need to restart the
2669 sizing operation. */
2673 GetClientRect(hwnd, &r_client);
2675 CopyRect(&d->sz_ch_source, &r_client);
2676 OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
2677 CopyRect(&d->sz_ch_target, &d->r_required);
2678 OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
2679 d->sz_ch_increment = 0;
2681 /* leave the other fields alone */
2684 assert(d->sz_ch_max >= NC_SZ_STEPS_MIN);
2685 assert(d->sz_ch_max <= NC_SZ_STEPS_MAX);
2686 assert(d->sz_ch_timeout >= NC_SZ_TIMEOUT_MIN);
2687 assert(d->sz_ch_timeout <= NC_SZ_TIMEOUT_MAX);
2688 assert(d->size_changing);
2692 /* we are going to do the next increment */
2693 d->sz_ch_increment ++;
2695 /* now, figure out the size of the client area for this
2701 #define PROPORTION(v1, v2, i, s) (((v1) * ((s) - (i)) + (v2) * (i)) / (s))
2703 r_now.right = PROPORTION(d->sz_ch_source.right, d->sz_ch_target.right,
2704 d->sz_ch_increment, d->sz_ch_max);
2706 r_now.bottom = PROPORTION(d->sz_ch_source.bottom, d->sz_ch_target.bottom,
2707 d->sz_ch_increment, d->sz_ch_max);
2713 long dx = (r_now.right - d->sz_ch_target.right) *
2714 (d->sz_ch_source.right - d->sz_ch_target.right);
2716 long dy = (r_now.bottom - d->sz_ch_target.bottom) *
2717 (d->sz_ch_source.bottom - d->sz_ch_target.bottom);
2719 if (dx < 0 || dy < 0) {
2720 KillTimer(hwnd, NC_TIMER_SIZER);
2723 SetTimer(hwnd, NC_TIMER_SIZER, d->sz_ch_timeout, NULL);
2728 AdjustWindowRectEx(&r_now, NC_WINDOW_STYLES, FALSE,
2729 NC_WINDOW_EX_STYLES);
2731 SetWindowPos(hwnd, NULL,
2733 r_now.right - r_now.left,
2734 r_now.bottom - r_now.top,
2735 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
2738 /* and now we wait for the next timer message */
2741 } else if (wParam == NC_TIMER_ENABLEANIMATE) {
2743 d->animation_enabled = TRUE;
2744 KillTimer(hwnd, NC_TIMER_ENABLEANIMATE);
2750 static LRESULT nc_handle_wm_notify(HWND hwnd,
2756 khui_nc_wnd_data * d;
2758 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2762 nmhdr = (LPNMHDR) lParam;
2764 if (nmhdr->code == TCN_SELCHANGE) {
2765 /* the current tab has changed. */
2769 idx = TabCtrl_GetCurSel(d->tab_wnd);
2770 ZeroMemory(&tcitem, sizeof(tcitem));
2772 tcitem.mask = TCIF_PARAM;
2773 TabCtrl_GetItem(d->tab_wnd, idx, &tcitem);
2775 d->current_panel = (int) tcitem.lParam;
2777 nc_layout_new_cred_window(d);
2785 static LRESULT nc_handle_wm_help(HWND hwnd,
2789 static DWORD ctxids[] = {
2790 NC_TS_CTRL_ID_MIN, IDH_NC_TABMAIN,
2791 NC_TS_CTRL_ID_MIN + 1, IDH_NC_TABBUTTON,
2792 NC_TS_CTRL_ID_MIN + 2, IDH_NC_TABBUTTON,
2793 NC_TS_CTRL_ID_MIN + 3, IDH_NC_TABBUTTON,
2794 NC_TS_CTRL_ID_MIN + 4, IDH_NC_TABBUTTON,
2795 NC_TS_CTRL_ID_MIN + 5, IDH_NC_TABBUTTON,
2796 NC_TS_CTRL_ID_MIN + 6, IDH_NC_TABBUTTON,
2797 NC_TS_CTRL_ID_MIN + 7, IDH_NC_TABBUTTON,
2799 IDCANCEL, IDH_NC_CANCEL,
2800 IDC_NC_HELP, IDH_NC_HELP,
2801 IDC_NC_ADVANCED, IDH_NC_ADVANCED,
2802 IDC_NC_CREDTEXT, IDH_NC_CREDWND,
2809 khui_nc_wnd_data * d;
2811 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2815 hlp = (HELPINFO *) lParam;
2817 if (d->nc->subtype != KMSG_CRED_NEW_CREDS &&
2818 d->nc->subtype != KMSG_CRED_PASSWORD)
2821 if (hlp->iContextType != HELPINFO_WINDOW)
2824 if (hlp->hItemHandle != NULL &&
2825 hlp->hItemHandle != hwnd) {
2829 hw_ctrl =hlp->hItemHandle;
2831 id = GetWindowLong(hw_ctrl, GWL_ID);
2832 for (i=0; ctxids[i] != 0; i += 2)
2833 if (ctxids[i] == id)
2837 hw = khm_html_help(hw_ctrl,
2838 ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
2839 L"::popups_newcreds.txt":
2840 L"::popups_password.txt"),
2842 (DWORD_PTR) ctxids);
2846 khm_html_help(hwnd, NULL, HH_HELP_CONTEXT,
2847 ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
2848 IDH_ACTION_NEW_ID: IDH_ACTION_PASSWD_ID));
2854 static LRESULT nc_handle_wm_activate(HWND hwnd,
2858 if (uMsg == WM_MOUSEACTIVATE ||
2859 wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) {
2862 khui_nc_wnd_data * d;
2865 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2867 if (d && d->flashing_enabled) {
2868 ZeroMemory(&fi, sizeof(fi));
2870 fi.cbSize = sizeof(fi);
2872 fi.dwFlags = FLASHW_STOP;
2876 d->flashing_enabled = FALSE;
2879 ex_style = GetWindowLongPtr(hwnd, GWL_EXSTYLE);
2881 if (ex_style & WS_EX_TOPMOST) {
2882 SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
2883 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
2887 return (uMsg == WM_MOUSEACTIVATE)? MA_ACTIVATE : 0;
2890 static LRESULT CALLBACK nc_window_proc(HWND hwnd,
2896 case WM_MOUSEACTIVATE:
2898 return nc_handle_wm_activate(hwnd, uMsg, wParam, lParam);
2901 return nc_handle_wm_create(hwnd, uMsg, wParam, lParam);
2904 return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam);
2907 return nc_handle_wm_command(hwnd, uMsg, wParam, lParam);
2910 return nc_handle_wm_notify(hwnd, uMsg, wParam, lParam);
2914 return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam);
2917 return nc_handle_wm_timer(hwnd, uMsg, wParam, lParam);
2920 return nc_handle_wm_help(hwnd, uMsg, wParam, lParam);
2922 case KHUI_WM_NC_NOTIFY:
2923 return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam);
2926 /* Note that this is technically a dialog box */
2927 return DefDlgProc(hwnd, uMsg, wParam, lParam);
2930 void khm_register_newcredwnd_class(void)
2934 wcx.cbSize = sizeof(wcx);
2935 wcx.style = CS_DBLCLKS | CS_OWNDC;
2936 wcx.lpfnWndProc = nc_window_proc;
2938 wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);
2939 wcx.hInstance = khm_hInstance;
2940 wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
2941 wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
2942 wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
2943 wcx.lpszMenuName = NULL;
2944 wcx.lpszClassName = KHUI_NEWCREDWND_CLASS;
2947 khui_newcredwnd_cls = RegisterClassEx(&wcx);
2950 void khm_unregister_newcredwnd_class(void)
2952 UnregisterClass((LPWSTR) khui_newcredwnd_cls, khm_hInstance);
2955 HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c)
2957 wchar_t wtitle[256];
2959 khm_int32 force_topmost = 0;
2961 if (c->window_title == NULL) {
2962 if (c->subtype == KMSG_CRED_PASSWORD)
2963 LoadString(khm_hInstance,
2966 ARRAYLENGTH(wtitle));
2968 LoadString(khm_hInstance,
2971 ARRAYLENGTH(wtitle));
2974 khc_read_int32(NULL, L"CredWindow\\Windows\\NewCred\\ForceToTop", &force_topmost);
2976 hwnd = CreateWindowEx(NC_WINDOW_EX_STYLES | (force_topmost ? WS_EX_TOPMOST : 0),
2977 MAKEINTATOM(khui_newcredwnd_cls),
2978 ((c->window_title)?c->window_title: wtitle),
2980 0,0,400,400, /* bogus values. the window
2981 is going to resize and
2990 assert(hwnd != NULL);
2993 /* note that the window is not visible yet. That's because, at
2994 this point we don't know what the panels are */
2999 void khm_prep_newcredwnd(HWND hwnd)
3001 SendMessage(hwnd, KHUI_WM_NC_NOTIFY,
3002 MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);
3005 void khm_show_newcredwnd(HWND hwnd)
3007 /* add all the panels in and prep UI */
3008 PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
3009 MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 0);