6864216779c4f02ff3e8500dd82f0fb7812b758e
[reactos.git] / reactos / lib / aclui / aclui.c
1 /*
2 * ReactOS Access Control List Editor
3 * Copyright (C) 2004 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 "acluilib.h"
30
31 HINSTANCE hDllInstance;
32
33 static VOID
34 DestroySecurityPage(IN PSECURITY_PAGE sp)
35 {
36 if(sp->hiUsrs != NULL)
37 {
38 ImageList_Destroy(sp->hiUsrs);
39 }
40
41 HeapFree(GetProcessHeap(),
42 0,
43 sp);
44 }
45
46 static VOID
47 FreeAceList(IN PACE_LISTITEM *AceListHead)
48 {
49 PACE_LISTITEM CurItem, NextItem;
50
51 CurItem = *AceListHead;
52 while (CurItem != NULL)
53 {
54 /* free the SID string if present */
55 if (CurItem->DisplayString != NULL)
56 {
57 LocalFree((HLOCAL)CurItem->DisplayString);
58 }
59
60 /* free the ACE list item */
61 NextItem = CurItem->Next;
62 HeapFree(GetProcessHeap(),
63 0,
64 CurItem);
65 CurItem = NextItem;
66 }
67
68 *AceListHead = NULL;
69 }
70
71 static PACE_LISTITEM
72 FindSidInAceList(IN PACE_LISTITEM AceListHead,
73 IN PSID Sid)
74 {
75 PACE_LISTITEM CurItem;
76
77 for (CurItem = AceListHead;
78 CurItem != NULL;
79 CurItem = CurItem->Next)
80 {
81 if (EqualSid((PSID)(CurItem + 1),
82 Sid))
83 {
84 return CurItem;
85 }
86 }
87
88 return NULL;
89 }
90
91 static VOID
92 ReloadUsersGroupsList(IN PSECURITY_PAGE sp)
93 {
94 PSECURITY_DESCRIPTOR SecurityDescriptor;
95 BOOL DaclPresent, DaclDefaulted;
96 PACL Dacl = NULL;
97 HRESULT hRet;
98
99 /* delete the cached ACL */
100 FreeAceList(&sp->AceListHead);
101
102 /* query the ACL */
103 hRet = sp->psi->lpVtbl->GetSecurity(sp->psi,
104 DACL_SECURITY_INFORMATION,
105 &SecurityDescriptor,
106 FALSE);
107 if (SUCCEEDED(hRet) && SecurityDescriptor != NULL)
108 {
109 if (GetSecurityDescriptorDacl(SecurityDescriptor,
110 &DaclPresent,
111 &Dacl,
112 &DaclDefaulted))
113 {
114 PACE_LISTITEM AceListItem, *NextAcePtr;
115 PSID Sid;
116 PVOID Ace;
117 ULONG AceIndex;
118 DWORD AccountNameSize, DomainNameSize, SidLength;
119 SID_NAME_USE SidNameUse;
120 DWORD LookupResult;
121
122 NextAcePtr = &sp->AceListHead;
123
124 for (AceIndex = 0;
125 AceIndex < Dacl->AceCount;
126 AceIndex++)
127 {
128 GetAce(Dacl,
129 AceIndex,
130 &Ace);
131
132 Sid = (PSID)&((PACCESS_ALLOWED_ACE)Ace)->SidStart;
133
134 if (!FindSidInAceList(sp->AceListHead,
135 Sid))
136 {
137 SidLength = GetLengthSid(Sid);
138
139 AccountNameSize = 0;
140 DomainNameSize = 0;
141
142 /* calculate the size of the buffer we need to calculate */
143 LookupAccountSid(sp->ServerName,
144 Sid,
145 NULL,
146 &AccountNameSize,
147 NULL,
148 &DomainNameSize,
149 &SidNameUse);
150
151 /* allocate the ace */
152 AceListItem = HeapAlloc(GetProcessHeap(),
153 0,
154 sizeof(ACE_LISTITEM) +
155 SidLength +
156 ((AccountNameSize + DomainNameSize) * sizeof(WCHAR)));
157 if (AceListItem != NULL)
158 {
159 AceListItem->AccountName = (LPWSTR)((ULONG_PTR)(AceListItem + 1) + SidLength);
160 AceListItem->DomainName = AceListItem->AccountName + AccountNameSize;
161
162 CopySid(SidLength,
163 (PSID)(AceListItem + 1),
164 Sid);
165
166 LookupResult = ERROR_SUCCESS;
167 if (!LookupAccountSid(sp->ServerName,
168 Sid,
169 AceListItem->AccountName,
170 &AccountNameSize,
171 AceListItem->DomainName,
172 &DomainNameSize,
173 &SidNameUse))
174 {
175 LookupResult = GetLastError();
176 if (LookupResult != ERROR_NONE_MAPPED)
177 {
178 HeapFree(GetProcessHeap(),
179 0,
180 AceListItem);
181 continue;
182 }
183 }
184
185 if (AccountNameSize == 0)
186 {
187 AceListItem->AccountName = NULL;
188 }
189 if (DomainNameSize == 0)
190 {
191 AceListItem->DomainName = NULL;
192 }
193
194 AceListItem->Next = NULL;
195 if (LookupResult == ERROR_NONE_MAPPED)
196 {
197 if (!ConvertSidToStringSid(Sid,
198 &AceListItem->DisplayString))
199 {
200 AceListItem->DisplayString = NULL;
201 }
202 }
203 else
204 {
205 LSA_HANDLE LsaHandle;
206 NTSTATUS Status;
207
208 AceListItem->DisplayString = NULL;
209
210 /* read the domain of the SID */
211 if (OpenLSAPolicyHandle(sp->ServerName,
212 POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
213 &LsaHandle))
214 {
215 PLSA_REFERENCED_DOMAIN_LIST ReferencedDomain;
216 PLSA_TRANSLATED_NAME Names;
217 PLSA_TRUST_INFORMATION Domain;
218 PLSA_UNICODE_STRING DomainName;
219 PPOLICY_ACCOUNT_DOMAIN_INFO PolicyAccountDomainInfo = NULL;
220
221 Status = LsaLookupSids(LsaHandle,
222 1,
223 &Sid,
224 &ReferencedDomain,
225 &Names);
226 if (NT_SUCCESS(Status))
227 {
228 if (ReferencedDomain != NULL &&
229 Names->DomainIndex >= 0)
230 {
231 Domain = &ReferencedDomain->Domains[Names->DomainIndex];
232 DomainName = &Domain->Name;
233 }
234 else
235 {
236 Domain = NULL;
237 DomainName = NULL;
238 }
239
240 AceListItem->SidNameUse = Names->Use;
241
242 switch (Names->Use)
243 {
244 case SidTypeAlias:
245 if (Domain != NULL)
246 {
247 /* query the domain name for BUILTIN accounts */
248 Status = LsaQueryInformationPolicy(LsaHandle,
249 PolicyAccountDomainInformation,
250 (PVOID*)&PolicyAccountDomainInfo);
251 if (NT_SUCCESS(Status))
252 {
253 DomainName = &PolicyAccountDomainInfo->DomainName;
254
255 /* make the user believe this is a group */
256 AceListItem->SidNameUse = SidTypeGroup;
257 }
258 }
259 /* fall through */
260
261 case SidTypeUser:
262 {
263 if (Domain != NULL)
264 {
265 AceListItem->DisplayString = (LPWSTR)LocalAlloc(LMEM_FIXED,
266 (AccountNameSize * sizeof(WCHAR)) +
267 (DomainName->Length + sizeof(WCHAR)) +
268 (Names->Name.Length + sizeof(WCHAR)) +
269 (4 * sizeof(WCHAR)));
270 if (AceListItem->DisplayString != NULL)
271 {
272 WCHAR *s;
273
274 /* NOTE: LSA_UNICODE_STRINGs are not always NULL-terminated! */
275
276 wcscpy(AceListItem->DisplayString,
277 AceListItem->AccountName);
278 wcscat(AceListItem->DisplayString,
279 L" (");
280 s = AceListItem->DisplayString + wcslen(AceListItem->DisplayString);
281 CopyMemory(s,
282 DomainName->Buffer,
283 DomainName->Length);
284 s += DomainName->Length / sizeof(WCHAR);
285 *(s++) = L'\\';
286 CopyMemory(s,
287 Names->Name.Buffer,
288 Names->Name.Length);
289 s += Names->Name.Length / sizeof(WCHAR);
290 *(s++) = L')';
291 *s = L'\0';
292 }
293
294 /* mark the ace as a user unless it's a
295 BUILTIN account */
296 if (PolicyAccountDomainInfo == NULL)
297 {
298 AceListItem->SidNameUse = SidTypeUser;
299 }
300 }
301 break;
302 }
303
304 case SidTypeWellKnownGroup:
305 {
306 /* make the user believe this is a group */
307 AceListItem->SidNameUse = SidTypeGroup;
308 break;
309 }
310
311 default:
312 {
313 DPRINT("Unhandled SID type: 0x%x\n", Names->Use);
314 break;
315 }
316 }
317
318 if (PolicyAccountDomainInfo != NULL)
319 {
320 LsaFreeMemory(PolicyAccountDomainInfo);
321 }
322
323 LsaFreeMemory(ReferencedDomain);
324 LsaFreeMemory(Names);
325 }
326 LsaClose(LsaHandle);
327 }
328 }
329
330 /* append item to the cached ACL */
331 *NextAcePtr = AceListItem;
332 NextAcePtr = &AceListItem->Next;
333 }
334 }
335 }
336 }
337 LocalFree((HLOCAL)SecurityDescriptor);
338 }
339 }
340
341 static INT
342 AddAceListEntry(IN PSECURITY_PAGE sp,
343 IN PACE_LISTITEM AceListItem,
344 IN INT Index,
345 IN BOOL Selected)
346 {
347 LVITEM li;
348
349 li.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
350 li.iItem = Index;
351 li.iSubItem = 0;
352 li.state = (Selected ? LVIS_SELECTED : 0);
353 li.stateMask = LVIS_SELECTED;
354 li.pszText = (AceListItem->DisplayString != NULL ? AceListItem->DisplayString : AceListItem->AccountName);
355 switch (AceListItem->SidNameUse)
356 {
357 case SidTypeUser:
358 li.iImage = 0;
359 break;
360 case SidTypeGroup:
361 li.iImage = 1;
362 break;
363 default:
364 li.iImage = -1;
365 break;
366 }
367 li.lParam = (LPARAM)AceListItem;
368
369 return ListView_InsertItem(sp->hWndAceList,
370 &li);
371 }
372
373 static VOID
374 FillUsersGroupsList(IN PSECURITY_PAGE sp)
375 {
376 LPARAM SelLParam;
377 PACE_LISTITEM CurItem;
378 RECT rcLvClient;
379
380 SelLParam = ListViewGetSelectedItemData(sp->hWndAceList);
381
382 DisableRedrawWindow(sp->hWndAceList);
383
384 ListView_DeleteAllItems(sp->hWndAceList);
385
386 ReloadUsersGroupsList(sp);
387
388 for (CurItem = sp->AceListHead;
389 CurItem != NULL;
390 CurItem = CurItem->Next)
391 {
392 AddAceListEntry(sp,
393 CurItem,
394 -1,
395 (SelLParam == (LPARAM)CurItem));
396 }
397
398 EnableRedrawWindow(sp->hWndAceList);
399
400 GetClientRect(sp->hWndAceList, &rcLvClient);
401
402 ListView_SetColumnWidth(sp->hWndAceList,
403 0,
404 rcLvClient.right);
405 }
406
407 static VOID
408 UpdateControlStates(IN PSECURITY_PAGE sp)
409 {
410 PACE_LISTITEM Selected = (PACE_LISTITEM)ListViewGetSelectedItemData(sp->hWndAceList);
411
412 EnableWindow(sp->hBtnRemove, Selected != NULL);
413 EnableWindow(sp->hAceCheckList, Selected != NULL);
414
415 if (Selected != NULL)
416 {
417 LPWSTR szLabel;
418
419 if (LoadAndFormatString(hDllInstance,
420 IDS_PERMISSIONS_FOR,
421 &szLabel,
422 Selected->AccountName))
423 {
424 SetWindowText(sp->hPermissionsForLabel,
425 szLabel);
426
427 LocalFree((HLOCAL)szLabel);
428 }
429
430 /* FIXME - update the checkboxes */
431 }
432 else
433 {
434 WCHAR szPermissions[255];
435
436 if (LoadString(hDllInstance,
437 IDS_PERMISSIONS,
438 szPermissions,
439 sizeof(szPermissions) / sizeof(szPermissions[0])))
440 {
441 SetWindowText(sp->hPermissionsForLabel,
442 szPermissions);
443 }
444
445 SendMessage(sp->hAceCheckList,
446 CLM_CLEARCHECKBOXES,
447 0,
448 0);
449 }
450 }
451
452 static UINT CALLBACK
453 SecurityPageCallback(IN HWND hwnd,
454 IN UINT uMsg,
455 IN LPPROPSHEETPAGE ppsp)
456 {
457 PSECURITY_PAGE sp = (PSECURITY_PAGE)ppsp->lParam;
458
459 switch(uMsg)
460 {
461 case PSPCB_CREATE:
462 {
463 return TRUE;
464 }
465 case PSPCB_RELEASE:
466 {
467 DestroySecurityPage(sp);
468 UnregisterCheckListControl();
469 return FALSE;
470 }
471 }
472
473 return FALSE;
474 }
475
476 static VOID
477 SetAceCheckListColumns(IN HWND hAceCheckList,
478 IN UINT Button,
479 IN HWND hLabel)
480 {
481 POINT pt;
482 RECT rcLabel;
483
484 GetWindowRect(hLabel,
485 &rcLabel);
486 pt.y = 0;
487 pt.x = (rcLabel.right - rcLabel.left) / 2;
488 MapWindowPoints(hLabel,
489 hAceCheckList,
490 &pt,
491 1);
492
493 SendMessage(hAceCheckList,
494 CLM_SETCHECKBOXCOLUMN,
495 Button,
496 pt.x);
497 }
498
499 static VOID
500 LoadPermissionsList(IN PSECURITY_PAGE sp,
501 IN GUID *GuidObjectType,
502 IN DWORD dwFlags,
503 OUT SI_ACCESS *DefaultAccess)
504 {
505 HRESULT hRet;
506 PSI_ACCESS AccessList;
507 ULONG nAccessList, DefaultAccessIndex;
508
509 /* clear the permissions list */
510
511 SendMessage(sp->hAceCheckList,
512 CLM_CLEAR,
513 0,
514 0);
515
516 /* query the access rights from the server */
517 hRet = sp->psi->lpVtbl->GetAccessRights(sp->psi,
518 GuidObjectType,
519 dwFlags,
520 &AccessList,
521 &nAccessList,
522 &DefaultAccessIndex);
523 if (SUCCEEDED(hRet) && nAccessList != 0)
524 {
525 LPCWSTR NameStr;
526 PSI_ACCESS CurAccess, LastAccess;
527 WCHAR NameBuffer[MAX_PATH];
528
529 /* save the default access rights to be used when adding ACEs later */
530 if (DefaultAccess != NULL)
531 {
532 *DefaultAccess = AccessList[DefaultAccessIndex];
533 }
534
535 LastAccess = AccessList + nAccessList;
536 for (CurAccess = &AccessList[0];
537 CurAccess != LastAccess;
538 CurAccess++)
539 {
540 if (CurAccess->dwFlags & dwFlags)
541 {
542 /* get the permission name, load it from a string table if necessary */
543 if (IS_INTRESOURCE(CurAccess->pszName))
544 {
545 if (!LoadString(sp->ObjectInfo.hInstance,
546 (UINT)((ULONG_PTR)CurAccess->pszName),
547 NameBuffer,
548 sizeof(NameBuffer) / sizeof(NameBuffer[0])))
549 {
550 LoadString(hDllInstance,
551 IDS_UNKNOWN,
552 NameBuffer,
553 sizeof(NameBuffer) / sizeof(NameBuffer[0]));
554 }
555 NameStr = NameBuffer;
556 }
557 else
558 {
559 NameStr = CurAccess->pszName;
560 }
561
562 SendMessage(sp->hAceCheckList,
563 CLM_ADDITEM,
564 CIS_NONE,
565 (LPARAM)NameStr);
566 }
567 }
568 }
569 }
570
571 static INT_PTR CALLBACK
572 SecurityPageProc(IN HWND hwndDlg,
573 IN UINT uMsg,
574 IN WPARAM wParam,
575 IN LPARAM lParam)
576 {
577 PSECURITY_PAGE sp;
578
579 switch(uMsg)
580 {
581 case WM_NOTIFY:
582 {
583 NMHDR *pnmh = (NMHDR*)lParam;
584 sp = (PSECURITY_PAGE)GetWindowLongPtr(hwndDlg,
585 DWL_USER);
586 if (sp != NULL)
587 {
588 if (pnmh->hwndFrom == sp->hWndAceList)
589 {
590 switch(pnmh->code)
591 {
592 case LVN_ITEMCHANGED:
593 {
594 LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
595
596 if ((pnmv->uChanged & LVIF_STATE) &&
597 ((pnmv->uOldState & (LVIS_FOCUSED | LVIS_SELECTED)) ||
598 (pnmv->uNewState & (LVIS_FOCUSED | LVIS_SELECTED))))
599 {
600 UpdateControlStates(sp);
601 }
602 break;
603 }
604 }
605 }
606 else if (pnmh->hwndFrom == sp->hAceCheckList)
607 {
608 switch(pnmh->code)
609 {
610 case CLN_CHANGINGITEMCHECKBOX:
611 {
612 PNMCHANGEITEMCHECKBOX pcicb = (PNMCHANGEITEMCHECKBOX)lParam;
613
614 /* make sure only one of both checkboxes is only checked
615 at the same time */
616 if (pcicb->Checked)
617 {
618 pcicb->NewState &= ~((pcicb->CheckBox != CLB_DENY) ? CIS_DENY : CIS_ALLOW);
619 }
620 break;
621 }
622 }
623 }
624 }
625 break;
626 }
627
628 case WM_INITDIALOG:
629 {
630 sp = (PSECURITY_PAGE)((LPPROPSHEETPAGE)lParam)->lParam;
631 if(sp != NULL)
632 {
633 LV_COLUMN lvc;
634 RECT rcLvClient;
635
636 sp->hWnd = hwndDlg;
637 sp->hWndAceList = GetDlgItem(hwndDlg, IDC_ACELIST);
638 sp->hBtnRemove = GetDlgItem(hwndDlg, IDC_ACELIST_REMOVE);
639 sp->hBtnAdvanced = GetDlgItem(hwndDlg, IDC_ADVANCED);
640 sp->hAceCheckList = GetDlgItem(hwndDlg, IDC_ACE_CHECKLIST);
641 sp->hPermissionsForLabel = GetDlgItem(hwndDlg, IDC_LABEL_PERMISSIONS_FOR);
642
643 sp->SpecialPermCheckIndex = -1;
644
645 if ((sp->ObjectInfo.dwFlags & SI_SERVER_IS_DC) &&
646 sp->ObjectInfo.pszServerName != NULL &&
647 sp->ObjectInfo.pszServerName[0] != L'\0')
648 {
649 sp->ServerName = sp->ObjectInfo.pszServerName;
650 }
651
652 /* save the pointer to the structure */
653 SetWindowLongPtr(hwndDlg,
654 DWL_USER,
655 (DWORD_PTR)sp);
656
657 sp->hiUsrs = ImageList_LoadBitmap(hDllInstance,
658 MAKEINTRESOURCE(IDB_USRGRPIMAGES),
659 16,
660 3,
661 0);
662
663 /* setup the listview control */
664 ListView_SetExtendedListViewStyleEx(sp->hWndAceList,
665 LVS_EX_FULLROWSELECT,
666 LVS_EX_FULLROWSELECT);
667 ListView_SetImageList(sp->hWndAceList,
668 sp->hiUsrs,
669 LVSIL_SMALL);
670
671 GetClientRect(sp->hWndAceList, &rcLvClient);
672
673 /* add a column to the list view */
674 lvc.mask = LVCF_FMT | LVCF_WIDTH;
675 lvc.fmt = LVCFMT_LEFT;
676 lvc.cx = rcLvClient.right;
677 ListView_InsertColumn(sp->hWndAceList, 0, &lvc);
678
679 FillUsersGroupsList(sp);
680
681 ListViewSelectItem(sp->hWndAceList,
682 0);
683
684 /* calculate the columns of the allow/deny checkboxes */
685 SetAceCheckListColumns(sp->hAceCheckList,
686 CLB_ALLOW,
687 GetDlgItem(hwndDlg, IDC_LABEL_ALLOW));
688 SetAceCheckListColumns(sp->hAceCheckList,
689 CLB_DENY,
690 GetDlgItem(hwndDlg, IDC_LABEL_DENY));
691
692 LoadPermissionsList(sp,
693 NULL,
694 SI_ACCESS_GENERAL |
695 ((sp->ObjectInfo.dwFlags & SI_CONTAINER) ? SI_ACCESS_CONTAINER : 0),
696 &sp->DefaultAccess);
697
698 /* hide controls in case the flags aren't present */
699 if (sp->ObjectInfo.dwFlags & SI_ADVANCED)
700 {
701 WCHAR szSpecialPermissions[255];
702
703 /* editing the permissions is least the user can do when
704 the advanced button is showed */
705 sp->ObjectInfo.dwFlags |= SI_EDIT_PERMS;
706
707 if (LoadString(hDllInstance,
708 IDS_SPECIAL_PERMISSIONS,
709 szSpecialPermissions,
710 sizeof(szSpecialPermissions) / sizeof(szSpecialPermissions[0])))
711 {
712 /* add the special permissions check item */
713 sp->SpecialPermCheckIndex = (INT)SendMessage(sp->hAceCheckList,
714 CLM_ADDITEM,
715 CIS_ALLOWDISABLED | CIS_DENYDISABLED | CIS_NONE,
716 (LPARAM)szSpecialPermissions);
717 }
718 }
719 else
720 {
721 ShowWindow(sp->hBtnAdvanced,
722 SW_HIDE);
723 ShowWindow(GetDlgItem(hwndDlg, IDC_LABEL_ADVANCED),
724 SW_HIDE);
725 }
726
727 /* enable quicksearch for the permissions checklist control */
728 SendMessage(sp->hAceCheckList,
729 CLM_ENABLEQUICKSEARCH,
730 TRUE,
731 0);
732 }
733 break;
734 }
735 }
736 return 0;
737 }
738
739
740 /*
741 * CreateSecurityPage EXPORTED
742 *
743 * @implemented
744 */
745 HPROPSHEETPAGE
746 WINAPI
747 CreateSecurityPage(IN LPSECURITYINFO psi)
748 {
749 PROPSHEETPAGE psp;
750 PSECURITY_PAGE sPage;
751 SI_OBJECT_INFO ObjectInfo;
752 HRESULT hRet;
753
754 if(psi == NULL)
755 {
756 SetLastError(ERROR_INVALID_PARAMETER);
757
758 DPRINT("No ISecurityInformation class passed!\n");
759 return NULL;
760 }
761
762 /* get the object information from the server. Zero the structure before
763 because some applications seem to return SUCCESS but only seem to set the
764 fields they care about. */
765 ZeroMemory(&ObjectInfo, sizeof(ObjectInfo));
766 hRet = psi->lpVtbl->GetObjectInformation(psi, &ObjectInfo);
767
768 if(FAILED(hRet))
769 {
770 SetLastError(hRet);
771
772 DPRINT("CreateSecurityPage() failed! Failed to query the object information!\n");
773 return NULL;
774 }
775
776 if (!RegisterCheckListControl(hDllInstance))
777 {
778 DPRINT("Registering the CHECKLIST_ACLUI class failed!\n");
779 return NULL;
780 }
781
782 sPage = HeapAlloc(GetProcessHeap(),
783 HEAP_ZERO_MEMORY,
784 sizeof(SECURITY_PAGE));
785 if (sPage == NULL)
786 {
787 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
788
789 DPRINT("Not enough memory to allocate a SECURITY_PAGE!\n");
790 return NULL;
791 }
792 sPage->psi = psi;
793 sPage->ObjectInfo = ObjectInfo;
794
795 ZeroMemory(&psp, sizeof(psp));
796
797 psp.dwSize = sizeof(PROPSHEETPAGE);
798 psp.dwFlags = PSP_USECALLBACK;
799 psp.hInstance = hDllInstance;
800 psp.pszTemplate = MAKEINTRESOURCE(IDD_SECPAGE);
801 psp.pfnDlgProc = SecurityPageProc;
802 psp.lParam = (LPARAM)sPage;
803 psp.pfnCallback = SecurityPageCallback;
804
805 if(ObjectInfo.dwFlags & SI_PAGE_TITLE)
806 {
807 psp.pszTitle = ObjectInfo.pszPageTitle;
808
809 if (psp.pszTitle != NULL)
810 {
811 psp.dwFlags |= PSP_USETITLE;
812 }
813 }
814 else
815 {
816 psp.pszTitle = NULL;
817 }
818
819 /* NOTE: the SECURITY_PAGE structure will be freed by the property page
820 callback! */
821
822 return CreatePropertySheetPage(&psp);
823 }
824
825
826 /*
827 * EditSecurity EXPORTED
828 *
829 * @implemented
830 */
831 BOOL
832 WINAPI
833 EditSecurity(IN HWND hwndOwner,
834 IN LPSECURITYINFO psi)
835 {
836 HRESULT hRet;
837 SI_OBJECT_INFO ObjectInfo;
838 PROPSHEETHEADER psh;
839 HPROPSHEETPAGE hPages[1];
840 LPWSTR lpCaption;
841 BOOL Ret;
842
843 if(psi == NULL)
844 {
845 SetLastError(ERROR_INVALID_PARAMETER);
846
847 DPRINT("No ISecurityInformation class passed!\n");
848 return FALSE;
849 }
850
851 /* get the object information from the server. Zero the structure before
852 because some applications seem to return SUCCESS but only seem to set the
853 fields they care about. */
854 ZeroMemory(&ObjectInfo, sizeof(ObjectInfo));
855 hRet = psi->lpVtbl->GetObjectInformation(psi, &ObjectInfo);
856
857 if(FAILED(hRet))
858 {
859 SetLastError(hRet);
860
861 DPRINT("GetObjectInformation() failed!\n");
862 return FALSE;
863 }
864
865 /* create the page */
866 hPages[0] = CreateSecurityPage(psi);
867 if(hPages[0] == NULL)
868 {
869 DPRINT("CreateSecurityPage(), couldn't create property sheet!\n");
870 return FALSE;
871 }
872
873 psh.dwSize = sizeof(PROPSHEETHEADER);
874 psh.dwFlags = PSH_DEFAULT;
875 psh.hwndParent = hwndOwner;
876 psh.hInstance = hDllInstance;
877
878 /* Set the page title to the object name, make sure the format string
879 has "%1" NOT "%s" because it uses FormatMessage() to automatically
880 allocate the right amount of memory. */
881 LoadAndFormatString(hDllInstance,
882 IDS_PSP_TITLE,
883 &lpCaption,
884 ObjectInfo.pszObjectName);
885 psh.pszCaption = lpCaption;
886
887 psh.nPages = sizeof(hPages) / sizeof(HPROPSHEETPAGE);
888 psh.nStartPage = 0;
889 psh.phpage = hPages;
890
891 Ret = (PropertySheet(&psh) != -1);
892
893 if(lpCaption != NULL)
894 {
895 LocalFree((HLOCAL)lpCaption);
896 }
897
898 return Ret;
899 }
900
901 BOOL STDCALL
902 DllMain(IN HINSTANCE hinstDLL,
903 IN DWORD dwReason,
904 IN LPVOID lpvReserved)
905 {
906 switch (dwReason)
907 {
908 case DLL_PROCESS_ATTACH:
909 hDllInstance = hinstDLL;
910 break;
911 case DLL_THREAD_ATTACH:
912 case DLL_THREAD_DETACH:
913 case DLL_PROCESS_DETACH:
914 break;
915 }
916 return TRUE;
917 }
918