Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28701 Discussions

Retrieving SID using LookupAccountName

kramer__walter
Beginner
967 Views

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

0 Kudos
2 Replies
JVanB
Valued Contributor II
967 Views

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

[fortran]

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[/fortran]

0 Kudos
kramer__walter
Beginner
967 Views

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

 

0 Kudos
Reply