Skip to content
⌘ NSIS Forum Archive

UserMgr Plugin

57 posts

TobbeSweden#
The user I'm testing with is myself. And I'm an administrator... I tried with the admin account and got the same error. It does work with the guest account though. It returns TRUE.
jpderuiter#
Originally posted by Ivan Andreevich
What do UserMgr::GetCurrentUserName and UserMgr::GetCurrentDomain return if there is some problem? I want to do some error checking on my end.
They both return "ERROR {errorcode}"

Originally posted by TobbeSweden
The user I'm testing with is myself. And I'm an administrator... I tried with the admin account and got the same error. It does work with the guest account though. It returns TRUE.
I tried the same, and I don't get an error for both users.
jpderuiter#
Tobbe,

have you tried the following code:


Is the same error code returned (the error code in $R8)?
TobbeSweden#
No, $R8 is -1073741772

I have been researching this, and it seems as if I should get an error, and that script gives me that error (in $R9).

I can't compile the source code for the plugin, but could you please make the following changes and post a build?

NTSTATUS nts; // This should be declared up at the top
nts = LsaEnumerateAccountRights(my_policy_handle, user_sid, (LSA_UNICODE_STRING **) &lucPrivilege, &count);
if (nts != STATUS_SUCCESS)
{
DWORD e;
if (lucPrivilege != NULL)LsaFreeMemory(&lucPrivilege);
LsaClose(my_policy_handle);
e = LsaNtStatusToWinError(nts);
if (e == 2)
{
pushstring("ERROR LsaEnumerateAccountRights - User only has inherited rights");
}
else
{
pushstring("ERROR LsaEnumerateAccountRights");
}
return;
}
jpderuiter#
Hello Tobbe

I uploaded a new version which return the errorcode for LsaEnumerateAccountRights (either the System errorcode if available, else the NTSTATUS errorcode).

I used the following code:

if (ntStatus = LsaEnumerateAccountRights(my_policy_handle, user_sid, (LSA_UNICODE_STRING **) &lucPrivilege, &count) != STATUS_SUCCESS)
{
if (lucPrivilege != NULL)LsaFreeMemory(&lucPrivilege);
LsaClose(my_policy_handle);
dwError = LsaNtStatusToWinError(ntStatus);
if(dwError == ERROR_FILE_NOT_FOUND)
{// No privileges found for the user
sprintf(tempbuf,"FALSE");
}
else if(dwError == ERROR_MR_MID_NOT_FOUND)
{// System errorcode not found for ntStatus
sprintf(tempbuf,"ERROR LsaEnumerateAccountRights n%d", ntStatus);
}
else
{
sprintf(tempbuf,"ERROR LsaEnumerateAccountRights w%d", dwError);
}
pushstring(tempbuf);
return;
}
(Attached newest version to this post)

Regards,
jpderuiter
TobbeSweden#
For some reason your code returns "ERROR LsaEnumerateAccountRights n1"

http://nsis.sourceforge.net/Enumerate_User_Privileges returns FILE_NOT_FOUND

I believe the correct return value in my case is FILE_NOT_FOUND
Ivan Andreevich#
I have a feature request. How about a function that checks whether the specified Username (password too, if needed) has access rights to go to a specified path. Is that feasible, or is this outside the scope of this plug-in?
Ivan Andreevich#
Cancel that. My studio has been closed down and we've all been fired today.

But thanks so much for the hard work you put in with this plug-in!
jpderuiter#
@Tobbe:
I'm sorry, but I'm not able to solve the HasPrivilege problem.
The function LsaEnumerateAccountRights returns 1 on every error, and I can't find a solution for it.
So I'm afraid you'll have to use the Macro mentioned before as a workaround.

@Ivan:
I'm really sorry to hear that.
I hope you will find yourself a new job soon.
About your feature request: I think it's a usefull feature so I'm thinking about adding it anyway as soon as I have the time for it.

Regards,
Jan Pieter
TobbeSweden#
I compiled and ran this code: http://win32.mvps.org/lsa/lsa_lear.cpp

