mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
0182dcd71b
- Make sure the DWLP_* values are correct on _WIN64 - Don't use the DWL_* constants, they are not portable. Enforce this by removing them entirely from winuser.h - Make sure Get/SetWindowLong*Ptr* is used and pointers are not truncated to LONG
1704 lines
52 KiB
C
1704 lines
52 KiB
C
/*
|
|
* ReactOS Access Control List Editor
|
|
* Copyright (C) 2004-2005 ReactOS Team
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/*
|
|
* PROJECT: ReactOS Access Control List Editor
|
|
* FILE: lib/aclui/aclui.c
|
|
* PURPOSE: Access Control List Editor
|
|
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
|
|
*
|
|
* UPDATE HISTORY:
|
|
* 08/10/2004 Created
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include <sddl.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
#include "resource.h"
|
|
|
|
HINSTANCE hDllInstance;
|
|
|
|
#define SIDN_LOOKUPSUCCEEDED (0x101)
|
|
typedef struct _SIDLOOKUPNOTIFYINFO
|
|
{
|
|
NMHDR nmh;
|
|
PSID Sid;
|
|
PSIDREQRESULT SidRequestResult;
|
|
} SIDLOOKUPNOTIFYINFO, *PSIDLOOKUPNOTIFYINFO;
|
|
|
|
static PSID
|
|
AceHeaderToSID(IN PACE_HEADER AceHeader)
|
|
{
|
|
PSID Sid = NULL;
|
|
switch (AceHeader->AceType)
|
|
{
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
Sid = (PSID)&((PACCESS_ALLOWED_ACE)AceHeader)->SidStart;
|
|
break;
|
|
#if 0
|
|
case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
|
|
Sid = (PSID)&((PACCESS_ALLOWED_CALLBACK_ACE)AceHeader)->SidStart;
|
|
break;
|
|
case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
|
|
Sid = (PSID)&((PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader)->SidStart;
|
|
break;
|
|
#endif
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
|
Sid = (PSID)&((PACCESS_ALLOWED_OBJECT_ACE)AceHeader)->SidStart;
|
|
break;
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
Sid = (PSID)&((PACCESS_DENIED_ACE)AceHeader)->SidStart;
|
|
break;
|
|
#if 0
|
|
case ACCESS_DENIED_CALLBACK_ACE_TYPE:
|
|
Sid = (PSID)&((PACCESS_DENIED_CALLBACK_ACE)AceHeader)->SidStart;
|
|
break;
|
|
case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
|
|
Sid = (PSID)&((PACCESS_DENIED_CALLBACK_OBJECT_ACE)AceHeader)->SidStart;
|
|
break;
|
|
#endif
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
Sid = (PSID)&((PACCESS_DENIED_OBJECT_ACE)AceHeader)->SidStart;
|
|
break;
|
|
}
|
|
|
|
return Sid;
|
|
}
|
|
|
|
static VOID
|
|
DestroySecurityPage(IN PSECURITY_PAGE sp)
|
|
{
|
|
if(sp->hiPrincipals != NULL)
|
|
{
|
|
ImageList_Destroy(sp->hiPrincipals);
|
|
}
|
|
|
|
DestroySidCacheMgr(sp->SidCacheMgr);
|
|
|
|
if (sp->OwnerSid != NULL)
|
|
LocalFree((HLOCAL)sp->OwnerSid);
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
sp);
|
|
|
|
CoUninitialize();
|
|
}
|
|
|
|
static VOID
|
|
FreePrincipalsList(IN PSECURITY_PAGE sp,
|
|
IN PPRINCIPAL_LISTITEM *PrincipalsListHead)
|
|
{
|
|
PPRINCIPAL_LISTITEM CurItem, NextItem;
|
|
PACE_ENTRY AceEntry, NextAceEntry;
|
|
|
|
CurItem = *PrincipalsListHead;
|
|
while (CurItem != NULL)
|
|
{
|
|
/* Free all ACEs */
|
|
AceEntry = CurItem->ACEs;
|
|
while (AceEntry != NULL)
|
|
{
|
|
NextAceEntry = AceEntry->Next;
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
AceEntry);
|
|
AceEntry = NextAceEntry;
|
|
}
|
|
|
|
/* free the SID string if present */
|
|
if (CurItem->SidReqResult != NULL)
|
|
{
|
|
DereferenceSidReqResult(sp->SidCacheMgr,
|
|
CurItem->SidReqResult);
|
|
}
|
|
|
|
if (CurItem->DisplayString != NULL)
|
|
{
|
|
LocalFree((HLOCAL)CurItem->DisplayString);
|
|
}
|
|
|
|
/* free the ACE list item */
|
|
NextItem = CurItem->Next;
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
CurItem);
|
|
CurItem = NextItem;
|
|
}
|
|
|
|
*PrincipalsListHead = NULL;
|
|
}
|
|
|
|
static PACE_ENTRY
|
|
AddAceToPrincipal(IN PPRINCIPAL_LISTITEM Principal,
|
|
IN PACE_HEADER AceHeader)
|
|
{
|
|
PACE_ENTRY AceEntry, *AceLink;
|
|
|
|
AceEntry = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
sizeof(ACE_ENTRY) + AceHeader->AceSize);
|
|
if (AceEntry != NULL)
|
|
{
|
|
AceEntry->Next = NULL;
|
|
|
|
/* copy the ACE */
|
|
CopyMemory(AceEntry + 1,
|
|
AceHeader,
|
|
AceHeader->AceSize);
|
|
|
|
/* append it to the list */
|
|
AceLink = &Principal->ACEs;
|
|
while (*AceLink != NULL)
|
|
{
|
|
AceLink = &(*AceLink)->Next;
|
|
}
|
|
*AceLink = AceEntry;
|
|
}
|
|
|
|
return AceEntry;
|
|
}
|
|
|
|
static PPRINCIPAL_LISTITEM
|
|
FindSidInPrincipalsListAddAce(IN PPRINCIPAL_LISTITEM PrincipalsListHead,
|
|
IN PSID Sid,
|
|
IN PACE_HEADER AceHeader)
|
|
{
|
|
PPRINCIPAL_LISTITEM CurItem;
|
|
|
|
for (CurItem = PrincipalsListHead;
|
|
CurItem != NULL;
|
|
CurItem = CurItem->Next)
|
|
{
|
|
if (EqualSid((PSID)(CurItem + 1),
|
|
Sid))
|
|
{
|
|
if (AddAceToPrincipal(CurItem,
|
|
AceHeader) != NULL)
|
|
{
|
|
return CurItem;
|
|
}
|
|
|
|
/* unable to add the ACE to the principal */
|
|
break;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static VOID
|
|
SidLookupCompletion(IN HANDLE SidCacheMgr,
|
|
IN PSID Sid,
|
|
IN PSIDREQRESULT SidRequestResult,
|
|
IN PVOID Context)
|
|
{
|
|
PSECURITY_PAGE sp = (PSECURITY_PAGE)Context;
|
|
|
|
/* NOTE: this routine may be executed in a different thread
|
|
than the GUI! */
|
|
|
|
if (SidRequestResult != NULL)
|
|
{
|
|
SIDLOOKUPNOTIFYINFO LookupInfo;
|
|
|
|
LookupInfo.nmh.hwndFrom = sp->hWnd;
|
|
LookupInfo.nmh.idFrom = 0;
|
|
LookupInfo.nmh.code = SIDN_LOOKUPSUCCEEDED;
|
|
LookupInfo.Sid = Sid;
|
|
LookupInfo.SidRequestResult = SidRequestResult;
|
|
|
|
/* notify the page that the sid lookup succeeded */
|
|
SendMessage(sp->hWnd,
|
|
WM_NOTIFY,
|
|
(WPARAM)LookupInfo.nmh.idFrom,
|
|
(LPARAM)&LookupInfo.nmh);
|
|
}
|
|
}
|
|
|
|
static PPRINCIPAL_LISTITEM
|
|
AddPrincipalToList(IN PSECURITY_PAGE sp,
|
|
IN PSID Sid,
|
|
IN PACE_HEADER AceHeader,
|
|
OUT BOOL *LookupDeferred OPTIONAL)
|
|
{
|
|
PPRINCIPAL_LISTITEM PrincipalListItem = NULL, *PrincipalLink;
|
|
PACE_ENTRY AceEntry;
|
|
BOOL Deferred = FALSE;
|
|
|
|
if (!FindSidInPrincipalsListAddAce(sp->PrincipalsListHead,
|
|
Sid,
|
|
AceHeader))
|
|
{
|
|
DWORD SidLength;
|
|
|
|
PrincipalLink = &sp->PrincipalsListHead;
|
|
while (*PrincipalLink != NULL)
|
|
{
|
|
PrincipalLink = &(*PrincipalLink)->Next;
|
|
}
|
|
|
|
SidLength = GetLengthSid(Sid);
|
|
|
|
/* allocate the principal */
|
|
PrincipalListItem = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
sizeof(PRINCIPAL_LISTITEM) + SidLength);
|
|
if (PrincipalListItem != NULL)
|
|
{
|
|
PrincipalListItem->DisplayString = NULL;
|
|
PrincipalListItem->SidReqResult = NULL;
|
|
|
|
CopySid(SidLength,
|
|
(PSID)(PrincipalListItem + 1),
|
|
Sid);
|
|
|
|
/* allocate some memory for the ACE and copy it */
|
|
AceEntry = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
sizeof(ACE_ENTRY) + AceHeader->AceSize);
|
|
if (AceEntry != NULL)
|
|
{
|
|
AceEntry->Next = NULL;
|
|
CopyMemory(AceEntry + 1,
|
|
AceHeader,
|
|
AceHeader->AceSize);
|
|
|
|
/* add the ACE to the list */
|
|
PrincipalListItem->ACEs = AceEntry;
|
|
|
|
PrincipalListItem->Next = NULL;
|
|
|
|
/* append item to the principals list */
|
|
*PrincipalLink = PrincipalListItem;
|
|
|
|
/* lookup the SID now */
|
|
Deferred = !LookupSidCache(sp->SidCacheMgr,
|
|
Sid,
|
|
SidLookupCompletion,
|
|
sp);
|
|
}
|
|
else
|
|
{
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
PrincipalListItem);
|
|
PrincipalListItem = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (PrincipalListItem != NULL && LookupDeferred != NULL)
|
|
{
|
|
*LookupDeferred = Deferred;
|
|
}
|
|
|
|
return PrincipalListItem;
|
|
}
|
|
|
|
static LPWSTR
|
|
GetDisplayStringFromSidRequestResult(IN PSIDREQRESULT SidReqResult)
|
|
{
|
|
LPWSTR lpDisplayString = NULL;
|
|
|
|
if (SidReqResult->SidNameUse == SidTypeUser ||
|
|
SidReqResult->SidNameUse == SidTypeGroup)
|
|
{
|
|
LoadAndFormatString(hDllInstance,
|
|
IDS_USERDOMAINFORMAT,
|
|
&lpDisplayString,
|
|
SidReqResult->AccountName,
|
|
SidReqResult->DomainName,
|
|
SidReqResult->AccountName);
|
|
}
|
|
else
|
|
{
|
|
LoadAndFormatString(hDllInstance,
|
|
IDS_USERFORMAT,
|
|
&lpDisplayString,
|
|
SidReqResult->AccountName);
|
|
}
|
|
|
|
return lpDisplayString;
|
|
}
|
|
|
|
static LPWSTR
|
|
GetPrincipalDisplayString(IN PPRINCIPAL_LISTITEM PrincipalListItem)
|
|
{
|
|
LPWSTR lpDisplayString = NULL;
|
|
|
|
if (PrincipalListItem->SidReqResult != NULL)
|
|
{
|
|
lpDisplayString = GetDisplayStringFromSidRequestResult(PrincipalListItem->SidReqResult);
|
|
}
|
|
else
|
|
{
|
|
ConvertSidToStringSidW((PSID)(PrincipalListItem + 1),
|
|
&lpDisplayString);
|
|
}
|
|
|
|
return lpDisplayString;
|
|
}
|
|
|
|
static LPWSTR
|
|
GetPrincipalAccountNameString(IN PPRINCIPAL_LISTITEM PrincipalListItem)
|
|
{
|
|
LPWSTR lpDisplayString = NULL;
|
|
|
|
if (PrincipalListItem->SidReqResult != NULL)
|
|
{
|
|
LoadAndFormatString(hDllInstance,
|
|
IDS_USERFORMAT,
|
|
&lpDisplayString,
|
|
PrincipalListItem->SidReqResult->AccountName);
|
|
}
|
|
else
|
|
{
|
|
ConvertSidToStringSid((PSID)(PrincipalListItem + 1),
|
|
&lpDisplayString);
|
|
}
|
|
|
|
return lpDisplayString;
|
|
}
|
|
|
|
static VOID
|
|
CreatePrincipalListItem(OUT LVITEM *li,
|
|
IN PSECURITY_PAGE sp,
|
|
IN PPRINCIPAL_LISTITEM PrincipalListItem,
|
|
IN INT Index,
|
|
IN BOOL Selected)
|
|
{
|
|
INT ImageIndex = 2;
|
|
|
|
if (PrincipalListItem->SidReqResult != NULL)
|
|
{
|
|
switch (PrincipalListItem->SidReqResult->SidNameUse)
|
|
{
|
|
case SidTypeUser:
|
|
ImageIndex = 0;
|
|
break;
|
|
case SidTypeWellKnownGroup:
|
|
case SidTypeGroup:
|
|
ImageIndex = 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
li->mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
|
|
li->iItem = Index;
|
|
li->iSubItem = 0;
|
|
li->state = (Selected ? LVIS_SELECTED : 0);
|
|
li->stateMask = LVIS_SELECTED;
|
|
li->pszText = PrincipalListItem->DisplayString;
|
|
li->iImage = ImageIndex;
|
|
li->lParam = (LPARAM)PrincipalListItem;
|
|
}
|
|
|
|
static INT
|
|
AddPrincipalListEntry(IN PSECURITY_PAGE sp,
|
|
IN PPRINCIPAL_LISTITEM PrincipalListItem,
|
|
IN INT Index,
|
|
IN BOOL Selected)
|
|
{
|
|
LVITEM li;
|
|
INT Ret;
|
|
|
|
if (PrincipalListItem->DisplayString != NULL)
|
|
{
|
|
LocalFree((HLOCAL)PrincipalListItem->DisplayString);
|
|
}
|
|
PrincipalListItem->DisplayString = GetPrincipalDisplayString(PrincipalListItem);
|
|
|
|
CreatePrincipalListItem(&li,
|
|
sp,
|
|
PrincipalListItem,
|
|
Index,
|
|
Selected);
|
|
|
|
Ret = ListView_InsertItem(sp->hWndPrincipalsList,
|
|
&li);
|
|
|
|
return Ret;
|
|
}
|
|
|
|
static int CALLBACK
|
|
PrincipalCompare(IN LPARAM lParam1,
|
|
IN LPARAM lParam2,
|
|
IN LPARAM lParamSort)
|
|
{
|
|
PPRINCIPAL_LISTITEM Item1 = (PPRINCIPAL_LISTITEM)lParam1;
|
|
PPRINCIPAL_LISTITEM Item2 = (PPRINCIPAL_LISTITEM)lParam2;
|
|
|
|
if (Item1->DisplayString != NULL && Item2->DisplayString != NULL)
|
|
{
|
|
return wcscmp(Item1->DisplayString,
|
|
Item2->DisplayString);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static VOID
|
|
UpdatePrincipalListItem(IN PSECURITY_PAGE sp,
|
|
IN INT PrincipalIndex,
|
|
IN PPRINCIPAL_LISTITEM PrincipalListItem,
|
|
IN PSIDREQRESULT SidReqResult)
|
|
{
|
|
LVITEM li;
|
|
|
|
/* replace the request result structure */
|
|
if (PrincipalListItem->SidReqResult != NULL)
|
|
{
|
|
DereferenceSidReqResult(sp->SidCacheMgr,
|
|
PrincipalListItem->SidReqResult);
|
|
}
|
|
|
|
ReferenceSidReqResult(sp->SidCacheMgr,
|
|
SidReqResult);
|
|
PrincipalListItem->SidReqResult = SidReqResult;
|
|
|
|
/* update the display string */
|
|
if (PrincipalListItem->DisplayString != NULL)
|
|
{
|
|
LocalFree((HLOCAL)PrincipalListItem->DisplayString);
|
|
}
|
|
PrincipalListItem->DisplayString = GetPrincipalDisplayString(PrincipalListItem);
|
|
|
|
/* update the list item */
|
|
CreatePrincipalListItem(&li,
|
|
sp,
|
|
PrincipalListItem,
|
|
PrincipalIndex,
|
|
FALSE);
|
|
|
|
/* don't change the list item state */
|
|
li.mask &= ~(LVIF_STATE | LVIF_PARAM);
|
|
|
|
(void)ListView_SetItem(sp->hWndPrincipalsList,
|
|
&li);
|
|
|
|
/* sort the principals list view again */
|
|
(void)ListView_SortItems(sp->hWndPrincipalsList,
|
|
PrincipalCompare,
|
|
(LPARAM)sp);
|
|
}
|
|
|
|
static VOID
|
|
ReloadPrincipalsList(IN PSECURITY_PAGE sp)
|
|
{
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
|
BOOL DaclPresent, DaclDefaulted, OwnerDefaulted;
|
|
PACL Dacl = NULL;
|
|
PSID OwnerSid = NULL;
|
|
LPTSTR OwnerSidString;
|
|
DWORD SidLen;
|
|
HRESULT hRet;
|
|
|
|
/* delete the cached ACL */
|
|
FreePrincipalsList(sp,
|
|
&sp->PrincipalsListHead);
|
|
|
|
/* query the ACL */
|
|
hRet = sp->psi->lpVtbl->GetSecurity(sp->psi,
|
|
DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
|
|
&SecurityDescriptor,
|
|
FALSE);
|
|
if (SUCCEEDED(hRet) && SecurityDescriptor != NULL)
|
|
{
|
|
if (GetSecurityDescriptorOwner(SecurityDescriptor,
|
|
&OwnerSid,
|
|
&OwnerDefaulted))
|
|
{
|
|
sp->OwnerDefaulted = OwnerDefaulted;
|
|
if (sp->OwnerSid != NULL)
|
|
{
|
|
LocalFree((HLOCAL)sp->OwnerSid);
|
|
sp->OwnerSid = NULL;
|
|
}
|
|
|
|
SidLen = GetLengthSid(OwnerSid);
|
|
if (SidLen == 0)
|
|
goto ClearOwner;
|
|
|
|
sp->OwnerSid = (PSID)LocalAlloc(LMEM_FIXED,
|
|
SidLen);
|
|
if (sp->OwnerSid != NULL)
|
|
{
|
|
if (CopySid(SidLen,
|
|
sp->OwnerSid,
|
|
OwnerSid))
|
|
{
|
|
/* Lookup the SID now */
|
|
if (!LookupSidCache(sp->SidCacheMgr,
|
|
sp->OwnerSid,
|
|
SidLookupCompletion,
|
|
sp))
|
|
{
|
|
/* Lookup was deferred */
|
|
if (ConvertSidToStringSid(sp->OwnerSid,
|
|
&OwnerSidString))
|
|
{
|
|
SetDlgItemText(sp->hWnd,
|
|
IDC_OWNER,
|
|
OwnerSidString);
|
|
LocalFree((HLOCAL)OwnerSidString);
|
|
}
|
|
else
|
|
goto ClearOwner;
|
|
}
|
|
}
|
|
else
|
|
goto ClearOwner;
|
|
}
|
|
else
|
|
goto ClearOwner;
|
|
}
|
|
else
|
|
{
|
|
ClearOwner:
|
|
SetDlgItemText(sp->hWnd,
|
|
IDC_OWNER,
|
|
NULL);
|
|
}
|
|
|
|
if (GetSecurityDescriptorDacl(SecurityDescriptor,
|
|
&DaclPresent,
|
|
&Dacl,
|
|
&DaclDefaulted) &&
|
|
DaclPresent && Dacl != NULL)
|
|
{
|
|
PSID Sid;
|
|
PACE_HEADER AceHeader;
|
|
ULONG AceIndex;
|
|
|
|
for (AceIndex = 0;
|
|
AceIndex < Dacl->AceCount;
|
|
AceIndex++)
|
|
{
|
|
if (GetAce(Dacl,
|
|
AceIndex,
|
|
(LPVOID*)&AceHeader) &&
|
|
AceHeader != NULL)
|
|
{
|
|
BOOL LookupDeferred;
|
|
PPRINCIPAL_LISTITEM PrincipalListItem;
|
|
|
|
Sid = AceHeaderToSID(AceHeader);
|
|
|
|
PrincipalListItem = AddPrincipalToList(sp,
|
|
Sid,
|
|
AceHeader,
|
|
&LookupDeferred);
|
|
|
|
if (PrincipalListItem != NULL && LookupDeferred)
|
|
{
|
|
AddPrincipalListEntry(sp,
|
|
PrincipalListItem,
|
|
-1,
|
|
FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
LocalFree((HLOCAL)SecurityDescriptor);
|
|
}
|
|
}
|
|
|
|
static VOID
|
|
UpdateControlStates(IN PSECURITY_PAGE sp)
|
|
{
|
|
PPRINCIPAL_LISTITEM Selected = (PPRINCIPAL_LISTITEM)ListViewGetSelectedItemData(sp->hWndPrincipalsList);
|
|
|
|
EnableWindow(sp->hBtnRemove,
|
|
Selected != NULL);
|
|
EnableWindow(sp->hAceCheckList,
|
|
Selected != NULL);
|
|
|
|
if (Selected != NULL)
|
|
{
|
|
LPWSTR szLabel;
|
|
LPWSTR szDisplayString;
|
|
|
|
szDisplayString = GetPrincipalAccountNameString(Selected);
|
|
if (LoadAndFormatString(hDllInstance,
|
|
IDS_PERMISSIONS_FOR,
|
|
&szLabel,
|
|
szDisplayString))
|
|
{
|
|
SetWindowText(sp->hPermissionsForLabel,
|
|
szLabel);
|
|
|
|
LocalFree((HLOCAL)szLabel);
|
|
}
|
|
|
|
LocalFree((HLOCAL)szDisplayString);
|
|
|
|
/* FIXME - update the checkboxes */
|
|
}
|
|
else
|
|
{
|
|
WCHAR szPermissions[255];
|
|
|
|
if (LoadString(hDllInstance,
|
|
IDS_PERMISSIONS,
|
|
szPermissions,
|
|
sizeof(szPermissions) / sizeof(szPermissions[0])))
|
|
{
|
|
SetWindowText(sp->hPermissionsForLabel,
|
|
szPermissions);
|
|
}
|
|
|
|
SendMessage(sp->hAceCheckList,
|
|
CLM_CLEARCHECKBOXES,
|
|
0,
|
|
0);
|
|
}
|
|
}
|
|
|
|
static void
|
|
UpdatePrincipalInfo(IN PSECURITY_PAGE sp,
|
|
IN PSIDLOOKUPNOTIFYINFO LookupInfo)
|
|
{
|
|
PPRINCIPAL_LISTITEM CurItem;
|
|
LPWSTR DisplayName;
|
|
|
|
if (sp->OwnerSid != NULL &&
|
|
EqualSid(sp->OwnerSid,
|
|
LookupInfo->Sid))
|
|
{
|
|
if (LookupInfo->SidRequestResult != NULL)
|
|
DisplayName = GetDisplayStringFromSidRequestResult(LookupInfo->SidRequestResult);
|
|
else if (!ConvertSidToStringSidW(LookupInfo->Sid,
|
|
&DisplayName))
|
|
{
|
|
DisplayName = NULL;
|
|
}
|
|
|
|
if (DisplayName != NULL)
|
|
{
|
|
SetDlgItemTextW(sp->hWnd,
|
|
IDC_OWNER,
|
|
DisplayName);
|
|
|
|
LocalFree((HLOCAL)DisplayName);
|
|
}
|
|
}
|
|
|
|
for (CurItem = sp->PrincipalsListHead;
|
|
CurItem != NULL;
|
|
CurItem = CurItem->Next)
|
|
{
|
|
if (EqualSid((PSID)(CurItem + 1),
|
|
LookupInfo->Sid))
|
|
{
|
|
INT PrincipalIndex;
|
|
LVFINDINFO lvfi;
|
|
|
|
/* find the principal in the list */
|
|
lvfi.flags = LVFI_PARAM;
|
|
lvfi.lParam = (LPARAM)CurItem;
|
|
PrincipalIndex = ListView_FindItem(sp->hWndPrincipalsList,
|
|
-1,
|
|
&lvfi);
|
|
|
|
if (PrincipalIndex != -1)
|
|
{
|
|
/* update the principal in the list view control */
|
|
UpdatePrincipalListItem(sp,
|
|
PrincipalIndex,
|
|
CurItem,
|
|
LookupInfo->SidRequestResult);
|
|
|
|
if (ListViewGetSelectedItemData(sp->hWndPrincipalsList) == (LPARAM)CurItem)
|
|
{
|
|
UpdateControlStates(sp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AddPrincipalListEntry(sp,
|
|
CurItem,
|
|
-1,
|
|
FALSE);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static UINT CALLBACK
|
|
SecurityPageCallback(IN HWND hwnd,
|
|
IN UINT uMsg,
|
|
IN LPPROPSHEETPAGE ppsp)
|
|
{
|
|
PSECURITY_PAGE sp = (PSECURITY_PAGE)ppsp->lParam;
|
|
|
|
switch (uMsg)
|
|
{
|
|
case PSPCB_CREATE:
|
|
{
|
|
return TRUE;
|
|
}
|
|
case PSPCB_RELEASE:
|
|
{
|
|
DestroySecurityPage(sp);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static VOID
|
|
SetAceCheckListColumns(IN HWND hAceCheckList,
|
|
IN UINT Button,
|
|
IN HWND hLabel)
|
|
{
|
|
POINT pt;
|
|
RECT rcLabel;
|
|
|
|
GetWindowRect(hLabel,
|
|
&rcLabel);
|
|
pt.y = 0;
|
|
pt.x = (rcLabel.right - rcLabel.left) / 2;
|
|
MapWindowPoints(hLabel,
|
|
hAceCheckList,
|
|
&pt,
|
|
1);
|
|
|
|
SendMessage(hAceCheckList,
|
|
CLM_SETCHECKBOXCOLUMN,
|
|
Button,
|
|
pt.x);
|
|
}
|
|
|
|
static VOID
|
|
LoadPermissionsList(IN PSECURITY_PAGE sp,
|
|
IN GUID *GuidObjectType,
|
|
IN DWORD dwFlags,
|
|
OUT SI_ACCESS *DefaultAccess)
|
|
{
|
|
HRESULT hRet;
|
|
PSI_ACCESS AccessList;
|
|
ULONG nAccessList, DefaultAccessIndex;
|
|
WCHAR szSpecialPermissions[255];
|
|
BOOLEAN SpecialPermissionsPresent = FALSE;
|
|
ACCESS_MASK SpecialPermissionsMask = 0;
|
|
|
|
/* clear the permissions list */
|
|
|
|
SendMessage(sp->hAceCheckList,
|
|
CLM_CLEAR,
|
|
0,
|
|
0);
|
|
|
|
/* query the access rights from the server */
|
|
hRet = sp->psi->lpVtbl->GetAccessRights(sp->psi,
|
|
GuidObjectType,
|
|
dwFlags, /* FIXME */
|
|
&AccessList,
|
|
&nAccessList,
|
|
&DefaultAccessIndex);
|
|
if (SUCCEEDED(hRet) && nAccessList != 0)
|
|
{
|
|
LPCWSTR NameStr;
|
|
PSI_ACCESS CurAccess, LastAccess;
|
|
WCHAR NameBuffer[MAX_PATH];
|
|
|
|
/* save the default access rights to be used when adding ACEs later */
|
|
if (DefaultAccess != NULL)
|
|
{
|
|
*DefaultAccess = AccessList[DefaultAccessIndex];
|
|
}
|
|
|
|
LastAccess = AccessList + nAccessList;
|
|
for (CurAccess = &AccessList[0];
|
|
CurAccess != LastAccess;
|
|
CurAccess++)
|
|
{
|
|
if (CurAccess->dwFlags & dwFlags)
|
|
{
|
|
/* get the permission name, load it from a string table if necessary */
|
|
if (IS_INTRESOURCE(CurAccess->pszName))
|
|
{
|
|
if (!LoadString(sp->ObjectInfo.hInstance,
|
|
(UINT)((ULONG_PTR)CurAccess->pszName),
|
|
NameBuffer,
|
|
sizeof(NameBuffer) / sizeof(NameBuffer[0])))
|
|
{
|
|
LoadString(hDllInstance,
|
|
IDS_UNKNOWN,
|
|
NameBuffer,
|
|
sizeof(NameBuffer) / sizeof(NameBuffer[0]));
|
|
}
|
|
NameStr = NameBuffer;
|
|
}
|
|
else
|
|
{
|
|
NameStr = CurAccess->pszName;
|
|
}
|
|
|
|
SendMessage(sp->hAceCheckList,
|
|
CLM_ADDITEM,
|
|
(WPARAM)CurAccess->mask,
|
|
(LPARAM)NameStr);
|
|
}
|
|
else if (CurAccess->dwFlags & SI_ACCESS_SPECIFIC)
|
|
{
|
|
SpecialPermissionsPresent = TRUE;
|
|
SpecialPermissionsMask |= CurAccess->mask;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* add the special permissions check item in case the specific access rights
|
|
aren't displayed */
|
|
if (SpecialPermissionsPresent &&
|
|
LoadString(hDllInstance,
|
|
IDS_SPECIAL_PERMISSIONS,
|
|
szSpecialPermissions,
|
|
sizeof(szSpecialPermissions) / sizeof(szSpecialPermissions[0])))
|
|
{
|
|
/* add the special permissions check item */
|
|
sp->SpecialPermCheckIndex = (INT)SendMessage(sp->hAceCheckList,
|
|
CLM_ADDITEM,
|
|
(WPARAM)SpecialPermissionsMask,
|
|
(LPARAM)szSpecialPermissions);
|
|
if (sp->SpecialPermCheckIndex != -1)
|
|
{
|
|
SendMessage(sp->hAceCheckList,
|
|
CLM_SETITEMSTATE,
|
|
(WPARAM)sp->SpecialPermCheckIndex,
|
|
CIS_ALLOWDISABLED | CIS_DENYDISABLED | CIS_NONE);
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID
|
|
ResizeControls(IN PSECURITY_PAGE sp,
|
|
IN INT Width,
|
|
IN INT Height)
|
|
{
|
|
HWND hWndAllow, hWndDeny, hWndOwnerEdit;
|
|
RECT rcControl, rcControl2, rcControl3, rcWnd;
|
|
INT cxWidth, cxEdge, btnSpacing;
|
|
POINT pt, pt2;
|
|
HDWP dwp;
|
|
INT nControls = 8;
|
|
LVCOLUMN lvc;
|
|
|
|
hWndAllow = GetDlgItem(sp->hWnd,
|
|
IDC_LABEL_ALLOW);
|
|
hWndDeny = GetDlgItem(sp->hWnd,
|
|
IDC_LABEL_DENY);
|
|
|
|
GetWindowRect(sp->hWnd,
|
|
&rcWnd);
|
|
|
|
cxEdge = GetSystemMetrics(SM_CXEDGE);
|
|
|
|
/* use the left margin of the principal list view control for all control
|
|
margins */
|
|
pt.x = 0;
|
|
pt.y = 0;
|
|
MapWindowPoints(sp->hWndPrincipalsList,
|
|
sp->hWnd,
|
|
&pt,
|
|
1);
|
|
cxWidth = Width - (2 * pt.x);
|
|
|
|
if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
|
|
{
|
|
nControls += 2;
|
|
}
|
|
|
|
if ((dwp = BeginDeferWindowPos(nControls)))
|
|
{
|
|
/* resize the owner edit field */
|
|
hWndOwnerEdit = GetDlgItem(sp->hWnd,
|
|
IDC_OWNER);
|
|
GetWindowRect(hWndOwnerEdit,
|
|
&rcControl);
|
|
pt2.x = 0;
|
|
pt2.y = 0;
|
|
MapWindowPoints(hWndOwnerEdit,
|
|
sp->hWnd,
|
|
&pt2,
|
|
1);
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
hWndOwnerEdit,
|
|
NULL,
|
|
0,
|
|
0,
|
|
Width - pt.x - pt2.x,
|
|
rcControl.bottom - rcControl.top,
|
|
SWP_NOMOVE | SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
|
|
/* resize the Principal list view */
|
|
GetWindowRect(sp->hWndPrincipalsList,
|
|
&rcControl);
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
sp->hWndPrincipalsList,
|
|
NULL,
|
|
0,
|
|
0,
|
|
cxWidth,
|
|
rcControl.bottom - rcControl.top,
|
|
SWP_NOMOVE | SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
|
|
/* move the Add Principal button */
|
|
GetWindowRect(sp->hBtnAdd,
|
|
&rcControl);
|
|
GetWindowRect(sp->hBtnRemove,
|
|
&rcControl2);
|
|
btnSpacing = rcControl2.left - rcControl.right;
|
|
pt2.x = 0;
|
|
pt2.y = 0;
|
|
MapWindowPoints(sp->hBtnAdd,
|
|
sp->hWnd,
|
|
&pt2,
|
|
1);
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
sp->hBtnAdd,
|
|
NULL,
|
|
pt.x + cxWidth - (rcControl2.right - rcControl2.left) -
|
|
(rcControl.right - rcControl.left) -
|
|
btnSpacing - cxEdge,
|
|
pt2.y,
|
|
0,
|
|
0,
|
|
SWP_NOSIZE | SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
|
|
/* move the Delete Principal button */
|
|
pt2.x = 0;
|
|
pt2.y = 0;
|
|
MapWindowPoints(sp->hBtnRemove,
|
|
sp->hWnd,
|
|
&pt2,
|
|
1);
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
sp->hBtnRemove,
|
|
NULL,
|
|
pt.x + cxWidth - (rcControl2.right - rcControl2.left) - cxEdge,
|
|
pt2.y,
|
|
0,
|
|
0,
|
|
SWP_NOSIZE | SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
|
|
/* move the Permissions For label */
|
|
GetWindowRect(hWndAllow,
|
|
&rcControl);
|
|
GetWindowRect(hWndDeny,
|
|
&rcControl2);
|
|
GetWindowRect(sp->hPermissionsForLabel,
|
|
&rcControl3);
|
|
pt2.x = 0;
|
|
pt2.y = 0;
|
|
MapWindowPoints(sp->hPermissionsForLabel,
|
|
sp->hWnd,
|
|
&pt2,
|
|
1);
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
sp->hPermissionsForLabel,
|
|
NULL,
|
|
0,
|
|
0,
|
|
cxWidth - (rcControl2.right - rcControl2.left) -
|
|
(rcControl.right - rcControl.left) -
|
|
(2 * btnSpacing) - cxEdge,
|
|
rcControl3.bottom - rcControl3.top,
|
|
SWP_NOMOVE | SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
|
|
/* move the Allow label */
|
|
pt2.x = 0;
|
|
pt2.y = 0;
|
|
MapWindowPoints(hWndAllow,
|
|
sp->hWnd,
|
|
&pt2,
|
|
1);
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
hWndAllow,
|
|
NULL,
|
|
cxWidth - (rcControl2.right - rcControl2.left) -
|
|
(rcControl.right - rcControl.left) -
|
|
btnSpacing - cxEdge,
|
|
pt2.y,
|
|
0,
|
|
0,
|
|
SWP_NOSIZE | SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
|
|
/* move the Deny label */
|
|
pt2.x = 0;
|
|
pt2.y = 0;
|
|
MapWindowPoints(hWndDeny,
|
|
sp->hWnd,
|
|
&pt2,
|
|
1);
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
hWndDeny,
|
|
NULL,
|
|
cxWidth - (rcControl2.right - rcControl2.left) - cxEdge,
|
|
pt2.y,
|
|
0,
|
|
0,
|
|
SWP_NOSIZE | SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
|
|
/* resize the Permissions check list box */
|
|
GetWindowRect(sp->hAceCheckList,
|
|
&rcControl);
|
|
GetWindowRect(sp->hBtnAdvanced,
|
|
&rcControl2);
|
|
GetWindowRect(GetDlgItem(sp->hWnd,
|
|
IDC_LABEL_ADVANCED),
|
|
&rcControl3);
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
sp->hAceCheckList,
|
|
NULL,
|
|
0,
|
|
0,
|
|
cxWidth,
|
|
((sp->ObjectInfo.dwFlags & SI_ADVANCED) ?
|
|
Height - (rcControl.top - rcWnd.top) -
|
|
(rcControl3.bottom - rcControl3.top) - pt.x - btnSpacing :
|
|
Height - (rcControl.top - rcWnd.top) - pt.x),
|
|
SWP_NOMOVE | SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
|
|
if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
|
|
{
|
|
/* move and resize the Advanced label */
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
GetDlgItem(sp->hWnd,
|
|
IDC_LABEL_ADVANCED),
|
|
NULL,
|
|
pt.x,
|
|
Height - (rcControl3.bottom - rcControl3.top) - pt.x,
|
|
cxWidth - (rcControl2.right - rcControl2.left) - cxEdge,
|
|
rcControl3.bottom - rcControl3.top,
|
|
SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
|
|
/* move and resize the Advanced button */
|
|
if (!(dwp = DeferWindowPos(dwp,
|
|
sp->hBtnAdvanced,
|
|
NULL,
|
|
cxWidth - (rcControl2.right - rcControl2.left) + pt.x,
|
|
Height - (rcControl2.bottom - rcControl2.top) - pt.x,
|
|
0,
|
|
0,
|
|
SWP_NOSIZE | SWP_NOZORDER)))
|
|
{
|
|
goto EndDeferWnds;
|
|
}
|
|
}
|
|
|
|
EndDeferWindowPos(dwp);
|
|
}
|
|
|
|
EndDeferWnds:
|
|
/* update the width of the principal list view column */
|
|
GetClientRect(sp->hWndPrincipalsList,
|
|
&rcControl);
|
|
lvc.mask = LVCF_WIDTH;
|
|
lvc.cx = rcControl.right;
|
|
(void)ListView_SetColumn(sp->hWndPrincipalsList,
|
|
0,
|
|
&lvc);
|
|
|
|
/* calculate the columns of the allow/deny checkboxes */
|
|
SetAceCheckListColumns(sp->hAceCheckList,
|
|
CLB_ALLOW,
|
|
hWndAllow);
|
|
SetAceCheckListColumns(sp->hAceCheckList,
|
|
CLB_DENY,
|
|
hWndDeny);
|
|
}
|
|
|
|
static PACE_HEADER
|
|
BuildDefaultPrincipalAce(IN PSECURITY_PAGE sp,
|
|
IN PSID pSid)
|
|
{
|
|
PACCESS_ALLOWED_ACE Ace;
|
|
DWORD SidLen;
|
|
WORD AceSize;
|
|
|
|
SidLen = GetLengthSid(pSid);
|
|
AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE,
|
|
SidStart) + (WORD)SidLen;
|
|
Ace = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
AceSize);
|
|
if (Ace != NULL)
|
|
{
|
|
Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
|
|
Ace->Header.AceFlags = 0; /* FIXME */
|
|
Ace->Header.AceSize = AceSize;
|
|
Ace->Mask = sp->DefaultAccess.mask;
|
|
|
|
if (CopySid(SidLen,
|
|
(PSID)&Ace->SidStart,
|
|
pSid))
|
|
{
|
|
return &Ace->Header;
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
Ace);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static BOOL
|
|
AddSelectedPrincipal(IN IDsObjectPicker *pDsObjectPicker,
|
|
IN HWND hwndParent OPTIONAL,
|
|
IN PSID pSid,
|
|
IN PVOID Context OPTIONAL)
|
|
{
|
|
PACE_HEADER AceHeader;
|
|
PSECURITY_PAGE sp = (PSECURITY_PAGE)Context;
|
|
|
|
AceHeader = BuildDefaultPrincipalAce(sp,
|
|
pSid);
|
|
if (AceHeader != NULL)
|
|
{
|
|
PPRINCIPAL_LISTITEM PrincipalListItem;
|
|
BOOL LookupDeferred;
|
|
|
|
PrincipalListItem = AddPrincipalToList(sp,
|
|
pSid,
|
|
AceHeader,
|
|
&LookupDeferred);
|
|
|
|
if (PrincipalListItem != NULL && LookupDeferred)
|
|
{
|
|
AddPrincipalListEntry(sp,
|
|
PrincipalListItem,
|
|
-1,
|
|
FALSE);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
AceHeader);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static INT_PTR CALLBACK
|
|
SecurityPageProc(IN HWND hwndDlg,
|
|
IN UINT uMsg,
|
|
IN WPARAM wParam,
|
|
IN LPARAM lParam)
|
|
{
|
|
PSECURITY_PAGE sp;
|
|
INT_PTR Ret = FALSE;
|
|
|
|
sp = (PSECURITY_PAGE)GetWindowLongPtr(hwndDlg, DWLP_USER);
|
|
if (sp != NULL || uMsg == WM_INITDIALOG)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_NOTIFY:
|
|
{
|
|
NMHDR *pnmh = (NMHDR*)lParam;
|
|
|
|
if (pnmh->hwndFrom == sp->hWndPrincipalsList)
|
|
{
|
|
switch (pnmh->code)
|
|
{
|
|
case LVN_ITEMCHANGED:
|
|
{
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
|
|
|
|
if ((pnmv->uChanged & LVIF_STATE) &&
|
|
((pnmv->uOldState & (LVIS_FOCUSED | LVIS_SELECTED)) ||
|
|
(pnmv->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))))
|
|
{
|
|
UpdateControlStates(sp);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (pnmh->hwndFrom == sp->hAceCheckList)
|
|
{
|
|
switch (pnmh->code)
|
|
{
|
|
case CLN_CHANGINGITEMCHECKBOX:
|
|
{
|
|
PNMCHANGEITEMCHECKBOX pcicb = (PNMCHANGEITEMCHECKBOX)lParam;
|
|
|
|
/* make sure only one of both checkboxes is only checked
|
|
at the same time */
|
|
if (pcicb->Checked)
|
|
{
|
|
pcicb->NewState &= ~((pcicb->CheckBox != CLB_DENY) ? CIS_DENY : CIS_ALLOW);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (pnmh->hwndFrom == sp->hWnd)
|
|
{
|
|
switch(pnmh->code)
|
|
{
|
|
case SIDN_LOOKUPSUCCEEDED:
|
|
{
|
|
PSIDLOOKUPNOTIFYINFO LookupInfo = CONTAINING_RECORD(lParam,
|
|
SIDLOOKUPNOTIFYINFO,
|
|
nmh);
|
|
|
|
/* a SID lookup succeeded, update the information */
|
|
UpdatePrincipalInfo(sp,
|
|
LookupInfo);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_ADD_PRINCIPAL:
|
|
{
|
|
HRESULT hRet;
|
|
|
|
hRet = InitializeObjectPicker(sp->ServerName,
|
|
&sp->ObjectInfo,
|
|
&sp->pDsObjectPicker);
|
|
if (SUCCEEDED(hRet))
|
|
{
|
|
hRet = InvokeObjectPickerDialog(sp->pDsObjectPicker,
|
|
hwndDlg,
|
|
AddSelectedPrincipal,
|
|
sp);
|
|
if (FAILED(hRet))
|
|
{
|
|
MessageBox(hwndDlg, L"InvokeObjectPickerDialog failed!\n", NULL, 0);
|
|
}
|
|
|
|
/* delete the instance */
|
|
FreeObjectPicker(sp->pDsObjectPicker);
|
|
}
|
|
else
|
|
{
|
|
MessageBox(hwndDlg, L"InitializeObjectPicker failed!\n", NULL, 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case IDC_REMOVE_PRINCIPAL:
|
|
{
|
|
PPRINCIPAL_LISTITEM SelectedPrincipal;
|
|
|
|
SelectedPrincipal = (PPRINCIPAL_LISTITEM)ListViewGetSelectedItemData(sp->hWndPrincipalsList);
|
|
if (SelectedPrincipal != NULL)
|
|
{
|
|
/* FIXME */
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_SIZE:
|
|
{
|
|
ResizeControls(sp,
|
|
(INT)LOWORD(lParam),
|
|
(INT)HIWORD(lParam));
|
|
break;
|
|
}
|
|
|
|
case WM_INITDIALOG:
|
|
{
|
|
sp = (PSECURITY_PAGE)((LPPROPSHEETPAGE)lParam)->lParam;
|
|
if(sp != NULL)
|
|
{
|
|
LV_COLUMN lvc;
|
|
RECT rcLvClient;
|
|
|
|
sp->hWnd = hwndDlg;
|
|
sp->hWndPrincipalsList = GetDlgItem(hwndDlg, IDC_PRINCIPALS);
|
|
sp->hBtnAdd = GetDlgItem(hwndDlg, IDC_ADD_PRINCIPAL);
|
|
sp->hBtnRemove = GetDlgItem(hwndDlg, IDC_REMOVE_PRINCIPAL);
|
|
sp->hBtnAdvanced = GetDlgItem(hwndDlg, IDC_ADVANCED);
|
|
sp->hAceCheckList = GetDlgItem(hwndDlg, IDC_ACE_CHECKLIST);
|
|
sp->hPermissionsForLabel = GetDlgItem(hwndDlg, IDC_LABEL_PERMISSIONS_FOR);
|
|
|
|
sp->SpecialPermCheckIndex = -1;
|
|
|
|
/* save the pointer to the structure */
|
|
SetWindowLongPtr(hwndDlg, DWLP_USER, (DWORD_PTR)sp);
|
|
|
|
(void)ListView_SetExtendedListViewStyleEx(sp->hWndPrincipalsList,
|
|
LVS_EX_FULLROWSELECT,
|
|
LVS_EX_FULLROWSELECT);
|
|
|
|
sp->hiPrincipals = ImageList_Create(16,
|
|
16,
|
|
ILC_COLOR32 | ILC_MASK,
|
|
0,
|
|
3);
|
|
if (sp->hiPrincipals != NULL)
|
|
{
|
|
HBITMAP hbmImages;
|
|
|
|
hbmImages = LoadBitmap(hDllInstance,
|
|
MAKEINTRESOURCE(IDB_USRGRPIMAGES));
|
|
if (hbmImages != NULL)
|
|
{
|
|
ImageList_AddMasked(sp->hiPrincipals,
|
|
hbmImages,
|
|
RGB(255,
|
|
0,
|
|
255));
|
|
|
|
DeleteObject(hbmImages);
|
|
}
|
|
}
|
|
|
|
/* setup the listview control */
|
|
if (sp->hiPrincipals != NULL)
|
|
{
|
|
(void)ListView_SetImageList(sp->hWndPrincipalsList,
|
|
sp->hiPrincipals,
|
|
LVSIL_SMALL);
|
|
}
|
|
|
|
GetClientRect(sp->hWndPrincipalsList,
|
|
&rcLvClient);
|
|
|
|
/* add a column to the list view */
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
lvc.cx = rcLvClient.right;
|
|
(void)ListView_InsertColumn(sp->hWndPrincipalsList,
|
|
0,
|
|
&lvc);
|
|
|
|
ReloadPrincipalsList(sp);
|
|
|
|
ListViewSelectItem(sp->hWndPrincipalsList,
|
|
0);
|
|
|
|
/* calculate the columns of the allow/deny checkboxes */
|
|
SetAceCheckListColumns(sp->hAceCheckList,
|
|
CLB_ALLOW,
|
|
GetDlgItem(hwndDlg, IDC_LABEL_ALLOW));
|
|
SetAceCheckListColumns(sp->hAceCheckList,
|
|
CLB_DENY,
|
|
GetDlgItem(hwndDlg, IDC_LABEL_DENY));
|
|
|
|
LoadPermissionsList(sp,
|
|
NULL,
|
|
SI_ACCESS_GENERAL |
|
|
((sp->ObjectInfo.dwFlags & SI_CONTAINER) ? SI_ACCESS_CONTAINER : 0),
|
|
&sp->DefaultAccess);
|
|
|
|
/* hide controls in case the flags aren't present */
|
|
if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
|
|
{
|
|
/* editing the permissions is least the user can do when
|
|
the advanced button is showed */
|
|
sp->ObjectInfo.dwFlags |= SI_EDIT_PERMS;
|
|
}
|
|
else
|
|
{
|
|
ShowWindow(sp->hBtnAdvanced,
|
|
SW_HIDE);
|
|
ShowWindow(GetDlgItem(hwndDlg, IDC_LABEL_ADVANCED),
|
|
SW_HIDE);
|
|
}
|
|
|
|
/* enable quicksearch for the permissions checklist control */
|
|
SendMessage(sp->hAceCheckList,
|
|
CLM_ENABLEQUICKSEARCH,
|
|
TRUE,
|
|
0);
|
|
|
|
UpdateControlStates(sp);
|
|
}
|
|
|
|
Ret = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
|
|
/*
|
|
* CreateSecurityPage EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
HPROPSHEETPAGE
|
|
WINAPI
|
|
CreateSecurityPage(IN LPSECURITYINFO psi)
|
|
{
|
|
PROPSHEETPAGE psp = {0};
|
|
PSECURITY_PAGE sPage;
|
|
SI_OBJECT_INFO ObjectInfo = {0};
|
|
HANDLE SidCacheMgr;
|
|
LPCWSTR SystemName = NULL;
|
|
HRESULT hRet;
|
|
|
|
if (psi == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
DPRINT("No ISecurityInformation class passed!\n");
|
|
return NULL;
|
|
}
|
|
|
|
/* get the object information from the server. Zero the structure before
|
|
because some applications seem to return SUCCESS but only seem to set the
|
|
fields they care about. */
|
|
hRet = psi->lpVtbl->GetObjectInformation(psi,
|
|
&ObjectInfo);
|
|
|
|
if (FAILED(hRet))
|
|
{
|
|
SetLastError(hRet);
|
|
|
|
DPRINT("CreateSecurityPage() failed! Failed to query the object information!\n");
|
|
return NULL;
|
|
}
|
|
|
|
if ((ObjectInfo.dwFlags & SI_SERVER_IS_DC) &&
|
|
ObjectInfo.pszServerName != NULL &&
|
|
ObjectInfo.pszServerName[0] != L'\0')
|
|
{
|
|
SystemName = ObjectInfo.pszServerName;
|
|
}
|
|
|
|
SidCacheMgr = CreateSidCacheMgr(GetProcessHeap(),
|
|
SystemName);
|
|
if (SidCacheMgr == NULL)
|
|
{
|
|
DPRINT("Creating the SID cache failed!\n");
|
|
return NULL;
|
|
}
|
|
|
|
hRet = CoInitialize(NULL);
|
|
if (FAILED(hRet))
|
|
{
|
|
DestroySidCacheMgr(SidCacheMgr);
|
|
DPRINT("CoInitialize failed!\n");
|
|
return NULL;
|
|
}
|
|
|
|
sPage = HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(SECURITY_PAGE));
|
|
if (sPage == NULL)
|
|
{
|
|
DestroySidCacheMgr(SidCacheMgr);
|
|
CoUninitialize();
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
DPRINT("Not enough memory to allocate a SECURITY_PAGE!\n");
|
|
return NULL;
|
|
}
|
|
|
|
ZeroMemory(sPage,
|
|
sizeof(*sPage));
|
|
|
|
sPage->psi = psi;
|
|
sPage->ObjectInfo = ObjectInfo;
|
|
sPage->ServerName = SystemName;
|
|
sPage->SidCacheMgr = SidCacheMgr;
|
|
|
|
psp.dwSize = sizeof(PROPSHEETPAGE);
|
|
psp.dwFlags = PSP_USECALLBACK;
|
|
psp.hInstance = hDllInstance;
|
|
psp.pszTemplate = MAKEINTRESOURCE(IDD_SECPAGE);
|
|
psp.pfnDlgProc = SecurityPageProc;
|
|
psp.lParam = (LPARAM)sPage;
|
|
psp.pfnCallback = SecurityPageCallback;
|
|
|
|
if (ObjectInfo.dwFlags & SI_PAGE_TITLE)
|
|
{
|
|
psp.pszTitle = ObjectInfo.pszPageTitle;
|
|
|
|
if (psp.pszTitle != NULL)
|
|
{
|
|
psp.dwFlags |= PSP_USETITLE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
psp.pszTitle = NULL;
|
|
}
|
|
|
|
/* NOTE: the SECURITY_PAGE structure will be freed by the property page
|
|
callback! */
|
|
|
|
return CreatePropertySheetPage(&psp);
|
|
}
|
|
|
|
|
|
/*
|
|
* EditSecurity EXPORTED
|
|
*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
EditSecurity(IN HWND hwndOwner,
|
|
IN LPSECURITYINFO psi)
|
|
{
|
|
HRESULT hRet;
|
|
SI_OBJECT_INFO ObjectInfo = {0};
|
|
PROPSHEETHEADER psh;
|
|
HPROPSHEETPAGE hPages[1];
|
|
LPWSTR lpCaption = NULL;
|
|
BOOL Ret;
|
|
|
|
if (psi == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
DPRINT("No ISecurityInformation class passed!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* get the object information from the server. Zero the structure before
|
|
because some applications seem to return SUCCESS but only seem to set the
|
|
fields they care about. */
|
|
hRet = psi->lpVtbl->GetObjectInformation(psi,
|
|
&ObjectInfo);
|
|
|
|
if (FAILED(hRet))
|
|
{
|
|
SetLastError(hRet);
|
|
|
|
DPRINT("GetObjectInformation() failed!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* create the page */
|
|
hPages[0] = CreateSecurityPage(psi);
|
|
if (hPages[0] == NULL)
|
|
{
|
|
DPRINT("CreateSecurityPage(), couldn't create property sheet!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_DEFAULT;
|
|
psh.hwndParent = hwndOwner;
|
|
psh.hInstance = hDllInstance;
|
|
|
|
/* Set the page title to the object name, make sure the format string
|
|
has "%1" NOT "%s" because it uses FormatMessage() to automatically
|
|
allocate the right amount of memory. */
|
|
if (LoadAndFormatString(hDllInstance,
|
|
IDS_PSP_TITLE,
|
|
&lpCaption,
|
|
ObjectInfo.pszObjectName))
|
|
{
|
|
psh.pszCaption = lpCaption;
|
|
}
|
|
else
|
|
{
|
|
psh.pszCaption = ObjectInfo.pszObjectName;
|
|
}
|
|
|
|
psh.nPages = sizeof(hPages) / sizeof(HPROPSHEETPAGE);
|
|
psh.nStartPage = 0;
|
|
psh.phpage = hPages;
|
|
|
|
Ret = (PropertySheet(&psh) != -1);
|
|
|
|
if (lpCaption != NULL)
|
|
{
|
|
LocalFree((HLOCAL)lpCaption);
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DllMain(IN HINSTANCE hinstDLL,
|
|
IN DWORD dwReason,
|
|
IN LPVOID lpvReserved)
|
|
{
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
hDllInstance = hinstDLL;
|
|
|
|
DisableThreadLibraryCalls(hinstDLL);
|
|
|
|
if (!RegisterCheckListControl(hinstDLL))
|
|
{
|
|
DPRINT("Registering the CHECKLIST_ACLUI class failed!\n");
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
UnregisterCheckListControl(hinstDLL);
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|