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