1

特定のユーザーがフォルダーに対して特定の権限を持っているかどうかを通知する関数を作成しようとしています。これまでのところ、ここでこれを行う方法の例を見つけたので、このコードをデルファイで記述しようとしました。

unit SysCommonUnit;

interface

uses
  SysUtils,
  Classes,
  System.Math,
  Winapi.Windows,
  WinTypes;

const
  NERR_SUCCESS                     = 0;
  MAX_NR_USERS                     = 1000;
  FILTER_TEMP_DUPLICATE_ACCOUNT    = $0001;
  FILTER_NORMAL_ACCOUNT            = $0002;
  FILTER_PROXY_ACCOUNT             = $0004;
  FILTER_INTERDOMAIN_TRUST_ACCOUNT = $0008;
  FILTER_WORKSTATION_TRUST_ACCOUNT = $0010;
  FILTER_SERVER_TRUST_ACCOUNT      = $0020;

  AUTHZ_RM_FLAG_NO_AUDIT    = $1;
  {$EXTERNALSYM AUTHZ_RM_FLAG_NO_AUDIT}

  FILE_READ_DATA            = $0001; // file & pipe
  FILE_LIST_DIRECTORY       = $0001; // directory
  FILE_WRITE_DATA           = $0002; // file & pipe
  FILE_ADD_FILE             = $0002; // directory
  FILE_APPEND_DATA          = $0004; // file
  FILE_ADD_SUBDIRECTORY     = $0004; // directory
  FILE_CREATE_PIPE_INSTANCE = $0004; // named pipe
  FILE_READ_EA              = $0008; // file & directory
  FILE_WRITE_EA             = $0010; // file & directory
  FILE_EXECUTE              = $0020; // file
  FILE_TRAVERSE             = $0020; // directory
  FILE_DELETE_CHILD         = $0040; // directory
  FILE_READ_ATTRIBUTES      = $0080; // all
  FILE_WRITE_ATTRIBUTES     = $0100; // all

  FILE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or
                    SYNCHRONIZE or
                    $1FF;

  FILE_GENERIC_READ = STANDARD_RIGHTS_READ or
                      FILE_READ_DATA or
                      FILE_READ_ATTRIBUTES or
                      FILE_READ_EA or
                      SYNCHRONIZE;

  FILE_GENERIC_WRITE =  STANDARD_RIGHTS_WRITE or
                        FILE_WRITE_DATA or
                        FILE_WRITE_ATTRIBUTES or
                        FILE_WRITE_EA or
                        FILE_APPEND_DATA or
                        SYNCHRONIZE;

  FILE_GENERIC_EXECUTE =  STANDARD_RIGHTS_EXECUTE or
                          FILE_READ_ATTRIBUTES or
                          FILE_EXECUTE or
                          SYNCHRONIZE;

