Completed work on AdvApi32

pull/60/head
David Hall 2019-06-04 12:16:41 -06:00
parent c8cb9a29d7
commit 5ee2b906b7
9 changed files with 10023 additions and 117 deletions

View File

@ -0,0 +1,556 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Vanara.Extensions;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
public static partial class AdvApi32
{
/// <summary>
/// The <c>INSTALLSPECTYPE</c> enumeration values define the ways a group policy application can be specified to the
/// InstallApplication function. The values are used in the <c>Type</c> member of INSTALLDATA.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/ne-appmgmt-installspectype typedef enum _INSTALLSPECTYPE { APPNAME,
// FILEEXT, PROGID, COMCLASS } INSTALLSPECTYPE;
[PInvokeData("appmgmt.h", MSDNShortId = "9e62a22d-cae7-4b3e-9000-71eddb1f3cad")]
public enum INSTALLSPECTYPE
{
/// <summary>This constant equals 1. The application is specified by its display name and group policy GUID.</summary>
APPNAME = 1,
/// <summary>The application is specified by its file name extension, for example, .jpg.</summary>
FILEEXT,
/// <summary/>
PROGID,
/// <summary/>
COMCLASS,
}
/// <summary>
/// The <c>GetLocalManagedApplications</c> function can be run on the target computer to get a list of managed applications on that
/// computer. The function can also be called in the context of a user to get a list of managed applications for that user. This
/// function only returns applications that can be installed by the Windows Installer.
/// </summary>
/// <param name="bUserApps">
/// A value that, if <c>TRUE</c>, the prgLocalApps parameter contains a list of managed applications that applies to the user. If the
/// value of this parameter is <c>FALSE</c>, the prgLocalApps parameter contains a list of managed applications that applies to the
/// local computer.
/// </param>
/// <param name="pdwApps">The address of a <c>DWORD</c> that specifies the number of applications in the list returned by prgLocalApps.</param>
/// <param name="prgLocalApps">
/// The address of an array that contains the list of managed applications. You must call <c>LocalFree</c> to free this array when
/// its contents are no longer required. This parameter cannot be null. The list is returned as a LOCALMANAGEDAPPLICATION structure.
/// </param>
/// <returns>
/// If the function succeeds, the return value is <c>ERROR_SUCCESS</c>. 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.
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/nf-appmgmt-getlocalmanagedapplications DWORD
// GetLocalManagedApplications( BOOL bUserApps, LPDWORD pdwApps, PLOCALMANAGEDAPPLICATION *prgLocalApps );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("appmgmt.h", MSDNShortId = "4606ff09-7e23-4953-aeef-cac822995d35")]
public static extern Win32Error GetLocalManagedApplications([MarshalAs(UnmanagedType.Bool)] bool bUserApps, out uint pdwApps, out SafeLocalHandle prgLocalApps);
/// <summary>
/// The <c>GetLocalManagedApplications</c> function can be run on the target computer to get a list of managed applications on that
/// computer. The function can also be called in the context of a user to get a list of managed applications for that user. This
/// function only returns applications that can be installed by the Windows Installer.
/// </summary>
/// <param name="bUserApps">
/// A value that, if <c>TRUE</c>, the prgLocalApps parameter contains a list of managed applications that applies to the user. If the
/// value of this parameter is <c>FALSE</c>, the prgLocalApps parameter contains a list of managed applications that applies to the
/// local computer.
/// </param>
/// <returns>The list of managed applications.</returns>
[PInvokeData("appmgmt.h", MSDNShortId = "4606ff09-7e23-4953-aeef-cac822995d35")]
public static IEnumerable<LOCALMANAGEDAPPLICATION> GetLocalManagedApplications(bool bUserApps)
{
GetLocalManagedApplications(bUserApps, out var c, out var p).ThrowIfFailed();
return p.ToArray<LOCALMANAGEDAPPLICATION>((int)c);
}
/// <summary>
/// The <c>GetManagedApplicationCategories</c> function gets a list of application categories for a domain. The list is the same for
/// all users in the domain.
/// </summary>
/// <param name="dwReserved">This parameter is reserved. Its value must be 0.</param>
/// <param name="pAppCategory">
/// A APPCATEGORYINFOLIST structure that contains a list of application categories. This structure must be freed by calling LocalFree
/// when the list is no longer required.
/// </param>
/// <returns>
/// If the function succeeds, the return value is <c>ERROR_SUCCESS</c>. 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.
/// </returns>
/// <remarks>
/// The structure returned by <c>GetManagedApplicationCategories</c> must be freed by calling LocalFree when the list is no longer required.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/nf-appmgmt-getmanagedapplicationcategories DWORD
// GetManagedApplicationCategories( DWORD dwReserved, APPCATEGORYINFOLIST *pAppCategory );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("appmgmt.h", MSDNShortId = "10824852-7810-483a-91b3-2d9cc3d21934")]
public static extern Win32Error GetManagedApplicationCategories([Optional] uint dwReserved, IntPtr pAppCategory);
/// <summary>
/// The <c>GetManagedApplicationCategories</c> function gets a list of application categories for a domain. The list is the same for
/// all users in the domain.
/// </summary>
/// <returns>A list of application categories.</returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/nf-appmgmt-getmanagedapplicationcategories DWORD
// GetManagedApplicationCategories( DWORD dwReserved, APPCATEGORYINFOLIST *pAppCategory );
[PInvokeData("appmgmt.h", MSDNShortId = "10824852-7810-483a-91b3-2d9cc3d21934")]
public static IEnumerable<APPCATEGORYINFO> GetManagedApplicationCategories()
{
var h = IntPtr.Zero;
try
{
GetManagedApplicationCategories(0, h).ThrowIfFailed();
var l = h.ToStructure<APPCATEGORYINFOLIST>();
return l.pCategoryInfo.ToArray<APPCATEGORYINFO>((int)l.cCategory) ?? new APPCATEGORYINFO[0];
}
finally
{
Kernel32.LocalFree(h);
}
}
/// <summary>
/// The <c>GetManagedApplications</c> function gets a list of applications that are displayed in the <c>Add</c> pane of <c>Add/Remove
/// Programs</c> (ARP) for a specified user context.
/// </summary>
/// <param name="pCategory">
/// <para>A pointer to a GUID that specifies the category</para>
/// <para>
/// of applications to be listed. If pCategory is not null, dwQueryFlags must contain <c>MANAGED_APPS_FROMCATEGORY</c>. If pCategory
/// is null, dwQueryFlags cannot contain <c>MANAGED_APPS_FROMCATEGORY</c>.
/// </para>
/// </param>
/// <param name="dwQueryFlags">
/// <para>This parameter can contain one or more of the following values.</para>
/// <para>MANAGED_APPS_USERAPPLICATIONS</para>
/// <para>Lists all applications that apply to the user. The parameter pCategory must be null.</para>
/// <para>MANAGED_APPS_FROMCATEGORY</para>
/// <para>Lists only applications in the category specified by pCategory. The pCategory parameter cannot be null.</para>
/// </param>
/// <param name="dwInfoLevel">This parameter must be <c>MANAGED_APPS_INFOLEVEL_DEFAULT</c>.</param>
/// <param name="pdwApps">The count of applications in the list returned by this function.</param>
/// <param name="prgManagedApps">
/// This parameter is a pointer to an array of MANAGEDAPPLICATION structures. This array contains the list of applications listed in
/// the <c>Add</c> pane of <c>Add/Remove Programs</c> (ARP). You must call <c>LocalFree</c> to free the array when they array is no
/// longer required.
/// </param>
/// <returns>
/// If the function succeeds, the return value is <c>ERROR_SUCCESS</c>. 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.
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/nf-appmgmt-getmanagedapplications DWORD GetManagedApplications( GUID
// *pCategory, DWORD dwQueryFlags, DWORD dwInfoLevel, LPDWORD pdwApps, PMANAGEDAPPLICATION *prgManagedApps );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("appmgmt.h", MSDNShortId = "62e32f36-cbb2-4557-9773-8bd454870d55")]
public static extern Win32Error GetManagedApplications(IntPtr pCategory, uint dwQueryFlags, uint dwInfoLevel, out uint pdwApps, out SafeLocalHandle prgManagedApps);
/// <summary>
/// The <c>GetManagedApplications</c> function gets a list of applications that are displayed in the <c>Add</c> pane of <c>Add/Remove
/// Programs</c> (ARP) for a specified user context.
/// </summary>
/// <param name="pCategory">
/// <para>A pointer to a GUID that specifies the category</para>
/// <para>
/// of applications to be listed. If pCategory is not null, dwQueryFlags must contain <c>MANAGED_APPS_FROMCATEGORY</c>. If pCategory
/// is null, dwQueryFlags cannot contain <c>MANAGED_APPS_FROMCATEGORY</c>.
/// </para>
/// </param>
/// <param name="dwQueryFlags">
/// <para>This parameter can contain one or more of the following values.</para>
/// <para>MANAGED_APPS_USERAPPLICATIONS</para>
/// <para>Lists all applications that apply to the user. The parameter pCategory must be null.</para>
/// <para>MANAGED_APPS_FROMCATEGORY</para>
/// <para>Lists only applications in the category specified by pCategory. The pCategory parameter cannot be null.</para>
/// </param>
/// <param name="dwInfoLevel">This parameter must be <c>MANAGED_APPS_INFOLEVEL_DEFAULT</c>.</param>
/// <param name="pdwApps">The count of applications in the list returned by this function.</param>
/// <param name="prgManagedApps">
/// This parameter is a pointer to an array of MANAGEDAPPLICATION structures. This array contains the list of applications listed in
/// the <c>Add</c> pane of <c>Add/Remove Programs</c> (ARP). You must call <c>LocalFree</c> to free the array when they array is no
/// longer required.
/// </param>
/// <returns>
/// If the function succeeds, the return value is <c>ERROR_SUCCESS</c>. 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.
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/nf-appmgmt-getmanagedapplications DWORD GetManagedApplications( GUID
// *pCategory, DWORD dwQueryFlags, DWORD dwInfoLevel, LPDWORD pdwApps, PMANAGEDAPPLICATION *prgManagedApps );
[PInvokeData("appmgmt.h", MSDNShortId = "62e32f36-cbb2-4557-9773-8bd454870d55")]
public static IEnumerable<MANAGEDAPPLICATION> GetManagedApplications(Guid? pCategory)
{
var pGuid = pCategory.HasValue ? SafeLocalHandle.CreateFromStructure(pCategory.Value) : SafeLocalHandle.Null;
GetManagedApplications((IntPtr)pGuid, pCategory.HasValue ? 2U : 1U, 0x10000, out var c, out var h).ThrowIfFailed();
return h.ToArray<MANAGEDAPPLICATION>((int)c);
}
/// <summary>
/// The <c>InstallApplication</c> function can install applications that have been deployed to target users that belong to a domain.
/// The security context of the user that is calling <c>InstallApplication</c> must be that of a domain user logged onto a computer
/// in a domain that trusts the target user's domain. Group Policy must be successfully applied when the target user logs on.
/// </summary>
/// <param name="pInstallInfo">A pointer to a INSTALLDATA structure that specifies the application to install.</param>
/// <returns>
/// If the function succeeds, the return value is <c>ERROR_SUCCESS</c>. 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.
/// </returns>
/// <remarks>
/// <para>
/// The <c>InstallApplication</c> function can only install applications that have been deployed by using Group Policy. A domain
/// administrator can deploy applications to target users by using the user configuration section of Group Policy Objects (GPO). The
/// target user must belong to the target domain and the GPO must apply to this user in the target domain. The
/// <c>InstallApplication</c> function installs applications according to standard Group Policy inheritance rules. If the same
/// application is deployed in multiple GPOs, the function installs the version of the application deployed in the highest precedence
/// GPO. After an application has been installed for a user, it is not visible to other users on the computer. This is standard for
/// applications that are deployed through user group policy.
/// </para>
/// <para>
/// The <c>InstallApplication</c> function can install deployed applications that use Windows Installer (.msi files) or software
/// installation settings (.zap files) to handle setup and installation.
/// </para>
/// <para>
/// The <c>InstallApplication</c> function can install applications that use a Windows Installer package for their installation. In
/// this case, the user calling <c>InstallApplication</c> is not required to have administrator privileges. The system can install
/// the application because the Windows Installer is a trusted application deployed by a domain administrator. The user that receives
/// the application must have access to the location of the .msi files.
/// </para>
/// <para>
/// Remove applications installed using .msi files by calling the Windows Installer function MsiConfigureProduct to uninstall the
/// application. Then call UninstallApplication to inform the system that the application is no longer managed on the client by Group
/// Policy. <c>UninstallApplication</c> should be called even if the uninstall fails because this enables the system to keep the
/// Resultant Set of Policy (RSoP) accurate.
/// </para>
/// <para>
/// The <c>InstallApplication</c> function can also install applications that use setup applications based on software installation
/// settings (.zap files). The user that receives the application must have access to the location of the .zap files. A .zap file is
/// a text file similar to an .ini file, which enables Windows to publish an application (for example, Setup.exe) for installation
/// with <c>Add or Remove Programs</c>. To publish applications that do not use the Windows Installer, you must create a .zap file,
/// copy the .zap file to the software distribution point servers, and then use Group Policybased software deployment to publish the
/// application for users. If the application is deployed using .zap files, the user installing the application must have privileges
/// on the machine to install the software. You cannot use .zap files for assigned applications.
/// </para>
/// <para>
/// Remove applications using software installation settings (.zap files) by calling the uninstall function or a command specific for
/// the installation application.
/// </para>
/// <para>
/// For information about using installation applications other than the Windows Installer see article 231747, "How to Publish
/// non-MSI Programs with .zap Files," in the Microsoft Knowledge Base.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/nf-appmgmt-installapplication DWORD InstallApplication( PINSTALLDATA
// pInstallInfo );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("appmgmt.h", MSDNShortId = "5b2e1d82-a421-42af-9e1b-391ae9d4813e")]
public static extern Win32Error InstallApplication(in INSTALLDATA pInstallInfo);
/// <summary>
/// <para>
/// The <c>UninstallApplication</c> function uninstalls a group policy application that handles setup and installation using Windows
/// Installer .msi files. The <c>UninstallApplication</c> function should only be called in the context of the user for whom the user
/// group policy application has previously attempted an uninstall by calling the MsiConfigureProduct function. The
/// InstallApplication function can install group policy applications.
/// </para>
/// <para>
/// <c>Note</c> Failure to call <c>UninstallApplication</c> as part of the protocol for uninstalling a group policy-based application
/// can cause the Resultant Set of Policy (RSoP) to indicate inaccurate information.
/// </para>
/// </summary>
/// <param name="ProductCode">
/// The Windows Installer product code of the product being uninstalled. The product code of the application should be provided in
/// the form of a Windows Installer GUID as a string with braces.
/// </param>
/// <param name="dwStatus">
/// The status of the uninstall attempt. The dwStatus parameter is the Windows success code of the uninstall attempt returned by
/// MsiConfigureProduct. The system can use this to ensure that the Resultant Set of Policy (RSoP) indicates whether the uninstall
/// failed or succeeded.
/// </param>
/// <returns>
/// If the function succeeds, the return value is <c>ERROR_SUCCESS</c>. 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.
/// </returns>
/// <remarks>
/// <para>
/// Remove a group policy application that uses .msi files by calling the Windows Installer function MsiConfigureProduct to uninstall
/// the application. Then call <c>UninstallApplication</c> to inform the system that the application is no longer managed on the
/// client by Group Policy. <c>UninstallApplication</c> should be called even if the uninstall fails because this enables the system
/// to keep the Resultant Set of Policy (RSoP) accurate.
/// </para>
/// <para>
/// Remove applications installed using software installation settings (.zap files) by calling the uninstall function or command
/// specific for the installation application. For information about using installation applications other than the Windows Installer
/// see article 231747, "How to Publish non-MSI Programs with .zap Files," in the Microsoft Knowledge Base.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/nf-appmgmt-uninstallapplication DWORD UninstallApplication( LPWSTR
// ProductCode, DWORD dwStatus );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("appmgmt.h", MSDNShortId = "d45494e2-d86e-4d94-a158-4024eacf46a2")]
public static extern Win32Error UninstallApplication([MarshalAs(UnmanagedType.LPWStr)] string ProductCode, Win32Error dwStatus);
/// <summary>
/// Provides application category information to Add/Remove Programs in Control Panel. The APPCATEGORYINFOLIST structure is used
/// create a complete list of categories for an application publisher.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/ns-appmgmt-appcategoryinfo typedef struct _APPCATEGORYINFO { LCID
// Locale; LPWSTR pszDescription; GUID AppCategoryId; } APPCATEGORYINFO;
[PInvokeData("appmgmt.h", MSDNShortId = "7a0e61cb-97f8-4ca2-a85a-889e671099d0")]
[StructLayout(LayoutKind.Sequential)]
public struct APPCATEGORYINFO
{
/// <summary>
/// <para>Type: <c>LCID</c></para>
/// <para>Unused.</para>
/// </summary>
public LCID Locale;
/// <summary>
/// <para>Type: <c>LPWSTR</c></para>
/// <para>
/// A pointer to a string containing the display name of the category. This string displays in the <c>Category</c> list in
/// Add/Remove Programs. This string buffer must be allocated using CoTaskMemAlloc and freed using CoTaskMemFree.
/// </para>
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string pszDescription;
/// <summary>
/// <para>Type: <c>GUID</c></para>
/// <para>A GUID identifying the application category.</para>
/// </summary>
public Guid AppCategoryId;
}
/// <summary>
/// Provides a list of supported application categories from an application publisher to Add/Remove Programs in Control Panel.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/ns-appmgmt-appcategoryinfolist typedef struct _APPCATEGORYINFOLIST {
// DWORD cCategory; APPCATEGORYINFO *pCategoryInfo; } APPCATEGORYINFOLIST;
[PInvokeData("appmgmt.h", MSDNShortId = "c590d9ab-ab41-4192-a6c2-c6c2c931e873")]
[StructLayout(LayoutKind.Sequential)]
public struct APPCATEGORYINFOLIST
{
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>A value of type <c>DWORD</c> that specifies the count of APPCATEGORYINFO elements in the array pointed to by <c>pCategoryInfo</c>.</para>
/// </summary>
public uint cCategory;
/// <summary>
/// <para>Type: <c>APPCATEGORYINFO*</c></para>
/// <para>
/// A pointer to an array of APPCATEGORYINFO structures. This array contains all the categories an application publisher supports
/// and must be allocated using CoTaskMemAlloc and freed using CoTaskMemFree.
/// </para>
/// </summary>
public IntPtr pCategoryInfo;
}
/// <summary>The <c>INSTALLDATA</c> structure specifies a group-policy application to be installed by InstallApplication.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/ns-appmgmt-_installdata typedef struct _INSTALLDATA { INSTALLSPECTYPE
// Type; INSTALLSPEC Spec; } INSTALLDATA, *PINSTALLDATA;
[PInvokeData("appmgmt.h", MSDNShortId = "0c0570c6-f8f5-41e1-a1d2-d4e8c450f73c")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct INSTALLDATA
{
/// <summary>
/// Defines how <c>Spec</c> specifies the application to InstallApplication. <c>Type</c> can be one of the INSTALLSPECTYPE
/// enumeration values. Set <c>Type</c> to APPNAME to install an application specified by its user-friendly name and GPO GUID.
/// Set <c>Type</c> to FILEEXT to install an application specified by its file name extension.
/// </summary>
public INSTALLSPECTYPE Type;
/// <summary>An INSTALLSPEC structure that specifies the application.</summary>
public INSTALLSPEC Spec;
}
/// <summary>
/// The <c>INSTALLSPEC</c> structure specifies a group policy application by its user-friendly name and group policy GUID or by its
/// file name extension. The <c>Spec</c> member of the INSTALLDATA structure provides this information to the InstallApplication function.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/ns-appmgmt-_installspec typedef union _INSTALLSPEC { struct { WCHAR
// *Name; GUID GPOId; } AppName; WCHAR *FileExt; WCHAR *ProgId; struct { GUID Clsid; DWORD ClsCtx; } COMClass; } INSTALLSPEC;
[PInvokeData("appmgmt.h", MSDNShortId = "e9c1b943-9cb0-480f-8ab7-0f439087216a")]
[StructLayout(LayoutKind.Explicit)]
public struct INSTALLSPEC
{
/// <summary>Structure that contains the following members.</summary>
[FieldOffset(0)]
public APPNAME AppName;
/// <summary>
/// <para>The file name extension, such as .jpg, of the application to be installed.</para>
/// <para>
/// <c>Note</c> InstallApplication fails if the <c>Type</c> member of INSTALLDATA equals <c>FILEEXT</c> and there is no
/// application deployed to the user with this file name extension.
/// </para>
/// </summary>
[FieldOffset(0), MarshalAs(UnmanagedType.LPWStr)]
public string FileExt;
/// <summary/>
[FieldOffset(0), MarshalAs(UnmanagedType.LPWStr)]
public string ProgId;
/// <summary/>
[FieldOffset(0)]
public COMCLASS COMClass;
/// <summary>Structure that contains the following members.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct APPNAME
{
/// <summary>
/// The user-friendly name of the application as it appears in <c>Add or Remove Programs</c> and the Group Policy Object
/// Editor. You can obtain the name by calling GetManagedApplications.
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
/// <summary>
/// The <c>GUID</c> for the group policy object in which the application exists. You can obtain the group policy object
/// <c>GUID</c> by calling GetManagedApplications.
/// </summary>
public Guid GPOId;
}
/// <summary>Structure that contains the following members.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct COMCLASS
{
/// <summary/>
public Guid Clsid;
/// <summary/>
public uint ClsCtx;
}
}
/// <summary>
/// The <c>LOCALMANAGEDAPPLICATION</c> structure describes a managed application installed for a user or a computer. Returned by the
/// GetLocalManagedApplications function.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/ns-appmgmt-_localmanagedapplication typedef struct
// _LOCALMANAGEDAPPLICATION { LPWSTR pszDeploymentName; LPWSTR pszPolicyName; LPWSTR pszProductId; DWORD dwState; }
// LOCALMANAGEDAPPLICATION, *PLOCALMANAGEDAPPLICATION;
[PInvokeData("appmgmt.h", MSDNShortId = "b2b7d209-76ee-4ba4-ac61-034d2c8e0689")]
[StructLayout(LayoutKind.Sequential)]
public struct LOCALMANAGEDAPPLICATION
{
/// <summary>
/// This is a Unicode string that gives the user friendly name of the application as it appears in the Application Deployment
/// Editor (ADE).
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)] public string pszDeploymentName;
/// <summary>This is the user-friendly name of the group policy object (GPO) from which the application originates.</summary>
[MarshalAs(UnmanagedType.LPWStr)] public string pszPolicyName;
/// <summary>This is a Unicode string that gives the Windows Installer product code GUID for the application.</summary>
[MarshalAs(UnmanagedType.LPWStr)] public string pszProductId;
/// <summary>
/// <para>Indicates the state of the installed application. This parameter can contain one or more of the following values.</para>
/// <para>LOCAL_STATE_ASSIGNED</para>
/// <para>The application is installed in the assigned state.</para>
/// <para>LOCAL_STATE_PUBLISHED</para>
/// <para>The application is installed in the published state.</para>
/// <para>LOCAL_STATE_UNINSTALL_UNMANAGED</para>
/// <para>The installation of this application uninstalled an unmanaged application with a conflicting transform.</para>
/// <para>LOCAL_STATE_POLICYREMOVE_ORPHAN</para>
/// <para>If the policy from which this application originates is removed, the application is left on the computer.</para>
/// <para>LOCAL_STATE_POLICYREMOVE_UNINSTALL</para>
/// <para>If the policy from which this application originates is removed, the application is uninstalled from the computer.</para>
/// </summary>
public uint dwState;
}
/// <summary>
/// The <c>MANAGEDAPPLICATION</c> structure contains information about an application. The function GetManagedApplications returns an
/// array of <c>MANAGEDAPPLICATION</c> structures.
/// </summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/appmgmt/ns-appmgmt-managedapplication typedef struct _MANAGEDAPPLICATION {
// LPWSTR pszPackageName; LPWSTR pszPublisher; DWORD dwVersionHi; DWORD dwVersionLo; DWORD dwRevision; GUID GpoId; LPWSTR
// pszPolicyName; GUID ProductId; LANGID Language; LPWSTR pszOwner; LPWSTR pszCompany; LPWSTR pszComments; LPWSTR pszContact; LPWSTR
// pszSupportUrl; DWORD dwPathType; BOOL bInstalled; } MANAGEDAPPLICATION, *PMANAGEDAPPLICATION;
[PInvokeData("appmgmt.h", MSDNShortId = "8ac78f92-e665-4dd0-b226-6bf41dcd050a")]
[StructLayout(LayoutKind.Sequential)]
public struct MANAGEDAPPLICATION
{
/// <summary>The user-friendly name of the application.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string pszPackageName;
/// <summary>The name of the application's publisher.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string pszPublisher;
/// <summary>The major version number of the application.</summary>
public uint dwVersionHi;
/// <summary>The minor version number of the application.</summary>
public uint dwVersionLo;
/// <summary>The version number of the deployment. The version changes each time an application gets patched.</summary>
public uint dwRevision;
/// <summary>The GUID of the GPO from which this application is deployed.</summary>
public Guid GpoId;
/// <summary>The user-friendly name for the GPO from which this application is deployed.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string pszPolicyName;
/// <summary>If this application is installed by Windows Installer, this member is the ProductId GUID.</summary>
public Guid ProductId;
/// <summary>
/// The numeric language identifier that indicates the language version of the application. For a list of language numeric
/// identifiers, see the Language Identifier Constants and Strings topic.
/// </summary>
public ushort Language;
/// <summary>This member is unused.</summary>
public StrPtrUni pszOwner;
/// <summary>This member is unused.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public StrPtrUni pszCompany;
/// <summary>This member is unused.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public StrPtrUni pszComments;
/// <summary>This member is unused.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public StrPtrUni pszContact;
/// <summary>This member is unused.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public StrPtrUni pszSupportUrl;
/// <summary>
/// <para>Indicates the type of package used to install the application. This member can have one of the following values.</para>
/// <para>MANAGED_APPTYPE_WINDOWSINSTALLER</para>
/// <para>The application is installed using the Windows Installer.</para>
/// <para>MANAGED_APPTYPE_SETUPEXE</para>
/// <para>The application is installed using a legacy setup application.</para>
/// <para>MANAGED_APPTYPE_UNSUPPORTED</para>
/// <para>The application is installed by an unsupported setup application.</para>
/// </summary>
public uint dwPathType;
/// <summary>This parameter is <c>TRUE</c> if the application is currently installed and is <c>FALSE</c> otherwise.</summary>
[MarshalAs(UnmanagedType.Bool)]
public bool bInstalled;
}
}
}

