Problem with the HighPart and LowPart property methods
A good way to demonstrate the problem encountered with these property methods is to use ADSI Edit to
update the maxStorage attribute of a test user object.
ADSI Edit is part of the "Windows 2000 Support Tools" found on any Windows 2000 Server CD.
It can be installed on any client with Windows 2000 or above by running Setup.exe in the
\Support\Tools folder on the CD.
With ADSI Edit you can browse all objects in your Active Directory and the attributes of each object.
The maxStorage attribute is used to specify the maximum amount of disk space the user is allowed to use.
This attribute is Integer8. ADSI Edit allows you to enter a large 64-bit number as the value for this
attribute. The VBScript program below will then reveal the values returned by the
HighPart and LowPart
property methods exposed by the IADsLargeInteger
interface:
strUserDN = "cn=TestUser,ou=Sales,dc=MyDomain,dc=com")
Set objUser = GetObject("LDAP://" & strUserDN)
Set objMax = objUser.maxStorage
lngHigh = objMax.HighPart
lngLow = objMax.LowPart
lngValue = lngHigh * (2^32) + lngLow
Wscript.Echo "HighPart: " & lngHigh
Wscript.Echo "LowPart: " & lngLow
Wscript.Echo "Value: " & lngValue
By selecting a test user, setting various values for the maxStorage attribute, then finding the resulting values returned by the HighPart and LowPart methods, you can verify that LowPart always returns values between –2^31 and 2^31 – 1 (2^31 = 2,147,483,648). This reveals that these methods perform unsigned arithmetic on the 64-bit numbers. For example, the following table shows the HighPart and LowPart values corresponding to critical values for maxStorage. The values are shown below with commas for legibility, but commas are not allowed in the actual values:
maxStorage | HighPart | LowPart | Value |
10,737,418,238 | 2 | 2,147,483,646 | 10,737,418,238 |
10,737,418,239 | 2 | 2,147,483,647 | 10,737,418,239 |
10,737,418,240 | 2 | -2,147,483,648 | 6,442,450,944 |
Notice in the last example, when the LowPart property method returns a negative value, the standard
formula for determining the value of maxStorage is wrong by
4,294,967,296 which is
2^32. Because VB
and VBScript do not support unsigned numbers, we must correct the value returned by the
LowPart
property method by adding 2^32. This is the same as increasing the value returned by the
HighPart
property method by one.
The following C code demonstrates the same issue:
_int64 i64;
i64 = -10;
i64 = i64 << 32;
i64 = i64 + -10;
You might expect the hex value of i64 to be
0xfffffff6fffffff6
but it will actually be
0xfffffff5fffffff6
In the last step of the program, the value
0xfffffff600000000
is added to –10. When the lower 32 bits (4 bytes) underflow, the upper 32 bits are decremented by one. This can be avoided in C by using unsigned numbers:
_int64 i64;
i64 = (ULONG)-10;
i64 = i64 << 32;
i64 = i64 + (ULONG)-10;
You can also assign negative values to the
maxStorage attribute (even though these values make no sense). The
same formula applies to calculate the value from the
HighPart and LowPart methods. When the
Integer8 value is negative, the HighPart
method returns a negative value.
Examples of Integer8 attributes include the following:
accountExpires, badPasswordTime,
lastLogon,
lockoutTime, maxStorage,
pwdLastSet, uSNChanged,
uSNCreated, lockoutDuration,
lockoutObservationWindow,
maxPwdAge, minPwdAge, and
modifiedCount.