type
  ACE_HEADER = record
    AceType: BYTE;
    AceFlags: BYTE;
    AceSize: WORD;
  end;

  PPSECURITY_DESCRIPTOR = ^PSECURITY_DESCRIPTOR;

  PACE_HEADER = ^ACE_HEADER;

  PAUTHZ_ACCESS_REQUEST = ^AUTHZ_ACCESS_REQUEST;

  POBJECT_TYPE_LIST = ^OBJECT_TYPE_LIST;

  _OBJECT_TYPE_LIST = record
    Level: WORD;
    Sbz: WORD;
    ObjectType: PGUID;
  end;

  OBJECT_TYPE_LIST = _OBJECT_TYPE_LIST;

  TObjectTypeList = OBJECT_TYPE_LIST;
  PObjectTypeList = POBJECT_TYPE_LIST;

  _AUTHZ_ACCESS_REQUEST = record
    DesiredAccess: ACCESS_MASK;
    PrincipalSelfSid: PSID;
    ObjectTypeList: POBJECT_TYPE_LIST;
    ObjectTypeListLength: DWORD;
    OptionalArguments: PVOID;
  end;

  AUTHZ_ACCESS_REQUEST = _AUTHZ_ACCESS_REQUEST;

  TAuthzAccessRequest = AUTHZ_ACCESS_REQUEST;
  PAuthzAccessRequest = PAUTHZ_ACCESS_REQUEST;

  PAUTHZ_ACCESS_REPLY = ^AUTHZ_ACCESS_REPLY;

  _AUTHZ_ACCESS_REPLY = record
    ResultListLength: DWORD;
    GrantedAccessMask: PACCESS_MASK;
    SaclEvaluationResults: PDWORD;
    Error: PDWORD;
  end;

  AUTHZ_ACCESS_REPLY = _AUTHZ_ACCESS_REPLY;

  TAuthzAccessReply = AUTHZ_ACCESS_REPLY;
  PAuthzAccessReply = PAUTHZ_ACCESS_REPLY;

  TCHAR = char;

  AUTHZ_RESOURCE_MANAGER_HANDLE = THANDLE;

  AUTHZ_CLIENT_CONTEXT_HANDLE = THANDLE;

  AUTHZ_AUDIT_EVENT_HANDLE = THANDLE;

  PAUTHZ_RESOURCE_MANAGER_HANDLE = ^AUTHZ_RESOURCE_MANAGER_HANDLE;

  PAUTHZ_CLIENT_CONTEXT_HANDLE = ^AUTHZ_CLIENT_CONTEXT_HANDLE;

  PFN_AUTHZ_DYNAMIC_ACCESS_CHECK = function(hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE;
                                            pAce: PACE_HEADER;
                                            pArgs: PVOID;
                                            var pbAceApplicable: BOOL): BOOL; stdcall;

  PFnAuthzDynamicAccessCheck = PFN_AUTHZ_DYNAMIC_ACCESS_CHECK;

  PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS = function(hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE;
                                              Args: PVOID;
                                              var pSidAttrArray: PSIDAndAttributes;
                                              var pSidCount: DWORD;
                                              var pRestrictedSidAttrArray: PSIDAndAttributes;
                                              var pRestrictedSidCount: DWORD): BOOL; stdcall;

  PFnAuthzComputeDynamicGroups = PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS;

  PFN_AUTHZ_FREE_DYNAMIC_GROUPS = procedure(pSidAttrArray: PSIDAndAttributes); stdcall;

  PFnAuthzFreeDynamicGroups = PFN_AUTHZ_FREE_DYNAMIC_GROUPS;

  AUTHZ_ACCESS_CHECK_RESULTS_HANDLE = THANDLE;

  PAUTHZ_ACCESS_CHECK_RESULTS_HANDLE = ^AUTHZ_ACCESS_CHECK_RESULTS_HANDLE;


  SE_OBJECT_TYPE = (SE_UNKNOWN_OBJECT_TYPE,
                    SE_FILE_OBJECT,
                    SE_SERVICE,
                    SE_PRINTER,
                    SE_REGISTRY_KEY,
                    SE_LMSHARE,
                    SE_KERNEL_OBJECT,
                    SE_WINDOW_OBJECT,
                    SE_DS_OBJECT,
                    SE_DS_OBJECT_ALL,
                    SE_PROVIDER_DEFINED_OBJECT,
                    SE_WMIGUID_OBJECT);


function GetNamedSecurityInfoW( pObjectName: PWideChar;
                                ObjectType: SE_OBJECT_TYPE;
                                SecurityInfo: SECURITY_INFORMATION;
                                var ppSidOwner: PSID;
                                var ppSidGroup: PSID;
                                var ppDacl: PACL;
                                var ppSacl: PACL;
                                var ppSecurityDescriptor: PSECURITY_DESCRIPTOR): DWORD; stdcall; external 'Advapi32.dll';

function AuthzInitializeResourceManagerWrapper( nFlags: DWORD;
                                                pfnDynamicAccessCheck: PFN_AUTHZ_DYNAMIC_ACCESS_CHECK;
                                                pfnComputeDynamicGroups: PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS;
                                                pfnFreeDynamicGroups: PFN_AUTHZ_FREE_DYNAMIC_GROUPS;
                                                szResourceManagerName: string;
                                                var hAuthzResourceManager: AUTHZ_RESOURCE_MANAGER_HANDLE): Boolean;

