Compile function Active_Directory_Services(@Service, @Params)
/***********************************************************************************************************************

    This program is proprietary and is not to be used by or disclosed to others, nor is it to be copied without written
    permission from SRP Computer Solutions, Inc.

    Name        :   Active_Directory_Services

    Description :   Handler program for all module related services.

    Notes       :   The generic parameters should contain all the necessary information to process the services. Often
                    this will be information like the data Record and Key ID.

    Parameters  :
        Service         [in] -- Name of the service being requested
        Param1-10   [in/out] -- Additional request parameter holders
        Response       [out] -- Response to be sent back to the Controller (MCP) or requesting procedure

    History     :   (Date, Initials, Notes)
        02/17/23    djs     Original programmer.

***********************************************************************************************************************/

#pragma precomp SRP_PreCompiler

$Insert SERVICE_SETUP
$Insert APP_INSERTS
$Insert REVDOTNETEQUATES

Declare function Logging_Services, Environment_Services, Active_Directory_Services
Declare subroutine Set_Property.Net, Logging_Services, Set_Status, Database_Services

LogPath      = Environment_Services('GetApplicationRootPath') : '\LogFiles\ActiveDirectory'
LogDate      = Oconv(Date(), 'D4/')
LogTime      = Oconv(Time(), 'MTS')
LoggingDTM   = LogDate : ' ' : LogTime   ; // Logging DTM

LogFileName  = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' ActiveDirectoryAuthLog.csv'
Headers      = 'Logging DTM' : @FM : 'Username' : @FM : 'Authenticated'
objADAuthLog = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

LogFileName = LogDate[7, 4] : '-' : LogDate[1, 2] : '-' : LogDate[4, 2] : ' ActiveDirectoryLog.csv'
Headers     = 'Logging DTM' : @FM : 'Operation' : @FM : 'Message'
objADLog    = Logging_Services('NewLog', LogPath, LogFileName, CRLF$, ',', Headers, '', False$, False$)

GoToService

Return Response or ""

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Service Parameter Options
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Options DOMAIN      = 'INFINEON', 'INFINEON.COM', 'NA.INFINEON.COM'
Options DESCRIPTION_BOOL = True$, False$
Options AD_GROUP_TYPE = 'DL', 'SECURITY'

//-----------------------------------------------------------------------------
// SERVICES
//-----------------------------------------------------------------------------


Service AuthenticateUser(Username, Password, Domain)
    
    Authenticated      = False$
    DotNetHandle       = StartDotNet("","4.0")
    DotNetDir          = CheckDotNet('4.0'):'\'
    AccountMgmtDllPath = DotNetDir:'System.DirectoryServices.AccountManagement.dll'
    Set_Property.Net(DotNetHandle, "AssemblyName", AccountMgmtDllPath)
    If Not(Get_Status(errCode)) then
        Params             = 'Domain':@FM:Domain
        ParamTypes         = 'System.DirectoryServices.AccountManagement.ContextType':@FM:'System.String'
        objPC              = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalContext", 0, Params, ParamTypes)
        If Not(Get_Status(errCode)) then
            Params        = Username:@FM:Password
            ParamTypes    = 'System.String':@FM:'System.String'
            Authenticated = Send_Message.Net(objPC, 'ValidateCredentials', Params, ParamTypes, 0)
            Swap 'True'  with True$ in Authenticated
            Swap 'False' with False$ in Authenticated
            Free_Class.Net(objPC)
        end
    end
    LogData    = ''
    LogData<1> = LoggingDTM
    LogData<2> = Username
    LogData<3> = Authenticated
    Logging_Services('AppendLog', objADAuthLog, LogData, @RM, @FM, False$)
    Response   = Authenticated
    
end service


