N'ayant pas eu de réponse suite à une question sur le forum sur comment lister les permissions de tous les users des dossiers partagés d'un ordi, il a bien fallu que je démerde +/- tout seul. Voici donc la solution. Vraiment pas super facile, merci Microsoft, comme d'hab : (((
Source / Exemple :
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <aclapi.h>
#include <lmshare.h>
#include <Lm.h>
#include "NetEnum.h"
/***************************************/
/***************************************/
/* CountNetShareEnum */
/***************************************/
/***************************************/
DWORD CountNetShareEnum
(
const char* p_pcServerName,
int* p_TotalOfShareRessource
)
{
PSHARE_INFO_502 l_PShareInfo, l_BufPShareInfo;
NET_API_STATUS l_nStatus;
DWORD l_dwErr=0,l_dwTr=0,l_dwResume=0, i;
LPWSTR l_pwUnicodeServerName = NULL;
int l_iSize;
try
{
// si on entre un nom de PC, on transforme le nom AINSI en UNICODE
if (p_pcServerName != NULL)
{
l_iSize = strlen (p_pcServerName) + 1;
l_pwUnicodeServerName = new WORD [l_iSize];
l_pwUnicodeServerName[0] = 0;
MultiByteToWideChar (CP_ACP, 0, p_pcServerName, -1, l_pwUnicodeServerName, l_iSize);
}
do // begin do
{
// on liste tout ou partie des dossiers partagés de p_pcServerName
l_nStatus = NetShareEnum (l_pwUnicodeServerName, 502, (LPBYTE *) &l_BufPShareInfo, -1, &l_dwErr, &l_dwTr, &l_dwResume);
if(l_nStatus != ERROR_SUCCESS && l_nStatus != ERROR_MORE_DATA)
throw l_nStatus;
// on fait pointer l_PShareInfo sur les données trouvées
l_PShareInfo=l_BufPShareInfo;
// pour chaque entrée trouvée (jusqu'à dwErr) on incrémente
for(i=1;i<=l_dwErr;i++)
{
l_PShareInfo++;
(*p_TotalOfShareRessource) ++;
}
// on libère le buffer
NetApiBufferFree(l_BufPShareInfo);
}
while (l_nStatus==ERROR_MORE_DATA);
}
catch (DWORD)
{
}
return l_nStatus;
}
/***************************************/
/***************************************/
/* CountNetShareEnum */
/***************************************/
/***************************************/
DWORD RetrieveNetShareEnum
(
const char* p_pcServerName,
const int p_TotalOfShareRessource,
int* p_piCurrentIndex,
STL_SHARE_INFO* p_ShareInfoArray
)
{
PSHARE_INFO_502 l_PShareInfo, l_BufPShareInfo;
NET_API_STATUS l_nStatus;
DWORD l_dwCount=0,l_dwTr=0,l_dwResume=0, i;
DWORD l_dwRetVal;
LPWSTR l_pwUnicodeServerName = NULL;
LPWSTR l_pwUnicodeRemark = NULL;
LPWSTR l_pwUnicodePath = NULL;
LPWSTR l_pwUnicodePassword = NULL;
BOOL l_bRetVal;
PACL l_Dacl;
int l_iSize, l_iTotalEntriesIndex;
unsigned long l_ulNbOfEntries = 0;
PEXPLICIT_ACCESS l_oAccessArray = NULL;
try
{
// si on entre un nom de PC, on transforme le nom AINSI en UNICODE
if (p_pcServerName != NULL)
{
l_iSize = strlen (p_pcServerName) + 1;
l_pwUnicodeServerName = new WORD [l_iSize];
l_pwUnicodeServerName[0] = 0;
MultiByteToWideChar (CP_ACP, 0, p_pcServerName, -1, l_pwUnicodeServerName, l_iSize);
}
// on mets le compteur à 0
do // begin do
{
// on récupère une partie des dossiers réseaux
l_nStatus = NetShareEnum (l_pwUnicodeServerName, 502, (LPBYTE *) &l_BufPShareInfo, -1, &l_dwCount, &l_dwTr, &l_dwResume);
if(l_nStatus != ERROR_SUCCESS && l_nStatus != ERROR_MORE_DATA)
throw l_nStatus;
l_PShareInfo=l_BufPShareInfo;
// pour tous les dossiers trouvés, on va recopier les infos pertinentes dans notre structure STL_SHARE_INFO
for(i=1;i<=l_dwCount;i++)
{
// on convertit du unicode en char pour récupérer le netname
l_dwRetVal = WideCharToMultiByte ( CP_ACP,
WC_NO_BEST_FIT_CHARS,
l_PShareInfo->shi502_netname,
-1,
p_ShareInfoArray[*p_piCurrentIndex].cNetname,
_MAX_PATH,
NULL,
NULL);
if (l_dwRetVal == 0)
throw (DWORD) "STL_UNICODE_TO_AINSI_ERROR";
// on teste la validité du SID afin de ne pas lister des infos inexistantes (et faire tout exploser)
// si le SID est invalide (NULL notamment)
l_bRetVal = IsValidSecurityDescriptor(l_PShareInfo->shi502_security_descriptor);
// si le SID est valide, on liste les infos
if (l_bRetVal != 0)
{
int size = strlen (p_ShareInfoArray[*p_piCurrentIndex].cNetname) - 1;
if (p_ShareInfoArray[*p_piCurrentIndex].cNetname[size] != '$')
{
// comme ce sont les values DWORD, on fait une copie brute de fonte
p_ShareInfoArray[*p_piCurrentIndex].dwType = l_PShareInfo->shi502_type;
p_ShareInfoArray[*p_piCurrentIndex].dwPermissions = l_PShareInfo->shi502_permissions;
p_ShareInfoArray[*p_piCurrentIndex].dwMax_uses = l_PShareInfo->shi502_max_uses;
p_ShareInfoArray[*p_piCurrentIndex].dwCurrent_uses = l_PShareInfo->shi502_current_uses;
p_ShareInfoArray[*p_piCurrentIndex].dwReserved = l_PShareInfo->shi502_reserved;
// pour les vlaues en unicode, on fait la transformation en AINSI
l_dwRetVal = WideCharToMultiByte ( CP_ACP,
WC_NO_BEST_FIT_CHARS,
l_PShareInfo->shi502_remark,
-1,
p_ShareInfoArray[*p_piCurrentIndex].cRemark,
_MAX_PATH,
NULL,
NULL);
if (l_dwRetVal == 0)
throw (DWORD) "STL_UNICODE_TO_AINSI_ERROR";
l_dwRetVal = WideCharToMultiByte ( CP_ACP,
WC_NO_BEST_FIT_CHARS,
l_PShareInfo->shi502_path,
-1,
p_ShareInfoArray[*p_piCurrentIndex].cPath,
_MAX_PATH,
NULL,
NULL);
if (l_dwRetVal == 0)
throw (DWORD) "STL_UNICODE_TO_AINSI_ERROR";
BOOL l_bDaclPresent, l_bDaclDefault;
/******************************************************************************************/
/* A cet endroit, si le l_PShareInfo->shi502_security_descriptor est NULL (ou le */
/* l_PShareInfo->shi502_reserved est = 0 (ils semblent marcher ensemble...) cela crash le */
/* le systeme completement. Ceci peut être bypassé en délétant le rep à pb et en le */
/* recréant... Bizarre, vous avez dit bizarre :D:D:D */
/******************************************************************************************/
// on récupère le Dacl lié au SID? C'est dans ce Dacl que l'on va trouver les infos de partage et de persmissions....
l_bRetVal = GetSecurityDescriptorDacl(l_PShareInfo->shi502_security_descriptor, &l_bDaclPresent, &l_Dacl, &l_bDaclDefault);
if (l_bRetVal == 0)
throw (DWORD) "STL_DACL_ERROR";
// on liste de façon explicite les permissions et users. La fonction renvoie un tableau de ExplicitEntries
l_dwRetVal = GetExplicitEntriesFromAcl ( l_Dacl,
&l_ulNbOfEntries,
&l_oAccessArray);
if (l_dwRetVal != 0)
throw l_dwRetVal;
// pour chaque entrée dans le tableau de EXPLICIT_ACCESS, on regarde si le trustee est identifié par un username, et si oui, on récupère le username et les droits d'accès
for (l_iTotalEntriesIndex = 0; l_iTotalEntriesIndex < (int) l_ulNbOfEntries; l_iTotalEntriesIndex ++)
{
// on copie le
p_ShareInfoArray[*p_piCurrentIndex].aEnumUserRights[l_iTotalEntriesIndex].AccessRights = l_oAccessArray[l_iTotalEntriesIndex].grfAccessPermissions;
if (l_oAccessArray[l_iTotalEntriesIndex].Trustee.TrusteeForm == TRUSTEE_IS_NAME)
{
// on copie les droits (sous forme de MASK DWORD)
strcpy(p_ShareInfoArray[*p_piCurrentIndex].aEnumUserRights[l_iTotalEntriesIndex].cUserName, l_oAccessArray[l_iTotalEntriesIndex].Trustee.ptstrName);
}
else
{
char l_cDomainName[_MAX_FNAME];
unsigned long l_ulDomSize = _MAX_FNAME;
unsigned long l_ulBufSize = _MAX_FNAME;
SID_NAME_USE l_oSIDNameUse;
DWORD l_dwErr;
// pour chaque entrée du tableau, on va récupérer le Nom du user depuis le SID associé
l_bRetVal = LookupAccountSid ( p_pcServerName,
l_oAccessArray[l_iTotalEntriesIndex].Trustee.ptstrName,
p_ShareInfoArray[*p_piCurrentIndex].aEnumUserRights[l_iTotalEntriesIndex].cUserName,
&l_ulBufSize,
l_cDomainName,
&l_ulBufSize,
&l_oSIDNameUse);
if (l_bRetVal == 0)
{
l_dwErr = GetLastError();
throw l_dwErr;
}
switch (l_oSIDNameUse)
{
case SidTypeUser :
p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeUser;
break;
case SidTypeGroup :
p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeGroup;
break;
case SidTypeDomain :
p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeDomain;
break;
case SidTypeAlias :
p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeAlias;
break;
case SidTypeWellKnownGroup :
p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeWellKnownGroup;
break;
case SidTypeDeletedAccount :
p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeDeletedAccount;
break;
case SidTypeInvalid :
p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeInvalid;
break;
default :
p_ShareInfoArray[*p_piCurrentIndex].l_oAccountType = STL_SidTypeUnknown;
break;
}//end switch
}
}// end for
p_ShareInfoArray[*p_piCurrentIndex].iTotalUserRights = l_iTotalEntriesIndex;
LocalFree (l_oAccessArray);
(*p_piCurrentIndex) ++;
}
}
else // si pb avec le SID
{
sprintf(p_ShareInfoArray[(*p_piCurrentIndex)++].cRemark, "ERREUR AVEC LE SID DE CE DOSSIER");
}
l_PShareInfo++;
} // end for
NetApiBufferFree(l_BufPShareInfo);
l_BufPShareInfo = NULL;
}
while (l_nStatus==ERROR_MORE_DATA);
}
catch (DWORD dwErr)
{
l_nStatus = dwErr;
}
// on delete les pointeurs si OK
if (l_BufPShareInfo != NULL)
NetApiBufferFree(l_BufPShareInfo);
return l_nStatus;
}
Conclusion :
Ne pas oublier de linker les lib advapi32.lib, mpr.lib et netapi32.lib.
Voila, cela peut peut être servir....
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.