2 * ReactOS Access Control List Editor
3 * Copyright (C) 2004-2005 ReactOS Team
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * PROJECT: ReactOS Access Control List Editor
21 * FILE: lib/aclui/aclui.c
22 * PURPOSE: Access Control List Editor
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
38 HINSTANCE hDllInstance
;
40 #define SIDN_LOOKUPSUCCEEDED (0x101)
41 typedef struct _SIDLOOKUPNOTIFYINFO
45 PSIDREQRESULT SidRequestResult
;
46 } SIDLOOKUPNOTIFYINFO
, *PSIDLOOKUPNOTIFYINFO
;
49 AceHeaderToSID(IN PACE_HEADER AceHeader
)
52 switch (AceHeader
->AceType
)
54 case ACCESS_ALLOWED_ACE_TYPE
:
55 Sid
= (PSID
)&((PACCESS_ALLOWED_ACE
)AceHeader
)->SidStart
;
58 case ACCESS_ALLOWED_CALLBACK_ACE_TYPE
:
59 Sid
= (PSID
)&((PACCESS_ALLOWED_CALLBACK_ACE
)AceHeader
)->SidStart
;
61 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE
:
62 Sid
= (PSID
)&((PACCESS_ALLOWED_CALLBACK_OBJECT_ACE
)AceHeader
)->SidStart
;
65 case ACCESS_ALLOWED_OBJECT_ACE_TYPE
:
66 Sid
= (PSID
)&((PACCESS_ALLOWED_OBJECT_ACE
)AceHeader
)->SidStart
;
68 case ACCESS_DENIED_ACE_TYPE
:
69 Sid
= (PSID
)&((PACCESS_DENIED_ACE
)AceHeader
)->SidStart
;
72 case ACCESS_DENIED_CALLBACK_ACE_TYPE
:
73 Sid
= (PSID
)&((PACCESS_DENIED_CALLBACK_ACE
)AceHeader
)->SidStart
;
75 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE
:
76 Sid
= (PSID
)&((PACCESS_DENIED_CALLBACK_OBJECT_ACE
)AceHeader
)->SidStart
;
79 case SYSTEM_AUDIT_OBJECT_ACE_TYPE
:
80 Sid
= (PSID
)&((PACCESS_DENIED_OBJECT_ACE
)AceHeader
)->SidStart
;
88 DestroySecurityPage(IN PSECURITY_PAGE sp
)
90 if(sp
->hiPrincipals
!= NULL
)
92 ImageList_Destroy(sp
->hiPrincipals
);
95 DestroySidCacheMgr(sp
->SidCacheMgr
);
97 if (sp
->OwnerSid
!= NULL
)
98 LocalFree((HLOCAL
)sp
->OwnerSid
);
100 HeapFree(GetProcessHeap(),
108 FreePrincipalsList(IN PSECURITY_PAGE sp
,
109 IN PPRINCIPAL_LISTITEM
*PrincipalsListHead
)
111 PPRINCIPAL_LISTITEM CurItem
, NextItem
;
112 PACE_ENTRY AceEntry
, NextAceEntry
;
114 CurItem
= *PrincipalsListHead
;
115 while (CurItem
!= NULL
)
118 AceEntry
= CurItem
->ACEs
;
119 while (AceEntry
!= NULL
)
121 NextAceEntry
= AceEntry
->Next
;
122 HeapFree(GetProcessHeap(),
125 AceEntry
= NextAceEntry
;
128 /* free the SID string if present */
129 if (CurItem
->SidReqResult
!= NULL
)
131 DereferenceSidReqResult(sp
->SidCacheMgr
,
132 CurItem
->SidReqResult
);
135 if (CurItem
->DisplayString
!= NULL
)
137 LocalFree((HLOCAL
)CurItem
->DisplayString
);
140 /* free the ACE list item */
141 NextItem
= CurItem
->Next
;
142 HeapFree(GetProcessHeap(),
148 *PrincipalsListHead
= NULL
;
152 AddAceToPrincipal(IN PPRINCIPAL_LISTITEM Principal
,
153 IN PACE_HEADER AceHeader
)
155 PACE_ENTRY AceEntry
, *AceLink
;
157 AceEntry
= HeapAlloc(GetProcessHeap(),
159 sizeof(ACE_ENTRY
) + AceHeader
->AceSize
);
160 if (AceEntry
!= NULL
)
162 AceEntry
->Next
= NULL
;
165 CopyMemory(AceEntry
+ 1,
169 /* append it to the list */
170 AceLink
= &Principal
->ACEs
;
171 while (*AceLink
!= NULL
)
173 AceLink
= &(*AceLink
)->Next
;
181 static PPRINCIPAL_LISTITEM
182 FindSidInPrincipalsListAddAce(IN PPRINCIPAL_LISTITEM PrincipalsListHead
,
184 IN PACE_HEADER AceHeader
)
186 PPRINCIPAL_LISTITEM CurItem
;
188 for (CurItem
= PrincipalsListHead
;
190 CurItem
= CurItem
->Next
)
192 if (EqualSid((PSID
)(CurItem
+ 1),
195 if (AddAceToPrincipal(CurItem
,
201 /* unable to add the ACE to the principal */
210 SidLookupCompletion(IN HANDLE SidCacheMgr
,
212 IN PSIDREQRESULT SidRequestResult
,
215 PSECURITY_PAGE sp
= (PSECURITY_PAGE
)Context
;
217 /* NOTE: this routine may be executed in a different thread
220 if (SidRequestResult
!= NULL
)
222 SIDLOOKUPNOTIFYINFO LookupInfo
;
224 LookupInfo
.nmh
.hwndFrom
= sp
->hWnd
;
225 LookupInfo
.nmh
.idFrom
= 0;
226 LookupInfo
.nmh
.code
= SIDN_LOOKUPSUCCEEDED
;
227 LookupInfo
.Sid
= Sid
;
228 LookupInfo
.SidRequestResult
= SidRequestResult
;
230 /* notify the page that the sid lookup succeeded */
231 SendMessage(sp
->hWnd
,
233 (WPARAM
)LookupInfo
.nmh
.idFrom
,
234 (LPARAM
)&LookupInfo
.nmh
);
238 static PPRINCIPAL_LISTITEM
239 AddPrincipalToList(IN PSECURITY_PAGE sp
,
241 IN PACE_HEADER AceHeader
,
242 OUT BOOL
*LookupDeferred OPTIONAL
)
244 PPRINCIPAL_LISTITEM PrincipalListItem
= NULL
, *PrincipalLink
;
246 BOOL Deferred
= FALSE
;
248 if (!FindSidInPrincipalsListAddAce(sp
->PrincipalsListHead
,
254 PrincipalLink
= &sp
->PrincipalsListHead
;
255 while (*PrincipalLink
!= NULL
)
257 PrincipalLink
= &(*PrincipalLink
)->Next
;
260 SidLength
= GetLengthSid(Sid
);
262 /* allocate the principal */
263 PrincipalListItem
= HeapAlloc(GetProcessHeap(),
265 sizeof(PRINCIPAL_LISTITEM
) + SidLength
);
266 if (PrincipalListItem
!= NULL
)
268 PrincipalListItem
->DisplayString
= NULL
;
269 PrincipalListItem
->SidReqResult
= NULL
;
272 (PSID
)(PrincipalListItem
+ 1),
275 /* allocate some memory for the ACE and copy it */
276 AceEntry
= HeapAlloc(GetProcessHeap(),
278 sizeof(ACE_ENTRY
) + AceHeader
->AceSize
);
279 if (AceEntry
!= NULL
)
281 AceEntry
->Next
= NULL
;
282 CopyMemory(AceEntry
+ 1,
286 /* add the ACE to the list */
287 PrincipalListItem
->ACEs
= AceEntry
;
289 PrincipalListItem
->Next
= NULL
;
291 /* append item to the principals list */
292 *PrincipalLink
= PrincipalListItem
;
294 /* lookup the SID now */
295 Deferred
= !LookupSidCache(sp
->SidCacheMgr
,
302 HeapFree(GetProcessHeap(),
305 PrincipalListItem
= NULL
;
310 if (PrincipalListItem
!= NULL
&& LookupDeferred
!= NULL
)
312 *LookupDeferred
= Deferred
;
315 return PrincipalListItem
;
319 GetDisplayStringFromSidRequestResult(IN PSIDREQRESULT SidReqResult
)
321 LPWSTR lpDisplayString
= NULL
;
323 if (SidReqResult
->SidNameUse
== SidTypeUser
||
324 SidReqResult
->SidNameUse
== SidTypeGroup
)
326 LoadAndFormatString(hDllInstance
,
327 IDS_USERDOMAINFORMAT
,
329 SidReqResult
->AccountName
,
330 SidReqResult
->DomainName
,
331 SidReqResult
->AccountName
);
335 LoadAndFormatString(hDllInstance
,
338 SidReqResult
->AccountName
);
341 return lpDisplayString
;
345 GetPrincipalDisplayString(IN PPRINCIPAL_LISTITEM PrincipalListItem
)
347 LPWSTR lpDisplayString
= NULL
;
349 if (PrincipalListItem
->SidReqResult
!= NULL
)
351 lpDisplayString
= GetDisplayStringFromSidRequestResult(PrincipalListItem
->SidReqResult
);
355 ConvertSidToStringSidW((PSID
)(PrincipalListItem
+ 1),
359 return lpDisplayString
;
363 GetPrincipalAccountNameString(IN PPRINCIPAL_LISTITEM PrincipalListItem
)
365 LPWSTR lpDisplayString
= NULL
;
367 if (PrincipalListItem
->SidReqResult
!= NULL
)
369 LoadAndFormatString(hDllInstance
,
372 PrincipalListItem
->SidReqResult
->AccountName
);
376 ConvertSidToStringSid((PSID
)(PrincipalListItem
+ 1),
380 return lpDisplayString
;
384 CreatePrincipalListItem(OUT LVITEM
*li
,
385 IN PSECURITY_PAGE sp
,
386 IN PPRINCIPAL_LISTITEM PrincipalListItem
,
392 if (PrincipalListItem
->SidReqResult
!= NULL
)
394 switch (PrincipalListItem
->SidReqResult
->SidNameUse
)
399 case SidTypeWellKnownGroup
:
408 li
->mask
= LVIF_IMAGE
| LVIF_PARAM
| LVIF_STATE
| LVIF_TEXT
;
411 li
->state
= (Selected
? LVIS_SELECTED
: 0);
412 li
->stateMask
= LVIS_SELECTED
;
413 li
->pszText
= PrincipalListItem
->DisplayString
;
414 li
->iImage
= ImageIndex
;
415 li
->lParam
= (LPARAM
)PrincipalListItem
;
419 AddPrincipalListEntry(IN PSECURITY_PAGE sp
,
420 IN PPRINCIPAL_LISTITEM PrincipalListItem
,
427 if (PrincipalListItem
->DisplayString
!= NULL
)
429 LocalFree((HLOCAL
)PrincipalListItem
->DisplayString
);
431 PrincipalListItem
->DisplayString
= GetPrincipalDisplayString(PrincipalListItem
);
433 CreatePrincipalListItem(&li
,
439 Ret
= ListView_InsertItem(sp
->hWndPrincipalsList
,
446 PrincipalCompare(IN LPARAM lParam1
,
448 IN LPARAM lParamSort
)
450 PPRINCIPAL_LISTITEM Item1
= (PPRINCIPAL_LISTITEM
)lParam1
;
451 PPRINCIPAL_LISTITEM Item2
= (PPRINCIPAL_LISTITEM
)lParam2
;
453 if (Item1
->DisplayString
!= NULL
&& Item2
->DisplayString
!= NULL
)
455 return wcscmp(Item1
->DisplayString
,
456 Item2
->DisplayString
);
463 UpdatePrincipalListItem(IN PSECURITY_PAGE sp
,
464 IN INT PrincipalIndex
,
465 IN PPRINCIPAL_LISTITEM PrincipalListItem
,
466 IN PSIDREQRESULT SidReqResult
)
470 /* replace the request result structure */
471 if (PrincipalListItem
->SidReqResult
!= NULL
)
473 DereferenceSidReqResult(sp
->SidCacheMgr
,
474 PrincipalListItem
->SidReqResult
);
477 ReferenceSidReqResult(sp
->SidCacheMgr
,
479 PrincipalListItem
->SidReqResult
= SidReqResult
;
481 /* update the display string */
482 if (PrincipalListItem
->DisplayString
!= NULL
)
484 LocalFree((HLOCAL
)PrincipalListItem
->DisplayString
);
486 PrincipalListItem
->DisplayString
= GetPrincipalDisplayString(PrincipalListItem
);
488 /* update the list item */
489 CreatePrincipalListItem(&li
,
495 /* don't change the list item state */
496 li
.mask
&= ~(LVIF_STATE
| LVIF_PARAM
);
498 (void)ListView_SetItem(sp
->hWndPrincipalsList
,
501 /* sort the principals list view again */
502 (void)ListView_SortItems(sp
->hWndPrincipalsList
,
508 ReloadPrincipalsList(IN PSECURITY_PAGE sp
)
510 PSECURITY_DESCRIPTOR SecurityDescriptor
;
511 BOOL DaclPresent
, DaclDefaulted
, OwnerDefaulted
;
513 PSID OwnerSid
= NULL
;
514 LPTSTR OwnerSidString
;
518 /* delete the cached ACL */
519 FreePrincipalsList(sp
,
520 &sp
->PrincipalsListHead
);
523 hRet
= sp
->psi
->lpVtbl
->GetSecurity(sp
->psi
,
524 DACL_SECURITY_INFORMATION
| OWNER_SECURITY_INFORMATION
,
527 if (SUCCEEDED(hRet
) && SecurityDescriptor
!= NULL
)
529 if (GetSecurityDescriptorOwner(SecurityDescriptor
,
533 sp
->OwnerDefaulted
= OwnerDefaulted
;
534 if (sp
->OwnerSid
!= NULL
)
536 LocalFree((HLOCAL
)sp
->OwnerSid
);
540 SidLen
= GetLengthSid(OwnerSid
);
544 sp
->OwnerSid
= (PSID
)LocalAlloc(LMEM_FIXED
,
546 if (sp
->OwnerSid
!= NULL
)
552 /* Lookup the SID now */
553 if (!LookupSidCache(sp
->SidCacheMgr
,
558 /* Lookup was deferred */
559 if (ConvertSidToStringSid(sp
->OwnerSid
,
562 SetDlgItemText(sp
->hWnd
,
565 LocalFree((HLOCAL
)OwnerSidString
);
580 SetDlgItemText(sp
->hWnd
,
585 if (GetSecurityDescriptorDacl(SecurityDescriptor
,
589 DaclPresent
&& Dacl
!= NULL
)
592 PACE_HEADER AceHeader
;
596 AceIndex
< Dacl
->AceCount
;
601 (LPVOID
*)&AceHeader
) &&
605 PPRINCIPAL_LISTITEM PrincipalListItem
;
607 Sid
= AceHeaderToSID(AceHeader
);
609 PrincipalListItem
= AddPrincipalToList(sp
,
614 if (PrincipalListItem
!= NULL
&& LookupDeferred
)
616 AddPrincipalListEntry(sp
,
624 LocalFree((HLOCAL
)SecurityDescriptor
);
629 UpdateControlStates(IN PSECURITY_PAGE sp
)
631 PPRINCIPAL_LISTITEM Selected
= (PPRINCIPAL_LISTITEM
)ListViewGetSelectedItemData(sp
->hWndPrincipalsList
);
633 EnableWindow(sp
->hBtnRemove
,
635 EnableWindow(sp
->hAceCheckList
,
638 if (Selected
!= NULL
)
641 LPWSTR szDisplayString
;
643 szDisplayString
= GetPrincipalAccountNameString(Selected
);
644 if (LoadAndFormatString(hDllInstance
,
649 SetWindowText(sp
->hPermissionsForLabel
,
652 LocalFree((HLOCAL
)szLabel
);
655 LocalFree((HLOCAL
)szDisplayString
);
657 /* FIXME - update the checkboxes */
661 WCHAR szPermissions
[255];
663 if (LoadString(hDllInstance
,
666 sizeof(szPermissions
) / sizeof(szPermissions
[0])))
668 SetWindowText(sp
->hPermissionsForLabel
,
672 SendMessage(sp
->hAceCheckList
,
680 UpdatePrincipalInfo(IN PSECURITY_PAGE sp
,
681 IN PSIDLOOKUPNOTIFYINFO LookupInfo
)
683 PPRINCIPAL_LISTITEM CurItem
;
686 if (sp
->OwnerSid
!= NULL
&&
687 EqualSid(sp
->OwnerSid
,
690 if (LookupInfo
->SidRequestResult
!= NULL
)
691 DisplayName
= GetDisplayStringFromSidRequestResult(LookupInfo
->SidRequestResult
);
692 else if (!ConvertSidToStringSidW(LookupInfo
->Sid
,
698 if (DisplayName
!= NULL
)
700 SetDlgItemTextW(sp
->hWnd
,
704 LocalFree((HLOCAL
)DisplayName
);
708 for (CurItem
= sp
->PrincipalsListHead
;
710 CurItem
= CurItem
->Next
)
712 if (EqualSid((PSID
)(CurItem
+ 1),
718 /* find the principal in the list */
719 lvfi
.flags
= LVFI_PARAM
;
720 lvfi
.lParam
= (LPARAM
)CurItem
;
721 PrincipalIndex
= ListView_FindItem(sp
->hWndPrincipalsList
,
725 if (PrincipalIndex
!= -1)
727 /* update the principal in the list view control */
728 UpdatePrincipalListItem(sp
,
731 LookupInfo
->SidRequestResult
);
733 if (ListViewGetSelectedItemData(sp
->hWndPrincipalsList
) == (LPARAM
)CurItem
)
735 UpdateControlStates(sp
);
740 AddPrincipalListEntry(sp
,
751 SecurityPageCallback(IN HWND hwnd
,
753 IN LPPROPSHEETPAGE ppsp
)
755 PSECURITY_PAGE sp
= (PSECURITY_PAGE
)ppsp
->lParam
;
765 DestroySecurityPage(sp
);
774 SetAceCheckListColumns(IN HWND hAceCheckList
,
781 GetWindowRect(hLabel
,
784 pt
.x
= (rcLabel
.right
- rcLabel
.left
) / 2;
785 MapWindowPoints(hLabel
,
790 SendMessage(hAceCheckList
,
791 CLM_SETCHECKBOXCOLUMN
,
797 LoadPermissionsList(IN PSECURITY_PAGE sp
,
798 IN GUID
*GuidObjectType
,
800 OUT SI_ACCESS
*DefaultAccess
)
803 PSI_ACCESS AccessList
;
804 ULONG nAccessList
, DefaultAccessIndex
;
805 WCHAR szSpecialPermissions
[255];
806 BOOLEAN SpecialPermissionsPresent
= FALSE
;
807 ACCESS_MASK SpecialPermissionsMask
= 0;
809 /* clear the permissions list */
811 SendMessage(sp
->hAceCheckList
,
816 /* query the access rights from the server */
817 hRet
= sp
->psi
->lpVtbl
->GetAccessRights(sp
->psi
,
822 &DefaultAccessIndex
);
823 if (SUCCEEDED(hRet
) && nAccessList
!= 0)
826 PSI_ACCESS CurAccess
, LastAccess
;
827 WCHAR NameBuffer
[MAX_PATH
];
829 /* save the default access rights to be used when adding ACEs later */
830 if (DefaultAccess
!= NULL
)
832 *DefaultAccess
= AccessList
[DefaultAccessIndex
];
835 LastAccess
= AccessList
+ nAccessList
;
836 for (CurAccess
= &AccessList
[0];
837 CurAccess
!= LastAccess
;
840 if (CurAccess
->dwFlags
& dwFlags
)
842 /* get the permission name, load it from a string table if necessary */
843 if (IS_INTRESOURCE(CurAccess
->pszName
))
845 if (!LoadString(sp
->ObjectInfo
.hInstance
,
846 (UINT
)((ULONG_PTR
)CurAccess
->pszName
),
848 sizeof(NameBuffer
) / sizeof(NameBuffer
[0])))
850 LoadString(hDllInstance
,
853 sizeof(NameBuffer
) / sizeof(NameBuffer
[0]));
855 NameStr
= NameBuffer
;
859 NameStr
= CurAccess
->pszName
;
862 SendMessage(sp
->hAceCheckList
,
864 (WPARAM
)CurAccess
->mask
,
867 else if (CurAccess
->dwFlags
& SI_ACCESS_SPECIFIC
)
869 SpecialPermissionsPresent
= TRUE
;
870 SpecialPermissionsMask
|= CurAccess
->mask
;
875 /* add the special permissions check item in case the specific access rights
877 if (SpecialPermissionsPresent
&&
878 LoadString(hDllInstance
,
879 IDS_SPECIAL_PERMISSIONS
,
880 szSpecialPermissions
,
881 sizeof(szSpecialPermissions
) / sizeof(szSpecialPermissions
[0])))
883 /* add the special permissions check item */
884 sp
->SpecialPermCheckIndex
= (INT
)SendMessage(sp
->hAceCheckList
,
886 (WPARAM
)SpecialPermissionsMask
,
887 (LPARAM
)szSpecialPermissions
);
888 if (sp
->SpecialPermCheckIndex
!= -1)
890 SendMessage(sp
->hAceCheckList
,
892 (WPARAM
)sp
->SpecialPermCheckIndex
,
893 CIS_ALLOWDISABLED
| CIS_DENYDISABLED
| CIS_NONE
);
899 ResizeControls(IN PSECURITY_PAGE sp
,
903 HWND hWndAllow
, hWndDeny
, hWndOwnerEdit
;
904 RECT rcControl
, rcControl2
, rcControl3
, rcWnd
;
905 INT cxWidth
, cxEdge
, btnSpacing
;
911 hWndAllow
= GetDlgItem(sp
->hWnd
,
913 hWndDeny
= GetDlgItem(sp
->hWnd
,
916 GetWindowRect(sp
->hWnd
,
919 cxEdge
= GetSystemMetrics(SM_CXEDGE
);
921 /* use the left margin of the principal list view control for all control
925 MapWindowPoints(sp
->hWndPrincipalsList
,
929 cxWidth
= Width
- (2 * pt
.x
);
931 if (sp
->ObjectInfo
.dwFlags
& SI_ADVANCED
)
936 if ((dwp
= BeginDeferWindowPos(nControls
)))
938 /* resize the owner edit field */
939 hWndOwnerEdit
= GetDlgItem(sp
->hWnd
,
941 GetWindowRect(hWndOwnerEdit
,
945 MapWindowPoints(hWndOwnerEdit
,
949 if (!(dwp
= DeferWindowPos(dwp
,
954 Width
- pt
.x
- pt2
.x
,
955 rcControl
.bottom
- rcControl
.top
,
956 SWP_NOMOVE
| SWP_NOZORDER
)))
961 /* resize the Principal list view */
962 GetWindowRect(sp
->hWndPrincipalsList
,
964 if (!(dwp
= DeferWindowPos(dwp
,
965 sp
->hWndPrincipalsList
,
970 rcControl
.bottom
- rcControl
.top
,
971 SWP_NOMOVE
| SWP_NOZORDER
)))
976 /* move the Add Principal button */
977 GetWindowRect(sp
->hBtnAdd
,
979 GetWindowRect(sp
->hBtnRemove
,
981 btnSpacing
= rcControl2
.left
- rcControl
.right
;
984 MapWindowPoints(sp
->hBtnAdd
,
988 if (!(dwp
= DeferWindowPos(dwp
,
991 pt
.x
+ cxWidth
- (rcControl2
.right
- rcControl2
.left
) -
992 (rcControl
.right
- rcControl
.left
) -
997 SWP_NOSIZE
| SWP_NOZORDER
)))
1002 /* move the Delete Principal button */
1005 MapWindowPoints(sp
->hBtnRemove
,
1009 if (!(dwp
= DeferWindowPos(dwp
,
1012 pt
.x
+ cxWidth
- (rcControl2
.right
- rcControl2
.left
) - cxEdge
,
1016 SWP_NOSIZE
| SWP_NOZORDER
)))
1021 /* move the Permissions For label */
1022 GetWindowRect(hWndAllow
,
1024 GetWindowRect(hWndDeny
,
1026 GetWindowRect(sp
->hPermissionsForLabel
,
1030 MapWindowPoints(sp
->hPermissionsForLabel
,
1034 if (!(dwp
= DeferWindowPos(dwp
,
1035 sp
->hPermissionsForLabel
,
1039 cxWidth
- (rcControl2
.right
- rcControl2
.left
) -
1040 (rcControl
.right
- rcControl
.left
) -
1041 (2 * btnSpacing
) - cxEdge
,
1042 rcControl3
.bottom
- rcControl3
.top
,
1043 SWP_NOMOVE
| SWP_NOZORDER
)))
1048 /* move the Allow label */
1051 MapWindowPoints(hWndAllow
,
1055 if (!(dwp
= DeferWindowPos(dwp
,
1058 cxWidth
- (rcControl2
.right
- rcControl2
.left
) -
1059 (rcControl
.right
- rcControl
.left
) -
1060 btnSpacing
- cxEdge
,
1064 SWP_NOSIZE
| SWP_NOZORDER
)))
1069 /* move the Deny label */
1072 MapWindowPoints(hWndDeny
,
1076 if (!(dwp
= DeferWindowPos(dwp
,
1079 cxWidth
- (rcControl2
.right
- rcControl2
.left
) - cxEdge
,
1083 SWP_NOSIZE
| SWP_NOZORDER
)))
1088 /* resize the Permissions check list box */
1089 GetWindowRect(sp
->hAceCheckList
,
1091 GetWindowRect(sp
->hBtnAdvanced
,
1093 GetWindowRect(GetDlgItem(sp
->hWnd
,
1094 IDC_LABEL_ADVANCED
),
1096 if (!(dwp
= DeferWindowPos(dwp
,
1102 ((sp
->ObjectInfo
.dwFlags
& SI_ADVANCED
) ?
1103 Height
- (rcControl
.top
- rcWnd
.top
) -
1104 (rcControl3
.bottom
- rcControl3
.top
) - pt
.x
- btnSpacing
:
1105 Height
- (rcControl
.top
- rcWnd
.top
) - pt
.x
),
1106 SWP_NOMOVE
| SWP_NOZORDER
)))
1111 if (sp
->ObjectInfo
.dwFlags
& SI_ADVANCED
)
1113 /* move and resize the Advanced label */
1114 if (!(dwp
= DeferWindowPos(dwp
,
1115 GetDlgItem(sp
->hWnd
,
1116 IDC_LABEL_ADVANCED
),
1119 Height
- (rcControl3
.bottom
- rcControl3
.top
) - pt
.x
,
1120 cxWidth
- (rcControl2
.right
- rcControl2
.left
) - cxEdge
,
1121 rcControl3
.bottom
- rcControl3
.top
,
1127 /* move and resize the Advanced button */
1128 if (!(dwp
= DeferWindowPos(dwp
,
1131 cxWidth
- (rcControl2
.right
- rcControl2
.left
) + pt
.x
,
1132 Height
- (rcControl2
.bottom
- rcControl2
.top
) - pt
.x
,
1135 SWP_NOSIZE
| SWP_NOZORDER
)))
1141 EndDeferWindowPos(dwp
);
1145 /* update the width of the principal list view column */
1146 GetClientRect(sp
->hWndPrincipalsList
,
1148 lvc
.mask
= LVCF_WIDTH
;
1149 lvc
.cx
= rcControl
.right
;
1150 (void)ListView_SetColumn(sp
->hWndPrincipalsList
,
1154 /* calculate the columns of the allow/deny checkboxes */
1155 SetAceCheckListColumns(sp
->hAceCheckList
,
1158 SetAceCheckListColumns(sp
->hAceCheckList
,
1164 BuildDefaultPrincipalAce(IN PSECURITY_PAGE sp
,
1167 PACCESS_ALLOWED_ACE Ace
;
1171 SidLen
= GetLengthSid(pSid
);
1172 AceSize
= FIELD_OFFSET(ACCESS_ALLOWED_ACE
,
1173 SidStart
) + (WORD
)SidLen
;
1174 Ace
= HeapAlloc(GetProcessHeap(),
1179 Ace
->Header
.AceType
= ACCESS_ALLOWED_ACE_TYPE
;
1180 Ace
->Header
.AceFlags
= 0; /* FIXME */
1181 Ace
->Header
.AceSize
= AceSize
;
1182 Ace
->Mask
= sp
->DefaultAccess
.mask
;
1185 (PSID
)&Ace
->SidStart
,
1188 return &Ace
->Header
;
1191 HeapFree(GetProcessHeap(),
1200 AddSelectedPrincipal(IN IDsObjectPicker
*pDsObjectPicker
,
1201 IN HWND hwndParent OPTIONAL
,
1203 IN PVOID Context OPTIONAL
)
1205 PACE_HEADER AceHeader
;
1206 PSECURITY_PAGE sp
= (PSECURITY_PAGE
)Context
;
1208 AceHeader
= BuildDefaultPrincipalAce(sp
,
1210 if (AceHeader
!= NULL
)
1212 PPRINCIPAL_LISTITEM PrincipalListItem
;
1213 BOOL LookupDeferred
;
1215 PrincipalListItem
= AddPrincipalToList(sp
,
1220 if (PrincipalListItem
!= NULL
&& LookupDeferred
)
1222 AddPrincipalListEntry(sp
,
1228 HeapFree(GetProcessHeap(),
1236 static INT_PTR CALLBACK
1237 SecurityPageProc(IN HWND hwndDlg
,
1243 INT_PTR Ret
= FALSE
;
1245 sp
= (PSECURITY_PAGE
)GetWindowLongPtr(hwndDlg
,
1247 if (sp
!= NULL
|| uMsg
== WM_INITDIALOG
)
1253 NMHDR
*pnmh
= (NMHDR
*)lParam
;
1255 if (pnmh
->hwndFrom
== sp
->hWndPrincipalsList
)
1259 case LVN_ITEMCHANGED
:
1261 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
)lParam
;
1263 if ((pnmv
->uChanged
& LVIF_STATE
) &&
1264 ((pnmv
->uOldState
& (LVIS_FOCUSED
| LVIS_SELECTED
)) ||
1265 (pnmv
->uNewState
& (LVIS_FOCUSED
| LVIS_SELECTED
))))
1267 UpdateControlStates(sp
);
1273 else if (pnmh
->hwndFrom
== sp
->hAceCheckList
)
1277 case CLN_CHANGINGITEMCHECKBOX
:
1279 PNMCHANGEITEMCHECKBOX pcicb
= (PNMCHANGEITEMCHECKBOX
)lParam
;
1281 /* make sure only one of both checkboxes is only checked
1285 pcicb
->NewState
&= ~((pcicb
->CheckBox
!= CLB_DENY
) ? CIS_DENY
: CIS_ALLOW
);
1291 else if (pnmh
->hwndFrom
== sp
->hWnd
)
1295 case SIDN_LOOKUPSUCCEEDED
:
1297 PSIDLOOKUPNOTIFYINFO LookupInfo
= CONTAINING_RECORD(lParam
,
1298 SIDLOOKUPNOTIFYINFO
,
1301 /* a SID lookup succeeded, update the information */
1302 UpdatePrincipalInfo(sp
,
1313 switch (LOWORD(wParam
))
1315 case IDC_ADD_PRINCIPAL
:
1319 hRet
= InitializeObjectPicker(sp
->ServerName
,
1321 &sp
->pDsObjectPicker
);
1322 if (SUCCEEDED(hRet
))
1324 hRet
= InvokeObjectPickerDialog(sp
->pDsObjectPicker
,
1326 AddSelectedPrincipal
,
1330 MessageBox(hwndDlg
, L
"InvokeObjectPickerDialog failed!\n", NULL
, 0);
1333 /* delete the instance */
1334 FreeObjectPicker(sp
->pDsObjectPicker
);
1338 MessageBox(hwndDlg
, L
"InitializeObjectPicker failed!\n", NULL
, 0);
1343 case IDC_REMOVE_PRINCIPAL
:
1345 PPRINCIPAL_LISTITEM SelectedPrincipal
;
1347 SelectedPrincipal
= (PPRINCIPAL_LISTITEM
)ListViewGetSelectedItemData(sp
->hWndPrincipalsList
);
1348 if (SelectedPrincipal
!= NULL
)
1361 (INT
)LOWORD(lParam
),
1362 (INT
)HIWORD(lParam
));
1368 sp
= (PSECURITY_PAGE
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1375 sp
->hWndPrincipalsList
= GetDlgItem(hwndDlg
, IDC_PRINCIPALS
);
1376 sp
->hBtnAdd
= GetDlgItem(hwndDlg
, IDC_ADD_PRINCIPAL
);
1377 sp
->hBtnRemove
= GetDlgItem(hwndDlg
, IDC_REMOVE_PRINCIPAL
);
1378 sp
->hBtnAdvanced
= GetDlgItem(hwndDlg
, IDC_ADVANCED
);
1379 sp
->hAceCheckList
= GetDlgItem(hwndDlg
, IDC_ACE_CHECKLIST
);
1380 sp
->hPermissionsForLabel
= GetDlgItem(hwndDlg
, IDC_LABEL_PERMISSIONS_FOR
);
1382 sp
->SpecialPermCheckIndex
= -1;
1384 /* save the pointer to the structure */
1385 SetWindowLongPtr(hwndDlg
,
1389 (void)ListView_SetExtendedListViewStyleEx(sp
->hWndPrincipalsList
,
1390 LVS_EX_FULLROWSELECT
,
1391 LVS_EX_FULLROWSELECT
);
1393 sp
->hiPrincipals
= ImageList_Create(16,
1395 ILC_COLOR32
| ILC_MASK
,
1398 if (sp
->hiPrincipals
!= NULL
)
1402 hbmImages
= LoadBitmap(hDllInstance
,
1403 MAKEINTRESOURCE(IDB_USRGRPIMAGES
));
1404 if (hbmImages
!= NULL
)
1406 ImageList_AddMasked(sp
->hiPrincipals
,
1412 DeleteObject(hbmImages
);
1416 /* setup the listview control */
1417 if (sp
->hiPrincipals
!= NULL
)
1419 (void)ListView_SetImageList(sp
->hWndPrincipalsList
,
1424 GetClientRect(sp
->hWndPrincipalsList
,
1427 /* add a column to the list view */
1428 lvc
.mask
= LVCF_FMT
| LVCF_WIDTH
;
1429 lvc
.fmt
= LVCFMT_LEFT
;
1430 lvc
.cx
= rcLvClient
.right
;
1431 (void)ListView_InsertColumn(sp
->hWndPrincipalsList
,
1435 ReloadPrincipalsList(sp
);
1437 ListViewSelectItem(sp
->hWndPrincipalsList
,
1440 /* calculate the columns of the allow/deny checkboxes */
1441 SetAceCheckListColumns(sp
->hAceCheckList
,
1443 GetDlgItem(hwndDlg
, IDC_LABEL_ALLOW
));
1444 SetAceCheckListColumns(sp
->hAceCheckList
,
1446 GetDlgItem(hwndDlg
, IDC_LABEL_DENY
));
1448 LoadPermissionsList(sp
,
1451 ((sp
->ObjectInfo
.dwFlags
& SI_CONTAINER
) ? SI_ACCESS_CONTAINER
: 0),
1452 &sp
->DefaultAccess
);
1454 /* hide controls in case the flags aren't present */
1455 if (sp
->ObjectInfo
.dwFlags
& SI_ADVANCED
)
1457 /* editing the permissions is least the user can do when
1458 the advanced button is showed */
1459 sp
->ObjectInfo
.dwFlags
|= SI_EDIT_PERMS
;
1463 ShowWindow(sp
->hBtnAdvanced
,
1465 ShowWindow(GetDlgItem(hwndDlg
, IDC_LABEL_ADVANCED
),
1469 /* enable quicksearch for the permissions checklist control */
1470 SendMessage(sp
->hAceCheckList
,
1471 CLM_ENABLEQUICKSEARCH
,
1475 UpdateControlStates(sp
);
1488 * CreateSecurityPage EXPORTED
1494 CreateSecurityPage(IN LPSECURITYINFO psi
)
1496 PROPSHEETPAGE psp
= {0};
1497 PSECURITY_PAGE sPage
;
1498 SI_OBJECT_INFO ObjectInfo
= {0};
1500 LPCWSTR SystemName
= NULL
;
1505 SetLastError(ERROR_INVALID_PARAMETER
);
1507 DPRINT("No ISecurityInformation class passed!\n");
1511 /* get the object information from the server. Zero the structure before
1512 because some applications seem to return SUCCESS but only seem to set the
1513 fields they care about. */
1514 hRet
= psi
->lpVtbl
->GetObjectInformation(psi
,
1521 DPRINT("CreateSecurityPage() failed! Failed to query the object information!\n");
1525 if ((ObjectInfo
.dwFlags
& SI_SERVER_IS_DC
) &&
1526 ObjectInfo
.pszServerName
!= NULL
&&
1527 ObjectInfo
.pszServerName
[0] != L
'\0')
1529 SystemName
= ObjectInfo
.pszServerName
;
1532 SidCacheMgr
= CreateSidCacheMgr(GetProcessHeap(),
1534 if (SidCacheMgr
== NULL
)
1536 DPRINT("Creating the SID cache failed!\n");
1540 hRet
= CoInitialize(NULL
);
1543 DestroySidCacheMgr(SidCacheMgr
);
1544 DPRINT("CoInitialize failed!\n");
1548 sPage
= HeapAlloc(GetProcessHeap(),
1550 sizeof(SECURITY_PAGE
));
1553 DestroySidCacheMgr(SidCacheMgr
);
1556 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1558 DPRINT("Not enough memory to allocate a SECURITY_PAGE!\n");
1566 sPage
->ObjectInfo
= ObjectInfo
;
1567 sPage
->ServerName
= SystemName
;
1568 sPage
->SidCacheMgr
= SidCacheMgr
;
1570 psp
.dwSize
= sizeof(PROPSHEETPAGE
);
1571 psp
.dwFlags
= PSP_USECALLBACK
;
1572 psp
.hInstance
= hDllInstance
;
1573 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_SECPAGE
);
1574 psp
.pfnDlgProc
= SecurityPageProc
;
1575 psp
.lParam
= (LPARAM
)sPage
;
1576 psp
.pfnCallback
= SecurityPageCallback
;
1578 if (ObjectInfo
.dwFlags
& SI_PAGE_TITLE
)
1580 psp
.pszTitle
= ObjectInfo
.pszPageTitle
;
1582 if (psp
.pszTitle
!= NULL
)
1584 psp
.dwFlags
|= PSP_USETITLE
;
1589 psp
.pszTitle
= NULL
;
1592 /* NOTE: the SECURITY_PAGE structure will be freed by the property page
1595 return CreatePropertySheetPage(&psp
);
1600 * EditSecurity EXPORTED
1606 EditSecurity(IN HWND hwndOwner
,
1607 IN LPSECURITYINFO psi
)
1610 SI_OBJECT_INFO ObjectInfo
= {0};
1611 PROPSHEETHEADER psh
;
1612 HPROPSHEETPAGE hPages
[1];
1613 LPWSTR lpCaption
= NULL
;
1618 SetLastError(ERROR_INVALID_PARAMETER
);
1620 DPRINT("No ISecurityInformation class passed!\n");
1624 /* get the object information from the server. Zero the structure before
1625 because some applications seem to return SUCCESS but only seem to set the
1626 fields they care about. */
1627 hRet
= psi
->lpVtbl
->GetObjectInformation(psi
,
1634 DPRINT("GetObjectInformation() failed!\n");
1638 /* create the page */
1639 hPages
[0] = CreateSecurityPage(psi
);
1640 if (hPages
[0] == NULL
)
1642 DPRINT("CreateSecurityPage(), couldn't create property sheet!\n");
1646 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
1647 psh
.dwFlags
= PSH_DEFAULT
;
1648 psh
.hwndParent
= hwndOwner
;
1649 psh
.hInstance
= hDllInstance
;
1651 /* Set the page title to the object name, make sure the format string
1652 has "%1" NOT "%s" because it uses FormatMessage() to automatically
1653 allocate the right amount of memory. */
1654 if (LoadAndFormatString(hDllInstance
,
1657 ObjectInfo
.pszObjectName
))
1659 psh
.pszCaption
= lpCaption
;
1663 psh
.pszCaption
= ObjectInfo
.pszObjectName
;
1666 psh
.nPages
= sizeof(hPages
) / sizeof(HPROPSHEETPAGE
);
1668 psh
.phpage
= hPages
;
1670 Ret
= (PropertySheet(&psh
) != -1);
1672 if (lpCaption
!= NULL
)
1674 LocalFree((HLOCAL
)lpCaption
);
1682 DllMain(IN HINSTANCE hinstDLL
,
1684 IN LPVOID lpvReserved
)
1688 case DLL_PROCESS_ATTACH
:
1689 hDllInstance
= hinstDLL
;
1691 DisableThreadLibraryCalls(hinstDLL
);
1693 if (!RegisterCheckListControl(hinstDLL
))
1695 DPRINT("Registering the CHECKLIST_ACLUI class failed!\n");
1700 case DLL_PROCESS_DETACH
:
1701 UnregisterCheckListControl(hinstDLL
);