diff --git a/PInvoke/UserEnv/CorrelationReport.md b/PInvoke/UserEnv/CorrelationReport.md
index 0bdc11e01..978fc3e6a 100644
--- a/PInvoke/UserEnv/CorrelationReport.md
+++ b/PInvoke/UserEnv/CorrelationReport.md
@@ -1,49 +1,53 @@
## Correlation report for userenv.dll
-### Methods (4% complete, 2 of 45 functions)
-Native Method | Header | Managed Method
+### Methods (35% complete)
+Native Method | Native DLL | Header | Managed Method
+--- | --- | --- | ---
+[AreThereVisibleLogoffScripts](https://www.google.com/search?num=5&q=AreThereVisibleLogoffScripts+site%3Amicrosoft.com) | userenv.dll | |
+[AreThereVisibleShutdownScripts](https://www.google.com/search?num=5&q=AreThereVisibleShutdownScripts+site%3Amicrosoft.com) | userenv.dll | |
+[CreateAppContainerProfile](http://msdn2.microsoft.com/en-us/library/73F5F30F-4083-4D33-B181-31B782AD40D6) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.CreateAppContainerProfile
+[CreateEnvironmentBlock](http://msdn2.microsoft.com/en-us/library/bda8879d-d33a-48f4-8b08-e3a279126a07) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.CreateEnvironmentBlock
+[CreateProfile](http://msdn2.microsoft.com/en-us/library/cab9e20b-d94c-42e5-ada9-27194f398bb3) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.CreateProfile
+[DeleteAppContainerProfile](http://msdn2.microsoft.com/en-us/library/ED79D661-D087-4E44-8C32-14705ACA9D40) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.DeleteAppContainerProfile
+[DeleteProfile](http://msdn2.microsoft.com/en-us/library/48a08d9a-4fdc-43ab-8323-c49bc2d0a58d) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.DeleteProfile
+[DeriveAppContainerSidFromAppContainerName](http://msdn2.microsoft.com/en-us/library/233EFA95-289D-4D55-9D56-0630C015ABC7) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.DeriveAppContainerSidFromAppContainerName
+[DeriveRestrictedAppContainerSidFromAppContainerSidAndRestrictedName](https://www.google.com/search?num=5&q=DeriveRestrictedAppContainerSidFromAppContainerSidAndRestrictedName+site%3Amicrosoft.com) | userenv.dll | |
+[DestroyEnvironmentBlock](http://msdn2.microsoft.com/en-us/library/8d03e102-3f8a-4aa7-b175-0a6781eedea7) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.DestroyEnvironmentBlock
+[EnterCriticalPolicySection](http://msdn2.microsoft.com/en-us/library/d17578b3-3a71-456b-97ca-961b81572528) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.EnterCriticalPolicySection
+[ExpandEnvironmentStringsForUser](http://msdn2.microsoft.com/en-us/library/d32fa6c8-035a-4c84-b210-5366f21b6c17) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.ExpandEnvironmentStringsForUser
+[ForceSyncFgPolicy](https://www.google.com/search?num=5&q=ForceSyncFgPolicy+site%3Amicrosoft.com) | userenv.dll | |
+[FreeGPOList](http://msdn2.microsoft.com/en-us/library/96bd2b5b-c088-4eea-bbc2-31d83c13aa99) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.FreeGPOList
+[GenerateGPNotification](https://www.google.com/search?num=5&q=GenerateGPNotification+site%3Amicrosoft.com) | userenv.dll | |
+[GetAllUsersProfileDirectory](http://msdn2.microsoft.com/en-us/library/bd08947a-df57-4dd9-b9ba-a01b315bfdf1) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.GetAllUsersProfileDirectory
+[GetAppContainerFolderPath](http://msdn2.microsoft.com/en-us/library/7D3AB78D-C094-4F89-8032-13F3C137E910) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.GetAppContainerFolderPath
+[GetAppContainerRegistryLocation](http://msdn2.microsoft.com/en-us/library/DAD7EC07-D57D-40F5-AA99-AD7579910294) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.GetAppContainerRegistryLocation
+[GetAppliedGPOList](http://msdn2.microsoft.com/en-us/library/11e80a4e-acc4-4229-aa34-8f7d083c1041) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.GetAppliedGPOList
+[GetDefaultUserProfileDirectory](https://www.google.com/search?num=5&q=GetDefaultUserProfileDirectoryA+site%3Amicrosoft.com) | userenv.dll | |
+[GetGPOList](http://msdn2.microsoft.com/en-us/library/26c54ac5-23d7-40ed-94a9-70d25e14431f) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.GetGPOList
+[GetNextFgPolicyRefreshInfo](https://www.google.com/search?num=5&q=GetNextFgPolicyRefreshInfo+site%3Amicrosoft.com) | userenv.dll | |
+[GetPreviousFgPolicyRefreshInfo](https://www.google.com/search?num=5&q=GetPreviousFgPolicyRefreshInfo+site%3Amicrosoft.com) | userenv.dll | |
+[GetProfilesDirectory](https://www.google.com/search?num=5&q=GetProfilesDirectoryA+site%3Amicrosoft.com) | userenv.dll | |
+[GetProfileType](https://www.google.com/search?num=5&q=GetProfileType+site%3Amicrosoft.com) | userenv.dll | |
+[GetUserProfileDirectory](https://www.google.com/search?num=5&q=GetUserProfileDirectoryA+site%3Amicrosoft.com) | userenv.dll | |
+[HasPolicyForegroundProcessingCompleted](https://www.google.com/search?num=5&q=HasPolicyForegroundProcessingCompleted+site%3Amicrosoft.com) | userenv.dll | |
+[LeaveCriticalPolicySection](http://msdn2.microsoft.com/en-us/library/9e6a938f-c9cb-4baf-b7d0-4316e45f874c) | userenv.dll | userenv.h | Vanara.PInvoke.UserEnv.LeaveCriticalPolicySection
+[LoadProfileExtender](https://www.google.com/search?num=5&q=LoadProfileExtender+site%3Amicrosoft.com) | userenv.dll | |
+[LoadUserProfile](https://www.google.com/search?num=5&q=LoadUserProfileA+site%3Amicrosoft.com) | userenv.dll | |
+[ProcessGroupPolicyCompleted](https://www.google.com/search?num=5&q=ProcessGroupPolicyCompleted+site%3Amicrosoft.com) | userenv.dll | |
+[ProcessGroupPolicyCompletedEx](https://www.google.com/search?num=5&q=ProcessGroupPolicyCompletedEx+site%3Amicrosoft.com) | userenv.dll | |
+[RefreshPolicy](https://www.google.com/search?num=5&q=RefreshPolicy+site%3Amicrosoft.com) | userenv.dll | |
+[RefreshPolicyEx](https://www.google.com/search?num=5&q=RefreshPolicyEx+site%3Amicrosoft.com) | userenv.dll | |
+[RegisterGPNotification](https://www.google.com/search?num=5&q=RegisterGPNotification+site%3Amicrosoft.com) | userenv.dll | |
+[RsopAccessCheckByType](https://www.google.com/search?num=5&q=RsopAccessCheckByType+site%3Amicrosoft.com) | userenv.dll | |
+[RsopFileAccessCheck](https://www.google.com/search?num=5&q=RsopFileAccessCheck+site%3Amicrosoft.com) | userenv.dll | |
+[RsopLoggingEnabled](https://www.google.com/search?num=5&q=RsopLoggingEnabled+site%3Amicrosoft.com) | userenv.dll | |
+[RsopResetPolicySettingStatus](https://www.google.com/search?num=5&q=RsopResetPolicySettingStatus+site%3Amicrosoft.com) | userenv.dll | |
+[RsopSetPolicySettingStatus](https://www.google.com/search?num=5&q=RsopSetPolicySettingStatus+site%3Amicrosoft.com) | userenv.dll | |
+[UnloadProfileExtender](https://www.google.com/search?num=5&q=UnloadProfileExtender+site%3Amicrosoft.com) | userenv.dll | |
+[UnloadUserProfile](https://www.google.com/search?num=5&q=UnloadUserProfile+site%3Amicrosoft.com) | userenv.dll | |
+[UnregisterGPNotification](https://www.google.com/search?num=5&q=UnregisterGPNotification+site%3Amicrosoft.com) | userenv.dll | |
+[WaitForMachinePolicyForegroundProcessing](https://www.google.com/search?num=5&q=WaitForMachinePolicyForegroundProcessing+site%3Amicrosoft.com) | userenv.dll | |
+[WaitForUserPolicyForegroundProcessing](https://www.google.com/search?num=5&q=WaitForUserPolicyForegroundProcessing+site%3Amicrosoft.com) | userenv.dll | |
+### Structures
+Native Structure | Header | Managed Structure
--- | --- | ---
-[AreThereVisibleLogoffScripts](https://www.google.com/search?num=5&q=AreThereVisibleLogoffScripts+site%3Amicrosoft.com) | |
-[AreThereVisibleShutdownScripts](https://www.google.com/search?num=5&q=AreThereVisibleShutdownScripts+site%3Amicrosoft.com) | |
-[CreateAppContainerProfile](https://www.google.com/search?num=5&q=CreateAppContainerProfile+site%3Amicrosoft.com) | |
-[CreateEnvironmentBlock](http://msdn2.microsoft.com/en-us/library/bda8879d-d33a-48f4-8b08-e3a279126a07) | userenv.h | [Vanara.PInvoke.UserEnv.CreateEnvironmentBlock](https://github.com/dahall/Vanara/search?l=C%23&q=CreateEnvironmentBlock)
-[CreateProfile](https://www.google.com/search?num=5&q=CreateProfile+site%3Amicrosoft.com) | |
-[DeleteAppContainerProfile](https://www.google.com/search?num=5&q=DeleteAppContainerProfile+site%3Amicrosoft.com) | |
-[DeleteProfile](https://www.google.com/search?num=5&q=DeleteProfileA+site%3Amicrosoft.com) | |
-[DeriveAppContainerSidFromAppContainerName](https://www.google.com/search?num=5&q=DeriveAppContainerSidFromAppContainerName+site%3Amicrosoft.com) | |
-[DeriveRestrictedAppContainerSidFromAppContainerSidAndRestrictedName](https://www.google.com/search?num=5&q=DeriveRestrictedAppContainerSidFromAppContainerSidAndRestrictedName+site%3Amicrosoft.com) | |
-[DestroyEnvironmentBlock](http://msdn2.microsoft.com/en-us/library/8d03e102-3f8a-4aa7-b175-0a6781eedea7) | userenv.h | [Vanara.PInvoke.UserEnv.DestroyEnvironmentBlock](https://github.com/dahall/Vanara/search?l=C%23&q=DestroyEnvironmentBlock)
-[EnterCriticalPolicySection](https://www.google.com/search?num=5&q=EnterCriticalPolicySection+site%3Amicrosoft.com) | |
-[ExpandEnvironmentStringsForUser](https://www.google.com/search?num=5&q=ExpandEnvironmentStringsForUserA+site%3Amicrosoft.com) | |
-[ForceSyncFgPolicy](https://www.google.com/search?num=5&q=ForceSyncFgPolicy+site%3Amicrosoft.com) | |
-[FreeGPOList](https://www.google.com/search?num=5&q=FreeGPOListA+site%3Amicrosoft.com) | |
-[GenerateGPNotification](https://www.google.com/search?num=5&q=GenerateGPNotification+site%3Amicrosoft.com) | |
-[GetAllUsersProfileDirectory](https://www.google.com/search?num=5&q=GetAllUsersProfileDirectoryA+site%3Amicrosoft.com) | |
-[GetAppContainerFolderPath](https://www.google.com/search?num=5&q=GetAppContainerFolderPath+site%3Amicrosoft.com) | |
-[GetAppContainerRegistryLocation](https://www.google.com/search?num=5&q=GetAppContainerRegistryLocation+site%3Amicrosoft.com) | |
-[GetAppliedGPOList](https://www.google.com/search?num=5&q=GetAppliedGPOListA+site%3Amicrosoft.com) | |
-[GetDefaultUserProfileDirectory](https://www.google.com/search?num=5&q=GetDefaultUserProfileDirectoryA+site%3Amicrosoft.com) | |
-[GetGPOList](https://www.google.com/search?num=5&q=GetGPOListA+site%3Amicrosoft.com) | |
-[GetNextFgPolicyRefreshInfo](https://www.google.com/search?num=5&q=GetNextFgPolicyRefreshInfo+site%3Amicrosoft.com) | |
-[GetPreviousFgPolicyRefreshInfo](https://www.google.com/search?num=5&q=GetPreviousFgPolicyRefreshInfo+site%3Amicrosoft.com) | |
-[GetProfilesDirectory](https://www.google.com/search?num=5&q=GetProfilesDirectoryA+site%3Amicrosoft.com) | |
-[GetProfileType](https://www.google.com/search?num=5&q=GetProfileType+site%3Amicrosoft.com) | |
-[GetUserProfileDirectory](https://www.google.com/search?num=5&q=GetUserProfileDirectoryA+site%3Amicrosoft.com) | |
-[HasPolicyForegroundProcessingCompleted](https://www.google.com/search?num=5&q=HasPolicyForegroundProcessingCompleted+site%3Amicrosoft.com) | |
-[LeaveCriticalPolicySection](https://www.google.com/search?num=5&q=LeaveCriticalPolicySection+site%3Amicrosoft.com) | |
-[LoadProfileExtender](https://www.google.com/search?num=5&q=LoadProfileExtender+site%3Amicrosoft.com) | |
-[LoadUserProfile](https://www.google.com/search?num=5&q=LoadUserProfileA+site%3Amicrosoft.com) | |
-[ProcessGroupPolicyCompleted](https://www.google.com/search?num=5&q=ProcessGroupPolicyCompleted+site%3Amicrosoft.com) | |
-[ProcessGroupPolicyCompletedEx](https://www.google.com/search?num=5&q=ProcessGroupPolicyCompletedEx+site%3Amicrosoft.com) | |
-[RefreshPolicy](https://www.google.com/search?num=5&q=RefreshPolicy+site%3Amicrosoft.com) | |
-[RefreshPolicyEx](https://www.google.com/search?num=5&q=RefreshPolicyEx+site%3Amicrosoft.com) | |
-[RegisterGPNotification](https://www.google.com/search?num=5&q=RegisterGPNotification+site%3Amicrosoft.com) | |
-[RsopAccessCheckByType](https://www.google.com/search?num=5&q=RsopAccessCheckByType+site%3Amicrosoft.com) | |
-[RsopFileAccessCheck](https://www.google.com/search?num=5&q=RsopFileAccessCheck+site%3Amicrosoft.com) | |
-[RsopLoggingEnabled](https://www.google.com/search?num=5&q=RsopLoggingEnabled+site%3Amicrosoft.com) | |
-[RsopResetPolicySettingStatus](https://www.google.com/search?num=5&q=RsopResetPolicySettingStatus+site%3Amicrosoft.com) | |
-[RsopSetPolicySettingStatus](https://www.google.com/search?num=5&q=RsopSetPolicySettingStatus+site%3Amicrosoft.com) | |
-[UnloadProfileExtender](https://www.google.com/search?num=5&q=UnloadProfileExtender+site%3Amicrosoft.com) | |
-[UnloadUserProfile](https://www.google.com/search?num=5&q=UnloadUserProfile+site%3Amicrosoft.com) | |
-[UnregisterGPNotification](https://www.google.com/search?num=5&q=UnregisterGPNotification+site%3Amicrosoft.com) | |
-[WaitForMachinePolicyForegroundProcessing](https://www.google.com/search?num=5&q=WaitForMachinePolicyForegroundProcessing+site%3Amicrosoft.com) | |
-[WaitForUserPolicyForegroundProcessing](https://www.google.com/search?num=5&q=WaitForUserPolicyForegroundProcessing+site%3Amicrosoft.com) | |
+[GROUP_POLICY_OBJECT](http://msdn2.microsoft.com/en-us/library/7275a3cd-6b19-4eb9-9481-b73bd5af5753) | userenv.h | Vanara.PInvoke.UserEnv+GROUP_POLICY_OBJECT
diff --git a/PInvoke/UserEnv/UserEnv.cs b/PInvoke/UserEnv/UserEnv.cs
index 80379506c..2d5609422 100644
--- a/PInvoke/UserEnv/UserEnv.cs
+++ b/PInvoke/UserEnv/UserEnv.cs
@@ -1,13 +1,202 @@
-using System;
+using Microsoft.Win32.SafeHandles;
+using System;
using System.Linq;
using System.Runtime.InteropServices;
+using System.Text;
using Vanara.Extensions;
+using Vanara.InteropServices;
+using static Vanara.PInvoke.AdvApi32;
+using static Vanara.PInvoke.Kernel32;
namespace Vanara.PInvoke
{
/// Functions and interfaces from UserEnv.dll.
public static partial class UserEnv
{
+ /// Specifies the link information for the GPO.
+ [PInvokeData("userenv.h", MSDNShortId = "7275a3cd-6b19-4eb9-9481-b73bd5af5753")]
+ public enum GPO_LINK
+ {
+ /// No link information is available.
+ GPLinkUnknown = 0,
+
+ /// The GPO is linked to a computer (local or remote).
+ GPLinkMachine,
+
+ /// The GPO is linked to a site.
+ GPLinkSite,
+
+ /// The GPO is linked to a domain.
+ GPLinkDomain,
+
+ /// The GPO is linked to an organizational unit.
+ GPLinkOrganizationalUnit
+ }
+
+ /// Flags used when getting GPO info.
+ [PInvokeData("userenv.h")]
+ [Flags]
+ public enum GPO_LIST_FLAG
+ {
+ /// The gpo list flag machine
+ GPO_LIST_FLAG_MACHINE = 0x00000001,
+
+ /// The gpo list flag siteonly
+ GPO_LIST_FLAG_SITEONLY = 0x00000002,
+
+ /// Ignore WMI filters when filtering GPO's
+ GPO_LIST_FLAG_NO_WMIFILTERS = 0x00000004,
+
+ /// Ignore security filters
+ GPO_LIST_FLAG_NO_SECURITYFILTERS = 0x00000008
+ }
+
+ /// Flags for .
+ [PInvokeData("profinfo.h", MSDNShortId = "09dae38c-3b2b-4f12-9c1e-90737cf0c7cc")]
+ [Flags]
+ public enum ProfileInfoFlags : uint
+ {
+ /// Prevents the display of profile error messages.
+ PI_NOUI = 0x00000001,
+
+ /// Not supported.
+ PI_APPLYPOLICY = 0x00000002,
+ }
+
+ /// Profile type flags.
+ [PInvokeData("userenv.h", MSDNShortId = "55ee76c8-1735-43eb-a98e-9e6c87ee1ba7")]
+ [Flags]
+ public enum ProfileType
+ {
+ /// The user has a Temporary User Profiles; it will be deleted at logoff.
+ PT_TEMPORARY = 0x00000001,
+
+ /// The user has a Roaming User Profiles.
+ PT_ROAMING = 0x00000002,
+
+ /// The user has a Mandatory User Profiles.
+ PT_MANDATORY = 0x00000004,
+
+ ///
+ /// The user has a Roaming User Profile that was created on another PC and is being downloaded. This profile type implies PT_ROAMING.
+ ///
+ PT_ROAMING_PREEXISTING = 0x00000008,
+ }
+
+ /// Options for .
+ [PInvokeData("userenv.h", MSDNShortId = "905ab96b-a7f2-4bb4-a539-385f78284644")]
+ [Flags]
+ public enum RefreshPolicyOption : uint
+ {
+ /// Reapply all policies even if no policy change was detected.
+ RP_FORCE = 1,
+
+ /// The call does not return till the time policy processing is completed.
+ RP_SYNC = 2
+ }
+
+ /// Creates a per-user, per-app profile for Windows Store apps.
+ ///
+ /// The name of the app container. To ensure uniqueness, it is recommended that this string contains the app name as well as the
+ /// publisher. This string can be up to 64 characters in length. Further, it must fit into the pattern described by the regular
+ /// expression "[-_. A-Za-z0-9]+".
+ ///
+ /// The display name. This string can be up to 512 characters in length.
+ /// A description for the app container. This string can be up to 2048 characters in length.
+ /// The SIDs that define the requested capabilities.
+ /// The number of SIDs in pCapabilities.
+ /// The SID for the profile.
+ ///
+ /// If this function succeeds, it returns a standard HRESULT code, including the following:
+ ///
+ ///
+ /// Return code
+ /// Description
+ ///
+ /// -
+ /// S_OK
+ /// The data store was created successfully.
+ ///
+ /// -
+ /// E_ACCESSDENIED
+ /// The caller does not have permission to create the profile.
+ ///
+ /// -
+ /// HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)
+ /// The application data store already exists.
+ ///
+ /// -
+ /// E_INVALIDARG
+ ///
+ /// The container name is NULL, or the container name, the display name, or the description strings exceed their specified
+ /// respective limits for length.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// A profile contains folders and registry storage that are per-user and per-app. The folders have ACLs that prevent them from
+ /// being accessed by other users and apps. These folders can be accessed by calling SHGetKnownFolderPath.
+ ///
+ ///
+ /// The function creates a profile for the current user. To create a profile on behalf of another user, you must impersonate that
+ /// user. To create profiles for multiple users of the same app, you must call CreateAppContainerProfile for each user.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-createappcontainerprofile USERENVAPI HRESULT
+ // CreateAppContainerProfile( PCWSTR pszAppContainerName, PCWSTR pszDisplayName, PCWSTR pszDescription, PSID_AND_ATTRIBUTES
+ // pCapabilities, DWORD dwCapabilityCount, PSID *ppSidAppContainerSid );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "73F5F30F-4083-4D33-B181-31B782AD40D6")]
+ public static extern HRESULT CreateAppContainerProfile([MarshalAs(UnmanagedType.LPWStr)] string pszAppContainerName, [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName,
+ [MarshalAs(UnmanagedType.LPWStr)] string pszDescription, [In] SID_AND_ATTRIBUTES[] pCapabilities, uint dwCapabilityCount, out SafeAllocatedSID ppSidAppContainerSid);
+
+ ///
+ /// Retrieves the environment variables for the specified user. This block can then be passed to the CreateProcessAsUser function.
+ ///
+ ///
+ /// Type: LPVOID*
+ /// When this function returns, receives an array of strings.
+ ///
+ ///
+ /// Type: HANDLE
+ ///
+ /// Token for the user, returned from the LogonUser function. If this is a primary token, the token must have TOKEN_QUERY and
+ /// TOKEN_DUPLICATE access. If the token is an impersonation token, it must have TOKEN_QUERY access. For more
+ /// information, see Access Rights for Access-Token Objects.
+ ///
+ /// If this parameter is NULL, the returned environment block contains system variables only.
+ ///
+ ///
+ /// Type: BOOL
+ ///
+ /// Specifies whether to inherit from the current process' environment. If this value is TRUE, the process inherits the
+ /// current process' environment. If this value is FALSE, the process does not inherit the current process' environment.
+ ///
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// If the environment block is passed to CreateProcessAsUser, you must also specify the CREATE_UNICODE_ENVIRONMENT flag.
+ /// After CreateProcessAsUser has returned, the new process has a copy of the environment block.
+ ///
+ ///
+ /// User-specific environment variables such as %USERPROFILE% are set only when the user's profile is loaded. To load a user's
+ /// profile, call the LoadUserProfile function.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-createenvironmentblock BOOL CreateEnvironmentBlock( LPVOID
+ // *lpEnvironment, HANDLE hToken, BOOL bInherit );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "bda8879d-d33a-48f4-8b08-e3a279126a07")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool CreateEnvironmentBlock([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(EnvBlockMarshaler))] out string[] lpEnvironment,
+ HTOKEN hToken, [MarshalAs(UnmanagedType.Bool)] bool bInherit);
+
///
/// Retrieves the environment variables for the specified user. This block can then be passed to the CreateProcessAsUser function.
///
@@ -55,7 +244,161 @@ public static partial class UserEnv
[DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
[PInvokeData("userenv.h", MSDNShortId = "bda8879d-d33a-48f4-8b08-e3a279126a07")]
[return: MarshalAs(UnmanagedType.Bool)]
- public static extern bool CreateEnvironmentBlock([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(EnvBlockMarshaler))] out string[] lpEnvironment, HTOKEN hToken, [MarshalAs(UnmanagedType.Bool)] bool bInherit);
+ public static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, HTOKEN hToken, [MarshalAs(UnmanagedType.Bool)] bool bInherit);
+
+ /// Creates a new user profile.
+ ///
+ /// Type: LPCWSTR
+ /// Pointer to the SID of the user as a string.
+ ///
+ ///
+ /// Type: LPCWSTR
+ /// The user name of the new user. This name is used as the base name for the profile directory.
+ ///
+ ///
+ /// Type: LPWSTR
+ /// When this function returns, contains a pointer to the full path of the profile.
+ ///
+ ///
+ /// Type: DWORD
+ /// Size of the buffer pointed to by pszProfilePath, in characters.
+ ///
+ ///
+ /// Type: HRESULT
+ /// Returns S_OK if successful, or an error value otherwise, including the following:
+ ///
+ ///
+ /// Return code
+ /// Description
+ ///
+ /// -
+ /// E_ACCESSDENIED
+ /// The caller does not have a sufficient permission level to create the profile.
+ ///
+ /// -
+ /// HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)
+ /// A profile already exists for the specified user.
+ ///
+ ///
+ ///
+ /// The caller must have administrator privileges to call this function.
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-createprofile USERENVAPI HRESULT CreateProfile( LPCWSTR
+ // pszUserSid, LPCWSTR pszUserName, LPWSTR pszProfilePath, DWORD cchProfilePath );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "cab9e20b-d94c-42e5-ada9-27194f398bb3")]
+ public static extern HRESULT CreateProfile([MarshalAs(UnmanagedType.LPWStr)] string pszUserSid, [MarshalAs(UnmanagedType.LPWStr)] string pszUserName,
+ [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszProfilePath, uint cchProfilePath);
+
+ /// Deletes the specified per-user, per-app profile.
+ ///
+ /// The name given to the profile in the call to the CreateAppContainerProfile function. This string is at most 64 characters in
+ /// length, and fits into the pattern described by the regular expression "[-_. A-Za-z0-9]+".
+ ///
+ ///
+ /// If this function succeeds, it returns a standard HRESULT code, including the following:
+ ///
+ ///
+ /// Return code
+ /// Description
+ ///
+ /// -
+ /// HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED)
+ /// If the method is called from within an app container.
+ ///
+ /// -
+ /// S_OK
+ /// The profile was deleted successfully.
+ ///
+ /// -
+ /// E_INVALIDARG
+ /// If the container name is NULL, or if it exceeds its specified limit for length.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// To ensure the best results, close all file handles in the profile storage locations before calling the
+ /// DeleteAppContainerProfile function. Otherwise, this function may not be able to completely remove the storage locations
+ /// for the profile.
+ ///
+ ///
+ /// This function deletes the profile for the current user. To delete the profile for another user, you must impersonate that user.
+ ///
+ ///
+ /// If the function fails, the status of the profile is undetermined, and you should call DeleteAppContainerProfile again to
+ /// complete the operation.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-deleteappcontainerprofile USERENVAPI HRESULT
+ // DeleteAppContainerProfile( PCWSTR pszAppContainerName );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "ED79D661-D087-4E44-8C32-14705ACA9D40")]
+ public static extern HRESULT DeleteAppContainerProfile([MarshalAs(UnmanagedType.LPWStr)] string pszAppContainerName);
+
+ ///
+ /// Deletes the user profile and all user-related settings from the specified computer. The caller must have administrative
+ /// privileges to delete a user's profile.
+ ///
+ ///
+ /// Type: LPCTSTR
+ /// Pointer to a string that specifies the user SID.
+ ///
+ ///
+ /// Type: LPCTSTR
+ ///
+ /// Pointer to a string that specifies the profile path. If this parameter is NULL, the function obtains the path from the registry.
+ ///
+ ///
+ ///
+ /// Type: LPCTSTR
+ ///
+ /// Pointer to a string that specifies the name of the computer from which the profile is to be deleted. If this parameter is
+ /// NULL, the local computer name is used.
+ ///
+ ///
+ /// Note As of Windows Vista, this parameter must be NULL. If it is not, this function fails with the error code ERROR_INVALID_PARAMETER.
+ ///
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// DeleteProfile might fail when passed the security identifier (SID) of the local system account (S-1-5-18). For more
+ /// information, see KB890212.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-deleteprofilea USERENVAPI BOOL DeleteProfileA( LPCSTR
+ // lpSidString, LPCSTR lpProfilePath, LPCSTR lpComputerName );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "48a08d9a-4fdc-43ab-8323-c49bc2d0a58d")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool DeleteProfile(string lpSidString, [Optional] string lpProfilePath, [Optional] string lpComputerName);
+
+ /// Gets the SID of the specified profile.
+ /// The name of the profile.
+ /// The SID for the profile.
+ ///
+ /// This function can return one of these values.
+ ///
+ ///
+ /// Return code
+ /// Description
+ ///
+ /// -
+ /// S_OK
+ /// The operation completed successfully.
+ ///
+ /// -
+ /// E_INVALIDARG
+ /// The pszAppContainerName parameter, or the ppsidAppContainerSid parameter is either NULL or not valid.
+ ///
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-deriveappcontainersidfromappcontainername USERENVAPI
+ // HRESULT DeriveAppContainerSidFromAppContainerName( PCWSTR pszAppContainerName, PSID *ppsidAppContainerSid );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "233EFA95-289D-4D55-9D56-0630C015ABC7")]
+ public static extern HRESULT DeriveAppContainerSidFromAppContainerName([MarshalAs(UnmanagedType.LPWStr)] string pszAppContainerName, out SafeAllocatedSID ppsidAppContainerSid);
/// Frees environment variables created by the CreateEnvironmentBlock function.
///
@@ -76,41 +419,1306 @@ public static partial class UserEnv
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DestroyEnvironmentBlock(IntPtr lpEnvironment);
- private class EnvBlockMarshaler : ICustomMarshaler
- {
- private EnvBlockMarshaler(string _)
- {
- }
+ ///
+ /// The EnterCriticalPolicySection function pauses the application of policy to allow applications to safely read policy
+ /// settings. Applications call this function if they read multiple policy entries and must ensure that the settings are not changed
+ /// while they are being read. This mutex protects Group Policy processing for all client-side extensions stored in a Group Policy
+ /// Object (GPO).
+ ///
+ ///
+ /// A value that specifies whether to stop the application of computer policy or user policy. If this value is TRUE, the
+ /// system stops applying computer policy. If this value is FALSE, the system stops applying user policy.
+ ///
+ ///
+ /// If the function succeeds, the return value is a handle to a policy section.
+ /// If the function fails, the return value is NULL. To get extended error information, call the GetLastError function.
+ ///
+ ///
+ ///
+ /// The maximum amount of time an application can hold a critical section is 10 minutes. After 10 minutes, the system releases the
+ /// critical section and policy can be applied again.
+ ///
+ ///
+ /// To acquire both the computer and user critical section objects, acquire the user critical section object before acquiring the
+ /// computer critical section object. This will help prevent a deadlock situation.
+ ///
+ ///
+ /// To close the handle, call the LeaveCriticalPolicySection function. The policy section handle cannot be used in any other Windows functions.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-entercriticalpolicysection USERENVAPI HANDLE
+ // EnterCriticalPolicySection( BOOL bMachine );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "d17578b3-3a71-456b-97ca-961b81572528")]
+ public static extern SafeCriticalPolicySectionHandle EnterCriticalPolicySection([MarshalAs(UnmanagedType.Bool)] bool bMachine);
- /// Gets the instance.
- /// The cookie.
- /// A new instance of this class.
- public static ICustomMarshaler GetInstance(string cookie) => new EnvBlockMarshaler(cookie);
+ /// Expands the source string by using the environment block established for the specified user.
+ ///
+ /// Type: HANDLE
+ ///
+ /// Token for the user, returned from the LogonUser, CreateRestrictedToken, DuplicateToken, OpenProcessToken, or OpenThreadToken
+ /// function. The token must have TOKEN_IMPERSONATE and TOKEN_QUERY access. In addition, as of Windows 7 the token must also have
+ /// TOKEN_DUPLICATE access. For more information, see Access Rights for Access-Token Objects.
+ ///
+ /// If hToken is NULL, the environment block contains system variables only.
+ ///
+ ///
+ /// Type: LPCTSTR
+ /// Pointer to the null-terminated source string to be expanded.
+ ///
+ ///
+ /// Type: LPTSTR
+ /// Pointer to a buffer that receives the expanded strings.
+ ///
+ ///
+ /// Type: DWORD
+ /// Specifies the size of the lpDest buffer, in TCHARs.
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// The following is an example source string:
+ /// When ExpandEnvironmentStringsForUser returns, the destination string expands as follows:
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-expandenvironmentstringsforusera USERENVAPI BOOL
+ // ExpandEnvironmentStringsForUserA( HANDLE hToken, LPCSTR lpSrc, LPSTR lpDest, DWORD dwSize );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "d32fa6c8-035a-4c84-b210-5366f21b6c17")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool ExpandEnvironmentStringsForUser(HTOKEN hToken, string lpSrc, StringBuilder lpDest, uint dwSize);
- ///
- void ICustomMarshaler.CleanUpManagedData(object ManagedObj) { }
+ /// The FreeGPOList function frees the specified list of GPOs.
+ ///
+ /// A pointer to the list of GPO structures. This list is returned by the GetGPOList or GetAppliedGPOList function. For more
+ /// information, see GROUP_POLICY_OBJECT.
+ ///
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-freegpolista USERENVAPI BOOL FreeGPOListA(
+ // PGROUP_POLICY_OBJECTA pGPOList );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "96bd2b5b-c088-4eea-bbc2-31d83c13aa99")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool FreeGPOList(IntPtr pGPOList);
- ///
- void ICustomMarshaler.CleanUpNativeData(IntPtr pNativeData) { }
+ /// Retrieves the path to the root of the directory that contains program data shared by all users.
+ ///
+ /// Type: LPTSTR
+ ///
+ /// A pointer to a buffer that, when this function returns successfully, receives the path. Set this value to NULL to
+ /// determine the required size of the buffer, including the terminating null character.
+ ///
+ ///
+ ///
+ /// Type: LPDWORD
+ /// A pointer to the size of the lpProfileDir buffer, in TCHARs.
+ ///
+ /// If the buffer specified by lpProfileDir is not large enough or lpProfileDir is NULL, the function fails and this
+ /// parameter receives the necessary buffer size, including the terminating null character.
+ ///
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// The following is an example of the path returned by GetAllUsersProfileDirectory in Windows XP:
+ /// The following is an example of the path returned by GetAllUsersProfileDirectory in Windows 7:
+ ///
+ /// To obtain the paths of subdirectories of this directory, use the SHGetFolderPath (Windows XP and earlier) or
+ /// SHGetKnownFolderPath (Windows Vista) function.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getallusersprofiledirectorya USERENVAPI BOOL
+ // GetAllUsersProfileDirectoryA( LPSTR lpProfileDir, LPDWORD lpcchSize );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "bd08947a-df57-4dd9-b9ba-a01b315bfdf1")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetAllUsersProfileDirectory(StringBuilder lpProfileDir, ref uint lpcchSize);
- ///
- int ICustomMarshaler.GetNativeDataSize() => -1;
+ /// Gets the path of the local app data folder for the specified app container.
+ /// A pointer to the SID of the app container.
+ ///
+ /// The address of a pointer to a string that, when this function returns successfully, receives the path of the local folder.
+ ///
+ ///
+ /// This function returns an HRESULT code, including but not limited to the following:
+ ///
+ ///
+ /// Return code
+ /// Description
+ ///
+ /// -
+ /// S_OK
+ /// The operation completed successfully.
+ ///
+ /// -
+ /// E_INVALIDARG
+ /// The pszAppContainerSid or ppszPath parameter is NULL.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// The path retrieved through this function is the same path that you would get by calling the SHGetKnownFolderPath function with FOLDERID_LocalAppData.
+ ///
+ ///
+ /// If a thread token is set, this function uses the app container for the current user. If no thread token is set, this function
+ /// uses the app container associated with the process identity.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getappcontainerfolderpath USERENVAPI HRESULT
+ // GetAppContainerFolderPath( PCWSTR pszAppContainerSid, PWSTR *ppszPath );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "7D3AB78D-C094-4F89-8032-13F3C137E910")]
+ public static extern HRESULT GetAppContainerFolderPath([MarshalAs(UnmanagedType.LPWStr)] string pszAppContainerSid, out SafeCoTaskMemString ppszPath);
- ///
- IntPtr ICustomMarshaler.MarshalManagedToNative(object ManagedObj) => throw new NotImplementedException();
+ /// Gets the location of the registry storage associated with an app container.
+ ///
+ /// Type: REGSAM
+ /// The desired registry access.
+ ///
+ ///
+ /// Type: PHKEY
+ ///
+ /// A pointer to an HKEY that, when this function returns successfully, receives the registry storage location for the current profile.
+ ///
+ ///
+ ///
+ /// Type: HRESULT
+ /// This function returns an HRESULT code, including but not limited to the following:
+ ///
+ ///
+ /// Return code
+ /// Description
+ ///
+ /// -
+ /// S_OK
+ /// The operation completed successfully.
+ ///
+ /// -
+ /// E_INVALIDARG
+ /// The caller is not running as or impersonating a user who can access this profile.
+ ///
+ ///
+ ///
+ ///
+ /// The function gets the registry storage for the current user. To get the registry storage for another user, you must impersonate
+ /// that user.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getappcontainerregistrylocation USERENVAPI HRESULT
+ // GetAppContainerRegistryLocation( REGSAM desiredAccess, PHKEY phAppContainerKey );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "DAD7EC07-D57D-40F5-AA99-AD7579910294")]
+ public static extern HRESULT GetAppContainerRegistryLocation(REGSAM desiredAccess, out HKEY phAppContainerKey);
- ///
- object ICustomMarshaler.MarshalNativeToManaged(IntPtr pNativeData)
- {
- try
- {
- return pNativeData.ToStringEnum(CharSet.Unicode).ToArray();
- }
- finally
- {
- DestroyEnvironmentBlock(pNativeData);
+ /// The GetAppliedGPOList function retrieves the list of GPOs applied for the specified user or computer.
+ ///
+ /// A value that specifies the policy type. This parameter can be the following value.
+ /// GPO_LIST_FLAG_MACHINE
+ /// Retrieves information about the computer policy.
+ /// If this value is not specified, the function retrieves only user policy information.
+ ///
+ ///
+ /// A pointer to the name of the remote computer. The format of the name is "\computer_name". If this parameter is NULL, the
+ /// local computer name is used.
+ ///
+ ///
+ ///
+ /// A value that specifies the SID of the user. If pMachineName is not NULL and dwFlags specifies user policy, then pSidUser
+ /// cannot be NULL.
+ ///
+ ///
+ /// If pMachineName is NULL and pSidUser is NULL, the user is the currently logged-on user. If pMachineName is
+ /// NULL and pSidUser is not NULL, the user is represented by pSidUser on the local computer. For more information,
+ /// see Security Identifiers.
+ ///
+ ///
+ /// A value that specifies the GUID of the extension.
+ /// A pointer that receives the list of GPO structures. For more information, see GROUP_POLICY_OBJECT.
+ ///
+ /// If the function succeeds, the return value is ERROR_SUCCESS. Otherwise, the function returns a system error code. For a
+ /// complete list of error codes, see System Error Codes or the header file WinError.h.
+ ///
+ /// To free the GPO list when you have finished processing it, call the FreeGPOList function.
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getappliedgpolista USERENVAPI DWORD GetAppliedGPOListA(
+ // DWORD dwFlags, LPCSTR pMachineName, PSID pSidUser, GUID *pGuidExtension, PGROUP_POLICY_OBJECTA *ppGPOList );
+ [DllImport(Lib.Userenv, SetLastError = false, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "11e80a4e-acc4-4229-aa34-8f7d083c1041")]
+ public static extern Win32Error GetAppliedGPOList(GPO_LIST_FLAG dwFlags, [Optional] string pMachineName, [Optional] PSID pSidUser, in Guid pGuidExtension, out IntPtr ppGPOList);
+
+ /// The GetAppliedGPOList function retrieves the list of GPOs applied for the specified user or computer.
+ ///
+ /// A value that specifies the policy type. This parameter can be the following value.
+ /// GPO_LIST_FLAG_MACHINE
+ /// Retrieves information about the computer policy.
+ /// If this value is not specified, the function retrieves only user policy information.
+ ///
+ ///
+ /// A pointer to the name of the remote computer. The format of the name is "\computer_name". If this parameter is NULL, the
+ /// local computer name is used.
+ ///
+ ///
+ ///
+ /// A value that specifies the SID of the user. If pMachineName is not NULL and dwFlags specifies user policy, then pSidUser
+ /// cannot be NULL.
+ ///
+ ///
+ /// If pMachineName is NULL and pSidUser is NULL, the user is the currently logged-on user. If pMachineName is
+ /// NULL and pSidUser is not NULL, the user is represented by pSidUser on the local computer. For more information,
+ /// see Security Identifiers.
+ ///
+ ///
+ /// A value that specifies the GUID of the extension.
+ /// A pointer that receives the list of GPO structures. For more information, see GROUP_POLICY_OBJECT.
+ ///
+ /// If the function succeeds, the return value is ERROR_SUCCESS. Otherwise, the function returns a system error code. For a
+ /// complete list of error codes, see System Error Codes or the header file WinError.h.
+ ///
+ /// To free the GPO list when you have finished processing it, call the FreeGPOList function.
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getappliedgpolista USERENVAPI DWORD GetAppliedGPOListA(
+ // DWORD dwFlags, LPCSTR pMachineName, PSID pSidUser, GUID *pGuidExtension, PGROUP_POLICY_OBJECTA *ppGPOList );
+ [DllImport(Lib.Userenv, SetLastError = false, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "11e80a4e-acc4-4229-aa34-8f7d083c1041")]
+ public static extern Win32Error GetAppliedGPOList(GPO_LIST_FLAG dwFlags, [Optional] string pMachineName, [Optional] PSID pSidUser, in Guid pGuidExtension,
+ [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(GPOMarshaler))] out GROUP_POLICY_OBJECT[] ppGPOList);
+
+ /// Retrieves the path to the root of the default user's profile.
+ ///
+ /// Type: LPTSTR
+ ///
+ /// A pointer to a buffer that, when this function returns successfully, receives the path to the default user's profile directory.
+ /// Set this value to NULL to determine the required size of the buffer.
+ ///
+ ///
+ ///
+ /// Type: LPDWORD
+ /// Specifies the size of the lpProfileDir buffer, in TCHARs.
+ ///
+ /// If the buffer specified by lpProfileDir is not large enough or lpProfileDir is NULL, the function fails and this
+ /// parameter receives the necessary buffer size, including the terminating null character.
+ ///
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// The following is an example of the path returned by GetDefaultUserProfileDirectory in Windows XP:
+ /// The following is an example of the path returned by GetDefaultUserProfileDirectory in Windows 7:
+ ///
+ /// To obtain the paths of subdirectories of this directory, use the SHGetFolderPath (Windows XP and earlier) or
+ /// SHGetKnownFolderPath (Windows Vista) function.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getdefaultuserprofiledirectorya USERENVAPI BOOL
+ // GetDefaultUserProfileDirectoryA( LPSTR lpProfileDir, LPDWORD lpcchSize );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "14ff99cb-838a-442b-9f51-414bd7c0a2ef")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetDefaultUserProfileDirectory(StringBuilder lpProfileDir, ref uint lpcchSize);
+
+ ///
+ /// The GetGPOList function retrieves the list of GPOs for the specified user or computer. This function can be called in two
+ /// ways: first, you can use the token for the user or computer, or, second, you can use the name of the user or computer and the
+ /// name of the domain controller.
+ ///
+ ///
+ ///
+ /// A token for the user or computer, returned from the LogonUser, CreateRestrictedToken, DuplicateToken, OpenProcessToken, or
+ /// OpenThreadToken function. This token must have TOKEN_IMPERSONATE and TOKEN_QUERY access. For more information, see
+ /// Access Rights for Access-Token Objects and the following Remarks section.
+ ///
+ /// If this parameter is NULL, you must supply values for the lpName and lpHostName parameters.
+ ///
+ ///
+ ///
+ /// A pointer to the user or computer name, in the fully qualified distinguished name format (for example, "CN=user, OU=users,
+ /// DC=contoso, DC=com").
+ ///
+ /// If the hToken parameter is not NULL, this parameter must be NULL.
+ ///
+ ///
+ ///
+ /// A DNS domain name or domain controller name. Domain controller name can be retrieved using the DsGetDcName function, specifying
+ /// DS_DIRECTORY_SERVICE_REQUIRED in the flags parameter.
+ ///
+ /// If the hToken parameter is not NULL, this parameter must be NULL.
+ ///
+ ///
+ /// A pointer to the name of the computer used to determine the site location. The format of the name is "\computer_name". If this
+ /// parameter is NULL, the local computer name is used.
+ ///
+ ///
+ ///
+ /// A value that specifies additional flags that are used to control information retrieval. If you specify
+ /// GPO_LIST_FLAG_MACHINE, the function retrieves policy information for the computer. If you do not specify
+ /// GPO_LIST_FLAG_MACHINE, the function retrieves policy information for the user.
+ ///
+ /// If you specify GPO_LIST_FLAG_SITEONLY the function returns only site information for the computer or user.
+ ///
+ /// A pointer that receives the list of GPO structures. For more information, see GROUP_POLICY_OBJECT.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// The GetGPOList function is intended for use by services acting on behalf of a user or computer. The service calls this
+ /// function to obtain a list of GPOs, then checks each GPO for service-specific policy.
+ ///
+ ///
+ /// Calling this function with a token provides the most accurate list. The system can perform access checking for the user or
+ /// computer. Calling this function with the user or computer name and the domain controller name is faster than calling it with a
+ /// token. However, if the token is not specified, the system uses the security access of the caller, which means that the list may
+ /// not be completely correct for the intended user or computer.
+ ///
+ ///
+ /// To obtain the most accurate list of GPOs for a computer when calling GetGPOList, the caller must have read access to each
+ /// OU and site in the computer domain, and also read and apply Group Policy access to all GPOs that are linked to the sites, domain
+ /// or OUs of that domain. An example of a caller would be a service running on the computer whose name is specified in the lpName
+ /// parameter. An alternate method of obtaining a list of GPOs would be to call the RsopCreateSession method of the
+ /// RsopPlanningModeProvider WMI class. The method can generate resultant policy data for a computer or user account in a
+ /// hypothetical scenario.
+ ///
+ /// Call the FreeGPOList function to free the GPO list when you have finished processing it.
+ ///
+ /// Generally, you should call GetGPOList with a token when retrieving a list of GPOs for a user as shown in the following
+ /// code example.
+ ///
+ ///
+ /// Typically, to retrieve a list of GPOs for a computer, you can call GetGPOList with the computer name and domain
+ /// controller name as demonstrated in the following code snippet.
+ ///
+ /// To retrieve the list of GPOs applied for a specific user or computer and extension, call the GetAppliedGPOList function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getgpolista USERENVAPI BOOL GetGPOListA( HANDLE hToken,
+ // LPCSTR lpName, LPCSTR lpHostName, LPCSTR lpComputerName, DWORD dwFlags, PGROUP_POLICY_OBJECTA *pGPOList );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "26c54ac5-23d7-40ed-94a9-70d25e14431f")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetGPOList([Optional] HTOKEN hToken, [Optional, MarshalAs(UnmanagedType.LPTStr)] string lpName, [Optional, MarshalAs(UnmanagedType.LPTStr)] string lpHostName,
+ [Optional, MarshalAs(UnmanagedType.LPTStr)] string lpComputerName, [Optional] GPO_LIST_FLAG dwFlags, out IntPtr pGPOList);
+
+ ///
+ /// The GetGPOList function retrieves the list of GPOs for the specified user or computer. This function can be called in two
+ /// ways: first, you can use the token for the user or computer, or, second, you can use the name of the user or computer and the
+ /// name of the domain controller.
+ ///
+ ///
+ ///
+ /// A token for the user or computer, returned from the LogonUser, CreateRestrictedToken, DuplicateToken, OpenProcessToken, or
+ /// OpenThreadToken function. This token must have TOKEN_IMPERSONATE and TOKEN_QUERY access. For more information, see
+ /// Access Rights for Access-Token Objects and the following Remarks section.
+ ///
+ /// If this parameter is NULL, you must supply values for the lpName and lpHostName parameters.
+ ///
+ ///
+ ///
+ /// A pointer to the user or computer name, in the fully qualified distinguished name format (for example, "CN=user, OU=users,
+ /// DC=contoso, DC=com").
+ ///
+ /// If the hToken parameter is not NULL, this parameter must be NULL.
+ ///
+ ///
+ ///
+ /// A DNS domain name or domain controller name. Domain controller name can be retrieved using the DsGetDcName function, specifying
+ /// DS_DIRECTORY_SERVICE_REQUIRED in the flags parameter.
+ ///
+ /// If the hToken parameter is not NULL, this parameter must be NULL.
+ ///
+ ///
+ /// A pointer to the name of the computer used to determine the site location. The format of the name is "\computer_name". If this
+ /// parameter is NULL, the local computer name is used.
+ ///
+ ///
+ ///
+ /// A value that specifies additional flags that are used to control information retrieval. If you specify
+ /// GPO_LIST_FLAG_MACHINE, the function retrieves policy information for the computer. If you do not specify
+ /// GPO_LIST_FLAG_MACHINE, the function retrieves policy information for the user.
+ ///
+ /// If you specify GPO_LIST_FLAG_SITEONLY the function returns only site information for the computer or user.
+ ///
+ /// A pointer that receives the list of GPO structures. For more information, see GROUP_POLICY_OBJECT.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// The GetGPOList function is intended for use by services acting on behalf of a user or computer. The service calls this
+ /// function to obtain a list of GPOs, then checks each GPO for service-specific policy.
+ ///
+ ///
+ /// Calling this function with a token provides the most accurate list. The system can perform access checking for the user or
+ /// computer. Calling this function with the user or computer name and the domain controller name is faster than calling it with a
+ /// token. However, if the token is not specified, the system uses the security access of the caller, which means that the list may
+ /// not be completely correct for the intended user or computer.
+ ///
+ ///
+ /// To obtain the most accurate list of GPOs for a computer when calling GetGPOList, the caller must have read access to each
+ /// OU and site in the computer domain, and also read and apply Group Policy access to all GPOs that are linked to the sites, domain
+ /// or OUs of that domain. An example of a caller would be a service running on the computer whose name is specified in the lpName
+ /// parameter. An alternate method of obtaining a list of GPOs would be to call the RsopCreateSession method of the
+ /// RsopPlanningModeProvider WMI class. The method can generate resultant policy data for a computer or user account in a
+ /// hypothetical scenario.
+ ///
+ ///
+ /// Generally, you should call GetGPOList with a token when retrieving a list of GPOs for a user as shown in the following
+ /// code example.
+ ///
+ ///
+ /// Typically, to retrieve a list of GPOs for a computer, you can call GetGPOList with the computer name and domain
+ /// controller name as demonstrated in the following code snippet.
+ ///
+ /// To retrieve the list of GPOs applied for a specific user or computer and extension, call the GetAppliedGPOList function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getgpolista USERENVAPI BOOL GetGPOListA( HANDLE hToken,
+ // LPCSTR lpName, LPCSTR lpHostName, LPCSTR lpComputerName, DWORD dwFlags, PGROUP_POLICY_OBJECTA *pGPOList );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "26c54ac5-23d7-40ed-94a9-70d25e14431f")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetGPOList([Optional] HTOKEN hToken, [Optional, MarshalAs(UnmanagedType.LPTStr)] string lpName, [Optional, MarshalAs(UnmanagedType.LPTStr)] string lpHostName,
+ [Optional, MarshalAs(UnmanagedType.LPTStr)] string lpComputerName, [Optional] GPO_LIST_FLAG dwFlags, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(GPOMarshaler))] out GROUP_POLICY_OBJECT[] pGPOList);
+
+ /// Retrieves the path to the root directory where user profiles are stored.
+ ///
+ /// Type: LPTSTR
+ ///
+ /// A pointer to a buffer that, when this function returns successfully, receives the path to the profiles directory. Set this value
+ /// to NULL to determine the required size of the buffer.
+ ///
+ ///
+ ///
+ /// Type: LPDWORD
+ /// Specifies the size of the lpProfilesDir buffer, in TCHARs.
+ ///
+ /// If the buffer specified by lpProfilesDir is not large enough or lpProfilesDir is NULL, the function fails and this
+ /// parameter receives the necessary buffer size, including the terminating null character.
+ ///
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// The following is an example of the path returned by GetProfilesDirectory in Windows XP:
+ /// The following is an example of the path returned by GetProfilesDirectory in Windows 7:
+ ///
+ /// To obtain the paths of subdirectories of this directory, use the SHGetFolderPath (Windows XP and earlier) or
+ /// SHGetKnownFolderPath (Windows Vista) function.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getprofilesdirectorya USERENVAPI BOOL
+ // GetProfilesDirectoryA( LPSTR lpProfileDir, LPDWORD lpcchSize );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "e21411fa-f7e1-4944-93ce-7d9314d79fbf")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetProfilesDirectory(StringBuilder lpProfileDir, ref uint lpcchSize);
+
+ /// Retrieves the type of profile loaded for the current user.
+ ///
+ /// Type: DWORD*
+ /// Pointer to a variable that receives the profile type. If the function succeeds, it sets one or more of the following values:
+ /// PT_MANDATORY
+ /// The user has a Mandatory User Profiles.
+ /// PT_ROAMING
+ /// The user has a Roaming User Profiles.
+ /// PT_ROAMING_PREEXISTING
+ ///
+ /// The user has a Roaming User Profile that was created on another PC and is being downloaded. This profile type implies PT_ROAMING.
+ ///
+ /// PT_TEMPORARY
+ /// The user has a Temporary User Profiles; it will be deleted at logoff.
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// If the user profile is not already loaded, the function fails.
+ ///
+ /// Note that the caller must have KEY_READ access to HKEY_LOCAL_MACHINE. This access right is granted by default. For
+ /// more information, see Registry Key Security and Access Rights.
+ ///
+ ///
+ /// If the profile type is PT_ROAMING_PREEXISTING, Explorer will not reinitialize default programs associations when a
+ /// profile is loaded on a machine for the first time.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getprofiletype USERENVAPI BOOL GetProfileType( DWORD
+ // *dwFlags );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "55ee76c8-1735-43eb-a98e-9e6c87ee1ba7")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetProfileType(out ProfileType dwFlags);
+
+ /// Retrieves the path to the root directory of the specified user's profile.
+ ///
+ /// Type: HANDLE
+ ///
+ /// A token for the user, which is returned by the LogonUser, CreateRestrictedToken, DuplicateToken, OpenProcessToken, or
+ /// OpenThreadToken function. The token must have TOKEN_QUERY access. For more information, see Access Rights for Access-Token Objects.
+ ///
+ ///
+ ///
+ /// Type: LPTSTR
+ ///
+ /// A pointer to a buffer that, when this function returns successfully, receives the path to the specified user's profile directory.
+ ///
+ ///
+ ///
+ /// Type: LPDWORD
+ /// Specifies the size of the lpProfileDir buffer, in TCHARs.
+ ///
+ /// If the buffer specified by lpProfileDir is not large enough or lpProfileDir is NULL, the function fails and this
+ /// parameter receives the necessary buffer size, including the terminating null character.
+ ///
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// The following is an example of the path returned by GetUserProfileDirectory in Windows XP:
+ /// The following is an example of the path returned by GetUserProfileDirectory in Windows 7:
+ ///
+ /// To obtain the paths of subdirectories of this directory, use the SHGetFolderPath (Windows XP and earlier) or
+ /// SHGetKnownFolderPath (Windows Vista) function.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectorya USERENVAPI BOOL
+ // GetUserProfileDirectoryA( HANDLE hToken, LPSTR lpProfileDir, LPDWORD lpcchSize );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "b5de762d-c9ee-42b0-bce0-e74bcc9c78f0")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool GetUserProfileDirectory(HTOKEN hToken, StringBuilder lpProfileDir, ref uint lpcchSize);
+
+ ///
+ /// The LeaveCriticalPolicySection function resumes the background application of policy. This function closes the handle to
+ /// the policy section.
+ ///
+ /// Handle to a policy section, which is returned by the EnterCriticalPolicySection function.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-leavecriticalpolicysection USERENVAPI BOOL
+ // LeaveCriticalPolicySection( HANDLE hSection );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "9e6a938f-c9cb-4baf-b7d0-4316e45f874c")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool LeaveCriticalPolicySection(IntPtr hSection);
+
+ /// Loads the specified user's profile. The profile can be a local user profile or a roaming user profile.
+ ///
+ /// Type: HANDLE
+ ///
+ /// Token for the user, which is returned by the LogonUser, CreateRestrictedToken, DuplicateToken, OpenProcessToken, or
+ /// OpenThreadToken function. The token must have TOKEN_QUERY, TOKEN_IMPERSONATE, and TOKEN_DUPLICATE access.
+ /// For more information, see Access Rights for Access-Token Objects.
+ ///
+ ///
+ ///
+ /// Type: LPPROFILEINFO
+ ///
+ /// Pointer to a PROFILEINFO structure. LoadUserProfile fails and returns ERROR_INVALID_PARAMETER if the dwSize
+ /// member of the structure is not set to or if the lpUserName member is NULL. For more information, see Remarks.
+ ///
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ /// The function fails and returns ERROR_INVALID_PARAMETER if the dwSize member of the structure at lpProfileInfo is not set
+ /// to or if the lpUserName member is NULL.
+ ///
+ ///
+ ///
+ ///
+ /// When a user logs on interactively, the system automatically loads the user's profile. If a service or an application
+ /// impersonates a user, the system does not load the user's profile. Therefore, the service or application should load the user's
+ /// profile with LoadUserProfile.
+ ///
+ ///
+ /// Services and applications that call LoadUserProfile should check to see if the user has a roaming profile. If the user
+ /// has a roaming profile, specify its path as the lpProfilePath member of PROFILEINFO. To retrieve the user's roaming
+ /// profile path, you can call the NetUserGetInfo function, specifying information level 3 or 4.
+ ///
+ ///
+ /// Upon successful return, the hProfile member of PROFILEINFO is a registry key handle opened to the root of the user's
+ /// hive. It has been opened with full access (KEY_ALL_ACCESS). If a service that is impersonating a user needs to read or write to
+ /// the user's registry file, use this handle instead of HKEY_CURRENT_USER. Do not close the hProfile handle. Instead,
+ /// pass it to the UnloadUserProfile function. This function closes the handle. You should ensure that all handles to keys in the
+ /// user's registry hive are closed. If you do not close all open registry handles, the user's profile fails to unload. For more
+ /// information, see Registry Key Security and Access Rights and Registry Hives.
+ ///
+ ///
+ /// Note that it is your responsibility to load the user's registry hive into the HKEY_USERS registry key with the
+ /// LoadUserProfile function before you call CreateProcessAsUser. This is because CreateProcessAsUser does not load
+ /// the specified user's profile into HKEY_USERS. This means that access to information in the HKEY_CURRENT_USER
+ /// registry key may not produce results consistent with a normal interactive logon.
+ ///
+ ///
+ /// The calling process must have the SE_RESTORE_NAME and SE_BACKUP_NAME privileges. For more information, see Running
+ /// with Special Privileges.
+ ///
+ ///
+ /// Starting with Windows XP Service Pack 2 (SP2) and Windows Server 2003, the caller must be an administrator or the LocalSystem
+ /// account. It is not sufficient for the caller to merely impersonate the administrator or LocalSystem account.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-loaduserprofilea USERENVAPI BOOL LoadUserProfileA( HANDLE
+ // hToken, LPPROFILEINFOA lpProfileInfo );
+ [DllImport(Lib.Userenv, SetLastError = true, CharSet = CharSet.Auto)]
+ [PInvokeData("userenv.h", MSDNShortId = "9ec1f8f2-8f20-4d38-9d41-70315b890336")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool LoadUserProfile(HTOKEN hToken, ref PROFILEINFO lpProfileInfo);
+
+ /* =====================================
+ * Unimplemented at this time due to lack of documentation on ASYNCCOMPLETIONHANDLE
+ *
+ *
+ ///
+ /// The ProcessGroupPolicyCompleted function notifies the system that the specified extension has finished applying policy.
+ ///
+ /// Specifies the unique GUID that identifies the extension.
+ /// Asynchronous completion handle. This handle is passed to the ProcessGroupPolicy function.
+ /// Specifies the completion status of asynchronous processing.
+ ///
+ /// If the function succeeds, the return value is ERROR_SUCCESS. Otherwise, the function returns one of the system error
+ /// codes. For a complete list of error codes, see System Error Codes or the header file WinError.h.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-processgrouppolicycompleted USERENVAPI DWORD
+ // ProcessGroupPolicyCompleted( REFGPEXTENSIONID extensionId, ASYNCCOMPLETIONHANDLE pAsyncHandle, DWORD dwStatus );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "f88c8072-af4c-44e0-a816-ecb841dd1a78")]
+ public static extern Win32Error ProcessGroupPolicyCompleted(in Guid extensionId, ASYNCCOMPLETIONHANDLE pAsyncHandle, uint dwStatus);
+
+ ///
+ /// The ProcessGroupPolicyCompletedEx function notifies the system that the specified policy extension has finished applying
+ /// policy. The function also reports the status of Resultant Set of Policy (RSoP) logging.
+ ///
+ /// Specifies the unique GUID that identifies the policy extension.
+ /// Asynchronous completion handle. This handle is passed to the ProcessGroupPolicyEx callback function.
+ /// Specifies the completion status of asynchronous processing of policy.
+ /// Specifies an HRESULT return code that indicates the status of RSoP logging.
+ ///
+ /// If the function succeeds, the return value is ERROR_SUCCESS. Otherwise, the function returns one of the system error
+ /// codes. For a complete list of error codes, see System Error Codes or the header file WinError.h.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-processgrouppolicycompletedex USERENVAPI DWORD
+ // ProcessGroupPolicyCompletedEx( REFGPEXTENSIONID extensionId, ASYNCCOMPLETIONHANDLE pAsyncHandle, DWORD dwStatus, HRESULT
+ // RsopStatus );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "0d899190-7345-4762-ab59-b89e2e87d10f")]
+ public static extern Win32Error ProcessGroupPolicyCompletedEx(in Guid extensionId, ASYNCCOMPLETIONHANDLE pAsyncHandle, uint dwStatus, HRESULT RsopStatus);
+ *
+ *
+ */
+
+ ///
+ /// The RefreshPolicy function causes policy to be applied immediately on the client computer. To apply policy and specify
+ /// the type of refresh that should occur, you can call the extended function RefreshPolicyEx.
+ ///
+ ///
+ /// Specifies whether to refresh the computer policy or user policy. If this value is TRUE, the system refreshes the computer
+ /// policy. If this value is FALSE, the system refreshes the user policy.
+ ///
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ /// By default, policy is reapplied every 90 minutes.
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-refreshpolicy USERENVAPI BOOL RefreshPolicy( BOOL bMachine );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "e08cb006-d174-4506-87f0-580660bd4023")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool RefreshPolicy([MarshalAs(UnmanagedType.Bool)] bool bMachine);
+
+ ///
+ /// The RefreshPolicyEx function causes policy to be applied immediately on the computer. The extended function allows you to
+ /// specify the type of policy refresh to apply.
+ ///
+ ///
+ /// Specifies whether to refresh the computer policy or user policy. If this value is TRUE, the system refreshes the computer
+ /// policy. If this value is FALSE, the system refreshes the user policy.
+ ///
+ ///
+ /// Specifies the type of policy refresh to apply. This parameter can be the following value.
+ /// RP_FORCE
+ /// Reapply all policies even if no policy change was detected.
+ ///
+ /// Note that if there are any client-side extensions that can be applied at boot or logon time, (for example, an application
+ /// installation extension), the extensions are re-applied at the next boot or logon, even if no policy change is detected.
+ ///
+ ///
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ /// If you do not need to specify the dwOptions parameter, you can call the RefreshPolicy function instead.
+ /// By default, policy is reapplied every 90 minutes.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-refreshpolicyex USERENVAPI BOOL RefreshPolicyEx( BOOL
+ // bMachine, DWORD dwOptions );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "905ab96b-a7f2-4bb4-a539-385f78284644")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool RefreshPolicyEx([MarshalAs(UnmanagedType.Bool)] bool bMachine, RefreshPolicyOption dwOptions = 0);
+
+ ///
+ /// The RegisterGPNotification function enables an application to receive notification when there is a change in policy. When
+ /// a policy change occurs, the specified event object is set to the signaled state.
+ ///
+ /// Handle to an event object. Use the function to create the event object.
+ ///
+ /// Specifies the policy change type. If TRUE, computer policy changes are reported. If FALSE, user policy changes are reported.
+ ///
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// Call the UnregisterGPNotification function to unregister the handle from receiving policy change notifications. Call the
+ /// CloseHandle function to close the handle when it is no longer required.
+ ///
+ ///
+ /// An application can also receive notifications about policy changes when a WM_SETTINGCHANGE message is broadcast. In this
+ /// instance, the wParam parameter value is 1 if computer policy was applied; it is zero if user policy was applied. The lParam
+ /// parameter points to the string "Policy".
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-registergpnotification USERENVAPI BOOL
+ // RegisterGPNotification( HANDLE hEvent, BOOL bMachine );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "0a758da3-73a8-4d9b-8663-e6cab1a1bd3f")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool RegisterGPNotification(SafeEventHandle hEvent, [MarshalAs(UnmanagedType.Bool)] bool bMachine);
+
+ /* =====================================
+ * Unimplemented at this time due to lack of documentation on RSOPTOKEN
+ *
+ *
+ ///
+ /// The RSoPAccessCheckByType function determines whether a security descriptor grants a specified set of access rights to
+ /// the client identified by an RSOPTOKEN.
+ ///
+ /// Pointer to a SECURITY_DESCRIPTOR against which access on the object is checked.
+ ///
+ ///
+ /// Pointer to a SID. If the security descriptor is associated with an object that represents a principal (for example, a user
+ /// object), this parameter should be the SID of the object. When evaluating access, this SID logically replaces the SID in any ACE
+ /// containing the well-known PRINCIPAL_SELF SID ("S-1-5-10"). For more information, see Security Identifiers and Well-Known SIDs.
+ ///
+ /// This parameter should be NULL if the protected object does not represent a principal.
+ ///
+ /// Pointer to a valid RSOPTOKEN representing the client attempting to gain access to the object.
+ ///
+ /// Specifies an access mask that indicates the access rights to check. This mask can contain a combination of generic, standard and
+ /// specific access rights. For more information, see Access Rights and Access Masks.
+ ///
+ ///
+ ///
+ /// Pointer to an array of OBJECT_TYPE_LIST structures that identify the hierarchy of object types for which to check access. Each
+ /// element in the array specifies a GUID that identifies the object type and a value indicating the level of the object type
+ /// in the hierarchy of object types. The array should not have two elements with the same GUID.
+ ///
+ ///
+ /// The array must have at least one element. The first element in the array must be at level zero and identify the object itself.
+ /// The array can have only one level zero element. The second element is a subobject, such as a property set, at level 1. Following
+ /// each level 1 entry are subordinate entries for the level 2 through 4 subobjects. Thus, the levels for the elements in the array
+ /// might be {0, 1, 2, 2, 1, 2, 3}. If the object type list is out of order, RSoPAccessCheckByType fails and GetLastError
+ /// returns ERROR_INVALID_PARAMETER.
+ ///
+ ///
+ /// Specifies the number of elements in the pObjectTypeList array.
+ ///
+ /// Pointer to the GENERIC_MAPPING structure associated with the object for which access is being checked.
+ ///
+ /// This parameter is currently unused.
+ /// This parameter is currently unused.
+ ///
+ /// Pointer to an access mask that receives the granted access rights.
+ ///
+ /// If the function succeeds, the pbAccessStatus parameter is set to TRUE, and the mask is updated to contain the standard
+ /// and specific rights granted. If pbAccessStatus is set to FALSE, this parameter is set to zero. If the function fails, the
+ /// mask is not modified.
+ ///
+ ///
+ ///
+ /// Pointer to a variable that receives the results of the access check.
+ ///
+ /// If the function succeeds, and the requested set of access rights are granted, this parameter is set to TRUE. Otherwise,
+ /// this parameter is set to FALSE. If the function fails, the status is not modified.
+ ///
+ ///
+ ///
+ /// If the function succeeds, the return value is S_OK. Otherwise, the function returns one of the COM error codes defined in
+ /// the Platform SDK header file WinError.h.
+ ///
+ ///
+ /// The RSoPAccessCheckByType function compares the specified security descriptor with the specified RSOPTOKEN and
+ /// indicates, in the pbAccessStatus parameter, whether access is granted or denied.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-rsopaccesscheckbytype USERENVAPI HRESULT
+ // RsopAccessCheckByType( PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pPrincipalSelfSid, PRSOPTOKEN pRsopToken, DWORD
+ // dwDesiredAccessMask, POBJECT_TYPE_LIST pObjectTypeList, DWORD ObjectTypeListLength, PGENERIC_MAPPING pGenericMapping,
+ // PPRIVILEGE_SET pPrivilegeSet, LPDWORD pdwPrivilegeSetLength, LPDWORD pdwGrantedAccessMask, LPBOOL pbAccessStatus );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "d63734a0-1a88-4669-828e-de467606fc14")]
+ public static extern HRESULT RsopAccessCheckByType(PSECURITY_DESCRIPTOR pSecurityDescriptor, PSID pPrincipalSelfSid, PRSOPTOKEN pRsopToken,
+ ACCESS_MASK dwDesiredAccessMask, [In] OBJECT_TYPE_LIST[] pObjectTypeList, uint ObjectTypeListLength, in GENERIC_MAPPING pGenericMapping,
+ [Optional] IntPtr pPrivilegeSet, [Optional] IntPtr pdwPrivilegeSetLength, out ACCESS_MASK pdwGrantedAccessMask, [MarshalAs(UnmanagedType.Bool)] out bool pbAccessStatus);
+
+ ///
+ /// The RSoPFileAccessCheck function determines whether a file's security descriptor grants a specified set of file access
+ /// rights to the client identified by an RSOPTOKEN.
+ ///
+ /// Pointer to the name of the relevant file. The file must already exist.
+ /// Pointer to a valid RSOPTOKEN representing the client attempting to gain access to the file.
+ ///
+ /// Specifies an access mask that indicates the access rights to check. This mask can contain a combination of generic, standard,
+ /// and specific access rights. For more information, see Access Rights and Access Masks.
+ ///
+ ///
+ /// Pointer to an access mask that receives the granted access rights.
+ ///
+ /// If the function succeeds, the pbAccessStatus parameter is set to TRUE, and the mask is updated to contain the standard
+ /// and specific rights granted. If pbAccessStatus is set to FALSE, this parameter is set to zero. If the function fails, the
+ /// mask is not modified.
+ ///
+ ///
+ ///
+ /// Pointer to a variable that receives the results of the access check.
+ ///
+ /// If the function succeeds, and the requested set of access rights are granted, this parameter is set to TRUE. Otherwise,
+ /// this parameter is set to FALSE. If the function fails, the status is not modified.
+ ///
+ ///
+ ///
+ /// If the function succeeds, the return value is S_OK. Otherwise, the function returns one of the COM error codes defined in
+ /// the Platform SDK header file WinError.h.
+ ///
+ ///
+ /// The RSoPFileAccessCheck function indicates, in the pbAccessStatus parameter, whether access is granted or denied to the
+ /// client identified by the RSOPTOKEN. If access is granted, the requested access mask becomes the object's granted access mask.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-rsopfileaccesscheck USERENVAPI HRESULT RsopFileAccessCheck(
+ // LPWSTR pszFileName, PRSOPTOKEN pRsopToken, DWORD dwDesiredAccessMask, LPDWORD pdwGrantedAccessMask, LPBOOL pbAccessStatus );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "dfdf14ee-fee1-4e96-9955-7f24dfe39487")]
+ public static extern HRESULT RsopFileAccessCheck([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, PRSOPTOKEN pRsopToken, ACCESS_MASK dwDesiredAccessMask,
+ out ACCESS_MASK pdwGrantedAccessMask, [MarshalAs(UnmanagedType.Bool)] ref bool pbAccessStatus);
+
+ ///
+ /// The RSoPResetPolicySettingStatus function unlinks the RSOP_PolicySettingStatus instance from its RSOP_PolicySetting
+ /// instance. The function deletes the instances of RSOP_PolicySettingStatus and RSOP_PolicySettingLink. Optionally, you can
+ /// also specify that the function delete the instance of RSOP_PolicySetting.
+ ///
+ /// This parameter is currently unused.
+ ///
+ /// Specifies a WMI services pointer to the RSoP namespace to which the policy data is to be written. This parameter is required.
+ ///
+ ///
+ /// Pointer to an instance of RSOP_PolicySetting containing the policy setting. This parameter is required and can also point to the
+ /// instance's children.
+ ///
+ ///
+ /// If the function succeeds, the return value is S_OK. Otherwise, the function returns one of the COM error codes defined in
+ /// the Platform SDK header file WinError.h.
+ ///
+ ///
+ /// To link (associate) the RSOP_PolicySettingStatus instance to its RSOP_PolicySetting instance, you can call the
+ /// RSoPSetPolicySettingStatus function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-rsopresetpolicysettingstatus USERENVAPI HRESULT
+ // RsopResetPolicySettingStatus( DWORD dwFlags, IWbemServices *pServices, IWbemClassObject *pSettingInstance );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "fd849efe-1ee7-4034-aea2-1a2bdb5e46bc")]
+ public static extern HRESULT RsopResetPolicySettingStatus([Optional] uint dwFlags, IWbemServices pServices, IWbemClassObject pSettingInstance);
+
+ ///
+ /// The RSoPSetPolicySettingStatus function creates an instance of RSOP_PolicySettingStatus and an instance of
+ /// RSOP_PolicySettingLink. The function links (associates) RSOP_PolicySettingStatus to its RSOP_PolicySetting instance.
+ ///
+ /// This parameter is currently unused.
+ ///
+ /// Specifies a WMI services pointer to the RSoP namespace to which the policy data is to be written. This parameter is required.
+ ///
+ ///
+ /// Pointer to an instance of RSOP_PolicySetting containing the policy setting. This parameter is required and can point to the
+ /// instance's children.
+ ///
+ /// Specifies the number of elements in the pStatus array.
+ /// Pointer to an array of POLICYSETTINGSTATUSINFO structures.
+ ///
+ /// If the function succeeds, the return value is S_OK. Otherwise, the function returns one of the COM error codes defined in
+ /// the Platform SDK header file WinError.h.
+ ///
+ ///
+ /// To unlink an RSOP_PolicySettingStatus instance from its RSOP_PolicySetting instance, you can call the
+ /// RSoPResetPolicySettingStatus function.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-rsopsetpolicysettingstatus USERENVAPI HRESULT
+ // RsopSetPolicySettingStatus( DWORD dwFlags, IWbemServices *pServices, IWbemClassObject *pSettingInstance, DWORD nInfo,
+ // POLICYSETTINGSTATUSINFO *pStatus );
+ [DllImport(Lib.Userenv, SetLastError = false, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "7ea2f217-4dd2-4c0f-af1b-d4bcb8707519")]
+ public static extern HRESULT RsopSetPolicySettingStatus([Optional] uint dwFlags, IWbemServices pServices, IWbemClassObject pSettingInstance,
+ uint nInfo, [In, MarshalAs(UnmanagedType.LPArray)] POLICYSETTINGSTATUSINFO[] pStatus);
+ *
+ *
+ */
+
+ ///
+ /// Unloads a user's profile that was loaded by the LoadUserProfile function. The caller must have administrative privileges on the
+ /// computer. For more information, see the Remarks section of the LoadUserProfile function.
+ ///
+ ///
+ /// Type: HANDLE
+ ///
+ /// Token for the user, returned from the LogonUser, CreateRestrictedToken, DuplicateToken, OpenProcessToken, or OpenThreadToken
+ /// function. The token must have TOKEN_IMPERSONATE and TOKEN_DUPLICATE access. For more information, see Access
+ /// Rights for Access-Token Objects.
+ ///
+ ///
+ ///
+ /// Type: HANDLE
+ ///
+ /// Handle to the registry key. This value is the hProfile member of the PROFILEINFO structure. For more information see the
+ /// Remarks section of LoadUserProfile and Registry Key Security and Access Rights.
+ ///
+ ///
+ ///
+ /// Type: BOOL
+ /// TRUE if successful; otherwise, FALSE. To get extended error information, call GetLastError.
+ ///
+ ///
+ ///
+ /// Before calling UnloadUserProfile you should ensure that all handles to keys that you have opened in the user's registry
+ /// hive are closed. If you do not close all open registry handles, the user's profile fails to unload. For more information, see
+ /// Registry Key Security and Access Rights and Registry Hives.
+ ///
+ /// For more information about calling functions that require administrator privileges, see Running with Special Privileges.
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-unloaduserprofile USERENVAPI BOOL UnloadUserProfile( HANDLE
+ // hToken, HANDLE hProfile );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "7ecb8a3f-c041-4133-b23a-101de8884882")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool UnloadUserProfile(HTOKEN hToken, HKEY hProfile);
+
+ ///
+ /// The UnregisterGPNotification function unregisters the specified policy-notification handle from receiving policy change notifications.
+ ///
+ /// Policy-notification handle passed to the RegisterGPNotification function.
+ ///
+ /// If the function succeeds, the return value is nonzero.
+ /// If the function fails, the return value is zero. To get extended error information, call GetLastError.
+ ///
+ /// The caller must call the CloseHandle function to close the handle when it is no longer needed.
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-unregistergpnotification USERENVAPI BOOL
+ // UnregisterGPNotification( HANDLE hEvent );
+ [DllImport(Lib.Userenv, SetLastError = true, ExactSpelling = true)]
+ [PInvokeData("userenv.h", MSDNShortId = "39ac1361-0160-44e3-8b99-ff50978cc425")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool UnregisterGPNotification(SafeEventHandle hEvent);
+
+ /// The GROUP_POLICY_OBJECT structure provides information about a GPO in a GPO list.
+ ///
+ ///
+ /// Each GPO could contain data that must be processed by multiple snap-in extensions. Therefore, the data in the
+ /// lpExtensions member is organized as a series of GUID s that identify the extensions and snap-in extensions. The
+ /// data format is as follows:
+ ///
+ ///
+ /// First, there is an opening bracket, "[", followed by the GUID of the extension. Next, you'll find one or more GUID
+ /// s identifying the snap-in extensions that have stored data in the GPO. After the last snap-in GUID for an extension,
+ /// there is a closing bracket, "]". This pattern is repeated for the next extension.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/userenv/ns-userenv-group_policy_objecta typedef struct _GROUP_POLICY_OBJECTA {
+ // DWORD dwOptions; DWORD dwVersion; LPSTR lpDSPath; LPSTR lpFileSysPath; LPSTR lpDisplayName; CHAR szGPOName[50]; GPO_LINK GPOLink;
+ // LPARAM lParam; struct _GROUP_POLICY_OBJECTA *pNext; struct _GROUP_POLICY_OBJECTA *pPrev; LPSTR lpExtensions; LPARAM lParam2;
+ // LPSTR lpLink; } GROUP_POLICY_OBJECTA, *PGROUP_POLICY_OBJECTA;
+ [PInvokeData("userenv.h", MSDNShortId = "7275a3cd-6b19-4eb9-9481-b73bd5af5753")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct GROUP_POLICY_OBJECT
+ {
+ ///
+ /// Specifies link options. This member can be one of the following values.
+ /// GPO_FLAG_DISABLE
+ /// This GPO is disabled.
+ /// GPO_FLAG_FORCE
+ /// Do not override the policy settings in this GPO with policy settings in a subsequent GPO.
+ ///
+ public uint dwOptions;
+
+ /// Specifies the version number of the GPO.
+ public uint dwVersion;
+
+ /// Pointer to a string that specifies the path to the directory service portion of the GPO.
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpDSPath;
+
+ /// Pointer to a string that specifies the path to the file system portion of the GPO.
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpFileSysPath;
+
+ /// Pointer to the display name of the GPO.
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpDisplayName;
+
+ /// Pointer to a string that specifies a unique name that identifies the GPO.
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
+ public string szGPOName;
+
+ ///
+ /// Specifies the link information for the GPO. This member may be one of the following values.
+ /// GPLinkUnknown
+ /// No link information is available.
+ /// GPLinkMachine
+ /// The GPO is linked to a computer (local or remote).
+ /// GPLinkSite
+ /// The GPO is linked to a site.
+ /// GPLinkDomain
+ /// The GPO is linked to a domain.
+ /// GPLinkOrganizationalUnit
+ /// The GPO is linked to an organizational unit.
+ ///
+ public GPO_LINK GPOLink;
+
+ /// User-supplied data.
+ public IntPtr lParam;
+
+ /// Pointer to the next GPO in the list.
+ public IntPtr pNext;
+
+ /// Pointer to the previous GPO in the list.
+ public IntPtr pPrev;
+
+ ///
+ /// Extensions that have stored data in this GPO. The format is a string of GUID s grouped in brackets. For more
+ /// information, see the following Remarks section.
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpExtensions;
+
+ /// User-supplied data.
+ public IntPtr lParam2;
+
+ ///
+ /// Path to the Active Directory site, domain, or organization unit to which this GPO is linked. If the GPO is linked to the
+ /// local GPO, this member is "Local".
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpLink;
+ }
+
+ /// Contains information used when loading or unloading a user profile.
+ ///
+ ///
+ /// Do not use environment variables when specifying a path. The LoadUserProfile function does not expand environment variables,
+ /// such as %username%, in a path.
+ ///
+ ///
+ /// When the LoadUserProfile call returns successfully, the hProfile member receives a registry key handle opened to the root
+ /// of the user's subtree, opened with full access (KEY_ALL_ACCESS). For more information see the Remarks sections in
+ /// LoadUserProfile, Registry Key Security and Access Rights, and Registry Hives.
+ ///
+ ///
+ /// Services and applications that call LoadUserProfile should check to see if the user has a roaming profile. If the user has a
+ /// roaming profile, specify its path as the lpProfilePath member of this structure.
+ ///
+ ///
+ // https://docs.microsoft.com/en-us/windows/win32/api/profinfo/ns-profinfo-profileinfoa typedef struct _PROFILEINFOA { DWORD dwSize;
+ // DWORD dwFlags; MIDL_STRING LPSTR lpUserName; MIDL_STRING LPSTR lpProfilePath; MIDL_STRING LPSTR lpDefaultPath; MIDL_STRING LPSTR
+ // lpServerName; MIDL_STRING LPSTR lpPolicyPath; #if ... ULONG_PTR hProfile; #else HANDLE hProfile; #endif } PROFILEINFOA, *LPPROFILEINFOA;
+ [PInvokeData("profinfo.h", MSDNShortId = "09dae38c-3b2b-4f12-9c1e-90737cf0c7cc")]
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct PROFILEINFO
+ {
+ ///
+ /// Type: DWORD
+ /// The size of this structure, in bytes.
+ ///
+ public uint dwSize;
+
+ ///
+ /// Type: DWORD
+ /// This member can be one of the following flags:
+ /// PI_NOUI
+ /// Prevents the display of profile error messages.
+ /// PI_APPLYPOLICY
+ /// Not supported.
+ ///
+ public ProfileInfoFlags dwFlags;
+
+ ///
+ /// Type: LPTSTR
+ /// A pointer to the name of the user. This member is used as the base name of the directory in which to store a new profile.
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpUserName;
+
+ ///
+ /// Type: LPTSTR
+ ///
+ /// A pointer to the roaming user profile path. If the user does not have a roaming profile, this member can be NULL. To
+ /// retrieve the user's roaming profile path, call the NetUserGetInfo function, specifying information level 3 or 4. For more
+ /// information, see Remarks.
+ ///
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpProfilePath;
+
+ ///
+ /// Type: LPTSTR
+ /// A pointer to the default user profile path. This member can be NULL.
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpDefaultPath;
+
+ ///
+ /// Type: LPTSTR
+ /// A pointer to the name of the validating domain controller, in NetBIOS format.
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpServerName;
+
+ ///
+ /// Type: LPTSTR
+ /// Not used, set to NULL.
+ ///
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public string lpPolicyPath;
+
+ ///
+ /// Type: HANDLE
+ /// A handle to the HKEY_CURRENT_USER registry subtree. For more information, see Remarks.
+ ///
+ public HKEY hProfile;
+
+ /// Initializes a new instance of the struct.
+ /// Name of the user.
+ /// If set to , prevents the display of profile error messages..
+ public PROFILEINFO(string userName, bool allowUI = true)
+ {
+ dwSize = Default.dwSize;
+ dwFlags = allowUI ? 0 : ProfileInfoFlags.PI_NOUI;
+ lpUserName = userName;
+ lpProfilePath = lpDefaultPath = lpServerName = lpPolicyPath = null;
+ hProfile = HKEY.NULL;
+ }
+
+ /// Gets a default instance of this structure with the size field set appropriately.
+ public static readonly PROFILEINFO Default = new PROFILEINFO { dwSize = (uint)Marshal.SizeOf(typeof(PROFILEINFO)) };
+ }
+
+ /// Provides a for that is disposed using .
+ public class SafeCriticalPolicySectionHandle : SafeHANDLE
+ {
+ ///
+ /// Initializes a new instance of the class and assigns an existing handle.
+ ///
+ /// An object that represents the pre-existing handle to use.
+ ///
+ /// to reliably release the handle during the finalization phase; otherwise, (not recommended).
+ ///
+ public SafeCriticalPolicySectionHandle(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
+
+ /// Initializes a new instance of the class.
+ private SafeCriticalPolicySectionHandle() : base() { }
+
+ ///
+ protected override bool InternalReleaseHandle() => LeaveCriticalPolicySection(handle);
+ }
+
+ private class EnvBlockMarshaler : ICustomMarshaler
+ {
+ private EnvBlockMarshaler(string _)
+ {
+ }
+
+ /// Gets the instance.
+ /// The cookie.
+ /// A new instance of this class.
+ public static ICustomMarshaler GetInstance(string cookie) => new EnvBlockMarshaler(cookie);
+
+ ///
+ void ICustomMarshaler.CleanUpManagedData(object ManagedObj) { }
+
+ ///
+ void ICustomMarshaler.CleanUpNativeData(IntPtr pNativeData) { }
+
+ ///
+ int ICustomMarshaler.GetNativeDataSize() => -1;
+
+ ///
+ IntPtr ICustomMarshaler.MarshalManagedToNative(object ManagedObj) => throw new NotImplementedException();
+
+ ///
+ object ICustomMarshaler.MarshalNativeToManaged(IntPtr pNativeData)
+ {
+ try
+ {
+ return pNativeData.ToStringEnum(CharSet.Unicode).ToArray();
+ }
+ finally
+ {
+ DestroyEnvironmentBlock(pNativeData);
+ }
+ }
+ }
+
+ private class GPOMarshaler : ICustomMarshaler
+ {
+ private GPOMarshaler(string _)
+ {
+ }
+
+ /// Gets the instance.
+ /// The cookie.
+ /// A new instance of this class.
+ public static ICustomMarshaler GetInstance(string cookie) => new GPOMarshaler(cookie);
+
+ ///
+ void ICustomMarshaler.CleanUpManagedData(object ManagedObj) { }
+
+ ///
+ void ICustomMarshaler.CleanUpNativeData(IntPtr pNativeData) { }
+
+ ///
+ int ICustomMarshaler.GetNativeDataSize() => -1;
+
+ ///
+ IntPtr ICustomMarshaler.MarshalManagedToNative(object ManagedObj) => throw new NotImplementedException();
+
+ ///
+ object ICustomMarshaler.MarshalNativeToManaged(IntPtr pNativeData)
+ {
+ try
+ {
+ var ret = pNativeData.LinkedListToIEnum(gpo => gpo.pNext).ToArray();
+ for (var i = 0; i < ret.Length; i++)
+ ret[i].pNext = ret[i].pPrev = IntPtr.Zero;
+ return ret;
+ }
+ finally
+ {
+ FreeGPOList(pNativeData);
}
}
}
}
-}
\ No newline at end of file
+}
+
+
+
\ No newline at end of file
diff --git a/PInvoke/UserEnv/Vanara.PInvoke.UserEnv.csproj b/PInvoke/UserEnv/Vanara.PInvoke.UserEnv.csproj
index 458051ef2..0d29f84bc 100644
--- a/PInvoke/UserEnv/Vanara.PInvoke.UserEnv.csproj
+++ b/PInvoke/UserEnv/Vanara.PInvoke.UserEnv.csproj
@@ -28,7 +28,10 @@
Currently implements:
Functions
-AreThereVisibleLogoffScripts, AreThereVisibleShutdownScripts, CreateAppContainerProfile, CreateEnvironmentBlock, CreateProfile, DeleteAppContainerProfile, DeleteProfile, DeriveAppContainerSidFromAppContainerName, DeriveRestrictedAppContainerSidFromAppContainerSidAndRestrictedName, DestroyEnvironmentBlock, EnterCriticalPolicySection, ExpandEnvironmentStringsForUser, ForceSyncFgPolicy, FreeGPOList, GenerateGPNotification, GetAllUsersProfileDirectory, GetAppContainerFolderPath, GetAppContainerRegistryLocation, GetAppliedGPOList, GetDefaultUserProfileDirectory, GetGPOList, GetNextFgPolicyRefreshInfo, GetPreviousFgPolicyRefreshInfo, GetProfilesDirectory, GetProfileType, GetUserProfileDirectory, HasPolicyForegroundProcessingCompleted, LeaveCriticalPolicySection, LoadProfileExtender, LoadUserProfile, ProcessGroupPolicyCompleted, ProcessGroupPolicyCompletedEx, RefreshPolicy, RefreshPolicyEx, RegisterGPNotification, RsopAccessCheckByType, RsopFileAccessCheck, RsopLoggingEnabled, RsopResetPolicySettingStatus, RsopSetPolicySettingStatus, UnloadProfileExtender, UnloadUserProfile, UnregisterGPNotification, WaitForMachinePolicyForegroundProcessing, WaitForUserPolicyForegroundProcessing
+CreateAppContainerProfile, CreateEnvironmentBlock, CreateProfile, DeleteAppContainerProfile, DeleteProfileA, DeleteProfileW, DeriveAppContainerSidFromAppContainerName, DestroyEnvironmentBlock, EnterCriticalPolicySection, ExpandEnvironmentStringsForUserA, ExpandEnvironmentStringsForUserW, FreeGPOListA, FreeGPOListW, GetAllUsersProfileDirectoryA, GetAllUsersProfileDirectoryW, GetAppContainerFolderPath, GetAppContainerRegistryLocation, GetAppliedGPOListA, GetAppliedGPOListW, GetGPOListA, GetGPOListW, LeaveCriticalPolicySection
+
+Structures
+GROUP_POLICY_OBJECT
true
@@ -50,6 +53,7 @@ AreThereVisibleLogoffScripts, AreThereVisibleShutdownScripts, CreateAppContainer
+
diff --git a/UnitTests/PInvoke/UserEnv/CreateEnvironmentBlockTest_And_DestroyEnvironmentBlockTest.cs b/UnitTests/PInvoke/UserEnv/CreateEnvironmentBlockTest_And_DestroyEnvironmentBlockTest.cs
deleted file mode 100644
index c3f12bf5b..000000000
--- a/UnitTests/PInvoke/UserEnv/CreateEnvironmentBlockTest_And_DestroyEnvironmentBlockTest.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using NUnit.Framework;
-using System;
-using static Vanara.PInvoke.AdvApi32;
-using static Vanara.PInvoke.Kernel32;
-using static Vanara.PInvoke.UserEnv;
-
-namespace Vanara.PInvoke.Tests
-{
- public partial class UserEnvTests
- {
- [Test]
- public void CreateEnvironmentBlockTest_And_DestroyEnvironmentBlockTest()
- {
- SafeHTOKEN hToken;
-
- using (hToken = SafeHTOKEN.FromProcess(GetCurrentProcess(), TokenAccess.TOKEN_IMPERSONATE | TokenAccess.TOKEN_DUPLICATE | TokenAccess.TOKEN_READ).Duplicate(SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation))
- {
- Assert.IsFalse(hToken.IsClosed);
-
- Assert.That(CreateEnvironmentBlock(out var environmentBlock, hToken, false), ResultIs.Successful);
-
-
- // Test all environment variables.
-
- var allEnvironmentVariables = Environment.GetEnvironmentVariables();
-
- foreach (var envVar in environmentBlock)
- {
- var envVarName = envVar.Split('=')[0];
-
- if (allEnvironmentVariables.Contains(envVarName))
- {
- var envVarValue = Environment.GetEnvironmentVariable(envVarName);
-
- Assert.AreEqual(allEnvironmentVariables[envVarName], envVarValue);
-
- TestContext.WriteLine(envVar);
- }
-
- else
- {
- TestContext.WriteLine();
- TestContext.WriteLine($"*** UNAVAILABLE: {envVar}");
- TestContext.WriteLine();
- }
- }
- }
-
-
- Assert.IsTrue(hToken.IsClosed);
- }
- }
-}
diff --git a/UnitTests/PInvoke/UserEnv/UserEnv.csproj b/UnitTests/PInvoke/UserEnv/UserEnv.csproj
index 893a30e07..bfce3dab9 100644
--- a/UnitTests/PInvoke/UserEnv/UserEnv.csproj
+++ b/UnitTests/PInvoke/UserEnv/UserEnv.csproj
@@ -44,7 +44,6 @@
-
diff --git a/UnitTests/PInvoke/UserEnv/UserEnvTests.cs b/UnitTests/PInvoke/UserEnv/UserEnvTests.cs
index 5e7cdf162..7550a8f10 100644
--- a/UnitTests/PInvoke/UserEnv/UserEnvTests.cs
+++ b/UnitTests/PInvoke/UserEnv/UserEnvTests.cs
@@ -1,9 +1,201 @@
using NUnit.Framework;
+using System;
+using System.Text;
+using static Vanara.PInvoke.AdvApi32;
+using static Vanara.PInvoke.Kernel32;
+using static Vanara.PInvoke.UserEnv;
namespace Vanara.PInvoke.Tests
{
[TestFixture()]
public partial class UserEnvTests
{
+ private const string localAcct = "test";
+ private const string localAcctPwd = "Passw0rd!";
+
+ [Test]
+ public void CreateAppContainerProfileTest()
+ {
+ const string cname = "MySillyImpossibleAppName098";
+
+ try
+ {
+ Assert.That(CreateAppContainerProfile(cname, "My silly display name", "Silly", null, 0, out var sid), ResultIs.Successful);
+ Assert.That(DeriveAppContainerSidFromAppContainerName(cname, out var sid2), ResultIs.Successful);
+ Assert.That(EqualSid(sid, sid2));
+ var ssid = ((PSID)sid2).ToString("D");
+ sid.Dispose();
+ sid2.Dispose();
+
+ Assert.That(GetAppContainerFolderPath(ssid, out var path), ResultIs.Successful);
+ Assert.That(path.ToString().Length, Is.GreaterThan(0));
+ TestContext.WriteLine(path.ToString());
+ path.Dispose();
+
+ }
+ finally
+ {
+ Assert.That(DeleteAppContainerProfile(cname), ResultIs.Successful);
+ }
+ }
+
+ [Test]
+ public void CreateEnvironmentBlockTest_And_DestroyEnvironmentBlockTest()
+ {
+ using var hToken = SafeHTOKEN.FromProcess(GetCurrentProcess(), TokenAccess.TOKEN_IMPERSONATE | TokenAccess.TOKEN_DUPLICATE | TokenAccess.TOKEN_READ);
+ Assert.That(hToken.IsInvalid, Is.False);
+
+ Assert.That(CreateEnvironmentBlock(out string[] environmentBlock, hToken, false), ResultIs.Successful);
+ Assert.That(environmentBlock, Is.Not.Empty);
+
+ // Validate same environment variables count as .NET method
+ // Assert.That(Environment.GetEnvironmentVariables().Count, Is.EqualTo(environmentBlock.Length));
+ TestContext.Write(string.Join("\r\n", environmentBlock));
+ }
+
+ [Test]
+ public void CreateProfileTest()
+ {
+ var curSid = SafePSID.Current;
+ var sb = new StringBuilder(260);
+ Assert.That(CreateProfile(curSid.ToString("D"), curSid.ToString("N"), sb, (uint)sb.Length), ResultIs.Failure);
+
+ Assert.That(LogonUser(localAcct, ".", localAcctPwd, LogonUserType.LOGON32_LOGON_INTERACTIVE, LogonUserProvider.LOGON32_PROVIDER_DEFAULT, out var hTok), ResultIs.Successful);
+ using var id = new System.Security.Principal.WindowsIdentity(hTok.DangerousGetHandle());
+ try
+ {
+ Assert.That(CreateProfile(id.User.Value, localAcct, sb, (uint)sb.Capacity), ResultIs.Successful);
+
+ var pi = new PROFILEINFO(localAcct);
+ Assert.That(LoadUserProfile(hTok, ref pi), ResultIs.Successful);
+ Assert.That(UnloadUserProfile(hTok, pi.hProfile), ResultIs.Successful);
+ }
+ finally
+ {
+ Assert.That(DeleteProfile(id.User.Value), ResultIs.Successful);
+ hTok.Dispose();
+ }
+ }
+
+ [Test]
+ public void EnterCriticalPolicySectionTest()
+ {
+ SafeCriticalPolicySectionHandle h;
+ Assert.That(h = EnterCriticalPolicySection(false), ResultIs.ValidHandle);
+ Assert.That(() => h.Dispose(), Throws.Nothing);
+ }
+
+ [Test]
+ public void ExpandEnvironmentStringsForUserTest()
+ {
+ Assert.That(LogonUser(localAcct, ".", localAcctPwd, LogonUserType.LOGON32_LOGON_INTERACTIVE, LogonUserProvider.LOGON32_PROVIDER_DEFAULT, out var hTok), ResultIs.Successful);
+ try
+ {
+ var sb = new StringBuilder(260);
+ Assert.That(ExpandEnvironmentStringsForUser(hTok, "TEMP", sb, (uint)sb.Capacity), ResultIs.Successful);
+ Assert.That(sb.Length, Is.GreaterThan(0));
+ }
+ finally
+ {
+ hTok.Dispose();
+ }
+ }
+
+ [Test]
+ public void GetAllUsersProfileDirectoryTest()
+ {
+ var sb = new StringBuilder(260);
+ var sbl = (uint)sb.Capacity;
+ Assert.That(GetAllUsersProfileDirectory(sb, ref sbl), ResultIs.Successful);
+ Assert.That(sb.Length, Is.GreaterThan(0));
+ }
+
+ [Test]
+ public void GetAppContainerRegistryLocationTest()
+ {
+ Assert.That(GetAppContainerRegistryLocation(REGSAM.KEY_ALL_ACCESS, out var hKey), ResultIs.Successful);
+ Assert.That(hKey, ResultIs.ValidHandle);
+ }
+ [Test]
+ public void GetAppliedGPOListTest1()
+ {
+ var guid = new Guid("{35378EAC-683F-11D2-A89A-00C04FBBCFA2}");
+ Assert.That(GetAppliedGPOList(0, default, default, guid, out GROUP_POLICY_OBJECT[] gpos), ResultIs.Successful);
+ Assert.That(gpos, Is.Not.Empty);
+ }
+
+ [Test]
+ public void GetAppliedGPOListTest2()
+ {
+ var guid = new Guid("{35378EAC-683F-11D2-A89A-00C04FBBCFA2}");
+ Assert.That(GetAppliedGPOList(0, default, default, guid, out IntPtr ptr), ResultIs.Successful);
+ Assert.That(ptr, Is.Not.EqualTo(IntPtr.Zero));
+ Assert.That(FreeGPOList(ptr), ResultIs.Successful);
+ }
+
+ [Test]
+ public void GetDefaultUserProfileDirectoryTest()
+ {
+ var sb = new StringBuilder(260);
+ var sbl = (uint)sb.Capacity;
+ Assert.That(GetDefaultUserProfileDirectory(sb, ref sbl), ResultIs.Successful);
+ Assert.That(sb.Length, Is.GreaterThan(0));
+ }
+
+ [Test]
+ public void GetGPOListTest()
+ {
+ using var hToken = SafeHTOKEN.FromProcess(GetCurrentProcess(), TokenAccess.TOKEN_IMPERSONATE | TokenAccess.TOKEN_DUPLICATE | TokenAccess.TOKEN_READ).Duplicate(SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation);
+ Assert.That(GetGPOList(hToken, null, null, null, 0, out GROUP_POLICY_OBJECT[] gpos), ResultIs.Successful);
+ Assert.That(gpos, Is.Not.Empty);
+ gpos.WriteValues();
+ }
+
+ [Test]
+ public void GetProfilesDirectoryTest()
+ {
+ var sb = new StringBuilder(260);
+ var sbl = (uint)sb.Capacity;
+ Assert.That(GetProfilesDirectory(sb, ref sbl), ResultIs.Successful);
+ Assert.That(sb.Length, Is.GreaterThan(0));
+ }
+
+ [Test]
+ public void GetProfileTypeTest()
+ {
+ Assert.That(GetProfileType(out var type), ResultIs.Successful);
+ Assert.That((int)type, Is.GreaterThanOrEqualTo(0));
+ }
+
+ [Test]
+ public void GetUserProfileDirectoryTest()
+ {
+ using var hToken = SafeHTOKEN.FromProcess(GetCurrentProcess(), TokenAccess.TOKEN_QUERY);
+ var sb = new StringBuilder(260);
+ var sbl = (uint)sb.Capacity;
+ Assert.That(GetUserProfileDirectory(hToken, sb, ref sbl), ResultIs.Successful);
+ Assert.That(sb.Length, Is.GreaterThan(0));
+ }
+
+ [Test]
+ public void RefreshPolicyExTest()
+ {
+ Assert.That(RefreshPolicyEx(false, RefreshPolicyOption.RP_FORCE), ResultIs.Successful);
+ }
+
+ [Test]
+ public void RefreshPolicyTest()
+ {
+ Assert.That(RefreshPolicy(false), ResultIs.Successful);
+ }
+
+ [Test]
+ public void RegisterGPNotificationTest()
+ {
+ using var hEvt = CreateEvent(null, false, false);
+ Assert.That(hEvt, ResultIs.ValidHandle);
+ Assert.That(RegisterGPNotification(hEvt, false), ResultIs.Successful);
+ Assert.That(UnregisterGPNotification(hEvt), ResultIs.Successful);
+ }
}
-}
+}
\ No newline at end of file