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);
99 /* message sent by parent to notify us of something */
100 switch(HIWORD(wParam)) {
101 case WMNC_DIALOG_EXPAND:
103 case WMNC_UPDATE_LAYOUT:
104 if(hwnd == d->dlg_main) {
106 nc_layout_main_panel(d);
116 /* check if we have a wnd_data, and if so pass the message on to
117 the identity provider callback. */
119 khui_nc_wnd_data * d;
121 d = (khui_nc_wnd_data *) (LONG_PTR)
122 GetWindowLongPtr(hwnd, DWLP_USER);
124 /* TODO: filter out and forward only the messages that
125 originated or pertain to the identity selection
127 if (d && d->nc && d->nc->ident_cb) {
128 return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg,
137 nc_notify_clear(khui_nc_wnd_data * d) {
139 if (d->notif_type == NC_NOTIFY_NONE)
140 /* there are no notifications anyway. */
143 if (d->hwnd_notif_label)
144 DestroyWindow(d->hwnd_notif_label);
146 if (d->hwnd_notif_aux)
147 DestroyWindow(d->hwnd_notif_aux);
149 d->hwnd_notif_label = NULL;
150 d->hwnd_notif_aux = NULL;
152 SetRectEmpty(&d->r_notif);
154 d->notif_type = NC_NOTIFY_NONE;
156 /* Note that we must call nc_layout_main_panel() after calling
157 this to adjust the layout of the main panel. However we aren't
158 calling it here since we might want to add another set of
159 notifications or make other changes to the main panel content
160 before calling nc_layout_main_panel(). */
164 nc_notify_marquee(khui_nc_wnd_data * d, const wchar_t * label) {
166 #if (_WIN32_IE >= 0x0600)
179 /* Clear the notification area. We only support one notification
187 #if (_WIN32_IE >= 0x0600)
189 /* We can only show the marquee control if the comctl32 DLL is
190 version 6.0 or later. Otherwise we only show the label. */
192 if (FAILED(StringCchLength(label, KHUI_MAXCCH_SHORT_DESC, &length))) {
196 length = KHUI_MAXCCH_SHORT_DESC;
199 /* See how big the notification control needs to be. */
201 hdc = GetDC(d->dlg_main);
206 GetTextExtentPoint32(hdc, label, (int) length, &label_size);
208 ReleaseDC(d->dlg_main, hdc);
210 CopyRect(&r_row, &d->r_row);
212 if (label_size.cx > d->r_e_label.right - d->r_e_label.left) {
213 /* using an entire row */
214 CopyRect(&r_label, &d->r_row);
215 CopyRect(&r_mq, &d->r_n_input);
216 OffsetRect(&r_mq, 0, r_row.bottom - r_row.top);
217 r_row.bottom += r_row.bottom - r_row.top;
218 } else if (label_size.cx > d->r_n_label.right - d->r_n_label.left) {
219 /* using large labels */
220 CopyRect(&r_label, &d->r_e_label);
221 CopyRect(&r_mq, &d->r_e_input);
224 CopyRect(&r_label, &d->r_n_label);
225 CopyRect(&r_mq, &d->r_n_input);
228 InflateRect(&r_mq, 0, - ((r_mq.bottom - r_mq.top) / 4));
230 #else /* _WIN32_IE < 0x0600 */
232 /* We are just showing the label */
233 CopyRect(&r_row, &d->r_row);
234 CopyRect(&r_label, &r_row);
237 #endif /* _WIN32_IE >= 0x0600 */
242 if (IsRectEmpty(&d->r_custprompt)) {
243 y = d->r_idspec.bottom;
245 y = d->r_custprompt.bottom;
248 OffsetRect(&r_row, d->r_area.left, y);
249 OffsetRect(&r_label, r_row.left, r_row.top);
250 OffsetRect(&r_mq, r_row.left, r_row.top);
253 hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
255 hdefer = BeginDeferWindowPos(2);
258 hwnd = CreateWindowEx(0,
261 WS_CHILD | SS_ENDELLIPSIS,
262 r_label.left, r_label.top,
263 r_label.right - r_label.left,
264 r_label.bottom - r_label.top,
268 assert(hwnd != NULL);
270 SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
272 DeferWindowPos(hdefer, hwnd, NULL,
274 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
275 SWP_NOSIZE | SWP_SHOWWINDOW);
277 d->hwnd_notif_label = hwnd;
279 /* and the marquee */
281 #if (_WIN32_IE >= 0x0600)
283 /* unfortunately, the marquee is only available on comctl32
284 version 6.0 or later. On previous versions, we only display
285 the message label. */
287 hwnd = CreateWindowEx(0,
290 WS_CHILD | PBS_MARQUEE,
292 r_mq.right - r_mq.left,
293 r_mq.bottom - r_mq.top,
297 assert(hwnd != NULL);
300 SendMessage(hwnd, PBM_SETMARQUEE, TRUE, 100);
302 DeferWindowPos(hdefer, hwnd, NULL,
304 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
305 SWP_NOSIZE | SWP_SHOWWINDOW);
307 d->hwnd_notif_aux = hwnd;
309 #endif /* _WIN32_IE >= 0x0600 */
311 EndDeferWindowPos(hdefer);
313 CopyRect(&d->r_notif, &r_row);
315 d->notif_type = NC_NOTIFY_MARQUEE;
317 /* Note that we must call nc_layout_main_panel() after calling
318 this to adjust the layout of the main panel. However we aren't
319 calling it here since we might want to add another set of
320 notifications or make other changes to the main panel content
321 before calling nc_layout_main_panel(). */
325 nc_notify_message(khui_nc_wnd_data * d,
326 kherr_severity severity,
327 const wchar_t * message) {
342 icon_size.cx = GetSystemMetrics(SM_CXSMICON);
343 icon_size.cy = GetSystemMetrics(SM_CYSMICON);
347 icon_res = MAKEINTRESOURCE(OIC_INFORMATION);
351 icon_res = MAKEINTRESOURCE(OIC_WARNING);
355 icon_res = MAKEINTRESOURCE(OIC_ERROR);
362 if (icon_res != NULL) {
363 h_icon = (HICON) LoadImage(NULL,
368 LR_DEFAULTCOLOR | LR_SHARED);
373 CopyRect(&r_row, &d->r_row);
375 #define CENTERVALUE(w,v) ((w)/2 - (v)/2)
378 0, CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy),
380 CENTERVALUE(r_row.bottom - r_row.top, icon_size.cy) + icon_size.cy);
384 CopyRect(&r_label, &r_row);
385 OffsetRect(&r_label, -r_label.left, -r_label.top);
386 r_label.left += (icon_size.cx * 3) / 2;
391 if (IsRectEmpty(&d->r_custprompt)) {
392 y = d->r_idspec.bottom;
394 y = d->r_custprompt.bottom;
397 OffsetRect(&r_row, d->r_area.left, y);
398 OffsetRect(&r_label, r_row.left, r_row.top);
399 OffsetRect(&r_icon, r_row.left, r_row.top);
402 hfont = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
404 hdefer = BeginDeferWindowPos(2);
406 hwnd = CreateWindowEx(0,
409 WS_CHILD | SS_ENDELLIPSIS | SS_CENTER,
410 r_label.left, r_label.top,
411 r_label.right - r_label.left,
412 r_label.bottom - r_label.top,
416 assert(hwnd != NULL);
418 SendMessage(hwnd, WM_SETFONT, (WPARAM) hfont, (LPARAM) TRUE);
420 DeferWindowPos(hdefer, hwnd, NULL,
422 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
423 SWP_NOSIZE | SWP_SHOWWINDOW);
425 d->hwnd_notif_label = hwnd;
427 hwnd = CreateWindowEx(0,
431 #if (_WIN32_IE >= 0x0600)
437 r_icon.left, r_icon.top,
438 r_icon.right - r_icon.left,
439 r_icon.bottom - r_icon.top,
443 assert(hwnd != NULL);
447 SendMessage(hwnd, STM_SETICON, (WPARAM) h_icon, 0);
449 DeferWindowPos(hdefer, hwnd, NULL,
451 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
452 SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOZORDER);
454 d->hwnd_notif_aux = hwnd;
456 EndDeferWindowPos(hdefer);
458 CopyRect(&d->r_notif, &r_row);
460 d->notif_type = NC_NOTIFY_MESSAGE;
462 /* Note that we must call nc_layout_main_panel() after calling
463 this to adjust the layout of the main panel. However we aren't
464 calling it here since we might want to add another set of
465 notifications or make other changes to the main panel content
466 before calling nc_layout_main_panel(). */
470 nc_layout_main_panel(khui_nc_wnd_data * d)
476 RECT r_used; /* extent used by identity specifiers,
477 custom prompts and notificaiton
480 RECT r_wmain; /* extents of the main window in screen
485 r_main.bottom = NCDLG_HEIGHT;
486 r_main.right = NCDLG_WIDTH;
488 MapDialogRect(d->dlg_main, &r_main);
490 CopyRect(&r_used, &d->r_idspec);
492 GetWindowRect(d->dlg_main, &r_wmain);
494 hdwp = BeginDeferWindowPos(7);
496 /* check if the notification area and the custom prompt area are
499 if (d->notif_type != NC_NOTIFY_NONE) {
503 CopyRect(&r, &d->r_custprompt);
505 if (IsRectEmpty(&d->r_custprompt)) {
506 /* if there are no custom prompts, then the notification
507 area should be immediately below the identitify
510 delta_y = d->r_idspec.bottom - d->r_notif.top;
512 /* otherwise, the notification area should be immediately
513 below the custom prompt area */
515 delta_y = d->r_custprompt.bottom - d->r_notif.top;
522 if (d->hwnd_notif_label) {
523 GetWindowRect(d->hwnd_notif_label, &r_lbl);
524 OffsetRect(&r_lbl, -r_wmain.left, delta_y - r_wmain.top);
526 DeferWindowPos(hdwp, d->hwnd_notif_label, NULL,
527 r_lbl.left, r_lbl.top, 0, 0,
528 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
529 SWP_NOZORDER | SWP_NOSIZE);
532 if (d->hwnd_notif_aux) {
533 GetWindowRect(d->hwnd_notif_aux, &r_aux);
534 OffsetRect(&r_aux, -r_wmain.left, delta_y - r_wmain.top);
536 DeferWindowPos(hdwp, d->hwnd_notif_aux, NULL,
537 r_aux.left, r_aux.top, 0, 0,
538 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
539 SWP_NOZORDER | SWP_NOSIZE);
542 OffsetRect(&d->r_notif, 0, delta_y);
546 if (!IsRectEmpty(&d->r_custprompt)) {
547 r_used.bottom = max(d->r_custprompt.bottom,
551 if (!IsRectEmpty(&d->r_notif)) {
552 r_used.bottom = max(d->r_notif.bottom,
556 if (d->nc->mode == KHUI_NC_MODE_MINI) {
562 hw = GetDlgItem(d->dlg_main, IDOK);
566 GetWindowRect(hw, &r_ok);
567 OffsetRect(&r_ok, -r_wmain.left, -r_ok.top + r_used.bottom);
569 DeferWindowPos(hdwp, hw, NULL,
570 r_ok.left, r_ok.top, 0, 0,
571 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
572 SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
574 hw = GetDlgItem(d->dlg_main, IDCANCEL);
578 GetWindowRect(hw, &r_cancel);
579 OffsetRect(&r_cancel, -r_wmain.left, -r_cancel.top + r_used.bottom);
581 DeferWindowPos(hdwp, hw, NULL,
582 r_cancel.left, r_cancel.top, 0, 0,
583 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
584 SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
586 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
590 GetWindowRect(hw, &r_advanced);
591 OffsetRect(&r_advanced, -r_wmain.left, -r_advanced.top + r_used.bottom);
593 DeferWindowPos(hdwp, hw, NULL,
594 r_advanced.left, r_advanced.top, 0, 0,
595 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
596 SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
598 /* and now update the extents of the main panel */
599 r_main.bottom = r_used.bottom + (r_ok.bottom - r_ok.top) + d->r_area.top;
601 CopyRect(&d->r_main, &r_main);
607 hw = GetDlgItem(d->dlg_main, IDOK);
611 if (IsWindowVisible(hw))
612 DeferWindowPos(hdwp, hw, NULL,
614 SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
615 SWP_NOOWNERZORDER | SWP_NOZORDER);
617 hw = GetDlgItem(d->dlg_main, IDCANCEL);
621 if (IsWindowVisible(hw))
622 DeferWindowPos(hdwp, hw, NULL,
624 SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
625 SWP_NOOWNERZORDER | SWP_NOZORDER);
627 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
631 if (IsWindowVisible(hw))
632 DeferWindowPos(hdwp, hw, NULL,
634 SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE |
635 SWP_NOOWNERZORDER | SWP_NOZORDER);
637 d->r_credtext.top = r_used.bottom;
639 CopyRect(&d->r_main, &r_main);
642 /* now update the layout of the credentials text window */
644 hw_ct = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);
645 hw_ct_label = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);
647 assert(hw_ct != NULL);
648 assert(hw_ct_label != NULL);
651 if (d->nc->mode == KHUI_NC_MODE_MINI ||
652 d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {
654 /* either we aren't supposed to show the credentials text
655 window, or we don't have enough room. */
656 if (IsWindowVisible(hw_ct) || IsWindowVisible(hw_ct_label)) {
658 DeferWindowPos(hdwp, hw_ct, NULL,
660 SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
661 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
663 DeferWindowPos(hdwp, hw_ct_label, NULL,
665 SWP_HIDEWINDOW | SWP_NOOWNERZORDER |
666 SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE);
674 d->r_credtext.left + d->r_n_input.left, /* x */
675 d->r_credtext.top, /* y */
676 d->r_n_input.right - d->r_n_input.left, /* width */
677 d->r_credtext.bottom - d->r_credtext.top, /* height */
678 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
679 SWP_NOZORDER | SWP_SHOWWINDOW);
683 d->r_credtext.left + d->r_n_label.left, /* x */
684 d->r_credtext.top, /* y */
685 d->r_n_label.right - d->r_n_label.left, /* width */
686 d->r_n_label.bottom - d->r_n_label.top, /* height */
687 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
688 SWP_NOZORDER | SWP_SHOWWINDOW);
691 EndDeferWindowPos(hdwp);
693 /* NOTE: although we updated d->r_main, if the new credentials
694 window is in mini mode, we must call
695 nc_layout_new_cred_window() to adjust the size of the new
696 credentials window to fit the main panel. We don't do it here
697 because we need to keep these two operations separate. */
700 /* Credential type panel comparison function. Tabs are sorted based
701 on the following criteria:
703 1) By ordinal - Panels with ordinal -1 will be ranked after panels
704 whose ordinal is not -1.
706 2) By name - Case insensitive comparison of the name. If the panel
707 does not have a name (i.e. the ->name member is NULL, it will be
708 ranked after panels which have a name.
711 nc_tab_sort_func(const void * v1, const void * v2)
713 /* v1 and v2 and of type : khui_new_creds_by_type ** */
714 khui_new_creds_by_type *t1, *t2;
716 t1 = *((khui_new_creds_by_type **) v1);
717 t2 = *((khui_new_creds_by_type **) v2);
719 if(t1->ordinal != -1) {
720 if(t2->ordinal != -1) {
721 if(t1->ordinal == t2->ordinal) {
722 if (t1->name && t2->name)
723 return _wcsicmp(t1->name, t2->name);
731 /* safe to convert to an int here */
732 return (int) (t1->ordinal - t2->ordinal);
737 if(t2->ordinal != -1)
739 else if (t1->name && t2->name)
740 return wcscmp(t1->name, t2->name);
751 nc_notify_types(khui_new_creds * c, UINT uMsg,
752 WPARAM wParam, LPARAM lParam, BOOL sync)
756 for(i=0; i<c->n_types; i++) {
758 if (c->types[i]->hwnd_panel == NULL)
762 SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
764 PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);
769 nc_clear_password_fields(khui_nc_wnd_data * d)
772 khm_boolean need_sync = FALSE;
774 khui_cw_lock_nc(d->nc);
776 for (i=0; i < d->nc->n_prompts; i++) {
777 if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) &&
778 d->nc->prompts[i]->hwnd_edit) {
779 SetWindowText(d->nc->prompts[i]->hwnd_edit,
785 khui_cw_unlock_nc(d->nc);
788 khui_cw_sync_prompt_values(d->nc);
792 /* used by nc_enable_controls */
794 struct nc_enum_wnd_data {
795 khui_nc_wnd_data * d;
801 nc_enum_wnd_proc(HWND hwnd,
804 struct nc_enum_wnd_data * wd;
806 wd = (struct nc_enum_wnd_data *) lParam;
808 EnableWindow(hwnd, wd->enable);
814 nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable)
816 struct nc_enum_wnd_data wd;
818 ZeroMemory(&wd, sizeof(wd));
823 EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd);
826 #define NC_MAXCCH_CREDTEXT 16384
827 #define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))
830 nc_update_credtext(khui_nc_wnd_data * d)
832 wchar_t * ctbuf = NULL;
834 BOOL okEnable = FALSE;
835 BOOL validId = FALSE;
839 ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);
841 assert(ctbuf != NULL);
843 LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);
844 StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);
846 nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
847 MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc, TRUE);
849 /* hopefully all the types have updated their credential texts */
851 /* if the dialog is in the mini mode, we have to display
852 exceptions using a notification. */
853 if (d->nc->mode == KHUI_NC_MODE_MINI) {
854 BOOL need_layout = FALSE;
855 if (d->nc->n_identities == 0) {
857 /* There are no identities selected. We don't show any
858 notifications here. */
859 if (d->notif_type != NC_NOTIFY_NONE) {
866 wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
868 wchar_t msg[ARRAYLENGTH(format) + ARRAYLENGTH(id_name)];
872 kcdb_identity_get_flags(d->nc->identities[0], &flags);
874 cbbuf = sizeof(id_name);
875 kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
877 if (flags & KCDB_IDENT_FLAG_INVALID) {
879 /* identity is invalid */
880 LoadString(khm_hInstance, IDS_NCN_IDENT_INVALID,
881 format, ARRAYLENGTH(format));
882 StringCbPrintf(msg, sizeof(msg), format, id_name);
884 nc_notify_message(d, KHERR_ERROR, msg);
888 } else if ((flags & KCDB_IDENT_FLAG_VALID) ||
889 d->nc->subtype == KMSG_CRED_PASSWORD) {
890 /* special case: If we are going to change the
891 password, we don't expect the identity provider to
892 validate the identity in real time. As such, we
893 assume that the identity is valid. */
895 /* identity is valid */
896 if (d->notif_type != NC_NOTIFY_NONE) {
901 } else if (flags & KCDB_IDENT_FLAG_UNKNOWN) {
904 LoadString(khm_hInstance, IDS_NCN_IDENT_UNKNOWN,
905 format, ARRAYLENGTH(format));
906 StringCbPrintf(msg, sizeof(msg), format, id_name);
908 nc_notify_message(d, KHERR_WARNING, msg);
915 LoadString(khm_hInstance, IDS_NCN_IDENT_CHECKING,
916 format, ARRAYLENGTH(format));
917 StringCbPrintf(msg, sizeof(msg), format, id_name);
919 nc_notify_marquee(d, msg);
927 nc_layout_main_panel(d);
928 nc_layout_new_cred_window(d);
932 if(d->nc->n_identities == 1) {
933 wchar_t main_fmt[256];
935 wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
936 wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
940 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE,
941 main_fmt, (int) ARRAYLENGTH(main_fmt));
943 cbbuf = sizeof(id_name);
944 kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
946 kcdb_identity_get_flags(d->nc->identities[0], &flags);
948 if (flags & KCDB_IDENT_FLAG_INVALID) {
949 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
950 id_fmt, (int) ARRAYLENGTH(id_fmt));
951 } else if(flags & KCDB_IDENT_FLAG_VALID) {
952 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
953 id_fmt, (int) ARRAYLENGTH(id_fmt));
954 } else if(flags & KCDB_IDENT_FLAG_UNKNOWN) {
955 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
956 id_fmt, (int) ARRAYLENGTH(id_fmt));
957 } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {
958 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING,
959 id_fmt, (int) ARRAYLENGTH(id_fmt));
961 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
962 id_fmt, (int) ARRAYLENGTH(id_fmt));
965 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
967 StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
968 main_fmt, id_string);
970 if (flags & KCDB_IDENT_FLAG_VALID) {
971 if (flags & KCDB_IDENT_FLAG_DEFAULT)
972 LoadString(khm_hInstance, IDS_NC_ID_DEF,
973 id_string, ARRAYLENGTH(id_string));
974 else if (d->nc->set_default)
975 LoadString(khm_hInstance, IDS_NC_ID_WDEF,
976 id_string, ARRAYLENGTH(id_string));
978 LoadString(khm_hInstance, IDS_NC_ID_NDEF,
979 id_string, ARRAYLENGTH(id_string));
981 StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t),
985 } else if(d->nc->n_identities > 1) {
987 khm_size cb_ids_string;
989 wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];
991 wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];
993 wchar_t main_fmt[256];
996 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY,
997 main_fmt, (int) ARRAYLENGTH(main_fmt));
999 /* we are going to concatenate all the identity names into
1000 a comma separated string */
1002 /* d->nc->n_identities is at least 2 */
1003 ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
1004 (d->nc->n_identities - 1));
1006 (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) *
1007 (d->nc->n_identities - 1);
1009 assert(ids_string != NULL);
1017 for(i=1; i<d->nc->n_identities; i++) {
1019 StringCbCat(ids_string, cb_ids_string, L",");
1024 cbbuf = sizeof(id_name);
1025 kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);
1026 kcdb_identity_get_flags(d->nc->identities[i], &flags);
1027 if(flags & KCDB_IDENT_FLAG_INVALID) {
1028 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
1029 id_fmt, (int) ARRAYLENGTH(id_fmt));
1030 } else if(flags & KCDB_IDENT_FLAG_VALID) {
1031 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
1032 id_fmt, (int) ARRAYLENGTH(id_fmt));
1034 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
1035 id_fmt, (int) ARRAYLENGTH(id_fmt));
1038 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
1039 StringCbCat(ids_string, cb_ids_string, id_string);
1042 cbbuf = sizeof(id_name);
1043 kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);
1044 kcdb_identity_get_flags(d->nc->identities[0], &flags);
1045 if(flags & KCDB_IDENT_FLAG_INVALID) {
1046 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID,
1047 id_fmt, (int) ARRAYLENGTH(id_fmt));
1048 } else if(flags & KCDB_IDENT_FLAG_VALID) {
1049 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID,
1050 id_fmt, (int) ARRAYLENGTH(id_fmt));
1052 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED,
1053 id_fmt, (int) ARRAYLENGTH(id_fmt));
1055 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);
1057 StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t),
1058 main_fmt, id_string, ids_string);
1063 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE,
1064 buf, (int)(NC_MAXCCH_CREDTEXT - cch));
1067 /* now, append the credtext string from each of the cred types */
1073 cb = NC_MAXCB_CREDTEXT;
1076 for(i=0; i<d->nc->n_types; i++) {
1077 if(d->nc->types[i]->credtext != NULL) {
1078 StringCbCatEx(buf, cb,
1079 d->nc->types[i]->credtext,
1086 SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);
1090 /* so depending on whether the primary identity was found to be
1091 invalid, we need to disable the Ok button and set the title to
1094 if(d->nc->n_identities > 0) {
1095 khm_int32 flags = 0;
1097 if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0],
1099 (flags & KCDB_IDENT_FLAG_VALID)) {
1104 if (d->nc->window_title == NULL) {
1106 wchar_t wpostfix[256];
1107 wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];
1110 cbsize = sizeof(wtitle);
1111 kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);
1113 if (d->nc->subtype == KMSG_CRED_PASSWORD)
1114 LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,
1115 wpostfix, (int) ARRAYLENGTH(wpostfix));
1117 LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS,
1118 wpostfix, (int) ARRAYLENGTH(wpostfix));
1120 StringCbCat(wtitle, sizeof(wtitle), wpostfix);
1122 SetWindowText(d->nc->hwnd, wtitle);
1124 wchar_t wtitle[256];
1126 if (d->nc->subtype == KMSG_CRED_PASSWORD)
1127 LoadString(khm_hInstance, IDS_WT_PASSWORD,
1128 wtitle, (int) ARRAYLENGTH(wtitle));
1130 LoadString(khm_hInstance, IDS_WT_NEW_CREDS,
1131 wtitle, (int) ARRAYLENGTH(wtitle));
1133 SetWindowText(d->nc->hwnd, wtitle);
1137 if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) {
1139 d->nc->subtype == KMSG_CRED_PASSWORD) {
1140 /* TODO: check if all the required fields have valid values
1141 before enabling the Ok button */
1145 hw = GetDlgItem(d->dlg_main, IDOK);
1146 EnableWindow(hw, okEnable);
1147 hw = GetDlgItem(d->dlg_bb, IDOK);
1148 EnableWindow(hw, okEnable);
1153 nc_layout_new_cred_window(khui_nc_wnd_data * ncd) {
1163 r_main.right = NCDLG_WIDTH;
1164 r_main.bottom = NCDLG_HEIGHT;
1166 MapDialogRect(ncd->dlg_main, &r_main);
1168 hdefer = BeginDeferWindowPos(5);
1170 if (c->mode == KHUI_NC_MODE_MINI) {
1172 if (IsWindowVisible(ncd->tab_wnd)) {
1173 DeferWindowPos(hdefer,
1177 SWP_NOMOVE | SWP_NOOWNERZORDER |
1178 SWP_NOSIZE | SWP_NOZORDER);
1181 if (IsWindowVisible(ncd->dlg_bb)) {
1182 DeferWindowPos(hdefer,
1186 SWP_NOMOVE | SWP_NOOWNERZORDER |
1187 SWP_NOSIZE | SWP_NOZORDER);
1190 DeferWindowPos(hdefer, ncd->dlg_main, NULL,
1191 r_main.left, r_main.top,
1192 r_main.right - r_main.left,
1193 r_main.bottom - r_main.top,
1194 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1195 SWP_NOZORDER | SWP_SHOWWINDOW);
1197 /* note that the ncd->r_main.bottom may not be the same as
1198 r_main.bottom because ncd->r_main.bottom is set dynamically
1199 depending on custom controls. ncd->r_main is valid only
1200 once nc_layout_main_panel() is called.*/
1201 CopyRect(&ncd->r_required, &ncd->r_main);
1209 /* calculate the size of the tab control so that it fits
1210 snugly around the expanded main panel. */
1211 CopyRect(&r_tabctrl, &r_main);
1212 TabCtrl_AdjustRect(ncd->tab_wnd, TRUE, &r_tabctrl);
1214 if (r_tabctrl.left < 0 ||
1215 r_tabctrl.top < 0) {
1217 OffsetRect(&r_tabctrl,
1218 (r_tabctrl.left < 0)? -r_tabctrl.left : 0,
1219 (r_tabctrl.top < 0)? -r_tabctrl.top : 0);
1224 assert(r_tabctrl.left == 0);
1225 assert(r_tabctrl.top == 0);
1228 OffsetRect(&r_tabctrl, 0, ncd->r_area.top);
1230 /* and now calculate the rectangle where the main panel should
1231 be inside the tab control. */
1232 CopyRect(&r_displayarea, &r_tabctrl);
1233 TabCtrl_AdjustRect(ncd->tab_wnd, FALSE, &r_displayarea);
1235 DeferWindowPos(hdefer,
1236 ncd->tab_wnd, HWND_BOTTOM,
1237 r_tabctrl.left, r_tabctrl.top,
1238 r_tabctrl.right - r_tabctrl.left,
1239 r_tabctrl.bottom - r_tabctrl.top,
1240 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1243 /* we have to place the button bar just to the right of the
1247 r_bbar.right = NCDLG_BBAR_WIDTH;
1248 r_bbar.bottom = NCDLG_BBAR_HEIGHT;
1250 MapDialogRect(ncd->dlg_main, &r_bbar);
1252 OffsetRect(&r_bbar, r_tabctrl.right, 0);
1254 DeferWindowPos(hdefer,
1256 r_bbar.left, r_bbar.top,
1257 r_bbar.right - r_bbar.left,
1258 r_bbar.bottom - r_bbar.top,
1259 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1260 SWP_NOZORDER | SWP_SHOWWINDOW);
1262 /* move the main panel inside the tab control... */
1263 DeferWindowPos(hdefer,
1264 ncd->dlg_main, NULL,
1265 r_displayarea.left, r_displayarea.top,
1266 r_displayarea.right - r_displayarea.left,
1267 r_displayarea.bottom - r_displayarea.top,
1268 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1270 (ncd->current_panel == 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
1272 /* and also move all the credential type panels (if they have
1273 been created) inside the tab control too. */
1276 for (i=0; i < c->n_types; i++) {
1277 if (c->types[i]->hwnd_panel != NULL) {
1278 DeferWindowPos(hdefer,
1279 c->types[i]->hwnd_panel, NULL,
1280 r_displayarea.left, r_displayarea.top,
1281 r_displayarea.right - r_displayarea.left,
1282 r_displayarea.bottom - r_displayarea.top,
1283 SWP_NOACTIVATE | SWP_NOOWNERZORDER |
1285 (ncd->current_panel == c->types[i]->ordinal ?
1286 SWP_SHOWWINDOW : SWP_HIDEWINDOW));
1290 khui_cw_unlock_nc(c);
1292 /* then update the required size of the new credentials
1294 ncd->r_required.left = 0;
1295 ncd->r_required.top = 0;
1296 ncd->r_required.right = r_bbar.right;
1297 ncd->r_required.bottom = max(r_tabctrl.bottom, r_bbar.bottom) + ncd->r_area.top;
1300 /* commit all the window moves, resizes and hides/shows we did*/
1301 EndDeferWindowPos(hdefer);
1303 /* now we have to see if the client area of the new credentials
1304 window is the right size. */
1306 GetClientRect(c->hwnd, &r_ncdialog);
1310 ((r_ncdialog.right - r_ncdialog.left !=
1311 ncd->r_required.right - ncd->r_required.left)
1315 (r_ncdialog.bottom - r_ncdialog.top !=
1316 ncd->r_required.bottom - ncd->r_required.top))
1320 /* we don't bother if the new creds window is already in the
1321 process of changing the size. */
1322 !ncd->size_changing) {
1324 /* if not, notify the window that the size needs adjusting. */
1325 if (IsWindowVisible(c->hwnd))
1326 PostMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
1327 MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
1329 SendMessage(c->hwnd, KHUI_WM_NC_NOTIFY,
1330 MAKEWPARAM(0, WMNC_UPDATE_LAYOUT), 0);
1334 #define CW_PARAM DWLP_USER
1337 nc_handle_wm_create(HWND hwnd,
1344 khui_nc_wnd_data * ncd;
1350 lpc = (LPCREATESTRUCT) lParam;
1352 ncd = PMALLOC(sizeof(*ncd));
1353 ZeroMemory(ncd, sizeof(*ncd));
1355 c = (khui_new_creds *) lpc->lpCreateParams;
1360 assert(c->subtype == KMSG_CRED_NEW_CREDS ||
1361 c->subtype == KMSG_CRED_PASSWORD);
1364 #pragma warning(push)
1365 #pragma warning(disable: 4244)
1366 SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);
1367 #pragma warning(pop)
1369 /* first, create the tab control that will house the main dialog
1370 panel as well as the plug-in specific panels */
1371 ncd->tab_wnd = CreateWindowEx(0, /* extended style */
1373 L"TabControloxxrz", /* window name */
1374 TCS_HOTTRACK | TCS_RAGGEDRIGHT |
1375 TCS_SINGLELINE | TCS_TABS |
1376 WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS,
1377 0, 0, 100, 100, /* x,y,width height.
1382 (HMENU) IDC_NC_TABS,
1387 assert(ncd->tab_wnd != NULL);
1390 /* try to create the main dialog panel */
1392 ncd->dlg_main = CreateDialogParam(khm_hInstance,
1393 MAKEINTRESOURCE(IDD_NC_NEWCRED),
1398 assert(ncd->dlg_main != NULL);
1401 hf_main = (HFONT) SendMessage(ncd->dlg_main, WM_GETFONT, 0, 0);
1403 SendMessage(ncd->tab_wnd, WM_SETFONT, (WPARAM) hf_main, FALSE);
1411 /* During the operation of the new credentials window, we will
1412 need to dynamically change the layout of the controls as a
1413 result of custom prompting from credentials providers and
1414 identity selectors from identity providers. In order to
1415 guide the dynamic layout, we pick out a few metrics from
1416 the dialog template for the main panel. The metrics come
1417 from hidden STATIC controls in the dialog template. */
1419 GetWindowRect(ncd->dlg_main, &r_main);
1421 /* IDC_NC_TPL_PANEL spans the full extent of the dialog that
1422 we can populate with custom controls. */
1423 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL);
1427 GetWindowRect(hw, &r_area);
1428 OffsetRect(&r_area,-r_main.left, -r_main.top);
1429 CopyRect(&ncd->r_area, &r_area);
1431 /* IDC_NC_TPL_ROW spans the extent of a row of normal sized
1432 custom controls. A row of custom controls typicall consist
1433 of a text label and an input control. */
1434 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW);
1438 GetWindowRect(hw, &r);
1439 CopyRect(&r_row, &r);
1440 OffsetRect(&r,-r.left, -r.top);
1441 CopyRect(&ncd->r_row, &r);
1443 /* IDC_NC_TPL_LABEL spans the extent that a normal sized
1444 label. The control overlaps IDC_NC_TPL_ROW so we can get
1445 coordinates relative to the row extents. */
1446 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL);
1450 GetWindowRect(hw, &r);
1451 OffsetRect(&r,-r_row.left, -r_row.top);
1452 CopyRect(&ncd->r_n_label, &r);
1454 /* IDC_NC_TPL_INPUT spans the extent of a normal sized input
1455 control in a custom control row. The control overlaps
1456 IDC_NC_TPL_ROW so we can get relative coordinates. */
1457 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT);
1461 GetWindowRect(hw, &r);
1462 OffsetRect(&r, -r_row.left, -r_row.top);
1463 CopyRect(&ncd->r_n_input, &r);
1465 /* IDC_NC_TPL_ROW_LG spans the extent of a row of large sized
1467 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG);
1471 GetWindowRect(hw, &r_row);
1473 /* IDC_NC_TPL_LABEL_LG is a large sized label. The control
1474 overlaps IDC_NC_TPL_ROW_LG. */
1475 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG);
1479 GetWindowRect(hw, &r);
1480 OffsetRect(&r, -r_row.left, -r_row.top);
1481 CopyRect(&ncd->r_e_label, &r);
1483 /* IDC_NC_TPL_INPUT_LG is a large sized input control.
1484 Overlaps IDC_NC_TPL_ROW_LG. */
1485 hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG);
1489 GetWindowRect(hw, &r);
1490 OffsetRect(&r, -r_row.left, -r_row.top);
1491 CopyRect(&ncd->r_e_input, &r);
1493 CopyRect(&ncd->r_credtext, &ncd->r_area);
1494 CopyRect(&ncd->r_idspec, &ncd->r_area);
1496 ncd->r_idspec.bottom = ncd->r_idspec.top;
1498 /* And finally the credential text window. The only metric we
1499 take from here is the Y coordinate of the bottom of the
1500 control since the actual size and position of the
1501 credentials window will change depending on the custom
1502 controls being displayed. */
1503 hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT);
1507 GetWindowRect(hw, &r);
1508 OffsetRect(&r, -r_main.left, -r_main.top);
1509 ncd->r_credtext.bottom = r.bottom;
1512 /* if the mode is 'mini'*/
1516 if(c->mode == KHUI_NC_MODE_MINI) {
1517 r.right = NCDLG_WIDTH;
1518 r.bottom = NCDLG_HEIGHT;
1520 r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;
1521 r.bottom = NCDLG_BBAR_HEIGHT;
1524 MapDialogRect(ncd->dlg_main, &r);
1526 /* position the new credentials dialog */
1527 width = r.right - r.left;
1528 height = r.bottom - r.top;
1530 /* adjust width and height to accomodate NC area */
1534 GetWindowRect(hwnd, &wr);
1535 GetClientRect(hwnd, &cr);
1537 /* the non-client and client areas have already been calculated
1538 at this point. We just use the difference to adjust the width
1540 width += (wr.right - wr.left) - (cr.right - cr.left);
1541 height += (wr.bottom - wr.top) - (cr.bottom - cr.top);
1544 /* if the parent window is visible, we center the new credentials
1545 dialog over the parent. Otherwise, we center it on the primary
1548 if (IsWindowVisible(lpc->hwndParent)) {
1549 GetWindowRect(lpc->hwndParent, &r);
1551 if(!SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID) &r, 0)) {
1552 /* failover to the window coordinates */
1553 GetWindowRect(lpc->hwndParent, &r);
1556 x = (r.right + r.left)/2 - width / 2;
1557 y = (r.top + r.bottom)/2 - height / 2;
1559 MoveWindow(hwnd, x, y, width, height, FALSE);
1561 ncd->dlg_bb = CreateDialogParam(khm_hInstance,
1562 MAKEINTRESOURCE(IDD_NC_BBAR),
1568 assert(ncd->dlg_bb);
1571 /* Call the identity provider callback to set the identity
1572 selector controls. These controls need to be there before we
1573 layout the main panel. */
1574 c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main);
1576 if (c->mode == KHUI_NC_MODE_EXPANDED) {
1577 SendMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY,
1578 MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
1580 /* we don't call nc_layout_main_panel() if the dialog is
1581 expanded because posting WMNC_DIALOG_EXPAND to the main
1582 panel results in it getting called anyway. */
1583 nc_layout_main_panel(ncd);
1586 nc_layout_new_cred_window(ncd);
1588 /* add this to the dialog chain */
1589 khm_add_dialog(hwnd);
1594 /* add a control row supplied by an identity provider */
1596 nc_add_control_row(khui_nc_wnd_data * d,
1599 khui_control_size size)
1607 hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
1608 SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);
1609 SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);
1611 CopyRect(&r_row, &d->r_row);
1612 OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);
1614 if (size == KHUI_CTRLSIZE_SMALL) {
1615 CopyRect(&r_label, &d->r_n_label);
1616 CopyRect(&r_input, &d->r_n_input);
1617 OffsetRect(&r_label, r_row.left, r_row.top);
1618 OffsetRect(&r_input, r_row.left, r_row.top);
1619 } else if (size == KHUI_CTRLSIZE_HALF) {
1620 CopyRect(&r_label, &d->r_e_label);
1621 CopyRect(&r_input, &d->r_e_input);
1622 OffsetRect(&r_label, r_row.left, r_row.top);
1623 OffsetRect(&r_input, r_row.left, r_row.top);
1624 } else if (size == KHUI_CTRLSIZE_FULL) {
1625 CopyRect(&r_label, &d->r_n_label);
1626 r_label.right = d->r_row.right;
1627 CopyRect(&r_input, &d->r_n_input);
1628 OffsetRect(&r_input, r_row.left, r_row.top);
1629 OffsetRect(&r_input, 0, r_input.bottom);
1630 r_row.bottom += r_input.bottom;
1631 OffsetRect(&r_label, r_row.left, r_row.top);
1633 SetRectEmpty(&r_label);
1634 SetRectEmpty(&r_input);
1641 hdefer = BeginDeferWindowPos(2);
1644 DeferWindowPos(hdefer, label,
1645 ((d->hwnd_last_idspec != NULL)?
1646 d->hwnd_last_idspec:
1648 r_label.left, r_label.top,
1649 r_label.right - r_label.left,
1650 r_label.bottom - r_label.top,
1651 SWP_NOACTIVATE | SWP_NOOWNERZORDER);
1654 DeferWindowPos(hdefer, input,
1655 (label ? label : ((d->hwnd_last_idspec != NULL)?
1656 d->hwnd_last_idspec:
1658 r_input.left, r_input.top,
1659 r_input.right - r_input.left,
1660 r_input.bottom - r_input.top,
1661 SWP_NOACTIVATE | SWP_NOOWNERZORDER);
1663 EndDeferWindowPos(hdefer);
1665 d->hwnd_last_idspec = (input ? input : label);
1667 d->r_idspec.bottom = r_row.bottom;
1669 /* we don't update the layout of the main panel yet, since these
1670 control additions happen before the main panel is displayed. A
1671 call to nc_layout_main_panel() will be made before the main
1672 panel is shown anyway. */
1678 nc_handle_wm_destroy(HWND hwnd,
1683 khui_nc_wnd_data * d;
1685 /* remove self from dialog chain */
1686 khm_del_dialog(hwnd);
1688 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1692 d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);
1694 if (d->hwnd_notif_label)
1695 DestroyWindow(d->hwnd_notif_label);
1696 if (d->hwnd_notif_aux)
1697 DestroyWindow(d->hwnd_notif_aux);
1700 DestroyWindow(d->dlg_bb);
1702 DestroyWindow(d->dlg_main);
1708 SetWindowLongPtr(hwnd, CW_PARAM, 0);
1714 nc_handle_wm_command(HWND hwnd,
1719 khui_nc_wnd_data * d;
1721 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1725 switch(HIWORD(wParam)) {
1727 switch(LOWORD(wParam)) {
1730 d->nc->result = KHUI_NC_RESULT_PROCESS;
1735 /* the default value for d->nc->result is set to
1736 KHUI_NC_RESULT_CANCEL */
1737 d->nc->response = KHUI_NC_RESPONSE_PROCESSING;
1739 nc_enable_controls(d, FALSE);
1741 nc_notify_types(d->nc,
1743 MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS),
1747 khui_cw_sync_prompt_values(d->nc);
1749 khm_cred_dispatch_process_message(d->nc);
1751 /* we won't know whether to abort or not until we get
1752 feedback from the plugins, even if the command was
1757 hw = GetDlgItem(d->dlg_main, IDOK);
1758 EnableWindow(hw, FALSE);
1759 hw = GetDlgItem(d->dlg_main, IDCANCEL);
1760 EnableWindow(hw, FALSE);
1761 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
1762 EnableWindow(hw, FALSE);
1763 hw = GetDlgItem(d->dlg_bb, IDOK);
1764 EnableWindow(hw, FALSE);
1765 hw = GetDlgItem(d->dlg_bb, IDCANCEL);
1766 EnableWindow(hw, FALSE);
1771 khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID);
1775 case IDC_NC_ADVANCED:
1776 /* the Options button in the main window was clicked. we
1777 respond by expanding the dialog. */
1778 PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
1779 MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);
1782 case IDC_NC_CREDTEXT: /* credtext link activated */
1784 khui_htwnd_link * l;
1785 wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];
1786 wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];
1789 l = (khui_htwnd_link *) lParam;
1791 /* do we have a valid link? */
1792 if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))
1793 return TRUE; /* nope */
1795 StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);
1796 sid[l->id_len] = L'\0'; /* just make sure */
1798 if(l->param != NULL &&
1799 l->param_len < ARRAYLENGTH(sparam) &&
1802 StringCchCopyN(sparam, ARRAYLENGTH(sparam),
1803 l->param, l->param_len);
1804 sparam[l->param_len] = L'\0';
1810 /* If the ID is of the form '<credtype>:<link_tag>'
1811 and <credtype> is a valid name of a credentials
1812 type that is participating in the credentials
1813 acquisition process, then we forward the message to
1814 the panel that is providing the UI for that cred
1815 type. We also switch to that panel first, unless
1816 the link is of the form '<credtype>:!<link_tag>'. */
1818 colon = wcschr(sid, L':');
1819 if (colon != NULL) {
1821 khui_new_creds_by_type * t;
1824 if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&
1825 KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){
1828 if (t->ordinal != d->current_panel &&
1829 *(colon + 1) != L'!')
1832 MAKEWPARAM(t->ordinal,
1833 WMNC_DIALOG_SWITCH_PANEL),
1836 return SendMessage(t->hwnd_panel,
1838 MAKEWPARAM(0, WMNC_CREDTEXT_LINK),
1845 /* if it was for us, then we need to process the message */
1846 if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {
1848 khui_new_creds_by_type * t;
1850 if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam,
1852 KHM_SUCCEEDED(khui_cw_find_type(d->nc,
1854 if (t->ordinal != d->current_panel)
1857 MAKEWPARAM(t->ordinal,
1858 WMNC_DIALOG_SWITCH_PANEL),
1861 } else if (!_wcsicmp(sid, L"NotDef")) {
1862 d->nc->set_default = FALSE;
1863 nc_update_credtext(d);
1864 } else if (!_wcsicmp(sid, L"MakeDef")) {
1865 d->nc->set_default = TRUE;
1866 nc_update_credtext(d);
1872 case NC_BN_SET_DEF_ID:
1874 d->nc->set_default =
1875 (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID)
1887 static LRESULT nc_handle_wm_moving(HWND hwnd,
1892 khui_nc_wnd_data * d;
1894 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1898 nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
1899 MAKEWPARAM(0, WMNC_DIALOG_MOVE), (LPARAM) d->nc, TRUE);
1904 static LRESULT nc_handle_wm_nc_notify(HWND hwnd,
1909 khui_nc_wnd_data * d;
1912 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
1916 switch(HIWORD(wParam)) {
1918 case WMNC_DIALOG_SWITCH_PANEL:
1919 id = LOWORD(wParam);
1920 if(id >= 0 && id <= (int) d->nc->n_types) {
1921 /* one of the tab buttons were pressed */
1922 if(d->current_panel == id) {
1923 return TRUE; /* nothing to do */
1926 d->current_panel = id;
1928 TabCtrl_SetCurSel(d->tab_wnd, id);
1931 if(d->nc->mode == KHUI_NC_MODE_EXPANDED) {
1932 nc_layout_new_cred_window(d);
1938 case WMNC_DIALOG_EXPAND:
1939 /* we are switching from basic to advanced or vice versa */
1941 if (d->nc->mode == KHUI_NC_MODE_EXPANDED) {
1943 if (d->current_panel != 0) {
1944 d->current_panel = 0;
1945 TabCtrl_SetCurSel(d->tab_wnd, 0);
1946 nc_layout_new_cred_window(d);
1949 d->nc->mode = KHUI_NC_MODE_MINI;
1951 d->nc->mode = KHUI_NC_MODE_EXPANDED;
1954 /* if we are switching to the advanced mode, we clear any
1955 notifications because we now have a credential text area
1957 if (d->nc->mode == KHUI_NC_MODE_EXPANDED)
1960 nc_layout_main_panel(d);
1962 nc_layout_new_cred_window(d);
1966 case WMNC_DIALOG_SETUP:
1968 if(d->nc->n_types > 0) {
1970 for(i=0; i < d->nc->n_types;i++) {
1972 if (d->nc->types[i]->dlg_proc == NULL) {
1973 d->nc->types[i]->hwnd_panel = NULL;
1975 /* Create the dialog panel */
1976 d->nc->types[i]->hwnd_panel =
1977 CreateDialogParam(d->nc->types[i]->h_module,
1978 d->nc->types[i]->dlg_template,
1980 d->nc->types[i]->dlg_proc,
1984 assert(d->nc->types[i]->hwnd_panel);
1992 case WMNC_DIALOG_ACTIVATE:
1994 wchar_t wname[KCDB_MAXCCH_NAME];
1998 /* About to activate the window. We should add all the
1999 panels to the tab control. */
2002 assert(d->tab_wnd != NULL);
2005 ZeroMemory(&tabitem, sizeof(tabitem));
2007 tabitem.mask = TCIF_PARAM | TCIF_TEXT;
2009 LoadString(khm_hInstance, IDS_NC_IDENTITY,
2010 wname, ARRAYLENGTH(wname));
2012 tabitem.pszText = wname;
2013 tabitem.lParam = 0; /* ordinal */
2015 TabCtrl_InsertItem(d->tab_wnd, 0, &tabitem);
2017 khui_cw_lock_nc(d->nc);
2019 if(d->nc->n_types > 0) {
2022 /* We should sort the tabs first. See
2023 nc_tab_sort_func() for sort criteria. */
2026 sizeof(*(d->nc->types)),
2029 for(i=0; i < d->nc->n_types;i++) {
2031 d->nc->types[i]->ordinal = i + 1;
2033 if(d->nc->types[i]->name)
2034 tabitem.pszText = d->nc->types[i]->name;
2038 cbsize = sizeof(wname);
2041 (kcdb_credtype_describe
2042 (d->nc->types[i]->type,
2054 tabitem.pszText = wname;
2058 tabitem.lParam = d->nc->types[i]->ordinal;
2060 TabCtrl_InsertItem(d->tab_wnd, d->nc->types[i]->ordinal,
2065 khui_cw_unlock_nc(d->nc);
2067 nc_update_credtext(d);
2069 TabCtrl_SetCurSel(d->tab_wnd, 0); /* the first selected
2073 /* bring the window to the top, if necessary */
2074 if (KHM_SUCCEEDED(khc_read_int32(NULL,
2075 L"CredWindow\\Windows\\NewCred\\ForceToTop",
2079 /* it used to be that the above condition also called
2080 !khm_is_dialog_active() to find out whether there
2081 was a dialog active. If there was, we wouldn't try
2082 to bring the new cred window to the foreground. But
2083 that was not the behavior we want. */
2085 /* if the main window is not visible, then the SetWindowPos()
2086 call is sufficient to bring the new creds window to the
2087 top. However, if the main window is visible but not
2088 active, the main window needs to be activated before a
2089 child window can be activated. */
2090 khm_activate_main_window();
2092 SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,
2093 (SWP_NOMOVE | SWP_NOSIZE));
2096 ShowWindow(hwnd, SW_SHOWNOACTIVATE);
2098 /* we don't enable animations until a specific timeout
2099 elapses after showing the window. We don't need to
2100 animate any size changes if the user has barely had a
2101 chance to notice the original size. This prevents the
2102 new cred window from appearing in an animated state. */
2103 SetTimer(hwnd, NC_TIMER_ENABLEANIMATE, ENABLEANIMATE_TIMEOUT, NULL);
2107 if (d->nc->n_identities == 0)
2113 case WMNC_IDENTITY_CHANGE:
2115 BOOL okEnable = FALSE;
2117 nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,
2118 MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), (LPARAM) d->nc,
2121 if (d->nc->subtype == KMSG_CRED_NEW_CREDS &&
2122 d->nc->n_identities > 0 &&
2123 d->nc->identities[0]) {
2126 kcdb_identity_get_flags(d->nc->identities[0], &f);
2128 if (!(f & KCDB_IDENT_FLAG_DEFAULT)) {
2129 d->nc->set_default = FALSE;
2133 nc_update_credtext(d);
2138 case WMNC_TYPE_STATE:
2140 case WMNC_UPDATE_CREDTEXT:
2141 nc_update_credtext(d);
2144 case WMNC_CLEAR_PROMPTS:
2148 khui_cw_lock_nc(d->nc);
2150 if(d->hwnd_banner != NULL) {
2151 DestroyWindow(d->hwnd_banner);
2152 d->hwnd_banner = NULL;
2155 if(d->hwnd_name != NULL) {
2156 DestroyWindow(d->hwnd_name);
2157 d->hwnd_name = NULL;
2160 for(i=0;i<d->nc->n_prompts;i++) {
2161 if(!(d->nc->prompts[i]->flags &
2162 KHUI_NCPROMPT_FLAG_STOCK)) {
2163 if(d->nc->prompts[i]->hwnd_static != NULL)
2164 DestroyWindow(d->nc->prompts[i]->hwnd_static);
2166 if(d->nc->prompts[i]->hwnd_edit != NULL)
2167 DestroyWindow(d->nc->prompts[i]->hwnd_edit);
2170 d->nc->prompts[i]->hwnd_static = NULL;
2171 d->nc->prompts[i]->hwnd_edit = NULL;
2174 khui_cw_unlock_nc(d->nc);
2176 SetRectEmpty(&d->r_custprompt);
2178 nc_layout_main_panel(d);
2180 nc_layout_new_cred_window(d);
2184 case WMNC_SET_PROMPTS:
2191 BOOL use_large_lables = FALSE;
2193 /* we assume that WMNC_CLEAR_PROMPTS has already been
2197 assert(IsRectEmpty(&d->r_custprompt));
2200 khui_cw_lock_nc(d->nc);
2203 /* special case, we have one prompt and it is a password
2204 prompt. very common */
2205 if(d->nc->n_prompts == 1 &&
2206 d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {
2208 hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);
2209 EnableWindow(hw, TRUE);
2211 d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;
2212 d->nc->prompts[0]->hwnd_edit = hw;
2213 d->nc->prompts[0]->hwnd_static = NULL; /* don't care */
2215 khui_cw_unlock_nc(d->nc);
2219 /* for everything else */
2221 y = d->r_idspec.bottom;
2223 d->r_custprompt.left = d->r_area.left;
2224 d->r_custprompt.right = d->r_area.right;
2225 d->r_custprompt.top = y;
2227 hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);
2229 if (d->nc->pname != NULL) {
2235 SS_SUNKEN | WS_CHILD,
2238 d->r_n_label.bottom - d->r_n_label.top,
2248 SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);
2249 ShowWindow(hw, SW_SHOW);
2251 y += d->r_n_label.bottom - d->r_n_label.top;
2254 if (d->nc->banner != NULL) {
2262 d->r_row.right, d->r_row.bottom,
2270 d->hwnd_banner = hw;
2271 SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);
2272 ShowWindow(hw, SW_SHOW);
2273 y += d->r_row.bottom;
2276 hw_prev = d->hwnd_last_idspec;
2278 hdc = GetWindowDC(d->dlg_main);
2279 hfold = SelectObject(hdc,hf);
2281 /* first do a trial run and see if we should use the
2282 larger text labels or not. This is so that all the
2283 labels and input controls align properly. */
2284 for (i=0; i < d->nc->n_prompts; i++) {
2285 if (d->nc->prompts[i]->prompt != NULL) {
2288 GetTextExtentPoint32(hdc,
2289 d->nc->prompts[i]->prompt,
2290 (int) wcslen(d->nc->prompts[i]->prompt),
2293 if(s.cx >= d->r_n_label.right - d->r_n_label.left) {
2294 use_large_lables = TRUE;
2300 for(i=0; i<d->nc->n_prompts; i++) {
2305 if(d->nc->prompts[i]->prompt != NULL) {
2306 GetTextExtentPoint32(hdc,
2307 d->nc->prompts[i]->prompt,
2308 (int) wcslen(d->nc->prompts[i]->prompt),
2310 if(s.cx < d->r_n_label.right - d->r_n_label.left &&
2311 !use_large_lables) {
2312 CopyRect(&pr, &d->r_n_label);
2313 CopyRect(&er, &d->r_n_input);
2314 dy = d->r_row.bottom;
2316 d->r_e_label.right - d->r_e_label.left) {
2317 CopyRect(&pr, &d->r_e_label);
2318 CopyRect(&er, &d->r_e_input);
2319 dy = d->r_row.bottom;
2321 /* oops. the prompt doesn't fit in our
2322 controls. we need to use up two lines */
2324 pr.right = d->r_row.right;
2326 pr.bottom = d->r_n_label.bottom -
2328 CopyRect(&er, &d->r_n_input);
2329 OffsetRect(&er, 0, pr.bottom);
2330 dy = er.bottom + (d->r_row.bottom -
2331 d->r_n_input.bottom);
2335 CopyRect(&er, &d->r_n_input);
2336 dy = d->r_row.bottom;
2339 if(IsRectEmpty(&pr)) {
2340 d->nc->prompts[i]->hwnd_static = NULL;
2342 OffsetRect(&pr, d->r_area.left, y);
2347 d->nc->prompts[i]->prompt,
2350 pr.right - pr.left, pr.bottom - pr.top,
2359 SendMessage(hw, WM_SETFONT,
2360 (WPARAM) hf, (LPARAM) TRUE);
2362 SetWindowPos(hw, hw_prev,
2364 SWP_NOACTIVATE | SWP_NOMOVE |
2365 SWP_NOOWNERZORDER | SWP_NOSIZE |
2368 d->nc->prompts[i]->hwnd_static = hw;
2372 OffsetRect(&er, d->r_area.left, y);
2377 (d->nc->prompts[i]->def ?
2378 d->nc->prompts[i]->def : L""),
2379 WS_CHILD | WS_TABSTOP |
2381 ((d->nc->prompts[i]->flags &
2382 KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0),
2384 er.right - er.left, er.bottom - er.top,
2394 SendMessage(hw, WM_SETFONT,
2395 (WPARAM) hf, (LPARAM) TRUE);
2397 SetWindowPos(hw, hw_prev,
2399 SWP_NOACTIVATE | SWP_NOMOVE |
2400 SWP_NOOWNERZORDER | SWP_NOSIZE |
2403 SendMessage(hw, EM_SETLIMITTEXT,
2404 KHUI_MAXCCH_PROMPT_VALUE -1,
2407 d->nc->prompts[i]->hwnd_edit = hw;
2414 if (d->nc->n_prompts > 0 &&
2415 d->nc->prompts[0]->hwnd_edit) {
2417 PostMessage(d->dlg_main, WM_NEXTDLGCTL,
2418 (WPARAM) d->nc->prompts[0]->hwnd_edit,
2419 MAKELPARAM(TRUE, 0));
2423 SelectObject(hdc, hfold);
2424 ReleaseDC(d->dlg_main, hdc);
2426 khui_cw_unlock_nc(d->nc);
2428 d->r_custprompt.bottom = y;
2430 if (d->r_custprompt.bottom == d->r_custprompt.top)
2431 SetRectEmpty(&d->r_custprompt);
2433 nc_layout_main_panel(d);
2435 nc_layout_new_cred_window(d);
2439 case WMNC_DIALOG_PROCESS_COMPLETE:
2441 khui_new_creds * nc;
2445 nc->response &= ~KHUI_NC_RESPONSE_PROCESSING;
2447 if(nc->response & KHUI_NC_RESPONSE_NOEXIT) {
2450 nc_enable_controls(d, TRUE);
2453 nc->result = KHUI_NC_RESULT_CANCEL;
2455 hw = GetDlgItem(d->dlg_main, IDOK);
2456 EnableWindow(hw, TRUE);
2457 hw = GetDlgItem(d->dlg_main, IDCANCEL);
2458 EnableWindow(hw, TRUE);
2459 hw = GetDlgItem(d->dlg_main, IDC_NC_ADVANCED);
2460 EnableWindow(hw, TRUE);
2461 hw = GetDlgItem(d->dlg_bb, IDOK);
2462 EnableWindow(hw, TRUE);
2463 hw = GetDlgItem(d->dlg_bb, IDCANCEL);
2464 EnableWindow(hw, TRUE);
2466 nc_clear_password_fields(d);
2471 DestroyWindow(hwnd);
2473 kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);
2477 /* MUST be called with SendMessage */
2478 case WMNC_ADD_CONTROL_ROW:
2480 khui_control_row * row;
2482 row = (khui_control_row *) lParam;
2489 nc_add_control_row(d, row->label, row->input, row->size);
2493 case WMNC_UPDATE_LAYOUT:
2501 /* We are already adjusting the size of the window. The
2502 next time the timer fires, it will notice if the target
2503 size has changed. */
2504 if (d->size_changing)
2507 GetClientRect(hwnd, &r_client);
2509 if ((r_client.right - r_client.left ==
2510 d->r_required.right - d->r_required.left) &&
2511 (r_client.bottom - r_client.top ==
2512 d->r_required.bottom - d->r_required.top)) {
2514 /* the window is already at the right size */
2519 if (!IsWindowVisible(hwnd)) {
2520 /* The window is not visible yet. There's no need to
2521 animate anything. */
2525 } else if (KHM_FAILED(khc_read_int32(NULL,
2526 L"CredWindow\\Windows\\NewCred\\AnimateSizeChanges",
2534 /* if we aren't animating the window resize, then we just
2535 do it in one call. */
2536 if (!animate || !d->animation_enabled) {
2539 CopyRect(&r_window, &d->r_required);
2540 AdjustWindowRectEx(&r_window, NC_WINDOW_STYLES, FALSE,
2541 NC_WINDOW_EX_STYLES);
2543 SetWindowPos(hwnd, NULL, 0, 0,
2544 r_window.right - r_window.left,
2545 r_window.bottom - r_window.top,
2546 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
2552 if (KHM_FAILED(khc_read_int32(NULL,
2553 L"CredWindow\\Windows\\NewCred\\AnimationSteps",
2558 steps = NC_SZ_STEPS_DEF;
2561 if (steps < NC_SZ_STEPS_MIN)
2562 steps = NC_SZ_STEPS_MIN;
2563 else if (steps > NC_SZ_STEPS_MAX)
2564 steps = NC_SZ_STEPS_MAX;
2568 if (KHM_FAILED(khc_read_int32(NULL,
2569 L"CredWindow\\Windows\\NewCred\\AnimationStepTimeout",
2574 timeout = NC_SZ_TIMEOUT_DEF;
2577 if (timeout < NC_SZ_TIMEOUT_MIN)
2578 timeout = NC_SZ_TIMEOUT_MIN;
2579 else if (timeout > NC_SZ_TIMEOUT_MAX)
2580 timeout = NC_SZ_TIMEOUT_MAX;
2584 CopyRect(&d->sz_ch_source, &r_client);
2585 OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
2586 CopyRect(&d->sz_ch_target, &d->r_required);
2587 OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
2588 d->sz_ch_increment = 0;
2589 d->sz_ch_max = steps;
2590 d->sz_ch_timeout = timeout;
2591 d->size_changing = TRUE;
2593 SetTimer(hwnd, NC_TIMER_SIZER, timeout, NULL);
2596 } /* switch(HIWORD(wParam)) */
2601 static LRESULT nc_handle_wm_timer(HWND hwnd,
2605 khui_nc_wnd_data * d;
2607 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2611 if (wParam == NC_TIMER_SIZER) {
2615 /* are we done with this sizing operation? */
2616 if (!d->size_changing ||
2617 d->sz_ch_increment >= d->sz_ch_max) {
2619 d->size_changing = FALSE;
2620 KillTimer(hwnd, NC_TIMER_SIZER);
2624 /* have the requirements changed while we were processing the
2625 sizing operation? */
2626 if ((d->r_required.right - d->r_required.left !=
2627 d->sz_ch_target.right)
2631 (d->r_required.bottom - d->r_required.top !=
2632 d->sz_ch_target.bottom)) {
2634 /* the target size has changed. we need to restart the
2635 sizing operation. */
2639 GetClientRect(hwnd, &r_client);
2641 CopyRect(&d->sz_ch_source, &r_client);
2642 OffsetRect(&d->sz_ch_source, -d->sz_ch_source.left, -d->sz_ch_source.top);
2643 CopyRect(&d->sz_ch_target, &d->r_required);
2644 OffsetRect(&d->sz_ch_target, -d->sz_ch_target.left, -d->sz_ch_target.top);
2645 d->sz_ch_increment = 0;
2647 /* leave the other fields alone */
2650 assert(d->sz_ch_max >= NC_SZ_STEPS_MIN);
2651 assert(d->sz_ch_max <= NC_SZ_STEPS_MAX);
2652 assert(d->sz_ch_timeout >= NC_SZ_TIMEOUT_MIN);
2653 assert(d->sz_ch_timeout <= NC_SZ_TIMEOUT_MAX);
2654 assert(d->size_changing);
2658 /* we are going to do the next increment */
2659 d->sz_ch_increment ++;
2661 /* now, figure out the size of the client area for this
2667 #define PROPORTION(v1, v2, i, s) (((v1) * ((s) - (i)) + (v2) * (i)) / (s))
2669 r_now.right = PROPORTION(d->sz_ch_source.right, d->sz_ch_target.right,
2670 d->sz_ch_increment, d->sz_ch_max);
2672 r_now.bottom = PROPORTION(d->sz_ch_source.bottom, d->sz_ch_target.bottom,
2673 d->sz_ch_increment, d->sz_ch_max);
2679 long dx = (r_now.right - d->sz_ch_target.right) *
2680 (d->sz_ch_source.right - d->sz_ch_target.right);
2682 long dy = (r_now.bottom - d->sz_ch_target.bottom) *
2683 (d->sz_ch_source.bottom - d->sz_ch_target.bottom);
2685 if (dx < 0 || dy < 0) {
2686 KillTimer(hwnd, NC_TIMER_SIZER);
2689 SetTimer(hwnd, NC_TIMER_SIZER, d->sz_ch_timeout, NULL);
2694 AdjustWindowRectEx(&r_now, NC_WINDOW_STYLES, FALSE,
2695 NC_WINDOW_EX_STYLES);
2697 SetWindowPos(hwnd, NULL,
2699 r_now.right - r_now.left,
2700 r_now.bottom - r_now.top,
2701 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER |
2704 /* and now we wait for the next timer message */
2707 } else if (wParam == NC_TIMER_ENABLEANIMATE) {
2709 d->animation_enabled = TRUE;
2710 KillTimer(hwnd, NC_TIMER_ENABLEANIMATE);
2716 static LRESULT nc_handle_wm_notify(HWND hwnd,
2722 khui_nc_wnd_data * d;
2724 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2728 nmhdr = (LPNMHDR) lParam;
2730 if (nmhdr->code == TCN_SELCHANGE) {
2731 /* the current tab has changed. */
2735 idx = TabCtrl_GetCurSel(d->tab_wnd);
2736 ZeroMemory(&tcitem, sizeof(tcitem));
2738 tcitem.mask = TCIF_PARAM;
2739 TabCtrl_GetItem(d->tab_wnd, idx, &tcitem);
2741 d->current_panel = (int) tcitem.lParam;
2743 nc_layout_new_cred_window(d);
2751 static LRESULT nc_handle_wm_help(HWND hwnd,
2755 static DWORD ctxids[] = {
2756 NC_TS_CTRL_ID_MIN, IDH_NC_TABMAIN,
2757 NC_TS_CTRL_ID_MIN + 1, IDH_NC_TABBUTTON,
2758 NC_TS_CTRL_ID_MIN + 2, IDH_NC_TABBUTTON,
2759 NC_TS_CTRL_ID_MIN + 3, IDH_NC_TABBUTTON,
2760 NC_TS_CTRL_ID_MIN + 4, IDH_NC_TABBUTTON,
2761 NC_TS_CTRL_ID_MIN + 5, IDH_NC_TABBUTTON,
2762 NC_TS_CTRL_ID_MIN + 6, IDH_NC_TABBUTTON,
2763 NC_TS_CTRL_ID_MIN + 7, IDH_NC_TABBUTTON,
2765 IDCANCEL, IDH_NC_CANCEL,
2766 IDC_NC_HELP, IDH_NC_HELP,
2767 IDC_NC_ADVANCED, IDH_NC_ADVANCED,
2768 IDC_NC_CREDTEXT, IDH_NC_CREDWND,
2775 khui_nc_wnd_data * d;
2777 d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);
2781 hlp = (HELPINFO *) lParam;
2783 if (d->nc->subtype != KMSG_CRED_NEW_CREDS &&
2784 d->nc->subtype != KMSG_CRED_PASSWORD)
2787 if (hlp->iContextType != HELPINFO_WINDOW)
2790 if (hlp->hItemHandle != NULL &&
2791 hlp->hItemHandle != hwnd) {
2795 hw_ctrl =hlp->hItemHandle;
2797 id = GetWindowLong(hw_ctrl, GWL_ID);
2798 for (i=0; ctxids[i] != 0; i += 2)
2799 if (ctxids[i] == id)
2803 hw = khm_html_help(hw_ctrl,
2804 ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
2805 L"::popups_newcreds.txt":
2806 L"::popups_password.txt"),
2808 (DWORD_PTR) ctxids);
2812 khm_html_help(hwnd, NULL, HH_HELP_CONTEXT,
2813 ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?
2814 IDH_ACTION_NEW_ID: IDH_ACTION_PASSWD_ID));
2820 static LRESULT CALLBACK nc_window_proc(HWND hwnd,
2827 return nc_handle_wm_create(hwnd, uMsg, wParam, lParam);
2830 return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam);
2833 return nc_handle_wm_command(hwnd, uMsg, wParam, lParam);
2836 return nc_handle_wm_notify(hwnd, uMsg, wParam, lParam);
2840 return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam);
2843 return nc_handle_wm_timer(hwnd, uMsg, wParam, lParam);
2846 return nc_handle_wm_help(hwnd, uMsg, wParam, lParam);
2848 case KHUI_WM_NC_NOTIFY:
2849 return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam);
2852 /* Note that this is technically a dialog box */
2853 return DefDlgProc(hwnd, uMsg, wParam, lParam);
2856 void khm_register_newcredwnd_class(void)
2860 wcx.cbSize = sizeof(wcx);
2861 wcx.style = CS_DBLCLKS | CS_OWNDC;
2862 wcx.lpfnWndProc = nc_window_proc;
2864 wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);
2865 wcx.hInstance = khm_hInstance;
2866 wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));
2867 wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
2868 wcx.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
2869 wcx.lpszMenuName = NULL;
2870 wcx.lpszClassName = KHUI_NEWCREDWND_CLASS;
2873 khui_newcredwnd_cls = RegisterClassEx(&wcx);
2876 void khm_unregister_newcredwnd_class(void)
2878 UnregisterClass((LPWSTR) khui_newcredwnd_cls, khm_hInstance);
2881 HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c)
2883 wchar_t wtitle[256];
2886 if (c->window_title == NULL) {
2887 if (c->subtype == KMSG_CRED_PASSWORD)
2888 LoadString(khm_hInstance,
2891 ARRAYLENGTH(wtitle));
2893 LoadString(khm_hInstance,
2896 ARRAYLENGTH(wtitle));
2899 hwnd = CreateWindowEx(NC_WINDOW_EX_STYLES,
2900 MAKEINTATOM(khui_newcredwnd_cls),
2901 ((c->window_title)?c->window_title: wtitle),
2903 0,0,400,400, /* bogus values. the window
2904 is going to resize and
2913 assert(hwnd != NULL);
2916 /* note that the window is not visible yet. That's because, at
2917 this point we don't know what the panels are */
2922 void khm_prep_newcredwnd(HWND hwnd)
2924 SendMessage(hwnd, KHUI_WM_NC_NOTIFY,
2925 MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);
2928 void khm_show_newcredwnd(HWND hwnd)
2930 /* add all the panels in and prep UI */
2931 PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
2932 MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 0);