terminal/src/cascadia/WindowsTerminal_UIATests/Common/NativeMethods.cs
Michael Niksa 7dadde5dd6
Implement PGO in pipelines for AMD64 architecture; supply training test scenarios (#10071)
Implement PGO in pipelines for AMD64 architecture; supply training test scenarios

## References
- #3075 - Relevant to speed interests there and other linked issues.

## PR Checklist
* [x] Closes #6963
* [x] I work here.
* [x] New UIA Tests added and passed. Manual build runs also tested.

## Detailed Description of the Pull Request / Additional comments
- Creates a new pipeline run for creating instrumented binaries for Profile Guided Optimization (PGO).
- Creates a new suite of UIA tests on the full Windows Terminal app to run PGO training scenarios on instrumented binaries (and incidentally can be used to write other UIA tests later for the full Terminal app.)
- Creates a new NuGet artifact to store trained PGO databases (PGD files) at `Microsoft.Internal.Windows.Terminal.PGODatabase`
- Creates a new NuGet artifact to supply large-scale test content for automated tests at `Microsoft.Internal.Windows.Terminal.TestContent`
- Adjusts the release pipeline to run binaries in PGO optimized mode where content from PGO databases is leveraged at link time to optimize the final release build

The following binaries are trained:
- OpenConsole.exe
- WindowsTerminal.exe
- TerminalApp.dll
- TerminalConnection.dll
- Microsoft.Terminal.Control.dll
- Microsoft.Terminal.Remoting.dll
- Microsoft.Terminal.Settings.Editor.dll
- Microsoft.Terminal.Settings.Model.dll

In the future, adding `<PgoTarget>true</PgoTarget>` to a new `vcxproj` file will automatically enroll the DLL/EXE for PGO instrumentation and optimization going forward.

Two training test scenarios are implemented:
- Smoke test the Terminal by just opening it and typing a bit of text then exiting. (Should help focus on the standard launch path.)
- Optimize bulk text output by launching terminal, outputting `big.txt`, then exiting.

Additional scenarios can be contributed to the `WindowsTerminal_UIATests` project with the `[TestProperty("IsPGO", "true")]` annotation to add them to the suite of scenarios for PGO.

**NOTE:** There are currently no weights applied to the various test scenarios. We will revisit that in the future when/if necessary.

## Validation Steps Performed
- [x] - Training run completed at https://dev.azure.com/ms/terminal/_build?definitionId=492&_a=summary
- [x] - Optimization run completed locally (by forcing `PGOBuildMode` to `Optimize` on my local machine, manually retrieving the databases with NuGet, and building).
- [x] - Validated locally that x86 and ARM64 do not get trained and automatically skip optimization as databases are not present for them.
- [x] - Smoke tested optimized binary versus latest releases. `big.txt` output through CMD is ~11-12seconds prior to PGO and just over 8 seconds with PGO.
2021-05-13 21:12:30 +00:00

862 lines
38 KiB
C#

//----------------------------------------------------------------------------------------------------------------------
// <copyright file="NativeMethods.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// <summary>Wrapper class for storing P/Invoke and COM Interop definitions.</summary>
//----------------------------------------------------------------------------------------------------------------------
namespace WindowsTerminal.UIA.Tests.Common.NativeMethods
{
using System;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32;
using WEX.TestExecution;
using WEX.Logging.Interop;
// Small extension method helpers to make C# feel closer to native.
public static class NativeExtensions
{
public static int LoWord(this int val)
{
return val & 0xffff;
}
public static int HiWord(this int val)
{
return (val >> 16) & 0xffff;
}
}
public static class NativeMethods
{
public static void Win32BoolHelper(bool result, string actionMessage)
{
if (!result)
{
string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error());
Log.Comment(errorMsg);
}
Verify.IsTrue(result, actionMessage);
}
public static void Win32NullHelper(IntPtr result, string actionMessage)
{
if (result == IntPtr.Zero)
{
string errorMsg = string.Format("Win32 error occurred: 0x{0:X}", Marshal.GetLastWin32Error());
Log.Comment(errorMsg);
}
Verify.IsNotNull(result, actionMessage);
}
}
public static class WinCon
{
[Flags()]
public enum CONSOLE_SELECTION_INFO_FLAGS : uint
{
CONSOLE_NO_SELECTION = 0x0,
CONSOLE_SELECTION_IN_PROGRESS = 0x1,
CONSOLE_SELECTION_NOT_EMPTY = 0x2,
CONSOLE_MOUSE_SELECTION = 0x4,
CONSOLE_MOUSE_DOWN = 0x8
}
public enum CONSOLE_STD_HANDLE : int
{
STD_INPUT_HANDLE = -10,
STD_OUTPUT_HANDLE = -11,
STD_ERROR_HANDLE = -12
}
public enum CONSOLE_ATTRIBUTES : ushort
{
FOREGROUND_BLUE = 0x1,
FOREGROUND_GREEN = 0x2,
FOREGROUND_RED = 0x4,
FOREGROUND_INTENSITY = 0x8,
FOREGROUND_YELLOW = FOREGROUND_RED | FOREGROUND_GREEN,
FOREGROUND_CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE,
FOREGROUND_MAGENTA = FOREGROUND_RED | FOREGROUND_BLUE,
FOREGROUND_COLORS = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN,
FOREGROUND_ALL = FOREGROUND_COLORS | FOREGROUND_INTENSITY,
BACKGROUND_BLUE = 0x10,
BACKGROUND_GREEN = 0x20,
BACKGROUND_RED = 0x40,
BACKGROUND_INTENSITY = 0x80,
BACKGROUND_YELLOW = BACKGROUND_RED | BACKGROUND_GREEN,
BACKGROUND_CYAN = BACKGROUND_GREEN | BACKGROUND_BLUE,
BACKGROUND_MAGENTA = BACKGROUND_RED | BACKGROUND_BLUE,
BACKGROUND_COLORS = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN,
BACKGROUND_ALL = BACKGROUND_COLORS | BACKGROUND_INTENSITY,
COMMON_LVB_LEADING_BYTE = 0x100,
COMMON_LVB_TRAILING_BYTE = 0x200,
COMMON_LVB_GRID_HORIZONTAL = 0x400,
COMMON_LVB_GRID_LVERTICAL = 0x800,
COMMON_LVB_GRID_RVERTICAL = 0x1000,
COMMON_LVB_REVERSE_VIDEO = 0x4000,
COMMON_LVB_UNDERSCORE = 0x8000
}
public enum CONSOLE_OUTPUT_MODES : uint
{
ENABLE_PROCESSED_OUTPUT = 0x1,
ENABLE_WRAP_AT_EOL_OUTPUT = 0x2,
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4
}
//CHAR_INFO struct, which was a union in the old days
// so we want to use LayoutKind.Explicit to mimic it as closely
// as we can
[StructLayout(LayoutKind.Explicit)]
public struct CHAR_INFO
{
[FieldOffset(0)]
internal char UnicodeChar;
[FieldOffset(0)]
internal char AsciiChar;
[FieldOffset(2)] //2 bytes seems to work properly
internal CONSOLE_ATTRIBUTES Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct COORD
{
public short X;
public short Y;
public override string ToString()
{
return string.Format("(X:{0} Y:{1})", X, Y);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SMALL_RECT
{
public short Left;
public short Top;
public short Right;
public short Bottom;
public short Width
{
get
{
// The API returns bottom/right as the inclusive lower-right
// corner, so we need +1 for the true width
return (short)(this.Right - this.Left + 1);
}
}
public short Height
{
get
{
// The API returns bottom/right as the inclusive lower-right
// corner, so we need +1 for the true height
return (short)(this.Bottom - this.Top + 1);
}
}
public override string ToString()
{
return string.Format("(L:{0} T:{1} R:{2} B:{3})", Left, Top, Right, Bottom);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct CONSOLE_CURSOR_INFO
{
public uint dwSize;
public bool bVisible;
}
[StructLayout(LayoutKind.Sequential)]
public struct CONSOLE_FONT_INFO
{
public int nFont;
public COORD dwFontSize;
}
[StructLayout(LayoutKind.Sequential)]
public struct CONSOLE_SELECTION_INFO
{
public CONSOLE_SELECTION_INFO_FLAGS Flags;
public COORD SelectionAnchor;
public SMALL_RECT Selection;
public override string ToString()
{
return string.Format("Flags:{0:X} Anchor:{1} Selection:{2}", Flags, SelectionAnchor, Selection);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct CONSOLE_SCREEN_BUFFER_INFO
{
public COORD dwSize;
public COORD dwCursorPosition;
public CONSOLE_ATTRIBUTES wAttributes;
public SMALL_RECT srWindow;
public COORD dwMaximumWindowSize;
}
[StructLayout(LayoutKind.Sequential)]
public struct CONSOLE_SCREEN_BUFFER_INFO_EX
{
public uint cbSize;
public COORD dwSize;
public COORD dwCursorPosition;
public CONSOLE_ATTRIBUTES wAttributes;
public SMALL_RECT srWindow;
public COORD dwMaximumWindowSize;
public CONSOLE_ATTRIBUTES wPopupAttributes;
public bool bFullscreenSupported;
internal COLORREF black;
internal COLORREF darkBlue;
internal COLORREF darkGreen;
internal COLORREF darkCyan;
internal COLORREF darkRed;
internal COLORREF darkMagenta;
internal COLORREF darkYellow;
internal COLORREF gray;
internal COLORREF darkGray;
internal COLORREF blue;
internal COLORREF green;
internal COLORREF cyan;
internal COLORREF red;
internal COLORREF magenta;
internal COLORREF yellow;
internal COLORREF white;
}
[StructLayout(LayoutKind.Sequential)]
public struct COLORREF
{
internal uint ColorDWORD;
public COLORREF(Color color)
{
ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16);
}
public COLORREF(uint r, uint g, uint b)
{
ColorDWORD = r + (g << 8) + (b << 16);
}
public Color GetColor()
{
return Color.FromArgb((int)(0x000000FFU & ColorDWORD),
(int)(0x0000FF00U & ColorDWORD) >> 8, (int)(0x00FF0000U & ColorDWORD) >> 16);
}
public void SetColor(Color color)
{
ColorDWORD = (uint)color.R + (((uint)color.G) << 8) + (((uint)color.B) << 16);
}
}
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(CONSOLE_STD_HANDLE nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool AttachConsole(UInt32 dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool FreeConsole();
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool SetConsoleTitle(string ConsoleTitle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleOutputHandle, out CONSOLE_OUTPUT_MODES lpMode);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern uint GetConsoleTitle(StringBuilder lpConsoleTitle, int nSize);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetConsoleWindow();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleSelectionInfo(out CONSOLE_SELECTION_INFO lpConsoleSelectionInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool bAbsolute, [In] ref SMALL_RECT lpConsoleWindow);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleCursorInfo(IntPtr hConsoleOutput, out CONSOLE_CURSOR_INFO lpConsoleCursorInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleScreenBufferInfoEx(IntPtr ConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX ConsoleScreenBufferInfoEx);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetCurrentConsoleFont(IntPtr hConsoleOutput, bool bMaximumWindow, out CONSOLE_FONT_INFO lpConsoleCurrentFont);
[DllImport("kernel32.dll", EntryPoint = "ReadConsoleOutputW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool ReadConsoleOutput(
IntPtr hConsoleOutput,
/* This pointer is treated as the origin of a two-dimensional array of CHAR_INFO structures
whose size is specified by the dwBufferSize parameter.*/
[MarshalAs(UnmanagedType.LPArray), Out] CHAR_INFO[,] lpBuffer,
COORD dwBufferSize,
COORD dwBufferCoord,
ref SMALL_RECT lpReadRegion);
[DllImport("kernel32.dll", EntryPoint = "WriteConsoleOutputCharacterW", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool WriteConsoleOutputCharacter(
IntPtr hConsoleOutput,
string lpCharacter,
UInt32 nLength,
COORD dwWriteCoord,
ref UInt32 lpNumberOfCharsWritten);
}
/// <summary>
/// The definitions within this file match the winconp.h file that is generated from wincon.w
/// Please see /windows/published/main/wincon.w
/// </summary>
public static class WinConP
{
private static readonly Guid PKEY_Console_FormatId = new Guid(0x0C570607, 0x0396, 0x43DE, new byte[] { 0x9D, 0x61, 0xE3, 0x21, 0xD7, 0xDF, 0x50, 0x26 });
public static readonly Wtypes.PROPERTYKEY PKEY_Console_ForceV2 = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 1 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_WrapText = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 2 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_FilterOnPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 3 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_CtrlKeysDisabled = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 4 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_LineSelection = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 5 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_WindowTransparency = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 6 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_TrimZeros = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 7 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorType = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 8 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_CursorColor = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 9 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_InterceptCopyPaste = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 10 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultForeground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 11 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_DefaultBackground = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 12 };
public static readonly Wtypes.PROPERTYKEY PKEY_Console_TerminalScrolling = new Wtypes.PROPERTYKEY() { fmtid = PKEY_Console_FormatId, pid = 13 };
public static readonly uint NT_CONSOLE_PROPS_SIG = 0xA0000002;
public static readonly uint NT_FE_CONSOLE_PROPS_SIG = 0xA0000004;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct NT_CONSOLE_PROPS
{
public Shell32.DATABLOCK_HEADER dbh;
public short wFillAttribute;
public short wPopupFillAttribute;
public WinCon.COORD dwScreenBufferSize;
public WinCon.COORD dwWindowSize;
public WinCon.COORD dwWindowOrigin;
public int nFont;
public int nInputBufferSize;
public WinCon.COORD dwFontSize;
public uint uFontFamily;
public uint uFontWeight;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string FaceName;
public uint uCursorSize;
public int bFullScreen;
public int bQuickEdit;
public int bInsertMode;
public int bAutoPosition;
public uint uHistoryBufferSize;
public uint uNumberOfHistoryBuffers;
public int bHistoryNoDup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public int[] ColorTable;
public uint CursorType;
public WinCon.COLORREF CursorColor;
public bool InterceptCopyPaste;
public WinCon.COLORREF DefaultForeground;
public WinCon.COLORREF DefaultBackground;
public bool TerminalScrolling;
}
[StructLayout(LayoutKind.Sequential)]
public struct NT_FE_CONSOLE_PROPS
{
Shell32.DATABLOCK_HEADER dbh;
uint uCodePage;
}
}
public static class User32
{
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897(v=vs.85).aspx
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public Int32 left;
public Int32 top;
public Int32 right;
public Int32 bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public Int32 x;
public Int32 y;
}
public const int WHEEL_DELTA = 120;
[DllImport("user32.dll")]
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
public const int GWL_STYLE = (-16);
public const int GWL_EXSTYLE = (-20);
[DllImport("user32.dll", SetLastError = true)]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
public static extern bool AdjustWindowRectEx(ref RECT lpRect, int dwStyle, bool bMenu, int dwExStyle);
[DllImport("user32.dll")]
public static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint);
public enum WindowMessages : UInt32
{
WM_KEYDOWN = 0x0100,
WM_KEYUP = 0x0101,
WM_CHAR = 0x0102,
WM_MOUSEWHEEL = 0x020A,
WM_MOUSEHWHEEL = 0x020E,
WM_USER = 0x0400,
CM_SET_KEY_STATE = WM_USER + 18
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, WindowMessages Msg, Int32 wParam, IntPtr lParam);
public enum SPI : uint
{
SPI_GETWHEELSCROLLLINES = 0x0068,
SPI_GETWHEELSCROLLCHARACTERS = 0x006C
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SystemParametersInfo(SPI uiAction, uint uiParam, ref uint pvParam, uint fWinIni);
public enum WinEventId : uint
{
EVENT_CONSOLE_CARET = 0x4001,
EVENT_CONSOLE_UPDATE_REGION = 0x4002,
EVENT_CONSOLE_UPDATE_SIMPLE = 0x4003,
EVENT_CONSOLE_UPDATE_SCROLL = 0x4004,
EVENT_CONSOLE_LAYOUT = 0x4005,
EVENT_CONSOLE_START_APPLICATION = 0x4006,
EVENT_CONSOLE_END_APPLICATION = 0x4007
}
[Flags]
public enum WinEventFlags : uint
{
WINEVENT_OUTOFCONTEXT = 0x0000, // Events are ASYNC
WINEVENT_SKIPOWNTHREAD = 0x0001, // Don't call back for events on installer's thread
WINEVENT_SKIPOWNPROCESS = 0x0002, // Don't call back for events on installer's process
WINEVENT_INCONTEXT = 0x0004, // Events are SYNC, this causes your dll to be injected into every process
}
public delegate void WinEventDelegate(IntPtr hWinEventHook, WinEventId eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWinEventHook(WinEventId eventMin, WinEventId eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, WinEventFlags dwFlags);
[DllImport("user32.dll")]
public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
public struct MSG
{
public IntPtr hwnd;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public POINT pt;
}
public enum PM : uint
{
PM_NOREMOVE = 0x0000,
PM_REMOVE = 0x0001,
PM_NOYIELD = 0x0002,
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax, PM wRemoveMsg);
[DllImport("user32.dll", SetLastError = true)]
public static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr DispatchMessage(ref MSG lpmsg);
}
public static class Shell32
{
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773249(v=vs.85).aspx
[StructLayout(LayoutKind.Sequential)]
public struct DATABLOCK_HEADER
{
public int cbSize;
public int dwSignature;
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774944(v=vs.85).aspx
// http://pinvoke.net/default.aspx/Enums/SLGP_FLAGS.html
/// <summary>IShellLink.GetPath fFlags: Flags that specify the type of path information to retrieve</summary>
[Flags()]
public enum SLGP_FLAGS
{
/// <summary>Retrieves the standard short (8.3 format) file name</summary>
SLGP_SHORTPATH = 0x1,
/// <summary>Retrieves the Universal Naming Convention (UNC) path name of the file</summary>
SLGP_UNCPRIORITY = 0x2,
/// <summary>Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded</summary>
SLGP_RAWPATH = 0x4
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774952(v=vs.85).aspx
// http://pinvoke.net/default.aspx/Enums/SLR_FLAGS.html
/// <summary>IShellLink.Resolve fFlags</summary>
[Flags()]
public enum SLR_FLAGS
{
/// <summary>
/// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set,
/// the high-order word of fFlags can be set to a time-out value that specifies the
/// maximum amount of time to be spent resolving the link. The function returns if the
/// link cannot be resolved within the time-out duration. If the high-order word is set
/// to zero, the time-out duration will be set to the default value of 3,000 milliseconds
/// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out
/// duration, in milliseconds.
/// </summary>
SLR_NO_UI = 0x1,
/// <summary>Obsolete and no longer used</summary>
SLR_ANY_MATCH = 0x2,
/// <summary>If the link object has changed, update its path and list of identifiers.
/// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine
/// whether or not the link object has changed.</summary>
SLR_UPDATE = 0x4,
/// <summary>Do not update the link information</summary>
SLR_NOUPDATE = 0x8,
/// <summary>Do not execute the search heuristics</summary>
SLR_NOSEARCH = 0x10,
/// <summary>Do not use distributed link tracking</summary>
SLR_NOTRACK = 0x20,
/// <summary>Disable distributed link tracking. By default, distributed link tracking tracks
/// removable media across multiple devices based on the volume name. It also uses the
/// Universal Naming Convention (UNC) path to track remote file systems whose drive letter
/// has changed. Setting SLR_NOLINKINFO disables both types of tracking.</summary>
SLR_NOLINKINFO = 0x40,
/// <summary>Call the Microsoft Windows Installer</summary>
SLR_INVOKE_MSI = 0x80
}
[ComImport, Guid("00021401-0000-0000-C000-000000000046")]
public class ShellLink
{
// Making new of this class will call CoCreate e.g. new ShellLink();
// Cast to one of the interfaces below will QueryInterface. e.g. (IPersistFile)new ShellLink();
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774950(v=vs.85).aspx
// http://pinvoke.net/default.aspx/Interfaces/IShellLinkW.html
/// <summary>The IShellLink interface allows Shell links to be created, modified, and resolved</summary>
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")]
public interface IShellLinkW
{
/// <summary>Retrieves the path and file name of a Shell link object</summary>
void GetPath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WinBase.WIN32_FIND_DATAW pfd, SLGP_FLAGS fFlags);
/// <summary>Retrieves the list of item identifiers for a Shell link object</summary>
void GetIDList(out IntPtr ppidl);
/// <summary>Sets the pointer to an item identifier list (PIDL) for a Shell link object.</summary>
void SetIDList(IntPtr pidl);
/// <summary>Retrieves the description string for a Shell link object</summary>
void GetDescription([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
/// <summary>Sets the description for a Shell link object. The description can be any application-defined string</summary>
void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
/// <summary>Retrieves the name of the working directory for a Shell link object</summary>
void GetWorkingDirectory([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
/// <summary>Sets the name of the working directory for a Shell link object</summary>
void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
/// <summary>Retrieves the command-line arguments associated with a Shell link object</summary>
void GetArguments([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
/// <summary>Sets the command-line arguments for a Shell link object</summary>
void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
/// <summary>Retrieves the hot key for a Shell link object</summary>
void GetHotkey(out short pwHotkey);
/// <summary>Sets a hot key for a Shell link object</summary>
void SetHotkey(short wHotkey);
/// <summary>Retrieves the show command for a Shell link object</summary>
void GetShowCmd(out int piShowCmd);
/// <summary>Sets the show command for a Shell link object. The show command sets the initial show state of the window.</summary>
void SetShowCmd(int iShowCmd);
/// <summary>Retrieves the location (path and index) of the icon for a Shell link object</summary>
void GetIconLocation([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
int cchIconPath, out int piIcon);
/// <summary>Sets the location (path and index) of the icon for a Shell link object</summary>
void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
/// <summary>Sets the relative path to the Shell link object</summary>
void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
/// <summary>Attempts to find the target of a Shell link, even if it has been moved or renamed</summary>
void Resolve(IntPtr hwnd, SLR_FLAGS fFlags);
/// <summary>Sets the path and file name of a Shell link object</summary>
void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb774916(v=vs.85).aspx
// http://pinvoke.net/default.aspx/Interfaces/IShellLonkDataList.html
[ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("45e2b4ae-b1c3-11d0-b92f-00a0c90312e1")]
public interface IShellLinkDataList
{
void AddDataBlock(IntPtr pDataBlock);
void CopyDataBlock(uint dwSig, out IntPtr ppDataBlock);
void RemoveDataBlock(uint dwSig);
void GetFlags(out uint pdwFlags);
void SetFlags(uint dwFlags);
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms688695(v=vs.85).aspx
// http://pinvoke.net/default.aspx/Interfaces/IPersist.html
[ComImport, Guid("0000010c-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersist
{
[PreserveSig]
void GetClassID(out Guid pClassID);
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms687223(v=vs.85).aspx
// http://www.pinvoke.net/default.aspx/Interfaces/IPersistFile.html
[ComImport, Guid("0000010b-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPersistFile : IPersist
{
new void GetClassID(out Guid pClassID);
[PreserveSig]
int IsDirty();
[PreserveSig]
void Load([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint dwMode);
[PreserveSig]
void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName,
[In, MarshalAs(UnmanagedType.Bool)] bool fRemember);
[PreserveSig]
void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName);
[PreserveSig]
void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName);
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb761474(v=vs.85).aspx
// http://www.pinvoke.net/default.aspx/Interfaces/IPropertyStore.html
[ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IPropertyStore
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetCount([Out] out uint cProps);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetAt([In] uint iProp, out Wtypes.PROPERTYKEY pkey);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetValue([In] ref Wtypes.PROPERTYKEY key, out object pv);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void SetValue([In] ref Wtypes.PROPERTYKEY key, [In] ref object pv);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void Commit();
}
}
public static class WinBase
{
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365740(v=vs.85).aspx
// http://www.pinvoke.net/default.aspx/Structures/WIN32_FIND_DATA.html
// The CharSet must match the CharSet of the corresponding PInvoke signature
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct WIN32_FIND_DATAW
{
public uint dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
public string cAlternateFileName;
}
public enum STARTF : Int32
{
STARTF_TITLEISLINKNAME = 0x00000800
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
{
public Int32 cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public Int32 dwX;
public Int32 dwY;
public Int32 dwXSize;
public Int32 dwYSize;
public Int32 dwXCountChars;
public Int32 dwYCountChars;
public Int32 dwFillAttribute;
public STARTF dwFlags;
public Int16 wShowWindow;
public Int16 cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFOEX
{
public STARTUPINFO StartupInfo;
public IntPtr lpAttributeList;
}
[Flags]
public enum CP_CreationFlags : uint
{
CREATE_SUSPENDED = 0x4,
CREATE_NEW_CONSOLE = 0x10,
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CreateProcess(string lpApplicationName,
string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
CP_CreationFlags dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, IntPtr lpName);
[DllImport("kernel32.dll")]
public static extern bool TerminateJobObject(IntPtr hJob, uint uExitCode);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int ResumeThread(IntPtr hThread);
public enum JOBOBJECTINFOCLASS : uint
{
JobObjectBasicProcessIdList = 3
}
[StructLayout(LayoutKind.Sequential)]
public struct JOBOBJECT_BASIC_PROCESS_ID_LIST
{
public uint NumberOfAssignedProcesses;
public uint NumberOfProcessIdsInList;
public IntPtr ProcessId;
public IntPtr ProcessId2;
}
[DllImport("kernel32.dll")]
public static extern bool QueryInformationJobObject(IntPtr hJob,
JOBOBJECTINFOCLASS JobObjectInformationClass,
IntPtr lpJobObjectInfo,
int cbJobObjectInfoLength,
IntPtr lpReturnLength);
}
public static class Wtypes
{
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb773381(v=vs.85).aspx
// http://pinvoke.net/default.aspx/Structures/PROPERTYKEY.html
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct PROPERTYKEY
{
public Guid fmtid;
public uint pid;
}
}
public static class ObjBase
{
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa380337(v=vs.85).aspx
// http://www.pinvoke.net/default.aspx/Enums/StgmConstants.html
[Flags]
public enum STGM
{
STGM_READ = 0x0,
STGM_WRITE = 0x1,
STGM_READWRITE = 0x2,
STGM_SHARE_DENY_NONE = 0x40,
STGM_SHARE_DENY_READ = 0x30,
STGM_SHARE_DENY_WRITE = 0x20,
STGM_SHARE_EXCLUSIVE = 0x10,
STGM_PRIORITY = 0x40000,
STGM_CREATE = 0x1000,
STGM_CONVERT = 0x20000,
STGM_FAILIFTHERE = 0x0,
STGM_DIRECT = 0x0,
STGM_TRANSACTED = 0x10000,
STGM_NOSCRATCH = 0x100000,
STGM_NOSNAPSHOT = 0x200000,
STGM_SIMPLE = 0x8000000,
STGM_DIRECT_SWMR = 0x400000,
STGM_DELETEONRELEASE = 0x4000000
}
}
}