diff --git a/hyperv-passthrough/App.config b/hyperv-passthrough/App.config index 1243f4282..6525f5822 100644 --- a/hyperv-passthrough/App.config +++ b/hyperv-passthrough/App.config @@ -3,22 +3,6 @@ - - - - - - - - - - - - - - - - diff --git a/hyperv-passthrough/DisplayAssignableDevices.Designer.cs b/hyperv-passthrough/DisplayAssignableDevices.Designer.cs new file mode 100644 index 000000000..cd3f91329 --- /dev/null +++ b/hyperv-passthrough/DisplayAssignableDevices.Designer.cs @@ -0,0 +1,88 @@ +namespace HyperVPassthoughDevice +{ + partial class DisplayAssignableDevices + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DisplayAssignableDevices)); + this.CloseButton = new System.Windows.Forms.Button(); + this.start = new System.Windows.Forms.Button(); + this.richTextBox1 = new System.Windows.Forms.RichTextBox(); + this.SuspendLayout(); + // + // CloseButton + // + this.CloseButton.Location = new System.Drawing.Point(505, 346); + this.CloseButton.Name = "CloseButton"; + this.CloseButton.Size = new System.Drawing.Size(75, 23); + this.CloseButton.TabIndex = 0; + this.CloseButton.Text = "Close"; + this.CloseButton.UseVisualStyleBackColor = true; + this.CloseButton.Click += new System.EventHandler(this.CloseDiaglog); + // + // start + // + this.start.Location = new System.Drawing.Point(397, 346); + this.start.Name = "start"; + this.start.Size = new System.Drawing.Size(102, 23); + this.start.TabIndex = 3; + this.start.Text = "Start Checking"; + this.start.UseVisualStyleBackColor = true; + this.start.Click += new System.EventHandler(this.StartChecking); + // + // richTextBox1 + // + this.richTextBox1.Location = new System.Drawing.Point(12, 12); + this.richTextBox1.Name = "richTextBox1"; + this.richTextBox1.Size = new System.Drawing.Size(568, 328); + this.richTextBox1.TabIndex = 1; + this.richTextBox1.Text = ""; + this.richTextBox1.WordWrap = false; + // + // DisplayAssignableDevices + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(592, 381); + this.Controls.Add(this.start); + this.Controls.Add(this.richTextBox1); + this.Controls.Add(this.CloseButton); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "DisplayAssignableDevices"; + this.Text = "Display Assignable Devices"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button CloseButton; + private System.Windows.Forms.Button start; + private System.Windows.Forms.RichTextBox richTextBox1; + } +} \ No newline at end of file diff --git a/hyperv-passthrough/DisplayAssignableDevices.cs b/hyperv-passthrough/DisplayAssignableDevices.cs new file mode 100644 index 000000000..51613ae44 --- /dev/null +++ b/hyperv-passthrough/DisplayAssignableDevices.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.ObjectModel; +using System.Management.Automation; +using System.Text; +using System.Windows.Forms; + +namespace HyperVPassthoughDevice +{ + public partial class DisplayAssignableDevices : Form + { + public DisplayAssignableDevices() + { + InitializeComponent(); + ShowDialog(); + } + + private void CloseDiaglog(object sender, EventArgs e) + { + Close(); + } + + private void StartChecking(object sender, EventArgs e) + { + richTextBox1.Clear(); //Clear textbox + + string script = "#\r\n# These variables are device properties. For people who are very\r\n# curious about this, you can download the Windows Driver Kit headers and\r\n# look for pciprop.h. All of these are contained in that file.\r\n#\r\n$devpkey_PciDevice_DeviceType = \"{3AB22E31-8264-4b4e-9AF5-A8D2D8E33E62} 1\"\r\n$devpkey_PciDevice_BaseClass = \"{3AB22E31-8264-4b4e-9AF5-A8D2D8E33E62} 3\"\r\n$devpkey_PciDevice_RequiresReservedMemoryRegion = \"{3AB22E31-8264-4b4e-9AF5-A8D2D8E33E62} 34\"\r\n$devpkey_PciDevice_AcsCompatibleUpHierarchy = \"{3AB22E31-8264-4b4e-9AF5-A8D2D8E33E62} 31\"\r\n\r\n$devprop_PciDevice_DeviceType_PciConventional = 0\r\n$devprop_PciDevice_DeviceType_PciX = 1\r\n$devprop_PciDevice_DeviceType_PciExpressEndpoint = 2\r\n$devprop_PciDevice_DeviceType_PciExpressLegacyEndpoint = 3\r\n$devprop_PciDevice_DeviceType_PciExpressRootComplexIntegratedEndpoint= 4\r\n$devprop_PciDevice_DeviceType_PciExpressTreatedAsPci = 5\r\n$devprop_PciDevice_BridgeType_PciConventional = 6\r\n$devprop_PciDevice_BridgeType_PciX = 7\r\n$devprop_PciDevice_BridgeType_PciExpressRootPort = 8\r\n$devprop_PciDevice_BridgeType_PciExpressUpstreamSwitchPort = 9\r\n$devprop_PciDevice_BridgeType_PciExpressDownstreamSwitchPort = 10\r\n$devprop_PciDevice_BridgeType_PciExpressToPciXBridge = 11\r\n$devprop_PciDevice_BridgeType_PciXToExpressBridge = 12\r\n$devprop_PciDevice_BridgeType_PciExpressTreatedAsPci = 13\r\n$devprop_PciDevice_BridgeType_PciExpressEventCollector = 14\r\n\r\n$devprop_PciDevice_AcsCompatibleUpHierarchy_NotSupported = 0\r\n$devprop_PciDevice_AcsCompatibleUpHierarchy_SingleFunctionSupported = 1\r\n$devprop_PciDevice_AcsCompatibleUpHierarchy_NoP2PSupported = 2\r\n$devprop_PciDevice_AcsCompatibleUpHierarchy_Supported = 3\r\n\r\n#\r\n# These values are defined in the PCI spec, and are also published in wdm.h\r\n# of the Windows Driver Kit headers.\r\n#\r\n$devprop_PciDevice_BaseClass_DisplayCtlr = 3\r\n\r\nWrite-Host \"Executing SurveyDDA.ps1, revision 1\"\r\n\r\nwrite-host \"Generating a list of PCI Express endpoint devices\"\r\n$pnpdevs = Get-PnpDevice -PresentOnly\r\n$pcidevs = $pnpdevs | Where-Object {$_.InstanceId -like \"PCI*\"}\r\n\r\nforeach ($pcidev in $pcidevs) {\r\n $rmrr = ($pcidev | Get-PnpDeviceProperty $devpkey_PciDevice_RequiresReservedMemoryRegion).Data\r\n if ($rmrr -ne 0) {\r\n write-host -ForegroundColor Red -BackgroundColor Black \"BIOS requires that this device remain attached to BIOS-owned memory. Not assignable.\"\r\n continue\r\n }\r\n\r\n $acsUp = ($pcidev | Get-PnpDeviceProperty $devpkey_PciDevice_AcsCompatibleUpHierarchy).Data\r\n if ($acsUp -eq $devprop_PciDevice_AcsCompatibleUpHierarchy_NotSupported) {\r\n write-host -ForegroundColor Red -BackgroundColor Black \"Traffic from this device may be redirected to other devices in the system. Not assignable.\"\r\n continue\r\n }\r\n\r\n $devtype = ($pcidev | Get-PnpDeviceProperty $devpkey_PciDevice_DeviceType).Data\r\n if ($devtype -eq $devprop_PciDevice_DeviceType_PciExpressEndpoint) {\r\n Write-Host \"Express Endpoint -- more secure.\"\r\n } else {\r\n if ($devtype -eq $devprop_PciDevice_DeviceType_PciExpressRootComplexIntegratedEndpoint) {\r\n Write-Host \"Embedded Endpoint -- less secure.\"\r\n } elseif ($devtype -eq $devprop_PciDevice_DeviceType_PciExpressLegacyEndpoint) {\r\n $devBaseClass = ($pcidev | Get-PnpDeviceProperty $devpkey_PciDevice_BaseClass).Data\r\n\r\n if ($devBaseClass -eq $devprop_PciDevice_BaseClass_DisplayCtlr) {\r\n Write-Host \"Legacy Express Endpoint -- graphics controller.\"\r\n } else {\r\n Write-Host -ForegroundColor Red -BackgroundColor Black \"Legacy, non-VGA PCI device. Not assignable.\"\r\n continue\r\n }\r\n } else {\r\n if ($devtype -eq $devprop_PciDevice_DeviceType_PciExpressTreatedAsPci) {\r\n Write-Host -ForegroundColor Red -BackgroundColor Black \"BIOS kept control of PCI Express for this device. Not assignable.\"\r\n } else {\r\n Write-Host -ForegroundColor Red -BackgroundColor Black \"Old-style PCI device, switch port, etc. Not assignable.\"\r\n }\r\n continue\r\n }\r\n }\r\n\r\n $locationpath = ($pcidev | get-pnpdeviceproperty DEVPKEY_Device_LocationPaths).data[0]\r\n\r\n #\r\n # If the device is disabled, we can't check the resources, report a warning and continue on.\r\n #\r\n #\r\n if ($pcidev.ConfigManagerErrorCode -eq \"CM_PROB_DISABLED\")\r\n {\r\n Write-Host -ForegroundColor Yellow -BackgroundColor Black \"Device is Disabled, unable to check resource requirements, it may be assignable.\"\r\n Write-Host -ForegroundColor Yellow -BackgroundColor Black \"Enable the device and rerun this script to confirm.\"\r\n $locationpath\r\n continue\r\n }\r\n\r\n #\r\n # Now do a check for the interrupts that the device uses. Line-based interrupts\r\n # aren't assignable.\r\n #\r\n $doubleslashDevId = \"*\" + $pcidev.PNPDeviceID.Replace(\"\\\",\"\\\\\") + \"*\"\r\n $irqAssignments = gwmi -query \"select * from Win32_PnPAllocatedResource\" | Where-Object {$_.__RELPATH -like \"*Win32_IRQResource*\"} | Where-Object {$_.Dependent -like $doubleslashDevId}\r\n\r\n #$irqAssignments | Format-Table -Property __RELPATH\r\n\r\n if ($irqAssignments.length -eq 0) {\r\n Write-Host -ForegroundColor Green -BackgroundColor Black \" And it has no interrupts at all -- assignment can work.\"\r\n } else {\r\n #\r\n # Find the message-signaled interrupts. They are reported with a really big number in\r\n # decimal, one which always happens to start with \"42949...\".\r\n #\r\n $msiAssignments = $irqAssignments | Where-Object {$_.Antecedent -like \"*IRQNumber=42949*\"}\r\n \r\n #$msiAssignments | Format-Table -Property __RELPATH\r\n\r\n if ($msiAssignments.length -eq 0) {\r\n Write-Host -ForegroundColor Red -BackgroundColor Black \"All of the interrupts are line-based, no assignment can work.\"\r\n continue\r\n } else {\r\n Write-Host -ForegroundColor Green -BackgroundColor Black \" And its interrupts are message-based, assignment can work.\"\r\n }\r\n }\r\n\r\n #\r\n # Check how much MMIO space the device needs\r\n # not strictly an issue devices, but very useful when you want to set MMIO gap sizes\r\n #\r\n\r\n $mmioAssignments = gwmi -query \"select * from Win32_PnPAllocatedResource\" | Where-Object {$_.__RELPATH -like \"*Win32_DeviceMemoryAddress*\"} | Where-Object {$_.Dependent -like $doubleslashDevId}\r\n $mmioTotal = 0\r\n foreach ($mem in $mmioAssignments) \r\n {\r\n $baseAdd =$mem.Antecedent.SubString($mem.Antecedent.IndexOf(\"\"\"\")+1)\r\n $baseAdd=$baseAdd.SubString(0,$baseAdd.IndexOf(\"\"\"\"))\r\n $mmioRange = gwmi -query \"select * from Win32_DeviceMemoryAddress\" | Where-Object{$_.StartingAddress -like $baseAdd}\r\n $mmioTotal = $mmioTotal + $mmioRange.EndingAddress - $mmioRange.StartingAddress\r\n }\r\n if ($mmioTotal -eq 0)\r\n {\r\n Write-Host -ForegroundColor Green -BackgroundColor Black \" And it has no MMIO space\"\r\n } else {\r\n \t [int]$mmioMB = [math]::ceiling($mmioTotal / 1MB)\r\n Write-Host -ForegroundColor Green -BackgroundColor Black \" And it requires at least:\" $mmioMB \"MB of MMIO gap space\"\r\n }\r\n \r\n\r\n\r\n #\r\n # Print out the location path, as that's the way to refer to this device that won't\r\n # change even if you add or remove devices from the machine or change the way that\r\n # the BIOS is configured.\r\n #\r\n\t\r\n\t$locationpath = $pcidev.FriendlyName + \"`n Location Path: \" + $locationpath + \"`n MMIO Space: \" + $mmioMB + \" MiB`n`n\"\r\n $locationpath\r\n \r\n\t\r\n}\r\n\r\n#\r\n# Now look at the host as a whole. Asking whether the host supports SR-IOV\r\n# is mostly equivalent to asking whether it supports Discrete Device\r\n# Assignment.\r\n#\r\nif ((Get-VMHost).IovSupport -eq $false) {\r\n Write-Host \"\"\r\n write-host \"Unfortunately, this machine doesn't support using them in a VM.\"\r\n Write-Host \"\"\r\n (Get-VMHost).IovSupportReasons\r\n}"; + using (PowerShell powerShell = PowerShell.Create()) + { + powerShell.AddScript(script); + powerShell.AddCommand("Out-String"); + Collection PSOutput = powerShell.Invoke(); + StringBuilder stringBuilder = new StringBuilder(); + foreach (PSObject pSObject in PSOutput) + stringBuilder.AppendLine(pSObject.ToString()); + richTextBox1.Text = stringBuilder.ToString() + "\n\n"; + } + } + } +} diff --git a/hyperv-passthrough/DisplayAssignableDevices.resx b/hyperv-passthrough/DisplayAssignableDevices.resx new file mode 100644 index 000000000..cddba4ac8 --- /dev/null +++ b/hyperv-passthrough/DisplayAssignableDevices.resx @@ -0,0 +1,480 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + 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 + + + \ No newline at end of file diff --git a/hyperv-passthrough/MainForm.Designer.cs b/hyperv-passthrough/MainForm.Designer.cs index 3c023b334..6712f2039 100644 --- a/hyperv-passthrough/MainForm.Designer.cs +++ b/hyperv-passthrough/MainForm.Designer.cs @@ -1,4 +1,4 @@ -namespace DiscreteDeviceAssigner +namespace HyperVPassthoughDevice { partial class MainForm { @@ -22,7 +22,6 @@ private void InitializeComponent() this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.其它toolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.GCCTtoolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.removegpupass = new System.Windows.Forms.ToolStripMenuItem(); this.changeMemoryLocationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.添加设备ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -30,6 +29,8 @@ private void InitializeComponent() this.复制地址toolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.刷新列表toolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.removeAllAssignedDevicesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.checkAssignableDevicesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.contextMenuStrip.SuspendLayout(); this.SuspendLayout(); // @@ -72,15 +73,17 @@ private void InitializeComponent() this.移除设备ToolStripMenuItem, this.复制地址toolStripMenuItem, this.toolStripSeparator1, - this.刷新列表toolStripMenuItem}); + this.刷新列表toolStripMenuItem, + this.removeAllAssignedDevicesToolStripMenuItem, + this.checkAssignableDevicesToolStripMenuItem}); this.contextMenuStrip.Name = "contextMenuStrip"; resources.ApplyResources(this.contextMenuStrip, "contextMenuStrip"); + this.contextMenuStrip.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip_Opening); // // 其它toolStripMenuItem // this.其它toolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.GCCTtoolStripMenuItem, - this.removegpupass, this.changeMemoryLocationToolStripMenuItem}); this.其它toolStripMenuItem.Name = "其它toolStripMenuItem"; resources.ApplyResources(this.其它toolStripMenuItem, "其它toolStripMenuItem"); @@ -94,12 +97,6 @@ private void InitializeComponent() resources.ApplyResources(this.GCCTtoolStripMenuItem, "GCCTtoolStripMenuItem"); this.GCCTtoolStripMenuItem.Click += new System.EventHandler(this.GCCTtoolStripMenuItem_Click); // - // removegpupass - // - this.removegpupass.Name = "removegpupass"; - resources.ApplyResources(this.removegpupass, "removegpupass"); - this.removegpupass.Click += new System.EventHandler(this.removegpupass_Click); - // // changeMemoryLocationToolStripMenuItem // this.changeMemoryLocationToolStripMenuItem.Name = "changeMemoryLocationToolStripMenuItem"; @@ -140,6 +137,18 @@ private void InitializeComponent() resources.ApplyResources(this.刷新列表toolStripMenuItem, "刷新列表toolStripMenuItem"); this.刷新列表toolStripMenuItem.Click += new System.EventHandler(this.刷新列表ToolStripMenuItem_Click); // + // removeAllAssignedDevicesToolStripMenuItem + // + this.removeAllAssignedDevicesToolStripMenuItem.Name = "removeAllAssignedDevicesToolStripMenuItem"; + resources.ApplyResources(this.removeAllAssignedDevicesToolStripMenuItem, "removeAllAssignedDevicesToolStripMenuItem"); + this.removeAllAssignedDevicesToolStripMenuItem.Click += new System.EventHandler(this.RemoveAllDev); + // + // checkAssignableDevicesToolStripMenuItem + // + this.checkAssignableDevicesToolStripMenuItem.Name = "checkAssignableDevicesToolStripMenuItem"; + resources.ApplyResources(this.checkAssignableDevicesToolStripMenuItem, "checkAssignableDevicesToolStripMenuItem"); + this.checkAssignableDevicesToolStripMenuItem.Click += new System.EventHandler(this.CheckAssignableDevice); + // // MainForm // resources.ApplyResources(this, "$this"); @@ -171,8 +180,9 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem 复制地址toolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem 其它toolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem GCCTtoolStripMenuItem; - private System.Windows.Forms.ToolStripMenuItem removegpupass; private System.Windows.Forms.ToolStripMenuItem changeMemoryLocationToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem removeAllAssignedDevicesToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem checkAssignableDevicesToolStripMenuItem; } } diff --git a/hyperv-passthrough/MainForm.cs b/hyperv-passthrough/MainForm.cs index 153c1f377..ac93b7f1a 100644 --- a/hyperv-passthrough/MainForm.cs +++ b/hyperv-passthrough/MainForm.cs @@ -1,12 +1,12 @@ -using Microsoft.Management.Infrastructure; +using HyperVpassthroughdev; +using Microsoft.Management.Infrastructure; using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Windows.Forms; using DeviceData = System.Tuple; -using HyperVpassthroughdev; -namespace DiscreteDeviceAssigner +namespace HyperVPassthoughDevice { public partial class MainForm : Form { @@ -139,7 +139,8 @@ private void 添加设备ToolStripMenuItem_Click(object sender, EventArgs e) private void 移除设备ToolStripMenuItem_Click(object sender, EventArgs e) { - try { + try + { DeviceData data = contextMenuStrip.Tag as DeviceData; if (MessageBox.Show("Perform removal device " + data.Item2.Name + " from " + data.Item1.Name, "Confirm?", MessageBoxButtons.YesNo) == DialogResult.Yes) { @@ -154,8 +155,9 @@ private void 移除设备ToolStripMenuItem_Click(object sender, EventArgs e) UpdateVM(); } } - catch (Exception ex) { - MessageBox.Show($"The specific VM has no device selected, nor the error has occured. \nError:" + ex.Message, $"Message", MessageBoxButtons.OK, MessageBoxIcon.Error); + catch (Exception ex) + { + MessageBox.Show($"The specific VM has no device selected, nor the error has occured. \nError:" + ex.Message, $"Message", MessageBoxButtons.OK, MessageBoxIcon.Error); } } @@ -186,29 +188,61 @@ private void GCCTtoolStripMenuItem_Click(object sender, EventArgs e) } } - private void listView1_SelectedIndexChanged(object sender, EventArgs e) + private void memchangeloc(object sender, EventArgs e) { + DeviceData data = contextMenuStrip.Tag as DeviceData; + try + { + UInt32[] LowHighCollection = new SetMemory().ReturnResult(); + UInt32 MemorySetLow = LowHighCollection[0]; + UInt32 MemorySetHigh = LowHighCollection[1]; + PowerShellWrapper.SetLowMemoryMappedIoSpace(data.Item1, MemorySetLow * 1024 * 1024); + PowerShellWrapper.SetHighMemoryMappedIoSpace(data.Item1, MemorySetHigh * 1024 * 1024); + } + catch (Exception ex) + { + MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK); + } } - private void 其它toolStripMenuItem_Click(object sender, EventArgs e) + private void RemoveAllDev(object sender, EventArgs e) + { + if (MessageBox.Show($"This will stop all virtual machines and perform the removal of all assigned device.\nContinue?", $"Warning", MessageBoxButtons.YesNoCancel) == DialogResult.Yes) + { + try + { + PowerShellWrapper.StartRemovalAssignedDevices(); + UpdateVM(); + } + catch (Exception exception) + { + MessageBox.Show($"An error has occured:\n\n" + exception, $"Error", MessageBoxButtons.OK); + } + } + } + + private void CheckAssignableDevice(object sender, EventArgs e) + { + new DisplayAssignableDevices(); + } + + /* + * Security functions + */ + private void listView1_SelectedIndexChanged(object sender, EventArgs e) { } - private void removegpupass_Click(object sender, EventArgs e) + private void 其它toolStripMenuItem_Click(object sender, EventArgs e) { - DeviceData data = contextMenuStrip.Tag as DeviceData; - PowerShellWrapper.RemoveGpuPartitioning(data.Item1); + } - private void memchangeloc(object sender, EventArgs e) + private void contextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e) { - DeviceData data = contextMenuStrip.Tag as DeviceData; - UInt32 MemorySet = new SetMemory().ReturnResult(); - PowerShellWrapper.SetLowMemoryMappedIoSpace(data.Item1); - PowerShellWrapper.SetHighMemoryMappedIoSpace(data.Item1, MemorySet * 1024 * 1024); - + } } } \ No newline at end of file diff --git a/hyperv-passthrough/MainForm.resx b/hyperv-passthrough/MainForm.resx index 8ff72bd61..4d72839cd 100644 --- a/hyperv-passthrough/MainForm.resx +++ b/hyperv-passthrough/MainForm.resx @@ -165,62 +165,56 @@ 21, 18 - - 228, 22 - - - GuestControlledCacheTypes - - - 228, 22 - - - Remove GPU Passed through - - - 228, 22 - - - Change Memory Location - - 182, 22 + 228, 22 Other settings - 179, 6 + 225, 6 - 182, 22 + 228, 22 Add device - 182, 22 + 228, 22 Remove device - 182, 22 + 228, 22 Copy device address - 179, 6 + 225, 6 - 182, 22 + 228, 22 Refresh + + 228, 22 + + + Remove All Assigned Devices + + + 228, 22 + + + Check Assignable Devices + - 183, 148 + 229, 192 contextMenuStrip @@ -228,6 +222,18 @@ System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 222, 22 + + + GuestControlledCacheTypes + + + 222, 22 + + + Change Memory Location + True @@ -638,12 +644,6 @@ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - removegpupass - - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - changeMemoryLocationToolStripMenuItem @@ -686,6 +686,18 @@ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + removeAllAssignedDevicesToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + checkAssignableDevicesToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + MainForm diff --git a/hyperv-passthrough/PnpDeviceForm.Designer.cs b/hyperv-passthrough/PnpDeviceForm.Designer.cs index 15527c2f1..5a1f4dc76 100644 --- a/hyperv-passthrough/PnpDeviceForm.Designer.cs +++ b/hyperv-passthrough/PnpDeviceForm.Designer.cs @@ -1,4 +1,4 @@ -namespace DiscreteDeviceAssigner +namespace HyperVPassthoughDevice { partial class PnpDeviceForm { diff --git a/hyperv-passthrough/PnpDeviceForm.cs b/hyperv-passthrough/PnpDeviceForm.cs index 41531ee2d..909a130a4 100644 --- a/hyperv-passthrough/PnpDeviceForm.cs +++ b/hyperv-passthrough/PnpDeviceForm.cs @@ -3,7 +3,7 @@ using System.Collections.ObjectModel; using System.Windows.Forms; -namespace DiscreteDeviceAssigner +namespace HyperVPassthoughDevice { public partial class PnpDeviceForm : Form { diff --git a/hyperv-passthrough/PowerShellWrapper.cs b/hyperv-passthrough/PowerShellWrapper.cs index d6de4253e..4ec3fc70c 100644 --- a/hyperv-passthrough/PowerShellWrapper.cs +++ b/hyperv-passthrough/PowerShellWrapper.cs @@ -1,13 +1,14 @@ using Microsoft.HyperV.PowerShell; using Microsoft.Management.Infrastructure; using System; +using System.Text; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Windows.Forms; -namespace DiscreteDeviceAssigner +namespace HyperVPassthoughDevice { class PowerShellWrapper { @@ -101,9 +102,9 @@ public static void SetGuestControlledCacheTypes(VirtualMachine vm, bool value) } } - public static void SetLowMemoryMappedIoSpace(VirtualMachine vm) + public static void SetLowMemoryMappedIoSpace(VirtualMachine vm, uint bytes) { - RunScript("Set-VM \"" + vm.Name + "\" -LowMemoryMappedIoSpace " + Convert.ToInt32("512") * 1024 * 1024); + RunScript("Set-VM \"" + vm.Name + "\" -LowMemoryMappedIoSpace " + bytes); } public static void SetHighMemoryMappedIoSpace(VirtualMachine vm, uint bytes) @@ -130,18 +131,17 @@ public static void GpuPartitioning(VirtualMachine vm, CimInstance device) { string DeviceIDInstance = device.CimInstanceProperties["DeviceId"] != null ? device.CimInstanceProperties["DeviceId"].Value as string : null; var locationPath = GetPnpDeviceLocationPath(DeviceIDInstance)[0]; - + //securing devices from crashing - try + try { RunScript("Set-VM -Name \"" + vm.Name + "\" -AutomaticStopAction TurnOff"); - RunScript("Set-VM -GuestControlledCacheTypes $true -VMName \"" + vm.Name + "\""); - RunScript("Set-VM -LowMemoryMappedIoSpace 3Gb -VMName \"" + vm.Name + "\""); - RunScript("Set-VM -HighMemoryMappedIoSpace 33280Mb -VMName \"" + vm.Name + "\""); - } catch + RunScript("Set-VM -GuestControlledCacheTypes $true -VMName \"" + vm.Name + "\""); //Needed + } + catch { MessageBox.Show($"Setting VM is failed, failing the application"); //Securing the devices - throw new InvalidOperationException("Operation failed! Raise function GpuPartitioning (line 129), with the debug DeviceIDInstance: " + DeviceIDInstance); + throw new InvalidOperationException("Operation failed! Raise function GpuPartitioning (line 143), with the debug DeviceIDInstance: " + DeviceIDInstance); } try @@ -149,10 +149,11 @@ public static void GpuPartitioning(VirtualMachine vm, CimInstance device) RunScript("Disable-PnpDevice -InstanceId \"" + DeviceIDInstance + "\" -Confirm:$false"); RunScript("Dismount-VMHostAssignableDevice -Force -LocationPath \"" + locationPath + "\""); RunScript("Add-VMAssignableDevice -LocationPath \"" + locationPath + "\" -VMName \"" + vm.Name + "\""); - } catch + } + catch { MessageBox.Show($"Disable device is failed, failing the application"); //Securing the devices and VMs - throw new InvalidOperationException("Operation failed! Raise function GpuPartitioning (line 129), with the debug locationPath: " + locationPath); + throw new InvalidOperationException("Operation failed! Raise function GpuPartitioning (line 154), with the debug locationPath: " + locationPath); } } @@ -206,9 +207,14 @@ public static void AddVMAssignableDevice(VirtualMachine vm, CimInstance device) RunScript("Add-VMAssignableDevice -LocationPath \"" + locationPaths[0] + "\" -VMName \"" + vm.Name + "\""); } - internal static void GpuPartitioning(VirtualMachine item1, VMAssignedDevice item2) + public static void StartRemovalAssignedDevices() { - throw new NotImplementedException(); + Collection HostDevicesAssigned = RunScript("Get-VMHostAssignableDevice | Select-Object -ExpandProperty LocationPath"); + foreach (PSObject obj in HostDevicesAssigned) + { + //MessageBox.Show("Device: " + obj.ToString(), $"Notification", MessageBoxButtons.OK); + RunScript("Mount-VMHostAssignableDevice -LocationPath \"" + obj.ToString() + "\""); + } } } } diff --git a/hyperv-passthrough/Program.cs b/hyperv-passthrough/Program.cs index 85b6c18f2..ba03f6234 100644 --- a/hyperv-passthrough/Program.cs +++ b/hyperv-passthrough/Program.cs @@ -1,7 +1,7 @@ using System; using System.Windows.Forms; -namespace DiscreteDeviceAssigner +namespace HyperVPassthoughDevice { static class Program { diff --git a/hyperv-passthrough/Properties/Resources.Designer.cs b/hyperv-passthrough/Properties/Resources.Designer.cs index 19d855052..e34daabbc 100644 --- a/hyperv-passthrough/Properties/Resources.Designer.cs +++ b/hyperv-passthrough/Properties/Resources.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace HyperVpassthroughdev.Properties { +namespace HyperVPassthoughDevice.Properties { using System; @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HyperVpassthroughdev.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HyperVPassthoughDevice.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/hyperv-passthrough/Properties/Settings.Designer.cs b/hyperv-passthrough/Properties/Settings.Designer.cs index c4ab87d36..322a7f3cf 100644 --- a/hyperv-passthrough/Properties/Settings.Designer.cs +++ b/hyperv-passthrough/Properties/Settings.Designer.cs @@ -8,11 +8,11 @@ // //------------------------------------------------------------------------------ -namespace HyperVpassthroughdev.Properties { +namespace HyperVPassthoughDevice.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/hyperv-passthrough/SetMemory.Designer.cs b/hyperv-passthrough/SetMemory.Designer.cs index a40d0a637..af2e176cb 100644 --- a/hyperv-passthrough/SetMemory.Designer.cs +++ b/hyperv-passthrough/SetMemory.Designer.cs @@ -32,6 +32,7 @@ private void InitializeComponent() this.labelhimem = new System.Windows.Forms.Label(); this.HighMem = new System.Windows.Forms.TextBox(); this.OK = new System.Windows.Forms.Button(); + this.LowMem = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); // @@ -40,25 +41,25 @@ private void InitializeComponent() this.labelhimem.AutoSize = true; this.labelhimem.Location = new System.Drawing.Point(2, 9); this.labelhimem.Name = "labelhimem"; - this.labelhimem.Size = new System.Drawing.Size(69, 13); + this.labelhimem.Size = new System.Drawing.Size(96, 13); this.labelhimem.TabIndex = 0; - this.labelhimem.Text = "High Memory"; - this.labelhimem.Click += new System.EventHandler(this.label1_Click); + this.labelhimem.Text = "High Memory (MiB)"; + this.labelhimem.Click += new System.EventHandler(this.labelhimem_Click); // // HighMem // this.HighMem.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.HighMem.Location = new System.Drawing.Point(78, 6); + this.HighMem.Location = new System.Drawing.Point(104, 6); this.HighMem.Name = "HighMem"; - this.HighMem.Size = new System.Drawing.Size(156, 20); + this.HighMem.Size = new System.Drawing.Size(155, 20); this.HighMem.TabIndex = 2; this.HighMem.TextChanged += new System.EventHandler(this.HighMemchanges); // // OK // - this.OK.Location = new System.Drawing.Point(78, 58); + this.OK.Location = new System.Drawing.Point(104, 62); this.OK.Name = "OK"; this.OK.Size = new System.Drawing.Size(75, 26); this.OK.TabIndex = 4; @@ -66,22 +67,34 @@ private void InitializeComponent() this.OK.UseVisualStyleBackColor = true; this.OK.Click += new System.EventHandler(this.OKClick); // + // LowMem + // + this.LowMem.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.LowMem.Cursor = System.Windows.Forms.Cursors.IBeam; + this.LowMem.Location = new System.Drawing.Point(104, 32); + this.LowMem.Name = "LowMem"; + this.LowMem.Size = new System.Drawing.Size(155, 20); + this.LowMem.TabIndex = 5; + this.LowMem.TextChanged += new System.EventHandler(this.LowMemChanges); + // // label1 // this.label1.AutoSize = true; - this.label1.ForeColor = System.Drawing.Color.DarkRed; - this.label1.Location = new System.Drawing.Point(5, 35); + this.label1.Location = new System.Drawing.Point(4, 36); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(235, 13); - this.label1.TabIndex = 5; - this.label1.Text = "By default, Low Memory location is set to 512Mb"; + this.label1.Size = new System.Drawing.Size(94, 13); + this.label1.TabIndex = 6; + this.label1.Text = "Low Memory (MiB)"; // // SetMemory // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(246, 96); + this.ClientSize = new System.Drawing.Size(271, 100); this.Controls.Add(this.label1); + this.Controls.Add(this.LowMem); this.Controls.Add(this.OK); this.Controls.Add(this.HighMem); this.Controls.Add(this.labelhimem); @@ -100,6 +113,7 @@ private void InitializeComponent() private System.Windows.Forms.Label labelhimem; private System.Windows.Forms.Button OK; private System.Windows.Forms.TextBox HighMem; + private System.Windows.Forms.TextBox LowMem; private System.Windows.Forms.Label label1; } } \ No newline at end of file diff --git a/hyperv-passthrough/SetMemory.cs b/hyperv-passthrough/SetMemory.cs index f23f7ca08..343790977 100644 --- a/hyperv-passthrough/SetMemory.cs +++ b/hyperv-passthrough/SetMemory.cs @@ -8,11 +8,7 @@ public partial class SetMemory : Form public SetMemory() { InitializeComponent(); - } - - private void label1_Click(object sender, EventArgs e) - { - + ShowDialog(); } private void HighMemchanges(object sender, EventArgs e) @@ -22,31 +18,23 @@ private void HighMemchanges(object sender, EventArgs e) public void OKClick(object sender, EventArgs e) { - try - { - if (Convert.ToInt32(HighMem.Text) < Convert.ToInt32("512")) - { - MessageBox.Show($"The high memory location must be higher than 512Mib", $"Error", MessageBoxButtons.OK); - } - else - { - Close(); - } - } - catch (Exception exp) - { - MessageBox.Show($"An error has occurred: \n" + exp, "Error", MessageBoxButtons.OK); - } + Close(); + } + public UInt32[] ReturnResult() + { + UInt32 LowMemSet = (uint)Convert.ToInt32(LowMem.Text); + UInt32 HighMemSet = (uint)Convert.ToInt32(HighMem.Text); + UInt32[] Memory = { LowMemSet, HighMemSet }; + return Memory; } - public UInt32 ReturnResult() + private void LowMemChanges(object sender, EventArgs e) { - ShowDialog(); - return (uint)Convert.ToInt32(HighMem.Text); + } - private void label1_Click_1(object sender, EventArgs e) + private void labelhimem_Click(object sender, EventArgs e) { } diff --git a/hyperv-passthrough/SetMemory.resx b/hyperv-passthrough/SetMemory.resx index 7108d3bfd..cddba4ac8 100644 --- a/hyperv-passthrough/SetMemory.resx +++ b/hyperv-passthrough/SetMemory.resx @@ -117,9 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True - diff --git a/hyperv-passthrough/bin/Hyper-V Device Passthrough.exe.CodeAnalysisLog.xml b/hyperv-passthrough/bin/Hyper-V Device Passthrough.exe.CodeAnalysisLog.xml new file mode 100644 index 000000000..e2b874cd7 --- /dev/null +++ b/hyperv-passthrough/bin/Hyper-V Device Passthrough.exe.CodeAnalysisLog.xml @@ -0,0 +1,28 @@ + + + + + Category + Certainty + Collapse All + Check Id + Error + error(s) + Expand All + Help + Line + message(s) + [Location not stored in Pdb] + Project + Resolution + Rule + Rule File + Rule Description + Source + Status + Target + Warning + warning(s) + Code Analysis Report + + diff --git a/hyperv-passthrough/bin/Hyper-V Device Passthrough.exe.config b/hyperv-passthrough/bin/Hyper-V Device Passthrough.exe.config new file mode 100644 index 000000000..1243f4282 --- /dev/null +++ b/hyperv-passthrough/bin/Hyper-V Device Passthrough.exe.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/hyperv-passthrough/bin/Hyper-V Device Passthrough.exe.lastcodeanalysissucceeded b/hyperv-passthrough/bin/Hyper-V Device Passthrough.exe.lastcodeanalysissucceeded new file mode 100644 index 000000000..e69de29bb diff --git a/hyperv-passthrough/hypervpassth.csproj b/hyperv-passthrough/hypervpassth.csproj index 7d2c03717..19a244471 100644 --- a/hyperv-passthrough/hypervpassth.csproj +++ b/hyperv-passthrough/hypervpassth.csproj @@ -7,7 +7,7 @@ {F2A2FC53-F5E9-4350-8D9B-98269DF4C9B1} WinExe Properties - HyperVpassthroughdev + HyperVPassthoughDevice Hyper-V Device Passthrough v4.8 512 @@ -72,7 +72,7 @@ true - DiscreteDeviceAssigner.Program + HyperVPassthoughDevice.Program main.ico @@ -103,7 +103,7 @@ ..\!bin!\Hyper-V Device Passthrough\ - CODE_ANALYSIS;TRACE + CODE_ANALYSIS;CODE_ANALYSIS true true pdbonly @@ -111,7 +111,7 @@ true 7.3 prompt - MixedRecommendedRules.ruleset + AllRules.ruleset true @@ -142,6 +142,12 @@ + + Form + + + DisplayAssignableDevices.cs + Form @@ -163,6 +169,9 @@ SetMemory.cs + + DisplayAssignableDevices.cs + MainForm.cs @@ -182,7 +191,6 @@ SetMemory.cs - SettingsSingleFileGenerator diff --git a/vlmcsd-beta/license-manager/KmsServer.xaml.cs b/vlmcsd-beta/license-manager/KmsServer.xaml.cs index 5de848651..e15385081 100644 --- a/vlmcsd-beta/license-manager/KmsServer.xaml.cs +++ b/vlmcsd-beta/license-manager/KmsServer.xaml.cs @@ -100,9 +100,6 @@ private set Dispatcher.InvokeAsync(() => { -#if DEBUG - Debug.Assert(UseTap.IsChecked != null, "UseTap.IsChecked != null"); -#endif // DEBUG ButtonStartStop.Content = (value ? "Stop" : "Start") + " Server"; TextBoxPort.IsEnabled = !value; @@ -431,52 +428,11 @@ private void Button_StartStop_Click(object sender, RoutedEventArgs e) } IsRunning = true; - KmsLists.LoadDatabase(); -#if DEBUG - Debug.Assert(CheckBoxPreCharge.IsChecked != null, "CheckBoxPreCharge.IsChecked != null"); -#endif foreach (AppItem appItem in KmsLists.AppItemList) { appItem.PreCharge(CheckBoxPreCharge.IsChecked.Value); } - //if - //( - // !string.IsNullOrWhiteSpace(TextBoxWindowsPid.Text) && - // !string.IsNullOrWhiteSpace(TextBoxOffice2010Pid.Text) && - // !string.IsNullOrWhiteSpace(TextBoxOffice2013Pid.Text) && - // !string.IsNullOrWhiteSpace(TextBoxOffice2016Pid.Text) && - // !string.IsNullOrWhiteSpace(TextBoxWindowsChinaGovPid.Text) - //) - //{ - // var winEpid = new EPid(TextBoxWindowsPid.Text); - // var o2010Epid = new EPid(TextBoxOffice2010Pid.Text); - // var o2013Epid = new EPid(TextBoxOffice2013Pid.Text); - // var o2016Epid = new EPid(TextBoxOffice2016Pid.Text); - // var winChinaGovEpid = new EPid(TextBoxWindowsChinaGovPid.Text); - - // if - // ( - // winEpid.LcidString != o2010Epid.LcidString || - // o2010Epid.LcidString != o2013Epid.LcidString || - // o2013Epid.LcidString != o2016Epid.LcidString || - // o2016Epid.LcidString != winChinaGovEpid.LcidString - // ) - // { - // TextBoxInfoText.AppendText($"{nl}Warning: LCIDs of all EPIDs must be the same."); - // } - // if - // ( - // winEpid.OsBuildString != o2010Epid.OsBuildString || - // o2010Epid.OsBuildString != o2013Epid.OsBuildString || - // o2013Epid.OsBuildString != o2016Epid.OsBuildString || - // o2016Epid.OsBuildString != winChinaGovEpid.OsBuildString - // ) - // { - // TextBoxInfoText.AppendText($"{nl}Warning: OS build numbers of all EPIDs must be the same."); - // } - //} - new Thread(KmsServerThread).Start(); } else @@ -516,11 +472,6 @@ private void ActivationInterval_TextChanged(object sender, TextChangedEventArgs private void UseTap_Click(object sender, RoutedEventArgs e) { CheckBox checkBox = (CheckBox)sender; - -#if DEBUG - Debug.Assert(checkBox.IsChecked != null, "checkBox.IsChecked != null"); -#endif // DEBUG - TextBoxTapIp.Visibility = ComboBoxTap.Visibility = checkBox.IsChecked.Value ? Visibility.Visible : Visibility.Collapsed; } diff --git a/vlmcsd-beta/license-manager/ProductBrowser.xaml.cs b/vlmcsd-beta/license-manager/ProductBrowser.xaml.cs index 0566fc6f1..25c335168 100644 --- a/vlmcsd-beta/license-manager/ProductBrowser.xaml.cs +++ b/vlmcsd-beta/license-manager/ProductBrowser.xaml.cs @@ -1081,9 +1081,6 @@ private void Button_Install_Click(object sender, RoutedEventArgs e) private void CheckBoxHideInput_Click(object sender, RoutedEventArgs e) { -#if DEBUG - Debug.Assert(CheckBoxHideInput.IsChecked != null, "CheckBoxHideInput.IsChecked != null"); -#endif if (CheckBoxHideInput.IsChecked.Value) { PassWordBoxEpidInput.Visibility = Visibility.Visible;