Check Which user profile is mounted on device - c#

I want to check which user profile is assigned to my machine whether it is Roaming or Local how can I check it using c# and is there any entry of it in registry.
Thank you in Advanced

I guess one way would be to call the win32 api function GetProfileType.
In order to use it you will have to declare it as a method and use the DllImport attribute like this:
[DllImport("Userenv.dll", EntryPoint = "GetProfileType", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool GetProfileType(out ProfileType dwflags);
As I have not seen a desciption of the flag values, you will have to test it yourself. As soon as you figured out which value is returned for which profile type, you might want to create an enumeration like the following one:
[Flags]
public enum ProfileType : uint
{
Local = 0x00,
Temporary = 0x01,
Roaming = 0x02,
Mandatory = 0x04
}
Usage:
ProfileType profileType;
if (!GetProfileType(ref profileType))
{
// Error handling here...
}
if (profileType.HasFlag(ProfileType.Local))
{
// We have a local profile...
}
For details about the different User profiles check the following links:
Local User Profiles
Mandatory User Profiles
Roaming User Profiles
Temporary User Profiles
Update: Oh... it seems someone has already done the work. I've updated my answer with the (presumably) correct values and marked the question as duplicate.

Related

Is it possible to set and unset the autoproxy (WPAD) and "apply" the configuration to the system?

I need to set an automatic configuration script that will set the proxy.
When I do this through the LAN settings, all is ok and Chrome is aware of the change immediately. I tried to replicate this behavior by changing the registry key Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings -> AutoConfigURL but Chrome is aware of the change only several minutes after the change (not sure why).
My next attempt is to use Winapi, but I cannot find how to set this script. I found the read function WinHttpDetectAutoProxyConfigUrl that works well, but I cannot find a write equivalent.
How do I setup the autoproxy script with Winapi?
I have a partial answer (only for the setup of the autoproxy). After the registry modification, InternetInitializeAutoProxyDll must be called.
Here is a sample code:
[DllImport("wininet.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int InternetInitializeAutoProxyDll(uint dwReserved);
// ...
registryKey = Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
// Setup the registry value:
registryKey.SetValue("AutoConfigURL", "http://the/config/path");
// Tell Windows to initialize the proxy:
if (InternetInitializeAutoProxyDll(0) == 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
However, it does not work when the proxy is unset:
registryKey.DeleteValue(AutomaticProxyRegistryName);
// Does nothing:
if (InternetInitializeAutoProxyDll(0) == 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
Instead of fiddling directly with the registry I recommend to do everything through the WinINet API. See Programmatically Set Browser Proxy Settings in C# for info on how to do this using C#. Code mentioned in that question can also be found here.
EDIT
The example mentioned fiddles with the registry, too. I have uploaded parts of a program that show how to do everything using WinINet calls. Unfortunately the program is written in Delphi, so you might have to translate it to C#. What is important is that one always resets the proxy settings before setting new values.

ASP.NET MVC - How to detect if user is using a screen reader

So I'm currently trying to check if a user is using a screen reader on our site. The reason I would like to check if they are is because our site provides a training module in which if they are using a screen reader, I would like to show a button that would allow them to download a printable version of the training.
Here is what I have tried so far:
internal class UnsafeNativeMethods
{
public const uint SPI_GETSCREENREADER = 0x0046;
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref bool pvParam, uint fWinIni);
}
public static class ScreenReader
{
public static bool IsRunning
{
get
{
bool returnValue = false;
if (!UnsafeNativeMethods.SystemParametersInfo(UnsafeNativeMethods.SPI_GETSCREENREADER, 0, ref returnValue, 0))
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "error calling SystemParametersInfo");
}
return returnValue;
}
}
}
I snagged this code from the following StackOverflow thread: C# : How to detect if screen reader is running?
The method I'm using apparently works for some as you can see on this thread, but I'm currently always getting "false" when calling ScreenReader.IsRunning. I'm storing the ScreenReader.IsRunning value in a ViewBag and then in my view I'm using razor syntax to show a button if that value is true. Not really sure why its always false. I have tested this using JAWS as well as Narrator that comes on everyone's computer if you are using Windows 10 I think. Any help would be much appreciated. Thank you all!
It's not possible to detect whether a user is running a screenreader. If it were possible, it would open a door for unscrupulous types to home in on people with disabilities, or for a totally different "accessible" browser experience to be delivered, rather than building interfaces that are inclusive by design.
You could create a button that's placed off-screen but still in the tab order, and make it visible when it receives focus. Then blind users could find it, and sighted keyboard users wouldn't think something strange had happened when the button received focus.
I think you can only check if user has a chrome extensions or something like that working on client side with javascript.
Idea:
You can create an exe or a bath file for check users system and send information about this to your server. If user download this file and there is no screen reader then load the page. Otherwise give error about the screen reader. And when response come from user computer maybe you can use SignalR for show content to user. You can make this file a must works in users system and start downloading this file when user load the page. Its not a good way but maybe you can check this with this way.
The HttpRequest.Browser property returns a HttpBrowserCapabilities object that enlists the capabilities of the device that has made the request. Bear in mind that ASP.NET uses the User-Agent string sent as part of the HTTP request to identify a client. Then to populate the HttpBrowserCapabilities properties, ASP.NET processes the user-agent string using a set of pre-installed browser files, which are contained in the following location: %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\CONFIG\Browsers
HttpBrowserCapabilities Class
There are also third-parties which are far more detailed and updated with detecting device info, i.e. 51Degrees

Identifying if a user is in the local administrators group

My Problem
I'm using PInvoked Windows API functions to verify if a user is part of the local administrators group. I'm utilizing GetCurrentProcess, OpenProcessToken, GetTokenInformationand LookupAccountSid to verify if the user is a local admin.
GetTokenInformation returns a TOKEN_GROUPS struct with an array of SID_AND_ATTRIBUTES structs. I iterate over the collection and compare the user names returned by LookupAccountSid.
My problem is that, locally (or more generally on our in-house domain), this works as expected. The builtin\Administrators is located within the group membership of the current process token and my method returns true. On another domain of another developer the function returns false.
The LookupAccountSid functions properly for the first 2 iterations of the TOKEN_GROUPS struct, returning None and Everyone, and then craps out complaining that "A Parameter is incorrect."
What would cause only two groups to work correctly?
The TOKEN_GROUPS struct indicates that there are 14 groups. I'm assuming it's the SID that is invalid.
Everything that I have PInvoked I have taken from an example on the PInvoke website. The only difference is that with the LookupAccountSid I have changed the Sid parameter from a byte[] to a IntPtr because SID_AND_ATTRIBUTESis also defined with an IntPtr. Is this ok since LookupAccountSid is defined with a PSID?
LookupAccountSid PInvoke
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool LookupAccountSid(
string lpSystemName,
IntPtr Sid,
StringBuilder lpName,
ref uint cchName,
StringBuilder ReferencedDomainName,
ref uint cchReferencedDomainName,
out SID_NAME_USE peUse);
Where the code falls over
for (int i = 0; i < usize; i++)
{
accountCount = 0;
domainCount = 0;
//Get Sizes
LookupAccountSid(null, tokenGroups.Groups[i].SID, null, ref accountCount, null,
ref domainCount, out snu);
accountName2.EnsureCapacity((int) accountCount);
domainName.EnsureCapacity((int) domainCount);
if (!LookupAccountSid(null, tokenGroups.Groups[i].SID, accountName2, ref accountCount, domainName,
ref domainCount, out snu))
{
//Finds its way here after 2 iterations
//But only in a different developers domain
var error = Marshal.GetLastWin32Error();
_log.InfoFormat("Failed to look up SID's account name. {0}", new Win32Exception(error).Message);
continue;
}
If more code is needed let me know. Any help would be greatly appreciated.
It sounds like you're trying to duplicate the functionality of NetUserGetLocalGroups. You can also use NetUserGetInfo with an information level of 1, and check the value of usri1_priv in the USER_INFO_1 for USER_PRIV_ADMIN.
I'm not sure if NetUserGetLocalGroups knows about deny SIDs (If you need to verify if the current process (not the user account!) is in the admin group, you have to handle deny SIDs)
If you only need to support 2000 and later, PInvoke CheckTokenMembership (That MSDN page has a IsUserAdmin example function)
On NT4 you need to get a TokenGroups array from GetTokenInformation, but you don't call LookupAccountSid, you just call EqualSid on every item and compare it to a admin group SID you create with AllocateAndInitializeSid(...,SECURITY_BUILTIN_DOMAIN_RID,...)

Getting the full-name of the current user, returns an empty string (C#/C++)

I try to get the full-name of the current log-in user (Fullname, not username).
The following code C#, C++ works fine but on XP computers not connected to the Net, I get empty string as result if I run it ~20 minutes after login (It runs OK whithin the first ~20 minutes after login)
A Win32 API (GetUserNameEx) is used rather that PrincipalContext since it PrincipalContext may takes up to 15 seconds when working offline.
Any Help why am I getting an empty string as result though a user full name is specified???
- C# Code
public static string CurrentUserFullName
{
get
{
const int EXTENDED_NAME_FORMAT_NAME_DISPLAY = 3;
StringBuilder userName = new StringBuilder(256);
uint length = (uint) userName.Capacity;
string ret;
if (GetUserNameEx(EXTENDED_NAME_FORMAT_NAME_DISPLAY, userName, ref length))
{
ret = userName.ToString();
}
else
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception("GetUserNameEx Failed. Error code - " + errorCode);
}
return ret;
}
}
[DllImport("Secur32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetUserNameEx(int nameFormat, StringBuilder lpNameBuffer, ref uint lpnSize);
- Code in C++
#include "stdafx.h"
#include <windows.h>
#define SECURITY_WIN32
#include <Security.h>
#pragma comment( lib, "Secur32.lib" )
int _tmain(int argc, _TCHAR* argv[])
{
char szName[100];
ULONG nChars = sizeof( szName );
if ( GetUserNameEx( NameDisplay, szName, &nChars ) )
{
printf( "Name: %s\n", szName);
}
else
{
printf( "Failed to GetUserNameEx\n" );
printf( "%d\n", GetLastError() );
}
return 0;
}
The function GetUserNameEx with NameDisplay can't work in offline mode. This information is only accessible when the computer is online. I recommend you to implement some caching of information like full name or other which is accessible in online mode only. For example, if the computer is online you can retrieve and save information like Full User Name. So you can have in some your config-file of in registry a mapping between users SID and it's full name. If you don't able give full name directly you can get the information from your cash.
Windows has a lot of different notification (like NotifyAddrChange) which you can use (if needed) to monitor change from online to offline mode and back.
Most information which you can get about current user session (also in offline mode) you can get from LsaGetLogonSessionData and WTSQuerySessionInformation API (GetUserNameEx you already know), but you will not find full user name inside.
If you do find a way to get full name of user in offline mode please post the information to me.
Try to use GetUserNameExA (for ASCII) instead of GetUserNameEx macro. Does it help? Print also the output of the program.
I'm curious: for a 'permamently offline' station, where (in the OS) is the user name stored? By browsing control panel Users, it looks like local user accounts have no place to store a 'NameDisplay', there's only a user name.
Where that data is stored for a non-connected node would be a mystery to me. If (in fact) the data is only stored with the domain controller, the only thing I can think of is to cache the information as mentioned earlier.
So use the 1st one, check result and then invoke the 2nd via async delegate. Your app won't get any lag and full name is certainly not it's core feature - I hope :-)
Please try disabling the UAC on your machine. I guess it should work after that.
Steps to disable it.
Go to control panel.
Then to Users.
Select which admin account you wanted to retain.
Delete the account with admin privilege, which you do not wish to have.
If in future you want to create any new account with admin rights, you create an account and make it as an admin account using change account type.

What is the most secure way to retrieve the system Drive

I know that the following should work:
Environment.GetEnvironmentVariable("windir", EnvironmentVariableTarget.Machine)
My problem with this call is that if for some reason someone decided to remove the "windir" Env Var , this won't work.
Is there an even more secure way to get the System drive?
string windir = Environment.SystemDirectory; // C:\windows\system32
string windrive = Path.GetPathRoot(Environment.SystemDirectory); // C:\
Note: This property internally uses the GetSystemDirectory() Win32 API. It doesn't rely on environment variables.
This one returns the path to the system directory (system32).
Environment.GetFolderPath(Environment.SpecialFolder.System)
You may be able to use that, then you don't need to rely on environment variables.
One thing i actually maybe misunderstand is that you want the System Drive, but by using "windir" you'll get the windows folder. So if you need a secure way to get the windows folder, you should use the good old API function GetWindowsDirectory.
Here is the function prepared for C# usage. ;-)
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint GetWindowsDirectory(StringBuilder lpBuffer, uint uSize);
private string WindowsDirectory()
{
uint size = 0;
size = GetWindowsDirectory(null, size);
StringBuilder sb = new StringBuilder((int)size);
GetWindowsDirectory(sb, size);
return sb.ToString();
}
So if you really need the drive on which windows is running, you could afterwards call
System.IO.Path.GetPathRoot(WindowsDirectory());
You can use the GetWindowsDirectory API to retrieve the windows directory.
Never read environment variables (any script or user can change them !)
The official method (MS internal, used by Explorer) is a Win32 api FAQ for decades (see Google groups, Win32, System api)
Theres an environment variable called SystemDrive
C:\>SET SystemDrive
SystemDrive=C:

Categories