It uses LsaEnumerateAccountRights and I got the "FILE_NOT_FOUND" error. Maybe you can work off of that?
jpderuiter#
Well, as far I can see I'm doing exactly the same.
And there is nothing wrong with the parameters I'm passing to LsaEnumerateAccountRights, since it returns no error if the user does have privileges.
jpderuiter#
I uploaded a new version of this plugin:
- Added GetUserNameFromSID function
- Added GetSIDFromUserName function
- Fixed a problem in the RegLoadUserHive function when a user was deleted and then recreated
Originally posted by TobbeSweden
Now I can run the plugin but there is one thing I find weird...
Name "UsrMgrTest"
OutFile "UsrMgrTest.exe"
ShowInstDetails show
Page instfiles

Section ""
UserMgr::GetCurrentUserName
Pop $0
DetailPrint ">$0<"
UserMgr::GetUserInfo $0 "HOMEDIR"
Pop $1
DetailPrint ">$1<"
UserMgr::HasPrivilege $0 "SeInteractiveLogonRight"
Pop $2
DetailPrint ">$2<"
SectionEnd
$1 is just an empty string when I run that. And $2 is "ERROR LsaEnumerateAccountRights". $0 does contain my username.
Thanks to ginglese I found a better way to get the HOMEDIR:http://forums.winamp.com/showthread....postid=2558509
UserMgr::GetCurrentUserName
Pop $0
UserMgr::GetSIDFromUserName "" $0
Pop $1
ReadRegStr $2 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$1" "ProfileImagePath"
ExpandEnvStrings $3 $2
DetailPrint "Homedir: $3"
langdon#
Having some trouble with this plugin on my work machine (which is joined to a domain, and I'm logged with a domain account). I keep getting ERROR 2221 (NERR_UserNotFound) from the following:

UserMgr::GetUserInfo "domain\username" "exists"
Pop $0
MessageBox MB_OK "$0"
UserMgr::GetSIDFromUserName "domain" "username"
Pop $1
MessageBox MB_OK "$1" 
1st MessageBox: "ERROR 2221"
2nd MessageBox: "ERROR GetAccountSid"

There's a slight delay when calling GetSIDFromUserName (like 1-2 seconds).

I've double and triple checked that I have the correct domain and username. I even went as far as pulling the SID from the registry and calling it sequence:

UserMgr::GetUserNameFromSID "S-1-5-21-4264112824-276356272-3790957511-1754"
Pop $0
MessageBox MB_OK "$0"
UserMgr::GetUserInfo "$0" "exists"
Pop $1
MessageBox MB_OK "$1" 
I still get ERROR 2221 (NERR_UserNotFound) with this.

Any ideas?
jpderuiter#
Hi,

what do you get when using the GetCurrentUserName and GetCurrentDomain functions?

And what do you get when using the following command in the DOS cmd:
net user {username} /domain
(replace {username} with your username)?

JP
langdon#
Re: GetCurrentUserName/Domain, these are identical:

UserMgr::GetUserNameFromSID "S-1-5-21-4264112824-276356272-3790957511-1754"
Pop $0
UserMgr::GetCurrentDomain 
Pop $1
UserMgr::GetCurrentUserName
Pop $2
MessageBox MB_OK "$0 vs $1\$2" 
The net user command tells somewhat of a different tale -- it appends ".com" onto the domain when it describes the request.

Going back and changing the code above to domain.com\username, still gets me the error, BUT calling GetSIDFromUsername with domain.com and my username, yields the correct SID.

What do you make of this?

C:\Users\oliverlw>net user oliverlw /domain
The request will be processed at a domain controller for domain xxxx.com.

User name xxxx
Full Name xxxx xxxx
Comment
User's comment
Country code 000 (System Default)
Account active Yes
Account expires Never

Password last set 8/5/2011 7:56:20 AM
Password expires 11/3/2011 7:56:20 AM
Password changeable 8/6/2011 7:56:20 AM
Password required Yes
User may change password Yes

Workstations allowed All
Logon script
User profile
Home directory
Last logon 9/1/2011 3:28:51 PM

Logon hours allowed All

Local Group Memberships
Global Group memberships *xxxx

The command completed successfully.
jpderuiter#
Sorry, I was too quick to answer.

The reason is GetUserInfo only works for local accounts...
The plugin should be updated to support domain users for GetUserInfo.
You can try to use the system plugin to get the information you need:
Are you a developer who uses NSIS to distribute your application? Are you a Winamp plug-in developer who wants to use NSIS to distribute your plug-in? Have suggestions for other people like you? This is the place.

Search for NetUserGetInfo in that post.
langdon#
Ahh, thanks, I'll give that a whirl.

I posted a response to your questions, but it's pending moderator approval?
rvintonyak#
Hi folks.

Currently I'm working on creating unicode nsis installer. In ansi version of installer I use UserMgr.dll to receive username and user SID.

For unicode installer I need UserMgr.dll to be compiled as unicode too.

So I'm just curious if I can download somewhere unicode UserMgr.dll or should I download sources and construct it by myself?

Thanks,
Roman
jpderuiter#
Unfortunately there is no Unicode version available yet.
And I don't have time to do the port any time soon...
JasonFriday13#
I've had a quick look at the code and it doesn't seem too hard. It's just the sheer quantity that's the time consuming part. I'll play around with it and see what I can do.
JasonFriday13#
So I've added unicode support to this plugin, but I haven't done any testing yet.

I used VS2008 for the development, and I've included the project file along with all the source files and compiled release versions. I used C runtime calls as much as I could, so the source should compile on older compilers with little or no modifications.
jpderuiter#
Hi Jason,

thanks for your update.

Did you change the plugin name on purpose from UserMgr to UsrMgr?
Now existing scripts are broken.

After changing the plugin file name, the UserMgr plugin is working fine in Unicode and Ansi.

Thanks again!

JP
JasonFriday13#
Whoops, that's a typo on my behalf. But yeah, I haven't tested it, so that's why I didn't notice the name was wrong. Consider this a patch that will hopefully get merged at some point (I was only going to upload the usermgr.c file).
Kanelo#
very usefull plugin but i missed a password validation function and the possibility to use SID Groups directly as GetLocalizedStdAccountName did not do the trick for me.

AddToGroup, IsMemberOfGroup and RemoveFromGroup now checks if GroupID is in square Brackets "[]", if so it is treated as SID.

This will Add, check and remove user Test to builtin\administrators
For this test a User "Test" is needed 😉
    UserMgr::IsMemberOfGroup "Test" "[S-1-5-32-544]"
    Pop $0
    DetailPrint "$$0: $0"
    
    UserMgr::AddToGroup  "Test" "[S-1-5-32-544]"
    Pop $0
    DetailPrint "$$0: $0"
    
    UserMgr::IsMemberOfGroup "Test" "[S-1-5-32-544]"
    Pop $0
    DetailPrint "$$0: $0"
    
    UserMgr::RemoveFromGroup "Test" "[S-1-5-32-544]"
    Pop $0
    DetailPrint "$$0: $0"
    
    UserMgr::IsMemberOfGroup "Test" "[S-1-5-32-544]"
    Pop $0
    DetailPrint "$$0: $0" 
As it should be a non invasive modification there should be no need to change existing code!
(the idea/methode is copied from AccessControl. Thanks 🙂 )


New Function ValidatePassword checks if the given password will be accepted on a given system.
UserMgr::ValidatePassword "password1234" "local" 
Checks if "password1234" will be accepted on the local machine. You can also type the name of a valid remote server for validation over network.
UserMgr::ValidatePassword "password1234" "dc.example.org" 
The Function places the return on top of the Stack. Return is "ERROR XXXX" or "OK".
Error codes can be found here Network Management Error Codes

NOTE: NERR_PasswordTooShort (2245) will sometimes be thrown if the password matches or contains the username. This can not be checked beforehand with this function as there is no username given.

Some code review would be appreciated.
If i don't hear anything wrong, i or hopefully one more experienced user will update the wiki page.


NOTE²: I used VS2019 to compile this, so if you use the included unicode/ansi dll file you need to install "Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019" before the use on a machine!

Bonus
Fixed: RemoveFromGroup, didn't work with NetGroupDelUser (at least on Windows 10)


Famous last words: Works for me
JasonFriday13#
Originally Posted by Kanelo View Post
NOTE²: I used VS2019 to compile this, so if you use the included unicode/ansi dll file you need to install "Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019" before the use on a machine!
That's easy to fix, in the project settings under code generation, change the runtime library to /MT. That statically links the C/C++ runtime so that it runs on any machine. The downside is that it increases the size of the DLL alot, but for compatibility it's a compromise worth doing.
Kanelo#
didn't know that, thank you 🙂