Service GetADGroups(Username, Domain)
    
    ADGroups           = ''
    DotNetHandle       = StartDotNet("","4.0")
    DotNetDir          = CheckDotNet('4.0'):'\'
    AccountMgmtDllPath = DotNetDir:'System.DirectoryServices.AccountManagement.dll'
    Set_Property.Net(DotNetHandle, "AssemblyName", AccountMgmtDllPath)
    If Not(Get_Status(errCode)) then
        Params             = 'Domain':@FM:'Infineon'
        ParamTypes         = 'System.DirectoryServices.AccountManagement.ContextType':@FM:'System.String'
        objPC              = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalContext", 0, Params, ParamTypes)
        If Not(Get_Status(errCode)) then
            objUserPrincipal = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.UserPrincipal", 0, objPC, 'RevDotNet')
            If Not(Get_Status(errCode)) then
                Set_Property.Net(objUserPrincipal, 'Name', Username)
                objPrinSearcher = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalSearcher", 0, objUserPrincipal, 'RevDotNet')
                If Not(Get_Status(errCode)) then
                    objPrin = Send_Message.Net(objPrinSearcher, 'FindOne', '', '', 1)
                    If Not(Get_Status(errCode)) then
                        Name                = Get_Property.Net(objPrin, 'Name', 0)
                        objPrinSearchResult = Send_Message.Net(objPrin, 'GetGroups', '', '', 1)
                        If Not(Get_Status(errCode)) then
                            objEnum = Send_Message.Net(objPrinSearchResult, 'GetEnumerator', '', '', 1)
                            If Not(Get_Status(errCode)) then
                                Loop
                                    Done = Send_Message.Net(objEnum, 'MoveNext', '', '', 0)
                                Until Done EQ 'False'
                                    If Not(Get_Status(errCode)) then
                                        objCurrPrin = Get_Property.Net(objEnum, 'Current', 1)
                                        If Not(Get_Status(errCode)) then
                                            CurrPrinName = Get_Property.Net(objCurrPrin, 'Name', 0)
                                            If CurrPrinName NE 'Domain Users' then ADGroups<-1> = CurrPrinName
                                            Free_Class.Net(objCurrPrin)
                                        end 
                                    end
                                Repeat
                                Free_Class.Net(objEnum)
                            end
                            Free_Class.Net(objPrinSearchResult)
                        end
                        Free_Class.Net(objPrin)
                    end
                    Free_class.Net(objPrinSearcher)
                end
                Free_Class.Net(objUserPrincipal)
            end
            Free_Class.Net(objPC)
        end
    end
    Response = ADGroups
    
End Service



Service GetComputerDomain()
    
    Domain       = ''
    DotNetHandle = StartDotNet("","4.0")
    DotNetDir    = CheckDotNet('4.0'):'\'
    DirDllPath   = DotNetDir:'System.DirectoryServices.dll'
    Set_Property.Net(DotNetHandle, "AssemblyName", DirDllPath)
    If Not(Get_Status(errCode)) then
        objDomain =  Create_Class.Net(DotNetHandle, "System.DirectoryServices.ActiveDirectory.Domain", 0, '', '')
        If Not(Get_status(errCode)) then
            ObjCompDomain = Send_Message.Net(objDomain, 'GetComputerDomain', '', '', True$)
            If Not(Get_Status(errCode)) then
                Domain = Get_Property.Net(objCompDomAin, 'Name', False$)
                Free_class.Net(objCompDomain)
            end
            Free_Class.Net(objDomain)
        end
    end
    Response = Domain
    
end service

