3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/advapi32/sec/ac.c
6 * PURPOSE: ACL/ACE functions
10 #include <wine/debug.h>
12 WINE_DEFAULT_DEBUG_CHANNEL(advapi
);
21 GetAclInformation(PACL pAcl
,
22 LPVOID pAclInformation
,
23 DWORD nAclInformationLength
,
24 ACL_INFORMATION_CLASS dwAclInformationClass
)
28 Status
= RtlQueryInformationAcl(pAcl
,
30 nAclInformationLength
,
31 dwAclInformationClass
);
32 if (!NT_SUCCESS(Status
))
34 SetLastError(RtlNtStatusToDosError(Status
));
47 InitializeAcl(PACL pAcl
,
53 Status
= RtlCreateAcl(pAcl
,
56 if (!NT_SUCCESS(Status
))
58 SetLastError(RtlNtStatusToDosError(Status
));
73 return RtlValidAcl (pAcl
);
82 SetAclInformation(PACL pAcl
,
83 LPVOID pAclInformation
,
84 DWORD nAclInformationLength
,
85 ACL_INFORMATION_CLASS dwAclInformationClass
)
89 Status
= RtlSetInformationAcl(pAcl
,
91 nAclInformationLength
,
92 dwAclInformationClass
);
93 if (!NT_SUCCESS(Status
))
95 SetLastError(RtlNtStatusToDosError(Status
));
110 AddAccessAllowedAce(PACL pAcl
,
117 Status
= RtlAddAccessAllowedAce(pAcl
,
121 if (!NT_SUCCESS(Status
))
123 SetLastError(RtlNtStatusToDosError(Status
));
135 AddAccessAllowedAceEx(PACL pAcl
,
143 Status
= RtlAddAccessAllowedAceEx(pAcl
,
148 if (!NT_SUCCESS(Status
))
150 SetLastError(RtlNtStatusToDosError(Status
));
163 AddAccessAllowedObjectAce(PACL pAcl
,
167 GUID
*ObjectTypeGuid
,
168 GUID
*InheritedObjectTypeGuid
,
173 Status
= RtlAddAccessAllowedObjectAce(pAcl
,
178 InheritedObjectTypeGuid
,
180 if (!NT_SUCCESS(Status
))
182 SetLastError(RtlNtStatusToDosError(Status
));
195 AddAccessDeniedAce(PACL pAcl
,
202 Status
= RtlAddAccessDeniedAce(pAcl
,
206 if (!NT_SUCCESS(Status
))
208 SetLastError(RtlNtStatusToDosError(Status
));
220 AddAccessDeniedAceEx(PACL pAcl
,
228 Status
= RtlAddAccessDeniedAceEx(pAcl
,
233 if (!NT_SUCCESS(Status
))
235 SetLastError(RtlNtStatusToDosError(Status
));
248 AddAccessDeniedObjectAce(PACL pAcl
,
252 GUID
* ObjectTypeGuid
,
253 GUID
* InheritedObjectTypeGuid
,
258 Status
= RtlAddAccessDeniedObjectAce(pAcl
,
263 InheritedObjectTypeGuid
,
265 if (!NT_SUCCESS(Status
))
267 SetLastError(RtlNtStatusToDosError(Status
));
282 DWORD dwStartingAceIndex
,
284 DWORD nAceListLength
)
288 Status
= RtlAddAce(pAcl
,
293 if (!NT_SUCCESS(Status
))
295 SetLastError(RtlNtStatusToDosError(Status
));
308 AddAuditAccessAce(PACL pAcl
,
317 Status
= RtlAddAuditAccessAce(pAcl
,
323 if (!NT_SUCCESS(Status
))
325 SetLastError(RtlNtStatusToDosError(Status
));
337 AddAuditAccessAceEx(PACL pAcl
,
347 Status
= RtlAddAuditAccessAceEx(pAcl
,
354 if (!NT_SUCCESS(Status
))
356 SetLastError(RtlNtStatusToDosError(Status
));
369 AddAuditAccessObjectAce(PACL pAcl
,
373 GUID
*ObjectTypeGuid
,
374 GUID
*InheritedObjectTypeGuid
,
381 Status
= RtlAddAuditAccessObjectAce(pAcl
,
386 InheritedObjectTypeGuid
,
390 if (!NT_SUCCESS(Status
))
392 SetLastError(RtlNtStatusToDosError(Status
));
405 AddMandatoryAce(IN OUT PACL pAcl
,
406 IN DWORD dwAceRevision
,
408 IN DWORD MandatoryPolicy
,
413 Status
= RtlAddMandatoryAce(pAcl
,
417 SYSTEM_MANDATORY_LABEL_ACE_TYPE
,
419 if (!NT_SUCCESS(Status
))
421 SetLastError(RtlNtStatusToDosError(Status
));
439 Status
= RtlDeleteAce(pAcl
,
441 if (!NT_SUCCESS(Status
))
443 SetLastError(RtlNtStatusToDosError(Status
));
456 FindFirstFreeAce(PACL pAcl
,
459 return RtlFirstFreeAce(pAcl
,
475 Status
= RtlGetAce(pAcl
,
478 if (!NT_SUCCESS(Status
))
480 SetLastError(RtlNtStatusToDosError(Status
));
493 GetInheritanceSourceW(LPWSTR pObjectName
,
494 SE_OBJECT_TYPE ObjectType
,
495 SECURITY_INFORMATION SecurityInfo
,
497 GUID
**pObjectClassGuids OPTIONAL
,
500 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL
,
501 PGENERIC_MAPPING pGenericMapping
,
502 PINHERITED_FROMW pInheritArray
)
506 ErrorCode
= CheckNtMartaPresent();
507 if (ErrorCode
== ERROR_SUCCESS
)
509 /* call the MARTA provider */
510 ErrorCode
= AccGetInheritanceSource(pObjectName
,
531 GetInheritanceSourceA(LPSTR pObjectName
,
532 SE_OBJECT_TYPE ObjectType
,
533 SECURITY_INFORMATION SecurityInfo
,
535 GUID
**pObjectClassGuids OPTIONAL
,
538 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL
,
539 PGENERIC_MAPPING pGenericMapping
,
540 PINHERITED_FROMA pInheritArray
)
542 /* That's all this function does, at least up to w2k3... Even MS was too
543 lazy to implement it... */
544 return ERROR_CALL_NOT_IMPLEMENTED
;
553 FreeInheritedFromArray(PINHERITED_FROMW pInheritArray
,
555 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL
)
559 ErrorCode
= CheckNtMartaPresent();
560 if (ErrorCode
== ERROR_SUCCESS
)
562 /* call the MARTA provider */
563 ErrorCode
= AccFreeIndexArray(pInheritArray
,
577 SetEntriesInAclW(ULONG cCountOfExplicitEntries
,
578 PEXPLICIT_ACCESS_W pListOfExplicitEntries
,
586 return ERROR_INVALID_PARAMETER
;
589 ErrorCode
= CheckNtMartaPresent();
590 if (ErrorCode
== ERROR_SUCCESS
)
592 /* call the MARTA provider */
593 ErrorCode
= AccRewriteSetEntriesInAcl(cCountOfExplicitEntries
,
594 pListOfExplicitEntries
,
604 InternalTrusteeAToW(IN PTRUSTEE_A pTrusteeA
,
605 OUT PTRUSTEE_W
*pTrusteeW
)
607 TRUSTEE_FORM TrusteeForm
;
610 DWORD ErrorCode
= ERROR_SUCCESS
;
612 //ASSERT(sizeof(TRUSTEE_W) == sizeof(TRUSTEE_A));
614 TrusteeForm
= GetTrusteeFormA(pTrusteeA
);
617 case TRUSTEE_IS_NAME
:
619 /* directly copy the array, this works as the size of the EXPLICIT_ACCESS_A
620 structure matches the size of the EXPLICIT_ACCESS_W version */
621 lpStr
= GetTrusteeNameA(pTrusteeA
);
623 BufferSize
= strlen(lpStr
) + 1;
625 *pTrusteeW
= RtlAllocateHeap(RtlGetProcessHeap(),
627 sizeof(TRUSTEE_W
) + (BufferSize
* sizeof(WCHAR
)));
628 if (*pTrusteeW
!= NULL
)
630 RtlCopyMemory(*pTrusteeW
,
632 FIELD_OFFSET(TRUSTEE_A
,
637 (*pTrusteeW
)->ptstrName
= (PWSTR
)((*pTrusteeW
) + 1);
639 /* convert the trustee's name */
640 if (MultiByteToWideChar(CP_ACP
,
644 (*pTrusteeW
)->ptstrName
,
652 RtlFreeHeap(RtlGetProcessHeap(),
655 goto NothingToConvert
;
659 ErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
663 case TRUSTEE_IS_OBJECTS_AND_NAME
:
665 POBJECTS_AND_NAME_A oanA
= (POBJECTS_AND_NAME_A
)GetTrusteeNameA(pTrusteeA
);
666 POBJECTS_AND_NAME_W oan
;
669 /* calculate the size needed */
670 if ((oanA
->ObjectsPresent
& ACE_INHERITED_OBJECT_TYPE_PRESENT
) &&
671 oanA
->InheritedObjectTypeName
!= NULL
)
673 BufferSize
= strlen(oanA
->InheritedObjectTypeName
) + 1;
675 if (oanA
->ptstrName
!= NULL
)
677 BufferSize
+= strlen(oanA
->ptstrName
) + 1;
680 *pTrusteeW
= RtlAllocateHeap(RtlGetProcessHeap(),
682 sizeof(TRUSTEE_W
) + sizeof(OBJECTS_AND_NAME_W
) +
683 (BufferSize
* sizeof(WCHAR
)));
685 if (*pTrusteeW
!= NULL
)
687 oan
= (POBJECTS_AND_NAME_W
)((*pTrusteeW
) + 1);
688 StrBuf
= (PWSTR
)(oan
+ 1);
690 /* copy over the parts of the TRUSTEE structure that don't need
692 RtlCopyMemory(*pTrusteeW
,
694 FIELD_OFFSET(TRUSTEE_A
,
697 (*pTrusteeW
)->ptstrName
= (LPWSTR
)oan
;
699 /* convert the OBJECTS_AND_NAME_A structure */
700 oan
->ObjectsPresent
= oanA
->ObjectsPresent
;
701 oan
->ObjectType
= oanA
->ObjectType
;
703 if ((oanA
->ObjectsPresent
& ACE_INHERITED_OBJECT_TYPE_PRESENT
) &&
704 oanA
->InheritedObjectTypeName
!= NULL
)
706 /* convert inherited object type name */
707 BufferSize
= strlen(oanA
->InheritedObjectTypeName
) + 1;
709 if (MultiByteToWideChar(CP_ACP
,
711 oanA
->InheritedObjectTypeName
,
718 oan
->InheritedObjectTypeName
= StrBuf
;
720 StrBuf
+= BufferSize
;
723 oan
->InheritedObjectTypeName
= NULL
;
725 if (oanA
->ptstrName
!= NULL
)
727 /* convert the trustee name */
728 BufferSize
= strlen(oanA
->ptstrName
) + 1;
730 if (MultiByteToWideChar(CP_ACP
,
739 oan
->ptstrName
= StrBuf
;
742 oan
->ptstrName
= NULL
;
745 ErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
752 /* no need to convert anything to unicode */
753 *pTrusteeW
= (PTRUSTEE_W
)pTrusteeA
;
761 ErrorCode
= GetLastError();
764 RtlFreeHeap(RtlGetProcessHeap(),
773 InternalFreeConvertedTrustee(IN PTRUSTEE_W pTrusteeW
,
774 IN PTRUSTEE_A pTrusteeA
)
776 if ((PVOID
)pTrusteeW
!= (PVOID
)pTrusteeA
)
778 RtlFreeHeap(RtlGetProcessHeap(),
786 InternalExplicitAccessAToW(IN ULONG cCountOfExplicitEntries
,
787 IN PEXPLICIT_ACCESS_A pListOfExplicitEntriesA
,
788 OUT PEXPLICIT_ACCESS_W
*pListOfExplicitEntriesW
)
790 TRUSTEE_FORM TrusteeForm
;
793 ULONG ObjectsAndNameCount
= 0;
794 PEXPLICIT_ACCESS_W peaw
= NULL
;
795 DWORD ErrorCode
= ERROR_SUCCESS
;
798 /* NOTE: This code assumes that the size of the TRUSTEE_A and TRUSTEE_W structure matches! */
799 //ASSERT(sizeof(TRUSTEE_A) == sizeof(TRUSTEE_W));
801 if (cCountOfExplicitEntries
!= 0)
803 /* calculate the size needed */
804 Size
= cCountOfExplicitEntries
* sizeof(EXPLICIT_ACCESS_W
);
805 for (i
= 0; i
!= cCountOfExplicitEntries
; i
++)
807 TrusteeForm
= GetTrusteeFormA(&pListOfExplicitEntriesA
[i
].Trustee
);
811 case TRUSTEE_IS_NAME
:
813 lpStr
= GetTrusteeNameA(&pListOfExplicitEntriesA
[i
].Trustee
);
815 Size
+= (strlen(lpStr
) + 1) * sizeof(WCHAR
);
819 case TRUSTEE_IS_OBJECTS_AND_NAME
:
821 POBJECTS_AND_NAME_A oan
= (POBJECTS_AND_NAME_A
)GetTrusteeNameA(&pListOfExplicitEntriesA
[i
].Trustee
);
823 if ((oan
->ObjectsPresent
& ACE_INHERITED_OBJECT_TYPE_PRESENT
) &&
824 oan
->InheritedObjectTypeName
!= NULL
)
826 Size
+= (strlen(oan
->InheritedObjectTypeName
) + 1) * sizeof(WCHAR
);
829 if (oan
->ptstrName
!= NULL
)
830 Size
+= (strlen(oan
->ptstrName
) + 1) * sizeof(WCHAR
);
832 ObjectsAndNameCount
++;
841 /* allocate the array */
842 peaw
= RtlAllocateHeap(RtlGetProcessHeap(),
848 POBJECTS_AND_NAME_W oan
= (POBJECTS_AND_NAME_W
)(peaw
+ cCountOfExplicitEntries
);
849 LPWSTR StrBuf
= (LPWSTR
)(oan
+ ObjectsAndNameCount
);
851 /* convert the array to unicode */
852 for (i
= 0; i
!= cCountOfExplicitEntries
; i
++)
854 peaw
[i
].grfAccessPermissions
= pListOfExplicitEntriesA
[i
].grfAccessPermissions
;
855 peaw
[i
].grfAccessMode
= pListOfExplicitEntriesA
[i
].grfAccessMode
;
856 peaw
[i
].grfInheritance
= pListOfExplicitEntriesA
[i
].grfInheritance
;
858 /* convert or copy the TRUSTEE structure */
859 TrusteeForm
= GetTrusteeFormA(&pListOfExplicitEntriesA
[i
].Trustee
);
862 case TRUSTEE_IS_NAME
:
864 lpStr
= GetTrusteeNameA(&pListOfExplicitEntriesA
[i
].Trustee
);
867 /* convert the trustee name */
868 BufferSize
= strlen(lpStr
) + 1;
870 if (MultiByteToWideChar(CP_ACP
,
879 peaw
[i
].Trustee
.ptstrName
= StrBuf
;
881 StrBuf
+= BufferSize
;
889 case TRUSTEE_IS_OBJECTS_AND_NAME
:
891 POBJECTS_AND_NAME_A oanA
= (POBJECTS_AND_NAME_A
)GetTrusteeNameA(&pListOfExplicitEntriesA
[i
].Trustee
);
893 /* copy over the parts of the TRUSTEE structure that don't need
895 RtlCopyMemory(&peaw
[i
].Trustee
,
896 &pListOfExplicitEntriesA
[i
].Trustee
,
897 FIELD_OFFSET(TRUSTEE_A
,
900 peaw
[i
].Trustee
.ptstrName
= (LPWSTR
)oan
;
902 /* convert the OBJECTS_AND_NAME_A structure */
903 oan
->ObjectsPresent
= oanA
->ObjectsPresent
;
904 oan
->ObjectType
= oanA
->ObjectType
;
906 if ((oanA
->ObjectsPresent
& ACE_INHERITED_OBJECT_TYPE_PRESENT
) &&
907 oanA
->InheritedObjectTypeName
!= NULL
)
909 /* convert inherited object type name */
910 BufferSize
= strlen(oanA
->InheritedObjectTypeName
) + 1;
912 if (MultiByteToWideChar(CP_ACP
,
914 oanA
->InheritedObjectTypeName
,
921 oan
->InheritedObjectTypeName
= StrBuf
;
923 StrBuf
+= BufferSize
;
926 oan
->InheritedObjectTypeName
= NULL
;
928 if (oanA
->ptstrName
!= NULL
)
930 /* convert the trustee name */
931 BufferSize
= strlen(oanA
->ptstrName
) + 1;
933 if (MultiByteToWideChar(CP_ACP
,
942 oan
->ptstrName
= StrBuf
;
944 StrBuf
+= BufferSize
;
947 oan
->ptstrName
= NULL
;
949 /* move on to the next OBJECTS_AND_NAME_A structure */
957 /* just copy over the TRUSTEE structure, they don't contain any
958 ansi/unicode specific data */
959 RtlCopyMemory(&peaw
[i
].Trustee
,
960 &pListOfExplicitEntriesA
[i
].Trustee
,
967 ASSERT(ErrorCode
== ERROR_SUCCESS
);
968 *pListOfExplicitEntriesW
= peaw
;
971 ErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
977 ErrorCode
= GetLastError();
980 RtlFreeHeap(RtlGetProcessHeap(),
993 SetEntriesInAclA(ULONG cCountOfExplicitEntries
,
994 PEXPLICIT_ACCESS_A pListOfExplicitEntries
,
998 PEXPLICIT_ACCESS_W ListOfExplicitEntriesW
= NULL
;
1001 ErrorCode
= InternalExplicitAccessAToW(cCountOfExplicitEntries
,
1002 pListOfExplicitEntries
,
1003 &ListOfExplicitEntriesW
);
1004 if (ErrorCode
== ERROR_SUCCESS
)
1006 ErrorCode
= SetEntriesInAclW(cCountOfExplicitEntries
,
1007 ListOfExplicitEntriesW
,
1011 /* free the allocated array */
1012 RtlFreeHeap(RtlGetProcessHeap(),
1014 ListOfExplicitEntriesW
);
1026 GetExplicitEntriesFromAclW(PACL pacl
,
1027 PULONG pcCountOfExplicitEntries
,
1028 PEXPLICIT_ACCESS_W
*pListOfExplicitEntries
)
1032 ErrorCode
= CheckNtMartaPresent();
1033 if (ErrorCode
== ERROR_SUCCESS
)
1035 /* call the MARTA provider */
1036 ErrorCode
= AccRewriteGetExplicitEntriesFromAcl(pacl
,
1037 pcCountOfExplicitEntries
,
1038 pListOfExplicitEntries
);
1050 GetEffectiveRightsFromAclW(IN PACL pacl
,
1051 IN PTRUSTEE_W pTrustee
,
1052 OUT PACCESS_MASK pAccessRights
)
1054 FIXME("%s() not implemented!\n", __FUNCTION__
);
1055 return ERROR_CALL_NOT_IMPLEMENTED
;
1064 GetEffectiveRightsFromAclA(IN PACL pacl
,
1065 IN PTRUSTEE_A pTrustee
,
1066 OUT PACCESS_MASK pAccessRights
)
1068 PTRUSTEE_W pTrusteeW
= NULL
;
1071 ErrorCode
= InternalTrusteeAToW(pTrustee
,
1073 if (ErrorCode
== ERROR_SUCCESS
)
1075 ErrorCode
= GetEffectiveRightsFromAclW(pacl
,
1079 InternalFreeConvertedTrustee(pTrusteeW
,
1083 ErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
1094 GetAuditedPermissionsFromAclW(IN PACL pacl
,
1095 IN PTRUSTEE_W pTrustee
,
1096 OUT PACCESS_MASK pSuccessfulAuditedRights
,
1097 OUT PACCESS_MASK pFailedAuditRights
)
1099 FIXME("%s() not implemented!\n", __FUNCTION__
);
1100 return ERROR_CALL_NOT_IMPLEMENTED
;
1109 GetAuditedPermissionsFromAclA(IN PACL pacl
,
1110 IN PTRUSTEE_A pTrustee
,
1111 OUT PACCESS_MASK pSuccessfulAuditedRights
,
1112 OUT PACCESS_MASK pFailedAuditRights
)
1114 PTRUSTEE_W pTrusteeW
= NULL
;
1117 ErrorCode
= InternalTrusteeAToW(pTrustee
,
1119 if (ErrorCode
== ERROR_SUCCESS
)
1121 ErrorCode
= GetAuditedPermissionsFromAclW(pacl
,
1123 pSuccessfulAuditedRights
,
1124 pFailedAuditRights
);
1126 InternalFreeConvertedTrustee(pTrusteeW
,
1130 ErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;