├── PolicyPlus ├── Version.vb ├── App.config ├── My Project │ ├── Settings.settings │ ├── Application.myapp │ ├── AssemblyInfo.vb │ ├── Application.Designer.vb │ ├── Resources.Designer.vb │ ├── Settings.Designer.vb │ ├── app.manifest │ └── Resources.resx ├── BitReinterpretation.vb ├── EditPolMultiStringData.vb ├── EditPolStringData.vb ├── EditPolKey.vb ├── SystemInfo.vb ├── Privilege.vb ├── LanguageOptions.vb ├── XmlExtensions.vb ├── ConfigurationStorage.vb ├── PolicyPlus.sln ├── OpenSection.vb ├── EditPolValue.vb ├── DetailCategory.vb ├── EditPolDelete.vb ├── LoadedAdmx.vb ├── CompiledStructures.vb ├── ExportReg.vb ├── LoadedSupportDefinitions.vb ├── AdmxStructures.vb ├── OpenUserGpo.vb ├── PInvoke.vb ├── ListEditor.vb ├── DetailPolicy.vb ├── PresentationStructures.vb ├── ImportReg.vb ├── ImportSpol.vb ├── OpenUserRegistry.vb ├── DetailProduct.vb ├── FindByRegistry.vb ├── EditPolNumericData.vb ├── OpenAdmxFolder.vb ├── DetailAdmx.vb ├── PolicyStructures.vb ├── DetailSupport.vb ├── InspectSpolFragment.vb ├── EditPolKey.Designer.vb ├── FindById.Designer.vb ├── FindById.vb ├── LoadedProducts.vb ├── OpenUserRegistry.Designer.vb ├── EditPolStringData.Designer.vb ├── OpenSection.Designer.vb ├── LanguageOptions.Designer.vb ├── FindByRegistry.Designer.vb ├── EditPolMultiStringData.Designer.vb ├── EditPolValue.Designer.vb ├── LoadedAdmx.Designer.vb ├── ImportReg.Designer.vb ├── OpenUserGpo.Designer.vb ├── FindByText.vb ├── LoadedSupportDefinitions.Designer.vb ├── EditPolNumericData.Designer.vb ├── FindByText.Designer.vb ├── InspectPolicyElements.Designer.vb ├── EditPolDelete.Designer.vb ├── ListEditor.Designer.vb ├── ExportReg.Designer.vb ├── ImportSpol.Designer.vb ├── EditPol.resx ├── FindById.resx └── FindByText.resx ├── version.bat ├── INSTALL.md ├── ATTRIBUTION.md ├── COMPILE.md ├── .github └── workflows │ └── latest.yml ├── Docs └── Lexicon.md ├── README.md └── .gitignore /PolicyPlus/Version.vb: -------------------------------------------------------------------------------- 1 | ' DO NOT MODIFY THIS FILE. It will be overwritten by version.bat. 2 | Module VersionHolder 3 | Public Const Version As String = "" 4 | End Module 5 | -------------------------------------------------------------------------------- /PolicyPlus/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /version.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set VF=PolicyPlus\Version.vb 3 | echo ' DO NOT MODIFY THIS FILE. To update it, run version.bat again. > %VF% 4 | echo Module VersionHolder >> %VF% 5 | echo Public Const Version As String = ^" >> %VF% 6 | git describe --always >> %VF% 7 | echo ^" >> %VF% 8 | echo End Module >> %VF% -------------------------------------------------------------------------------- /PolicyPlus/My Project/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # Installing Policy Plus 2 | Policy Plus requires the .NET Framework, version 4.5 or greater. If that doesn't already come with your Windows version, you can [download it from Microsoft](https://www.microsoft.com/en-us/download/details.aspx?id=30653). 3 | You'll probably have to reboot your computer after installing the Framework. 4 | 5 | Once that's done, you can run the Policy Plus executable without any other installation. -------------------------------------------------------------------------------- /PolicyPlus/BitReinterpretation.vb: -------------------------------------------------------------------------------- 1 | Imports System.Runtime.InteropServices 2 | 3 | 4 | Public Structure ReinterpretableDword 5 | Public Signed As Integer 6 | Public Unsigned As UInteger 7 | End Structure 8 | 9 | 10 | Public Structure ReinterpretableQword 11 | Public Signed As Long 12 | Public Unsigned As ULong 13 | End Structure -------------------------------------------------------------------------------- /PolicyPlus/My Project/Application.myapp: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | Main 5 | false 6 | 0 7 | true 8 | 0 9 | true 10 | -------------------------------------------------------------------------------- /PolicyPlus/EditPolMultiStringData.vb: -------------------------------------------------------------------------------- 1 | Public Class EditPolMultiStringData 2 | Private Sub EditPolMultiStringData_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown 3 | If e.KeyCode = Keys.Escape Then DialogResult = DialogResult.Cancel 4 | End Sub 5 | Public Function PresentDialog(ValueName As String, InitialData As String()) As DialogResult 6 | TextName.Text = ValueName 7 | TextData.Lines = InitialData 8 | TextData.Select() 9 | Return ShowDialog() 10 | End Function 11 | End Class -------------------------------------------------------------------------------- /PolicyPlus/EditPolStringData.vb: -------------------------------------------------------------------------------- 1 | Public Class EditPolStringData 2 | Public Function PresentDialog(ValueName As String, InitialData As String) As DialogResult 3 | TextName.Text = ValueName 4 | TextData.Text = InitialData 5 | TextData.Select() 6 | TextData.SelectAll() 7 | Return ShowDialog() 8 | End Function 9 | Private Sub EditPolStringData_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown 10 | If e.KeyCode = Keys.Escape Then DialogResult = DialogResult.Cancel 11 | End Sub 12 | End Class -------------------------------------------------------------------------------- /PolicyPlus/EditPolKey.vb: -------------------------------------------------------------------------------- 1 | Public Class EditPolKey 2 | Private Sub EditPolKey_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown 3 | If e.KeyCode = Keys.Escape Then DialogResult = DialogResult.Cancel 4 | End Sub 5 | Private Sub EditPolKey_Shown(sender As Object, e As EventArgs) Handles Me.Shown 6 | TextName.Select() 7 | TextName.SelectAll() 8 | End Sub 9 | Public Function PresentDialog(InitialName As String) As String 10 | TextName.Text = InitialName 11 | If ShowDialog() = DialogResult.OK Then 12 | Return TextName.Text 13 | Else 14 | Return "" 15 | End If 16 | End Function 17 | End Class -------------------------------------------------------------------------------- /PolicyPlus/SystemInfo.vb: -------------------------------------------------------------------------------- 1 | Public Module SystemInfo 2 | 3 | Public Function HasGroupPolicyInfrastructure() As Boolean 4 | Dim windowsEdition As Integer 5 | PInvoke.GetProductInfo(6, 0, 0, 0, windowsEdition) 6 | Return {6, &H10, &H12, &H40, &H50, 8, &HC, &H27, &H25, &HA, &HE, &H29, &HF, &H26, &H3C, 7 | &H3E, &H3B, &H3D, &H2A, &H1E, &H20, &H1F, &H4D, &H4C, &H67, &H32, &H36, &H33, 8 | &H37, &H18, &H23, &H21, 9, &H19, &H3F, &H38, &H4F, 7, &HD, &H28, &H24, &H34, &H35, 9 | &H17, &H2E, &H14, &H2B, &H60, &H15, &H2C, &H5F, &H16, &H2D, 1, &H1C, &H11, &H1D, 10 | &H79, &H7A}.Contains(windowsEdition) 11 | End Function 12 | End Module 13 | -------------------------------------------------------------------------------- /ATTRIBUTION.md: -------------------------------------------------------------------------------- 1 | # Attribution 2 | 3 | All icons are from the [FamFamFam "Silk" set](http://www.famfamfam.com/lab/icons/silk/), available under Creative Commons Attribution 2.5. 4 | 5 | Much information on the policy-related formats was gained from Microsoft documentation: [Group Policy File Formats](https://msdn.microsoft.com/en-us/library/aa374150(v=vs.85).aspx) and [Group Policy ADMX Syntax Reference Guide](https://technet.microsoft.com/en-us/library/cc753471(v=ws.10).aspx). [How to add, modify, or delete registry subkeys and values by using a .reg file](https://support.microsoft.com/en-us/help/310516/how-to-add--modify--or-delete-registry-subkeys-and-values-by-using-a) was a good start on understanding the exported Registry format. -------------------------------------------------------------------------------- /PolicyPlus/Privilege.vb: -------------------------------------------------------------------------------- 1 | Imports System.Runtime.InteropServices 2 | Public Class Privilege 3 | Public Shared Sub EnablePrivilege(Name As String) 4 | ' Enable the given Win32 privilege 5 | Dim luid As PInvokeLuid 6 | Dim priv As PInvokeTokenPrivileges 7 | Dim thisProcToken As IntPtr 8 | PInvoke.OpenProcessToken(PInvoke.GetCurrentProcess, &H28, thisProcToken) ' 0x28 = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY 9 | PInvoke.LookupPrivilegeValueW(Nothing, Name, luid) 10 | priv.Attributes = 2 ' SE_PRIVILEGE_ENABLED 11 | priv.PrivilegeCount = 1 12 | priv.LUID = luid 13 | PInvoke.AdjustTokenPrivileges(thisProcToken, False, priv, Marshal.SizeOf(priv), IntPtr.Zero, 0) 14 | PInvoke.CloseHandle(thisProcToken) 15 | End Sub 16 | End Class 17 | -------------------------------------------------------------------------------- /PolicyPlus/LanguageOptions.vb: -------------------------------------------------------------------------------- 1 | Public Class LanguageOptions 2 | Private OriginalLanguage As String 3 | Public NewLanguage As String 4 | Public Function PresentDialog(CurrentLanguage As String) As DialogResult 5 | OriginalLanguage = CurrentLanguage 6 | TextAdmlLanguage.Text = CurrentLanguage 7 | Return ShowDialog() 8 | End Function 9 | Private Sub ButtonOK_Click(sender As Object, e As EventArgs) Handles ButtonOK.Click 10 | Dim selection = TextAdmlLanguage.Text.Trim() 11 | If selection.Split("-"c).Length <> 2 Then 12 | MsgBox("Please enter a valid language code.", MsgBoxStyle.Exclamation) 13 | Exit Sub 14 | End If 15 | If selection = OriginalLanguage Then 16 | DialogResult = DialogResult.Cancel 17 | Else 18 | NewLanguage = selection 19 | DialogResult = DialogResult.OK 20 | End If 21 | End Sub 22 | End Class -------------------------------------------------------------------------------- /PolicyPlus/XmlExtensions.vb: -------------------------------------------------------------------------------- 1 | Imports System.ComponentModel 2 | Imports System.Runtime.CompilerServices 3 | Imports System.Xml 4 | Public Module XmlExtensions 5 | ' Convenience methods for parsing XML in AdmxFile and AdmlFile 6 | Public Function AttributeOrNull(Node As XmlNode, Attribute As String) As String 7 | If Node.Attributes(Attribute) Is Nothing Then Return Nothing Else Return Node.Attributes(Attribute).Value 8 | End Function 9 | Public Function AttributeOrDefault(Node As XmlNode, Attribute As String, DefaultVal As Object) As Object 10 | If Node.Attributes(Attribute) Is Nothing Then Return DefaultVal 11 | Dim converter As TypeConverter = TypeDescriptor.GetConverter(DefaultVal.GetType()) 12 | If converter.IsValid(Node.Attributes(Attribute).Value) Then 13 | Return converter.ConvertFromString(Node.Attributes(Attribute).Value) 14 | End If 15 | Return DefaultVal 16 | End Function 17 | End Module -------------------------------------------------------------------------------- /PolicyPlus/ConfigurationStorage.vb: -------------------------------------------------------------------------------- 1 | Imports Microsoft.Win32 2 | Public Class ConfigurationStorage 3 | Dim ConfigKey As RegistryKey 4 | Public Sub New(RegistryBase As RegistryHive, Subkey As String) 5 | Try 6 | ConfigKey = RegistryKey.OpenBaseKey(RegistryBase, RegistryView.Default).CreateSubKey(Subkey) 7 | Catch ex As Exception 8 | ' The key couldn't be created 9 | End Try 10 | End Sub 11 | Public Function GetValue(ValueName As String, DefaultValue As Object) As Object 12 | If ConfigKey IsNot Nothing Then Return ConfigKey.GetValue(ValueName, DefaultValue) Else Return DefaultValue 13 | End Function 14 | Public Sub SetValue(ValueName As String, Data As Object) 15 | If ConfigKey IsNot Nothing Then ConfigKey.SetValue(ValueName, Data) 16 | End Sub 17 | Public Function HasValue(ValueName As String) As Boolean 18 | Return ConfigKey IsNot Nothing AndAlso ConfigKey.GetValue(ValueName) IsNot Nothing 19 | End Function 20 | End Class 21 | -------------------------------------------------------------------------------- /PolicyPlus/PolicyPlus.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "PolicyPlus", "PolicyPlus.vbproj", "{3E52E1E6-4FCF-403D-A84C-9C5CB0EDC739}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3E52E1E6-4FCF-403D-A84C-9C5CB0EDC739}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {3E52E1E6-4FCF-403D-A84C-9C5CB0EDC739}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {3E52E1E6-4FCF-403D-A84C-9C5CB0EDC739}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {3E52E1E6-4FCF-403D-A84C-9C5CB0EDC739}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /COMPILE.md: -------------------------------------------------------------------------------- 1 | # Compiling Policy Plus 2 | You can acquire the Policy Plus source code by cloning with [Git](https://git-scm.com/): 3 | 4 | git clone https://github.com/Fleex255/PolicyPlus.git 5 | 6 | It is recommended to set Git to ignore local changes to the autogenerated version file: 7 | 8 | git update-index --assume-unchanged PolicyPlus\Version.vb 9 | 10 | You can run `version.bat` at any time to replace that file with one that specifies your current commit. 11 | 12 | Policy Plus is developed with [Visual Studio 2019 Community](https://visualstudio.microsoft.com/vs/community/). (Fancier Visual Studio editions will work too.) 13 | 14 | To compile, open `PolicyPlus.sln` or `PolicyPlus.vbproj` (from the `PolicyPlus` folder) in Visual Studio. Set the *Solution Configurations* dropdown to Release (or Debug for a debug build). 15 | Choose *Build* | *Build PolicyPlus* from the main menu. The result is `PolicyPlus.exe`, which is set to run on 32-bit or 64-bit environments, preferring to run in a 64-bit process. 16 | You can find that file in the subfolder of `bin` that corresponds to the build type. -------------------------------------------------------------------------------- /PolicyPlus/OpenSection.vb: -------------------------------------------------------------------------------- 1 | Public Class OpenSection 2 | Public SelectedSection As AdmxPolicySection 3 | Private Sub ButtonOK_Click(sender As Object, e As EventArgs) Handles ButtonOK.Click 4 | ' Report the selected section 5 | If OptUser.Checked Or OptComputer.Checked Then 6 | SelectedSection = If(OptUser.Checked, AdmxPolicySection.User, AdmxPolicySection.Machine) 7 | DialogResult = DialogResult.OK 8 | End If 9 | End Sub 10 | Private Sub OpenSection_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown 11 | If e.KeyCode = Keys.Escape Then DialogResult = DialogResult.Cancel 12 | End Sub 13 | Private Sub OpenSection_Shown(sender As Object, e As EventArgs) Handles Me.Shown 14 | OptUser.Checked = False 15 | OptComputer.Checked = False 16 | End Sub 17 | Public Function PresentDialog(UserEnabled As Boolean, CompEnabled As Boolean) As DialogResult 18 | OptUser.Enabled = UserEnabled 19 | OptComputer.Enabled = CompEnabled 20 | Return ShowDialog() 21 | End Function 22 | End Class -------------------------------------------------------------------------------- /PolicyPlus/EditPolValue.vb: -------------------------------------------------------------------------------- 1 | Imports Microsoft.Win32 2 | Public Class EditPolValue 3 | Public SelectedKind As RegistryValueKind 4 | Public ChosenName As String 5 | Private Sub EditPolValueType_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown 6 | If e.KeyCode = Keys.Escape Then DialogResult = DialogResult.Cancel 7 | End Sub 8 | Public Function PresentDialog() As DialogResult 9 | TextName.Text = "" 10 | ComboKind.SelectedIndex = 0 11 | Dim dlgRes = ShowDialog() 12 | If dlgRes = DialogResult.OK Then 13 | Select Case ComboKind.SelectedIndex 14 | Case 0 15 | SelectedKind = RegistryValueKind.String 16 | Case 1 17 | SelectedKind = RegistryValueKind.ExpandString 18 | Case 2 19 | SelectedKind = RegistryValueKind.MultiString 20 | Case 3 21 | SelectedKind = RegistryValueKind.DWord 22 | Case 4 23 | SelectedKind = RegistryValueKind.QWord 24 | End Select 25 | ChosenName = TextName.Text 26 | End If 27 | Return dlgRes 28 | End Function 29 | End Class -------------------------------------------------------------------------------- /PolicyPlus/DetailCategory.vb: -------------------------------------------------------------------------------- 1 | Public Class DetailCategory 2 | Dim SelectedCategory As PolicyPlusCategory 3 | Public Sub PresentDialog(Category As PolicyPlusCategory) 4 | PrepareDialog(Category) 5 | ShowDialog() 6 | End Sub 7 | Private Sub PrepareDialog(Category As PolicyPlusCategory) 8 | SelectedCategory = Category 9 | NameTextbox.Text = Category.DisplayName 10 | IdTextbox.Text = Category.UniqueID 11 | DefinedTextbox.Text = Category.RawCategory.DefinedIn.SourceFile 12 | DisplayCodeTextbox.Text = Category.RawCategory.DisplayCode 13 | InfoCodeTextbox.Text = Category.RawCategory.ExplainCode 14 | ParentButton.Enabled = Category.Parent IsNot Nothing 15 | If Category.Parent IsNot Nothing Then 16 | ParentTextbox.Text = Category.Parent.DisplayName 17 | ElseIf Category.RawCategory.ParentID <> "" Then 18 | ParentTextbox.Text = "" 19 | Else 20 | ParentTextbox.Text = "" 21 | End If 22 | End Sub 23 | Private Sub ParentButton_Click(sender As Object, e As EventArgs) Handles ParentButton.Click 24 | PrepareDialog(SelectedCategory.Parent) 25 | End Sub 26 | End Class -------------------------------------------------------------------------------- /.github/workflows/latest.yml: -------------------------------------------------------------------------------- 1 | name: Build Latest 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | workflow_dispatch: 7 | 8 | jobs: 9 | BuildLatest: 10 | runs-on: windows-2022 11 | 12 | steps: 13 | - name: Checkout master 14 | uses: actions/checkout@v2 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Embed version 19 | run: | 20 | cd $env:GITHUB_WORKSPACE 21 | cmd /c version.bat 22 | 23 | - name: Set up MSBuild 24 | uses: microsoft/setup-msbuild@v1.0.2 25 | 26 | - name: Compile 27 | run: msbuild.exe $env:GITHUB_WORKSPACE\PolicyPlus\PolicyPlus.sln /p:platform="Any CPU" /p:configuration="Release" 28 | 29 | - name: Compute hash 30 | run: Get-FileHash "$env:GITHUB_WORKSPACE\PolicyPlus\bin\Release\Policy Plus.exe" 31 | 32 | - name: Upload to S3 33 | uses: stcalica/s3-upload@0.0.1 34 | with: 35 | bucket: ${{ secrets.AWS_S3_BUCKET }} 36 | package: PolicyPlus\bin\Release\Policy Plus.exe 37 | key: PolicyPlusLatest.exe 38 | AWS_REGION: ${{ secrets.AWS_REGION }} 39 | AWS_SECRET_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} 40 | AWS_SECRET_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 41 | -------------------------------------------------------------------------------- /PolicyPlus/EditPolDelete.vb: -------------------------------------------------------------------------------- 1 | Public Class EditPolDelete 2 | Public Function PresentDialog(ContainerKey As String) As DialogResult 3 | OptClearFirst.Checked = False 4 | OptDeleteOne.Checked = False 5 | OptPurge.Checked = False 6 | TextKey.Text = ContainerKey 7 | TextValueName.Text = "" 8 | Return ShowDialog() 9 | End Function 10 | Private Sub ButtonOK_Click(sender As Object, e As EventArgs) Handles ButtonOK.Click 11 | If OptClearFirst.Checked Or OptPurge.Checked Then DialogResult = DialogResult.OK 12 | If OptDeleteOne.Checked Then 13 | If TextValueName.Text = "" Then 14 | MsgBox("You must enter a value name.", MsgBoxStyle.Exclamation) 15 | Exit Sub 16 | End If 17 | DialogResult = DialogResult.OK 18 | End If 19 | End Sub 20 | Private Sub EditPolDelete_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown 21 | If e.KeyCode = Keys.Escape Then DialogResult = DialogResult.Cancel 22 | End Sub 23 | Sub ChoiceChanged(sender As Object, e As EventArgs) Handles OptClearFirst.CheckedChanged, OptDeleteOne.CheckedChanged, OptPurge.CheckedChanged 24 | TextValueName.Enabled = OptDeleteOne.Checked 25 | End Sub 26 | End Class -------------------------------------------------------------------------------- /PolicyPlus/My Project/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Reflection 3 | Imports System.Runtime.InteropServices 4 | 5 | ' General Information about an assembly is controlled through the following 6 | ' set of attributes. Change these attribute values to modify the information 7 | ' associated with an assembly. 8 | 9 | ' Review the values of the assembly attributes 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 'The following GUID is for the ID of the typelib if this project is exposed to COM 21 | 22 | 23 | ' Version information for an assembly consists of the following four values: 24 | ' 25 | ' Major Version 26 | ' Minor Version 27 | ' Build Number 28 | ' Revision 29 | ' 30 | ' You can specify all the values or you can default the Build and Revision Numbers 31 | ' by using the '*' as shown below: 32 | ' 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /PolicyPlus/LoadedAdmx.vb: -------------------------------------------------------------------------------- 1 | Public Class LoadedAdmx 2 | Dim Bundle As AdmxBundle 3 | Public Sub PresentDialog(Workspace As AdmxBundle) 4 | LsvAdmx.Items.Clear() 5 | For Each admx In Workspace.Sources.Keys 6 | Dim lsvi = LsvAdmx.Items.Add(IO.Path.GetFileName(admx.SourceFile)) 7 | lsvi.SubItems.Add(IO.Path.GetDirectoryName(admx.SourceFile)) 8 | lsvi.SubItems.Add(admx.AdmxNamespace) 9 | lsvi.Tag = admx 10 | Next 11 | LoadedAdmx_SizeChanged(Nothing, Nothing) 12 | ChNamespace.Width -= SystemInformation.VerticalScrollBarWidth ' For some reason, this only needs to be taken into account on the first draw 13 | Bundle = Workspace 14 | ShowDialog() 15 | End Sub 16 | Private Sub LsvAdmx_DoubleClick(sender As Object, e As EventArgs) Handles LsvAdmx.DoubleClick 17 | DetailAdmx.PresentDialog(LsvAdmx.SelectedItems(0).Tag, Bundle) 18 | End Sub 19 | Private Sub LoadedAdmx_SizeChanged(sender As Object, e As EventArgs) Handles Me.SizeChanged 20 | ChNamespace.Width = Math.Max(30, LsvAdmx.ClientRectangle.Width - ChFolder.Width - ChFileTitle.Width) 21 | End Sub 22 | Private Sub LsvAdmx_KeyDown(sender As Object, e As KeyEventArgs) Handles LsvAdmx.KeyDown 23 | If e.KeyCode = Keys.Enter And LsvAdmx.SelectedItems.Count > 0 Then LsvAdmx_DoubleClick(sender, e) 24 | End Sub 25 | End Class -------------------------------------------------------------------------------- /PolicyPlus/CompiledStructures.vb: -------------------------------------------------------------------------------- 1 | ' Compiled data, more object-oriented and display-worthy than raw data from ADMX files 2 | Public Class PolicyPlusCategory 3 | Public UniqueID As String 4 | Public Parent As PolicyPlusCategory 5 | Public Children As New List(Of PolicyPlusCategory) 6 | Public DisplayName As String 7 | Public DisplayExplanation As String 8 | Public Policies As New List(Of PolicyPlusPolicy) 9 | Public RawCategory As AdmxCategory 10 | End Class 11 | Public Class PolicyPlusProduct 12 | Public UniqueID As String 13 | Public Parent As PolicyPlusProduct 14 | Public Children As New List(Of PolicyPlusProduct) 15 | Public DisplayName As String 16 | Public RawProduct As AdmxProduct 17 | End Class 18 | Public Class PolicyPlusSupport 19 | Public UniqueID As String 20 | Public DisplayName As String 21 | Public Elements As New List(Of PolicyPlusSupportEntry) 22 | Public RawSupport As AdmxSupportDefinition 23 | End Class 24 | Public Class PolicyPlusSupportEntry 25 | Public Product As PolicyPlusProduct 26 | Public SupportDefinition As PolicyPlusSupport ' Only used if this entry actually points to another support definition 27 | Public RawSupportEntry As AdmxSupportEntry 28 | End Class 29 | Public Class PolicyPlusPolicy 30 | Public UniqueID As String 31 | Public Category As PolicyPlusCategory 32 | Public DisplayName As String 33 | Public DisplayExplanation As String 34 | Public SupportedOn As PolicyPlusSupport 35 | Public Presentation As Presentation 36 | Public RawPolicy As AdmxPolicy 37 | End Class -------------------------------------------------------------------------------- /PolicyPlus/ExportReg.vb: -------------------------------------------------------------------------------- 1 | Public Class ExportReg 2 | Dim Source As PolFile 3 | Public Function PresentDialog(Branch As String, Pol As PolFile, IsUser As Boolean) As DialogResult 4 | Source = Pol 5 | TextBranch.Text = Branch 6 | TextRoot.Text = If(IsUser, "HKEY_CURRENT_USER\", "HKEY_LOCAL_MACHINE\") 7 | TextReg.Text = "" 8 | Return ShowDialog() 9 | End Function 10 | Private Sub ButtonBrowse_Click(sender As Object, e As EventArgs) Handles ButtonBrowse.Click 11 | Using sfd As New SaveFileDialog 12 | sfd.Filter = "Registry scripts|*.reg" 13 | If sfd.ShowDialog = DialogResult.OK Then TextReg.Text = sfd.FileName 14 | End Using 15 | End Sub 16 | Private Sub ExportReg_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp 17 | If e.KeyCode = Keys.Escape Then DialogResult = DialogResult.Cancel 18 | End Sub 19 | Private Sub ButtonExport_Click(sender As Object, e As EventArgs) Handles ButtonExport.Click 20 | If TextReg.Text = "" Then 21 | MsgBox("Please specify a filename and path for the exported REG.", MsgBoxStyle.Exclamation) 22 | Exit Sub 23 | End If 24 | Dim reg As New RegFile 25 | reg.SetPrefix(TextRoot.Text) 26 | reg.SetSourceBranch(TextBranch.Text) 27 | Try 28 | Source.Apply(reg) 29 | reg.Save(TextReg.Text) 30 | MsgBox("REG exported successfully.", MsgBoxStyle.Information) 31 | DialogResult = DialogResult.OK 32 | Catch ex As Exception 33 | MsgBox("Failed to export REG!", MsgBoxStyle.Exclamation) 34 | End Try 35 | End Sub 36 | End Class -------------------------------------------------------------------------------- /PolicyPlus/LoadedSupportDefinitions.vb: -------------------------------------------------------------------------------- 1 | Public Class LoadedSupportDefinitions 2 | Dim Definitions As IEnumerable(Of PolicyPlusSupport) 3 | Public Sub PresentDialog(Workspace As AdmxBundle) 4 | TextFilter.Text = "" 5 | Definitions = Workspace.SupportDefinitions.Values 6 | UpdateListing() 7 | ChName.Width = LsvSupport.ClientRectangle.Width - ChDefinedIn.Width - SystemInformation.VerticalScrollBarWidth 8 | ShowDialog() 9 | End Sub 10 | Sub UpdateListing() 11 | ' Add all the (matching) support definitions to the list view 12 | LsvSupport.Items.Clear() 13 | For Each support In Definitions.OrderBy(Function(s) s.DisplayName.Trim()) ' Some default support definitions have leading spaces 14 | If Not support.DisplayName.ToLowerInvariant.Contains(TextFilter.Text.ToLowerInvariant) Then Continue For 15 | Dim lsvi = LsvSupport.Items.Add(support.DisplayName.Trim()) 16 | lsvi.SubItems.Add(IO.Path.GetFileName(support.RawSupport.DefinedIn.SourceFile)) 17 | lsvi.Tag = support 18 | Next 19 | End Sub 20 | Private Sub LsvSupport_DoubleClick(sender As Object, e As EventArgs) Handles LsvSupport.DoubleClick 21 | DetailSupport.PresentDialog(LsvSupport.SelectedItems(0).Tag) 22 | End Sub 23 | Private Sub TextFilter_TextChanged(sender As Object, e As EventArgs) Handles TextFilter.TextChanged 24 | ' Only repopulate if the form isn't still setting up 25 | If Visible Then UpdateListing() 26 | End Sub 27 | Private Sub LsvSupport_KeyDown(sender As Object, e As KeyEventArgs) Handles LsvSupport.KeyDown 28 | If e.KeyCode = Keys.Enter And LsvSupport.SelectedItems.Count > 0 Then LsvSupport_DoubleClick(sender, e) 29 | End Sub 30 | End Class -------------------------------------------------------------------------------- /PolicyPlus/AdmxStructures.vb: -------------------------------------------------------------------------------- 1 | ' Raw data loaded from ADMX files 2 | Public Class AdmxProduct 3 | Public ID As String 4 | Public DisplayCode As String 5 | Public Type As AdmxProductType 6 | Public Version As Integer 7 | Public Parent As AdmxProduct 8 | Public DefinedIn As AdmxFile 9 | End Class 10 | Public Enum AdmxProductType 11 | Product 12 | MajorRevision 13 | MinorRevision 14 | End Enum 15 | Public Class AdmxSupportDefinition 16 | Public ID As String 17 | Public DisplayCode As String 18 | Public Logic As AdmxSupportLogicType 19 | Public Entries As List(Of AdmxSupportEntry) 20 | Public DefinedIn As AdmxFile 21 | End Class 22 | Public Enum AdmxSupportLogicType 23 | Blank 24 | AllOf 25 | AnyOf 26 | End Enum 27 | Public Class AdmxSupportEntry 28 | Public ProductID As String 29 | Public IsRange As Boolean 30 | Public MinVersion As Integer? 31 | Public MaxVersion As Integer? 32 | End Class 33 | Public Class AdmxCategory 34 | Public ID As String 35 | Public DisplayCode As String 36 | Public ExplainCode As String 37 | Public ParentID As String 38 | Public DefinedIn As AdmxFile 39 | End Class 40 | Public Class AdmxPolicy 41 | Public ID As String 42 | Public Section As AdmxPolicySection 43 | Public CategoryID As String 44 | Public DisplayCode As String 45 | Public ExplainCode As String 46 | Public SupportedCode As String 47 | Public PresentationID As String 48 | Public ClientExtension As String 49 | Public RegistryKey As String 50 | Public RegistryValue As String 51 | Public AffectedValues As PolicyRegistryList 52 | Public Elements As List(Of PolicyElement) 53 | Public DefinedIn As AdmxFile 54 | End Class 55 | Public Enum AdmxPolicySection 56 | Machine = 1 57 | User = 2 58 | Both = 3 59 | End Enum -------------------------------------------------------------------------------- /PolicyPlus/OpenUserGpo.vb: -------------------------------------------------------------------------------- 1 | Imports System.Security.Principal 2 | Public Class OpenUserGpo 3 | Public SelectedSid As String 4 | Private Sub SearchButton_Click(sender As Object, e As EventArgs) Handles SearchButton.Click 5 | ' Resolve the username to a security identifier (SID) 6 | Try 7 | Dim userAccount As New NTAccount(UsernameTextbox.Text) 8 | Dim sid As SecurityIdentifier = userAccount.Translate(GetType(SecurityIdentifier)) 9 | SidTextbox.Text = sid.ToString 10 | Catch ex As Exception 11 | MsgBox("The name could not be translated to a SID.", MsgBoxStyle.Exclamation) 12 | End Try 13 | End Sub 14 | Private Sub OkButton_Click(sender As Object, e As EventArgs) Handles OkButton.Click 15 | If SidTextbox.Text = "" And UsernameTextbox.Text <> "" Then 16 | ' Automatically resolve if the user didn't click Search 17 | SearchButton_Click(Nothing, Nothing) 18 | If SidTextbox.Text = "" Then Exit Sub 19 | End If 20 | Try 21 | ' Make sure the SID is valid 22 | Dim sid As New SecurityIdentifier(SidTextbox.Text) 23 | Catch ex As Exception 24 | MsgBox("The SID is not valid. Enter a SID in the lower box, or enter a username in the top box and press Search to translate.", MsgBoxStyle.Exclamation) 25 | Exit Sub 26 | End Try 27 | SelectedSid = SidTextbox.Text 28 | DialogResult = DialogResult.OK 29 | End Sub 30 | Private Sub OpenUserGpo_Shown(sender As Object, e As EventArgs) Handles Me.Shown 31 | SidTextbox.Text = "" 32 | UsernameTextbox.Text = "" 33 | End Sub 34 | Private Sub OpenUserGpo_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp 35 | If e.KeyCode = Keys.Escape Then DialogResult = DialogResult.Cancel 36 | End Sub 37 | End Class -------------------------------------------------------------------------------- /PolicyPlus/PInvoke.vb: -------------------------------------------------------------------------------- 1 | Imports System.Runtime.InteropServices 2 | Class PInvoke 3 | Declare Function ShowScrollBar Lib "user32.dll" (Handle As IntPtr, Scrollbar As Integer, Show As Boolean) As Boolean 4 | Declare Function RefreshPolicyEx Lib "userenv.dll" (IsMachine As Boolean, Options As UInteger) As Boolean 5 | Declare Unicode Function RegLoadKeyW Lib "advapi32.dll" (HiveKey As IntPtr, Subkey As String, File As String) As Integer 6 | Declare Unicode Function RegUnLoadKeyW Lib "advapi32.dll" (HiveKey As IntPtr, Subkey As String) As Integer 7 | Declare Function GetCurrentProcess Lib "kernel32.dll" () As IntPtr 8 | Declare Function OpenProcessToken Lib "advapi32.dll" (Process As IntPtr, Access As UInteger, ByRef TokenHandle As IntPtr) As Boolean 9 | Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (Token As IntPtr, DisableAll As Boolean, ByRef NewState As PInvokeTokenPrivileges, BufferLength As UInteger, Null As IntPtr, ByRef ReturnLength As UInteger) As Boolean 10 | Declare Unicode Function LookupPrivilegeValueW Lib "advapi32.dll" (SystemName As String, Name As String, ByRef LUID As PInvokeLuid) As Boolean 11 | Declare Function CloseHandle Lib "kernel32.dll" (Handle As IntPtr) As Boolean 12 | Declare Function GetProductInfo Lib "kernel32.dll" (MajorVersion As Integer, MinorVersion As Integer, SPMajor As Integer, SPMinor As Integer, ByRef EditionCode As Integer) As Boolean 13 | Declare Unicode Function SendNotifyMessageW Lib "user32.dll" (Handle As IntPtr, Message As Integer, WParam As UIntPtr, LParam As IntPtr) As Boolean 14 | End Class 15 | Structure PInvokeTokenPrivileges 16 | Public PrivilegeCount As UInteger 17 | Public LUID As PInvokeLuid 18 | Public Attributes As UInteger 19 | End Structure 20 | Structure PInvokeLuid 21 | Public LowPart As UInteger 22 | Public HighPart As Integer 23 | End Structure -------------------------------------------------------------------------------- /PolicyPlus/My Project/Application.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' Runtime Version:4.0.30319.42000 5 | ' 6 | ' Changes to this file may cause incorrect behavior and will be lost if 7 | ' the code is regenerated. 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | 15 | Namespace My 16 | 17 | 'NOTE: This file is auto-generated; do not modify it directly. To make changes, 18 | ' or if you encounter build errors in this file, go to the Project Designer 19 | ' (go to Project Properties or double-click the My Project node in 20 | ' Solution Explorer), and make changes on the Application tab. 21 | ' 22 | Partial Friend Class MyApplication 23 | 24 | _ 25 | Public Sub New() 26 | MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.AuthenticationMode.Windows) 27 | Me.IsSingleInstance = false 28 | Me.EnableVisualStyles = true 29 | Me.SaveMySettingsOnExit = true 30 | Me.ShutDownStyle = Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses 31 | End Sub 32 | 33 | _ 34 | Protected Overrides Sub OnCreateMainForm() 35 | Me.MainForm = Global.PolicyPlus.Main 36 | End Sub 37 | 38 | _ 39 | Protected Overrides Function OnInitialize(ByVal commandLineArgs As System.Collections.ObjectModel.ReadOnlyCollection(Of String)) As Boolean 40 | Me.MinimumSplashScreenDisplayTime = 0 41 | Return MyBase.OnInitialize(commandLineArgs) 42 | End Function 43 | End Class 44 | End Namespace 45 | -------------------------------------------------------------------------------- /PolicyPlus/ListEditor.vb: -------------------------------------------------------------------------------- 1 | Public Class ListEditor 2 | Dim UserProvidesNames As Boolean 3 | Public FinalData As Object 4 | Public Function PresentDialog(Title As String, Data As Object, TwoColumn As Boolean) As DialogResult 5 | UserProvidesNames = TwoColumn 6 | NameColumn.Visible = TwoColumn 7 | ElementNameLabel.Text = Title 8 | EntriesDatagrid.Rows.Clear() 9 | If Data IsNot Nothing Then 10 | If TwoColumn Then 11 | Dim dict As Dictionary(Of String, String) = Data 12 | For Each kv In dict 13 | EntriesDatagrid.Rows.Add(kv.Key, kv.Value) 14 | Next 15 | Else 16 | Dim list As List(Of String) = Data 17 | For Each entry In list 18 | EntriesDatagrid.Rows.Add("", entry) 19 | Next 20 | End If 21 | End If 22 | FinalData = Nothing 23 | Return ShowDialog() 24 | End Function 25 | Private Sub OkButton_Click(sender As Object, e As EventArgs) Handles OkButton.Click 26 | If UserProvidesNames Then 27 | ' Check for duplicate keys 28 | Dim dict As New Dictionary(Of String, String) 29 | For Each row As DataGridViewRow In EntriesDatagrid.Rows 30 | If row.IsNewRow Then Continue For 31 | Dim key As String = row.Cells(0).Value 32 | If dict.ContainsKey(key) Then 33 | MsgBox("Multiple entries are named """ & key & """! Remove or rename all but one.", MsgBoxStyle.Exclamation) 34 | Exit Sub 35 | Else 36 | dict.Add(key, row.Cells(1).Value) 37 | End If 38 | Next 39 | FinalData = dict 40 | Else 41 | Dim list As New List(Of String) 42 | For Each row As DataGridViewRow In EntriesDatagrid.Rows 43 | If Not row.IsNewRow Then list.Add(row.Cells(1).Value) 44 | Next 45 | FinalData = list 46 | End If 47 | DialogResult = DialogResult.OK 48 | End Sub 49 | End Class -------------------------------------------------------------------------------- /PolicyPlus/DetailPolicy.vb: -------------------------------------------------------------------------------- 1 | Public Class DetailPolicy 2 | Dim SelectedPolicy As PolicyPlusPolicy 3 | Public Sub PresentDialog(Policy As PolicyPlusPolicy) 4 | SelectedPolicy = Policy 5 | NameTextbox.Text = Policy.DisplayName 6 | IdTextbox.Text = Policy.UniqueID 7 | DefinedTextbox.Text = Policy.RawPolicy.DefinedIn.SourceFile 8 | DisplayCodeTextbox.Text = Policy.RawPolicy.DisplayCode 9 | InfoCodeTextbox.Text = Policy.RawPolicy.ExplainCode 10 | PresentCodeTextbox.Text = Policy.RawPolicy.PresentationID 11 | Select Case Policy.RawPolicy.Section 12 | Case AdmxPolicySection.Both 13 | SectionTextbox.Text = "User or computer" 14 | Case AdmxPolicySection.Machine 15 | SectionTextbox.Text = "Computer" 16 | Case AdmxPolicySection.User 17 | SectionTextbox.Text = "User" 18 | End Select 19 | SupportButton.Enabled = Policy.SupportedOn IsNot Nothing 20 | If Policy.SupportedOn IsNot Nothing Then 21 | SupportTextbox.Text = Policy.SupportedOn.DisplayName 22 | ElseIf Policy.RawPolicy.SupportedCode <> "" Then 23 | SupportTextbox.Text = "" 24 | Else 25 | SupportTextbox.Text = "" 26 | End If 27 | CategoryButton.Enabled = Policy.Category IsNot Nothing 28 | If Policy.Category IsNot Nothing Then 29 | CategoryTextbox.Text = Policy.Category.DisplayName 30 | ElseIf Policy.RawPolicy.CategoryID <> "" Then 31 | CategoryTextbox.Text = "" 32 | Else 33 | CategoryTextbox.Text = "" 34 | End If 35 | ShowDialog() 36 | End Sub 37 | Private Sub SupportButton_Click(sender As Object, e As EventArgs) Handles SupportButton.Click 38 | DetailSupport.PresentDialog(SelectedPolicy.SupportedOn) 39 | End Sub 40 | Private Sub CategoryButton_Click(sender As Object, e As EventArgs) Handles CategoryButton.Click 41 | DetailCategory.PresentDialog(SelectedPolicy.Category) 42 | End Sub 43 | End Class -------------------------------------------------------------------------------- /PolicyPlus/PresentationStructures.vb: -------------------------------------------------------------------------------- 1 | ' These structures hold information on how the UI for policy elements appears 2 | Public Class Presentation 3 | Public Name As String 4 | Public Elements As New List(Of PresentationElement) 5 | End Class 6 | Public MustInherit Class PresentationElement 7 | Public ID As String ' refId 8 | Public ElementType As String 9 | End Class 10 | Public Class LabelPresentationElement ' 11 | Inherits PresentationElement 12 | Public Text As String ' Inner text 13 | End Class 14 | Public Class NumericBoxPresentationElement ' 15 | Inherits PresentationElement 16 | Public DefaultValue As UInteger ' defaultValue 17 | Public HasSpinner As Boolean = True ' spin 18 | Public SpinnerIncrement As UInteger ' spinStep 19 | Public Label As String ' Inner text 20 | End Class 21 | Public Class TextBoxPresentationElement ' 22 | Inherits PresentationElement 23 | Public Label As String '