NIM - Context sensitive system tray menu and more
[krb5.git] / src / windows / identity / ui / newcredwnd.c
1 /*\r
2  * Copyright (c) 2005 Massachusetts Institute of Technology\r
3  * Copyright (c) 2007 Secure Endpoints Inc.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person\r
6  * obtaining a copy of this software and associated documentation\r
7  * files (the "Software"), to deal in the Software without\r
8  * restriction, including without limitation the rights to use, copy,\r
9  * modify, merge, publish, distribute, sublicense, and/or sell copies\r
10  * of the Software, and to permit persons to whom the Software is\r
11  * furnished to do so, subject to the following conditions:\r
12  *\r
13  * The above copyright notice and this permission notice shall be\r
14  * included in all copies or substantial portions of the Software.\r
15  *\r
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
23  * SOFTWARE.\r
24  */\r
25 \r
26 /* $Id$ */\r
27 \r
28 #include<khmapp.h>\r
29 #include<assert.h>\r
30 \r
31 ATOM khui_newcredwnd_cls;\r
32 \r
33 /* forward dcl */\r
34 static void\r
35 nc_position_credtext(khui_nc_wnd_data * d);\r
36 \r
37 /* Common dialog procedure.  Be careful.  This is used by more than\r
38    one dialog. */\r
39 static INT_PTR CALLBACK \r
40 nc_common_dlg_proc(HWND hwnd,\r
41                    UINT uMsg,\r
42                    WPARAM wParam,\r
43                    LPARAM lParam)\r
44 {\r
45     switch(uMsg) {\r
46     case WM_INITDIALOG:\r
47         {\r
48             khui_nc_wnd_data * d;\r
49 \r
50             d = (khui_nc_wnd_data *) lParam;\r
51 \r
52 #pragma warning(push)\r
53 #pragma warning(disable: 4244)\r
54             SetWindowLongPtr(hwnd, DWLP_USER, lParam);\r
55 #pragma warning(pop)\r
56             if (d->nc->subtype == KMSG_CRED_PASSWORD) {\r
57                 ShowWindow(GetDlgItem(hwnd, IDC_NC_OPTIONS),\r
58                            SW_HIDE);\r
59             }\r
60         }\r
61         return TRUE;\r
62 \r
63     case WM_COMMAND:\r
64         {\r
65             int ctrl_id;\r
66 \r
67             ctrl_id = LOWORD(wParam);\r
68             if (ctrl_id < KHUI_CW_ID_MIN ||\r
69                 ctrl_id > KHUI_CW_ID_MAX) {\r
70                 /* pump it to the parent */\r
71                 PostMessage(GetParent(hwnd), WM_COMMAND, wParam, lParam);\r
72                 return TRUE;\r
73             } /* else we allow the message to fall through and get\r
74                  passed into the identity provider's message\r
75                  handler. */\r
76         }\r
77         break;\r
78 \r
79 #if 0\r
80         /* someday this will be used to draw custom tab buttons.  But\r
81            that's not today */\r
82     case WM_DRAWITEM:\r
83         {\r
84             khui_nc_wnd_data * d;\r
85             int id;\r
86             LPDRAWITEMSTRUCT ds;\r
87 \r
88             d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);\r
89             id = wParam;\r
90             ds = (LPDRAWITEMSTRUCT) lParam;\r
91 \r
92             if(id >= NC_TS_CTRL_ID_MIN && id <= NC_TS_CTRL_ID_MAX) {\r
93                 /*TODO: custom draw the buttons */\r
94             }\r
95             else\r
96                 return FALSE;\r
97         }\r
98         break;\r
99 #endif\r
100 \r
101     case KHUI_WM_NC_NOTIFY:\r
102         {\r
103             khui_nc_wnd_data * d;\r
104             d = (khui_nc_wnd_data *)(LONG_PTR) \r
105                 GetWindowLongPtr(hwnd, DWLP_USER);\r
106 \r
107             /* message sent by parent to notify us of something */\r
108             switch(HIWORD(wParam)) {\r
109             case WMNC_DIALOG_EXPAND:\r
110                 if(hwnd == d->dlg_main) {\r
111                     HWND hw;\r
112                         \r
113                     if(hw = GetDlgItem(hwnd, IDOK))\r
114                         ShowWindow(hw, SW_HIDE);\r
115                     if(hw = GetDlgItem(hwnd, IDCANCEL))\r
116                         ShowWindow(hw, SW_HIDE);\r
117                     if(hw = GetDlgItem(hwnd, IDC_NC_OPTIONS))\r
118                         ShowWindow(hw, SW_HIDE);\r
119 \r
120                     d->r_credtext.bottom = d->r_area.bottom;\r
121 \r
122                     nc_position_credtext(d);\r
123 \r
124                     return TRUE;\r
125                 }\r
126             }\r
127         }\r
128         return TRUE;\r
129     }\r
130 \r
131     /* check if we have a wnd_data, and if so pass the message on to\r
132        the identity provider callback. */\r
133     {\r
134         khui_nc_wnd_data * d;\r
135 \r
136         d = (khui_nc_wnd_data *) (LONG_PTR)\r
137             GetWindowLongPtr(hwnd, DWLP_USER);\r
138 \r
139         if (d && d->nc && d->nc->ident_cb) {\r
140             return d->nc->ident_cb(d->nc, WMNC_IDENT_WMSG, hwnd, uMsg, \r
141                                    wParam, lParam);\r
142         }\r
143     }\r
144 \r
145     return FALSE;\r
146 }\r
147 \r
148 static void\r
149 nc_position_credtext(khui_nc_wnd_data * d)\r
150 {\r
151     HWND hw;\r
152 \r
153     hw = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT);\r
154 #ifdef DEBUG\r
155     assert(hw);\r
156 #endif\r
157 \r
158     if (d->r_credtext.bottom < d->r_credtext.top + d->r_row.bottom * 2) {\r
159         /* not enough room */\r
160         if (d->nc->mode == KHUI_NC_MODE_MINI &&\r
161             d->nc->subtype != KMSG_CRED_PASSWORD) {\r
162             PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,\r
163                         MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);\r
164             return;\r
165         } else {\r
166             ShowWindow(hw, SW_HIDE);\r
167             return;\r
168         }\r
169     } else {\r
170         ShowWindow(hw, SW_SHOW);\r
171     }\r
172 \r
173     SetWindowPos(hw, NULL,\r
174                  d->r_credtext.left + d->r_n_input.left, /* x */\r
175                  d->r_credtext.top, /* y */\r
176                  d->r_n_input.right - d->r_n_input.left, /* width */\r
177                  d->r_credtext.bottom - d->r_credtext.top, /* height */\r
178                  SWP_NOACTIVATE | SWP_NOOWNERZORDER | \r
179                  SWP_NOZORDER);\r
180 \r
181     hw = GetDlgItem(d->dlg_main, IDC_NC_CREDTEXT_LABEL);\r
182 \r
183     SetWindowPos(hw, NULL,\r
184                  d->r_credtext.left + d->r_n_label.left, /* x */\r
185                  d->r_credtext.top, /* y */\r
186                  d->r_n_label.right - d->r_n_label.left, /* width */\r
187                  d->r_n_label.bottom - d->r_n_label.top, /* height */\r
188                  SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
189                  SWP_NOZORDER);\r
190 }\r
191 \r
192 /* sorts tab buttons */\r
193 static int __cdecl \r
194 nc_tab_sort_func(const void * v1, const void * v2)\r
195 {\r
196     /* v1 and v2 and of type : khui_new_creds_by_type ** */\r
197     khui_new_creds_by_type *t1, *t2;\r
198 \r
199     t1 = *((khui_new_creds_by_type **) v1);\r
200     t2 = *((khui_new_creds_by_type **) v2);\r
201 \r
202     if(t1->ordinal !=  -1) {\r
203         if(t2->ordinal != -1) {\r
204             if(t1->ordinal == t2->ordinal)\r
205                 return wcscmp(t1->name, t2->name);\r
206             else\r
207                 /* safe to convert to an int here */\r
208                 return (int) (t1->ordinal - t2->ordinal);\r
209         } else\r
210             return -1;\r
211     } else {\r
212         if(t2->ordinal != -1)\r
213             return 1;\r
214         else if (t1->name && t2->name)\r
215             return wcscmp(t1->name, t2->name);\r
216         else\r
217             return 0;\r
218     }\r
219 }\r
220 \r
221 static void \r
222 nc_notify_types_async(khui_new_creds * c, UINT uMsg,\r
223                       WPARAM wParam, LPARAM lParam)\r
224 {\r
225     khm_size i;\r
226 \r
227     for(i=0; i<c->n_types; i++) {\r
228         PostMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);\r
229     }\r
230 }\r
231 \r
232 static void \r
233 nc_notify_types(khui_new_creds * c, UINT uMsg,\r
234                 WPARAM wParam, LPARAM lParam)\r
235 {\r
236     khm_size i;\r
237 \r
238     for(i=0; i<c->n_types; i++) {\r
239         SendMessage(c->types[i]->hwnd_panel, uMsg, wParam, lParam);\r
240     }\r
241 }\r
242 \r
243 static void\r
244 nc_clear_password_fields(khui_nc_wnd_data * d)\r
245 {\r
246     khm_size i;\r
247     khm_boolean need_sync = FALSE;\r
248 \r
249     khui_cw_lock_nc(d->nc);\r
250 \r
251     for (i=0; i < d->nc->n_prompts; i++) {\r
252         if ((d->nc->prompts[i]->flags & KHUI_NCPROMPT_FLAG_HIDDEN) &&\r
253             d->nc->prompts[i]->hwnd_edit) {\r
254             SetWindowText(d->nc->prompts[i]->hwnd_edit,\r
255                           L"");\r
256             need_sync = TRUE;\r
257         }\r
258     }\r
259 \r
260     khui_cw_unlock_nc(d->nc);\r
261 \r
262     if (need_sync) {\r
263         khui_cw_sync_prompt_values(d->nc);\r
264     }\r
265 }\r
266 \r
267 struct nc_enum_wnd_data {\r
268     khui_nc_wnd_data * d;\r
269     khm_boolean enable;\r
270 };\r
271 \r
272 static\r
273 BOOL CALLBACK\r
274 nc_enum_wnd_proc(HWND hwnd,\r
275                  LPARAM lParam)\r
276 {\r
277     struct nc_enum_wnd_data * wd;\r
278 \r
279     wd = (struct nc_enum_wnd_data *) lParam;\r
280 \r
281     EnableWindow(hwnd, wd->enable);\r
282 \r
283     return TRUE;\r
284 }\r
285 \r
286 static void\r
287 nc_enable_controls(khui_nc_wnd_data * d, khm_boolean enable)\r
288 {\r
289     struct nc_enum_wnd_data wd;\r
290 \r
291     ZeroMemory(&wd, sizeof(wd));\r
292 \r
293     wd.d = d;\r
294     wd.enable = enable;\r
295 \r
296     EnumChildWindows(d->dlg_main, nc_enum_wnd_proc, (LPARAM) &wd);\r
297 }\r
298 \r
299 #define NC_MAXCCH_CREDTEXT 16384\r
300 #define NC_MAXCB_CREDTEXT (NC_MAXCCH_CREDTEXT * sizeof(wchar_t))\r
301 \r
302 static void \r
303 nc_update_credtext(khui_nc_wnd_data * d) \r
304 {\r
305     wchar_t * ctbuf = NULL;\r
306     wchar_t * buf;\r
307     BOOL okEnable = FALSE;\r
308     BOOL validId = FALSE;\r
309     HWND hw = NULL;\r
310     size_t cch = 0;\r
311 \r
312     ctbuf = PMALLOC(NC_MAXCB_CREDTEXT);\r
313 \r
314     assert(ctbuf != NULL);\r
315 \r
316     LoadString(khm_hInstance, IDS_NC_CREDTEXT_TABS, ctbuf, NC_MAXCCH_CREDTEXT);\r
317     StringCchLength(ctbuf, NC_MAXCCH_CREDTEXT, &cch);\r
318     buf = ctbuf + cch;\r
319     nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY, \r
320                     MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), (LPARAM) d->nc);\r
321 \r
322     /* hopefully all the types have updated their credential texts */\r
323     if(d->nc->n_identities == 1) {\r
324         wchar_t main_fmt[256];\r
325         wchar_t id_fmt[256];\r
326         wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];\r
327         wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];\r
328         khm_size cbbuf;\r
329         khm_int32 flags;\r
330 \r
331         LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_ONE, \r
332                    main_fmt, (int) ARRAYLENGTH(main_fmt));\r
333 \r
334         cbbuf = sizeof(id_name);\r
335         kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);\r
336 \r
337         kcdb_identity_get_flags(d->nc->identities[0], &flags);\r
338 \r
339         if (flags & KCDB_IDENT_FLAG_INVALID) {\r
340             LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, \r
341                        id_fmt, (int) ARRAYLENGTH(id_fmt));\r
342         } else if(flags & KCDB_IDENT_FLAG_VALID) {\r
343             LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, \r
344                        id_fmt, (int) ARRAYLENGTH(id_fmt));\r
345         } else if(d->nc->subtype == KMSG_CRED_NEW_CREDS) {\r
346             LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_CHECKING, \r
347                        id_fmt, (int) ARRAYLENGTH(id_fmt));\r
348         } else {\r
349             LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, \r
350                        id_fmt, (int) ARRAYLENGTH(id_fmt));\r
351         }\r
352 \r
353         StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);\r
354 \r
355         StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t), \r
356                        main_fmt, id_string);\r
357 \r
358         if (flags & KCDB_IDENT_FLAG_VALID) {\r
359             if (flags & KCDB_IDENT_FLAG_DEFAULT)\r
360                 LoadString(khm_hInstance, IDS_NC_ID_DEF,\r
361                            id_string, ARRAYLENGTH(id_string));\r
362             else if (d->nc->set_default)\r
363                 LoadString(khm_hInstance, IDS_NC_ID_WDEF,\r
364                            id_string, ARRAYLENGTH(id_string));\r
365             else\r
366                 LoadString(khm_hInstance, IDS_NC_ID_NDEF,\r
367                            id_string, ARRAYLENGTH(id_string));\r
368 \r
369             StringCbCat(buf, NC_MAXCB_CREDTEXT - cch * sizeof(wchar_t),\r
370                         id_string);\r
371         }\r
372 \r
373     } else if(d->nc->n_identities > 1) {\r
374         wchar_t *ids_string;\r
375         khm_size cb_ids_string;\r
376 \r
377         wchar_t id_name[KCDB_IDENT_MAXCCH_NAME];\r
378         wchar_t id_fmt[256];\r
379         wchar_t id_string[KCDB_IDENT_MAXCCH_NAME + 256];\r
380 \r
381         wchar_t main_fmt[256];\r
382         khm_size cbbuf;\r
383 \r
384         LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_MANY, \r
385                    main_fmt, (int) ARRAYLENGTH(main_fmt));\r
386 \r
387         /* we are going to concatenate all the identity names into\r
388            a comma separated string */\r
389 \r
390         /* d->nc->n_identities is at least 2 */\r
391         ids_string = PMALLOC((KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) * \r
392                             (d->nc->n_identities - 1));\r
393         cb_ids_string = \r
394             (KCDB_IDENT_MAXCB_NAME + sizeof(id_fmt)) * \r
395             (d->nc->n_identities - 1);\r
396 \r
397         assert(ids_string != NULL);\r
398 \r
399         ids_string[0] = 0;\r
400 \r
401         {\r
402             khm_size i;\r
403             khm_int32 flags;\r
404 \r
405             for(i=1; i<d->nc->n_identities; i++) {\r
406                 if(i>1) {\r
407                     StringCbCat(ids_string, cb_ids_string, L",");\r
408                 }\r
409 \r
410                 flags = 0;\r
411 \r
412                 cbbuf = sizeof(id_name);\r
413                 kcdb_identity_get_name(d->nc->identities[i], id_name, &cbbuf);\r
414                 kcdb_identity_get_flags(d->nc->identities[i], &flags);\r
415                 if(flags & KCDB_IDENT_FLAG_INVALID) {\r
416                     LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, \r
417                                id_fmt, (int) ARRAYLENGTH(id_fmt));\r
418                 } else if(flags & KCDB_IDENT_FLAG_VALID) {\r
419                     LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, \r
420                                id_fmt, (int) ARRAYLENGTH(id_fmt));\r
421                 } else {\r
422                     LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, \r
423                                id_fmt, (int) ARRAYLENGTH(id_fmt));\r
424                 }\r
425 \r
426                 StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);\r
427                 StringCbCat(ids_string, cb_ids_string, id_string);\r
428             }\r
429 \r
430             cbbuf = sizeof(id_name);\r
431             kcdb_identity_get_name(d->nc->identities[0], id_name, &cbbuf);\r
432             kcdb_identity_get_flags(d->nc->identities[0], &flags);\r
433             if(flags & KCDB_IDENT_FLAG_INVALID) {\r
434                 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_INVALID, \r
435                            id_fmt, (int) ARRAYLENGTH(id_fmt));\r
436             } else if(flags & KCDB_IDENT_FLAG_VALID) {\r
437                 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_VALID, \r
438                            id_fmt, (int) ARRAYLENGTH(id_fmt));\r
439             } else {\r
440                 LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_UNCHECKED, \r
441                            id_fmt, (int) ARRAYLENGTH(id_fmt));\r
442             }\r
443             StringCbPrintf(id_string, sizeof(id_string), id_fmt, id_name);\r
444 \r
445             StringCbPrintf(buf, NC_MAXCB_CREDTEXT - cch*sizeof(wchar_t), \r
446                            main_fmt, id_string, ids_string);\r
447 \r
448             PFREE(ids_string);\r
449         }\r
450     } else {\r
451         LoadString(khm_hInstance, IDS_NC_CREDTEXT_ID_NONE, \r
452                    buf, (int)(NC_MAXCCH_CREDTEXT - cch));\r
453     }\r
454 \r
455     /* now, append the credtext string from each of the cred types */\r
456     {\r
457         khm_size i;\r
458         size_t cb;\r
459         wchar_t * buf;\r
460 \r
461         cb = NC_MAXCB_CREDTEXT;\r
462         buf = ctbuf;\r
463 \r
464         for(i=0; i<d->nc->n_types; i++) {\r
465             if(d->nc->types[i]->credtext != NULL) {\r
466                 StringCbCatEx(buf, cb, \r
467                               d->nc->types[i]->credtext,\r
468                               &buf, &cb,\r
469                               0);\r
470             }\r
471         }\r
472     }\r
473 \r
474     SetDlgItemText(d->dlg_main, IDC_NC_CREDTEXT, ctbuf);\r
475 \r
476     PFREE(ctbuf);\r
477 \r
478     /* so depending on whether the primary identity was found to be\r
479        invalid, we need to disable the Ok button and set the title to\r
480        reflect this */\r
481 \r
482     if(d->nc->n_identities > 0) {\r
483         khm_int32 flags = 0;\r
484 \r
485         if(KHM_SUCCEEDED(kcdb_identity_get_flags(d->nc->identities[0], \r
486                                                &flags)) &&\r
487            (flags & KCDB_IDENT_FLAG_VALID)) {\r
488             validId = TRUE;\r
489         }\r
490     }\r
491 \r
492     if (d->nc->window_title == NULL) {\r
493         if(validId) {\r
494             wchar_t wpostfix[256];\r
495             wchar_t wtitle[KCDB_IDENT_MAXCCH_NAME + 256];\r
496             khm_size cbsize;\r
497 \r
498             cbsize = sizeof(wtitle);\r
499             kcdb_identity_get_name(d->nc->identities[0], wtitle, &cbsize);\r
500 \r
501             if (d->nc->subtype == KMSG_CRED_PASSWORD)\r
502                 LoadString(khm_hInstance, IDS_WTPOST_PASSWORD,\r
503                            wpostfix, (int) ARRAYLENGTH(wpostfix));\r
504             else\r
505                 LoadString(khm_hInstance, IDS_WTPOST_NEW_CREDS, \r
506                            wpostfix, (int) ARRAYLENGTH(wpostfix));\r
507 \r
508             StringCbCat(wtitle, sizeof(wtitle), wpostfix);\r
509 \r
510             SetWindowText(d->nc->hwnd, wtitle);\r
511         } else {\r
512             wchar_t wtitle[256];\r
513 \r
514             if (d->nc->subtype == KMSG_CRED_PASSWORD)\r
515                 LoadString(khm_hInstance, IDS_WT_PASSWORD,\r
516                            wtitle, (int) ARRAYLENGTH(wtitle));\r
517             else\r
518                 LoadString(khm_hInstance, IDS_WT_NEW_CREDS, \r
519                            wtitle, (int) ARRAYLENGTH(wtitle));\r
520 \r
521             SetWindowText(d->nc->hwnd, wtitle);\r
522         }\r
523     }\r
524 \r
525     if (!(d->nc->response & KHUI_NC_RESPONSE_PROCESSING)) {\r
526         if(validId ||\r
527            d->nc->subtype == KMSG_CRED_PASSWORD) {\r
528             /* TODO: check if all the required fields have valid values\r
529                before enabling the Ok button */\r
530             okEnable = TRUE;\r
531         }\r
532 \r
533         hw = GetDlgItem(d->dlg_main, IDOK);\r
534         EnableWindow(hw, okEnable);\r
535         hw = GetDlgItem(d->dlg_bb, IDOK);\r
536         EnableWindow(hw, okEnable);\r
537     }\r
538 }\r
539 \r
540 #define CW_PARAM DWLP_USER\r
541 \r
542 static void\r
543 nc_add_control_row(khui_nc_wnd_data * d, \r
544                    HWND label,\r
545                    HWND input,\r
546                    khui_control_size size);\r
547 \r
548 static LRESULT \r
549 nc_handle_wm_create(HWND hwnd,\r
550                     UINT uMsg,\r
551                     WPARAM wParam,\r
552                     LPARAM lParam)\r
553 {\r
554     LPCREATESTRUCT lpc;\r
555     khui_new_creds * c;\r
556     khui_nc_wnd_data * ncd;\r
557     int x, y;\r
558     int width, height;\r
559     RECT r;\r
560     khm_int32 t;\r
561 \r
562     lpc = (LPCREATESTRUCT) lParam;\r
563 \r
564     ncd = PMALLOC(sizeof(*ncd));\r
565     ZeroMemory(ncd, sizeof(*ncd));\r
566 \r
567     c = (khui_new_creds *) lpc->lpCreateParams;\r
568     ncd->nc = c;\r
569     c->hwnd = hwnd;\r
570 \r
571 #pragma warning(push)\r
572 #pragma warning(disable: 4244)\r
573     SetWindowLongPtr(hwnd, CW_PARAM, (LONG_PTR) ncd);\r
574 #pragma warning(pop)\r
575 \r
576     /* first try to create the main dialog panel */\r
577     \r
578     assert(c->subtype == KMSG_CRED_NEW_CREDS ||\r
579            c->subtype == KMSG_CRED_PASSWORD);\r
580 \r
581     ncd->dlg_main = CreateDialogParam(khm_hInstance,\r
582                                       MAKEINTRESOURCE(IDD_NC_PASSWORD),\r
583                                       hwnd,\r
584                                       nc_common_dlg_proc,\r
585                                       (LPARAM) ncd);\r
586 #ifdef DEBUG\r
587     assert(ncd->dlg_main);\r
588 #endif\r
589 \r
590     {\r
591         RECT r_main;\r
592         RECT r_area;\r
593         RECT r_row;\r
594         HWND hw;\r
595             \r
596         /* pick out metrics for use by the custom prompter stuff */\r
597         GetWindowRect(ncd->dlg_main, &r_main);\r
598 \r
599         hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_PANEL);\r
600 #ifdef DEBUG\r
601         assert(hw);\r
602 #endif\r
603         GetWindowRect(hw, &r_area);\r
604         OffsetRect(&r_area,-r_main.left, -r_main.top);\r
605         CopyRect(&ncd->r_area, &r_area);\r
606 \r
607         hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW);\r
608 #ifdef DEBUG\r
609         assert(hw);\r
610 #endif\r
611         GetWindowRect(hw, &r);\r
612         CopyRect(&r_row, &r);\r
613         OffsetRect(&r,-r.left, -r.top);\r
614         CopyRect(&ncd->r_row, &r);\r
615 \r
616         hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL);\r
617 #ifdef DEBUG\r
618         assert(hw);\r
619 #endif\r
620         GetWindowRect(hw, &r);\r
621         OffsetRect(&r,-r_row.left, -r_row.top);\r
622         CopyRect(&ncd->r_n_label, &r);\r
623 \r
624         hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT);\r
625 #ifdef DEBUG\r
626         assert(hw);\r
627 #endif\r
628         GetWindowRect(hw, &r);\r
629         OffsetRect(&r, -r_row.left, -r_row.top);\r
630         CopyRect(&ncd->r_n_input, &r);\r
631 \r
632         hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_ROW_LG);\r
633 #ifdef DEBUG\r
634         assert(hw);\r
635 #endif\r
636         GetWindowRect(hw, &r_row);\r
637 \r
638         hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_LABEL_LG);\r
639 #ifdef DEBUG\r
640         assert(hw);\r
641 #endif\r
642         GetWindowRect(hw, &r);\r
643         OffsetRect(&r, -r_row.left, -r_row.top);\r
644         CopyRect(&ncd->r_e_label, &r);\r
645 \r
646         hw = GetDlgItem(ncd->dlg_main, IDC_NC_TPL_INPUT_LG);\r
647 #ifdef DEBUG\r
648         assert(hw);\r
649 #endif\r
650         GetWindowRect(hw, &r);\r
651         OffsetRect(&r, -r_row.left, -r_row.top);\r
652         CopyRect(&ncd->r_e_input, &r);\r
653 \r
654         CopyRect(&ncd->r_credtext, &ncd->r_area);\r
655         CopyRect(&ncd->r_idspec, &ncd->r_area);\r
656 \r
657         ncd->r_idspec.bottom = ncd->r_idspec.top;\r
658 \r
659         hw = GetDlgItem(ncd->dlg_main, IDC_NC_CREDTEXT);\r
660 #ifdef DEBUG\r
661         assert(hw);\r
662 #endif\r
663         GetWindowRect(hw, &r);\r
664         OffsetRect(&r, -r_main.left, -r_main.top);\r
665         ncd->r_credtext.bottom = r.bottom;\r
666     }\r
667 \r
668     /* if the mode is 'mini'*/\r
669     r.left = 0;\r
670     r.top = 0;\r
671     if(c->mode == KHUI_NC_MODE_MINI) {\r
672         r.right = NCDLG_WIDTH;\r
673         r.bottom = NCDLG_HEIGHT;\r
674     } else {\r
675         r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;\r
676         r.bottom = NCDLG_HEIGHT + NCDLG_TAB_HEIGHT;\r
677     }\r
678 \r
679     MapDialogRect(ncd->dlg_main, &r);\r
680 \r
681     ncd->r_main.left = 0;\r
682     ncd->r_main.top = 0;\r
683     ncd->r_main.right = NCDLG_WIDTH;\r
684     ncd->r_main.bottom = NCDLG_HEIGHT;\r
685 \r
686     ncd->r_ts.left = 0;\r
687     ncd->r_ts.top = ncd->r_main.bottom;\r
688     ncd->r_ts.right = ncd->r_main.right;\r
689     ncd->r_ts.bottom = ncd->r_ts.top + NCDLG_TAB_HEIGHT;\r
690 \r
691     ncd->r_bb.left = ncd->r_main.right;\r
692     ncd->r_bb.top = 0;\r
693     ncd->r_bb.right = ncd->r_bb.left + NCDLG_BBAR_WIDTH;\r
694     ncd->r_bb.bottom = ncd->r_ts.bottom;\r
695 \r
696     MapDialogRect(ncd->dlg_main, &(ncd->r_main));\r
697     MapDialogRect(ncd->dlg_main, &(ncd->r_ts));\r
698     MapDialogRect(ncd->dlg_main, &(ncd->r_bb));\r
699 \r
700     /* center the new creds window over the main NetIDMgr window */\r
701     width = r.right - r.left;\r
702     height = r.bottom - r.top;\r
703 \r
704     /* adjust width and height to accomodate NC area */\r
705     {\r
706         RECT wr,cr;\r
707 \r
708         GetWindowRect(hwnd, &wr);\r
709         GetClientRect(hwnd, &cr);\r
710 \r
711         /* the non-client and client areas have already been calculated\r
712            at this point.  We just use the difference to adjust the width\r
713            and height */\r
714         width += (wr.right - wr.left) - (cr.right - cr.left);\r
715         height += (wr.bottom - wr.top) - (cr.bottom - cr.top);\r
716     }\r
717 \r
718     GetWindowRect(lpc->hwndParent, &r);\r
719     x = (r.right + r.left)/2 - width / 2;\r
720     y = (r.top + r.bottom)/2 - height / 2;\r
721 \r
722     MoveWindow(hwnd, x, y, width, height, FALSE);\r
723 \r
724     SetWindowPos(ncd->dlg_main, \r
725                  NULL, \r
726                  ncd->r_main.left, \r
727                  ncd->r_main.top,\r
728                  ncd->r_main.right - ncd->r_main.left,\r
729                  ncd->r_main.bottom - ncd->r_main.top,\r
730                  SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | \r
731                  SWP_NOREDRAW | SWP_NOZORDER);\r
732 \r
733     /* IDD_NC_BBAR is the button bar that sits on the right of the\r
734        dialog when the new creds window is in 'expanded' mode. */\r
735 \r
736     ncd->dlg_bb = CreateDialogParam(khm_hInstance,\r
737                                     MAKEINTRESOURCE(IDD_NC_BBAR),\r
738                                     hwnd,\r
739                                     nc_common_dlg_proc,\r
740                                     (LPARAM) ncd);\r
741 \r
742 #ifdef DEBUG\r
743     assert(ncd->dlg_bb);\r
744 #endif\r
745 \r
746     SetWindowPos(ncd->dlg_bb, \r
747                  NULL, \r
748                  ncd->r_bb.left, \r
749                  ncd->r_bb.top,\r
750                  ncd->r_bb.right - ncd->r_bb.left,\r
751                  ncd->r_bb.bottom - ncd->r_bb.top,\r
752                  SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | \r
753                  SWP_NOREDRAW | SWP_NOZORDER);\r
754 \r
755     /* IDD_NC_TS is the tab strip that sits below the main panel when\r
756        the new creds window is in 'expanded' mode */\r
757 \r
758     ncd->dlg_ts = CreateDialogParam(khm_hInstance,\r
759                                     MAKEINTRESOURCE(IDD_NC_TS),\r
760                                     hwnd,\r
761                                     nc_common_dlg_proc,\r
762                                     (LPARAM) ncd);\r
763 \r
764 #ifdef DEBUG\r
765     assert(ncd->dlg_ts);\r
766 #endif\r
767 \r
768     SetWindowPos(ncd->dlg_ts, \r
769                  NULL, \r
770                  ncd->r_ts.left, \r
771                  ncd->r_ts.top,\r
772                  ncd->r_ts.right - ncd->r_ts.left,\r
773                  ncd->r_ts.bottom - ncd->r_ts.top,\r
774                  SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | \r
775                  SWP_NOREDRAW | SWP_NOZORDER);\r
776 \r
777     if(c->mode == KHUI_NC_MODE_MINI) {\r
778         /* hide and show stuff */\r
779         ShowWindow(ncd->dlg_main, SW_SHOW);\r
780         ShowWindow(ncd->dlg_bb, SW_HIDE);\r
781         ShowWindow(ncd->dlg_ts, SW_HIDE);\r
782 \r
783         nc_position_credtext(ncd);\r
784 \r
785     } else {\r
786         /* hide and show stuff */\r
787         ShowWindow(ncd->dlg_main, SW_SHOW);\r
788         ShowWindow(ncd->dlg_bb, SW_SHOW);\r
789         ShowWindow(ncd->dlg_ts, SW_SHOW);\r
790 \r
791         PostMessage(ncd->dlg_main, KHUI_WM_NC_NOTIFY, \r
792                     MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);\r
793     }\r
794 \r
795     /* Call the identity provider callback to set the identity\r
796        selector controls */\r
797     c->ident_cb(c, WMNC_IDENT_INIT, NULL, 0, 0, (LPARAM) ncd->dlg_main);\r
798 \r
799 #if 0\r
800     {\r
801         HWND hw;\r
802         wchar_t wcaption[64];\r
803 \r
804         LoadString(khm_hInstance, IDS_NC_SETDEF, wcaption,\r
805                    ARRAYLENGTH(wcaption));\r
806 \r
807         /* Now create the set as default button */\r
808         hw = CreateWindow\r
809             (L"BUTTON",\r
810              wcaption,\r
811              WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_AUTOCHECKBOX,\r
812              0, 0, 100, 100,\r
813              ncd->dlg_main,\r
814              (HMENU) NC_BN_SET_DEF_ID,\r
815              khm_hInstance,\r
816              NULL);\r
817 \r
818         nc_add_control_row(ncd, NULL, hw, KHUI_CTRLSIZE_HALF);\r
819     }\r
820 #endif\r
821     /* we defer the creation of the tab buttons for later */\r
822 \r
823     /* bring the window to the top, if necessary */\r
824     if (KHM_SUCCEEDED(khc_read_int32(NULL,\r
825                                      L"CredWindow\\Windows\\NewCred\\ForceToTop",\r
826                                      &t)) &&\r
827         t != 0 &&\r
828         !khm_is_dialog_active()) {\r
829 \r
830         /* if the main window is not visible, then the SetWindowPos()\r
831            call is sufficient to bring the new creds window to the\r
832            top.  However, if the main window is visible but not\r
833            active, the main window needs to be activated before a\r
834            child window can be activated. */\r
835         khm_activate_main_window();\r
836 \r
837         SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0,\r
838                      (SWP_NOMOVE | SWP_NOSIZE));\r
839 \r
840     }\r
841 \r
842     /* add this to the dialog chain */\r
843     khm_add_dialog(hwnd);\r
844 \r
845     return TRUE;\r
846 }\r
847 \r
848 static void\r
849 nc_add_control_row(khui_nc_wnd_data * d, \r
850                    HWND label,\r
851                    HWND input,\r
852                    khui_control_size size)\r
853 {\r
854     RECT r_row;\r
855     RECT r_label;\r
856     RECT r_input;\r
857     HFONT hf;\r
858 \r
859     hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
860     SendMessage(label, WM_SETFONT, (WPARAM) hf, FALSE);\r
861     SendMessage(input, WM_SETFONT, (WPARAM) hf, FALSE);\r
862 \r
863     CopyRect(&r_row, &d->r_row);\r
864     OffsetRect(&r_row, d->r_idspec.left, d->r_idspec.bottom);\r
865 \r
866     if (size == KHUI_CTRLSIZE_SMALL) {\r
867         CopyRect(&r_label, &d->r_n_label);\r
868         CopyRect(&r_input, &d->r_n_input);\r
869         OffsetRect(&r_label, r_row.left, r_row.top);\r
870         OffsetRect(&r_input, r_row.left, r_row.top);\r
871     } else if (size == KHUI_CTRLSIZE_HALF) {\r
872         CopyRect(&r_label, &d->r_e_label);\r
873         CopyRect(&r_input, &d->r_e_input);\r
874         OffsetRect(&r_label, r_row.left, r_row.top);\r
875         OffsetRect(&r_input, r_row.left, r_row.top);\r
876     } else if (size == KHUI_CTRLSIZE_FULL) {\r
877         CopyRect(&r_label, &d->r_n_label);\r
878         r_label.right = d->r_row.right;\r
879         CopyRect(&r_input, &d->r_n_input);\r
880         OffsetRect(&r_input, r_row.left, r_row.top);\r
881         OffsetRect(&r_input, 0, r_input.bottom);\r
882         r_row.bottom += r_input.bottom;\r
883         OffsetRect(&r_label, r_row.left, r_row.top);\r
884     } else {\r
885         SetRectEmpty(&r_label);\r
886         SetRectEmpty(&r_input);\r
887 #ifdef DEBUG\r
888         assert(FALSE);\r
889 #endif\r
890         return;\r
891     }\r
892 \r
893     if (label)\r
894         SetWindowPos(label,\r
895                      ((d->hwnd_last_idspec != NULL)?\r
896                       d->hwnd_last_idspec:\r
897                       HWND_TOP),\r
898                      r_label.left, r_label.top,\r
899                      r_label.right - r_label.left,\r
900                      r_label.bottom - r_label.top,\r
901                      SWP_DEFERERASE | SWP_NOACTIVATE |\r
902                      SWP_NOOWNERZORDER);\r
903 \r
904     if (input)\r
905         SetWindowPos(input,\r
906                      (label ? label : ((d->hwnd_last_idspec != NULL)?\r
907                                        d->hwnd_last_idspec:\r
908                                        HWND_TOP)),\r
909                      r_input.left, r_input.top,\r
910                      r_input.right - r_input.left,\r
911                      r_input.bottom - r_input.top,\r
912                      SWP_DEFERERASE | SWP_NOACTIVATE |\r
913                      SWP_NOOWNERZORDER);\r
914 \r
915     d->hwnd_last_idspec = input;\r
916 \r
917     d->r_idspec.bottom = r_row.bottom;\r
918 \r
919     d->r_credtext.top = r_row.bottom;\r
920 \r
921     nc_position_credtext(d);\r
922 }\r
923 \r
924 \r
925 static LRESULT \r
926 nc_handle_wm_destroy(HWND hwnd,\r
927                      UINT uMsg,\r
928                      WPARAM wParam,\r
929                      LPARAM lParam)\r
930 {\r
931     khui_nc_wnd_data * d;\r
932     khm_size i;\r
933 \r
934     /* remove self from dialog chain */\r
935     khm_del_dialog(hwnd);\r
936 \r
937     d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
938 \r
939     d->nc->ident_cb(d->nc, WMNC_IDENT_EXIT, NULL, 0, 0, 0);\r
940 \r
941     if(d->hwnd_tc_main)\r
942         DestroyWindow(d->hwnd_tc_main);\r
943     for(i=0;i<d->nc->n_types;i++) {\r
944         if(d->nc->types[i]->hwnd_tc) {\r
945             DestroyWindow(d->nc->types[i]->hwnd_tc);\r
946             d->nc->types[i]->hwnd_tc = NULL;\r
947         }\r
948     }\r
949 \r
950     if(d->dlg_bb)\r
951         DestroyWindow(d->dlg_bb);\r
952     if(d->dlg_main)\r
953         DestroyWindow(d->dlg_main);\r
954     if(d->dlg_ts)\r
955         DestroyWindow(d->dlg_ts);\r
956 \r
957     d->dlg_bb = NULL;\r
958     d->dlg_main = NULL;\r
959     d->dlg_ts = NULL;\r
960 \r
961     PFREE(d);\r
962 \r
963     return TRUE;\r
964 }\r
965 \r
966 static LRESULT \r
967 nc_handle_wm_command(HWND hwnd,\r
968                      UINT uMsg,\r
969                      WPARAM wParam,\r
970                      LPARAM lParam)\r
971 {\r
972     khui_nc_wnd_data * d;\r
973     int id;\r
974 \r
975     d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
976 \r
977     switch(HIWORD(wParam)) {\r
978     case BN_CLICKED:\r
979         switch(LOWORD(wParam)) {\r
980 \r
981         case IDOK:\r
982             d->nc->result = KHUI_NC_RESULT_PROCESS;\r
983 \r
984             /* fallthrough */\r
985 \r
986         case IDCANCEL:\r
987             /* the default value for d->nc->result is set to\r
988                KHUI_NC_RESULT_CANCEL */\r
989             d->nc->response = KHUI_NC_RESPONSE_PROCESSING;\r
990 \r
991             nc_enable_controls(d, FALSE);\r
992 \r
993             nc_notify_types(d->nc, \r
994                             KHUI_WM_NC_NOTIFY, \r
995                             MAKEWPARAM(0,WMNC_DIALOG_PREPROCESS), \r
996                             (LPARAM) d->nc);\r
997 \r
998             khui_cw_sync_prompt_values(d->nc);\r
999 \r
1000             khm_cred_dispatch_process_message(d->nc);\r
1001 \r
1002             /* we won't know whether to abort or not until we get\r
1003                feedback from the plugins, even if the command was\r
1004                to cancel */\r
1005             {\r
1006                 HWND hw;\r
1007 \r
1008                 hw = GetDlgItem(d->dlg_main, IDOK);\r
1009                 EnableWindow(hw, FALSE);\r
1010                 hw = GetDlgItem(d->dlg_main, IDCANCEL);\r
1011                 EnableWindow(hw, FALSE);\r
1012                 hw = GetDlgItem(d->dlg_main, IDC_NC_OPTIONS);\r
1013                 EnableWindow(hw, FALSE);\r
1014                 hw = GetDlgItem(d->dlg_bb, IDOK);\r
1015                 EnableWindow(hw, FALSE);\r
1016                 hw = GetDlgItem(d->dlg_bb, IDCANCEL);\r
1017                 EnableWindow(hw, FALSE);\r
1018             }\r
1019             return FALSE;\r
1020 \r
1021         case IDC_NC_HELP:\r
1022             khm_html_help(hwnd, NULL, HH_HELP_CONTEXT, IDH_ACTION_NEW_ID);\r
1023             return FALSE;\r
1024 \r
1025         case IDC_NC_OPTIONS: \r
1026             /* the Options button in the main window was clicked.  we\r
1027                respond by expanding the dialog. */\r
1028             PostMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
1029                         MAKEWPARAM(0, WMNC_DIALOG_EXPAND), 0);\r
1030             return FALSE;\r
1031 \r
1032         case IDC_NC_CREDTEXT: /* credtext link activated */\r
1033             {\r
1034                 khui_htwnd_link * l;\r
1035                 wchar_t sid[KHUI_MAXCCH_HTLINK_FIELD];\r
1036                 wchar_t sparam[KHUI_MAXCCH_HTLINK_FIELD];\r
1037                 wchar_t * colon;\r
1038 \r
1039                 l = (khui_htwnd_link *) lParam;\r
1040 \r
1041                 /* do we have a valid link? */\r
1042                 if(l->id == NULL || l->id_len >= ARRAYLENGTH(sid))\r
1043                     return TRUE; /* nope */\r
1044 \r
1045                 StringCchCopyN(sid, ARRAYLENGTH(sid), l->id, l->id_len);\r
1046                 sid[l->id_len] = L'\0'; /* just make sure */\r
1047 \r
1048                 if(l->param != NULL && \r
1049                    l->param_len < ARRAYLENGTH(sparam) &&\r
1050                    l->param_len > 0) {\r
1051 \r
1052                     StringCchCopyN(sparam, ARRAYLENGTH(sparam),\r
1053                                    l->param, l->param_len);\r
1054                     sparam[l->param_len] = L'\0';\r
1055 \r
1056                 } else {\r
1057                     sparam[0] = L'\0';\r
1058                 }\r
1059 \r
1060                 /* If the ID is of the form '<credtype>:<link_tag>'\r
1061                    and <credtype> is a valid name of a credentials\r
1062                    type that is participating in the credentials\r
1063                    acquisition process, then we forward the message to\r
1064                    the panel that is providing the UI for that cred\r
1065                    type.  We also switch to that panel first, unless\r
1066                    the link is of the form '<credtype>:!<link_tag>'. */\r
1067 \r
1068                 colon = wcschr(sid, L':');\r
1069                 if (colon != NULL) {\r
1070                     khm_int32 credtype;\r
1071                     khui_new_creds_by_type * t;\r
1072 \r
1073                     *colon = L'\0';\r
1074                     if (KHM_SUCCEEDED(kcdb_credtype_get_id(sid, &credtype)) &&\r
1075                         KHM_SUCCEEDED(khui_cw_find_type(d->nc, credtype, &t))){\r
1076                         *colon = L':';\r
1077 \r
1078                         if (t->ordinal != d->ctab &&\r
1079                             *(colon + 1) != L'!')\r
1080                             PostMessage(hwnd,\r
1081                                         KHUI_WM_NC_NOTIFY,\r
1082                                         MAKEWPARAM(t->ordinal,\r
1083                                                    WMNC_DIALOG_SWITCH_PANEL),\r
1084                                         0);\r
1085 \r
1086                         return SendMessage(t->hwnd_panel,\r
1087                                            KHUI_WM_NC_NOTIFY,\r
1088                                            MAKEWPARAM(0, WMNC_CREDTEXT_LINK),\r
1089                                            lParam);\r
1090                     } else {\r
1091                         *colon = L':';\r
1092                     }\r
1093                 }\r
1094 \r
1095                 /* if it was for us, then we need to process the message */\r
1096                 if(!_wcsicmp(sid, CTLINKID_SWITCH_PANEL)) {\r
1097                     khm_int32 credtype;\r
1098                     khui_new_creds_by_type * t;\r
1099 \r
1100                     if (KHM_SUCCEEDED(kcdb_credtype_get_id(sparam, \r
1101                                                            &credtype)) &&\r
1102                         KHM_SUCCEEDED(khui_cw_find_type(d->nc,\r
1103                                                         credtype, &t))) {\r
1104                         if (t->ordinal != d->ctab)\r
1105                             PostMessage(hwnd,\r
1106                                         KHUI_WM_NC_NOTIFY,\r
1107                                         MAKEWPARAM(t->ordinal,\r
1108                                                    WMNC_DIALOG_SWITCH_PANEL),\r
1109                                         0);\r
1110                     }\r
1111                 } else if (!_wcsicmp(sid, L"NotDef")) {\r
1112                     d->nc->set_default = FALSE;\r
1113                     nc_update_credtext(d);\r
1114                 } else if (!_wcsicmp(sid, L"MakeDef")) {\r
1115                     d->nc->set_default = TRUE;\r
1116                     nc_update_credtext(d);\r
1117                 }\r
1118             }\r
1119             return FALSE;\r
1120 \r
1121 #if 0\r
1122         case NC_BN_SET_DEF_ID:\r
1123             {\r
1124                 d->nc->set_default =\r
1125                     (IsDlgButtonChecked(d->dlg_main, NC_BN_SET_DEF_ID)\r
1126                      == BST_CHECKED);\r
1127             }\r
1128             return FALSE;\r
1129 #endif\r
1130 \r
1131         default:\r
1132             /* if one of the tab strip buttons were pressed, then\r
1133                we should switch to that panel */\r
1134             id = LOWORD(wParam);\r
1135             if(id >= NC_TS_CTRL_ID_MIN && id <= NC_TS_CTRL_ID_MAX) {\r
1136                 id -= NC_TS_CTRL_ID_MIN;\r
1137                 PostMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
1138                             MAKEWPARAM(id, WMNC_DIALOG_SWITCH_PANEL),0);\r
1139                 return FALSE;\r
1140             }\r
1141         }\r
1142         break;\r
1143     }\r
1144 \r
1145     return TRUE;\r
1146 }\r
1147 \r
1148 static LRESULT nc_handle_wm_moving(HWND hwnd,\r
1149                                    UINT uMsg,\r
1150                                    WPARAM wParam,\r
1151                                    LPARAM lParam)\r
1152 {\r
1153     khui_nc_wnd_data * d;\r
1154 \r
1155     d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
1156 \r
1157     nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY, \r
1158                     MAKEWPARAM(0, WMNC_DIALOG_MOVE), (LPARAM) d->nc);\r
1159 \r
1160     return FALSE;\r
1161 }\r
1162 \r
1163 static LRESULT nc_handle_wm_nc_notify(HWND hwnd,\r
1164                                UINT uMsg,\r
1165                                WPARAM wParam,\r
1166                                LPARAM lParam)\r
1167 {\r
1168     khui_nc_wnd_data * d;\r
1169     RECT r;\r
1170     int width, height;\r
1171     khm_size id;\r
1172 \r
1173     d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
1174 \r
1175     switch(HIWORD(wParam)) {\r
1176 \r
1177     case WMNC_DIALOG_SWITCH_PANEL:\r
1178         id = LOWORD(wParam);\r
1179         if(id >= 0 && id <= d->nc->n_types) {\r
1180             /* one of the tab buttons were pressed */\r
1181             if(d->ctab == id) {\r
1182                 return TRUE; /* nothign to do */\r
1183             }\r
1184 \r
1185             if(d->ctab == 0) {\r
1186                 ShowWindow(d->dlg_main, SW_HIDE);\r
1187                 SendMessage(d->hwnd_tc_main, \r
1188                             BM_SETCHECK, BST_UNCHECKED, 0);\r
1189             } else {\r
1190                 ShowWindow(d->nc->types[d->ctab - 1]->hwnd_panel, SW_HIDE);\r
1191                 SendMessage(d->nc->types[d->ctab - 1]->hwnd_tc, \r
1192                             BM_SETCHECK, BST_UNCHECKED, 0);\r
1193             }\r
1194 \r
1195             d->ctab = id;\r
1196 \r
1197             if(d->ctab == 0) {\r
1198                 ShowWindow(d->dlg_main, SW_SHOW);\r
1199                 SendMessage(d->hwnd_tc_main, \r
1200                             BM_SETCHECK, BST_CHECKED, 0);\r
1201             } else {\r
1202                 ShowWindow(d->nc->types[id - 1]->hwnd_panel, SW_SHOW);\r
1203                 SendMessage(d->nc->types[id - 1]->hwnd_tc, \r
1204                             BM_SETCHECK, BST_CHECKED, 0);\r
1205             }\r
1206         }\r
1207 \r
1208         if(d->nc->mode == KHUI_NC_MODE_EXPANDED)\r
1209             return TRUE;\r
1210         /*else*/\r
1211         /* fallthrough */\r
1212 \r
1213     case WMNC_DIALOG_EXPAND:\r
1214         /* we are expanding the dialog box */\r
1215 \r
1216         /* nothing to do? */\r
1217         if (d->nc->mode == KHUI_NC_MODE_EXPANDED)\r
1218             break;\r
1219 \r
1220         d->nc->mode = KHUI_NC_MODE_EXPANDED;\r
1221 \r
1222         r.top = 0;\r
1223         r.left = 0;\r
1224         r.right = NCDLG_WIDTH + NCDLG_BBAR_WIDTH;\r
1225         r.bottom = NCDLG_HEIGHT + NCDLG_TAB_HEIGHT;\r
1226 \r
1227         MapDialogRect(d->dlg_main, &r);\r
1228 \r
1229         width = r.right - r.left;\r
1230         height = r.bottom - r.top;\r
1231 \r
1232         /* adjust width and height to accomodate NC area */\r
1233         {\r
1234             RECT wr,cr;\r
1235 \r
1236             GetWindowRect(hwnd, &wr);\r
1237             GetClientRect(hwnd, &cr);\r
1238 \r
1239             /* the non-client and client areas have already been\r
1240                calculated at this point.  We just use the difference\r
1241                to adjust the width and height */\r
1242             width += (wr.right - wr.left) - (cr.right - cr.left);\r
1243             height += (wr.bottom - wr.top) - (cr.bottom - cr.top);\r
1244         }\r
1245 \r
1246         SendMessage(d->dlg_main, \r
1247                     KHUI_WM_NC_NOTIFY, \r
1248                     MAKEWPARAM(0,WMNC_DIALOG_EXPAND), \r
1249                     0);\r
1250 \r
1251         SetWindowPos(hwnd, \r
1252                      NULL, \r
1253                      0, 0, \r
1254                      width, height, \r
1255                      SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER | \r
1256                      SWP_NOZORDER);\r
1257 \r
1258         ShowWindow(d->dlg_bb, SW_SHOW);\r
1259         ShowWindow(d->dlg_ts, SW_SHOW);\r
1260         break;\r
1261 \r
1262     case WMNC_DIALOG_SETUP:\r
1263         if(d->nc->n_types > 0) {\r
1264             khm_size i;\r
1265             for(i=0; i < d->nc->n_types;i++) {\r
1266 \r
1267                 if (d->nc->types[i]->dlg_proc == NULL) {\r
1268                     d->nc->types[i]->hwnd_panel = NULL;\r
1269                 } else {\r
1270                     /* Create the dialog panel */\r
1271                     d->nc->types[i]->hwnd_panel = \r
1272                         CreateDialogParam(d->nc->types[i]->h_module,\r
1273                                           d->nc->types[i]->dlg_template,\r
1274                                           d->nc->hwnd,\r
1275                                           d->nc->types[i]->dlg_proc,\r
1276                                           (LPARAM) d->nc);\r
1277 \r
1278 #ifdef DEBUG\r
1279                     assert(d->nc->types[i]->hwnd_panel);\r
1280 #endif\r
1281                 }\r
1282             }\r
1283         }\r
1284         break;\r
1285 \r
1286     case WMNC_DIALOG_ACTIVATE:\r
1287         {\r
1288             int x,y,width,height;\r
1289             RECT r;\r
1290             int id;\r
1291             wchar_t wbuf[256];\r
1292             HFONT hf;\r
1293 \r
1294             /* now we create all the tab strip controls */\r
1295             r.left = 0;\r
1296             r.top = 0;\r
1297             r.right = NCDLG_TAB_WIDTH;\r
1298             r.bottom = NCDLG_TAB_HEIGHT;\r
1299             MapDialogRect(d->dlg_main, &r);\r
1300 \r
1301             width = r.right - r.left;\r
1302             height = r.bottom - r.top;\r
1303 \r
1304             x = 0;\r
1305             y = 0;\r
1306 \r
1307             id = NC_TS_CTRL_ID_MIN;\r
1308 \r
1309             /* if we have too many buttons than would fit on the\r
1310                button bar, we have to adjust the width of the buttons.\r
1311                Of course, having too many of them would be bad and\r
1312                make the buttons fairly useless.  This is just an\r
1313                interim measure. */\r
1314 \r
1315             khui_cw_lock_nc(d->nc);\r
1316 \r
1317             GetWindowRect(d->dlg_ts, &r);\r
1318             if (x + width * (d->nc->n_types + 1) > (khm_size) (r.right - r.left)) {\r
1319                 width = (int)(((r.right - r.left) - x) / (d->nc->n_types + 1));\r
1320             }\r
1321 \r
1322             /* first, the control for the main panel */\r
1323             LoadString(khm_hInstance, IDS_NC_IDENTITY, \r
1324                        wbuf, ARRAYLENGTH(wbuf));\r
1325 \r
1326             d->hwnd_tc_main = \r
1327                 CreateWindow(L"BUTTON",\r
1328                              wbuf,\r
1329                              WS_VISIBLE | WS_CHILD | WS_TABSTOP |\r
1330                              BS_PUSHLIKE | BS_CHECKBOX | BS_TEXT,\r
1331                              x,y,width,height,\r
1332                              d->dlg_ts,\r
1333                              (HMENU)(INT_PTR) id,\r
1334                              khm_hInstance,\r
1335                              NULL);\r
1336 \r
1337             hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
1338             SendMessage(d->hwnd_tc_main, WM_SETFONT, (WPARAM) hf, 0);\r
1339             SendMessage(d->hwnd_tc_main, BM_SETCHECK, BST_CHECKED, 0);\r
1340 \r
1341             id++;\r
1342             x += width;\r
1343 \r
1344             if(d->nc->n_types > 0) {\r
1345                 khm_size i;\r
1346                 /* we should sort the tabs first */\r
1347                 qsort(d->nc->types, \r
1348                       d->nc->n_types, \r
1349                       sizeof(*(d->nc->types)), \r
1350                       nc_tab_sort_func);\r
1351 \r
1352                 for(i=0; i < d->nc->n_types;i++) {\r
1353                     wchar_t * name = NULL;\r
1354 \r
1355                     d->nc->types[i]->ordinal = i + 1;\r
1356 \r
1357                     if(d->nc->types[i]->name)\r
1358                         name = d->nc->types[i]->name;\r
1359                     else {\r
1360                         khm_size cbsize;\r
1361 \r
1362                         if(kcdb_credtype_describe\r
1363                            (d->nc->types[i]->type, \r
1364                             NULL, \r
1365                             &cbsize, \r
1366                             KCDB_TS_SHORT) == KHM_ERROR_TOO_LONG) {\r
1367 \r
1368                             name = PMALLOC(cbsize);\r
1369                             kcdb_credtype_describe(d->nc->types[i]->type, \r
1370                                                    name, \r
1371                                                    &cbsize, \r
1372                                                    KCDB_TS_SHORT);\r
1373                         } else {\r
1374 #ifdef DEBUG\r
1375                             assert(FALSE);\r
1376 #endif\r
1377                             continue;\r
1378                         }\r
1379                     }\r
1380 \r
1381                     d->nc->types[i]->hwnd_tc = \r
1382                         CreateWindow(L"BUTTON",\r
1383                                      name,\r
1384                                      WS_VISIBLE | WS_CHILD | WS_TABSTOP |\r
1385                                      BS_PUSHLIKE | BS_CHECKBOX | BS_TEXT |\r
1386                                      ((d->nc->types[i]->hwnd_panel == NULL)? \r
1387                                       WS_DISABLED : 0),\r
1388                                      x,y,width,height,\r
1389                                      d->dlg_ts,\r
1390                                      (HMENU)(INT_PTR) id,\r
1391                                      khm_hInstance,\r
1392                                      NULL);\r
1393 \r
1394                     SendMessage(d->nc->types[i]->hwnd_tc, WM_SETFONT, \r
1395                                 (WPARAM)hf, 0);\r
1396 \r
1397 #if 0\r
1398                     if(d->nc->types[i]->flags & KHUI_NCT_FLAG_DISABLED)\r
1399                         SendMessage(d->nc->types[i]->hwnd_tc, \r
1400                                     BM_SETIMAGE, \r
1401                                     IMAGE_ICON, \r
1402                                     LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_DISABLED)));\r
1403                     else\r
1404                         SendMessage(d->nc->types[i]->hwnd_tc, \r
1405                                     BM_SETIMAGE, \r
1406                                     IMAGE_ICON, \r
1407                                     LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_ENABLED)));\r
1408 #endif\r
1409 \r
1410                     id++;\r
1411                     x += width;\r
1412 \r
1413                     if(!(d->nc->types[i]->name))\r
1414                         PFREE(name);\r
1415 \r
1416                     /* Now set the position of the type panel */\r
1417                     ShowWindow(d->nc->types[i]->hwnd_panel, SW_HIDE);\r
1418                     SetWindowPos(d->nc->types[i]->hwnd_panel, \r
1419                                  NULL,\r
1420                                  d->r_main.left, \r
1421                                  d->r_main.top,\r
1422                                  d->r_main.right - d->r_main.left,\r
1423                                  d->r_main.bottom - d->r_main.top,\r
1424                                  SWP_DEFERERASE | SWP_NOACTIVATE | \r
1425                                  SWP_NOOWNERZORDER | SWP_NOREDRAW | \r
1426                                  SWP_NOZORDER);\r
1427 \r
1428                 }\r
1429             }\r
1430 \r
1431             khui_cw_unlock_nc(d->nc);\r
1432 \r
1433             nc_update_credtext(d);\r
1434 \r
1435             ShowWindow(hwnd, SW_SHOWNOACTIVATE);\r
1436             SetFocus(hwnd);\r
1437 \r
1438             if (d->nc->n_identities == 0)\r
1439                 break;\r
1440             /* else */\r
1441             /*   fallthrough */\r
1442         }\r
1443 \r
1444     case WMNC_IDENTITY_CHANGE:\r
1445         {\r
1446             BOOL okEnable = FALSE;\r
1447 \r
1448             nc_notify_types(d->nc, KHUI_WM_NC_NOTIFY,\r
1449                             MAKEWPARAM(0, WMNC_IDENTITY_CHANGE), (LPARAM) d->nc);\r
1450 \r
1451             if (d->nc->subtype == KMSG_CRED_NEW_CREDS &&\r
1452                 d->nc->n_identities > 0 &&\r
1453                 d->nc->identities[0]) {\r
1454                 khm_int32 f = 0;\r
1455 \r
1456                 kcdb_identity_get_flags(d->nc->identities[0], &f);\r
1457 \r
1458                 if (!(f & KCDB_IDENT_FLAG_DEFAULT)) {\r
1459                     d->nc->set_default = FALSE;\r
1460                 }\r
1461             }\r
1462 \r
1463             nc_update_credtext(d);\r
1464 \r
1465         }\r
1466         break;\r
1467 \r
1468     case WMNC_TYPE_STATE:\r
1469         /* fallthrough */\r
1470     case WMNC_UPDATE_CREDTEXT:\r
1471         nc_update_credtext(d);\r
1472         break;\r
1473 \r
1474     case WMNC_CLEAR_PROMPTS:\r
1475         {\r
1476             khm_size i;\r
1477 \r
1478             khui_cw_lock_nc(d->nc);\r
1479 \r
1480             if(d->hwnd_banner != NULL) {\r
1481                 DestroyWindow(d->hwnd_banner);\r
1482                 d->hwnd_banner = NULL;\r
1483             }\r
1484 \r
1485             if(d->hwnd_name != NULL) {\r
1486                 DestroyWindow(d->hwnd_name);\r
1487                 d->hwnd_name = NULL;\r
1488             }\r
1489 \r
1490             for(i=0;i<d->nc->n_prompts;i++) {\r
1491                 if(!(d->nc->prompts[i]->flags & \r
1492                      KHUI_NCPROMPT_FLAG_STOCK)) {\r
1493                     if(d->nc->prompts[i]->hwnd_static != NULL)\r
1494                         DestroyWindow(d->nc->prompts[i]->hwnd_static);\r
1495 \r
1496                     if(d->nc->prompts[i]->hwnd_edit != NULL)\r
1497                         DestroyWindow(d->nc->prompts[i]->hwnd_edit);\r
1498                 }\r
1499 \r
1500                 d->nc->prompts[i]->hwnd_static = NULL;\r
1501                 d->nc->prompts[i]->hwnd_edit = NULL;\r
1502             }\r
1503 \r
1504             khui_cw_unlock_nc(d->nc);\r
1505 \r
1506             d->r_credtext.top = d->r_idspec.bottom;\r
1507 \r
1508             nc_position_credtext(d);\r
1509         }\r
1510         break;\r
1511 \r
1512     case WMNC_SET_PROMPTS:\r
1513         {\r
1514             khm_size i;\r
1515             int  y;\r
1516             HWND hw, hw_prev;\r
1517             HFONT hf, hfold;\r
1518             HDC hdc;\r
1519             BOOL use_large_lables = FALSE;\r
1520 \r
1521             /* we assume that WMNC_CLEAR_PROMPTS has already been\r
1522                received */\r
1523 \r
1524             khui_cw_lock_nc(d->nc);\r
1525 \r
1526 #if 0\r
1527             /* special case, we have one prompt and it is a password\r
1528                prompt.  very common */\r
1529             if(d->nc->n_prompts == 1 && \r
1530                d->nc->prompts[0]->type == KHUI_NCPROMPT_TYPE_PASSWORD) {\r
1531 \r
1532                 hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);\r
1533                 EnableWindow(hw, TRUE);\r
1534 \r
1535                 d->nc->prompts[0]->flags |= KHUI_NCPROMPT_FLAG_STOCK;\r
1536                 d->nc->prompts[0]->hwnd_edit = hw;\r
1537                 d->nc->prompts[0]->hwnd_static = NULL; /* don't care */\r
1538 \r
1539                 khui_cw_unlock_nc(d->nc);\r
1540                 break;\r
1541             }\r
1542 #endif\r
1543             /* for everything else */\r
1544 \r
1545             /* hide the stock password controls */\r
1546 #if 0\r
1547             /* TAGREMOVE */\r
1548             hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD);\r
1549             ShowWindow(hw, SW_HIDE);\r
1550             hw = GetDlgItem(d->dlg_main, IDC_NC_PASSWORD_LABEL);\r
1551             ShowWindow(hw, SW_HIDE);\r
1552 #endif\r
1553 \r
1554             y = d->r_idspec.bottom;\r
1555 \r
1556             hf = (HFONT) SendMessage(d->dlg_main, WM_GETFONT, 0, 0);\r
1557 \r
1558             if (d->nc->pname != NULL) {\r
1559                 hw =\r
1560                     CreateWindowEx\r
1561                     (0,\r
1562                      L"STATIC",\r
1563                      d->nc->pname,\r
1564                      SS_SUNKEN | WS_CHILD,\r
1565                      d->r_area.left, y,\r
1566                      d->r_row.right, \r
1567                      d->r_n_label.bottom - d->r_n_label.top,\r
1568                      d->dlg_main,\r
1569                      NULL,\r
1570                      khm_hInstance,\r
1571                      NULL);\r
1572 \r
1573 #ifdef DEBUG\r
1574                 assert(hw);\r
1575 #endif\r
1576                 d->hwnd_name = hw;\r
1577                 SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM) TRUE);\r
1578                 ShowWindow(hw, SW_SHOW);\r
1579 \r
1580                 y += d->r_n_label.bottom - d->r_n_label.top;\r
1581             }\r
1582 \r
1583             if (d->nc->banner != NULL) {\r
1584                 hw = \r
1585                     CreateWindowEx\r
1586                     (0,\r
1587                      L"STATIC",\r
1588                      d->nc->banner,\r
1589                      WS_CHILD,\r
1590                      d->r_area.left, y,\r
1591                      d->r_row.right, d->r_row.bottom,\r
1592                      d->dlg_main,\r
1593                      NULL,\r
1594                      khm_hInstance,\r
1595                      NULL);\r
1596 #ifdef DEBUG\r
1597                 assert(hw);\r
1598 #endif\r
1599                 d->hwnd_banner = hw;\r
1600                 SendMessage(hw, WM_SETFONT, (WPARAM)hf, (LPARAM)TRUE);\r
1601                 ShowWindow(hw, SW_SHOW);\r
1602                 y += d->r_row.bottom;\r
1603             }\r
1604 \r
1605             hw_prev = d->hwnd_last_idspec;\r
1606 \r
1607             hdc = GetWindowDC(d->dlg_main);\r
1608             hfold = SelectObject(hdc,hf);\r
1609 \r
1610             /* first do a trial run and see if we should use the\r
1611                larger text labels or not.  This is so that all the\r
1612                labels and input controls align properly. */\r
1613             for (i=0; i < d->nc->n_prompts; i++) {\r
1614                 if (d->nc->prompts[i]->prompt != NULL) {\r
1615                     SIZE s;\r
1616 \r
1617                     GetTextExtentPoint32(hdc, \r
1618                                          d->nc->prompts[i]->prompt, \r
1619                                          (int) wcslen(d->nc->prompts[i]->prompt),\r
1620                                          &s);\r
1621 \r
1622                     if(s.cx >= d->r_n_label.right - d->r_n_label.left) {\r
1623                         use_large_lables = TRUE;\r
1624                         break;\r
1625                     }\r
1626                 }\r
1627             }\r
1628 \r
1629             for(i=0; i<d->nc->n_prompts; i++) {\r
1630                 RECT pr, er;\r
1631                 SIZE s;\r
1632                 int dy;\r
1633 \r
1634                 if(d->nc->prompts[i]->prompt != NULL) {\r
1635                     GetTextExtentPoint32(hdc, \r
1636                                          d->nc->prompts[i]->prompt, \r
1637                                          (int) wcslen(d->nc->prompts[i]->prompt),\r
1638                                          &s);\r
1639                     if(s.cx < d->r_n_label.right - d->r_n_label.left &&\r
1640                        !use_large_lables) {\r
1641                         CopyRect(&pr, &d->r_n_label);\r
1642                         CopyRect(&er, &d->r_n_input);\r
1643                         dy = d->r_row.bottom;\r
1644                     } else if(s.cx <\r
1645                               d->r_e_label.right - d->r_e_label.left) {\r
1646                         CopyRect(&pr, &d->r_e_label);\r
1647                         CopyRect(&er, &d->r_e_input);\r
1648                         dy = d->r_row.bottom;\r
1649                     } else {\r
1650                         /* oops. the prompt doesn't fit in our\r
1651                            controls.  we need to use up two lines */\r
1652                         pr.left = 0;\r
1653                         pr.right = d->r_row.right;\r
1654                         pr.top = 0;\r
1655                         pr.bottom = d->r_n_label.bottom - \r
1656                             d->r_n_label.top;\r
1657                         CopyRect(&er, &d->r_n_input);\r
1658                         OffsetRect(&er, 0, pr.bottom);\r
1659                         dy = er.bottom + (d->r_row.bottom - \r
1660                                           d->r_n_input.bottom);\r
1661                     }\r
1662                 } else {\r
1663                     SetRectEmpty(&pr);\r
1664                     CopyRect(&er, &d->r_n_input);\r
1665                     dy = d->r_row.bottom;\r
1666                 }\r
1667 \r
1668                 if(IsRectEmpty(&pr)) {\r
1669                     d->nc->prompts[i]->hwnd_static = NULL;\r
1670                 } else {\r
1671                     OffsetRect(&pr, d->r_area.left, y);\r
1672 \r
1673                     hw = CreateWindowEx\r
1674                         (0,\r
1675                          L"STATIC",\r
1676                          d->nc->prompts[i]->prompt,\r
1677                          WS_CHILD,\r
1678                          pr.left, pr.top,\r
1679                          pr.right - pr.left, pr.bottom - pr.top,\r
1680                          d->dlg_main,\r
1681                          NULL,\r
1682                          khm_hInstance,\r
1683                          NULL);\r
1684 #ifdef DEBUG\r
1685                     assert(hw);\r
1686 #endif\r
1687 \r
1688                     SendMessage(hw, WM_SETFONT, \r
1689                                 (WPARAM) hf, (LPARAM) TRUE);\r
1690 \r
1691                     SetWindowPos(hw, hw_prev,\r
1692                                  0, 0, 0, 0,\r
1693                                  SWP_NOACTIVATE | SWP_NOMOVE |\r
1694                                  SWP_NOOWNERZORDER | SWP_NOSIZE |\r
1695                                  SWP_SHOWWINDOW);\r
1696 \r
1697                     d->nc->prompts[i]->hwnd_static = hw;\r
1698                     hw_prev = hw;\r
1699                 }\r
1700 \r
1701                 OffsetRect(&er, d->r_area.left, y);\r
1702 \r
1703                 hw = CreateWindowEx\r
1704                     (0,\r
1705                      L"EDIT",\r
1706                      (d->nc->prompts[i]->def ? \r
1707                       d->nc->prompts[i]->def : L""),\r
1708                      WS_CHILD | WS_TABSTOP |\r
1709                      WS_BORDER |\r
1710                      ((d->nc->prompts[i]->flags & \r
1711                        KHUI_NCPROMPT_FLAG_HIDDEN)? ES_PASSWORD:0),\r
1712                      er.left, er.top,\r
1713                      er.right - er.left, er.bottom - er.top,\r
1714                      d->dlg_main,\r
1715                      NULL,\r
1716                      khm_hInstance,\r
1717                      NULL);\r
1718 \r
1719 #ifdef DEBUG\r
1720                 assert(hw);\r
1721 #endif\r
1722 \r
1723                 SendMessage(hw, WM_SETFONT, \r
1724                             (WPARAM) hf, (LPARAM) TRUE);\r
1725 \r
1726                 SetWindowPos(hw, hw_prev,\r
1727                              0, 0, 0, 0, \r
1728                              SWP_NOACTIVATE | SWP_NOMOVE | \r
1729                              SWP_NOOWNERZORDER | SWP_NOSIZE | \r
1730                              SWP_SHOWWINDOW);\r
1731 \r
1732                 SendMessage(hw, EM_SETLIMITTEXT,\r
1733                             KHUI_MAXCCH_PROMPT_VALUE -1,\r
1734                             0);\r
1735 \r
1736                 d->nc->prompts[i]->hwnd_edit = hw;\r
1737 \r
1738                 hw_prev = hw;\r
1739 \r
1740                 y += dy;\r
1741             }\r
1742 \r
1743             if (d->nc->n_prompts > 0 &&\r
1744                 d->nc->prompts[0]->hwnd_edit) {\r
1745 \r
1746                 SetFocus(d->nc->prompts[0]->hwnd_edit);\r
1747 \r
1748             }\r
1749 \r
1750             SelectObject(hdc, hfold);\r
1751             ReleaseDC(d->dlg_main, hdc);\r
1752 \r
1753             khui_cw_unlock_nc(d->nc);\r
1754 \r
1755             d->r_credtext.top = y;\r
1756 \r
1757             nc_position_credtext(d);\r
1758         }\r
1759         break;\r
1760 \r
1761     case WMNC_DIALOG_PROCESS_COMPLETE:\r
1762         {\r
1763             khui_new_creds * nc;\r
1764 \r
1765             nc = d->nc;\r
1766 \r
1767             nc->response &= ~KHUI_NC_RESPONSE_PROCESSING;\r
1768 \r
1769             if(nc->response & KHUI_NC_RESPONSE_NOEXIT) {\r
1770                 HWND hw;\r
1771 \r
1772                 nc_enable_controls(d, TRUE);\r
1773 \r
1774                 /* reset state */\r
1775                 nc->result = KHUI_NC_RESULT_CANCEL;\r
1776 \r
1777                 hw = GetDlgItem(d->dlg_main, IDOK);\r
1778                 EnableWindow(hw, TRUE);\r
1779                 hw = GetDlgItem(d->dlg_main, IDCANCEL);\r
1780                 EnableWindow(hw, TRUE);\r
1781                 hw = GetDlgItem(d->dlg_main, IDC_NC_OPTIONS);\r
1782                 EnableWindow(hw, TRUE);\r
1783                 hw = GetDlgItem(d->dlg_bb, IDOK);\r
1784                 EnableWindow(hw, TRUE);\r
1785                 hw = GetDlgItem(d->dlg_bb, IDCANCEL);\r
1786                 EnableWindow(hw, TRUE);\r
1787 \r
1788                 nc_clear_password_fields(d);\r
1789 \r
1790                 return TRUE;\r
1791             }\r
1792 \r
1793             DestroyWindow(hwnd);\r
1794 \r
1795             kmq_post_message(KMSG_CRED, KMSG_CRED_END, 0, (void *) nc);\r
1796         }\r
1797         break;\r
1798 \r
1799         /* MUST be called with SendMessage */\r
1800     case WMNC_ADD_CONTROL_ROW:\r
1801         {\r
1802             khui_control_row * row;\r
1803 \r
1804             row = (khui_control_row *) lParam;\r
1805 \r
1806 #ifdef DEBUG\r
1807             assert(row->label);\r
1808             assert(row->input);\r
1809 #endif\r
1810 \r
1811             nc_add_control_row(d, row->label, row->input, row->size);\r
1812         }\r
1813         break;\r
1814     } /* switch(HIWORD(wParam)) */\r
1815 \r
1816     return TRUE;\r
1817 }\r
1818 \r
1819 static LRESULT nc_handle_wm_help(HWND hwnd,\r
1820                                  UINT uMsg,\r
1821                                  WPARAM wParam,\r
1822                                  LPARAM lParam) {\r
1823     static DWORD ctxids[] = {\r
1824         NC_TS_CTRL_ID_MIN, IDH_NC_TABMAIN,\r
1825         NC_TS_CTRL_ID_MIN + 1, IDH_NC_TABBUTTON,\r
1826         NC_TS_CTRL_ID_MIN + 2, IDH_NC_TABBUTTON,\r
1827         NC_TS_CTRL_ID_MIN + 3, IDH_NC_TABBUTTON,\r
1828         NC_TS_CTRL_ID_MIN + 4, IDH_NC_TABBUTTON,\r
1829         NC_TS_CTRL_ID_MIN + 5, IDH_NC_TABBUTTON,\r
1830         NC_TS_CTRL_ID_MIN + 6, IDH_NC_TABBUTTON,\r
1831         NC_TS_CTRL_ID_MIN + 7, IDH_NC_TABBUTTON,\r
1832         IDOK, IDH_NC_OK,\r
1833         IDCANCEL, IDH_NC_CANCEL,\r
1834         IDC_NC_HELP, IDH_NC_HELP,\r
1835         IDC_NC_OPTIONS, IDH_NC_OPTIONS,\r
1836         IDC_NC_CREDTEXT, IDH_NC_CREDWND,\r
1837         0\r
1838     };\r
1839 \r
1840     HELPINFO * hlp;\r
1841     HWND hw = NULL;\r
1842     HWND hw_ctrl;\r
1843     khui_nc_wnd_data * d;\r
1844 \r
1845     d = (khui_nc_wnd_data *)(LONG_PTR) GetWindowLongPtr(hwnd, CW_PARAM);\r
1846 \r
1847     hlp = (HELPINFO *) lParam;\r
1848 \r
1849     if (d->nc->subtype != KMSG_CRED_NEW_CREDS &&\r
1850         d->nc->subtype != KMSG_CRED_PASSWORD)\r
1851         return TRUE;\r
1852 \r
1853     if (hlp->iContextType != HELPINFO_WINDOW)\r
1854         return TRUE;\r
1855 \r
1856     if (hlp->hItemHandle != NULL &&\r
1857         hlp->hItemHandle != hwnd) {\r
1858         DWORD id;\r
1859         int i;\r
1860 \r
1861         hw_ctrl =hlp->hItemHandle;\r
1862 \r
1863         id = GetWindowLong(hw_ctrl, GWL_ID);\r
1864         for (i=0; ctxids[i] != 0; i += 2)\r
1865             if (ctxids[i] == id)\r
1866                 break;\r
1867 \r
1868         if (ctxids[i] != 0)\r
1869             hw = khm_html_help(hw_ctrl,\r
1870                                ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?\r
1871                                 L"::popups_newcreds.txt":\r
1872                                 L"::popups_password.txt"),\r
1873                                HH_TP_HELP_WM_HELP,\r
1874                                (DWORD_PTR) ctxids);\r
1875     }\r
1876 \r
1877     if (hw == NULL) {\r
1878         khm_html_help(hwnd, NULL, HH_HELP_CONTEXT,\r
1879                       ((d->nc->subtype == KMSG_CRED_NEW_CREDS)?\r
1880                        IDH_ACTION_NEW_ID: IDH_ACTION_PASSWD_ID));\r
1881     }\r
1882 \r
1883     return TRUE;\r
1884 }\r
1885 \r
1886 static LRESULT CALLBACK nc_window_proc(HWND hwnd,\r
1887                                        UINT uMsg,\r
1888                                        WPARAM wParam,\r
1889                                        LPARAM lParam)\r
1890 {\r
1891     switch(uMsg) {\r
1892     case WM_CREATE:\r
1893         return nc_handle_wm_create(hwnd, uMsg, wParam, lParam);\r
1894 \r
1895     case WM_DESTROY:\r
1896         return nc_handle_wm_destroy(hwnd, uMsg, wParam, lParam);\r
1897 \r
1898     case WM_COMMAND:\r
1899         return nc_handle_wm_command(hwnd, uMsg, wParam, lParam);\r
1900 \r
1901     case WM_MOVE:\r
1902     case WM_MOVING:\r
1903         return nc_handle_wm_moving(hwnd, uMsg, wParam, lParam);\r
1904 \r
1905     case WM_HELP:\r
1906         return nc_handle_wm_help(hwnd, uMsg, wParam, lParam);\r
1907 \r
1908     case KHUI_WM_NC_NOTIFY:\r
1909         return nc_handle_wm_nc_notify(hwnd, uMsg, wParam, lParam);\r
1910     }\r
1911 \r
1912     /* Note that this is technically a dialog box */\r
1913     return DefDlgProc(hwnd, uMsg, wParam, lParam);\r
1914 }\r
1915 \r
1916 void khm_register_newcredwnd_class(void)\r
1917 {\r
1918     WNDCLASSEX wcx;\r
1919 \r
1920     wcx.cbSize = sizeof(wcx);\r
1921     wcx.style = CS_DBLCLKS | CS_OWNDC;\r
1922     wcx.lpfnWndProc = nc_window_proc;\r
1923     wcx.cbClsExtra = 0;\r
1924     wcx.cbWndExtra = DLGWINDOWEXTRA + sizeof(LONG_PTR);\r
1925     wcx.hInstance = khm_hInstance;\r
1926     wcx.hIcon = LoadIcon(khm_hInstance, MAKEINTRESOURCE(IDI_MAIN_APP));\r
1927     wcx.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);\r
1928     wcx.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);\r
1929     wcx.lpszMenuName = NULL;\r
1930     wcx.lpszClassName = KHUI_NEWCREDWND_CLASS;\r
1931     wcx.hIconSm = NULL;\r
1932 \r
1933     khui_newcredwnd_cls = RegisterClassEx(&wcx);\r
1934 }\r
1935 \r
1936 void khm_unregister_newcredwnd_class(void)\r
1937 {\r
1938     UnregisterClass((LPWSTR) khui_newcredwnd_cls, khm_hInstance);\r
1939 }\r
1940 \r
1941 HWND khm_create_newcredwnd(HWND parent, khui_new_creds * c)\r
1942 {\r
1943     wchar_t wtitle[256];\r
1944     HWND hwnd;\r
1945 \r
1946     if (c->window_title == NULL) {\r
1947         if (c->subtype == KMSG_CRED_PASSWORD)\r
1948             LoadString(khm_hInstance, \r
1949                        IDS_WT_PASSWORD,\r
1950                        wtitle,\r
1951                        ARRAYLENGTH(wtitle));\r
1952         else\r
1953             LoadString(khm_hInstance, \r
1954                        IDS_WT_NEW_CREDS,\r
1955                        wtitle,\r
1956                        ARRAYLENGTH(wtitle));\r
1957     }\r
1958 \r
1959     hwnd = CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_CONTEXTHELP,\r
1960                           MAKEINTATOM(khui_newcredwnd_cls),\r
1961                           ((c->window_title)?c->window_title: wtitle),\r
1962                           WS_DLGFRAME | WS_POPUPWINDOW | WS_CLIPCHILDREN,\r
1963                           0,0,400,400,    /* bogus values.  the window\r
1964                                              is going to resize and\r
1965                                              reposition itself\r
1966                                              anyway */\r
1967                           parent,\r
1968                           NULL,\r
1969                           khm_hInstance,\r
1970                           (LPVOID) c);\r
1971 \r
1972 #ifdef DEBUG\r
1973     assert(hwnd != NULL);\r
1974 #endif\r
1975 \r
1976     /* note that the window is not visible yet.  That's because, at\r
1977        this point we don't know what the panels are */\r
1978 \r
1979     return hwnd;\r
1980 }\r
1981 \r
1982 void khm_prep_newcredwnd(HWND hwnd)\r
1983 {\r
1984     SendMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
1985                 MAKEWPARAM(0, WMNC_DIALOG_SETUP), 0);\r
1986 }\r
1987 \r
1988 void khm_show_newcredwnd(HWND hwnd)\r
1989 {\r
1990     /* add all the panels in and prep UI */\r
1991     SendMessage(hwnd, KHUI_WM_NC_NOTIFY, \r
1992                 MAKEWPARAM(0, WMNC_DIALOG_ACTIVATE), 0);\r
1993 }\r