Beispiel #1
0
        public static void RunForEach <TEnum>(Type lib, string name, Func <TEnum, object[]> makeParam, Action <TEnum, Exception> error = null, Action <TEnum, object, object[]> action = null, CorrespondingAction?filter = null) where TEnum : Enum
        {
            var mi = lib.GetMethods(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static).Where(m => m.IsGenericMethod && m.Name == name).First();

            if (mi is null)
            {
                throw new ArgumentException("Unable to find method.");
            }
            foreach (var e in Enum.GetValues(typeof(TEnum)).Cast <TEnum>())
            {
                var type = (filter.HasValue ? CorrespondingTypeAttribute.GetCorrespondingTypes(e, filter.Value) : CorrespondingTypeAttribute.GetCorrespondingTypes(e)).FirstOrDefault();
                if (type is null)
                {
                    TestContext.WriteLine($"No corresponding type found for {e}.");
                    continue;
                }
                var gmi   = mi.MakeGenericMethod(type);
                var param = makeParam(e);
                try
                {
                    var ret = gmi.Invoke(null, param);
                    action?.Invoke(e, ret, param);
                }
                catch (Exception ex)
                {
                    error?.Invoke(e, ex.InnerException);
                }
            }
        }
Beispiel #2
0
        /// <summary>Converts the generic GDI object handle to a specific handle.</summary>
        /// <typeparam name="T">The handle type to which to convert.</typeparam>
        /// <param name="hObj">The generic GDI object handle.</param>
        /// <returns>The converted handle of type <typeparamref name="T"/>.</returns>
        /// <exception cref="ArgumentException">The conversion type specified is not valid for the supplied GDI object.</exception>
        public static T ConvertTo <T>(this IGraphicsObjectHandle hObj) where T : IGraphicsObjectHandle
        {
            var ot = GetObjectType(hObj.DangerousGetHandle());

            if (ot == 0)
            {
                Win32Error.ThrowLastError();
            }
            if (!CorrespondingTypeAttribute.CanGet(ot, typeof(T)))
            {
                throw new ArgumentException($"The conversion type specified is not valid for the supplied GDI object.");
            }
            return((T)(object)hObj.DangerousGetHandle());
        }
Beispiel #3
0
        /// <summary>
        /// <para>Retrieves information about the specified process.</para>
        /// </summary>
        /// <typeparam name="T">The type of the structure to retrieve.</typeparam>
        /// <param name="ProcessHandle">A handle to the process for which information is to be retrieved.</param>
        /// <param name="ProcessInformationClass">
        /// <para>
        /// The type of process information to be retrieved. This parameter can be one of the following values from the
        /// <c>PROCESSINFOCLASS</c> enumeration.
        /// </para>
        /// <list type="table">
        /// <listheader>
        /// <term>Value</term>
        /// <term>Meaning</term>
        /// </listheader>
        /// <item>
        /// <term>ProcessBasicInformation <br/> 0</term>
        /// <term>
        /// Retrieves a pointer to a PEB structure that can be used to determine whether the specified process is being debugged, and a
        /// unique value used by the system to identify the specified process. Use the CheckRemoteDebuggerPresent and GetProcessId functions
        /// to obtain this information.
        /// </term>
        /// </item>
        /// <item>
        /// <term>ProcessDebugPort <br/> 7</term>
        /// <term>
        /// Retrieves a DWORD_PTR value that is the port number of the debugger for the process. A nonzero value indicates that the process
        /// is being run under the control of a ring 3 debugger. Use the CheckRemoteDebuggerPresent or IsDebuggerPresent function.
        /// </term>
        /// </item>
        /// <item>
        /// <term>ProcessWow64Information <br/> 26</term>
        /// <term>
        /// Determines whether the process is running in the WOW64 environment (WOW64 is the x86 emulator that allows Win32-based
        /// applications to run on 64-bit Windows). Use the IsWow64Process2 function to obtain this information.
        /// </term>
        /// </item>
        /// <item>
        /// <term>ProcessImageFileName <br/> 27</term>
        /// <term>
        /// Retrieves a UNICODE_STRING value containing the name of the image file for the process. Use the QueryFullProcessImageName or
        /// GetProcessImageFileName function to obtain this information.
        /// </term>
        /// </item>
        /// <item>
        /// <term>ProcessBreakOnTermination <br/> 29</term>
        /// <term>Retrieves a ULONG value indicating whether the process is considered critical.</term>
        /// </item>
        /// <item>
        /// <term>ProcessSubsystemInformation <br/> 75</term>
        /// <term>
        /// Retrieves a SUBSYSTEM_INFORMATION_TYPE value indicating the subsystem type of the process. The buffer pointed to by the
        /// ProcessInformation parameter should be large enough to hold a single SUBSYSTEM_INFORMATION_TYPE enumeration.
        /// </term>
        /// </item>
        /// </list>
        /// </param>
        /// <returns>The structure and associated memory for any allocated sub-types.</returns>
        /// <exception cref="System.ArgumentException">Mismatch between requested type and class.</exception>
        public static NtQueryResult <T> NtQueryInformationProcess <T>([In] HPROCESS ProcessHandle, PROCESSINFOCLASS ProcessInformationClass) where T : struct
        {
            if (!CorrespondingTypeAttribute.CanGet(ProcessInformationClass, typeof(T)))
            {
                throw new ArgumentException("Mismatch between requested type and class.");
            }
            var mem    = new NtQueryResult <T>();
            var status = NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, mem, mem.Size, out var sz);

            if (status.Succeeded)
            {
                return(mem);
            }
            if (status != NTStatus.STATUS_INFO_LENGTH_MISMATCH || sz == 0)
            {
                throw status.GetException();
            }
            mem.Size = sz;
            NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, mem, mem.Size, out _).ThrowIfFailed();
            return(mem);
        }
