windows-64-bit-type-safety-20051105
[openafs.git] / src / WINNT / afsusrmgr / grp_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 "grp_prop.h"
17 #include "usr_col.h"
18 #include "winlist.h"
19 #include "browse.h"
20
21
22 /*
23  * DEFINITIONS ________________________________________________________________
24  *
25  */
26
27 #define GWD_ASIDLIST_MEMBER   TEXT("AsidList - Members")
28 #define GWD_ASIDLIST_OWNER    TEXT("AsidList - Owned")
29
30
31 /*
32  * PROTOTYPES _________________________________________________________________
33  *
34  */
35
36 BOOL CALLBACK GroupProp_General_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
37 void GroupProp_General_OnInitDialog (HWND hDlg);
38 void GroupProp_General_OnDestroy (HWND hDlg);
39 void GroupProp_General_OnApply (HWND hDlg);
40 void GroupProp_General_OnBrowse (HWND hDlg);
41 void GroupProp_General_UpdateDialog (HWND hDlg);
42 void GroupProp_General_UpdateDialog_Perm (HWND hDlg, int idc, ACCOUNTACCESS aa, BOOL fMixed);
43
44 BOOL CALLBACK GroupProp_Member_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
45 void GroupProp_Member_OnInitDialog (HWND hDlg);
46 void GroupProp_Member_OnDestroy (HWND hDlg);
47 void GroupProp_Member_OnShowType (HWND hDlg);
48 void GroupProp_Member_OnSelect (HWND hDlg);
49 void GroupProp_Member_OnApply (HWND hDlg);
50 void GroupProp_Member_OnAdd (HWND hDlg);
51 void GroupProp_Member_OnRemove (HWND hDlg);
52 void GroupProp_Member_OnEndTask_GetMembers (HWND hDlg, LPTASKPACKET ptp);
53 void GroupProp_Member_OnEndTask_GetOwned (HWND hDlg, LPTASKPACKET ptp);
54 void GroupProp_Member_PopulateList (HWND hDlg);
55
56
57 /*
58  * ROUTINES ___________________________________________________________________
59  *
60  */
61
62 void Group_FreeProperties (LPGROUPPROPINFO lpp)
63 {
64    if (lpp)
65       {
66       if (lpp->fApplyGeneral && lpp->pGroupList)
67          {
68          for (size_t ii = 0; ii < lpp->pGroupList->cEntries; ++ii)
69             {
70             ULONG status;
71             ASOBJPROP Properties;
72             if (!asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, lpp->pGroupList->aEntries[ ii ].idObject, &Properties, &status))
73                continue;
74
75             LPGROUP_CHANGE_PARAMS pTask = New (GROUP_CHANGE_PARAMS);
76             memset (pTask, 0x00, sizeof(GROUP_CHANGE_PARAMS));
77             pTask->idGroup = lpp->pGroupList->aEntries[ ii ].idObject;
78
79             // From General tab:
80
81             if (!lpp->fApplyGeneral || lpp->fStatus_Mixed)
82                pTask->NewProperties.aaListStatus = Properties.u.GroupProperties.aaListStatus;
83             else
84                pTask->NewProperties.aaListStatus = lpp->aaStatus;
85
86             if (!lpp->fApplyGeneral || lpp->fGroups_Mixed)
87                pTask->NewProperties.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
88             else
89                pTask->NewProperties.aaListGroupsOwned = lpp->aaGroups;
90
91             if (!lpp->fApplyGeneral || lpp->fMembers_Mixed)
92                pTask->NewProperties.aaListMembers = Properties.u.GroupProperties.aaListMembers;
93             else
94                pTask->NewProperties.aaListMembers = lpp->aaMembers;
95
96             if (!lpp->fApplyGeneral || lpp->fAdd_Mixed)
97                pTask->NewProperties.aaAddMember = Properties.u.GroupProperties.aaAddMember;
98             else
99                pTask->NewProperties.aaAddMember = lpp->aaAdd;
100
101             if (!lpp->fApplyGeneral || lpp->fRemove_Mixed)
102                pTask->NewProperties.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
103             else
104                pTask->NewProperties.aaDeleteMember = lpp->aaRemove;
105
106             if (!lpp->fApplyGeneral || lpp->fOwner_Mixed)
107                lstrcpy (pTask->NewProperties.szOwner, Properties.u.GroupProperties.szOwner);
108             else
109                lstrcpy (pTask->NewProperties.szOwner, lpp->szOwner);
110
111             StartTask (taskGROUP_CHANGE, NULL, pTask);
112             }
113          }
114
115       if (lpp->pMembers)
116          asc_AsidListFree (&lpp->pMembers);
117       if (lpp->pGroupsOwner)
118          asc_AsidListFree (&lpp->pGroupsOwner);
119       if (lpp->pGroupList)
120          asc_AsidListFree (&lpp->pGroupList);
121       memset (lpp, 0x00, sizeof(GROUPPROPINFO));
122       Delete (lpp);
123       }
124 }
125
126
127 void Group_ShowProperties (LPASIDLIST pGroupList, GROUPPROPTAB gptTarget)
128 {
129    LPGROUPPROPINFO lpp = New (GROUPPROPINFO);
130    memset (lpp, 0x00, sizeof(GROUPPROPINFO));
131    lpp->pGroupList = pGroupList;
132    lpp->fDeleteMeOnClose = TRUE;
133    lpp->fShowModal = FALSE;
134    Group_ShowProperties (lpp, gptTarget);
135 }
136
137
138 void Group_ShowProperties (LPGROUPPROPINFO lpp, GROUPPROPTAB gptTarget)
139 {
140    HWND hSheet = NULL;
141
142    // If we've been asked to view properties for only one group, and there is
143    // already a window open for that group, switch to it.
144    //
145    if (lpp->pGroupList)
146       {
147       if (lpp->pGroupList->cEntries == 1)
148          {
149          ASID idGroup = lpp->pGroupList->aEntries[0].idObject;
150
151          if ((hSheet = WindowList_Search (wltGROUP_PROPERTIES, idGroup)) != NULL)
152             {
153             SetForegroundWindow (hSheet);
154             if (gptTarget != gptANY)
155                {
156                HWND hTab = GetDlgItem (hSheet, IDC_PROPSHEET_TABCTRL);
157                int nTabs = TabCtrl_GetItemCount (hTab);
158                if (nTabs < nGROUPPROPTAB_MAX)
159                   gptTarget = (GROUPPROPTAB)( ((int)gptTarget-1) );
160                TabCtrl_SwitchToTab (hTab, gptTarget);
161                }
162             return;
163             }
164          }
165
166       // Otherwise, make sure there are no Properties windows open for any
167       // of the selected groups
168       //
169       for (size_t iGroup = 0; iGroup < lpp->pGroupList->cEntries; ++iGroup)
170          {
171          ASID idGroup = lpp->pGroupList->aEntries[ iGroup ].idObject;
172
173          // See if there's a Properties window open that is dedicated to
174          // this group
175          //
176          if ((hSheet = WindowList_Search (wltGROUP_PROPERTIES, idGroup)) != NULL)
177             {
178             ErrorDialog (0, IDS_ERROR_GROUP_MULTIPROP);
179             return;
180             }
181
182          // See if there is a multiple-group properties window open; if so,
183          // test it to see if it covers this group
184          //
185          if ((hSheet = WindowList_Search (wltGROUP_PROPERTIES, 0)) != NULL)
186             {
187             LPGROUPPROPINFO pInfo = (LPGROUPPROPINFO)PropSheet_FindTabParam (hSheet);
188             if (pInfo && pInfo->pGroupList && asc_AsidListTest (&pInfo->pGroupList, idGroup))
189                {
190                ErrorDialog (0, IDS_ERROR_GROUP_MULTIPROP);
191                return;
192                }
193             }
194          }
195       }
196
197    // Okay, we're clear to create the new properties window.
198    //
199    LPTSTR pszTitle;
200    if (!lpp->pGroupList)
201       {
202       pszTitle = FormatString (IDS_NEWGROUP_PROPERTIES_TITLE);
203       }
204    else if (lpp->pGroupList->cEntries > 1)
205       {
206       pszTitle = FormatString (IDS_GROUP_PROPERTIES_TITLE_MULTIPLE);
207       }
208    else
209       {
210       TCHAR szGroup[ cchRESOURCE ];
211       asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->pGroupList->aEntries[0].idObject, szGroup);
212       pszTitle = FormatString (IDS_GROUP_PROPERTIES_TITLE, TEXT("%s"), szGroup);
213       }
214
215    LPPROPSHEET psh = PropSheet_Create (pszTitle, TRUE, NULL, (LPARAM)lpp);
216    PropSheet_AddTab (psh, 0, (lpp->pGroupList) ? IDD_GROUP_GENERAL : IDD_NEWGROUP_GENERAL, (DLGPROC)GroupProp_General_DlgProc, (LPARAM)lpp, TRUE, (gptTarget == gptGENERAL) ? TRUE : FALSE);
217    PropSheet_AddTab (psh, 0, (lpp->pGroupList) ? IDD_GROUP_MEMBER : IDD_NEWGROUP_MEMBER, (DLGPROC)GroupProp_Member_DlgProc, (LPARAM)lpp, TRUE, (gptTarget == gptMEMBERS) ? TRUE : FALSE);
218
219    if (lpp->fShowModal)
220       PropSheet_ShowModal (psh, PumpMessage);
221    else
222       PropSheet_ShowModeless (psh, SW_SHOW);
223 }
224
225
226 BOOL CALLBACK GroupProp_General_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
227 {
228    if (AfsAppLib_HandleHelp (IDD_GROUP_GENERAL, hDlg, msg, wp, lp))
229       return TRUE;
230
231    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
232
233    switch (msg)
234       {
235       case WM_INITDIALOG_SHEET:
236          if (lpp && lpp->pGroupList && !lpp->fShowModal)
237             {
238             if (lpp->pGroupList->cEntries == 1)
239                WindowList_Add (hDlg, wltGROUP_PROPERTIES, lpp->pGroupList->aEntries[0].idObject);
240             else // (lpp->pGroupList->cEntries > 1)
241                WindowList_Add (hDlg, wltGROUP_PROPERTIES, 0);
242             }
243          break;
244
245       case WM_DESTROY_SHEET:
246          WindowList_Remove (hDlg);
247          if (lpp && lpp->fDeleteMeOnClose)
248             Group_FreeProperties (lpp);
249          break;
250
251       case WM_INITDIALOG:
252          GroupProp_General_OnInitDialog (hDlg);
253          break;
254
255       case WM_DESTROY:
256          GroupProp_General_OnDestroy (hDlg);
257          break;
258
259       case WM_ASC_NOTIFY_OBJECT:
260          GroupProp_General_UpdateDialog (hDlg);
261          break;
262
263       case WM_COMMAND:
264          switch (LOWORD(wp))
265             {
266             case IDAPPLY:
267                GroupProp_General_OnApply (hDlg);
268                break;
269
270             case IDC_GROUP_CHANGEOWNER:
271                GroupProp_General_OnBrowse (hDlg);
272                break;
273
274             case IDC_GROUP_PERM_STATUS:
275             case IDC_GROUP_PERM_GROUPS:
276             case IDC_GROUP_PERM_MEMBERS:
277             case IDC_GROUP_PERM_ADD:
278             case IDC_GROUP_PERM_REMOVE:
279                if (HIWORD(wp) == CBN_SELCHANGE)
280                   PropSheetChanged (hDlg);
281                break;
282             }
283          break;
284       }
285
286    return FALSE;
287 }
288
289
290 void GroupProp_General_OnInitDialog (HWND hDlg)
291 {
292    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
293
294    // Indicate we want to know if anything changes with these groups
295    //
296    if (lpp->pGroupList)
297       {
298       LPOBJECT_LISTEN_PARAMS pTask = New (OBJECT_LISTEN_PARAMS);
299       memset (pTask, 0x00, sizeof(OBJECT_LISTEN_PARAMS));
300       pTask->hNotify = hDlg;
301       asc_AsidListCopy (&pTask->pAsidList, &lpp->pGroupList);
302       StartTask (taskOBJECT_LISTEN, NULL, pTask);
303       }
304
305    // Fill in the information about the selected groups
306    //
307    GroupProp_General_UpdateDialog (hDlg);
308 }
309
310
311 void GroupProp_General_OnDestroy (HWND hDlg)
312 {
313    // Indicate we no longer care if anything changes with these groups
314    //
315    LPOBJECT_LISTEN_PARAMS pTask = New (OBJECT_LISTEN_PARAMS);
316    memset (pTask, 0x00, sizeof(OBJECT_LISTEN_PARAMS));
317    pTask->hNotify = hDlg;
318    StartTask (taskOBJECT_LISTEN, NULL, pTask);
319 }
320
321
322 void GroupProp_General_UpdateDialog (HWND hDlg)
323 {
324    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
325
326    // Fix the name shown on the dialog
327    //
328    if (!lpp->pGroupList || (lpp->pGroupList->cEntries == 1))
329       {
330       ULONG status;
331       TCHAR szName[ cchRESOURCE ];
332       asc_ObjectNameGet_Fast (g.idClient, g.idCell, (lpp->pGroupList) ? (lpp->pGroupList->aEntries[ 0 ].idObject) : g.idCell, szName, &status);
333
334       if (lpp->pGroupList)
335          {
336          ASOBJPROP Properties;
337          if (asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, lpp->pGroupList->aEntries[ 0 ].idObject, &Properties, &status))
338             AppendUID (szName, Properties.u.GroupProperties.uidName);
339          }
340
341       LPTSTR pszText = FormatString (IDS_GROUP_TITLE, TEXT("%s"), szName);
342       SetDlgItemText (hDlg, IDC_GROUP_NAME, pszText);
343       FreeString (pszText);
344       }
345    else  // More than one name?
346       {
347       LPTSTR pszText = CreateNameList (lpp->pGroupList, IDS_GROUP_NAME_MULTIPLE);
348       SetDlgItemText (hDlg, IDC_GROUP_NAME, pszText);
349       FreeString (pszText);
350       }
351
352    // Fill in the rest of the dialog
353    //
354    BOOL fGotAnyData = FALSE;
355
356    for (size_t ii = 0; lpp->pGroupList && (ii < lpp->pGroupList->cEntries); ++ii)
357       {
358       ULONG status;
359       ASOBJPROP Properties;
360       if (!asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, lpp->pGroupList->aEntries[ ii ].idObject, &Properties, &status))
361          continue;
362
363       if (!fGotAnyData)
364          {
365          lpp->aaStatus = Properties.u.GroupProperties.aaListStatus;
366          lpp->aaGroups = Properties.u.GroupProperties.aaListGroupsOwned;
367          lpp->aaMembers = Properties.u.GroupProperties.aaListMembers;
368          lpp->aaAdd = Properties.u.GroupProperties.aaAddMember;
369          lpp->aaRemove = Properties.u.GroupProperties.aaDeleteMember;
370          lstrcpy (lpp->szOwner, Properties.u.GroupProperties.szOwner);
371          AppendUID (lpp->szOwner, Properties.u.GroupProperties.uidOwner);
372          lstrcpy (lpp->szCreator, Properties.u.GroupProperties.szCreator);
373          AppendUID (lpp->szCreator, Properties.u.GroupProperties.uidCreator);
374          fGotAnyData = TRUE;
375          }
376       else // (fGotAnyData)
377          {
378          if (lpp->aaStatus != Properties.u.GroupProperties.aaListStatus)
379             lpp->fStatus_Mixed = TRUE;
380          if (lpp->aaGroups != Properties.u.GroupProperties.aaListGroupsOwned)
381             lpp->fGroups_Mixed = TRUE;
382          if (lpp->aaMembers != Properties.u.GroupProperties.aaListMembers)
383             lpp->fMembers_Mixed = TRUE;
384          if (lpp->aaAdd != Properties.u.GroupProperties.aaAddMember)
385             lpp->fAdd_Mixed = TRUE;
386          if (lpp->aaRemove != Properties.u.GroupProperties.aaDeleteMember)
387             lpp->fRemove_Mixed = TRUE;
388
389          TCHAR szThisOwner[ cchNAME ];
390          lstrcpy (szThisOwner, Properties.u.GroupProperties.szOwner);
391          AppendUID (szThisOwner, Properties.u.GroupProperties.uidOwner);
392          if (lstrcmpi (lpp->szOwner, szThisOwner))
393             lpp->fOwner_Mixed = TRUE;
394
395          TCHAR szThisCreator[ cchNAME ];
396          lstrcpy (szThisCreator, Properties.u.GroupProperties.szCreator);
397          AppendUID (szThisCreator, Properties.u.GroupProperties.uidCreator);
398          if (lstrcmpi (lpp->szCreator, szThisCreator))
399             lpp->fCreator_Mixed = TRUE;
400          }
401       }
402
403    // Fill in the dialog's controls
404    //
405    GroupProp_General_UpdateDialog_Perm (hDlg, IDC_GROUP_PERM_STATUS, lpp->aaStatus, lpp->fStatus_Mixed);
406    GroupProp_General_UpdateDialog_Perm (hDlg, IDC_GROUP_PERM_GROUPS, lpp->aaGroups, lpp->fGroups_Mixed);
407    GroupProp_General_UpdateDialog_Perm (hDlg, IDC_GROUP_PERM_MEMBERS, lpp->aaMembers, lpp->fMembers_Mixed);
408    GroupProp_General_UpdateDialog_Perm (hDlg, IDC_GROUP_PERM_ADD, lpp->aaAdd, lpp->fAdd_Mixed);
409    GroupProp_General_UpdateDialog_Perm (hDlg, IDC_GROUP_PERM_REMOVE, lpp->aaRemove, lpp->fRemove_Mixed);
410
411    if (lpp->fOwner_Mixed)
412       GetString (lpp->szOwner, IDS_OWNER_MIXED);
413    if (lpp->fCreator_Mixed)
414       GetString (lpp->szCreator, IDS_CREATOR_MIXED);
415    SetDlgItemText (hDlg, IDC_GROUP_OWNER, lpp->szOwner);
416    SetDlgItemText (hDlg, IDC_GROUP_CREATOR, lpp->szCreator);
417 }
418
419
420 void GroupProp_General_UpdateDialog_Perm (HWND hDlg, int idc, ACCOUNTACCESS aa, BOOL fMixed)
421 {
422    CB_StartChange (GetDlgItem (hDlg, idc), TRUE);
423    CB_AddItem (GetDlgItem (hDlg, idc), IDS_ACCOUNTACCESS_OWNGROUP, aaOWNER_ONLY);
424    if (idc != IDC_GROUP_PERM_GROUPS)
425       CB_AddItem (GetDlgItem (hDlg, idc), IDS_ACCOUNTACCESS_GROUP, aaGROUP_ONLY);
426    if (idc != IDC_GROUP_PERM_REMOVE)
427       CB_AddItem (GetDlgItem (hDlg, idc), IDS_ACCOUNTACCESS_ANYONE, aaANYONE);
428    if (fMixed)
429       CB_AddItem (GetDlgItem (hDlg, idc), IDS_ACCOUNTACCESS_MIXED, (LPARAM)-1);
430    CB_EndChange (GetDlgItem (hDlg, idc), TRUE);
431
432    LPARAM lpSelect = (fMixed) ? ((LPARAM)-1) : (LPARAM)aa;
433    CB_SetSelectedByData (GetDlgItem (hDlg, idc), lpSelect);
434 }
435
436
437 void GroupProp_General_OnApply (HWND hDlg)
438 {
439    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
440
441    lpp->fApplyGeneral = TRUE;
442
443    GetDlgItemText (hDlg, IDC_GROUP_OWNER, lpp->szOwner, cchNAME);
444
445    TCHAR szOwnerMixed[ cchNAME ];
446    GetString (szOwnerMixed, IDS_OWNER_MIXED);
447    if (!lstrcmpi (lpp->szOwner, szOwnerMixed))
448       {
449       lpp->szOwner[0] = TEXT('\0');
450       lpp->fOwner_Mixed = TRUE;
451       }
452    else
453       {
454       LPTSTR pch;
455       if ((pch = (LPTSTR)lstrchr (lpp->szOwner, TEXT(' '))) != NULL)
456          *pch = TEXT('\0'); // strip off any displayed UID
457       lpp->fOwner_Mixed = FALSE;
458       }
459
460    lpp->aaStatus = (ACCOUNTACCESS)CB_GetSelectedData (GetDlgItem (hDlg, IDC_GROUP_PERM_STATUS));
461    lpp->fStatus_Mixed = (lpp->aaStatus == (ACCOUNTACCESS)-1);
462    lpp->aaGroups = (ACCOUNTACCESS)CB_GetSelectedData (GetDlgItem (hDlg, IDC_GROUP_PERM_GROUPS));
463    lpp->fGroups_Mixed = (lpp->aaGroups == (ACCOUNTACCESS)-1);
464    lpp->aaMembers = (ACCOUNTACCESS)CB_GetSelectedData (GetDlgItem (hDlg, IDC_GROUP_PERM_MEMBERS));
465    lpp->fMembers_Mixed = (lpp->aaMembers == (ACCOUNTACCESS)-1);
466    lpp->aaAdd = (ACCOUNTACCESS)CB_GetSelectedData (GetDlgItem (hDlg, IDC_GROUP_PERM_ADD));
467    lpp->fAdd_Mixed = (lpp->aaAdd == (ACCOUNTACCESS)-1);
468    lpp->aaRemove = (ACCOUNTACCESS)CB_GetSelectedData (GetDlgItem (hDlg, IDC_GROUP_PERM_REMOVE));
469    lpp->fRemove_Mixed = (lpp->aaRemove == (ACCOUNTACCESS)-1);
470 }
471
472
473 void GroupProp_General_OnBrowse (HWND hDlg)
474 {
475    BROWSE_PARAMS pp;
476    memset (&pp, 0x00, sizeof(pp));
477    pp.hParent = hDlg;
478    pp.iddForHelp = IDD_BROWSE_OWNER;
479    pp.idsTitle = IDS_GROUP_CHANGEOWNER_TITLE;
480    pp.idsPrompt = IDS_GROUP_CHANGEOWNER_PROMPT;
481    pp.idsCheck = 0;
482    pp.TypeToShow = (ASOBJTYPE)( (ULONG)TYPE_USER | (ULONG)TYPE_GROUP );
483    pp.fAllowMultiple = FALSE;
484    GetDlgItemText (hDlg, IDC_GROUP_OWNER, pp.szName, cchNAME);
485
486    TCHAR szOwnerMixed[ cchNAME ];
487    GetString (szOwnerMixed, IDS_OWNER_MIXED);
488    LPTSTR pch;
489    if (!lstrcmpi (pp.szName, szOwnerMixed))
490       pp.szName[0] = TEXT('\0');
491    else if ((pch = (LPTSTR)lstrchr (pp.szName, TEXT(' '))) != NULL)
492       *pch = TEXT('\0');
493
494    if (ShowBrowseDialog (&pp))
495       {
496       TCHAR szName[ cchNAME ];
497       lstrcpy (szName, pp.szName);
498
499       if (pp.pObjectsSelected && (pp.pObjectsSelected->cEntries == 1))
500          {
501          ULONG status;
502          ASOBJPROP Properties;
503          if (asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, pp.pObjectsSelected->aEntries[0].idObject, &Properties, &status))
504             {
505             if (Properties.Type == TYPE_USER)
506                AppendUID (szName, Properties.u.UserProperties.PTSINFO.uidName);
507             else if (Properties.Type == TYPE_GROUP)
508                AppendUID (szName, Properties.u.GroupProperties.uidName);
509             }
510          }
511
512       SetDlgItemText (hDlg, IDC_GROUP_OWNER, szName);
513       }
514
515    if (pp.pObjectsSelected)
516       asc_AsidListFree (&pp.pObjectsSelected);
517 }
518
519
520 BOOL CALLBACK GroupProp_Member_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
521 {
522    if (AfsAppLib_HandleHelp (IDD_GROUP_MEMBER, hDlg, msg, wp, lp))
523       return TRUE;
524
525    switch (msg)
526       {
527       case WM_INITDIALOG:
528          GroupProp_Member_OnInitDialog (hDlg);
529          break;
530
531       case WM_DESTROY:
532          GroupProp_Member_OnDestroy (hDlg);
533          break;
534
535       case WM_ENDTASK:
536          LPTASKPACKET ptp;
537          if ((ptp = (LPTASKPACKET)lp) != NULL)
538             {
539             if (ptp->idTask == taskGROUP_MEMBERS_GET)
540                GroupProp_Member_OnEndTask_GetMembers (hDlg, ptp);
541             else if (ptp->idTask == taskGROUP_OWNED_GET)
542                GroupProp_Member_OnEndTask_GetOwned (hDlg, ptp);
543             FreeTaskPacket (ptp);
544             }
545          break;
546
547       case WM_COMMAND:
548          switch (LOWORD(wp))
549             {
550             case IDAPPLY:
551                GroupProp_Member_OnApply (hDlg);
552                break;
553
554             case IDC_GROUP_SHOW_MEMBER:
555             case IDC_GROUP_SHOW_OWNER:
556                GroupProp_Member_OnShowType (hDlg);
557                break;
558
559             case IDC_MEMBER_ADD:
560                GroupProp_Member_OnAdd (hDlg);
561                break;
562
563             case IDC_MEMBER_REMOVE:
564                GroupProp_Member_OnRemove (hDlg);
565                break;
566             }
567          break;
568
569       case WM_NOTIFY:
570          switch (((LPNMHDR)lp)->code)
571             {
572             case FLN_ITEMSELECT:
573                GroupProp_Member_OnSelect (hDlg);
574                break;
575             }
576          break;
577       }
578    return FALSE;
579 }
580
581
582 void GroupProp_Member_OnInitDialog (HWND hDlg)
583 {
584    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
585
586    // If we've come in here with a valid set of groups to display,
587    // copy those. We'll need the copies if the user cancels the dialog.
588    //
589    SetWindowData (hDlg, GWD_ASIDLIST_MEMBER, (UINT_PTR)(lpp->pMembers));
590    SetWindowData (hDlg, GWD_ASIDLIST_OWNER,  (UINT_PTR)(lpp->pGroupsOwner));
591
592    LPASIDLIST pList;
593    if ((pList = lpp->pMembers) != NULL)
594       asc_AsidListCopy (&lpp->pMembers, &pList);
595    if ((pList = lpp->pGroupsOwner) != NULL)
596       asc_AsidListCopy (&lpp->pGroupsOwner, &pList);
597
598    // If this prop sheet reflects more than one group, disable the
599    // Ownership button (we do this primarily because the Add/Remove
600    // buttons have no straight-forward semantic for that case).
601    // Actually, instead of disabling the thing, we'll hide the buttons
602    // entirely and resize the list/move the title.
603    //
604    if (lpp->pGroupList && (lpp->pGroupList->cEntries > 1))
605       {
606       ShowWindow (GetDlgItem (hDlg, IDC_GROUP_SHOW_MEMBER), SW_HIDE);
607       ShowWindow (GetDlgItem (hDlg, IDC_GROUP_SHOW_OWNER), SW_HIDE);
608
609       RECT rButton;
610       GetRectInParent (GetDlgItem (hDlg, IDC_GROUP_SHOW_MEMBER), &rButton);
611
612       RECT rTitle;
613       GetRectInParent (GetDlgItem (hDlg, IDC_USERS_TITLE), &rTitle);
614
615       RECT rList;
616       GetRectInParent (GetDlgItem (hDlg, IDC_USERS_LIST), &rList);
617
618       LONG cyDelta = rTitle.top - rButton.top;
619
620       SetWindowPos (GetDlgItem (hDlg, IDC_USERS_TITLE), NULL,
621                     rTitle.left, rTitle.top-cyDelta,
622                     rTitle.right-rTitle.left, rTitle.bottom-rTitle.top,
623                     SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
624
625       SetWindowPos (GetDlgItem (hDlg, IDC_USERS_LIST), NULL,
626                     rList.left, rList.top-cyDelta,
627                     rList.right-rList.left, rList.bottom-rList.top+cyDelta,
628                     SWP_NOZORDER | SWP_NOACTIVATE);
629       }
630
631    // Apply an imagelist to the dialog's fastlist
632    //
633    FastList_SetImageLists (GetDlgItem (hDlg, IDC_USERS_LIST), AfsAppLib_CreateImageList (FALSE), NULL);
634
635    // Select a checkbox and pretend that the user clicked it; that will
636    // make the dialog automatically re-populate the list of groups
637    //
638    CheckDlgButton (hDlg, IDC_GROUP_SHOW_MEMBER, TRUE);
639    GroupProp_Member_OnShowType (hDlg);
640 }
641
642
643 void GroupProp_Member_OnDestroy (HWND hDlg)
644 {
645    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
646
647    LPASIDLIST pList;
648    if ((pList = (LPASIDLIST)GetWindowData (hDlg, GWD_ASIDLIST_MEMBER)) != NULL)
649       lpp->pMembers = pList;
650    if ((pList = (LPASIDLIST)GetWindowData (hDlg, GWD_ASIDLIST_OWNER)) != NULL)
651       lpp->pGroupsOwner = pList;
652 }
653
654
655 void GroupProp_Member_OnShowType (HWND hDlg)
656 {
657    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
658
659    // If we've already obtained the list of users we should be displaying,
660    // just go show it.
661    //
662    if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER))
663       {
664       if (lpp->pMembers)
665          {
666          GroupProp_Member_PopulateList (hDlg);
667          return;
668          }
669       }
670    else // (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_OWNER))
671       {
672       if (lpp->pGroupsOwner)
673          {
674          GroupProp_Member_PopulateList (hDlg);
675          return;
676          }
677       }
678
679    // Otherwise, we'll have to start a background task to do the querying.
680    // Change the text above the list to "Querying...", disable the buttons,
681    // and remove any items in the list
682    //
683    if (!lpp->pGroupList)
684       {
685       // Generate a few empty ASID list; this is a new group account we're
686       // displaying, and the caller hasn't yet added any members to it.
687       //
688       if (!lpp->pMembers)
689          {
690          if (!asc_AsidListCreate (&lpp->pMembers))
691             return;
692          }
693       if (!lpp->pGroupsOwner)
694          {
695          if (!asc_AsidListCreate (&lpp->pGroupsOwner))
696             return;
697          }
698       GroupProp_Member_OnShowType (hDlg);
699       }
700    else // (lpp->pUserList)
701       {
702       TCHAR szTitle[ cchRESOURCE ];
703       GetString (szTitle, IDS_QUERYING_LONG);
704       SetDlgItemText (hDlg, IDC_USERS_TITLE, szTitle);
705
706       EnableWindow (GetDlgItem (hDlg, IDC_MEMBER_ADD), FALSE);
707       EnableWindow (GetDlgItem (hDlg, IDC_MEMBER_REMOVE), FALSE);
708
709       FastList_RemoveAll (GetDlgItem (hDlg, IDC_USERS_LIST));
710
711       // Then start a background task to grab an ASIDLIST of users which
712       // match the specified search criteria.
713       //
714       if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER))
715          {
716          LPASIDLIST pGroups;
717          asc_AsidListCopy (&pGroups, &lpp->pGroupList);
718          StartTask (taskGROUP_MEMBERS_GET, hDlg, pGroups);
719          }
720       else // (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_OWNER))
721          {
722          StartTask (taskGROUP_OWNED_GET, hDlg, (PVOID)(lpp->pGroupList->aEntries[0].idObject));
723          }
724       }
725 }
726
727
728 void GroupProp_Member_OnEndTask_GetMembers (HWND hDlg, LPTASKPACKET ptp)
729 {
730    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
731
732    // The search is complete. If we've just obtained an ASIDLIST successfully,
733    // associate it with the dialog and repopulate the display.
734    //
735    if (ptp->rc && TASKDATA(ptp)->pAsidList)
736       {
737       if (!lpp->pMembers)
738          {
739          asc_AsidListCopy (&lpp->pMembers, &TASKDATA(ptp)->pAsidList);
740          GroupProp_Member_PopulateList (hDlg);
741          }
742       }
743 }
744
745
746 void GroupProp_Member_OnEndTask_GetOwned (HWND hDlg, LPTASKPACKET ptp)
747 {
748    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
749
750    // The search is complete. If we've just obtained an ASIDLIST successfully,
751    // associate it with the dialog and repopulate the display.
752    //
753    if (ptp->rc && TASKDATA(ptp)->pAsidList)
754       {
755       if (!lpp->pGroupsOwner)
756          {
757          asc_AsidListCopy (&lpp->pGroupsOwner, &TASKDATA(ptp)->pAsidList);
758          GroupProp_Member_PopulateList (hDlg);
759          }
760       }
761 }
762
763
764 void GroupProp_Member_PopulateList (HWND hDlg)
765 {
766    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
767
768    // Clear the list of members/owned groups
769    //
770    HWND hList = GetDlgItem (hDlg, IDC_USERS_LIST);
771    FastList_Begin (hList);
772    FastList_RemoveAll (hList);
773
774    // We should have an ASIDLIST associated with the dialog to reflect
775    // which objects to display. Find it, and repopulate the list on
776    // the display.
777    //
778    LPASIDLIST pDisplay;
779    if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER))
780       pDisplay = lpp->pMembers;
781    else // (!IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_OWNER))
782       pDisplay = lpp->pGroupsOwner;
783
784    if (pDisplay)
785       {
786       TCHAR szMixed[ cchRESOURCE ];
787       GetString (szMixed, IDS_MEMBER_MIXED);
788
789       for (size_t ii = 0; ii < pDisplay->cEntries; ++ii)
790          {
791          ULONG status;
792          ASOBJPROP Properties;
793          if (!asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, pDisplay->aEntries[ ii ].idObject, &Properties, &status))
794             continue;
795
796          TCHAR szName[ cchNAME ];
797          if (Properties.Type == TYPE_USER)
798             User_GetDisplayName (szName, &Properties);
799          else
800             lstrcpy (szName, Properties.szName);
801
802          if (!pDisplay->aEntries[ ii ].lParam)
803             lstrcat (szName, szMixed);
804
805          FASTLISTADDITEM flai;
806          memset (&flai, 0x00, sizeof(flai));
807          flai.iFirstImage = (Properties.Type == TYPE_USER) ? imageUSER : imageGROUP;
808          flai.iSecondImage = IMAGE_NOIMAGE;
809          flai.pszText = szName;
810          flai.lParam = (LPARAM)(pDisplay->aEntries[ ii ].idObject);
811          FastList_AddItem (hList, &flai);
812          }
813       }
814
815    FastList_End (hList);
816
817    // Fix the buttons, and the text at the top of the list
818    //
819    TCHAR szTitle[ cchRESOURCE ];
820    if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER))
821       GetString (szTitle, (!lpp->pGroupList) ? IDS_NEWGROUP_SHOW_MEMBER_TITLE : (lpp->pGroupList->cEntries == 1) ? IDS_GROUP_SHOW_MEMBER_TITLE : IDS_GROUP_SHOW_MEMBER_TITLE_MULTIPLE);
822    else
823       GetString (szTitle, (!lpp->pGroupList) ? IDS_NEWGROUP_SHOW_OWNED_TITLE : IDS_GROUP_SHOW_OWNED_TITLE);
824
825    SetDlgItemText (hDlg, IDC_USERS_TITLE, szTitle);
826
827    EnableWindow (GetDlgItem (hDlg, IDC_MEMBER_ADD), TRUE);
828    GroupProp_Member_OnSelect (hDlg);
829 }
830
831
832 void GroupProp_Member_OnSelect (HWND hDlg)
833 {
834    BOOL fEnable = IsWindowEnabled (GetDlgItem (hDlg, IDC_MEMBER_ADD));
835    if (fEnable && !FastList_FindFirstSelected (GetDlgItem (hDlg, IDC_USERS_LIST)))
836       fEnable = FALSE;
837    EnableWindow (GetDlgItem (hDlg, IDC_MEMBER_REMOVE), fEnable);
838 }
839
840
841 void GroupProp_Member_OnAdd (HWND hDlg)
842 {
843    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
844
845    LPBROWSE_PARAMS pParams = New (BROWSE_PARAMS);
846    memset (pParams, 0x00, sizeof(BROWSE_PARAMS));
847    pParams->hParent = GetParent(hDlg);
848    pParams->iddForHelp = IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER) ? IDD_BROWSE_MEMBER : IDD_BROWSE_OWNED;
849    pParams->idsTitle = IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER) ? IDS_BROWSE_TITLE_MEMBER : IDS_BROWSE_TITLE_OWNED;
850    pParams->idsPrompt = IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER) ? IDS_BROWSE_PROMPT_MEMBER : IDS_BROWSE_PROMPT_OWNED;
851    pParams->idsCheck = IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER) ? IDS_BROWSE_CHECK_MEMBER : IDS_BROWSE_CHECK_OWNED;
852    pParams->fAllowMultiple = TRUE;
853    if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER))
854       pParams->TypeToShow = (ASOBJTYPE)( (ULONG)TYPE_USER | (ULONG)TYPE_GROUP );
855    else // (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_OWNER))
856       pParams->TypeToShow = TYPE_GROUP;
857
858    // First prepare an ASIDLIST which reflects only the groups which
859    // all selected users own/are members in.
860    //
861    LPASIDLIST pDisplay;
862    if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER))
863       pDisplay = lpp->pMembers;
864    else // (!IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_OWNER))
865       pDisplay = lpp->pGroupsOwner;
866
867    if (pDisplay)
868       {
869       asc_AsidListCreate (&pParams->pObjectsToSkip);
870       for (size_t ii = 0; ii < pDisplay->cEntries; ++ii)
871          {
872          if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_OWNER) || pDisplay->aEntries[ ii ].lParam) // all groups have this member?
873             asc_AsidListAddEntry (&pParams->pObjectsToSkip, pDisplay->aEntries[ ii ].idObject, 0);
874          }
875       }
876
877    if (ShowBrowseDialog (pParams))
878       {
879       // The user added some entries; modify pDisplay (and the dialog,
880       // at the same time).
881       //
882       HWND hList = GetDlgItem (hDlg, IDC_USERS_LIST);
883       FastList_Begin (hList);
884
885       for (size_t ii = 0; ii < pParams->pObjectsSelected->cEntries; ++ii)
886          {
887          ASID idMember = pParams->pObjectsSelected->aEntries[ ii ].idObject;
888
889          // The user has chosen to add member {idMember}. If it's not in our
890          // list at all, add it (and a new entry for the display). If it
891          // *is* in our list, make sure its lParam is 1--indicating all users
892          // get it--and modify the display's entry to remove the "(some)"
893          // marker.
894          //
895          LPARAM lParam;
896          if (!asc_AsidListTest (&pDisplay, idMember, &lParam))
897             {
898             ULONG status;
899             ASOBJPROP Properties;
900             if (!asc_ObjectPropertiesGet_Fast (g.idClient, g.idCell, idMember, &Properties, &status))
901                continue;
902
903             asc_AsidListAddEntry (&pDisplay, idMember, TRUE);
904
905             FASTLISTADDITEM flai;
906             memset (&flai, 0x00, sizeof(flai));
907             flai.iFirstImage = (Properties.Type == TYPE_USER) ? imageUSER : imageGROUP;
908             flai.iSecondImage = IMAGE_NOIMAGE;
909             flai.pszText = Properties.szName;
910             flai.lParam = (LPARAM)idMember;
911             FastList_AddItem (hList, &flai);
912             PropSheetChanged (hDlg);
913             }
914          else if (!lParam)
915             {
916             TCHAR szName[ cchNAME ];
917             if (!User_GetDisplayName (szName, idMember))
918                continue;
919
920             asc_AsidListSetEntryParam (&pDisplay, idMember, TRUE);
921
922             HLISTITEM hItem;
923             if ((hItem = FastList_FindItem (hList, (LPARAM)idMember)) != NULL)
924                FastList_SetItemText (hList, hItem, 0, szName);
925             PropSheetChanged (hDlg);
926             }
927          }
928
929       if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER))
930          lpp->pMembers = pDisplay;
931       else // (!IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_OWNER))
932          lpp->pGroupsOwner = pDisplay;
933
934       FastList_End (hList);
935       }
936
937    if (pParams->pObjectsToSkip)
938       asc_AsidListFree (&pParams->pObjectsToSkip);
939    if (pParams->pObjectsSelected)
940       asc_AsidListFree (&pParams->pObjectsSelected);
941    Delete (pParams);
942 }
943
944
945 void GroupProp_Member_OnRemove (HWND hDlg)
946 {
947    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
948
949    // Find which list-of-members is currently being displayed.
950    //
951    LPASIDLIST pDisplay;
952    if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER))
953       pDisplay = lpp->pMembers;
954    else // (!IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_OWNER))
955       pDisplay = lpp->pGroupsOwner;
956
957    // The user wants to remove some members/owned groups; modify pDisplay
958    // (and the dialog, at the same time).
959    //
960    HWND hList = GetDlgItem (hDlg, IDC_USERS_LIST);
961    FastList_Begin (hList);
962
963    HLISTITEM hItem;
964    while ((hItem = FastList_FindFirstSelected (hList)) != NULL)
965       {
966       ASID idMember = (ASID)FastList_GetItemParam (hList, hItem);
967       FastList_RemoveItem (hList, hItem);
968       asc_AsidListRemoveEntry (&pDisplay, idMember);
969       PropSheetChanged (hDlg);
970       }
971
972    if (IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_MEMBER))
973       lpp->pMembers = pDisplay;
974    else // (!IsDlgButtonChecked (hDlg, IDC_GROUP_SHOW_OWNER))
975       lpp->pGroupsOwner = pDisplay;
976
977    FastList_End (hList);
978 }
979
980
981 void GroupProp_Member_OnApply (HWND hDlg)
982 {
983    LPGROUPPROPINFO lpp = (LPGROUPPROPINFO)PropSheet_FindTabParam (hDlg);
984
985    // Free the old backup ASIDLIST copies we attached to the dialog during
986    // WM_INITDIALOG processing.
987    //
988    LPASIDLIST pList;
989    if ((pList = (LPASIDLIST)GetWindowData (hDlg, GWD_ASIDLIST_MEMBER)) != NULL)
990       asc_AsidListFree (&pList);
991    if ((pList = (LPASIDLIST)GetWindowData (hDlg, GWD_ASIDLIST_OWNER)) != NULL)
992       asc_AsidListFree (&pList);
993    SetWindowData (hDlg, GWD_ASIDLIST_MEMBER, 0);
994    SetWindowData (hDlg, GWD_ASIDLIST_OWNER, 0);
995
996    if (lpp->pGroupList)
997       {
998       // Start a background task to update the member-list etc
999       //
1000       if (lpp->pMembers)
1001          {
1002          LPGROUP_MEMBERS_SET_PARAMS pTask = New (GROUP_MEMBERS_SET_PARAMS);
1003          memset (pTask, 0x00, sizeof(GROUP_MEMBERS_SET_PARAMS));
1004          asc_AsidListCopy (&pTask->pGroups, &lpp->pGroupList);
1005          asc_AsidListCopy (&pTask->pMembers, &lpp->pMembers);
1006          StartTask (taskGROUP_MEMBERS_SET, NULL, pTask);
1007          }
1008       if (lpp->pGroupsOwner)
1009          {
1010          LPGROUP_OWNED_SET_PARAMS pTask = New (GROUP_OWNED_SET_PARAMS);
1011          memset (pTask, 0x00, sizeof(GROUP_OWNED_SET_PARAMS));
1012          pTask->idGroup = lpp->pGroupList->aEntries[0].idObject;
1013          asc_AsidListCopy (&pTask->pOwnedGroups, &lpp->pGroupsOwner);
1014          StartTask (taskGROUP_OWNED_SET, NULL, pTask);
1015          }
1016       }
1017 }
1018