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 DWORD WINAPI Task_ThreadProc (PVOID lp);
38 void Task_Perform (LPTASKPACKET ptp);
40 void Task_OpenCell (LPTASKPACKET ptp);
41 void Task_UpdCreds (LPTASKPACKET ptp);
42 void Task_UpdUsers (LPTASKPACKET ptp);
43 void Task_UpdGroups (LPTASKPACKET ptp);
44 void Task_UpdMachines (LPTASKPACKET ptp);
45 void Task_Refresh (LPTASKPACKET ptp);
46 void Task_RefreshMult (LPTASKPACKET ptp);
47 void Task_Get_Actions (LPTASKPACKET ptp);
48 void Task_Get_Random_Key (LPTASKPACKET ptp);
49 void Task_User_Change (LPTASKPACKET ptp);
50 void Task_User_Find (LPTASKPACKET ptp);
51 void Task_User_Enum (LPTASKPACKET ptp);
52 void Task_User_GroupList_Set (LPTASKPACKET ptp);
53 BOOL Task_User_GroupList_Set_Do (LPUSER_GROUPLIST_SET_PARAMS lpp, ULONG *pStatus);
54 void Task_User_CPW (LPTASKPACKET ptp);
55 void Task_User_Unlock (LPTASKPACKET ptp);
56 void Task_User_Create (LPTASKPACKET ptp);
57 void Task_User_Delete (LPTASKPACKET ptp);
58 void Task_Group_Change (LPTASKPACKET ptp);
59 void Task_Group_Search (LPTASKPACKET ptp);
60 void Task_Group_Members_Get (LPTASKPACKET ptp);
61 void Task_Group_Members_Set (LPTASKPACKET ptp);
62 BOOL Task_Group_Members_Set_Do (LPGROUP_MEMBERS_SET_PARAMS lpp, ULONG *pStatus);
63 void Task_Group_Enum (LPTASKPACKET ptp);
64 void Task_Group_Rename (LPTASKPACKET ptp);
65 void Task_Group_Owned_Get (LPTASKPACKET ptp);
66 void Task_Group_Owned_Set (LPTASKPACKET ptp);
67 BOOL Task_Group_Owned_Set_Do (LPGROUP_OWNED_SET_PARAMS lpp, ULONG *pStatus);
68 void Task_Group_Create (LPTASKPACKET ptp);
69 void Task_Group_Delete (LPTASKPACKET ptp);
70 void Task_Cell_Change (LPTASKPACKET ptp);
71 void Task_List_Translate (LPTASKPACKET ptp);
72 void Task_Object_Listen (LPTASKPACKET ptp);
73 void Task_Object_Get (LPTASKPACKET ptp);
74 void Task_Set_Refresh (LPTASKPACKET ptp);
75 void Task_Expired_Creds (LPTASKPACKET ptp);
77 void WeedAsidList (LPASIDLIST *ppList, BOOL fWantMachines);
78 void TranslateRegExp (LPTSTR pszTarget, LPCTSTR pszSource);
79 BOOL PerformRefresh (LPTASKPACKET ptp, ASID idScope, ULONG *pStatus);
83 * ROUTINES ___________________________________________________________________
87 LPTASKPACKET CreateTaskPacket (int idTask, HWND hReply, PVOID lpUser)
91 if ((ptp = New (TASKPACKET)) != NULL)
93 memset (ptp, 0x00, sizeof(TASKPACKET));
101 if ((ptp->pReturn = New (TASKPACKETDATA)) != NULL)
103 memset (ptp->pReturn, 0x00, sizeof(TASKPACKETDATA));
111 void FreeTaskPacket (LPTASKPACKET ptp)
117 if (TASKDATA(ptp)->pAsidList)
118 asc_AsidListFree (&TASKDATA(ptp)->pAsidList);
119 if (TASKDATA(ptp)->pActionList)
120 asc_ActionListFree (&TASKDATA(ptp)->pActionList);
121 Delete (ptp->pReturn);
128 void PerformTask (LPTASKPACKET ptp)
145 Task_UpdGroups (ptp);
148 case taskUPD_MACHINES:
149 Task_UpdMachines (ptp);
156 case taskREFRESHMULT:
157 Task_RefreshMult (ptp);
160 case taskGET_ACTIONS:
161 Task_Get_Actions (ptp);
164 case taskGET_RANDOM_KEY:
165 Task_Get_Random_Key (ptp);
168 case taskUSER_CHANGE:
169 Task_User_Change (ptp);
173 Task_User_Find (ptp);
177 Task_User_Enum (ptp);
180 case taskUSER_GROUPLIST_SET:
181 Task_User_GroupList_Set (ptp);
188 case taskUSER_UNLOCK:
189 Task_User_Unlock (ptp);
192 case taskUSER_CREATE:
193 Task_User_Create (ptp);
196 case taskUSER_DELETE:
197 Task_User_Delete (ptp);
200 case taskGROUP_CHANGE:
201 Task_Group_Change (ptp);
204 case taskGROUP_SEARCH:
205 Task_Group_Search (ptp);
208 case taskGROUP_MEMBERS_GET:
209 Task_Group_Members_Get (ptp);
212 case taskGROUP_MEMBERS_SET:
213 Task_Group_Members_Set (ptp);
217 Task_Group_Enum (ptp);
220 case taskGROUP_RENAME:
221 Task_Group_Rename (ptp);
224 case taskGROUP_OWNED_GET:
225 Task_Group_Owned_Get (ptp);
228 case taskGROUP_OWNED_SET:
229 Task_Group_Owned_Set (ptp);
232 case taskGROUP_CREATE:
233 Task_Group_Create (ptp);
236 case taskGROUP_DELETE:
237 Task_Group_Delete (ptp);
240 case taskCELL_CHANGE:
241 Task_Cell_Change (ptp);
244 case taskLIST_TRANSLATE:
245 Task_List_Translate (ptp);
248 case taskOBJECT_LISTEN:
249 Task_Object_Listen (ptp);
253 Task_Object_Get (ptp);
256 case taskSET_REFRESH:
257 Task_Set_Refresh (ptp);
260 case taskEXPIRED_CREDS:
261 Task_Expired_Creds (ptp);
266 ptp->status = ERROR_INVALID_FUNCTION;
273 * KEYS _______________________________________________________________________
277 HASHVALUE CALLBACK Key_Asid_HashData (LPHASHLISTKEY pKey, PVOID pData)
279 return *(ASID*)pData;
282 HASHVALUE CALLBACK Key_Asid_HashObject (LPHASHLISTKEY pKey, PVOID pObject)
284 return Key_Asid_HashData (pKey, (ASID*)pObject);
287 BOOL CALLBACK Key_Asid_Compare (LPHASHLISTKEY pKey, PVOID pObject, PVOID pData)
289 return ((*(ASID*)pObject) == (*(ASID*)pData));
294 * TASKS ______________________________________________________________________
298 void Task_OpenCell (LPTASKPACKET ptp)
300 LPOPENCELL_PARAMS lpp = (LPOPENCELL_PARAMS)( ptp->lpUser );
302 Display_StartWorking();
304 // Try to open the cell for administration
306 ptp->rc = asc_CellOpen (g.idClient, lpp->hCreds, lpp->szCell, AFSADMSVR_SCOPE_USERS, &TASKDATA(ptp)->idCell, &ptp->status);
310 PostMessage (g.hMain, WM_SHOW_YOURSELF, 0, 1);
312 else if ((!ptp->rc) && (!IsWindow(ptp->hReply)))
314 if (lpp->fCloseAppOnFail)
315 FatalErrorDialog (ptp->status, IDS_ERROR_CANT_OPEN_CELL, TEXT("%s"), lpp->szCell);
317 ErrorDialog (ptp->status, IDS_ERROR_CANT_OPEN_CELL, TEXT("%s"), lpp->szCell);
320 // If we previously had another cell open, close it.
329 (void)asc_CellClose (g.idClient, g.idCell, &status);
331 g.idCell = TASKDATA(ptp)->idCell;
336 // Update the "Selected Cell:" text on the main window
338 TCHAR szCell[ cchNAME ];
340 GetString (szCell, IDS_CELL_NONE);
341 else if (!asc_CellNameGet_Fast (g.idClient, g.idCell, szCell))
342 GetString (szCell, IDS_CELL_NONE);
343 SetDlgItemText (g.hMain, IDC_CELL, szCell);
344 ShowCurrentCredentials();
346 // Oh--also, set the refresh rate for the newly-opened cell
349 asc_CellRefreshRateSet (g.idClient, g.idCell, gr.cminRefreshRate, &dummy);
351 // Start re-populating the Users or Groups tab (whichever is showing)
353 Display_PopulateList();
355 Display_StopWorking();
357 // When we've opened a new cell, it's time to open the Actions window.
360 PostMessage (g.hMain, WM_SHOW_ACTIONS, 0, 0);
363 ptp->lpUser = 0; // we freed this; don't let the caller use it again
367 void Task_UpdCreds (LPTASKPACKET ptp)
369 // Update the display to report our new credentials
371 ShowCurrentCredentials();
373 // Tell the admin server to use our new credentials, and refresh everything
375 if (!asc_CredentialsPush (g.idClient, g.hCreds, g.idCell, &ptp->status))
378 ptp->rc = PerformRefresh (ptp, g.idCell, &ptp->status);
382 void Task_UpdUsers (LPTASKPACKET ptp)
384 // First we'll query the admin server to find a list of all users which
385 // match our search pattern.
387 lstrcpy (TASKDATA(ptp)->szPattern, g.szPatternUsers);
389 TCHAR szRegExp[ cchNAME ];
390 TranslateRegExp (szRegExp, TASKDATA(ptp)->szPattern);
391 if (!asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_USER, szRegExp, &gr.SearchUsers, &TASKDATA(ptp)->pAsidList, &ptp->status))
394 // If we got a result back, weed out any entries that look like machines.
398 WeedAsidList (&TASKDATA(ptp)->pAsidList, FALSE);
401 // Wow, that was easy. Okay, next step: ensure that we have properties
402 // for all these guys in the local cache--to do that, we'll query their
403 // properties, then free the result.
407 LPASOBJPROPLIST pPropList = NULL;
408 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_ALL_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status))
411 asc_ObjPropListFree (&pPropList);
416 void Task_UpdGroups (LPTASKPACKET ptp)
418 // First we'll query the admin server to find a list of all groups which
419 // match our search pattern.
421 lstrcpy (TASKDATA(ptp)->szPattern, g.szPatternGroups);
423 TCHAR szRegExp[ cchNAME ];
424 TranslateRegExp (szRegExp, TASKDATA(ptp)->szPattern);
425 if (!asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_GROUP, szRegExp, NULL, &TASKDATA(ptp)->pAsidList, &ptp->status))
428 // Wow, that was easy. Okay, next step: ensure that we have properties
429 // for all these guys in the local cache--to do that, we'll query their
430 // properties, then free the result.
434 LPASOBJPROPLIST pPropList = NULL;
435 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_ALL_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status))
438 asc_ObjPropListFree (&pPropList);
443 void Task_UpdMachines (LPTASKPACKET ptp)
445 // First we'll query the admin server to find a list of all users which
446 // match our search pattern.
448 TCHAR szRegExp[ cchNAME ];
449 if (g.szPatternMachines[0])
450 TranslateRegExp (szRegExp, g.szPatternMachines);
452 lstrcpy (szRegExp, TEXT("^[0-9.]*$"));
454 if (!asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_USER, szRegExp, NULL, &TASKDATA(ptp)->pAsidList, &ptp->status))
457 lstrcpy (TASKDATA(ptp)->szPattern, g.szPatternMachines);
459 // If we got a result back, weed out any entries that don't look
464 WeedAsidList (&TASKDATA(ptp)->pAsidList, TRUE);
467 // Wow, that was easy. Okay, next step: ensure that we have properties
468 // for all these guys in the local cache--to do that, we'll query their
469 // properties, then free the result.
473 LPASOBJPROPLIST pPropList = NULL;
474 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_ALL_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status))
477 asc_ObjPropListFree (&pPropList);
483 void Task_Refresh (LPTASKPACKET ptp)
485 ASID idScope = (ASID)( ptp->lpUser );
487 ptp->rc = PerformRefresh (ptp, idScope, &ptp->status);
491 void Task_RefreshMult (LPTASKPACKET ptp)
493 LPASIDLIST pAsidList = (LPASIDLIST)( ptp->lpUser );
495 // Invalidate the admin server's cached information about the specified
496 // object. Remember that this is recursive hierarchically: if you pass
497 // in a cell's ID, for instance, information about all users, groups,
498 // servers, services, partitions and volumes anywhere in that cell will
501 ptp->rc = asc_ObjectRefreshMultiple (g.idClient, g.idCell, pAsidList, &ptp->status);
503 // The Refresh call above just made us invalidate the status for one or
504 // more objects; to get the display to reflect the changes, we'll have to
505 // query the server for the latest properties for those objects. Once that's
506 // done, we'll just redraw the main window and it will pick up the changes.
511 LPASOBJPROPLIST pPropList = NULL;
512 if (asc_ObjectPropertiesGetMultiple (g.idClient, GET_ALL_DATA, g.idCell, pAsidList, &pPropList, &status))
514 // That call returned properties for the objects; we don't need
515 // the properties here--we just wanted to get them in the cache.
516 // Now that they're in the cache, redrawing the main window will
517 // cause the latest data to be displayed.
520 asc_ObjPropListFree (&pPropList);
521 Display_RefreshView_Fast();
525 asc_AsidListFree (&pAsidList);
526 ptp->lpUser = 0; // we freed this; don't let the caller use it again
530 void Task_Get_Actions (LPTASKPACKET ptp)
532 // Query the admin server to get a current list of operations-in-progress.
533 // We'll limit our search to operations being performed on this cell.
535 ptp->rc = asc_ActionGetMultiple (g.idClient, 0, g.idCell, &TASKDATA(ptp)->pActionList, &ptp->status);
539 void Task_Get_Random_Key (LPTASKPACKET ptp)
541 ptp->rc = asc_RandomKeyGet (g.idClient, g.idCell, TASKDATA(ptp)->key, &ptp->status);
543 if (!ptp->rc && !IsWindow(ptp->hReply))
545 ErrorDialog (ptp->status, IDS_ERROR_CANT_GET_RANDOM_KEY);
550 void Task_User_Change (LPTASKPACKET ptp)
552 LPUSER_CHANGE_PARAMS lpp = (LPUSER_CHANGE_PARAMS)( ptp->lpUser );
554 if ((ptp->rc = asc_UserChange (g.idClient, g.idCell, lpp->idUser, &lpp->NewProperties, &ptp->status)) == TRUE)
556 Display_RefreshView_Fast();
559 if (!ptp->rc && !IsWindow (ptp->hReply))
561 TCHAR szUser[ cchNAME ];
562 User_GetDisplayName (szUser, lpp->idUser);
563 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_USER, TEXT("%s"), szUser);
567 ptp->lpUser = 0; // we freed this; don't let the caller use it again
571 void Task_User_Find (LPTASKPACKET ptp)
573 LPTSTR pszName = (LPTSTR)( ptp->lpUser );
575 if ((ptp->rc = asc_ObjectFind (g.idClient, g.idCell, TYPE_USER, pszName, &TASKDATA(ptp)->idObject, &ptp->status)) == TRUE)
577 ptp->rc = asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, TASKDATA(ptp)->idObject, &TASKDATA(ptp)->Properties, &ptp->status);
580 FreeString (pszName);
581 ptp->lpUser = 0; // we freed this; don't let the caller use it again
585 void Task_User_Enum (LPTASKPACKET ptp)
587 LPCTSTR pszPattern = (LPCTSTR)( ptp->lpUser );
589 TCHAR szRegExp[ cchNAME ];
590 TranslateRegExp (szRegExp, pszPattern);
591 if ((ptp->rc = asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_USER, szRegExp, NULL, &TASKDATA(ptp)->pAsidList, &ptp->status)) == TRUE)
593 LPASOBJPROPLIST pPropList = NULL;
595 ptp->rc = asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status);
598 asc_ObjPropListFree (&pPropList);
601 FreeString (pszPattern);
602 ptp->lpUser = 0; // we freed this; don't let the caller use it again
606 void Task_User_GroupList_Set (LPTASKPACKET ptp)
608 LPUSER_GROUPLIST_SET_PARAMS lpp = (LPUSER_GROUPLIST_SET_PARAMS)( ptp->lpUser );
610 ptp->rc = Task_User_GroupList_Set_Do (lpp, &ptp->status);
612 asc_AsidListFree (&lpp->pUsers);
613 asc_AsidListFree (&lpp->pGroups);
615 ptp->lpUser = 0; // we freed this; don't let the caller use it again
619 BOOL Task_User_GroupList_Set_Do (LPUSER_GROUPLIST_SET_PARAMS lpp, ULONG *pStatus)
623 // Maintain a structure describing any errors we encounter, so we can give
624 // a reasonable error dialog if need be.
626 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_SET_GROUPS, IDS_ERROR_CANT_SET_GROUPS_MULTIPLE);
628 // We'll need the supplied group-list in a hashlist, so we can quickly
629 // test it for inclusion of a particular group.
631 LPHASHLIST pGroupsAllow = New (HASHLIST);
632 for (size_t iGroup = 0; iGroup < lpp->pGroups->cEntries; ++iGroup)
633 pGroupsAllow->AddUnique ((PVOID)(lpp->pGroups->aEntries[ iGroup ].idObject));
635 // We'll have to do this next bit for each user in the supplied user-list
637 for (size_t iUser = 0; iUser < lpp->pUsers->cEntries; ++iUser)
641 // Obtain the appropriate current list of groups for this user
643 LPASIDLIST pGroupsOld = NULL;
644 if (lpp->fMembership)
646 if (!asc_GroupMembershipGet (g.idClient, g.idCell, lpp->pUsers->aEntries[ iUser ].idObject, &pGroupsOld, &status))
648 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
652 else // (!lpp->fMembership)
654 if (!asc_GroupOwnershipGet (g.idClient, g.idCell, lpp->pUsers->aEntries[ iUser ].idObject, &pGroupsOld, &status))
656 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
663 // Test each group in that current list to see if it's also on our
664 // pGroupsAllow list. If not, remove it.
666 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
668 if (pGroupsAllow->fIsInList ((PVOID)(pGroupsOld->aEntries[iGroup].idObject)))
671 if (lpp->fMembership)
673 if (!asc_GroupMemberRemove (g.idClient, g.idCell, pGroupsOld->aEntries[iGroup].idObject, lpp->pUsers->aEntries[iUser].idObject, &status))
674 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
676 else // (!lpp->fMembership)
678 ASOBJPROP Properties;
679 if (asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &Properties, &status))
681 AFSADMSVR_CHANGEGROUP_PARAMS pp;
682 memset (&pp, 0x00, sizeof(pp));
683 lstrcpy (pp.szOwner, Properties.szName); // make group self-owned
684 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
685 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
686 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
687 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
688 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
689 if (!asc_GroupChange (g.idClient, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &pp, &status))
690 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
695 // Now the more complex part: see if there are any groups in the
696 // supplied group-list which are marked as mandatory, but which
697 // aren't in our pGroupsOld list. We'll need to put the latter in a
698 // hashlist for this...
700 LPHASHLIST pGroupsOldList = New (HASHLIST);
701 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
702 pGroupsOldList->AddUnique ((PVOID)(pGroupsOld->aEntries[ iGroup ].idObject));
704 for (iGroup = 0; iGroup < lpp->pGroups->cEntries; ++iGroup)
706 if (!lpp->pGroups->aEntries[ iGroup ].lParam)
707 continue; // group not mandatory
708 if (pGroupsOldList->fIsInList ((PVOID)(lpp->pGroups->aEntries[ iGroup ].idObject)))
709 continue; // already a member
711 if (lpp->fMembership)
713 if (!asc_GroupMemberAdd (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, lpp->pUsers->aEntries[iUser].idObject, &status))
714 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
716 else // (!lpp->fMembership)
718 ASOBJPROP Properties;
719 if (asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, &Properties, &status))
721 AFSADMSVR_CHANGEGROUP_PARAMS pp;
722 memset (&pp, 0x00, sizeof(pp));
723 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
724 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
725 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
726 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
727 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
729 if (asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->pUsers->aEntries[iUser].idObject, pp.szOwner, &status))
731 if (!asc_GroupChange (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, &pp, &status))
732 ED_RegisterStatus (ped, lpp->pUsers->aEntries[ iUser ].idObject, FALSE, status);
738 Delete (pGroupsOldList);
739 asc_AsidListFree (&pGroupsOld);
742 // If there were any errors, report them.
744 if ((*pStatus = ED_GetFinalStatus(ped)) != 0)
747 ED_ShowErrorDialog(ped);
753 Delete (pGroupsAllow);
758 void Task_User_CPW (LPTASKPACKET ptp)
760 LPUSER_CPW_PARAMS lpp = (LPUSER_CPW_PARAMS)( ptp->lpUser );
762 ptp->rc = asc_UserPasswordSet (g.idClient, g.idCell, lpp->idUser, lpp->keyVersion, lpp->keyString, lpp->keyData, &ptp->status);
764 if ((!ptp->rc) && (!IsWindow(ptp->hReply)))
766 TCHAR szName[ cchNAME ];
767 User_GetDisplayName (szName, lpp->idUser);
768 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_PASSWORD, TEXT("%s"), szName);
772 ptp->lpUser = 0; // we freed this; don't let the caller use it again
776 void Task_User_Unlock (LPTASKPACKET ptp)
778 LPASIDLIST pUserList = (LPASIDLIST)( ptp->lpUser );
780 // Maintain a structure describing any errors we encounter, so we can give
781 // a reasonable error dialog if need be.
783 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_UNLOCK, IDS_ERROR_CANT_UNLOCK_MULTIPLE);
785 // Try to unlock the users' accounts...
787 for (size_t iUser = 0; iUser < pUserList->cEntries; ++iUser)
789 if (!asc_UserUnlock (g.idClient, g.idCell, pUserList->aEntries[ iUser ].idObject, &ptp->status))
790 ED_RegisterStatus (ped, pUserList->aEntries[ iUser ].idObject, FALSE, ptp->status);
793 // If there were any errors, report them.
795 if (ED_GetFinalStatus(ped) && !IsWindow(ptp->hReply))
796 ED_ShowErrorDialog(ped);
799 asc_AsidListFree (&pUserList);
800 ptp->lpUser = 0; // we freed this; don't let the caller use it again
804 void Task_User_Create (LPTASKPACKET ptp)
806 LPUSER_CREATE_PARAMS lpp = (LPUSER_CREATE_PARAMS)(ptp->lpUser);
808 // We may actually have been asked to create more than one user here;
809 // the {lpp->mszNames} parameter is a multi-string. So everything we
810 // do, we'll do for each new user-name...
812 for (LPTSTR pszName = lpp->mszNames; pszName && *pszName; pszName += 1+lstrlen(pszName))
814 // First create this new user account
818 AFSADMSVR_CREATEUSER_PARAMS pp;
819 memset (&pp, 0x00, sizeof(AFSADMSVR_CREATEUSER_PARAMS));
820 User_SplitDisplayName (pszName, pp.szName, pp.szInstance);
821 lstrcpy (pp.szPassword, lpp->szPassword);
822 pp.idUser = lpp->idUser;
823 pp.fCreateKAS = lpp->fCreateKAS;
824 pp.fCreatePTS = lpp->fCreatePTS;
825 if ((ptp->rc = asc_UserCreate (g.idClient, g.idCell, &pp, &idUser, &ptp->status)) == FALSE)
827 if (!IsWindow (ptp->hReply))
828 ErrorDialog (ptp->status, IDS_ERROR_CANT_CREATE_USER, TEXT("%s"), pszName);
832 // Then change its properties to be what we want
834 if ((ptp->rc = asc_UserChange (g.idClient, g.idCell, idUser, &lpp->Properties, &ptp->status)) == FALSE)
836 if (!IsWindow (ptp->hReply))
837 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_USER, TEXT("%s"), pszName);
842 // Finally update its lists of groups
844 if (lpp->pGroupsMember)
846 USER_GROUPLIST_SET_PARAMS pp;
847 memset (&pp, 0x00, sizeof(USER_GROUPLIST_SET_PARAMS));
848 asc_AsidListCreate (&pp.pUsers);
849 asc_AsidListAddEntry (&pp.pUsers, idUser, 0);
850 asc_AsidListCopy (&pp.pGroups, &lpp->pGroupsMember);
851 pp.fMembership = TRUE;
852 ptp->rc = Task_User_GroupList_Set_Do (&pp, &ptp->status);
853 asc_AsidListFree (&pp.pUsers);
854 asc_AsidListFree (&pp.pGroups);
856 if (lpp->pGroupsOwner)
858 USER_GROUPLIST_SET_PARAMS pp;
859 memset (&pp, 0x00, sizeof(USER_GROUPLIST_SET_PARAMS));
860 asc_AsidListCreate (&pp.pUsers);
861 asc_AsidListAddEntry (&pp.pUsers, idUser, 0);
862 asc_AsidListCopy (&pp.pGroups, &lpp->pGroupsOwner);
863 pp.fMembership = FALSE;
864 ptp->rc = Task_User_GroupList_Set_Do (&pp, &ptp->status);
865 asc_AsidListFree (&pp.pUsers);
866 asc_AsidListFree (&pp.pGroups);
872 Display_PopulateList();
874 if (lpp->pGroupsOwner)
875 asc_AsidListFree (&lpp->pGroupsOwner);
876 if (lpp->pGroupsMember)
877 asc_AsidListFree (&lpp->pGroupsMember);
879 FreeString (lpp->mszNames);
881 ptp->lpUser = 0; // we freed this; don't let the caller use it again
885 void Task_User_Delete (LPTASKPACKET ptp)
887 LPUSER_DELETE_PARAMS lpp = (LPUSER_DELETE_PARAMS)(ptp->lpUser);
889 // Maintain a structure describing any errors we encounter, so we can give
890 // a reasonable error dialog if need be.
892 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_DELETE_USER, IDS_ERROR_CANT_DELETE_USER_MULTIPLE);
894 // Go through and delete these users
896 for (size_t iUser = 0; iUser < lpp->pUserList->cEntries; ++iUser)
898 AFSADMSVR_DELETEUSER_PARAMS pp;
899 memset (&pp, 0x00, sizeof(pp));
900 pp.fDeleteKAS = lpp->fDeleteKAS;
901 pp.fDeletePTS = lpp->fDeletePTS;
904 if (!asc_UserDelete (g.idClient, g.idCell, lpp->pUserList->aEntries[iUser].idObject, &pp, &status))
905 ED_RegisterStatus (ped, lpp->pUserList->aEntries[iUser].idObject, FALSE, status);
908 // If there were any errors, report them.
910 if (ED_GetFinalStatus(ped) && !IsWindow(ptp->hReply))
911 ED_ShowErrorDialog(ped);
916 Display_PopulateList();
919 asc_AsidListFree (&lpp->pUserList);
921 ptp->lpUser = 0; // we freed this; don't let the caller use it again
925 void Task_Group_Change (LPTASKPACKET ptp)
927 LPGROUP_CHANGE_PARAMS lpp = (LPGROUP_CHANGE_PARAMS)( ptp->lpUser );
929 if ((ptp->rc = asc_GroupChange (g.idClient, g.idCell, lpp->idGroup, &lpp->NewProperties, &ptp->status)) == TRUE)
931 Display_RefreshView_Fast();
934 if (!ptp->rc && !IsWindow (ptp->hReply))
936 TCHAR szGroup[ cchNAME ];
937 asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->idGroup, szGroup);
938 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_GROUP, TEXT("%s"), szGroup);
942 ptp->lpUser = 0; // we freed this; don't let the caller use it again
946 void Task_Group_Search (LPTASKPACKET ptp)
948 LPGROUP_SEARCH_PARAMS lpp = (LPGROUP_SEARCH_PARAMS)( ptp->lpUser );
950 // Prepare an intermediate place for us to put the results of our search.
951 // We'll be doing lots of work in this intermediate list, so it'll be
952 // implemented as a hashlist with a key over the objects' ASIDs.
958 } GROUP_SEARCH_FOUND, *LPGROUP_SEARCH_FOUND;
960 LPHASHLIST pListGroups = New (HASHLIST);
961 LPHASHLISTKEY pListKeyAsid = pListGroups->CreateKey ("ASID", Key_Asid_Compare, Key_Asid_HashObject, Key_Asid_HashData);
963 // Search through the appropriate groups for each user in the list
965 for (size_t iUser = 0; iUser < lpp->pUserList->cEntries; ++iUser)
967 LPASIDLIST pGroups = NULL;
970 if (lpp->fMembership)
972 if (!asc_GroupMembershipGet (g.idClient, g.idCell, lpp->pUserList->aEntries[ iUser ].idObject, &pGroups, &status))
975 else // (!lpp->fMembership)
977 if (!asc_GroupOwnershipGet (g.idClient, g.idCell, lpp->pUserList->aEntries[ iUser ].idObject, &pGroups, &status))
983 // For each group we found, make sure the group is in the big
984 // list we'll be returning. Use the {lParam} field of the
985 // list's entry as a counter, to remember how many users have
988 for (size_t iGroup = 0; iGroup < pGroups->cEntries; ++iGroup)
990 // Is it in the list already? If not, add it.
992 LPGROUP_SEARCH_FOUND pFind;
993 if ((pFind = (LPGROUP_SEARCH_FOUND)pListKeyAsid->GetFirstObject (&pGroups->aEntries[ iGroup ].idObject)) != NULL)
999 pFind = New (GROUP_SEARCH_FOUND);
1000 pFind->idGroup = pGroups->aEntries[ iGroup ].idObject;
1002 pListGroups->Add (pFind);
1006 asc_AsidListFree (&pGroups);
1010 // Now that we have a list of groups that match our search criteria,
1011 // stick it in an ASID list. The lParam field for each ASID will be set
1012 // to 1 if all users have that group, or 0 if only some have it.
1014 if (!asc_AsidListCreate (&TASKDATA(ptp)->pAsidList))
1017 ptp->status = ERROR_NOT_ENOUGH_MEMORY;
1022 for (LPENUM pEnum = pListGroups->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1024 LPGROUP_SEARCH_FOUND pFind = (LPGROUP_SEARCH_FOUND)( pEnum->GetObject() );
1026 asc_AsidListAddEntry (&TASKDATA(ptp)->pAsidList, pFind->idGroup, (LPARAM)( (pFind->cUsers == lpp->pUserList->cEntries) ? 1 : 0 ));
1028 pListGroups->Remove (pFind);
1032 TASKDATA(ptp)->fMembership = lpp->fMembership;
1035 // Now that we have an ASID list full of groups to return, make sure we
1036 // have rudimentary properties for all those groups.
1041 asc_AsidListCopy (&pList, &TASKDATA(ptp)->pAsidList);
1043 LPASOBJPROPLIST pPropList = NULL;
1044 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, pList, &pPropList, &ptp->status))
1047 asc_ObjPropListFree (&pPropList);
1049 asc_AsidListFree (&pList);
1053 Delete (pListGroups);
1054 asc_AsidListFree (&lpp->pUserList);
1056 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1060 void Task_Group_Members_Get (LPTASKPACKET ptp)
1062 LPASIDLIST pGroups = (LPASIDLIST)( ptp->lpUser );
1064 // Prepare an intermediate place for us to put the results of our search.
1065 // We'll be doing lots of work in this intermediate list, so it'll be
1066 // implemented as a hashlist with a key over the objects' ASIDs.
1072 } GROUP_MEMBER_FOUND, *LPGROUP_MEMBER_FOUND;
1074 LPHASHLIST pListUsers = New (HASHLIST);
1075 LPHASHLISTKEY pListKeyAsid = pListUsers->CreateKey ("ASID", Key_Asid_Compare, Key_Asid_HashObject, Key_Asid_HashData);
1077 // For each group in the list, find all of that group's members
1079 for (size_t iGroup = 0; iGroup < pGroups->cEntries; ++iGroup)
1081 LPASIDLIST pMembers = NULL;
1084 if (!asc_GroupMembersGet (g.idClient, g.idCell, pGroups->aEntries[ iGroup ].idObject, &pMembers, &status))
1089 // For each member we found, make sure the member is in the big
1090 // list we'll be returning. Use the {lParam} field of the
1091 // list's entry as a counter, to remember how many groups have
1094 for (size_t iMember = 0; iMember < pMembers->cEntries; ++iMember)
1096 // Is it in the list already? If not, add it.
1098 LPGROUP_MEMBER_FOUND pFind;
1099 if ((pFind = (LPGROUP_MEMBER_FOUND)pListKeyAsid->GetFirstObject (&pMembers->aEntries[ iMember ].idObject)) != NULL)
1105 pFind = New (GROUP_MEMBER_FOUND);
1106 pFind->idUser = pMembers->aEntries[ iMember ].idObject;
1108 pListUsers->Add (pFind);
1112 asc_AsidListFree (&pMembers);
1116 // Now that we have a list of users that match our search criteria,
1117 // stick it in an ASID list. The lParam field for each ASID will be set
1118 // to 1 if all groups have that member, or 0 if only some have it.
1120 if (!asc_AsidListCreate (&TASKDATA(ptp)->pAsidList))
1123 ptp->status = ERROR_NOT_ENOUGH_MEMORY;
1128 for (LPENUM pEnum = pListUsers->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1130 LPGROUP_MEMBER_FOUND pFind = (LPGROUP_MEMBER_FOUND)( pEnum->GetObject() );
1132 asc_AsidListAddEntry (&TASKDATA(ptp)->pAsidList, pFind->idUser, (LPARAM)( (pFind->cGroups == pGroups->cEntries) ? 1 : 0 ));
1134 pListUsers->Remove (pFind);
1139 // Now that we have an ASID list full of users to return, make sure we
1140 // have rudimentary properties for all those users.
1145 asc_AsidListCopy (&pList, &TASKDATA(ptp)->pAsidList);
1147 LPASOBJPROPLIST pPropList = NULL;
1148 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, pList, &pPropList, &ptp->status))
1151 asc_ObjPropListFree (&pPropList);
1153 asc_AsidListFree (&pList);
1157 Delete (pListUsers);
1158 asc_AsidListFree (&pGroups);
1159 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1163 void Task_Group_Members_Set (LPTASKPACKET ptp)
1165 LPGROUP_MEMBERS_SET_PARAMS lpp = (LPGROUP_MEMBERS_SET_PARAMS)( ptp->lpUser );
1167 ptp->rc = Task_Group_Members_Set_Do (lpp, &ptp->status);
1169 asc_AsidListFree (&lpp->pGroups);
1170 asc_AsidListFree (&lpp->pMembers);
1172 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1176 BOOL Task_Group_Members_Set_Do (LPGROUP_MEMBERS_SET_PARAMS lpp, ULONG *pStatus)
1180 // Maintain a structure describing any errors we encounter, so we can give
1181 // a reasonable error dialog if need be.
1183 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_SET_MEMBERS, IDS_ERROR_CANT_SET_MEMBERS_MULTIPLE);
1185 // We'll need the supplied member-list in a hashlist, so we can quickly
1186 // test it to see if a particular member should remain in a group.
1188 LPHASHLIST pMembersAllow = New (HASHLIST);
1189 for (size_t iMember = 0; iMember < lpp->pMembers->cEntries; ++iMember)
1190 pMembersAllow->AddUnique ((PVOID)(lpp->pMembers->aEntries[ iMember ].idObject));
1192 // We'll have to do this next bit for each group in the supplied group-list
1194 for (size_t iGroup = 0; iGroup < lpp->pGroups->cEntries; ++iGroup)
1198 // Obtain the current list of members for this group
1200 LPASIDLIST pMembersOld = NULL;
1201 if (!asc_GroupMembersGet (g.idClient, g.idCell, lpp->pGroups->aEntries[ iGroup ].idObject, &pMembersOld, &status))
1203 ED_RegisterStatus (ped, lpp->pGroups->aEntries[ iGroup ].idObject, FALSE, status);
1209 // Test each member in that current list to see if it's also on our
1210 // pMembersAllow list. If not, remove it.
1212 for (iMember = 0; iMember < pMembersOld->cEntries; ++iMember)
1214 if (pMembersAllow->fIsInList ((PVOID)(pMembersOld->aEntries[iMember].idObject)))
1217 if (!asc_GroupMemberRemove (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, pMembersOld->aEntries[iMember].idObject, &status))
1218 ED_RegisterStatus (ped, lpp->pGroups->aEntries[ iGroup ].idObject, FALSE, status);
1221 // Now the more complex part: see if there are any members in the
1222 // supplied member-list which are marked as mandatory, but which
1223 // aren't in our pMembersOld list. We'll need to put the latter in a
1224 // hashlist for this...
1226 LPHASHLIST pMembersOldList = New (HASHLIST);
1227 for (iMember = 0; iMember < pMembersOld->cEntries; ++iMember)
1228 pMembersOldList->AddUnique ((PVOID)(pMembersOld->aEntries[ iMember ].idObject));
1230 for (iMember = 0; iMember < lpp->pMembers->cEntries; ++iMember)
1232 if (!lpp->pMembers->aEntries[ iMember ].lParam)
1233 continue; // member not mandatory
1234 if (pMembersOldList->fIsInList ((PVOID)(lpp->pMembers->aEntries[ iMember ].idObject)))
1235 continue; // already a member
1237 if (!asc_GroupMemberAdd (g.idClient, g.idCell, lpp->pGroups->aEntries[iGroup].idObject, lpp->pMembers->aEntries[iMember].idObject, &status))
1238 ED_RegisterStatus (ped, lpp->pGroups->aEntries[ iGroup ].idObject, FALSE, status);
1241 Delete (pMembersOldList);
1243 asc_AsidListFree (&pMembersOld);
1246 // If there were any errors, report them.
1248 if ((*pStatus = ED_GetFinalStatus(ped)) != 0)
1251 ED_ShowErrorDialog(ped);
1257 Delete (pMembersAllow);
1262 void Task_Group_Enum (LPTASKPACKET ptp)
1264 LPCTSTR pszPattern = (LPCTSTR)( ptp->lpUser );
1266 TCHAR szRegExp[ cchNAME ];
1267 TranslateRegExp (szRegExp, pszPattern);
1268 if ((ptp->rc = asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_GROUP, szRegExp, NULL, &TASKDATA(ptp)->pAsidList, &ptp->status)) == TRUE)
1270 LPASOBJPROPLIST pPropList = NULL;
1272 ptp->rc = asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, TASKDATA(ptp)->pAsidList, &pPropList, &ptp->status);
1275 asc_ObjPropListFree (&pPropList);
1278 FreeString (pszPattern);
1279 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1283 void Task_Group_Rename (LPTASKPACKET ptp)
1285 LPGROUP_RENAME_PARAMS lpp = (LPGROUP_RENAME_PARAMS)( ptp->lpUser );
1287 if ((ptp->rc = asc_GroupRename (g.idClient, g.idCell, lpp->idGroup, lpp->szNewName, &ptp->status)) != FALSE)
1289 Display_RefreshView_Fast();
1292 if (!ptp->rc && !IsWindow (ptp->hReply))
1294 TCHAR szOldName[ cchNAME ];
1295 asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->idGroup, szOldName);
1296 ErrorDialog (ptp->status, IDS_ERROR_CANT_RENAME_GROUP, TEXT("%s%s"), szOldName, lpp->szNewName);
1300 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1304 void Task_Group_Owned_Get (LPTASKPACKET ptp)
1306 ASID idGroup = (ASID)( ptp->lpUser );
1308 ptp->rc = asc_GroupOwnershipGet (g.idClient, g.idCell, idGroup, &TASKDATA(ptp)->pAsidList, &ptp->status);
1310 // Modify the ASID list to have lParams of 1. (This indicates that all
1311 // our supplied groups own this thing; silly but consistent with the
1312 // other such interfaces.)
1314 if (TASKDATA(ptp)->pAsidList)
1316 for (size_t ii = 0; ii < TASKDATA(ptp)->pAsidList->cEntries; ++ii)
1317 TASKDATA(ptp)->pAsidList->aEntries[ ii ].lParam = 1;
1320 // Now that we have an ASID list full of groups to return, make sure we
1321 // have rudimentary properties for all those groups.
1326 asc_AsidListCopy (&pList, &TASKDATA(ptp)->pAsidList);
1328 LPASOBJPROPLIST pPropList = NULL;
1329 if (!asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, pList, &pPropList, &ptp->status))
1332 asc_ObjPropListFree (&pPropList);
1334 asc_AsidListFree (&pList);
1339 void Task_Group_Owned_Set (LPTASKPACKET ptp)
1341 LPGROUP_OWNED_SET_PARAMS lpp = (LPGROUP_OWNED_SET_PARAMS)( ptp->lpUser );
1343 ptp->rc = Task_Group_Owned_Set_Do (lpp, &ptp->status);
1345 asc_AsidListFree (&lpp->pOwnedGroups);
1347 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1351 BOOL Task_Group_Owned_Set_Do (LPGROUP_OWNED_SET_PARAMS lpp, ULONG *pStatus)
1355 // Maintain a structure describing any errors we encounter, so we can give
1356 // a reasonable error dialog if need be.
1358 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_CHANGE_OWNER, IDS_ERROR_CANT_CHANGE_OWNER_MULTIPLE);
1360 // We'll need the supplied groups-to-own list in a hashlist, so we can
1361 // quickly test it for inclusion of a particular group.
1363 LPHASHLIST pGroupsAllow = New (HASHLIST);
1364 for (size_t iGroup = 0; iGroup < lpp->pOwnedGroups->cEntries; ++iGroup)
1365 pGroupsAllow->AddUnique ((PVOID)(lpp->pOwnedGroups->aEntries[ iGroup ].idObject));
1367 // Obtain the current list-of-groups-owned for this group
1369 LPASIDLIST pGroupsOld = NULL;
1370 if ((rc = asc_GroupOwnershipGet (g.idClient, g.idCell, lpp->idGroup, &pGroupsOld, pStatus)) == FALSE)
1375 for (size_t ii = 0; ii < lpp->pOwnedGroups->cEntries; ++ii)
1376 ED_RegisterStatus (ped, lpp->pOwnedGroups->aEntries[ii].idObject, FALSE, *pStatus);
1380 // Test each group in that current list to see if it's also on our
1381 // pGroupsAllow list. If not, remove it.
1383 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
1385 if (pGroupsAllow->fIsInList ((PVOID)(pGroupsOld->aEntries[iGroup].idObject)))
1389 ASOBJPROP Properties;
1390 if (!asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &Properties, &status))
1391 ED_RegisterStatus (ped, pGroupsOld->aEntries[iGroup].idObject, FALSE, status);
1394 AFSADMSVR_CHANGEGROUP_PARAMS pp;
1395 memset (&pp, 0x00, sizeof(pp));
1396 lstrcpy (pp.szOwner, Properties.szName); // make group self-owned
1397 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
1398 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
1399 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
1400 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
1401 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
1403 if (!asc_GroupChange (g.idClient, g.idCell, pGroupsOld->aEntries[iGroup].idObject, &pp, &status))
1404 ED_RegisterStatus (ped, pGroupsOld->aEntries[iGroup].idObject, FALSE, status);
1408 // Now the more complex part: see if there are any groups in the
1409 // supplied group-list which are marked as mandatory, but which
1410 // aren't in our pGroupsOld list. We'll need to put the latter in a
1411 // hashlist for this...
1413 LPHASHLIST pGroupsOldList = New (HASHLIST);
1414 for (iGroup = 0; iGroup < pGroupsOld->cEntries; ++iGroup)
1415 pGroupsOldList->AddUnique ((PVOID)(pGroupsOld->aEntries[ iGroup ].idObject));
1417 for (iGroup = 0; iGroup < lpp->pOwnedGroups->cEntries; ++iGroup)
1419 if (!lpp->pOwnedGroups->aEntries[ iGroup ].lParam)
1420 continue; // group not mandatory
1421 if (pGroupsOldList->fIsInList ((PVOID)(lpp->pOwnedGroups->aEntries[ iGroup ].idObject)))
1422 continue; // already a member
1425 ASOBJPROP Properties;
1426 if (!asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, lpp->pOwnedGroups->aEntries[iGroup].idObject, &Properties, &status))
1427 ED_RegisterStatus (ped, lpp->pOwnedGroups->aEntries[iGroup].idObject, FALSE, status);
1430 AFSADMSVR_CHANGEGROUP_PARAMS pp;
1431 memset (&pp, 0x00, sizeof(pp));
1432 pp.aaListStatus = Properties.u.GroupProperties.aaListStatus;
1433 pp.aaListGroupsOwned = Properties.u.GroupProperties.aaListGroupsOwned;
1434 pp.aaListMembers = Properties.u.GroupProperties.aaListMembers;
1435 pp.aaAddMember = Properties.u.GroupProperties.aaAddMember;
1436 pp.aaDeleteMember = Properties.u.GroupProperties.aaDeleteMember;
1438 if (asc_ObjectNameGet_Fast (g.idClient, g.idCell, lpp->idGroup, pp.szOwner, &status))
1440 if (!asc_GroupChange (g.idClient, g.idCell, lpp->pOwnedGroups->aEntries[iGroup].idObject, &pp, &status))
1441 ED_RegisterStatus (ped, lpp->pOwnedGroups->aEntries[iGroup].idObject, FALSE, status);
1446 Delete (pGroupsOldList);
1447 asc_AsidListFree (&pGroupsOld);
1450 // If there were any errors, report them.
1452 if ((*pStatus = ED_GetFinalStatus(ped)) != 0)
1455 ED_ShowErrorDialog(ped);
1461 Delete (pGroupsAllow);
1466 void Task_Group_Create (LPTASKPACKET ptp)
1468 LPGROUP_CREATE_PARAMS lpp = (LPGROUP_CREATE_PARAMS)(ptp->lpUser);
1470 // If no owner was specified, use our current credentials' ID. If
1471 // we can't get that, we'll make each group self-owned.
1473 if (!lpp->szOwner[0])
1475 TCHAR szCell[ cchNAME ];
1476 if (!AfsAppLib_CrackCredentials (g.hCreds, szCell, lpp->szOwner))
1477 lpp->szOwner[0] = TEXT('\0');
1480 // We may actually have been asked to create more than one group here;
1481 // the {lpp->mszNames} parameter is a multi-string. So everything we
1482 // do, we'll do for each new group-name...
1484 for (LPTSTR pszName = lpp->mszNames; pszName && *pszName; pszName += 1+lstrlen(pszName))
1486 // First create this new group account
1490 AFSADMSVR_CREATEGROUP_PARAMS pp;
1491 memset (&pp, 0x00, sizeof(AFSADMSVR_CREATEGROUP_PARAMS));
1492 pp.idGroup = lpp->idGroup;
1493 lstrcpy (pp.szName, pszName);
1494 lstrcpy (pp.szOwner, lpp->szOwner);
1496 lstrcpy (pp.szOwner, pszName);
1498 if ((ptp->rc = asc_GroupCreate (g.idClient, g.idCell, &pp, &idGroup, &ptp->status)) == FALSE)
1500 if (!IsWindow (ptp->hReply))
1501 ErrorDialog (ptp->status, IDS_ERROR_CANT_CREATE_GROUP, TEXT("%s"), pszName);
1505 // Then change its properties to be what we want
1507 if ((ptp->rc = asc_GroupChange (g.idClient, g.idCell, idGroup, &lpp->Properties, &ptp->status)) == FALSE)
1509 if (!IsWindow (ptp->hReply))
1510 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_GROUP, TEXT("%s"), pszName);
1515 // Finally update its lists of groups
1519 GROUP_MEMBERS_SET_PARAMS pp;
1520 memset (&pp, 0x00, sizeof(GROUP_MEMBERS_SET_PARAMS));
1521 asc_AsidListCreate (&pp.pGroups);
1522 asc_AsidListAddEntry (&pp.pGroups, idGroup, 0);
1523 asc_AsidListCopy (&pp.pMembers, &lpp->pMembers);
1524 ptp->rc = Task_Group_Members_Set_Do (&pp, &ptp->status);
1525 asc_AsidListFree (&pp.pGroups);
1526 asc_AsidListFree (&pp.pMembers);
1528 if (lpp->pGroupsOwner)
1530 GROUP_OWNED_SET_PARAMS pp;
1531 memset (&pp, 0x00, sizeof(GROUP_OWNED_SET_PARAMS));
1532 pp.idGroup = idGroup;
1533 asc_AsidListCopy (&pp.pOwnedGroups, &lpp->pGroupsOwner);
1534 ptp->rc = Task_Group_Owned_Set_Do (&pp, &ptp->status);
1535 asc_AsidListFree (&pp.pOwnedGroups);
1541 Display_PopulateList();
1543 if (lpp->pGroupsOwner)
1544 asc_AsidListFree (&lpp->pGroupsOwner);
1546 asc_AsidListFree (&lpp->pMembers);
1548 FreeString (lpp->mszNames);
1550 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1554 void Task_Group_Delete (LPTASKPACKET ptp)
1556 LPASIDLIST pGroupList = (LPASIDLIST)(ptp->lpUser);
1558 // Maintain a structure describing any errors we encounter, so we can give
1559 // a reasonable error dialog if need be.
1561 LPERRORDATA ped = ED_Create (IDS_ERROR_CANT_DELETE_GROUP, IDS_ERROR_CANT_DELETE_GROUP_MULTIPLE);
1563 // Go through and delete these users
1565 for (size_t iGroup = 0; iGroup < pGroupList->cEntries; ++iGroup)
1568 if (!asc_GroupDelete (g.idClient, g.idCell, pGroupList->aEntries[iGroup].idObject, &status))
1569 ED_RegisterStatus (ped, pGroupList->aEntries[iGroup].idObject, FALSE, status);
1572 // If there were any errors, report them.
1574 if (ED_GetFinalStatus(ped) && !IsWindow(ptp->hReply))
1575 ED_ShowErrorDialog(ped);
1580 Display_PopulateList();
1583 asc_AsidListFree (&pGroupList);
1584 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1588 void Task_Cell_Change (LPTASKPACKET ptp)
1590 LPCELL_CHANGE_PARAMS lpp = (LPCELL_CHANGE_PARAMS)(ptp->lpUser);
1592 AFSADMSVR_CHANGECELL_PARAMS Change;
1593 memset (&Change, 0x00, sizeof(Change));
1594 Change.idUserMax = (DWORD)(lpp->idUserMax);
1595 Change.idGroupMax = (DWORD)(lpp->idGroupMax);
1596 ptp->rc = asc_CellChange (g.idClient, lpp->idCell, &Change, &ptp->status);
1598 if (!ptp->rc && !IsWindow (ptp->hReply))
1600 TCHAR szCell[ cchNAME ];
1601 asc_CellNameGet_Fast (g.idClient, lpp->idCell, szCell);
1602 ErrorDialog (ptp->status, IDS_ERROR_CANT_CHANGE_CELL, TEXT("%s"), szCell);
1606 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1610 void Task_List_Translate (LPTASKPACKET ptp)
1612 LPLIST_TRANSLATE_PARAMS lpp = (LPLIST_TRANSLATE_PARAMS)( ptp->lpUser );
1613 TASKDATA(ptp)->Type = lpp->Type;
1615 // We'll need a hashlist into which to dump our results as we build
1616 // them (we use a hashlist so we can quickly detect and ignore duplicates).
1618 LPHASHLIST pList = New (HASHLIST);
1620 // Now split the input string up into a series of names. To do that,
1621 // we'll valid separator characters are; since names can't have whitespace,
1622 // we'll include that.
1624 TCHAR szSeparators[ cchRESOURCE ];
1625 if (!GetLocaleInfo (LOCALE_USER_DEFAULT, LOCALE_SLIST, szSeparators, cchRESOURCE))
1626 szSeparators[0] = TEXT(',');
1627 GetString (&szSeparators[1], IDS_SEPARATORS);
1631 LPCTSTR pszStart = lpp->pszNames;
1632 while (iswhite(*pszStart) || lstrchr (szSeparators, *pszStart))
1637 // Find the first non-name character
1639 LPCTSTR pszEnd = pszStart;
1640 while (*pszEnd && !iswhite(*pszEnd) && !lstrchr(szSeparators, *pszEnd))
1643 // Copy off this particular name
1645 TCHAR szName[ cchNAME ];
1646 lstrcpy (szName, pszStart);
1647 szName[ pszEnd - pszStart ] = TEXT('\0');
1649 // Find the next valid-name character
1652 while (iswhite(*pszStart) || lstrchr(szSeparators, *pszStart))
1655 // Translate this particular name. We'll also handle wildcards
1656 // here: if we don't get any wildcard characters, treat it as
1657 // a direct lookup; if we do, treat it as a regexp match.
1659 if (lstrchr (szName, TEXT('*')) || lstrchr (szName, TEXT('?')) ||
1660 lstrchr (szName, TEXT('^')) || lstrchr (szName, TEXT('!')))
1662 TCHAR szRegExp[ cchNAME ];
1663 TranslateRegExp (szRegExp, szName);
1665 LPASIDLIST pAsidList;
1666 if (asc_ObjectFindMultiple (g.idClient, g.idCell, lpp->Type, szRegExp, NULL, &pAsidList, &ptp->status))
1670 for (size_t ii = 0; ii < pAsidList->cEntries; ++ii)
1671 pList->AddUnique ((PVOID)(pAsidList->aEntries[ii].idObject));
1672 asc_AsidListFree (&pAsidList);
1676 else // No wildcards; just look up the name directly
1679 if (asc_ObjectFind (g.idClient, g.idCell, lpp->Type, szName, &idObject, &ptp->status))
1680 pList->AddUnique ((PVOID)idObject);
1685 // Finally, build an ASIDLIST from our hashlist's contents.
1687 if (!asc_AsidListCreate (&TASKDATA(ptp)->pAsidList))
1690 ptp->status = ERROR_NOT_ENOUGH_MEMORY;
1694 for (LPENUM pEnum = pList->FindFirst(); pEnum; pEnum = pEnum->FindNext())
1696 ASID idObject = (ASID)(pEnum->GetObject());
1697 asc_AsidListAddEntry (&TASKDATA(ptp)->pAsidList, idObject, 0);
1704 FreeString (lpp->pszNames);
1706 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1710 void Task_Object_Listen (LPTASKPACKET ptp)
1712 LPOBJECT_LISTEN_PARAMS lpp = (LPOBJECT_LISTEN_PARAMS)( ptp->lpUser );
1714 if (IsWindow(lpp->hNotify) && (lpp->pAsidList))
1715 ptp->rc = asc_ObjectListenMultiple (g.idClient, g.idCell, lpp->pAsidList, lpp->hNotify, &ptp->status);
1717 ptp->rc = asc_ObjectListenClear (g.idClient, lpp->hNotify, &ptp->status);
1720 asc_AsidListFree (&lpp->pAsidList);
1722 ptp->lpUser = 0; // we freed this; don't let the caller use it again
1726 void Task_Object_Get (LPTASKPACKET ptp)
1728 ASID idObject = (ASID)(ptp->lpUser);
1729 ptp->rc = asc_ObjectPropertiesGet (g.idClient, GET_ALL_DATA, g.idCell, idObject, &TASKDATA(ptp)->Properties, &ptp->status);
1733 void Task_Set_Refresh (LPTASKPACKET ptp)
1737 ptp->rc = asc_CellRefreshRateSet (g.idClient, g.idCell, gr.cminRefreshRate, &ptp->status);
1742 void Task_Expired_Creds (LPTASKPACKET ptp)
1746 CheckForExpiredCredentials();
1751 void WeedAsidList (LPASIDLIST *ppList, BOOL fWantMachines)
1755 // First off, we can't do anything unless we have these guys' names.
1757 if (ppList && (*ppList) && (*ppList)->cEntries)
1759 LPASOBJPROPLIST pPropList = NULL;
1760 asc_ObjectPropertiesGetMultiple (g.idClient, GET_RUDIMENTARY_DATA, g.idCell, *ppList, &pPropList, &status);
1762 asc_ObjPropListFree (&pPropList);
1765 for (size_t ii = 0; ppList && (*ppList) && (ii < (*ppList)->cEntries); )
1767 TCHAR szName[ cchRESOURCE ];
1768 if (!asc_ObjectNameGet_Fast (g.idClient, g.idCell, (*ppList)->aEntries[ ii ].idObject, szName, &status))
1774 if (fIsMachineAccount(szName) == fWantMachines)
1777 asc_AsidListRemoveEntryByIndex (ppList, ii);
1782 void TranslateRegExp (LPTSTR pszTarget, LPCTSTR pszSource)
1786 if (!gr.fWindowsRegexp)
1788 lstrcpy (pszTarget, pszSource);
1792 for ( ; *pszSource; pszSource++)
1799 *pszTarget++ = TEXT('\\');
1800 *pszTarget++ = *pszSource;
1804 *pszTarget++ = TEXT('.');
1808 *pszTarget++ = TEXT('.');
1809 *pszTarget++ = TEXT('*');
1813 *pszTarget++ = *pszSource;
1820 *pszTarget++ = TEXT('\0');
1824 BOOL PerformRefresh (LPTASKPACKET ptp, ASID idScope, ULONG *pStatus)
1826 // Invalidate the admin server's cached information about the specified
1827 // object. Remember that this is recursive hierarchically: if you pass
1828 // in a cell's ID, for instance, information about all users, groups,
1829 // servers, services, partitions and volumes anywhere in that cell will
1835 if (!asc_ObjectRefresh (g.idClient, g.idCell, idScope, pStatus))
1838 // The Refresh call above is a misnomer; it's really an Invalidate request,
1839 // in that it only causes the admin server to dump its cached information
1840 // over the specified scope. At this point we need to do something to
1841 // trigger the server to re-query that information, so that it will send
1842 // an ACTION_REFRESH notification (indicating it's doing that requery),
1843 // which we'll pick up on and use as a trigger to refresh our display.
1844 // A convenient way to get the server to do that re-query is to ask it
1845 // to perform some simple search among the users in the cell--we'll ask
1846 // it to find, oh, say, "JoeBobUser", and in order to do that, it will
1847 // have to re-fill its cache.
1849 LPASIDLIST pListDummy;
1851 (void)asc_ObjectFindMultiple (g.idClient, g.idCell, TYPE_USER, TEXT("JoeBobUser"), NULL, &pListDummy, &statusDummy);
1852 if (pListDummy != NULL)
1853 asc_AsidListFree (&pListDummy);