//----------------------------------------------------------------------------------------------------------------------
// GetADGroupsByString
//
// SearchString - [Required] Defines the string name or description of the group you want to search for. Accepts * as a wildcard
// Domain - Defines the domain to search in. If null will set to 'INFINEON'
// SearchByDescription - Boolean flag to indicate if you'd like to search for groups that match the description. Set to false by default.
// GroupType - Used to indicate if you want only Security Groups or only Distribution list group types. If you want both don't set this variable.
//              If you want only security groups, set to SECURITY. If you want only distribution lists, set to DL
//
// Takes in a search string either whole or part of a full string and returns a @FM delimited list of matching results. Supports * as a wildcard.
// For each @FM there are three values that are @VM delimited. First value is the Group Name, second value is the group description, third value is
// the groups type, either SECURITY or DL
//
// 9/26/2024 - [JRO] Initial Programmer.
//----------------------------------------------------------------------------------------------------------------------
Service GetADGroupsByString(SearchString, Domain=DOMAIN, SearchByDescription=DESCRIPTION_BOOL, GroupType=AD_GROUP_TYPE)
	
    Set_Status(0)
    ErrMessage         = ''
    ADGroups           = ''
    If SearchString EQ '' then
        ErrMessage = 'Error calling GetADGroupsByString: Search string was null.'
    end
    If Domain EQ '' then
        Domain = 'INFINEON'
    end
    If SearchByDescription EQ ''  then
        SearchByDescription = False$
    end
    If ErrMessage EQ '' then
        DotNetHandle       = StartDotNet("","4.0")
        DotNetDir          = CheckDotNet('4.0'):'\'
        AccountMgmtDllPath = DotNetDir:'System.DirectoryServices.AccountManagement.dll'
        Set_Property.Net(DotNetHandle, "AssemblyName", AccountMgmtDllPath)
        If Not(Get_Status(errCode)) then
            Params             = 'Domain':@FM:Domain
            ParamTypes         = 'System.DirectoryServices.AccountManagement.ContextType':@FM:'System.String'
            objPC              = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalContext", 0, Params, ParamTypes)
            If Not(Get_Status(errCode)) then
                objGroupPrincipal = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.GroupPrincipal", 0, objPC, 'RevDotNet')
                If Not(Get_Status(errCode)) then
                    If SearchByDescription then
                        Set_Property.Net(objGroupPrincipal, 'Description', SearchString)
                    end else
                        Set_Property.Net(objGroupPrincipal, 'Name', SearchString)
                    end
                    Begin Case
                        Case GroupType EQ 'DL'
                            Set_Property.Net(objGroupPrincipal, 'IsSecurityGroup', 'False')
                        Case GroupType EQ 'SECURITY'
                            Set_Property.Net(objGroupPrincipal, 'IsSecurityGroup', 'True')
                    End Case
                    objPrinSearcher = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalSearcher", 0, objGroupPrincipal, 'RevDotNet')
                    If Not(Get_Status(errCode)) then
                        objSearchResultCollection = Create_Class.Net(objPrinSearcher, 'System.DirectoryServices.AccountManagement.PrincipalSearchResult', 0, '', '', 'RevDotNet')
                        objSearchResultCollection = Send_Message.Net(objPrinSearcher, 'FindAll', '', '', 1)
                        
                        if  Not(Get_Status(errCode)) then
                            
                            objEnum = Send_Message.Net(objSearchResultCollection, 'GetEnumerator', '', '', 1)
                            If Not(Get_Status(errCode)) then
                                Void    = Send_Message.Net(objEnum, 'Reset', '', '', 0)
                                Loop
                                    Done      = Send_Message.Net(objEnum, 'MoveNext', '', '', 0)
                                Until Done EQ 'False' OR Done EQ ''
                                    If Not(Get_Status(errCode)) then
                                        ThisGroup = Get_Property.Net(objEnum, 'Current', 1)
                                        If Not(Get_Status(errCode)) then
                                            ADGroup      = ''
                                            ADGroup<1,1> = Get_Property.Net(ThisGroup, 'Name', 0)
                                            ADGroup<1,2> = Get_Property.Net(ThisGroup, 'Description', 0)
                                            IsSecGroup   = Get_Property.Net(ThisGroup, 'IsSecurityGroup', 0)
                                            If IsSecGroup EQ 'True' then
                                                ADGroup<1,3> = 'SECURITY'
                                            end else
                                                ADGroup<1,3> = 'DL'
                                            end
                                            ADGroups<-1> = ADGroup
                                            Free_Class.Net(ThisGroup)
                                        end else
                                            Error_Services('Add', 'DotNet Error, Error getting group properties')
                                        end
                                    end else
                                        Error_Services('Add', 'DotNet Error, Error iterating through results')
                                    end
                                Repeat
                                Free_Class.Net(objEnum)
                                If ADGroups EQ '' then
                                    ErrMessage = 'No groups were found.'
                                end
                            end else
                                ErrMessage = 'DotNet Error, Error getting object enumerator'
                            end
                            Free_Class.Net(objSearchResultCollection)
                        end else
                            ErrMessage = 'DotNet Error, Error getting AD search results'
                        end
                        Free_Class.Net(objPrinSearcher)
                    end else
                        ErrMessage = 'DotNet Error, Error creating AD searcher.'
                    end
                    Free_Class.Net(objGroupPrincipal)
                end else
                    ErrMessage = 'DotNet Error, Error creating group principle.'
                end
                Free_Class.Net(objPC)
            end else
                ErrMessage = 'DotNet Error, Error creating principle context.'
            end
        end else
            ErrMessage = 'DotNet Error, Error starting DotNet.'
        end
        If ErrMessage EQ ''  then
            Message    = 'Successfully retrieved list of AD groups matching the search string ' : SearchString : ' within the ' : Domain : ' domain.'
            LogData    = ''
            LogData<1> = LoggingDTM
            LogData<2> = 'GetADGroupsByString'
            LogData<3> = Message
            Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
        end else   
            LogData    = ''
            LogData<1> = LoggingDTM
            LogData<2> = 'GetADGroupsByString'
            LogData<3> = 'Error list of groups matching the search string ' : SearchString : ':' : ErrMessage
            Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
            Error_Services('Add', ErrMessage)
        end
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = 'GetADGroupsByString'
        LogData<3> = ErrMessage
        Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrMessage)
    end
    
    Response = ADGroups
