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