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