end service

//----------------------------------------------------------------------------------------------------------------------
// GetADGroupMembersByGroupDescription
//
// DescriptionName - [Required] Defines the string name or description of the group you want to find.
// Domain - Defines the domain to search in. If null will set to 'INFINEON'
//
// Takes in a whole string description of a groupand returns a @FM delimited list of matching results. Does not support * as a wildcard.
// If a matching group is found it calls GetADGroupMembersByGroupName to get the group member list.
// It then returns a @FM delimited list of users.
// For each @FM there are three @VM delimited values. They are the Users AD name, their display name, and their email.
//
// 9/26/2024 - [JRO] Initial Programmer.
//----------------------------------------------------------------------------------------------------------------------
Service GetADGroupMembersByGroupDescription(DescriptionName, Domain=DOMAIN)
    Set_Status(0)
    ErrMessage = ''
    GroupUsers = ''
    If DescriptionName EQ '' then
        ErrMessage = 'Error calling GetADGroupMembersByGroupDescription: Description was null.'
    end
    If Domain EQ '' then
        Domain = 'INFINEON'
    end
    If ErrMessage EQ '' then
        DotNetHandle       = StartDotNet("","4.0")
        DotNetDir          = CheckDotNet('4.0'):'\'
        AccountMgmtDllPath = DotNetDir:'System.DirectoryServices.AccountManagement.dll'
        Set_Property.Net(DotNetHandle, "AssemblyName", AccountMgmtDllPath)
        If Not(Get_Status(errCode)) then
            Params             = 'Domain':@FM:Domain
            ParamTypes         = 'System.DirectoryServices.AccountManagement.ContextType':@FM:'System.String'
            objPC              = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalContext", 0, Params, ParamTypes)
            If Not(Get_Status(errCode)) then
                objGroupPrincipal = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.GroupPrincipal", 0, objPC, 'RevDotNet')
                If Not(Get_Status(errCode)) then
                    Set_Property.Net(objGroupPrincipal, 'Description', DescriptionName)
                    objPrinSearcher = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalSearcher", 0, objGroupPrincipal, 'RevDotNet')
                    If Not(Get_Status(errCode)) then
                        objSearchResult = Create_Class.Net(objPrinSearcher, 'System.DirectoryServices.AccountManagement.PrincipalSearcher', 0, '', '', 'RevDotNet')
                        objSearchResult = Send_Message.Net(objPrinSearcher, 'FindOne', '', '', 1)
                        if  Not(Get_Status(errCode)) then
                            GroupName = Get_Property.Net(objSearchResult, 'Name', 0)
                            If GroupName NE '' then
                                GroupUsers = Active_Directory_Services('GetADGroupMembersByGroupName', GroupName, Domain)
                                If GroupUsers EQ '' then
                                    ErrMessage = 'No group members were returned.'
                                end
                            end else
                                ErrMessage = 'No group matching that description was found.'
                            end
                            Free_Class.Net(objSearchResult)
                        end else
                            ErrMessage = 'DotNet Error, Error getting AD search results'
                        end
                        Free_Class.Net(objPrinSearcher)
                    end else
                        ErrMessage = 'DotNet Error, Error creating AD searcher.'
                    end
                    Free_Class.Net(objGroupPrincipal)
                end else
                    ErrMessage = 'DotNet Error, Error creating group principle.'
                end
                Free_Class.Net(objPC)
                
            end else
                ErrMessage =  'DotNet Error, Error creating principle context.'
            end
        end
        If ErrMessage EQ ''  then
            Message    = 'Successfully retrieved members of AD group with description of ' : DescriptionName : ' within the ' : Domain : ' domain.'
            LogData    = ''
            LogData<1> = LoggingDTM
            LogData<2> = 'GetADGroupMembersByGroupDescription'
            LogData<3> = Message
            Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
        end else   
            LogData    = ''
            LogData<1> = LoggingDTM
            LogData<2> = 'GetADGroupMembersByGroupDescription'
            LogData<3> = 'Error getting members of group with description ' : DescriptionName : ':' : ErrMessage
            Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
            Error_Services('Add', ErrMessage)
        end
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = 'GetADGroupMembersByGroupDescription'
        LogData<3> = ErrMessage
        Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrMessage)
    end
    Response = GroupUsers
end service

