context: using System;
  using System.DirectoryServices;
  using System.Collections;
  using System.Data;
  using System.Data.SqlClient;
  using System.Text;
  using System.Reflection;
  
  namespace Inclive
  {
  	/// <summary>
  	/// This is an Active Directory helper class.
  	/// </summary>
  	public class DotnetAD
  	{
  		#region Private Variables
  		public static string ADAdminUser;// = "administrator"; //Administrator username of DC
  		public static string ADAdminPassword;// = "password"; //Password of admin user on DC
  
  		//This needs to have the domain name or IP address on this line
  		public static string ADFullPath;// = "LDAP://192.168.0.3"; 
  		
  		//This must be the domain name of the domain controller (not the computer name, just the domain name)
  		public static string ADServer;// = "sakura.com";
   
  //		private static string ADPath= ADFullPath ; 
  //		private static string ADUser = ADAdminUser ;
  //		private static string ADPassword = ADAdminPassword ;
  
  		#endregion
  
  		#region Enumerations
  		public enum ADAccountOptions
  		{
  			UF_TEMP_DUPLICATE_ACCOUNT = 0x0100,
  			UF_NORMAL_ACCOUNT =0x0200,
  			UF_INTERDOMAIN_TRUST_ACCOUNT =0x0800,
  			UF_WORKSTATION_TRUST_ACCOUNT = 0x1000,
  			UF_SERVER_TRUST_ACCOUNT =0x2000,
  			UF_DONT_EXPIRE_PASSWD=0x10000,
  			UF_SCRIPT =0x0001,
  			UF_ACCOUNTDISABLE=0x0002,
  			UF_HOMEDIR_REQUIRED =0x0008,
  			UF_LOCKOUT=0x0010,
  			UF_PASSWD_NOTREQD=0x0020,
  			UF_PASSWD_CANT_CHANGE=0x0040,
  			UF_ACCOUNT_LOCKOUT=0X0010,
  			UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED=0X0080,
  		}	
  
  
  		public enum LoginResult
  		{
  			LOGIN_OK=0,
  			LOGIN_USER_DOESNT_EXIST,
  			LOGIN_USER_ACCOUNT_INACTIVE
  		}
  
  		#endregion
  
  		#region Methods
  		public DotnetAD()
  		{
  			//
  			// TODO: Add constructor logic here
  			//
  		}
  		
  
  		/// <summary>
  		/// This is used mainy for the logon process to ensure that the username and password match
  		/// </summary>
  		/// <param name="UserName"></param>
  		/// <param name="Password"></param>
  		/// <returns></returns>
  		public static DirectoryEntry UserExists(string UserName, string Password)
  		{
  			//create an instance of the DirectoryEntry
  			DirectoryEntry de = GetDirectoryObject();//UserName,Password);
  
  			//create instance fo the direcory searcher
  			DirectorySearcher deSearch = new DirectorySearcher();
  
  			//set the search filter
  			deSearch.SearchRoot =de;
  			deSearch.Filter = "((objectClass=user)(cn=" + UserName + ")(userPassword=" + Password + "))";
  			deSearch.SearchScope = SearchScope.Subtree;
  
  			//set the property to return
  			//deSearch.PropertiesToLoad.Add("givenName");
              
  			//find the first instance
  			SearchResult results= deSearch.FindOne();
  
  
  			//if the username and password do match, then this implies a valid login
  			//if so then return the DirectoryEntry object
  			de= new DirectoryEntry(results.Path,ADAdminUser,ADAdminPassword,AuthenticationTypes.Secure);
  
  			return de;
  
  		}
  
  
  		public static bool UserExists(string UserName)
  		{
  			//create an instance of the DirectoryEntry
  			DirectoryEntry de = GetDirectoryObject("/" + GetLDAPDomain());
  
  			//create instance fo the direcory searcher
  			DirectorySearcher deSearch = new DirectorySearcher(de);
  
  			//set the search filter
  			deSearch.SearchRoot =de;
  			deSearch.Filter = "(&(objectCategory=user)(cn=" + UserName +"))"; 
              
  			//find the first instance
  			SearchResultCollection results= deSearch.FindAll();
  
  			//if the username and password do match, then this implies a valid login
  			//if so then return the DirectoryEntry object
  			if(results.Count ==0)
  			{
  				return false;
  			}
  			else
  			{
  				return true;
  			}
  			
  		}
  
  		/// <summary>
  		/// This method will not actually log a user in, but will perform tests to ensure
  		/// that the user account exists (matched by both the username and password), and also
  		/// checks if the account is active.
  		/// </summary>
  		/// <param name="UserName"></param>
  		/// <param name="Password"></param>
  		/// <returns></returns>
  		public static DotnetAD.LoginResult  Login(string UserName, string Password)
  		{
  			//first, check if the logon exists based on the username and password
  			//DirectoryEntry de = GetUser(UserName,Password);
  			
  			if(IsUserValid(UserName,Password))
  			{
  				DirectoryEntry de = GetUser(UserName);
  				if(de !=null)
  				{
  					//convert the accountControl value so that a logical operation can be performed
  					//to check of the Disabled option exists.
  					int userAccountControl = Convert.ToInt32(de.Properties["userAccountControl"][0]);
  					de.Close();
  
  					//if the disabled item does not exist then the account is active
  					if(!IsAccountActive(userAccountControl))
  					{
  						return LoginResult.LOGIN_USER_ACCOUNT_INACTIVE;
  					}
  					else
  					{
  						return LoginResult.LOGIN_OK;
  					}
  
  				}
  				else
  				{
  					return LoginResult.LOGIN_USER_DOESNT_EXIST; 
  				}
  			}
  			else
  			{
  				return LoginResult.LOGIN_USER_DOESNT_EXIST; 
  			}
  		}
  
  		/// <summary>
  		/// This will perfrom a logical operation on the userAccountControl values
  		/// to see if the user account is enabled or disabled.  The flag for determining if the
  		/// account is active is a bitwise value (decimal =2)
  		/// </summary>
  		/// <param name="userAccountControl"></param>
  		/// <returns></returns>
  		public static bool IsAccountActive(int userAccountControl)
  		{
  			int userAccountControl_Disabled= Convert.ToInt32(ADAccountOptions.UF_ACCOUNTDISABLE);
  			int flagExists = userAccountControl & userAccountControl_Disabled;
  			//if a match is found, then the disabled flag exists within the control flags
  			if(flagExists >0)
  			{
  				return false;
  			}
  			else
  			{
  				return true;
  			}
  		}
  		/// <summary>
  		/// This method will attempt to log in a user based on the username and password
  		/// to ensure that they have been set up within the Active Directory.  This is the basic UserName, Password
  		/// check.
  		/// </summary>
  		/// <param name="UserName"></param>
  		/// <param name="Password"></param>
  		/// <returns></returns>
  		public static bool IsUserValid (string UserName, string Password)
  		{
  			try
  			{
  				//if the object can be created then return true
  				DirectoryEntry deUser = GetUser(UserName,Password);
  				deUser.Close();
  				return true;
  			}
  			catch(Exception)
  			{
  				//otherwise return false
  				return false;
  			}
  		}
  
  		#region Search Methods
  		/// <summary>
  		/// This will return a DirectoryEntry object if the user does exist
  		/// </summary>
  		/// <param name="UserName"></param>
  		/// <returns></returns>
  		public static DirectoryEntry GetUser(string UserName)
  		{
  			//create an instance of the DirectoryEntry
  			DirectoryEntry de = GetDirectoryObject("/" + GetLDAPDomain());
  
  			//create instance fo the direcory searcher
  			DirectorySearcher deSearch = new DirectorySearcher(de);
  			
  			deSearch.SearchRoot =de;
  			//set the search filter
  			deSearch.Filter = "(&(objectCategory=user)(cn=" + UserName + "))";
  			//deSearch.SearchScope = SearchScope.Subtree;
              
  			//find the first instance
  			SearchResult results= deSearch.FindOne();
  
  			//if found then return, otherwise return Null
  			if(results !=null)
  			{
  				//de= new DirectoryEntry(results.Path,ADAdminUser,ADAdminPassword,AuthenticationTypes.Secure);
  				//if so then return the DirectoryEntry object
  				return results.GetDirectoryEntry();
  			}
  			else
  			{
  				return null;
  			}
  		}
  
  		/// <summary>
  		/// Override method which will perfrom query based on combination of username and password
  		/// This is used with the login process to validate the user credentials and return a user
  		/// object for further validation.  This is slightly different from the other GetUser... methods as this
  		/// will use the UserName and Password supplied as the authentication to check if the user exists, if so then
  		/// the users object will be queried using these credentials.s
  		/// </summary>
  		/// <param name="UserName"></param>
  		/// <param name="password"></param>
  		/// <returns></returns>
  		public static DirectoryEntry GetUser(string UserName, string Password)
  		{
  			//create an instance of the DirectoryEntry
  			DirectoryEntry de = GetDirectoryObject(UserName,Password);
  
  			//create instance fo the direcory searcher
  			DirectorySearcher deSearch = new DirectorySearcher();
  			
  			deSearch.SearchRoot =de;
  			//set the search filter
  			deSearch.Filter = "(&(objectClass=user)(cn=" + UserName + "))";
  			deSearch.SearchScope = SearchScope.Subtree;
  
  			//set the property to return
  			//deSearch.PropertiesToLoad.Add("givenName");
              
  			//find the first instance
  			SearchResult results= deSearch.FindOne();
  		
  			//if a match is found, then create directiry object and return, otherwise return Null
  			if(results !=null)
  			{
  				//create the user object based on the admin priv.
  				de= new DirectoryEntry(results.Path,ADAdminUser,ADAdminPassword,AuthenticationTypes.Secure);
  				return de;
  			}
  			else
  			{
  				return null;
  			}
  
  			
  		}
  		/// <summary>
  		/// This will take a username and query the AD for the user.  When found it will transform
  		/// the results from the poperty collection into a Dataset which can be used by the client
  		/// </summary>
  		/// <param name="UserName"></param>
  		/// <returns></returns>
  		public static DataSet GetUserDataSet(string UserName)
  		{
  			DirectoryEntry de = GetDirectoryObject();
  
  			//create instance fo the direcory searcher
  			DirectorySearcher deSearch = new DirectorySearcher();
  			
  			deSearch.SearchRoot =de;
  			//set the search filter
  			deSearch.Filter = "(&(objectClass=user)(cn=" + UserName + "))";
  			deSearch.SearchScope = SearchScope.Subtree;
              
  			//find the first instance
  			SearchResult results= deSearch.FindOne();
  
  			//get Empty user dataset
  			DataSet dsUser = CreateUserDataSet();
  
  			//If no user record returned, then dont do anything, otherwise
  			//populate
  			if(results != null)
  			{
  				//populate the dataset with the values from the results
  				dsUser.Tables["User"].Rows.Add( PopulateUserDataSet(results,dsUser.Tables["User"]));
  				
  			}
  			de.Close();
  			
  			return dsUser;
  
  		}
  
  		/// <summary>
  		/// This method will return a dataset of user details based on criteria
  		/// passed to the query.  The criteria is in the LDAP format ie
  		/// (cn='xxx')(sn='eee') etc
  		/// </summary>
  		/// <param name="Criteria"></param>
  		/// <returns></returns>
  		public static DataSet GetUsersDataSet(string Criteria)
  		{
  			DirectoryEntry de = GetDirectoryObject();
  
  			//create instance fo the direcory searcher
  			DirectorySearcher deSearch = new DirectorySearcher();
  			
  			deSearch.SearchRoot =de;
  			//set the search filter
  			deSearch.Filter = "(&(objectClass=user)(objectCategory=person)" + Criteria +")";
  			deSearch.SearchScope = SearchScope.Subtree;
              
  			//find the first instance
  			SearchResultCollection  results= deSearch.FindAll();
  
  			//get Empty user dataset
  			DataSet dsUser = CreateUserDataSet();
  
  			//If no user record returned, then dont do anything, otherwise
  			//populate
  			if(results.Count>0)
  			{
  				foreach(SearchResult result in results)
  				{
  					//populate the dataset with the values from the results
  					dsUser.Tables["User"].Rows.Add( PopulateUserDataSet(result,dsUser.Tables["User"]));
  				}
  			}
  
  			de.Close();
  			return dsUser;
  
  		}
  
  		/// <summary>
  		/// This method will query all of the defined AD groups
  		/// and will turn the results into a dataset to be returned
  		/// </summary>
  		/// <returns></returns>
  		public static DataSet GetGroups()
  		{
  			DataSet dsGroup = new DataSet();
  			DirectoryEntry de = GetDirectoryObject();
  
  			//create instance fo the direcory searcher
  			DirectorySearcher deSearch = new DirectorySearcher();
  
  			//set the search filter
  			deSearch.SearchRoot =de;
  			//deSearch.PropertiesToLoad.Add("cn");
  			deSearch.Filter = "(&(objectClass=group)(cn=CS_*))";
              
  			//find the first instance
  			SearchResultCollection   results= deSearch.FindAll();
  
  			//Create a new table object within the dataset
  
gt: 			DataTable tbGroup = dsGroup.Tables.Add("Groups");