function AuthzInitializeContextFromSidWrapper(Flags: DWORD;
                                              UserSid: PSID;
                                              hAuthzResourceManager: AUTHZ_RESOURCE_MANAGER_HANDLE;
                                              pExpirationTime: PLargeInteger;
                                              Identifier: LUID;
                                              DynamicGroupArgs: PVOID;
                                              var hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE): Boolean;

function AuthzFreeResourceManagerWrapper(hAuthzResourceManager: AUTHZ_RESOURCE_MANAGER_HANDLE): Boolean;

function AuthzFreeContextWrapper(hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE): Boolean;

function AuthzAccessCheckWrapper( Flags: DWORD;
                                  hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE;
                                  var pRequest: AUTHZ_ACCESS_REQUEST;
                                  hAuditEvent: AUTHZ_AUDIT_EVENT_HANDLE;
                                  var pSecurityDescriptor: SECURITY_DESCRIPTOR;
                                  var OptionalSecurityDescriptorArray: PSECURITY_DESCRIPTOR;
                                  OptionalSecurityDescriptorCount: DWORD;
                                  var pReply: AUTHZ_ACCESS_REPLY;
                                  var phAccessCheckResultsOPTIONAL: AUTHZ_ACCESS_CHECK_RESULTS_HANDLE): Boolean;

function ConvertUsernameToBinarySID(p_pAccountName: string): PSID;

function HasRightsForUser(p_hManager: AUTHZ_RESOURCE_MANAGER_HANDLE;
                          p_oPsd: PSECURITY_DESCRIPTOR;
                          p_sUsername: string;
                          p_nDesiredRights: DWORD): Boolean;

function HasAccess(p_hAuthzClient: AUTHZ_CLIENT_CONTEXT_HANDLE; p_oPsd: PSECURITY_DESCRIPTOR; p_nDesiredRights: DWORD): Boolean;

function HasAccessRights(p_nDesiredRights: Integer; p_sFileName: string; p_sUsername: string): Boolean;

implementation

function AuthzInitializeResourceManagerWrapper( nFlags: DWORD;
                                                pfnDynamicAccessCheck: PFN_AUTHZ_DYNAMIC_ACCESS_CHECK;
                                                pfnComputeDynamicGroups: PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS;
                                                pfnFreeDynamicGroups: PFN_AUTHZ_FREE_DYNAMIC_GROUPS;
                                                szResourceManagerName: string;
                                                var hAuthzResourceManager: AUTHZ_RESOURCE_MANAGER_HANDLE): Boolean;
var
  DLLHandle                       : THandle;
  wResourceManagerName            : array[0..1024] of Widechar;
  AuthzInitializeResourceManager  : function (nFlags: DWORD;
                                              pfnDynamicAccessCheck: PFN_AUTHZ_DYNAMIC_ACCESS_CHECK;
                                              pfnComputeDynamicGroups: PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS;
                                              pfnFreeDynamicGroups: PFN_AUTHZ_FREE_DYNAMIC_GROUPS;
                                              szResourceManagerName: PWideChar;
                                              phAuthzResourceManager: PAUTHZ_RESOURCE_MANAGER_HANDLE): BOOL; cdecl stdcall;
begin
  Result    := False;
  DLLHandle := LoadLibrary('authz.dll');
  if DLLHandle >= 32 then
  begin
    @AuthzInitializeResourceManager := GetProcAddress(DLLHandle, 'AuthzInitializeResourceManager');

    StringToWideChar(szResourceManagerName, wResourceManagerName, sizeof(wResourceManagerName));

    Result := AuthzInitializeResourceManager( nFlags,
                                              pfnDynamicAccessCheck,
                                              pfnComputeDynamicGroups,
                                              pfnFreeDynamicGroups,
                                              wResourceManagerName,
                                              @hAuthzResourceManager);
    FreeLibrary(DLLHandle);
  end;
end;

