locked
DirectoryEntry properties long from large int time missmatch RRS feed

  • Question

  • Hi All,

    This might be a little picky but our auditors will try to debunk my application if it doesn't match and this minor thing is really bugging me. So I was hoping someone could either explain or help me figure out why something is happening.

     

    Here's what I am doing. I'm getting a bunch of properties from AD, one in particular are the password policies. All of them seem to match what is in the domain GPO except 1 item. LockoutAbservationWindow when I calculate the number returned appears to be 2 minutes off.

    Any help is much appreciated. Thanks.

     

    I'm using the standard longfromlargeinteger conversion function on the result of directoryentry.properties("lockoutduration')(0) and receiving this in return after the conversion -3701444032. I'm using 86400000000000 nanoseconds in a day * 100 * 24 hours * 60 minutes.

    Dim dirEntry As DirectoryEntry = New DirectoryEntry("LDAP://mydomain")
    Dim nanoSecondsInADay As Long = 86400000000000
    Dim LockoutWindow As Long = LongFromLargeInteger(dirEntry.Properties("lockOutObservationWindow")(0))
    LockoutWindow = (System.Math.Round(System.Math.Abs(LockoutWindow) / nanoSecondsInADay * 100 * 24 * 60))

    Private Function LongFromLargeInteger(ByVal largeInteger As Object) As Long
            Dim type As System.Type = largeInteger.[GetType]()
            Dim highPart As Integer = 0
            Dim lowPart As Integer = 0
            highPart = CInt(type.InvokeMember("HighPart", BindingFlags.GetProperty, Nothing, largeInteger, Nothing))
            lowPart = CInt(type.InvokeMember("LowPart", BindingFlags.GetProperty, Nothing, largeInteger, Nothing))
            Return CLng(highPart) << 32 Or CUInt(System.Math.Abs(lowPart))
    End Function


    Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.

    Wednesday, December 5, 2012 7:55 PM

Answers

  • I actually use the TimeSpan Class to generate this value. I assembled this code a while ago, but it might work for you. The first section fetches the domain object with the policy attributes and then there is a Property for LockoutObservationWindow that returns the TimeSpan:

                    Dim policyAttributes() As String = {"maxPwdAge", "minPwdAge", "minPwdLength", "lockoutDuration", "lockOutObservationWindow", "lockoutThreshold", "pwdProperties", "pwdHistoryLength", "objectClass", "distinguishedName"}
    
                    'we take advantage of the marshaling with
                    'the DirectorySearcher for Large Integer values...
                    Dim ds As New DirectorySearcher(DomainRoot, "(objectClass=domainDNS)", policyAttributes, System.DirectoryServices.SearchScope.Base)
    
                    Dim result As SearchResult = ds.FindOne()
    
                    'do some quick validation...	   
                    If result Is Nothing Then
                        Throw New ArgumentException("DomainRoot is not a domainDNS object.")
                    End If
    
                    _attribs = result.Properties
    
                Public ReadOnly Property LockoutObservationWindow() As TimeSpan
                    Get
                        Dim val As String = "lockoutObservationWindow"
                        If _attribs.Contains(val) Then
                            Dim ticks As Long = GetAbsValue(_attribs(val)(0))
    
                            If ticks > 0 Then
                                Return TimeSpan.FromTicks(ticks)
                            End If
                        End If
    
                        Return TimeSpan.MaxValue
                    End Get
                End Property
    
                Private Function GetAbsValue(ByVal longInt As Object) As Long
                    Return Math.Abs(CLng(Fix(longInt)))
                End Function


    Paul ~~~~ Microsoft MVP (Visual Basic)

    • Proposed as answer by Cor Ligthert Friday, December 7, 2012 6:44 PM
    • Marked as answer by Youen Zen Thursday, December 13, 2012 9:53 AM
    Friday, December 7, 2012 3:18 PM

