Lister les groupes auquels appartient un utilisateur (winnt et supérieurs)

Contenu du snippet

Il peut être utile des fois de déterminer si un utilisateur est membre d'un groupe ou de lister les groupes auquel appartient un utilisateur.
Voici donc 2 méthodes permettant de le faire : GetLocalGroupsFor et UserIsMemberOf

Méthodes de l'API Netapi32 utilisées : NetApiBufferFree et NetUserGetLocalGroups
Struct : LOCALGROUP_USERS_INFO_0

Source / Exemple :


using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace Utils
{
	public class UserInfo
	{
		#region API - Methods

		[DllImport("Netapi32.dll")]
		private extern static int NetApiBufferFree(
			IntPtr Buffer
			);

		[DllImport("Netapi32.dll")]
		private extern static int NetUserGetLocalGroups(
			[MarshalAs(UnmanagedType.LPWStr)] string servername, 
			[MarshalAs(UnmanagedType.LPWStr)] string username, 
			int level, 
			int flags, 
			out IntPtr bufptr, 
			int prefmaxlen, 
			out int entriesread, 
			out int totalentries
			);

		#endregion

		#region API - Consts

		private const int MAX_PREFERRED_LENGTH            = -1;

		private const int LG_INCLUDE_INDIRECT             = 0x0001;

		private const int NERR_BASE                       = 2100;
		private const int NERR_Success                    = 0;               // Succes.
		private const int NERR_InvalidComputer            = NERR_BASE + 251; // The computer name is invalid.
		private const int NERR_UserNotFound               = NERR_BASE + 121; // The user name could not be found.

		private const int ERROR_ACCESS_DENIED             = 5;               // The user does not have access to the requested information.
		private const int ERROR_MORE_DATA                 = 234;             // More entries are available. Specify a large enough buffer to receive all entries.

		#endregion

		#region API - Structs

		[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
			private struct LOCALGROUP_USERS_INFO_0
		{
			public string groupname;
		}

		#endregion

		/// <overloads>Obtient la liste des groupes dont l'utilisateur est membre.</overloads>
		/// <summary>
		/// Obtient la liste des groupes dont l'utilisateur est membre, sans inclure les groupes dont l'utilisateur est membre indirectement.
		/// </summary>
		/// --- PARAMS ---
		/// <param name="userName">Nom d'utilisateur.</param>
		/// --- EXCEPTIONS ---
		/// <exception cref="NotSupportedException">
		/// <para>Echec de l'appel à NetUserGetLocalGroups.</para>
		/// <para><i>ou</i></para>
		/// <para>Cette méthode ne peut s'executer que sur WinNT ou supérieur.</para>
		/// </exception>
		/// <exception cref="ArgumentNullException"><c>userName</c> est une référence nulle.</exception>
		/// <exception cref="ArgumentException">
		/// <para>Utilisateur introuvable.</para>
		/// <para><i>ou</i></para>
		/// <para>Nom d'utilsateur invalide.</para>
		/// </exception>
		/// <exception cref="SecurityException">Droits insuffisants pour effectuer l'opération.</exception>
		/// --- RETURN ---
		/// <returns>Liste des groupes dont est membre l'utilisateur.</returns>
		public static string[] GetLocalGroupsFor(string userName)
		{
			try
			{
				return GetLocalGroupsFor(userName, false);
			}
			catch
			{
				throw;
			}
		}

		/// <summary>
		/// Obtient la liste des groupes dont l'utilisateur est membre.
		/// </summary>
		/// --- PARAMS ---
		/// <param name="userName">Nom d'utilisateur.</param>
		/// <param name="includeIndirect"><c>true</c> pour inclure les groupes dont l'utilisateur est membre indirectement, sinon <c>false</c>.</param>
		/// --- EXCEPTIONS ---
		/// <exception cref="NotSupportedException">
		/// <para>Echec de l'appel à NetUserGetLocalGroups.</para>
		/// <para><i>ou</i></para>
		/// <para>Cette méthode ne peut s'executer que sur WinNT ou supérieur.</para>
		/// </exception>
		/// <exception cref="ArgumentNullException"><c>userName</c> est une référence nulle.</exception>
		/// <exception cref="ArgumentException">
		/// <para>Utilisateur introuvable.</para>
		/// <para><i>ou</i></para>
		/// <para>Nom d'utilsateur invalide.</para>
		/// </exception>
		/// <exception cref="SecurityException">Droits insuffisants pour effectuer l'opération.</exception>
		/// --- RETURN ---
		/// <returns>Liste des groupes dont est membre l'utilisateur.</returns>
		public static string[] GetLocalGroupsFor(string userName, bool includeIndirect)
		{
			if ( Environment.OSVersion.Platform != PlatformID.Win32NT )
				throw new NotSupportedException("Cette méthode ne peut s'executer que sur WinNT ou supérieur.");

			if ( userName == null )
				throw new ArgumentNullException("userName", "Ce paramètre ne peut être une référence nulle.");

			int flags = 0;
			if ( includeIndirect )
				flags = LG_INCLUDE_INDIRECT;

			string[] groups;
			IntPtr bufptr = IntPtr.Zero;
			int entriesread = 0;
			int totalentries = 0;

			try
			{
				// récupération des données pour l'utilisateur
				int ret = NetUserGetLocalGroups(
					null,                 // sur cette machine
					userName,             // nom d'utilisateur
					0,                    // level
					flags, 
					out bufptr,           // buffer qui sera alloué par le systeme pour y placer les informations
					MAX_PREFERRED_LENGTH, // le buffer sera alloué de manière à y stocker toutes les informations
					out entriesread, 
					out totalentries
					);
			
				#region Gestion d'erreurs

				if ( ret != NERR_Success )
				{
					if ( ret == ERROR_ACCESS_DENIED )
					{
						throw new System.Security.SecurityException("Droits insuffisants pour effectuer l'opération.");
					}
					else if ( ret == NERR_UserNotFound )
					{
						throw new ArgumentException(userName + " : utilisateur introuvable.");
					}
				}

				#endregion

				groups = new string[totalentries];

				Type typeOfStruct = typeof(LOCALGROUP_USERS_INFO_0);
				int sizeOfStruct = Marshal.SizeOf(typeOfStruct);
				LOCALGROUP_USERS_INFO_0 LGInfo;
				IntPtr currentStructPtr;

				// parcours du buffer
				for ( int i=0; i < totalentries; i++ )
				{
					// définition du pointeur de lecture dans le buffer
					currentStructPtr = new IntPtr( (int)bufptr+(i*sizeOfStruct) );
					// récupération de l'instance de LOCALGROUP_USERS_INFO_0
					LGInfo = (LOCALGROUP_USERS_INFO_0)Marshal.PtrToStructure(currentStructPtr, typeOfStruct);
					groups[i] = LGInfo.groupname;
				}
			}
			catch ( Win32Exception ex )
			{
				throw new NotSupportedException("Echec de l'appel à NetUserGetLocalGroups : " + ex.Message, ex);
			}
			finally
			{
				// même en cas d'erreur, la mémoire doit être libérée
				NetApiBufferFree(bufptr);
			}

			return groups;
		}

		/// <overloads>Détermine si l'utilisateur est membre d'un groupe.</overloads>
		/// <summary>
		/// Détermine si l'utilisateur est membre d'un groupe, sans inclure les groupes dont l'utilisateur est membre indirectement.
		/// </summary>
		/// --- PARAMS ---
		/// <param name="userName">Nom d'utilisateur.</param>
		/// <param name="groupName">Nom du groupe.</param>
		/// <param name="includeIndirect"><c>true</c> pour inclure les groupes dont l'utilisateur est membre indirectement, sinon <c>false</c>.</param>
		/// --- EXCEPTIONS ---
		/// <exception cref="NotSupportedException">
		/// <para>Echec de l'appel à NetUserGetLocalGroups.</para>
		/// <para><i>ou</i></para>
		/// <para>Cette méthode ne peut s'executer que sur WinNT ou supérieur.</para>
		/// </exception>
		/// <exception cref="ArgumentNullException"><c>userName</c> est une référence nulle.</exception>
		/// <exception cref="ArgumentException">
		/// <para>Utilisateur introuvable.</para>
		/// <para><i>ou</i></para>
		/// <para>Nom d'utilsateur invalide.</para>
		/// </exception>
		/// <exception cref="SecurityException">Droits insuffisants pour effectuer l'opération.</exception>
		/// --- RETURN ---
		/// <returns><c>true</c> si l'utilisateur est membre du groupe, sinon <c>false</c>.</returns>
		public static bool UserIsMemberOf(string userName, string groupName)
		{
			try
			{
				return UserIsMemberOf(userName, groupName, false);
			}
			catch
			{
				throw;
			}
		}

		/// <summary>
		/// Détermine si l'utilisateur est membre d'un groupe.
		/// </summary>
		/// --- PARAMS ---
		/// <param name="userName">Nom d'utilisateur.</param>
		/// <param name="groupName">Nom du groupe.</param>
		/// <param name="includeIndirect"><c>true</c> pour inclure les groupes dont l'utilisateur est membre indirectement, sinon <c>false</c>.</param>
		/// --- EXCEPTIONS ---
		/// <exception cref="NotSupportedException">
		/// <para>Echec de l'appel à NetUserGetLocalGroups.</para>
		/// <para><i>ou</i></para>
		/// <para>Cette méthode ne peut s'executer que sur WinNT ou supérieur.</para>
		/// </exception>
		/// <exception cref="ArgumentNullException"><c>userName</c> est une référence nulle.</exception>
		/// <exception cref="ArgumentException">
		/// <para>Utilisateur introuvable.</para>
		/// <para><i>ou</i></para>
		/// <para>Nom d'utilsateur invalide.</para>
		/// </exception>
		/// <exception cref="SecurityException">Droits insuffisants pour effectuer l'opération.</exception>
		/// --- RETURN ---
		/// <returns><c>true</c> si l'utilisateur est membre du groupe, sinon <c>false</c>.</returns>
		public static bool UserIsMemberOf(string userName, string groupName, bool includeIndirect)
		{
			try
			{
				// récupération de la liste des groupes pour l'utilisateur.
				string[] groups = GetLocalGroupsFor(userName, includeIndirect);

				if ( groups.Length == 0 )
					return false;

				System.Collections.Specialized.StringCollection strCol = new System.Collections.Specialized.StringCollection();
				strCol.AddRange(groups);
				return strCol.Contains(groupName);
			}
			catch
			{
				throw;
			}
		}
	}
}

Conclusion :


Docs :
NetUserGetLocalGroups : http://msdn.microsoft.com/en-us/library/aa370655.aspx
NetApiBufferFree : http://msdn.microsoft.com/en-us/library/aa370304.aspx
LOCALGROUP_USERS_INFO_0 : http://msdn.microsoft.com/en-us/library/aa370282.aspx

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.