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