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