1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * WINE COPYRIGHT: 4 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net> 5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla) 6 * Copyright 2006 Robert Reif 7 * 8 * PROJECT: ReactOS system libraries 9 * FILE: dll/win32/advapi32/sec/misc.c 10 * PURPOSE: Miscellaneous security functions (some ported from Wine) 11 */ 12 13 #include <advapi32.h> 14 15 WINE_DEFAULT_DEBUG_CHANNEL(advapi); 16 17 /* Interface to ntmarta.dll ***************************************************/ 18 19 NTMARTA NtMartaStatic = { 0 }; 20 static PNTMARTA NtMarta = NULL; 21 22 #define FindNtMartaProc(Name) \ 23 NtMartaStatic.Name = (PVOID)GetProcAddress(NtMartaStatic.hDllInstance, \ 24 "Acc" # Name ); \ 25 if (NtMartaStatic.Name == NULL) \ 26 { \ 27 return GetLastError(); \ 28 } 29 30 31 static DWORD 32 LoadAndInitializeNtMarta(VOID) 33 { 34 /* this code may be executed simultaneously by multiple threads in case they're 35 trying to initialize the interface at the same time, but that's no problem 36 because the pointers returned by GetProcAddress will be the same. However, 37 only one of the threads will change the NtMarta pointer to the NtMartaStatic 38 structure, the others threads will detect that there were other threads 39 initializing the structure faster and will release the reference to the 40 DLL */ 41 42 NtMartaStatic.hDllInstance = LoadLibraryW(L"ntmarta.dll"); 43 if (NtMartaStatic.hDllInstance == NULL) 44 { 45 return GetLastError(); 46 } 47 48 #if 0 49 FindNtMartaProc(LookupAccountTrustee); 50 FindNtMartaProc(LookupAccountName); 51 FindNtMartaProc(LookupAccountSid); 52 FindNtMartaProc(SetEntriesInAList); 53 FindNtMartaProc(ConvertAccessToSecurityDescriptor); 54 FindNtMartaProc(ConvertSDToAccess); 55 FindNtMartaProc(ConvertAclToAccess); 56 FindNtMartaProc(GetAccessForTrustee); 57 FindNtMartaProc(GetExplicitEntries); 58 #endif 59 FindNtMartaProc(RewriteGetNamedRights); 60 FindNtMartaProc(RewriteSetNamedRights); 61 FindNtMartaProc(RewriteGetHandleRights); 62 FindNtMartaProc(RewriteSetHandleRights); 63 FindNtMartaProc(RewriteSetEntriesInAcl); 64 FindNtMartaProc(RewriteGetExplicitEntriesFromAcl); 65 FindNtMartaProc(TreeResetNamedSecurityInfo); 66 FindNtMartaProc(GetInheritanceSource); 67 FindNtMartaProc(FreeIndexArray); 68 69 return ERROR_SUCCESS; 70 } 71 72 73 DWORD 74 CheckNtMartaPresent(VOID) 75 { 76 DWORD ErrorCode; 77 78 if (InterlockedCompareExchangePointer((PVOID)&NtMarta, 79 NULL, 80 NULL) == NULL) 81 { 82 /* we're the first one trying to use ntmarta, initialize it and change 83 the pointer after initialization */ 84 ErrorCode = LoadAndInitializeNtMarta(); 85 86 if (ErrorCode == ERROR_SUCCESS) 87 { 88 /* try change the NtMarta pointer */ 89 if (InterlockedCompareExchangePointer((PVOID)&NtMarta, 90 &NtMartaStatic, 91 NULL) != NULL) 92 { 93 /* another thread initialized ntmarta in the meanwhile, release 94 the reference of the dll loaded. */ 95 FreeLibrary(NtMartaStatic.hDllInstance); 96 } 97 } 98 #if DBG 99 else 100 { 101 ERR("Failed to initialize ntmarta.dll! Error: 0x%x\n", ErrorCode); 102 } 103 #endif 104 } 105 else 106 { 107 /* ntmarta was already initialized */ 108 ErrorCode = ERROR_SUCCESS; 109 } 110 111 return ErrorCode; 112 } 113 114 115 VOID 116 UnloadNtMarta(VOID) 117 { 118 if (InterlockedExchangePointer((PVOID)&NtMarta, 119 NULL) != NULL) 120 { 121 FreeLibrary(NtMartaStatic.hDllInstance); 122 } 123 } 124 125 126 /******************************************************************************/ 127 128 /* 129 * @implemented 130 */ 131 BOOL 132 WINAPI 133 ImpersonateAnonymousToken(IN HANDLE ThreadHandle) 134 { 135 NTSTATUS Status; 136 137 Status = NtImpersonateAnonymousToken(ThreadHandle); 138 if (!NT_SUCCESS(Status)) 139 { 140 SetLastError(RtlNtStatusToDosError(Status)); 141 return FALSE; 142 } 143 144 return TRUE; 145 } 146 147 /* 148 * @implemented 149 */ 150 BOOL 151 WINAPI 152 ImpersonateLoggedOnUser(HANDLE hToken) 153 { 154 SECURITY_QUALITY_OF_SERVICE Qos; 155 OBJECT_ATTRIBUTES ObjectAttributes; 156 HANDLE NewToken; 157 TOKEN_TYPE Type; 158 ULONG ReturnLength; 159 BOOL Duplicated; 160 NTSTATUS Status; 161 162 /* Get the token type */ 163 Status = NtQueryInformationToken(hToken, 164 TokenType, 165 &Type, 166 sizeof(TOKEN_TYPE), 167 &ReturnLength); 168 if (!NT_SUCCESS(Status)) 169 { 170 SetLastError(RtlNtStatusToDosError(Status)); 171 return FALSE; 172 } 173 174 if (Type == TokenPrimary) 175 { 176 /* Create a duplicate impersonation token */ 177 Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); 178 Qos.ImpersonationLevel = SecurityImpersonation; 179 Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; 180 Qos.EffectiveOnly = FALSE; 181 182 ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES); 183 ObjectAttributes.RootDirectory = NULL; 184 ObjectAttributes.ObjectName = NULL; 185 ObjectAttributes.Attributes = 0; 186 ObjectAttributes.SecurityDescriptor = NULL; 187 ObjectAttributes.SecurityQualityOfService = &Qos; 188 189 Status = NtDuplicateToken(hToken, 190 TOKEN_IMPERSONATE | TOKEN_QUERY, 191 &ObjectAttributes, 192 FALSE, 193 TokenImpersonation, 194 &NewToken); 195 if (!NT_SUCCESS(Status)) 196 { 197 ERR("NtDuplicateToken failed: Status %08x\n", Status); 198 SetLastError(RtlNtStatusToDosError(Status)); 199 return FALSE; 200 } 201 202 Duplicated = TRUE; 203 } 204 else 205 { 206 /* User the original impersonation token */ 207 NewToken = hToken; 208 Duplicated = FALSE; 209 } 210 211 /* Impersonate the the current thread */ 212 Status = NtSetInformationThread(NtCurrentThread(), 213 ThreadImpersonationToken, 214 &NewToken, 215 sizeof(HANDLE)); 216 217 if (Duplicated != FALSE) 218 { 219 NtClose(NewToken); 220 } 221 222 if (!NT_SUCCESS(Status)) 223 { 224 ERR("NtSetInformationThread failed: Status %08x\n", Status); 225 SetLastError(RtlNtStatusToDosError(Status)); 226 return FALSE; 227 } 228 229 return TRUE; 230 } 231 232 /****************************************************************************** 233 * GetUserNameA [ADVAPI32.@] 234 * 235 * Get the current user name. 236 * 237 * PARAMS 238 * lpszName [O] Destination for the user name. 239 * lpSize [I/O] Size of lpszName. 240 * 241 * 242 * @implemented 243 */ 244 BOOL 245 WINAPI 246 GetUserNameA(LPSTR lpszName, 247 LPDWORD lpSize) 248 { 249 UNICODE_STRING NameW; 250 ANSI_STRING NameA; 251 BOOL Ret; 252 253 /* apparently Win doesn't check whether lpSize is valid at all! */ 254 255 NameW.MaximumLength = (*lpSize) * sizeof(WCHAR); 256 NameW.Buffer = LocalAlloc(LMEM_FIXED, NameW.MaximumLength); 257 if(NameW.Buffer == NULL) 258 { 259 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 260 return FALSE; 261 } 262 263 NameA.Length = 0; 264 NameA.MaximumLength = ((*lpSize) < 0xFFFF ? (USHORT)(*lpSize) : 0xFFFF); 265 NameA.Buffer = lpszName; 266 267 Ret = GetUserNameW(NameW.Buffer, 268 lpSize); 269 if(Ret) 270 { 271 NameW.Length = (*lpSize - 1) * sizeof(WCHAR); 272 RtlUnicodeStringToAnsiString(&NameA, &NameW, FALSE); 273 274 *lpSize = NameA.Length + 1; 275 } 276 277 LocalFree(NameW.Buffer); 278 279 return Ret; 280 } 281 282 /****************************************************************************** 283 * GetUserNameW [ADVAPI32.@] 284 * 285 * See GetUserNameA. 286 * 287 * @implemented 288 */ 289 BOOL 290 WINAPI 291 GetUserNameW(LPWSTR lpszName, 292 LPDWORD lpSize) 293 { 294 HANDLE hToken = INVALID_HANDLE_VALUE; 295 DWORD tu_len = 0; 296 char* tu_buf = NULL; 297 TOKEN_USER* token_user = NULL; 298 DWORD an_len = 0; 299 SID_NAME_USE snu = SidTypeUser; 300 WCHAR* domain_name = NULL; 301 DWORD dn_len = 0; 302 303 if (!OpenThreadToken (GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) 304 { 305 DWORD dwLastError = GetLastError(); 306 if (dwLastError != ERROR_NO_TOKEN 307 && dwLastError != ERROR_NO_IMPERSONATION_TOKEN) 308 { 309 /* don't call SetLastError(), 310 as OpenThreadToken() ought to have set one */ 311 return FALSE; 312 } 313 314 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) 315 { 316 /* don't call SetLastError(), 317 as OpenProcessToken() ought to have set one */ 318 return FALSE; 319 } 320 } 321 322 tu_buf = LocalAlloc(LMEM_FIXED, 36); 323 if (!tu_buf) 324 { 325 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 326 CloseHandle(hToken); 327 return FALSE; 328 } 329 330 if (!GetTokenInformation(hToken, TokenUser, tu_buf, 36, &tu_len) || tu_len > 36) 331 { 332 LocalFree(tu_buf); 333 tu_buf = LocalAlloc(LMEM_FIXED, tu_len); 334 if (!tu_buf) 335 { 336 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 337 CloseHandle(hToken); 338 return FALSE; 339 } 340 341 if (!GetTokenInformation(hToken, TokenUser, tu_buf, tu_len, &tu_len)) 342 { 343 /* don't call SetLastError(), 344 as GetTokenInformation() ought to have set one */ 345 LocalFree(tu_buf); 346 CloseHandle(hToken); 347 return FALSE; 348 } 349 } 350 351 CloseHandle(hToken); 352 token_user = (TOKEN_USER*)tu_buf; 353 354 an_len = *lpSize; 355 dn_len = 32; 356 domain_name = LocalAlloc(LMEM_FIXED, dn_len * sizeof(WCHAR)); 357 if (!domain_name) 358 { 359 LocalFree(tu_buf); 360 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 361 return FALSE; 362 } 363 364 if (!LookupAccountSidW(NULL, token_user->User.Sid, lpszName, &an_len, domain_name, &dn_len, &snu) 365 || dn_len > 32) 366 { 367 if (dn_len > 32) 368 { 369 LocalFree(domain_name); 370 domain_name = LocalAlloc(LMEM_FIXED, dn_len * sizeof(WCHAR)); 371 if (!domain_name) 372 { 373 LocalFree(tu_buf); 374 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 375 return FALSE; 376 } 377 } 378 379 an_len = *lpSize; 380 if (!LookupAccountSidW(NULL, token_user->User.Sid, lpszName, &an_len, domain_name, &dn_len, &snu)) 381 { 382 /* don't call SetLastError(), 383 as LookupAccountSid() ought to have set one */ 384 LocalFree(domain_name); 385 LocalFree(tu_buf); 386 *lpSize = an_len; 387 return FALSE; 388 } 389 } 390 391 LocalFree(domain_name); 392 LocalFree(tu_buf); 393 *lpSize = an_len + 1; 394 return TRUE; 395 } 396 397 398 /****************************************************************************** 399 * LookupAccountSidA [ADVAPI32.@] 400 * 401 * @implemented 402 */ 403 BOOL 404 WINAPI 405 LookupAccountSidA(LPCSTR lpSystemName, 406 PSID lpSid, 407 LPSTR lpName, 408 LPDWORD cchName, 409 LPSTR lpReferencedDomainName, 410 LPDWORD cchReferencedDomainName, 411 PSID_NAME_USE peUse) 412 { 413 UNICODE_STRING NameW, ReferencedDomainNameW, SystemNameW; 414 LPWSTR NameBuffer = NULL; 415 LPWSTR ReferencedDomainNameBuffer = NULL; 416 DWORD dwName, dwReferencedDomainName; 417 BOOL Ret; 418 419 /* 420 * save the buffer sizes the caller passed to us, as they may get modified and 421 * we require the original values when converting back to ansi 422 */ 423 dwName = *cchName; 424 dwReferencedDomainName = *cchReferencedDomainName; 425 426 /* allocate buffers for the unicode strings to receive */ 427 if (dwName > 0) 428 { 429 NameBuffer = LocalAlloc(LMEM_FIXED, dwName * sizeof(WCHAR)); 430 if (NameBuffer == NULL) 431 { 432 SetLastError(ERROR_OUTOFMEMORY); 433 return FALSE; 434 } 435 } 436 else 437 NameBuffer = NULL; 438 439 if (dwReferencedDomainName > 0) 440 { 441 ReferencedDomainNameBuffer = LocalAlloc(LMEM_FIXED, dwReferencedDomainName * sizeof(WCHAR)); 442 if (ReferencedDomainNameBuffer == NULL) 443 { 444 if (dwName > 0) 445 { 446 LocalFree(NameBuffer); 447 } 448 449 SetLastError(ERROR_OUTOFMEMORY); 450 return FALSE; 451 } 452 } 453 else 454 ReferencedDomainNameBuffer = NULL; 455 456 457 /* convert the system name to unicode - if present */ 458 if (lpSystemName != NULL) 459 { 460 ANSI_STRING SystemNameA; 461 462 RtlInitAnsiString(&SystemNameA, lpSystemName); 463 RtlAnsiStringToUnicodeString(&SystemNameW, &SystemNameA, TRUE); 464 } 465 else 466 SystemNameW.Buffer = NULL; 467 468 /* it's time to call the unicode version */ 469 Ret = LookupAccountSidW(SystemNameW.Buffer, 470 lpSid, 471 NameBuffer, 472 cchName, 473 ReferencedDomainNameBuffer, 474 cchReferencedDomainName, 475 peUse); 476 if (Ret) 477 { 478 /* 479 * convert unicode strings back to ansi, don't forget that we can't convert 480 * more than 0xFFFF (USHORT) characters! Also don't forget to explicitly 481 * terminate the converted string, the Rtl functions don't do that! 482 */ 483 if (lpName != NULL) 484 { 485 ANSI_STRING NameA; 486 487 NameA.Length = 0; 488 NameA.MaximumLength = ((dwName <= 0xFFFF) ? (USHORT)dwName : 0xFFFF); 489 NameA.Buffer = lpName; 490 491 RtlInitUnicodeString(&NameW, NameBuffer); 492 RtlUnicodeStringToAnsiString(&NameA, &NameW, FALSE); 493 NameA.Buffer[NameA.Length] = '\0'; 494 } 495 496 if (lpReferencedDomainName != NULL) 497 { 498 ANSI_STRING ReferencedDomainNameA; 499 500 ReferencedDomainNameA.Length = 0; 501 ReferencedDomainNameA.MaximumLength = ((dwReferencedDomainName <= 0xFFFF) ? 502 (USHORT)dwReferencedDomainName : 0xFFFF); 503 ReferencedDomainNameA.Buffer = lpReferencedDomainName; 504 505 RtlInitUnicodeString(&ReferencedDomainNameW, ReferencedDomainNameBuffer); 506 RtlUnicodeStringToAnsiString(&ReferencedDomainNameA, &ReferencedDomainNameW, FALSE); 507 ReferencedDomainNameA.Buffer[ReferencedDomainNameA.Length] = '\0'; 508 } 509 } 510 511 /* free previously allocated buffers */ 512 if (SystemNameW.Buffer != NULL) 513 { 514 RtlFreeUnicodeString(&SystemNameW); 515 } 516 517 if (NameBuffer != NULL) 518 { 519 LocalFree(NameBuffer); 520 } 521 522 if (ReferencedDomainNameBuffer != NULL) 523 { 524 LocalFree(ReferencedDomainNameBuffer); 525 } 526 527 return Ret; 528 } 529 530 531 /****************************************************************************** 532 * LookupAccountSidW [ADVAPI32.@] 533 * 534 * @implemented 535 */ 536 BOOL WINAPI 537 LookupAccountSidW(LPCWSTR pSystemName, 538 PSID pSid, 539 LPWSTR pAccountName, 540 LPDWORD pdwAccountName, 541 LPWSTR pDomainName, 542 LPDWORD pdwDomainName, 543 PSID_NAME_USE peUse) 544 { 545 LSA_UNICODE_STRING SystemName; 546 LSA_OBJECT_ATTRIBUTES ObjectAttributes = {0}; 547 LSA_HANDLE PolicyHandle = NULL; 548 NTSTATUS Status; 549 PLSA_REFERENCED_DOMAIN_LIST ReferencedDomain = NULL; 550 PLSA_TRANSLATED_NAME TranslatedName = NULL; 551 BOOL ret; 552 DWORD dwAccountName, dwDomainName; 553 554 RtlInitUnicodeString(&SystemName, pSystemName); 555 Status = LsaOpenPolicy(&SystemName, &ObjectAttributes, POLICY_LOOKUP_NAMES, &PolicyHandle); 556 if (!NT_SUCCESS(Status)) 557 { 558 SetLastError(LsaNtStatusToWinError(Status)); 559 return FALSE; 560 } 561 562 Status = LsaLookupSids(PolicyHandle, 1, &pSid, &ReferencedDomain, &TranslatedName); 563 564 LsaClose(PolicyHandle); 565 566 if (!NT_SUCCESS(Status) || Status == STATUS_SOME_NOT_MAPPED) 567 { 568 SetLastError(LsaNtStatusToWinError(Status)); 569 ret = FALSE; 570 } 571 else 572 { 573 ret = TRUE; 574 575 dwAccountName = TranslatedName->Name.Length / sizeof(WCHAR); 576 if (ReferencedDomain && ReferencedDomain->Entries > 0) 577 dwDomainName = ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR); 578 else 579 dwDomainName = 0; 580 581 if (*pdwAccountName <= dwAccountName || *pdwDomainName <= dwDomainName) 582 { 583 /* One or two buffers are insufficient, add up a char for NULL termination */ 584 *pdwAccountName = dwAccountName + 1; 585 *pdwDomainName = dwDomainName + 1; 586 ret = FALSE; 587 } 588 else 589 { 590 /* Lengths are sufficient, copy the data */ 591 if (dwAccountName) 592 RtlCopyMemory(pAccountName, TranslatedName->Name.Buffer, dwAccountName * sizeof(WCHAR)); 593 pAccountName[dwAccountName] = L'\0'; 594 595 if (dwDomainName) 596 RtlCopyMemory(pDomainName, ReferencedDomain->Domains[0].Name.Buffer, dwDomainName * sizeof(WCHAR)); 597 pDomainName[dwDomainName] = L'\0'; 598 599 *pdwAccountName = dwAccountName; 600 *pdwDomainName = dwDomainName; 601 602 if (peUse) 603 *peUse = TranslatedName->Use; 604 } 605 606 if (!ret) 607 SetLastError(ERROR_INSUFFICIENT_BUFFER); 608 } 609 610 if (ReferencedDomain) 611 LsaFreeMemory(ReferencedDomain); 612 613 if (TranslatedName) 614 LsaFreeMemory(TranslatedName); 615 616 return ret; 617 } 618 619 /****************************************************************************** 620 * LookupAccountNameW [ADVAPI32.@] 621 * 622 * @implemented 623 */ 624 BOOL 625 WINAPI 626 LookupAccountNameW(LPCWSTR lpSystemName, 627 LPCWSTR lpAccountName, 628 PSID Sid, 629 LPDWORD cbSid, 630 LPWSTR ReferencedDomainName, 631 LPDWORD cchReferencedDomainName, 632 PSID_NAME_USE peUse) 633 { 634 OBJECT_ATTRIBUTES ObjectAttributes = {0}; 635 UNICODE_STRING SystemName; 636 UNICODE_STRING AccountName; 637 LSA_HANDLE PolicyHandle = NULL; 638 PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL; 639 PLSA_TRANSLATED_SID TranslatedSid = NULL; 640 PSID pDomainSid; 641 DWORD dwDomainNameLength; 642 DWORD dwSidLength; 643 UCHAR nSubAuthorities; 644 BOOL bResult; 645 NTSTATUS Status; 646 647 TRACE("%s %s %p %p %p %p %p\n", lpSystemName, lpAccountName, 648 Sid, cbSid, ReferencedDomainName, cchReferencedDomainName, peUse); 649 650 RtlInitUnicodeString(&SystemName, 651 lpSystemName); 652 653 Status = LsaOpenPolicy(lpSystemName ? &SystemName : NULL, 654 &ObjectAttributes, 655 POLICY_LOOKUP_NAMES, 656 &PolicyHandle); 657 if (!NT_SUCCESS(Status)) 658 { 659 SetLastError(LsaNtStatusToWinError(Status)); 660 return FALSE; 661 } 662 663 RtlInitUnicodeString(&AccountName, 664 lpAccountName); 665 666 Status = LsaLookupNames(PolicyHandle, 667 1, 668 &AccountName, 669 &ReferencedDomains, 670 &TranslatedSid); 671 672 LsaClose(PolicyHandle); 673 674 if (!NT_SUCCESS(Status) || Status == STATUS_SOME_NOT_MAPPED) 675 { 676 SetLastError(LsaNtStatusToWinError(Status)); 677 bResult = FALSE; 678 } 679 else 680 { 681 pDomainSid = ReferencedDomains->Domains[TranslatedSid->DomainIndex].Sid; 682 nSubAuthorities = *GetSidSubAuthorityCount(pDomainSid); 683 dwSidLength = GetSidLengthRequired(nSubAuthorities + 1); 684 685 dwDomainNameLength = ReferencedDomains->Domains->Name.Length / sizeof(WCHAR); 686 687 if (*cbSid < dwSidLength || 688 *cchReferencedDomainName < dwDomainNameLength + 1) 689 { 690 *cbSid = dwSidLength; 691 *cchReferencedDomainName = dwDomainNameLength + 1; 692 693 bResult = FALSE; 694 } 695 else 696 { 697 CopySid(*cbSid, Sid, pDomainSid); 698 *GetSidSubAuthorityCount(Sid) = nSubAuthorities + 1; 699 *GetSidSubAuthority(Sid, (DWORD)nSubAuthorities) = TranslatedSid->RelativeId; 700 701 RtlCopyMemory(ReferencedDomainName, ReferencedDomains->Domains->Name.Buffer, dwDomainNameLength * sizeof(WCHAR)); 702 ReferencedDomainName[dwDomainNameLength] = L'\0'; 703 704 *cchReferencedDomainName = dwDomainNameLength; 705 706 *peUse = TranslatedSid->Use; 707 708 bResult = TRUE; 709 } 710 711 if (bResult == FALSE) 712 SetLastError(ERROR_INSUFFICIENT_BUFFER); 713 } 714 715 if (ReferencedDomains != NULL) 716 LsaFreeMemory(ReferencedDomains); 717 718 if (TranslatedSid != NULL) 719 LsaFreeMemory(TranslatedSid); 720 721 return bResult; 722 } 723 724 725 /********************************************************************** 726 * LookupPrivilegeValueA EXPORTED 727 * 728 * @implemented 729 */ 730 BOOL 731 WINAPI 732 LookupPrivilegeValueA(LPCSTR lpSystemName, 733 LPCSTR lpName, 734 PLUID lpLuid) 735 { 736 UNICODE_STRING SystemName; 737 UNICODE_STRING Name; 738 BOOL Result; 739 740 /* Remote system? */ 741 if (lpSystemName != NULL) 742 { 743 RtlCreateUnicodeStringFromAsciiz(&SystemName, 744 (LPSTR)lpSystemName); 745 } 746 else 747 SystemName.Buffer = NULL; 748 749 /* Check the privilege name is not NULL */ 750 if (lpName == NULL) 751 { 752 SetLastError(ERROR_NO_SUCH_PRIVILEGE); 753 return FALSE; 754 } 755 756 RtlCreateUnicodeStringFromAsciiz(&Name, 757 (LPSTR)lpName); 758 759 Result = LookupPrivilegeValueW(SystemName.Buffer, 760 Name.Buffer, 761 lpLuid); 762 763 RtlFreeUnicodeString(&Name); 764 765 /* Remote system? */ 766 if (SystemName.Buffer != NULL) 767 { 768 RtlFreeUnicodeString(&SystemName); 769 } 770 771 return Result; 772 } 773 774 775 /********************************************************************** 776 * LookupPrivilegeValueW 777 * 778 * @implemented 779 */ 780 BOOL 781 WINAPI 782 LookupPrivilegeValueW(LPCWSTR lpSystemName, 783 LPCWSTR lpPrivilegeName, 784 PLUID lpLuid) 785 { 786 OBJECT_ATTRIBUTES ObjectAttributes = {0}; 787 UNICODE_STRING SystemName; 788 UNICODE_STRING PrivilegeName; 789 LSA_HANDLE PolicyHandle = NULL; 790 NTSTATUS Status; 791 792 TRACE("%S,%S,%p\n", lpSystemName, lpPrivilegeName, lpLuid); 793 794 RtlInitUnicodeString(&SystemName, 795 lpSystemName); 796 797 Status = LsaOpenPolicy(lpSystemName ? &SystemName : NULL, 798 &ObjectAttributes, 799 POLICY_LOOKUP_NAMES, 800 &PolicyHandle); 801 if (!NT_SUCCESS(Status)) 802 { 803 SetLastError(LsaNtStatusToWinError(Status)); 804 return FALSE; 805 } 806 807 RtlInitUnicodeString(&PrivilegeName, 808 lpPrivilegeName); 809 810 Status = LsaLookupPrivilegeValue(PolicyHandle, 811 &PrivilegeName, 812 lpLuid); 813 814 LsaClose(PolicyHandle); 815 816 if (!NT_SUCCESS(Status)) 817 { 818 SetLastError(LsaNtStatusToWinError(Status)); 819 return FALSE; 820 } 821 822 return TRUE; 823 } 824 825 /********************************************************************** 826 * LookupPrivilegeNameW EXPORTED 827 * 828 * @implemented 829 */ 830 BOOL 831 WINAPI 832 LookupPrivilegeNameW(LPCWSTR lpSystemName, 833 PLUID lpLuid, 834 LPWSTR lpName, 835 LPDWORD cchName) 836 { 837 OBJECT_ATTRIBUTES ObjectAttributes = {0}; 838 UNICODE_STRING SystemName; 839 PUNICODE_STRING PrivilegeName = NULL; 840 LSA_HANDLE PolicyHandle = NULL; 841 NTSTATUS Status; 842 843 TRACE("%S,%p,%p,%p\n", lpSystemName, lpLuid, lpName, cchName); 844 845 RtlInitUnicodeString(&SystemName, 846 lpSystemName); 847 848 Status = LsaOpenPolicy(lpSystemName ? &SystemName : NULL, 849 &ObjectAttributes, 850 POLICY_LOOKUP_NAMES, 851 &PolicyHandle); 852 if (!NT_SUCCESS(Status)) 853 { 854 SetLastError(LsaNtStatusToWinError(Status)); 855 return FALSE; 856 } 857 858 Status = LsaLookupPrivilegeName(PolicyHandle, 859 lpLuid, 860 &PrivilegeName); 861 if (NT_SUCCESS(Status)) 862 { 863 if (PrivilegeName->Length + sizeof(WCHAR) > *cchName * sizeof(WCHAR)) 864 { 865 Status = STATUS_BUFFER_TOO_SMALL; 866 867 *cchName = (PrivilegeName->Length + sizeof(WCHAR)) / sizeof(WCHAR); 868 } 869 else 870 { 871 RtlMoveMemory(lpName, 872 PrivilegeName->Buffer, 873 PrivilegeName->Length); 874 lpName[PrivilegeName->Length / sizeof(WCHAR)] = 0; 875 876 *cchName = PrivilegeName->Length / sizeof(WCHAR); 877 } 878 879 LsaFreeMemory(PrivilegeName->Buffer); 880 LsaFreeMemory(PrivilegeName); 881 } 882 883 LsaClose(PolicyHandle); 884 885 if (!NT_SUCCESS(Status)) 886 { 887 SetLastError(LsaNtStatusToWinError(Status)); 888 return FALSE; 889 } 890 891 return TRUE; 892 } 893 894 /********************************************************************** 895 * LookupPrivilegeDisplayNameW EXPORTED 896 * 897 * @unimplemented 898 */ 899 BOOL 900 WINAPI 901 LookupPrivilegeDisplayNameW(LPCWSTR lpSystemName, 902 LPCWSTR lpName, 903 LPWSTR lpDisplayName, 904 LPDWORD cchDisplayName, 905 LPDWORD lpLanguageId) 906 { 907 OBJECT_ATTRIBUTES ObjectAttributes = {0}; 908 UNICODE_STRING SystemName, Name; 909 PUNICODE_STRING DisplayName; 910 LSA_HANDLE PolicyHandle = NULL; 911 USHORT LanguageId; 912 NTSTATUS Status; 913 914 TRACE("%S,%S,%p,%p,%p\n", lpSystemName, lpName, lpDisplayName, cchDisplayName, lpLanguageId); 915 916 RtlInitUnicodeString(&SystemName, lpSystemName); 917 RtlInitUnicodeString(&Name, lpName); 918 919 Status = LsaOpenPolicy(lpSystemName ? &SystemName : NULL, 920 &ObjectAttributes, 921 POLICY_LOOKUP_NAMES, 922 &PolicyHandle); 923 if (!NT_SUCCESS(Status)) 924 { 925 SetLastError(LsaNtStatusToWinError(Status)); 926 return FALSE; 927 } 928 929 Status = LsaLookupPrivilegeDisplayName(PolicyHandle, &Name, &DisplayName, &LanguageId); 930 if (NT_SUCCESS(Status)) 931 { 932 *lpLanguageId = LanguageId; 933 if (DisplayName->Length + sizeof(WCHAR) > *cchDisplayName * sizeof(WCHAR)) 934 { 935 Status = STATUS_BUFFER_TOO_SMALL; 936 937 *cchDisplayName = (DisplayName->Length + sizeof(WCHAR)) / sizeof(WCHAR); 938 } 939 else 940 { 941 RtlMoveMemory(lpDisplayName, 942 DisplayName->Buffer, 943 DisplayName->Length); 944 lpDisplayName[DisplayName->Length / sizeof(WCHAR)] = 0; 945 946 *cchDisplayName = DisplayName->Length / sizeof(WCHAR); 947 } 948 949 LsaFreeMemory(DisplayName->Buffer); 950 LsaFreeMemory(DisplayName); 951 } 952 953 LsaClose(PolicyHandle); 954 955 if (!NT_SUCCESS(Status)) 956 { 957 SetLastError(LsaNtStatusToWinError(Status)); 958 return FALSE; 959 } 960 961 return TRUE; 962 } 963 964 static DWORD 965 pGetSecurityInfoCheck(SECURITY_INFORMATION SecurityInfo, 966 PSID *ppsidOwner, 967 PSID *ppsidGroup, 968 PACL *ppDacl, 969 PACL *ppSacl, 970 PSECURITY_DESCRIPTOR* ppSecurityDescriptor) 971 { 972 if ((SecurityInfo & (OWNER_SECURITY_INFORMATION | 973 GROUP_SECURITY_INFORMATION | 974 DACL_SECURITY_INFORMATION | 975 SACL_SECURITY_INFORMATION)) && 976 ppSecurityDescriptor == NULL) 977 { 978 /* if one of the SIDs or ACLs are present, the security descriptor 979 most not be NULL */ 980 return ERROR_INVALID_PARAMETER; 981 } 982 else 983 { 984 /* reset the pointers unless they're ignored */ 985 if ((SecurityInfo & OWNER_SECURITY_INFORMATION) && 986 ppsidOwner != NULL) 987 { 988 *ppsidOwner = NULL; 989 } 990 if ((SecurityInfo & GROUP_SECURITY_INFORMATION) && 991 ppsidGroup != NULL) 992 { 993 *ppsidGroup = NULL; 994 } 995 if ((SecurityInfo & DACL_SECURITY_INFORMATION) && 996 ppDacl != NULL) 997 { 998 *ppDacl = NULL; 999 } 1000 if ((SecurityInfo & SACL_SECURITY_INFORMATION) && 1001 ppSacl != NULL) 1002 { 1003 *ppSacl = NULL; 1004 } 1005 1006 if (SecurityInfo & (OWNER_SECURITY_INFORMATION | 1007 GROUP_SECURITY_INFORMATION | 1008 DACL_SECURITY_INFORMATION | 1009 SACL_SECURITY_INFORMATION)) 1010 { 1011 *ppSecurityDescriptor = NULL; 1012 } 1013 1014 return ERROR_SUCCESS; 1015 } 1016 } 1017 1018 1019 static DWORD 1020 pSetSecurityInfoCheck(PSECURITY_DESCRIPTOR pSecurityDescriptor, 1021 SECURITY_INFORMATION SecurityInfo, 1022 PSID psidOwner, 1023 PSID psidGroup, 1024 PACL pDacl, 1025 PACL pSacl) 1026 { 1027 /* initialize a security descriptor on the stack */ 1028 if (!InitializeSecurityDescriptor(pSecurityDescriptor, 1029 SECURITY_DESCRIPTOR_REVISION)) 1030 { 1031 return GetLastError(); 1032 } 1033 1034 if (SecurityInfo & OWNER_SECURITY_INFORMATION) 1035 { 1036 if (RtlValidSid(psidOwner)) 1037 { 1038 if (!SetSecurityDescriptorOwner(pSecurityDescriptor, 1039 psidOwner, 1040 FALSE)) 1041 { 1042 return GetLastError(); 1043 } 1044 } 1045 else 1046 { 1047 return ERROR_INVALID_PARAMETER; 1048 } 1049 } 1050 1051 if (SecurityInfo & GROUP_SECURITY_INFORMATION) 1052 { 1053 if (RtlValidSid(psidGroup)) 1054 { 1055 if (!SetSecurityDescriptorGroup(pSecurityDescriptor, 1056 psidGroup, 1057 FALSE)) 1058 { 1059 return GetLastError(); 1060 } 1061 } 1062 else 1063 { 1064 return ERROR_INVALID_PARAMETER; 1065 } 1066 } 1067 1068 if (SecurityInfo & DACL_SECURITY_INFORMATION) 1069 { 1070 if (pDacl != NULL) 1071 { 1072 if (SetSecurityDescriptorDacl(pSecurityDescriptor, 1073 TRUE, 1074 pDacl, 1075 FALSE)) 1076 { 1077 /* check if the DACL needs to be protected from being 1078 modified by inheritable ACEs */ 1079 if (SecurityInfo & PROTECTED_DACL_SECURITY_INFORMATION) 1080 { 1081 goto ProtectDacl; 1082 } 1083 } 1084 else 1085 { 1086 return GetLastError(); 1087 } 1088 } 1089 else 1090 { 1091 ProtectDacl: 1092 /* protect the DACL from being modified by inheritable ACEs */ 1093 if (!SetSecurityDescriptorControl(pSecurityDescriptor, 1094 SE_DACL_PROTECTED, 1095 SE_DACL_PROTECTED)) 1096 { 1097 return GetLastError(); 1098 } 1099 } 1100 } 1101 1102 if (SecurityInfo & SACL_SECURITY_INFORMATION) 1103 { 1104 if (pSacl != NULL) 1105 { 1106 if (SetSecurityDescriptorSacl(pSecurityDescriptor, 1107 TRUE, 1108 pSacl, 1109 FALSE)) 1110 { 1111 /* check if the SACL needs to be protected from being 1112 modified by inheritable ACEs */ 1113 if (SecurityInfo & PROTECTED_SACL_SECURITY_INFORMATION) 1114 { 1115 goto ProtectSacl; 1116 } 1117 } 1118 else 1119 { 1120 return GetLastError(); 1121 } 1122 } 1123 else 1124 { 1125 ProtectSacl: 1126 /* protect the SACL from being modified by inheritable ACEs */ 1127 if (!SetSecurityDescriptorControl(pSecurityDescriptor, 1128 SE_SACL_PROTECTED, 1129 SE_SACL_PROTECTED)) 1130 { 1131 return GetLastError(); 1132 } 1133 } 1134 } 1135 1136 return ERROR_SUCCESS; 1137 } 1138 1139 1140 /********************************************************************** 1141 * GetNamedSecurityInfoW EXPORTED 1142 * 1143 * @implemented 1144 */ 1145 DWORD 1146 WINAPI 1147 GetNamedSecurityInfoW(LPWSTR pObjectName, 1148 SE_OBJECT_TYPE ObjectType, 1149 SECURITY_INFORMATION SecurityInfo, 1150 PSID *ppsidOwner, 1151 PSID *ppsidGroup, 1152 PACL *ppDacl, 1153 PACL *ppSacl, 1154 PSECURITY_DESCRIPTOR *ppSecurityDescriptor) 1155 { 1156 DWORD ErrorCode; 1157 1158 if (pObjectName != NULL) 1159 { 1160 ErrorCode = CheckNtMartaPresent(); 1161 if (ErrorCode == ERROR_SUCCESS) 1162 { 1163 ErrorCode = pGetSecurityInfoCheck(SecurityInfo, 1164 ppsidOwner, 1165 ppsidGroup, 1166 ppDacl, 1167 ppSacl, 1168 ppSecurityDescriptor); 1169 1170 if (ErrorCode == ERROR_SUCCESS) 1171 { 1172 /* call the MARTA provider */ 1173 ErrorCode = AccRewriteGetNamedRights(pObjectName, 1174 ObjectType, 1175 SecurityInfo, 1176 ppsidOwner, 1177 ppsidGroup, 1178 ppDacl, 1179 ppSacl, 1180 ppSecurityDescriptor); 1181 } 1182 } 1183 } 1184 else 1185 ErrorCode = ERROR_INVALID_PARAMETER; 1186 1187 return ErrorCode; 1188 } 1189 1190 /********************************************************************** 1191 * SetNamedSecurityInfoW EXPORTED 1192 * 1193 * @implemented 1194 */ 1195 DWORD 1196 WINAPI 1197 SetNamedSecurityInfoW(LPWSTR pObjectName, 1198 SE_OBJECT_TYPE ObjectType, 1199 SECURITY_INFORMATION SecurityInfo, 1200 PSID psidOwner, 1201 PSID psidGroup, 1202 PACL pDacl, 1203 PACL pSacl) 1204 { 1205 DWORD ErrorCode; 1206 1207 if (pObjectName != NULL) 1208 { 1209 ErrorCode = CheckNtMartaPresent(); 1210 if (ErrorCode == ERROR_SUCCESS) 1211 { 1212 SECURITY_DESCRIPTOR SecurityDescriptor; 1213 1214 ErrorCode = pSetSecurityInfoCheck(&SecurityDescriptor, 1215 SecurityInfo, 1216 psidOwner, 1217 psidGroup, 1218 pDacl, 1219 pSacl); 1220 1221 if (ErrorCode == ERROR_SUCCESS) 1222 { 1223 /* call the MARTA provider */ 1224 ErrorCode = AccRewriteSetNamedRights(pObjectName, 1225 ObjectType, 1226 SecurityInfo, 1227 &SecurityDescriptor); 1228 } 1229 } 1230 } 1231 else 1232 ErrorCode = ERROR_INVALID_PARAMETER; 1233 1234 return ErrorCode; 1235 } 1236 1237 /********************************************************************** 1238 * GetSecurityInfo EXPORTED 1239 * 1240 * @implemented 1241 */ 1242 DWORD 1243 WINAPI 1244 GetSecurityInfo(HANDLE handle, 1245 SE_OBJECT_TYPE ObjectType, 1246 SECURITY_INFORMATION SecurityInfo, 1247 PSID *ppsidOwner, 1248 PSID *ppsidGroup, 1249 PACL *ppDacl, 1250 PACL *ppSacl, 1251 PSECURITY_DESCRIPTOR *ppSecurityDescriptor) 1252 { 1253 DWORD ErrorCode; 1254 1255 if (handle != NULL) 1256 { 1257 ErrorCode = CheckNtMartaPresent(); 1258 if (ErrorCode == ERROR_SUCCESS) 1259 { 1260 ErrorCode = pGetSecurityInfoCheck(SecurityInfo, 1261 ppsidOwner, 1262 ppsidGroup, 1263 ppDacl, 1264 ppSacl, 1265 ppSecurityDescriptor); 1266 1267 if (ErrorCode == ERROR_SUCCESS) 1268 { 1269 /* call the MARTA provider */ 1270 ErrorCode = AccRewriteGetHandleRights(handle, 1271 ObjectType, 1272 SecurityInfo, 1273 ppsidOwner, 1274 ppsidGroup, 1275 ppDacl, 1276 ppSacl, 1277 ppSecurityDescriptor); 1278 } 1279 } 1280 } 1281 else 1282 ErrorCode = ERROR_INVALID_HANDLE; 1283 1284 return ErrorCode; 1285 } 1286 1287 1288 /********************************************************************** 1289 * SetSecurityInfo EXPORTED 1290 * 1291 * @implemented 1292 */ 1293 DWORD 1294 WINAPI 1295 SetSecurityInfo(HANDLE handle, 1296 SE_OBJECT_TYPE ObjectType, 1297 SECURITY_INFORMATION SecurityInfo, 1298 PSID psidOwner, 1299 PSID psidGroup, 1300 PACL pDacl, 1301 PACL pSacl) 1302 { 1303 DWORD ErrorCode; 1304 1305 if (handle != NULL) 1306 { 1307 ErrorCode = CheckNtMartaPresent(); 1308 if (ErrorCode == ERROR_SUCCESS) 1309 { 1310 SECURITY_DESCRIPTOR SecurityDescriptor; 1311 1312 ErrorCode = pSetSecurityInfoCheck(&SecurityDescriptor, 1313 SecurityInfo, 1314 psidOwner, 1315 psidGroup, 1316 pDacl, 1317 pSacl); 1318 1319 if (ErrorCode == ERROR_SUCCESS) 1320 { 1321 /* call the MARTA provider */ 1322 ErrorCode = AccRewriteSetHandleRights(handle, 1323 ObjectType, 1324 SecurityInfo, 1325 &SecurityDescriptor); 1326 } 1327 } 1328 } 1329 else 1330 ErrorCode = ERROR_INVALID_HANDLE; 1331 1332 return ErrorCode; 1333 } 1334 1335 /* 1336 * @implemented 1337 */ 1338 BOOL 1339 WINAPI 1340 CreatePrivateObjectSecurity(PSECURITY_DESCRIPTOR ParentDescriptor, 1341 PSECURITY_DESCRIPTOR CreatorDescriptor, 1342 PSECURITY_DESCRIPTOR *NewDescriptor, 1343 BOOL IsDirectoryObject, 1344 HANDLE Token, 1345 PGENERIC_MAPPING GenericMapping) 1346 { 1347 NTSTATUS Status; 1348 1349 Status = RtlNewSecurityObject(ParentDescriptor, 1350 CreatorDescriptor, 1351 NewDescriptor, 1352 IsDirectoryObject, 1353 Token, 1354 GenericMapping); 1355 if (!NT_SUCCESS(Status)) 1356 { 1357 SetLastError(RtlNtStatusToDosError(Status)); 1358 return FALSE; 1359 } 1360 1361 return TRUE; 1362 } 1363 1364 1365 /* 1366 * @unimplemented 1367 */ 1368 BOOL 1369 WINAPI 1370 CreatePrivateObjectSecurityEx(PSECURITY_DESCRIPTOR ParentDescriptor, 1371 PSECURITY_DESCRIPTOR CreatorDescriptor, 1372 PSECURITY_DESCRIPTOR* NewDescriptor, 1373 GUID* ObjectType, 1374 BOOL IsContainerObject, 1375 ULONG AutoInheritFlags, 1376 HANDLE Token, 1377 PGENERIC_MAPPING GenericMapping) 1378 { 1379 FIXME("%s() not implemented!\n", __FUNCTION__); 1380 return FALSE; 1381 } 1382 1383 1384 /* 1385 * @unimplemented 1386 */ 1387 BOOL 1388 WINAPI 1389 CreatePrivateObjectSecurityWithMultipleInheritance(PSECURITY_DESCRIPTOR ParentDescriptor, 1390 PSECURITY_DESCRIPTOR CreatorDescriptor, 1391 PSECURITY_DESCRIPTOR* NewDescriptor, 1392 GUID** ObjectTypes, 1393 ULONG GuidCount, 1394 BOOL IsContainerObject, 1395 ULONG AutoInheritFlags, 1396 HANDLE Token, 1397 PGENERIC_MAPPING GenericMapping) 1398 { 1399 FIXME("%s() semi-stub\n", __FUNCTION__); 1400 return CreatePrivateObjectSecurity(ParentDescriptor, CreatorDescriptor, NewDescriptor, IsContainerObject, Token, GenericMapping); 1401 } 1402 1403 1404 /* 1405 * @implemented 1406 */ 1407 BOOL 1408 WINAPI 1409 DestroyPrivateObjectSecurity(PSECURITY_DESCRIPTOR *ObjectDescriptor) 1410 { 1411 NTSTATUS Status; 1412 1413 Status = RtlDeleteSecurityObject(ObjectDescriptor); 1414 if (!NT_SUCCESS(Status)) 1415 { 1416 SetLastError(RtlNtStatusToDosError(Status)); 1417 return FALSE; 1418 } 1419 1420 return TRUE; 1421 } 1422 1423 1424 /* 1425 * @implemented 1426 */ 1427 BOOL 1428 WINAPI 1429 GetPrivateObjectSecurity(IN PSECURITY_DESCRIPTOR ObjectDescriptor, 1430 IN SECURITY_INFORMATION SecurityInformation, 1431 OUT PSECURITY_DESCRIPTOR ResultantDescriptor OPTIONAL, 1432 IN DWORD DescriptorLength, 1433 OUT PDWORD ReturnLength) 1434 { 1435 NTSTATUS Status; 1436 1437 /* Call RTL */ 1438 Status = RtlQuerySecurityObject(ObjectDescriptor, 1439 SecurityInformation, 1440 ResultantDescriptor, 1441 DescriptorLength, 1442 ReturnLength); 1443 if (!NT_SUCCESS(Status)) 1444 { 1445 /* Fail */ 1446 SetLastError(RtlNtStatusToDosError(Status)); 1447 return FALSE; 1448 } 1449 1450 /* Success */ 1451 return TRUE; 1452 } 1453 1454 1455 /* 1456 * @implemented 1457 */ 1458 BOOL 1459 WINAPI 1460 SetPrivateObjectSecurity(SECURITY_INFORMATION SecurityInformation, 1461 PSECURITY_DESCRIPTOR ModificationDescriptor, 1462 PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, 1463 PGENERIC_MAPPING GenericMapping, 1464 HANDLE Token) 1465 { 1466 NTSTATUS Status; 1467 1468 Status = RtlSetSecurityObject(SecurityInformation, 1469 ModificationDescriptor, 1470 ObjectsSecurityDescriptor, 1471 GenericMapping, 1472 Token); 1473 if (!NT_SUCCESS(Status)) 1474 { 1475 SetLastError(RtlNtStatusToDosError(Status)); 1476 return FALSE; 1477 } 1478 1479 return TRUE; 1480 } 1481 1482 1483 /* 1484 * @implemented 1485 */ 1486 DWORD 1487 WINAPI 1488 TreeResetNamedSecurityInfoW(LPWSTR pObjectName, 1489 SE_OBJECT_TYPE ObjectType, 1490 SECURITY_INFORMATION SecurityInfo, 1491 PSID pOwner, 1492 PSID pGroup, 1493 PACL pDacl, 1494 PACL pSacl, 1495 BOOL KeepExplicit, 1496 FN_PROGRESSW fnProgress, 1497 PROG_INVOKE_SETTING ProgressInvokeSetting, 1498 PVOID Args) 1499 { 1500 DWORD ErrorCode; 1501 1502 if (pObjectName != NULL) 1503 { 1504 ErrorCode = CheckNtMartaPresent(); 1505 if (ErrorCode == ERROR_SUCCESS) 1506 { 1507 switch (ObjectType) 1508 { 1509 case SE_FILE_OBJECT: 1510 case SE_REGISTRY_KEY: 1511 { 1512 /* check the SecurityInfo flags for sanity (both, the protected 1513 and unprotected dacl/sacl flag must not be passed together) */ 1514 if (((SecurityInfo & DACL_SECURITY_INFORMATION) && 1515 (SecurityInfo & (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION)) == 1516 (PROTECTED_DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION)) 1517 1518 || 1519 1520 ((SecurityInfo & SACL_SECURITY_INFORMATION) && 1521 (SecurityInfo & (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION)) == 1522 (PROTECTED_SACL_SECURITY_INFORMATION | UNPROTECTED_SACL_SECURITY_INFORMATION))) 1523 { 1524 ErrorCode = ERROR_INVALID_PARAMETER; 1525 break; 1526 } 1527 1528 /* call the MARTA provider */ 1529 ErrorCode = AccTreeResetNamedSecurityInfo(pObjectName, 1530 ObjectType, 1531 SecurityInfo, 1532 pOwner, 1533 pGroup, 1534 pDacl, 1535 pSacl, 1536 KeepExplicit, 1537 fnProgress, 1538 ProgressInvokeSetting, 1539 Args); 1540 break; 1541 } 1542 1543 default: 1544 /* object type not supported */ 1545 ErrorCode = ERROR_INVALID_PARAMETER; 1546 break; 1547 } 1548 } 1549 } 1550 else 1551 ErrorCode = ERROR_INVALID_PARAMETER; 1552 1553 return ErrorCode; 1554 } 1555 1556 #ifdef HAS_FN_PROGRESSW 1557 1558 typedef struct _INTERNAL_FNPROGRESSW_DATA 1559 { 1560 FN_PROGRESSA fnProgress; 1561 PVOID Args; 1562 } INTERNAL_FNPROGRESSW_DATA, *PINTERNAL_FNPROGRESSW_DATA; 1563 1564 static VOID WINAPI 1565 InternalfnProgressW(LPWSTR pObjectName, 1566 DWORD Status, 1567 PPROG_INVOKE_SETTING pInvokeSetting, 1568 PVOID Args, 1569 BOOL SecuritySet) 1570 { 1571 PINTERNAL_FNPROGRESSW_DATA pifnProgressData = (PINTERNAL_FNPROGRESSW_DATA)Args; 1572 INT ObjectNameSize; 1573 LPSTR pObjectNameA; 1574 1575 ObjectNameSize = WideCharToMultiByte(CP_ACP, 1576 0, 1577 pObjectName, 1578 -1, 1579 NULL, 1580 0, 1581 NULL, 1582 NULL); 1583 1584 if (ObjectNameSize > 0) 1585 { 1586 pObjectNameA = RtlAllocateHeap(RtlGetProcessHeap(), 1587 0, 1588 ObjectNameSize); 1589 if (pObjectNameA != NULL) 1590 { 1591 pObjectNameA[0] = '\0'; 1592 WideCharToMultiByte(CP_ACP, 1593 0, 1594 pObjectName, 1595 -1, 1596 pObjectNameA, 1597 ObjectNameSize, 1598 NULL, 1599 NULL); 1600 1601 pifnProgressData->fnProgress((LPWSTR)pObjectNameA, /* FIXME: wrong cast!! */ 1602 Status, 1603 pInvokeSetting, 1604 pifnProgressData->Args, 1605 SecuritySet); 1606 1607 RtlFreeHeap(RtlGetProcessHeap(), 1608 0, 1609 pObjectNameA); 1610 } 1611 } 1612 } 1613 #endif 1614 1615 1616 /* 1617 * @implemented 1618 */ 1619 DWORD 1620 WINAPI 1621 TreeResetNamedSecurityInfoA(LPSTR pObjectName, 1622 SE_OBJECT_TYPE ObjectType, 1623 SECURITY_INFORMATION SecurityInfo, 1624 PSID pOwner, 1625 PSID pGroup, 1626 PACL pDacl, 1627 PACL pSacl, 1628 BOOL KeepExplicit, 1629 FN_PROGRESSA fnProgress, 1630 PROG_INVOKE_SETTING ProgressInvokeSetting, 1631 PVOID Args) 1632 { 1633 #ifndef HAS_FN_PROGRESSW 1634 /* That's all this function does, at least up to w2k3... Even MS was too 1635 lazy to implement it... */ 1636 return ERROR_CALL_NOT_IMPLEMENTED; 1637 #else 1638 INTERNAL_FNPROGRESSW_DATA ifnProgressData; 1639 UNICODE_STRING ObjectName; 1640 DWORD Ret; 1641 1642 if (!RtlCreateUnicodeStringFromAsciiz(&ObjectName, pObjectName)) 1643 { 1644 return ERROR_NOT_ENOUGH_MEMORY; 1645 } 1646 1647 ifnProgressData.fnProgress = fnProgress; 1648 ifnProgressData.Args = Args; 1649 1650 Ret = TreeResetNamedSecurityInfoW(ObjectName.Buffer, 1651 ObjectType, 1652 SecurityInfo, 1653 pOwner, 1654 pGroup, 1655 pDacl, 1656 pSacl, 1657 KeepExplicit, 1658 (fnProgress != NULL ? InternalfnProgressW : NULL), 1659 ProgressInvokeSetting, 1660 &ifnProgressData); 1661 1662 RtlFreeUnicodeString(&ObjectName); 1663 1664 return Ret; 1665 #endif 1666 } 1667 1668 /* EOF */ 1669