ntmakefile-clean-20040401
[openafs.git] / src / WINNT / afsusrmgr / usr_prop.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include "TaAfsUsrMgr.h"
16 #include "usr_prop.h"
17 #include "usr_cpw.h"
18 #include "usr_col.h"
19 #include "winlist.h"
20 #include "browse.h"
21
22
23 /*
24  * DEFINITIONS ________________________________________________________________
25  *
26  */
27
28 #define cdayPWEXPIRATION_MAX   254
29
30 #define cFAILLOCKCOUNT_MAX     254
31
32 #define csecFAILLOCK_MAX   (csec1HOUR * 36L)
33
34 #define GWD_ASIDLIST_MEMBER   TEXT("AsidList - Members")
35 #define GWD_ASIDLIST_OWNER    TEXT("AsidList - Owned")
36
37
38 /*
39  * PROTOTYPES _________________________________________________________________
40  *
41  */
42
43 BOOL CALLBACK UserProp_General_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
44 void UserProp_General_OnInitDialog (HWND hDlg);
45 void UserProp_General_OnDestroy (HWND hDlg);
46 void UserProp_General_OnUnlock (HWND hDlg);
47 void UserProp_General_OnChangePwNow (HWND hDlg);
48 void UserProp_General_OnChangePw (HWND hDlg);
49 void UserProp_General_OnPwExpires (HWND hDlg);
50 void UserProp_General_OnFailLock (HWND hDlg);
51 void UserProp_General_OnFailLockTime (HWND hDlg);
52 void UserProp_General_OnApply (HWND hDlg);
53 void UserProp_General_UpdateDialog (HWND hDlg);
54 void UserProp_General_OnExpiration (HWND hDlg);
55
56 BOOL CALLBACK UserProp_Advanced_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
57 void UserProp_Advanced_OnInitDialog (HWND hDlg);
58 void UserProp_Advanced_OnDestroy (HWND hDlg);
59 void UserProp_Advanced_OnGrantTickets (HWND hDlg);
60 void UserProp_Advanced_OnHasGroupQuota (HWND hDlg);
61 void UserProp_Advanced_OnAdmin (HWND hDlg);
62 void UserProp_Advanced_OnApply (HWND hDlg);
63 void UserProp_Advanced_UpdateDialog (HWND hDlg);
64 void UserProp_Advanced_UpdateDialog_Perm (HWND hDlg, int idc, ACCOUNTACCESS aa, BOOL fMixed);
65
66 BOOL CALLBACK UserProp_Member_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
67 void UserProp_Member_OnInitDialog (HWND hDlg);
68 void UserProp_Member_OnDestroy (HWND hDlg);
69 void UserProp_Member_OnShowType (HWND hDlg);
70 void UserProp_Member_OnSelect (HWND hDlg);
71 void UserProp_Member_OnApply (HWND hDlg);
72 void UserProp_Member_OnAdd (HWND hDlg);
73 void UserProp_Member_OnRemove (HWND hDlg);
74 void UserProp_Member_OnEndTask_GroupSearch (HWND hDlg, LPTASKPACKET ptp);
75 void UserProp_Member_PopulateList (HWND hDlg);
76
77 void UserProp_UpdateName (HWND hDlg);
78
79
80 /*
81  * ROUTINES ___________________________________________________________________
82  *
83  */
84
85 void User_FreeProperties (LPUSERPROPINFO lpp)
86 {
87    if (lpp)
88       {
89       if ((lpp->fApplyAdvanced || lpp->fApplyGeneral) && lpp->pUserList)
90          {
91
92          // See if we have anything to scare the user about. If the
93          // "afs", "authserver" or "krbtgt" accounts have any modified
94          // properties, there may be reason for concern.
95          //
96          BOOL fMakeChanges = TRUE;
97
98          if (lpp->fApplyGeneral || lpp->fApplyAdvanced)
99             {
100             for (size_t ii = 0; ii < lpp->pUserList->cEntries; ++ii)
101                {
102                TCHAR szUser[ cchRESOURCE ];
103                asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->pUserList->aEntries[ ii ].idObject, szUser);
104
105                if ( (!lstrcmpi (szUser, TEXT("afs"))) ||
106                     (!lstrcmpi (szUser, TEXT("AuthServer"))) ||
107                     (!lstrcmpi (szUser, TEXT("krbtgt"))) )
108                   {
109                   if (Message (MB_ICONASTERISK | MB_YESNO | MB_DEFBUTTON2, IDS_WARNING_TITLE, IDS_WARNING_SYSTEM_ACCOUNT, TEXT("%s"), szUser) != IDYES)
110                      {
111                      fMakeChanges = FALSE;
112                      break;
113                      }
114                   }
115                }
116             }
117
118          if (fMakeChanges)
119             {
120             for (size_t ii = 0; ii < lpp->pUserList->cEntries; ++ii)
121                {
122                ULONG status;
123                ASOBJPROP Properties;
124                if (!asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, lpp->pUserList->aEntries[ ii ].idObject, &Properties, &status))
125                   continue;
126
127                LPUSER_CHANGE_PARAMS pTask = New (USER_CHANGE_PARAMS);
128                memset (pTask, 0x00, sizeof(USER_CHANGE_PARAMS));
129                pTask->idUser = lpp->pUserList->aEntries[ ii ].idObject;
130
131                // From Advanced tab:
132
133                if (!lpp->fApplyAdvanced || lpp->fSeal_Mixed)
134                   pTask->NewProperties.fEncrypt = Properties.u.UserProperties.KASINFO.fEncrypt;
135                else
136                   pTask->NewProperties.fEncrypt = lpp->fSeal;
137
138                if (!lpp->fApplyAdvanced || lpp->fAdmin_Mixed)
139                   pTask->NewProperties.fIsAdmin = Properties.u.UserProperties.KASINFO.fIsAdmin;
140                else
141                   pTask->NewProperties.fIsAdmin = lpp->fAdmin;
142
143                if (!lpp->fApplyAdvanced || lpp->fGrantTickets_Mixed)
144                   pTask->NewProperties.fCanGetTickets = Properties.u.UserProperties.KASINFO.fCanGetTickets;
145                else
146                   pTask->NewProperties.fCanGetTickets = lpp->fGrantTickets;
147
148                if (!lpp->fApplyAdvanced || lpp->fGrantTickets_Mixed)
149                   pTask->NewProperties.csecTicketLifetime = Properties.u.UserProperties.KASINFO.csecTicketLifetime;
150                else if (!lpp->fGrantTickets)
151                   pTask->NewProperties.csecTicketLifetime = 0;
152                else
153                   pTask->NewProperties.csecTicketLifetime = lpp->csecLifetime;
154
155                if (!lpp->fApplyAdvanced || lpp->fGroupQuota_Mixed)
156                   pTask->NewProperties.cgroupCreationQuota = Properties.u.UserProperties.PTSINFO.cgroupCreationQuota;
157                else
158                   pTask->NewProperties.cgroupCreationQuota = lpp->cGroupQuota;
159
160                if (!lpp->fApplyAdvanced || lpp->fStatus_Mixed)
161                   pTask->NewProperties.aaListStatus = Properties.u.UserProperties.PTSINFO.aaListStatus;
162                else
163                   pTask->NewProperties.aaListStatus = lpp->aaStatus;
164
165                if (!lpp->fApplyAdvanced || lpp->fOwned_Mixed)
166                   pTask->NewProperties.aaGroupsOwned = Properties.u.UserProperties.PTSINFO.aaGroupsOwned;
167                else
168                   pTask->NewProperties.aaGroupsOwned = lpp->aaOwned;
169
170                if (!lpp->fApplyAdvanced || lpp->fMember_Mixed)
171                   pTask->NewProperties.aaMembership = Properties.u.UserProperties.PTSINFO.aaMembership;
172                else
173                   pTask->NewProperties.aaMembership = lpp->aaMember;
174
175                // From General tab:
176
177                if (!lpp->fApplyGeneral || lpp->fCanChangePw_Mixed)
178                   pTask->NewProperties.fCanChangePassword = Properties.u.UserProperties.KASINFO.fCanChangePassword;
179                else
180                   pTask->NewProperties.fCanChangePassword = lpp->fCanChangePw;
181
182                if (!lpp->fApplyGeneral || lpp->fCanReusePw_Mixed)
183                   pTask->NewProperties.fCanReusePasswords = Properties.u.UserProperties.KASINFO.fCanReusePasswords;
184                else
185                   pTask->NewProperties.fCanReusePasswords = lpp->fCanReusePw;
186
187                if (!lpp->fApplyGeneral || lpp->fPwExpires_Mixed)
188                   pTask->NewProperties.cdayPwExpire = Properties.u.UserProperties.KASINFO.cdayPwExpire;
189                else
190                   pTask->NewProperties.cdayPwExpire = lpp->cdayPwExpires;
191
192                if (!lpp->fApplyGeneral || lpp->fExpires_Mixed)
193                   memcpy (&pTask->NewProperties.timeExpires, &Properties.u.UserProperties.KASINFO.timeExpires, sizeof(SYSTEMTIME));
194                else if (!lpp->fExpires)
195                   memset (&pTask->NewProperties.timeExpires, 0x00, sizeof(SYSTEMTIME));
196                else // (lpp->fExpires)
197                   memcpy (&pTask->NewProperties.timeExpires, &lpp->stExpires, sizeof(SYSTEMTIME));
198
199                if (!lpp->fApplyGeneral || lpp->fFailLock_Mixed)
200                   pTask->NewProperties.cFailLogin = Properties.u.UserProperties.KASINFO.cFailLogin;
201                else
202                   pTask->NewProperties.cFailLogin = lpp->cFailLock;
203
204                if (!lpp->fApplyGeneral || lpp->fFailLock_Mixed)
205                   pTask->NewProperties.csecFailLoginLock = Properties.u.UserProperties.KASINFO.csecFailLoginLock;
206                else
207                   pTask->NewProperties.csecFailLoginLock = lpp->csecFailLock;
208
209                StartTask (taskUSER_CHANGE, NULL, pTask);
210                }
211             }
212          }
213
214       if (lpp->pGroupsMember)
215          asc_AsidListFree (&lpp->pGroupsMember);
216       if (lpp->pGroupsOwner)
217          asc_AsidListFree (&lpp->pGroupsOwner);
218       if (lpp->pUserList)
219          asc_AsidListFree (&lpp->pUserList);
220       memset (lpp, 0x00, sizeof(USERPROPINFO));
221       Delete (lpp);
222       }
223 }
224
225
226 void User_ShowProperties (LPASIDLIST pUserList, USERPROPTAB uptTarget)
227 {
228    LPUSERPROPINFO lpp = New (USERPROPINFO);
229    memset (lpp, 0x00, sizeof(USERPROPINFO));
230    lpp->pUserList = pUserList;
231    lpp->fDeleteMeOnClose = TRUE;
232    lpp->fShowModal = FALSE;
233
234    if (pUserList && pUserList->cEntries)
235       lpp->fMachine = fIsMachineAccount (pUserList->aEntries[0].idObject);
236
237    User_ShowProperties (lpp, uptTarget);
238 }
239
240
241 void User_ShowProperties (LPUSERPROPINFO lpp, USERPROPTAB uptTarget)
242 {
243    HWND hSheet = NULL;
244
245    // If we've been asked to view properties for only one user, and there is
246    // already a window open for that user, switch to it.
247    //
248    if (lpp->pUserList)
249       {
250       if (lpp->pUserList->cEntries == 1)
251          {
252          ASID idUser = lpp->pUserList->aEntries[0].idObject;
253
254          if ((hSheet = WindowList_Search (wltUSER_PROPERTIES, idUser)) != NULL)
255             {
256             SetForegroundWindow (hSheet);
257             if (uptTarget != uptANY)
258                {
259                HWND hTab = GetDlgItem (hSheet, IDC_PROPSHEET_TABCTRL);
260                int nTabs = TabCtrl_GetItemCount (hTab);
261                if (nTabs < nUSERPROPTAB_MAX)
262                   uptTarget = (USERPROPTAB)( ((int)uptTarget-1) );
263                TabCtrl_SwitchToTab (hTab, uptTarget);
264                }
265             return;
266             }
267          }
268
269       // Otherwise, make sure there are no Properties windows open for any
270       // of the selected users
271       //
272       for (size_t iUser = 0; iUser < lpp->pUserList->cEntries; ++iUser)
273          {
274          ASID idUser = lpp->pUserList->aEntries[ iUser ].idObject;
275
276          // See if there's a Properties window open that is dedicated to
277          // this user
278          //
279          if ((hSheet = WindowList_Search (wltUSER_PROPERTIES, idUser)) != NULL)
280             {
281             ErrorDialog (0, IDS_ERROR_USER_MULTIPROP);
282             return;
283             }
284
285          // See if there is a multiple-user properties window open; if so,
286          // test it to see if it covers this user
287          //
288          if ((hSheet = WindowList_Search (wltUSER_PROPERTIES, 0)) != NULL)
289             {
290             LPUSERPROPINFO pInfo = (LPUSERPROPINFO)PropSheet_FindTabParam (hSheet);
291             if (pInfo && pInfo->pUserList && asc_AsidListTest (&pInfo->pUserList, idUser))
292                {
293                ErrorDialog (0, IDS_ERROR_USER_MULTIPROP);
294                return;
295                }
296             }
297          }
298       }
299
300    // Okay, we're clear to create the new properties window.
301    //
302    LPTSTR pszTitle;
303    if (!lpp->pUserList)
304       {
305       if (lpp->fMachine)
306          pszTitle = FormatString (IDS_NEWMACHINE_PROPERTIES_TITLE);
307       else
308          pszTitle = FormatString (IDS_NEWUSER_PROPERTIES_TITLE);
309       }
310    else if (lpp->pUserList->cEntries > 1)
311       {
312       if (lpp->fMachine)
313          pszTitle = FormatString (IDS_MACHINE_PROPERTIES_TITLE_MULTIPLE);
314       else
315          pszTitle = FormatString (IDS_USER_PROPERTIES_TITLE_MULTIPLE);
316       }
317    else
318       {
319       TCHAR szUser[ cchRESOURCE ];
320       User_GetDisplayName (szUser, lpp->pUserList->aEntries[0].idObject);
321       if (lpp->fMachine)
322          pszTitle = FormatString (IDS_MACHINE_PROPERTIES_TITLE, TEXT("%s"), szUser);
323       else
324          pszTitle = FormatString (IDS_USER_PROPERTIES_TITLE, TEXT("%s"), szUser);
325       }
326
327    if (lpp->fMachine && (uptTarget == uptGENERAL))
328       uptTarget = uptADVANCED;
329
330    LPPROPSHEET psh = PropSheet_Create (pszTitle, TRUE, lpp->hParent, (LPARAM)lpp);
331    if (!lpp->fMachine)
332       PropSheet_AddTab (psh, 0, (lpp->pUserList) ? IDD_USER_GENERAL : IDD_NEWUSER_GENERAL, (DLGPROC)UserProp_General_DlgProc, (LPARAM)lpp, TRUE, (uptTarget == uptGENERAL) ? TRUE : FALSE);
333    PropSheet_AddTab (psh, 0, (lpp->pUserList) ? (lpp->fMachine ? IDD_MACHINE_ADVANCED : IDD_USER_ADVANCED) : (lpp->fMachine ? IDD_NEWMACHINE_ADVANCED : IDD_NEWUSER_ADVANCED), (DLGPROC)UserProp_Advanced_DlgProc, (LPARAM)lpp, TRUE, (uptTarget == uptADVANCED) ? TRUE : FALSE);
334    PropSheet_AddTab (psh, 0, (lpp->pUserList) ? (lpp->fMachine ? IDD_MACHINE_MEMBER : IDD_USER_MEMBER) : (lpp->fMachine ? IDD_NEWMACHINE_MEMBER : IDD_NEWUSER_MEMBER), (DLGPROC)UserProp_Member_DlgProc, (LPARAM)lpp, TRUE, (uptTarget == uptMEMBERSHIP) ? TRUE : FALSE);
335
336    if (lpp->fShowModal)
337       PropSheet_ShowModal (psh, PumpMessage);
338    else
339       PropSheet_ShowModeless (psh, SW_SHOW);
340 }
341
342
343 BOOL CALLBACK UserProp_General_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
344 {
345    if (AfsAppLib_HandleHelp (IDD_USER_GENERAL, hDlg, msg, wp, lp))
346       return TRUE;
347
348    switch (msg)
349       {
350       case WM_INITDIALOG:
351          UserProp_General_OnInitDialog (hDlg);
352          break;
353
354       case WM_DESTROY:
355          UserProp_General_OnDestroy (hDlg);
356          break;
357
358       case WM_ASC_NOTIFY_OBJECT:
359          UserProp_General_UpdateDialog (hDlg);
360          break;
361
362       case WM_COMMAND:
363          switch (LOWORD(wp))
364             {
365             case IDAPPLY:
366                UserProp_General_OnApply (hDlg);
367                break;
368
369             case IDC_USER_UNLOCK:
370                UserProp_General_OnUnlock (hDlg);
371                break;
372
373             case IDC_USER_CPW_NOW:
374                UserProp_General_OnChangePwNow (hDlg);
375                break;
376
377             case IDC_USER_CPW:
378                UserProp_General_OnChangePw (hDlg);
379                PropSheetChanged (hDlg);
380                break;
381
382             case IDC_USER_PWEXPIRES:
383                UserProp_General_OnPwExpires (hDlg);
384                PropSheetChanged (hDlg);
385                break;
386
387             case IDC_USER_EXPIRES:
388                UserProp_General_OnExpiration (hDlg);
389                PropSheetChanged (hDlg);
390                break;
391
392             case IDC_USER_FAILLOCK:
393                UserProp_General_OnFailLock (hDlg);
394                PropSheetChanged (hDlg);
395                break;
396
397             case IDC_USER_FAILLOCK_INFINITE:
398             case IDC_USER_FAILLOCK_FINITE:
399                UserProp_General_OnFailLockTime (hDlg);
400                PropSheetChanged (hDlg);
401                break;
402
403             case IDC_USER_RPW:
404             case IDC_USER_PWEXPIRATION:
405             case IDC_USER_EXPIRE_DATE:
406             case IDC_USER_EXPIRE_TIME:
407             case IDC_USER_FAILLOCK_COUNT:
408             case IDC_USER_FAILLOCK_DURATION:
409                PropSheetChanged (hDlg);
410                break;
411             }
412          break;
413       }
414
415    return FALSE;
416 }
417
418
419 void UserProp_General_OnInitDialog (HWND hDlg)
420 {
421    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
422
423    // Indicate we want to know if anything changes with these users
424    //
425    if (lpp->pUserList)
426       {
427       LPOBJECT_LISTEN_PARAMS pTask = New (OBJECT_LISTEN_PARAMS);
428       memset (pTask, 0x00, sizeof(OBJECT_LISTEN_PARAMS));
429       pTask->hNotify = hDlg;
430       asc_AsidListCopy (&pTask->pAsidList, &lpp->pUserList);
431       StartTask (taskOBJECT_LISTEN, NULL, pTask);
432       }
433
434    // Fix the name shown on the dialog
435    //
436    UserProp_UpdateName (hDlg);
437
438    // Update the dialog's display
439    //
440    if (lpp->pUserList && (lpp->pUserList->cEntries > 1))
441       EnableWindow (GetDlgItem (hDlg, IDC_USER_CPW_NOW), FALSE);
442
443    UserProp_General_UpdateDialog (hDlg);
444 }
445
446
447 void UserProp_General_OnDestroy (HWND hDlg)
448 {
449    // Indicate we no longer care if anything changes with these users
450    //
451    LPOBJECT_LISTEN_PARAMS pTask = New (OBJECT_LISTEN_PARAMS);
452    memset (pTask, 0x00, sizeof(OBJECT_LISTEN_PARAMS));
453    pTask->hNotify = hDlg;
454    StartTask (taskOBJECT_LISTEN, NULL, pTask);
455 }
456
457
458 void UserProp_General_UpdateDialog (HWND hDlg)
459 {
460    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
461
462    // Most of the controls on the dialog can be gathered by looping
463    // through our pUserList.
464    //
465    BOOL fGotAnyData = FALSE;
466
467    for (size_t ii = 0; lpp->pUserList && (ii < lpp->pUserList->cEntries); ++ii)
468       {
469       ULONG status;
470       ASOBJPROP Properties;
471       if (!asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, lpp->pUserList->aEntries[ ii ].idObject, &Properties, &status))
472          continue;
473
474       if (!fGotAnyData)
475          {
476          lpp->fCanChangePw = Properties.u.UserProperties.KASINFO.fCanChangePassword;
477          lpp->fCanReusePw = Properties.u.UserProperties.KASINFO.fCanReusePasswords;
478          lpp->cdayPwExpires = Properties.u.UserProperties.KASINFO.cdayPwExpire;
479          lpp->cFailLock = Properties.u.UserProperties.KASINFO.cFailLogin;
480          lpp->csecFailLock = Properties.u.UserProperties.KASINFO.csecFailLoginLock;
481          lpp->fExpires = fIsValidDate (&Properties.u.UserProperties.KASINFO.timeExpires);
482          if (lpp->fExpires)
483             lpp->stExpires = Properties.u.UserProperties.KASINFO.timeExpires;
484          else
485             GetLocalSystemTime (&lpp->stExpires);
486          fGotAnyData = TRUE;
487          }
488       else
489          {
490          if (lpp->fCanChangePw != Properties.u.UserProperties.KASINFO.fCanChangePassword)
491             lpp->fCanChangePw_Mixed = TRUE;
492          if (lpp->fCanReusePw != Properties.u.UserProperties.KASINFO.fCanReusePasswords)
493             lpp->fCanReusePw_Mixed = TRUE;
494          if (lpp->cdayPwExpires != Properties.u.UserProperties.KASINFO.cdayPwExpire)
495             lpp->fPwExpires_Mixed = TRUE;
496          if (lpp->cFailLock != Properties.u.UserProperties.KASINFO.cFailLogin)
497             lpp->fFailLock_Mixed = TRUE;
498          if (lpp->csecFailLock != Properties.u.UserProperties.KASINFO.csecFailLoginLock)
499             lpp->fFailLock_Mixed = TRUE;
500          if (lpp->fExpires != fIsValidDate (&Properties.u.UserProperties.KASINFO.timeExpires))
501             lpp->fExpires_Mixed = TRUE;
502          if (memcmp (&lpp->stExpires, &Properties.u.UserProperties.KASINFO.timeExpires, sizeof(SYSTEMTIME)))
503             lpp->fExpires_Mixed = TRUE;
504          }
505       }
506
507    // Set up the dialog controls to reflect what we just learned
508    //
509    if (lpp->fCanChangePw_Mixed)
510       Set3State (hDlg, IDC_USER_CPW);
511    else
512       Set2State (hDlg, IDC_USER_CPW);
513    CheckDlgButton (hDlg, IDC_USER_CPW, (lpp->fCanChangePw_Mixed) ? BST_INDETERMINATE : lpp->fCanChangePw);
514
515    if (lpp->fCanReusePw_Mixed)
516       Set3State (hDlg, IDC_USER_RPW);
517    else
518       Set2State (hDlg, IDC_USER_RPW);
519    CheckDlgButton (hDlg, IDC_USER_RPW, (lpp->fCanReusePw_Mixed) ? BST_INDETERMINATE : lpp->fCanReusePw);
520
521    if (lpp->fPwExpires_Mixed)
522       Set3State (hDlg, IDC_USER_PWEXPIRES);
523    else
524       Set2State (hDlg, IDC_USER_PWEXPIRES);
525    CheckDlgButton (hDlg, IDC_USER_PWEXPIRES, (lpp->fPwExpires_Mixed) ? BST_INDETERMINATE : (lpp->cdayPwExpires == 0) ? BST_UNCHECKED : BST_CHECKED);
526
527    if (fHasSpinner (GetDlgItem (hDlg, IDC_USER_PWEXPIRATION)))
528       SP_SetPos (GetDlgItem (hDlg, IDC_USER_PWEXPIRATION), lpp->cdayPwExpires);
529    else
530       CreateSpinner (GetDlgItem (hDlg, IDC_USER_PWEXPIRATION), 10, FALSE, 1, lpp->cdayPwExpires, cdayPWEXPIRATION_MAX);
531
532    if (lpp->fExpires_Mixed)
533       Set3State (hDlg, IDC_USER_EXPIRES);
534    else
535       Set2State (hDlg, IDC_USER_EXPIRES);
536    CheckDlgButton (hDlg, IDC_USER_EXPIRES, (lpp->fExpires_Mixed) ? BST_INDETERMINATE : lpp->fExpires);
537
538    SYSTEMTIME stExpires;
539    if (fIsValidDate (&lpp->stExpires))
540       memcpy (&stExpires, &lpp->stExpires, sizeof(SYSTEMTIME));
541    else
542       {
543       GetSystemTime (&stExpires);
544       stExpires.wYear ++;
545       }
546
547    // Our controls use local time, not GMT--so translate the account expiration
548    // date before we display it
549    //
550    FILETIME ftGMT;
551    SystemTimeToFileTime (&stExpires, &ftGMT);
552    FILETIME ftLocal;
553    FileTimeToLocalFileTime (&ftGMT, &ftLocal);
554    SYSTEMTIME stLocal;
555    FileTimeToSystemTime (&ftLocal, &stLocal);
556
557    DA_SetDate (GetDlgItem (hDlg, IDC_USER_EXPIRE_DATE), &stLocal);
558    TI_SetTime (GetDlgItem (hDlg, IDC_USER_EXPIRE_TIME), &stLocal);
559
560    if (lpp->fFailLock_Mixed)
561       Set3State (hDlg, IDC_USER_FAILLOCK);
562    else
563       Set2State (hDlg, IDC_USER_FAILLOCK);
564    CheckDlgButton (hDlg, IDC_USER_FAILLOCK, (lpp->fFailLock_Mixed) ? BST_INDETERMINATE : (lpp->cFailLock == 0) ? BST_UNCHECKED : BST_CHECKED);
565
566    if (fHasSpinner (GetDlgItem (hDlg, IDC_USER_FAILLOCK_COUNT)))
567       SP_SetPos (GetDlgItem (hDlg, IDC_USER_FAILLOCK_COUNT), lpp->cFailLock);
568    else
569       CreateSpinner (GetDlgItem (hDlg, IDC_USER_FAILLOCK_COUNT), 10, FALSE, 1, lpp->cFailLock, cFAILLOCKCOUNT_MAX);
570
571    CheckDlgButton (hDlg, IDC_USER_FAILLOCK_INFINITE, (lpp->csecFailLock == 0) ? TRUE : FALSE);
572    CheckDlgButton (hDlg, IDC_USER_FAILLOCK_FINITE,   (lpp->csecFailLock != 0) ? TRUE : FALSE);
573
574    SYSTEMTIME stMin;
575    SYSTEMTIME stNow;
576    SYSTEMTIME stMax;
577    ULONG csecMin = 1;
578    ULONG csecNow = lpp->csecFailLock;
579    ULONG csecMax = csecFAILLOCK_MAX;
580    SET_ELAPSED_TIME_FROM_SECONDS (&stMin, csecMin);
581    SET_ELAPSED_TIME_FROM_SECONDS (&stNow, csecNow);
582    SET_ELAPSED_TIME_FROM_SECONDS (&stMax, csecMax);
583    EL_SetRange (GetDlgItem (hDlg, IDC_USER_FAILLOCK_DURATION), &stMin, &stMax);
584    EL_SetTime (GetDlgItem (hDlg, IDC_USER_FAILLOCK_DURATION), &stNow);
585
586    UserProp_General_OnChangePw (hDlg);
587    UserProp_General_OnPwExpires (hDlg);
588    UserProp_General_OnFailLock (hDlg);
589    UserProp_General_OnFailLockTime (hDlg);
590    UserProp_General_OnExpiration (hDlg);
591 }
592
593
594 void UserProp_General_OnChangePw (HWND hDlg)
595 {
596    BOOL fEnable = (IsDlgButtonChecked (hDlg, IDC_USER_CPW) == BST_CHECKED);
597    EnableWindow (GetDlgItem (hDlg, IDC_USER_RPW), fEnable);
598    EnableWindow (GetDlgItem (hDlg, IDC_USER_PWEXPIRES), fEnable);
599    UserProp_General_OnPwExpires (hDlg);
600 }
601
602
603 void UserProp_General_OnPwExpires (HWND hDlg)
604 {
605    BOOL fEnable = IsWindowEnabled (GetDlgItem (hDlg, IDC_USER_PWEXPIRES)) && (IsDlgButtonChecked (hDlg, IDC_USER_PWEXPIRES) == BST_CHECKED);
606    EnableWindow (GetDlgItem (hDlg, IDC_USER_PWEXPIRATION), fEnable);
607 }
608
609
610 void UserProp_General_OnExpiration (HWND hDlg)
611 {
612    BOOL fEnable = (IsDlgButtonChecked (hDlg, IDC_USER_EXPIRES) == BST_CHECKED);
613    EnableWindow (GetDlgItem (hDlg, IDC_USER_EXPIRE_DATE), fEnable);
614    EnableWindow (GetDlgItem (hDlg, IDC_USER_EXPIRE_AT), fEnable);
615    EnableWindow (GetDlgItem (hDlg, IDC_USER_EXPIRE_TIME), fEnable);
616 }
617
618
619 void UserProp_General_OnFailLock (HWND hDlg)
620 {
621    BOOL fEnable = (IsDlgButtonChecked (hDlg, IDC_USER_FAILLOCK) == BST_CHECKED);
622    EnableWindow (GetDlgItem (hDlg, IDC_USER_FAILLOCK_COUNT), fEnable);
623    EnableWindow (GetDlgItem (hDlg, IDC_USER_FAILLOCK_INFINITE), fEnable);
624    EnableWindow (GetDlgItem (hDlg, IDC_USER_FAILLOCK_FINITE), fEnable);
625    UserProp_General_OnFailLockTime (hDlg);
626 }
627
628
629 void UserProp_General_OnFailLockTime (HWND hDlg)
630 {
631    BOOL fEnable = IsWindowEnabled (GetDlgItem (hDlg, IDC_USER_FAILLOCK_FINITE)) && (IsDlgButtonChecked (hDlg, IDC_USER_FAILLOCK_FINITE) == BST_CHECKED);
632    EnableWindow (GetDlgItem (hDlg, IDC_USER_FAILLOCK_DURATION), fEnable);
633 }
634
635
636 void UserProp_General_OnApply (HWND hDlg)
637 {
638    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
639
640    lpp->fApplyGeneral = TRUE;
641
642    lpp->fCanChangePw = IsDlgButtonChecked (hDlg, IDC_USER_CPW);
643    lpp->fCanChangePw_Mixed = (IsDlgButtonChecked (hDlg, IDC_USER_CPW) == BST_INDETERMINATE);
644    lpp->fCanReusePw = IsDlgButtonChecked (hDlg, IDC_USER_RPW);
645    lpp->fCanReusePw_Mixed = (IsDlgButtonChecked (hDlg, IDC_USER_RPW) == BST_INDETERMINATE);
646
647    lpp->fExpires = IsDlgButtonChecked (hDlg, IDC_USER_EXPIRES);
648    lpp->fExpires_Mixed = (IsDlgButtonChecked (hDlg, IDC_USER_EXPIRES) == BST_INDETERMINATE);
649
650    // Our controls use local time, not GMT--so translate the account expiration
651    // date after we read it from the controls
652    //
653    SYSTEMTIME stLocal;
654    memset (&stLocal, 0x00, sizeof(SYSTEMTIME));
655    DA_GetDate (GetDlgItem (hDlg, IDC_USER_EXPIRE_DATE), &stLocal);
656    TI_GetTime (GetDlgItem (hDlg, IDC_USER_EXPIRE_TIME), &stLocal);
657
658    FILETIME ftLocal;
659    SystemTimeToFileTime (&stLocal, &ftLocal);
660    FILETIME ftGMT;
661    LocalFileTimeToFileTime (&ftLocal, &ftGMT);
662    FileTimeToSystemTime (&ftGMT, &lpp->stExpires);
663
664    if (!IsDlgButtonChecked (hDlg, IDC_USER_PWEXPIRES))
665       lpp->cdayPwExpires = 0;
666    else
667       lpp->cdayPwExpires = SP_GetPos (GetDlgItem (hDlg, IDC_USER_PWEXPIRATION));
668    lpp->fPwExpires_Mixed = (IsDlgButtonChecked (hDlg, IDC_USER_PWEXPIRES) == BST_INDETERMINATE);
669
670    if (!IsDlgButtonChecked (hDlg, IDC_USER_FAILLOCK))
671       lpp->cFailLock = 0;
672    else
673       lpp->cFailLock = SP_GetPos (GetDlgItem (hDlg, IDC_USER_FAILLOCK_COUNT));
674    lpp->fFailLock_Mixed = (IsDlgButtonChecked (hDlg, IDC_USER_FAILLOCK) == BST_INDETERMINATE);
675
676    if (!IsDlgButtonChecked (hDlg, IDC_USER_FAILLOCK_FINITE))
677       lpp->csecFailLock = 0;
678    else
679       {
680       SYSTEMTIME stFailLock;
681       EL_GetTime (GetDlgItem (hDlg, IDC_USER_FAILLOCK_DURATION), &stFailLock);
682       lpp->csecFailLock = GET_SECONDS_FROM_ELAPSED_TIME (&stFailLock);
683       }
684 }
685
686
687 void UserProp_General_OnUnlock (HWND hDlg)
688 {
689    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
690    if (lpp->pUserList)
691       {
692       LPASIDLIST pCopy;
693       asc_AsidListCopy (&pCopy, &lpp->pUserList);
694       StartTask (taskUSER_UNLOCK, NULL, pCopy);
695       }
696 }
697
698
699 void UserProp_General_OnChangePwNow (HWND hDlg)
700 {
701    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
702    if (lpp->pUserList && (lpp->pUserList->cEntries == 1))
703       {
704       User_ShowChangePassword (hDlg, lpp->pUserList->aEntries[0].idObject);
705       }
706 }
707
708
709 BOOL CALLBACK UserProp_Advanced_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
710 {
711    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
712
713    if (AfsAppLib_HandleHelp ((lpp && lpp->fMachine) ? IDD_MACHINE_ADVANCED : IDD_USER_ADVANCED, hDlg, msg, wp, lp))
714       return TRUE;
715
716    switch (msg)
717       {
718       case WM_INITDIALOG_SHEET:
719          if (lpp && lpp->pUserList && !lpp->fShowModal)
720             {
721             if (lpp->pUserList->cEntries == 1)
722                WindowList_Add (hDlg, wltUSER_PROPERTIES, lpp->pUserList->aEntries[0].idObject);
723             else // (lpp->pUserList->cEntries > 1)
724                WindowList_Add (hDlg, wltUSER_PROPERTIES, 0);
725             }
726          break;
727
728       case WM_DESTROY_SHEET:
729          WindowList_Remove (hDlg);
730          if (lpp && lpp->fDeleteMeOnClose)
731             User_FreeProperties (lpp);
732          break;
733
734       case WM_INITDIALOG:
735          UserProp_Advanced_OnInitDialog (hDlg);
736          break;
737
738       case WM_DESTROY:
739          UserProp_Advanced_OnDestroy (hDlg);
740          break;
741
742       case WM_ASC_NOTIFY_OBJECT:
743          UserProp_Advanced_UpdateDialog (hDlg);
744          break;
745
746       case WM_COMMAND:
747          switch (LOWORD(wp))
748             {
749             case IDAPPLY:
750                UserProp_Advanced_OnApply (hDlg);
751                break;
752
753             case IDC_USER_TGS:
754                UserProp_Advanced_OnGrantTickets (hDlg);
755                PropSheetChanged (hDlg);
756                break;
757
758             case IDC_USER_GROUP_HASQUOTA:
759                UserProp_Advanced_OnHasGroupQuota (hDlg);
760                PropSheetChanged (hDlg);
761                break;
762
763             case IDC_USER_ADMIN:
764                UserProp_Advanced_OnAdmin (hDlg);
765                PropSheetChanged (hDlg);
766                break;
767
768             case IDC_USER_NOSEAL:
769             case IDC_USER_LIFETIME:
770             case IDC_USER_GROUP_QUOTA:
771             case IDC_USER_PERM_STATUS:
772             case IDC_USER_PERM_OWNED:
773             case IDC_USER_PERM_MEMBER:
774                PropSheetChanged (hDlg);
775                break;
776             }
777          break;
778       }
779
780    return FALSE;
781 }
782
783
784 void UserProp_Advanced_OnInitDialog (HWND hDlg)
785 {
786    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
787
788    // Indicate we want to know if anything changes with these users
789    //
790    if (lpp->pUserList)
791       {
792       LPOBJECT_LISTEN_PARAMS pTask = New (OBJECT_LISTEN_PARAMS);
793       memset (pTask, 0x00, sizeof(OBJECT_LISTEN_PARAMS));
794       pTask->hNotify = hDlg;
795       asc_AsidListCopy (&pTask->pAsidList, &lpp->pUserList);
796       StartTask (taskOBJECT_LISTEN, NULL, pTask);
797       }
798
799    // Fix the name shown on the dialog
800    //
801    UserProp_UpdateName (hDlg);
802
803    // Fill in the information about the selected users
804    //
805    UserProp_Advanced_UpdateDialog (hDlg);
806 }
807
808
809 void UserProp_Advanced_OnDestroy (HWND hDlg)
810 {
811    // Indicate we no longer care if anything changes with these users
812    //
813    LPOBJECT_LISTEN_PARAMS pTask = New (OBJECT_LISTEN_PARAMS);
814    memset (pTask, 0x00, sizeof(OBJECT_LISTEN_PARAMS));
815    pTask->hNotify = hDlg;
816    StartTask (taskOBJECT_LISTEN, NULL, pTask);
817 }
818
819
820 void UserProp_Advanced_OnGrantTickets (HWND hDlg)
821 {
822    BOOL fEnable = (IsDlgButtonChecked (hDlg, IDC_USER_TGS) == BST_CHECKED);
823    EnableWindow (GetDlgItem (hDlg, IDC_USER_LIFETIME), fEnable);
824 }
825
826
827 void UserProp_Advanced_OnHasGroupQuota (HWND hDlg)
828 {
829    BOOL fEnable = (IsDlgButtonChecked (hDlg, IDC_USER_GROUP_HASQUOTA) == BST_CHECKED);
830    if (!IsWindowEnabled (GetDlgItem (hDlg, IDC_USER_GROUP_HASQUOTA)))
831       fEnable = FALSE;
832    EnableWindow (GetDlgItem (hDlg, IDC_USER_GROUP_QUOTA), fEnable);
833 }
834
835
836 void UserProp_Advanced_OnAdmin (HWND hDlg)
837 {
838    BOOL fAdmin = (IsDlgButtonChecked (hDlg, IDC_USER_ADMIN) == BST_CHECKED);
839    EnableWindow (GetDlgItem (hDlg, IDC_USER_GROUP_HASQUOTA), !fAdmin);
840
841    if (fAdmin)
842       {
843       CheckDlgButton (hDlg, IDC_USER_GROUP_HASQUOTA, TRUE);
844       SP_SetPos (GetDlgItem (hDlg, IDC_USER_GROUP_QUOTA), 9999);
845       }
846
847    UserProp_Advanced_OnHasGroupQuota (hDlg);
848 }
849
850
851 void UserProp_Advanced_UpdateDialog (HWND hDlg)
852 {
853    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
854
855    // Fill in the user's key. If this dialog represents more than one
856    // user, put in some stock text instead.
857    //
858    if ((lpp->pUserList) && (lpp->pUserList->cEntries > 1))
859       {
860       TCHAR szText[ cchRESOURCE ];
861       GetString (szText, IDS_USER_KEY_MULTIPLE);
862       SetDlgItemText (hDlg, IDC_USER_KEY, szText);
863       }
864    else if (lpp->pUserList && (lpp->pUserList->cEntries == 1))
865       {
866       ULONG status;
867       ASOBJPROP Properties;
868       if (!asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, lpp->pUserList->aEntries[ 0 ].idObject, &Properties, &status))
869          {
870          TCHAR szText[ cchRESOURCE ];
871          GetString (szText, IDS_USER_KEY_UNKNOWN);
872          SetDlgItemText (hDlg, IDC_USER_KEY, szText);
873          }
874       else if (!Properties.u.UserProperties.fHaveKasInfo)
875          {
876          TCHAR szText[ cchRESOURCE ];
877          GetString (szText, IDS_USER_KEY_UNKNOWN);
878          SetDlgItemText (hDlg, IDC_USER_KEY, szText);
879          }
880       else
881          {
882          TCHAR szReadableKey[ cchRESOURCE ];
883          FormatServerKey (szReadableKey, Properties.u.UserProperties.KASINFO.keyData);
884
885          LPTSTR pszText = FormatString (IDS_USER_KEY, TEXT("%s%lu%lu"), szReadableKey, Properties.u.UserProperties.KASINFO.keyVersion, Properties.u.UserProperties.KASINFO.dwKeyChecksum);
886          SetDlgItemText (hDlg, IDC_USER_KEY, pszText);
887          FreeString (pszText);
888          }
889       }
890
891    // Fill in the other fields
892    //
893    BOOL fGotAnyData = FALSE;
894
895    for (size_t ii = 0; lpp->pUserList && (ii < lpp->pUserList->cEntries); ++ii)
896       {
897       ULONG status;
898       ASOBJPROP Properties;
899       if (!asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, lpp->pUserList->aEntries[ ii ].idObject, &Properties, &status))
900          continue;
901
902       if (!fGotAnyData)
903          {
904          lpp->fSeal = Properties.u.UserProperties.KASINFO.fEncrypt;
905          lpp->fAdmin = Properties.u.UserProperties.KASINFO.fIsAdmin;
906          lpp->fGrantTickets = Properties.u.UserProperties.KASINFO.fCanGetTickets;
907          lpp->csecLifetime = Properties.u.UserProperties.KASINFO.csecTicketLifetime;
908          lpp->cGroupQuota = Properties.u.UserProperties.PTSINFO.cgroupCreationQuota;
909          lpp->aaStatus = Properties.u.UserProperties.PTSINFO.aaListStatus;
910          lpp->aaOwned = Properties.u.UserProperties.PTSINFO.aaGroupsOwned;
911          lpp->aaMember = Properties.u.UserProperties.PTSINFO.aaMembership;
912          fGotAnyData = TRUE;
913          }
914       else // (fGotAnyData)
915          {
916          if (lpp->fSeal != Properties.u.UserProperties.KASINFO.fEncrypt)
917             lpp->fSeal_Mixed = TRUE;
918          if (lpp->fAdmin != Properties.u.UserProperties.KASINFO.fIsAdmin)
919             lpp->fAdmin_Mixed = TRUE;
920          if (lpp->fGrantTickets != Properties.u.UserProperties.KASINFO.fCanGetTickets)
921             lpp->fGrantTickets_Mixed = TRUE;
922          if (lpp->csecLifetime != (ULONG)Properties.u.UserProperties.KASINFO.csecTicketLifetime)
923             lpp->fGrantTickets_Mixed = TRUE;
924          if (lpp->cGroupQuota != Properties.u.UserProperties.PTSINFO.cgroupCreationQuota)
925             lpp->fGroupQuota_Mixed = TRUE;
926          if (lpp->aaStatus != Properties.u.UserProperties.PTSINFO.aaListStatus)
927             lpp->fStatus_Mixed = TRUE;
928          if (lpp->aaOwned != Properties.u.UserProperties.PTSINFO.aaGroupsOwned)
929             lpp->fOwned_Mixed = TRUE;
930          if (lpp->aaMember != Properties.u.UserProperties.PTSINFO.aaMembership)
931             lpp->fMember_Mixed = TRUE;
932          }
933       }
934
935    // Fill in the dialog's state
936    //
937    CheckDlgButton (hDlg, IDC_USER_CREATE_KAS, lpp->fCreateKAS);
938    CheckDlgButton (hDlg, IDC_USER_CREATE_PTS, lpp->fCreatePTS);
939
940    if (lpp->fSeal_Mixed)
941       Set3State (hDlg, IDC_USER_NOSEAL);
942    else
943       Set2State (hDlg, IDC_USER_NOSEAL);
944    CheckDlgButton (hDlg, IDC_USER_NOSEAL, (lpp->fSeal_Mixed) ? BST_INDETERMINATE : (!lpp->fSeal));
945
946    if (lpp->fAdmin_Mixed)
947       Set3State (hDlg, IDC_USER_ADMIN);
948    else
949       Set2State (hDlg, IDC_USER_ADMIN);
950    CheckDlgButton (hDlg, IDC_USER_ADMIN, (lpp->fAdmin_Mixed) ? BST_INDETERMINATE : lpp->fAdmin);
951
952    if (lpp->fGrantTickets_Mixed)
953       Set3State (hDlg, IDC_USER_TGS);
954    else
955       Set2State (hDlg, IDC_USER_TGS);
956    CheckDlgButton (hDlg, IDC_USER_TGS, (lpp->fGrantTickets_Mixed) ? BST_INDETERMINATE : lpp->fGrantTickets);
957
958    SYSTEMTIME stMin;
959    SYSTEMTIME stNow;
960    SYSTEMTIME stMax;
961    ULONG csecMin = 0;
962    ULONG csecNow = lpp->csecLifetime;
963    ULONG csecMax = csecTICKETLIFETIME_MAX;
964    SET_ELAPSED_TIME_FROM_SECONDS (&stMin, csecMin);
965    SET_ELAPSED_TIME_FROM_SECONDS (&stNow, csecNow);
966    SET_ELAPSED_TIME_FROM_SECONDS (&stMax, csecMax);
967    EL_SetRange (GetDlgItem (hDlg, IDC_USER_LIFETIME), &stMin, &stMax);
968    EL_SetTime (GetDlgItem (hDlg, IDC_USER_LIFETIME), &stNow);
969
970    if (lpp->fGroupQuota_Mixed)
971       Set3State (hDlg, IDC_USER_GROUP_HASQUOTA);
972    else
973       Set2State (hDlg, IDC_USER_GROUP_HASQUOTA);
974    CheckDlgButton (hDlg, IDC_USER_GROUP_HASQUOTA, (lpp->fGroupQuota_Mixed) ? BST_INDETERMINATE : (lpp->cGroupQuota == cGROUPQUOTA_INFINITE) ? BST_UNCHECKED : BST_CHECKED);
975
976    if (fHasSpinner (GetDlgItem (hDlg, IDC_USER_GROUP_QUOTA)))
977       SP_SetPos (GetDlgItem (hDlg, IDC_USER_GROUP_QUOTA), lpp->cGroupQuota);
978    else
979       CreateSpinner (GetDlgItem (hDlg, IDC_USER_GROUP_QUOTA), 10, FALSE, cGROUPQUOTA_MIN, lpp->cGroupQuota, cGROUPQUOTA_MAX);
980
981    UserProp_Advanced_UpdateDialog_Perm (hDlg, IDC_USER_PERM_STATUS, lpp->aaStatus, lpp->fStatus_Mixed);
982    UserProp_Advanced_UpdateDialog_Perm (hDlg, IDC_USER_PERM_OWNED, lpp->aaOwned, lpp->fOwned_Mixed);
983    UserProp_Advanced_UpdateDialog_Perm (hDlg, IDC_USER_PERM_MEMBER, lpp->aaMember, lpp->fMember_Mixed);
984
985    UserProp_Advanced_OnGrantTickets (hDlg);
986    UserProp_Advanced_OnHasGroupQuota (hDlg);
987    UserProp_Advanced_OnAdmin (hDlg);
988 }
989
990
991 void UserProp_Advanced_UpdateDialog_Perm (HWND hDlg, int idc, ACCOUNTACCESS aa, BOOL fMixed)
992 {
993    CB_StartChange (GetDlgItem (hDlg, idc), TRUE);
994    CB_AddItem (GetDlgItem (hDlg, idc), IDS_ACCOUNTACCESS_OWNER, aaOWNER_ONLY);
995    CB_AddItem (GetDlgItem (hDlg, idc), IDS_ACCOUNTACCESS_ANYONE, aaANYONE);
996    if (fMixed)
997       CB_AddItem (GetDlgItem (hDlg, idc), IDS_ACCOUNTACCESS_MIXED, (LPARAM)-1);
998    CB_EndChange (GetDlgItem (hDlg, idc), TRUE);
999
1000    LPARAM lpSelect = (fMixed) ? ((LPARAM)-1) : (LPARAM)aa;
1001    CB_SetSelectedByData (GetDlgItem (hDlg, idc), lpSelect);
1002 }
1003
1004
1005 void UserProp_Advanced_OnApply (HWND hDlg)
1006 {
1007    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1008
1009    lpp->fApplyAdvanced = TRUE;
1010    lpp->fCreateKAS = IsDlgButtonChecked (hDlg, IDC_USER_CREATE_KAS);
1011    lpp->fCreatePTS = IsDlgButtonChecked (hDlg, IDC_USER_CREATE_PTS);
1012
1013    if (IsWindow (GetDlgItem (hDlg, IDC_USER_NOSEAL)))
1014       {
1015       lpp->fSeal = !IsDlgButtonChecked (hDlg, IDC_USER_NOSEAL);
1016       lpp->fSeal_Mixed = (IsDlgButtonChecked (hDlg, IDC_USER_NOSEAL) == BST_INDETERMINATE);
1017       }
1018
1019    if (IsWindow (GetDlgItem (hDlg, IDC_USER_ADMIN)))
1020       {
1021       lpp->fAdmin = IsDlgButtonChecked (hDlg, IDC_USER_ADMIN);
1022       lpp->fAdmin_Mixed = (IsDlgButtonChecked (hDlg, IDC_USER_ADMIN) == BST_INDETERMINATE);
1023       }
1024
1025    if (IsWindow (GetDlgItem (hDlg, IDC_USER_TGS)))
1026       {
1027       lpp->fGrantTickets = IsDlgButtonChecked (hDlg, IDC_USER_TGS);
1028       lpp->fGrantTickets_Mixed = (IsDlgButtonChecked (hDlg, IDC_USER_TGS) == BST_INDETERMINATE);
1029       }
1030
1031    if (IsWindow (GetDlgItem (hDlg, IDC_USER_LIFETIME)))
1032       {
1033       SYSTEMTIME stLifetime;
1034       EL_GetTime (GetDlgItem (hDlg, IDC_USER_LIFETIME), &stLifetime);
1035       lpp->csecLifetime = GET_SECONDS_FROM_ELAPSED_TIME (&stLifetime);
1036       }
1037
1038    if (IsWindow (GetDlgItem (hDlg, IDC_USER_GROUP_HASQUOTA)))
1039       {
1040       if (!IsDlgButtonChecked (hDlg, IDC_USER_GROUP_HASQUOTA))
1041          lpp->cGroupQuota = cGROUPQUOTA_INFINITE;
1042       else // (IsDlgButtonChecked (hDlg, IDC_USER_GROUP_HASQUOTA))
1043          lpp->cGroupQuota = SP_GetPos (GetDlgItem (hDlg, IDC_USER_GROUP_QUOTA));
1044       lpp->fGroupQuota_Mixed = (IsDlgButtonChecked (hDlg, IDC_USER_GROUP_HASQUOTA) == BST_INDETERMINATE);
1045       }
1046
1047    lpp->aaStatus = (ACCOUNTACCESS)CB_GetSelectedData (GetDlgItem (hDlg, IDC_USER_PERM_STATUS));
1048    lpp->fStatus_Mixed = (lpp->aaStatus == (ACCOUNTACCESS)-1) ? TRUE : FALSE;
1049
1050    lpp->aaOwned = (ACCOUNTACCESS)CB_GetSelectedData (GetDlgItem (hDlg, IDC_USER_PERM_OWNED));
1051    lpp->fOwned_Mixed = (lpp->aaOwned == (ACCOUNTACCESS)-1) ? TRUE : FALSE;
1052
1053    lpp->aaMember = (ACCOUNTACCESS)CB_GetSelectedData (GetDlgItem (hDlg, IDC_USER_PERM_MEMBER));
1054    lpp->fMember_Mixed = (lpp->aaMember == (ACCOUNTACCESS)-1) ? TRUE : FALSE;
1055 }
1056
1057
1058 BOOL CALLBACK UserProp_Member_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
1059 {
1060    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1061
1062    if (AfsAppLib_HandleHelp ((lpp && lpp->fMachine) ? IDD_MACHINE_MEMBER : IDD_USER_MEMBER, hDlg, msg, wp, lp))
1063       return TRUE;
1064
1065    switch (msg)
1066       {
1067       case WM_INITDIALOG:
1068          UserProp_Member_OnInitDialog (hDlg);
1069          break;
1070
1071       case WM_DESTROY:
1072          UserProp_Member_OnDestroy (hDlg);
1073          break;
1074
1075       case WM_ENDTASK:
1076          LPTASKPACKET ptp;
1077          if ((ptp = (LPTASKPACKET)lp) != NULL)
1078             {
1079             if (ptp->idTask == taskGROUP_SEARCH)
1080                UserProp_Member_OnEndTask_GroupSearch (hDlg, ptp);
1081             FreeTaskPacket (ptp);
1082             }
1083          break;
1084
1085       case WM_COMMAND:
1086          switch (LOWORD(wp))
1087             {
1088             case IDAPPLY:
1089                UserProp_Member_OnApply (hDlg);
1090                break;
1091
1092             case IDC_USER_SHOW_MEMBER:
1093             case IDC_USER_SHOW_OWNER:
1094                UserProp_Member_OnShowType (hDlg);
1095                break;
1096
1097             case IDC_MEMBER_ADD:
1098                UserProp_Member_OnAdd (hDlg);
1099                break;
1100
1101             case IDC_MEMBER_REMOVE:
1102                UserProp_Member_OnRemove (hDlg);
1103                break;
1104             }
1105          break;
1106
1107       case WM_NOTIFY:
1108          switch (((LPNMHDR)lp)->code)
1109             {
1110             case FLN_ITEMSELECT:
1111                UserProp_Member_OnSelect (hDlg);
1112                break;
1113             }
1114          break;
1115       }
1116    return FALSE;
1117 }
1118
1119
1120 void UserProp_Member_OnInitDialog (HWND hDlg)
1121 {
1122    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1123
1124    // If we've come in here with a valid set of groups to display,
1125    // copy those. We'll need the copies if the user cancels the dialog.
1126    //
1127    SetWindowData (hDlg, GWD_ASIDLIST_MEMBER, (LPARAM)(lpp->pGroupsMember));
1128    SetWindowData (hDlg, GWD_ASIDLIST_OWNER,  (LPARAM)(lpp->pGroupsOwner));
1129
1130    LPASIDLIST pList;
1131    if ((pList = lpp->pGroupsMember) != NULL)
1132       asc_AsidListCopy (&lpp->pGroupsMember, &pList);
1133    if ((pList = lpp->pGroupsOwner) != NULL)
1134       asc_AsidListCopy (&lpp->pGroupsOwner, &pList);
1135
1136    // If this prop sheet reflects more than one user, disable the
1137    // Ownership button (we do this primarily because the Add/Remove
1138    // buttons have no straight-forward semantic for that case).
1139    // Actually, instead of disabling the thing, we'll hide the buttons
1140    // entirely and resize the list/move the title.
1141    //
1142    if (lpp->pUserList && (lpp->pUserList->cEntries > 1))
1143       {
1144       ShowWindow (GetDlgItem (hDlg, IDC_USER_SHOW_MEMBER), SW_HIDE);
1145       ShowWindow (GetDlgItem (hDlg, IDC_USER_SHOW_OWNER), SW_HIDE);
1146
1147       RECT rButton;
1148       GetRectInParent (GetDlgItem (hDlg, IDC_USER_SHOW_MEMBER), &rButton);
1149
1150       RECT rTitle;
1151       GetRectInParent (GetDlgItem (hDlg, IDC_GROUPS_TITLE), &rTitle);
1152
1153       RECT rList;
1154       GetRectInParent (GetDlgItem (hDlg, IDC_GROUPS_LIST), &rList);
1155
1156       LONG cyDelta = rTitle.top - rButton.top;
1157
1158       SetWindowPos (GetDlgItem (hDlg, IDC_GROUPS_TITLE), NULL,
1159                     rTitle.left, rTitle.top-cyDelta,
1160                     rTitle.right-rTitle.left, rTitle.bottom-rTitle.top,
1161                     SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
1162
1163       SetWindowPos (GetDlgItem (hDlg, IDC_GROUPS_LIST), NULL,
1164                     rList.left, rList.top-cyDelta,
1165                     rList.right-rList.left, rList.bottom-rList.top+cyDelta,
1166                     SWP_NOZORDER | SWP_NOACTIVATE);
1167       }
1168
1169    // Apply an imagelist to the dialog's fastlist
1170    //
1171    FastList_SetImageLists (GetDlgItem (hDlg, IDC_GROUPS_LIST), AfsAppLib_CreateImageList (FALSE), NULL);
1172
1173    // Select a checkbox and pretend that the user clicked it; that will
1174    // make the dialog automatically re-populate the list of groups
1175    //
1176    CheckDlgButton (hDlg, IDC_USER_SHOW_MEMBER, TRUE);
1177    UserProp_Member_OnShowType (hDlg);
1178 }
1179
1180
1181 void UserProp_Member_OnDestroy (HWND hDlg)
1182 {
1183    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1184
1185    LPASIDLIST pList;
1186    if ((pList = (LPASIDLIST)GetWindowData (hDlg, GWD_ASIDLIST_MEMBER)) != NULL)
1187       lpp->pGroupsMember = pList;
1188    if ((pList = (LPASIDLIST)GetWindowData (hDlg, GWD_ASIDLIST_OWNER)) != NULL)
1189       lpp->pGroupsOwner = pList;
1190 }
1191
1192
1193 void UserProp_Member_OnShowType (HWND hDlg)
1194 {
1195    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1196
1197    // If we've already obtained the list of groups we should be displaying,
1198    // just go show it.
1199    //
1200    if (IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER))
1201       {
1202       if (lpp->pGroupsMember)
1203          {
1204          UserProp_Member_PopulateList (hDlg);
1205          return;
1206          }
1207       }
1208    else // (IsDlgButtonChecked (hDlg, IDC_USER_SHOW_OWNER))
1209       {
1210       if (lpp->pGroupsOwner)
1211          {
1212          UserProp_Member_PopulateList (hDlg);
1213          return;
1214          }
1215       }
1216
1217    // Otherwise, we'll have to start a background task to do the querying.
1218    // Change the text above the list to "Querying...", disable the buttons,
1219    // and remove any items in the list.
1220    //
1221    if (!lpp->pUserList)
1222       {
1223       // Generate a few empty ASID list; this is a new user account we're
1224       // displaying, and the caller hasn't yet added any groups.
1225       //
1226       if (!lpp->pGroupsMember)
1227          {
1228          if (!asc_AsidListCreate (&lpp->pGroupsMember))
1229             return;
1230          }
1231       if (!lpp->pGroupsOwner)
1232          {
1233          if (!asc_AsidListCreate (&lpp->pGroupsOwner))
1234             return;
1235          }
1236       UserProp_Member_OnShowType (hDlg);
1237       }
1238    else // (lpp->pUserList)
1239       {
1240       TCHAR szTitle[ cchRESOURCE ];
1241       GetString (szTitle, IDS_QUERYING_LONG);
1242       SetDlgItemText (hDlg, IDC_GROUPS_TITLE, szTitle);
1243
1244       EnableWindow (GetDlgItem (hDlg, IDC_MEMBER_ADD), FALSE);
1245       EnableWindow (GetDlgItem (hDlg, IDC_MEMBER_REMOVE), FALSE);
1246
1247       FastList_RemoveAll (GetDlgItem (hDlg, IDC_GROUPS_LIST));
1248
1249       // Then start a background task to grab an ASIDLIST of groups which
1250       // match the specified search criteria.
1251       //
1252       LPGROUP_SEARCH_PARAMS pTask = New (GROUP_SEARCH_PARAMS);
1253       asc_AsidListCopy (&pTask->pUserList, &lpp->pUserList);
1254       pTask->fMembership = IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER);
1255       StartTask (taskGROUP_SEARCH, hDlg, pTask);
1256       }
1257 }
1258
1259
1260 void UserProp_Member_OnEndTask_GroupSearch (HWND hDlg, LPTASKPACKET ptp)
1261 {
1262    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1263
1264    // The search is complete. If we've just obtained an ASIDLIST successfully,
1265    // associate it with the dialog and repopulate the display.
1266    //
1267    if (ptp->rc && TASKDATA(ptp)->pAsidList)
1268       {
1269       if (TASKDATA(ptp)->fMembership)
1270          {
1271          if (!lpp->pGroupsMember)
1272             {
1273             asc_AsidListCopy (&lpp->pGroupsMember, &TASKDATA(ptp)->pAsidList);
1274             UserProp_Member_PopulateList (hDlg);
1275             }
1276          }
1277       else // (!TASKDATA(ptp)->fMembership)
1278          {
1279          if (!lpp->pGroupsOwner)
1280             {
1281             asc_AsidListCopy (&lpp->pGroupsOwner, &TASKDATA(ptp)->pAsidList);
1282             UserProp_Member_PopulateList (hDlg);
1283             }
1284          }
1285       }
1286 }
1287
1288
1289 void UserProp_Member_PopulateList (HWND hDlg)
1290 {
1291    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1292
1293    // Clear the list of groups
1294    //
1295    HWND hList = GetDlgItem (hDlg, IDC_GROUPS_LIST);
1296    FastList_Begin (hList);
1297    FastList_RemoveAll (hList);
1298
1299    // We should have an ASIDLIST associated with the dialog to reflect
1300    // which groups to display. Find it, and repopulate the list on the display.
1301    //
1302    LPASIDLIST pGroupList;
1303    if (IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER))
1304       pGroupList = lpp->pGroupsMember;
1305    else // (!IsDlgButtonChecked (hDlg, IDC_USER_SHOW_OWNER))
1306       pGroupList = lpp->pGroupsOwner;
1307
1308    if (pGroupList)
1309       {
1310       TCHAR szMixed[ cchRESOURCE ];
1311       GetString (szMixed, IDS_MEMBER_MIXED);
1312
1313       for (size_t ii = 0; ii < pGroupList->cEntries; ++ii)
1314          {
1315          ULONG status;
1316          TCHAR szName[ cchNAME ];
1317          if (!asc_ObjectNameGet_Fast (g.idClient, g.idCell, pGroupList->aEntries[ ii ].idObject, szName, &status))
1318             continue;
1319          if (!pGroupList->aEntries[ ii ].lParam)
1320             lstrcat (szName, szMixed);
1321
1322          FASTLISTADDITEM flai;
1323          memset (&flai, 0x00, sizeof(flai));
1324          flai.iFirstImage = imageGROUP;
1325          flai.iSecondImage = IMAGE_NOIMAGE;
1326          flai.pszText = szName;
1327          flai.lParam = (LPARAM)(pGroupList->aEntries[ ii ].idObject);
1328          FastList_AddItem (hList, &flai);
1329          }
1330       }
1331
1332    FastList_End (hList);
1333
1334    // Fix the buttons, and the text at the top of the list
1335    //
1336    TCHAR szTitle[ cchRESOURCE ];
1337    if (lpp->fMachine)
1338       {
1339       if (IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER))
1340          {
1341          if (!lpp->pUserList) 
1342             GetString (szTitle, IDS_NEWMACHINE_SHOW_MEMBER_TITLE);
1343          else if (lpp->pUserList->cEntries == 1)
1344             GetString (szTitle, IDS_MACHINE_SHOW_MEMBER_TITLE);
1345          else
1346             GetString (szTitle, IDS_MACHINE_SHOW_MEMBER_TITLE_MULTIPLE);
1347          }
1348       else
1349          {
1350          if (!lpp->pUserList)
1351             GetString (szTitle, IDS_NEWMACHINE_SHOW_OWNER_TITLE);
1352          else
1353             GetString (szTitle, IDS_MACHINE_SHOW_OWNER_TITLE);
1354          }
1355       }
1356    else
1357       {
1358       if (IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER))
1359          {
1360          if (!lpp->pUserList) 
1361             GetString (szTitle, IDS_NEWUSER_SHOW_MEMBER_TITLE);
1362          else if (lpp->pUserList->cEntries == 1)
1363             GetString (szTitle, IDS_USER_SHOW_MEMBER_TITLE);
1364          else
1365             GetString (szTitle, IDS_USER_SHOW_MEMBER_TITLE_MULTIPLE);
1366          }
1367       else
1368          {
1369          if (!lpp->pUserList)
1370             GetString (szTitle, IDS_NEWUSER_SHOW_OWNER_TITLE);
1371          else
1372             GetString (szTitle, IDS_USER_SHOW_OWNER_TITLE);
1373          }
1374       }
1375
1376    SetDlgItemText (hDlg, IDC_GROUPS_TITLE, szTitle);
1377
1378    EnableWindow (GetDlgItem (hDlg, IDC_MEMBER_ADD), TRUE);
1379    UserProp_Member_OnSelect (hDlg);
1380 }
1381
1382
1383 void UserProp_Member_OnSelect (HWND hDlg)
1384 {
1385    BOOL fEnable = IsWindowEnabled (GetDlgItem (hDlg, IDC_MEMBER_ADD));
1386    if (fEnable && !FastList_FindFirstSelected (GetDlgItem (hDlg, IDC_GROUPS_LIST)))
1387       fEnable = FALSE;
1388    EnableWindow (GetDlgItem (hDlg, IDC_MEMBER_REMOVE), fEnable);
1389 }
1390
1391
1392 void UserProp_Member_OnAdd (HWND hDlg)
1393 {
1394    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1395
1396    LPBROWSE_PARAMS pParams = New (BROWSE_PARAMS);
1397    memset (pParams, 0x00, sizeof(BROWSE_PARAMS));
1398    pParams->hParent = GetParent(hDlg);
1399    pParams->iddForHelp = IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER) ? IDD_BROWSE_JOIN : IDD_BROWSE_OWN;
1400    pParams->idsTitle = IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER) ? IDS_BROWSE_TITLE_JOIN : IDS_BROWSE_TITLE_OWN;
1401    pParams->idsPrompt = IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER) ? IDS_BROWSE_PROMPT_JOIN : IDS_BROWSE_PROMPT_OWN;
1402    pParams->idsCheck = IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER) ? IDS_BROWSE_CHECK_JOIN : IDS_BROWSE_CHECK_OWN;
1403    pParams->TypeToShow = TYPE_GROUP;
1404    pParams->fAllowMultiple = TRUE;
1405
1406    // First prepare an ASIDLIST which reflects only the groups which
1407    // all selected users own/are members in.
1408    //
1409    LPASIDLIST pGroupList;
1410    if (IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER))
1411       pGroupList = lpp->pGroupsMember;
1412    else // (!IsDlgButtonChecked (hDlg, IDC_USER_SHOW_OWNER))
1413       pGroupList = lpp->pGroupsOwner;
1414
1415    if (pGroupList)
1416       {
1417       asc_AsidListCreate (&pParams->pObjectsToSkip);
1418       for (size_t ii = 0; ii < pGroupList->cEntries; ++ii)
1419          {
1420          if (pGroupList->aEntries[ ii ].lParam) // all users have this group?
1421             asc_AsidListAddEntry (&pParams->pObjectsToSkip, pGroupList->aEntries[ ii ].idObject, 0);
1422          }
1423       }
1424
1425    if (ShowBrowseDialog (pParams))
1426       {
1427       // The user added some groups; modify pGroupList (and the dialog,
1428       // at the same time).
1429       //
1430       HWND hList = GetDlgItem (hDlg, IDC_GROUPS_LIST);
1431       FastList_Begin (hList);
1432
1433       for (size_t ii = 0; ii < pParams->pObjectsSelected->cEntries; ++ii)
1434          {
1435          ASID idGroup = pParams->pObjectsSelected->aEntries[ ii ].idObject;
1436
1437          // The user has chosen to add group {idGroup}. If it's not in our
1438          // list at all, add it (and a new entry for the display). If it
1439          // *is* in our list, make sure its lParam is 1--indicating all users
1440          // get it--and modify the display's entry to remove the "(some)"
1441          // marker.
1442          //
1443          LPARAM lParam;
1444          if (!asc_AsidListTest (&pGroupList, idGroup, &lParam))
1445             {
1446             ULONG status;
1447             TCHAR szName[ cchNAME ];
1448             if (!asc_ObjectNameGet_Fast (g.idClient, g.idCell, idGroup, szName, &status))
1449                continue;
1450
1451             asc_AsidListAddEntry (&pGroupList, idGroup, TRUE);
1452
1453             FASTLISTADDITEM flai;
1454             memset (&flai, 0x00, sizeof(flai));
1455             flai.iFirstImage = imageGROUP;
1456             flai.iSecondImage = IMAGE_NOIMAGE;
1457             flai.pszText = szName;
1458             flai.lParam = (LPARAM)idGroup;
1459             FastList_AddItem (hList, &flai);
1460             PropSheetChanged (hDlg);
1461             }
1462          else if (!lParam)
1463             {
1464             ULONG status;
1465             TCHAR szName[ cchNAME ];
1466             if (!asc_ObjectNameGet_Fast (g.idClient, g.idCell, idGroup, szName, &status))
1467                continue;
1468
1469             asc_AsidListSetEntryParam (&pGroupList, idGroup, TRUE);
1470
1471             HLISTITEM hItem;
1472             if ((hItem = FastList_FindItem (hList, (LPARAM)idGroup)) != NULL)
1473                FastList_SetItemText (hList, hItem, 0, szName);
1474             PropSheetChanged (hDlg);
1475             }
1476          }
1477
1478       if (IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER))
1479          lpp->pGroupsMember = pGroupList;
1480       else // (!IsDlgButtonChecked (hDlg, IDC_USER_SHOW_OWNER))
1481          lpp->pGroupsOwner = pGroupList;
1482
1483       FastList_End (hList);
1484       }
1485
1486    if (pParams->pObjectsToSkip)
1487       asc_AsidListFree (&pParams->pObjectsToSkip);
1488    if (pParams->pObjectsSelected)
1489       asc_AsidListFree (&pParams->pObjectsSelected);
1490    Delete (pParams);
1491 }
1492
1493
1494 void UserProp_Member_OnRemove (HWND hDlg)
1495 {
1496    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1497
1498    // Find which list-of-groups is currently being displayed.
1499    //
1500    LPASIDLIST pGroupList;
1501    if (IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER))
1502       pGroupList = lpp->pGroupsMember;
1503    else // (!IsDlgButtonChecked (hDlg, IDC_USER_SHOW_OWNER))
1504       pGroupList = lpp->pGroupsOwner;
1505
1506    // The user wants to remove some groups; modify pGroupList
1507    // (and the dialog, at the same time).
1508    //
1509    HWND hList = GetDlgItem (hDlg, IDC_GROUPS_LIST);
1510    FastList_Begin (hList);
1511
1512    HLISTITEM hItem;
1513    while ((hItem = FastList_FindFirstSelected (hList)) != NULL)
1514       {
1515       ASID idGroup = (ASID)FastList_GetItemParam (hList, hItem);
1516       FastList_RemoveItem (hList, hItem);
1517       asc_AsidListRemoveEntry (&pGroupList, idGroup);
1518       PropSheetChanged (hDlg);
1519       }
1520
1521    if (IsDlgButtonChecked (hDlg, IDC_USER_SHOW_MEMBER))
1522       lpp->pGroupsMember = pGroupList;
1523    else // (!IsDlgButtonChecked (hDlg, IDC_USER_SHOW_OWNER))
1524       lpp->pGroupsOwner = pGroupList;
1525
1526    FastList_End (hList);
1527 }
1528
1529
1530 void UserProp_Member_OnApply (HWND hDlg)
1531 {
1532    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1533
1534    // Free the old backup ASIDLIST copies we attached to the dialog during
1535    // WM_INITDIALOG processing.
1536    //
1537    LPASIDLIST pList;
1538    if ((pList = (LPASIDLIST)GetWindowData (hDlg, GWD_ASIDLIST_MEMBER)) != NULL)
1539       asc_AsidListFree (&pList);
1540    if ((pList = (LPASIDLIST)GetWindowData (hDlg, GWD_ASIDLIST_OWNER)) != NULL)
1541       asc_AsidListFree (&pList);
1542    SetWindowData (hDlg, GWD_ASIDLIST_MEMBER, 0);
1543    SetWindowData (hDlg, GWD_ASIDLIST_OWNER, 0);
1544
1545    if (lpp->pUserList)
1546       {
1547       // Start a background task to update the membership and ownership lists
1548       //
1549       if (lpp->pGroupsMember)
1550          {
1551          LPUSER_GROUPLIST_SET_PARAMS pTask = New (USER_GROUPLIST_SET_PARAMS);
1552          memset (pTask, 0x00, sizeof(USER_GROUPLIST_SET_PARAMS));
1553          asc_AsidListCopy (&pTask->pUsers, &lpp->pUserList);
1554          asc_AsidListCopy (&pTask->pGroups, &lpp->pGroupsMember);
1555          pTask->fMembership = TRUE;
1556          StartTask (taskUSER_GROUPLIST_SET, NULL, pTask);
1557          }
1558       if (lpp->pGroupsOwner)
1559          {
1560          LPUSER_GROUPLIST_SET_PARAMS pTask = New (USER_GROUPLIST_SET_PARAMS);
1561          memset (pTask, 0x00, sizeof(USER_GROUPLIST_SET_PARAMS));
1562          asc_AsidListCopy (&pTask->pUsers, &lpp->pUserList);
1563          asc_AsidListCopy (&pTask->pGroups, &lpp->pGroupsOwner);
1564          pTask->fMembership = FALSE;
1565          StartTask (taskUSER_GROUPLIST_SET, NULL, pTask);
1566          }
1567       }
1568 }
1569
1570
1571 void UserProp_UpdateName (HWND hDlg)
1572 {
1573    LPUSERPROPINFO lpp = (LPUSERPROPINFO)PropSheet_FindTabParam (hDlg);
1574
1575    if (IsWindow (GetDlgItem (hDlg, IDC_USER_NAME)))
1576       {
1577       if (!lpp->pUserList || (lpp->pUserList->cEntries == 1))
1578          {
1579          TCHAR szText[ cchRESOURCE ];
1580          GetDlgItemText (hDlg, IDC_USER_NAME, szText, cchRESOURCE);
1581
1582          ULONG status;
1583          TCHAR szName[ cchRESOURCE ];
1584          if (lpp->pUserList)
1585             User_GetDisplayName (szName, lpp->pUserList->aEntries[ 0 ].idObject);
1586          else
1587             asc_ObjectNameGet_Fast (g.idClient, g.idCell, g.idCell, szName, &status);
1588
1589          if (lpp->pUserList)
1590             {
1591             ASOBJPROP Properties;
1592             if (asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, lpp->pUserList->aEntries[ 0 ].idObject, &Properties, &status))
1593                AppendUID (szName, Properties.u.UserProperties.PTSINFO.uidName);
1594             }
1595
1596          LPTSTR pszText = FormatString (szText, TEXT("%s"), szName);
1597          SetDlgItemText (hDlg, IDC_USER_NAME, pszText);
1598          FreeString (pszText);
1599          }
1600       else if (lpp->pUserList && (lpp->pUserList->cEntries > 1))
1601          {
1602          LPTSTR pszText = CreateNameList (lpp->pUserList, IDS_USER_NAME_MULTIPLE);
1603          SetDlgItemText (hDlg, IDC_USER_NAME, pszText);
1604          FreeString (pszText);
1605          }
1606       }
1607 }
1608