function AuthzInitializeContextFromSidWrapper(Flags: DWORD;
                                              UserSid: PSID;
                                              hAuthzResourceManager: AUTHZ_RESOURCE_MANAGER_HANDLE;
                                              pExpirationTime: PLargeInteger;
                                              Identifier: LUID;
                                              DynamicGroupArgs: PVOID;
                                              var hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE): Boolean;
var
  DLLHandle                       : THandle;
  AuthzInitializeContextFromSid   : function (Flags: DWORD;
                                              UserSid: PSID;
                                              hAuthzResourceManager: AUTHZ_RESOURCE_MANAGER_HANDLE;
                                              pExpirationTime: PLargeInteger;
                                              Identifier: LUID;
                                              DynamicGroupArgs: PVOID;
                                              hAuthzClientContext: PAUTHZ_CLIENT_CONTEXT_HANDLE): BOOL; cdecl stdcall;
begin
  Result    := False;
  DLLHandle := LoadLibrary('authz.dll');

  if DLLHandle >= 32 then
  begin
    @AuthzInitializeContextFromSid := GetProcAddress(DLLHandle, 'AuthzInitializeContextFromSid');
    Result := AuthzInitializeContextFromSid(Flags,
                                            UserSid,
                                            hAuthzResourceManager,
                                            pExpirationTime,
                                            Identifier,
                                            DynamicGroupArgs,
                                            @hAuthzClientContext);
    FreeLibrary(DLLHandle);
  end;
end;

function AuthzFreeResourceManagerWrapper(hAuthzResourceManager: AUTHZ_RESOURCE_MANAGER_HANDLE): Boolean;
var
  DLLHandle                       : THandle;
  AuthzFreeResourceManager        : function(hAuthzResourceManager: AUTHZ_RESOURCE_MANAGER_HANDLE): BOOL; cdecl stdcall;
begin
  Result    := False;
  DLLHandle := LoadLibrary('authz.dll');

  if DLLHandle >= 32 then
  begin
    @AuthzFreeResourceManager := GetProcAddress(DLLHandle, 'AuthzFreeResourceManager');
    Result := AuthzFreeResourceManager(hAuthzResourceManager);

    FreeLibrary(DLLHandle);
  end;
end;

function AuthzFreeContextWrapper(hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE): Boolean;
var
  DLLHandle               : THandle;
  AuthzFreeContext        : function(hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE): BOOL; cdecl stdcall;
begin
  Result    := False;
  DLLHandle := LoadLibrary('authz.dll');

  if DLLHandle >= 32 then
  begin
    @AuthzFreeContext := GetProcAddress(DLLHandle, 'AuthzFreeResourceManager');
    Result := AuthzFreeContext(hAuthzClientContext);

    FreeLibrary(DLLHandle);
  end;
end;


function AuthzAccessCheckWrapper( Flags: DWORD;
                                  hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE;
                                  var pRequest: AUTHZ_ACCESS_REQUEST;
                                  hAuditEvent: AUTHZ_AUDIT_EVENT_HANDLE;
                                  var pSecurityDescriptor: SECURITY_DESCRIPTOR;
                                  var OptionalSecurityDescriptorArray: PSECURITY_DESCRIPTOR;
                                  OptionalSecurityDescriptorCount: DWORD;
                                  var pReply: AUTHZ_ACCESS_REPLY;
                                  var phAccessCheckResultsOPTIONAL: AUTHZ_ACCESS_CHECK_RESULTS_HANDLE): Boolean;
var
  nError                  : Integer;
  DLLHandle               : THandle;
  AuthzAccessCheck        : function( Flags: DWORD;
                                      hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE;
                                      pRequest: PAUTHZ_ACCESS_REQUEST;
                                      hAuditEvent: AUTHZ_AUDIT_EVENT_HANDLE;
                                      pSecurityDescriptor: PSECURITY_DESCRIPTOR ;
                                      OptionalSecurityDescriptorArray: PPSECURITY_DESCRIPTOR;
                                      OptionalSecurityDescriptorCount: DWORD;
                                      pReply: PAUTHZ_ACCESS_REPLY;
                                      phAccessCheckResultsOPTIONAL: PAUTHZ_ACCESS_CHECK_RESULTS_HANDLE): BOOL; cdecl stdcall;
