NetUserEnum
Stagiaire WDF
Inscrit:
02/02/2004 11:41
De 77
Post(s): 3
Bonjour, j'essaye d'utiliser la fonction 'NetUserEnum' de l'API 'Netapi32.dll'.
Le but étant de récupérer la liste des utilisateurs (plus fullname, ...) déclarés sur un controleur de domaine (NT4, mais devrait être identique sut 2000 ou 2003 d'après la doc Microsoft).

A priori j'obtiens le bon nombre d'infos, mais impossible d'obtenir des chaines de caractères lisibles ! Je ne sais pas si mon soucis vient de moi, ou du fonctionnement des fonctions WinDev 'ChaîneRécupère' et 'Transfert'.

Quelqu'un a-t-il réussi à utiliser la fonction 'NetUserEnum' ? Si oui, pourrais-t-il mettre son code en ligne ? Merci.

PS : ce qui est rageant, c'est que la même chose en Visual C ou Delphi fonctionne parfaitement...

Contribution le : 02/02/2004 11:45
Créer un fichier PDF de la contribution Imprimer


Re: NetUserEnum
Animateur WDF
Inscrit:
26/06/2002 16:24
De wdforge.org
Post(s): 2822
Bonjour lolo,
Peut être qu'en postant ledit code C (juste pour le enum), la migration serai plus facile.

ps : préciser les include

Contribution le : 03/02/2004 16:10
_________________
R&B
Contact, CV.
Créer un fichier PDF de la contribution Imprimer


Re: NetUserEnum
Anonyme
Salut Romu,
là tout de suite sous la main j'ai que la version Delphi (Pascal) :

Pour une version en C, y a l'exemple du MSDN à l'adresse suivante :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netuserenum.asp

unit ListeUsers;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Constantes;

type
TForm1 = class(TForm)
Lister: TButton;
ListeUsers: TListBox;
ZNbreUsers: TEdit;
Label1: TLabel;
ZServeur: TEdit;
Label2: TLabel;
procedure BtFinClick(Sender: TObject);
procedure ListerClick(Sender: TObject);

private
{ Déclarations privées }
public
{ Déclarations publiques }
end;

Type
NET_API_STATUS = DWORD;
StrUniCode = ARRAY[0..255] of WideChar ;
UserInf2 = record
Nom : PWideChar;
Passe : PWideChar;
Passe_age : DWORD;
Priv : DWORD ;
HomeDir : PWideChar;
Comment : PWideChar;
flags : DWord;
PathScript : PWideChar;
PrivOp : DWORD;
FullName : PWideChar;
UserComment : PWideChar;
Parms : PWideChar;
Stations : PWideChar;
LastLogon : DWORD ;
LastLogoff : DWORD;
DateExpire : DWORD;
MaxDisk : DWORD;
UnitsPerWeek : DWORD;
HeureConnect : PBYTE;
BadPwCount : DWORD;
GoodLogCount : DWORD;
ServeurDeLog : PWideChar;
CodePays : DWORD;
CodePage : DWORD;
end;
TabloUser = ARRAY [1..1000] of UserInf2;
function UserEnum
(servername:PWideChar ;
level: DWord;
filter : DWord;
var buf: Pointer;
PrefMaxLen : DWord;
EntriesRead : LPDWord;
TotalEntries : LPDWORD;
ResumeHandle: LPDWord
): NET_API_STATUS;stdcall;
external 'NetApi32.dll' name 'NetUserEnum';
function NetBufferFree
(PBuffer : Pointer):NET_API_STATUS;stdcall;
external 'NetApi32.dll' name 'NetApiBufferFree';

var
Form1: TForm1;
implementation

{$R *.DFM}


procedure TForm1.BtFinClick(Sender: TObject);
begin
Application.Terminate ;
end;

procedure TForm1.ListerClick(Sender: TObject);
Var Result : Net_Api_Status;
EntreesLues, TotalEntrees, ResumeHandle : DWord;
i:integer;
PTableauUser : ^TabloUser;
Serveur : StrUniCode;
begin
ListeUsers.Clear;
EntreesLues:=0 ; TotalEntrees := 0 ; ResumeHandle := 0;
if Length(ZServeur.text) >0 then ZServeur.text:='\\'+UpperCase(Trim(ZServeur.Text));
StringToWideChar(ZServeur.Text,@Serveur, sizeof(Serveur));
Result:=UserEnum(@Serveur,2,0,pointer(PTableauUser),$FFFFFFFF,@EntreesLues,@TotalEntrees,@ResumeHandle);
if result = NERR_SUCCESS
then begin
ZNbreUsers.Text:=IntToStr(TotalEntrees);
for i:=1 to TotalEntrees do
begin
ListeUsers.Items.Add('Nom :'+String(PTableauUser[i].Nom));
{ListeUsers.Items.Add('Passe :'+String(PTableauUser[i].Passe));
ListeUsers.Items.Add('Passe_age :'+IntToStr(PTableauUser[i].Passe_age));
ListeUsers.Items.Add('Priv :'+IntToStr(PTableauUser[i].Priv)) ;
ListeUsers.Items.Add('HomeDir :'+String(PTableauUser[i].HomeDir))} ;
ListeUsers.Items.Add('Comment :'+String(PTableauUser[i].Comment)) ;
{ListeUsers.Items.Add('flags :'+IntToHex(PTableauUser[i].flags,8)) ;
ListeUsers.Items.Add('Pathscript :'+String(PTableauUser[i].PathScript)) ;
ListeUsers.Items.Add('PrivOp :'+IntToHex(PTableauUser[i].PrivOp,8)); }
ListeUsers.Items.Add('FullName :'+String(PTableauUser[i].FullName)) ;
ListeUsers.Items.Add('UserComment :'+String(PTableauUser[i].UserComment));
{ListeUsers.Items.Add('Parms :'+String(PTableauUser[i].Parms ));
ListeUsers.Items.Add('Stations :'+String(PTableauUser[i].Stations ));
ListeUsers.Items.Add('LastLogon :'+IntToStr(PTableauUser[i].LastLogon )) ;
ListeUsers.Items.Add('LastLogOff :'+IntToStr(PTableauUser[i].LastLogoff));
ListeUsers.Items.Add('DateExpire :'+IntToStr(PTableauUser[i].DateExpire));
ListeUsers.Items.Add('MaxDisk :'+IntToStr(PTableauUser[i].MaxDisk));
ListeUsers.Items.Add('UnitsPerWeek :'+IntToStr(PTableauUser[i].UnitsPerWeek ));
ListeUsers.Items.Add('BadPwCount : '+IntToStr(PTableauUser[i].BadPwCount));
ListeUsers.Items.Add('GoodLogCount :'+IntToStr(PTableauUser[i].GoodLogCount));
ListeUsers.Items.Add('ServeurDeLog :'+String(PTableauUser[i].ServeurDeLog));
ListeUsers.Items.Add('CodePays :'+IntToStr(PTableauUser[i].CodePays));
ListeUsers.Items.Add('CodePage :'+IntToStr(PTableauUser[i].CodePage));}
ListeUsers.Items.Add('------------------------');
end;
NetBufferFree(PTableauUser);
end
else showmessage('Erreur : '+IntToStr(Result));
end;

end.

Si tu trouves le truc, ça m'arrangerai beaucoup.

Contribution le : 03/02/2004 16:32
Créer un fichier PDF de la contribution Imprimer


Re: NetUserEnum
Stagiaire WDF
Inscrit:
02/02/2004 11:41
De 77
Post(s): 3
Je mets le code de la doc microsoft, le lien indiqué ne menant pas directement à la bonne page

#ifndef UNICODE
#define UNICODE
#endif

#include
#include
#include
#include

int wmain(int argc, wchar_t *argv[])
{
LPUSER_INFO_0 pBuf = NULL;
LPUSER_INFO_0 pTmpBuf;
DWORD dwLevel = 0;
DWORD dwPrefMaxLen = MAX_PREFERRED_LENGTH;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
DWORD i;
DWORD dwTotalCount = 0;
NET_API_STATUS nStatus;
LPTSTR pszServerName = NULL;

if (argc > 2)
{
fwprintf(stderr, L"Usage: %s [\\\\ServerName]\n", argv[0]);
exit(1);
}
// The server is not the default local computer.
//
if (argc == 2)
pszServerName = argv[1];
wprintf(L"\nUser account on %s: \n", pszServerName);
//
// Call the NetUserEnum function, specifying level 0;
// enumerate global user account types only.
//
do // begin do
{
nStatus = NetUserEnum(pszServerName,
dwLevel,
FILTER_NORMAL_ACCOUNT, // global users
(LPBYTE*)&pBuf,
dwPrefMaxLen,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
//
// If the call succeeds,
//
if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
{
if ((pTmpBuf = pBuf) != NULL)
{
//
// Loop through the entries.
//
for (i = 0; (i < dwEntriesRead); i++)
{
assert(pTmpBuf != NULL);

if (pTmpBuf == NULL)
{
fprintf(stderr, "An access violation has occurred\n");
break;
}
//
// Print the name of the user account.
//
wprintf(L"\t-- %s\n", pTmpBuf->usri0_name);

pTmpBuf++;
dwTotalCount++;
}
}
}
//
// Otherwise, print the system error.
//
else
fprintf(stderr, "A system error has occurred: %d\n", nStatus);
//
// Free the allocated buffer.
//
if (pBuf != NULL)
{
NetApiBufferFree(pBuf);
pBuf = NULL;
}
}
// Continue to call NetUserEnum while
// there are more entries.
//
while (nStatus == ERROR_MORE_DATA); // end do
//
// Check again for allocated memory.
//
if (pBuf != NULL)
NetApiBufferFree(pBuf);
//
// Print the final count of users enumerated.
//
fprintf(stderr, "\nTotal of %d entries enumerated\n", dwTotalCount);

return 0;
}

Contribution le : 04/02/2004 13:51
Créer un fichier PDF de la contribution Imprimer


Re: NetUserEnum
Stagiaire WDF
Inscrit:
02/02/2004 11:41
De 77
Post(s): 3
Ne cherchez plus, le problème est que sous WinDev nous n'avons pas le fabuleux opérateur -> (contenu pointé par). Il faut utiliser la fonction transfert pour cela. Voir le code joint (et documenté) pour la solution complète.

-------------------------------------------------------
Y-a pas de mal à se faire du fric
http://www.eurexcelpartners.com/index.php/rep/lf20486
-------------------------------------------------------

Le code :

chDomaine, chServeur est une chaîne // Noms du domaine et du CPD (Contrôleur Principal du Domaine)

pDomaine, pServeur est une chaîne UNICODE // Les mêmes en UNICODE

hInst est un entier // Instance de l'API
pInfos est un entier // Pointeur sur les infos retournées par l'API
res est un entier // Résultat de l'appel à l'API
EntreesLues, TotalEntrees, ResumeHandle sont des entiers // Pour NetUserEnum
boolEncoreDesInfos est un booléen

// Structure USER_INFO_10 (Il existe : USER_INFO_0,1 à 4,10,11,20 à 23,1003,1005 à 1014,1017,1018,1020,1023 à 1025,1051 à 1053
USER_INFO_10 est une structure
p_name est un entier // Pointeur sur une chaine UNICODE : login
p_comment est un entier // Pointeur sur une chaine UNICODE : commentaires
p_usr_comment est un entier // Pointeur sur une chaine UNICODE : commentaires
p_full_name est un entier // Pointeur sur une chaine UNICODE : nom complet
FIN
InfoUtilisateur est une USER_INFO_10

NiveauInformation est un entier =10 // Niveau d'informations de NetUserEnum, correspond à la structure USER_INFO_10
nbInfos est un entier = 1 // Nombre d'infos à retourner, si on met plus, il faut récupérer un tableau de structure
// Filtre de recherche pour NetUserEnum
FILTER_TEMP_DUPLICATE_ACCOUNT est un entier = 1
FILTER_NORMAL_ACCOUNT est un entier = 2
FILTER_INTERDOMAIN_TRUST_ACCOUNT est un entier = 8
FILTER_WORKSTATION_TRUST_ACCOUNT est un entier = 16
FILTER_SERVER_TRUST_ACCOUNT est un entier = 32

USER_INFO_CH est une structure // J'utilise une structure de chaine, on pourrait prendre autre chose
ch_name est une chaîne
ch_comment est une chaîne
ch_usr_comment est une chaîne
ch_full_name est une chaîne
FIN
InfoUtilisateurCH est une USER_INFO_CH

// Récupération du nom de domaine sur lequel est connecté le poste
chDomaine = SansEspace(SysEnvironnement("USERDOMAIN")[[12 A ]])
// Conversion en UNICODE
pDomaine = AnsiVersUnicode(chDomaine,alphabetAnsi)

// Chargement de l'API adéquate
hInst = ChargeDLL("Netapi32.dll")
SI hInst = 0 ALORS
Erreur("Impossible de charger la DLL")
SINON
// Récupération du nom du CPD
res = API("NetApi32.dll","NetGetDCName",Null,&pDomaine,&pInfos)
// Récupération de l'info retournée par NetGetDCName en UNICODE
chServeur = SansEspace(ChaîneRécupère(pInfos,crAdresseUNICODE))
// Conversion en UNICODE
pServeur = AnsiVersUnicode(chServeur,alphabetAnsi)
// Libération de la mémoire réservée par NetGetDCName
res = API("NetApi32.dll","NetApiBufferFree",pInfos)

Info("Domaine : "+chDomaine+RC+"Serveur : "+chServeur)

// Enumération des utilisateurs
ResumeHandle = 0 // Pour récupérer la première info
BOUCLE
res = API("NetApi32.dll","NetUserEnum", pServeur, NiveauInformation, FILTER_NORMAL_ACCOUNT, &pInfos, nbInfos , &EntreesLues, &TotalEntrees, &ResumeHandle)
boolEncoreDesInfos = ( TotalEntrees > 1 )
// Récupération des informations, l'opérateur C -> n'existant pas sous WinDev, on utilise la fonction Transfert
Transfert(&InfoUtilisateur,pInfos,16) // On transfert le contenu de la mémoire réservée par NetUserEnum dans notre structure.
// 16 c'est la taille de ma structure ( 4 entiers = 4 * 4 octets )
// Les infos récupérées sont des chaines UNICODE, il convient donc de les convertir
InfoUtilisateurCH:ch_name = ChaîneRécupère(InfoUtilisateur:p_name,crAdresseUNICODE)
InfoUtilisateurCH:ch_comment = ChaîneRécupère(InfoUtilisateur:p_comment,crAdresseUNICODE)
InfoUtilisateurCH:ch_usr_comment = ChaîneRécupère(InfoUtilisateur:p_usr_comment,crAdresseUNICODE)
InfoUtilisateurCH:ch_full_name = ChaîneRécupère(InfoUtilisateur:p_full_name,crAdresseUNICODE)

Info(InfoUtilisateurCH:ch_name+RC+InfoUtilisateurCH:ch_full_name+RC+InfoUtilisateurCH:ch_comment+RC+InfoUtilisateurCH:ch_usr_comment)

// Libération de la mémoire réservée par NetUserEnum
res = API("NetApi32.dll","NetApiBufferFree",pInfos)
SI PAS boolEncoreDesInfos ALORS SORTIR
FIN
DéchargeDLL(hInst)
FIN

Citation :

Lolo a écrit :
Bonjour, j'essaye d'utiliser la fonction 'NetUserEnum' de l'API 'Netapi32.dll'.
Le but étant de récupérer la liste des utilisateurs (plus fullname, ...) déclarés sur un controleur de domaine (NT4, mais devrait être identique sut 2000 ou 2003 d'après la doc Microsoft).

A priori j'obtiens le bon nombre d'infos, mais impossible d'obtenir des chaines de caractères lisibles ! Je ne sais pas si mon soucis vient de moi, ou du fonctionnement des fonctions WinDev 'ChaîneRécupère' et 'Transfert'.

Quelqu'un a-t-il réussi à utiliser la fonction 'NetUserEnum' ? Si oui, pourrais-t-il mettre son code en ligne ? Merci.

PS : ce qui est rageant, c'est que la même chose en Visual C ou Delphi fonctionne parfaitement...

Contribution le : 17/03/2004 11:03
Créer un fichier PDF de la contribution Imprimer


Re: NetUserEnum
Animateur WDF
Inscrit:
02/03/2003 04:07
De Noisy le grand(93)
Post(s): 2745
Bonjour Lolo,

Merci de faire profiter la communauté de tes recherches sur ce sujet.

Contribution le : 19/03/2004 10:19
_________________
@A+
Contact (privé)......
email : drcharly@wdforge.org
[DrCharly93]
Créer un fichier PDF de la contribution Imprimer



 Haut   Précédent   Suivant




Enregistrer votre réponse
CompteNom   Mot de passe   Authentification
Message:


Vous ne pouvez pas débuter de nouveaux sujets.
Vous pouvez voir les sujets.
Vous ne pouvez pas répondre aux contributions.
Vous ne pouvez pas éditer vos contributions.
Vous ne pouvez pas effacez vos contributions.
Vous ne pouvez pas ajouter de nouveaux sondages.
Vous ne pouvez pas voter en sondage.
Vous ne pouvez pas attacher des fichiers à vos contributions.
Vous ne pouvez pas poster sans approbation.

[Recherche avancée]


Connexion
Menu
Chercher WDForge
Chercher Web
Partenaires
Visualiser tous les Partenaires...
WinDev, WebDev, WinDev Mobile et HyperFile sont des marques déposées par PCSoft. |  Voter |  Legal |  Contact |   XOOPS 2.0.13.2