I have a requirement to detect all users from local and Active Directory(if present) in Windows.
I have found that C API: NetQueryDisplayInformation() has also the option to retrieve the information from a "serverName", which is presumably an Active Directory which can be queried.
But how do I find out if ActiveDirectory is available/ and it's name ?
Thanks.
This information is available in WMI. In the Win32_ComputerSystem class (there will be a single instance per computer) has a Domain property containing the domain's name.
Another way of finding out domain name (if present) is to use WIN API ::DsGetDcName()
This one returns information about Active Dir server name in DOMAIN_CONTROLLER_INFO struct.
You get there all the domain information you need. Much sympler than using WMI :-)
Related
I need the DNS suffix of all my local interfaces on my PC.
Is there way how I can achieve this via Go?
Best case would be for any OS
Necessary: working on Windows
I have tried net.Inferfaces() and all the net commands but I haven't found anything regarding the DNS server.
EDIT
I have found the solution for the Windows-specific version but it would be interesting if there is anything that works for Linux and macOS too.
I don't think there is a solution that work for any OS. In Linux the DNS suffix is not interface specific but system wide, it is configured in /etc/resolv.conf. Here is an excerpt from the man page:
search Search list for host-name lookup.
By default, the search list contains one entry, the local domain name. It is determined from the local hostname returned by gethostname(2); the local domain name is taken to be everything after the first '.'. Finally, if the hostname does not contain a '.', the root domain is assumed as the
local domain name.
This may be changed by listing the desired domain search path following the search keyword with spaces or tabs separating the names. Resolver queries having fewer than ndots dots (default is 1) in them will be attempted using each component of the search path in turn until a match is found.
For environments with multiple subdomains please read options ndots:n below to avoid man-in-the-middle attacks and unnecessary traffic for the root-dns-servers. Note that this process may be slow and will generate a lot of network traffic if the servers for the listed domains are not local, and
that queries will time out if no server is available for one of the domains.
If there are multiple search directives, only the search list from the last instance is used.
The net package standard library parses this file to get the DNS config, so the DNS resolver should behave as expected, however, the parsing functionality is not exposed.
The libnetwork.GetSearchDomains func in the libnetwork library should be able to help you out. If there are no search entries in /etc/resolv.conf, you should use the hostname, which can be gotten with the os.Hostname func.
I believe this also works for FreeBSD and Mac OS since they are both "UNIX like". But I am not 100% sure.
I'm working on a System Service project with SYSTEM privilege (cleaning utility)... It does not interactive with any user interface.
My goal is to check files in "Desktop" and "AppData" folders for any user that exists on the PC.
I'm using NetUserEnum() to get the user list on the PC. Then I want to get the path of each user's Desktop and AppData with SHGetKnownFolderPath(), but I can't find a way to get each user's access token for SHGetKnownFolderPath(). Without a token defined in SHGetKnownFolderPath(), it returns the path for SYSTEM and not specific users.
Q1. How can I get the token of each user for SHGetKnownFolderPath()?
Q2. If no answer for Q1, is there any documented way to get the desktop & appdata path of each user in the PC?
I understand this can be achieved with dirty way ---> Registry key with some string replacement. However, the Registry key method is undocumented, which may easily break in future updates to Windows.
Edit Update:
#RaymondChen Thanks for pointing out that some user profiles may not exist. Also,
About Q1 : #Remy Lebeau provides a solution with LogonUser/Ex(),login to each user with their credentials,might be the only answer that fits the need of Q1.
About Q2 : There might have no documented way to achieve this. The only method might have to stick with Windows Registry (Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders) , as #Remy Lebeau and #Olaf Hess said. I tried to dig more information on Microsoft Community Forum and I got Microsoft would never allow access other users' profile with their native API for security reason. They do not provide APIs that can possibly violate the security rules. Each user profile can only access by its credentials.
btw, I totally understand that "Cleaning utility" aka "Windows-breaking tool", especially when the tool is not being well codded(ex. compatibility problem). For the sake of avoiding to make it become a totally Windows-Destroyer, I tried to use more documented API as possible.
For Windows Vista with SP1 / Server 2008 and better you can query the existing user profiles using the WMI class Win32_UserProfile. This allows you to retrieve the profile path and check whether it is a local or roaming profile and to get status information. The rest (retrieving the paths to APPDATA, DESKTOP, etc.) is likely going to involve reading values straight from the registry (HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders or HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders).
Is is possible to specify the SID when creating a new local group account?
I've successfully created a new group using the NetLocalGroupAdd function by specifying information level 1 (LOCALGROUP_INFO_1) but his creates the group with a different SID each time. This beahviour I expected.
What I would like to do is to specify the SID when creating the group account. It isn't possible to use NetLocalGroupAdd with level 3. So I moved to look at NetGroupAdd. But this function creates a global group rather than a local one.
Is there a way to do this either during the creation of the group or update the SID with the desired one after the group has been created.
You can't do that. Any SID generated on your particular machine is issued that machine's local security authority. (Okay, or the domain security authority if you're talking about a domain controller) That means, it will always have the form
S-1-5-21<the machine LSA SID>-<random local identifier of the user/group>.
This is because the structure of a SID is hierarchical. For instance, all SIDs under NT AUTHORITY have the prefix S-1-5, because that is NT AUTHORITY's SID. (e.g. NT AUTHORITY\SYSTEM is S-1-5-18) Your machine's LSA isn't allowed to issue a SID that doesn't belong under its authority, which is going to be the S-1-5-21<random number generated when Windows is installed> SID.
No, the OS supplies the SID. The same is true of other identifiers like GUIDs. Generally speaking.
There are a narrow class of scenarios where the caller can supply these IDs, like during migration you can write SIDHistory, or if you use permissive add mode for GUIDs in AD. But generally speaking these things are frowned upon unless you really know what you are doing.
With more data about why you want this we might be able to suggest another path...
MSDN says: LookupAccountSid function returns the name of the first domain on which SID is found.
If a User is migrated to domain B from domain A and we query the old SID of user by using LookupAccountSid function from any machine of domain A, we get domain name of domain A instead of domain B.
It seems that even after migrating the user, Active directory is keeping user info on domain A. This problem is not resolved even after restarting the machines of domain A including domain controller.
I need name of new domain of User. Can you suggest how to resolve this issue?
The most Win32 API are designed to work in the environment where one account has one sid. Active Directory supports sidHistory attribute which can save additional SIDs. If you would use Active Directory API (for example ADSI) or LDAP API you can find the main users name, primary SID and all ather attributes which you need.
The most problem in answering on your question is that you don't describe the domain migration scenario which are planned and used in your organisation. When you plan to switch off the old domains controllers? Do you plan to clear the old SIDs saved in the file system, shares or in the registry?
It is important to know the full domain migration scenario, so that the program which you now write will continue to work on the next steps of domain migration. I recommend you to speak with administrators or the project manager of the domain migration project of your organization to understand what is exactly planned to do.
Assume I have access to a SMB server at IP 1.2.3.4, how can I determine the list of available shares?
Windows Explorer can do it when I enter a UNC path \\1.2.3.4\ - but command prompt "dir \\1.2.3.4\" fails!
I've tried the usual FindFirstFile/FindNext calls - which I use successfully to read the files and directories on each share, but they don't work directly on the server root.
Ideally, I need something that works for XP onwards.
Edit: I want to do this programatically, rather than from command line. Redirecting and parsing the output from 'net view 1.2.3.4' would work, but I'm ideally looking for an API for this job.
According to the docs there's a NetShareEnum and a WNetEnumResource function.
net view \\1.2.3.4
Check out http://www.ss64.com/nt/net_share.html
Edit: If you want to do this programmatically, it looks like NetShareEnum would work.
It appears you can use WMI to get this information. Check this post for some neat PowerShell tutorials that show now to use the Win32_Share WMI object.
Never use WMI (not installed natively)
Use Win32 api to enumerate shares, posted millions of times on google groups( win32)