Beispiel #4
0
        /// <summary>Gets the .NET runtime type which corresponds to the <see cref="VARTYPE"/>.</summary>
        /// <param name="vt">The <see cref="VARTYPE"/> enumeration value to evaluate.</param>
        /// <returns>
        /// <para>The corresponding .NET runtime type.</para>
        /// <para>
        /// If <paramref name="vt"/> specifies <see cref="VARTYPE.VT_VECTOR"/> or <see cref="VARTYPE.VT_ARRAY"/>, the return type is an
        /// array of the element type.
        /// </para>
        /// <para>
        /// If <paramref name="vt"/> specifies <see cref="VARTYPE.VT_BYREF"/> and the element type is a value type, the return type is a
        /// pointer to the element type.
        /// </para>
        /// </returns>
        public static Type GetCorrespondingType(this VARTYPE vt)
        {
            var elemVT = vt & ~(VARTYPE)0xF000;
            var specVT = vt & (VARTYPE)0xF000;
            var type   = CorrespondingTypeAttribute.GetCorrespondingTypes(elemVT).FirstOrDefault();

            if (type is null || elemVT == 0)
            {
                return(null);
            }
            // Change type if by reference
            if (specVT.IsFlagSet(VARTYPE.VT_BYREF) && type.IsValueType)
            {
                type = type.MakePointerType();
            }
            // Change type if vector
            if (specVT.IsFlagSet(VARTYPE.VT_VECTOR) || specVT.IsFlagSet(VARTYPE.VT_ARRAY))
            {
                type = type.MakeArrayType();
            }
            return(type);
        }
