2 * Copyright 2000, International Business Machines Corporation and others.
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
11 #include <afs/param.h>
15 #include "TaAfsUsrMgr.h"
23 * DEFINITIONS ________________________________________________________________
28 #define iswhite(_ch) ( ((_ch) == TEXT(' ')) || ((_ch) == TEXT('\t')) )
32 * PROTOTYPES _________________________________________________________________
36 void Task_OpenCell (LPTASKPACKET ptp);
37 void Task_UpdCreds (LPTASKPACKET ptp);
38 void Task_UpdUsers (LPTASKPACKET ptp);
39 void Task_UpdGroups (LPTASKPACKET ptp);
40 void Task_UpdMachines (LPTASKPACKET ptp);
41 void Task_Refresh (LPTASKPACKET ptp);
42 void Task_RefreshMult (LPTASKPACKET ptp);
43 void Task_Get_Actions (LPTASKPACKET ptp);
44 void Task_Get_Random_Key (LPTASKPACKET ptp);
45 void Task_User_Change (LPTASKPACKET ptp);
46 void Task_User_Find (LPTASKPACKET ptp);
47 void Task_User_Enum (LPTASKPACKET ptp);
48 void Task_User_GroupList_Set (LPTASKPACKET ptp);
49 BOOL Task_User_GroupList_Set_Do (LPUSER_GROUPLIST_SET_PARAMS lpp, ULONG *pStatus);
50 void Task_User_CPW (LPTASKPACKET ptp);
51 void Task_User_Unlock (LPTASKPACKET ptp);
52 void Task_User_Create (LPTASKPACKET ptp);
53 void Task_User_Delete (LPTASKPACKET ptp);
54 void Task_Group_Change (LPTASKPACKET ptp);
55 void Task_Group_Search (LPTASKPACKET ptp);
56 void Task_Group_Members_Get (LPTASKPACKET ptp);
57 void Task_Group_Members_Set (LPTASKPACKET ptp);
58 BOOL Task_Group_Members_Set_Do (LPGROUP_MEMBERS_SET_PARAMS lpp, ULONG *pStatus);
59 void Task_Group_Enum (LPTASKPACKET ptp);
60 void Task_Group_Rename (LPTASKPACKET ptp);
61 void Task_Group_Owned_Get (LPTASKPACKET ptp);
62 void Task_Group_Owned_Set (LPTASKPACKET ptp);
63 BOOL Task_Group_Owned_Set_Do (LPGROUP_OWNED_SET_PARAMS lpp, ULONG *pStatus);
64 void Task_Group_Create (LPTASKPACKET ptp);
65 void Task_Group_Delete (LPTASKPACKET ptp);
66 void Task_Cell_Change (LPTASKPACKET ptp);
67 void Task_List_Translate (LPTASKPACKET ptp);
68 void Task_Object_Listen (LPTASKPACKET ptp);
69 void Task_Object_Get (LPTASKPACKET ptp);
70 void Task_Set_Refresh (LPTASKPACKET ptp);
71 void Task_Expired_Creds (LPTASKPACKET ptp);
73 void WeedAsidList (LPASIDLIST *ppList, BOOL fWantMachines);
74 void TranslateRegExp (LPTSTR pszTarget, LPCTSTR pszSource);
75 BOOL PerformRefresh (LPTASKPACKET ptp, ASID idScope, ULONG *pStatus);
79 * ROUTINES ___________________________________________________________________
83 LPTASKPACKET CreateTaskPacket (int idTask, HWND hReply, PVOID lpUser)
87 if ((ptp = New (TASKPACKET)) != NULL)
89 memset (ptp, 0x00, sizeof(TASKPACKET));
97 if ((ptp->pReturn = New (TASKPACKETDATA)) != NULL)
99 memset (ptp->pReturn, 0x00, sizeof(TASKPACKETDATA));
107 void FreeTaskPacket (LPTASKPACKET ptp)
113 if (TASKDATA(ptp)->pAsidList)
114 asc_AsidListFree (&TASKDATA(ptp)->pAsidList);
115 if (TASKDATA(ptp)->pActionList)
116 asc_ActionListFree (&TASKDATA(ptp)->pActionList);
117 Delete (ptp->pReturn);
124 void PerformTask (LPTASKPACKET ptp)
141 Task_UpdGroups (ptp);
144 case taskUPD_MACHINES:
145 Task_UpdMachines (ptp);
152 case taskREFRESHMULT:
153 Task_RefreshMult (ptp);
156 case taskGET_ACTIONS:
157 Task_Get_Actions (ptp);
160 case taskGET_RANDOM_KEY:
161 Task_Get_Random_Key (ptp);
164 case taskUSER_CHANGE:
165 Task_User_Change (ptp);
169 Task_User_Find (ptp);
173 Task_User_Enum (ptp);
176 case taskUSER_GROUPLIST_SET:
177 Task_User_GroupList_Set (ptp);
184 case taskUSER_UNLOCK:
185 Task_User_Unlock (ptp);
188 case taskUSER_CREATE:
189 Task_User_Create (ptp);
192 case taskUSER_DELETE:
193 Task_User_Delete (ptp);
196 case taskGROUP_CHANGE:
197 Task_Group_Change (ptp);
200 case taskGROUP_SEARCH:
201 Task_Group_Search (ptp);
204 case taskGROUP_MEMBERS_GET:
205 Task_Group_Members_Get (ptp);
208 case taskGROUP_MEMBERS_SET:
209 Task_Group_Members_Set (ptp);
213 Task_Group_Enum (ptp);
216 case taskGROUP_RENAME:
217 Task_Group_Rename (ptp);
220 case taskGROUP_OWNED_GET:
221 Task_Group_Owned_Get (ptp);
224 case taskGROUP_OWNED_SET:
225 Task_Group_Owned_Set (ptp);
228 case taskGROUP_CREATE:
229 Task_Group_Create (ptp);
232 case taskGROUP_DELETE:
233 Task_Group_Delete (ptp);
236 case taskCELL_CHANGE:
237 Task_Cell_Change (ptp);
240 case taskLIST_TRANSLATE:
241 Task_List_Translate (ptp);
244 case taskOBJECT_LISTEN:
245 Task_Object_Listen (ptp);
249 Task_Object_Get (ptp);
252 case taskSET_REFRESH:
253 Task_Set_Refresh (ptp);
256 case taskEXPIRED_CREDS:
257 Task_Expired_Creds (ptp);
262 ptp->status = ERROR_INVALID_FUNCTION;
269 * KEYS _______________________________________________________________________
273 HASHVALUE CALLBACK Key_Asid_HashData (LPHASHLISTKEY pKey, PVOID pData)
275 return *(ASID*)pData;
278 HASHVALUE CALLBACK Key_Asid_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
280 return Key_Asid_HashData (pKey, (ASID*)pObject);
283 BOOL CALLBACK Key_Asid_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
285 return ((*(ASID*)pObject) == (*(ASID*)pData));
290 * TASKS ______________________________________________________________________
294 void Task_OpenCell (LPTASKPACKET ptp)
296 LPOPENCELL_PARAMS lpp = (LPOPENCELL_PARAMS)( ptp->lpUser );
298 Display_StartWorking();
300 // Try to open the cell for administration
302 ptp->rc = asc_CellOpen (g.idClient, lpp->hCreds, lpp->szCell, AFSADMSVR_SCOPE_USERS, &TASKDATA(ptp)->idCell, &ptp->status);
306 PostMessage (g.hMain, WM_SHOW_YOURSELF, 0, 1);
308 else if ((!ptp->rc) && (!IsWindow(ptp->hReply)))
310 if (lpp->fCloseAppOnFail)
311 FatalErrorDialog (ptp->status, IDS_ERROR_CANT_OPEN_CELL, TEXT("%s"), lpp->szCell);
313 ErrorDialog (ptp->status, IDS_ERROR_CANT_OPEN_CELL, TEXT("%s"), lpp->szCell);
316 // If we previously had another cell open, close it.
325 (void)asc_CellClose (g.idClient, g.idCell, &status);
327 g.idCell = TASKDATA(ptp)->idCell;
332 // Update the "Selected Cell:" text on the main window
334 TCHAR szCell[ cchNAME ];
336 GetString (szCell, IDS_CELL_NONE);
337 else if (!asc_CellNameGet_Fast (g.idClient, g.idCell, szCell))
338 GetString (szCell, IDS_CELL_NONE);
339 SetDlgItemText (g.hMain, IDC_CELL, szCell);
340 ShowCurrentCredentials();
342 // Oh--also, set the refresh rate for the newly-opened cell
345 asc_CellRefreshRateSet (g.idClient, g.idCell, gr.cminRefreshRate, &dummy);
347 // Start re-populating the Users or Groups tab (whichever is showing)
349 Display_PopulateList();
351 Display_StopWorking();
353 // When we've opened a new cell, it's time to open the Actions window.
356 PostMessage (g.hMain, WM_SHOW_ACTIONS, 0, 0);
359 ptp->lpUser = 0; // we freed this; don't let the caller use it again
363 void Task_UpdCreds (LPTASKPACKET ptp)
365 // Update the display to report our new credentials
367 ShowCurrentCredentials();
369 // Tell the admin server to use our new credentials, and refresh everything
371 if (!asc_CredentialsPush (g.idClient, g.hCreds, g.idCell, &ptp->status))
374 ptp->rc = PerformRefresh (ptp, g.idCell, &ptp->status);
378 void Task_UpdUsers (LPTASKPACKET ptp)
380 // First we'll query the admin server to find a list of all users which
381 // match our search pattern.
383 lstrcpy (TASKDATA(ptp)->szPattern, g.szPatternUsers);
385 TCHAR szRegExp[ cchNAME ];
386 TranslateRegExp (szRegExp, TASKDATA(ptp)->szPattern);
387 if (!asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_USER, szRegExp, &gr.SearchUsers, &TASKDATA(ptp)->pAsidList, &ptp->status))
390 // If we got a result back, weed out any entries that look like machines.
394 WeedAsidList (&TASKDATA(ptp)->pAsidList, FALSE);
397 // Wow, that was easy. Okay, next step: ensure that we have properties
398 // for all these guys in the local cache--to do that, we'll query their
399 // properties, then free the result.
403 LPASOBJPROPLIST pPropList = NULL;
404 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_ALL_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status))
407 asc_ObjPropListFree (&pPropList);
412 void Task_UpdGroups (LPTASKPACKET ptp)
414 // First we'll query the admin server to find a list of all groups which
415 // match our search pattern.
417 lstrcpy (TASKDATA(ptp)->szPattern, g.szPatternGroups);
419 TCHAR szRegExp[ cchNAME ];
420 TranslateRegExp (szRegExp, TASKDATA(ptp)->szPattern);
421 if (!asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_GROUP, szRegExp, NULL, &TASKDATA(ptp)->pAsidList, &ptp->status))
424 // Wow, that was easy. Okay, next step: ensure that we have properties
425 // for all these guys in the local cache--to do that, we'll query their
426 // properties, then free the result.
430 LPASOBJPROPLIST pPropList = NULL;
431 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_ALL_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status))
434 asc_ObjPropListFree (&pPropList);
439 void Task_UpdMachines (LPTASKPACKET ptp)
441 // First we'll query the admin server to find a list of all users which
442 // match our search pattern.
444 TCHAR szRegExp[ cchNAME ];
445 if (g.szPatternMachines[0])
446 TranslateRegExp (szRegExp, g.szPatternMachines);
448 lstrcpy (szRegExp, TEXT("^[0-9.]*$"));
450 if (!asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_USER, szRegExp, NULL, &TASKDATA(ptp)->pAsidList, &ptp->status))
453 lstrcpy (TASKDATA(ptp)->szPattern, g.szPatternMachines);
455 // If we got a result back, weed out any entries that don't look
460 WeedAsidList (&TASKDATA(ptp)->pAsidList, TRUE);
463 // Wow, that was easy. Okay, next step: ensure that we have properties
464 // for all these guys in the local cache--to do that, we'll query their
465 // properties, then free the result.
469 LPASOBJPROPLIST pPropList = NULL;
470 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_ALL_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status))
473 asc_ObjPropListFree (&pPropList);
479 void Task_Refresh (LPTASKPACKET ptp)
481 ASID idScope = (ASID)( ptp->lpUser );
483 ptp->rc = PerformRefresh (ptp, idScope, &ptp->status);
487 void Task_RefreshMult (LPTASKPACKET ptp)
489 LPASIDLIST pAsidList = (LPASIDLIST)( ptp->lpUser );
491 // Invalidate the admin server's cached information about the specified
492 // object. Remember that this is recursive hierarchically: if you pass
493 // in a cell's ID, for instance, information about all users, groups,
494 // servers, services, partitions and volumes anywhere in that cell will
497 ptp->rc = asc_ObjectRefreshMultiple (g.idClient, g.idCell, pAsidList, &ptp->status);
499 // The Refresh call above just made us invalidate the status for one or
500 // more objects; to get the display to reflect the changes, we'll have to
501 // query the server for the latest properties for those objects. Once that's
502 // done, we'll just redraw the main window and it will pick up the changes.
507 LPASOBJPROPLIST pPropList = NULL;
508 if (asc_ObjectPropertiesGetMultiple (g.idClient, GET_ALL_DATA, g.idCell, pAsidList, &pPropList, &status))
510 // That call returned properties for the objects; we don't need
511 // the properties here--we just wanted to get them in the cache.
512 // Now that they're in the cache, redrawing the main window will
513 // cause the latest data to be displayed.
516 asc_ObjPropListFree (&pPropList);
517 Display_RefreshView_Fast();
521 asc_AsidListFree (&pAsidList);
522 ptp->lpUser = 0; // we freed this; don't let the caller use it again
526 void Task_Get_Actions (LPTASKPACKET ptp)
528 // Query the admin server to get a current list of operations-in-progress.
529 // We'll limit our search to operations being performed on this cell.
531 ptp->rc = asc_ActionGetMultiple (g.idClient, 0, g.idCell, &TASKDATA(ptp)->pActionList, &ptp->status);
535 void Task_Get_Random_Key (LPTASKPACKET ptp)
537 ptp->rc = asc_RandomKeyGet (g.idClient, g.idCell, TASKDATA(ptp)->key, &ptp->status);
539 if (!ptp->rc && !IsWindow(ptp->hReply))
541 ErrorDialog (ptp->status, IDS_ERROR_CANT_GET_RANDOM_KEY);
546 void Task_User_Change (LPTASKPACKET ptp)
548 LPUSER_CHANGE_PARAMS lpp = (LPUSER_CHANGE_PARAMS)( ptp->lpUser );
550 if ((ptp->rc = asc_UserChange (g.idClient, g.idCell, lpp->idUser, &lpp->NewProperties, &ptp->status)) == TRUE)
552 Display_RefreshView_Fast();
555 if (!ptp->rc && !IsWindow (ptp->hReply))
557 TCHAR szUser[ cchNAME ];
558 User_GetDisplayName (szUser, lpp->idUser);
559 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_USER, TEXT("%s"), szUser);
563 ptp->lpUser = 0; // we freed this; don't let the caller use it again
567 void Task_User_Find (LPTASKPACKET ptp)
569 LPTSTR pszName = (LPTSTR)( ptp->lpUser );
571 if ((ptp->rc = asc_ObjectFind (g.idClient, g.idCell, TYPE_USER, pszName, &TASKDATA(ptp)->idObject, &ptp->status)) == TRUE)
573 ptp->rc = asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, TASKDATA(ptp)->idObject, &TASKDATA(ptp)->Properties, &ptp->status);
576 FreeString (pszName);
577 ptp->lpUser = 0; // we freed this; don't let the caller use it again
581 void Task_User_Enum (LPTASKPACKET ptp)
583 LPCTSTR pszPattern = (LPCTSTR)( ptp->lpUser );
585 TCHAR szRegExp[ cchNAME ];
586 TranslateRegExp (szRegExp, pszPattern);
587 if ((ptp->rc = asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_USER, szRegExp, NULL, &TASKDATA(ptp)->pAsidList, &ptp->status)) == TRUE)
589 LPASOBJPROPLIST pPropList = NULL;
591 ptp->rc = asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status);
594 asc_ObjPropListFree (&pPropList);
597 FreeString (pszPattern);
598 ptp->lpUser = 0; // we freed this; don't let the caller use it again
602 void Task_User_GroupList_Set (LPTASKPACKET ptp)
604 LPUSER_GROUPLIST_SET_PARAMS lpp = (LPUSER_GROUPLIST_SET_PARAMS)( ptp->lpUser );
606 ptp->rc = Task_User_GroupList_Set_Do (lpp, &ptp->status);
608 asc_AsidListFree (&lpp->pUsers);
609 asc_AsidListFree (&lpp->pGroups);
611 ptp->lpUser = 0; // we freed this; don't let the caller use it again
615 BOOL Task_User_GroupList_Set_Do (LPUSER_GROUPLIST_SET_PARAMS lpp, ULONG *pStatus)
619 // Maintain a structure describing any errors we encounter, so we can give
620 // a reasonable error dialog if need be.
622 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_SET_GROUPS, IDS_ERROR_CANT_SET_GROUPS_MULTIPLE);
624 // We'll need the supplied group-list in a hashlist, so we can quickly
625 // test it for inclusion of a particular group.
627 LPHASHLIST pGroupsAllow = New (HASHLIST);
628 for (size_t iGroup = 0; iGroup < lpp->pGroups->cEntries; ++iGroup)
629 pGroupsAllow->AddUnique ((PVOID)(lpp->pGroups->aEntries[ iGroup ].idObject));
631 // We'll have to do this next bit for each user in the supplied user-list
633 for (size_t iUser = 0; iUser < lpp->pUsers->cEntries; ++iUser)
637 // Obtain the appropriate current list of groups for this user
639 LPASIDLIST pGroupsOld = NULL;
640 if (lpp->fMembership)
642 if (!asc_GroupMembershipGet (g.idClient, g.idCell, lpp->pUsers->aEntries[ iUser ].idObject, &pGroupsOld, &status))
644 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
648 else // (!lpp->fMembership)
650 if (!asc_GroupOwnershipGet (g.idClient, g.idCell, lpp->pUsers->aEntries[ iUser ].idObject, &pGroupsOld, &status))
652 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
659 // Test each group in that current list to see if it's also on our
660 // pGroupsAllow list. If not, remove it.
662 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
664 if (pGroupsAllow->fIsInList ((PVOID)(pGroupsOld->aEntries[iGroup].idObject)))
667 if (lpp->fMembership)
669 if (!asc_GroupMemberRemove (g.idClient, g.idCell, pGroupsOld->aEntries[iGroup].idObject, lpp->pUsers->aEntries[iUser].idObject, &status))
670 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
672 else // (!lpp->fMembership)
674 ASOBJPROP Properties;
675 if (asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &Properties, &status))
677 AFSADMSVR_CHANGEGROUP_PARAMS pp;
678 memset (&pp, 0x00, sizeof(pp));
679 lstrcpy (pp.szOwner, Properties.szName); // make group self-owned
680 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
681 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
682 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
683 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
684 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
685 if (!asc_GroupChange (g.idClient, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &pp, &status))
686 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
691 // Now the more complex part: see if there are any groups in the
692 // supplied group-list which are marked as mandatory, but which
693 // aren't in our pGroupsOld list. We'll need to put the latter in a
694 // hashlist for this...
696 LPHASHLIST pGroupsOldList = New (HASHLIST);
697 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
698 pGroupsOldList->AddUnique ((PVOID)(pGroupsOld->aEntries[ iGroup ].idObject));
700 for (iGroup = 0; iGroup < lpp->pGroups->cEntries; ++iGroup)
702 if (!lpp->pGroups->aEntries[ iGroup ].lParam)
703 continue; // group not mandatory
704 if (pGroupsOldList->fIsInList ((PVOID)(lpp->pGroups->aEntries[ iGroup ].idObject)))
705 continue; // already a member
707 if (lpp->fMembership)
709 if (!asc_GroupMemberAdd (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, lpp->pUsers->aEntries[iUser].idObject, &status))
710 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
712 else // (!lpp->fMembership)
714 ASOBJPROP Properties;
715 if (asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, &Properties, &status))
717 AFSADMSVR_CHANGEGROUP_PARAMS pp;
718 memset (&pp, 0x00, sizeof(pp));
719 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
720 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
721 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
722 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
723 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
725 if (asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->pUsers->aEntries[iUser].idObject, pp.szOwner, &status))
727 if (!asc_GroupChange (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, &pp, &status))
728 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
734 Delete (pGroupsOldList);
735 asc_AsidListFree (&pGroupsOld);
738 // If there were any errors, report them.
740 if ((*pStatus = ED_GetFinalStatus(ped)) != 0)
743 ED_ShowErrorDialog(ped);
749 Delete (pGroupsAllow);
754 void Task_User_CPW (LPTASKPACKET ptp)
756 LPUSER_CPW_PARAMS lpp = (LPUSER_CPW_PARAMS)( ptp->lpUser );
758 ptp->rc = asc_UserPasswordSet (g.idClient, g.idCell, lpp->idUser, lpp->keyVersion, lpp->keyString, lpp->keyData, &ptp->status);
760 if ((!ptp->rc) && (!IsWindow(ptp->hReply)))
762 TCHAR szName[ cchNAME ];
763 User_GetDisplayName (szName, lpp->idUser);
764 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_PASSWORD, TEXT("%s"), szName);
768 ptp->lpUser = 0; // we freed this; don't let the caller use it again
772 void Task_User_Unlock (LPTASKPACKET ptp)
774 LPASIDLIST pUserList = (LPASIDLIST)( ptp->lpUser );
776 // Maintain a structure describing any errors we encounter, so we can give
777 // a reasonable error dialog if need be.
779 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_UNLOCK, IDS_ERROR_CANT_UNLOCK_MULTIPLE);
781 // Try to unlock the users' accounts...
783 for (size_t iUser = 0; iUser < pUserList->cEntries; ++iUser)
785 if (!asc_UserUnlock (g.idClient, g.idCell, pUserList->aEntries[ iUser ].idObject, &ptp->status))
786 ED_RegisterStatus (ped, pUserList->aEntries[ iUser ].idObject, FALSE, ptp->status);
789 // If there were any errors, report them.
791 if (ED_GetFinalStatus(ped) && !IsWindow(ptp->hReply))
792 ED_ShowErrorDialog(ped);
795 asc_AsidListFree (&pUserList);
796 ptp->lpUser = 0; // we freed this; don't let the caller use it again
800 void Task_User_Create (LPTASKPACKET ptp)
802 LPUSER_CREATE_PARAMS lpp = (LPUSER_CREATE_PARAMS)(ptp->lpUser);
804 // We may actually have been asked to create more than one user here;
805 // the {lpp->mszNames} parameter is a multi-string. So everything we
806 // do, we'll do for each new user-name...
808 for (LPTSTR pszName = lpp->mszNames; pszName && *pszName; pszName += 1+lstrlen(pszName))
810 // First create this new user account
814 AFSADMSVR_CREATEUSER_PARAMS pp;
815 memset (&pp, 0x00, sizeof(AFSADMSVR_CREATEUSER_PARAMS));
816 User_SplitDisplayName (pszName, pp.szName, pp.szInstance);
817 lstrcpy (pp.szPassword, lpp->szPassword);
818 pp.idUser = lpp->idUser;
819 pp.fCreateKAS = lpp->fCreateKAS;
820 pp.fCreatePTS = lpp->fCreatePTS;
821 if ((ptp->rc = asc_UserCreate (g.idClient, g.idCell, &pp, &idUser, &ptp->status)) == FALSE)
823 if (!IsWindow (ptp->hReply))
824 ErrorDialog (ptp->status, IDS_ERROR_CANT_CREATE_USER, TEXT("%s"), pszName);
828 // Then change its properties to be what we want
830 if ((ptp->rc = asc_UserChange (g.idClient, g.idCell, idUser, &lpp->Properties, &ptp->status)) == FALSE)
832 if (!IsWindow (ptp->hReply))
833 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_USER, TEXT("%s"), pszName);
838 // Finally update its lists of groups
840 if (lpp->pGroupsMember)
842 USER_GROUPLIST_SET_PARAMS pp;
843 memset (&pp, 0x00, sizeof(USER_GROUPLIST_SET_PARAMS));
844 asc_AsidListCreate (&pp.pUsers);
845 asc_AsidListAddEntry (&pp.pUsers, idUser, 0);
846 asc_AsidListCopy (&pp.pGroups, &lpp->pGroupsMember);
847 pp.fMembership = TRUE;
848 ptp->rc = Task_User_GroupList_Set_Do (&pp, &ptp->status);
849 asc_AsidListFree (&pp.pUsers);
850 asc_AsidListFree (&pp.pGroups);
852 if (lpp->pGroupsOwner)
854 USER_GROUPLIST_SET_PARAMS pp;
855 memset (&pp, 0x00, sizeof(USER_GROUPLIST_SET_PARAMS));
856 asc_AsidListCreate (&pp.pUsers);
857 asc_AsidListAddEntry (&pp.pUsers, idUser, 0);
858 asc_AsidListCopy (&pp.pGroups, &lpp->pGroupsOwner);
859 pp.fMembership = FALSE;
860 ptp->rc = Task_User_GroupList_Set_Do (&pp, &ptp->status);
861 asc_AsidListFree (&pp.pUsers);
862 asc_AsidListFree (&pp.pGroups);
868 Display_PopulateList();
870 if (lpp->pGroupsOwner)
871 asc_AsidListFree (&lpp->pGroupsOwner);
872 if (lpp->pGroupsMember)
873 asc_AsidListFree (&lpp->pGroupsMember);
875 FreeString (lpp->mszNames);
877 ptp->lpUser = 0; // we freed this; don't let the caller use it again
881 void Task_User_Delete (LPTASKPACKET ptp)
883 LPUSER_DELETE_PARAMS lpp = (LPUSER_DELETE_PARAMS)(ptp->lpUser);
885 // Maintain a structure describing any errors we encounter, so we can give
886 // a reasonable error dialog if need be.
888 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_DELETE_USER, IDS_ERROR_CANT_DELETE_USER_MULTIPLE);
890 // Go through and delete these users
892 for (size_t iUser = 0; iUser < lpp->pUserList->cEntries; ++iUser)
894 AFSADMSVR_DELETEUSER_PARAMS pp;
895 memset (&pp, 0x00, sizeof(pp));
896 pp.fDeleteKAS = lpp->fDeleteKAS;
897 pp.fDeletePTS = lpp->fDeletePTS;
900 if (!asc_UserDelete (g.idClient, g.idCell, lpp->pUserList->aEntries[iUser].idObject, &pp, &status))
901 ED_RegisterStatus (ped, lpp->pUserList->aEntries[iUser].idObject, FALSE, status);
904 // If there were any errors, report them.
906 if (ED_GetFinalStatus(ped) && !IsWindow(ptp->hReply))
907 ED_ShowErrorDialog(ped);
912 Display_PopulateList();
915 asc_AsidListFree (&lpp->pUserList);
917 ptp->lpUser = 0; // we freed this; don't let the caller use it again
921 void Task_Group_Change (LPTASKPACKET ptp)
923 LPGROUP_CHANGE_PARAMS lpp = (LPGROUP_CHANGE_PARAMS)( ptp->lpUser );
925 if ((ptp->rc = asc_GroupChange (g.idClient, g.idCell, lpp->idGroup, &lpp->NewProperties, &ptp->status)) == TRUE)
927 Display_RefreshView_Fast();
930 if (!ptp->rc && !IsWindow (ptp->hReply))
932 TCHAR szGroup[ cchNAME ];
933 asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->idGroup, szGroup);
934 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_GROUP, TEXT("%s"), szGroup);
938 ptp->lpUser = 0; // we freed this; don't let the caller use it again
942 void Task_Group_Search (LPTASKPACKET ptp)
944 LPGROUP_SEARCH_PARAMS lpp = (LPGROUP_SEARCH_PARAMS)( ptp->lpUser );
946 // Prepare an intermediate place for us to put the results of our search.
947 // We'll be doing lots of work in this intermediate list, so it'll be
948 // implemented as a hashlist with a key over the objects' ASIDs.
954 } GROUP_SEARCH_FOUND, *LPGROUP_SEARCH_FOUND;
956 LPHASHLIST pListGroups = New (HASHLIST);
957 LPHASHLISTKEY pListKeyAsid = pListGroups->CreateKey ("ASID", Key_Asid_Compare, Key_Asid_HashObject, Key_Asid_HashData);
959 // Search through the appropriate groups for each user in the list
961 for (size_t iUser = 0; iUser < lpp->pUserList->cEntries; ++iUser)
963 LPASIDLIST pGroups = NULL;
966 if (lpp->fMembership)
968 if (!asc_GroupMembershipGet (g.idClient, g.idCell, lpp->pUserList->aEntries[ iUser ].idObject, &pGroups, &status))
971 else // (!lpp->fMembership)
973 if (!asc_GroupOwnershipGet (g.idClient, g.idCell, lpp->pUserList->aEntries[ iUser ].idObject, &pGroups, &status))
979 // For each group we found, make sure the group is in the big
980 // list we'll be returning. Use the {lParam} field of the
981 // list's entry as a counter, to remember how many users have
984 for (size_t iGroup = 0; iGroup < pGroups->cEntries; ++iGroup)
986 // Is it in the list already? If not, add it.
988 LPGROUP_SEARCH_FOUND pFind;
989 if ((pFind = (LPGROUP_SEARCH_FOUND)pListKeyAsid->GetFirstObject (&pGroups->aEntries[ iGroup ].idObject)) != NULL)
995 pFind = New (GROUP_SEARCH_FOUND);
996 pFind->idGroup = pGroups->aEntries[ iGroup ].idObject;
998 pListGroups->Add (pFind);
1002 asc_AsidListFree (&pGroups);
1006 // Now that we have a list of groups that match our search criteria,
1007 // stick it in an ASID list. The lParam field for each ASID will be set
1008 // to 1 if all users have that group, or 0 if only some have it.
1010 if (!asc_AsidListCreate (&TASKDATA(ptp)->pAsidList))
1013 ptp->status = ERROR_NOT_ENOUGH_MEMORY;
1018 for (LPENUM pEnum = pListGroups->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1020 LPGROUP_SEARCH_FOUND pFind = (LPGROUP_SEARCH_FOUND)( pEnum->GetObject() );
1022 asc_AsidListAddEntry (&TASKDATA(ptp)->pAsidList, pFind->idGroup, (LPARAM)( (pFind->cUsers == lpp->pUserList->cEntries) ? 1 : 0 ));
1024 pListGroups->Remove (pFind);
1028 TASKDATA(ptp)->fMembership = lpp->fMembership;
1031 // Now that we have an ASID list full of groups to return, make sure we
1032 // have rudimentary properties for all those groups.
1037 asc_AsidListCopy (&pList, &TASKDATA(ptp)->pAsidList);
1039 LPASOBJPROPLIST pPropList = NULL;
1040 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, pList, &pPropList, &ptp->status))
1043 asc_ObjPropListFree (&pPropList);
1045 asc_AsidListFree (&pList);
1049 Delete (pListGroups);
1050 asc_AsidListFree (&lpp->pUserList);
1052 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1056 void Task_Group_Members_Get (LPTASKPACKET ptp)
1058 LPASIDLIST pGroups = (LPASIDLIST)( ptp->lpUser );
1060 // Prepare an intermediate place for us to put the results of our search.
1061 // We'll be doing lots of work in this intermediate list, so it'll be
1062 // implemented as a hashlist with a key over the objects' ASIDs.
1068 } GROUP_MEMBER_FOUND, *LPGROUP_MEMBER_FOUND;
1070 LPHASHLIST pListUsers = New (HASHLIST);
1071 LPHASHLISTKEY pListKeyAsid = pListUsers->CreateKey ("ASID", Key_Asid_Compare, Key_Asid_HashObject, Key_Asid_HashData);
1073 // For each group in the list, find all of that group's members
1075 for (size_t iGroup = 0; iGroup < pGroups->cEntries; ++iGroup)
1077 LPASIDLIST pMembers = NULL;
1080 if (!asc_GroupMembersGet (g.idClient, g.idCell, pGroups->aEntries[ iGroup ].idObject, &pMembers, &status))
1085 // For each member we found, make sure the member is in the big
1086 // list we'll be returning. Use the {lParam} field of the
1087 // list's entry as a counter, to remember how many groups have
1090 for (size_t iMember = 0; iMember < pMembers->cEntries; ++iMember)
1092 // Is it in the list already? If not, add it.
1094 LPGROUP_MEMBER_FOUND pFind;
1095 if ((pFind = (LPGROUP_MEMBER_FOUND)pListKeyAsid->GetFirstObject (&pMembers->aEntries[ iMember ].idObject)) != NULL)
1101 pFind = New (GROUP_MEMBER_FOUND);
1102 pFind->idUser = pMembers->aEntries[ iMember ].idObject;
1104 pListUsers->Add (pFind);
1108 asc_AsidListFree (&pMembers);
1112 // Now that we have a list of users that match our search criteria,
1113 // stick it in an ASID list. The lParam field for each ASID will be set
1114 // to 1 if all groups have that member, or 0 if only some have it.
1116 if (!asc_AsidListCreate (&TASKDATA(ptp)->pAsidList))
1119 ptp->status = ERROR_NOT_ENOUGH_MEMORY;
1124 for (LPENUM pEnum = pListUsers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1126 LPGROUP_MEMBER_FOUND pFind = (LPGROUP_MEMBER_FOUND)( pEnum->GetObject() );
1128 asc_AsidListAddEntry (&TASKDATA(ptp)->pAsidList, pFind->idUser, (LPARAM)( (pFind->cGroups == pGroups->cEntries) ? 1 : 0 ));
1130 pListUsers->Remove (pFind);
1135 // Now that we have an ASID list full of users to return, make sure we
1136 // have rudimentary properties for all those users.
1141 asc_AsidListCopy (&pList, &TASKDATA(ptp)->pAsidList);
1143 LPASOBJPROPLIST pPropList = NULL;
1144 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, pList, &pPropList, &ptp->status))
1147 asc_ObjPropListFree (&pPropList);
1149 asc_AsidListFree (&pList);
1153 Delete (pListUsers);
1154 asc_AsidListFree (&pGroups);
1155 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1159 void Task_Group_Members_Set (LPTASKPACKET ptp)
1161 LPGROUP_MEMBERS_SET_PARAMS lpp = (LPGROUP_MEMBERS_SET_PARAMS)( ptp->lpUser );
1163 ptp->rc = Task_Group_Members_Set_Do (lpp, &ptp->status);
1165 asc_AsidListFree (&lpp->pGroups);
1166 asc_AsidListFree (&lpp->pMembers);
1168 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1172 BOOL Task_Group_Members_Set_Do (LPGROUP_MEMBERS_SET_PARAMS lpp, ULONG *pStatus)
1176 // Maintain a structure describing any errors we encounter, so we can give
1177 // a reasonable error dialog if need be.
1179 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_SET_MEMBERS, IDS_ERROR_CANT_SET_MEMBERS_MULTIPLE);
1181 // We'll need the supplied member-list in a hashlist, so we can quickly
1182 // test it to see if a particular member should remain in a group.
1184 LPHASHLIST pMembersAllow = New (HASHLIST);
1185 for (size_t iMember = 0; iMember < lpp->pMembers->cEntries; ++iMember)
1186 pMembersAllow->AddUnique ((PVOID)(lpp->pMembers->aEntries[ iMember ].idObject));
1188 // We'll have to do this next bit for each group in the supplied group-list
1190 for (size_t iGroup = 0; iGroup < lpp->pGroups->cEntries; ++iGroup)
1194 // Obtain the current list of members for this group
1196 LPASIDLIST pMembersOld = NULL;
1197 if (!asc_GroupMembersGet (g.idClient, g.idCell, lpp->pGroups->aEntries[ iGroup ].idObject, &pMembersOld, &status))
1199 ED_RegisterStatus (ped, lpp->pGroups->aEntries[ iGroup ].idObject, FALSE, status);
1205 // Test each member in that current list to see if it's also on our
1206 // pMembersAllow list. If not, remove it.
1208 for (iMember = 0; iMember < pMembersOld->cEntries; ++iMember)
1210 if (pMembersAllow->fIsInList ((PVOID)(pMembersOld->aEntries[iMember].idObject)))
1213 if (!asc_GroupMemberRemove (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, pMembersOld->aEntries[iMember].idObject, &status))
1214 ED_RegisterStatus (ped, lpp->pGroups->aEntries[ iGroup ].idObject, FALSE, status);
1217 // Now the more complex part: see if there are any members in the
1218 // supplied member-list which are marked as mandatory, but which
1219 // aren't in our pMembersOld list. We'll need to put the latter in a
1220 // hashlist for this...
1222 LPHASHLIST pMembersOldList = New (HASHLIST);
1223 for (iMember = 0; iMember < pMembersOld->cEntries; ++iMember)
1224 pMembersOldList->AddUnique ((PVOID)(pMembersOld->aEntries[ iMember ].idObject));
1226 for (iMember = 0; iMember < lpp->pMembers->cEntries; ++iMember)
1228 if (!lpp->pMembers->aEntries[ iMember ].lParam)
1229 continue; // member not mandatory
1230 if (pMembersOldList->fIsInList ((PVOID)(lpp->pMembers->aEntries[ iMember ].idObject)))
1231 continue; // already a member
1233 if (!asc_GroupMemberAdd (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, lpp->pMembers->aEntries[iMember].idObject, &status))
1234 ED_RegisterStatus (ped, lpp->pGroups->aEntries[ iGroup ].idObject, FALSE, status);
1237 Delete (pMembersOldList);
1239 asc_AsidListFree (&pMembersOld);
1242 // If there were any errors, report them.
1244 if ((*pStatus = ED_GetFinalStatus(ped)) != 0)
1247 ED_ShowErrorDialog(ped);
1253 Delete (pMembersAllow);
1258 void Task_Group_Enum (LPTASKPACKET ptp)
1260 LPCTSTR pszPattern = (LPCTSTR)( ptp->lpUser );
1262 TCHAR szRegExp[ cchNAME ];
1263 TranslateRegExp (szRegExp, pszPattern);
1264 if ((ptp->rc = asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_GROUP, szRegExp, NULL, &TASKDATA(ptp)->pAsidList, &ptp->status)) == TRUE)
1266 LPASOBJPROPLIST pPropList = NULL;
1268 ptp->rc = asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status);
1271 asc_ObjPropListFree (&pPropList);
1274 FreeString (pszPattern);
1275 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1279 void Task_Group_Rename (LPTASKPACKET ptp)
1281 LPGROUP_RENAME_PARAMS lpp = (LPGROUP_RENAME_PARAMS)( ptp->lpUser );
1283 if ((ptp->rc = asc_GroupRename (g.idClient, g.idCell, lpp->idGroup, lpp->szNewName, &ptp->status)) != FALSE)
1285 Display_RefreshView_Fast();
1288 if (!ptp->rc && !IsWindow (ptp->hReply))
1290 TCHAR szOldName[ cchNAME ];
1291 asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->idGroup, szOldName);
1292 ErrorDialog (ptp->status, IDS_ERROR_CANT_RENAME_GROUP, TEXT("%s%s"), szOldName, lpp->szNewName);
1296 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1300 void Task_Group_Owned_Get (LPTASKPACKET ptp)
1302 ASID idGroup = (ASID)( ptp->lpUser );
1304 ptp->rc = asc_GroupOwnershipGet (g.idClient, g.idCell, idGroup, &TASKDATA(ptp)->pAsidList, &ptp->status);
1306 // Modify the ASID list to have lParams of 1. (This indicates that all
1307 // our supplied groups own this thing; silly but consistent with the
1308 // other such interfaces.)
1310 if (TASKDATA(ptp)->pAsidList)
1312 for (size_t ii = 0; ii < TASKDATA(ptp)->pAsidList->cEntries; ++ii)
1313 TASKDATA(ptp)->pAsidList->aEntries[ ii ].lParam = 1;
1316 // Now that we have an ASID list full of groups to return, make sure we
1317 // have rudimentary properties for all those groups.
1322 asc_AsidListCopy (&pList, &TASKDATA(ptp)->pAsidList);
1324 LPASOBJPROPLIST pPropList = NULL;
1325 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, pList, &pPropList, &ptp->status))
1328 asc_ObjPropListFree (&pPropList);
1330 asc_AsidListFree (&pList);
1335 void Task_Group_Owned_Set (LPTASKPACKET ptp)
1337 LPGROUP_OWNED_SET_PARAMS lpp = (LPGROUP_OWNED_SET_PARAMS)( ptp->lpUser );
1339 ptp->rc = Task_Group_Owned_Set_Do (lpp, &ptp->status);
1341 asc_AsidListFree (&lpp->pOwnedGroups);
1343 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1347 BOOL Task_Group_Owned_Set_Do (LPGROUP_OWNED_SET_PARAMS lpp, ULONG *pStatus)
1351 // Maintain a structure describing any errors we encounter, so we can give
1352 // a reasonable error dialog if need be.
1354 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_CHANGE_OWNER, IDS_ERROR_CANT_CHANGE_OWNER_MULTIPLE);
1356 // We'll need the supplied groups-to-own list in a hashlist, so we can
1357 // quickly test it for inclusion of a particular group.
1359 LPHASHLIST pGroupsAllow = New (HASHLIST);
1360 for (size_t iGroup = 0; iGroup < lpp->pOwnedGroups->cEntries; ++iGroup)
1361 pGroupsAllow->AddUnique ((PVOID)(lpp->pOwnedGroups->aEntries[ iGroup ].idObject));
1363 // Obtain the current list-of-groups-owned for this group
1365 LPASIDLIST pGroupsOld = NULL;
1366 if ((rc = asc_GroupOwnershipGet (g.idClient, g.idCell, lpp->idGroup, &pGroupsOld, pStatus)) == FALSE)
1371 for (size_t ii = 0; ii < lpp->pOwnedGroups->cEntries; ++ii)
1372 ED_RegisterStatus (ped, lpp->pOwnedGroups->aEntries[ii].idObject, FALSE, *pStatus);
1376 // Test each group in that current list to see if it's also on our
1377 // pGroupsAllow list. If not, remove it.
1379 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
1381 if (pGroupsAllow->fIsInList ((PVOID)(pGroupsOld->aEntries[iGroup].idObject)))
1385 ASOBJPROP Properties;
1386 if (!asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &Properties, &status))
1387 ED_RegisterStatus (ped, pGroupsOld->aEntries[iGroup].idObject, FALSE, status);
1390 AFSADMSVR_CHANGEGROUP_PARAMS pp;
1391 memset (&pp, 0x00, sizeof(pp));
1392 lstrcpy (pp.szOwner, Properties.szName); // make group self-owned
1393 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
1394 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
1395 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
1396 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
1397 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
1399 if (!asc_GroupChange (g.idClient, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &pp, &status))
1400 ED_RegisterStatus (ped, pGroupsOld->aEntries[iGroup].idObject, FALSE, status);
1404 // Now the more complex part: see if there are any groups in the
1405 // supplied group-list which are marked as mandatory, but which
1406 // aren't in our pGroupsOld list. We'll need to put the latter in a
1407 // hashlist for this...
1409 LPHASHLIST pGroupsOldList = New (HASHLIST);
1410 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
1411 pGroupsOldList->AddUnique ((PVOID)(pGroupsOld->aEntries[ iGroup ].idObject));
1413 for (iGroup = 0; iGroup < lpp->pOwnedGroups->cEntries; ++iGroup)
1415 if (!lpp->pOwnedGroups->aEntries[ iGroup ].lParam)
1416 continue; // group not mandatory
1417 if (pGroupsOldList->fIsInList ((PVOID)(lpp->pOwnedGroups->aEntries[ iGroup ].idObject)))
1418 continue; // already a member
1421 ASOBJPROP Properties;
1422 if (!asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, lpp->pOwnedGroups->aEntries[iGroup].idObject, &Properties, &status))
1423 ED_RegisterStatus (ped, lpp->pOwnedGroups->aEntries[iGroup].idObject, FALSE, status);
1426 AFSADMSVR_CHANGEGROUP_PARAMS pp;
1427 memset (&pp, 0x00, sizeof(pp));
1428 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
1429 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
1430 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
1431 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
1432 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
1434 if (asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->idGroup, pp.szOwner, &status))
1436 if (!asc_GroupChange (g.idClient, g.idCell, lpp->pOwnedGroups->aEntries[iGroup].idObject, &pp, &status))
1437 ED_RegisterStatus (ped, lpp->pOwnedGroups->aEntries[iGroup].idObject, FALSE, status);
1442 Delete (pGroupsOldList);
1443 asc_AsidListFree (&pGroupsOld);
1446 // If there were any errors, report them.
1448 if ((*pStatus = ED_GetFinalStatus(ped)) != 0)
1451 ED_ShowErrorDialog(ped);
1457 Delete (pGroupsAllow);
1462 void Task_Group_Create (LPTASKPACKET ptp)
1464 LPGROUP_CREATE_PARAMS lpp = (LPGROUP_CREATE_PARAMS)(ptp->lpUser);
1466 // If no owner was specified, use our current credentials' ID. If
1467 // we can't get that, we'll make each group self-owned.
1469 if (!lpp->szOwner[0])
1471 TCHAR szCell[ cchNAME ];
1472 if (!AfsAppLib_CrackCredentials (g.hCreds, szCell, lpp->szOwner))
1473 lpp->szOwner[0] = TEXT('\0');
1476 // We may actually have been asked to create more than one group here;
1477 // the {lpp->mszNames} parameter is a multi-string. So everything we
1478 // do, we'll do for each new group-name...
1480 for (LPTSTR pszName = lpp->mszNames; pszName && *pszName; pszName += 1+lstrlen(pszName))
1482 // First create this new group account
1486 AFSADMSVR_CREATEGROUP_PARAMS pp;
1487 memset (&pp, 0x00, sizeof(AFSADMSVR_CREATEGROUP_PARAMS));
1488 pp.idGroup = lpp->idGroup;
1489 lstrcpy (pp.szName, pszName);
1490 lstrcpy (pp.szOwner, lpp->szOwner);
1492 lstrcpy (pp.szOwner, pszName);
1494 if ((ptp->rc = asc_GroupCreate (g.idClient, g.idCell, &pp, &idGroup, &ptp->status)) == FALSE)
1496 if (!IsWindow (ptp->hReply))
1497 ErrorDialog (ptp->status, IDS_ERROR_CANT_CREATE_GROUP, TEXT("%s"), pszName);
1501 // Then change its properties to be what we want
1503 if ((ptp->rc = asc_GroupChange (g.idClient, g.idCell, idGroup, &lpp->Properties, &ptp->status)) == FALSE)
1505 if (!IsWindow (ptp->hReply))
1506 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_GROUP, TEXT("%s"), pszName);
1511 // Finally update its lists of groups
1515 GROUP_MEMBERS_SET_PARAMS pp;
1516 memset (&pp, 0x00, sizeof(GROUP_MEMBERS_SET_PARAMS));
1517 asc_AsidListCreate (&pp.pGroups);
1518 asc_AsidListAddEntry (&pp.pGroups, idGroup, 0);
1519 asc_AsidListCopy (&pp.pMembers, &lpp->pMembers);
1520 ptp->rc = Task_Group_Members_Set_Do (&pp, &ptp->status);
1521 asc_AsidListFree (&pp.pGroups);
1522 asc_AsidListFree (&pp.pMembers);
1524 if (lpp->pGroupsOwner)
1526 GROUP_OWNED_SET_PARAMS pp;
1527 memset (&pp, 0x00, sizeof(GROUP_OWNED_SET_PARAMS));
1528 pp.idGroup = idGroup;
1529 asc_AsidListCopy (&pp.pOwnedGroups, &lpp->pGroupsOwner);
1530 ptp->rc = Task_Group_Owned_Set_Do (&pp, &ptp->status);
1531 asc_AsidListFree (&pp.pOwnedGroups);
1537 Display_PopulateList();
1539 if (lpp->pGroupsOwner)
1540 asc_AsidListFree (&lpp->pGroupsOwner);
1542 asc_AsidListFree (&lpp->pMembers);
1544 FreeString (lpp->mszNames);
1546 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1550 void Task_Group_Delete (LPTASKPACKET ptp)
1552 LPASIDLIST pGroupList = (LPASIDLIST)(ptp->lpUser);
1554 // Maintain a structure describing any errors we encounter, so we can give
1555 // a reasonable error dialog if need be.
1557 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_DELETE_GROUP, IDS_ERROR_CANT_DELETE_GROUP_MULTIPLE);
1559 // Go through and delete these users
1561 for (size_t iGroup = 0; iGroup < pGroupList->cEntries; ++iGroup)
1564 if (!asc_GroupDelete (g.idClient, g.idCell, pGroupList->aEntries[iGroup].idObject, &status))
1565 ED_RegisterStatus (ped, pGroupList->aEntries[iGroup].idObject, FALSE, status);
1568 // If there were any errors, report them.
1570 if (ED_GetFinalStatus(ped) && !IsWindow(ptp->hReply))
1571 ED_ShowErrorDialog(ped);
1576 Display_PopulateList();
1579 asc_AsidListFree (&pGroupList);
1580 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1584 void Task_Cell_Change (LPTASKPACKET ptp)
1586 LPCELL_CHANGE_PARAMS lpp = (LPCELL_CHANGE_PARAMS)(ptp->lpUser);
1588 AFSADMSVR_CHANGECELL_PARAMS Change;
1589 memset (&Change, 0x00, sizeof(Change));
1590 Change.idUserMax = (DWORD)(lpp->idUserMax);
1591 Change.idGroupMax = (DWORD)(lpp->idGroupMax);
1592 ptp->rc = asc_CellChange (g.idClient, lpp->idCell, &Change, &ptp->status);
1594 if (!ptp->rc && !IsWindow (ptp->hReply))
1596 TCHAR szCell[ cchNAME ];
1597 asc_CellNameGet_Fast (g.idClient, lpp->idCell, szCell);
1598 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_CELL, TEXT("%s"), szCell);
1602 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1606 void Task_List_Translate (LPTASKPACKET ptp)
1608 LPLIST_TRANSLATE_PARAMS lpp = (LPLIST_TRANSLATE_PARAMS)( ptp->lpUser );
1609 TASKDATA(ptp)->Type = lpp->Type;
1611 // We'll need a hashlist into which to dump our results as we build
1612 // them (we use a hashlist so we can quickly detect and ignore duplicates).
1614 LPHASHLIST pList = New (HASHLIST);
1616 // Now split the input string up into a series of names. To do that,
1617 // we'll valid separator characters are; since names can't have whitespace,
1618 // we'll include that.
1620 TCHAR szSeparators[ cchRESOURCE ];
1621 if (!GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SLIST, szSeparators, cchRESOURCE))
1622 szSeparators[0] = TEXT(',');
1623 GetString (&szSeparators[1], IDS_SEPARATORS);
1627 LPCTSTR pszStart = lpp->pszNames;
1628 while (iswhite(*pszStart) || lstrchr (szSeparators, *pszStart))
1633 // Find the first non-name character
1635 LPCTSTR pszEnd = pszStart;
1636 while (*pszEnd && !iswhite(*pszEnd) && !lstrchr(szSeparators, *pszEnd))
1639 // Copy off this particular name
1641 TCHAR szName[ cchNAME ];
1642 lstrcpy (szName, pszStart);
1643 szName[ pszEnd - pszStart ] = TEXT('\0');
1645 // Find the next valid-name character
1648 while (iswhite(*pszStart) || lstrchr(szSeparators, *pszStart))
1651 // Translate this particular name. We'll also handle wildcards
1652 // here: if we don't get any wildcard characters, treat it as
1653 // a direct lookup; if we do, treat it as a regexp match.
1655 if (lstrchr (szName, TEXT('*')) || lstrchr (szName, TEXT('?')) ||
1656 lstrchr (szName, TEXT('^')) || lstrchr (szName, TEXT('!')))
1658 TCHAR szRegExp[ cchNAME ];
1659 TranslateRegExp (szRegExp, szName);
1661 LPASIDLIST pAsidList;
1662 if (asc_ObjectFindMultiple (g.idClient, g.idCell, lpp->Type, szRegExp, NULL, &pAsidList, &ptp->status))
1666 for (size_t ii = 0; ii < pAsidList->cEntries; ++ii)
1667 pList->AddUnique ((PVOID)(pAsidList->aEntries[ii].idObject));
1668 asc_AsidListFree (&pAsidList);
1672 else // No wildcards; just look up the name directly
1675 if (asc_ObjectFind (g.idClient, g.idCell, lpp->Type, szName, &idObject, &ptp->status))
1676 pList->AddUnique ((PVOID)idObject);
1681 // Finally, build an ASIDLIST from our hashlist's contents.
1683 if (!asc_AsidListCreate (&TASKDATA(ptp)->pAsidList))
1686 ptp->status = ERROR_NOT_ENOUGH_MEMORY;
1690 for (LPENUM pEnum = pList->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1692 ASID idObject = (ASID)(pEnum->GetObject());
1693 asc_AsidListAddEntry (&TASKDATA(ptp)->pAsidList, idObject, 0);
1700 FreeString (lpp->pszNames);
1702 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1706 void Task_Object_Listen (LPTASKPACKET ptp)
1708 LPOBJECT_LISTEN_PARAMS lpp = (LPOBJECT_LISTEN_PARAMS)( ptp->lpUser );
1710 if (IsWindow(lpp->hNotify) && (lpp->pAsidList))
1711 ptp->rc = asc_ObjectListenMultiple (g.idClient, g.idCell, lpp->pAsidList, lpp->hNotify, &ptp->status);
1713 ptp->rc = asc_ObjectListenClear (g.idClient, lpp->hNotify, &ptp->status);
1716 asc_AsidListFree (&lpp->pAsidList);
1718 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1722 void Task_Object_Get (LPTASKPACKET ptp)
1724 ASID idObject = (ASID)(ptp->lpUser);
1725 ptp->rc = asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, idObject, &TASKDATA(ptp)->Properties, &ptp->status);
1729 void Task_Set_Refresh (LPTASKPACKET ptp)
1733 ptp->rc = asc_CellRefreshRateSet (g.idClient, g.idCell, gr.cminRefreshRate, &ptp->status);
1738 void Task_Expired_Creds (LPTASKPACKET ptp)
1742 CheckForExpiredCredentials();
1747 void WeedAsidList (LPASIDLIST *ppList, BOOL fWantMachines)
1751 // First off, we can't do anything unless we have these guys' names.
1753 if (ppList && (*ppList) && (*ppList)->cEntries)
1755 LPASOBJPROPLIST pPropList = NULL;
1756 asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, *ppList, &pPropList, &status);
1758 asc_ObjPropListFree (&pPropList);
1761 for (size_t ii = 0; ppList && (*ppList) && (ii < (*ppList)->cEntries); )
1763 TCHAR szName[ cchRESOURCE ];
1764 if (!asc_ObjectNameGet_Fast (g.idClient, g.idCell, (*ppList)->aEntries[ ii ].idObject, szName, &status))
1770 if (fIsMachineAccount(szName) == fWantMachines)
1773 asc_AsidListRemoveEntryByIndex (ppList, ii);
1778 void TranslateRegExp (LPTSTR pszTarget, LPCTSTR pszSource)
1782 if (!gr.fWindowsRegexp)
1784 lstrcpy (pszTarget, pszSource);
1788 for ( ; *pszSource; pszSource++)
1795 *pszTarget++ = TEXT('\\');
1796 *pszTarget++ = *pszSource;
1800 *pszTarget++ = TEXT('.');
1804 *pszTarget++ = TEXT('.');
1805 *pszTarget++ = TEXT('*');
1809 *pszTarget++ = *pszSource;
1816 *pszTarget++ = TEXT('\0');
1820 BOOL PerformRefresh (LPTASKPACKET ptp, ASID idScope, ULONG *pStatus)
1822 // Invalidate the admin server's cached information about the specified
1823 // object. Remember that this is recursive hierarchically: if you pass
1824 // in a cell's ID, for instance, information about all users, groups,
1825 // servers, services, partitions and volumes anywhere in that cell will
1831 if (!asc_ObjectRefresh (g.idClient, g.idCell, idScope, pStatus))
1834 // The Refresh call above is a misnomer; it's really an Invalidate request,
1835 // in that it only causes the admin server to dump its cached information
1836 // over the specified scope. At this point we need to do something to
1837 // trigger the server to re-query that information, so that it will send
1838 // an ACTION_REFRESH notification (indicating it's doing that requery),
1839 // which we'll pick up on and use as a trigger to refresh our display.
1840 // A convenient way to get the server to do that re-query is to ask it
1841 // to perform some simple search among the users in the cell--we'll ask
1842 // it to find, oh, say, "JoeBobUser", and in order to do that, it will
1843 // have to re-fill its cache.
1845 LPASIDLIST pListDummy;
1847 (void)asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_USER, TEXT("JoeBobUser"), NULL, &pListDummy, &statusDummy);
1848 if (pListDummy != NULL)
1849 asc_AsidListFree (&pListDummy);