d674edfc619184baa96ddd406fe1a17b011c2181
[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 VOID
346 CreatePrincipalListItem(OUT LVITEM *li,
347 IN PSECURITY_PAGE sp,
348 IN PPRINCIPAL_LISTITEM PrincipalListItem,
349 IN INT Index,
350 IN BOOL Selected)
351 {
352 INT ImageIndex = 2;
353
354 if (PrincipalListItem->SidReqResult != NULL)
355 {
356 switch (PrincipalListItem->SidReqResult->SidNameUse)
357 {
358 case SidTypeUser:
359 ImageIndex = 0;
360 break;
361 case SidTypeWellKnownGroup:
362 case SidTypeGroup:
363 ImageIndex = 1;
364 break;
365 default:
366 break;
367 }
368 }
369
370 li->mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
371 li->iItem = Index;
372 li->iSubItem = 0;
373 li->state = (Selected ? LVIS_SELECTED : 0);
374 li->stateMask = LVIS_SELECTED;
375 li->pszText = PrincipalListItem->DisplayString;
376 li->iImage = ImageIndex;
377 li->lParam = (LPARAM)PrincipalListItem;
378 }
379
380 static INT
381 AddPrincipalListEntry(IN PSECURITY_PAGE sp,
382 IN PPRINCIPAL_LISTITEM PrincipalListItem,
383 IN INT Index,
384 IN BOOL Selected)
385 {
386 LVITEM li;
387 INT Ret;
388
389 if (PrincipalListItem->DisplayString != NULL)
390 {
391 LocalFree((HLOCAL)PrincipalListItem->DisplayString);
392 }
393 PrincipalListItem->DisplayString = GetPrincipalDisplayString(PrincipalListItem);
394
395 CreatePrincipalListItem(&li,
396 sp,
397 PrincipalListItem,
398 Index,
399 Selected);
400
401 Ret = ListView_InsertItem(sp->hWndPrincipalsList,
402 &li);
403
404 return Ret;
405 }
406
407 static int CALLBACK
408 PrincipalCompare(IN LPARAM lParam1,
409 IN LPARAM lParam2,
410 IN LPARAM lParamSort)
411 {
412 PPRINCIPAL_LISTITEM Item1 = (PPRINCIPAL_LISTITEM)lParam1;
413 PPRINCIPAL_LISTITEM Item2 = (PPRINCIPAL_LISTITEM)lParam2;
414
415 if (Item1->DisplayString != NULL && Item2->DisplayString != NULL)
416 {
417 return wcscmp(Item1->DisplayString,
418 Item2->DisplayString);
419 }
420
421 return 0;
422 }
423
424 static VOID
425 UpdatePrincipalListItem(IN PSECURITY_PAGE sp,
426 IN INT PrincipalIndex,
427 IN PPRINCIPAL_LISTITEM PrincipalListItem,
428 IN PSIDREQRESULT SidReqResult)
429 {
430 LVITEM li;
431
432 /* replace the request result structure */
433 if (PrincipalListItem->SidReqResult != NULL)
434 {
435 DereferenceSidReqResult(sp->SidCacheMgr,
436 PrincipalListItem->SidReqResult);
437 }
438
439 ReferenceSidReqResult(sp->SidCacheMgr,
440 SidReqResult);
441 PrincipalListItem->SidReqResult = SidReqResult;
442
443 /* update the display string */
444 if (PrincipalListItem->DisplayString != NULL)
445 {
446 LocalFree((HLOCAL)PrincipalListItem->DisplayString);
447 }
448 PrincipalListItem->DisplayString = GetPrincipalDisplayString(PrincipalListItem);
449
450 /* update the list item */
451 CreatePrincipalListItem(&li,
452 sp,
453 PrincipalListItem,
454 PrincipalIndex,
455 FALSE);
456
457 /* don't change the list item state */
458 li.mask &= ~(LVIF_STATE | LVIF_PARAM);
459
460 ListView_SetItem(sp->hWndPrincipalsList,
461 &li);
462
463 /* sort the principals list view again */
464 ListView_SortItems(sp->hWndPrincipalsList,
465 PrincipalCompare,
466 (LPARAM)sp);
467 }
468
469 static VOID
470 ReloadPrincipalsList(IN PSECURITY_PAGE sp)
471 {
472 PSECURITY_DESCRIPTOR SecurityDescriptor;
473 BOOL DaclPresent, DaclDefaulted;
474 PACL Dacl = NULL;
475 HRESULT hRet;
476
477 /* delete the cached ACL */
478 FreePrincipalsList(sp,
479 &sp->PrincipalsListHead);
480
481 /* query the ACL */
482 hRet = sp->psi->lpVtbl->GetSecurity(sp->psi,
483 DACL_SECURITY_INFORMATION,
484 &SecurityDescriptor,
485 FALSE);
486 if (SUCCEEDED(hRet) && SecurityDescriptor != NULL)
487 {
488 if (GetSecurityDescriptorDacl(SecurityDescriptor,
489 &DaclPresent,
490 &Dacl,
491 &DaclDefaulted) &&
492 DaclPresent && Dacl != NULL)
493 {
494 PSID Sid;
495 PACE_HEADER AceHeader;
496 ULONG AceIndex;
497
498 for (AceIndex = 0;
499 AceIndex < Dacl->AceCount;
500 AceIndex++)
501 {
502 if (GetAce(Dacl,
503 AceIndex,
504 (LPVOID*)&AceHeader) &&
505 AceHeader != NULL)
506 {
507 BOOL LookupDeferred;
508 PPRINCIPAL_LISTITEM PrincipalListItem;
509
510 Sid = AceHeaderToSID(AceHeader);
511
512 PrincipalListItem = AddPrincipalToList(sp,
513 Sid,
514 AceHeader,
515 &LookupDeferred);
516
517 if (PrincipalListItem != NULL && LookupDeferred)
518 {
519 AddPrincipalListEntry(sp,
520 PrincipalListItem,
521 -1,
522 FALSE);
523 }
524 }
525 }
526 }
527 LocalFree((HLOCAL)SecurityDescriptor);
528 }
529 }
530
531 static VOID
532 UpdateControlStates(IN PSECURITY_PAGE sp)
533 {
534 PPRINCIPAL_LISTITEM Selected = (PPRINCIPAL_LISTITEM)ListViewGetSelectedItemData(sp->hWndPrincipalsList);
535
536 EnableWindow(sp->hBtnRemove,
537 Selected != NULL);
538 EnableWindow(sp->hAceCheckList,
539 Selected != NULL);
540
541 if (Selected != NULL)
542 {
543 LPWSTR szLabel;
544 LPWSTR szDisplayString;
545
546 szDisplayString = GetPrincipalDisplayString(Selected);
547 if (LoadAndFormatString(hDllInstance,
548 IDS_PERMISSIONS_FOR,
549 &szLabel,
550 szDisplayString))
551 {
552 SetWindowText(sp->hPermissionsForLabel,
553 szLabel);
554
555 LocalFree((HLOCAL)szLabel);
556 }
557
558 LocalFree((HLOCAL)szDisplayString);
559
560 /* FIXME - update the checkboxes */
561 }
562 else
563 {
564 WCHAR szPermissions[255];
565
566 if (LoadString(hDllInstance,
567 IDS_PERMISSIONS,
568 szPermissions,
569 sizeof(szPermissions) / sizeof(szPermissions[0])))
570 {
571 SetWindowText(sp->hPermissionsForLabel,
572 szPermissions);
573 }
574
575 SendMessage(sp->hAceCheckList,
576 CLM_CLEARCHECKBOXES,
577 0,
578 0);
579 }
580 }
581
582 static void
583 UpdatePrincipalInfo(IN PSECURITY_PAGE sp,
584 IN PSIDLOOKUPNOTIFYINFO LookupInfo)
585 {
586 PPRINCIPAL_LISTITEM CurItem;
587
588 for (CurItem = sp->PrincipalsListHead;
589 CurItem != NULL;
590 CurItem = CurItem->Next)
591 {
592 if (EqualSid((PSID)(CurItem + 1),
593 LookupInfo->Sid))
594 {
595 INT PrincipalIndex;
596 LVFINDINFO lvfi;
597
598 /* find the principal in the list */
599 lvfi.flags = LVFI_PARAM;
600 lvfi.lParam = (LPARAM)CurItem;
601 PrincipalIndex = ListView_FindItem(sp->hWndPrincipalsList,
602 -1,
603 &lvfi);
604
605 if (PrincipalIndex != -1)
606 {
607 /* update the principal in the list view control */
608 UpdatePrincipalListItem(sp,
609 PrincipalIndex,
610 CurItem,
611 LookupInfo->SidRequestResult);
612
613 if (ListViewGetSelectedItemData(sp->hWndPrincipalsList) == (LPARAM)CurItem)
614 {
615 UpdateControlStates(sp);
616 }
617 }
618 else
619 {
620 AddPrincipalListEntry(sp,
621 CurItem,
622 -1,
623 FALSE);
624 }
625 break;
626 }
627 }
628 }
629
630 static UINT CALLBACK
631 SecurityPageCallback(IN HWND hwnd,
632 IN UINT uMsg,
633 IN LPPROPSHEETPAGE ppsp)
634 {
635 PSECURITY_PAGE sp = (PSECURITY_PAGE)ppsp->lParam;
636
637 switch (uMsg)
638 {
639 case PSPCB_CREATE:
640 {
641 return TRUE;
642 }
643 case PSPCB_RELEASE:
644 {
645 DestroySecurityPage(sp);
646 return FALSE;
647 }
648 }
649
650 return FALSE;
651 }
652
653 static VOID
654 SetAceCheckListColumns(IN HWND hAceCheckList,
655 IN UINT Button,
656 IN HWND hLabel)
657 {
658 POINT pt;
659 RECT rcLabel;
660
661 GetWindowRect(hLabel,
662 &rcLabel);
663 pt.y = 0;
664 pt.x = (rcLabel.right - rcLabel.left) / 2;
665 MapWindowPoints(hLabel,
666 hAceCheckList,
667 &pt,
668 1);
669
670 SendMessage(hAceCheckList,
671 CLM_SETCHECKBOXCOLUMN,
672 Button,
673 pt.x);
674 }
675
676 static VOID
677 LoadPermissionsList(IN PSECURITY_PAGE sp,
678 IN GUID *GuidObjectType,
679 IN DWORD dwFlags,
680 OUT SI_ACCESS *DefaultAccess)
681 {
682 HRESULT hRet;
683 PSI_ACCESS AccessList;
684 ULONG nAccessList, DefaultAccessIndex;
685 WCHAR szSpecialPermissions[255];
686 BOOLEAN SpecialPermissionsPresent = FALSE;
687 ACCESS_MASK SpecialPermissionsMask = 0;
688
689 /* clear the permissions list */
690
691 SendMessage(sp->hAceCheckList,
692 CLM_CLEAR,
693 0,
694 0);
695
696 /* query the access rights from the server */
697 hRet = sp->psi->lpVtbl->GetAccessRights(sp->psi,
698 GuidObjectType,
699 dwFlags, /* FIXME */
700 &AccessList,
701 &nAccessList,
702 &DefaultAccessIndex);
703 if (SUCCEEDED(hRet) && nAccessList != 0)
704 {
705 LPCWSTR NameStr;
706 PSI_ACCESS CurAccess, LastAccess;
707 WCHAR NameBuffer[MAX_PATH];
708
709 /* save the default access rights to be used when adding ACEs later */
710 if (DefaultAccess != NULL)
711 {
712 *DefaultAccess = AccessList[DefaultAccessIndex];
713 }
714
715 LastAccess = AccessList + nAccessList;
716 for (CurAccess = &AccessList[0];
717 CurAccess != LastAccess;
718 CurAccess++)
719 {
720 if (CurAccess->dwFlags & dwFlags)
721 {
722 /* get the permission name, load it from a string table if necessary */
723 if (IS_INTRESOURCE(CurAccess->pszName))
724 {
725 if (!LoadString(sp->ObjectInfo.hInstance,
726 (UINT)((ULONG_PTR)CurAccess->pszName),
727 NameBuffer,
728 sizeof(NameBuffer) / sizeof(NameBuffer[0])))
729 {
730 LoadString(hDllInstance,
731 IDS_UNKNOWN,
732 NameBuffer,
733 sizeof(NameBuffer) / sizeof(NameBuffer[0]));
734 }
735 NameStr = NameBuffer;
736 }
737 else
738 {
739 NameStr = CurAccess->pszName;
740 }
741
742 SendMessage(sp->hAceCheckList,
743 CLM_ADDITEM,
744 (WPARAM)CurAccess->mask,
745 (LPARAM)NameStr);
746 }
747 else if (CurAccess->dwFlags & SI_ACCESS_SPECIFIC)
748 {
749 SpecialPermissionsPresent = TRUE;
750 SpecialPermissionsMask |= CurAccess->mask;
751 }
752 }
753 }
754
755 /* add the special permissions check item in case the specific access rights
756 aren't displayed */
757 if (SpecialPermissionsPresent &&
758 LoadString(hDllInstance,
759 IDS_SPECIAL_PERMISSIONS,
760 szSpecialPermissions,
761 sizeof(szSpecialPermissions) / sizeof(szSpecialPermissions[0])))
762 {
763 /* add the special permissions check item */
764 sp->SpecialPermCheckIndex = (INT)SendMessage(sp->hAceCheckList,
765 CLM_ADDITEM,
766 (WPARAM)SpecialPermissionsMask,
767 (LPARAM)szSpecialPermissions);
768 if (sp->SpecialPermCheckIndex != -1)
769 {
770 SendMessage(sp->hAceCheckList,
771 CLM_SETITEMSTATE,
772 (WPARAM)sp->SpecialPermCheckIndex,
773 CIS_ALLOWDISABLED | CIS_DENYDISABLED | CIS_NONE);
774 }
775 }
776 }
777
778 static VOID
779 ResizeControls(IN PSECURITY_PAGE sp,
780 IN INT Width,
781 IN INT Height)
782 {
783 HWND hWndAllow, hWndDeny;
784 RECT rcControl, rcControl2, rcControl3, rcWnd;
785 INT cxWidth, cxEdge, btnSpacing;
786 POINT pt, pt2;
787 HDWP dwp;
788 INT nControls = 7;
789 LVCOLUMN lvc;
790
791 hWndAllow = GetDlgItem(sp->hWnd,
792 IDC_LABEL_ALLOW);
793 hWndDeny = GetDlgItem(sp->hWnd,
794 IDC_LABEL_DENY);
795
796 GetWindowRect(sp->hWnd,
797 &rcWnd);
798
799 cxEdge = GetSystemMetrics(SM_CXEDGE);
800
801 /* use the left margin of the principal list view control for all control
802 margins */
803 pt.x = 0;
804 pt.y = 0;
805 MapWindowPoints(sp->hWndPrincipalsList,
806 sp->hWnd,
807 &pt,
808 1);
809 cxWidth = Width - (2 * pt.x);
810
811 if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
812 {
813 nControls += 2;
814 }
815
816 if ((dwp = BeginDeferWindowPos(nControls)))
817 {
818 /* resize the Principal list view */
819 GetWindowRect(sp->hWndPrincipalsList,
820 &rcControl);
821 if (!(dwp = DeferWindowPos(dwp,
822 sp->hWndPrincipalsList,
823 NULL,
824 0,
825 0,
826 cxWidth,
827 rcControl.bottom - rcControl.top,
828 SWP_NOMOVE | SWP_NOZORDER)))
829 {
830 goto EndDeferWnds;
831 }
832
833 /* move the Add Principal button */
834 GetWindowRect(sp->hBtnAdd,
835 &rcControl);
836 GetWindowRect(sp->hBtnRemove,
837 &rcControl2);
838 btnSpacing = rcControl2.left - rcControl.right;
839 pt2.x = 0;
840 pt2.y = 0;
841 MapWindowPoints(sp->hBtnAdd,
842 sp->hWnd,
843 &pt2,
844 1);
845 if (!(dwp = DeferWindowPos(dwp,
846 sp->hBtnAdd,
847 NULL,
848 pt.x + cxWidth - (rcControl2.right - rcControl2.left) -
849 (rcControl.right - rcControl.left) -
850 btnSpacing - cxEdge,
851 pt2.y,
852 0,
853 0,
854 SWP_NOSIZE | SWP_NOZORDER)))
855 {
856 goto EndDeferWnds;
857 }
858
859 /* move the Delete Principal button */
860 pt2.x = 0;
861 pt2.y = 0;
862 MapWindowPoints(sp->hBtnRemove,
863 sp->hWnd,
864 &pt2,
865 1);
866 if (!(dwp = DeferWindowPos(dwp,
867 sp->hBtnRemove,
868 NULL,
869 pt.x + cxWidth - (rcControl2.right - rcControl2.left) - cxEdge,
870 pt2.y,
871 0,
872 0,
873 SWP_NOSIZE | SWP_NOZORDER)))
874 {
875 goto EndDeferWnds;
876 }
877
878 /* move the Permissions For label */
879 GetWindowRect(hWndAllow,
880 &rcControl);
881 GetWindowRect(hWndDeny,
882 &rcControl2);
883 GetWindowRect(sp->hPermissionsForLabel,
884 &rcControl3);
885 pt2.x = 0;
886 pt2.y = 0;
887 MapWindowPoints(sp->hPermissionsForLabel,
888 sp->hWnd,
889 &pt2,
890 1);
891 if (!(dwp = DeferWindowPos(dwp,
892 sp->hPermissionsForLabel,
893 NULL,
894 0,
895 0,
896 cxWidth - (rcControl2.right - rcControl2.left) -
897 (rcControl.right - rcControl.left) -
898 (2 * btnSpacing) - cxEdge,
899 rcControl3.bottom - rcControl3.top,
900 SWP_NOMOVE | SWP_NOZORDER)))
901 {
902 goto EndDeferWnds;
903 }
904
905 /* move the Allow label */
906 pt2.x = 0;
907 pt2.y = 0;
908 MapWindowPoints(hWndAllow,
909 sp->hWnd,
910 &pt2,
911 1);
912 if (!(dwp = DeferWindowPos(dwp,
913 hWndAllow,
914 NULL,
915 cxWidth - (rcControl2.right - rcControl2.left) -
916 (rcControl.right - rcControl.left) -
917 btnSpacing - cxEdge,
918 pt2.y,
919 0,
920 0,
921 SWP_NOSIZE | SWP_NOZORDER)))
922 {
923 goto EndDeferWnds;
924 }
925
926 /* move the Deny label */
927 pt2.x = 0;
928 pt2.y = 0;
929 MapWindowPoints(hWndDeny,
930 sp->hWnd,
931 &pt2,
932 1);
933 if (!(dwp = DeferWindowPos(dwp,
934 hWndDeny,
935 NULL,
936 cxWidth - (rcControl2.right - rcControl2.left) - cxEdge,
937 pt2.y,
938 0,
939 0,
940 SWP_NOSIZE | SWP_NOZORDER)))
941 {
942 goto EndDeferWnds;
943 }
944
945 /* resize the Permissions check list box */
946 GetWindowRect(sp->hAceCheckList,
947 &rcControl);
948 GetWindowRect(sp->hBtnAdvanced,
949 &rcControl2);
950 GetWindowRect(GetDlgItem(sp->hWnd,
951 IDC_LABEL_ADVANCED),
952 &rcControl3);
953 if (!(dwp = DeferWindowPos(dwp,
954 sp->hAceCheckList,
955 NULL,
956 0,
957 0,
958 cxWidth,
959 ((sp->ObjectInfo.dwFlags & SI_ADVANCED) ?
960 Height - (rcControl.top - rcWnd.top) -
961 (rcControl3.bottom - rcControl3.top) - pt.x - btnSpacing :
962 Height - (rcControl.top - rcWnd.top) - pt.x),
963 SWP_NOMOVE | SWP_NOZORDER)))
964 {
965 goto EndDeferWnds;
966 }
967
968 if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
969 {
970 /* move and resize the Advanced label */
971 if (!(dwp = DeferWindowPos(dwp,
972 GetDlgItem(sp->hWnd,
973 IDC_LABEL_ADVANCED),
974 NULL,
975 pt.x,
976 Height - (rcControl3.bottom - rcControl3.top) - pt.x,
977 cxWidth - (rcControl2.right - rcControl2.left) - cxEdge,
978 rcControl3.bottom - rcControl3.top,
979 SWP_NOZORDER)))
980 {
981 goto EndDeferWnds;
982 }
983
984 /* move and resize the Advanced button */
985 if (!(dwp = DeferWindowPos(dwp,
986 sp->hBtnAdvanced,
987 NULL,
988 cxWidth - (rcControl2.right - rcControl2.left) + pt.x,
989 Height - (rcControl2.bottom - rcControl2.top) - pt.x,
990 0,
991 0,
992 SWP_NOSIZE | SWP_NOZORDER)))
993 {
994 goto EndDeferWnds;
995 }
996 }
997
998 EndDeferWindowPos(dwp);
999 }
1000
1001 EndDeferWnds:
1002 /* update the width of the principal list view column */
1003 GetClientRect(sp->hWndPrincipalsList,
1004 &rcControl);
1005 lvc.mask = LVCF_WIDTH;
1006 lvc.cx = rcControl.right;
1007 ListView_SetColumn(sp->hWndPrincipalsList,
1008 0,
1009 &lvc);
1010
1011 /* calculate the columns of the allow/deny checkboxes */
1012 SetAceCheckListColumns(sp->hAceCheckList,
1013 CLB_ALLOW,
1014 hWndAllow);
1015 SetAceCheckListColumns(sp->hAceCheckList,
1016 CLB_DENY,
1017 hWndDeny);
1018 }
1019
1020 static PACE_HEADER
1021 BuildDefaultPrincipalAce(IN PSECURITY_PAGE sp,
1022 IN PSID pSid)
1023 {
1024 PACCESS_ALLOWED_ACE Ace;
1025 DWORD SidLen;
1026 WORD AceSize;
1027
1028 SidLen = GetLengthSid(pSid);
1029 AceSize = sizeof(ACCESS_ALLOWED_ACE) + (WORD)SidLen - sizeof(DWORD);
1030 Ace = HeapAlloc(GetProcessHeap(),
1031 0,
1032 AceSize);
1033 if (Ace != NULL)
1034 {
1035 Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
1036 Ace->Header.AceFlags = 0; /* FIXME */
1037 Ace->Header.AceSize = AceSize;
1038 Ace->Mask = sp->DefaultAccess.mask;
1039
1040 if (CopySid(SidLen,
1041 (PSID)&Ace->SidStart,
1042 pSid))
1043 {
1044 return &Ace->Header;
1045 }
1046
1047 HeapFree(GetProcessHeap(),
1048 0,
1049 Ace);
1050 }
1051
1052 return NULL;
1053 }
1054
1055 static BOOL
1056 AddSelectedPrincipal(IN IDsObjectPicker *pDsObjectPicker,
1057 IN HWND hwndParent OPTIONAL,
1058 IN PSID pSid,
1059 IN PVOID Context OPTIONAL)
1060 {
1061 PACE_HEADER AceHeader;
1062 PSECURITY_PAGE sp = (PSECURITY_PAGE)Context;
1063
1064 AceHeader = BuildDefaultPrincipalAce(sp,
1065 pSid);
1066 if (AceHeader != NULL)
1067 {
1068 PPRINCIPAL_LISTITEM PrincipalListItem;
1069 BOOL LookupDeferred;
1070
1071 PrincipalListItem = AddPrincipalToList(sp,
1072 pSid,
1073 AceHeader,
1074 &LookupDeferred);
1075
1076 if (PrincipalListItem != NULL && LookupDeferred)
1077 {
1078 AddPrincipalListEntry(sp,
1079 PrincipalListItem,
1080 -1,
1081 FALSE);
1082 }
1083
1084 HeapFree(GetProcessHeap(),
1085 0,
1086 AceHeader);
1087 }
1088
1089 return TRUE;
1090 }
1091
1092 static INT_PTR CALLBACK
1093 SecurityPageProc(IN HWND hwndDlg,
1094 IN UINT uMsg,
1095 IN WPARAM wParam,
1096 IN LPARAM lParam)
1097 {
1098 PSECURITY_PAGE sp;
1099 INT_PTR Ret = FALSE;
1100
1101 sp = (PSECURITY_PAGE)GetWindowLongPtr(hwndDlg,
1102 DWL_USER);
1103 if (sp != NULL || uMsg == WM_INITDIALOG)
1104 {
1105 switch (uMsg)
1106 {
1107 case WM_NOTIFY:
1108 {
1109 NMHDR *pnmh = (NMHDR*)lParam;
1110
1111 if (pnmh->hwndFrom == sp->hWndPrincipalsList)
1112 {
1113 switch (pnmh->code)
1114 {
1115 case LVN_ITEMCHANGED:
1116 {
1117 LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
1118
1119 if ((pnmv->uChanged & LVIF_STATE) &&
1120 ((pnmv->uOldState & (LVIS_FOCUSED | LVIS_SELECTED)) ||
1121 (pnmv->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))))
1122 {
1123 UpdateControlStates(sp);
1124 }
1125 break;
1126 }
1127 }
1128 }
1129 else if (pnmh->hwndFrom == sp->hAceCheckList)
1130 {
1131 switch (pnmh->code)
1132 {
1133 case CLN_CHANGINGITEMCHECKBOX:
1134 {
1135 PNMCHANGEITEMCHECKBOX pcicb = (PNMCHANGEITEMCHECKBOX)lParam;
1136
1137 /* make sure only one of both checkboxes is only checked
1138 at the same time */
1139 if (pcicb->Checked)
1140 {
1141 pcicb->NewState &= ~((pcicb->CheckBox != CLB_DENY) ? CIS_DENY : CIS_ALLOW);
1142 }
1143 break;
1144 }
1145 }
1146 }
1147 else if (pnmh->hwndFrom == sp->hWnd)
1148 {
1149 switch(pnmh->code)
1150 {
1151 case SIDN_LOOKUPSUCCEEDED:
1152 {
1153 PSIDLOOKUPNOTIFYINFO LookupInfo = CONTAINING_RECORD(lParam,
1154 SIDLOOKUPNOTIFYINFO,
1155 nmh);
1156
1157 /* a SID lookup succeeded, update the information */
1158 UpdatePrincipalInfo(sp,
1159 LookupInfo);
1160 break;
1161 }
1162 }
1163 }
1164 break;
1165 }
1166
1167 case WM_COMMAND:
1168 {
1169 switch (LOWORD(wParam))
1170 {
1171 case IDC_ADD_PRINCIPAL:
1172 {
1173 HRESULT hRet;
1174
1175 hRet = InitializeObjectPicker(sp->ServerName,
1176 &sp->ObjectInfo,
1177 &sp->pDsObjectPicker);
1178 if (SUCCEEDED(hRet))
1179 {
1180 hRet = InvokeObjectPickerDialog(sp->pDsObjectPicker,
1181 hwndDlg,
1182 AddSelectedPrincipal,
1183 sp);
1184 if (FAILED(hRet))
1185 {
1186 MessageBox(hwndDlg, L"InvokeObjectPickerDialog failed!\n", NULL, 0);
1187 }
1188
1189 /* delete the instance */
1190 FreeObjectPicker(sp->pDsObjectPicker);
1191 }
1192 else
1193 {
1194 MessageBox(hwndDlg, L"InitializeObjectPicker failed!\n", NULL, 0);
1195 }
1196 break;
1197 }
1198
1199 case IDC_REMOVE_PRINCIPAL:
1200 {
1201 PPRINCIPAL_LISTITEM SelectedPrincipal;
1202
1203 SelectedPrincipal = (PPRINCIPAL_LISTITEM)ListViewGetSelectedItemData(sp->hWndPrincipalsList);
1204 if (SelectedPrincipal != NULL)
1205 {
1206 /* FIXME */
1207 }
1208 break;
1209 }
1210 }
1211 break;
1212 }
1213
1214 case WM_SIZE:
1215 {
1216 ResizeControls(sp,
1217 (INT)LOWORD(lParam),
1218 (INT)HIWORD(lParam));
1219 break;
1220 }
1221
1222 case WM_INITDIALOG:
1223 {
1224 sp = (PSECURITY_PAGE)((LPPROPSHEETPAGE)lParam)->lParam;
1225 if(sp != NULL)
1226 {
1227 LV_COLUMN lvc;
1228 RECT rcLvClient;
1229
1230 sp->hWnd = hwndDlg;
1231 sp->hWndPrincipalsList = GetDlgItem(hwndDlg, IDC_PRINCIPALS);
1232 sp->hBtnAdd = GetDlgItem(hwndDlg, IDC_ADD_PRINCIPAL);
1233 sp->hBtnRemove = GetDlgItem(hwndDlg, IDC_REMOVE_PRINCIPAL);
1234 sp->hBtnAdvanced = GetDlgItem(hwndDlg, IDC_ADVANCED);
1235 sp->hAceCheckList = GetDlgItem(hwndDlg, IDC_ACE_CHECKLIST);
1236 sp->hPermissionsForLabel = GetDlgItem(hwndDlg, IDC_LABEL_PERMISSIONS_FOR);
1237
1238 sp->SpecialPermCheckIndex = -1;
1239
1240 /* save the pointer to the structure */
1241 SetWindowLongPtr(hwndDlg,
1242 DWL_USER,
1243 (DWORD_PTR)sp);
1244
1245 ListView_SetExtendedListViewStyleEx(sp->hWndPrincipalsList,
1246 LVS_EX_FULLROWSELECT,
1247 LVS_EX_FULLROWSELECT);
1248
1249 sp->hiPrincipals = ImageList_LoadBitmap(hDllInstance,
1250 MAKEINTRESOURCE(IDB_USRGRPIMAGES),
1251 16,
1252 3,
1253 RGB(255,
1254 0,
1255 255));
1256
1257 /* setup the listview control */
1258 if (sp->hiPrincipals != NULL)
1259 {
1260 ListView_SetImageList(sp->hWndPrincipalsList,
1261 sp->hiPrincipals,
1262 LVSIL_SMALL);
1263 }
1264
1265 GetClientRect(sp->hWndPrincipalsList,
1266 &rcLvClient);
1267
1268 /* add a column to the list view */
1269 lvc.mask = LVCF_FMT | LVCF_WIDTH;
1270 lvc.fmt = LVCFMT_LEFT;
1271 lvc.cx = rcLvClient.right;
1272 ListView_InsertColumn(sp->hWndPrincipalsList,
1273 0,
1274 &lvc);
1275
1276 ReloadPrincipalsList(sp);
1277
1278 ListViewSelectItem(sp->hWndPrincipalsList,
1279 0);
1280
1281 /* calculate the columns of the allow/deny checkboxes */
1282 SetAceCheckListColumns(sp->hAceCheckList,
1283 CLB_ALLOW,
1284 GetDlgItem(hwndDlg, IDC_LABEL_ALLOW));
1285 SetAceCheckListColumns(sp->hAceCheckList,
1286 CLB_DENY,
1287 GetDlgItem(hwndDlg, IDC_LABEL_DENY));
1288
1289 LoadPermissionsList(sp,
1290 NULL,
1291 SI_ACCESS_GENERAL |
1292 ((sp->ObjectInfo.dwFlags & SI_CONTAINER) ? SI_ACCESS_CONTAINER : 0),
1293 &sp->DefaultAccess);
1294
1295 /* hide controls in case the flags aren't present */
1296 if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
1297 {
1298 /* editing the permissions is least the user can do when
1299 the advanced button is showed */
1300 sp->ObjectInfo.dwFlags |= SI_EDIT_PERMS;
1301 }
1302 else
1303 {
1304 ShowWindow(sp->hBtnAdvanced,
1305 SW_HIDE);
1306 ShowWindow(GetDlgItem(hwndDlg, IDC_LABEL_ADVANCED),
1307 SW_HIDE);
1308 }
1309
1310 /* enable quicksearch for the permissions checklist control */
1311 SendMessage(sp->hAceCheckList,
1312 CLM_ENABLEQUICKSEARCH,
1313 TRUE,
1314 0);
1315
1316 UpdateControlStates(sp);
1317 }
1318
1319 Ret = TRUE;
1320 break;
1321 }
1322 }
1323 }
1324 return Ret;
1325 }
1326
1327
1328 /*
1329 * CreateSecurityPage EXPORTED
1330 *
1331 * @implemented
1332 */
1333 HPROPSHEETPAGE
1334 WINAPI
1335 CreateSecurityPage(IN LPSECURITYINFO psi)
1336 {
1337 PROPSHEETPAGE psp = {0};
1338 PSECURITY_PAGE sPage;
1339 SI_OBJECT_INFO ObjectInfo = {0};
1340 HANDLE SidCacheMgr;
1341 LPCWSTR SystemName = NULL;
1342 HRESULT hRet;
1343
1344 if (psi == NULL)
1345 {
1346 SetLastError(ERROR_INVALID_PARAMETER);
1347
1348 DPRINT("No ISecurityInformation class passed!\n");
1349 return NULL;
1350 }
1351
1352 /* get the object information from the server. Zero the structure before
1353 because some applications seem to return SUCCESS but only seem to set the
1354 fields they care about. */
1355 hRet = psi->lpVtbl->GetObjectInformation(psi,
1356 &ObjectInfo);
1357
1358 if (FAILED(hRet))
1359 {
1360 SetLastError(hRet);
1361
1362 DPRINT("CreateSecurityPage() failed! Failed to query the object information!\n");
1363 return NULL;
1364 }
1365
1366 if ((ObjectInfo.dwFlags & SI_SERVER_IS_DC) &&
1367 ObjectInfo.pszServerName != NULL &&
1368 ObjectInfo.pszServerName[0] != L'\0')
1369 {
1370 SystemName = ObjectInfo.pszServerName;
1371 }
1372
1373 SidCacheMgr = CreateSidCacheMgr(GetProcessHeap(),
1374 SystemName);
1375 if (SidCacheMgr == NULL)
1376 {
1377 DPRINT("Creating the SID cache failed!\n");
1378 return NULL;
1379 }
1380
1381 hRet = CoInitialize(NULL);
1382 if (FAILED(hRet))
1383 {
1384 DestroySidCacheMgr(SidCacheMgr);
1385 DPRINT("CoInitialize failed!\n");
1386 return NULL;
1387 }
1388
1389 sPage = HeapAlloc(GetProcessHeap(),
1390 HEAP_ZERO_MEMORY,
1391 sizeof(SECURITY_PAGE));
1392 if (sPage == NULL)
1393 {
1394 DestroySidCacheMgr(SidCacheMgr);
1395 CoUninitialize();
1396
1397 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1398
1399 DPRINT("Not enough memory to allocate a SECURITY_PAGE!\n");
1400 return NULL;
1401 }
1402
1403 sPage->psi = psi;
1404 sPage->ObjectInfo = ObjectInfo;
1405 sPage->ServerName = SystemName;
1406 sPage->SidCacheMgr = SidCacheMgr;
1407
1408 psp.dwSize = sizeof(PROPSHEETPAGE);
1409 psp.dwFlags = PSP_USECALLBACK;
1410 psp.hInstance = hDllInstance;
1411 psp.pszTemplate = MAKEINTRESOURCE(IDD_SECPAGE);
1412 psp.pfnDlgProc = SecurityPageProc;
1413 psp.lParam = (LPARAM)sPage;
1414 psp.pfnCallback = SecurityPageCallback;
1415
1416 if (ObjectInfo.dwFlags & SI_PAGE_TITLE)
1417 {
1418 psp.pszTitle = ObjectInfo.pszPageTitle;
1419
1420 if (psp.pszTitle != NULL)
1421 {
1422 psp.dwFlags |= PSP_USETITLE;
1423 }
1424 }
1425 else
1426 {
1427 psp.pszTitle = NULL;
1428 }
1429
1430 /* NOTE: the SECURITY_PAGE structure will be freed by the property page
1431 callback! */
1432
1433 return CreatePropertySheetPage(&psp);
1434 }
1435
1436
1437 /*
1438 * EditSecurity EXPORTED
1439 *
1440 * @implemented
1441 */
1442 BOOL
1443 WINAPI
1444 EditSecurity(IN HWND hwndOwner,
1445 IN LPSECURITYINFO psi)
1446 {
1447 HRESULT hRet;
1448 SI_OBJECT_INFO ObjectInfo = {0};
1449 PROPSHEETHEADER psh;
1450 HPROPSHEETPAGE hPages[1];
1451 LPWSTR lpCaption = NULL;
1452 BOOL Ret;
1453
1454 if (psi == NULL)
1455 {
1456 SetLastError(ERROR_INVALID_PARAMETER);
1457
1458 DPRINT("No ISecurityInformation class passed!\n");
1459 return FALSE;
1460 }
1461
1462 /* get the object information from the server. Zero the structure before
1463 because some applications seem to return SUCCESS but only seem to set the
1464 fields they care about. */
1465 hRet = psi->lpVtbl->GetObjectInformation(psi,
1466 &ObjectInfo);
1467
1468 if (FAILED(hRet))
1469 {
1470 SetLastError(hRet);
1471
1472 DPRINT("GetObjectInformation() failed!\n");
1473 return FALSE;
1474 }
1475
1476 /* create the page */
1477 hPages[0] = CreateSecurityPage(psi);
1478 if (hPages[0] == NULL)
1479 {
1480 DPRINT("CreateSecurityPage(), couldn't create property sheet!\n");
1481 return FALSE;
1482 }
1483
1484 psh.dwSize = sizeof(PROPSHEETHEADER);
1485 psh.dwFlags = PSH_DEFAULT;
1486 psh.hwndParent = hwndOwner;
1487 psh.hInstance = hDllInstance;
1488
1489 /* Set the page title to the object name, make sure the format string
1490 has "%1" NOT "%s" because it uses FormatMessage() to automatically
1491 allocate the right amount of memory. */
1492 if (LoadAndFormatString(hDllInstance,
1493 IDS_PSP_TITLE,
1494 &lpCaption,
1495 ObjectInfo.pszObjectName))
1496 {
1497 psh.pszCaption = lpCaption;
1498 }
1499 else
1500 {
1501 psh.pszCaption = ObjectInfo.pszObjectName;
1502 }
1503
1504 psh.nPages = sizeof(hPages) / sizeof(HPROPSHEETPAGE);
1505 psh.nStartPage = 0;
1506 psh.phpage = hPages;
1507
1508 Ret = (PropertySheet(&psh) != -1);
1509
1510 if (lpCaption != NULL)
1511 {
1512 LocalFree((HLOCAL)lpCaption);
1513 }
1514
1515 return Ret;
1516 }
1517
1518 BOOL
1519 WINAPI
1520 DllMain(IN HINSTANCE hinstDLL,
1521 IN DWORD dwReason,
1522 IN LPVOID lpvReserved)
1523 {
1524 switch (dwReason)
1525 {
1526 case DLL_PROCESS_ATTACH:
1527 hDllInstance = hinstDLL;
1528
1529 DisableThreadLibraryCalls(hinstDLL);
1530
1531 if (!RegisterCheckListControl(hinstDLL))
1532 {
1533 DPRINT("Registering the CHECKLIST_ACLUI class failed!\n");
1534 return FALSE;
1535 }
1536 break;
1537
1538 case DLL_PROCESS_DETACH:
1539 UnregisterCheckListControl();
1540 break;
1541 }
1542
1543 return TRUE;
1544 }
1545