PJLeyther
asked on
Query Username membership of NT groups?
Hi All hope you can help
Our users are logging on to a
client/server app using NT (4.0)
account information. I need to see if
the user is a member of a
particular group. As the client is
running on Win 95 the API functions
need to be compliant. Can you point
me to the rel source (or maybe even
a component).
Dev Env: Delphi 5 enterprise on Win 98
thanks
PJLeyther
Our users are logging on to a
client/server app using NT (4.0)
account information. I need to see if
the user is a member of a
particular group. As the client is
running on Win 95 the API functions
need to be compliant. Can you point
me to the rel source (or maybe even
a component).
Dev Env: Delphi 5 enterprise on Win 98
thanks
PJLeyther
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Hi Cameron, it seems that your stuff only works under NT. But PJLeyther needs it for win9x... :-(
Regards, Madshi.
Regards, Madshi.
Listening..
ASKER
Thanks for the prompt replys, Madshi and CameronCole. I will investigate your responses. Speak to you soon.
regards
pjleyther
regards
pjleyther
It can work under win9x. You just need to copy NetAPI32.DLL to the machine. Some of the write functions will not work correctly, but the reads should be fine.
If you need the write functions, write a server side process on NT that the win9x client calls. You can use tserversocket and tclientsocket. If you are lazy, you can just spit out a tstringslist to a file every so often. Getting the groups otherwise will be difficult at best.
If you need the write functions, write a server side process on NT that the win9x client calls. You can use tserversocket and tclientsocket. If you are lazy, you can just spit out a tstringslist to a file every so often. Getting the groups otherwise will be difficult at best.
listen
Hi,
I am answering this question so it can be saved as a PAQ.
PJLeyther wishes to split the points equally between Madshi and CameronCole.
I have issued separate questions for each expert in this topic area.
IanB
Community Support @ Experts Exchange
I am answering this question so it can be saved as a PAQ.
PJLeyther wishes to split the points equally between Madshi and CameronCole.
I have issued separate questions for each expert in this topic area.
IanB
Community Support @ Experts Exchange
ASKER
Hi Madshi, CameronCole
I have managed to solve my problem with the help of you both. Because of this, and I hope you both agree, I have arranged that the points be split between you.
Thanks Madshi your URL pointer has been really usefull. Thanks also CameronCole for your example app. My task only involved reading the SAM so exerts of your code together with the posted information proved adequate.
Thanks again
PJLeyther :-)
I have managed to solve my problem with the help of you both. Because of this, and I hope you both agree, I have arranged that the points be split between you.
Thanks Madshi your URL pointer has been really usefull. Thanks also CameronCole for your example app. My task only involved reading the SAM so exerts of your code together with the posted information proved adequate.
Thanks again
PJLeyther :-)
That's nice, that you got it working... Hmmm... Would you mind sharing your results with us? :-)
Regards, Madshi.
Regards, Madshi.
ASKER
Madshi
Not at all. Will post very soon keep listening. I have only opened this at the end of my working day (UK) ... other (must dooos - under the thumb and other expressions come to mind) things on tonight.
regards
PJLeyther
Not at all. Will post very soon keep listening. I have only opened this at the end of my working day (UK) ... other (must dooos - under the thumb and other expressions come to mind) things on tonight.
regards
PJLeyther
Thanx... :-) I'll keep listening...
ASKER
Hi Madshi, CameronCole
As promised.
Our task was to find the current users NT Account membership groups available by calls from client software running on Win 95 - all reads, no writes.
Our results were satisfied with the following...
A component has been written using Delphi 5 enterpise on Win 98 with all calls declared/defined within the same pas file. Hope it helps.
BTW: We wont be held responsible for this code... etc, etc, etc... you know the score.
unit insNTSecurity;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
procedure NetApiBufferFree(pBuffer: pByte); stdcall;
external 'radmin32.DLL' name 'NetApiBufferFree';
function NetGetDCName(pServerName: pChar; pDomainName: pChar;
pBuffer: pByte): DWord; stdcall;
external 'radmin32.DLL' name 'NetGetDCNameA';
function NetUserGetInfo(pServerName : pWideChar; pUserName: pWideChar;
wLevel: DWord; pBuffer: PByte): DWord; stdcall;
external 'radmin32.DLL' name 'NetUserGetInfo';
function NetGroupEnum(pServerName: pWideChar; wLevel: DWord;
pBuffer: pByte; wBufLen: DWord; wpEntriesRead: pDWord;
wpTotalEntries: pDWord; wpResume_Handle: pDWord): DWord; stdcall;
external 'radmin32.DLL' name 'NetGroupEnum';
function NetUserGetGroups(pServerNa me: pWideChar; pUserName: pWideChar;
wLevel: DWord; pBuffer: PByte; wBufLen: DWord; wpEntriesRead: pDWord;
wpTotalEntries: pDWord): DWord; stdcall;
external 'radmin32.DLL' name 'NetUserGetGroups';
type
TUserInfo1 = packed record
usri1_name: pWideChar;
usri1_password: pWideChar;
usri1_password_age: DWord;
usri1_priv: DWord;
usri1_home_dir: pWideChar;
usri1_comment: pWideChar;
usri1_flags: DWord;
usri1_script_path: pWideChar;
end;
PUserInfo1 = ^TUserInfo1;
TGroupInfo1 = packed record
grpi1_name: pWideChar;
grpi1_comment: pWideChar;
end;
PGroupInfo1 = ^TGroupInfo1;
type
TUserDetails = class(TPersistent)
private
FName : String;
FPassword : String;
FPasswordAge : DWord;
FPriv : DWord;
FHomeDir : String;
FComment : string;
FFlags : DWord;
FScriptPath : String;
FGroups : TStrings;
protected
public
constructor Create;
destructor Destroy;
published
property Name : String Read FName write FName;
property Password : String read FPassword write FPassword;
property PasswordAge : DWord read FPasswordAge write FPasswordAge;
property Priv : DWord read FPriv write FPriv;
property HomeDir : String read FHomeDir write FHomeDir;
property Comment : String read FComment write FComment;
property Flags : Dword read FFlags write FFlags;
property ScriptPath : String read FScriptPath write FScriptPath;
property Groups : TStrings read FGroups write FGroups;
end;
TINSNTSecurity = class(TComponent)
private
FPDCName : String;
FUserName : String;
FUserDetails : TUserDetails;
FGroups : TStrings;
Procedure SetFPDCName(Value:String);
Procedure SetUserName(Value:String);
protected
{ Protected declarations }
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property PDCName : String Read FPDCName write SetFPDCName;
property UserName : String read FUserName write SetUserName;
property UserDetails : TUserDetails read FUserDetails write FUserDetails;
property Groups : TStrings read FGroups write FGroups;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Insigh t Approved', [TINSNTSecurity]);
end;
constructor TUserDetails.Create;
begin
inherited Create;
FGroups:=TStringList.Creat e;
end;
destructor TUserDetails.Destroy;
begin
FGroups.Free;
inherited Destroy;
end;
constructor TINSNTSecurity.Create(AOwn er : TComponent);
var
wResult: DWord;
pBuffer: Pointer;
wBufLen : DWord;
wTotalEntries: DWord;
wEntriesRead: DWord;
wLevel: DWord;
wResumeHandle: DWord;
iLoop : Integer;
GroupRecInfo: PGroupInfo1;
begin
inherited Create(AOwner);
FUserDetails:=TUserDetails .Create;
FGroups:=TStringList.Creat e;
pBuffer:=Nil;
wResult:=NetGetDCName('',' ',@pBuffer );
if wResult=0 then begin
FPDCName:=strpas(pBuffer);
end else
FPDCName:='NA';
// Free the Buffer
NetApiBufferFree(pBuffer);
// now go get the group list
FGroups.Clear;
wBufLen:=64000;
wEntriesRead := 0;
wTotalEntries := 0;
wResumeHandle := 0;
wLevel:=1;
wResult := NetGroupEnum(pwidechar(Wid eString(FP DCName)),w Level, @pBuffer, wBufLen, @wEntriesRead, @wTotalEntries, @wResumeHandle);
if wResult=0 then begin
for iLoop := 0 to wEntriesRead - 1 do begin
GroupRecInfo := PGroupInfo1(LongInt(pBuffe r) + (iLoop * SizeOf(TGroupInfo1)));
FGroups.Add(string(GroupRe cInfo^.grp i1_name)+# 9+string(G roupRecInf o^.grpi1_c omment));
end;
end;
end;
destructor TINSNTSecurity.Destroy;
begin
FUserDetails.Free;
FGroups.Free;
inherited Destroy;
end;
procedure TINSNTSecurity.SetFPDCName (Value:Str ing);
begin
// Just ignore the value
end;
procedure TINSNTSecurity.SetUserName (Value:Str ing);
var
wResult: DWord;
pBuffer: Pointer;
UserRecInfo: PUserInfo1;
wBufLen : DWord;
wTotalEntries: DWord;
wEntriesRead: DWord;
wLevel: DWord;
wResumeHandle: DWord;
iLoop : Integer;
GroupRecInfo: PGroupInfo1;
begin
// Go Get the NT User Info
FUserName:=Value;
wResult:=NetUserGetInfo(pW ideChar(Wi deString(F PDCName)), pwidechar( WideString (FUserName )),1,@pBuf fer);
if wResult=0 then begin
UserRecInfo := PUserInfo1(LongInt(pBuffer ));
FUserDetails.FName:=UserRe cInfo^.usr i1_name;
FUserDetails.FPassword:=Us erRecInfo^ .usri1_pas sword;
FUserDetails.FHomeDir:=Use rRecInfo^. usri1_home _dir;
FUserDetails.FPasswordAge: =UserRecIn fo^.usri1_ password_a ge;
FUserDetails.FPriv:=UserRe cInfo^.usr i1_priv;
FUserDetails.FComment:=Use rRecInfo^. usri1_comm ent;
FUserDetails.FFlags:=UserR ecInfo^.us ri1_flags;
FUserDetails.FScriptPath:= UserRecInf o^.usri1_s cript_path ;
NetApiBufferFree(pBuffer);
// go get users groups
FUserDetails.Groups.Clear;
wBufLen:=64000;
wEntriesRead := 0;
wTotalEntries := 0;
wResumeHandle := 0;
wLevel:=1;
wResult := NetGroupEnum(pwidechar(Wid eString(FP DCName)),w Level, @pBuffer, wBufLen, @wEntriesRead, @wTotalEntries, @wResumeHandle);
if wResult=0 then begin
for iLoop := 0 to wEntriesRead - 1 do begin
GroupRecInfo := PGroupInfo1(LongInt(pBuffe r) + (iLoop * SizeOf(TGroupInfo1)));
FUserDetails.Groups.Add(st ring(Group RecInfo^.g rpi1_name) +#9+string (GroupRecI nfo^.grpi1 _comment)) ;
end;
end;
NetApiBufferFree(pBuffer);
end else begin
FUserDetails.Name:='NA';
FUserDetails.HomeDir:='NA' ;
FUserDetails.Password:='NA ';
FUserDetails.FPasswordAge: =0;
FUserDetails.FPriv:=0;
FUserDetails.FComment:='NA ';
FUserDetails.FFlags:=0;
FUserDetails.FScriptPath:= 'NA';
FUserDetails.Groups.Clear;
end;
end;
end.
(with thanks to Darren who built the component while I was busy on something else)
As promised.
Our task was to find the current users NT Account membership groups available by calls from client software running on Win 95 - all reads, no writes.
Our results were satisfied with the following...
A component has been written using Delphi 5 enterpise on Win 98 with all calls declared/defined within the same pas file. Hope it helps.
BTW: We wont be held responsible for this code... etc, etc, etc... you know the score.
unit insNTSecurity;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
procedure NetApiBufferFree(pBuffer: pByte); stdcall;
external 'radmin32.DLL' name 'NetApiBufferFree';
function NetGetDCName(pServerName: pChar; pDomainName: pChar;
pBuffer: pByte): DWord; stdcall;
external 'radmin32.DLL' name 'NetGetDCNameA';
function NetUserGetInfo(pServerName
wLevel: DWord; pBuffer: PByte): DWord; stdcall;
external 'radmin32.DLL' name 'NetUserGetInfo';
function NetGroupEnum(pServerName: pWideChar; wLevel: DWord;
pBuffer: pByte; wBufLen: DWord; wpEntriesRead: pDWord;
wpTotalEntries: pDWord; wpResume_Handle: pDWord): DWord; stdcall;
external 'radmin32.DLL' name 'NetGroupEnum';
function NetUserGetGroups(pServerNa
wLevel: DWord; pBuffer: PByte; wBufLen: DWord; wpEntriesRead: pDWord;
wpTotalEntries: pDWord): DWord; stdcall;
external 'radmin32.DLL' name 'NetUserGetGroups';
type
TUserInfo1 = packed record
usri1_name: pWideChar;
usri1_password: pWideChar;
usri1_password_age: DWord;
usri1_priv: DWord;
usri1_home_dir: pWideChar;
usri1_comment: pWideChar;
usri1_flags: DWord;
usri1_script_path: pWideChar;
end;
PUserInfo1 = ^TUserInfo1;
TGroupInfo1 = packed record
grpi1_name: pWideChar;
grpi1_comment: pWideChar;
end;
PGroupInfo1 = ^TGroupInfo1;
type
TUserDetails = class(TPersistent)
private
FName : String;
FPassword : String;
FPasswordAge : DWord;
FPriv : DWord;
FHomeDir : String;
FComment : string;
FFlags : DWord;
FScriptPath : String;
FGroups : TStrings;
protected
public
constructor Create;
destructor Destroy;
published
property Name : String Read FName write FName;
property Password : String read FPassword write FPassword;
property PasswordAge : DWord read FPasswordAge write FPasswordAge;
property Priv : DWord read FPriv write FPriv;
property HomeDir : String read FHomeDir write FHomeDir;
property Comment : String read FComment write FComment;
property Flags : Dword read FFlags write FFlags;
property ScriptPath : String read FScriptPath write FScriptPath;
property Groups : TStrings read FGroups write FGroups;
end;
TINSNTSecurity = class(TComponent)
private
FPDCName : String;
FUserName : String;
FUserDetails : TUserDetails;
FGroups : TStrings;
Procedure SetFPDCName(Value:String);
Procedure SetUserName(Value:String);
protected
{ Protected declarations }
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property PDCName : String Read FPDCName write SetFPDCName;
property UserName : String read FUserName write SetUserName;
property UserDetails : TUserDetails read FUserDetails write FUserDetails;
property Groups : TStrings read FGroups write FGroups;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Insigh
end;
constructor TUserDetails.Create;
begin
inherited Create;
FGroups:=TStringList.Creat
end;
destructor TUserDetails.Destroy;
begin
FGroups.Free;
inherited Destroy;
end;
constructor TINSNTSecurity.Create(AOwn
var
wResult: DWord;
pBuffer: Pointer;
wBufLen : DWord;
wTotalEntries: DWord;
wEntriesRead: DWord;
wLevel: DWord;
wResumeHandle: DWord;
iLoop : Integer;
GroupRecInfo: PGroupInfo1;
begin
inherited Create(AOwner);
FUserDetails:=TUserDetails
FGroups:=TStringList.Creat
pBuffer:=Nil;
wResult:=NetGetDCName('','
if wResult=0 then begin
FPDCName:=strpas(pBuffer);
end else
FPDCName:='NA';
// Free the Buffer
NetApiBufferFree(pBuffer);
// now go get the group list
FGroups.Clear;
wBufLen:=64000;
wEntriesRead := 0;
wTotalEntries := 0;
wResumeHandle := 0;
wLevel:=1;
wResult := NetGroupEnum(pwidechar(Wid
if wResult=0 then begin
for iLoop := 0 to wEntriesRead - 1 do begin
GroupRecInfo := PGroupInfo1(LongInt(pBuffe
FGroups.Add(string(GroupRe
end;
end;
end;
destructor TINSNTSecurity.Destroy;
begin
FUserDetails.Free;
FGroups.Free;
inherited Destroy;
end;
procedure TINSNTSecurity.SetFPDCName
begin
// Just ignore the value
end;
procedure TINSNTSecurity.SetUserName
var
wResult: DWord;
pBuffer: Pointer;
UserRecInfo: PUserInfo1;
wBufLen : DWord;
wTotalEntries: DWord;
wEntriesRead: DWord;
wLevel: DWord;
wResumeHandle: DWord;
iLoop : Integer;
GroupRecInfo: PGroupInfo1;
begin
// Go Get the NT User Info
FUserName:=Value;
wResult:=NetUserGetInfo(pW
if wResult=0 then begin
UserRecInfo := PUserInfo1(LongInt(pBuffer
FUserDetails.FName:=UserRe
FUserDetails.FPassword:=Us
FUserDetails.FHomeDir:=Use
FUserDetails.FPasswordAge:
FUserDetails.FPriv:=UserRe
FUserDetails.FComment:=Use
FUserDetails.FFlags:=UserR
FUserDetails.FScriptPath:=
NetApiBufferFree(pBuffer);
// go get users groups
FUserDetails.Groups.Clear;
wBufLen:=64000;
wEntriesRead := 0;
wTotalEntries := 0;
wResumeHandle := 0;
wLevel:=1;
wResult := NetGroupEnum(pwidechar(Wid
if wResult=0 then begin
for iLoop := 0 to wEntriesRead - 1 do begin
GroupRecInfo := PGroupInfo1(LongInt(pBuffe
FUserDetails.Groups.Add(st
end;
end;
NetApiBufferFree(pBuffer);
end else begin
FUserDetails.Name:='NA';
FUserDetails.HomeDir:='NA'
FUserDetails.Password:='NA
FUserDetails.FPasswordAge:
FUserDetails.FPriv:=0;
FUserDetails.FComment:='NA
FUserDetails.FFlags:=0;
FUserDetails.FScriptPath:=
FUserDetails.Groups.Clear;
end;
end;
end.
(with thanks to Darren who built the component while I was busy on something else)
Thank you... :-)
ASKER
Madshi, CameronCole
No problem. I hope we can do business in the future.
Thanks again
PJLeyther
No problem. I hope we can do business in the future.
Thanks again
PJLeyther
"http://www.wsb.poznan.pl/~pawel/vb/www.mvps.org/win32/network/nt95.html#Section 3: Radmin32 to the Rescue"
Does that help?
NetUserGetGroups is the API.
Regards, Madshi.