2 * COPYRIGHT: See COPYING in the top level directory
4 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6 * Copyright 2006 Robert Reif
8 * PROJECT: ReactOS system libraries
9 * FILE: dll/win32/advapi32/sec/misc.c
10 * PURPOSE: Miscellaneous security functions (some ported from Wine)
15 WINE_DEFAULT_DEBUG_CHANNEL(advapi
);
17 /* Interface to ntmarta.dll ***************************************************/
19 NTMARTA NtMartaStatic
= { 0 };
20 static PNTMARTA NtMarta
= NULL
;
22 #define FindNtMartaProc(Name) \
23 NtMartaStatic.Name = (PVOID)GetProcAddress(NtMartaStatic.hDllInstance, \
25 if (NtMartaStatic.Name == NULL) \
27 return GetLastError(); \
32 LoadAndInitializeNtMarta(VOID
)
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
42 NtMartaStatic
.hDllInstance
= LoadLibraryW(L
"ntmarta.dll");
43 if (NtMartaStatic
.hDllInstance
== NULL
)
45 return GetLastError();
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
);
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
);
74 CheckNtMartaPresent(VOID
)
78 if (InterlockedCompareExchangePointer((PVOID
)&NtMarta
,
82 /* we're the first one trying to use ntmarta, initialize it and change
83 the pointer after initialization */
84 ErrorCode
= LoadAndInitializeNtMarta();
86 if (ErrorCode
== ERROR_SUCCESS
)
88 /* try change the NtMarta pointer */
89 if (InterlockedCompareExchangePointer((PVOID
)&NtMarta
,
93 /* another thread initialized ntmarta in the meanwhile, release
94 the reference of the dll loaded. */
95 FreeLibrary(NtMartaStatic
.hDllInstance
);
101 ERR("Failed to initialize ntmarta.dll! Error: 0x%x", ErrorCode
);
107 /* ntmarta was already initialized */
108 ErrorCode
= ERROR_SUCCESS
;
118 if (InterlockedExchangePointer((PVOID
)&NtMarta
,
121 FreeLibrary(NtMartaStatic
.hDllInstance
);
126 /******************************************************************************/
133 ImpersonateAnonymousToken(IN HANDLE ThreadHandle
)
137 Status
= NtImpersonateAnonymousToken(ThreadHandle
);
138 if (!NT_SUCCESS(Status
))
140 SetLastError(RtlNtStatusToDosError(Status
));
152 ImpersonateLoggedOnUser(HANDLE hToken
)
154 SECURITY_QUALITY_OF_SERVICE Qos
;
155 OBJECT_ATTRIBUTES ObjectAttributes
;
162 /* Get the token type */
163 Status
= NtQueryInformationToken(hToken
,
168 if (!NT_SUCCESS(Status
))
170 SetLastError(RtlNtStatusToDosError(Status
));
174 if (Type
== TokenPrimary
)
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
;
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
;
189 Status
= NtDuplicateToken(hToken
,
190 TOKEN_IMPERSONATE
| TOKEN_QUERY
,
195 if (!NT_SUCCESS(Status
))
197 ERR("NtDuplicateToken failed: Status %08x\n", Status
);
198 SetLastError(RtlNtStatusToDosError(Status
));
206 /* User the original impersonation token */
211 /* Impersonate the the current thread */
212 Status
= NtSetInformationThread(NtCurrentThread(),
213 ThreadImpersonationToken
,
217 if (Duplicated
== TRUE
)
222 if (!NT_SUCCESS(Status
))
224 ERR("NtSetInformationThread failed: Status %08x\n", Status
);
225 SetLastError(RtlNtStatusToDosError(Status
));
232 /******************************************************************************
233 * GetUserNameA [ADVAPI32.@]
235 * Get the current user name.
238 * lpszName [O] Destination for the user name.
239 * lpSize [I/O] Size of lpszName.
246 GetUserNameA(LPSTR lpszName
,
249 UNICODE_STRING NameW
;
253 /* apparently Win doesn't check whether lpSize is valid at all! */
255 NameW
.MaximumLength
= (*lpSize
) * sizeof(WCHAR
);
256 NameW
.Buffer
= LocalAlloc(LMEM_FIXED
, NameW
.MaximumLength
);
257 if(NameW
.Buffer
== NULL
)
259 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
264 NameA
.MaximumLength
= ((*lpSize
) < 0xFFFF ? (USHORT
)(*lpSize
) : 0xFFFF);
265 NameA
.Buffer
= lpszName
;
267 Ret
= GetUserNameW(NameW
.Buffer
,
271 NameW
.Length
= (*lpSize
- 1) * sizeof(WCHAR
);
272 RtlUnicodeStringToAnsiString(&NameA
, &NameW
, FALSE
);
274 *lpSize
= NameA
.Length
+ 1;
277 LocalFree(NameW
.Buffer
);
282 /******************************************************************************
283 * GetUserNameW [ADVAPI32.@]
291 GetUserNameW(LPWSTR lpszName
,
294 HANDLE hToken
= INVALID_HANDLE_VALUE
;
297 TOKEN_USER
* token_user
= NULL
;
299 SID_NAME_USE snu
= SidTypeUser
;
300 WCHAR
* domain_name
= NULL
;
303 if (!OpenThreadToken (GetCurrentThread(), TOKEN_QUERY
, FALSE
, &hToken
))
305 DWORD dwLastError
= GetLastError();
306 if (dwLastError
!= ERROR_NO_TOKEN
307 && dwLastError
!= ERROR_NO_IMPERSONATION_TOKEN
)
309 /* don't call SetLastError(),
310 as OpenThreadToken() ought to have set one */
314 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
))
316 /* don't call SetLastError(),
317 as OpenProcessToken() ought to have set one */
322 tu_buf
= LocalAlloc(LMEM_FIXED
, 36);
325 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
330 if (!GetTokenInformation(hToken
, TokenUser
, tu_buf
, 36, &tu_len
) || tu_len
> 36)
333 tu_buf
= LocalAlloc(LMEM_FIXED
, tu_len
);
336 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
341 if (!GetTokenInformation(hToken
, TokenUser
, tu_buf
, tu_len
, &tu_len
))
343 /* don't call SetLastError(),
344 as GetTokenInformation() ought to have set one */
352 token_user
= (TOKEN_USER
*)tu_buf
;
356 domain_name
= LocalAlloc(LMEM_FIXED
, dn_len
* sizeof(WCHAR
));
360 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
364 if (!LookupAccountSidW(NULL
, token_user
->User
.Sid
, lpszName
, &an_len
, domain_name
, &dn_len
, &snu
)
369 LocalFree(domain_name
);
370 domain_name
= LocalAlloc(LMEM_FIXED
, dn_len
* sizeof(WCHAR
));
374 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
380 if (!LookupAccountSidW(NULL
, token_user
->User
.Sid
, lpszName
, &an_len
, domain_name
, &dn_len
, &snu
))
382 /* don't call SetLastError(),
383 as LookupAccountSid() ought to have set one */
384 LocalFree(domain_name
);
391 LocalFree(domain_name
);
393 *lpSize
= an_len
+ 1;
398 /******************************************************************************
399 * LookupAccountSidA [ADVAPI32.@]
405 LookupAccountSidA(LPCSTR lpSystemName
,
409 LPSTR lpReferencedDomainName
,
410 LPDWORD cchReferencedDomainName
,
413 UNICODE_STRING NameW
, ReferencedDomainNameW
, SystemNameW
;
414 LPWSTR NameBuffer
= NULL
;
415 LPWSTR ReferencedDomainNameBuffer
= NULL
;
416 DWORD dwName
, dwReferencedDomainName
;
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
424 dwReferencedDomainName
= *cchReferencedDomainName
;
426 /* allocate buffers for the unicode strings to receive */
429 NameBuffer
= LocalAlloc(LMEM_FIXED
, dwName
* sizeof(WCHAR
));
430 if (NameBuffer
== NULL
)
432 SetLastError(ERROR_OUTOFMEMORY
);
439 if (dwReferencedDomainName
> 0)
441 ReferencedDomainNameBuffer
= LocalAlloc(LMEM_FIXED
, dwReferencedDomainName
* sizeof(WCHAR
));
442 if (ReferencedDomainNameBuffer
== NULL
)
446 LocalFree(NameBuffer
);
449 SetLastError(ERROR_OUTOFMEMORY
);
454 ReferencedDomainNameBuffer
= NULL
;
457 /* convert the system name to unicode - if present */
458 if (lpSystemName
!= NULL
)
460 ANSI_STRING SystemNameA
;
462 RtlInitAnsiString(&SystemNameA
, lpSystemName
);
463 RtlAnsiStringToUnicodeString(&SystemNameW
, &SystemNameA
, TRUE
);
466 SystemNameW
.Buffer
= NULL
;
468 /* it's time to call the unicode version */
469 Ret
= LookupAccountSidW(SystemNameW
.Buffer
,
473 ReferencedDomainNameBuffer
,
474 cchReferencedDomainName
,
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!
488 NameA
.MaximumLength
= ((dwName
<= 0xFFFF) ? (USHORT
)dwName
: 0xFFFF);
489 NameA
.Buffer
= lpName
;
491 RtlInitUnicodeString(&NameW
, NameBuffer
);
492 RtlUnicodeStringToAnsiString(&NameA
, &NameW
, FALSE
);
493 NameA
.Buffer
[NameA
.Length
] = '\0';
496 if (lpReferencedDomainName
!= NULL
)
498 ANSI_STRING ReferencedDomainNameA
;
500 ReferencedDomainNameA
.Length
= 0;
501 ReferencedDomainNameA
.MaximumLength
= ((dwReferencedDomainName
<= 0xFFFF) ?
502 (USHORT
)dwReferencedDomainName
: 0xFFFF);
503 ReferencedDomainNameA
.Buffer
= lpReferencedDomainName
;
505 RtlInitUnicodeString(&ReferencedDomainNameW
, ReferencedDomainNameBuffer
);
506 RtlUnicodeStringToAnsiString(&ReferencedDomainNameA
, &ReferencedDomainNameW
, FALSE
);
507 ReferencedDomainNameA
.Buffer
[ReferencedDomainNameA
.Length
] = '\0';
511 /* free previously allocated buffers */
512 if (SystemNameW
.Buffer
!= NULL
)
514 RtlFreeUnicodeString(&SystemNameW
);
517 if (NameBuffer
!= NULL
)
519 LocalFree(NameBuffer
);
522 if (ReferencedDomainNameBuffer
!= NULL
)
524 LocalFree(ReferencedDomainNameBuffer
);
531 /******************************************************************************
532 * LookupAccountSidW [ADVAPI32.@]
537 LookupAccountSidW(LPCWSTR pSystemName
,
540 LPDWORD pdwAccountName
,
542 LPDWORD pdwDomainName
,
545 LSA_UNICODE_STRING SystemName
;
546 LSA_OBJECT_ATTRIBUTES ObjectAttributes
= {0};
547 LSA_HANDLE PolicyHandle
= NULL
;
549 PLSA_REFERENCED_DOMAIN_LIST ReferencedDomain
= NULL
;
550 PLSA_TRANSLATED_NAME TranslatedName
= NULL
;
552 DWORD dwAccountName
, dwDomainName
;
554 RtlInitUnicodeString(&SystemName
, pSystemName
);
555 Status
= LsaOpenPolicy(&SystemName
, &ObjectAttributes
, POLICY_LOOKUP_NAMES
, &PolicyHandle
);
556 if (!NT_SUCCESS(Status
))
558 SetLastError(LsaNtStatusToWinError(Status
));
562 Status
= LsaLookupSids(PolicyHandle
, 1, &pSid
, &ReferencedDomain
, &TranslatedName
);
564 LsaClose(PolicyHandle
);
566 if (!NT_SUCCESS(Status
) || Status
== STATUS_SOME_NOT_MAPPED
)
568 SetLastError(LsaNtStatusToWinError(Status
));
575 dwAccountName
= TranslatedName
->Name
.Length
/ sizeof(WCHAR
);
576 if (ReferencedDomain
&& ReferencedDomain
->Entries
> 0)
577 dwDomainName
= ReferencedDomain
->Domains
[0].Name
.Length
/ sizeof(WCHAR
);
581 if (*pdwAccountName
<= dwAccountName
|| *pdwDomainName
<= dwDomainName
)
583 /* One or two buffers are insufficient, add up a char for NULL termination */
584 *pdwAccountName
= dwAccountName
+ 1;
585 *pdwDomainName
= dwDomainName
+ 1;
590 /* Lengths are sufficient, copy the data */
592 RtlCopyMemory(pAccountName
, TranslatedName
->Name
.Buffer
, dwAccountName
* sizeof(WCHAR
));
593 pAccountName
[dwAccountName
] = L
'\0';
596 RtlCopyMemory(pDomainName
, ReferencedDomain
->Domains
[0].Name
.Buffer
, dwDomainName
* sizeof(WCHAR
));
597 pDomainName
[dwDomainName
] = L
'\0';
599 *pdwAccountName
= dwAccountName
;
600 *pdwDomainName
= dwDomainName
;
603 *peUse
= TranslatedName
->Use
;
607 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
610 if (ReferencedDomain
)
611 LsaFreeMemory(ReferencedDomain
);
614 LsaFreeMemory(TranslatedName
);
619 /******************************************************************************
620 * LookupAccountNameW [ADVAPI32.@]
626 LookupAccountNameW(LPCWSTR lpSystemName
,
627 LPCWSTR lpAccountName
,
630 LPWSTR ReferencedDomainName
,
631 LPDWORD cchReferencedDomainName
,
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
;
641 DWORD dwDomainNameLength
;
643 UCHAR nSubAuthorities
;
647 TRACE("%s %s %p %p %p %p %p\n", lpSystemName
, lpAccountName
,
648 Sid
, cbSid
, ReferencedDomainName
, cchReferencedDomainName
, peUse
);
650 RtlInitUnicodeString(&SystemName
,
653 Status
= LsaOpenPolicy(lpSystemName
? &SystemName
: NULL
,
657 if (!NT_SUCCESS(Status
))
659 SetLastError(LsaNtStatusToWinError(Status
));
663 RtlInitUnicodeString(&AccountName
,
666 Status
= LsaLookupNames(PolicyHandle
,
672 LsaClose(PolicyHandle
);
674 if (!NT_SUCCESS(Status
) || Status
== STATUS_SOME_NOT_MAPPED
)
676 SetLastError(LsaNtStatusToWinError(Status
));
681 pDomainSid
= ReferencedDomains
->Domains
[TranslatedSid
->DomainIndex
].Sid
;
682 nSubAuthorities
= *GetSidSubAuthorityCount(pDomainSid
);
683 dwSidLength
= GetSidLengthRequired(nSubAuthorities
+ 1);
685 dwDomainNameLength
= ReferencedDomains
->Domains
->Name
.Length
/ sizeof(WCHAR
);
687 if (*cbSid
< dwSidLength
||
688 *cchReferencedDomainName
< dwDomainNameLength
+ 1)
690 *cbSid
= dwSidLength
;
691 *cchReferencedDomainName
= dwDomainNameLength
+ 1;
697 CopySid(*cbSid
, Sid
, pDomainSid
);
698 *GetSidSubAuthorityCount(Sid
) = nSubAuthorities
+ 1;
699 *GetSidSubAuthority(Sid
, (DWORD
)nSubAuthorities
) = TranslatedSid
->RelativeId
;
701 RtlCopyMemory(ReferencedDomainName
, ReferencedDomains
->Domains
->Name
.Buffer
, dwDomainNameLength
* sizeof(WCHAR
));
702 ReferencedDomainName
[dwDomainNameLength
] = L
'\0';
704 *cchReferencedDomainName
= dwDomainNameLength
;
706 *peUse
= TranslatedSid
->Use
;
711 if (bResult
== FALSE
)
712 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
715 if (ReferencedDomains
!= NULL
)
716 LsaFreeMemory(ReferencedDomains
);
718 if (TranslatedSid
!= NULL
)
719 LsaFreeMemory(TranslatedSid
);
725 /**********************************************************************
726 * LookupPrivilegeValueA EXPORTED
732 LookupPrivilegeValueA(LPCSTR lpSystemName
,
736 UNICODE_STRING SystemName
;
741 if (lpSystemName
!= NULL
)
743 RtlCreateUnicodeStringFromAsciiz(&SystemName
,
744 (LPSTR
)lpSystemName
);
747 SystemName
.Buffer
= NULL
;
749 /* Check the privilege name is not NULL */
752 SetLastError(ERROR_NO_SUCH_PRIVILEGE
);
756 RtlCreateUnicodeStringFromAsciiz(&Name
,
759 Result
= LookupPrivilegeValueW(SystemName
.Buffer
,
763 RtlFreeUnicodeString(&Name
);
766 if (SystemName
.Buffer
!= NULL
)
768 RtlFreeUnicodeString(&SystemName
);
775 /**********************************************************************
776 * LookupPrivilegeValueW
782 LookupPrivilegeValueW(LPCWSTR lpSystemName
,
783 LPCWSTR lpPrivilegeName
,
786 OBJECT_ATTRIBUTES ObjectAttributes
= {0};
787 UNICODE_STRING SystemName
;
788 UNICODE_STRING PrivilegeName
;
789 LSA_HANDLE PolicyHandle
= NULL
;
792 TRACE("%S,%S,%p\n", lpSystemName
, lpPrivilegeName
, lpLuid
);
794 RtlInitUnicodeString(&SystemName
,
797 Status
= LsaOpenPolicy(lpSystemName
? &SystemName
: NULL
,
801 if (!NT_SUCCESS(Status
))
803 SetLastError(LsaNtStatusToWinError(Status
));
807 RtlInitUnicodeString(&PrivilegeName
,
810 Status
= LsaLookupPrivilegeValue(PolicyHandle
,
814 LsaClose(PolicyHandle
);
816 if (!NT_SUCCESS(Status
))
818 SetLastError(LsaNtStatusToWinError(Status
));
825 /**********************************************************************
826 * LookupPrivilegeNameW EXPORTED
832 LookupPrivilegeNameW(LPCWSTR lpSystemName
,
837 OBJECT_ATTRIBUTES ObjectAttributes
= {0};
838 UNICODE_STRING SystemName
;
839 PUNICODE_STRING PrivilegeName
= NULL
;
840 LSA_HANDLE PolicyHandle
= NULL
;
843 TRACE("%S,%p,%p,%p\n", lpSystemName
, lpLuid
, lpName
, cchName
);
845 RtlInitUnicodeString(&SystemName
,
848 Status
= LsaOpenPolicy(lpSystemName
? &SystemName
: NULL
,
852 if (!NT_SUCCESS(Status
))
854 SetLastError(LsaNtStatusToWinError(Status
));
858 Status
= LsaLookupPrivilegeName(PolicyHandle
,
861 if (NT_SUCCESS(Status
))
863 if (PrivilegeName
->Length
+ sizeof(WCHAR
) > *cchName
* sizeof(WCHAR
))
865 Status
= STATUS_BUFFER_TOO_SMALL
;
867 *cchName
= (PrivilegeName
->Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
871 RtlMoveMemory(lpName
,
872 PrivilegeName
->Buffer
,
873 PrivilegeName
->Length
);
874 lpName
[PrivilegeName
->Length
/ sizeof(WCHAR
)] = 0;
876 *cchName
= PrivilegeName
->Length
/ sizeof(WCHAR
);
879 LsaFreeMemory(PrivilegeName
->Buffer
);
880 LsaFreeMemory(PrivilegeName
);
883 LsaClose(PolicyHandle
);
885 if (!NT_SUCCESS(Status
))
887 SetLastError(LsaNtStatusToWinError(Status
));
894 /**********************************************************************
895 * LookupPrivilegeDisplayNameW EXPORTED
901 LookupPrivilegeDisplayNameW(LPCWSTR lpSystemName
,
903 LPWSTR lpDisplayName
,
904 LPDWORD cchDisplayName
,
905 LPDWORD lpLanguageId
)
907 OBJECT_ATTRIBUTES ObjectAttributes
= {0};
908 UNICODE_STRING SystemName
, Name
;
909 PUNICODE_STRING DisplayName
;
910 LSA_HANDLE PolicyHandle
= NULL
;
914 TRACE("%S,%S,%p,%p,%p\n", lpSystemName
, lpName
, lpDisplayName
, cchDisplayName
, lpLanguageId
);
916 RtlInitUnicodeString(&SystemName
, lpSystemName
);
917 RtlInitUnicodeString(&Name
, lpName
);
919 Status
= LsaOpenPolicy(lpSystemName
? &SystemName
: NULL
,
923 if (!NT_SUCCESS(Status
))
925 SetLastError(LsaNtStatusToWinError(Status
));
929 Status
= LsaLookupPrivilegeDisplayName(PolicyHandle
, &Name
, &DisplayName
, &LanguageId
);
930 if (NT_SUCCESS(Status
))
932 *lpLanguageId
= LanguageId
;
933 if (DisplayName
->Length
+ sizeof(WCHAR
) > *cchDisplayName
* sizeof(WCHAR
))
935 Status
= STATUS_BUFFER_TOO_SMALL
;
937 *cchDisplayName
= (DisplayName
->Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
941 RtlMoveMemory(lpDisplayName
,
943 DisplayName
->Length
);
944 lpDisplayName
[DisplayName
->Length
/ sizeof(WCHAR
)] = 0;
946 *cchDisplayName
= DisplayName
->Length
/ sizeof(WCHAR
);
949 LsaFreeMemory(DisplayName
->Buffer
);
950 LsaFreeMemory(DisplayName
);
953 LsaClose(PolicyHandle
);
955 if (!NT_SUCCESS(Status
))
957 SetLastError(LsaNtStatusToWinError(Status
));
965 pGetSecurityInfoCheck(SECURITY_INFORMATION SecurityInfo
,
970 PSECURITY_DESCRIPTOR
* ppSecurityDescriptor
)
972 if ((SecurityInfo
& (OWNER_SECURITY_INFORMATION
|
973 GROUP_SECURITY_INFORMATION
|
974 DACL_SECURITY_INFORMATION
|
975 SACL_SECURITY_INFORMATION
)) &&
976 ppSecurityDescriptor
== NULL
)
978 /* if one of the SIDs or ACLs are present, the security descriptor
980 return ERROR_INVALID_PARAMETER
;
984 /* reset the pointers unless they're ignored */
985 if ((SecurityInfo
& OWNER_SECURITY_INFORMATION
) &&
990 if ((SecurityInfo
& GROUP_SECURITY_INFORMATION
) &&
995 if ((SecurityInfo
& DACL_SECURITY_INFORMATION
) &&
1000 if ((SecurityInfo
& SACL_SECURITY_INFORMATION
) &&
1006 if (SecurityInfo
& (OWNER_SECURITY_INFORMATION
|
1007 GROUP_SECURITY_INFORMATION
|
1008 DACL_SECURITY_INFORMATION
|
1009 SACL_SECURITY_INFORMATION
))
1011 *ppSecurityDescriptor
= NULL
;
1014 return ERROR_SUCCESS
;
1020 pSetSecurityInfoCheck(PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1021 SECURITY_INFORMATION SecurityInfo
,
1027 /* initialize a security descriptor on the stack */
1028 if (!InitializeSecurityDescriptor(pSecurityDescriptor
,
1029 SECURITY_DESCRIPTOR_REVISION
))
1031 return GetLastError();
1034 if (SecurityInfo
& OWNER_SECURITY_INFORMATION
)
1036 if (RtlValidSid(psidOwner
))
1038 if (!SetSecurityDescriptorOwner(pSecurityDescriptor
,
1042 return GetLastError();
1047 return ERROR_INVALID_PARAMETER
;
1051 if (SecurityInfo
& GROUP_SECURITY_INFORMATION
)
1053 if (RtlValidSid(psidGroup
))
1055 if (!SetSecurityDescriptorGroup(pSecurityDescriptor
,
1059 return GetLastError();
1064 return ERROR_INVALID_PARAMETER
;
1068 if (SecurityInfo
& DACL_SECURITY_INFORMATION
)
1072 if (SetSecurityDescriptorDacl(pSecurityDescriptor
,
1077 /* check if the DACL needs to be protected from being
1078 modified by inheritable ACEs */
1079 if (SecurityInfo
& PROTECTED_DACL_SECURITY_INFORMATION
)
1086 return GetLastError();
1092 /* protect the DACL from being modified by inheritable ACEs */
1093 if (!SetSecurityDescriptorControl(pSecurityDescriptor
,
1097 return GetLastError();
1102 if (SecurityInfo
& SACL_SECURITY_INFORMATION
)
1106 if (SetSecurityDescriptorSacl(pSecurityDescriptor
,
1111 /* check if the SACL needs to be protected from being
1112 modified by inheritable ACEs */
1113 if (SecurityInfo
& PROTECTED_SACL_SECURITY_INFORMATION
)
1120 return GetLastError();
1126 /* protect the SACL from being modified by inheritable ACEs */
1127 if (!SetSecurityDescriptorControl(pSecurityDescriptor
,
1131 return GetLastError();
1136 return ERROR_SUCCESS
;
1140 /**********************************************************************
1141 * GetNamedSecurityInfoW EXPORTED
1147 GetNamedSecurityInfoW(LPWSTR pObjectName
,
1148 SE_OBJECT_TYPE ObjectType
,
1149 SECURITY_INFORMATION SecurityInfo
,
1154 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
1158 if (pObjectName
!= NULL
)
1160 ErrorCode
= CheckNtMartaPresent();
1161 if (ErrorCode
== ERROR_SUCCESS
)
1163 ErrorCode
= pGetSecurityInfoCheck(SecurityInfo
,
1168 ppSecurityDescriptor
);
1170 if (ErrorCode
== ERROR_SUCCESS
)
1172 /* call the MARTA provider */
1173 ErrorCode
= AccRewriteGetNamedRights(pObjectName
,
1180 ppSecurityDescriptor
);
1185 ErrorCode
= ERROR_INVALID_PARAMETER
;
1190 /**********************************************************************
1191 * SetNamedSecurityInfoW EXPORTED
1197 SetNamedSecurityInfoW(LPWSTR pObjectName
,
1198 SE_OBJECT_TYPE ObjectType
,
1199 SECURITY_INFORMATION SecurityInfo
,
1207 if (pObjectName
!= NULL
)
1209 ErrorCode
= CheckNtMartaPresent();
1210 if (ErrorCode
== ERROR_SUCCESS
)
1212 SECURITY_DESCRIPTOR SecurityDescriptor
;
1214 ErrorCode
= pSetSecurityInfoCheck(&SecurityDescriptor
,
1221 if (ErrorCode
== ERROR_SUCCESS
)
1223 /* call the MARTA provider */
1224 ErrorCode
= AccRewriteSetNamedRights(pObjectName
,
1227 &SecurityDescriptor
);
1232 ErrorCode
= ERROR_INVALID_PARAMETER
;
1237 /**********************************************************************
1238 * GetSecurityInfo EXPORTED
1244 GetSecurityInfo(HANDLE handle
,
1245 SE_OBJECT_TYPE ObjectType
,
1246 SECURITY_INFORMATION SecurityInfo
,
1251 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
1257 ErrorCode
= CheckNtMartaPresent();
1258 if (ErrorCode
== ERROR_SUCCESS
)
1260 ErrorCode
= pGetSecurityInfoCheck(SecurityInfo
,
1265 ppSecurityDescriptor
);
1267 if (ErrorCode
== ERROR_SUCCESS
)
1269 /* call the MARTA provider */
1270 ErrorCode
= AccRewriteGetHandleRights(handle
,
1277 ppSecurityDescriptor
);
1282 ErrorCode
= ERROR_INVALID_HANDLE
;
1288 /**********************************************************************
1289 * SetSecurityInfo EXPORTED
1295 SetSecurityInfo(HANDLE handle
,
1296 SE_OBJECT_TYPE ObjectType
,
1297 SECURITY_INFORMATION SecurityInfo
,
1307 ErrorCode
= CheckNtMartaPresent();
1308 if (ErrorCode
== ERROR_SUCCESS
)
1310 SECURITY_DESCRIPTOR SecurityDescriptor
;
1312 ErrorCode
= pSetSecurityInfoCheck(&SecurityDescriptor
,
1319 if (ErrorCode
== ERROR_SUCCESS
)
1321 /* call the MARTA provider */
1322 ErrorCode
= AccRewriteSetHandleRights(handle
,
1325 &SecurityDescriptor
);
1330 ErrorCode
= ERROR_INVALID_HANDLE
;
1340 CreatePrivateObjectSecurity(PSECURITY_DESCRIPTOR ParentDescriptor
,
1341 PSECURITY_DESCRIPTOR CreatorDescriptor
,
1342 PSECURITY_DESCRIPTOR
*NewDescriptor
,
1343 BOOL IsDirectoryObject
,
1345 PGENERIC_MAPPING GenericMapping
)
1349 Status
= RtlNewSecurityObject(ParentDescriptor
,
1355 if (!NT_SUCCESS(Status
))
1357 SetLastError(RtlNtStatusToDosError(Status
));
1370 CreatePrivateObjectSecurityEx(PSECURITY_DESCRIPTOR ParentDescriptor
,
1371 PSECURITY_DESCRIPTOR CreatorDescriptor
,
1372 PSECURITY_DESCRIPTOR
* NewDescriptor
,
1374 BOOL IsContainerObject
,
1375 ULONG AutoInheritFlags
,
1377 PGENERIC_MAPPING GenericMapping
)
1379 FIXME("%s() not implemented!\n", __FUNCTION__
);
1389 CreatePrivateObjectSecurityWithMultipleInheritance(PSECURITY_DESCRIPTOR ParentDescriptor
,
1390 PSECURITY_DESCRIPTOR CreatorDescriptor
,
1391 PSECURITY_DESCRIPTOR
* NewDescriptor
,
1394 BOOL IsContainerObject
,
1395 ULONG AutoInheritFlags
,
1397 PGENERIC_MAPPING GenericMapping
)
1399 FIXME("%s() semi-stub\n", __FUNCTION__
);
1400 return CreatePrivateObjectSecurity(ParentDescriptor
, CreatorDescriptor
, NewDescriptor
, IsContainerObject
, Token
, GenericMapping
);
1409 DestroyPrivateObjectSecurity(PSECURITY_DESCRIPTOR
*ObjectDescriptor
)
1413 Status
= RtlDeleteSecurityObject(ObjectDescriptor
);
1414 if (!NT_SUCCESS(Status
))
1416 SetLastError(RtlNtStatusToDosError(Status
));
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
)
1438 Status
= RtlQuerySecurityObject(ObjectDescriptor
,
1439 SecurityInformation
,
1440 ResultantDescriptor
,
1443 if (!NT_SUCCESS(Status
))
1446 SetLastError(RtlNtStatusToDosError(Status
));
1460 SetPrivateObjectSecurity(SECURITY_INFORMATION SecurityInformation
,
1461 PSECURITY_DESCRIPTOR ModificationDescriptor
,
1462 PSECURITY_DESCRIPTOR
*ObjectsSecurityDescriptor
,
1463 PGENERIC_MAPPING GenericMapping
,
1468 Status
= RtlSetSecurityObject(SecurityInformation
,
1469 ModificationDescriptor
,
1470 ObjectsSecurityDescriptor
,
1473 if (!NT_SUCCESS(Status
))
1475 SetLastError(RtlNtStatusToDosError(Status
));
1488 TreeResetNamedSecurityInfoW(LPWSTR pObjectName
,
1489 SE_OBJECT_TYPE ObjectType
,
1490 SECURITY_INFORMATION SecurityInfo
,
1496 FN_PROGRESSW fnProgress
,
1497 PROG_INVOKE_SETTING ProgressInvokeSetting
,
1502 if (pObjectName
!= NULL
)
1504 ErrorCode
= CheckNtMartaPresent();
1505 if (ErrorCode
== ERROR_SUCCESS
)
1509 case SE_FILE_OBJECT
:
1510 case SE_REGISTRY_KEY
:
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
))
1520 ((SecurityInfo
& SACL_SECURITY_INFORMATION
) &&
1521 (SecurityInfo
& (PROTECTED_SACL_SECURITY_INFORMATION
| UNPROTECTED_SACL_SECURITY_INFORMATION
)) ==
1522 (PROTECTED_SACL_SECURITY_INFORMATION
| UNPROTECTED_SACL_SECURITY_INFORMATION
)))
1524 ErrorCode
= ERROR_INVALID_PARAMETER
;
1528 /* call the MARTA provider */
1529 ErrorCode
= AccTreeResetNamedSecurityInfo(pObjectName
,
1538 ProgressInvokeSetting
,
1544 /* object type not supported */
1545 ErrorCode
= ERROR_INVALID_PARAMETER
;
1551 ErrorCode
= ERROR_INVALID_PARAMETER
;
1556 #ifdef HAS_FN_PROGRESSW
1558 typedef struct _INERNAL_FNPROGRESSW_DATA
1560 FN_PROGRESSA fnProgress
;
1562 } INERNAL_FNPROGRESSW_DATA
, *PINERNAL_FNPROGRESSW_DATA
;
1565 InternalfnProgressW(LPWSTR pObjectName
,
1567 PPROG_INVOKE_SETTING pInvokeSetting
,
1571 PINERNAL_FNPROGRESSW_DATA pifnProgressData
= (PINERNAL_FNPROGRESSW_DATA
)Args
;
1575 ObjectNameSize
= WideCharToMultiByte(CP_ACP
,
1584 if (ObjectNameSize
> 0)
1586 pObjectNameA
= RtlAllocateHeap(RtlGetProcessHeap(),
1589 if (pObjectNameA
!= NULL
)
1591 pObjectNameA
[0] = '\0';
1592 WideCharToMultiByte(CP_ACP
,
1601 pifnProgressData
->fnProgress((LPWSTR
)pObjectNameA
, /* FIXME: wrong cast!! */
1604 pifnProgressData
->Args
,
1607 RtlFreeHeap(RtlGetProcessHeap(),
1621 TreeResetNamedSecurityInfoA(LPSTR pObjectName
,
1622 SE_OBJECT_TYPE ObjectType
,
1623 SECURITY_INFORMATION SecurityInfo
,
1629 FN_PROGRESSA fnProgress
,
1630 PROG_INVOKE_SETTING ProgressInvokeSetting
,
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
;
1638 INERNAL_FNPROGRESSW_DATA ifnProgressData
;
1639 UNICODE_STRING ObjectName
;
1642 if (!RtlCreateUnicodeStringFromAsciiz(&ObjectName
, pObjectName
))
1644 return ERROR_NOT_ENOUGH_MEMORY
;
1647 ifnProgressData
.fnProgress
= fnProgress
;
1648 ifnProgressData
.Args
= Args
;
1650 Ret
= TreeResetNamedSecurityInfoW(ObjectName
.Buffer
,
1658 (fnProgress
!= NULL
? InternalfnProgressW
: NULL
),
1659 ProgressInvokeSetting
,
1662 RtlFreeUnicodeString(&ObjectName
);