//----------------------------------------------------------------------------------------------------------------------
// GetADGroupMembersByGroupName
//
// GroupName - [Required] Defines the Group name of the group you want to find.
// Domain - Defines the domain to search in. If null will set to 'INFINEON'
//
// Takes in a whole string group name of a group and returns a @FM delimited list of matching results. Does not support * as a wildcard.
// If a matching group is found it gets a group members list and calls GetADUserAttributes for each member to get the user attributes
// It then returns a @FM delimited list of users.
// For each @FM there are three @VM delimited values. They are the Users AD name, their display name, and their email.
//
// 9/26/2024 - [JRO] Initial Programmer.
//----------------------------------------------------------------------------------------------------------------------
Service GetADGroupMembersByGroupName(GroupName, Domain=DOMAIN)
    Set_Status(0)
    Users              = ''
    ErrMessage         = ''
    If GroupName EQ '' then
        ErrMessage = 'Error calling GetADGroupMembersByGroupName: Group name was null.'
    end
    If Domain EQ '' then
        Domain = 'INFINEON'
    end
    If ErrMessage EQ '' then
        DotNetHandle       = StartDotNet("","4.0")
        DotNetDir          = CheckDotNet('4.0'):'\'
        AccountMgmtDllPath = DotNetDir:'System.DirectoryServices.AccountManagement.dll'
        Set_Property.Net(DotNetHandle, "AssemblyName", AccountMgmtDllPath)
        If Not(Get_Status(errCode)) then
            Params             = 'Domain':@FM:Domain
            ParamTypes         = 'System.DirectoryServices.AccountManagement.ContextType':@FM:'System.String'
            objPC              = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalContext", 0, Params, ParamTypes)
            If Not(Get_Status(errCode)) then
                objGroupPrincipal = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.GroupPrincipal", 0, objPC, 'RevDotNet')
                If Not(Get_Status(errCode)) then
                    ThisGroup = Send_Message.Net(objGroupPrincipal, 'FindByIdentity', objPC:@FM:GroupName, 'RevDotNet':@FM:'System.String', 1)
                    objPrinSearcher = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalSearcher", 0, objGroupPrincipal, 'RevDotNet')
                    if  Not(Get_Status(errCode)) then
                        objPrinSearcher = Send_Message.Net(ThisGroup, 'GetMembers', '', '', 1)
                        if  Not(Get_Status(errCode)) then
                            objEnum = Send_Message.Net(objPrinSearcher, 'GetEnumerator', '', '', 1)
                            Loop
                                Done = Send_Message.Net(objEnum, 'MoveNext', '', '', 0)
                            Until Done EQ 'False' OR Done EQ ''
                                If Not(Get_Status(errCode)) then
                                    ThisUser = Get_Property.Net(objEnum, 'Current', 1)
                                    If Not(Get_Status(errCode)) then
                                        Username         = Get_Property.Net(ThisUser, 'Name', 0)
                                        UserADAttributes = Active_Directory_Services('GetADUserAttributes', Username, Domain)
                                        swap @FM with @VM in UserADAttributes
                                        users<-1>        = UserADAttributes
                                        Free_Class.Net(username)
                                    end
                                    Free_Class.Net(ThisUser)
                                end
                            Repeat
                            If Users EQ '' then
                                ErrMessage = 'No group members were returned.'
                            end
                            Free_Class.Net(objEnum)
                        end else
                            ErrMessage = 'Error applying searcher object for group.'
                        end
                    end else
                        ErrMessage = 'Error creating searcher object.'
                    end
                    Free_Class.Net(objPrinSearcher)
                end else
                    ErrMessage = 'Error creating Group Principle object.'
                end
            end else
                ErrMessage = 'Error creating Principle Context object.'
            end
            Free_Class.Net(objGroupPrincipal)
        end else
            ErrMessage = 'Error creating dotnet object.'
        end
        Free_Class.Net(objPC)
        If ErrMessage EQ ''  then
            Message    = 'Successfully retrieved members of AD group ' : GroupName : ' within the ' : Domain : ' domain.'
            LogData    = ''
            LogData<1> = LoggingDTM
            LogData<2> = 'GetADGroupMembersByGroupName'
            LogData<3> = Message
            Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
        end else   
            LogData    = ''
            LogData<1> = LoggingDTM
            LogData<2> = 'GetADGroupMembersByGroupName'
            LogData<3> = 'Error getting members of group with name ' : GroupName : ':' : ErrMessage
            Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
            Error_Services('Add', ErrMessage)
        end
    end else
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = 'GetADGroupMembersByGroupName'
        LogData<3> = ErrMessage
        Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrMessage)
    end
    Response = Users
