views:

96

answers:

2

I am trying to convert AD maxpwdAge (a 64-bit integer) into a number of days.

According to Microsoft:

Uses the IADs interface's Get method to retrieve the value of the domain's maxPwdAge attribute (line 5).

Notice we use the Set keyword in VBScript to initialize the variable named objMaxPwdAge—the variable used to store the value returned by Get. Why is that?

When you fetch a 64-bit large integer, ADSI does not return one giant scalar value. Instead, ADSI automatically returns an IADsLargeInteger object. You use the IADsLargeInteger interface's HighPart and LowPart properties to calculate the large integer's value. As you may have guessed, HighPart gets the high order 32 bits, and LowPart gets the low order 32 bits. You use the following formula to convert HighPart and LowPart to the large integer's value.

The existing code in VBScript from the same page:

Const ONE_HUNDRED_NANOSECOND = .000000100   ' .000000100 is equal to 10^-7
Const SECONDS_IN_DAY = 86400

Set objDomain = GetObject("LDAP://DC=fabrikam,DC=com")     ' LINE 4
Set objMaxPwdAge = objDomain.Get("maxPwdAge")              ' LINE 5

If objMaxPwdAge.LowPart = 0 Then
  WScript.Echo "The Maximum Password Age is set to 0 in the " & _
               "domain. Therefore, the password does not expire."
  WScript.Quit
Else
  dblMaxPwdNano = Abs(objMaxPwdAge.HighPart * 2^32 + objMaxPwdAge.LowPart)
  dblMaxPwdSecs = dblMaxPwdNano * ONE_HUNDRED_NANOSECOND   ' LINE 13
  dblMaxPwdDays = Int(dblMaxPwdSecs / SECONDS_IN_DAY)      ' LINE 14
  WScript.Echo "Maximum password age: " & dblMaxPwdDays & " days"
End If

How can I do this in Perl?

+1  A: 

Endianness may come into this, but you may be able to say

#!/usr/bin/perl

use strict;
use warnings;

my $num = -37_108_517_437_440;

my $binary = sprintf "%064b", $num;

my ($high, $low) = $binary =~ /(.{32})(.{32})/;

$high = oct "0b$high";
$low  = oct "0b$low";

my $together = unpack "q", pack "LL", $low, $high;

print "num $num, low $low, high $high, together $together\n";
Chas. Owens
ya .. it will but how to generate the highpart and low part ( for ex : value is -37108517437440 )
Tree
I thought you had the high and the low 32-bit parts and wanted to build the original 64-bit value. What do you have?
Chas. Owens
i have 64 bit singed integer value : -37108517437440
Tree
What do you want? The high and low parts?
Chas. Owens
yes i am looking for high and low parts
Tree
i am having perl 5.8.8 it shows that unpack q is invaild option...
Tree
The `q` template was valid in Perl 5.8.8: http://perldoc.perl.org/5.8.8/functions/pack.html It may be that you are using a 32-bit version of Perl that can't hold a 64-bit integer. Can you post the exact error message?
Chas. Owens
A: 

Am I missing something? As far as I can tell from your question, your problem has nothing at all to do with 2’s complement. As far as I can tell, all you need/want to do is

use Math::BigInt;

use constant MAXPWDAGE_UNIT_PER_SEC => (
      1000 # milliseconds
    * 1000 # microseconds
    * 10   # 100 nanoseconds
);

use constant SECS_PER_DAY => (
      24 # hours
    * 60 # minutes
    * 60 # seconds
);

my $maxpwdage_full = ( Math::BigInt->new( $maxpwdage_highpart ) << 32 ) + $maxpwdage_lowpart;

my $days = $maxpwdage_full / MAXPWDAGE_UNIT_PER_SEC / SECS_PER_DAY;

Note that I deliberately use 2 separate constants, and I divide by them in sequence, because that keeps the divisors smaller than the range of a 32-bit integer. If you want to write this another way and you want it to work correctly on 32-bit perls, you’ll have to keep all the precision issues in mind.

Aristotle Pagaltzis