Beispiel #5
0
        /// <summary>
        /// <para>Retrieves information about the specified process.</para>
        /// </summary>
        /// <typeparam name="T">The type of the structure to retrieve.</typeparam>
        /// <param name="ProcessHandle">A handle to the process for which information is to be retrieved.</param>
        /// <param name="ProcessInformationClass">
        /// <para>
        /// The type of process information to be retrieved. This parameter can be one of the following values from the
        /// <c>PROCESSINFOCLASS</c> enumeration.
        /// </para>
        /// <list type="table">
        /// <listheader>
        /// <term>Value</term>
        /// <term>Meaning</term>
        /// </listheader>
        /// <item>
        /// <term>ProcessBasicInformation <br/> 0</term>
        /// <term>
        /// Retrieves a pointer to a PEB structure that can be used to determine whether the specified process is being debugged, and a
        /// unique value used by the system to identify the specified process. Use the CheckRemoteDebuggerPresent and GetProcessId functions
        /// to obtain this information.
        /// </term>
        /// </item>
        /// <item>
        /// <term>ProcessDebugPort <br/> 7</term>
        /// <term>
        /// Retrieves a DWORD_PTR value that is the port number of the debugger for the process. A nonzero value indicates that the process
        /// is being run under the control of a ring 3 debugger. Use the CheckRemoteDebuggerPresent or IsDebuggerPresent function.
        /// </term>
        /// </item>
        /// <item>
        /// <term>ProcessWow64Information <br/> 26</term>
        /// <term>
        /// Determines whether the process is running in the WOW64 environment (WOW64 is the x86 emulator that allows Win32-based
        /// applications to run on 64-bit Windows). Use the IsWow64Process2 function to obtain this information.
        /// </term>
        /// </item>
        /// <item>
        /// <term>ProcessImageFileName <br/> 27</term>
        /// <term>
        /// Retrieves a UNICODE_STRING value containing the name of the image file for the process. Use the QueryFullProcessImageName or
        /// GetProcessImageFileName function to obtain this information.
        /// </term>
        /// </item>
        /// <item>
        /// <term>ProcessBreakOnTermination <br/> 29</term>
        /// <term>Retrieves a ULONG value indicating whether the process is considered critical.</term>
        /// </item>
        /// <item>
        /// <term>ProcessSubsystemInformation <br/> 75</term>
        /// <term>
        /// Retrieves a SUBSYSTEM_INFORMATION_TYPE value indicating the subsystem type of the process. The buffer pointed to by the
        /// ProcessInformation parameter should be large enough to hold a single SUBSYSTEM_INFORMATION_TYPE enumeration.
        /// </term>
        /// </item>
        /// </list>
        /// </param>
        /// <returns>The structure and associated memory for any allocated sub-types.</returns>
        /// <exception cref="System.ArgumentException">Mismatch between requested type and class.</exception>
        public static NtQueryResult <T> NtQueryInformationProcess <T>([In] HPROCESS ProcessHandle, PROCESSINFOCLASS ProcessInformationClass) where T : struct
        {
            var validTypes = CorrespondingTypeAttribute.GetCorrespondingTypes(ProcessInformationClass, CorrespondingAction.Get).ToArray();

            if (validTypes.Length > 0 && Array.IndexOf(validTypes, typeof(T)) == -1)
            {
                throw new ArgumentException("Mismatch between requested type and class.");
            }
#if x64
            // Check if the target is a 32 bit process running in WoW64 mode.
            if (IsWow64(ProcessHandle))
            {
                // We are 64 bit. Target process is 32 bit running in WoW64 mode.
                throw new PlatformNotSupportedException("Unable to query a 32-bit process from a 64-bit process.");
            }
#else
            if (NtQueryInformationProcessRequiresWow64Structs(ProcessHandle))
            {
                if (validTypes.Length > 1 && !TypeIsWow())
                {
                    throw new ArgumentException("Type name must end in WOW64 to indicate it was configured exclusively for 64-bit use.");
                }
                var mem    = new NtQueryResult <T>();
                var status = NtWow64QueryInformationProcess64(ProcessHandle, ProcessInformationClass, ((IntPtr)mem).ToInt32(), mem.Size, out var sz);
                if (status.Succeeded)
                {
                    return(mem);
                }
                if (status != NTStatus.STATUS_INFO_LENGTH_MISMATCH || sz == 0)
                {
                    throw status.GetException();
                }
                mem.Size = sz;
                NtWow64QueryInformationProcess64(ProcessHandle, ProcessInformationClass, ((IntPtr)mem).ToInt32(), mem.Size, out _).ThrowIfFailed();
                return(mem);
            }
#endif
            // Target process is of the same bitness as us.
            else
            {
                if (validTypes.Length > 1 && TypeIsWow())
                {
                    throw new ArgumentException("Type name must not end in WOW64 should be configured for 32 or 64-bit use.");
                }
                var mem    = new NtQueryResult <T>();
                var status = NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, mem, mem.Size, out var sz);
                if (status.Succeeded)
                {
                    return(mem);
                }
                if (status != NTStatus.STATUS_INFO_LENGTH_MISMATCH || sz == 0)
                {
                    throw status.GetException();
                }
                mem.Size = sz;
                NtQueryInformationProcess(ProcessHandle, ProcessInformationClass, mem, mem.Size, out _).ThrowIfFailed();
                return(mem);
            }

            bool TypeIsWow() => typeof(T).Name.EndsWith("WOW64");
        }