开发者

Perl function for negative integers using the 2's complement

开发者 https://www.devze.com 2023-01-15 07:25 出处:网络
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 attribut

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=c开发者_Go百科om")     ' 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?


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";


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消