diff options
author | zturner@chromium.org <zturner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-18 20:26:52 +0000 |
---|---|---|
committer | zturner@chromium.org <zturner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-18 20:26:52 +0000 |
commit | 81cc64b423512b123de7412179ed1d256e0443be (patch) | |
tree | cee5bcb2f238d863652f2984c75e7cd7b1003114 /tools/win | |
parent | 0e9cdd55c8fd221ab6fb38b295aea3c2273bb485 (diff) | |
download | chromium_src-81cc64b423512b123de7412179ed1d256e0443be.zip chromium_src-81cc64b423512b123de7412179ed1d256e0443be.tar.gz chromium_src-81cc64b423512b123de7412179ed1d256e0443be.tar.bz2 |
Resubmit of ChromeDebug extension with fixed license headers.
BUG=0
notry=TRUE
Review URL: https://chromiumcodereview.appspot.com/23526064
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223930 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/win')
25 files changed, 2252 insertions, 0 deletions
diff --git a/tools/win/ChromeDebug/.gitignore b/tools/win/ChromeDebug/.gitignore new file mode 100644 index 0000000..58eea67 --- /dev/null +++ b/tools/win/ChromeDebug/.gitignore @@ -0,0 +1,5 @@ +!*.sln +ChromeDebug/obj/* +ChromeDebug/bin/* +LowLevel/obj/* +LowLevel/bin/* diff --git a/tools/win/ChromeDebug/ChromeDebug.sln b/tools/win/ChromeDebug/ChromeDebug.sln new file mode 100644 index 0000000..ade84fd --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChromeDebug", "ChromeDebug\ChromeDebug.csproj", "{4CC60BED-569D-481A-B56B-6ECBC23CBC16}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LowLevel", "LowLevel\LowLevel.csproj", "{998C0725-F123-4ED3-9D44-12C1945F00D1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4CC60BED-569D-481A-B56B-6ECBC23CBC16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CC60BED-569D-481A-B56B-6ECBC23CBC16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CC60BED-569D-481A-B56B-6ECBC23CBC16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CC60BED-569D-481A-B56B-6ECBC23CBC16}.Release|Any CPU.Build.0 = Release|Any CPU + {998C0725-F123-4ED3-9D44-12C1945F00D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {998C0725-F123-4ED3-9D44-12C1945F00D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {998C0725-F123-4ED3-9D44-12C1945F00D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {998C0725-F123-4ED3-9D44-12C1945F00D1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tools/win/ChromeDebug/ChromeDebug/AttachDialog.Designer.cs b/tools/win/ChromeDebug/ChromeDebug/AttachDialog.Designer.cs new file mode 100644 index 0000000..392a7142 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/AttachDialog.Designer.cs @@ -0,0 +1,207 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +namespace ChromeDebug +{ + partial class AttachDialog + { + /// <summary> + /// Required designer variable. + /// </summary> + private System.ComponentModel.IContainer components = null; + + /// <summary> + /// Clean up any resources being used. + /// </summary> + /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// <summary> + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// </summary> + private void InitializeComponent() + { + this.listViewProcesses = new System.Windows.Forms.ListView(); + this.columnHeaderDummy = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeaderProcess = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeaderPid = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeaderTitle = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeaderType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeaderSession = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeaderCmdLine = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.buttonAttach = new System.Windows.Forms.Button(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.buttonRefresh = new System.Windows.Forms.Button(); + this.checkBoxOnlyChrome = new System.Windows.Forms.CheckBox(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // listViewProcesses + // + this.listViewProcesses.AllowColumnReorder = true; + this.listViewProcesses.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.listViewProcesses.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeaderDummy, + this.columnHeaderProcess, + this.columnHeaderPid, + this.columnHeaderTitle, + this.columnHeaderType, + this.columnHeaderSession, + this.columnHeaderCmdLine}); + this.listViewProcesses.FullRowSelect = true; + this.listViewProcesses.Location = new System.Drawing.Point(14, 27); + this.listViewProcesses.Name = "listViewProcesses"; + this.listViewProcesses.Size = new System.Drawing.Size(884, 462); + this.listViewProcesses.TabIndex = 0; + this.listViewProcesses.UseCompatibleStateImageBehavior = false; + this.listViewProcesses.View = System.Windows.Forms.View.Details; + // + // columnHeaderDummy + // + this.columnHeaderDummy.Width = 0; + // + // columnHeaderProcess + // + this.columnHeaderProcess.Text = "Executable"; + this.columnHeaderProcess.Width = 65; + // + // columnHeaderPid + // + this.columnHeaderPid.Text = "PID"; + this.columnHeaderPid.Width = 30; + // + // columnHeaderTitle + // + this.columnHeaderTitle.Text = "Title"; + this.columnHeaderTitle.Width = 32; + // + // columnHeaderType + // + this.columnHeaderType.Text = "Type"; + this.columnHeaderType.Width = 36; + // + // columnHeaderSession + // + this.columnHeaderSession.Text = "Session"; + this.columnHeaderSession.Width = 49; + // + // columnHeaderCmdLine + // + this.columnHeaderCmdLine.Text = "Command Line"; + this.columnHeaderCmdLine.Width = 668; + // + // buttonAttach + // + this.buttonAttach.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonAttach.DialogResult = System.Windows.Forms.DialogResult.OK; + this.buttonAttach.Location = new System.Drawing.Point(684, 603); + this.buttonAttach.Name = "buttonAttach"; + this.buttonAttach.Size = new System.Drawing.Size(118, 41); + this.buttonAttach.TabIndex = 2; + this.buttonAttach.Text = "Attach"; + this.buttonAttach.UseVisualStyleBackColor = true; + this.buttonAttach.Click += new System.EventHandler(this.buttonAttach_Click); + // + // buttonCancel + // + this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.buttonCancel.Location = new System.Drawing.Point(808, 603); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(118, 41); + this.buttonCancel.TabIndex = 3; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = true; + // + // groupBox1 + // + this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox1.Controls.Add(this.listViewProcesses); + this.groupBox1.Location = new System.Drawing.Point(12, 27); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(914, 511); + this.groupBox1.TabIndex = 5; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Available Processes"; + // + // buttonRefresh + // + this.buttonRefresh.Location = new System.Drawing.Point(808, 552); + this.buttonRefresh.Name = "buttonRefresh"; + this.buttonRefresh.Size = new System.Drawing.Size(117, 33); + this.buttonRefresh.TabIndex = 6; + this.buttonRefresh.Text = "Refresh"; + this.buttonRefresh.UseVisualStyleBackColor = true; + this.buttonRefresh.Click += new System.EventHandler(this.buttonRefresh_Click); + // + // checkBoxOnlyChrome + // + this.checkBoxOnlyChrome.AutoSize = true; + this.checkBoxOnlyChrome.Checked = true; + this.checkBoxOnlyChrome.CheckState = System.Windows.Forms.CheckState.Checked; + this.checkBoxOnlyChrome.Location = new System.Drawing.Point(12, 561); + this.checkBoxOnlyChrome.Name = "checkBoxOnlyChrome"; + this.checkBoxOnlyChrome.Size = new System.Drawing.Size(165, 17); + this.checkBoxOnlyChrome.TabIndex = 7; + this.checkBoxOnlyChrome.Text = "Only show Chrome processes"; + this.checkBoxOnlyChrome.UseVisualStyleBackColor = true; + this.checkBoxOnlyChrome.CheckedChanged += new System.EventHandler(this.checkBoxOnlyChrome_CheckedChanged); + // + // AttachDialog + // + this.AcceptButton = this.buttonAttach; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.buttonCancel; + this.ClientSize = new System.Drawing.Size(940, 656); + this.ControlBox = false; + this.Controls.Add(this.checkBoxOnlyChrome); + this.Controls.Add(this.buttonRefresh); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.buttonAttach); + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "AttachDialog"; + this.ShowInTaskbar = false; + this.Text = "Attach to Chrome"; + this.Load += new System.EventHandler(this.AttachDialog_Load); + this.groupBox1.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ListView listViewProcesses; + private System.Windows.Forms.Button buttonAttach; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.ColumnHeader columnHeaderProcess; + private System.Windows.Forms.ColumnHeader columnHeaderPid; + private System.Windows.Forms.ColumnHeader columnHeaderTitle; + private System.Windows.Forms.ColumnHeader columnHeaderCmdLine; + private System.Windows.Forms.ColumnHeader columnHeaderDummy; + private System.Windows.Forms.ColumnHeader columnHeaderType; + private System.Windows.Forms.ColumnHeader columnHeaderSession; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button buttonRefresh; + private System.Windows.Forms.CheckBox checkBoxOnlyChrome; + } +}
\ No newline at end of file diff --git a/tools/win/ChromeDebug/ChromeDebug/AttachDialog.cs b/tools/win/ChromeDebug/ChromeDebug/AttachDialog.cs new file mode 100644 index 0000000..a6505d3 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/AttachDialog.cs @@ -0,0 +1,254 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Management; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +using ChromeDebug.LowLevel; + +namespace ChromeDebug { + // The form that is displayed to allow the user to select processes to attach to. Note that we + // cannot interact with the DTE object from here (I assume this is because the dialog is running + // on a different thread, although I don't fully understand), so any access to the DTE object + // will have to be done through events that get posted back to the main package thread. + public partial class AttachDialog : Form { + private class ProcessViewItem : ListViewItem { + public ProcessViewItem() { + Category = ProcessCategory.Other; + MachineType = LowLevelTypes.MachineType.UNKNOWN; + } + + public string Exe; + public int ProcessId; + public int SessionId; + public string Title; + public string DisplayCmdLine; + public string[] CmdLineArgs; + public ProcessCategory Category; + public LowLevelTypes.MachineType MachineType; + + public ProcessDetail Detail; + } + + private Dictionary<ProcessCategory, List<ProcessViewItem>> loadedProcessTable = null; + private Dictionary<ProcessCategory, ListViewGroup> processGroups = null; + private List<int> selectedProcesses = null; + + public AttachDialog() { + InitializeComponent(); + + loadedProcessTable = new Dictionary<ProcessCategory, List<ProcessViewItem>>(); + processGroups = new Dictionary<ProcessCategory, ListViewGroup>(); + selectedProcesses = new List<int>(); + + // Create and initialize the groups and process lists only once. On a reset + // we don't clear the groups manually, clearing the list view should clear the + // groups. And we don't clear the entire processes_ dictionary, only the + // individual buckets inside the dictionary. + foreach (object value in Enum.GetValues(typeof(ProcessCategory))) { + ProcessCategory category = (ProcessCategory)value; + + ListViewGroup group = new ListViewGroup(category.ToGroupTitle()); + processGroups[category] = group; + listViewProcesses.Groups.Add(group); + + loadedProcessTable[category] = new List<ProcessViewItem>(); + } + } + + // Provides an iterator that evaluates to the process ids of the entries that are selected + // in the list view. + public IEnumerable<int> SelectedItems { + get { + foreach (ProcessViewItem item in listViewProcesses.SelectedItems) + yield return item.ProcessId; + } + } + + private void AttachDialog_Load(object sender, EventArgs e) { + RepopulateListView(); + } + + // Remove command line arguments that we aren't interested in displaying as part of the command + // line of the process. + private string[] FilterCommandLine(string[] args) { + Func<string, int, bool> AllowArgument = delegate(string arg, int index) { + if (index == 0) + return false; + return !arg.StartsWith("--force-fieldtrials", StringComparison.CurrentCultureIgnoreCase); + }; + + // The force-fieldtrials command line option makes the command line view useless, so remove + // it. Also remove args[0] since that is the process name. + args = args.Where(AllowArgument).ToArray(); + return args; + } + + private void ReloadNativeProcessInfo() { + foreach (List<ProcessViewItem> list in loadedProcessTable.Values) { + list.Clear(); + } + + Process[] processes = Process.GetProcesses(); + foreach (Process p in processes) { + ProcessViewItem item = new ProcessViewItem(); + try { + item.Detail = new ProcessDetail(p.Id); + if (item.Detail.CanReadPeb && item.Detail.CommandLine != null) { + item.CmdLineArgs = Utility.SplitArgs(item.Detail.CommandLine); + item.DisplayCmdLine = GetFilteredCommandLineString(item.CmdLineArgs); + } + item.MachineType = item.Detail.MachineType; + } + catch (Exception) { + // Generally speaking, an exception here means the process is privileged and we cannot + // get any information about the process. For those processes, we will just display the + // information that the Framework gave us in the Process structure. + } + + // If we don't have the machine type, its privilege level is high enough that we won't be + // able to attach a debugger to it anyway, so skip it. + if (item.MachineType == LowLevelTypes.MachineType.UNKNOWN) + continue; + + item.ProcessId = p.Id; + item.SessionId = p.SessionId; + item.Title = p.MainWindowTitle; + item.Exe = p.ProcessName; + if (item.CmdLineArgs != null) + item.Category = DetermineProcessCategory(item.CmdLineArgs); + + List<ProcessViewItem> items = loadedProcessTable[item.Category]; + item.Group = processGroups[item.Category]; + items.Add(item); + } + } + + // Filter the command line arguments to remove extraneous arguments that we don't wish to + // display. + private string GetFilteredCommandLineString(string[] args) { + if (args == null || args.Length == 0) + return string.Empty; + + args = FilterCommandLine(args); + return string.Join(" ", args, 0, args.Length); + } + + // Using a heuristic based on the command line, tries to determine what type of process this + // is. + private ProcessCategory DetermineProcessCategory(string[] cmdline) { + if (cmdline == null || cmdline.Length == 0) + return ProcessCategory.Other; + + string file = Path.GetFileName(cmdline[0]); + if (file.Equals("delegate_execute.exe", StringComparison.CurrentCultureIgnoreCase)) + return ProcessCategory.DelegateExecute; + else if (file.Equals("chrome.exe", StringComparison.CurrentCultureIgnoreCase)) { + if (cmdline.Contains("--type=renderer")) + return ProcessCategory.Renderer; + else if (cmdline.Contains("--type=plugin") || cmdline.Contains("--type=ppapi")) + return ProcessCategory.Plugin; + else if (cmdline.Contains("--type=gpu-process")) + return ProcessCategory.Gpu; + else if (cmdline.Contains("--type=service")) + return ProcessCategory.Service; + else if (cmdline.Any(arg => arg.StartsWith("-ServerName"))) + return ProcessCategory.MetroViewer; + else + return ProcessCategory.Browser; + } else + return ProcessCategory.Other; + } + + private void InsertCategoryItems(ProcessCategory category) { + foreach (ProcessViewItem item in loadedProcessTable[category]) { + item.SubItems.Add(item.Exe); + item.SubItems.Add(item.ProcessId.ToString()); + item.SubItems.Add(item.Title); + item.SubItems.Add(item.MachineType.ToString()); + item.SubItems.Add(item.SessionId.ToString()); + item.SubItems.Add(item.DisplayCmdLine); + listViewProcesses.Items.Add(item); + } + } + + private void AutoResizeColumns() { + // First adjust to the width of the headers, since it's fast. + listViewProcesses.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); + + // Save the widths so we can use them again later. + List<int> widths = new List<int>(); + foreach (ColumnHeader header in listViewProcesses.Columns) + widths.Add(header.Width); + + // Now let Windows do the slow adjustment based on the content. + listViewProcesses.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent); + + // Finally, iterate over each column, and resize those columns that just got smaller. + listViewProcesses.Columns[0].Width = 0; + int total = 0; + for (int i = 1; i < listViewProcesses.Columns.Count; ++i) { + // Resize to the largest of the two, but don't let it go over a pre-defined maximum. + int max = Math.Max(listViewProcesses.Columns[i].Width, widths[i]); + int capped = Math.Min(max, 300); + + // We do still want to fill up the available space in the list view however, so if we're + // under then we can fill. + int globalMinWidth = listViewProcesses.Width - SystemInformation.VerticalScrollBarWidth; + if (i == listViewProcesses.Columns.Count - 1 && (total + capped) < (globalMinWidth - 4)) + capped = globalMinWidth - total - 4; + + total += capped; + listViewProcesses.Columns[i].Width = capped; + } + } + + private void RepopulateListView() { + listViewProcesses.Items.Clear(); + + ReloadNativeProcessInfo(); + + InsertCategoryItems(ProcessCategory.Browser); + InsertCategoryItems(ProcessCategory.Renderer); + InsertCategoryItems(ProcessCategory.Gpu); + InsertCategoryItems(ProcessCategory.Plugin); + InsertCategoryItems(ProcessCategory.MetroViewer); + InsertCategoryItems(ProcessCategory.Service); + InsertCategoryItems(ProcessCategory.DelegateExecute); + if (!checkBoxOnlyChrome.Checked) + InsertCategoryItems(ProcessCategory.Other); + + AutoResizeColumns(); + } + + private void buttonRefresh_Click(object sender, EventArgs e) { + RepopulateListView(); + } + + private void buttonAttach_Click(object sender, EventArgs e) { + System.Diagnostics.Debug.WriteLine("Closing dialog."); + this.Close(); + } + + private void checkBoxOnlyChrome_CheckedChanged(object sender, EventArgs e) { + if (!checkBoxOnlyChrome.Checked) + InsertCategoryItems(ProcessCategory.Other); + else { + foreach (ProcessViewItem item in loadedProcessTable[ProcessCategory.Other]) { + listViewProcesses.Items.Remove(item); + } + } + } + } +} diff --git a/tools/win/ChromeDebug/ChromeDebug/AttachDialog.resx b/tools/win/ChromeDebug/ChromeDebug/AttachDialog.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/AttachDialog.resx @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root>
\ No newline at end of file diff --git a/tools/win/ChromeDebug/ChromeDebug/ChromeDebug.csproj b/tools/win/ChromeDebug/ChromeDebug/ChromeDebug.csproj new file mode 100644 index 0000000..97bd38d --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/ChromeDebug.csproj @@ -0,0 +1,211 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0"> + <PropertyGroup> + <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion> + <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion> + <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> + <FileUpgradeFlags> + </FileUpgradeFlags> + <UpgradeBackupLocation> + </UpgradeBackupLocation> + <OldToolsVersion>4.0</OldToolsVersion> + </PropertyGroup> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{4CC60BED-569D-481A-B56B-6ECBC23CBC16}</ProjectGuid> + <ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>ChromeDebug</RootNamespace> + <AssemblyName>ChromeDebug</AssemblyName> + <SignAssembly>True</SignAssembly> + <AssemblyOriginatorKeyFile> + </AssemblyOriginatorKeyFile> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <RunCodeAnalysis>true</RunCodeAnalysis> + </PropertyGroup> + <ItemGroup> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="Microsoft.VisualStudio.OLE.Interop" /> + <Reference Include="Microsoft.VisualStudio.Shell.Interop" /> + <Reference Include="Microsoft.VisualStudio.Shell.Interop.8.0" /> + <Reference Include="Microsoft.VisualStudio.Shell.Interop.9.0" /> + <Reference Include="Microsoft.VisualStudio.Shell.Interop.10.0" /> + <Reference Include="Microsoft.VisualStudio.Shell.Interop.11.0"> + <EmbedInteropTypes>true</EmbedInteropTypes> + </Reference> + <Reference Include="Microsoft.VisualStudio.TextManager.Interop" /> + <Reference Include="Microsoft.VisualStudio.Shell.11.0" /> + <Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0" /> + <Reference Include="Microsoft.VisualStudio.Shell.Immutable.11.0" /> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Data" /> + <Reference Include="System.Design" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Management" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <COMReference Include="EnvDTE"> + <Guid>{80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2}</Guid> + <VersionMajor>8</VersionMajor> + <VersionMinor>0</VersionMinor> + <Lcid>0</Lcid> + <WrapperTool>primary</WrapperTool> + <Isolated>False</Isolated> + <EmbedInteropTypes>False</EmbedInteropTypes> + </COMReference> + <COMReference Include="EnvDTE100"> + <Guid>{26AD1324-4B7C-44BC-84F8-B86AED45729F}</Guid> + <VersionMajor>10</VersionMajor> + <VersionMinor>0</VersionMinor> + <Lcid>0</Lcid> + <WrapperTool>primary</WrapperTool> + <Isolated>False</Isolated> + <EmbedInteropTypes>False</EmbedInteropTypes> + </COMReference> + <COMReference Include="EnvDTE80"> + <Guid>{1A31287A-4D7D-413E-8E32-3B374931BD89}</Guid> + <VersionMajor>8</VersionMajor> + <VersionMinor>0</VersionMinor> + <Lcid>0</Lcid> + <WrapperTool>primary</WrapperTool> + <Isolated>False</Isolated> + <EmbedInteropTypes>False</EmbedInteropTypes> + </COMReference> + <COMReference Include="EnvDTE90"> + <Guid>{2CE2370E-D744-4936-A090-3FFFE667B0E1}</Guid> + <VersionMajor>9</VersionMajor> + <VersionMinor>0</VersionMinor> + <Lcid>0</Lcid> + <WrapperTool>primary</WrapperTool> + <Isolated>False</Isolated> + <EmbedInteropTypes>False</EmbedInteropTypes> + </COMReference> + <COMReference Include="EnvDTE90a1"> + <Guid>{64A96FE8-CCCF-4EDF-B341-FF7C528B60C9}</Guid> + <VersionMajor>9</VersionMajor> + <VersionMinor>0</VersionMinor> + <Lcid>0</Lcid> + <WrapperTool>primary</WrapperTool> + <Isolated>False</Isolated> + <EmbedInteropTypes>False</EmbedInteropTypes> + </COMReference> + <COMReference Include="Microsoft.VisualStudio.CommandBars"> + <Guid>{1CBA492E-7263-47BB-87FE-639000619B15}</Guid> + <VersionMajor>8</VersionMajor> + <VersionMinor>0</VersionMinor> + <Lcid>0</Lcid> + <WrapperTool>primary</WrapperTool> + <Isolated>False</Isolated> + <EmbedInteropTypes>False</EmbedInteropTypes> + </COMReference> + <COMReference Include="stdole"> + <Guid>{00020430-0000-0000-C000-000000000046}</Guid> + <VersionMajor>2</VersionMajor> + <VersionMinor>0</VersionMinor> + <Lcid>0</Lcid> + <WrapperTool>primary</WrapperTool> + <Isolated>False</Isolated> + <EmbedInteropTypes>False</EmbedInteropTypes> + </COMReference> + </ItemGroup> + <ItemGroup> + <Compile Include="AttachDialog.cs"> + <SubType>Form</SubType> + </Compile> + <Compile Include="AttachDialog.Designer.cs"> + <DependentUpon>AttachDialog.cs</DependentUpon> + </Compile> + <Compile Include="ProcessCategory.cs" /> + <Compile Include="ProcessDetail.cs" /> + <Compile Include="Utility.cs" /> + <Compile Include="Guids.cs" /> + <Compile Include="Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="GlobalSuppressions.cs" /> + <Compile Include="ChromeDebugPackage.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="PkgCmdID.cs" /> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="AttachDialog.resx"> + <DependentUpon>AttachDialog.cs</DependentUpon> + </EmbeddedResource> + <EmbeddedResource Include="Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + <SubType>Designer</SubType> + </EmbeddedResource> + <EmbeddedResource Include="VSPackage.resx"> + <MergeWithCTO>true</MergeWithCTO> + <ManifestResourceName>VSPackage</ManifestResourceName> + <SubType>Designer</SubType> + </EmbeddedResource> + </ItemGroup> + <ItemGroup> + <None Include="Key.snk" /> + <Content Include="LICENSE"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + <IncludeInVSIX>true</IncludeInVSIX> + </Content> + <None Include="source.extension.vsixmanifest"> + <SubType>Designer</SubType> + </None> + </ItemGroup> + <ItemGroup> + <VSCTCompile Include="ChromeDebug.vsct"> + <ResourceName>Menus.ctmenu</ResourceName> + <SubType>Designer</SubType> + </VSCTCompile> + </ItemGroup> + <ItemGroup> + <None Include="Resources\Images.png" /> + </ItemGroup> + <ItemGroup> + <Content Include="Resources\Package.ico" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\LowLevel\LowLevel.csproj"> + <Project>{998c0725-f123-4ed3-9d44-12c1945f00d1}</Project> + <Name>LowLevel</Name> + </ProjectReference> + </ItemGroup> + <PropertyGroup> + <UseCodebase>true</UseCodebase> + </PropertyGroup> + <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> + <Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/tools/win/ChromeDebug/ChromeDebug/ChromeDebug.vsct b/tools/win/ChromeDebug/ChromeDebug/ChromeDebug.vsct new file mode 100644 index 0000000..ca02527 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/ChromeDebug.vsct @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="utf-8"?> +<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" + xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <!-- This is the file that defines the actual layout and type of the commands. + It is divided in different sections (e.g. command definition, command + placement, ...), with each defining a specific set of properties. + See the comment before each section for more details about how to + use it. --> + + <!-- The VSCT compiler (the tool that translates this file into the binary + format that VisualStudio will consume) has the ability to run a preprocessor + on the vsct file; this preprocessor is (usually) the C++ preprocessor, so + it is possible to define includes and macros with the same syntax used + in C++ files. Using this ability of the compiler here, we include some files + defining some of the constants that we will use inside the file. --> + + <!--This is the file that defines the IDs for all the commands exposed by VisualStudio. --> + <Extern href="stdidcmd.h"/> + + <!--This header contains the command ids for the menus provided by the shell. --> + <Extern href="vsshlids.h"/> + + + + + <!--The Commands section is where we the commands, menus and menu groups are defined. + This section uses a Guid to identify the package that provides the command defined inside it. + --> + <Commands package="guidChromeDebugPkg"> + <!-- Inside this section we have different sub-sections: one for the menus, another + for the menu groups, one for the buttons (the actual commands), one for the combos + and the last one for the bitmaps used. Each element is identified by a command id that + is a unique pair of guid and numeric identifier; the guid part of the identifier is usually + called "command set" and is used to group different command inside a logically related + group; your package should define its own command set in order to avoid collisions + with command ids defined by other packages. --> + + + <!-- In this section you can define new menu groups. A menu group is a container for + other menus or buttons (commands); from a visual point of view you can see the + group as the part of a menu contained between two lines. The parent of a group + must be a menu. --> + <Groups> + + <Group guid="guidChromeDebugCmdSet" id="MyMenuGroup" priority="0x0600"> + <Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/> + </Group> + + + + </Groups> + + <!--Buttons section. --> + <!--This section defines the elements the user can interact with, like a menu command or a + button or combo box in a toolbar. --> + <Buttons> + <!--To define a menu group you have to specify its ID, the parent menu and its display + priority. The command is visible and enabled by default. If you need to change the + visibility, status, etc, you can use the CommandFlag node. You can add more than one + CommandFlag node e.g.: + <CommandFlag>DefaultInvisible</CommandFlag> + <CommandFlag>DynamicVisibility</CommandFlag> + If you do not want an image next to your command, remove the Icon node /> --> + + <Button guid="guidChromeDebugCmdSet" id="cmdidAttachToProcess" priority="0x0100" + type="Button"> + <Parent guid="guidChromeDebugCmdSet" id="MyMenuGroup" /> + <Icon guid="guidImages" id="bmpPic1" /> + <Strings> + <ButtonText>Attach to Chrome</ButtonText> + </Strings> + </Button> + + + + </Buttons> + + <!--The bitmaps section is used to define the bitmaps that are used for the commands.--> + <Bitmaps> + <!-- The bitmap id is defined in a way that is a little bit different from the others: + the declaration starts with a guid for the bitmap strip, then there is the resource id + of the bitmap strip containing the bitmaps and then there are the numeric ids of the + elements used inside a button definition. An important aspect of this declaration is + that the element id must be the actual index (1-based) of the bitmap inside the bitmap + strip. --> + <Bitmap guid="guidImages" href="Resources\Images.png" + usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows"/> + + </Bitmaps> + + </Commands> + + + + + + <Symbols> + <!-- This is the package guid. --> + <GuidSymbol name="guidChromeDebugPkg" value="{7de8bbab-82c7-4871-b82c-4d5d44a3979d}" /> + + <!-- This is the guid used to group the menu commands together --> + <GuidSymbol name="guidChromeDebugCmdSet" value="{6608d840-ce6c-45ab-b856-eb0a0b471ff1}"> + + <IDSymbol name="MyMenuGroup" value="0x1020" /> + <IDSymbol name="cmdidAttachToProcess" value="0x0100" /> + </GuidSymbol> + + + + <GuidSymbol name="guidImages" value="{7142ff8d-aa4e-45a5-a090-2e2ed8c5672b}" > + <IDSymbol name="bmpPic1" value="1" /> + <IDSymbol name="bmpPic2" value="2" /> + <IDSymbol name="bmpPicSearch" value="3" /> + <IDSymbol name="bmpPicX" value="4" /> + <IDSymbol name="bmpPicArrows" value="5" /> + <IDSymbol name="bmpPicStrikethrough" value="6" /> + </GuidSymbol> + </Symbols> + +</CommandTable> diff --git a/tools/win/ChromeDebug/ChromeDebug/ChromeDebugPackage.cs b/tools/win/ChromeDebug/ChromeDebug/ChromeDebugPackage.cs new file mode 100644 index 0000000..2a697b6 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/ChromeDebugPackage.cs @@ -0,0 +1,107 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using System; +using System.Diagnostics; +using System.Globalization; +using System.Runtime.InteropServices; +using System.ComponentModel.Design; +using Microsoft.Win32; +using Microsoft.VisualStudio; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.OLE.Interop; +using Microsoft.VisualStudio.Shell; +using System.Windows.Forms; + +namespace ChromeDebug { + /// <summary> + /// This is the class that implements the package exposed by this assembly. + /// + /// The minimum requirement for a class to be considered a valid package for Visual Studio + /// is to implement the IVsPackage interface and register itself with the shell. + /// This package uses the helper classes defined inside the Managed Package Framework (MPF) + /// to do it: it derives from the Package class that provides the implementation of the + /// IVsPackage interface and uses the registration attributes defined in the framework to + /// register itself and its components with the shell. + /// </summary> + // This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is + // a package. + [PackageRegistration(UseManagedResourcesOnly = true)] + // This attribute is used to register the information needed to show this package + // in the Help/About dialog of Visual Studio. + [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] + // This attribute is needed to let the shell know that this package exposes some menus. + [ProvideMenuResource("Menus.ctmenu", 1)] + [Guid(GuidList.guidChromeDebugPkgString)] + public sealed class ChromeDebugPackage : Package { + /// <summary> + /// Default constructor of the package. + /// Inside this method you can place any initialization code that does not require + /// any Visual Studio service because at this point the package object is created but + /// not sited yet inside Visual Studio environment. The place to do all the other + /// initialization is the Initialize method. + /// </summary> + public ChromeDebugPackage() { + Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", + this.ToString())); + } + + + + ///////////////////////////////////////////////////////////////////////////// + // Overridden Package Implementation + #region Package Members + + /// <summary> + /// Initialization of the package; this method is called right after the package is sited, so this is the place + /// where you can put all the initialization code that rely on services provided by VisualStudio. + /// </summary> + protected override void Initialize() { + Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString())); + base.Initialize(); + + // Add our command handlers for menu (commands must exist in the .vsct file) + OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService; + if (null != mcs) { + // Create the command for the menu item. + CommandID menuCommandID = new CommandID(GuidList.guidChromeDebugCmdSet, (int)PkgCmdIDList.cmdidAttachToProcess); + MenuCommand menuItem = new MenuCommand(MenuItemCallback, menuCommandID); + mcs.AddCommand(menuItem); + } + } + #endregion + + /// <summary> + /// This function is the callback used to execute a command when the a menu item is clicked. + /// See the Initialize method to see how the menu item is associated to this function using + /// the OleMenuCommandService service and the MenuCommand class. + /// </summary> + private void MenuItemCallback(object sender, EventArgs e) { + // Show a Message Box to prove we were here + EnvDTE.DTE dte = (EnvDTE.DTE)GetService(typeof(EnvDTE.DTE)); + + IVsUIShell uiShell = (IVsUIShell)GetService(typeof(SVsUIShell)); + Guid clsid = Guid.Empty; + IntPtr parentHwnd = IntPtr.Zero; + uiShell.GetDialogOwnerHwnd(out parentHwnd); + + NativeWindow parentShim = new NativeWindow(); + parentShim.AssignHandle(parentHwnd); + AttachDialog dialog = new AttachDialog(); + DialogResult result = dialog.ShowDialog(parentShim); + if (result == DialogResult.OK) { + foreach (int selected_id in dialog.SelectedItems) { + foreach (EnvDTE90a.Process4 p in dte.Debugger.LocalProcesses) { + System.Diagnostics.Debug.WriteLine("Found process {0}", p.ProcessID); + if (p.ProcessID != selected_id) + continue; + p.Attach(); + System.Diagnostics.Debug.WriteLine("Attaching to process successful."); + break; + } + } + } + } + } +} diff --git a/tools/win/ChromeDebug/ChromeDebug/GlobalSuppressions.cs b/tools/win/ChromeDebug/ChromeDebug/GlobalSuppressions.cs new file mode 100644 index 0000000..f967862 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/GlobalSuppressions.cs @@ -0,0 +1,16 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. Project-level +// suppressions either have no target or are given a specific target +// and scoped to a namespace, type, member, etc. +// +// To add a suppression to this file, right-click the message in the +// Error List, point to "Suppress Message(s)", and click "In Project +// Suppression File". You do not need to add suppressions to this +// file manually. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", + "CA1017:MarkAssembliesWithComVisible")] diff --git a/tools/win/ChromeDebug/ChromeDebug/Guids.cs b/tools/win/ChromeDebug/ChromeDebug/Guids.cs new file mode 100644 index 0000000..7a7a660 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/Guids.cs @@ -0,0 +1,16 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Guids.cs +// MUST match guids.h +using System; + +namespace ChromeDebug { + static class GuidList { + public const string guidChromeDebugPkgString = "7de8bbab-82c7-4871-b82c-4d5d44a3979d"; + public const string guidChromeDebugCmdSetString = "6608d840-ce6c-45ab-b856-eb0a0b471ff1"; + + public static readonly Guid guidChromeDebugCmdSet = new Guid(guidChromeDebugCmdSetString); + }; +}
\ No newline at end of file diff --git a/tools/win/ChromeDebug/ChromeDebug/LICENSE b/tools/win/ChromeDebug/ChromeDebug/LICENSE new file mode 100644 index 0000000..8fb3cc2 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/LICENSE @@ -0,0 +1,27 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/tools/win/ChromeDebug/ChromeDebug/PkgCmdID.cs b/tools/win/ChromeDebug/ChromeDebug/PkgCmdID.cs new file mode 100644 index 0000000..816b804 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/PkgCmdID.cs @@ -0,0 +1,13 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// PkgCmdID.cs +// MUST match PkgCmdID.h +using System; + +namespace ChromeDebug { + static class PkgCmdIDList { + public const uint cmdidAttachToProcess = 0x100; + }; +}
\ No newline at end of file diff --git a/tools/win/ChromeDebug/ChromeDebug/ProcessCategory.cs b/tools/win/ChromeDebug/ChromeDebug/ProcessCategory.cs new file mode 100644 index 0000000..ffcffdd --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/ProcessCategory.cs @@ -0,0 +1,37 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDebug { + internal enum ProcessCategory { + Browser, + Renderer, + Gpu, + Plugin, + DelegateExecute, + MetroViewer, + Service, + Other + } + + // Defines an extension method for the ProcessCategory enum which converts the enum value into + // the group title. + internal static class ProcessCategoryExtensions { + public static string ToGroupTitle(this ProcessCategory category) { + switch (category) { + case ProcessCategory.DelegateExecute: + return "Delegate Execute"; + case ProcessCategory.MetroViewer: + return "Metro Viewer"; + default: + return category.ToString(); + } + } + } +} diff --git a/tools/win/ChromeDebug/ChromeDebug/ProcessDetail.cs b/tools/win/ChromeDebug/ChromeDebug/ProcessDetail.cs new file mode 100644 index 0000000..fbbb358 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/ProcessDetail.cs @@ -0,0 +1,238 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using ChromeDebug.LowLevel; + +namespace ChromeDebug { + internal class ProcessDetail : IDisposable { + public ProcessDetail(int pid) { + // Initialize everything to null in case something fails. + this.processId = pid; + this.processHandleFlags = LowLevelTypes.ProcessAccessFlags.NONE; + this.cachedProcessBasicInfo = null; + this.machineTypeIsLoaded = false; + this.machineType = LowLevelTypes.MachineType.UNKNOWN; + this.cachedPeb = null; + this.cachedProcessParams = null; + this.cachedCommandLine = null; + this.processHandle = IntPtr.Zero; + + OpenAndCacheProcessHandle(); + } + + // Returns the machine type (x86, x64, etc) of this process. Uses lazy evaluation and caches + // the result. + public LowLevelTypes.MachineType MachineType { + get { + if (machineTypeIsLoaded) + return machineType; + if (!CanQueryProcessInformation) + return LowLevelTypes.MachineType.UNKNOWN; + + CacheMachineType(); + return machineType; + } + } + + // Returns the command line that this process was launched with. Uses lazy evaluation and + // caches the result. Reads the command line from the PEB of the running process. + public string CommandLine { + get { + if (!CanReadPeb) + throw new InvalidOperationException(); + CacheProcessInformation(); + CachePeb(); + CacheProcessParams(); + CacheCommandLine(); + return cachedCommandLine; + } + } + + // Determines if we have permission to read the process's PEB. + public bool CanReadPeb { + get { + LowLevelTypes.ProcessAccessFlags required_flags = + LowLevelTypes.ProcessAccessFlags.VM_READ + | LowLevelTypes.ProcessAccessFlags.QUERY_INFORMATION; + + // In order to read the PEB, we must have *both* of these flags. + if ((processHandleFlags & required_flags) != required_flags) + return false; + + // If we're on a 64-bit OS, in a 32-bit process, and the target process is not 32-bit, + // we can't read its PEB. + if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess + && (MachineType != LowLevelTypes.MachineType.X86)) + return false; + + return true; + } + } + + // If we can't read the process's PEB, we may still be able to get other kinds of information + // from the process. This flag determines if we can get lesser information. + private bool CanQueryProcessInformation { + get { + LowLevelTypes.ProcessAccessFlags required_flags = + LowLevelTypes.ProcessAccessFlags.QUERY_LIMITED_INFORMATION + | LowLevelTypes.ProcessAccessFlags.QUERY_INFORMATION; + + // In order to query the process, we need *either* of these flags. + return (processHandleFlags & required_flags) != LowLevelTypes.ProcessAccessFlags.NONE; + } + } + + // Loads the top-level structure of the process's information block and caches it. + private void CacheProcessInformation() { + System.Diagnostics.Debug.Assert(CanReadPeb); + + // Fetch the process info and set the fields. + LowLevelTypes.PROCESS_BASIC_INFORMATION temp = new LowLevelTypes.PROCESS_BASIC_INFORMATION(); + int size; + LowLevelTypes.NTSTATUS status = NativeMethods.NtQueryInformationProcess( + processHandle, + LowLevelTypes.PROCESSINFOCLASS.PROCESS_BASIC_INFORMATION, + ref temp, + Utility.UnmanagedStructSize<LowLevelTypes.PROCESS_BASIC_INFORMATION>(), + out size); + + if (status != LowLevelTypes.NTSTATUS.SUCCESS) { + throw new Win32Exception(); + } + + cachedProcessBasicInfo = temp; + } + + // Follows a pointer from the PROCESS_BASIC_INFORMATION structure in the target process's + // address space to read the PEB. + private void CachePeb() { + System.Diagnostics.Debug.Assert(CanReadPeb); + + if (cachedPeb == null) { + cachedPeb = Utility.ReadUnmanagedStructFromProcess<LowLevelTypes.PEB>( + processHandle, + cachedProcessBasicInfo.Value.PebBaseAddress); + } + } + + // Follows a pointer from the PEB structure in the target process's address space to read the + // RTL_USER_PROCESS_PARAMETERS structure. + private void CacheProcessParams() { + System.Diagnostics.Debug.Assert(CanReadPeb); + + if (cachedProcessParams == null) { + cachedProcessParams = + Utility.ReadUnmanagedStructFromProcess<LowLevelTypes.RTL_USER_PROCESS_PARAMETERS>( + processHandle, cachedPeb.Value.ProcessParameters); + } + } + + private void CacheCommandLine() { + System.Diagnostics.Debug.Assert(CanReadPeb); + + if (cachedCommandLine == null) { + cachedCommandLine = Utility.ReadStringUniFromProcess( + processHandle, + cachedProcessParams.Value.CommandLine.Buffer, + cachedProcessParams.Value.CommandLine.Length / 2); + } + } + + private void CacheMachineType() { + System.Diagnostics.Debug.Assert(CanQueryProcessInformation); + + StringBuilder moduleBuffer = new StringBuilder(1024); + int size = moduleBuffer.Capacity; + + // If our extension is running in a 32-bit process (which it is), then attempts to access + // files in C:\windows\system (and a few other files) will redirect to C:\Windows\SysWOW64 + // and we will mistakenly think that the image file is a 32-bit image. The way around this + // is to use a native system format path, of the form: + // \\?\GLOBALROOT\Device\HarddiskVolume0\Windows\System\foo.dat + // By using the NATIVE_SYSTEM_FORMAT flag to QueryFullProcessImageName, we can get the path + // in this format. + NativeMethods.QueryFullProcessImageName( + processHandle, + LowLevelTypes.ProcessQueryImageNameMode.NATIVE_SYSTEM_FORMAT, + moduleBuffer, + ref size); + moduleBuffer.Insert(0, "\\\\?\\GLOBALROOT"); + string module = moduleBuffer.ToString(); + + // Open the PE File as a binary file, and parse just enough information to determine the + // machine type. + //http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx + using (SafeFileHandle safeHandle = NativeMethods.CreateFile( + module, + LowLevelTypes.FileAccessFlags.GENERIC_READ, + LowLevelTypes.FileShareFlags.SHARE_READ, + IntPtr.Zero, + LowLevelTypes.FileCreationDisposition.OPEN_EXISTING, + LowLevelTypes.FileFlagsAndAttributes.NORMAL, + IntPtr.Zero)) { + FileStream fs = new FileStream(safeHandle, FileAccess.Read); + using (BinaryReader br = new BinaryReader(fs)) { + fs.Seek(0x3c, SeekOrigin.Begin); + Int32 peOffset = br.ReadInt32(); + fs.Seek(peOffset, SeekOrigin.Begin); + UInt32 peHead = br.ReadUInt32(); + if (peHead != 0x00004550) // "PE\0\0", little-endian + throw new Exception("Can't find PE header"); + machineType = (LowLevelTypes.MachineType)br.ReadUInt16(); + machineTypeIsLoaded = true; + } + } + } + + private void OpenAndCacheProcessHandle() { + // Try to open a handle to the process with the highest level of privilege, but if we can't + // do that then fallback to requesting access with a lower privilege level. + processHandleFlags = LowLevelTypes.ProcessAccessFlags.QUERY_INFORMATION + | LowLevelTypes.ProcessAccessFlags.VM_READ; + processHandle = NativeMethods.OpenProcess(processHandleFlags, false, processId); + if (processHandle == IntPtr.Zero) { + processHandleFlags = LowLevelTypes.ProcessAccessFlags.QUERY_LIMITED_INFORMATION; + processHandle = NativeMethods.OpenProcess(processHandleFlags, false, processId); + if (processHandle == IntPtr.Zero) { + processHandleFlags = LowLevelTypes.ProcessAccessFlags.NONE; + throw new Win32Exception(); + } + } + } + + // An open handle to the process, along with the set of access flags that the handle was + // open with. + private int processId; + private IntPtr processHandle; + LowLevelTypes.ProcessAccessFlags processHandleFlags; + + // The machine type is read by parsing the PE image file of the running process, so we cache + // its value since the operation expensive. + private bool machineTypeIsLoaded; + private LowLevelTypes.MachineType machineType; + + // The following fields exist ultimately so that we can access the command line. However, + // each field must be read separately through a pointer into another process's address + // space so the access is expensive, hence we cache the values. + private Nullable<LowLevelTypes.PROCESS_BASIC_INFORMATION> cachedProcessBasicInfo; + private Nullable<LowLevelTypes.PEB> cachedPeb; + private Nullable<LowLevelTypes.RTL_USER_PROCESS_PARAMETERS> cachedProcessParams; + private string cachedCommandLine; + + public void Dispose() { + if (processHandle != IntPtr.Zero) + NativeMethods.CloseHandle(processHandle); + processHandle = IntPtr.Zero; + } + } +} diff --git a/tools/win/ChromeDebug/ChromeDebug/Properties/AssemblyInfo.cs b/tools/win/ChromeDebug/ChromeDebug/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..29c8203 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ChromeDebug")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Chromium Authors")] +[assembly: AssemblyProduct("ChromeDebug")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +[assembly: CLSCompliant(false)] +[assembly: NeutralResourcesLanguage("en-US")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + + + diff --git a/tools/win/ChromeDebug/ChromeDebug/Resources.Designer.cs b/tools/win/ChromeDebug/ChromeDebug/Resources.Designer.cs new file mode 100644 index 0000000..529a0a7 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.33439 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace ChromeDebug { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ChromeDebug.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/tools/win/ChromeDebug/ChromeDebug/Resources.resx b/tools/win/ChromeDebug/ChromeDebug/Resources.resx new file mode 100644 index 0000000..9fa8826 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/Resources.resx @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + VS SDK Notes: This resx file contains the resources that will be consumed directly by your + package. For example, if you chose to create a tool window, there is a resource with ID + 'CanNotCreateWindow'. This is used in VsPkg.cs to determine the string to show the user if + there is an error when attempting to create the tool window. + + Resources that are accessed directly from your package *by Visual Studio* are stored in the + VSPackage.resx file. +--> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader"> + System.Resources.ResXResourceReader, System.Windows.Forms, ... + </resheader> + <resheader name="writer"> + System.Resources.ResXResourceWriter, System.Windows.Forms, ... + </resheader> + <data name="Name1"> + <value>this is my long string</value> + <comment>this is a comment</comment> + </data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" + mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root>
\ No newline at end of file diff --git a/tools/win/ChromeDebug/ChromeDebug/Utility.cs b/tools/win/ChromeDebug/ChromeDebug/Utility.cs new file mode 100644 index 0000000..bdba408 --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/Utility.cs @@ -0,0 +1,85 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +using ChromeDebug.LowLevel; + +namespace ChromeDebug { + internal static class Utility { + public static string[] SplitArgs(string unsplitArgumentLine) { + if (unsplitArgumentLine == null) + return new string[0]; + + int numberOfArgs; + IntPtr ptrToSplitArgs; + string[] splitArgs; + + ptrToSplitArgs = NativeMethods.CommandLineToArgvW(unsplitArgumentLine, out numberOfArgs); + + // CommandLineToArgvW returns NULL upon failure. + if (ptrToSplitArgs == IntPtr.Zero) + throw new ArgumentException("Unable to split argument.", new Win32Exception()); + + // Make sure the memory ptrToSplitArgs to is freed, even upon failure. + try { + splitArgs = new string[numberOfArgs]; + + // ptrToSplitArgs is an array of pointers to null terminated Unicode strings. + // Copy each of these strings into our split argument array. + for (int i = 0; i < numberOfArgs; i++) + splitArgs[i] = Marshal.PtrToStringUni( + Marshal.ReadIntPtr(ptrToSplitArgs, i * IntPtr.Size)); + + return splitArgs; + } + finally { + // Free memory obtained by CommandLineToArgW. + NativeMethods.LocalFree(ptrToSplitArgs); + } + } + + public static T ReadUnmanagedStructFromProcess<T>(IntPtr processHandle, + IntPtr addressInProcess) { + int bytesRead; + int bytesToRead = Marshal.SizeOf(typeof(T)); + IntPtr buffer = Marshal.AllocHGlobal(bytesToRead); + if (!NativeMethods.ReadProcessMemory(processHandle, addressInProcess, buffer, bytesToRead, + out bytesRead)) + throw new Win32Exception(); + T result = (T)Marshal.PtrToStructure(buffer, typeof(T)); + Marshal.FreeHGlobal(buffer); + return result; + } + + public static string ReadStringUniFromProcess(IntPtr processHandle, + IntPtr addressInProcess, + int NumChars) { + int bytesRead; + IntPtr outBuffer = Marshal.AllocHGlobal(NumChars * 2); + + bool bresult = NativeMethods.ReadProcessMemory(processHandle, + addressInProcess, + outBuffer, + NumChars * 2, + out bytesRead); + if (!bresult) + throw new Win32Exception(); + + string result = Marshal.PtrToStringUni(outBuffer, bytesRead / 2); + Marshal.FreeHGlobal(outBuffer); + return result; + } + + public static int UnmanagedStructSize<T>() { + return Marshal.SizeOf(typeof(T)); + } + } +} diff --git a/tools/win/ChromeDebug/ChromeDebug/VSPackage.resx b/tools/win/ChromeDebug/ChromeDebug/VSPackage.resx new file mode 100644 index 0000000..36cd9ee --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/VSPackage.resx @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + VS SDK Notes: This resx file contains the resources that will be consumed from your package by + Visual Studio. For example, Visual Studio will attempt to load resource '400' from this + resource stream when it needs to load your package's icon. Because Visual Studio will always + look in the VSPackage.resources stream first for resources it needs, you should put additional + resources that Visual Studio will load directly into this resx file. + + Resources that you would like to access directly from your package in a strong-typed fashion + should be stored in Resources.resx or another resx file. +--> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader"> + System.Resources.ResXResourceReader, System.Windows.Forms, ... + </resheader> + <resheader name="writer"> + System.Resources.ResXResourceWriter, System.Windows.Forms, ... + </resheader> + <data name="Name1"> + <value>this is my long string</value> + <comment>this is a comment</comment> + </data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" + mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value> + [base64 mime encoded string representing a byte array form of the .NET Framework object] + </value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="110" xml:space="preserve"> + <value>ChromeDebug</value> + </data> + <data name="112" xml:space="preserve"> + <value>Advanced Debugging Features</value> + </data> + <data name="400" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>Resources\Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> + </data> +</root>
\ No newline at end of file diff --git a/tools/win/ChromeDebug/ChromeDebug/source.extension.vsixmanifest b/tools/win/ChromeDebug/ChromeDebug/source.extension.vsixmanifest new file mode 100644 index 0000000..c0814aa --- /dev/null +++ b/tools/win/ChromeDebug/ChromeDebug/source.extension.vsixmanifest @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" + xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011"> + <Metadata> + <Identity Id="7de8bbab-82c7-4871-b82c-4d5d44a3979d" Version="1.0" Language="en-US" + Publisher="The Chromium Authors" /> + <DisplayName>ChromeDebug</DisplayName> + <Description xml:space="preserve">Debugging Features for Chromium</Description> + <License>LICENSE</License> + </Metadata> + <Installation InstalledByMsi="false"> + <InstallationTarget Id="Microsoft.VisualStudio.Pro" Version="[11.0,12.0]" /> + </Installation> + <Dependencies> + <Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" + d:Source="Manual" Version="4.5" /> + <Dependency Id="Microsoft.VisualStudio.MPF.11.0" DisplayName="Visual Studio MPF 11.0" + d:Source="Installed" Version="11.0" /> + </Dependencies> + <Assets> + <Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" + d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" /> + </Assets> +</PackageManifest> diff --git a/tools/win/ChromeDebug/LowLevel/LowLevel.csproj b/tools/win/ChromeDebug/LowLevel/LowLevel.csproj new file mode 100644 index 0000000..4649f33 --- /dev/null +++ b/tools/win/ChromeDebug/LowLevel/LowLevel.csproj @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{998C0725-F123-4ED3-9D44-12C1945F00D1}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>LowLevel</RootNamespace> + <AssemblyName>LowLevel</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup> + <SignAssembly>true</SignAssembly> + </PropertyGroup> + <PropertyGroup> + <AssemblyOriginatorKeyFile> + </AssemblyOriginatorKeyFile> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="NativeMethods.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Types.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="Key.snk" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/tools/win/ChromeDebug/LowLevel/NativeMethods.cs b/tools/win/ChromeDebug/LowLevel/NativeMethods.cs new file mode 100644 index 0000000..4fb46fd --- /dev/null +++ b/tools/win/ChromeDebug/LowLevel/NativeMethods.cs @@ -0,0 +1,65 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using Microsoft.Win32.SafeHandles; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDebug.LowLevel { + public static class NativeMethods { + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ReadProcessMemory(IntPtr hProcess, + IntPtr lpBaseAddress, + IntPtr lpBuffer, + int dwSize, + out int lpNumberOfBytesRead); + + [DllImport("ntdll.dll", SetLastError = true)] + public static extern LowLevelTypes.NTSTATUS NtQueryInformationProcess( + IntPtr hProcess, + LowLevelTypes.PROCESSINFOCLASS pic, + ref LowLevelTypes.PROCESS_BASIC_INFORMATION pbi, + int cb, + out int pSize); + + [DllImport("shell32.dll", SetLastError = true)] + public static extern IntPtr CommandLineToArgvW( + [MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine, + out int pNumArgs); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr LocalFree(IntPtr hMem); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenProcess( + LowLevelTypes.ProcessAccessFlags dwDesiredAccess, + [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, + int dwProcessId); + + [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall, + CharSet = CharSet.Unicode)] + public static extern uint QueryFullProcessImageName( + IntPtr hProcess, + [MarshalAs(UnmanagedType.U4)] LowLevelTypes.ProcessQueryImageNameMode flags, + [Out] StringBuilder lpImageName, ref int size); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CloseHandle(IntPtr hObject); + + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + public static extern SafeFileHandle CreateFile(string lpFileName, + LowLevelTypes.FileAccessFlags dwDesiredAccess, + LowLevelTypes.FileShareFlags dwShareMode, + IntPtr lpSecurityAttributes, + LowLevelTypes.FileCreationDisposition dwDisp, + LowLevelTypes.FileFlagsAndAttributes dwFlags, + IntPtr hTemplateFile); + } +} diff --git a/tools/win/ChromeDebug/LowLevel/Properties/AssemblyInfo.cs b/tools/win/ChromeDebug/LowLevel/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7a77cff --- /dev/null +++ b/tools/win/ChromeDebug/LowLevel/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("LowLevel")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("LowLevel")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5bfd12c9-dfa1-4994-b31d-755f3e064640")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/tools/win/ChromeDebug/LowLevel/Types.cs b/tools/win/ChromeDebug/LowLevel/Types.cs new file mode 100644 index 0000000..17fc19b --- /dev/null +++ b/tools/win/ChromeDebug/LowLevel/Types.cs @@ -0,0 +1,177 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace ChromeDebug.LowLevel { + // Defines structures, enumerations, and types used by Win32 API calls. In some cases, the API + // calls support (and even document) many more values than what are listed here. Should + // additional values be required, they can be added to the respective types. + public static class LowLevelTypes { + + #region Constants and Enums + // Represents the image format of a DLL or executable. + public enum ImageFormat { + NATIVE, + MANAGED, + UNKNOWN + } + + // Flags used for opening a file handle (e.g. in a call to CreateFile), that determine the + // requested permission level. + [Flags] + public enum FileAccessFlags : uint { + GENERIC_WRITE = 0x40000000, + GENERIC_READ = 0x80000000 + } + + // Value used for CreateFile to determine how to behave in the presence (or absence) of a + // file with the requested name. Used only for CreateFile. + public enum FileCreationDisposition : uint { + CREATE_NEW = 1, + CREATE_ALWAYS = 2, + OPEN_EXISTING = 3, + OPEN_ALWAYS = 4, + TRUNCATE_EXISTING = 5 + } + + // Flags that determine what level of sharing this application requests on the target file. + // Used only for CreateFile. + [Flags] + public enum FileShareFlags : uint { + EXCLUSIVE_ACCESS = 0x0, + SHARE_READ = 0x1, + SHARE_WRITE = 0x2, + SHARE_DELETE = 0x4 + } + + // Flags that control caching and other behavior of the underlying file object. Used only for + // CreateFile. + [Flags] + public enum FileFlagsAndAttributes : uint { + NORMAL = 0x80, + OPEN_REPARSE_POINT = 0x200000, + SEQUENTIAL_SCAN = 0x8000000, + RANDOM_ACCESS = 0x10000000, + NO_BUFFERING = 0x20000000, + OVERLAPPED = 0x40000000 + } + + // The target architecture of a given executable image. The various values correspond to the + // magic numbers defined by the PE Executable Image File Format. + // http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx + public enum MachineType : ushort { + UNKNOWN = 0x0, + X64 = 0x8664, + X86 = 0x14c, + IA64 = 0x200 + } + + // A flag indicating the format of the path string that Windows returns from a call to + // QueryFullProcessImageName(). + public enum ProcessQueryImageNameMode : uint { + WIN32_FORMAT = 0, + NATIVE_SYSTEM_FORMAT = 1 + } + + // Flags indicating the level of permission requested when opening a handle to an external + // process. Used by OpenProcess(). + [Flags] + public enum ProcessAccessFlags : uint { + NONE = 0x0, + ALL = 0x001F0FFF, + VM_OPERATION = 0x00000008, + VM_READ = 0x00000010, + QUERY_INFORMATION = 0x00000400, + QUERY_LIMITED_INFORMATION = 0x00001000 + } + + // Defines return value codes used by various Win32 System APIs. + public enum NTSTATUS : int { + SUCCESS = 0, + } + + // Determines the amount of information requested (and hence the type of structure returned) + // by a call to NtQueryInformationProcess. + public enum PROCESSINFOCLASS : int { + PROCESS_BASIC_INFORMATION = 0 + }; + #endregion + + #region Structures + // In general, for all structures below which contains a pointer (represented here by IntPtr), + // the pointers refer to memory in the address space of the process from which the original + // structure was read. While this seems obvious, it means we cannot provide an elegant + // interface to the various fields in the structure due to the de-reference requiring a + // handle to the target process. Instead, that functionality needs to be provided at a + // higher level. + // + // Additionally, since we usually explicitly define the fields that we're interested in along + // with their respective offsets, we frequently specify the exact size of the native structure. + + // Win32 UNICODE_STRING structure. + [StructLayout(LayoutKind.Sequential)] + public struct UNICODE_STRING { + // The length in bytes of the string pointed to by buffer, not including the null-terminator. + private ushort length; + // The total allocated size in memory pointed to by buffer. + private ushort maximumLength; + // A pointer to the buffer containing the string data. + private IntPtr buffer; + + public ushort Length { get { return length; } } + public ushort MaximumLength { get { return maximumLength; } } + public IntPtr Buffer { get { return buffer; } } + } + + // Win32 RTL_USER_PROCESS_PARAMETERS structure. + [StructLayout(LayoutKind.Explicit, Size = 72)] + public struct RTL_USER_PROCESS_PARAMETERS { + [FieldOffset(56)] + private UNICODE_STRING imagePathName; + [FieldOffset(64)] + private UNICODE_STRING commandLine; + + public UNICODE_STRING ImagePathName { get { return imagePathName; } } + public UNICODE_STRING CommandLine { get { return commandLine; } } + }; + + // Win32 PEB structure. Represents the process environment block of a process. + [StructLayout(LayoutKind.Explicit, Size = 472)] + public struct PEB { + [FieldOffset(2), MarshalAs(UnmanagedType.U1)] + private bool isBeingDebugged; + [FieldOffset(12)] + private IntPtr ldr; + [FieldOffset(16)] + private IntPtr processParameters; + [FieldOffset(468)] + private uint sessionId; + + public bool IsBeingDebugged { get { return isBeingDebugged; } } + public IntPtr Ldr { get { return ldr; } } + public IntPtr ProcessParameters { get { return processParameters; } } + public uint SessionId { get { return sessionId; } } + }; + + // Win32 PROCESS_BASIC_INFORMATION. Contains a pointer to the PEB, and various other + // information about a process. + [StructLayout(LayoutKind.Explicit, Size = 24)] + public struct PROCESS_BASIC_INFORMATION { + [FieldOffset(4)] + private IntPtr pebBaseAddress; + [FieldOffset(16)] + private UIntPtr uniqueProcessId; + + public IntPtr PebBaseAddress { get { return pebBaseAddress; } } + public UIntPtr UniqueProcessId { get { return uniqueProcessId; } } + } + #endregion + } +} diff --git a/tools/win/ChromeDebug/README.txt b/tools/win/ChromeDebug/README.txt new file mode 100644 index 0000000..6039462 --- /dev/null +++ b/tools/win/ChromeDebug/README.txt @@ -0,0 +1,5 @@ +Usage Instructions: + +1) Compile with VS2012 or VS2013. +2) Double click the .vsix in the output directory. +3) Choose the version of VS to install to.
\ No newline at end of file |