begin
  Result    := False;
  DLLHandle := LoadLibrary('authz.dll');

  if DLLHandle >= 32 then
  begin
    @AuthzAccessCheck := GetProcAddress(DLLHandle, 'AuthzAccessCheck');
    Result := AuthzAccessCheck(Flags,
                               hAuthzClientContext,
                               @pRequest,
                               hAuditEvent,
                               @pSecurityDescriptor,
                               @OptionalSecurityDescriptorArray,
                               OptionalSecurityDescriptorCount,
                               @pReply,
                               @phAccessCheckResultsOPTIONAL);

    if not Result then
      nError := GetLastError;

    FreeLibrary(DLLHandle);
  end;
end;


function HasAccessRights(p_nDesiredRights: Integer; p_sFileName: string; p_sUsername: string): Boolean;
var
  nDW      : DWORD;
  pSidOwner: PSID;
  pSidGroup: PSID;
  pPsd     : PSECURITY_DESCRIPTOR;
  oDAcl    : PACL;
  oSAcl    : PACL;
  hManager : AUTHZ_RESOURCE_MANAGER_HANDLE;
  bRes     : Boolean;
begin
  oSAcl     := nil;
  oDAcl     := nil;
  pSidOwner := nil;
  pSidGroup := nil;
  pPsd      := nil;

  hManager  := 0;

  Result    := False;

  try
    nDW := GetNamedSecurityInfoW( PWideChar(p_sFileName),
                                  SE_FILE_OBJECT,
                                  DACL_SECURITY_INFORMATION or OWNER_SECURITY_INFORMATION or GROUP_SECURITY_INFORMATION,
                                  pSidOwner,
                                  pSidGroup,
                                  oDAcl,
                                  oSAcl,
                                  pPsd);

    if nDW <> ERROR_SUCCESS then
      Exit;

    bRes := AuthzInitializeResourceManagerWrapper(AUTHZ_RM_FLAG_NO_AUDIT, nil, nil, nil, PWideChar(EmptyStr), hManager);
    if not bRes then
      Exit;

    bRes := HasRightsForUser(hManager, pPsd, p_sUsername, p_nDesiredRights);
    if not bRes then
      Exit;

    Result := True;

  finally
    AuthzFreeResourceManagerWrapper(hManager);
    if Assigned(pPsd) then
      LocalFree(HLOCAL(pPsd));

  end;
end;

function HasRightsForUser(p_hManager: AUTHZ_RESOURCE_MANAGER_HANDLE;
                          p_oPsd: PSECURITY_DESCRIPTOR;
                          p_sUsername: string;
                          p_nDesiredRights: DWORD): Boolean;
var
  hAuthzClientContext: AUTHZ_CLIENT_CONTEXT_HANDLE;
  bResult            : Boolean;
  n_UnusedID         : LUID;
  oSid               : PSID;
begin
  hAuthzClientContext := 0;
  Result              := false;
  n_UnusedID.LowPart  := 0;
  n_UnusedID.HighPart := 0;

  oSid := ConvertUsernameToBinarySID(p_sUsername);

  if Assigned(oSid) then
  begin
    try
      bResult := AuthzInitializeContextFromSidWrapper(0, oSid, p_hManager, nil, n_UnusedID, nil, hAuthzClientContext);

      if not bResult then
        Exit;

      bResult := HasAccess(hAuthzClientContext, p_oPsd, p_nDesiredRights);

      if bResult then
        Result := True;

    finally
      if Assigned(oSid) then
        LocalFree(HLOCAL(oSid));

      AuthzFreeContextWrapper(hAuthzClientContext);
    end;
  end;
end;

function ConvertUsernameToBinarySID(p_pAccountName: string): PSID;
var
  psDomainName   : LPTSTR;
  nDomainNameSize: DWORD;
  oSid           : PSID;
  nSidSize       : DWORD;
  eSidType       : SID_NAME_USE;
  bResult        : Boolean;
