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