end service

//----------------------------------------------------------------------------------------------------------------------
// GetADUserAttributes
//
// Username - The exact AD username of the user you are looking for.
// Domain - Sets to infineon by Default. override with and string value
//
// Searches for a matching user in Active Directory and returns a user with @VM delimited attributes.
// First value is the AD User Name, Second value is the Display Name, and third value is the email.
//----------------------------------------------------------------------------------------------------------------------
Service GetADUserAttributes(Username, Domain=DOMAIN)
    Set_Status(0)
    ThisUser   = ''
    ErrMessage = ''
    If Username EQ '' then
        ErrMessage = 'Username was null.'
    end
    If Domain EQ ''  then
        Domain = 'INFINEON'
    end
    If ErrMessage EQ '' then
        DotNetHandle       = StartDotNet("","4.0")
        DotNetDir          = CheckDotNet('4.0'):'\'
        AccountMgmtDllPath = DotNetDir:'System.DirectoryServices.AccountManagement.dll'
        Set_Property.Net(DotNetHandle, "AssemblyName", AccountMgmtDllPath)
        If Not(Get_Status(errCode)) then
            Params             = 'Domain':@FM:'Infineon'
            ParamTypes         = 'System.DirectoryServices.AccountManagement.ContextType':@FM:'System.String'
            objPC              = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalContext", 0, Params, ParamTypes)
            If Not(Get_Status(errCode)) then
                objUserPrincipal = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.UserPrincipal", 0, objPC, 'RevDotNet')
                If Not(Get_Status(errCode)) then
                    Set_Property.Net(objUserPrincipal, 'Name', Username)
                    objPrinSearcher = Create_Class.Net(DotNetHandle, "System.DirectoryServices.AccountManagement.PrincipalSearcher", 0, objUserPrincipal, 'RevDotNet')
                    If Not(Get_Status(errCode)) then
                        objUserPrincipal = Send_Message.Net(objPrinSearcher, 'FindOne', '', '', 1)
                        If Not(Get_Status(errCode)) then
                            ADUserName  = Get_Property.Net(objUserPrincipal, 'Name', 0)
                            Email       = Get_Property.Net(objUserPrincipal, 'EmailAddress', 0)
                            DisplayName = Get_Property.Net(objUserPrincipal, 'DisplayName', 0)
                            ThisUser<1> = ADUserName
                            ThisUser<2> = DisplayName
                            ThisUser<3> = Email
                        end else
                            //Error getting user object
                            ErrMessage = 'Error getting user attributes of user: ' : Username : ' within the ' : Domain : ' domain.'
                        end
                        Free_class.Net(objPrinSearcher)
                    end else
                        //error creating principle searcher
                        ErrMessage = 'Error creating principle searcher. Username: ' : Username : ' within the ' : Domain : ' domain.'
                    end
                    Free_Class.Net(objUserPrincipal)
                end else
                    //error creating user principle object
                    ErrMessage = 'Error creating principle searcher. Username' : Username : 'within the ' : Domain : ' domain.'
                end
                Free_Class.Net(objPC)
            end else
                //Error creating principle context
                ErrMessage = 'Error creating principle context Username' : Username : 'within the ' : Domain : ' domain.'
            end
        end else
            //error calling dotnet
            ErrMessage = 'Error creating dotnet object. Username' : Username : 'within the ' : Domain : ' domain.'
        end
        If ErrMessage EQ ''  then
            Message    = 'Successfully retrieved attributes of user ' : Username : ' within the ' : Domain : ' domain.'
            LogData    = ''
            LogData<1> = LoggingDTM
            LogData<2> = 'GetADUserAttributes'
            LogData<3> = Message
            Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
        end else   
            LogData    = ''
            LogData<1> = LoggingDTM
            LogData<2> = 'GetADUserAttributes'
            LogData<3> = 'Error getting attributes of user ' : Username : ':' : ErrMessage
            Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
            Error_Services('Add', ErrMessage)
        end
    end else
        //Error, missing username or domain name
        LogData    = ''
        LogData<1> = LoggingDTM
        LogData<2> = 'GetADUserAttributes'
        LogData<3> = 'Error getting user attributes: ' : ErrMessage
        Logging_Services('AppendLog', objADLog, LogData, @RM, @FM, False$)
        Error_Services('Add', ErrMessage)
    end
    Response = ThisUser
end service