All replies

  • This calculation is approximate (since performed in double-precision floating point) and is incorrectly stated to minimize precision loss:

    LockoutWindow = (System.Math.Round(System.Math.Abs(LockoutWindow)
    / nanoSecondsInADay * 100 * 24 * 60))

    A better statement of the expression is the following:

    LockoutWindow = (
       System.Math.Round(
          System.Math.Abs(LockoutWindow)
          / ( nanoSecondsInADay \ (100 * 24 * 60) )
    )  )


    "Premature optimization is the root of all evil." - Knuth

    If I provoked thought, please click the green arrow

    If I provoked Aha! please click Propose as Answer

    We are here to learn, to share knowledge, and to earn points; all in about equal measure.


    Wednesday, December 5, 2012 9:07 PM
  • Thanks for the reply. Both calculations actually give the same answer. How would I do an exact calculation instead of an approximation?

    Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.

    Thursday, December 6, 2012 1:58 PM
  • Hi,

    You may get idea form this  forum Directory Services http://social.technet.microsoft.com/Forums/en/winserverDS/threads which discuss AD issue. Sorry I'm not in this and can't help much.


    Think again!

    • Proposed as answer by Cor Ligthert Friday, December 7, 2012 10:23 AM
    • Unproposed as answer by Cor Ligthert Friday, December 7, 2012 10:30 AM
    Friday, December 7, 2012 8:43 AM
  • I'm curious why are you converting an Int64 to an Int64?

    Did you get this code from VB6?


    Success
    Cor

    Friday, December 7, 2012 10:29 AM
  • I actually use the TimeSpan Class to generate this value. I assembled this code a while ago, but it might work for you. The first section fetches the domain object with the policy attributes and then there is a Property for LockoutObservationWindow that returns the TimeSpan:

                    Dim policyAttributes() As String = {"maxPwdAge", "minPwdAge", "minPwdLength", "lockoutDuration", "lockOutObservationWindow", "lockoutThreshold", "pwdProperties", "pwdHistoryLength", "objectClass", "distinguishedName"}
    
                    'we take advantage of the marshaling with
                    'the DirectorySearcher for Large Integer values...
                    Dim ds As New DirectorySearcher(DomainRoot, "(objectClass=domainDNS)", policyAttributes, System.DirectoryServices.SearchScope.Base)
    
                    Dim result As SearchResult = ds.FindOne()
    
                    'do some quick validation...	   
                    If result Is Nothing Then
                        Throw New ArgumentException("DomainRoot is not a domainDNS object.")
                    End If
    
                    _attribs = result.Properties
    
                Public ReadOnly Property LockoutObservationWindow() As TimeSpan
                    Get
                        Dim val As String = "lockoutObservationWindow"
                        If _attribs.Contains(val) Then
                            Dim ticks As Long = GetAbsValue(_attribs(val)(0))
    
                            If ticks > 0 Then
                                Return TimeSpan.FromTicks(ticks)
                            End If
                        End If
    
                        Return TimeSpan.MaxValue
                    End Get
                End Property
    
                Private Function GetAbsValue(ByVal longInt As Object) As Long
                    Return Math.Abs(CLng(Fix(longInt)))
                End Function


    Paul ~~~~ Microsoft MVP (Visual Basic)

    • Proposed as answer by Cor Ligthert Friday, December 7, 2012 6:44 PM
    • Marked as answer by Youen Zen Thursday, December 13, 2012 9:53 AM
    Friday, December 7, 2012 3:18 PM
  • Hello Paul,

    It is a while ago I was busy with the AD, was in this part but never this tick (I assume the OP does it also for Sharepoint). Does it mean that the Tick has the same size and starting point as the one in .Net? Just for my curiosity.


    Success
    Cor

    Friday, December 7, 2012 3:52 PM
  • Cor,

    A Tick is the same (100 nanosecond interval) for .NET and AD in this instance, if this is what you are asking.


    Paul ~~~~ Microsoft MVP (Visual Basic)

    Friday, December 7, 2012 6:08 PM
  • How do you know this: "Both calculations actually give the same answer"

    If you are "assuming" this from it being "theoretically" equivalent to my expression, then you do not yet understand how arithmetic, and particularly floating point arithmetic, is performed by a computer.

    My point is that for supposedly identical mathematical expressions, theri formulation in code can affect, sometimes grossly effect, the end result. All mathematical expressions that might "at any point n the calculation" come close to the precision or extent limits of the datatype being used for the calculation, must be carefully crafted to avoid over-/under-flow of either precision or magnitude.

    My expression is. Yours is not.


    "Premature optimization is the root of all evil." - Knuth

    If I provoked thought, please click the green arrow

    If I provoked Aha! please click Propose as Answer

    We are here to learn, to share knowledge, and to earn points; all in about equal measure.


    Friday, December 7, 2012 6:41 PM
  • Paul,

    Thanks, 



    Cor


    Friday, December 7, 2012 6:43 PM