Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

884 lines
24 KiB

/****************************************************************************
PROGRAM: TOKEDIT.C
PURPOSE: Displays and allows the user to edit the contents of a token
****************************************************************************/
#include "PVIEWP.h"
#include "string.h"
INT_PTR CALLBACK TokenEditDlgProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK MoreDlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL TokenEditDlgInit(HWND);
BOOL TokenEditDlgEnd(HWND, BOOL);
BOOL EnablePrivilege(HWND, BOOL);
BOOL EnableGroup(HWND, BOOL);
BOOL SetDefaultOwner(HWND);
BOOL SetPrimaryGroup(HWND);
BOOL MoreDlgInit(HWND hDlg, LPARAM lParam);
BOOL DisplayMyToken(HWND);
/****************************************************************************
FUNCTION: EditToken
PURPOSE: Displays and allows the user to edit a token
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/
BOOL EditToken(
HWND hwndParent,
HANDLE Token,
LPWSTR Name
)
{
//DLGPROC lpProc;
int Result;
HANDLE hMyToken;
HANDLE Instance;
hMyToken = OpenMyToken(Token, Name);
if (hMyToken == NULL) {
return(FALSE);
}
//
// Get the application instance handle
//
Instance = (HANDLE)(NtCurrentPeb()->ImageBaseAddress);
ASSERT(Instance != 0);
//lpProc = (DLGPROC)MakeProcInstance(TokenEditDlgProc, Instance);
//Result = (int)DialogBoxParam(Instance,(LPSTR)IDD_MAIN, hwndParent, lpProc, (LPARAM)hMyToken);
//FreeProcInstance(lpProc);
Result = (int)DialogBoxParam(Instance,(LPSTR)IDD_MAIN, hwndParent, TokenEditDlgProc, (LPARAM)hMyToken);
return(TRUE);
}
/****************************************************************************
FUNCTION: TokenEditDlgProc(HWND, unsigned, WORD, LONG)
PURPOSE: Processes messages
MESSAGES:
WM_COMMAND - application menu (About dialog box)
WM_DESTROY - destroy window
COMMENTS:
****************************************************************************/
INT_PTR CALLBACK TokenEditDlgProc(hDlg, message, wParam, lParam)
HWND hDlg;
UINT message;
WPARAM wParam;
LPARAM lParam;
{
DLGPROC lpProc;
HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA);
switch (message) {
case WM_INITDIALOG:
SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
if (!TokenEditDlgInit(hDlg)) {
// Failed to initialize dialog, get out
EndDialog(hDlg, FALSE);
}
return (TRUE);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
// we're done, drop through to quit dialog....
case IDCANCEL:
TokenEditDlgEnd(hDlg, LOWORD(wParam) == IDOK);
EndDialog(hDlg, TRUE);
return TRUE;
case IDB_DISABLEPRIVILEGE:
case IDB_ENABLEPRIVILEGE:
EnablePrivilege(hDlg, LOWORD(wParam) == IDB_ENABLEPRIVILEGE);
return(TRUE);
case IDB_DISABLEGROUP:
case IDB_ENABLEGROUP:
EnableGroup(hDlg, LOWORD(wParam) == IDB_ENABLEGROUP);
return(TRUE);
case IDC_DEFAULTOWNER:
SetDefaultOwner(hDlg);
return(TRUE);
case IDC_PRIMARYGROUP:
SetPrimaryGroup(hDlg);
return(TRUE);
case IDB_MORE:
{
HANDLE Instance = (HANDLE)(NtCurrentPeb()->ImageBaseAddress);
//lpProc = (DLGPROC)MakeProcInstance(MoreDlgProc, Instance);
//DialogBoxParam(Instance,(LPSTR)IDD_MORE, hDlg, lpProc, (LPARAM)hMyToken);
//FreeProcInstance(lpProc);
DialogBoxParam(Instance,(LPSTR)IDD_MORE, hDlg, MoreDlgProc, (LPARAM)hMyToken);
return(TRUE);
}
case IDB_DEFAULT_DACL:
{
HANDLE Token = ((PMYTOKEN)hMyToken)->Token;
LPWSTR Name = ((PMYTOKEN)hMyToken)->Name;
EditTokenDefaultDacl(hDlg, Token, Name);
return(TRUE);
}
default:
// We didn't process this message
return FALSE;
}
break;
default:
// We didn't process this message
return FALSE;
}
// We processed the message
return TRUE;
}
/****************************************************************************
FUNCTION: TokenEditDlgInit(HWND)
PURPOSE: Initialises the controls in the main dialog window.
RETURNS: TRUE on success, FALSE if dialog should be terminated.
****************************************************************************/
BOOL TokenEditDlgInit(
HWND hDlg
)
{
HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA);
WCHAR string[MAX_STRING_LENGTH];
HCURSOR OldCursor;
if (!LsaInit()) {
DbgPrint("PVIEW - LsaInit failed\n");
return(FALSE);
}
OldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
DisplayMyToken(hDlg);
SetCursor(OldCursor);
//
// Set the dialog caption appropriately
//
GetWindowTextW(hDlg, string, sizeof(string)/sizeof(*string));
lstrcatW(string, L" for <");
lstrcatW(string, ((PMYTOKEN)hMyToken)->Name);
lstrcatW(string, L">");
SetWindowTextW(hDlg, string);
return(TRUE);
}
/****************************************************************************
FUNCTION: TokenEditDlgEnd(HWND)
PURPOSE: Do whatever we have to do to clean up when dialog ends
RETURNS: TRUE on success, FALSE on failure.
****************************************************************************/
BOOL TokenEditDlgEnd(
HWND hDlg,
BOOL fSaveChanges)
{
HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA);
BOOL Success;
Success = CloseMyToken(hDlg, hMyToken, fSaveChanges);
LsaTerminate();
return(Success);
}
/****************************************************************************
FUNCTION: DisplayMyToken
PURPOSE: Reads data out of mytoken and puts in dialog controls.
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/
BOOL DisplayMyToken(
HWND hDlg
)
{
HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA);
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
CHAR string[MAX_STRING_BYTES];
UINT GroupIndex;
UINT PrivIndex;
//
// Groups
//
if (pMyToken->Groups != NULL) {
for (GroupIndex=0; GroupIndex < pMyToken->Groups->GroupCount; GroupIndex++ ) {
PSID Sid = pMyToken->Groups->Groups[GroupIndex].Sid;
ULONG Attributes = pMyToken->Groups->Groups[GroupIndex].Attributes;
USHORT ControlID;
if (Attributes & SE_GROUP_ENABLED) {
ControlID = IDL_ENABLEDGROUPS;
} else {
ControlID = IDL_DISABLEDGROUPS;
}
if (SID2Name(Sid, string, MAX_STRING_BYTES)) {
// Add to disable or enabled group box
AddLBItem(hDlg, ControlID, string, GroupIndex);
// Add this group to default owner combo box if it's valid
if (Attributes & SE_GROUP_OWNER) {
AddCBItem(hDlg, IDC_DEFAULTOWNER, string, (LPARAM)Sid);
}
// Add this group to primary group combo box
AddCBItem(hDlg, IDC_PRIMARYGROUP, string, (LPARAM)Sid);
} else {
DbgPrint("PVIEW: Failed to convert Group sid to string\n");
}
}
} else {
DbgPrint("PVIEW : No group info in mytoken\n");
}
//
// User ID
//
if (pMyToken->UserId != NULL) {
PSID Sid = pMyToken->UserId->User.Sid;
if (SID2Name(Sid, string, MAX_STRING_BYTES)) {
// Set user-name static text
SetDlgItemText(hDlg, IDS_USERID, string);
// Add to default owner combo box
AddCBItem(hDlg, IDC_DEFAULTOWNER, string, (LPARAM)Sid);
// Add to primary group combo box
AddCBItem(hDlg, IDC_PRIMARYGROUP, string, (LPARAM)Sid);
} else {
DbgPrint("PVIEW: Failed to convert User ID SID to string\n");
}
} else {
DbgPrint("PVIEW: No user id in mytoken\n");
}
//
// Default Owner
//
if (pMyToken->DefaultOwner != NULL) {
PSID Sid = pMyToken->DefaultOwner->Owner;
if (SID2Name(Sid, string, MAX_STRING_BYTES)) {
INT iItem;
iItem = FindCBSid(hDlg, IDC_DEFAULTOWNER, Sid);
if (iItem >= 0) {
SendMessage(GetDlgItem(hDlg, IDC_DEFAULTOWNER), CB_SETCURSEL, iItem, 0);
} else {
DbgPrint("PVIEW: Default Owner is not userID or one of our groups\n");
}
} else {
DbgPrint("PVIEW: Failed to convert Default Owner SID to string\n");
}
} else {
DbgPrint("PVIEW: No default owner in mytoken\n");
}
//
// Primary group
//
if (pMyToken->PrimaryGroup != NULL) {
PSID Sid = pMyToken->PrimaryGroup->PrimaryGroup;
if (SID2Name(Sid, string, MAX_STRING_BYTES)) {
INT iItem;
iItem = FindCBSid(hDlg, IDC_PRIMARYGROUP, Sid);
if (iItem < 0) {
// Group is not already in combo-box, add it
iItem = AddCBItem(hDlg, IDC_PRIMARYGROUP, string, (LPARAM)Sid);
}
// Select the primary group
SendMessage(GetDlgItem(hDlg, IDC_PRIMARYGROUP), CB_SETCURSEL, iItem, 0);
} else {
DbgPrint("PVIEW: Failed to convert primary group SID to string\n");
}
} else {
DbgPrint("PVIEW: No primary group in mytoken\n");
}
//
// Privileges
//
if (pMyToken->Privileges != NULL) {
for (PrivIndex=0; PrivIndex < pMyToken->Privileges->PrivilegeCount; PrivIndex++ ) {
LUID Privilege = pMyToken->Privileges->Privileges[PrivIndex].Luid;
ULONG Attributes = pMyToken->Privileges->Privileges[PrivIndex].Attributes;
USHORT ControlID;
if (Attributes & SE_PRIVILEGE_ENABLED) {
ControlID = IDL_ENABLEDPRIVILEGES;
} else {
ControlID = IDL_DISABLEDPRIVILEGES;
}
if (PRIV2Name(Privilege, string, MAX_STRING_BYTES)) {
// Add this privelege to the appropriate list-box
AddLBItem(hDlg, ControlID, string, PrivIndex);
} else {
DbgPrint("PVIEW: Failed to convert privilege to string\n");
}
}
} else {
DbgPrint("PVIEW: No privilege info in mytoken\n");
}
return(TRUE);
}
/****************************************************************************
FUNCTION: EnablePrivilege(HWND, fEnable)
PURPOSE: Enables or disables one or more privileges.
If fEnable = TRUE, the selected privileges in the disabled
privilege control are enabled.
Vice versa for fEnable = FALSE
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/
BOOL EnablePrivilege(
HWND hDlg,
BOOL fEnable)
{
HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA);
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
HWND hwndFrom;
HWND hwndTo;
USHORT idFrom;
USHORT idTo;
INT cItems;
PINT pItems;
PTOKEN_PRIVILEGES Privileges;
Privileges = pMyToken->Privileges;
if (Privileges == NULL) {
return(FALSE);
}
// Calculate source and destination controls
//
if (fEnable) {
idFrom = IDL_DISABLEDPRIVILEGES;
idTo = IDL_ENABLEDPRIVILEGES;
} else {
idFrom = IDL_ENABLEDPRIVILEGES;
idTo = IDL_DISABLEDPRIVILEGES;
}
hwndFrom = GetDlgItem(hDlg, idFrom);
hwndTo = GetDlgItem(hDlg, idTo);
// Find how many items are selected
//
cItems = (INT)SendMessage(hwndFrom, LB_GETSELCOUNT, 0, 0);
if (cItems <= 0) {
// No items selected
return(TRUE);
}
// Allocate space for the item array
//
pItems = Alloc(cItems * sizeof(*pItems));
if (pItems == NULL) {
return(FALSE);
}
// Read the selected items into the array
//
cItems = (INT)SendMessage(hwndFrom, LB_GETSELITEMS, (WPARAM)cItems, (LPARAM)pItems);
if (cItems == LB_ERR) {
// Something went wrong
Free(pItems);
return(FALSE);
}
while (cItems-- > 0) {
INT iItem;
UINT PrivIndex;
UCHAR PrivilegeName[MAX_STRING_BYTES];
iItem = pItems[cItems]; // Read the item index from the selected item array
// Read the text and data from the source item
//
PrivIndex = (UINT)SendMessage(hwndFrom, LB_GETITEMDATA, iItem, 0);
SendMessage(hwndFrom, LB_GETTEXT, iItem, (LPARAM)PrivilegeName);
// Delete item from source control
//
SendMessage(hwndFrom, LB_DELETESTRING, iItem, 0);
// Add privilege to destination control
//
iItem = (INT)SendMessage(hwndTo, LB_ADDSTRING, 0, (LPARAM)PrivilegeName);
SendMessage(hwndTo, LB_SETITEMDATA, iItem, (LPARAM)PrivIndex);
// Modify global data structure to reflect change
//
if (fEnable) {
Privileges->Privileges[PrivIndex].Attributes |= SE_PRIVILEGE_ENABLED;
} else {
Privileges->Privileges[PrivIndex].Attributes &= ~SE_PRIVILEGE_ENABLED;
}
}
// Free up space allocated for selected item array
Free(pItems);
return(TRUE);
}
/****************************************************************************
FUNCTION: EnableGroup(HWND, fEnable)
PURPOSE: Enables or disables one or more selected groups.
If fEnable = TRUE, the selected groups in the disabled
group control are enabled.
If fEnable = FALSE the selected groups in the enabled
group control are disabled.
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/
BOOL EnableGroup(
HWND hDlg,
BOOL fEnable)
{
HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA);
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
HWND hwndFrom;
HWND hwndTo;
USHORT idFrom;
USHORT idTo;
INT cItems;
PINT pItems;
PTOKEN_GROUPS Groups;
Groups = pMyToken->Groups;
if (Groups == NULL) {
return(FALSE);
}
// Calculate source and destination controls
//
if (fEnable) {
idFrom = IDL_DISABLEDGROUPS;
idTo = IDL_ENABLEDGROUPS;
} else {
idFrom = IDL_ENABLEDGROUPS;
idTo = IDL_DISABLEDGROUPS;
}
hwndFrom = GetDlgItem(hDlg, idFrom);
hwndTo = GetDlgItem(hDlg, idTo);
// Find how many items are selected
//
cItems = (INT)SendMessage(hwndFrom, LB_GETSELCOUNT, 0, 0);
if (cItems <= 0) {
// No items selected
return(TRUE);
}
// Allocate space for the item array
//
pItems = Alloc(cItems * sizeof(*pItems));
if (pItems == NULL) {
return(FALSE);
}
// Read the selected items into the array
//
cItems = (INT)SendMessage(hwndFrom, LB_GETSELITEMS, (WPARAM)cItems, (LPARAM)pItems);
if (cItems == LB_ERR) {
// Something went wrong
Free(pItems);
return(FALSE);
}
while (cItems-- > 0) {
INT iItem;
UINT GroupIndex;
UCHAR GroupName[MAX_STRING_BYTES];
iItem = pItems[cItems]; // Read the item index from the selected item array
// Read the text and data from the source item
//
GroupIndex = (UINT)SendMessage(hwndFrom, LB_GETITEMDATA, iItem, 0);
SendMessage(hwndFrom, LB_GETTEXT, iItem, (LPARAM)GroupName);
// Check it's not a mandatory group (Can-not be disabled)
//
if (Groups->Groups[GroupIndex].Attributes & SE_GROUP_MANDATORY) {
CHAR buf[256];
strcpy(buf, "'");
strcat(buf, GroupName);
strcat(buf, "' is a mandatory group and cannot be disabled");
MessageBox(hDlg, buf, NULL, MB_ICONSTOP | MB_APPLMODAL | MB_OK);
continue; // skip to next group
}
// Delete item from source control
//
SendMessage(hwndFrom, LB_DELETESTRING, iItem, 0);
// Add item to destination control
//
iItem = (INT)SendMessage(hwndTo, LB_ADDSTRING, 0, (LPARAM)GroupName);
SendMessage(hwndTo, LB_SETITEMDATA, iItem, (LONG)GroupIndex);
// Modify global data structure to reflect change
//
if (fEnable) {
Groups->Groups[GroupIndex].Attributes |= SE_GROUP_ENABLED;
} else {
Groups->Groups[GroupIndex].Attributes &= ~SE_GROUP_ENABLED;
}
}
// Free up space allocated for selected item array
Free(pItems);
return(TRUE);
}
/****************************************************************************
FUNCTION: SetDefaultOwner()
PURPOSE: Sets the default owner to the new value selected by the user.
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/
BOOL SetDefaultOwner(
HWND hDlg)
{
HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA);
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
HWND hwnd;
INT iItem;
PTOKEN_OWNER DefaultOwner;
DefaultOwner = pMyToken->DefaultOwner;
if (DefaultOwner == NULL) {
return(FALSE);
}
hwnd = GetDlgItem(hDlg, IDC_DEFAULTOWNER);
iItem = (INT)SendMessage(hwnd, CB_GETCURSEL, 0, 0);
if (iItem == CB_ERR) {
// No selection ?
return(FALSE);
}
// Modify global data structure to reflect change
DefaultOwner->Owner = (PSID)SendMessage(hwnd, CB_GETITEMDATA, iItem, 0);
return(TRUE);
}
/****************************************************************************
FUNCTION: SetPrimaryGroup()
PURPOSE: Sets the primary group to the new value selected by the user.
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/
BOOL SetPrimaryGroup(
HWND hDlg)
{
HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA);
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
HWND hwnd;
INT iItem;
PTOKEN_PRIMARY_GROUP PrimaryGroup;
PrimaryGroup = pMyToken->PrimaryGroup;
if (PrimaryGroup == NULL) {
return(FALSE);
}
hwnd = GetDlgItem(hDlg, IDC_PRIMARYGROUP);
iItem = (INT)SendMessage(hwnd, CB_GETCURSEL, 0, 0);
if (iItem == CB_ERR) {
// No selection ?
return(FALSE);
}
// Modify global data structure to reflect change
PrimaryGroup->PrimaryGroup = (PSID)SendMessage(hwnd, CB_GETITEMDATA, iItem, 0);
return(TRUE);
}
/****************************************************************************
FUNCTION: MoreDlgProc(HWND, UINT, WPARAM, LPARAM)
PURPOSE: Processes messages
****************************************************************************/
INT_PTR CALLBACK MoreDlgProc(hDlg, message, wParam, lParam)
HWND hDlg;
UINT message;
WPARAM wParam;
LPARAM lParam;
{
HANDLE hMyToken = (HANDLE)GetWindowLongPtr(hDlg, GWLP_USERDATA);
switch (message) {
case WM_INITDIALOG:
if (!MoreDlgInit(hDlg, lParam)) {
// Failed to initialize dialog, get out
EndDialog(hDlg, FALSE);
}
return (TRUE);
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
// we're done, drop through to quit dialog....
case IDCANCEL:
EndDialog(hDlg, TRUE);
return TRUE;
break;
default:
// We didn't process this message
return FALSE;
break;
}
break;
default:
// We didn't process this message
return FALSE;
}
// We processed the message
return TRUE;
}
/****************************************************************************
FUNCTION: MoreDlgInit(HWND)
PURPOSE: Initialises the controls in the more dialog window.
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/
BOOL MoreDlgInit(
HWND hDlg,
LPARAM lParam
)
{
TCHAR string[MAX_STRING_LENGTH];
HANDLE hMyToken = (HANDLE)lParam;
PMYTOKEN pMyToken = (PMYTOKEN)hMyToken;
PTOKEN_STATISTICS Statistics;
PTOKEN_GROUPS Restrictions ;
UINT GroupIndex;
Statistics = pMyToken->TokenStats;
if (Statistics == NULL) {
DbgPrint("PVIEW: No token statistics in mytoken\n");
return(FALSE);
}
wsprintf(string, "0x%lx-%lx",
pMyToken->TokenStats->AuthenticationId.HighPart,
pMyToken->TokenStats->AuthenticationId.LowPart);
SetDlgItemText(hDlg, IDS_LOGONSESSION, string);
if (LUID2String(Statistics->TokenId, string, MAX_STRING_BYTES)) {
SetDlgItemText(hDlg, IDS_TOKENID, string);
} else {
DbgPrint("PVIEW: Failed to convert tokenid luid to string\n");
}
if (Time2String(Statistics->ExpirationTime, string, MAX_STRING_BYTES)) {
SetDlgItemText(hDlg, IDS_EXPIRATIONTIME, string);
} else {
DbgPrint("PVIEW: Failed to convert expiration time to string\n");
}
if (TokenType2String(Statistics->TokenType, string, MAX_STRING_BYTES)) {
SetDlgItemText(hDlg, IDS_TOKENTYPE, string);
} else {
DbgPrint("PVIEW: Failed to convert token type to string\n");
}
if (Statistics->TokenType == TokenPrimary) {
SetDlgItemText(hDlg, IDS_IMPERSONATION, "N/A");
} else {
if (ImpersonationLevel2String(Statistics->ImpersonationLevel, string, MAX_STRING_BYTES)) {
SetDlgItemText(hDlg, IDS_IMPERSONATION, string);
} else {
DbgPrint("PVIEW: Failed to convert impersonation level to string\n");
}
}
if (Dynamic2String(Statistics->DynamicCharged, string, MAX_STRING_BYTES)) {
SetDlgItemText(hDlg, IDS_DYNAMICCHARGED, string);
} else {
DbgPrint("PVIEW: Failed to convert dynamic charged to string\n");
}
if (Dynamic2String(Statistics->DynamicAvailable, string, MAX_STRING_BYTES)) {
SetDlgItemText(hDlg, IDS_DYNAMICAVAILABLE, string);
} else {
DbgPrint("PVIEW: Failed to convert dynamic available to string\n");
}
if (LUID2String(Statistics->ModifiedId, string, MAX_STRING_BYTES)) {
SetDlgItemText(hDlg, IDS_MODIFIEDID, string);
} else {
DbgPrint("PVIEW: Failed to convert modifiedid luid to string\n");
}
Restrictions = pMyToken->RestrictedSids ;
if ( Restrictions && (Restrictions->GroupCount) )
{
for (GroupIndex=0; GroupIndex < Restrictions->GroupCount; GroupIndex++ ) {
PSID Sid = Restrictions->Groups[GroupIndex].Sid;
ULONG Attributes = Restrictions->Groups[GroupIndex].Attributes;
if (SID2Name(Sid, string, MAX_STRING_BYTES)) {
// Add to disable or enabled group box
AddLBItem(hDlg, IDS_RESTRICTEDSIDS, string, GroupIndex);
} else {
DbgPrint("PVIEW: Failed to convert Group sid to string\n");
}
}
}
else
{
AddLBItem( hDlg, IDS_RESTRICTEDSIDS, TEXT("None"), 0 );
}
return(TRUE);
}