Answered by:
DirectoryEntry properties long from large int time missmatch
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 FunctionLife 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 doubleprecision 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.
 Edited by Pieter Geerkens Wednesday, December 5, 2012 9:09 PM
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
CorFriday, 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
CorFriday, 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/underflow 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.
 Edited by Pieter Geerkens Friday, December 7, 2012 6:42 PM
Friday, December 7, 2012 6:41 PM 
Paul,
Thanks,
Cor Edited by Cor Ligthert Friday, December 7, 2012 6:44 PM
Friday, December 7, 2012 6:43 PM