Skip to content

Commit

Permalink
Icons are now shown for admin processes as well #11
Browse files Browse the repository at this point in the history
  • Loading branch information
kvakulo committed Apr 18, 2014
1 parent 085d4f5 commit fcd09be
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 3 deletions.
45 changes: 42 additions & 3 deletions Switcheroo/AppWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.Caching;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Media.Imaging;
using ManagedWinapi.Windows;

Expand Down Expand Up @@ -90,13 +93,16 @@ private BitmapImage ExtractIcon()
Icon extractAssociatedIcon = null;
try
{
extractAssociatedIcon = Icon.ExtractAssociatedIcon(Process.MainModule.FileName);
extractAssociatedIcon = Icon.ExtractAssociatedIcon(GetExecutablePath(Process));
}
catch (Win32Exception)
{
// no access to process
// Could not extract icon
}
if (extractAssociatedIcon == null)
{
return null;
}
if (extractAssociatedIcon == null) return null;

using (var memory = new MemoryStream())
{
Expand All @@ -112,6 +118,39 @@ private BitmapImage ExtractIcon()
}
}

private static string GetExecutablePath(Process process)
{
// If Vista or later
if (Environment.OSVersion.Version.Major >= 6)
{
return GetExecutablePathAboveVista(process.Id);
}

return process.MainModule.FileName;
}

private static string GetExecutablePathAboveVista(int processId)
{
var buffer = new StringBuilder(1024);
var hprocess = WinApi.OpenProcess(WinApi.ProcessAccess.QueryLimitedInformation, false, processId);
if (hprocess == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error());

try
{
// ReSharper disable once RedundantAssignment
var size = buffer.Capacity;
if (WinApi.QueryFullProcessImageName(hprocess, 0, buffer, out size))
{
return buffer.ToString();
}
}
finally
{
WinApi.CloseHandle(hprocess);
}
throw new Win32Exception(Marshal.GetLastWin32Error());
}

public AppWindow(IntPtr HWnd) : base(HWnd) { }

/// <summary>
Expand Down
108 changes: 108 additions & 0 deletions Switcheroo/winapi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,113 @@ public enum GetAncestorFlags

[DllImport("user32.dll")]
public static extern IntPtr GetLastActivePopup(IntPtr hWnd);

[Flags]
public enum ProcessAccess
{
/// <summary>
/// Required to create a thread.
/// </summary>
CreateThread = 0x0002,

/// <summary>
///
/// </summary>
SetSessionId = 0x0004,

/// <summary>
/// Required to perform an operation on the address space of a process
/// </summary>
VmOperation = 0x0008,

/// <summary>
/// Required to read memory in a process using ReadProcessMemory.
/// </summary>
VmRead = 0x0010,

/// <summary>
/// Required to write to memory in a process using WriteProcessMemory.
/// </summary>
VmWrite = 0x0020,

/// <summary>
/// Required to duplicate a handle using DuplicateHandle.
/// </summary>
DupHandle = 0x0040,

/// <summary>
/// Required to create a process.
/// </summary>
CreateProcess = 0x0080,

/// <summary>
/// Required to set memory limits using SetProcessWorkingSetSize.
/// </summary>
SetQuota = 0x0100,

/// <summary>
/// Required to set certain information about a process, such as its priority class (see SetPriorityClass).
/// </summary>
SetInformation = 0x0200,

/// <summary>
/// Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken).
/// </summary>
QueryInformation = 0x0400,

/// <summary>
/// Required to suspend or resume a process.
/// </summary>
SuspendResume = 0x0800,

/// <summary>
/// Required to retrieve certain information about a process (see GetExitCodeProcess, GetPriorityClass, IsProcessInJob, QueryFullProcessImageName).
/// A handle that has the PROCESS_QUERY_INFORMATION access right is automatically granted PROCESS_QUERY_LIMITED_INFORMATION.
/// </summary>
QueryLimitedInformation = 0x1000,

/// <summary>
/// Required to wait for the process to terminate using the wait functions.
/// </summary>
Synchronize = 0x100000,

/// <summary>
/// Required to delete the object.
/// </summary>
Delete = 0x00010000,

/// <summary>
/// Required to read information in the security descriptor for the object, not including the information in the SACL.
/// To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information, see SACL Access Right.
/// </summary>
ReadControl = 0x00020000,

/// <summary>
/// Required to modify the DACL in the security descriptor for the object.
/// </summary>
WriteDac = 0x00040000,

/// <summary>
/// Required to change the owner in the security descriptor for the object.
/// </summary>
WriteOwner = 0x00080000,

StandardRightsRequired = 0x000F0000,

/// <summary>
/// All possible access rights for a process object.
/// </summary>
AllAccess = StandardRightsRequired | Synchronize | 0xFFFF
}


[DllImport("kernel32.dll")]
public static extern bool QueryFullProcessImageName(IntPtr hprocess, int dwFlags, StringBuilder lpExeName, out int size);

[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(ProcessAccess dwDesiredAccess, bool bInheritHandle, int dwProcessId);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hHandle);
}
}

0 comments on commit fcd09be

Please sign in to comment.