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, (PVOID)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, (PVOID)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);
629 for (iGroup = 0; iGroup < lpp->pGroups->cEntries; ++iGroup)
630 pGroupsAllow->AddUnique ((PVOID)(lpp->pGroups->aEntries[ iGroup ].idObject));
632 // We'll have to do this next bit for each user in the supplied user-list
634 for (size_t iUser = 0; iUser < lpp->pUsers->cEntries; ++iUser)
638 // Obtain the appropriate current list of groups for this user
640 LPASIDLIST pGroupsOld = NULL;
641 if (lpp->fMembership)
643 if (!asc_GroupMembershipGet (g.idClient, g.idCell, lpp->pUsers->aEntries[ iUser ].idObject, &pGroupsOld, &status))
645 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
649 else // (!lpp->fMembership)
651 if (!asc_GroupOwnershipGet (g.idClient, g.idCell, lpp->pUsers->aEntries[ iUser ].idObject, &pGroupsOld, &status))
653 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
660 // Test each group in that current list to see if it's also on our
661 // pGroupsAllow list. If not, remove it.
663 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
665 if (pGroupsAllow->fIsInList ((PVOID)(pGroupsOld->aEntries[iGroup].idObject)))
668 if (lpp->fMembership)
670 if (!asc_GroupMemberRemove (g.idClient, g.idCell, pGroupsOld->aEntries[iGroup].idObject, lpp->pUsers->aEntries[iUser].idObject, &status))
671 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
673 else // (!lpp->fMembership)
675 ASOBJPROP Properties;
676 if (asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &Properties, &status))
678 AFSADMSVR_CHANGEGROUP_PARAMS pp;
679 memset (&pp, 0x00, sizeof(pp));
680 lstrcpy (pp.szOwner, Properties.szName); // make group self-owned
681 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
682 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
683 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
684 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
685 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
686 if (!asc_GroupChange (g.idClient, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &pp, &status))
687 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
692 // Now the more complex part: see if there are any groups in the
693 // supplied group-list which are marked as mandatory, but which
694 // aren't in our pGroupsOld list. We'll need to put the latter in a
695 // hashlist for this...
697 LPHASHLIST pGroupsOldList = New (HASHLIST);
698 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
699 pGroupsOldList->AddUnique ((PVOID)(pGroupsOld->aEntries[ iGroup ].idObject));
701 for (iGroup = 0; iGroup < lpp->pGroups->cEntries; ++iGroup)
703 if (!lpp->pGroups->aEntries[ iGroup ].lParam)
704 continue; // group not mandatory
705 if (pGroupsOldList->fIsInList ((PVOID)(lpp->pGroups->aEntries[ iGroup ].idObject)))
706 continue; // already a member
708 if (lpp->fMembership)
710 if (!asc_GroupMemberAdd (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, lpp->pUsers->aEntries[iUser].idObject, &status))
711 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
713 else // (!lpp->fMembership)
715 ASOBJPROP Properties;
716 if (asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, &Properties, &status))
718 AFSADMSVR_CHANGEGROUP_PARAMS pp;
719 memset (&pp, 0x00, sizeof(pp));
720 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
721 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
722 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
723 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
724 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
726 if (asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->pUsers->aEntries[iUser].idObject, pp.szOwner, &status))
728 if (!asc_GroupChange (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, &pp, &status))
729 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
735 Delete (pGroupsOldList);
736 asc_AsidListFree (&pGroupsOld);
739 // If there were any errors, report them.
741 if ((*pStatus = ED_GetFinalStatus(ped)) != 0)
744 ED_ShowErrorDialog(ped);
750 Delete (pGroupsAllow);
755 void Task_User_CPW (LPTASKPACKET ptp)
757 LPUSER_CPW_PARAMS lpp = (LPUSER_CPW_PARAMS)( ptp->lpUser );
759 ptp->rc = asc_UserPasswordSet (g.idClient, g.idCell, lpp->idUser, lpp->keyVersion, lpp->keyString, lpp->keyData, &ptp->status);
761 if ((!ptp->rc) && (!IsWindow(ptp->hReply)))
763 TCHAR szName[ cchNAME ];
764 User_GetDisplayName (szName, lpp->idUser);
765 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_PASSWORD, TEXT("%s"), szName);
769 ptp->lpUser = 0; // we freed this; don't let the caller use it again
773 void Task_User_Unlock (LPTASKPACKET ptp)
775 LPASIDLIST pUserList = (LPASIDLIST)( ptp->lpUser );
777 // Maintain a structure describing any errors we encounter, so we can give
778 // a reasonable error dialog if need be.
780 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_UNLOCK, IDS_ERROR_CANT_UNLOCK_MULTIPLE);
782 // Try to unlock the users' accounts...
784 for (size_t iUser = 0; iUser < pUserList->cEntries; ++iUser)
786 if (!asc_UserUnlock (g.idClient, g.idCell, pUserList->aEntries[ iUser ].idObject, &ptp->status))
787 ED_RegisterStatus (ped, pUserList->aEntries[ iUser ].idObject, FALSE, ptp->status);
790 // If there were any errors, report them.
792 if (ED_GetFinalStatus(ped) && !IsWindow(ptp->hReply))
793 ED_ShowErrorDialog(ped);
796 asc_AsidListFree (&pUserList);
797 ptp->lpUser = 0; // we freed this; don't let the caller use it again
801 void Task_User_Create (LPTASKPACKET ptp)
803 LPUSER_CREATE_PARAMS lpp = (LPUSER_CREATE_PARAMS)(ptp->lpUser);
805 // We may actually have been asked to create more than one user here;
806 // the {lpp->mszNames} parameter is a multi-string. So everything we
807 // do, we'll do for each new user-name...
809 for (LPTSTR pszName = lpp->mszNames; pszName && *pszName; pszName += 1+lstrlen(pszName))
811 // First create this new user account
815 AFSADMSVR_CREATEUSER_PARAMS pp;
816 memset (&pp, 0x00, sizeof(AFSADMSVR_CREATEUSER_PARAMS));
817 User_SplitDisplayName (pszName, pp.szName, pp.szInstance);
818 lstrcpy (pp.szPassword, lpp->szPassword);
819 pp.idUser = lpp->idUser;
820 pp.fCreateKAS = lpp->fCreateKAS;
821 pp.fCreatePTS = lpp->fCreatePTS;
822 if ((ptp->rc = asc_UserCreate (g.idClient, g.idCell, &pp, &idUser, &ptp->status)) == FALSE)
824 if (!IsWindow (ptp->hReply))
825 ErrorDialog (ptp->status, IDS_ERROR_CANT_CREATE_USER, TEXT("%s"), pszName);
829 // Then change its properties to be what we want
831 if ((ptp->rc = asc_UserChange (g.idClient, g.idCell, idUser, &lpp->Properties, &ptp->status)) == FALSE)
833 if (!IsWindow (ptp->hReply))
834 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_USER, TEXT("%s"), pszName);
839 // Finally update its lists of groups
841 if (lpp->pGroupsMember)
843 USER_GROUPLIST_SET_PARAMS pp;
844 memset (&pp, 0x00, sizeof(USER_GROUPLIST_SET_PARAMS));
845 asc_AsidListCreate (&pp.pUsers);
846 asc_AsidListAddEntry (&pp.pUsers, idUser, 0);
847 asc_AsidListCopy (&pp.pGroups, &lpp->pGroupsMember);
848 pp.fMembership = TRUE;
849 ptp->rc = Task_User_GroupList_Set_Do (&pp, &ptp->status);
850 asc_AsidListFree (&pp.pUsers);
851 asc_AsidListFree (&pp.pGroups);
853 if (lpp->pGroupsOwner)
855 USER_GROUPLIST_SET_PARAMS pp;
856 memset (&pp, 0x00, sizeof(USER_GROUPLIST_SET_PARAMS));
857 asc_AsidListCreate (&pp.pUsers);
858 asc_AsidListAddEntry (&pp.pUsers, idUser, 0);
859 asc_AsidListCopy (&pp.pGroups, &lpp->pGroupsOwner);
860 pp.fMembership = FALSE;
861 ptp->rc = Task_User_GroupList_Set_Do (&pp, &ptp->status);
862 asc_AsidListFree (&pp.pUsers);
863 asc_AsidListFree (&pp.pGroups);
869 Display_PopulateList();
871 if (lpp->pGroupsOwner)
872 asc_AsidListFree (&lpp->pGroupsOwner);
873 if (lpp->pGroupsMember)
874 asc_AsidListFree (&lpp->pGroupsMember);
876 FreeString (lpp->mszNames);
878 ptp->lpUser = 0; // we freed this; don't let the caller use it again
882 void Task_User_Delete (LPTASKPACKET ptp)
884 LPUSER_DELETE_PARAMS lpp = (LPUSER_DELETE_PARAMS)(ptp->lpUser);
886 // Maintain a structure describing any errors we encounter, so we can give
887 // a reasonable error dialog if need be.
889 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_DELETE_USER, IDS_ERROR_CANT_DELETE_USER_MULTIPLE);
891 // Go through and delete these users
893 for (size_t iUser = 0; iUser < lpp->pUserList->cEntries; ++iUser)
895 AFSADMSVR_DELETEUSER_PARAMS pp;
896 memset (&pp, 0x00, sizeof(pp));
897 pp.fDeleteKAS = lpp->fDeleteKAS;
898 pp.fDeletePTS = lpp->fDeletePTS;
901 if (!asc_UserDelete (g.idClient, g.idCell, lpp->pUserList->aEntries[iUser].idObject, &pp, &status))
902 ED_RegisterStatus (ped, lpp->pUserList->aEntries[iUser].idObject, FALSE, status);
905 // If there were any errors, report them.
907 if (ED_GetFinalStatus(ped) && !IsWindow(ptp->hReply))
908 ED_ShowErrorDialog(ped);
913 Display_PopulateList();
916 asc_AsidListFree (&lpp->pUserList);
918 ptp->lpUser = 0; // we freed this; don't let the caller use it again
922 void Task_Group_Change (LPTASKPACKET ptp)
924 LPGROUP_CHANGE_PARAMS lpp = (LPGROUP_CHANGE_PARAMS)( ptp->lpUser );
926 if ((ptp->rc = asc_GroupChange (g.idClient, g.idCell, lpp->idGroup, &lpp->NewProperties, &ptp->status)) == TRUE)
928 Display_RefreshView_Fast();
931 if (!ptp->rc && !IsWindow (ptp->hReply))
933 TCHAR szGroup[ cchNAME ];
934 asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->idGroup, szGroup);
935 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_GROUP, TEXT("%s"), szGroup);
939 ptp->lpUser = 0; // we freed this; don't let the caller use it again
943 void Task_Group_Search (LPTASKPACKET ptp)
945 LPGROUP_SEARCH_PARAMS lpp = (LPGROUP_SEARCH_PARAMS)( ptp->lpUser );
947 // Prepare an intermediate place for us to put the results of our search.
948 // We'll be doing lots of work in this intermediate list, so it'll be
949 // implemented as a hashlist with a key over the objects' ASIDs.
955 } GROUP_SEARCH_FOUND, *LPGROUP_SEARCH_FOUND;
957 LPHASHLIST pListGroups = New (HASHLIST);
958 LPHASHLISTKEY pListKeyAsid = pListGroups->CreateKey ("ASID", Key_Asid_Compare, Key_Asid_HashObject, Key_Asid_HashData);
960 // Search through the appropriate groups for each user in the list
962 for (size_t iUser = 0; iUser < lpp->pUserList->cEntries; ++iUser)
964 LPASIDLIST pGroups = NULL;
967 if (lpp->fMembership)
969 if (!asc_GroupMembershipGet (g.idClient, g.idCell, lpp->pUserList->aEntries[ iUser ].idObject, &pGroups, &status))
972 else // (!lpp->fMembership)
974 if (!asc_GroupOwnershipGet (g.idClient, g.idCell, lpp->pUserList->aEntries[ iUser ].idObject, &pGroups, &status))
980 // For each group we found, make sure the group is in the big
981 // list we'll be returning. Use the {lParam} field of the
982 // list's entry as a counter, to remember how many users have
985 for (size_t iGroup = 0; iGroup < pGroups->cEntries; ++iGroup)
987 // Is it in the list already? If not, add it.
989 LPGROUP_SEARCH_FOUND pFind;
990 if ((pFind = (LPGROUP_SEARCH_FOUND)pListKeyAsid->GetFirstObject (&pGroups->aEntries[ iGroup ].idObject)) != NULL)
996 pFind = New (GROUP_SEARCH_FOUND);
997 pFind->idGroup = pGroups->aEntries[ iGroup ].idObject;
999 pListGroups->Add (pFind);
1003 asc_AsidListFree (&pGroups);
1007 // Now that we have a list of groups that match our search criteria,
1008 // stick it in an ASID list. The lParam field for each ASID will be set
1009 // to 1 if all users have that group, or 0 if only some have it.
1011 if (!asc_AsidListCreate (&TASKDATA(ptp)->pAsidList))
1014 ptp->status = ERROR_NOT_ENOUGH_MEMORY;
1019 for (LPENUM pEnum = pListGroups->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1021 LPGROUP_SEARCH_FOUND pFind = (LPGROUP_SEARCH_FOUND)( pEnum->GetObject() );
1023 asc_AsidListAddEntry (&TASKDATA(ptp)->pAsidList, pFind->idGroup, (LPARAM)( (pFind->cUsers == lpp->pUserList->cEntries) ? 1 : 0 ));
1025 pListGroups->Remove (pFind);
1029 TASKDATA(ptp)->fMembership = lpp->fMembership;
1032 // Now that we have an ASID list full of groups to return, make sure we
1033 // have rudimentary properties for all those groups.
1038 asc_AsidListCopy (&pList, &TASKDATA(ptp)->pAsidList);
1040 LPASOBJPROPLIST pPropList = NULL;
1041 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, pList, &pPropList, &ptp->status))
1044 asc_ObjPropListFree (&pPropList);
1046 asc_AsidListFree (&pList);
1050 Delete (pListGroups);
1051 asc_AsidListFree (&lpp->pUserList);
1053 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1057 void Task_Group_Members_Get (LPTASKPACKET ptp)
1059 LPASIDLIST pGroups = (LPASIDLIST)( ptp->lpUser );
1061 // Prepare an intermediate place for us to put the results of our search.
1062 // We'll be doing lots of work in this intermediate list, so it'll be
1063 // implemented as a hashlist with a key over the objects' ASIDs.
1069 } GROUP_MEMBER_FOUND, *LPGROUP_MEMBER_FOUND;
1071 LPHASHLIST pListUsers = New (HASHLIST);
1072 LPHASHLISTKEY pListKeyAsid = pListUsers->CreateKey ("ASID", Key_Asid_Compare, Key_Asid_HashObject, Key_Asid_HashData);
1074 // For each group in the list, find all of that group's members
1076 for (size_t iGroup = 0; iGroup < pGroups->cEntries; ++iGroup)
1078 LPASIDLIST pMembers = NULL;
1081 if (!asc_GroupMembersGet (g.idClient, g.idCell, pGroups->aEntries[ iGroup ].idObject, &pMembers, &status))
1086 // For each member we found, make sure the member is in the big
1087 // list we'll be returning. Use the {lParam} field of the
1088 // list's entry as a counter, to remember how many groups have
1091 for (size_t iMember = 0; iMember < pMembers->cEntries; ++iMember)
1093 // Is it in the list already? If not, add it.
1095 LPGROUP_MEMBER_FOUND pFind;
1096 if ((pFind = (LPGROUP_MEMBER_FOUND)pListKeyAsid->GetFirstObject (&pMembers->aEntries[ iMember ].idObject)) != NULL)
1102 pFind = New (GROUP_MEMBER_FOUND);
1103 pFind->idUser = pMembers->aEntries[ iMember ].idObject;
1105 pListUsers->Add (pFind);
1109 asc_AsidListFree (&pMembers);
1113 // Now that we have a list of users that match our search criteria,
1114 // stick it in an ASID list. The lParam field for each ASID will be set
1115 // to 1 if all groups have that member, or 0 if only some have it.
1117 if (!asc_AsidListCreate (&TASKDATA(ptp)->pAsidList))
1120 ptp->status = ERROR_NOT_ENOUGH_MEMORY;
1125 for (LPENUM pEnum = pListUsers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1127 LPGROUP_MEMBER_FOUND pFind = (LPGROUP_MEMBER_FOUND)( pEnum->GetObject() );
1129 asc_AsidListAddEntry (&TASKDATA(ptp)->pAsidList, pFind->idUser, (LPARAM)( (pFind->cGroups == pGroups->cEntries) ? 1 : 0 ));
1131 pListUsers->Remove (pFind);
1136 // Now that we have an ASID list full of users to return, make sure we
1137 // have rudimentary properties for all those users.
1142 asc_AsidListCopy (&pList, &TASKDATA(ptp)->pAsidList);
1144 LPASOBJPROPLIST pPropList = NULL;
1145 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, pList, &pPropList, &ptp->status))
1148 asc_ObjPropListFree (&pPropList);
1150 asc_AsidListFree (&pList);
1154 Delete (pListUsers);
1155 asc_AsidListFree (&pGroups);
1156 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1160 void Task_Group_Members_Set (LPTASKPACKET ptp)
1162 LPGROUP_MEMBERS_SET_PARAMS lpp = (LPGROUP_MEMBERS_SET_PARAMS)( ptp->lpUser );
1164 ptp->rc = Task_Group_Members_Set_Do (lpp, &ptp->status);
1166 asc_AsidListFree (&lpp->pGroups);
1167 asc_AsidListFree (&lpp->pMembers);
1169 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1173 BOOL Task_Group_Members_Set_Do (LPGROUP_MEMBERS_SET_PARAMS lpp, ULONG *pStatus)
1177 // Maintain a structure describing any errors we encounter, so we can give
1178 // a reasonable error dialog if need be.
1180 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_SET_MEMBERS, IDS_ERROR_CANT_SET_MEMBERS_MULTIPLE);
1182 // We'll need the supplied member-list in a hashlist, so we can quickly
1183 // test it to see if a particular member should remain in a group.
1185 LPHASHLIST pMembersAllow = New (HASHLIST);
1187 for (iMember = 0; iMember < lpp->pMembers->cEntries; ++iMember)
1188 pMembersAllow->AddUnique ((PVOID)(lpp->pMembers->aEntries[ iMember ].idObject));
1190 // We'll have to do this next bit for each group in the supplied group-list
1192 for (size_t iGroup = 0; iGroup < lpp->pGroups->cEntries; ++iGroup)
1196 // Obtain the current list of members for this group
1198 LPASIDLIST pMembersOld = NULL;
1199 if (!asc_GroupMembersGet (g.idClient, g.idCell, lpp->pGroups->aEntries[ iGroup ].idObject, &pMembersOld, &status))
1201 ED_RegisterStatus (ped, lpp->pGroups->aEntries[ iGroup ].idObject, FALSE, status);
1207 // Test each member in that current list to see if it's also on our
1208 // pMembersAllow list. If not, remove it.
1210 for (iMember = 0; iMember < pMembersOld->cEntries; ++iMember)
1212 if (pMembersAllow->fIsInList ((PVOID)(pMembersOld->aEntries[iMember].idObject)))
1215 if (!asc_GroupMemberRemove (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, pMembersOld->aEntries[iMember].idObject, &status))
1216 ED_RegisterStatus (ped, lpp->pGroups->aEntries[ iGroup ].idObject, FALSE, status);
1219 // Now the more complex part: see if there are any members in the
1220 // supplied member-list which are marked as mandatory, but which
1221 // aren't in our pMembersOld list. We'll need to put the latter in a
1222 // hashlist for this...
1224 LPHASHLIST pMembersOldList = New (HASHLIST);
1225 for (iMember = 0; iMember < pMembersOld->cEntries; ++iMember)
1226 pMembersOldList->AddUnique ((PVOID)(pMembersOld->aEntries[ iMember ].idObject));
1228 for (iMember = 0; iMember < lpp->pMembers->cEntries; ++iMember)
1230 if (!lpp->pMembers->aEntries[ iMember ].lParam)
1231 continue; // member not mandatory
1232 if (pMembersOldList->fIsInList ((PVOID)(lpp->pMembers->aEntries[ iMember ].idObject)))
1233 continue; // already a member
1235 if (!asc_GroupMemberAdd (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, lpp->pMembers->aEntries[iMember].idObject, &status))
1236 ED_RegisterStatus (ped, lpp->pGroups->aEntries[ iGroup ].idObject, FALSE, status);
1239 Delete (pMembersOldList);
1241 asc_AsidListFree (&pMembersOld);
1244 // If there were any errors, report them.
1246 if ((*pStatus = ED_GetFinalStatus(ped)) != 0)
1249 ED_ShowErrorDialog(ped);
1255 Delete (pMembersAllow);
1260 void Task_Group_Enum (LPTASKPACKET ptp)
1262 LPCTSTR pszPattern = (LPCTSTR)( ptp->lpUser );
1264 TCHAR szRegExp[ cchNAME ];
1265 TranslateRegExp (szRegExp, pszPattern);
1266 if ((ptp->rc = asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_GROUP, szRegExp, NULL, &TASKDATA(ptp)->pAsidList, &ptp->status)) == TRUE)
1268 LPASOBJPROPLIST pPropList = NULL;
1270 ptp->rc = asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status);
1273 asc_ObjPropListFree (&pPropList);
1276 FreeString (pszPattern);
1277 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1281 void Task_Group_Rename (LPTASKPACKET ptp)
1283 LPGROUP_RENAME_PARAMS lpp = (LPGROUP_RENAME_PARAMS)( ptp->lpUser );
1285 if ((ptp->rc = asc_GroupRename (g.idClient, g.idCell, lpp->idGroup, lpp->szNewName, &ptp->status)) != FALSE)
1287 Display_RefreshView_Fast();
1290 if (!ptp->rc && !IsWindow (ptp->hReply))
1292 TCHAR szOldName[ cchNAME ];
1293 asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->idGroup, szOldName);
1294 ErrorDialog (ptp->status, IDS_ERROR_CANT_RENAME_GROUP, TEXT("%s%s"), szOldName, lpp->szNewName);
1298 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1302 void Task_Group_Owned_Get (LPTASKPACKET ptp)
1304 ASID idGroup = (ASID)( ptp->lpUser );
1306 ptp->rc = asc_GroupOwnershipGet (g.idClient, g.idCell, idGroup, &TASKDATA(ptp)->pAsidList, &ptp->status);
1308 // Modify the ASID list to have lParams of 1. (This indicates that all
1309 // our supplied groups own this thing; silly but consistent with the
1310 // other such interfaces.)
1312 if (TASKDATA(ptp)->pAsidList)
1314 for (size_t ii = 0; ii < TASKDATA(ptp)->pAsidList->cEntries; ++ii)
1315 TASKDATA(ptp)->pAsidList->aEntries[ ii ].lParam = 1;
1318 // Now that we have an ASID list full of groups to return, make sure we
1319 // have rudimentary properties for all those groups.
1324 asc_AsidListCopy (&pList, &TASKDATA(ptp)->pAsidList);
1326 LPASOBJPROPLIST pPropList = NULL;
1327 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, pList, &pPropList, &ptp->status))
1330 asc_ObjPropListFree (&pPropList);
1332 asc_AsidListFree (&pList);
1337 void Task_Group_Owned_Set (LPTASKPACKET ptp)
1339 LPGROUP_OWNED_SET_PARAMS lpp = (LPGROUP_OWNED_SET_PARAMS)( ptp->lpUser );
1341 ptp->rc = Task_Group_Owned_Set_Do (lpp, &ptp->status);
1343 asc_AsidListFree (&lpp->pOwnedGroups);
1345 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1349 BOOL Task_Group_Owned_Set_Do (LPGROUP_OWNED_SET_PARAMS lpp, ULONG *pStatus)
1353 // Maintain a structure describing any errors we encounter, so we can give
1354 // a reasonable error dialog if need be.
1356 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_CHANGE_OWNER, IDS_ERROR_CANT_CHANGE_OWNER_MULTIPLE);
1358 // We'll need the supplied groups-to-own list in a hashlist, so we can
1359 // quickly test it for inclusion of a particular group.
1361 LPHASHLIST pGroupsAllow = New (HASHLIST);
1363 for (iGroup = 0; iGroup < lpp->pOwnedGroups->cEntries; ++iGroup)
1364 pGroupsAllow->AddUnique ((PVOID)(lpp->pOwnedGroups->aEntries[ iGroup ].idObject));
1366 // Obtain the current list-of-groups-owned for this group
1368 LPASIDLIST pGroupsOld = NULL;
1369 if ((rc = asc_GroupOwnershipGet (g.idClient, g.idCell, lpp->idGroup, &pGroupsOld, pStatus)) == FALSE)
1374 for (size_t ii = 0; ii < lpp->pOwnedGroups->cEntries; ++ii)
1375 ED_RegisterStatus (ped, lpp->pOwnedGroups->aEntries[ii].idObject, FALSE, *pStatus);
1379 // Test each group in that current list to see if it's also on our
1380 // pGroupsAllow list. If not, remove it.
1382 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
1384 if (pGroupsAllow->fIsInList ((PVOID)(pGroupsOld->aEntries[iGroup].idObject)))
1388 ASOBJPROP Properties;
1389 if (!asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &Properties, &status))
1390 ED_RegisterStatus (ped, pGroupsOld->aEntries[iGroup].idObject, FALSE, status);
1393 AFSADMSVR_CHANGEGROUP_PARAMS pp;
1394 memset (&pp, 0x00, sizeof(pp));
1395 lstrcpy (pp.szOwner, Properties.szName); // make group self-owned
1396 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
1397 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
1398 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
1399 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
1400 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
1402 if (!asc_GroupChange (g.idClient, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &pp, &status))
1403 ED_RegisterStatus (ped, pGroupsOld->aEntries[iGroup].idObject, FALSE, status);
1407 // Now the more complex part: see if there are any groups in the
1408 // supplied group-list which are marked as mandatory, but which
1409 // aren't in our pGroupsOld list. We'll need to put the latter in a
1410 // hashlist for this...
1412 LPHASHLIST pGroupsOldList = New (HASHLIST);
1413 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
1414 pGroupsOldList->AddUnique ((PVOID)(pGroupsOld->aEntries[ iGroup ].idObject));
1416 for (iGroup = 0; iGroup < lpp->pOwnedGroups->cEntries; ++iGroup)
1418 if (!lpp->pOwnedGroups->aEntries[ iGroup ].lParam)
1419 continue; // group not mandatory
1420 if (pGroupsOldList->fIsInList ((PVOID)(lpp->pOwnedGroups->aEntries[ iGroup ].idObject)))
1421 continue; // already a member
1424 ASOBJPROP Properties;
1425 if (!asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, lpp->pOwnedGroups->aEntries[iGroup].idObject, &Properties, &status))
1426 ED_RegisterStatus (ped, lpp->pOwnedGroups->aEntries[iGroup].idObject, FALSE, status);
1429 AFSADMSVR_CHANGEGROUP_PARAMS pp;
1430 memset (&pp, 0x00, sizeof(pp));
1431 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
1432 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
1433 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
1434 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
1435 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
1437 if (asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->idGroup, pp.szOwner, &status))
1439 if (!asc_GroupChange (g.idClient, g.idCell, lpp->pOwnedGroups->aEntries[iGroup].idObject, &pp, &status))
1440 ED_RegisterStatus (ped, lpp->pOwnedGroups->aEntries[iGroup].idObject, FALSE, status);
1445 Delete (pGroupsOldList);
1446 asc_AsidListFree (&pGroupsOld);
1449 // If there were any errors, report them.
1451 if ((*pStatus = ED_GetFinalStatus(ped)) != 0)
1454 ED_ShowErrorDialog(ped);
1460 Delete (pGroupsAllow);
1465 void Task_Group_Create (LPTASKPACKET ptp)
1467 LPGROUP_CREATE_PARAMS lpp = (LPGROUP_CREATE_PARAMS)(ptp->lpUser);
1469 // If no owner was specified, use our current credentials' ID. If
1470 // we can't get that, we'll make each group self-owned.
1472 if (!lpp->szOwner[0])
1474 TCHAR szCell[ cchNAME ];
1475 if (!AfsAppLib_CrackCredentials (g.hCreds, szCell, lpp->szOwner))
1476 lpp->szOwner[0] = TEXT('\0');
1479 // We may actually have been asked to create more than one group here;
1480 // the {lpp->mszNames} parameter is a multi-string. So everything we
1481 // do, we'll do for each new group-name...
1483 for (LPTSTR pszName = lpp->mszNames; pszName && *pszName; pszName += 1+lstrlen(pszName))
1485 // First create this new group account
1489 AFSADMSVR_CREATEGROUP_PARAMS pp;
1490 memset (&pp, 0x00, sizeof(AFSADMSVR_CREATEGROUP_PARAMS));
1491 pp.idGroup = (int) lpp->idGroup;
1492 lstrcpy (pp.szName, pszName);
1493 lstrcpy (pp.szOwner, lpp->szOwner);
1495 lstrcpy (pp.szOwner, pszName);
1497 if ((ptp->rc = asc_GroupCreate (g.idClient, g.idCell, &pp, &idGroup, &ptp->status)) == FALSE)
1499 if (!IsWindow (ptp->hReply))
1500 ErrorDialog (ptp->status, IDS_ERROR_CANT_CREATE_GROUP, TEXT("%s"), pszName);
1504 // Then change its properties to be what we want
1506 if ((ptp->rc = asc_GroupChange (g.idClient, g.idCell, idGroup, &lpp->Properties, &ptp->status)) == FALSE)
1508 if (!IsWindow (ptp->hReply))
1509 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_GROUP, TEXT("%s"), pszName);
1514 // Finally update its lists of groups
1518 GROUP_MEMBERS_SET_PARAMS pp;
1519 memset (&pp, 0x00, sizeof(GROUP_MEMBERS_SET_PARAMS));
1520 asc_AsidListCreate (&pp.pGroups);
1521 asc_AsidListAddEntry (&pp.pGroups, idGroup, 0);
1522 asc_AsidListCopy (&pp.pMembers, &lpp->pMembers);
1523 ptp->rc = Task_Group_Members_Set_Do (&pp, &ptp->status);
1524 asc_AsidListFree (&pp.pGroups);
1525 asc_AsidListFree (&pp.pMembers);
1527 if (lpp->pGroupsOwner)
1529 GROUP_OWNED_SET_PARAMS pp;
1530 memset (&pp, 0x00, sizeof(GROUP_OWNED_SET_PARAMS));
1531 pp.idGroup = idGroup;
1532 asc_AsidListCopy (&pp.pOwnedGroups, &lpp->pGroupsOwner);
1533 ptp->rc = Task_Group_Owned_Set_Do (&pp, &ptp->status);
1534 asc_AsidListFree (&pp.pOwnedGroups);
1540 Display_PopulateList();
1542 if (lpp->pGroupsOwner)
1543 asc_AsidListFree (&lpp->pGroupsOwner);
1545 asc_AsidListFree (&lpp->pMembers);
1547 FreeString (lpp->mszNames);
1549 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1553 void Task_Group_Delete (LPTASKPACKET ptp)
1555 LPASIDLIST pGroupList = (LPASIDLIST)(ptp->lpUser);
1557 // Maintain a structure describing any errors we encounter, so we can give
1558 // a reasonable error dialog if need be.
1560 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_DELETE_GROUP, IDS_ERROR_CANT_DELETE_GROUP_MULTIPLE);
1562 // Go through and delete these users
1564 for (size_t iGroup = 0; iGroup < pGroupList->cEntries; ++iGroup)
1567 if (!asc_GroupDelete (g.idClient, g.idCell, pGroupList->aEntries[iGroup].idObject, &status))
1568 ED_RegisterStatus (ped, pGroupList->aEntries[iGroup].idObject, FALSE, status);
1571 // If there were any errors, report them.
1573 if (ED_GetFinalStatus(ped) && !IsWindow(ptp->hReply))
1574 ED_ShowErrorDialog(ped);
1579 Display_PopulateList();
1582 asc_AsidListFree (&pGroupList);
1583 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1587 void Task_Cell_Change (LPTASKPACKET ptp)
1589 LPCELL_CHANGE_PARAMS lpp = (LPCELL_CHANGE_PARAMS)(ptp->lpUser);
1591 AFSADMSVR_CHANGECELL_PARAMS Change;
1592 memset (&Change, 0x00, sizeof(Change));
1593 Change.idUserMax = (DWORD)(lpp->idUserMax);
1594 Change.idGroupMax = (DWORD)(lpp->idGroupMax);
1595 ptp->rc = asc_CellChange (g.idClient, lpp->idCell, &Change, &ptp->status);
1597 if (!ptp->rc && !IsWindow (ptp->hReply))
1599 TCHAR szCell[ cchNAME ];
1600 asc_CellNameGet_Fast (g.idClient, lpp->idCell, szCell);
1601 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_CELL, TEXT("%s"), szCell);
1605 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1609 void Task_List_Translate (LPTASKPACKET ptp)
1611 LPLIST_TRANSLATE_PARAMS lpp = (LPLIST_TRANSLATE_PARAMS)( ptp->lpUser );
1612 TASKDATA(ptp)->Type = lpp->Type;
1614 // We'll need a hashlist into which to dump our results as we build
1615 // them (we use a hashlist so we can quickly detect and ignore duplicates).
1617 LPHASHLIST pList = New (HASHLIST);
1619 // Now split the input string up into a series of names. To do that,
1620 // we'll valid separator characters are; since names can't have whitespace,
1621 // we'll include that.
1623 TCHAR szSeparators[ cchRESOURCE ];
1624 if (!GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SLIST, szSeparators, cchRESOURCE))
1625 szSeparators[0] = TEXT(',');
1626 GetString (&szSeparators[1], IDS_SEPARATORS);
1630 LPCTSTR pszStart = lpp->pszNames;
1631 while (iswhite(*pszStart) || lstrchr (szSeparators, *pszStart))
1636 // Find the first non-name character
1638 LPCTSTR pszEnd = pszStart;
1639 while (*pszEnd && !iswhite(*pszEnd) && !lstrchr(szSeparators, *pszEnd))
1642 // Copy off this particular name
1644 TCHAR szName[ cchNAME ];
1645 lstrcpy (szName, pszStart);
1646 szName[ pszEnd - pszStart ] = TEXT('\0');
1648 // Find the next valid-name character
1651 while (iswhite(*pszStart) || lstrchr(szSeparators, *pszStart))
1654 // Translate this particular name. We'll also handle wildcards
1655 // here: if we don't get any wildcard characters, treat it as
1656 // a direct lookup; if we do, treat it as a regexp match.
1658 if (lstrchr (szName, TEXT('*')) || lstrchr (szName, TEXT('?')) ||
1659 lstrchr (szName, TEXT('^')) || lstrchr (szName, TEXT('!')))
1661 TCHAR szRegExp[ cchNAME ];
1662 TranslateRegExp (szRegExp, szName);
1664 LPASIDLIST pAsidList;
1665 if (asc_ObjectFindMultiple (g.idClient, g.idCell, lpp->Type, szRegExp, NULL, &pAsidList, &ptp->status))
1669 for (size_t ii = 0; ii < pAsidList->cEntries; ++ii)
1670 pList->AddUnique ((PVOID)(pAsidList->aEntries[ii].idObject));
1671 asc_AsidListFree (&pAsidList);
1675 else // No wildcards; just look up the name directly
1678 if (asc_ObjectFind (g.idClient, g.idCell, lpp->Type, szName, &idObject, &ptp->status))
1679 pList->AddUnique ((PVOID)idObject);
1684 // Finally, build an ASIDLIST from our hashlist's contents.
1686 if (!asc_AsidListCreate (&TASKDATA(ptp)->pAsidList))
1689 ptp->status = ERROR_NOT_ENOUGH_MEMORY;
1693 for (LPENUM pEnum = pList->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1695 ASID idObject = (ASID)(pEnum->GetObject());
1696 asc_AsidListAddEntry (&TASKDATA(ptp)->pAsidList, idObject, 0);
1703 FreeString (lpp->pszNames);
1705 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1709 void Task_Object_Listen (LPTASKPACKET ptp)
1711 LPOBJECT_LISTEN_PARAMS lpp = (LPOBJECT_LISTEN_PARAMS)( ptp->lpUser );
1713 if (IsWindow(lpp->hNotify) && (lpp->pAsidList))
1714 ptp->rc = asc_ObjectListenMultiple (g.idClient, g.idCell, lpp->pAsidList, lpp->hNotify, &ptp->status);
1716 ptp->rc = asc_ObjectListenClear (g.idClient, lpp->hNotify, &ptp->status);
1719 asc_AsidListFree (&lpp->pAsidList);
1721 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1725 void Task_Object_Get (LPTASKPACKET ptp)
1727 ASID idObject = (ASID)(ptp->lpUser);
1728 ptp->rc = asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, idObject, &TASKDATA(ptp)->Properties, &ptp->status);
1732 void Task_Set_Refresh (LPTASKPACKET ptp)
1736 ptp->rc = asc_CellRefreshRateSet (g.idClient, g.idCell, gr.cminRefreshRate, &ptp->status);
1741 void Task_Expired_Creds (LPTASKPACKET ptp)
1745 CheckForExpiredCredentials();
1750 void WeedAsidList (LPASIDLIST *ppList, BOOL fWantMachines)
1754 // First off, we can't do anything unless we have these guys' names.
1756 if (ppList && (*ppList) && (*ppList)->cEntries)
1758 LPASOBJPROPLIST pPropList = NULL;
1759 asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, *ppList, &pPropList, &status);
1761 asc_ObjPropListFree (&pPropList);
1764 for (size_t ii = 0; ppList && (*ppList) && (ii < (*ppList)->cEntries); )
1766 TCHAR szName[ cchRESOURCE ];
1767 if (!asc_ObjectNameGet_Fast (g.idClient, g.idCell, (*ppList)->aEntries[ ii ].idObject, szName, &status))
1773 if (fIsMachineAccount(szName) == fWantMachines)
1776 asc_AsidListRemoveEntryByIndex (ppList, ii);
1781 void TranslateRegExp (LPTSTR pszTarget, LPCTSTR pszSource)
1785 if (!gr.fWindowsRegexp)
1787 lstrcpy (pszTarget, pszSource);
1791 for ( ; *pszSource; pszSource++)
1798 *pszTarget++ = TEXT('\\');
1799 *pszTarget++ = *pszSource;
1803 *pszTarget++ = TEXT('.');
1807 *pszTarget++ = TEXT('.');
1808 *pszTarget++ = TEXT('*');
1812 *pszTarget++ = *pszSource;
1819 *pszTarget++ = TEXT('\0');
1823 BOOL PerformRefresh (LPTASKPACKET ptp, ASID idScope, ULONG *pStatus)
1825 // Invalidate the admin server's cached information about the specified
1826 // object. Remember that this is recursive hierarchically: if you pass
1827 // in a cell's ID, for instance, information about all users, groups,
1828 // servers, services, partitions and volumes anywhere in that cell will
1834 if (!asc_ObjectRefresh (g.idClient, g.idCell, idScope, pStatus))
1837 // The Refresh call above is a misnomer; it's really an Invalidate request,
1838 // in that it only causes the admin server to dump its cached information
1839 // over the specified scope. At this point we need to do something to
1840 // trigger the server to re-query that information, so that it will send
1841 // an ACTION_REFRESH notification (indicating it's doing that requery),
1842 // which we'll pick up on and use as a trigger to refresh our display.
1843 // A convenient way to get the server to do that re-query is to ask it
1844 // to perform some simple search among the users in the cell--we'll ask
1845 // it to find, oh, say, "JoeBobUser", and in order to do that, it will
1846 // have to re-fill its cache.
1848 LPASIDLIST pListDummy;
1850 (void)asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_USER, TEXT("JoeBobUser"), NULL, &pListDummy, &statusDummy);
1851 if (pListDummy != NULL)
1852 asc_AsidListFree (&pListDummy);