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
14 #include <afs/param.h>
18 #include <WINNT/afsapplib.h>
19 #include "al_dynlink.h"
20 #include <WINNT/TaAfsAdmSvrClient.h>
24 * DEFINITIONS ________________________________________________________________
28 #define cxICON 19 // size of an ACL entry icon
30 #define cyICON 16 // size of an ACL entry icon
32 #define clrTRANSPARENT RGB(0,255,0) // background color on ACL entry icons
36 * BROWSE DIALOG ______________________________________________________________
40 typedef struct BROWSEDIALOGPARAMS
{
41 TCHAR szCell
[ cchRESOURCE
];
42 TCHAR szNamed
[ cchRESOURCE
];
46 BROWSETYPE bt
; // for what entry type do we browse?
50 BOOL fCanStopThreadEasily
;
51 BOOL fShouldStopThread
;
53 TCHAR szThreadCell
[ cchRESOURCE
];
61 } BROWSEDIALOGPARAMS
, *LPBROWSEDIALOGPARAMS
;
64 HRESULT CALLBACK
DlgProc_Browse (HWND hDlg
, UINT msg
, WPARAM wp
, LPARAM lp
);
65 void DlgProc_Browse_OnInitDialog (HWND hDlg
, BROWSEDIALOGPARAMS
*pbdp
);
66 void DlgProc_Browse_OnNone (HWND hDlg
, BROWSEDIALOGPARAMS
*pbdp
);
67 void DlgProc_Browse_SelectedEntry (HWND hDlg
, BROWSEDIALOGPARAMS
*pbdp
);
68 void DlgProc_Browse_UpdateCellText (BROWSEDIALOGPARAMS
*pbdp
, LPTSTR pszCell
);
70 BOOL
DlgProc_Browse_StartSearch (BROWSEDIALOGPARAMS
*pbdp
, BOOL fCloseDlgIfFail
);
71 void DlgProc_Browse_StopSearch (BROWSEDIALOGPARAMS
*pbdp
);
72 DWORD _stdcall
DlgProc_Browse_ThreadProc (LPARAM lp
);
74 void EnumeratePrincipalsRemotely (LPBROWSEDIALOGPARAMS pbdp
, UINT_PTR idClient
);
75 void EnumeratePrincipalsLocally (LPBROWSEDIALOGPARAMS pbdp
);
81 * This function presents a dialog which allows the user to select a user
82 * or group from a list.
86 BOOL
AfsAppLib_ShowBrowseDialog (LPBROWSEDLG_PARAMS lpp
)
88 BROWSEDIALOGPARAMS
*pbdp
;
91 if ((pbdp
= New (BROWSEDIALOGPARAMS
)) != NULL
)
93 memset (pbdp
, 0x00, sizeof(BROWSEDIALOGPARAMS
));
94 lstrcpy (pbdp
->szNamed
, lpp
->szNamed
);
95 lstrcpy (pbdp
->szCell
, lpp
->szCell
);
96 pbdp
->lpcl
= lpp
->lpcl
;
98 pbdp
->idsTitle
= lpp
->idsTitle
;
99 pbdp
->idsPrompt
= lpp
->idsPrompt
;
100 pbdp
->idsNone
= lpp
->idsNone
;
101 pbdp
->hCreds
= lpp
->hCreds
;
107 pbdp
->fThisCellOnly
= TRUE
;
112 pbdp
->fThisCellOnly
= FALSE
;
116 if (ModalDialogParam (IDD_APPLIB_BROWSE
, lpp
->hParent
, (DLGPROC
)DlgProc_Browse
, (LPARAM
)pbdp
) == IDOK
)
118 lstrcpy (lpp
->szCell
, pbdp
->szCell
);
119 lstrcpy (lpp
->szNamed
, pbdp
->szNamed
);
133 * This is the dialog proc for the Browse Cell dialog.
137 #define WM_FOUNDNAME (WM_USER +100)
138 #define WM_THREADSTART (WM_USER +101)
139 #define WM_THREADDONE (WM_USER +102)
141 HRESULT CALLBACK
DlgProc_Browse (HWND hDlg
, UINT msg
, WPARAM wp
, LPARAM lp
)
143 BROWSEDIALOGPARAMS
*pbdp
;
145 if (AfsAppLib_HandleHelp (IDD_APPLIB_BROWSE
, hDlg
, msg
, wp
, lp
))
150 if (msg
== WM_INITDIALOG
)
152 SetWindowLongPtr (hDlg
, DWLP_USER
, lp
);
155 if ((pbdp
= (BROWSEDIALOGPARAMS
*)GetWindowLongPtr (hDlg
, DWLP_USER
)) != NULL
)
160 DlgProc_Browse_OnInitDialog (hDlg
, pbdp
);
164 switch (((LPNMHDR
)lp
)->code
)
166 case LVN_ITEMCHANGED
:
167 if ( ((LPNM_LISTVIEW
)lp
)->uNewState
& LVIS_SELECTED
)
169 DlgProc_Browse_SelectedEntry (hDlg
, pbdp
);
174 PostMessage (hDlg
, WM_COMMAND
, MAKELONG(IDC_BROWSE_SELECT
,BN_CLICKED
), (LPARAM
)GetDlgItem(hDlg
,IDC_BROWSE_SELECT
));
180 DlgProc_Browse_StopSearch (pbdp
);
182 if (pbdp
->hImages
!= NULL
)
184 ListView_SetImageList (GetDlgItem (hDlg
, IDC_BROWSE_LIST
), 0, 0);
185 ImageList_Destroy (pbdp
->hImages
);
191 LPTSTR pszName
= (LPTSTR
)lp
;
194 HWND hList
= GetDlgItem (hDlg
, IDC_BROWSE_LIST
);
195 LV_AddItem (hList
, 1, INDEX_SORT
, 0, 0, pszName
);
196 FreeString (pszName
);
203 TCHAR szText
[ cchRESOURCE
];
204 GetString (szText
, IDS_BROWSE_WAITING
);
205 SetDlgItemText (pbdp
->hDlg
, IDC_BROWSE_STATUS
, szText
);
211 SetDlgItemText (pbdp
->hDlg
, IDC_BROWSE_STATUS
, TEXT(""));
219 EndDialog (hDlg
, LOWORD(wp
));
222 case IDC_BROWSE_SELECT
:
223 if ( (GetDlgItem (pbdp
->hDlg
, IDC_BROWSE_NONE
) != NULL
) &&
224 (IsDlgButtonChecked (pbdp
->hDlg
, IDC_BROWSE_NONE
)) )
226 pbdp
->szCell
[0] = TEXT('\0');
227 pbdp
->szNamed
[0] = TEXT('\0');
231 GetDlgItemText (hDlg
, IDC_BROWSE_CELL
, pbdp
->szCell
, cchNAME
);
232 GetDlgItemText (hDlg
, IDC_BROWSE_NAMED
, pbdp
->szNamed
, cchRESOURCE
);
234 EndDialog (hDlg
, IDOK
);
237 case IDC_BROWSE_CELL
:
238 if (HIWORD(wp
) == CBN_SELCHANGE
)
240 GetDlgItemText (hDlg
, IDC_BROWSE_CELL
, pbdp
->szCell
, cchNAME
);
241 DlgProc_Browse_StartSearch (pbdp
, FALSE
);
245 case IDC_BROWSE_RESTART
:
246 GetDlgItemText (hDlg
, IDC_BROWSE_CELL
, pbdp
->szCell
, cchNAME
);
247 DlgProc_Browse_StartSearch (pbdp
, FALSE
);
248 PostMessage (hDlg
, WM_NEXTDLGCTL
, (WPARAM
)GetDlgItem (hDlg
, IDC_BROWSE_NAMED
), (LPARAM
)TRUE
);
251 case IDC_BROWSE_NAMED
:
252 if (HIWORD(wp
) == EN_UPDATE
) // has the user hit Enter here?
254 TCHAR szTest
[ cchRESOURCE
];
256 GetDlgItemText (hDlg
, IDC_BROWSE_NAMED
, szTest
, cchRESOURCE
);
258 if ( (lstrlen (szTest
) > 0) &&
259 (szTest
[ lstrlen(szTest
)-1 ] == TEXT('\n')) )
261 szTest
[ lstrlen(szTest
)-1 ] = TEXT('\0');
263 if ( (lstrlen (szTest
) > 0) &&
264 (szTest
[ lstrlen(szTest
)-1 ] == TEXT('\r')) )
266 szTest
[ lstrlen(szTest
)-1 ] = TEXT('\0');
269 SetDlgItemText (hDlg
, IDC_BROWSE_NAMED
, szTest
);
270 PostMessage (hDlg
, WM_COMMAND
, MAKELONG(IDC_BROWSE_SELECT
,BN_CLICKED
), (LPARAM
)GetDlgItem(hDlg
,IDC_BROWSE_SELECT
));
275 case IDC_BROWSE_NONE
:
276 DlgProc_Browse_OnNone (hDlg
, pbdp
);
288 *** DlgProc_Browse_OnInitDialog
290 * The WM_INITDIALOG handler for the Browse dialog. This routine fills
291 * in the dialog with any starting parameters, and kicks off a new
292 * searching thread for the given cell.
296 void DlgProc_Browse_OnInitDialog (HWND hDlg
, BROWSEDIALOGPARAMS
*pbdp
)
298 TCHAR szText
[ cchRESOURCE
];
303 // We'll need an imagelist, if we want icons in the listview.
304 // This looks difficult but it's not--tis just a matter of selecting
305 // an appropriate bitmap.
307 if ((pbdp
->hImages
= ImageList_Create (cxICON
, cyICON
, ILC_COLOR4
| ILC_MASK
, 1, 1)) != 0)
311 if (pbdp
->bt
== btLOCAL_USER
)
313 bmp
= LoadBitmap (APPLIB_HINST
, MAKEINTRESOURCE( IDB_LOCAL_USER
));
315 else if (pbdp
->bt
== btANY_USER
)
317 bmp
= LoadBitmap (APPLIB_HINST
, MAKEINTRESOURCE( IDB_FOREIGN_USER
));
319 else if (pbdp
->bt
== btLOCAL_GROUP
)
321 bmp
= LoadBitmap (APPLIB_HINST
, MAKEINTRESOURCE( IDB_LOCAL_GROUP
));
323 else if (pbdp
->bt
== btANY_GROUP
)
325 bmp
= LoadBitmap (APPLIB_HINST
, MAKEINTRESOURCE( IDB_FOREIGN_GROUP
));
330 ImageList_AddMasked (pbdp
->hImages
, bmp
, clrTRANSPARENT
);
334 ListView_SetImageList (GetDlgItem (hDlg
, IDC_BROWSE_LIST
), pbdp
->hImages
, LVSIL_SMALL
);
337 // There's a default pushbutton on this dialog, so that hitting
338 // RETURN when you're in the Cell combobox will restart the search
339 // (a default pushbutton always gets called when RETURN is hit,
340 // unless your control traps it). But the user doesn't want to *see*
341 // that thing, so move it way off the dialog's client area.
344 GetWindowRect (GetDlgItem (hDlg
, IDC_BROWSE_RESTART
), &r
);
345 SetWindowPos (GetDlgItem (hDlg
, IDC_BROWSE_RESTART
), NULL
,
346 0 - (r
.right
-r
.left
), 0 - (r
.bottom
-r
.top
), 0, 0,
347 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
349 // Fill in the choices underneath IDC_BROWSE_CELL. Can the
350 // user enter a new cell name?
352 if (pbdp
->fThisCellOnly
)
354 EnableWindow (GetDlgItem (hDlg
, IDC_BROWSE_CELL
), FALSE
);
358 CB_StartChange (GetDlgItem (hDlg
, IDC_BROWSE_CELL
));
362 TCHAR szDefCell
[ cchNAME
];
363 if (AfsAppLib_GetLocalCell (szDefCell
) && *szDefCell
)
365 CB_AddItem (GetDlgItem (hDlg
, IDC_BROWSE_CELL
), szDefCell
, 1);
368 else for (size_t ii
= 0; ii
< pbdp
->lpcl
->nCells
; ++ii
)
370 CB_AddItem (GetDlgItem (hDlg
, IDC_BROWSE_CELL
), pbdp
->lpcl
->aCells
[ii
], 1+ii
);
373 CB_EndChange (GetDlgItem (hDlg
, IDC_BROWSE_CELL
), 1);
376 // Select various texts to display in the dialog
378 psz
= FormatString (TEXT("%1"), TEXT("%m"), pbdp
->idsTitle
);
379 SetWindowText (hDlg
, psz
);
381 GetString (szText
, pbdp
->idsPrompt
);
382 SetDlgItemText (hDlg
, IDC_BROWSE_TYPE
, szText
);
384 // If the caller wants us to display a "[X] No Group" checkbox, do so
385 // by creating a checkbox right underneath the IDC_BROWSE_NAMED edit
386 // control--note that we'll have to hide IDC_BROWSE_STATUS if that's
389 if (pbdp
->idsNone
!= 0)
391 ShowWindow (GetDlgItem (pbdp
->hDlg
, IDC_BROWSE_STATUS
), FALSE
);
394 GetRectInParent (GetDlgItem (pbdp
->hDlg
, IDC_BROWSE_NAMED
), &rr
);
397 cy
= rr
.bottom
-rr
.top
;
399 rr
.bottom
= rr
.top
+cy
;
401 GetString (szText
, pbdp
->idsNone
);
402 CreateWindow ("Button", szText
, WS_CHILD
| BS_AUTOCHECKBOX
,
403 rr
.left
, rr
.top
, rr
.right
-rr
.left
, rr
.bottom
-rr
.top
,
404 pbdp
->hDlg
, (HMENU
)IDC_BROWSE_NONE
, APPLIB_HINST
, 0);
406 HFONT hf
= (HFONT
)GetStockObject (DEFAULT_GUI_FONT
);
407 SendMessage (GetDlgItem (pbdp
->hDlg
, IDC_BROWSE_NONE
), WM_SETFONT
, (WPARAM
)hf
, FALSE
);
408 ShowWindow (GetDlgItem (pbdp
->hDlg
, IDC_BROWSE_NONE
), TRUE
);
410 if (pbdp
->szNamed
[0] == TEXT('\0'))
411 CheckDlgButton (pbdp
->hDlg
, IDC_BROWSE_NONE
, TRUE
);
413 CheckDlgButton (pbdp
->hDlg
, IDC_BROWSE_NONE
, FALSE
);
415 DlgProc_Browse_OnNone (pbdp
->hDlg
, pbdp
);
418 SetDlgItemText (hDlg
, IDC_BROWSE_CELL
, pbdp
->szCell
);
419 SetDlgItemText (hDlg
, IDC_BROWSE_NAMED
, pbdp
->szNamed
);
421 // Start looking for users/groups
423 DlgProc_Browse_StartSearch (pbdp
, TRUE
);
428 *** DlgProc_Browse_OnNone
430 * This routine is called whenever the user checks or unchecks the
431 * "[X] None" checkbox (which we may not even be displaying)
435 void DlgProc_Browse_OnNone (HWND hDlg
, BROWSEDIALOGPARAMS
*pbdp
)
437 if (GetDlgItem (pbdp
->hDlg
, IDC_BROWSE_NONE
) != NULL
)
439 BOOL fNone
= IsDlgButtonChecked (pbdp
->hDlg
, IDC_BROWSE_NONE
);
441 EnableWindow (GetDlgItem (hDlg
, IDC_BROWSE_CELL
), !fNone
&& !pbdp
->fThisCellOnly
);
442 EnableWindow (GetDlgItem (hDlg
, IDC_BROWSE_NAMED
), !fNone
);
443 EnableWindow (GetDlgItem (hDlg
, IDC_BROWSE_LIST
), !fNone
);
445 DlgProc_Browse_SelectedEntry (hDlg
, pbdp
);
451 *** DlgProc_Browse_SelectedEntry
453 * This routine is called whenever the user selects a new entry within
454 * the Browse dialog's listview
458 void DlgProc_Browse_SelectedEntry (HWND hDlg
, BROWSEDIALOGPARAMS
*pbdp
)
460 if ( (GetDlgItem (pbdp
->hDlg
, IDC_BROWSE_NONE
) != NULL
) &&
461 (IsDlgButtonChecked (pbdp
->hDlg
, IDC_BROWSE_NONE
)) )
463 pbdp
->szNamed
[0] = TEXT('\0');
467 HWND hList
= GetDlgItem (hDlg
, IDC_BROWSE_LIST
);
468 short idxSelected
= LV_GetSelected (hList
);
470 if (idxSelected
== -1)
471 pbdp
->szNamed
[0] = TEXT('\0');
473 LV_GetItemText (hList
, idxSelected
, 0, pbdp
->szNamed
);
475 SetDlgItemText (hDlg
, IDC_BROWSE_NAMED
, pbdp
->szNamed
);
481 *** DlgProc_Browse_UpdateCellText
483 * This routine places the given cell name in the browse dialog.
487 void DlgProc_Browse_UpdateCellText (BROWSEDIALOGPARAMS
*pbdp
, LPTSTR pszCell
)
489 SetDlgItemText (pbdp
->hDlg
, IDC_BROWSE_CELL
, pbdp
->szCell
);
494 *** DlgProc_Browse_StartSearch
496 * This routine initiates a thread which enumerates all users/groups within
497 * the given cell, posting messages to describe what it finds to the Browse
502 BOOL
DlgProc_Browse_StartSearch (BROWSEDIALOGPARAMS
*pbdp
, BOOL fCloseDlgIfFail
)
506 // Can't start a new search until the old search terminates.
508 DlgProc_Browse_StopSearch (pbdp
);
510 // Then make sure that we have a valid cell to query--if not, it may
511 // be grounds to terminate the entire browse dialog.
513 lstrcpy (pbdp
->szThreadCell
, pbdp
->szCell
);
515 if (!pbdp
->szCell
[0])
517 AfsAppLib_GetLocalCell (pbdp
->szCell
);
519 lstrcpy (pbdp
->szThreadCell
, pbdp
->szCell
);
521 DlgProc_Browse_UpdateCellText (pbdp
, pbdp
->szThreadCell
);
524 if (!pbdp
->szCell
[0])
527 EndDialog (pbdp
->hDlg
, IDCANCEL
);
529 MessageBeep (MB_ICONHAND
);
530 Message (MB_ICONHAND
, IDS_BROWSE_BADCELL_TITLE
, IDS_BROWSE_BADCELL_DESC
);
532 if (!fCloseDlgIfFail
)
533 PostMessage (pbdp
->hDlg
, WM_NEXTDLGCTL
, (WPARAM
)GetDlgItem (pbdp
->hDlg
, IDC_BROWSE_CELL
), (LPARAM
)TRUE
);
537 // Great--we can do the search. Start a thread to do so.
539 pbdp
->fCanStopThreadEasily
= FALSE
;
540 pbdp
->fShouldStopThread
= FALSE
;
541 pbdp
->fThreadActive
= FALSE
;
543 ListView_DeleteAllItems (GetDlgItem (pbdp
->hDlg
, IDC_BROWSE_LIST
));
545 pbdp
->hThread
= CreateThread (NULL
, 0,
546 (LPTHREAD_START_ROUTINE
)DlgProc_Browse_ThreadProc
,
547 pbdp
, 0, &dwThreadID
);
549 return (pbdp
->hThread
== 0) ? FALSE
: TRUE
;
554 *** DlgProc_Browse_StopSearch
556 * This routine signals the search thread to stop, and will not return
561 void DlgProc_Browse_StopSearch (BROWSEDIALOGPARAMS
*pbdp
)
563 if (pbdp
->fThreadActive
)
565 if (pbdp
->fCanStopThreadEasily
)
567 pbdp
->fShouldStopThread
= TRUE
;
569 WaitForSingleObject (pbdp
->hThread
, INFINITE
);
573 TerminateThread (pbdp
->hThread
, 0);
574 pbdp
->fThreadActive
= FALSE
;
578 SetDlgItemText (pbdp
->hDlg
, IDC_BROWSE_STATUS
, TEXT(""));
583 *** DlgProc_Browse_ThreadProc
585 * The worker thread for the Browse dialog; this routine enumerates all
586 * users or groups on the given cell, posting a WM_FOUNDNAME message to
587 * the Browse dialog after every successful find. Note that LPARAM on
588 * such messages points to a string which should be freed with FreeString()
589 * when no longer needed.
593 DWORD _stdcall
DlgProc_Browse_ThreadProc (LPARAM lp
)
595 BROWSEDIALOGPARAMS
*pbdp
;
597 if ((pbdp
= (BROWSEDIALOGPARAMS
*)lp
) != NULL
)
599 pbdp
->fThreadActive
= TRUE
;
601 PostMessage (pbdp
->hDlg
, WM_THREADSTART
, 0, 0);
604 if ((idClient
= AfsAppLib_GetAdminServerClientID()) != 0)
606 EnumeratePrincipalsRemotely (pbdp
, idClient
);
610 if (OpenClientLibrary())
612 if (OpenKasLibrary())
614 EnumeratePrincipalsLocally (pbdp
);
618 CloseClientLibrary();
622 pbdp
->fThreadActive
= FALSE
;
624 PostMessage (pbdp
->hDlg
, WM_THREADDONE
, 0, 0);
631 void EnumeratePrincipalsLocally (LPBROWSEDIALOGPARAMS pbdp
)
635 char szCellA
[ MAX_PATH
];
636 CopyStringToAnsi (szCellA
, pbdp
->szCell
);
639 if (afsclient_CellOpen (szCellA
, (PVOID
)pbdp
->hCreds
, &hCell
, (afs_status_p
)&status
))
641 // Enumerate the principals recognized by KAS.
644 if (kas_PrincipalGetBegin (hCell
, NULL
, &hEnum
, (afs_status_p
)&status
))
646 pbdp
->fCanStopThreadEasily
= TRUE
;
648 while (!pbdp
->fShouldStopThread
)
651 if (!kas_PrincipalGetNext (hEnum
, &who
, (afs_status_p
)&status
))
655 if ((pszName
= CloneAnsi ((LPSTR
)who
.principal
)) == NULL
)
658 PostMessage (pbdp
->hDlg
, WM_FOUNDNAME
, 0, (LPARAM
)pszName
);
659 // pszName freed by DlgProc_Browse when it receives the message
662 kas_PrincipalGetDone (hEnum
, (afs_status_p
)&status
);
665 afsclient_CellClose (hCell
, (afs_status_p
)&status
);
670 void EnumeratePrincipalsRemotely (LPBROWSEDIALOGPARAMS pbdp
, UINT_PTR idClient
)
674 // Open the relevant cell
677 if (asc_CellOpen (idClient
, (PVOID
)pbdp
->hCreds
, pbdp
->szThreadCell
, AFSADMSVR_SCOPE_USERS
, &idCell
, &status
))
679 // Obtain a list of ASIDs from the admin server, each representing
680 // a principal which we want to show.
682 LPASIDLIST pAsidList
;
683 if (asc_ObjectFindMultiple (idClient
, idCell
, TYPE_USER
, NULL
, NULL
, &pAsidList
, &status
))
687 // Obtain rudimentary properties (e.g., their names) for these ASIDs
689 LPASOBJPROPLIST pPropList
;
690 if (asc_ObjectPropertiesGetMultiple (idClient
, GET_RUDIMENTARY_DATA
, idCell
, pAsidList
, &pPropList
, &status
))
694 // Use the information in {pPropList} to populate the display
696 for (size_t iEntry
= 0; iEntry
< pPropList
->cEntries
; ++iEntry
)
699 if ((pszName
= CloneString (pPropList
->aEntries
[ iEntry
].ObjectProperties
.szName
)) != NULL
)
701 PostMessage (pbdp
->hDlg
, WM_FOUNDNAME
, 0, (LPARAM
)pszName
);
702 // pszName freed by DlgProc_Browse when it receives the message
706 asc_ObjPropListFree (&pPropList
);
710 asc_AsidListFree (&pAsidList
);
714 asc_CellClose (idClient
, idCell
, &status
);