xref: /reactos/dll/win32/aclui/aclui.c (revision 43d6fdf2)
1 /*
2  * ReactOS Access Control List Editor
3  * Copyright (C) 2004-2005 ReactOS Team
4  *
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.
9  *
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.
14  *
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
18  */
19 /*
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>
24  *
25  * UPDATE HISTORY:
26  *      08/10/2004  Created
27  */
28 
29 #include "precomp.h"
30 
31 #include <sddl.h>
32 
33 #define NDEBUG
34 #include <debug.h>
35 
36 #include "resource.h"
37 
38 HINSTANCE hDllInstance;
39 
40 #define SIDN_LOOKUPSUCCEEDED    (0x101)
41 typedef struct _SIDLOOKUPNOTIFYINFO
42 {
43     NMHDR nmh;
44     PSID Sid;
45     PSIDREQRESULT SidRequestResult;
46 } SIDLOOKUPNOTIFYINFO, *PSIDLOOKUPNOTIFYINFO;
47 
48 static PSID
AceHeaderToSID(IN PACE_HEADER AceHeader)49 AceHeaderToSID(IN PACE_HEADER AceHeader)
50 {
51     PSID Sid = NULL;
52     switch (AceHeader->AceType)
53     {
54         case ACCESS_ALLOWED_ACE_TYPE:
55             Sid = (PSID)&((PACCESS_ALLOWED_ACE)AceHeader)->SidStart;
56             break;
57 #if 0
58         case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
59             Sid = (PSID)&((PACCESS_ALLOWED_CALLBACK_ACE)AceHeader)->SidStart;
60             break;
61         case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
62             Sid = (PSID)&((PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader)->SidStart;
63             break;
64 #endif
65         case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
66             Sid = (PSID)&((PACCESS_ALLOWED_OBJECT_ACE)AceHeader)->SidStart;
67             break;
68         case ACCESS_DENIED_ACE_TYPE:
69             Sid = (PSID)&((PACCESS_DENIED_ACE)AceHeader)->SidStart;
70             break;
71 #if 0
72         case ACCESS_DENIED_CALLBACK_ACE_TYPE:
73             Sid = (PSID)&((PACCESS_DENIED_CALLBACK_ACE)AceHeader)->SidStart;
74             break;
75         case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
76             Sid = (PSID)&((PACCESS_DENIED_CALLBACK_OBJECT_ACE)AceHeader)->SidStart;
77             break;
78 #endif
79         case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
80             Sid = (PSID)&((PACCESS_DENIED_OBJECT_ACE)AceHeader)->SidStart;
81             break;
82     }
83 
84     return Sid;
85 }
86 
87 static VOID
DestroySecurityPage(IN PSECURITY_PAGE sp)88 DestroySecurityPage(IN PSECURITY_PAGE sp)
89 {
90     DestroySidCacheMgr(sp->SidCacheMgr);
91 
92     if (sp->OwnerSid != NULL)
93         LocalFree((HLOCAL)sp->OwnerSid);
94 
95     HeapFree(GetProcessHeap(),
96              0,
97              sp);
98 
99     CoUninitialize();
100 }
101 
102 static VOID
FreePrincipalsList(IN PSECURITY_PAGE sp,IN PPRINCIPAL_LISTITEM * PrincipalsListHead)103 FreePrincipalsList(IN PSECURITY_PAGE sp,
104                    IN PPRINCIPAL_LISTITEM *PrincipalsListHead)
105 {
106     PPRINCIPAL_LISTITEM CurItem, NextItem;
107     PACE_ENTRY AceEntry, NextAceEntry;
108 
109     CurItem = *PrincipalsListHead;
110     while (CurItem != NULL)
111     {
112         /* Free all ACEs */
113         AceEntry = CurItem->ACEs;
114         while (AceEntry != NULL)
115         {
116             NextAceEntry = AceEntry->Next;
117             HeapFree(GetProcessHeap(),
118                      0,
119                      AceEntry);
120             AceEntry = NextAceEntry;
121         }
122 
123         /* free the SID string if present */
124         if (CurItem->SidReqResult != NULL)
125         {
126             DereferenceSidReqResult(sp->SidCacheMgr,
127                                     CurItem->SidReqResult);
128         }
129 
130         if (CurItem->DisplayString != NULL)
131         {
132             LocalFree((HLOCAL)CurItem->DisplayString);
133         }
134 
135         /* free the ACE list item */
136         NextItem = CurItem->Next;
137         HeapFree(GetProcessHeap(),
138                  0,
139                  CurItem);
140         CurItem = NextItem;
141     }
142 
143     *PrincipalsListHead = NULL;
144 }
145 
146 static PACE_ENTRY
AddAceToPrincipal(IN PPRINCIPAL_LISTITEM Principal,IN PACE_HEADER AceHeader)147 AddAceToPrincipal(IN PPRINCIPAL_LISTITEM Principal,
148                   IN PACE_HEADER AceHeader)
149 {
150     PACE_ENTRY AceEntry, *AceLink;
151 
152     AceEntry = HeapAlloc(GetProcessHeap(),
153                          0,
154                          sizeof(ACE_ENTRY) + AceHeader->AceSize);
155     if (AceEntry != NULL)
156     {
157         AceEntry->Next = NULL;
158 
159         /* copy the ACE */
160         CopyMemory(AceEntry + 1,
161                    AceHeader,
162                    AceHeader->AceSize);
163 
164         /* append it to the list */
165         AceLink = &Principal->ACEs;
166         while (*AceLink != NULL)
167         {
168             AceLink = &(*AceLink)->Next;
169         }
170         *AceLink = AceEntry;
171     }
172 
173     return AceEntry;
174 }
175 
176 static PPRINCIPAL_LISTITEM
FindSidInPrincipalsListAddAce(IN PPRINCIPAL_LISTITEM PrincipalsListHead,IN PSID Sid,IN PACE_HEADER AceHeader)177 FindSidInPrincipalsListAddAce(IN PPRINCIPAL_LISTITEM PrincipalsListHead,
178                               IN PSID Sid,
179                               IN PACE_HEADER AceHeader)
180 {
181     PPRINCIPAL_LISTITEM CurItem;
182 
183     for (CurItem = PrincipalsListHead;
184          CurItem != NULL;
185          CurItem = CurItem->Next)
186     {
187         if (EqualSid((PSID)(CurItem + 1),
188                      Sid))
189         {
190             if (AddAceToPrincipal(CurItem,
191                                   AceHeader) != NULL)
192             {
193                 return CurItem;
194             }
195 
196             /* unable to add the ACE to the principal */
197             break;
198         }
199     }
200 
201     return NULL;
202 }
203 
204 static VOID
SidLookupCompletion(IN HANDLE SidCacheMgr,IN PSID Sid,IN PSIDREQRESULT SidRequestResult,IN PVOID Context)205 SidLookupCompletion(IN HANDLE SidCacheMgr,
206                     IN PSID Sid,
207                     IN PSIDREQRESULT SidRequestResult,
208                     IN PVOID Context)
209 {
210     PSECURITY_PAGE sp = (PSECURITY_PAGE)Context;
211 
212     /* NOTE: this routine may be executed in a different thread
213              than the GUI! */
214 
215     if (SidRequestResult != NULL)
216     {
217         SIDLOOKUPNOTIFYINFO LookupInfo;
218 
219         LookupInfo.nmh.hwndFrom = sp->hWnd;
220         LookupInfo.nmh.idFrom = 0;
221         LookupInfo.nmh.code = SIDN_LOOKUPSUCCEEDED;
222         LookupInfo.Sid = Sid;
223         LookupInfo.SidRequestResult = SidRequestResult;
224 
225         /* notify the page that the sid lookup succeeded */
226         SendMessage(sp->hWnd,
227                     WM_NOTIFY,
228                     (WPARAM)LookupInfo.nmh.idFrom,
229                     (LPARAM)&LookupInfo.nmh);
230     }
231 }
232 
233 static PPRINCIPAL_LISTITEM
AddPrincipalToList(IN PSECURITY_PAGE sp,IN PSID Sid,IN PACE_HEADER AceHeader,OUT BOOL * LookupDeferred OPTIONAL)234 AddPrincipalToList(IN PSECURITY_PAGE sp,
235                    IN PSID Sid,
236                    IN PACE_HEADER AceHeader,
237                    OUT BOOL *LookupDeferred  OPTIONAL)
238 {
239     PPRINCIPAL_LISTITEM PrincipalListItem = NULL, *PrincipalLink;
240     PACE_ENTRY AceEntry;
241     BOOL Deferred = FALSE;
242 
243     if (!FindSidInPrincipalsListAddAce(sp->PrincipalsListHead,
244                                        Sid,
245                                        AceHeader))
246     {
247         DWORD SidLength;
248 
249         PrincipalLink = &sp->PrincipalsListHead;
250         while (*PrincipalLink != NULL)
251         {
252             PrincipalLink = &(*PrincipalLink)->Next;
253         }
254 
255         SidLength = GetLengthSid(Sid);
256 
257         /* allocate the principal */
258         PrincipalListItem = HeapAlloc(GetProcessHeap(),
259                                       0,
260                                       sizeof(PRINCIPAL_LISTITEM) + SidLength);
261         if (PrincipalListItem != NULL)
262         {
263             PrincipalListItem->DisplayString = NULL;
264             PrincipalListItem->SidReqResult = NULL;
265 
266             CopySid(SidLength,
267                     (PSID)(PrincipalListItem + 1),
268                     Sid);
269 
270             /* allocate some memory for the ACE and copy it */
271             AceEntry = HeapAlloc(GetProcessHeap(),
272                                  0,
273                                  sizeof(ACE_ENTRY) + AceHeader->AceSize);
274             if (AceEntry != NULL)
275             {
276                 AceEntry->Next = NULL;
277                 CopyMemory(AceEntry + 1,
278                            AceHeader,
279                            AceHeader->AceSize);
280 
281                 /* add the ACE to the list */
282                 PrincipalListItem->ACEs = AceEntry;
283 
284                 PrincipalListItem->Next = NULL;
285 
286                 /* append item to the principals list */
287                 *PrincipalLink = PrincipalListItem;
288 
289                 /* lookup the SID now */
290                 Deferred = !LookupSidCache(sp->SidCacheMgr,
291                                            Sid,
292                                            SidLookupCompletion,
293                                            sp);
294             }
295             else
296             {
297                 HeapFree(GetProcessHeap(),
298                          0,
299                          PrincipalListItem);
300                 PrincipalListItem = NULL;
301             }
302         }
303     }
304 
305     if (PrincipalListItem != NULL && LookupDeferred != NULL)
306     {
307         *LookupDeferred = Deferred;
308     }
309 
310     return PrincipalListItem;
311 }
312 
313 static LPWSTR
GetDisplayStringFromSidRequestResult(IN PSIDREQRESULT SidReqResult)314 GetDisplayStringFromSidRequestResult(IN PSIDREQRESULT SidReqResult)
315 {
316     LPWSTR lpDisplayString = NULL;
317 
318     if (SidReqResult->SidNameUse == SidTypeUser ||
319         SidReqResult->SidNameUse == SidTypeGroup)
320     {
321         LoadAndFormatString(hDllInstance,
322                             IDS_USERDOMAINFORMAT,
323                             &lpDisplayString,
324                             SidReqResult->AccountName,
325                             SidReqResult->DomainName,
326                             SidReqResult->AccountName);
327     }
328     else
329     {
330         LoadAndFormatString(hDllInstance,
331                             IDS_USERFORMAT,
332                             &lpDisplayString,
333                             SidReqResult->AccountName);
334     }
335 
336     return lpDisplayString;
337 }
338 
339 static LPWSTR
GetPrincipalDisplayString(IN PPRINCIPAL_LISTITEM PrincipalListItem)340 GetPrincipalDisplayString(IN PPRINCIPAL_LISTITEM PrincipalListItem)
341 {
342     LPWSTR lpDisplayString = NULL;
343 
344     if (PrincipalListItem->SidReqResult != NULL)
345     {
346         lpDisplayString = GetDisplayStringFromSidRequestResult(PrincipalListItem->SidReqResult);
347     }
348     else
349     {
350         ConvertSidToStringSidW((PSID)(PrincipalListItem + 1),
351                                &lpDisplayString);
352     }
353 
354     return lpDisplayString;
355 }
356 
357 static LPWSTR
GetPrincipalAccountNameString(IN PPRINCIPAL_LISTITEM PrincipalListItem)358 GetPrincipalAccountNameString(IN PPRINCIPAL_LISTITEM PrincipalListItem)
359 {
360     LPWSTR lpDisplayString = NULL;
361 
362     if (PrincipalListItem->SidReqResult != NULL)
363     {
364         LoadAndFormatString(hDllInstance,
365                             IDS_USERFORMAT,
366                             &lpDisplayString,
367                             PrincipalListItem->SidReqResult->AccountName);
368     }
369     else
370     {
371         ConvertSidToStringSid((PSID)(PrincipalListItem + 1),
372                               &lpDisplayString);
373     }
374 
375     return lpDisplayString;
376 }
377 
378 static VOID
CreatePrincipalListItem(OUT LVITEM * li,IN PSECURITY_PAGE sp,IN PPRINCIPAL_LISTITEM PrincipalListItem,IN INT Index,IN BOOL Selected)379 CreatePrincipalListItem(OUT LVITEM *li,
380                         IN PSECURITY_PAGE sp,
381                         IN PPRINCIPAL_LISTITEM PrincipalListItem,
382                         IN INT Index,
383                         IN BOOL Selected)
384 {
385     INT ImageIndex = 2;
386 
387     if (PrincipalListItem->SidReqResult != NULL)
388     {
389         switch (PrincipalListItem->SidReqResult->SidNameUse)
390         {
391             case SidTypeUser:
392                 ImageIndex = 0;
393                 break;
394             case SidTypeWellKnownGroup:
395             case SidTypeGroup:
396                 ImageIndex = 1;
397                 break;
398             default:
399                 break;
400         }
401     }
402 
403     li->mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
404     li->iItem = Index;
405     li->iSubItem = 0;
406     li->state = (Selected ? LVIS_SELECTED : 0);
407     li->stateMask = LVIS_SELECTED;
408     li->pszText = PrincipalListItem->DisplayString;
409     li->iImage = ImageIndex;
410     li->lParam = (LPARAM)PrincipalListItem;
411 }
412 
413 static INT
AddPrincipalListEntry(IN PSECURITY_PAGE sp,IN PPRINCIPAL_LISTITEM PrincipalListItem,IN INT Index,IN BOOL Selected)414 AddPrincipalListEntry(IN PSECURITY_PAGE sp,
415                       IN PPRINCIPAL_LISTITEM PrincipalListItem,
416                       IN INT Index,
417                       IN BOOL Selected)
418 {
419     LVITEM li;
420     INT Ret;
421 
422     if (PrincipalListItem->DisplayString != NULL)
423     {
424         LocalFree((HLOCAL)PrincipalListItem->DisplayString);
425     }
426     PrincipalListItem->DisplayString = GetPrincipalDisplayString(PrincipalListItem);
427 
428     CreatePrincipalListItem(&li,
429                             sp,
430                             PrincipalListItem,
431                             Index,
432                             Selected);
433 
434     Ret = ListView_InsertItem(sp->hWndPrincipalsList,
435                               &li);
436 
437     return Ret;
438 }
439 
440 static int CALLBACK
PrincipalCompare(IN LPARAM lParam1,IN LPARAM lParam2,IN LPARAM lParamSort)441 PrincipalCompare(IN LPARAM lParam1,
442                  IN LPARAM lParam2,
443                  IN LPARAM lParamSort)
444 {
445     PPRINCIPAL_LISTITEM Item1 = (PPRINCIPAL_LISTITEM)lParam1;
446     PPRINCIPAL_LISTITEM Item2 = (PPRINCIPAL_LISTITEM)lParam2;
447 
448     if (Item1->DisplayString != NULL && Item2->DisplayString != NULL)
449     {
450         return wcscmp(Item1->DisplayString,
451                       Item2->DisplayString);
452     }
453 
454     return 0;
455 }
456 
457 static VOID
UpdatePrincipalListItem(IN PSECURITY_PAGE sp,IN INT PrincipalIndex,IN PPRINCIPAL_LISTITEM PrincipalListItem,IN PSIDREQRESULT SidReqResult)458 UpdatePrincipalListItem(IN PSECURITY_PAGE sp,
459                         IN INT PrincipalIndex,
460                         IN PPRINCIPAL_LISTITEM PrincipalListItem,
461                         IN PSIDREQRESULT SidReqResult)
462 {
463     LVITEM li;
464 
465     /* replace the request result structure */
466     if (PrincipalListItem->SidReqResult != NULL)
467     {
468         DereferenceSidReqResult(sp->SidCacheMgr,
469                                 PrincipalListItem->SidReqResult);
470     }
471 
472     ReferenceSidReqResult(sp->SidCacheMgr,
473                           SidReqResult);
474     PrincipalListItem->SidReqResult = SidReqResult;
475 
476     /* update the display string */
477     if (PrincipalListItem->DisplayString != NULL)
478     {
479         LocalFree((HLOCAL)PrincipalListItem->DisplayString);
480     }
481     PrincipalListItem->DisplayString = GetPrincipalDisplayString(PrincipalListItem);
482 
483     /* update the list item */
484     CreatePrincipalListItem(&li,
485                             sp,
486                             PrincipalListItem,
487                             PrincipalIndex,
488                             FALSE);
489 
490     /* don't change the list item state */
491     li.mask &= ~(LVIF_STATE | LVIF_PARAM);
492 
493     (void)ListView_SetItem(sp->hWndPrincipalsList,
494                            &li);
495 
496     /* sort the principals list view again */
497     (void)ListView_SortItems(sp->hWndPrincipalsList,
498                              PrincipalCompare,
499                              (LPARAM)sp);
500 }
501 
502 static VOID
ReloadPrincipalsList(IN PSECURITY_PAGE sp)503 ReloadPrincipalsList(IN PSECURITY_PAGE sp)
504 {
505     PSECURITY_DESCRIPTOR SecurityDescriptor;
506     BOOL DaclPresent, DaclDefaulted, OwnerDefaulted;
507     PACL Dacl = NULL;
508     PSID OwnerSid = NULL;
509     LPTSTR OwnerSidString;
510     DWORD SidLen;
511     HRESULT hRet;
512 
513     /* delete the cached ACL */
514     FreePrincipalsList(sp,
515                        &sp->PrincipalsListHead);
516 
517     /* query the ACL */
518     hRet = sp->psi->lpVtbl->GetSecurity(sp->psi,
519                                         DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION,
520                                         &SecurityDescriptor,
521                                         FALSE);
522     if (SUCCEEDED(hRet) && SecurityDescriptor != NULL)
523     {
524         if (GetSecurityDescriptorOwner(SecurityDescriptor,
525                                        &OwnerSid,
526                                        &OwnerDefaulted))
527         {
528             sp->OwnerDefaulted = OwnerDefaulted;
529             if (sp->OwnerSid != NULL)
530             {
531                 LocalFree((HLOCAL)sp->OwnerSid);
532                 sp->OwnerSid = NULL;
533             }
534 
535             SidLen = GetLengthSid(OwnerSid);
536             if (SidLen == 0)
537                 goto ClearOwner;
538 
539             sp->OwnerSid = (PSID)LocalAlloc(LMEM_FIXED,
540                                             SidLen);
541             if (sp->OwnerSid != NULL)
542             {
543                 if (CopySid(SidLen,
544                             sp->OwnerSid,
545                             OwnerSid))
546                 {
547                     /* Lookup the SID now */
548                     if (!LookupSidCache(sp->SidCacheMgr,
549                                         sp->OwnerSid,
550                                         SidLookupCompletion,
551                                         sp))
552                     {
553                         /* Lookup was deferred */
554                         if (ConvertSidToStringSid(sp->OwnerSid,
555                                                   &OwnerSidString))
556                         {
557                             SetDlgItemText(sp->hWnd,
558                                            IDC_OWNER,
559                                            OwnerSidString);
560                             LocalFree((HLOCAL)OwnerSidString);
561                         }
562                         else
563                             goto ClearOwner;
564                     }
565                 }
566                 else
567                     goto ClearOwner;
568             }
569             else
570                 goto ClearOwner;
571         }
572         else
573         {
574 ClearOwner:
575             SetDlgItemText(sp->hWnd,
576                            IDC_OWNER,
577                            NULL);
578         }
579 
580         if (GetSecurityDescriptorDacl(SecurityDescriptor,
581                                       &DaclPresent,
582                                       &Dacl,
583                                       &DaclDefaulted) &&
584             DaclPresent && Dacl != NULL)
585         {
586             PSID Sid;
587             PACE_HEADER AceHeader;
588             ULONG AceIndex;
589 
590             for (AceIndex = 0;
591                  AceIndex < Dacl->AceCount;
592                  AceIndex++)
593             {
594                 if (GetAce(Dacl,
595                            AceIndex,
596                            (LPVOID*)&AceHeader) &&
597                     AceHeader != NULL)
598                 {
599                     BOOL LookupDeferred;
600                     PPRINCIPAL_LISTITEM PrincipalListItem;
601 
602                     Sid = AceHeaderToSID(AceHeader);
603 
604                     PrincipalListItem = AddPrincipalToList(sp,
605                                                            Sid,
606                                                            AceHeader,
607                                                            &LookupDeferred);
608 
609                     if (PrincipalListItem != NULL && LookupDeferred)
610                     {
611                         AddPrincipalListEntry(sp,
612                                               PrincipalListItem,
613                                               -1,
614                                               FALSE);
615                     }
616                 }
617             }
618         }
619         LocalFree((HLOCAL)SecurityDescriptor);
620     }
621 }
622 
623 static VOID
UpdateControlStates(IN PSECURITY_PAGE sp)624 UpdateControlStates(IN PSECURITY_PAGE sp)
625 {
626     PPRINCIPAL_LISTITEM Selected = (PPRINCIPAL_LISTITEM)ListViewGetSelectedItemData(sp->hWndPrincipalsList);
627 
628     EnableWindow(sp->hBtnRemove,
629                  Selected != NULL);
630     EnableWindow(sp->hAceCheckList,
631                  Selected != NULL);
632 
633     if (Selected != NULL)
634     {
635         LPWSTR szLabel;
636         LPWSTR szDisplayString;
637 
638         szDisplayString = GetPrincipalAccountNameString(Selected);
639         if (LoadAndFormatString(hDllInstance,
640                                 IDS_PERMISSIONS_FOR,
641                                 &szLabel,
642                                 szDisplayString))
643         {
644             SetWindowText(sp->hPermissionsForLabel,
645                           szLabel);
646 
647             LocalFree((HLOCAL)szLabel);
648         }
649 
650         LocalFree((HLOCAL)szDisplayString);
651 
652         /* FIXME - update the checkboxes */
653     }
654     else
655     {
656         WCHAR szPermissions[255];
657 
658         if (LoadString(hDllInstance,
659                        IDS_PERMISSIONS,
660                        szPermissions,
661                        sizeof(szPermissions) / sizeof(szPermissions[0])))
662         {
663             SetWindowText(sp->hPermissionsForLabel,
664                           szPermissions);
665         }
666 
667         SendMessage(sp->hAceCheckList,
668                     CLM_CLEARCHECKBOXES,
669                     0,
670                     0);
671     }
672 }
673 
674 static void
UpdatePrincipalInfo(IN PSECURITY_PAGE sp,IN PSIDLOOKUPNOTIFYINFO LookupInfo)675 UpdatePrincipalInfo(IN PSECURITY_PAGE sp,
676                     IN PSIDLOOKUPNOTIFYINFO LookupInfo)
677 {
678     PPRINCIPAL_LISTITEM CurItem;
679     LPWSTR DisplayName;
680 
681     if (sp->OwnerSid != NULL &&
682         EqualSid(sp->OwnerSid,
683                  LookupInfo->Sid))
684     {
685         if (LookupInfo->SidRequestResult != NULL)
686             DisplayName = GetDisplayStringFromSidRequestResult(LookupInfo->SidRequestResult);
687         else if (!ConvertSidToStringSidW(LookupInfo->Sid,
688                                          &DisplayName))
689         {
690             DisplayName = NULL;
691         }
692 
693         if (DisplayName != NULL)
694         {
695             SetDlgItemTextW(sp->hWnd,
696                             IDC_OWNER,
697                             DisplayName);
698 
699             LocalFree((HLOCAL)DisplayName);
700         }
701     }
702 
703     for (CurItem = sp->PrincipalsListHead;
704          CurItem != NULL;
705          CurItem = CurItem->Next)
706     {
707         if (EqualSid((PSID)(CurItem + 1),
708                      LookupInfo->Sid))
709         {
710             INT PrincipalIndex;
711             LVFINDINFO lvfi;
712 
713             /* find the principal in the list */
714             lvfi.flags = LVFI_PARAM;
715             lvfi.lParam = (LPARAM)CurItem;
716             PrincipalIndex = ListView_FindItem(sp->hWndPrincipalsList,
717                                                -1,
718                                                &lvfi);
719 
720             if (PrincipalIndex != -1)
721             {
722                 /* update the principal in the list view control */
723                 UpdatePrincipalListItem(sp,
724                                         PrincipalIndex,
725                                         CurItem,
726                                         LookupInfo->SidRequestResult);
727 
728                 if (ListViewGetSelectedItemData(sp->hWndPrincipalsList) == (LPARAM)CurItem)
729                 {
730                     UpdateControlStates(sp);
731                 }
732             }
733             else
734             {
735                 AddPrincipalListEntry(sp,
736                                       CurItem,
737                                       -1,
738                                       FALSE);
739             }
740             break;
741         }
742     }
743 }
744 
745 static UINT CALLBACK
SecurityPageCallback(IN HWND hwnd,IN UINT uMsg,IN LPPROPSHEETPAGE ppsp)746 SecurityPageCallback(IN HWND hwnd,
747                      IN UINT uMsg,
748                      IN LPPROPSHEETPAGE ppsp)
749 {
750     PSECURITY_PAGE sp = (PSECURITY_PAGE)ppsp->lParam;
751 
752     switch (uMsg)
753     {
754         case PSPCB_CREATE:
755         {
756             return TRUE;
757         }
758         case PSPCB_RELEASE:
759         {
760             DestroySecurityPage(sp);
761             return FALSE;
762         }
763     }
764 
765     return FALSE;
766 }
767 
768 static VOID
SetAceCheckListColumns(IN HWND hAceCheckList,IN UINT Button,IN HWND hLabel)769 SetAceCheckListColumns(IN HWND hAceCheckList,
770                        IN UINT Button,
771                        IN HWND hLabel)
772 {
773     POINT pt;
774     RECT rcLabel;
775 
776     GetWindowRect(hLabel,
777                   &rcLabel);
778     pt.y = 0;
779     pt.x = (rcLabel.right - rcLabel.left) / 2;
780     MapWindowPoints(hLabel,
781                     hAceCheckList,
782                     &pt,
783                     1);
784 
785     SendMessage(hAceCheckList,
786                 CLM_SETCHECKBOXCOLUMN,
787                 Button,
788                 pt.x);
789 }
790 
791 static VOID
LoadPermissionsList(IN PSECURITY_PAGE sp,IN GUID * GuidObjectType,IN DWORD dwFlags,OUT SI_ACCESS * DefaultAccess)792 LoadPermissionsList(IN PSECURITY_PAGE sp,
793                     IN GUID *GuidObjectType,
794                     IN DWORD dwFlags,
795                     OUT SI_ACCESS *DefaultAccess)
796 {
797     HRESULT hRet;
798     PSI_ACCESS AccessList;
799     ULONG nAccessList, DefaultAccessIndex;
800     WCHAR szSpecialPermissions[255];
801     BOOLEAN SpecialPermissionsPresent = FALSE;
802     ACCESS_MASK SpecialPermissionsMask = 0;
803 
804     /* clear the permissions list */
805 
806     SendMessage(sp->hAceCheckList,
807                 CLM_CLEAR,
808                 0,
809                 0);
810 
811     /* query the access rights from the server */
812     hRet = sp->psi->lpVtbl->GetAccessRights(sp->psi,
813                                             GuidObjectType,
814                                             dwFlags, /* FIXME */
815                                             &AccessList,
816                                             &nAccessList,
817                                             &DefaultAccessIndex);
818     if (SUCCEEDED(hRet) && nAccessList != 0)
819     {
820         LPCWSTR NameStr;
821         PSI_ACCESS CurAccess, LastAccess;
822         WCHAR NameBuffer[MAX_PATH];
823 
824         /* save the default access rights to be used when adding ACEs later */
825         if (DefaultAccess != NULL)
826         {
827             *DefaultAccess = AccessList[DefaultAccessIndex];
828         }
829 
830         LastAccess = AccessList + nAccessList;
831         for (CurAccess = &AccessList[0];
832              CurAccess != LastAccess;
833              CurAccess++)
834         {
835             if (CurAccess->dwFlags & dwFlags)
836             {
837                 /* get the permission name, load it from a string table if necessary */
838                 if (IS_INTRESOURCE(CurAccess->pszName))
839                 {
840                     if (!LoadString(sp->ObjectInfo.hInstance,
841                                     (UINT)((ULONG_PTR)CurAccess->pszName),
842                                     NameBuffer,
843                                     sizeof(NameBuffer) / sizeof(NameBuffer[0])))
844                     {
845                         LoadString(hDllInstance,
846                                    IDS_UNKNOWN,
847                                    NameBuffer,
848                                    sizeof(NameBuffer) / sizeof(NameBuffer[0]));
849                     }
850                     NameStr = NameBuffer;
851                 }
852                 else
853                 {
854                     NameStr = CurAccess->pszName;
855                 }
856 
857                 SendMessage(sp->hAceCheckList,
858                             CLM_ADDITEM,
859                             (WPARAM)CurAccess->mask,
860                             (LPARAM)NameStr);
861             }
862             else if (CurAccess->dwFlags & SI_ACCESS_SPECIFIC)
863             {
864                 SpecialPermissionsPresent = TRUE;
865                 SpecialPermissionsMask |= CurAccess->mask;
866             }
867         }
868     }
869 
870     /* add the special permissions check item in case the specific access rights
871        aren't displayed */
872     if (SpecialPermissionsPresent &&
873         LoadString(hDllInstance,
874                    IDS_SPECIAL_PERMISSIONS,
875                    szSpecialPermissions,
876                    sizeof(szSpecialPermissions) / sizeof(szSpecialPermissions[0])))
877     {
878         /* add the special permissions check item */
879         sp->SpecialPermCheckIndex = (INT)SendMessage(sp->hAceCheckList,
880                                                      CLM_ADDITEM,
881                                                      (WPARAM)SpecialPermissionsMask,
882                                                      (LPARAM)szSpecialPermissions);
883         if (sp->SpecialPermCheckIndex != -1)
884         {
885             SendMessage(sp->hAceCheckList,
886                         CLM_SETITEMSTATE,
887                         (WPARAM)sp->SpecialPermCheckIndex,
888                         CIS_ALLOWDISABLED | CIS_DENYDISABLED | CIS_NONE);
889         }
890     }
891 }
892 
893 static VOID
ResizeControls(IN PSECURITY_PAGE sp,IN INT Width,IN INT Height)894 ResizeControls(IN PSECURITY_PAGE sp,
895                IN INT Width,
896                IN INT Height)
897 {
898     HWND hWndAllow, hWndDeny, hWndOwnerEdit;
899     RECT rcControl, rcControl2, rcControl3, rcWnd;
900     INT cxWidth, cxEdge, btnSpacing;
901     POINT pt, pt2;
902     HDWP dwp;
903     INT nControls = 8;
904     LVCOLUMN lvc;
905 
906     hWndAllow = GetDlgItem(sp->hWnd,
907                            IDC_LABEL_ALLOW);
908     hWndDeny = GetDlgItem(sp->hWnd,
909                           IDC_LABEL_DENY);
910 
911     GetWindowRect(sp->hWnd,
912                   &rcWnd);
913 
914     cxEdge = GetSystemMetrics(SM_CXEDGE);
915 
916     /* use the left margin of the principal list view control for all control
917        margins */
918     pt.x = 0;
919     pt.y = 0;
920     MapWindowPoints(sp->hWndPrincipalsList,
921                     sp->hWnd,
922                     &pt,
923                     1);
924     cxWidth = Width - (2 * pt.x);
925 
926     if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
927     {
928         nControls += 2;
929     }
930 
931     if ((dwp = BeginDeferWindowPos(nControls)))
932     {
933         /* resize the owner edit field */
934         hWndOwnerEdit = GetDlgItem(sp->hWnd,
935                                    IDC_OWNER);
936         GetWindowRect(hWndOwnerEdit,
937                       &rcControl);
938         pt2.x = 0;
939         pt2.y = 0;
940         MapWindowPoints(hWndOwnerEdit,
941                         sp->hWnd,
942                         &pt2,
943                         1);
944         if (!(dwp = DeferWindowPos(dwp,
945                                    hWndOwnerEdit,
946                                    NULL,
947                                    0,
948                                    0,
949                                    Width - pt.x - pt2.x,
950                                    rcControl.bottom - rcControl.top,
951                                    SWP_NOMOVE | SWP_NOZORDER)))
952         {
953             goto EndDeferWnds;
954         }
955 
956         /* resize the Principal list view */
957         GetWindowRect(sp->hWndPrincipalsList,
958                       &rcControl);
959         if (!(dwp = DeferWindowPos(dwp,
960                                    sp->hWndPrincipalsList,
961                                    NULL,
962                                    0,
963                                    0,
964                                    cxWidth,
965                                    rcControl.bottom - rcControl.top,
966                                    SWP_NOMOVE | SWP_NOZORDER)))
967         {
968             goto EndDeferWnds;
969         }
970 
971         /* move the Add Principal button */
972         GetWindowRect(sp->hBtnAdd,
973                       &rcControl);
974         GetWindowRect(sp->hBtnRemove,
975                       &rcControl2);
976         btnSpacing = rcControl2.left - rcControl.right;
977         pt2.x = 0;
978         pt2.y = 0;
979         MapWindowPoints(sp->hBtnAdd,
980                         sp->hWnd,
981                         &pt2,
982                         1);
983         if (!(dwp = DeferWindowPos(dwp,
984                                    sp->hBtnAdd,
985                                    NULL,
986                                    pt.x + cxWidth - (rcControl2.right - rcControl2.left) -
987                                        (rcControl.right - rcControl.left) -
988                                        btnSpacing - cxEdge,
989                                    pt2.y,
990                                    0,
991                                    0,
992                                    SWP_NOSIZE | SWP_NOZORDER)))
993         {
994             goto EndDeferWnds;
995         }
996 
997         /* move the Delete Principal button */
998         pt2.x = 0;
999         pt2.y = 0;
1000         MapWindowPoints(sp->hBtnRemove,
1001                         sp->hWnd,
1002                         &pt2,
1003                         1);
1004         if (!(dwp = DeferWindowPos(dwp,
1005                                    sp->hBtnRemove,
1006                                    NULL,
1007                                    pt.x + cxWidth - (rcControl2.right - rcControl2.left) - cxEdge,
1008                                    pt2.y,
1009                                    0,
1010                                    0,
1011                                    SWP_NOSIZE | SWP_NOZORDER)))
1012         {
1013             goto EndDeferWnds;
1014         }
1015 
1016         /* move the Permissions For label */
1017         GetWindowRect(hWndAllow,
1018                       &rcControl);
1019         GetWindowRect(hWndDeny,
1020                       &rcControl2);
1021         GetWindowRect(sp->hPermissionsForLabel,
1022                       &rcControl3);
1023         pt2.x = 0;
1024         pt2.y = 0;
1025         MapWindowPoints(sp->hPermissionsForLabel,
1026                         sp->hWnd,
1027                         &pt2,
1028                         1);
1029         if (!(dwp = DeferWindowPos(dwp,
1030                                    sp->hPermissionsForLabel,
1031                                    NULL,
1032                                    0,
1033                                    0,
1034                                    cxWidth - (rcControl2.right - rcControl2.left) -
1035                                        (rcControl.right - rcControl.left) -
1036                                        (2 * btnSpacing) - cxEdge,
1037                                    rcControl3.bottom - rcControl3.top,
1038                                    SWP_NOMOVE | SWP_NOZORDER)))
1039         {
1040             goto EndDeferWnds;
1041         }
1042 
1043         /* move the Allow label */
1044         pt2.x = 0;
1045         pt2.y = 0;
1046         MapWindowPoints(hWndAllow,
1047                         sp->hWnd,
1048                         &pt2,
1049                         1);
1050         if (!(dwp = DeferWindowPos(dwp,
1051                                    hWndAllow,
1052                                    NULL,
1053                                    cxWidth - (rcControl2.right - rcControl2.left) -
1054                                        (rcControl.right - rcControl.left) -
1055                                        btnSpacing - cxEdge,
1056                                    pt2.y,
1057                                    0,
1058                                    0,
1059                                    SWP_NOSIZE | SWP_NOZORDER)))
1060         {
1061             goto EndDeferWnds;
1062         }
1063 
1064         /* move the Deny label */
1065         pt2.x = 0;
1066         pt2.y = 0;
1067         MapWindowPoints(hWndDeny,
1068                         sp->hWnd,
1069                         &pt2,
1070                         1);
1071         if (!(dwp = DeferWindowPos(dwp,
1072                                    hWndDeny,
1073                                    NULL,
1074                                    cxWidth - (rcControl2.right - rcControl2.left) - cxEdge,
1075                                    pt2.y,
1076                                    0,
1077                                    0,
1078                                    SWP_NOSIZE | SWP_NOZORDER)))
1079         {
1080             goto EndDeferWnds;
1081         }
1082 
1083         /* resize the Permissions check list box */
1084         GetWindowRect(sp->hAceCheckList,
1085                       &rcControl);
1086         GetWindowRect(sp->hBtnAdvanced,
1087                       &rcControl2);
1088         GetWindowRect(GetDlgItem(sp->hWnd,
1089                                  IDC_LABEL_ADVANCED),
1090                       &rcControl3);
1091         if (!(dwp = DeferWindowPos(dwp,
1092                                    sp->hAceCheckList,
1093                                    NULL,
1094                                    0,
1095                                    0,
1096                                    cxWidth,
1097                                    ((sp->ObjectInfo.dwFlags & SI_ADVANCED) ?
1098                                        Height - (rcControl.top - rcWnd.top) -
1099                                            (rcControl3.bottom - rcControl3.top) - pt.x - btnSpacing :
1100                                        Height - (rcControl.top - rcWnd.top) - pt.x),
1101                                    SWP_NOMOVE | SWP_NOZORDER)))
1102         {
1103             goto EndDeferWnds;
1104         }
1105 
1106         if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
1107         {
1108             /* move and resize the Advanced label */
1109             if (!(dwp = DeferWindowPos(dwp,
1110                                        GetDlgItem(sp->hWnd,
1111                                                   IDC_LABEL_ADVANCED),
1112                                        NULL,
1113                                        pt.x,
1114                                        Height - (rcControl3.bottom - rcControl3.top) - pt.x,
1115                                        cxWidth - (rcControl2.right - rcControl2.left) - cxEdge,
1116                                        rcControl3.bottom - rcControl3.top,
1117                                        SWP_NOZORDER)))
1118             {
1119                 goto EndDeferWnds;
1120             }
1121 
1122             /* move and resize the Advanced button */
1123             if (!(dwp = DeferWindowPos(dwp,
1124                                        sp->hBtnAdvanced,
1125                                        NULL,
1126                                        cxWidth - (rcControl2.right - rcControl2.left) + pt.x,
1127                                        Height - (rcControl2.bottom - rcControl2.top) - pt.x,
1128                                        0,
1129                                        0,
1130                                        SWP_NOSIZE | SWP_NOZORDER)))
1131             {
1132                 goto EndDeferWnds;
1133             }
1134         }
1135 
1136         EndDeferWindowPos(dwp);
1137     }
1138 
1139 EndDeferWnds:
1140     /* update the width of the principal list view column */
1141     GetClientRect(sp->hWndPrincipalsList,
1142                   &rcControl);
1143     lvc.mask = LVCF_WIDTH;
1144     lvc.cx = rcControl.right;
1145     (void)ListView_SetColumn(sp->hWndPrincipalsList,
1146                              0,
1147                              &lvc);
1148 
1149     /* calculate the columns of the allow/deny checkboxes */
1150     SetAceCheckListColumns(sp->hAceCheckList,
1151                            CLB_ALLOW,
1152                            hWndAllow);
1153     SetAceCheckListColumns(sp->hAceCheckList,
1154                            CLB_DENY,
1155                            hWndDeny);
1156 }
1157 
1158 static PACE_HEADER
BuildDefaultPrincipalAce(IN PSECURITY_PAGE sp,IN PSID pSid)1159 BuildDefaultPrincipalAce(IN PSECURITY_PAGE sp,
1160                          IN PSID pSid)
1161 {
1162     PACCESS_ALLOWED_ACE Ace;
1163     DWORD SidLen;
1164     WORD AceSize;
1165 
1166     SidLen = GetLengthSid(pSid);
1167     AceSize = FIELD_OFFSET(ACCESS_ALLOWED_ACE,
1168                            SidStart) + (WORD)SidLen;
1169     Ace = HeapAlloc(GetProcessHeap(),
1170                     0,
1171                     AceSize);
1172     if (Ace != NULL)
1173     {
1174         Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
1175         Ace->Header.AceFlags = 0; /* FIXME */
1176         Ace->Header.AceSize = AceSize;
1177         Ace->Mask = sp->DefaultAccess.mask;
1178 
1179         if (CopySid(SidLen,
1180                     (PSID)&Ace->SidStart,
1181                     pSid))
1182         {
1183             return &Ace->Header;
1184         }
1185 
1186         HeapFree(GetProcessHeap(),
1187                  0,
1188                  Ace);
1189     }
1190 
1191     return NULL;
1192 }
1193 
1194 static BOOL
AddSelectedPrincipal(IN IDsObjectPicker * pDsObjectPicker,IN HWND hwndParent OPTIONAL,IN PSID pSid,IN PVOID Context OPTIONAL)1195 AddSelectedPrincipal(IN IDsObjectPicker *pDsObjectPicker,
1196                      IN HWND hwndParent  OPTIONAL,
1197                      IN PSID pSid,
1198                      IN PVOID Context  OPTIONAL)
1199 {
1200     PACE_HEADER AceHeader;
1201     PSECURITY_PAGE sp = (PSECURITY_PAGE)Context;
1202 
1203     AceHeader = BuildDefaultPrincipalAce(sp,
1204                                          pSid);
1205     if (AceHeader != NULL)
1206     {
1207         PPRINCIPAL_LISTITEM PrincipalListItem;
1208         BOOL LookupDeferred;
1209 
1210         PrincipalListItem = AddPrincipalToList(sp,
1211                                                pSid,
1212                                                AceHeader,
1213                                                &LookupDeferred);
1214 
1215         if (PrincipalListItem != NULL && LookupDeferred)
1216         {
1217             AddPrincipalListEntry(sp,
1218                                   PrincipalListItem,
1219                                   -1,
1220                                   FALSE);
1221         }
1222 
1223         HeapFree(GetProcessHeap(),
1224                  0,
1225                  AceHeader);
1226     }
1227 
1228     return TRUE;
1229 }
1230 
1231 static INT_PTR CALLBACK
SecurityPageProc(IN HWND hwndDlg,IN UINT uMsg,IN WPARAM wParam,IN LPARAM lParam)1232 SecurityPageProc(IN HWND hwndDlg,
1233                  IN UINT uMsg,
1234                  IN WPARAM wParam,
1235                  IN LPARAM lParam)
1236 {
1237     PSECURITY_PAGE sp;
1238     INT_PTR Ret = FALSE;
1239 
1240     sp = (PSECURITY_PAGE)GetWindowLongPtr(hwndDlg, DWLP_USER);
1241     if (sp != NULL || uMsg == WM_INITDIALOG)
1242     {
1243         switch (uMsg)
1244         {
1245             case WM_NOTIFY:
1246             {
1247                 NMHDR *pnmh = (NMHDR*)lParam;
1248 
1249                 if (pnmh->hwndFrom == sp->hWndPrincipalsList)
1250                 {
1251                     switch (pnmh->code)
1252                     {
1253                         case LVN_ITEMCHANGED:
1254                         {
1255                             LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
1256 
1257                             if ((pnmv->uChanged & LVIF_STATE) &&
1258                                 ((pnmv->uOldState & (LVIS_FOCUSED | LVIS_SELECTED)) ||
1259                                  (pnmv->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))))
1260                             {
1261                                 UpdateControlStates(sp);
1262                             }
1263                             break;
1264                         }
1265                     }
1266                 }
1267                 else if (pnmh->hwndFrom == sp->hAceCheckList)
1268                 {
1269                     switch (pnmh->code)
1270                     {
1271                         case CLN_CHANGINGITEMCHECKBOX:
1272                         {
1273                             PNMCHANGEITEMCHECKBOX pcicb = (PNMCHANGEITEMCHECKBOX)lParam;
1274 
1275                             /* make sure only one of both checkboxes is only checked
1276                                at the same time */
1277                             if (pcicb->Checked)
1278                             {
1279                                 pcicb->NewState &= ~((pcicb->CheckBox != CLB_DENY) ? CIS_DENY : CIS_ALLOW);
1280                             }
1281                             break;
1282                         }
1283                     }
1284                 }
1285                 else if (pnmh->hwndFrom == sp->hWnd)
1286                 {
1287                     switch(pnmh->code)
1288                     {
1289                         case SIDN_LOOKUPSUCCEEDED:
1290                         {
1291                             PSIDLOOKUPNOTIFYINFO LookupInfo = CONTAINING_RECORD(lParam,
1292                                                                                 SIDLOOKUPNOTIFYINFO,
1293                                                                                 nmh);
1294 
1295                             /* a SID lookup succeeded, update the information */
1296                             UpdatePrincipalInfo(sp,
1297                                                 LookupInfo);
1298                             break;
1299                         }
1300                     }
1301                 }
1302                 break;
1303             }
1304 
1305             case WM_COMMAND:
1306             {
1307                 switch (LOWORD(wParam))
1308                 {
1309                     case IDC_ADD_PRINCIPAL:
1310                     {
1311                         HRESULT hRet;
1312 
1313                         hRet = InitializeObjectPicker(sp->ServerName,
1314                                                       &sp->ObjectInfo,
1315                                                       &sp->pDsObjectPicker);
1316                         if (SUCCEEDED(hRet))
1317                         {
1318                             hRet = InvokeObjectPickerDialog(sp->pDsObjectPicker,
1319                                                             hwndDlg,
1320                                                             AddSelectedPrincipal,
1321                                                             sp);
1322                             if (FAILED(hRet))
1323                             {
1324                                 MessageBox(hwndDlg, L"InvokeObjectPickerDialog failed!\n", NULL, 0);
1325                             }
1326 
1327                             /* delete the instance */
1328                             FreeObjectPicker(sp->pDsObjectPicker);
1329                         }
1330                         else
1331                         {
1332                             MessageBox(hwndDlg, L"InitializeObjectPicker failed!\n", NULL, 0);
1333                         }
1334                         break;
1335                     }
1336 
1337                     case IDC_REMOVE_PRINCIPAL:
1338                     {
1339                         PPRINCIPAL_LISTITEM SelectedPrincipal;
1340 
1341                         SelectedPrincipal = (PPRINCIPAL_LISTITEM)ListViewGetSelectedItemData(sp->hWndPrincipalsList);
1342                         if (SelectedPrincipal != NULL)
1343                         {
1344                             /* FIXME */
1345                         }
1346                         break;
1347                     }
1348                 }
1349                 break;
1350             }
1351 
1352             case WM_SIZE:
1353             {
1354                 ResizeControls(sp,
1355                                (INT)LOWORD(lParam),
1356                                (INT)HIWORD(lParam));
1357                 break;
1358             }
1359 
1360             case WM_INITDIALOG:
1361             {
1362                 sp = (PSECURITY_PAGE)((LPPROPSHEETPAGE)lParam)->lParam;
1363                 if(sp != NULL)
1364                 {
1365                     LV_COLUMN lvc;
1366                     RECT rcLvClient;
1367 
1368                     sp->hWnd = hwndDlg;
1369                     sp->hWndPrincipalsList = GetDlgItem(hwndDlg, IDC_PRINCIPALS);
1370                     sp->hBtnAdd = GetDlgItem(hwndDlg, IDC_ADD_PRINCIPAL);
1371                     sp->hBtnRemove = GetDlgItem(hwndDlg, IDC_REMOVE_PRINCIPAL);
1372                     sp->hBtnAdvanced = GetDlgItem(hwndDlg, IDC_ADVANCED);
1373                     sp->hAceCheckList = GetDlgItem(hwndDlg, IDC_ACE_CHECKLIST);
1374                     sp->hPermissionsForLabel = GetDlgItem(hwndDlg, IDC_LABEL_PERMISSIONS_FOR);
1375 
1376                     sp->SpecialPermCheckIndex = -1;
1377 
1378                     /* save the pointer to the structure */
1379                     SetWindowLongPtr(hwndDlg, DWLP_USER, (DWORD_PTR)sp);
1380 
1381                     (void)ListView_SetExtendedListViewStyleEx(sp->hWndPrincipalsList,
1382                                                               LVS_EX_FULLROWSELECT,
1383                                                               LVS_EX_FULLROWSELECT);
1384 
1385                     sp->hiPrincipals = ImageList_Create(16,
1386                                                         16,
1387                                                         ILC_COLOR32 | ILC_MASK,
1388                                                         0,
1389                                                         3);
1390                     if (sp->hiPrincipals != NULL)
1391                     {
1392                         HBITMAP hbmImages;
1393 
1394                         hbmImages = LoadBitmap(hDllInstance,
1395                                                MAKEINTRESOURCE(IDB_USRGRPIMAGES));
1396                         if (hbmImages != NULL)
1397                         {
1398                             ImageList_AddMasked(sp->hiPrincipals,
1399                                                 hbmImages,
1400                                                 RGB(255,
1401                                                     0,
1402                                                     255));
1403 
1404                             DeleteObject(hbmImages);
1405                         }
1406                     }
1407 
1408                     /* setup the listview control */
1409                     if (sp->hiPrincipals != NULL)
1410                     {
1411                         (void)ListView_SetImageList(sp->hWndPrincipalsList,
1412                                                     sp->hiPrincipals,
1413                                                     LVSIL_SMALL);
1414                     }
1415 
1416                     GetClientRect(sp->hWndPrincipalsList,
1417                                   &rcLvClient);
1418 
1419                     /* add a column to the list view */
1420                     lvc.mask = LVCF_FMT | LVCF_WIDTH;
1421                     lvc.fmt = LVCFMT_LEFT;
1422                     lvc.cx = rcLvClient.right;
1423                     (void)ListView_InsertColumn(sp->hWndPrincipalsList,
1424                                                 0,
1425                                                 &lvc);
1426 
1427                     ReloadPrincipalsList(sp);
1428 
1429                     ListViewSelectItem(sp->hWndPrincipalsList,
1430                                        0);
1431 
1432                     /* calculate the columns of the allow/deny checkboxes */
1433                     SetAceCheckListColumns(sp->hAceCheckList,
1434                                            CLB_ALLOW,
1435                                            GetDlgItem(hwndDlg, IDC_LABEL_ALLOW));
1436                     SetAceCheckListColumns(sp->hAceCheckList,
1437                                            CLB_DENY,
1438                                            GetDlgItem(hwndDlg, IDC_LABEL_DENY));
1439 
1440                     LoadPermissionsList(sp,
1441                                         NULL,
1442                                         SI_ACCESS_GENERAL |
1443                                         ((sp->ObjectInfo.dwFlags & SI_CONTAINER) ? SI_ACCESS_CONTAINER : 0),
1444                                         &sp->DefaultAccess);
1445 
1446                     /* hide controls in case the flags aren't present */
1447                     if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
1448                     {
1449                         /* editing the permissions is least the user can do when
1450                            the advanced button is showed */
1451                         sp->ObjectInfo.dwFlags |= SI_EDIT_PERMS;
1452                     }
1453                     else
1454                     {
1455                         ShowWindow(sp->hBtnAdvanced,
1456                                    SW_HIDE);
1457                         ShowWindow(GetDlgItem(hwndDlg, IDC_LABEL_ADVANCED),
1458                                    SW_HIDE);
1459                     }
1460 
1461                     /* enable quicksearch for the permissions checklist control */
1462                     SendMessage(sp->hAceCheckList,
1463                                 CLM_ENABLEQUICKSEARCH,
1464                                 TRUE,
1465                                 0);
1466 
1467                     UpdateControlStates(sp);
1468                 }
1469 
1470                 Ret = TRUE;
1471                 break;
1472             }
1473         }
1474     }
1475     return Ret;
1476 }
1477 
1478 
1479 /*
1480  * CreateSecurityPage							EXPORTED
1481  *
1482  * @implemented
1483  */
1484 HPROPSHEETPAGE
1485 WINAPI
CreateSecurityPage(IN LPSECURITYINFO psi)1486 CreateSecurityPage(IN LPSECURITYINFO psi)
1487 {
1488     PROPSHEETPAGE psp = {0};
1489     PSECURITY_PAGE sPage;
1490     SI_OBJECT_INFO ObjectInfo = {0};
1491     HANDLE SidCacheMgr;
1492     LPCWSTR SystemName = NULL;
1493     HRESULT hRet;
1494 
1495     if (psi == NULL)
1496     {
1497         SetLastError(ERROR_INVALID_PARAMETER);
1498 
1499         DPRINT("No ISecurityInformation class passed!\n");
1500         return NULL;
1501     }
1502 
1503     /* get the object information from the server. Zero the structure before
1504        because some applications seem to return SUCCESS but only seem to set the
1505        fields they care about. */
1506     hRet = psi->lpVtbl->GetObjectInformation(psi,
1507                                              &ObjectInfo);
1508 
1509     if (FAILED(hRet))
1510     {
1511         SetLastError(hRet);
1512 
1513         DPRINT("CreateSecurityPage() failed! Failed to query the object information!\n");
1514         return NULL;
1515     }
1516 
1517     if ((ObjectInfo.dwFlags & SI_SERVER_IS_DC) &&
1518          ObjectInfo.pszServerName != NULL &&
1519          ObjectInfo.pszServerName[0] != L'\0')
1520     {
1521         SystemName = ObjectInfo.pszServerName;
1522     }
1523 
1524     SidCacheMgr = CreateSidCacheMgr(GetProcessHeap(),
1525                                     SystemName);
1526     if (SidCacheMgr == NULL)
1527     {
1528         DPRINT("Creating the SID cache failed!\n");
1529         return NULL;
1530     }
1531 
1532     hRet = CoInitialize(NULL);
1533     if (FAILED(hRet))
1534     {
1535         DestroySidCacheMgr(SidCacheMgr);
1536         DPRINT("CoInitialize failed!\n");
1537         return NULL;
1538     }
1539 
1540     sPage = HeapAlloc(GetProcessHeap(),
1541                       HEAP_ZERO_MEMORY,
1542                       sizeof(SECURITY_PAGE));
1543     if (sPage == NULL)
1544     {
1545         DestroySidCacheMgr(SidCacheMgr);
1546         CoUninitialize();
1547 
1548         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1549 
1550         DPRINT("Not enough memory to allocate a SECURITY_PAGE!\n");
1551         return NULL;
1552     }
1553 
1554     ZeroMemory(sPage,
1555                sizeof(*sPage));
1556 
1557     sPage->psi = psi;
1558     sPage->ObjectInfo = ObjectInfo;
1559     sPage->ServerName = SystemName;
1560     sPage->SidCacheMgr = SidCacheMgr;
1561 
1562     psp.dwSize = sizeof(PROPSHEETPAGE);
1563     psp.dwFlags = PSP_USECALLBACK;
1564     psp.hInstance = hDllInstance;
1565     psp.pszTemplate = MAKEINTRESOURCE(IDD_SECPAGE);
1566     psp.pfnDlgProc = SecurityPageProc;
1567     psp.lParam = (LPARAM)sPage;
1568     psp.pfnCallback = SecurityPageCallback;
1569 
1570     if (ObjectInfo.dwFlags & SI_PAGE_TITLE)
1571     {
1572         psp.pszTitle = ObjectInfo.pszPageTitle;
1573 
1574         if (psp.pszTitle != NULL)
1575         {
1576             psp.dwFlags |= PSP_USETITLE;
1577         }
1578     }
1579     else
1580     {
1581         psp.pszTitle = NULL;
1582     }
1583 
1584     /* NOTE: the SECURITY_PAGE structure will be freed by the property page
1585              callback! */
1586 
1587     return CreatePropertySheetPage(&psp);
1588 }
1589 
1590 
1591 /*
1592  * EditSecurity								EXPORTED
1593  *
1594  * @implemented
1595  */
1596 BOOL
1597 WINAPI
EditSecurity(IN HWND hwndOwner,IN LPSECURITYINFO psi)1598 EditSecurity(IN HWND hwndOwner,
1599              IN LPSECURITYINFO psi)
1600 {
1601     HRESULT hRet;
1602     SI_OBJECT_INFO ObjectInfo = {0};
1603     PROPSHEETHEADER psh;
1604     HPROPSHEETPAGE hPages[1];
1605     LPWSTR lpCaption = NULL;
1606     BOOL Ret;
1607 
1608     if (psi == NULL)
1609     {
1610         SetLastError(ERROR_INVALID_PARAMETER);
1611 
1612         DPRINT("No ISecurityInformation class passed!\n");
1613         return FALSE;
1614     }
1615 
1616     /* get the object information from the server. Zero the structure before
1617        because some applications seem to return SUCCESS but only seem to set the
1618        fields they care about. */
1619     hRet = psi->lpVtbl->GetObjectInformation(psi,
1620                                              &ObjectInfo);
1621 
1622     if (FAILED(hRet))
1623     {
1624         SetLastError(hRet);
1625 
1626         DPRINT("GetObjectInformation() failed!\n");
1627         return FALSE;
1628     }
1629 
1630     /* create the page */
1631     hPages[0] = CreateSecurityPage(psi);
1632     if (hPages[0] == NULL)
1633     {
1634         DPRINT("CreateSecurityPage(), couldn't create property sheet!\n");
1635         return FALSE;
1636     }
1637 
1638     psh.dwSize = sizeof(PROPSHEETHEADER);
1639     psh.dwFlags = PSH_DEFAULT;
1640     psh.hwndParent = hwndOwner;
1641     psh.hInstance = hDllInstance;
1642 
1643     /* Set the page title to the object name, make sure the format string
1644        has "%1" NOT "%s" because it uses FormatMessage() to automatically
1645        allocate the right amount of memory. */
1646     if (LoadAndFormatString(hDllInstance,
1647                             IDS_PSP_TITLE,
1648                             &lpCaption,
1649                             ObjectInfo.pszObjectName))
1650     {
1651         psh.pszCaption = lpCaption;
1652     }
1653     else
1654     {
1655         psh.pszCaption = ObjectInfo.pszObjectName;
1656     }
1657 
1658     psh.nPages = sizeof(hPages) / sizeof(HPROPSHEETPAGE);
1659     psh.nStartPage = 0;
1660     psh.phpage = hPages;
1661 
1662     Ret = (PropertySheet(&psh) != -1);
1663 
1664     if (lpCaption != NULL)
1665     {
1666         LocalFree((HLOCAL)lpCaption);
1667     }
1668 
1669     return Ret;
1670 }
1671 
1672 BOOL
1673 WINAPI
DllMain(IN HINSTANCE hinstDLL,IN DWORD dwReason,IN LPVOID lpvReserved)1674 DllMain(IN HINSTANCE hinstDLL,
1675         IN DWORD dwReason,
1676         IN LPVOID lpvReserved)
1677 {
1678     switch (dwReason)
1679     {
1680         case DLL_PROCESS_ATTACH:
1681             hDllInstance = hinstDLL;
1682 
1683             DisableThreadLibraryCalls(hinstDLL);
1684 
1685             if (!RegisterCheckListControl(hinstDLL))
1686             {
1687                 DPRINT("Registering the CHECKLIST_ACLUI class failed!\n");
1688                 return FALSE;
1689             }
1690             break;
1691 
1692         case DLL_PROCESS_DETACH:
1693             UnregisterCheckListControl(hinstDLL);
1694             break;
1695     }
1696 
1697     return TRUE;
1698 }
1699 
1700