View File

@ -0,0 +1,970 @@
using System;
using System.Runtime.InteropServices;
namespace Vanara.PInvoke
{
public static partial class AdvApi32
{
/// <summary>
/// <para>Providers implement this function to receive enable or disable notification requests.</para>
/// <para>
/// The <c>PENABLECALLBACK</c> type defines a pointer to this callback function. <c>EnableCallback</c> is a placeholder for the
/// application-defined function name.
/// </para>
/// </summary>
/// <param name="SourceId">
/// GUID that identifies the session that enabled the provider. The value is GUID_NULL if EnableTraceEx did not specify a source identifier.
/// </param>
/// <param name="IsEnabled">
/// <para>
/// Indicates if the session is enabling or disabling the provider. A value of zero indicates that the session is disabling the
/// provider. A value of 1 indicates that the session is enabling the provider. Beginning with Windows 7, this value can be one of
/// the following values:
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <term>Meaning</term>
/// </listheader>
/// <item>
/// <term>EVENT_CONTROL_CODE_DISABLE_PROVIDER 0</term>
/// <term>The session is disabling the provider.</term>
/// </item>
/// <item>
/// <term>EVENT_CONTROL_CODE_ENABLE_PROVIDER 1</term>
/// <term>The session is enabling the provider.</term>
/// </item>
/// <item>
/// <term>EVENT_CONTROL_CODE_CAPTURE_STATE 2</term>
/// <term>
/// The session is requesting that the provider log its state information. The provider determines the state information that it logs.
/// </term>
/// </item>
/// </list>
/// <para>
/// If you receive a value (for example, EVENT_CONTROL_CODE_CAPTURE_STATE) that you do not support, ignore the value (do not fail).
/// </para>
/// </param>
/// <param name="Level">
/// <para>
/// Provider-defined value that specifies the verboseness of the events that the provider writes. The provider must write the event
/// if this value is less than or equal to the level value that the event defines.
/// </para>
/// <para>This value is passed in the Level parameter of the EnableTraceEx function or the EnableLevel parameter of EnableTrace.</para>
/// </param>
/// <param name="MatchAnyKeyword">
/// <para>Bitmask of keywords that the provider uses to determine the category of events that it writes.</para>
/// <para>This value is passed in the MatchAnyKeyword parameter of the EnableTraceEx function or the EnableFlag parameter of EnableTrace.</para>
/// </param>
/// <param name="MatchAllKeyword"/>
/// <param name="FilterData">
/// <para>
/// A list of filter data that one or more sessions passed to the provider. A session can specify only one filter but the list will
/// contain filters from all sessions that used filter data to enable the provider.
/// </para>
/// <para>The filter data is valid only within the callback, so providers should make a local copy of the data.</para>
/// </param>
/// <param name="CallbackContext">Context of the callback defined when the provider called EventRegister to register itself.</param>
/// <returns>This callback function does not return a value.</returns>
/// <remarks>
/// <para>
/// To specify that you want to receive notification when a session enables or disables your provider, set the EnableCallback
/// parameter when calling the EventRegister function.
/// </para>
/// <para>
/// Classic providers needed to specify and implement a callback because it used the information that was passed to the callback to
/// determine the types of events to log and the level of verboseness to use when logging the events. However, with manifest-based
/// providers, the callback is optional and is used for informational purposes; you do not need to specify or implement the callback
/// when registering the provider unless your provider supports filtering. Providers can now just write events and ETW will determine
/// if the event is logged to the session. If you want to verify that the event should be written before writing the event, you can
/// call either the EventEnabled or EventProviderEnabled function.
/// </para>
/// <para>
/// Each time a new session enables the provider or a current session updates the provider, ETW calls the provider's callback
/// function, if implemented. The level value that ETW passes to the callback is the highest level value specified amongst all the
/// sessions. For example, if session A enabled the provider for warning (3) events and then session B enabled the provider for
/// critical (1) events, the level value for the second callback is also 3, not 1.
/// </para>
/// <para>
/// The MatchAnyKeyword value that ETW passes to the callback is a composite value of all MatchAnyKeyword values specified for all
/// sessions that enabled the provider. The same is true for the MatchAllKeywords value. The SourceId and FilterData values are those
/// values passed to the EnableTraceEx call.
/// </para>
/// <para>
/// Your callback function must not call anything that may incur LoadLibrary (more specifically, anything that requires a loader lock).
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nc-evntprov-penablecallback PENABLECALLBACK Penablecallback; void
// Penablecallback( LPCGUID SourceId, ULONG IsEnabled, UCHAR Level, ULONGLONG MatchAnyKeyword, ULONGLONG MatchAllKeyword,
// PEVENT_FILTER_DESCRIPTOR FilterData, PVOID CallbackContext ) {...}
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
[PInvokeData("evntprov.h", MSDNShortId = "f339323e-9da9-495f-aac5-f44969a018eb")]
public delegate void EnableCallback(in Guid SourceId, [MarshalAs(UnmanagedType.Bool)] bool IsEnabled, byte Level, ulong MatchAnyKeyword, ulong MatchAllKeyword, IntPtr FilterData, IntPtr CallbackContext);
/// <summary>A control code that specifies if you want to create, query or set the current activity identifier.</summary>
[PInvokeData("evntprov.h", MSDNShortId = "1c412909-bdff-4181-9750-f3444fda4c8f")]
public enum EVENT_ACTIVITY_CTRL
{
/// <summary>Sets the ActivityId parameter to the current identifier value from thread local storage.</summary>
EVENT_ACTIVITY_CTRL_GET_ID = 1,
/// <summary>
/// Uses the identifier in the ActivityId parameter to set the value of the current identifier in the thread local storage.
/// </summary>
EVENT_ACTIVITY_CTRL_SET_ID = 2,
/// <summary>Creates a new identifier and sets the ActivityId parameter to the value of the new identifier.</summary>
EVENT_ACTIVITY_CTRL_CREATE_ID = 3,
/// <summary>
/// Performs the following:
/// <list type="bullet">
/// <item>
/// <term>Copies the current identifier from thread local storage.</term>
/// </item>
/// <item>
/// <term>Sets the current identifier in thread local storage to the new identifier specified in the ActivityId parameter.</term>
/// </item>
/// <item>
/// <term>Sets the ActivityId parameter to the copy of the previous current identifier.</term>
/// </item>
/// </list>
/// </summary>
EVENT_ACTIVITY_CTRL_GET_SET_ID = 4,
/// <summary>
/// Performs the following:
/// <list type="bullet">
/// <item>
/// <term>Copies the current identifier from thread local storage.</term>
/// </item>
/// <item>
/// <term>Creates a new identifier and sets the current identifier in thread local storage to the new identifier.</term>
/// </item>
/// <item>
/// <term>Sets the ActivityId parameter to the copy of the previous current identifier.</term>
/// </item>
/// </list>
/// </summary>
EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5,
}
/// <summary>The <c>EVENT_INFO_CLASS</c> enumerated type defines a type of operation to perform on a registration object.</summary>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ne-evntprov-_event_info_class typedef enum _EVENT_INFO_CLASS {
// EventProviderBinaryTrackInfo, EventProviderSetReserved1, EventProviderSetTraits, EventProviderUseDescriptorType, MaxEventInfo } EVENT_INFO_CLASS;
[PInvokeData("evntprov.h", MSDNShortId = "76ac2b93-d5df-4504-b36d-1530bbb12ab4")]
public enum EVENT_INFO_CLASS
{
/// <summary>Tracks the full path for the binary (DLL or EXE) from which the ETW registration was made.</summary>
EventProviderBinaryTrackInfo,
/// <summary/>
EventProviderSetReserved1,
/// <summary>
/// Sets traits for the provider. Implicitly indicates that the provider correctly initializes the EVENT_DATA_DESCRIPTOR values
/// passed to EventWrite APIs, so the EVENT_DATA_DESCRIPTOR::Type field will be respected. For more information on the format of
/// the traits, see Provider Traits.
/// </summary>
EventProviderSetTraits,
/// <summary>
/// Indicates whether the provider correctly initializes the EVENT_DATA_DESCRIPTOR values passed to EventWrite APIs, which in
/// turn indicates whether the EVENT_DATA_DESCRIPTOR::Type field will be respected by the EventWrite APIs.
/// </summary>
EventProviderUseDescriptorType,
/// <summary>Maximum value for testing purposes.</summary>
MaxEventInfo,
}
/// <summary>Creates, queries, and sets the current activity identifier used by the EventWriteTransfer function.</summary>
/// <param name="ControlCode">
/// A control code that specifies if you want to create, query or set the current activity identifier. You can specify one of the
/// following codes.
/// </param>
/// <param name="ActivityId">
/// A GUID that uniquely identifies the activity. To determine when this parameter is an input parameter, an output parameter or
/// both, see the descriptions for the ControlCodes parameter.
/// </param>
/// <returns>Returns ERROR_SUCCESS if successful.</returns>
/// <remarks>
/// The EVENT_ACTIVITY_CTRL_GET_ID control code returns a GUID with all zeros (GUID_NULL) if the identifier has not been set.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventactivityidcontrol ULONG EVNTAPI
// EventActivityIdControl( ULONG ControlCode, LPGUID ActivityId );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "1c412909-bdff-4181-9750-f3444fda4c8f")]
public static extern Win32Error EventActivityIdControl(EVENT_ACTIVITY_CTRL ControlCode, in Guid ActivityId);
/// <summary>Determines if the event is enabled for any session.</summary>
/// <param name="RegHandle">
/// <para>Registration handle of the provider. The handle comes from EventRegister.</para>
/// <para><c>Note</c> A valid registration handle must be used.</para>
/// </param>
/// <param name="EventDescriptor">Describes the event. For details, see EVENT_DESCRIPTOR.</param>
/// <returns>Returns <c>TRUE</c> if the event is enabled for a session; otherwise, <c>FALSE</c>.</returns>
/// <remarks>
/// <para>
/// Typically, providers do not call this function to determine if a session is expecting this event, they simply write the event and
/// ETW determines if the event is logged to the session.
/// </para>
/// <para>
/// Providers may want to call this function if they need to perform extra work to generate the event. Calling this function first to
/// determine if a session is expecting this event or not, may save resources and time.
/// </para>
/// <para>
/// The provider would call this function if the provider generated an EVENT_DESCRIPTOR structure for the event from the manifest. If
/// the event descriptor is not available, call the EventProviderEnabled function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventenabled BOOLEAN EVNTAPI EventEnabled( REGHANDLE
// RegHandle, PCEVENT_DESCRIPTOR EventDescriptor );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "b332b6d4-6921-40bd-bebc-6646b5b9bcde")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool EventEnabled(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor);
/// <summary>Determines if the event is enabled for any session.</summary>
/// <param name="RegHandle">Registration handle of the provider. The handle comes from EventRegister.</param>
/// <param name="Level">
/// Level of detail included in the event. Specify one of the following levels that are defined in Winmeta.h. Higher numbers imply
/// that you get lower levels as well. For example, if you specify TRACE_LEVEL_WARNING, you also receive all warning, error, and
/// fatal events.
/// </param>
/// <param name="Keyword">
/// Bitmask that specifies the event category. This mask should be the same keyword mask that you defined in the manifest for the event.
/// </param>
/// <returns>Returns <c>TRUE</c> if the event is enabled for a session; otherwise, returns <c>FALSE</c>.</returns>
/// <remarks>
/// <para>
/// Typically, providers do not call this function to determine if a session is expecting this event; they simply write the event and
/// ETW determines if the event is logged to the session.
/// </para>
/// <para>
/// Providers may want to call this function if they need to perform extra work to generate the event. In this case, calling this
/// function first (to determine if a session is expecting this event or not) may save resources and time.
/// </para>
/// <para>
/// The provider would call this function if the provider did not generate an EVENT_DESCRIPTOR structure for the event from the
/// manifest. If the event descriptor is available, call the EventEnabled function.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventproviderenabled BOOLEAN EVNTAPI
// EventProviderEnabled( REGHANDLE RegHandle, UCHAR Level, ULONGLONG Keyword );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "84c035b1-cdc7-47b7-b887-e5b508f17266")]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool EventProviderEnabled(REGHANDLE RegHandle, byte Level, ulong Keyword);
/// <summary>Registers the provider.</summary>
/// <param name="ProviderId">GUID that uniquely identifies the provider.</param>
/// <param name="EnableCallback">
/// Callback that ETW calls to notify you when a session enables or disables your provider. Can be <c>NULL</c>.
/// </param>
/// <param name="CallbackContext">
/// Provider-defined context data to pass to the callback when the provider is enabled or disabled. Can be <c>NULL</c>.
/// </param>
/// <param name="RegHandle">
/// Registration handle. The handle is used by most provider function calls. Before your provider exits, you must pass this handle to
/// EventUnregister to free the handle.
/// </param>
/// <returns>Returns ERROR_SUCCESS if successful.</returns>
/// <remarks>
/// <para>Use this function to register your provider if you call EventWrite to write your events.</para>
/// <para>
/// A process can register up to 1,024 provider GUIDs; however, you should limit the number of providers that your process registers
/// to one or two. This limit includes those registered using this function and the RegisterTraceGuids function.
/// </para>
/// <para><c>Prior to Windows Vista:</c> There is no limit to the number of providers that a process can register.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventregister ULONG EVNTAPI EventRegister( LPCGUID
// ProviderId, PENABLECALLBACK EnableCallback, PVOID CallbackContext, PREGHANDLE RegHandle );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "6025c3a6-7d88-49dc-bbc3-655c172dde3c")]
public static extern Win32Error EventRegister(in Guid ProviderId, EnableCallback EnableCallback, IntPtr CallbackContext, out SafeREGHANDLE RegHandle);
/// <summary>Performs operations on a registration object.</summary>
/// <param name="RegHandle">
/// <para>Type: <c>REGHANDLE</c></para>
/// <para>Registration handle returned by EventRegister.</para>
/// </param>
/// <param name="InformationClass">
/// <para>Type: <c>EVENT_INFO_CLASS</c></para>
/// <para>Type of operation to be performed on the registration object.</para>
/// </param>
/// <param name="EventInformation">
/// <para>Type: <c>PVOID</c></para>
/// <para>The input buffer.</para>
/// </param>
/// <param name="InformationLength">
/// <para>Type: <c>ULONG</c></para>
/// <para>Size of the input buffer.</para>
/// </param>
/// <returns>
/// <para>Type: <c>ULONG</c></para>
/// <para>If the function succeeds, the return value is ERROR_SUCCESS.</para>
/// <para>If the function fails, the return value is one of the following error codes.</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>The parameter is incorrect. This error is returned if the RegHandle parameter is not a valid registration handle.</term>
/// </item>
/// <item>
/// <term>ERROR_NOT_SUPPORTED</term>
/// <term>The request is not supported.</term>
/// </item>
/// <item>
/// <term>Other</term>
/// <term>Use FormatMessage to obtain the message string for the returned error.</term>
/// </item>
/// </list>
/// </returns>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventsetinformation ULONG EVNTAPI EventSetInformation(
// REGHANDLE RegHandle, EVENT_INFO_CLASS InformationClass, PVOID EventInformation, ULONG InformationLength );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "e8b408ba-4bb5-4166-bf43-d18e4fe8de32")]
public static extern Win32Error EventSetInformation(REGHANDLE RegHandle, EVENT_INFO_CLASS InformationClass, IntPtr EventInformation, uint InformationLength);
/// <summary>Removes the provider's registration. You must call this function before your process exits.</summary>
/// <param name="RegHandle">Registration handle returned by EventRegister.</param>
/// <returns>Returns ERROR_SUCCESS if successful.</returns>
/// <remarks>
/// For private sessions, you must stop the trace (call the ControlTrace function with the ControlCode parameter set to
/// EVENT_TRACE_CONTROL_STOP) before calling this function.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventunregister ULONG EVNTAPI EventUnregister( REGHANDLE
// RegHandle );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "fdcccf6f-2f31-4356-a4ee-3b6229c01b75")]
public static extern Win32Error EventUnregister(REGHANDLE RegHandle);
/// <summary>Use this function to write an event.</summary>
/// <param name="RegHandle">Registration handle of the provider. The handle comes from EventRegister.</param>
/// <param name="EventDescriptor">Metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR.</param>
/// <param name="UserDataCount">Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128.</param>
/// <param name="UserData">
/// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this
/// parameter to <c>NULL</c> if UserDataCount is zero. The data must be in the order specified in the manifest.
/// </param>
/// <returns>Returns ERROR_SUCCESS if successful or one of the following values on error.</returns>
/// <remarks>
/// <para>Event data written with this function requires a manifest to consume the data.</para>
/// <para>ETW decides based on the event descriptor if the event is written to a session (for details, see EnableTraceEx).</para>
/// <para>
/// If you call the EventActivityIdControl function to specify an activity identifier for the event, <c>EventWrite</c> retrieves the
/// identifier from thread local storage and includes it with the event.
/// </para>
/// <para>Examples</para>
/// <para>For an example that uses <c>EventWrite</c>, see Writing Manifest-based Events.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwrite ULONG EVNTAPI EventWrite( REGHANDLE
// RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG UserDataCount, PEVENT_DATA_DESCRIPTOR UserData );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "93070eb7-c167-4419-abff-e861877dad07")]
public static extern Win32Error EventWrite(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, uint UserDataCount, IntPtr UserData);
/// <summary>Use this function to write an event.</summary>
/// <param name="RegHandle">Registration handle of the provider. The handle comes from EventRegister.</param>
/// <param name="EventDescriptor">
/// A descriptor that contains the metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR.
/// </param>
/// <param name="Filter">
/// The instance identifiers that identify the session to which the event will not written. Use a bitwise OR to specify multiple
/// identifiers. Set to zero if you do not support filters or if the event is being written to all sessions (no filters failed). For
/// information on getting the identifier for a session, see the FilterData parameter of your EnableCallback callback.
/// </param>
/// <param name="Flags">Reserved. Must be zero.</param>
/// <param name="ActivityId">
/// GUID that uniquely identifies this activity. If <c>NULL</c>, ETW gets the identifier from the thread local storage. For details
/// on getting this identifier, see EventActivityIdControl.
/// </param>
/// <param name="RelatedActivityId">
/// Activity identifier from the previous component. Use this parameter to link your component's events to the previous component's
/// events. To get the activity identifier that was set for the previous component, see the descriptions for the ControlCode
/// parameter of the EventActivityIdControl function.
/// </param>
/// <param name="UserDataCount">Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128.</param>
/// <param name="UserData">
/// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this
/// parameter to <c>NULL</c> if UserDataCount is zero. The data must be in the order specified in the manifest.
/// </param>
/// <returns>Returns ERROR_SUCCESS if successful or one of the following values on error.</returns>
/// <remarks>
/// <para>
/// Event data written with this function requires a manifest. Since the manifest is embedded in the provider, the provider must be
/// available for a consumer to consume the data written by the provider.
/// </para>
/// <para>
/// Use the ActivityId and RelatedActivityId parameters when several components want to relate their events in an end-to-end tracing
/// scenario. For example, components A, B, and C perform work on a related activity and want to link their events so that a consumer
/// can consume all the events related to that activity. ETW uses thread local storage to make available to the next component the
/// previous component's activity identifier. The component retrieves from the local storage the previous component's identifier and
/// sets the related activity identifier to it. The consumer can then use the related activity identifier to walk the chain of the
/// events from one component to the next.
/// </para>
/// <para>If each component defined their own activity identifier, the components can make the following calls to link the events:</para>
/// <list type="bullet">
/// <item>
/// <term>
/// Call the EventActivityIdControl function using the EVENT_ACTIVITY_CTRL_GET_SET_ID control code. The function uses your identifier
/// to set the activity identifier in the thread local storage and returns the activity identifier for the previous component, if set.
/// </term>
/// </item>
/// <item>
/// <term>
/// Set the RelatedActivityId parameter of this function to the ActivityId value that the EventActivityIdControl function returned.
/// Note that for the first component, the related identifier will be all zeros (GUID_NULL).
/// </term>
/// </item>
/// <item>
/// <term>Set the ActivityId of this function to <c>NULL</c> to use the activity identifier that you set in thread local storage.</term>
/// </item>
/// </list>
/// <para>
/// A provider can define filters that a session uses to filter events based on event data. With level and keywords, ETW determines
/// whether the event is written to the session but with filters, the provider uses the filter data to determine whether it writes
/// the event to the session. For example, if your provider generates process events, you could define a data filter that filters
/// process events based on the process identifier. If the identifier of the process did not match the identifier that the session
/// passed as filter data, you would set (perform a bitwise OR) the Filter parameter to the session's instance identifier to prevent
/// the event from being written to that session.
/// </para>
/// <para>Examples</para>
/// <para>For an example that uses EventWrite, see Writing Manifest-based Events.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwriteex ULONG EVNTAPI EventWriteEx( REGHANDLE
// RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG64 Filter, ULONG Flags, LPCGUID ActivityId, LPCGUID RelatedActivityId, ULONG
// UserDataCount, PEVENT_DATA_DESCRIPTOR UserData );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "00b907cb-45cd-48c7-bea4-4d8a39b4fa24")]
public static extern Win32Error EventWriteEx(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, ulong Filter, [Optional] uint Flags, in Guid ActivityId, in Guid RelatedActivityId, uint UserDataCount, IntPtr UserData);
/// <summary>Use this function to write an event.</summary>
/// <param name="RegHandle">Registration handle of the provider. The handle comes from EventRegister.</param>
/// <param name="EventDescriptor">
/// A descriptor that contains the metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR.
/// </param>
/// <param name="Filter">
/// The instance identifiers that identify the session to which the event will not written. Use a bitwise OR to specify multiple
/// identifiers. Set to zero if you do not support filters or if the event is being written to all sessions (no filters failed). For
/// information on getting the identifier for a session, see the FilterData parameter of your EnableCallback callback.
/// </param>
/// <param name="Flags">Reserved. Must be zero.</param>
/// <param name="ActivityId">
/// GUID that uniquely identifies this activity. If <c>NULL</c>, ETW gets the identifier from the thread local storage. For details
/// on getting this identifier, see EventActivityIdControl.
/// </param>
/// <param name="RelatedActivityId">
/// Activity identifier from the previous component. Use this parameter to link your component's events to the previous component's
/// events. To get the activity identifier that was set for the previous component, see the descriptions for the ControlCode
/// parameter of the EventActivityIdControl function.
/// </param>
/// <param name="UserDataCount">Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128.</param>
/// <param name="UserData">
/// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this
/// parameter to <c>NULL</c> if UserDataCount is zero. The data must be in the order specified in the manifest.
/// </param>
/// <returns>Returns ERROR_SUCCESS if successful or one of the following values on error.</returns>
/// <remarks>
/// <para>
/// Event data written with this function requires a manifest. Since the manifest is embedded in the provider, the provider must be
/// available for a consumer to consume the data written by the provider.
/// </para>
/// <para>
/// Use the ActivityId and RelatedActivityId parameters when several components want to relate their events in an end-to-end tracing
/// scenario. For example, components A, B, and C perform work on a related activity and want to link their events so that a consumer
/// can consume all the events related to that activity. ETW uses thread local storage to make available to the next component the
/// previous component's activity identifier. The component retrieves from the local storage the previous component's identifier and
/// sets the related activity identifier to it. The consumer can then use the related activity identifier to walk the chain of the
/// events from one component to the next.
/// </para>
/// <para>If each component defined their own activity identifier, the components can make the following calls to link the events:</para>
/// <list type="bullet">
/// <item>
/// <term>
/// Call the EventActivityIdControl function using the EVENT_ACTIVITY_CTRL_GET_SET_ID control code. The function uses your identifier
/// to set the activity identifier in the thread local storage and returns the activity identifier for the previous component, if set.
/// </term>
/// </item>
/// <item>
/// <term>
/// Set the RelatedActivityId parameter of this function to the ActivityId value that the EventActivityIdControl function returned.
/// Note that for the first component, the related identifier will be all zeros (GUID_NULL).
/// </term>
/// </item>
/// <item>
/// <term>Set the ActivityId of this function to <c>NULL</c> to use the activity identifier that you set in thread local storage.</term>
/// </item>
/// </list>
/// <para>
/// A provider can define filters that a session uses to filter events based on event data. With level and keywords, ETW determines
/// whether the event is written to the session but with filters, the provider uses the filter data to determine whether it writes
/// the event to the session. For example, if your provider generates process events, you could define a data filter that filters
/// process events based on the process identifier. If the identifier of the process did not match the identifier that the session
/// passed as filter data, you would set (perform a bitwise OR) the Filter parameter to the session's instance identifier to prevent
/// the event from being written to that session.
/// </para>
/// <para>Examples</para>
/// <para>For an example that uses EventWrite, see Writing Manifest-based Events.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwriteex ULONG EVNTAPI EventWriteEx( REGHANDLE
// RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, ULONG64 Filter, ULONG Flags, LPCGUID ActivityId, LPCGUID RelatedActivityId, ULONG
// UserDataCount, PEVENT_DATA_DESCRIPTOR UserData );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "00b907cb-45cd-48c7-bea4-4d8a39b4fa24")]
public static extern Win32Error EventWriteEx(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, ulong Filter, [Optional] uint Flags, [Optional] IntPtr ActivityId, [Optional] IntPtr RelatedActivityId, uint UserDataCount, IntPtr UserData);
/// <summary>Writes an event that contains a string as its data.</summary>
/// <param name="RegHandle">Registration handle of the provider. The handle comes from EventRegister.</param>
/// <param name="Level">
/// Level of detail included in the event. If the provider uses a manifest to define the event, set this value to the same level
/// defined in the manifest. If the event is not defined in a manifest, set this value to 0 to ensure the event is written,
/// otherwise, the event is written based on the level rule defined in EnableTraceEx.
/// </param>
/// <param name="Keyword">
/// Bitmask that specifies the event category. If the provider uses a manifest to define the event, set this value to the same
/// keyword mask defined in the manifest. If the event is not defined in a manifest, set this value to 0 to ensure the event is
/// written, otherwise, the event is written based on the keyword rules defined in EnableTraceEx.
/// </param>
/// <param name="String">Null-terminated string to write as the event data.</param>
/// <returns>Returns ERROR_SUCCESS if successful or one of the following values on error.</returns>
/// <remarks>
/// <para>
/// The provider does not need a manifest to use this function to write the event, unlike the EventWrite function which does require
/// a manifest. Consumers also do not need a manifest to consume events written with this function.
/// </para>
/// <para>This function gets the acitivity identifier from the thread local storage, if set.</para>
/// <para>ETW decides based on the level and keyword mask whether the event is written to a session (for details, see EnableTraceEx).</para>
/// <para>This function cannot be used to write events to the Admin or Operational channels.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwritestring ULONG EVNTAPI EventWriteString(
// REGHANDLE RegHandle, UCHAR Level, ULONGLONG Keyword, PCWSTR String );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "ecdb0e92-fcc1-4b4f-99ea-6812b6b49381")]
public static extern Win32Error EventWriteString(REGHANDLE RegHandle, byte Level, ulong Keyword, [MarshalAs(UnmanagedType.LPWStr)] string String);
/// <summary>Links events together when tracing events in an end-to-end scenario.</summary>
/// <param name="RegHandle">Registration handle of the provider. The handle comes from EventRegister.</param>
/// <param name="EventDescriptor">Metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR.</param>
/// <param name="ActivityId">
/// GUID that uniquely identifies this activity. If <c>NULL</c>, ETW gets the identifier from the thread local storage. For details
/// on getting this identifier, see EventActivityIdControl.
/// </param>
/// <param name="RelatedActivityId">
/// Activity identifier from the previous component. Use this parameter to link your component's events to the previous component's
/// events. To get the activity identifier that was set for the previous component, see the descriptions for the ControlCode
/// parameter of the EventActivityIdControl function.
/// </param>
/// <param name="UserDataCount">Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128.</param>
/// <param name="UserData">
/// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this
/// parameter to <c>NULL</c> if UserDataCount is zero. The data must be in the order specified in the manifest.
/// </param>
/// <returns>Returns ERROR_SUCCESS if successful or one of the following values on error.</returns>
/// <remarks>
/// <para>Beginning with Windows 7 and Windows Server 2008 R2, use EventWriteEx to write transfer events in an end-to-end scenario.</para>
/// <para>
/// Use this function when several components want to relate their events in an end-to-end tracing scenario. For example, components
/// A, B, and C perform work on a related activity and want to link their events so that a consumer can consume all the events
/// related to that activity. ETW uses thread local storage to make available to the next component the previous component's activity
/// identifier. The component retrieves from the local storage the previous component's identifier and sets the related activity
/// identifier to it. The consumer can then use the related activity identifier to walk the chain of the events from one component to
/// the next.
/// </para>
/// <para>If each component defined their own activity identifier, the components can make the following calls to link the events:</para>
/// <list type="bullet">
/// <item>
/// <term>
/// Call the EventActivityIdControl function using the EVENT_ACTIVITY_CTRL_GET_SET_ID control code. The function uses your identifier
/// to set the activity identifier in the thread local storage and returns the activity identifier for the previous component, if set.
/// </term>
/// </item>
/// <item>
/// <term>
/// Set the RelatedActivityId parameter of this function to the ActivityId value that the EventActivityIdControl function returned.
/// Note that for the first component, the related identifier will be all zeros (GUID_NULL).
/// </term>
/// </item>
/// <item>
/// <term>Set the ActivityId of this function to <c>NULL</c> to use the activity identifier that you set in thread local storage.</term>
/// </item>
/// </list>
/// <para>
/// Event data written with this function requires a manifest. Since the manifest is embedded in the provider, the provider must be
/// available for a consumer to consume the data written by the provider.
/// </para>
/// <para>ETW decides based on the event descriptor if the event is written to a session (for details, see EnableTraceEx).</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwritetransfer ULONG EVNTAPI EventWriteTransfer(
// REGHANDLE RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, LPCGUID ActivityId, LPCGUID RelatedActivityId, ULONG UserDataCount,
// PEVENT_DATA_DESCRIPTOR UserData );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "798cf3ba-e1cc-4eaf-a1d2-2313a64aab1a")]
public static extern Win32Error EventWriteTransfer(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, in Guid ActivityId, in Guid RelatedActivityId, uint UserDataCount, IntPtr UserData);
/// <summary>Links events together when tracing events in an end-to-end scenario.</summary>
/// <param name="RegHandle">Registration handle of the provider. The handle comes from EventRegister.</param>
/// <param name="EventDescriptor">Metadata that identifies the event to write. For details, see EVENT_DESCRIPTOR.</param>
/// <param name="ActivityId">
/// GUID that uniquely identifies this activity. If <c>NULL</c>, ETW gets the identifier from the thread local storage. For details
/// on getting this identifier, see EventActivityIdControl.
/// </param>
/// <param name="RelatedActivityId">
/// Activity identifier from the previous component. Use this parameter to link your component's events to the previous component's
/// events. To get the activity identifier that was set for the previous component, see the descriptions for the ControlCode
/// parameter of the EventActivityIdControl function.
/// </param>
/// <param name="UserDataCount">Number of EVENT_DATA_DESCRIPTOR structures in UserData. The maximum number is 128.</param>
/// <param name="UserData">
/// The event data to write. Allocate a block of memory that contains one or more EVENT_DATA_DESCRIPTOR structures. Set this
/// parameter to <c>NULL</c> if UserDataCount is zero. The data must be in the order specified in the manifest.
/// </param>
/// <returns>Returns ERROR_SUCCESS if successful or one of the following values on error.</returns>
/// <remarks>
/// <para>Beginning with Windows 7 and Windows Server 2008 R2, use EventWriteEx to write transfer events in an end-to-end scenario.</para>
/// <para>
/// Use this function when several components want to relate their events in an end-to-end tracing scenario. For example, components
/// A, B, and C perform work on a related activity and want to link their events so that a consumer can consume all the events
/// related to that activity. ETW uses thread local storage to make available to the next component the previous component's activity
/// identifier. The component retrieves from the local storage the previous component's identifier and sets the related activity
/// identifier to it. The consumer can then use the related activity identifier to walk the chain of the events from one component to
/// the next.
/// </para>
/// <para>If each component defined their own activity identifier, the components can make the following calls to link the events:</para>
/// <list type="bullet">
/// <item>
/// <term>
/// Call the EventActivityIdControl function using the EVENT_ACTIVITY_CTRL_GET_SET_ID control code. The function uses your identifier
/// to set the activity identifier in the thread local storage and returns the activity identifier for the previous component, if set.
/// </term>
/// </item>
/// <item>
/// <term>
/// Set the RelatedActivityId parameter of this function to the ActivityId value that the EventActivityIdControl function returned.
/// Note that for the first component, the related identifier will be all zeros (GUID_NULL).
/// </term>
/// </item>
/// <item>
/// <term>Set the ActivityId of this function to <c>NULL</c> to use the activity identifier that you set in thread local storage.</term>
/// </item>
/// </list>
/// <para>
/// Event data written with this function requires a manifest. Since the manifest is embedded in the provider, the provider must be
/// available for a consumer to consume the data written by the provider.
/// </para>
/// <para>ETW decides based on the event descriptor if the event is written to a session (for details, see EnableTraceEx).</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/nf-evntprov-eventwritetransfer ULONG EVNTAPI EventWriteTransfer(
// REGHANDLE RegHandle, PCEVENT_DESCRIPTOR EventDescriptor, LPCGUID ActivityId, LPCGUID RelatedActivityId, ULONG UserDataCount,
// PEVENT_DATA_DESCRIPTOR UserData );
[DllImport(Lib.AdvApi32, SetLastError = false, ExactSpelling = true)]
[PInvokeData("evntprov.h", MSDNShortId = "798cf3ba-e1cc-4eaf-a1d2-2313a64aab1a")]
public static extern Win32Error EventWriteTransfer(REGHANDLE RegHandle, in EVENT_DESCRIPTOR EventDescriptor, [Optional] IntPtr ActivityId, [Optional] IntPtr RelatedActivityId, uint UserDataCount, IntPtr UserData);
/// <summary>
/// The EVENT_DATA_DESCRIPTOR structure is used with the user mode EventWrite and the kernel mode EtwWrite functions to send events.
/// The EVENT_DATA_DESCRIPTOR structure describes the event payload.
/// </summary>
/// <remarks>
/// The most convenient method of populating the EVENT_DATA_DESCRIPTOR structure is to use the <c>EventDataDescCreate</c> macro. This
/// macro is declared in Evntprov.h and its use is documented in the Microsoft Windows SDK documentation. The following example uses
/// the <c>EventDataDescCreate</c> macro to populate an array of three EVENT_DATA_DESCRIPTOR structures. This array is then passed to
/// the <c>EtwWrite</c> function.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_data_descriptor typedef struct
// _EVENT_DATA_DESCRIPTOR { ULONGLONG Ptr; ULONG Size; union { ULONG Reserved; struct { UCHAR Type; UCHAR Reserved1; USHORT
// Reserved2; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; } EVENT_DATA_DESCRIPTOR, *PEVENT_DATA_DESCRIPTOR;
[PInvokeData("evntprov.h", MSDNShortId = "eb2b7ab6-52da-4d16-b315-6adab3131a05")]
[StructLayout(LayoutKind.Sequential)]
public struct EVENT_DATA_DESCRIPTOR
{
/// <summary>A pointer to the event descriptor data.</summary>
public ulong Ptr;
/// <summary>The size of the payload field, in bytes.</summary>
public uint Size;
/// <summary/>
public byte Type;
/// <summary/>
public byte Reserved1;
/// <summary/>
public ushort Reserved2;
/// <summary>Initializes a new instance of the <see cref="EVENT_DATA_DESCRIPTOR"/> struct.</summary>
/// <param name="DataPtr">
/// <para>A pointer to the event data used to set the <c>Ptr</c> member of EVENT_DATA_DESCRIPTOR.</para>
/// <para>If the event data's type is a <c>NULL</c>-terminated string, the DataPtr parameter must not be <c>NULL</c>.</para>
/// <para>
/// If the event data's type is a string whose size is described by some other field in the event, the DataPtr parameter may be <c>NULL</c>.
/// </para>
/// </param>
/// <param name="DataSize">The size of the event data. The value is used to set the <c>Size</c> member of EVENT_DATA_DESCRIPTOR.</param>
public EVENT_DATA_DESCRIPTOR(IntPtr DataPtr, uint DataSize)
{
Ptr = unchecked((ulong)DataPtr.ToInt64());
Size = DataSize;
Reserved2 = Reserved1 = Type = 0;
}
}
/// <summary>The EVENT_DESCRIPTOR structure identifies the description information that is available for each event.</summary>
/// <remarks>
/// <para>
/// The <c>Id</c> member is the event identifier. The structure members <c>Id</c> and <c>Version</c> can be used together to identify
/// all events for a specific provider. When the <c>Id</c> and <c>Version</c> are used in conjunction with the manifest, you can
/// precisely identify the structure and metadata of the event.
/// </para>
/// <para>
/// The pointer to the EVENT_DESCRIPTOR is passed to the EtwEventEnabled, EtwWrite, and EtwWriteTransfer functions. The most
/// convenient method of populating the EVENT_DESCRIPTOR structure is to use the <c>EventDescCreate</c> macro. This macro is declared
/// in Evntprov.h and its use is documented in the Microsoft Windows SDK.
/// </para>
/// <para>
/// The following is a list of the convenience macros that you can use to create the event descriptors and to extract and set fields
/// in the structure. For information on these macros, see Event Tracing Macros.
/// </para>
/// <para><c>Macros to create event descriptors:</c></para>
/// <list type="bullet">
/// <item>
/// <term><c>EventDescCreate</c></term>
/// </item>
/// <item>
/// <term><c>EventDescZero</c></term>
/// </item>
/// </list>
/// <para><c>Macros to extract information from an event descriptor:</c></para>
/// <list type="bullet">
/// <item>
/// <term><c>EventDescGetId</c></term>
/// </item>
/// <item>
/// <term><c>EventDescGetVersion</c></term>
/// </item>
/// <item>
/// <term><c>EventDescGetTask</c></term>
/// </item>
/// <item>
/// <term><c>EventDescGetOpcode</c></term>
/// </item>
/// <item>
/// <term><c>EventDescGetChannel</c></term>
/// </item>
/// <item>
/// <term><c>EventDescGetLevel</c></term>
/// </item>
/// <item>
/// <term><c>EventDescGetKeyword</c></term>
/// </item>
/// </list>
/// <para><c>Macros to set fields in an event descriptor:</c></para>
/// <list type="bullet">
/// <item>
/// <term><c>EventDescSetId</c></term>
/// </item>
/// <item>
/// <term><c>EventDescSetVersion</c></term>
/// </item>
/// <item>
/// <term><c>EventDescSetTask</c></term>
/// </item>
/// <item>
/// <term><c>EventDescSetOpcode</c></term>
/// </item>
/// <item>
/// <term><c>EventDescSetLevel</c></term>
/// </item>
/// <item>
/// <term><c>EventDescSetChannel</c></term>
/// </item>
/// <item>
/// <term><c>EventDescSetKeyword</c></term>
/// </item>
/// <item>
/// <term><c>EventDescOrKeyword</c></term>
/// </item>
/// </list>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_descriptor typedef struct _EVENT_DESCRIPTOR {
// USHORT Id; UCHAR Version; UCHAR Channel; UCHAR Level; UCHAR Opcode; USHORT Task; ULONGLONG Keyword; } EVENT_DESCRIPTOR, *PEVENT_DESCRIPTOR;
[PInvokeData("evntprov.h", MSDNShortId = "cfe84b3d-fed2-4624-9899-8451e5b39de0")]
[StructLayout(LayoutKind.Sequential)]
public struct EVENT_DESCRIPTOR
{
/// <summary>The event identifier. Each event is associated with a 16-bit numeric value.</summary>
public ushort Id;
/// <summary>
/// A numeric value that represents a version of the event. Component updates can change this value for a specific event.
/// </summary>
public byte Version;
/// <summary>
/// The channel that the event is intended for. Note that the channel name is not stored here. The value of the channel is
/// assigned by the message compiler.
/// </summary>
public byte Channel;
/// <summary>
/// The level of the event. The level indicates the severity or verbosity of the event. The level is used with earlier versions
/// of the ETW and WPP event fields. The levels have names with values, such as Error, Warning, Information, and so on.
/// </summary>
public byte Level;
/// <summary>
/// The activity that the driver was performing at the time of the event. The <c>Opcode</c> member is defined by the provider or
/// is one of the system-defined values defined in the Winmeta.xml file that is provided with the Windows Driver Kit (WDK) in the
/// %Winddk%&lt;i&gt;version\inc\api directory.
/// </summary>
public byte Opcode;
/// <summary>
/// The <c>Task</c> corresponds to the logical activity that the driver was performing when it raised the event. The
/// <c>Opcode</c> member refers to a specific action within that logical activity.
/// </summary>
public ushort Task;
/// <summary>
/// The categories or tags assigned to the event. Each keyword categorizes the event in some way. For example, a category could
/// be <c>Network</c>, <c>Storage</c>, or <c>Not Found</c>. An event can belong to more then one category, in which case multiple
/// keywords are specified for the event. The keyword values are bitmasks and can be combined.
/// </summary>
public ulong Keyword;
/// <summary>Initializes a new instance of the <see cref="EVENT_DESCRIPTOR"/> struct.</summary>
/// <param name="Id">Event identifier. The value is used to set the <c>Id</c> member of EVENT_DESCRIPTOR.</param>
/// <param name="Version">Version of the event. The value is used to set the <c>Version</c> member of EVENT_DESCRIPTOR.</param>
/// <param name="Channel">
/// The category of events to which this event belongs. The value is used to set the <c>Channel</c> member of EVENT_DESCRIPTOR.
/// </param>
/// <param name="Level">Specifies the severity of the event. The value is used to set the <c>Level</c> member of EVENT_DESCRIPTOR.</param>
/// <param name="Task">
/// Identifies a logical component of the application whose events you want to enable. The value is used to set the <c>Task</c>
/// member of EVENT_DESCRIPTOR.
/// </param>
/// <param name="Opcode">
/// Operation being performed at the time the event was written. The value is used to set the <c>Opcode</c> member of EVENT_DESCRIPTOR.
/// </param>
/// <param name="Keyword">
/// Bitmask that further defines the category of events to which the event belongs. The value is used to set the <c>Keyword</c>
/// member of EVENT_DESCRIPTOR.
/// </param>
public EVENT_DESCRIPTOR(ushort Id, byte Version, byte Channel, byte Level, ushort Task, byte Opcode, ulong Keyword)
{
this.Channel = Channel;
this.Id = Id;
this.Keyword = Keyword;
this.Level = Level;
this.Opcode = Opcode;
this.Task = Task;
this.Version = Version;
}
}
/// <summary>
/// The EVENT_FILTER_DESCRIPTOR structure supplements the event provider, level, and keyword data that determines which events are
/// reported and traced. The EVENT_FILTER_DESCRIPTOR structure gives the event provider greater control over the selection of events
/// for reporting and tracing.
/// </summary>
/// <remarks>
/// You pass a pointer to the EVENT_FILTER_DESCRIPTOR structure when you create the optional driver-supplied
/// EtwEnableCallbackfunction. When you register the driver with ETW, the EtwRegister function takes a pointer to the
/// <c>EtwEnableCallback</c> function as a parameter.
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/evntprov/ns-evntprov-_event_filter_descriptor typedef struct
// _EVENT_FILTER_DESCRIPTOR { ULONGLONG Ptr; ULONG Size; ULONG Type; } EVENT_FILTER_DESCRIPTOR, *PEVENT_FILTER_DESCRIPTOR;
[PInvokeData("evntprov.h", MSDNShortId = "3870a471-a3cf-424f-bba3-bc06de1ebecc")]
[StructLayout(LayoutKind.Sequential)]
public struct EVENT_FILTER_DESCRIPTOR
{
/// <summary>A pointer to the filter data.</summary>
public ulong Ptr;
/// <summary>The size of the filter data, in bytes. The maximum size is 1024 bytes.</summary>
public uint Size;
/// <summary>
/// The type of filter data. The type is application-defined. An event controller that knows about the provider and knows details
/// about the provider's events can use the <c>Type</c> field to send the provider an arbitrary set of data for use as
/// enhancements to the filtering of events.
/// </summary>
public uint Type;
}
/// <summary>Provides a handle to a provider registration handle.</summary>
[StructLayout(LayoutKind.Sequential)]
public struct REGHANDLE : IHandle
{
private IntPtr handle;
/// <summary>Initializes a new instance of the <see cref="REGHANDLE"/> struct.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
public REGHANDLE(IntPtr preexistingHandle) => handle = preexistingHandle;
/// <summary>Returns an invalid handle by instantiating a <see cref="REGHANDLE"/> object with <see cref="IntPtr.Zero"/>.</summary>
public static REGHANDLE NULL => new REGHANDLE(IntPtr.Zero);
/// <summary>Gets a value indicating whether this instance is a null handle.</summary>
public bool IsNull => handle == IntPtr.Zero;
/// <summary>Performs an explicit conversion from <see cref="REGHANDLE"/> to <see cref="IntPtr"/>.</summary>
/// <param name="h">The handle.</param>
/// <returns>The result of the conversion.</returns>
public static explicit operator IntPtr(REGHANDLE h) => h.handle;
/// <summary>Performs an implicit conversion from <see cref="IntPtr"/> to <see cref="REGHANDLE"/>.</summary>
/// <param name="h">The pointer to a handle.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator REGHANDLE(IntPtr h) => new REGHANDLE(h);
/// <summary>Implements the operator !=.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator !=(REGHANDLE h1, REGHANDLE h2) => !(h1 == h2);
/// <summary>Implements the operator ==.</summary>
/// <param name="h1">The first handle.</param>
/// <param name="h2">The second handle.</param>
/// <returns>The result of the operator.</returns>
public static bool operator ==(REGHANDLE h1, REGHANDLE h2) => h1.Equals(h2);
/// <inheritdoc/>
public override bool Equals(object obj) => obj is REGHANDLE h ? handle == h.handle : false;
/// <inheritdoc/>
public override int GetHashCode() => handle.GetHashCode();
/// <inheritdoc/>
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Provides a <see cref="SafeHandle"/> for <see cref="REGHANDLE"/> that is disposed using <see cref="EventUnregister"/>.</summary>
public class SafeREGHANDLE : SafeHANDLE
{
/// <summary>Initializes a new instance of the <see cref="SafeREGHANDLE"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle">
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
/// </param>
public SafeREGHANDLE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeREGHANDLE"/> class.</summary>
private SafeREGHANDLE() : base() { }
/// <summary>Performs an implicit conversion from <see cref="SafeREGHANDLE"/> to <see cref="REGHANDLE"/>.</summary>
/// <param name="h">The safe handle instance.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator REGHANDLE(SafeREGHANDLE h) => h.handle;
/// <inheritdoc/>
protected override bool InternalReleaseHandle() => EventUnregister(handle).Succeeded;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,325 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using static Vanara.PInvoke.Kernel32;
namespace Vanara.PInvoke
{
public static partial class AdvApi32
{
/// <summary>
/// <para>
/// Creates a new process and its primary thread. The new process runs in the security context of the user represented by the
/// specified token.
/// </para>
/// <para>
/// Typically, the process that calls the <c>CreateProcessAsUser</c> function must have the <c>SE_INCREASE_QUOTA_NAME</c> privilege
/// and may require the <c>SE_ASSIGNPRIMARYTOKEN_NAME</c> privilege if the token is not assignable. If this function fails with
/// <c>ERROR_PRIVILEGE_NOT_HELD</c> (1314), use the CreateProcessWithLogonW function instead. <c>CreateProcessWithLogonW</c> requires
/// no special privileges, but the specified user account must be allowed to log on interactively. Generally, it is best to use
/// <c>CreateProcessWithLogonW</c> to create a process with alternate credentials.
/// </para>
/// </summary>
/// <param name="hToken">
/// <para>
/// A handle to the primary token that represents a user. The handle must have the <c>TOKEN_QUERY</c>, <c>TOKEN_DUPLICATE</c>, and
/// <c>TOKEN_ASSIGN_PRIMARY</c> access rights. For more information, see Access Rights for Access-Token Objects. The user represented
/// by the token must have read and execute access to the application specified by the lpApplicationName or the lpCommandLine parameter.
/// </para>
/// <para>
/// To get a primary token that represents the specified user, call the LogonUser function. Alternatively, you can call the
/// DuplicateTokenEx function to convert an impersonation token into a primary token. This allows a server application that is
/// impersonating a client to create a process that has the security context of the client.
/// </para>
/// <para>
/// If hToken is a restricted version of the caller's primary token, the <c>SE_ASSIGNPRIMARYTOKEN_NAME</c> privilege is not required.
/// If the necessary privileges are not already enabled, <c>CreateProcessAsUser</c> enables them for the duration of the call. For
/// more information, see Running with Special Privileges.
/// </para>
/// <para>
/// <c>Terminal Services:</c> The process is run in the session specified in the token. By default, this is the same session that
/// called LogonUser. To change the session, use the SetTokenInformation function.
/// </para>
/// </param>
/// <param name="lpApplicationName">
/// <para>
/// The name of the module to be executed. This module can be a Windows-based application. It can be some other type of module (for
/// example, MS-DOS or OS/2) if the appropriate subsystem is available on the local computer.
/// </para>
/// <para>
/// The string can specify the full path and file name of the module to execute or it can specify a partial name. In the case of a
/// partial name, the function uses the current drive and current directory to complete the specification. The function will not use
/// the search path. This parameter must include the file name extension; no default extension is assumed.
/// </para>
/// <para>
/// The lpApplicationName parameter can be <c>NULL</c>. In that case, the module name must be the first white spacedelimited token
/// in the lpCommandLine string. If you are using a long file name that contains a space, use quoted strings to indicate where the
/// file name ends and the arguments begin; otherwise, the file name is ambiguous. For example, consider the string "c:\program
/// files\sub dir\program name". This string can be interpreted in a number of ways. The system tries to interpret the possibilities
/// in the following order:
/// </para>
/// <para>
/// <c>c:\program.exe</c><c>c:\program files\sub.exe</c><c>c:\program files\sub dir\program.exe</c><c>c:\program files\sub
/// dir\program name.exe</c> If the executable module is a 16-bit application, lpApplicationName should be <c>NULL</c>, and the
/// string pointed to by lpCommandLine should specify the executable module as well as its arguments. By default, all 16-bit
/// Windows-based applications created by <c>CreateProcessAsUser</c> are run in a separate VDM (equivalent to
/// <c>CREATE_SEPARATE_WOW_VDM</c> in CreateProcess).
/// </para>
/// </param>
/// <param name="lpCommandLine">
/// <para>
/// The command line to be executed. The maximum length of this string is 32K characters. If lpApplicationName is <c>NULL</c>, the
/// module name portion of lpCommandLine is limited to <c>MAX_PATH</c> characters.
/// </para>
/// <para>
/// The Unicode version of this function, <c>CreateProcessAsUserW</c>, can modify the contents of this string. Therefore, this
/// parameter cannot be a pointer to read-only memory (such as a <c>const</c> variable or a literal string). If this parameter is a
/// constant string, the function may cause an access violation.
/// </para>
/// <para>
/// The lpCommandLine parameter can be <c>NULL</c>. In that case, the function uses the string pointed to by lpApplicationName as the
/// command line.
/// </para>
/// <para>
/// If both lpApplicationName and lpCommandLine are non- <c>NULL</c>, *lpApplicationName specifies the module to execute, and
/// *lpCommandLine specifies the command line. The new process can use GetCommandLine to retrieve the entire command line. Console
/// processes written in C can use the argc and argv arguments to parse the command line. Because argv[0] is the module name, C
/// programmers generally repeat the module name as the first token in the command line.
/// </para>
/// <para>
/// If lpApplicationName is <c>NULL</c>, the first white spacedelimited token of the command line specifies the module name. If you
/// are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin
/// (see the explanation for the lpApplicationName parameter). If the file name does not contain an extension, .exe is appended.
/// Therefore, if the file name extension is .com, this parameter must include the .com extension. If the file name ends in a period
/// (.) with no extension, or if the file name contains a path, .exe is not appended. If the file name does not contain a directory
/// path, the system searches for the executable file in the following sequence:
/// </para>
/// <list type="number">
/// <item>
/// <term>The directory from which the application loaded.</term>
/// </item>
/// <item>
/// <term>The current directory for the parent process.</term>
/// </item>
/// <item>
/// <term>The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory.</term>
/// </item>
/// <item>
/// <term>The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched.</term>
/// </item>
/// <item>
/// <term>The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.</term>
/// </item>
/// <item>
/// <term>
/// The directories that are listed in the PATH environment variable. Note that this function does not search the per-application
/// path specified by the <c>App Paths</c> registry key. To include this per-application path in the search sequence, use the
/// ShellExecute function.
/// </term>
/// </item>
/// </list>
/// <para>
/// The system adds a null character to the command line string to separate the file name from the arguments. This divides the
/// original string into two strings for internal processing.
/// </para>
/// </param>
/// <param name="lpProcessAttributes">
/// A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new process object and determines
/// whether child processes can inherit the returned handle to the process. If lpProcessAttributes is <c>NULL</c> or
/// <c>lpSecurityDescriptor</c> is <c>NULL</c>, the process gets a default security descriptor and the handle cannot be inherited.
/// The default security descriptor is that of the user referenced in the hToken parameter. This security descriptor may not allow
/// access for the caller, in which case the process may not be opened again after it is run. The process handle is valid and will
/// continue to have full access rights.
/// </param>
/// <param name="lpThreadAttributes">
/// A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new thread object and determines
/// whether child processes can inherit the returned handle to the thread. If lpThreadAttributes is <c>NULL</c> or
/// <c>lpSecurityDescriptor</c> is <c>NULL</c>, the thread gets a default security descriptor and the handle cannot be inherited. The
/// default security descriptor is that of the user referenced in the hToken parameter. This security descriptor may not allow access
/// for the caller.
/// </param>
/// <param name="bInheritHandles">
/// <para>
/// If this parameter is <c>TRUE</c>, each inheritable handle in the calling process is inherited by the new process. If the
/// parameter is <c>FALSE</c>, the handles are not inherited. Note that inherited handles have the same value and access rights as
/// the original handles.
/// </para>
/// <para>
/// <c>Terminal Services:</c> You cannot inherit handles across sessions. Additionally, if this parameter is <c>TRUE</c>, you must
/// create the process in the same session as the caller.
/// </para>
/// <para>
/// <c>Protected Process Light (PPL) processes:</c> The generic handle inheritance is blocked when a PPL process creates a non-PPL
/// process since PROCESS_DUP_HANDLE is not allowed from a non-PPL process to a PPL process. See Process Security and Access Rights
/// </para>
/// </param>
/// <param name="dwCreationFlags">
/// <para>
/// The flags that control the priority class and the creation of the process. For a list of values, see Process Creation Flags.
/// </para>
/// <para>
/// This parameter also controls the new process's priority class, which is used to determine the scheduling priorities of the
/// process's threads. For a list of values, see GetPriorityClass. If none of the priority class flags is specified, the priority
/// class defaults to <c>NORMAL_PRIORITY_CLASS</c> unless the priority class of the creating process is <c>IDLE_PRIORITY_CLASS</c> or
/// <c>BELOW_NORMAL_PRIORITY_CLASS</c>. In this case, the child process receives the default priority class of the calling process.
/// </para>
/// </param>
/// <param name="lpEnvironment">
/// <para>
/// A pointer to an environment block for the new process. If this parameter is <c>NULL</c>, the new process uses the environment of
/// the calling process.
/// </para>
/// <para>An environment block consists of a null-terminated block of null-terminated strings. Each string is in the following form:</para>
/// <para>name=value\0</para>
/// <para>Because the equal sign is used as a separator, it must not be used in the name of an environment variable.</para>
/// <para>
/// An environment block can contain either Unicode or ANSI characters. If the environment block pointed to by lpEnvironment contains
/// Unicode characters, be sure that dwCreationFlags includes <c>CREATE_UNICODE_ENVIRONMENT</c>. If this parameter is <c>NULL</c> and
/// the environment block of the parent process contains Unicode characters, you must also ensure that dwCreationFlags includes <c>CREATE_UNICODE_ENVIRONMENT</c>.
/// </para>
/// <para>
/// The ANSI version of this function, <c>CreateProcessAsUserA</c> fails if the total size of the environment block for the process
/// exceeds 32,767 characters.
/// </para>
/// <para>
/// Note that an ANSI environment block is terminated by two zero bytes: one for the last string, one more to terminate the block. A
/// Unicode environment block is terminated by four zero bytes: two for the last string, two more to terminate the block.
/// </para>
/// <para>
/// <c>Windows Server 2003 and Windows XP:</c> If the size of the combined user and system environment variable exceeds 8192 bytes,
/// the process created by <c>CreateProcessAsUser</c> no longer runs with the environment block passed to the function by the parent
/// process. Instead, the child process runs with the environment block returned by the CreateEnvironmentBlock function.
/// </para>
/// <para>To retrieve a copy of the environment block for a given user, use the CreateEnvironmentBlock function.</para>
/// </param>
/// <param name="lpCurrentDirectory">
/// <para>The full path to the current directory for the process. The string can also specify a UNC path.</para>
/// <para>
/// If this parameter is NULL, the new process will have the same current drive and directory as the calling process. (This feature
/// is provided primarily for shells that need to start an application and specify its initial drive and working directory.)
/// </para>
/// </param>
/// <param name="lpStartupInfo">
/// <para>A pointer to a STARTUPINFO or STARTUPINFOEX structure.</para>
/// <para>
/// The user must have full access to both the specified window station and desktop. If you want the process to be interactive,
/// specify winsta0\default. If the <c>lpDesktop</c> member is NULL, the new process inherits the desktop and window station of its
/// parent process. If this member is an empty string, "", the new process connects to a window station using the rules described in
/// Process Connection to a Window Station.
/// </para>
/// <para>
/// To set extended attributes, use a STARTUPINFOEX structure and specify <c>EXTENDED_STARTUPINFO_PRESENT</c> in the dwCreationFlags parameter.
/// </para>
/// <para>Handles in STARTUPINFO or STARTUPINFOEX must be closed with CloseHandle when they are no longer needed.</para>
/// <para>
/// <c>Important</c> The caller is responsible for ensuring that the standard handle fields in STARTUPINFO contain valid handle
/// values. These fields are copied unchanged to the child process without validation, even when the <c>dwFlags</c> member specifies
/// <c>STARTF_USESTDHANDLES</c>. Incorrect values can cause the child process to misbehave or crash. Use the Application Verifier
/// runtime verification tool to detect invalid handles.
/// </para>
/// </param>
/// <param name="lpProcessInformation">
/// <para>A pointer to a PROCESS_INFORMATION structure that receives identification information about the new process.</para>
/// <para>Handles in PROCESS_INFORMATION must be closed with CloseHandle when they are no longer needed.</para>
/// </param>
/// <returns>
/// <para>If the function succeeds, the return value is nonzero.</para>
/// <para>If the function fails, the return value is zero. To get extended error information, call GetLastError.</para>
/// <para>
/// Note that the function returns before the process has finished initialization. If a required DLL cannot be located or fails to
/// initialize, the process is terminated. To get the termination status of a process, call GetExitCodeProcess.
/// </para>
/// </returns>
/// <remarks>
/// <para>
/// <c>CreateProcessAsUser</c> must be able to open the primary token of the calling process with the <c>TOKEN_DUPLICATE</c> and
/// <c>TOKEN_IMPERSONATE</c> access rights.
/// </para>
/// <para>
/// By default, <c>CreateProcessAsUser</c> creates the new process on a noninteractive window station with a desktop that is not
/// visible and cannot receive user input. To enable user interaction with the new process, you must specify the name of the default
/// interactive window station and desktop, "winsta0\default", in the <c>lpDesktop</c> member of the STARTUPINFO structure. In
/// addition, before calling <c>CreateProcessAsUser</c>, you must change the discretionary access control list (DACL) of both the
/// default interactive window station and the default desktop. The DACLs for the window station and desktop must grant access to the
/// user or the logon session represented by the hToken parameter.
/// </para>
/// <para>
/// <c>CreateProcessAsUser</c> does not load the specified user's profile into the <c>HKEY_USERS</c> registry key. Therefore, to
/// access the information in the <c>HKEY_CURRENT_USER</c> registry key, you must load the user's profile information into
/// <c>HKEY_USERS</c> with the LoadUserProfile function before calling <c>CreateProcessAsUser</c>. Be sure to call UnloadUserProfile
/// after the new process exits.
/// </para>
/// <para>
/// If the lpEnvironment parameter is NULL, the new process inherits the environment of the calling process.
/// <c>CreateProcessAsUser</c> does not automatically modify the environment block to include environment variables specific to the
/// user represented by hToken. For example, the USERNAME and USERDOMAIN variables are inherited from the calling process if
/// lpEnvironment is NULL. It is your responsibility to prepare the environment block for the new process and specify it in lpEnvironment.
/// </para>
/// <para>
/// The CreateProcessWithLogonW and CreateProcessWithTokenW functions are similar to <c>CreateProcessAsUser</c>, except that the
/// caller does not need to call the LogonUser function to authenticate the user and get a token.
/// </para>
/// <para>
/// <c>CreateProcessAsUser</c> allows you to access the specified directory and executable image in the security context of the
/// caller or the target user. By default, <c>CreateProcessAsUser</c> accesses the directory and executable image in the security
/// context of the caller. In this case, if the caller does not have access to the directory and executable image, the function
/// fails. To access the directory and executable image using the security context of the target user, specify hToken in a call to
/// the ImpersonateLoggedOnUser function before calling <c>CreateProcessAsUser</c>.
/// </para>
/// <para>
/// The process is assigned a process identifier. The identifier is valid until the process terminates. It can be used to identify
/// the process, or specified in the OpenProcess function to open a handle to the process. The initial thread in the process is also
/// assigned a thread identifier. It can be specified in the OpenThread function to open a handle to the thread. The identifier is
/// valid until the thread terminates and can be used to uniquely identify the thread within the system. These identifiers are
/// returned in the PROCESS_INFORMATION structure.
/// </para>
/// <para>
/// The calling thread can use the WaitForInputIdle function to wait until the new process has finished its initialization and is
/// waiting for user input with no input pending. This can be useful for synchronization between parent and child processes, because
/// <c>CreateProcessAsUser</c> returns without waiting for the new process to finish its initialization. For example, the creating
/// process would use <c>WaitForInputIdle</c> before trying to find a window associated with the new process.
/// </para>
/// <para>
/// The preferred way to shut down a process is by using the ExitProcess function, because this function sends notification of
/// approaching termination to all DLLs attached to the process. Other means of shutting down a process do not notify the attached
/// DLLs. Note that when a thread calls <c>ExitProcess</c>, other threads of the process are terminated without an opportunity to
/// execute any additional code (including the thread termination code of attached DLLs). For more information, see Terminating a Process.
/// </para>
/// <para>Security Remarks</para>
/// <para>
/// The lpApplicationName parameter can be NULL, in which case the executable name must be the first white spacedelimited string in
/// lpCommandLine. If the executable or path name has a space in it, there is a risk that a different executable could be run because
/// of the way the function parses spaces. The following example is dangerous because the function will attempt to run "Program.exe",
/// if it exists, instead of "MyApp.exe".
/// </para>
/// <para>
/// If a malicious user were to create an application called "Program.exe" on a system, any program that incorrectly calls
/// <c>CreateProcessAsUser</c> using the Program Files directory will run this application instead of the intended application.
/// </para>
/// <para>
/// To avoid this problem, do not pass NULL for lpApplicationName. If you do pass <c>NULL</c> for lpApplicationName, use quotation
/// marks around the executable path in lpCommandLine, as shown in the example below.
/// </para>
/// <para>
/// <c>PowerShell:</c> When the <c>CreateProcessAsUser</c> function is used to implement a cmdlet in PowerShell version 2.0, the
/// cmdlet operates correctly for both fan-in and fan-out remote sessions. Because of certain security scenarios, however, a cmdlet
/// implemented with <c>CreateProcessAsUser</c> only operates correctly in PowerShell version 3.0 for fan-in remote sessions; fan-out
/// remote sessions will fail because of insufficient client security privileges. To implement a cmdlet that works for both fan-in
/// and fan-out remote sessions in PowerShell version 3.0, use the CreateProcess function.
/// </para>
/// <para>Examples</para>
/// <para>For an example, see Starting an Interactive Client Process.</para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessasusera BOOL
// CreateProcessAsUserA( HANDLE hToken, LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
// LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR
// lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation );
[DllImport(Lib.AdvApi32, SetLastError = true, CharSet = CharSet.Auto)]
[PInvokeData("processthreadsapi.h", MSDNShortId = "6b3f4dd9-500b-420e-804a-401a9e188be8")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CreateProcessAsUser(HTOKEN hToken, [Optional] string lpApplicationName, [Optional] StringBuilder lpCommandLine, [Optional] SECURITY_ATTRIBUTES lpProcessAttributes, [Optional] SECURITY_ATTRIBUTES lpThreadAttributes,
[MarshalAs(UnmanagedType.Bool)] bool bInheritHandles, CREATE_PROCESS dwCreationFlags, [Optional] IntPtr lpEnvironment, [Optional] string lpCurrentDirectory, in STARTUPINFO lpStartupInfo, [Out] PROCESS_INFORMATION lpProcessInformation);
/// <summary>The OpenProcessToken function opens the access token associated with a process.</summary>
/// <param name="ProcessHandle">
/// A handle to the process whose access token is opened. The process must have the PROCESS_QUERY_INFORMATION access permission.

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,9 @@
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Vanara.InteropServices;
namespace Vanara.PInvoke
{
public static partial class AdvApi32
{
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -2564,6 +2564,53 @@ namespace Vanara.PInvoke
[PInvokeData("winsvc.h", MSDNShortId = "87861465-c966-479a-b906-27ae36cc83c8")]
public static extern SC_LOCK LockServiceDatabase(SC_HANDLE hSCManager);
/// <summary>
/// Reports the boot status to the service control manager. It is used by boot verification programs. This function can be called
/// only by a process running in the LocalSystem or Administrator's account.
/// </summary>
/// <param name="BootAcceptable">
/// If the value is TRUE, the system saves the configuration as the last-known good configuration. If the value is FALSE, the system
/// immediately reboots, using the previously saved last-known good configuration.
/// </param>
/// <returns>
/// <para>If the BootAcceptable parameter is FALSE, the function does not return.</para>
/// <para>If the last-known good configuration was successfully saved, the return value is nonzero.</para>
/// <para>If an error occurs, the return value is zero. To get extended error information, call GetLastError.</para>
/// <para>
/// The following error codes may be set by the service control manager. Other error codes may be set by the registry functions that
/// are called by the service control manager to set parameters in the configuration registry.
/// </para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_ACCESS_DENIED</term>
/// <term>
/// The user does not have permission to perform this operation. Only the system and members of the Administrator's group can do so.
/// </term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// Saving the configuration of a running system with this function is an acceptable method for saving the last-known good
/// configuration. If the boot configuration is unacceptable, use this function to reboot the system using the existing last-known
/// good configuration.
/// </para>
/// <para>
/// This function call requires the caller's token to have permission to acquire the SC_MANAGER_MODIFY_BOOT_CONFIG access right. For
/// more information, see Service Security and Access Rights.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/nf-winsvc-notifybootconfigstatus
// BOOL NotifyBootConfigStatus( BOOL BootAcceptable );
[DllImport(Lib.AdvApi32, SetLastError = true, ExactSpelling = true)]
[PInvokeData("winsvc.h", MSDNShortId = "0b2b9cd0-f897-4681-9e99-5d0bed986112")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool NotifyBootConfigStatus([MarshalAs(UnmanagedType.Bool)] bool BootAcceptable);
/// <summary>
/// Enables an application to receive notification when the specified service is created or deleted or when its status changes.
/// </summary>

View File

@ -0,0 +1,38 @@
using NUnit.Framework;
using System;
using System.Linq;
using System.Security.Principal;
using Vanara.InteropServices;
using static Vanara.PInvoke.AdvApi32;
namespace Vanara.PInvoke.Tests
{
[TestFixture()]
public class AppMgmtTests
{
[Test]
public void GetLocalManagedApplicationsTest()
{
var l = GetLocalManagedApplications(true).ToArray();
TestContext.WriteLine("; ", l.Select(i => i.pszDeploymentName));
l = GetLocalManagedApplications(false).ToArray();
TestContext.WriteLine("; ", l.Select(i => i.pszDeploymentName));
}
[Test]
public void GetManagedApplicationCategoriesTest()
{
var l = GetManagedApplicationCategories().ToArray();
TestContext.WriteLine("; ", l.Select(i => i.pszDescription));
Assert.That(l, Is.Not.Empty);
}
[Test]
public void GetManagedApplicationsTest()
{
var l = GetManagedApplications(null).ToArray();
TestContext.WriteLine("; ", l.Select(i => i.pszPackageName));
Assert.That(l, Is.Not.Empty);
}
}
}