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 <WINNT/afsapplib.h>
16 #include "al_dynlink.h"
17 #include <WINNT/TaAfsAdmSvrClient.h>
21 * DEFINITIONS ________________________________________________________________
25 #define cxICON 19 // size of an ACL entry icon
27 #define cyICON 16 // size of an ACL entry icon
29 #define clrTRANSPARENT RGB(0,255,0) // background color on ACL entry icons
33 * BROWSE DIALOG ______________________________________________________________
37 typedef struct BROWSEDIALOGPARAMS {
38 TCHAR szCell[ cchRESOURCE ];
39 TCHAR szNamed[ cchRESOURCE ];
43 BROWSETYPE bt; // for what entry type do we browse?
47 BOOL fCanStopThreadEasily;
48 BOOL fShouldStopThread;
50 TCHAR szThreadCell[ cchRESOURCE ];
58 } BROWSEDIALOGPARAMS, *LPBROWSEDIALOGPARAMS;
61 BOOL CALLBACK DlgProc_Browse (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
62 void DlgProc_Browse_OnInitDialog (HWND hDlg, BROWSEDIALOGPARAMS *pbdp);
63 void DlgProc_Browse_OnNone (HWND hDlg, BROWSEDIALOGPARAMS *pbdp);
64 void DlgProc_Browse_SelectedEntry (HWND hDlg, BROWSEDIALOGPARAMS *pbdp);
65 void DlgProc_Browse_UpdateCellText (BROWSEDIALOGPARAMS *pbdp, LPTSTR pszCell);
67 BOOL DlgProc_Browse_StartSearch (BROWSEDIALOGPARAMS *pbdp, BOOL fCloseDlgIfFail);
68 void DlgProc_Browse_StopSearch (BROWSEDIALOGPARAMS *pbdp);
69 DWORD _stdcall DlgProc_Browse_ThreadProc (LPARAM lp);
71 void EnumeratePrincipalsRemotely (LPBROWSEDIALOGPARAMS pbdp, DWORD idClient);
72 void EnumeratePrincipalsLocally (LPBROWSEDIALOGPARAMS pbdp);
78 * This function presents a dialog which allows the user to select a user
79 * or group from a list.
83 BOOL AfsAppLib_ShowBrowseDialog (LPBROWSEDLG_PARAMS lpp)
85 BROWSEDIALOGPARAMS *pbdp;
88 if ((pbdp = New (BROWSEDIALOGPARAMS)) != NULL)
90 memset (pbdp, 0x00, sizeof(BROWSEDIALOGPARAMS));
91 lstrcpy (pbdp->szNamed, lpp->szNamed);
92 lstrcpy (pbdp->szCell, lpp->szCell);
93 pbdp->lpcl = lpp->lpcl;
95 pbdp->idsTitle = lpp->idsTitle;
96 pbdp->idsPrompt = lpp->idsPrompt;
97 pbdp->idsNone = lpp->idsNone;
98 pbdp->hCreds = lpp->hCreds;
104 pbdp->fThisCellOnly = TRUE;
109 pbdp->fThisCellOnly = FALSE;
113 if (ModalDialogParam (IDD_APPLIB_BROWSE, lpp->hParent, (DLGPROC)DlgProc_Browse, (LPARAM)pbdp) == IDOK)
115 lstrcpy (lpp->szCell, pbdp->szCell);
116 lstrcpy (lpp->szNamed, pbdp->szNamed);
130 * This is the dialog proc for the Browse Cell dialog.
134 #define WM_FOUNDNAME (WM_USER +100)
135 #define WM_THREADSTART (WM_USER +101)
136 #define WM_THREADDONE (WM_USER +102)
138 BOOL CALLBACK DlgProc_Browse (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
140 BROWSEDIALOGPARAMS *pbdp;
142 if (AfsAppLib_HandleHelp (IDD_APPLIB_BROWSE, hDlg, msg, wp, lp))
147 if (msg == WM_INITDIALOG)
149 SetWindowLong (hDlg, DWL_USER, lp);
152 if ((pbdp = (BROWSEDIALOGPARAMS *)GetWindowLong (hDlg, DWL_USER)) != NULL)
157 DlgProc_Browse_OnInitDialog (hDlg, pbdp);
161 switch (((LPNMHDR)lp)->code)
163 case LVN_ITEMCHANGED:
164 if ( ((LPNM_LISTVIEW)lp)->uNewState & LVIS_SELECTED )
166 DlgProc_Browse_SelectedEntry (hDlg, pbdp);
171 PostMessage (hDlg, WM_COMMAND, MAKELONG(IDC_BROWSE_SELECT,BN_CLICKED), (LPARAM)GetDlgItem(hDlg,IDC_BROWSE_SELECT));
177 DlgProc_Browse_StopSearch (pbdp);
179 if (pbdp->hImages != NULL)
181 ListView_SetImageList (GetDlgItem (hDlg, IDC_BROWSE_LIST), 0, 0);
182 ImageList_Destroy (pbdp->hImages);
188 LPTSTR pszName = (LPTSTR)lp;
191 HWND hList = GetDlgItem (hDlg, IDC_BROWSE_LIST);
192 LV_AddItem (hList, 1, INDEX_SORT, 0, 0, pszName);
193 FreeString (pszName);
200 TCHAR szText[ cchRESOURCE ];
201 GetString (szText, IDS_BROWSE_WAITING);
202 SetDlgItemText (pbdp->hDlg, IDC_BROWSE_STATUS, szText);
208 SetDlgItemText (pbdp->hDlg, IDC_BROWSE_STATUS, TEXT(""));
216 EndDialog (hDlg, LOWORD(wp));
219 case IDC_BROWSE_SELECT:
220 if ( (GetDlgItem (pbdp->hDlg, IDC_BROWSE_NONE) != NULL) &&
221 (IsDlgButtonChecked (pbdp->hDlg, IDC_BROWSE_NONE)) )
223 pbdp->szCell[0] = TEXT('\0');
224 pbdp->szNamed[0] = TEXT('\0');
228 GetDlgItemText (hDlg, IDC_BROWSE_CELL, pbdp->szCell, cchNAME);
229 GetDlgItemText (hDlg, IDC_BROWSE_NAMED, pbdp->szNamed, cchRESOURCE);
231 EndDialog (hDlg, IDOK);
234 case IDC_BROWSE_CELL:
235 if (HIWORD(wp) == CBN_SELCHANGE)
237 GetDlgItemText (hDlg, IDC_BROWSE_CELL, pbdp->szCell, cchNAME);
238 DlgProc_Browse_StartSearch (pbdp, FALSE);
242 case IDC_BROWSE_RESTART:
243 GetDlgItemText (hDlg, IDC_BROWSE_CELL, pbdp->szCell, cchNAME);
244 DlgProc_Browse_StartSearch (pbdp, FALSE);
245 PostMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem (hDlg, IDC_BROWSE_NAMED), (LPARAM)TRUE);
248 case IDC_BROWSE_NAMED:
249 if (HIWORD(wp) == EN_UPDATE) // has the user hit Enter here?
251 TCHAR szTest[ cchRESOURCE ];
253 GetDlgItemText (hDlg, IDC_BROWSE_NAMED, szTest, cchRESOURCE);
255 if ( (lstrlen (szTest) > 0) &&
256 (szTest[ lstrlen(szTest)-1 ] == TEXT('\n')) )
258 szTest[ lstrlen(szTest)-1 ] = TEXT('\0');
260 if ( (lstrlen (szTest) > 0) &&
261 (szTest[ lstrlen(szTest)-1 ] == TEXT('\r')) )
263 szTest[ lstrlen(szTest)-1 ] = TEXT('\0');
266 SetDlgItemText (hDlg, IDC_BROWSE_NAMED, szTest);
267 PostMessage (hDlg, WM_COMMAND, MAKELONG(IDC_BROWSE_SELECT,BN_CLICKED), (LPARAM)GetDlgItem(hDlg,IDC_BROWSE_SELECT));
272 case IDC_BROWSE_NONE:
273 DlgProc_Browse_OnNone (hDlg, pbdp);
285 *** DlgProc_Browse_OnInitDialog
287 * The WM_INITDIALOG handler for the Browse dialog. This routine fills
288 * in the dialog with any starting parameters, and kicks off a new
289 * searching thread for the given cell.
293 void DlgProc_Browse_OnInitDialog (HWND hDlg, BROWSEDIALOGPARAMS *pbdp)
295 TCHAR szText[ cchRESOURCE ];
300 // We'll need an imagelist, if we want icons in the listview.
301 // This looks difficult but it's not--tis just a matter of selecting
302 // an appropriate bitmap.
304 if ((pbdp->hImages = ImageList_Create (cxICON, cyICON, ILC_COLOR4 | ILC_MASK, 1, 1)) != 0)
308 if (pbdp->bt == btLOCAL_USER)
310 bmp = LoadBitmap (APPLIB_HINST, MAKEINTRESOURCE( IDB_LOCAL_USER ));
312 else if (pbdp->bt == btANY_USER)
314 bmp = LoadBitmap (APPLIB_HINST, MAKEINTRESOURCE( IDB_FOREIGN_USER ));
316 else if (pbdp->bt == btLOCAL_GROUP)
318 bmp = LoadBitmap (APPLIB_HINST, MAKEINTRESOURCE( IDB_LOCAL_GROUP ));
320 else if (pbdp->bt == btANY_GROUP)
322 bmp = LoadBitmap (APPLIB_HINST, MAKEINTRESOURCE( IDB_FOREIGN_GROUP ));
327 ImageList_AddMasked (pbdp->hImages, bmp, clrTRANSPARENT);
331 ListView_SetImageList (GetDlgItem (hDlg, IDC_BROWSE_LIST), pbdp->hImages, LVSIL_SMALL);
334 // There's a default pushbutton on this dialog, so that hitting
335 // RETURN when you're in the Cell combobox will restart the search
336 // (a default pushbutton always gets called when RETURN is hit,
337 // unless your control traps it). But the user doesn't want to *see*
338 // that thing, so move it way off the dialog's client area.
341 GetWindowRect (GetDlgItem (hDlg, IDC_BROWSE_RESTART), &r);
342 SetWindowPos (GetDlgItem (hDlg, IDC_BROWSE_RESTART), NULL,
343 0 - (r.right-r.left), 0 - (r.bottom-r.top), 0, 0,
344 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
346 // Fill in the choices underneath IDC_BROWSE_CELL. Can the
347 // user enter a new cell name?
349 if (pbdp->fThisCellOnly)
351 EnableWindow (GetDlgItem (hDlg, IDC_BROWSE_CELL), FALSE);
355 CB_StartChange (GetDlgItem (hDlg, IDC_BROWSE_CELL));
359 TCHAR szDefCell[ cchNAME ];
360 if (AfsAppLib_GetLocalCell (szDefCell) && *szDefCell)
362 CB_AddItem (GetDlgItem (hDlg, IDC_BROWSE_CELL), szDefCell, 1);
365 else for (size_t ii = 0; ii < pbdp->lpcl->nCells; ++ii)
367 CB_AddItem (GetDlgItem (hDlg, IDC_BROWSE_CELL), pbdp->lpcl->aCells[ii], 1+ii);
370 CB_EndChange (GetDlgItem (hDlg, IDC_BROWSE_CELL), 1);
373 // Select various texts to display in the dialog
375 psz = FormatString (TEXT("%1"), TEXT("%m"), pbdp->idsTitle);
376 SetWindowText (hDlg, psz);
378 GetString (szText, pbdp->idsPrompt);
379 SetDlgItemText (hDlg, IDC_BROWSE_TYPE, szText);
381 // If the caller wants us to display a "[X] No Group" checkbox, do so
382 // by creating a checkbox right underneath the IDC_BROWSE_NAMED edit
383 // control--note that we'll have to hide IDC_BROWSE_STATUS if that's
386 if (pbdp->idsNone != 0)
388 ShowWindow (GetDlgItem (pbdp->hDlg, IDC_BROWSE_STATUS), FALSE);
391 GetRectInParent (GetDlgItem (pbdp->hDlg, IDC_BROWSE_NAMED), &rr);
394 cy = rr.bottom -rr.top;
396 rr.bottom = rr.top +cy;
398 GetString (szText, pbdp->idsNone);
399 CreateWindow ("Button", szText, WS_CHILD | BS_AUTOCHECKBOX,
400 rr.left, rr.top, rr.right-rr.left, rr.bottom-rr.top,
401 pbdp->hDlg, (HMENU)IDC_BROWSE_NONE, APPLIB_HINST, 0);
403 HFONT hf = (HFONT)GetStockObject (DEFAULT_GUI_FONT);
404 SendMessage (GetDlgItem (pbdp->hDlg, IDC_BROWSE_NONE), WM_SETFONT, (WPARAM)hf, FALSE);
405 ShowWindow (GetDlgItem (pbdp->hDlg, IDC_BROWSE_NONE), TRUE);
407 if (pbdp->szNamed[0] == TEXT('\0'))
408 CheckDlgButton (pbdp->hDlg, IDC_BROWSE_NONE, TRUE);
410 CheckDlgButton (pbdp->hDlg, IDC_BROWSE_NONE, FALSE);
412 DlgProc_Browse_OnNone (pbdp->hDlg, pbdp);
415 SetDlgItemText (hDlg, IDC_BROWSE_CELL, pbdp->szCell);
416 SetDlgItemText (hDlg, IDC_BROWSE_NAMED, pbdp->szNamed);
418 // Start looking for users/groups
420 DlgProc_Browse_StartSearch (pbdp, TRUE);
425 *** DlgProc_Browse_OnNone
427 * This routine is called whenever the user checks or unchecks the
428 * "[X] None" checkbox (which we may not even be displaying)
432 void DlgProc_Browse_OnNone (HWND hDlg, BROWSEDIALOGPARAMS *pbdp)
434 if (GetDlgItem (pbdp->hDlg, IDC_BROWSE_NONE) != NULL)
436 BOOL fNone = IsDlgButtonChecked (pbdp->hDlg, IDC_BROWSE_NONE);
438 EnableWindow (GetDlgItem (hDlg, IDC_BROWSE_CELL), !fNone && !pbdp->fThisCellOnly);
439 EnableWindow (GetDlgItem (hDlg, IDC_BROWSE_NAMED), !fNone);
440 EnableWindow (GetDlgItem (hDlg, IDC_BROWSE_LIST), !fNone);
442 DlgProc_Browse_SelectedEntry (hDlg, pbdp);
448 *** DlgProc_Browse_SelectedEntry
450 * This routine is called whenever the user selects a new entry within
451 * the Browse dialog's listview
455 void DlgProc_Browse_SelectedEntry (HWND hDlg, BROWSEDIALOGPARAMS *pbdp)
457 if ( (GetDlgItem (pbdp->hDlg, IDC_BROWSE_NONE) != NULL) &&
458 (IsDlgButtonChecked (pbdp->hDlg, IDC_BROWSE_NONE)) )
460 pbdp->szNamed[0] = TEXT('\0');
464 HWND hList = GetDlgItem (hDlg, IDC_BROWSE_LIST);
465 short idxSelected = LV_GetSelected (hList);
467 if (idxSelected == -1)
468 pbdp->szNamed[0] = TEXT('\0');
470 LV_GetItemText (hList, idxSelected, 0, pbdp->szNamed);
472 SetDlgItemText (hDlg, IDC_BROWSE_NAMED, pbdp->szNamed);
478 *** DlgProc_Browse_UpdateCellText
480 * This routine places the given cell name in the browse dialog.
484 void DlgProc_Browse_UpdateCellText (BROWSEDIALOGPARAMS *pbdp, LPTSTR pszCell)
486 SetDlgItemText (pbdp->hDlg, IDC_BROWSE_CELL, pbdp->szCell);
491 *** DlgProc_Browse_StartSearch
493 * This routine initiates a thread which enumerates all users/groups within
494 * the given cell, posting messages to describe what it finds to the Browse
499 BOOL DlgProc_Browse_StartSearch (BROWSEDIALOGPARAMS *pbdp, BOOL fCloseDlgIfFail)
503 // Can't start a new search until the old search terminates.
505 DlgProc_Browse_StopSearch (pbdp);
507 // Then make sure that we have a valid cell to query--if not, it may
508 // be grounds to terminate the entire browse dialog.
510 lstrcpy (pbdp->szThreadCell, pbdp->szCell);
512 if (!pbdp->szCell[0])
514 AfsAppLib_GetLocalCell (pbdp->szCell);
516 lstrcpy (pbdp->szThreadCell, pbdp->szCell);
518 DlgProc_Browse_UpdateCellText (pbdp, pbdp->szThreadCell);
521 if (!pbdp->szCell[0])
524 EndDialog (pbdp->hDlg, IDCANCEL);
526 MessageBeep (MB_ICONHAND);
527 Message (MB_ICONHAND, IDS_BROWSE_BADCELL_TITLE, IDS_BROWSE_BADCELL_DESC);
529 if (!fCloseDlgIfFail)
530 PostMessage (pbdp->hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem (pbdp->hDlg, IDC_BROWSE_CELL), (LPARAM)TRUE);
534 // Great--we can do the search. Start a thread to do so.
536 pbdp->fCanStopThreadEasily = FALSE;
537 pbdp->fShouldStopThread = FALSE;
538 pbdp->fThreadActive = FALSE;
540 ListView_DeleteAllItems (GetDlgItem (pbdp->hDlg, IDC_BROWSE_LIST));
542 pbdp->hThread = CreateThread (NULL, 0,
543 (LPTHREAD_START_ROUTINE)DlgProc_Browse_ThreadProc,
544 pbdp, 0, &dwThreadID);
546 return (pbdp->hThread == 0) ? FALSE : TRUE;
551 *** DlgProc_Browse_StopSearch
553 * This routine signals the search thread to stop, and will not return
558 void DlgProc_Browse_StopSearch (BROWSEDIALOGPARAMS *pbdp)
560 if (pbdp->fThreadActive)
562 if (pbdp->fCanStopThreadEasily)
564 pbdp->fShouldStopThread = TRUE;
566 WaitForSingleObject (pbdp->hThread, INFINITE);
570 TerminateThread (pbdp->hThread, 0);
571 pbdp->fThreadActive = FALSE;
575 SetDlgItemText (pbdp->hDlg, IDC_BROWSE_STATUS, TEXT(""));
580 *** DlgProc_Browse_ThreadProc
582 * The worker thread for the Browse dialog; this routine enumerates all
583 * users or groups on the given cell, posting a WM_FOUNDNAME message to
584 * the Browse dialog after every successful find. Note that LPARAM on
585 * such messages points to a string which should be freed with FreeString()
586 * when no longer needed.
590 DWORD _stdcall DlgProc_Browse_ThreadProc (LPARAM lp)
592 BROWSEDIALOGPARAMS *pbdp;
594 if ((pbdp = (BROWSEDIALOGPARAMS *)lp) != NULL)
596 pbdp->fThreadActive = TRUE;
598 PostMessage (pbdp->hDlg, WM_THREADSTART, 0, 0);
601 if ((idClient = AfsAppLib_GetAdminServerClientID()) != 0)
603 EnumeratePrincipalsRemotely (pbdp, idClient);
607 if (OpenClientLibrary())
609 if (OpenKasLibrary())
611 EnumeratePrincipalsLocally (pbdp);
615 CloseClientLibrary();
619 pbdp->fThreadActive = FALSE;
621 PostMessage (pbdp->hDlg, WM_THREADDONE, 0, 0);
628 void EnumeratePrincipalsLocally (LPBROWSEDIALOGPARAMS pbdp)
632 char szCellA[ MAX_PATH ];
633 CopyStringToAnsi (szCellA, pbdp->szCell);
636 if (afsclient_CellOpen (szCellA, pbdp->hCreds, &hCell, (afs_status_p)&status))
638 // Enumerate the principals recognized by KAS.
641 if (kas_PrincipalGetBegin (hCell, NULL, &hEnum, (afs_status_p)&status))
643 pbdp->fCanStopThreadEasily = TRUE;
645 while (!pbdp->fShouldStopThread)
648 if (!kas_PrincipalGetNext (hEnum, &who, (afs_status_p)&status))
652 if ((pszName = CloneAnsi ((LPSTR)who.principal)) == NULL)
655 PostMessage (pbdp->hDlg, WM_FOUNDNAME, 0, (LPARAM)pszName);
656 // pszName freed by DlgProc_Browse when it receives the message
659 kas_PrincipalGetDone (hEnum, (afs_status_p)&status);
662 afsclient_CellClose (hCell, (afs_status_p)&status);
667 void EnumeratePrincipalsRemotely (LPBROWSEDIALOGPARAMS pbdp, DWORD idClient)
671 // Open the relevant cell
674 if (asc_CellOpen (idClient, pbdp->hCreds, pbdp->szThreadCell, AFSADMSVR_SCOPE_USERS, &idCell, &status))
676 // Obtain a list of ASIDs from the admin server, each representing
677 // a principal which we want to show.
679 LPASIDLIST pAsidList;
680 if (asc_ObjectFindMultiple (idClient, idCell, TYPE_USER, NULL, NULL, &pAsidList, &status))
684 // Obtain rudimentary properties (e.g., their names) for these ASIDs
686 LPASOBJPROPLIST pPropList;
687 if (asc_ObjectPropertiesGetMultiple (idClient, GET_RUDIMENTARY_DATA, idCell, pAsidList, &pPropList, &status))
691 // Use the information in {pPropList} to populate the display
693 for (size_t iEntry = 0; iEntry < pPropList->cEntries; ++iEntry)
696 if ((pszName = CloneString (pPropList->aEntries[ iEntry ].ObjectProperties.szName)) != NULL)
698 PostMessage (pbdp->hDlg, WM_FOUNDNAME, 0, (LPARAM)pszName);
699 // pszName freed by DlgProc_Browse when it receives the message
703 asc_ObjPropListFree (&pPropList);
707 asc_AsidListFree (&pAsidList);
711 asc_CellClose (idClient, idCell, &status);