# Win32::Exchange
# Freely Distribute the code without modification.
#
# Creates and Modifies Exchange 5.5 and 2K Mailboxes
# (eventually it will do more, but for now, that's the scope)
#
# This is the culmination of 3 years of work in building Exchange Mailboxes, but now as a module.
# It uses Win32::OLE exclusively (and technically is just a wrapper for the underlying OLE calls).
#
# This build is tested and works with ActivePerl build 633 (and Win32::OLE .1502)
# There is not currently a package that is tested on older (non-multi-threading versions of
# ActivePerl)... My guess is that it may work except for the SetPerms and SetOwner subs but,
# remember.. That's a guess.
#
# Sorry... :(
#
package Win32::Exchange;
use strict;
use vars qw ($VERSION $Version $DEBUG);
use Win32::Exchange::Mailbox;
use Win32::Exchange::SMTP::Security;
use Win32::Exchange::Const;
use Win32::OLE qw (in);
Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE);
Win32::OLE->Option('_Unique' => 1);
#@ISA = qw(Win32::OLE);
my $Version;
my $VERSION = $Version = "0.042";
my $DEBUG = 2;
sub new {
my $server;
my $ver = "";
if (scalar(@_) == 1) {
if ($_[0] eq "5.5" || $_[0] eq "6.0") {
$ver = $_[0];
} else {
$server = $_[0];
}
} elsif (scalar(@_) == 2) {
if ($_[0] eq "Win32::Exchange") {
if ($_[1] eq "5.5" || $_[1] eq "6.0") {
$ver = $_[1];
} else {
$server = $_[1];
}
} else {
_ReportArgError("new",scalar(@_));
}
} else {
_ReportArgError("new",scalar(@_));
return 0;
}
my $class = "Win32::Exchange";
my $ldap_provider = {};
if ($ver eq "") {
my %version;
if (!Win32::Exchange::GetVersion($server,\%version)) {
return undef;
} else {
$ver = $version{'ver'}
}
}
if ($ver eq "5.5") {
#Exchange 5.5
if ($ldap_provider = Win32::OLE->new('ADsNamespaces')) {
return bless $ldap_provider,$class;
} else {
_DebugComment("Failed creating ADsNamespaces object\n",1);
return undef;
}
} elsif ($ver eq "6.0") {
#Exchange 2000
if ($ldap_provider = Win32::OLE->new('CDO.Person')) {
return bless $ldap_provider,$class;
} else {
_DebugComment("Failed creating CDO.Person object\n",1);
return undef;
}
} else {
_DebugComment("Unable to verify version information for version: $ver\n",1);
return undef;
}
}
sub DESTROY {
my $object = shift;
bless $object,"Win32::OLE";
return undef;
}
sub GetLDAPPath {
my $ldap_provider;
my $server_name;
my $ldap_path;
my $return_point;
if (scalar(@_) == 3) {
$server_name = $_[0];
$ldap_path = "LDAP://$server_name";
$return_point = 1;
} elsif (scalar(@_) == 4) {
$ldap_provider = $_[0];
$server_name = $_[1];
$return_point = 2;
} else {
_ReportArgError("GetLDAPPath",scalar(@_));
return 0;
}
my $result;
if (_AdodbExtendedSearch($server_name,"LDAP://$server_name","(&(objectClass=Computer)(rdn=$server_name))","rdn,distinguishedName",$result)) {
_DebugComment("result = $result\n",2);
if ($result =~ /cn=.*,cn=Servers,cn=Configuration,ou=(.*),o=(.*)/) {
my $returned_ou = $1;
my $returned_o = $2;
$_[$return_point]=$returned_o;
$_[($return_point+1)]=$returned_ou;
_DebugComment("ou=$returned_ou\no=$returned_o\n",2);
return 1;
} else {
_DebugComment("result = $result\n",2);
_DebugComment("result from ADODB search failed to produce an acceptable match\n",1);
return 0;
}
} else {
_DebugComment("ADODB search failed\n",1);
return 0;
}
}
sub GetVersion {
my $server_name;
my $error_num;
my $error_name;
if (scalar(@_) == 2) {
$server_name = $_[0];
} elsif (scalar(@_) == 3) {
if ($_[0] eq "Win32::Exchange") {
$server_name = $_[1];
} else {
_ReportArgError("GetVersion",scalar(@_));
return 0;
}
} else {
_ReportArgError("GetVersion",scalar(@_));
return 0;
}
my $original_ole_warn_value = $Win32::OLE::Warn;
$Win32::OLE::Warn = 0;
my $serial_val;
my $serial_version_check_obj = Win32::OLE->new('CDOEXM.ExchangeServer'); #substantiates the possible existance of e2k
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
if ($error_num eq "0x80040154" ||
$error_num eq "0x800401f3") {
#0x80040154 Class not registered
#0x800401f3 Invalid class string
_DebugComment("The Exchange 2000 client tools don't look to be installed on this machine\n",2);
if (!_E55VersionInfo($server_name,$serial_val)) {
_DebugComment("Error getting version information from Exchange 5.5\n",1);
$Win32::OLE::Warn = $original_ole_warn_value;
return 0;
}
} else {
_DebugComment("error: $error_num - $error_name on $server_name encountered while trying to perform GetVersion\n",1);
$Win32::OLE::Warn = $original_ole_warn_value;
return 0;
}
} else {
_DebugComment("found e2k tools, so we'll look and see what version of Exchange you have.\n",3);
if (!_E2kVersionInfo($server_name,$serial_val)) {
_DebugComment("Error getting version information from Exchange 2000 tools, let's try the Exch 5.5 way\n",3);
if (!_E55VersionInfo($server_name,$serial_val)) {
_DebugComment("Error getting version information trying the Exch 5.5 way\n",3);
_DebugComment("Error getting version information\n",1);
$Win32::OLE::Warn = $original_ole_warn_value;
return 0;
}
}
}
$Win32::OLE::Warn = $original_ole_warn_value;
if ($serial_val =~ /Version (.*) \(Build (.{6})?(.*)\)/i) {
my %return_struct;
$return_struct{ver}= $1;
$return_struct{build}= $2;
$return_struct{sp}= $3;
if ($return_struct{sp} =~ /service pack (.)/i) {
$return_struct{sp} = $1;
} else {
$return_struct{sp}= "0";
}
if ($return_struct{sp} < 2 && $return_struct{ver} eq "6.0") {
_DebugComment("It's possible that some of the E2K permissions functions will fail due to an incompatible E2K Service Pack level (please see the HTML docs for details)\n",2)
}
if (scalar(@_) == 2) {
%{$_[1]} = %return_struct;
} else {
%{$_[2]} = %return_struct;
}
return 1;
} else {
return 0;
}
}
sub _E55VersionInfo {
my $server_name;
my $error_num;
my $error_name;
if (scalar(@_) == 2) {
$server_name = uc($_[0]);
} else {
_ReportArgError("_E55VersionInfo",scalar(@_));
return 0;
}
my $serial_val;
my $provider;
my $org;
my $ou;
$provider = Win32::Exchange->new("5.5");
if (!$provider) {
_DebugComment("new provider create in GetVersion (E55) failed\n",1);
return 0;
}
if ($provider->GetLDAPPath($server_name,$org,$ou)) {
_DebugComment("returned -> o=$org,ou=$ou\n",3);
} else {
_DebugComment("Error Returning from GetLDAPPath in GetVersion (E55)\n",1);
return 0;
}
bless $provider,"Win32::OLE";
my $exch_server_obj = $provider->GetObject("","LDAP://$server_name/cn=$server_name,cn=Servers,cn=Configuration,ou=$ou,o=$org");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Failed getting the server object in Server container for version info (E55): $error_num,$error_name\n",1);
return 0;
}
$exch_server_obj->GetInfoEx(['serialNumber'],0);
$serial_val = $exch_server_obj->{"serialNumber"};
if ($serial_val =~ /Version (.*) \(Build (.*): Service Pack (.*)\)/i) {
$_[1] = $serial_val;
return 1;
} else {
_DebugComment("GetVersion failed to produce acceptable results (E55)\n",1);
return 0;
}
}
sub _E2kVersionInfo {
my $error_num;
my $error_name;
if (scalar(@_) != 2) {
_ReportArgError("_E2kVersionInfo",scalar(@_));
}
my $server_name = $_[0];
my $exchange_server = Win32::OLE->new("CDOEXM.ExchangeServer");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Failed creating object for version information (E2K) on $server_name -> $error_num ($error_name)\n",1);
return 0;
}
$exchange_server->DataSource->Open($server_name);
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
if ($error_num eq "0x80072032") {
#This error might be there if the server is on another domain... not sure.. I'll need to research more.
#It happenned on an E5.5 server anyway so I didn't need the E2K version strucure.
_DebugComment("Failed opening object for version information (E2K) on $server_name -> $error_num ($error_name)\n",2);
} else {
_DebugComment("Failed opening object for version information (E2K) on $server_name -> $error_num ($error_name)\n",1);
}
return 0;
}
#example output:
#Version 5.5 (Build 2653.23: Service Pack 4)
#Version 6.0 (Build 6249.4: Service Pack 3)
#Version 6.5 (Build 6944.4)
if ($exchange_server->{ExchangeVersion} ne "") {
if (ref($_[1]) eq "HASH") {
my %verhash;
$verhash{'ver'} = $exchange_server->{ExchangeVersion};
$verhash{'dc'} = $exchange_server->{DirectoryServer};
%{$_[1]} = %verhash;
} else {
$_[1] = $exchange_server->{ExchangeVersion};
}
return 1;
} else {
_DebugComment("Failed failed to produce valid version info for $server_name\n",1);
return 0;
}
}
sub _AdodbExtendedSearch {
my $search_string;
my $path;
my $filter;
my $columns;
my $error_num;
my $error_name;
my $fuzzy;
my $return_point;
if (scalar(@_) > 4) {
$search_string = $_[0];
$path = $_[1];
$filter = $_[2];
$columns = $_[3];
if (scalar(@_) == 5) {
$return_point = 4;
} elsif (scalar(@_) == 6) {
$fuzzy = $_[4];
$return_point = 5;
}
} else {
_ReportArgError("_AdodbExtendedSearch (".scalar(@_));
return 0;
}
my @cols = split (/,/,$columns);
if (scalar(@cols) != 2) {
_DebugComment("Only 2 columns can be sent to _AdodbExtendedSearch (total recieved = ".scalar(@cols).")\n",1);
}
my $option;
if ($path =~ /^LDAP:\/\/RootDSE\/(.*)/i) {
$option = $1;
my $RootDSE = Win32::OLE->GetObject("LDAP://RootDSE");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Failed creating object for _AdodbExtendedSearch on $search_string -> $error_num ($error_name)\n",1);
return 0;
}
my $actual_ldap_path = $RootDSE->Get($option);
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Failed creating object for _AdodbExtendedSearch on $search_string -> $error_num ($error_name)\n",1);
return 0;
}
$path = "LDAP://".$actual_ldap_path;
}
my $string = "<$path>;$filter;$columns;subtree";
my $Com = Win32::OLE->new("ADODB.Command");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("path=$path\nfilter=$filter\ncolumns=$columns\n",2);
_DebugComment("Failed creating ADODB.Command object for _AdodbExtendedSearch on $search_string -> $error_num ($error_name)\n",1);
return 0;
}
my $Conn = Win32::OLE->new("ADODB.Connection");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("path=$path\nfilter=$filter\ncolumns=$columns\n",2);
_DebugComment("Failed creating ADODB.Connection object for version information (E55) on $search_string -> $error_num ($error_name)\n",1);
return 0;
}
$Conn->{'Provider'} = "ADsDSOObject";
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("path=$path\nfilter=$filter\ncolumns=$columns\n",2);
_DebugComment("Failed executing ADODB.Command for version information (E55) on $search_string -> $error_num ($error_name)\n",1);
return 0;
}
$Conn->{Open} = "Win32-Exchange a perl module";
$Com->{ActiveConnection} = $Conn;
$Com->{CommandText} = $string;
$Com->{Properties}->{"Page Size"} = 99; #One less than the default of 100 for Exchange so we don't return an empty resultset if more than 100 results are found
my $RS = $Com->Execute();
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("path=$path\nfilter=$filter\ncolumns=$columns\n",2);
_DebugComment("Failed executing ADODB.Command for version information (E55) on $search_string -> $error_num ($error_name)\n",1);
return 0;
}
my $not_found = 1;
my $search_val = "";
while ($search_val eq "") {
if ($fuzzy != 0) {
_DebugComment("fuzzy=$fuzzy\n",3);
if ($RS->Fields($cols[($fuzzy - 1)])->value =~ /$search_string/i) {
if (ref($RS->Fields($cols[($fuzzy - 1)])->value) eq "ARRAY") {
_DebugComment("array - ".@{$RS->Fields($cols[1])->value}[0]."\n",3);
$search_val = @{$RS->Fields($cols[1])->value}[0];
@{$_[$return_point]} = @{$search_val};
return 1;
} else {
_DebugComment("string - ".$RS->Fields($cols[1])->value."\n",3);
$search_val = $RS->Fields($cols[1])->value;
$_[$return_point] = $search_val;
return 1;
}
}
} else {
_DebugComment("found: $cols[0] -- ".($RS->Fields($cols[0])->value)[0]."\n $cols[0] -- ".($RS->Fields($cols[1])->value)[0]."\n -->$search_string\n",4);
if (lc($search_string) eq lc($RS->Fields($cols[0])->value)) {
if (ref($RS->Fields($cols[1])->value) eq "ARRAY") {
_DebugComment("found (not fuzzy) (ARRAY)".$RS->Fields($cols[1])->value."\n",3);
$search_val = @{$RS->Fields($cols[1])->value}[0];
$_[$return_point] = $search_val;
return 1;
} else {
_DebugComment("found (not fuzzy) (string)".$RS->Fields($cols[1])->value."\n",3);
$search_val = $RS->Fields($cols[1])->value;
$_[$return_point] = $search_val;
return 1;
}
}
}
_DebugComment($RS->Fields($cols[0])->value." - ".$RS->Fields($cols[1])->value."\n",3);
if ($RS->EOF) {
$search_val = "-1";
}
$RS->MoveNext;
}
if ($search_val eq "-1") {
_DebugComment("Unable to match valid data for your search on $search_string\n",1);
return 0;
}
}
sub LocateMailboxStore {
my $store_server;
my $storage_group;
my $mb_store;
my $count = "no";
if ($_[0] eq "Win32::Exchange") {
if (scalar(@_) > 4) {
if (scalar(@_) == 5) {
} elsif (scalar(@_) == 6) {
if (ref($_[5]) eq "ARRAY") {
$count = "yes";
} else {
_DebugComment("the fifth argument passed to LocateMailboxStore must be an array (but is optional).\n",1);
return 0;
}
} else {
_ReportArgError("LocateMailboxStore [E2K] (".scalar(@_));
return 0;
}
} else {
_ReportArgError("LocateMailboxStore [E2K] (".scalar(@_));
return 0;
}
} else {
if (scalar(@_) > 3) {
if (scalar(@_) == 4) {
} elsif (scalar(@_) == 5) {
if (ref($_[4]) eq "ARRAY") {
$count = "yes";
} else {
_DebugComment("the fifth argument passed to LocateMailboxStore must be an array (but is optional).\n",1);
return 0;
}
} else {
_ReportArgError("LocateMailboxStore [E2K] (".scalar(@_));
return 0;
}
} else {
_ReportArgError("LocateMailboxStore [E2K] (".scalar(@_));
return 0;
}
}
my $ldap_path;
my $mb_count;
my %storage_groups;
$store_server = $_[0];
$storage_group = $_[1];
$mb_store = $_[2];
if (_EnumStorageGroups($store_server,\%storage_groups)) {
if ($count eq "yes") {
foreach my $sg (keys %storage_groups) {
$mb_count += scalar(keys %{$storage_groups{$sg}});
}
push (@{$_[4]},scalar(keys %storage_groups));
push (@{$_[4]},$mb_count);
}
if (_TraverseStorageGroups(\%storage_groups,$store_server,$storage_group,$mb_store,$ldap_path)) {
$_[3] = $ldap_path;
return 1;
} else {
_DebugComment("Unable to locate valid mailbox store for mailbox creation.\n",1);
return 0;
}
} else {
_DebugComment("Unable to locate valid storage group for mailbox creation.\n",1);
return 0;
}
}
sub _EnumStorageGroups {
my $server_name;
my $error_num;
my $error_name;
if (scalar(@_) == 2) {
$server_name = $_[0];
} else {
_ReportArgError("_EnumStorageGroups (".scalar(@_));
return 0;
}
my $exchange_server = Win32::OLE->new("CDOEXM.ExchangeServer");
$exchange_server->DataSource->Open($server_name);
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Failed opening ADODB ExchangeServer object for Storage Group enumeration on $server_name -> $error_num ($error_name)\n",1);
return 0;
}
my @storegroups = Win32::OLE::in($exchange_server->StorageGroups);
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Failed enumerating Storage Groups on $server_name -> $error_num ($error_name)\n",1);
return 0;
}
my %storage_groups;
my $stor_group_obj = Win32::OLE->new("CDOEXM.StorageGroup");
my $mbx_store_obj = Win32::OLE->new("CDOEXM.MailboxStoreDB");
foreach my $storegroup (@storegroups) {
$stor_group_obj->DataSource->Open($storegroup);
_DebugComment("Stor Name = ".$stor_group_obj->{Name}."\n",3);
foreach my $mbx_store (Win32::OLE::in($stor_group_obj->{MailboxStoreDBs})) {
$mbx_store_obj->DataSource->Open($mbx_store);
_DebugComment(" Mailbox Store = $mbx_store_obj->{Name}\n",3);
$storage_groups{$stor_group_obj->{Name}}{$mbx_store_obj->{Name}}=$mbx_store;
}
}
%{$_[1]} = %storage_groups;
return 1;
}
sub _TraverseStorageGroups {
if (scalar(@_) != 5) {
_ReportArgError("_TraverseStorageGroups [E2K] (".scalar(@_));
return 0;
}
if (ref($_[0]) ne "HASH") {
_DebugComment("Storage group object is not a hash\n",1);
return 0;
}
my %storage_groups = %{$_[0]};
my $info_store_server = $_[1];
my $storage_group = $_[2];
my $mb_store = $_[3];
my $ldap_path;
if (scalar(keys %storage_groups) == 0) {
_DebugComment("No Storage Groups were found\n",1);
return 0;
}
my $sg;
my $mb;
foreach $sg (keys %storage_groups) {
if (scalar(keys %storage_groups) == 1) {
foreach $mb (keys %{$storage_groups{$sg}}) {
if (scalar(keys %{$storage_groups{$sg}}) == 1 || $mb eq $mb_store && $mb_store ne "") {
$_[4] = "LDAP://".$storage_groups{$sg}{$mb};
return 1;
} else {
next;
}
}
_DebugComment("Error locating proper storage group and mailbox db for mailbox creation (1SG)\n",1);
return 0;
} elsif ($sg eq $storage_group && $storage_group ne "") {
foreach $mb (keys %{$storage_groups{$sg}}) {
if (scalar(keys %{$storage_groups{$sg}}) == 1 || $mb eq $mb_store && $mb_store ne "") {
$_[4] = "LDAP://".$storage_groups{$sg}{$mb};
return 1;
} else {
next;
}
}
_DebugComment("Error locating proper storage group and mailbox db for mailbox creation (2+SG)\n",1);
return 0;
}
}
}
sub GetDistinguishedName {
my $server_name;
my $filter;
my $filter_name;
my $result;
if (scalar(@_) == 3) {
$server_name = $_[0];
$filter = $_[1];
} else {
_ReportArgError("GetDistinguishedName",scalar(@_));
}
my %filters;
%filters = ('Home-MDB' => "(objectClass=MHS-Message-Store)",
'Home-MTA' => "(objectClass=MTA)",
);
if ($filters{$filter} ne "") {
$filter_name=$filters{$filter};
} else {
$filter_name = $filter;#If someone wants to actually send a correctly formatted objectClass
}
_DebugComment("filter=$filter_name\n",2);
_DebugComment("search=$server_name\n",2);
if (_AdodbExtendedSearch($server_name,"LDAP://$server_name",$filter_name,"cn,distinguishedName",2,$result)) {
$_[2] = $result;
return 1;
} else {
return 0;
}
}
sub _StripBackslashes {
my $nt_pdc = $_[0];
if ($nt_pdc =~ /^\\\\(.*)/) {
$_[1] = $1;
return 1;
} else {
$_[1] = $nt_pdc;
return 1;
}
}
sub FindCloseDC {
# Requires Exchange 2000 SP2 or greater
# Author: Andy Webb / Simpler-Webb
# Version: 20020903.01
# ------------------------------------------------------------------------
# Copyright (C) 2002 Simpler-Webb, Inc.
# ------------------------------------------------------------------------
# Terms of use: This script is provided AS IS without warranty of any kind,
# either expressed or implied.
#
# This code may be modified from the original form for personal use without
# the permission of the original authors.
#
#With modifications by Steven Manross for functionality requirements of this module
my $host = $_[0];
my $error_name;
my $error_num;
my $WMI = Win32::OLE->new('WbemScripting.SWbemLocator');
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Error creating new WMI object (FindCloseDC)\n",1);
return 0;
} else {
my $Service = $WMI->ConnectServer($host,"root\\microsoftexchangev2");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Error connecting to the exchange WMI root node (FindCloseDC)\n",1);
return 0;
}
my $listDCs = $Service->InstancesOf("Exchange_DSAccessDC");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Error using InstancesOf in WMI object (FindCloseDC)\n",2);
return 0;
}
my $dc = "";
my $isup=0;
foreach my $item (in($listDCs)) {
if ($item->{'Type'} == 0) {
#Configuration Domain Controller
if ($item->{'DirectoryType'} == 0) {
#Active Directory
if ($item->{'IsUp'} == $item->{'IsInSync'} &&
$item->{'IsInSync'} == $item->{'IsFast'} &&
$item->{'IsFast'} == 1) {
$dc = $item->{'Name'};
_DebugComment("Found $dc, and it is: UP, FAST, and INSYNC\n",3);
last;
}
if ($item->{'IsUp'} == $item->{'IsInSync'} &&
$item->{'IsInSync'} == 1 &&
($dc eq "" || $isup == 1)) {
$dc = $item->{'Name'};
$isup=2;
_DebugComment("Found $dc, and it is: UP, and INSYNC\n",4);
#don't return its possible to still find something better
}
if ($item->{'IsUp'} == 1 && $dc eq "") {
$isup = 1;
$dc = $item->{'Name'};
_DebugComment("Found $dc, and it is: UP\n",4);
#don't return its possible to still find something better
}
}
}
}
if ($dc ne "") {
if (scalar(@_) == 2) {
$_[1] = $dc;
return 1;
} else {
return $dc;
}
} else {
_DebugComment("WMI was unable to find a DC that was UP, sorry.\n",1);
return 0;
}
}
}
sub IsMixedModeExchangeOrg {
my $error_num;
my $error_name;
my $ldap_provider = Win32::OLE->new("ADsNamespaces");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Error creating RootDSE object for Native/Mixed Mode determination\n",1);
return 0;
}
my $rootdse = $ldap_provider->GetObject("","LDAP://RootDSE");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Error creating RootDSE object for Native/Mixed Mode determination\n",1);
return 0;
}
my $result;
my $cnc = $rootdse->Get("configurationNamingContext");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Error getting ConfigurationNamingContext property for Native/Mixed Mode determination\n",1);
return 0;
}
if (!Win32::Exchange::_AdodbExtendedSearch("Microsoft Exchange","LDAP://$cnc","(objectCategory=CN=ms-Exch-Organization-Container,CN=Schema,CN=Configuration,DC=manross,DC=net)","cn,DistinguishedName",2,$result)) {
_DebugComment("Error performing ADODB search for Native/Mixed Mode determination\n",1);
return 0;
}
my $org = $ldap_provider->GetObject("","LDAP://$result");
if (!ErrorCheck("0x00000000",$error_num,$error_name)) {
_DebugComment("Error performing GetObject for Native/Mixed Mode determination\n",1);
return 0;
}
$_[0] = $org->{"msExchMixedMode"};
return 1;
}
sub ErrorCheck {
my $last_error_expected = $_[0];
my $error_num;
my $error_name;
my $last_ole_error = Win32::OLE->LastError();
$error_num = sprintf "0x%lx",Win32::OLE->LastError();
if ($error_num eq "0x0") {
$error_num = "0x00000000"
}
my @error_list = split(/\"/,$last_ole_error,3);
$error_name = $error_list[1];
if (lc($error_num) ne lc($last_error_expected)) {
$_[1] = $error_num;
$_[2] = $error_name;
return 0;
} else {
return 1;
}
}
sub _ReportArgError {
_DebugComment("incorrect number of options passed to $_[0] ($_[1])\n",0);
return 1;
}
sub _DebugComment {
if (scalar(@_) == 2) {
print "$_[0]" if ($DEBUG > ($_[1] - 1));
} elsif (scalar(@_) == 3) {
#usually called from another routine (eg.. Win32::Exchange::SMTP::Security or an external script)
print "$_[0]" if ($_[2] > ($_[1] - 1));
} else {
print "DebugComment Error!!!!\n";
}
return 1;
}
1;