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