begin
  Result          := nil;
  psDomainName    := nil;
  nDomainNameSize := 0;
  oSid            := nil;
  bResult         := false;

  try
    LookupAccountName(nil,             // lpServerName: look up on local system
      PWideChar(p_pAccountName), oSid, // buffer to receive name
      nSidSize, psDomainName, nDomainNameSize, eSidType);

    if GetLastError = ERROR_INSUFFICIENT_BUFFER then
    begin
      oSid := LPTSTR(LocalAlloc(LPTR, nSidSize * SizeOf(TCHAR)));
      if not Assigned(oSid) then
        Exit;

      psDomainName := LPTSTR(LocalAlloc(LPTR, nDomainNameSize * SizeOf(TCHAR)));
      if not Assigned(psDomainName) then
        Exit;

      bResult := LookupAccountName( nil,  // lpServerName: look up on local system
                                    PWideChar(p_pAccountName),
                                    oSid, // buffer to receive name
                                    nSidSize,
                                    psDomainName,
                                    nDomainNameSize,
                                    eSidType);
      if bResult then
        Result := oSid;

    end
    else
      Exit;
  finally
    if Assigned(psDomainName) then
    begin
      LocalFree(HLOCAL(psDomainName));
    end;
    // Free pSid only if failed;
    // otherwise, the caller has to free it after use.
    if (bResult = false) and Assigned(oSid) then
    begin
      LocalFree(HLOCAL(oSid));
    end;
  end;
end;

function HasAccess(p_hAuthzClient: AUTHZ_CLIENT_CONTEXT_HANDLE; p_oPsd: PSECURITY_DESCRIPTOR; p_nDesiredRights: DWORD): Boolean;
var
  oDescArray    : Pointer;
  oCheckResults : AUTHZ_ACCESS_CHECK_RESULTS_HANDLE;
  oAccessRequest: AUTHZ_ACCESS_REQUEST;
  oAccessReply  : AUTHZ_ACCESS_REPLY;
  a_nBuffer     : array [0 .. 1024] of BYTE;
  bResult       : Boolean;
  oPsd          : SECURITY_DESCRIPTOR;
begin
  Result := False;

  //  Do AccessCheck.
  oAccessRequest.DesiredAccess        := FILE_TRAVERSE;
  oAccessRequest.PrincipalSelfSid     := nil;
  oAccessRequest.ObjectTypeList       := nil;
  oAccessRequest.OptionalArguments    := nil;
  oAccessRequest.ObjectTypeListLength := 0;

  ZeroMemory(@a_nBuffer, sizeof(a_nBuffer));

  oAccessReply.ResultListLength       := 1;
  oAccessReply.GrantedAccessMask      := PACCESS_MASK(@a_nBuffer);
  oAccessReply.Error                  := PDWORD(Cardinal(@a_nBuffer) + sizeof(ACCESS_MASK));

  oPsd    := SECURITY_DESCRIPTOR(p_oPsd^);
  bResult := AuthzAccessCheckWrapper( 0,
                                      p_hAuthzClient,
                                      oAccessRequest,
                                      0,
                                      oPsd,
                                      oDescArray,
                                      0,
                                      oAccessReply,
                                      oCheckResults);
  if bResult then
    Result := True;
end;

end.

私の問題は AuthzAccessCheckWrapper の 348 行目です

Result := AuthzAccessCheck(Flags,
                               hAuthzClientContext,
                               @pRequest,
                               hAuditEvent,
                               @pSecurityDescriptor,
                               @OptionalSecurityDescriptorArray,
                               OptionalSecurityDescriptorCount,
                               @pReply,
                               @phAccessCheckResultsOPTIONAL);

if not Result then
  nError := GetLastError;

エラー 87 (ERROR_INVALID_PARAMETER) が表示される場所

私は Delphi にまったく慣れていないため、これは初心者のエラーである可能性がありますが、これを解決する方法がわからないため、ヘルプや提案をいただければ幸いです。

4

1 に答える 1