@@ -391,7 +391,7 @@ public static NtResult<AccessCheckResult> AccessCheck(SecurityDescriptor sd, NtT
391391
392392 if ( desired_access . IsEmpty )
393393 {
394- return new AccessCheckResult ( NtStatus . STATUS_ACCESS_DENIED , 0 , null ) . CreateResult ( ) ;
394+ return new AccessCheckResult ( NtStatus . STATUS_ACCESS_DENIED , 0 , null , generic_mapping ) . CreateResult ( ) ;
395395 }
396396
397397 using ( var list = new DisposableList ( ) )
@@ -404,19 +404,19 @@ public static NtResult<AccessCheckResult> AccessCheck(SecurityDescriptor sd, NtT
404404 }
405405 var self_sid = list . AddResource ( principal ? . ToSafeBuffer ( ) ?? SafeSidBufferHandle . Null ) ;
406406 var privs = list . AddResource ( new SafePrivilegeSetBuffer ( ) ) ;
407- var object_type_list = list . AddResource ( ConvertObjectTypes ( object_types ) ) ;
407+ var object_type_list = ConvertObjectTypes ( object_types , list ) ;
408408 int repeat_count = 1 ;
409409
410410 while ( true )
411411 {
412412 int buffer_length = privs . Length ;
413413 NtStatus status = NtSystemCalls . NtAccessCheckByType ( sd_buffer , self_sid , imp_token . Result . Handle , desired_access ,
414- object_type_list , 0 , ref generic_mapping , privs ,
414+ object_type_list , object_type_list ? . Length ?? 0 , ref generic_mapping , privs ,
415415 ref buffer_length , out AccessMask granted_access , out NtStatus result_status ) ;
416416 if ( repeat_count == 0 || status != NtStatus . STATUS_BUFFER_TOO_SMALL )
417417 {
418418 return status . CreateResult ( throw_on_error , ( )
419- => new AccessCheckResult ( result_status , granted_access , privs ) ) ;
419+ => new AccessCheckResult ( result_status , granted_access , privs , generic_mapping ) ) ;
420420 }
421421
422422 repeat_count -- ;
@@ -425,6 +425,26 @@ public static NtResult<AccessCheckResult> AccessCheck(SecurityDescriptor sd, NtT
425425 }
426426 }
427427
428+ /// <summary>
429+ /// Do an access check between a security descriptor and a token to determine the allowed access.
430+ /// </summary>
431+ /// <param name="sd">The security descriptor</param>
432+ /// <param name="token">The access token.</param>
433+ /// <param name="desired_access">The set of access rights to check against</param>
434+ /// <param name="principal">An optional principal SID used to replace the SELF SID in a security descriptor.</param>
435+ /// <param name="generic_mapping">The type specific generic mapping (get from corresponding NtType entry).</param>
436+ /// <param name="object_types">List of object types to check against.</param>
437+ /// <param name="throw_on_error">True to throw on error.</param>
438+ /// <returns>The result of the access check.</returns>
439+ /// <exception cref="NtException">Thrown if an error occurred in the access check.</exception>
440+ public static NtResult < AccessCheckResult < T > > AccessCheck < T > ( SecurityDescriptor sd , NtToken token ,
441+ T desired_access , Sid principal , GenericMapping generic_mapping , IEnumerable < ObjectTypeEntry > object_types ,
442+ bool throw_on_error ) where T : Enum
443+ {
444+ return AccessCheck ( sd , token , ( AccessMask ) desired_access , principal ,
445+ generic_mapping , object_types , throw_on_error ) . Map ( r => r . ToSpecificAccess < T > ( ) ) ;
446+ }
447+
428448 /// <summary>
429449 /// Do an access check between a security descriptor and a token to determine the allowed access.
430450 /// </summary>
@@ -443,6 +463,24 @@ public static NtResult<AccessCheckResult> AccessCheck(SecurityDescriptor sd, NtT
443463 return AccessCheck ( sd , token , desired_access , principal , generic_mapping , null , throw_on_error ) ;
444464 }
445465
466+ /// <summary>
467+ /// Do an access check between a security descriptor and a token to determine the allowed access.
468+ /// </summary>
469+ /// <param name="sd">The security descriptor</param>
470+ /// <param name="token">The access token.</param>
471+ /// <param name="desired_access">The set of access rights to check against</param>
472+ /// <param name="principal">An optional principal SID used to replace the SELF SID in a security descriptor.</param>
473+ /// <param name="generic_mapping">The type specific generic mapping (get from corresponding NtType entry).</param>
474+ /// <param name="throw_on_error">True to throw on error.</param>
475+ /// <returns>The result of the access check.</returns>
476+ /// <exception cref="NtException">Thrown if an error occurred in the access check.</exception>
477+ public static NtResult < AccessCheckResult < T > > AccessCheck < T > ( SecurityDescriptor sd , NtToken token ,
478+ T desired_access , Sid principal , GenericMapping generic_mapping ,
479+ bool throw_on_error ) where T : Enum
480+ {
481+ return AccessCheck ( sd , token , desired_access , principal , generic_mapping , null , throw_on_error ) ;
482+ }
483+
446484 /// <summary>
447485 /// Do an access check between a security descriptor and a token to determine the allowed access.
448486 /// </summary>
@@ -459,6 +497,22 @@ public static AccessCheckResult AccessCheck(SecurityDescriptor sd, NtToken token
459497 return AccessCheck ( sd , token , desired_access , principal , generic_mapping , true ) . Result ;
460498 }
461499
500+ /// <summary>
501+ /// Do an access check between a security descriptor and a token to determine the allowed access.
502+ /// </summary>
503+ /// <param name="sd">The security descriptor</param>
504+ /// <param name="token">The access token.</param>
505+ /// <param name="desired_access">The set of access rights to check against</param>
506+ /// <param name="principal">An optional principal SID used to replace the SELF SID in a security descriptor.</param>
507+ /// <param name="generic_mapping">The type specific generic mapping (get from corresponding NtType entry).</param>
508+ /// <returns>The result of the access check.</returns>
509+ /// <exception cref="NtException">Thrown if an error occurred in the access check.</exception>
510+ public static AccessCheckResult < T > AccessCheck < T > ( SecurityDescriptor sd , NtToken token ,
511+ T desired_access , Sid principal , GenericMapping generic_mapping ) where T : Enum
512+ {
513+ return AccessCheck ( sd , token , desired_access , principal , generic_mapping , true ) . Result ;
514+ }
515+
462516 /// <summary>
463517 /// Do an access check between a security descriptor and a token to determine the allowed access.
464518 /// </summary>
@@ -1232,26 +1286,12 @@ private static NtResult<NtToken> DuplicateForAccessCheck(NtToken token, bool thr
12321286 }
12331287 }
12341288
1235- private static SafeArrayBuffer < ObjectTypeList > ConvertObjectTypes ( IEnumerable < ObjectTypeEntry > object_types )
1289+ private static ObjectTypeList [ ] ConvertObjectTypes ( IEnumerable < ObjectTypeEntry > object_types , DisposableList list )
12361290 {
12371291 if ( object_types == null || ! object_types . Any ( ) )
1238- return SafeArrayBuffer < ObjectTypeList > . Null ;
1292+ return null ;
12391293
1240- var guids = object_types . Select ( o => o . ObjectType ) . ToArray ( ) ;
1241- var ret = new SafeArrayBuffer < ObjectTypeList > ( new ObjectTypeList [ guids . Length ] , guids . Length * 16 ) ;
1242- try
1243- {
1244- IntPtr ptr = ret . Data . DangerousGetHandle ( ) ;
1245- var arr = object_types . Select ( ( t , i ) => new ObjectTypeList ( ) { Level = ( short ) t . Level , ObjectType = ptr + ( i * 16 ) } ) . ToArray ( ) ;
1246- ret . WriteArray ( 0 , arr , 0 , arr . Length ) ;
1247- ret . Data . WriteArray ( 0 , guids , 0 , guids . Length ) ;
1248- return ret ;
1249- }
1250- catch
1251- {
1252- ret ? . Dispose ( ) ;
1253- throw ;
1254- }
1294+ return object_types . Select ( o => o . ToStruct ( list ) ) . ToArray ( ) ;
12551295 }
12561296
12571297 private static CachedSigningLevelEaBuffer ReadCachedSigningLevelVersion1 ( BinaryReader reader )
0 commit comments