Files
Josh Soref 74a1a6eca2 Upgrade to check-spelling v0.0.24 (#36235)
This upgrades to [v0.0.24](https://github.com/check-spelling/check-spelling/releases/tag/v0.0.24).

A number of GitHub APIs are being turned off shortly, so you need to upgrade or various uncertain outcomes will occur.

There's a new accessibility forbidden pattern:

> Do not use `(click) here` links
> For more information, see:
> * https://www.w3.org/QA/Tips/noClickHere
> * https://webaim.org/techniques/hypertext/link_text
> * https://granicus.com/blog/why-click-here-links-are-bad/
> * https://heyoka.medium.com/dont-use-click-here-f32f445d1021
```pl
(?i)(?:>|\[)(?:(?:click |)here|link|(?:read |)more)(?:</|\]\()
```

There are some minor bugs that I'm aware of and which I've fixed since this release, but I don't expect to make another release this month.

I've added a pair of patterns for includes and pragmas. My argument is that the **compiler** will _generally_ tell you if you've misspelled an include and the **linker** will _generally_ tell you if you misspell a lib.

- There's a caveat here: If your include case-insensitively matches the referenced file (but doesn't properly match it), then unless you either use a case-sensitive file system (as opposed to case-preserving) or beg clang to warn, you won't notice when you make this specific mistake -- this matters in that a couple of Windows headers (e.g. Unknwn.h) have particular case and repositories don't tend to consistently/properly write them.
2024-12-06 10:33:08 -06:00

245 lines
8.3 KiB
C#

// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Wox.Infrastructure;
using Wox.Plugin.Common.Win32;
namespace Microsoft.Plugin.WindowWalker.Components
{
/// <summary>
/// Represents the process data of an open window. This class is used in the process cache and for the process object of the open window
/// </summary>
internal class WindowProcess
{
/// <summary>
/// Maximum size of a file name
/// </summary>
private const int MaximumFileNameLength = 1000;
/// <summary>
/// An indicator if the window belongs to an 'Universal Windows Platform (UWP)' process
/// </summary>
private readonly bool _isUwpApp;
/// <summary>
/// Gets the id of the process
/// </summary>
internal uint ProcessID
{
get; private set;
}
/// <summary>
/// Gets a value indicating whether the process is responding or not
/// </summary>
internal bool IsResponding
{
get
{
try
{
return Process.GetProcessById((int)ProcessID).Responding;
}
catch (InvalidOperationException)
{
// Thrown when process not exist.
return true;
}
catch (NotSupportedException)
{
// Thrown when process is not running locally.
return true;
}
}
}
/// <summary>
/// Gets the id of the thread
/// </summary>
internal uint ThreadID
{
get; private set;
}
/// <summary>
/// Gets the name of the process
/// </summary>
internal string Name
{
get; private set;
}
/// <summary>
/// Gets a value indicating whether the window belongs to an 'Universal Windows Platform (UWP)' process
/// </summary>
internal bool IsUwpApp
{
get { return _isUwpApp; }
}
/// <summary>
/// Gets a value indicating whether this is the shell process or not
/// The shell process (like explorer.exe) hosts parts of the user interface (like taskbar, start menu, ...)
/// </summary>
internal bool IsShellProcess
{
get
{
IntPtr hShellWindow = NativeMethods.GetShellWindow();
return GetProcessIDFromWindowHandle(hShellWindow) == ProcessID;
}
}
/// <summary>
/// Gets a value indicating whether the process exists on the machine
/// </summary>
internal bool DoesExist
{
get
{
try
{
var p = Process.GetProcessById((int)ProcessID);
p.Dispose();
return true;
}
catch (InvalidOperationException)
{
// Thrown when process not exist.
return false;
}
catch (ArgumentException)
{
// Thrown when process not exist.
return false;
}
}
}
/// <summary>
/// Gets a value indicating whether full access to the process is denied or not
/// </summary>
internal bool IsFullAccessDenied
{
get; private set;
}
/// <summary>
/// Initializes a new instance of the <see cref="WindowProcess"/> class.
/// </summary>
/// <param name="pid">New process id.</param>
/// <param name="tid">New thread id.</param>
/// <param name="name">New process name.</param>
internal WindowProcess(uint pid, uint tid, string name)
{
UpdateProcessInfo(pid, tid, name);
_isUwpApp = string.Equals(Name, "ApplicationFrameHost.exe", StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Updates the process information of the <see cref="WindowProcess"/> instance.
/// </summary>
/// <param name="pid">New process id.</param>
/// <param name="tid">New thread id.</param>
/// <param name="name">New process name.</param>
internal void UpdateProcessInfo(uint pid, uint tid, string name)
{
// TODO: Add verification as to whether the process id and thread id is valid
ProcessID = pid;
ThreadID = tid;
Name = name;
// Process can be elevated only if process id is not 0 (Dummy value on error)
IsFullAccessDenied = (pid != 0) ? TestProcessAccessUsingAllAccessFlag(pid) : false;
}
/// <summary>
/// Gets the process ID for the window handle
/// </summary>
/// <param name="hwnd">The handle to the window</param>
/// <returns>The process ID</returns>
internal static uint GetProcessIDFromWindowHandle(IntPtr hwnd)
{
_ = NativeMethods.GetWindowThreadProcessId(hwnd, out uint processId);
return processId;
}
/// <summary>
/// Gets the thread ID for the window handle
/// </summary>
/// <param name="hwnd">The handle to the window</param>
/// <returns>The thread ID</returns>
internal static uint GetThreadIDFromWindowHandle(IntPtr hwnd)
{
uint threadId = NativeMethods.GetWindowThreadProcessId(hwnd, out _);
return threadId;
}
/// <summary>
/// Gets the process name for the process ID
/// </summary>
/// <param name="pid">The id of the process/param>
/// <returns>A string representing the process name or an empty string if the function fails</returns>
internal static string GetProcessNameFromProcessID(uint pid)
{
IntPtr processHandle = NativeMethods.OpenProcess(ProcessAccessFlags.QueryLimitedInformation, true, (int)pid);
StringBuilder processName = new StringBuilder(MaximumFileNameLength);
if (NativeMethods.GetProcessImageFileName(processHandle, processName, MaximumFileNameLength) != 0)
{
_ = Win32Helpers.CloseHandleIfNotNull(processHandle);
return processName.ToString().Split('\\').Reverse().ToArray()[0];
}
else
{
_ = Win32Helpers.CloseHandleIfNotNull(processHandle);
return string.Empty;
}
}
/// <summary>
/// Kills the process by its id. If permissions are required, they will be requested.
/// </summary>
/// <param name="killProcessTree">Kill process and sub processes.</param>
internal void KillThisProcess(bool killProcessTree)
{
if (IsFullAccessDenied)
{
string killTree = killProcessTree ? " /t" : string.Empty;
Helper.OpenInShell("taskkill.exe", $"/pid {(int)ProcessID} /f{killTree}", null, Helper.ShellRunAsType.Administrator, true);
}
else
{
Process.GetProcessById((int)ProcessID).Kill(killProcessTree);
}
}
/// <summary>
/// Gets a boolean value indicating whether the access to a process using the AllAccess flag is denied or not.
/// </summary>
/// <param name="pid">The process ID of the process</param>
/// <returns>True if denied and false if not.</returns>
private static bool TestProcessAccessUsingAllAccessFlag(uint pid)
{
IntPtr processHandle = NativeMethods.OpenProcess(ProcessAccessFlags.AllAccess, true, (int)pid);
if (Win32Helpers.GetLastError() == 5)
{
// Error 5 = ERROR_ACCESS_DENIED
_ = Win32Helpers.CloseHandleIfNotNull(processHandle);
return true;
}
else
{
_ = Win32Helpers.CloseHandleIfNotNull(processHandle);
return false;
}
}
}
}