Retrieving SID using LookupAccountName

Retrieving SID using LookupAccountName

Hello,

I am trying to retrieve a security identifier by calling the windows API function LookupAccountName (see attached source code).

The problem is that I keep getting the following error message when calling LookupAccountName:

HEAP[SID.exe]: Invalid allocation size - 99999998 (exceeded 7ffdefff)

I have been trying all kind of variations (including using loc() an not using loc()), but cannot find a solution.

I hope someone sees where I am going wrong.

Walter Kramer

附件尺寸
下载 sid.f902.08 KB
3 帖子 / 0 全新
最新文章
如需更全面地了解编译器优化,请参阅优化注意事项
Repeat Offender的头像

I got as far as getting LookupAccountName to return nonzero in gfortran. What works in ifort would be a little different, but I think you want to change the first invocation of LookupAccountName to

iret = LookupAccountName(NULL, ComputerName, NULL, loc(cbSid), NULL, loc(cbReferencedDomain), loc(peUse))

Then you should change the declaration of ReferencedDomain to

character, allocatable :: ReferencedDomain(:)

And add a declaration

character, allocatable, target :: SidBuffer(:)

Now, before the next allocation, you want:

allocate(ReferencedDomain(cbReferencedDomain))
allocate(SidBuffer(cbSid))
pSid = loc(SidBuffer(1))

Then your second invocation might work.

 The gfortran test code was

module winstuff
   use ISO_C_BINDING
   use ISO_C_BINDING, only: C_PTR
   use ISO_C_BINDING, only: T_SID => C_PTR
   implicit none
   private
   public T_SID
   integer, parameter, public :: BOOL = C_INT
   integer, parameter, public :: DWORD = C_LONG
   integer, parameter, public :: MAX_COMPUTERNAME_LENGTH = 15
   public GetComputerName
   interface
      function GetComputerName(lpBuffer, lpnSize) bind(C,name='GetComputerNameA')
         import
         implicit none
!gcc$ attributes stdcall :: GetComputerName
         integer(BOOL) GetComputerName
         character(kind=C_CHAR) lpBuffer(*)
         integer(DWORD) lpnSize
      end function GetComputerName
   end interface
   public LookupAccountName
   interface
      function LookupAccountName(lpSystemName,lpAccountName,Sid,cbSid, &
         referencedDomainName,cchReferencedDomainName,peUse) &
         bind(C,name='LookupAccountNameA')
         import
         implicit none
!gcc$ attributes stdcall :: LookupAccountName
         integer(BOOL) LookupAccountName
         character(kind=C_CHAR) lpSystemName(*)
         character(kind=C_CHAR) lpAccountName(*)
         type(T_SID), value :: Sid
         integer(DWORD) cbSid
         character(kind=C_CHAR) ReferencedDomainName(*)
         integer(DWORD) cchReferencedDomainName
         integer(C_INT) peUse
      end function LookupAccountName
   end interface
   public GetLastError
   interface
      function GetLastError() bind(C,name='GetLastError')
         import
         implicit none
!gcc$ attributes stdcall :: GetLastError
         integer(DWORD) GetLastError
      end function GetLastError
   end interface
end module winstuff
program sid_main
   use ISO_C_BINDING
   use winstuff
   implicit none
   integer(BOOL) result4
   character(len=MAX_COMPUTERNAME_LENGTH+1,kind=C_CHAR) lpBuffer
   integer(DWORD) lpnSize
   character(kind=C_CHAR), pointer :: lpSystemName(:)
   character(kind=C_CHAR), pointer :: lpAccountName(:)
   integer(DWORD) cbSid
!   type(T_SID) Sid
! Work around ICE etc. in gfortran
   type(C_PTR) Sid
   character(kind=C_CHAR), pointer :: ReferencedDomainName(:)
   integer(DWORD) cchReferencedDomainName
   integer(C_INT) peUse
   character(kind=C_CHAR), allocatable, target :: SidBuffer(:)
   character(len=:,kind=C_CHAR), allocatable ::DomainName
   lpnSize = len(lpBuffer)
   result4 = GetComputerName(lpBuffer,lpnSize)
   write(*,'(a)') 'GetComputerName '//trim(merge('succeeded','failed   ',result4 /= 0))
   write(*,'(a,i0)') 'lpnSize = ',lpnSize
   write(*,'(a)') 'Computer name = '//lpBuffer(1:lpnSize)
   call C_F_POINTER(C_NULL_PTR,lpSystemName,[0])
   call C_F_POINTER(C_NULL_PTR,lpAccountName,[0])
   Sid = C_NULL_PTR
   cbSid = 0
   call C_F_POINTER(C_NULL_PTR,ReferencedDomainName,[0])
   cchReferencedDomainName = 0
   result4 = LookupAccountName(lpSystemName,lpAccountName,Sid, &
      cbSid,ReferencedDomainName,cchReferencedDomainName,peUse)
   write(*,'(a)') 'LookupAccountName '//trim(merge('succeeded','failed   ',result4 /= 0))
   write(*,'(a,i0)') 'GetLastError = ',GetLastError() ! 122 = ERROR_INSUFFICIENT_BUFFER
   write(*,'(a,i0)') 'cbSid = ', cbSid
   write(*,'(a,i0)') 'cchReferencedDomainName = ', cchReferencedDomainName
   allocate(SidBuffer(cbSid))
   Sid = C_LOC(SidBuffer(1))
   allocate(ReferencedDomainName(cchReferencedDomainName))
   result4 = LookupAccountName(lpSystemName,lpAccountName,Sid, &
      cbSid,ReferencedDomainName,cchReferencedDomainName,peUse)
   write(*,'(a)') 'LookupAccountName '//trim(merge('succeeded','failed   ',result4 /= 0))
   write(*,'(a,i0)') 'cbSid = ', cbSid
   write(*,'(a,i0)') 'cchReferencedDomainName = ', cchReferencedDomainName
   DomainName = repeat('A',cchReferencedDomainName-1)
   DomainName = transfer(ReferencedDomainName(1:len(DomainName)),DomainName)
   write(*,'(a)') 'ReferencedDomainName = '//DomainName
   write(*,'(a,i0)') 'peUse = ', peUse ! 3 = SidTypeDomain
end program sid_main

Hello Repeat Offender,

Thanks for your tips. Forgetting to allocate a buffer for the SID structure before the second invocation was indeed my major mistake.  Passing NULL for ReferencedDomainName on the first invocation (and initializing cbReferencedDomainName) did the rest. Now everything works (including the ConvertSidtoStringSid function). I have attached the resulting code.

Regards,

Walter Kramer

 

附件: 

附件尺寸
下载 sid.f902.28 KB

登陆并发表评论。