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