D
Dave Coate
Hi,
I have been attempting to get at file security information using
vb.net. I have had some success so far. I am able to read the Security
Descriptor information of a file object, (Trustee, Access Mask etc) so
I think I am on the right track. I am currently stuck on the GetAce
Function. When I call it, LastDllError returns 127 the first time and
87 each time after that. (Until I restart the program) I stripped down
the program to the bare minimum to demonstrate the Problem. (Below) I
have successfully used the 'GetFileSecurity' and
'GetSecurityDescriptorDacl' functions in code to display the Security
Descriptor Information, so I believe that part of this code is
correct.
**************************************
Imports System.Runtime.InteropServices
Public Class SecurityAPI2
'This function retrieves the security information for a file.
Private Declare Function GetFileSecurity Lib "advapi32.dll" _
Alias "GetFileSecurityA" ( _
ByVal lpFileName As String, _
ByVal RequestedInformation As SECURITY_INFORMATION, _
ByVal pSecurityDescriptor As IntPtr, _
ByVal nLength As Int32, _
ByRef lpnLengthNeeded As Int32) As Boolean
' This function retrieves the DACL from the file's security
descriptor.
Private Declare Function GetSecurityDescriptorDacl Lib
"advapi32.dll" ( _
ByVal pSecurityDescriptor As IntPtr, _
ByRef lpbDaclPresent As Boolean, _
ByRef pDacl As IntPtr, _
ByRef lpbDaclDefaulted As Boolean) As Boolean
Declare Function GetAce Lib "advapi32.dll" ( _
ByRef pAcl As IntPtr, _
ByVal dwAceIndex As Integer, _
ByRef pAce As IntPtr) As Boolean
' This enumeration tells what type of information we want to
retrieve
' about the file's security.
Public Enum SECURITY_INFORMATION
OWNER_SECURITY_INFORMATION = &H1
GROUP_SECURITY_INFORMATION = &H2
DACL_SECURITY_INFORMATION = &H4
SACL_SECURITY_INFORMATION = &H8
PROTECTED_DACL_SECURITY_INFORMATION = &H80000000
PROTECTED_SACL_SECURITY_INFORMATION = &H40000000
UNPROTECTED_DACL_SECURITY_INFORMATION = &H20000000
UNPROTECTED_SACL_SECURITY_INFORMATION = &H10000000
End Enum
Const ERROR_INSUFFICIENT_BUFFER As Integer = 122
Public Function ReadFileSecurity(ByVal sPath As String)
Dim SD As IntPtr
' Get the old SD
SD = GetExistingSD(sPath,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION)
' Obtain the DACL.
Dim DACLPresent As Boolean ' Is the DACL present?
Dim Defaulted As Boolean ' Is the DACL
defaulted?
Dim DACL As IntPtr ' Pointer to the DACL.
If (GetSecurityDescriptorDacl(SD, DACLPresent, DACL,
Defaulted) <> True) Then
MsgBox("Unable to Get Dacl")
End If
' Obtain the array of ACEs from the DACL.
Dim bSuccess As Integer
Dim ACECount As Integer ' Number of ACEs in
DACL.
Dim ACEList As IntPtr ' An array of ACE
entries.
Dim pAce As IntPtr
bSuccess = GetAce(DACL, 0, pAce)
If (bSuccess = 0) Then
MsgBox("Error: " & _
"Unable to Get Ace")
MsgBox(Err.LastDllError)
End If
End Function
' This function encapsulates the code required to obtain a
security
' descriptor.
Public Function GetExistingSD( _
ByVal sPath As String, _
ByVal SEType As SECURITY_INFORMATION) As IntPtr
Dim bSuccess As Integer 'Status variable
Dim SD As IntPtr
Dim SDSize As Int32 ' Actual size of the
security descriptor.
Dim SDSizeNeeded As Int32 ' Required security
descriptor size.
' Call GetFileSecurity the first time to obtain the size of
the Buffer
' required for the Security Descriptor.
SDSizeNeeded = 0
bSuccess = GetFileSecurity(sPath, SEType, SD, 0, SDSizeNeeded)
' exit if any error
If (bSuccess = 0) And (Err.LastDllError <>
ERROR_INSUFFICIENT_BUFFER) Then
MsgBox("Failure")
End If
'Determine the size of the security descriptor
SD = Marshal.AllocHGlobal(SDSizeNeeded)
SDSize = SDSizeNeeded
bSuccess = GetFileSecurity(sPath, SEType, SD, SDSize,
SDSizeNeeded)
If bSuccess = 0 Then
MsgBox("Failure")
End If
Return SD
End Function
End Class
I have been attempting to get at file security information using
vb.net. I have had some success so far. I am able to read the Security
Descriptor information of a file object, (Trustee, Access Mask etc) so
I think I am on the right track. I am currently stuck on the GetAce
Function. When I call it, LastDllError returns 127 the first time and
87 each time after that. (Until I restart the program) I stripped down
the program to the bare minimum to demonstrate the Problem. (Below) I
have successfully used the 'GetFileSecurity' and
'GetSecurityDescriptorDacl' functions in code to display the Security
Descriptor Information, so I believe that part of this code is
correct.
**************************************
Imports System.Runtime.InteropServices
Public Class SecurityAPI2
'This function retrieves the security information for a file.
Private Declare Function GetFileSecurity Lib "advapi32.dll" _
Alias "GetFileSecurityA" ( _
ByVal lpFileName As String, _
ByVal RequestedInformation As SECURITY_INFORMATION, _
ByVal pSecurityDescriptor As IntPtr, _
ByVal nLength As Int32, _
ByRef lpnLengthNeeded As Int32) As Boolean
' This function retrieves the DACL from the file's security
descriptor.
Private Declare Function GetSecurityDescriptorDacl Lib
"advapi32.dll" ( _
ByVal pSecurityDescriptor As IntPtr, _
ByRef lpbDaclPresent As Boolean, _
ByRef pDacl As IntPtr, _
ByRef lpbDaclDefaulted As Boolean) As Boolean
Declare Function GetAce Lib "advapi32.dll" ( _
ByRef pAcl As IntPtr, _
ByVal dwAceIndex As Integer, _
ByRef pAce As IntPtr) As Boolean
' This enumeration tells what type of information we want to
retrieve
' about the file's security.
Public Enum SECURITY_INFORMATION
OWNER_SECURITY_INFORMATION = &H1
GROUP_SECURITY_INFORMATION = &H2
DACL_SECURITY_INFORMATION = &H4
SACL_SECURITY_INFORMATION = &H8
PROTECTED_DACL_SECURITY_INFORMATION = &H80000000
PROTECTED_SACL_SECURITY_INFORMATION = &H40000000
UNPROTECTED_DACL_SECURITY_INFORMATION = &H20000000
UNPROTECTED_SACL_SECURITY_INFORMATION = &H10000000
End Enum
Const ERROR_INSUFFICIENT_BUFFER As Integer = 122
Public Function ReadFileSecurity(ByVal sPath As String)
Dim SD As IntPtr
' Get the old SD
SD = GetExistingSD(sPath,
SECURITY_INFORMATION.DACL_SECURITY_INFORMATION)
' Obtain the DACL.
Dim DACLPresent As Boolean ' Is the DACL present?
Dim Defaulted As Boolean ' Is the DACL
defaulted?
Dim DACL As IntPtr ' Pointer to the DACL.
If (GetSecurityDescriptorDacl(SD, DACLPresent, DACL,
Defaulted) <> True) Then
MsgBox("Unable to Get Dacl")
End If
' Obtain the array of ACEs from the DACL.
Dim bSuccess As Integer
Dim ACECount As Integer ' Number of ACEs in
DACL.
Dim ACEList As IntPtr ' An array of ACE
entries.
Dim pAce As IntPtr
bSuccess = GetAce(DACL, 0, pAce)
If (bSuccess = 0) Then
MsgBox("Error: " & _
"Unable to Get Ace")
MsgBox(Err.LastDllError)
End If
End Function
' This function encapsulates the code required to obtain a
security
' descriptor.
Public Function GetExistingSD( _
ByVal sPath As String, _
ByVal SEType As SECURITY_INFORMATION) As IntPtr
Dim bSuccess As Integer 'Status variable
Dim SD As IntPtr
Dim SDSize As Int32 ' Actual size of the
security descriptor.
Dim SDSizeNeeded As Int32 ' Required security
descriptor size.
' Call GetFileSecurity the first time to obtain the size of
the Buffer
' required for the Security Descriptor.
SDSizeNeeded = 0
bSuccess = GetFileSecurity(sPath, SEType, SD, 0, SDSizeNeeded)
' exit if any error
If (bSuccess = 0) And (Err.LastDllError <>
ERROR_INSUFFICIENT_BUFFER) Then
MsgBox("Failure")
End If
'Determine the size of the security descriptor
SD = Marshal.AllocHGlobal(SDSizeNeeded)
SDSize = SDSizeNeeded
bSuccess = GetFileSecurity(sPath, SEType, SD, SDSize,
SDSizeNeeded)
If bSuccess = 0 Then
MsgBox("Failure")
End If
Return SD
End Function
End Class